.model small

.stack

.data    
    hexaPosX = 5
    posY = 3
    charRelPosX = 5 
    rows = 15
    
    ;-------------------------
    hexaWidth = 47 ;3*16-1, mert az utolso hexa utan nem kell space
    charWidth = 16
    borderWidth = hexaWidth+charRelPosX+charWidth+2
    charPosX = hexaPosX+hexaWidth+charRelPosX
    ;------------------------------
    ESCAPE = 27
    cr = 13     ;carrige return (kocsi vissza)
    lf = 10     ;line feed (uj sor)
    space = ' '
    
    maxRows = 512 / 16
    lastPageRows = maxRows mod rows
    maxPage = (maxRows / rows) + ((lastPageRows+(rows-1)) / rows )
    
    dcrlf db cr,lf,0   ;uj sor
    goodbye db 'Szep napot! Hasznalj maskor is!!',0
    goodbyeLength = $-goodbye-1
    borderTop db 201, hexaWidth + (charRelPosX/2) dup(205), 203,
                      (charRelPosX/2) + charWidth dup(205), 187,0
    borderMiddle db 186
    borderBottom db 200, hexaWidth + (charRelPosX/2) dup(205) ,202,
                     (charRelPosX/2) + charWidth dup(205) , 188,0
    pagenum db 0 
    offs dw 0
    
    txtPage db 'Oldal: ',0
    txtDiskId db 'Lemez:',0
    txtBlockNumber db 'Block szama:',0
    
    quit db 0
    
.data?
    block db 512 dup(?)
.code

writem_char macro chr    ;atadott karakter kiirasa kepernyore
    push dx
    
    mov dl, chr
    call write_char
    
    pop dx
endm

writem macro string       ;atadott karakter kiirasa kepernyore
    push bx
   
    lea bx, string
    call write_string
   
    pop bx
endm

gotoXY macro x, y       ;kurzor pozicionalasa x, y pozicioba (x=oszlop, y=sor)
    push dx             ;hasznalt regiszterek mentese
    push ax
    push bx

    mov dh, y           ;dh-ba kell kerulnie az sorszamnak
    mov dl, x           ;es dl-be kell kerulni a oszlopszamnak
    mov ah, 2h          ;A kettes kod a kurzor pozicionalasa

    xor bh, bh          ;Hasznalt kepernyo lap szama 0
    int 10h             ;képernyő driver hivasa

    pop bx              ;regiszterek visszatoltese
    pop ax
    pop dx
endm

gotoXYRel macro x, y
    push dx             ;hasznalt regiszterek mentese
    push ax
    push bx
    push cx

    mov ah, 03h
    xor bh, bh
    int 10h

    add dh, y           ;dh-ba kell kerulnie az sorszamnak
    add dl, x           ;es dl-be kell kerulni a oszlopszamnak
    mov ah, 2h          ;A kettes kod a kurzor pozicionalasa

    xor bh, bh          ;Hasznalt kepernyo lap szama 0
    int 10h             ;képernyő driver hivasa

    pop cx
    pop bx              ;regiszterek visszatoltese
    pop ax
    pop dx
endm

writeto macro string, x, y ;szoveg kiirasa x, y pozicioba
    gotoxy x, y            ;eloszor pozicionalas
    writem string          ;majd kiiras
endm

read_char proc uses ax  ;egy karakter beolvasasa
    mov ah, 1           ;karakter bekeres kodja
    int 21h             ;hexa 21 -es megszakitas DOS-funkciok hivasahoz
                        ;A karakter ekkor AL regiszterbe kerül
    mov dl, al          ;A karakter-t a DL regiszterbe tesszuk
    ret                 ;visszateres subrutinbol
read_char endp

;dl-ben levo kezdocimtol string kiirasa
write_string proc uses bx dx
    .while byte ptr [bx] != 0
      mov dl, [bx]
      call write_char
      inc bx
    .endw
    ret
write_string endp

;dl-ben varja mit kell kiirni
write_char proc uses ax
    mov ah, 2h	; Kiiras kodja
    int 21h
    ret
write_char endp

;adatszegmens inicializalasa
dsinit proc uses ax  
    mov ax, dgroup   ;adatszegmens kezdocime ax-be
    mov ds, ax       ;ezt betoltjuk az adatszegmens regiszterbe
    ret
dsinit endp

;DOS kepernyo torlese
clrscr proc uses ax
    mov ax, 3  ;3-as bekerul ah-ba. Utasitas kepernyo torlesere
    int 10h    ;hexa 10-es megszakitas. Kepernyo driver hivasara
    ret
clrscr endp

;sortores
linebreak proc
    writem dcrlf
    ret
linebreak endp

lcase proc
    .if (dl >= "A" && dl <= "Z")
        add dl, "a"-"A"
    .endif
    ret
lcase endp

read_block proc uses ax bx cx dx

    writeto txtDiskId, 26, 6
    writeto txtBlockNumber, 20, 7
    
    gotoXY 33, 6
    call read_char
    .if dl == ESCAPE
        mov quit, 1
        ret
    .endif
    call lcase
    sub dl, 'a'
    mov al, dl

    gotoXY 33, 7
    call read_decimal

    lea bx, block
    mov cx, 1 ;beolvasando blokkok száma  
    int 25h
    popf
    ret
read_block endp

out_line_hexa proc uses bx cx dx
    mov cx, 16
    .repeat
        mov dl, block[bx]
        call write_hexa
        mov dl, space
        call write_char
        inc bx
    .untilcxz
    ret
out_line_hexa endp

out_line_char proc uses bx cx dx
    mov cx, 16
    .repeat
        mov dl, block[bx]
        .if dl < space
            mov dl, space
        .endif
        call write_char
        inc bx
    .untilcxz
    ret
out_line_char endp

init_write_block proc
    .if pagenum == (maxPage-1) && lastPageRows
        mov cx, lastPageRows
    .else
        mov cx, rows
    .endif
    add bx, offs
    ret
init_write_block endp

write_block_hexa proc uses cx bx
    call init_write_block
    .repeat
        gotoXYRel hexaPosX, 0
        call out_line_hexa
        call linebreak
        add bx, 16
    .untilcxz  
    ret
write_block_hexa endp

write_block_char proc uses cx bx
    call init_write_block
    .repeat
        gotoXYRel charPosX, 0
        call out_line_char
        call linebreak
        add bx, 16
    .untilcxz  
    ret
write_block_char endp

write_hexa_digit proc uses dx
    .if dl >= 10
        add dl, 'A'-'0'-10
    .endif
    add dl, '0'        
    call write_char
    ret
write_hexa_digit endp

write_hexa proc uses cx dx
    mov dh, dl
    mov cl, 4
    shr dl, cl
    call write_hexa_digit
    mov dl, dh
    and dl, 0Fh
    call write_hexa_digit

    ret
write_hexa endp

read_decimal proc uses ax bx
    mov bx, 10
    xor ax, ax
    xor dx, dx
    
    .while 1
        call read_char
        .break .if dl == cr
        sub dl, '0'
        mul bl
        add ax, dx
    .endw
    mov dx, ax
    ret
read_decimal endp

write_decimal proc uses ax dx cx si
    mov ax, dx
    mov si, 10   ; 10-el osztjuk si-t

    xor cx, cx   ; cx torlese

    .while ax != 0
        xor dx, dx
        div si
        push dx
        inc cx
    .endw

    .repeat
        pop dx
        call write_hexa_digit
    .untilcxz
    ret
write_decimal endp

readCmdKey proc
    mov ah, 00h	
    int 16h
    ret
readCmdKey endp

pager proc uses dx ax
    .if al == 0
      .if (ah == 'H' && pagenum >= 1)
         dec pagenum
      .elseif (ah == 'P' && pagenum < (maxPage-1)) 
         inc pagenum
      .endif
       mov ax, rows*16
       mul word ptr pagenum
       mov offs, ax
    .endif  
    ret
pager endp


hideCursor proc uses ax cx dx bx
    mov ah, 03h
    int 10h
    or ch, 30h
    mov ah, 1
    int 10h
    ret
hideCursor endp

goodbyeProc proc uses ax
    call clrscr
    call hideCursor
    mov al, goodByelength
    shr al, 1
    mov ah, 40
    sub ah, al 
    gotoXY ah, 12
    writem goodbye
    ret
goodbyeProc endp

writeInfo proc uses dx bx

    ;oldal info
    writem txtPage
    xor dx, dx
    mov dl, maxPage
    call write_decimal
    writem_char '/'
    ;oldalszam
    mov dl, pagenum
    inc dl
    call write_decimal
    ret
writeInfo endp

drawBorder proc uses cx ax
    ;felso keret
    gotoXY hexaPosX-1, posY-1
    writem borderTop
    ;kozepso resz
    mov cx, rows
    mov al, posY
    .repeat
       gotoXY hexaPosX-1,al 
       writem_char borderMiddle
       gotoXY hexaPosX+hexaWidth+(charRelPosX/2), al
       writem_char borderMiddle
       gotoXY hexaPosX+borderWidth-2, al
       writem_char borderMiddle
       inc al
    .untilcxz
    ;keret alja
    gotoXY hexaPosX-1, al
    writem borderBottom
    inc al
    ;keret alatti informacios sav
    gotoXY hexaPosX, al
    call writeInfo
    
    gotoXY 0, 0
    ret
drawBorder endp

run_read_block proc uses ax
    call read_block
    .if quit == 1
        ret
    .endif
    mov pagenum, 0
    .repeat
        call clrscr
        call hideCursor
        call drawBorder
        gotoXYRel 0, posY
        call write_block_hexa
        .if pagenum == (maxPage-1) && lastPageRows
            gotoXYRel 0, -lastPageRows
        .else 
            gotoXYRel 0, -rows
        .endif
        call write_block_char                                  
        call readCmdKey
        call pager
        gotoXY 0, 0
    .until al == ESCAPE
   ret
run_read_block endp

main proc
    call dsinit
    call clrscr
    call hideCursor
    
    ;comment *
    .repeat
    .break .if quit == 1
        call clrscr
        call run_read_block
    .until al == ESCAPE
    call goodbyeProc
    call readCmdKey
    ;*
    
    .exit
main endp

end main
