; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ (c) Lord Julus - 2000                Vxtasy #1 - Magazine source code ³
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

;===========( Routine to rearange menu on the screen )=======================

reorder_menu proc near
        mov cs:events, 0
        cmp onlyactualize, 1
        je no_menu_display
        call display_menu_bar

no_menu_display:
        push current_popup
        call print_popup
        call wait_vert
        mov cs:events, 1
        ret
reorder_menu endp

;=========( Procedure to display menu bar )==================================

display_menu_bar proc near
        pusha
        xor dx, dx
        mov dh, menu_bar_row
        mov cx, max_menu_item
        lea di, menu_items
        inc di
        inc di
        mov counter, 1

repeat_display_menu:
        call display_menu_space

        inc dl
        push cx
        mov ax, 1212h                      ;
        int 2fh                            ; get asciiz string length in cx

        mov ax, counter
        cmp ax, current_popup
        je set_another_color
        mov bl, menu_item_attr
        jmp over_change

set_another_color:
        mov bl, menu_sele_attr
over_change:
        mov ah, 13h
        mov al, 01h
        mov bh, 00h
        mov bp, di
        int 10h

   pusha

        mov ax, counter
        cmp ax, current_popup
        je set_another_color2
        mov bl, menu_aclt_attr
        jmp over_change2

set_another_color2:
        mov bl, menu_selt_attr

over_change2:

   xor ax, ax
   mov al, byte ptr [di-1]
   add dl, al
   call pos_cursor
   add di, ax
   mov al, byte ptr [di]
   mov ah, 09h
   mov bh, 0
   mov cx, 1
   int 10h

   popa

        add di, cx
        inc di
        inc di
        inc counter
        add dl, cl
        pop cx

        loop repeat_display_menu
        popa
        ret
display_menu_bar endp

display_menu_space proc near
        pusha

        mov cx, menu_items_space
        mov al, menu_bar_char
        mov bl, menu_bar_attr

repeat_display_space:
        call display_char
        inc dl
        loop repeat_display_space
        popa
        ret
display_menu_space endp

;=========( Procedure to display a popup )===================================

print_popup proc near
        push bp
        mov bp, sp
        push ax bx cx dx si

        mov bx, word ptr ss:[bp+04h]

        call calculate_position            ;

        push bx                            ;
        call create_popup                  ; di points to the popup

        cmp byte ptr [di], '~'
        jne continue_display
        mov no_popup, 1
        jmp over_modification

continue_display:
        mov no_popup, 0

over_modification:
        call print_description

        call calculate_height_width        ;
        mov ax, popup_height               ;
        mov bx, popup_width                ;

mov bx, popup_width
add dl, bl
redo:
cmp dl, 78
jb ok_exception
dec dl
jmp redo
ok_exception:
sub dl, bl

cmp popup_downwards, 1
je downward_popup

        mov ax, popup_height
        sub dh, al
        sub dh, 3
        sub dh, pop_up_distance

downward_popup:



        call fill_mouse_coords

        cmp onlyactualize, 1
        je only_redisplay

        cmp anysave, 0
        je no_restore_area
        call restore_area

no_restore_area:

        call save_area

        cmp showpopup, 1
        jne no_popup_to_display

only_redisplay:
        cmp no_popup, 1
        je no_popup_to_display

        call make_popup                    ;
        inc dl
        inc dh
        mov counter, 1

repeat_print_popup:
        mov ax, 1212h                      ;
        int 2fh                            ; get asciiz string length in cx

        mov ax, current_popit
        cmp ax, counter
        jne no_current_popup
        mov bl, pop_up_sele_attr
        jmp continue_print

no_current_popup:
        mov bl, pop_up_item_attr

continue_print:
;        mov ah, 13h
;        mov al, 01h
;        mov bh, 00h
;
;        mov bp, di
;        int 10h

        call display_one_line

        inc dh
        mov si, di
        add si, cx
        lodsb
        cmp al, 0
        jz exit_print_popup
        dec si
        mov di, si
        inc counter
        jmp repeat_print_popup

exit_print_popup:
        call display_shadow

no_popup_to_display:
;        mov no_popup, 0
        call wait_vert
        pop si dx cx bx ax
        pop bp
        ret 2
print_popup endp

display_one_line proc near
        pusha
        mov bh, 0
        mov current_attr, bl
repeat_display_one_line:
        mov bl, current_attr

display_hot_letter:
        mov al, byte ptr [di]
        cmp al, '~'
        je dont_display_next
        cmp al, 0
        je done_this_line

        call pos_cursor
        call put_char

        inc dl
        inc di
        jmp repeat_display_one_line

dont_display_next:
        inc di
        cmp bl, pop_up_sele_attr
        je select_selected_hot_letter

        mov bl, hot_letter_norm_attr
        jmp display_hot_letter

select_selected_hot_letter:
        mov bl, hot_letter_sele_attr
        jmp display_hot_letter

done_this_line:
        popa
        ret
display_one_line endp

display_shadow proc near
        pusha
        push es

        mov ax, 0b800h
        mov es, ax

        mov ax, popup_shadow
        cmp ax, TRUE
        jne no_shadow

        mov dh, saved_row
        mov dl, saved_col
        add dl, saved_hei
        dec dl
        inc dh
        inc dh
        xor cx, cx
        mov cl, saved_wid
        dec cx
        dec cx
        dec cx

repeat_down_shadow:
        push dx
        mov al, popup_shadow_attr
        call computeaddress
        inc dx
        mov di, dx
        stosb
        pop dx
        inc dh
        loop repeat_down_shadow

        mov dh, saved_row
        mov dl, saved_col
        add dh, saved_wid
        dec dh
        dec dh
        inc dl
        xor cx, cx
        mov cl, saved_hei
        dec cx

repeat_up_shadow:
        push dx
        mov al, popup_shadow_attr
        call computeaddress
        inc dx
        mov di, dx
        stosb

        inc di
        stosb

        pop dx
        inc dl
        loop repeat_up_shadow


no_shadow:
        pop es
        popa
        ret
display_shadow endp

print_description proc near
        pusha

        cmp showpopup, 0
        je no_popup_description
        push current_popup
        push current_popit
        call locate_popup_item_desc
        jmp display_it

no_popup_description:
        push current_popup
        call locate_menubar_name
        jmp __2

display_it:
        mov dx, description_position
        jmp __1

__2:
        mov dx, description_position
        add dl, 3

__1:
        mov ax, 1225h
        int 2fh
        mov bp, si
        mov bl, description_attr
        mov bh, 0
        mov ah, 13h
        mov al, 01h
        int 10h

        mov ah, 03h
        mov bh, 0
        int 10h

        xor cx, cx
        mov cl, clreol_until
        cmp dl, cl
        jae no_clreol

        sub cl, dl
        mov ah, 09h
        mov al, clreol_char
        mov bl, clreol_attr
        mov bh, 0
        int 10h

no_clreol:

        popa
        ret
print_description endp

;=========( Procedure to calculate the position of a popup )=================

calculate_position proc near
        push cx bx di
        mov cx, bx              ; popup number
        mov bx, 1               ; bar number
        lea di, menu_items      ;
        xor dx, dx

search_position:
        add dx, menu_items_space
        cmp cx, bx
        je found_rite_column
        push cx

push bx
call locate_menubar_name
        mov di, si
        mov ax, 1212h                      ;
        int 2fh                            ; get asciiz string length in cx

        inc cx
        add dx, cx

        pop cx
        inc bx
        jmp search_position

found_rite_column:
        mov dh, menu_bar_row
        inc dh
        add dh, pop_up_distance

        pop di bx cx
        ret
calculate_position endp

;=========( Procedure to calculate the height and width of the popup )=======

calculate_height_width proc near
        push di
        mov popup_width, 0
        mov popup_height, 1

repeat_calculate:
        mov ax, 1212h                      ;
        int 2fh                            ; get asciiz string length in cx
        cmp cx, popup_width
        jbe ok_width
        mov popup_width, cx

ok_width:
        mov si, di
        add si, cx
        lodsb
        cmp al, 0
        jz exit_calculate_height_width
        inc popup_height
        dec si
        mov di, si
        jmp repeat_calculate

exit_calculate_height_width:
        dec popup_width
        pop di
        ret
calculate_height_width endp

;=========( Procedure to display graphical characters around popup )=========

make_popup proc near
        pusha                              ; dx = pos, ax=height, bx=width

; Display corners
        push dx
        push ax bx
        mov al, upper_left_char
        mov bl, upper_left_attr
        call display_char
        pop bx ax
        push ax bx
        add dl, bl
        mov al, upper_right_char
        mov bl, upper_right_attr
        call display_char
        pop bx ax
        push ax bx
        add dh, al
        inc dh
        mov al, lower_right_char
        mov bl, lower_right_attr
        call display_char
        pop bx ax
        push ax bx
        sub dl, bl
        mov al, lower_left_char
        mov bl, lower_left_attr
        call display_char
        pop bx ax
        pop dx

        inc dl
        mov cx, bx
        dec cx
        push dx bx ax

repeat_display_horizontal:
        push ax
        mov al, top_horiz_char
        mov bl, top_horiz_attr
        call display_char
        pop ax
        add dh, al
        inc dh
        push ax
        mov al, bott_horiz_char
        mov bl, bott_horiz_attr
        call display_char
        pop ax
        sub dh, al
        dec dh
        inc dl
        loop repeat_display_horizontal

        pop ax bx dx
        mov cx, ax
        dec dl
        inc dh

repeat_display_vertical:
        push bx
        mov al, left_vert_char
        mov bl, left_vert_attr
        call display_char
        pop bx
        add dl, bl
        push bx
        mov al, right_vert_char
        mov bl, right_vert_attr
        call display_char
        pop bx
        sub dl, bl
        inc dh
        loop repeat_display_vertical

        popa
        ret
make_popup endp

display_char proc near
        pusha
        call pos_cursor
        mov ah, 09h
        mov bh, 0
        mov cx, 1
        int 10h
        popa
        ret
display_char endp

pos_cursor proc near
        pusha
        mov ah, 02h
        mov bh, 0
        int 10h
        popa
        ret
pos_cursor endp

;=========( Procedure to save the screen and the cursor position )===========

SaveScreen  proc                           ;
         push ds                           ;
         push es                           ;
         mov ah, 03h                       ; save cursor
         mov bh, 0                         ;
         int 10h                           ;
         mov cursor, dx                    ;
         mov ax, 0b800h                    ; and then all the screen
         mov ds, ax                        ;
         mov si, 0h                        ;
         mov ax, seg screen                ;
         mov es, ax                        ;
         lea di, screen                    ;
         mov cx, 80*25*2                   ;
         rep movsb                         ;
         pop es                            ;
         pop ds                            ;
         ret                               ;
SaveScreen endp                            ;

;==========( Procedure to restore the screen and cursor position )===========

RestoreScreen proc                         ;
         push ds                           ;
         push es                           ;
         mov ax, 0b800h                    ;
         mov es, ax                        ;
         mov di, 0                         ;
         mov ax, seg screen                ;
         mov ds, ax                        ;
         lea si, screen                    ;
         mov cx, 80*25*2                   ;
         rep movsb                         ;
         mov ah, 02h                       ;
         mov bh, 0                         ;
         mov dx, cursor                    ;
         int 10h                           ;
         pop es                            ;
         pop ds                            ;
         ret                               ;
RestoreScreen endp                         ;


makescreen proc near                         ;
           pusha                             ;
           push es                           ;
           push ds                           ;
                                             ;
           mov ax, 0b800h                    ; clear video memory
           mov es, ax                        ;
           mov di, 0                         ;
           mov ax, 0                         ;
           mov cx, 80*25*2                   ;
           rep stosb                         ;
                                             ;
           mov cx, 24

go_in_loop:
           push cx
           mov ax, 160d
           xor dx, dx
           mul cx
           mov si, offset gmc_layout_source  ; move the layout to the
           mov di, 0                         ; video memory
           add di, ax
           mov cx, gmc_layout_length         ;
           sub cx, ax
           rep movsw                         ;

        mov cx, 0ffffh
x:
        push cx
        mov cx, 10h
y:      cmp cx, cx
        loop y
        pop cx
        loop x

           pop cx
           dec cx
           cmp cx, -1
           jne go_in_loop
                                             ;
           pop ds                            ;
           pop es                            ;
           popa                              ;
           ret                               ;
makescreen endp                              ;

;=========( This calculates the video address for a given row-column )=======

computeaddress proc near                     ;
           push cx                           ; dl = row / dh = column
           push ax                           ; returns video address for DX
           push dx                           ;
           xor ax, ax                        ; Video address = row*160+col*2
           mov al, dl                        ;
           mov cx, 160d                      ;
           mul cx                            ;
           pop dx                            ;
           xor cx, cx                        ;
           mov cl, dh                        ;
           shl cl, 1                         ;
           xor dx, dx                        ;
           add dx, ax                        ;
           add dx, cx                        ;
           pop ax                            ;
           pop cx                            ;
           ret                               ;
computeaddress endp                          ;

save_area proc near                          ; dl=col / dh=row
           pusha                             ; al=width / bl=height
           push ds

           add al, 3
           add bl, 3

           cmp popup_shadow, 1
           je ok_with_shadow
           dec al

ok_with_shadow:
           mov saved_row, dl
           mov saved_col, dh
           mov saved_wid, bl
           mov saved_hei, al

           lea di, save_area_buffer
           mov cx, 0b800h
           mov ds, cx

           xor cx, cx
           mov cl, bl

second_save_loop:
           push cx
           push dx

           mov cl, al

first_save_loop:
           push dx
           xchg dl, dh
           call computeaddress
           mov si, dx
           pop dx
           push ax
           lodsw
           stosw
           pop ax
           inc dh
           loop first_save_loop

           pop dx
           pop cx
           inc dl
           loop second_save_loop

           pop ds
           popa
           mov anysave, 1
           ret
save_area endp

restore_area proc near                       ; dl=row / dh=col
           pusha                             ; bl=width / al=height
           push es

           mov dl, saved_row
           mov dh, saved_col
           mov bl, saved_wid
           mov al, saved_hei

           lea si, save_area_buffer
           mov cx, 0b800h
           mov es, cx

           xor cx, cx
           mov cl, bl

second_restore_loop:
           push cx
           push dx

           mov cl, al

first_restore_loop:
           push dx
           xchg dh, dl
           call computeaddress
           mov di, dx
           pop dx
           push ax
           lodsw
           stosw
           pop ax
           inc dh
           loop first_restore_loop

           pop dx
           pop cx
           inc dl
           loop second_restore_loop

           pop es
           popa
           ret
restore_area endp

;==========( Save to page 2 )================================================

save_to_page_2 proc near
        call hide_mouse
        pusha
        push ds
        push es
        mov ax, 0b800h
        mov ds, ax
        mov si, 0
        lea di, savescr
        mov cx, 80*25*2
        rep movsb

        pop es
        pop ds
        popa
        call show_mouse
        ret
save_to_page_2 endp

;==========( Restore from page 2 )===========================================

restore_from_page_2 proc near
        call hide_mouse
        pusha
        push ds
        push es

        mov ax, 0b800h
        mov es, ax
        lea si, savescr
        mov di, 0
        mov cx, 80*25*2
        rep movsb

        pop es
        pop ds
        popa
        call show_mouse
        ret
restore_from_page_2 endp

;==========( Save to page 3 )================================================

save_to_page_3 proc near
        call hide_mouse
        pusha
        push ds
        push es
        mov ax, 0b800h
        mov ds, ax
        mov si, 0
        lea di, savescr2
        mov cx, 80*25*2
        rep movsb

        pop es
        pop ds
        popa
        call show_mouse
        ret
save_to_page_3 endp

;==========( Restore from page 3 )===========================================

restore_from_page_3 proc near
        call hide_mouse
        pusha
        push ds
        push es

        mov ax, 0b800h
        mov es, ax
        lea si, savescr2
        mov di, 0
        mov cx, 80*25*2
        rep movsb

        pop es
        pop ds
        popa
        call show_mouse
        ret
restore_from_page_3 endp


fill_mouse_coords proc near
        pusha
        push ds
        push es

        lea di, popup_coords
        mov cx, ax

repeat_calculate_popup_coords:
        push cx

        push dx
        mov cl, dl                ; cx=column
        shr dx, 8                 ; dx=row
        mov ax, dx
        inc ax
        stosw                     ; store row
        mov ax, cx
        stosw                     ; store column 1
        add ax, bx                ;
        stosw                     ; store column 2
        pop dx
        inc dh

        pop cx
        loop repeat_calculate_popup_coords

        pop es
        pop ds
        popa
        ret
fill_mouse_coords endp

wait_vert:
        pusha
        mov dx,3dah             ;astept cursa inversa
rr:     in al,dx
        test al,8
        jnz rr          ;pana cand se termina
rrr:    in al,dx
        test al,8
        jz rrr          ;pana cand incepe
        popa
        retn

destroyscreen proc near
       pusha
       push es
       push ds

       mov ax, 0b800h
       mov es, ax
       mov ds, ax

       mov cx, 6
       mov dh, 0
       call loop_____

       mov cx, 10d
       mov dh, 15
       call loop_____
       jmp zxcvb

loop_____:
    push cx
       mov cx, 80

loop____:
    push cx
       mov cx, 80
       mov dl, 79


loop___:
       call pos_cursor
       push dx
       xchg dl, dh
       call computeaddress
       mov si, dx
       sub si, 2
       lodsw
       mov di, dx
       stosw
       pop dx
       dec dl
       push cx
       mov cx, 0400h
       loop $
       pop cx
       loop loop___
       mov word ptr [si], 0720h

   pop cx
   loop loop____

   inc dh
   pop cx
   loop loop_____
   ret

zxcvb:
       mov cx, 5
       call Delay
       pop ds
       pop es
       popa
       ret
destroyscreen endp

