
; hocker1 - Roman Hocke - uloha c. 5
; ==================================

[org 100h]
[segment .text]

; alokovani pameti
; ----------------

		mov       AX, CS		; alokuju pamet
		mov       ES, AX
		mov       AH, 4Ah
		mov       BX, 4000              ; 64000 / 16 = 4000 paragrafu
		int       21h
		jnc       _stinram              ; alokovano?
		jmp	  _konec2               ; ne, tak konec

_stinram:       mov       AX, CS                ; jo, nastavim promenou stinram
		add       AX, 4096
		mov       [stinram], AX

; pritomnost mysi
; ---------------

		mov       AX, 0			
		int       33h
		test      AX, AX                ; je pritomna mys?
		jnz       _grmod                ; ano
		jmp	  _konec2               ; ne, tak konec

; puvodni graf. mod
; -----------------

_grmod:         mov       AH, 0Fh               ; zjistim puvodni graf. mod
                int       10h
	        mov	  [grmod], AL	        ; ulozim ho
		mov       AX, 0013h		; nastavim 320x200x256
		int       10h

; nastaveni mysi
; --------------

		mov       AX, 7			; max. a min. souradnice mysi
		xor       CX, CX
		mov       DX, 321-2*R
		int       33h
		inc       AX
		mov       DX, 201-2*R
		int       33h

; cteni prikazoveho radku
; -----------------------

		mov       SI, 82h		; nactu command line
		mov       BX, filename          ; potrebujeme nastavit jmeno souboru
_nextchar:	mov	  AL, [SI]              ; nactu znak
		cmp       AL, 0dh               ; je to prazdny znak?
		jz        _finish               ; ano, jmeno je cele
		mov       [BX], AL              ; ne, pripisu znak jmena
		inc       BX                    ; a nastavim na dalsi znak
		inc	  SI
		jmp       _nextchar             
_finish:        mov       [BX], byte 0

; pokus o otevreni souboru
; ------------------------

		mov       AX, 3d00h		; budu otevirat jen pro cteni
		mov       DX, filename          
		int       21h
		jnc       _fileopen             ; podarilo se otevrit?
		jmp	  _konec2               ; ne, tak konec
_fileopen:      mov       BX, AX                ; ano, ulozim handle souboru

; cteni ze souboru
; ----------------

		mov       AX, 4200h		; nastavim sluzbu, v BX je ulozen handle
		xor       CX, CX
		mov       DX, 18                ; offset 18, tam zacina paleta
		int       21h

		push      DS			
		mov       AX, [stinram]         ; paletu docasne ulozim do stinove RAM
		mov       DS, AX

		xor       DX, DX
		mov       AH, 3fh               ; nactu celou paletu do stinove RAM
		mov       CX, 768
		int       21h

		xor       AX, AX
		xor       SI, SI
		mov       CX, 256               ; 256 barev

_palnext:	mov       DX, 03c8h             ; port adres graf. karty
                mov       AL, AH                ; index barvy
		out       DX, AL
		inc       DX                    ; port data graf. karty
		inc       AH

                mov       AL, [DS:SI+2]         
		shr       AL, 2                 ; R slozka
		out       DX, AL
		push      AX                    ; ulozim AH (index barvy)
		lodsw                           ; nactu do AH G a do AL B slozku barvy
		push      AX                    ; ulozim AH (B)
		mov       AL, AH                
		shr       AL, 2
		out       DX, AL		; a odeslu G
                pop       AX                    ; obnovim AH (B)
		shr       AL, 2
		out       DX, AL                ; a odeslu
                inc       SI
                pop       AX                    ; obnovim AH (index barvy)
		loop      _palnext

; cteni obrazku do stinove video RAM
; ----------------------------------

		xor       DX, DX
		mov       AH, 3fh
		mov       CX, 64000
		int       21h

		mov       AH, 3eh		; a uzavreme soubor
		int       21h
		pop       DS                    ; a obnovime DS

		call      MAPbuild              ; zavolame proceduru, ktera vytvori mapu lupy

; cteni polohy mysi
; -----------------

_prekresli:	mov       AX, 3h		; nacteme polohu mysi
		int       33h
		mov       BX, CX                ; ulozime si x do BX
		push      BX                    ; ulozime si souradnice
		push      DX

		call      _uloz_vyrez           ; musime si ulozit vyrez, ktery budeme lupit
		call      _lupa                 ; vylupime
		call      _flip                 ; a prekreslime, co mame ve virt scr do graf. pam

_kontrola:	mov       AX, 0bh               ; nacteme relativni zmenu
		int       33h
		test      CX, CX                ; pohnul uzivatel mysi v X?
		jnz       _pohnul               ; jo tak to musime prekreslit
		test      DX, DX                ; pohnul uzivatel mysi v Y?
		jnz       _pohnul               ; jo, prekreslit

                mov       ah, 6
                mov       dl, 0ffh
                int       21h			; zmackl uzivatel klavesu?
                jnz       _konec                ; jo tak budeme koncit

		jmp       _kontrola             ; uzivatl nic nezmack ani nepoh mysi, tak se podivame znova, jestli neco neudelal

_pohnul		pop       DX                    ; uzivatel pohnul mysi, tak vratime souradnice, co jsme lupili
		pop       BX
		call      _obnov_vyrez          ; prekreslime zpet ten vyrez co sme si ulozili
		jmp       _prekresli            ; znova prekreslime lupu

_konec:		pop       DX                    ; uzivatel neco zmacknul, tak si vybereme registry, co sou ulozeny
		pop       BX

_konec2:        xor       AH, AH                ; obnovime puvodni grafickej rezim
		mov       AL, [grmod]
		int       10h
		ret				; a ukoncime program

; okopirovani stinove video RAM do video RAM
; ------------------------------------------

_flip:		push      DS
      		push      word 0A000h
		pop       ES                    ; ES zacatek video ram
		mov       DS, [stinram]         ; DS zacatek stinove RAM
		xor       DI, DI
		xor       SI, SI
		mov       CX, 32000
		rep       movsw                 ; 32000 wordu = 64000 bajtu
		pop       DS
		ret

; ulozeni vyrezu z originalniho obrazku do promenne vyrez, od souradnice BX, DX
; -----------------------------------------------------------------------------

_uloz_vyrez:	push      DS
		push      DX
		push      BX
		mov       SI, DX                ; zjistim zacatek vyrezu
		shl       DX, 8                 ; 2^8 = 256
		shl       SI, 6                 ; 2^6 = 64
		add       SI, DX                ; y*320
		add       SI, BX                ; +x

                push      DS
                pop       ES			; do ES zacatek vyrezu
                push      word [stinram]        ; do DS zacatek stinove RAM
                pop       DS
		mov       DI, vyrez

		mov       CX, 2*R-1             ; velikost mapy y
_uloz_dalsi:	push      CX
		mov       CX, 2*R-1             ; velikost mapy x
		rep       movsb
		add       SI, 321-2*R           ; dalsi radek ve stinove RAM
		pop       CX
		loop      _uloz_dalsi
		pop       BX
		pop       DX
		pop       DS
		ret

; obnoveni puvodniho obrazku pomoci obsahu promenne vyrez
; -------------------------------------------------------

_obnov_vyrez:	push      DS
		push      DX
		push      BX
		mov       DI, DX                ; zjistim zacatek vyrezu
		shl       DX, 8                 ; 2^8 = 256
		shl       DI, 6                 ; 2^6 = 64
		add       DI, DX                ; y*320
		add       DI, BX                ; +x

		push      word [stinram]
		pop       ES
		mov       SI,vyrez

		mov       CX, 2*R-1
_obnov_dalsi:	push      CX
		mov       CX, 2*R-1
		rep       movsb
		add       DI, 321-2*R
		pop       CX
		loop      _obnov_dalsi
		pop       BX
		pop       DX
		pop       DS
		ret

; efekt lupy - z vyrezu do stinove video RAM
; ------------------------------------------

_lupa:		push      DX
		push      BX

		mov       DI, DX                ; zjistim zacatek vyrezu
		shl       DX, 8                 ; 2^8 = 256
		shl       DI, 6                 ; 2^6 = 64
		add       DI, DX                ; y*320
		add       DI, BX                ; +x

		push      word [stinram]
		pop       ES
		mov       SI, map
		mov       BX, vyrez

		mov       CX, 2*R-1
_lupa_y:	push      CX
		mov       CX, 2*R-1
_lupa_x:	lodsw                           ; nactu z mapy offset
		add       BX, AX                ; pripoctu ho
		mov       AL, [DS:BX]           ; barvu na danem pixelu vyrezu...
		stosb                           ; ...zapisu do stinove RAM
		loop      _lupa_x
		add       DI, 321-2*R           ; dalsi radek
		pop       CX
		loop      _lupa_y
		pop       BX
		pop       DX
		ret

; rutina pro vytvoreni mapy lupy
; ------------------------------

MAPbuild	mov       AX, DS
		mov       ES, AX
	        mov       BX, 1-R
		mov       SI, R*R
		mov       DI, map
		mov       BP, -2*R*(R-1)

nok		mov       CX, 1-R
nol		mov       AX, CX
		imul      CX
		push      AX
		mov       AX, BX
		imul      BX
		pop       DX
		add       AX, DX
		cmp       AX, SI
		jc        nor
		mov       AX, BX
		push      CX
		jmp       short nos
nor		mov       DX, 65536*(M-N)/M/N
		mul       DX
		mov       AX, DX
		add       AX, R*R/M
		push      AX
		imul      CX
		idiv      SI
		mov       DX, AX
		pop       AX
		push      DX
		imul      BX
		idiv      SI
nos		mov       AH, 2*R-1
		imul      AH
		pop       DX
		add       AX, DX
		push      AX
		sub       AX, BP
		stosw
		pop       BP
		inc       CX
		cmp       CL, R
		jl        nol
		inc       BX
		cmp       BL, R
		jl        nok
		ret


R	  equ             31                    ; parametry lupy
N	  equ             2
M         equ             3
filename: resb            8                     ; jmeno souboru
grmod:    db              0                     ; puvodni graficky mod
vyrez:    resb            (2*R-1)*(2*R-1)       ; ulozeni vyrezu pred zvetsenim
map:      resw            (2*R-1)*(2*R-1)       ; vlastni mapa, ze ktere pocitame zvetseni
stinram:  dw              0                     ; zacatek virtual screenu
