;================================================================================================== ; TESTOVACÍ PROGRAM PRO ŠIPKU ;================================================================================================== cpu z80undoc org 60000 START di push ix exx push hl ; HL' nutno zachovat kvůli Basicu exx ld a,6 out (254),a call MOUSE ld a,2 out (254),a END exx pop hl exx pop ix ei ret EXIT ld a,1 out (254),a jr END XYIKON db 0,255,0,192 ; x1,x2,y1,y2 (celá obrazovka) dw EXIT db 255 ;================================================================================================== ; KOMPLEXNÍ PROGRAM PRO ČTENÍ KLÁVESNICE, AMIGA MYŠI A K-MOUSE ;================================================================================================== ; ; Stručný princip: ; ; - Vezmi původní souřadnice, spočítej adresu na obrazovce (MOUSE_XY). ; - Vykresli šipku na obrazovku, zároveň ulož co bylo pod ní. ; - pracuj vstup ze zvoleného HID a spočítej nové souřadnice. ; - Zapiš nové souřadnice. ; - Zapiš stav tlačítek HID (proměnná MOUSE_B) ; - Čekej na přerušení. ; - Smaž šipku a místo ní vykresli původní obsah obrazovky. ; - Opakuj celý proces dokud není stisknuto tlačítko fire. ; - Zjisti jestli a na jakou ikonu bylo kliknuto, jinak opakuj. ; - Skoč na obslužnou rutinu ikony (JP). ; ; Význam bitů proměnné MOUSE_B: ; ; bit 0 = klávesa 1, nebo levé tlačítko myši ; bit 1 = klávesa 2, nebo pravé tlačítko myši ; bit 2 = klávesa 3, nebo prostřední tlačítko myši ; ; další tlačítka nejsou definována %00000xxx - horní bity jsou vždy 0 ; ; update (spíše jen úvaha do budoucna): ; bit 3 = kolečko myši nahoru?, resp. tlačítko 4 ; bit 4 = kolečko myši dolu, resp. tlačítko 5 ; bit 5 = tlačítko 6, resp. tlačítko pod kolečkem myši MOUSE_X equ MOUSE+2 ; poslední známé souřadnice šipky MOUSE_Y equ MOUSE+1 MOUSE_XY equ MOUSE_Y ; 16ti bitové souřadnice MOUSE_T equ MOUSE_S+1 ; typ zařízení 0=KEYS, 1=AMOUSE, 2=KMOUSE MOUSE_B equ MOUSEBUTT+1 ; stav tlačítek MOUSE_KS equ MOUSEKS ; KEYSTEP, velikost kroku při ovládání pomocí kláves MOUSE ld hl,96+128*256 ; souřadnice šipky X do L, Y do H push hl ; náhrada za neexistující instrukci ld bc,hl pop bc ; takže X je v C, Y v B ld ix,MSIPKA ; do IX adresu spritu exx ld hl,MSIPKA_B ; do HL' adresu bufferu na pozadi sipky exx ld a,b ; vezmi Y-ovou souradnici (jaký význam má v A?) call 8881 ; ze souřadnic v BC spočítej adresu ve VRAM do HL ld (MOUSEC+1),hl ; ulož tuto adresu, bude užitečná při mazání šipky ld (MOUSE2+1),a ; toto cislo budu odecitat, co znamena ???? ; vykreslení šipky - pochází z knihy Assembler a ZX Spectrum II, komentáře jsem přepsal ld b,15 ; sprite šipky je vysoký 15 pixelů (mimochodem široký je 1 byte) MOUSE1 push bc ; ulož kolik opakování - mikrořádků zbývá push hl ; dvakrát ulož adresu šipky ve VRAM, na kterou se bude kreslit push hl ld h,0 ; do H ulož 0, sem se bude rotovat sprite/maska, pokud to bude třeba ld l,(ix+0) ; do L přečti byte spritu ld d,h ; vynuluj D (to samé jako H) ld e,(ix+15) ; do E přečti byte masky inc ix ; posuň ukazatel na grafiku spritu ld a,8 ; rotovat můžu nejvýše 8x MOUSE2 sub 0 ; od počtu rotací odečtu počet rotací vlevo a získám počet rotací vpravo ld b,a ; počet rotací vpravo si uložím do B MOUSE3 add hl,hl ; HL *= 2 (náhrada rr hl) ex de,hl ; prohoď HL a DE (add de,de taky bohužel neexistuje) add hl,hl ; HL *= 2 (náhrada rr de) ex de,hl ; HL a DE prohoď zase zpátky djnz MOUSE3 ; jednobytový sprite a maska jsou uloženy v HL a DE posunuté jak je třeba ex (sp),hl ; prohoď poslední hodnotu v zásobníku (adresa šipky ve VRAM) a obsahem HL pop bc ; do BC tak ze zásobníku vyzvednu odrotovanou předlohu ld a,(hl) ; do A načtu původní obsah obrazovky exx ld (hl),a ; uložím na (HL') - adresa bufferu na původní pozadí (1. levý byte, budou dva) inc hl ; posunu ukazatel do bufferu exx ld a,d ; vezmu do a pravou část masky cpl ; invertuju ji (kdybych ji uložil už invertovanou, měl bych problém s rotací) and (hl) ; a z pozadí vymažu ty pixely, kde měla maska 0 or b ; a do vykousnutého pozadí zaoruju předlohu ld (hl),a ; a nakonec uložím do VRAM ; call RIGHTL ; spočítej adresu o byte vpravo inc hl ld a,(hl) ; celé kreslení provedu ještě jednou pro 2. byte více vpravo exx ld (hl),a inc hl exx ld a,e cpl and (hl) or c ld (hl),a pop hl ; obnov adresu levého bytu ve VRAM call DOWNHL ; spočítej adresu o pixel níž pop bc ; obnov počítadlo djnz MOUSE1 ; a opakuj, dokud nejsou vykresleny všechny mikrořádky šipky ; volba polohovacího zařízení 0=KEYS, 1=AMOUSE, 2=KMOUSE MOUSE_S ld a,0 or a jp z,MOUSEB ; A=0 ; Buttons - klávesy dec a jp z,MOUSEA ; A=1 ; Amiga mouse (myška z Amigy zapojená do UR-4) dec a jp z,MOUSEK ; A=2 ; ruská Kempston mouse vracející přímé souřadnice ; v ostatních případech čtu klávesy ;-------------------------------------------------------------------------------------------------- ; ZMĚNA SOUŘADNIC [X,Y] pomocí klávesnice ;-------------------------------------------------------------------------------------------------- MOUSEB call MOUSRKEY ; prečti porty definovaných kláves, v D bude stav testovaných kláves ld hl,(MOUSE_XY) ; do HL přečti souřadnice šipky MOUSEKS ld c,2 ; velikost kroku šipky, o kolik se šipka pohne při stisku klávesy bit 5,d ; testování 1. klávesy (UP) jr z,MOUSEB1 ; Z = klávesa nebyla stisknuta => přeskoč zpracování ld a,h ; vezmi z H Y-ovou souřadnici sub c ; odečti krok posunu ld h,a ; ulož novou Y-ovou souřadnici do H jr nc,MOUSEB1 ; nedošlo-li k podtečení, přeskoč korekci ld h,0 ; C = šipka narazila do horního okraje => proveď korekci, aby neprošla MOUSEB1 bit 6,d ; testování 2. klávesy (DOWN) jr z,MOUSEB2 ; Z = klávesa nebyla stisknuta => přeskoč zpracování ld a,h ; vezmi z H Y-ovou souřadnici add a,c ; pričti krok posunu ld h,a ; ulož novou Y-ovou souřadnici do H cp 189 ; a otestuj jestli šipka neprošla dolním okrajem jr c,MOUSEB2 ; není-li souřadnice větší než 189, přeskoč korekci ld h,190 ; C = šipka narazila do dolního okraje => proveď korekci, aby neprošla MOUSEB2 bit 3,d ; testování 3. klávesy (LEFT) jr z,MOUSEB3 ; Z = klávesa nebyla stisknuta => přeskoč zpracování ld a,l ; vezmi z L X-ovou souřadnici sub c ; odečti krok posunu ld l,a ; ulož novou X-ovou souřadnici do L jr nc,MOUSEB3 ; nedošlo-li k podtečení, přeskoč korekci ld l,0 ; C = šipka narazila do levého okraje => proveď korekci, aby neprošla MOUSEB3 bit 4,d ; testování 4. klávesy (RIGHT) jr z,MOUSEB4 ; Z = klávesa nebyla stisknuta => přeskoč zpracování ld a,l ; vezmi z L X-ovou souřadnici add a,c ; přičti krok posunu ld l,a ; ulož novou X-ovou souřadnici do L cp 252 ; a otestuj jestli šipka neprošla pravým okrajem jr c,MOUSEB4 ; není-li souřadnice větší než 252, přeskoč korekci ld l,252 ; C = šipka narazila do pravého okraje => proveď korekci, aby neprošla MOUSEB4 ld a,d ; vezmi do A stav prečtených kláves and 00000111b ; ponech jen bity, které označují tlačítka jako fire (jako tlač. myši) ld (MOUSE_B),a ; a stav tlačítek zapiš do proměnné MOUSE_B ld (MOUSE_XY),hl ; ulož nové souřadnice šipky pro příští použití jp MOUSE50 ; Rutina na čtení kláves z knihy "Assembler a ZX Spectrum 2" ; Může být společná pro klávesu a Kempston joystick (nemá s ruskou Kempston Myší nic společného, jen jméno) MOUSRKEY ld hl,MOUSEKTAB ; vezmi adresu tabulky kláves ld de,7 ; v E je počet kláves a v D bude výsledek (1 = stisknuto) MOUSRK1 ld c,(hl) ; do BC prečti z tabulky adresu portu inc hl ld b,(hl) inc hl in a,(c) ; prečti port (BC - 16ti bitové adresování) bit 7,c ; otestuj bit 7, u kempston joysticku je tam vždy 0 (leda by byl vadný) jp z,MOUSRK2 ; přeskoč CPL jedná-li se o Kempston joystick cpl ; 1 = klávesa stisknuta (normálně to je u kláves obráceně) MOUSRK2 and (hl) ; ponech jen testovaný bit (filtrace tabulkou) inc hl ; a posuň HL na začátek dalšího řádku tabulky jr z,MOUSRK3 set 7,d ; nastav bit 7 na 1 MOUSRK3 srl d ; a posuň ho dolů (tím se do D postupně uloží stav všech kláves) dec e ; sniž počítadlo portů k prečtení jr nz,MOUSRK1 ; opakuj dokud není vše přečteno ret ; Tabulka kódů kláves, kterou je možné měnit - první 2 byty jsou adresou portu, 3. byte je bitový filtr. ; Tímto způsobem je možno definovat i Kempston joystick, ale není možné ho rozumně detekovat, pokud je ; zároveň připojena amiga mouse, uživatel musí sám rozhodnout co chce používat, nejlépe stiskem klávesy. ; Kempston joystick a klávesy je samozřejmě možné libovolně kombinovat, i když to asi není praktické. MOUSEKTAB db 254, 127, 00000100b ; FIRE 1 (M) db 254, 127, 00001000b ; FIRE 2 (N) db 254, 127, 00010000b ; FIRE 3 (B) db 254, 223, 00000010b ; LEFT (O) db 254, 223, 00000001b ; RIGHT (P) db 254, 251, 00000001b ; UP (Q) db 254, 253, 00000001b ; DOWN (A) ;-------------------------------------------------------------------------------------------------- ; ZMĚNA SOUŘADNIC [X,Y] pomocí AMIGA MOUSE ;-------------------------------------------------------------------------------------------------- ; Pozor! Interface s MHB8255 je nutné inicializovat mimo tento program. MOUSEA ld bc,130*256 ; B = počet průchodů čtecí smyčkou (rozumný kompromis) ld a,(MOUSE_X) ; souřadnice se budou uvnitř smyčky měnit a je lépe budou-li operandem ld (MOUSAX+1),a ld a,(MOUSE_Y) ld (MOUSAY+1),a MOUSEA1 push bc ; uloz BC do zasobniku - zde zacina smycka ld b,c ; a do B ????? in a,(31) ; čti port ld de,MOUSEAP ; pomocná proměnná call MOUS_SM ; zjisti jakym smerem se mys pohnula MOUSAX ld a,77h ; vezmi souradnice mysi add a,(hl) jr z,MOUSAKX ; Z = preskoc zapis X-ove souradnice ld (MOUSAX+1),a MOUSAKX inc de in a,(31) ; čti port rrca ; posun o 1 bit vpravo, kvuli detekci smeru call MOUS_SM ; a ted se da pouzit stejna rutina jako pro X MOUSAY ld a,60h ; vezmi starou Y-ovou souradnici add a,(hl) ; a pricti cislo prectene z tabulky jr z,MOUSAKY ; Z = preskoc zapis a korekci Y-ove souradnice cp 192 ; otestuj jestli sipka neprosla spodnim okr. jr nz,MOUSADO ; pokud prosla (Z) ld a,191 ; proced korekci MOUSADO ld (MOUSAY+1),a ; zapis novou Y-ovou souradnici MOUSAKY pop bc ; obnov pocitadlo pruchodu djnz MOUSEA1 ; a opakuj pokud tento nebyl posledni ld a,(MOUSAX+1) ; zapis nove souradnice do promennych ld (MOUSE_X),a ld a,(MOUSAY+1) ld (MOUSE_Y),a in a,(31) ; naposledy precti port mysi rra rra rra rra and 00000111b ; ponech jen bity tlacitek ld (MOUSE_B),a jp MOUSE50 MOUS_SM and 5 ; testuje jakym smerem se amiga mys pohnula ld c,a ; na zaklade Karnaughovych map ld a,(de) rlca and 10 or c ld (de),a ld c,a ld hl,MOUSTAB add hl,bc ret MOUSTAB db 0,255,1,0 ; tabulka kódů pro výpočet pohybu AMOUSE db 1,0,0,255 db 255,0,0,1 db 0,1,255,0 MOUSEAP dw 0 ; promenna tykajici se vyhradne detekce smeru ; pohybu AMIGA MOUSE ;-------------------------------------------------------------------------------------------------- ; ZMENA SOURADNIC [X,Y] pomocí KMOUSE (Ruská verze - později i od Velesofta) ;-------------------------------------------------------------------------------------------------- ; .... OTESTOVAT V PRAXI! MOUSEK ld a,251 ; cti X-ovou souradnici z portu 64479 in a,(223) ld (MOUSE_X),a ; uloz pro pristi zavolani programu MOUSE ld a,255 in a,(223) ; cti Y-ovou souradnici z portu 65503 cpl ; u souradnice Y nam nevyhovuje hodnota nad 192 cp 191 ; takze provedu jednoduchou korekci jp c,MOUSEKK ; IF A>191 THEN A=191 ld a,191 MOUSEKK ld (MOUSE_Y),a ; a uloz pro dalsi volani programu MOUSE ld a,250 ; cti port 64223 - BUTTONS in a,(223) ; ale ziskal jsem nevhodny zpusob ulozeni stavu cpl ; takze zase provedu korekci, nejdrive neguju and 00000111b ; byte a pak z nej necham jen dolni 3 bity ld b,a ; zalohuju do B a ted prehodim bit 0 a bit 1 rla ; bit 0 v A posunu na pozici bitu 1 and 00000010b ; ponecham jen bit 1 ld c,a ; a ulozim do C ld a,b ; znovu vezmu puvodni byte rra ; posunu bit 1 v A na pozici bitu 0 and 00000001b ; ponecham jen bit 0 or c ; pridam bit 1 ulozeny v C ld c,a ; ted budu mit v C ulozene prehozene bity 0 a 1 ld a,b ; naposledy vezmu puvodni byte and 00000100b ; ponecham z nej jen bit 2 or c ; pridam k nemu bity 0 a 1 ld (MOUSE_B),a ; ulozim do pameti a je hotovo jp MOUSE50 ; Před HALT (za MOUSE50) je možno přidat automatickou detekci polohovacího zařízení a ; následnou změnu proměnné MOUSE_T. V dalším volaní pak bude takto zvolené zařízení ; normálně používáno. ; autodetect KEYBOARD - Je-li stisknuta klávesa přepne se ovladač na čtení klávesnice, užitečné ; pokud uživatel potřebuje z jakéhokoliv důvodu ovládat program klávesnicí ; ale byla zvolena myš. ; xor a ; ctu port 0*256+254 ; in a,(254) ; cpl ; and %00011111 ; ponecham dolnich 5 bitu ; jr nz,MOUSE50 ; ld a,0 ; do A cislo odpovidajici klavesnici ; ld (MOUSE_T),a ; a zapisu ho do promenne MOUSE_T ; autodetect AMIGA MOUSE - Amiga mouse se oproti Kempston joysticku liší tím, že u ní mohou běžně ; nastat log. 1 na bitech, které u joysticku znamenají protilehlé směry, ; takže je není možno zvolit bez jeho mechanického zničení. ; Bohužel detekce nemůže být 100% spolehlivá, ačkoli většinou funguje. ; in a,(31) ; čti port na němž je připojena myš ; bit a,7 ; je-li bit 7 log. 1 pravděpodobně port 31 není funkční ; jp nz,MOUSE50 ; takže zbytek rutiny přeskoč ; and %101 ; tyto bity nemohou být nikdy v log. 1 pokud ; cp %101 ; je připojen jenom Kempston joystick ; jp nz,MOUSE50 ; Z = bity byly v log. 1 => myš je pravděpodobně připojena ; ld a,1 ; do A číslo odpovídající amiga myši ; ld (MOUSE_T),a ; a zapíšu ho do proměnné MOUSE_T ; Jak jednoduše detekovat KEMPSTON MOUSE nevím! ; Jak jednoduše detekovat KEMPSTON joystick nevím (resp. vím, ale ne v kombinaci s Amiga mouse)! MOUSE50 ei ; povolím přerušení, pokud náhodou povolené nebylo halt ; a počkám na něj (paprsek začíná kreslit obrazovku) ; případný zákaz přerušení si přidejte sami ; smazání šipky a vykreslení původního obsahu obrazovky MOUSEC ld hl,0 ; do operandu je místo 0 zapisována adresa šipky ve VRAM ld b,15 ; počet pixelů na výšku ld de,MSIPKA_B ; adresa uloženého původnho pozadí pod šipkou MOUSEC1 ld a,(de) ; vezmu byte z původního pozadí ld (hl),a ; a zapíšu ho do VRAM inc de ; posunu DE o 1 push hl ; zapamatuju HL call RIGHTL ; a spočítám adresu HL o byte vpravo (inc HL nestačí, kus šipky může zmizet) ld a,(de) ; vezmi další byte z původního pozadí ld (hl),a ; a zapíšu ho do VRAM inc de ; posunu DE o 1 pop hl ; obnovím v HL adresu levého bytu call DOWNHL ; a z ní spočítám adresu o pixel níž djnz MOUSEC1 ; opakuj tolikrát, kolik pixelů na výšku šipka má MOUSEBUTT ld a,0 ; vezmi stav stisknutí tlačítek or a ; 0 = žádné nebylo stisknuto jp z,MOUSE ; pokud nebylo tlačítko stisknuto, opakuj činnost celého programu ret ; nějaké tlačítko bylo stisknuto, vrať se, záleží na programu ; využívajícím šipku jak tlačítka zpracuje (tím může být NOIKON) ;-------------------------------------------------------------------------------------------------- ; GRAFIKA ;-------------------------------------------------------------------------------------------------- MSIPKA db 00000000b ; sprite šipky db 01000000b db 01100000b db 01110000b db 01111000b db 01111100b db 01111110b db 01111000b db 01001000b db 00001000b db 00000100b db 00000100b db 00000010b db 00000010b db 00000000b MSIPKA_M db 11100000b ; maska šipky - musí následovat hned za spritem db 11110000b db 11111000b db 11111100b db 11111110b db 11111111b db 11111111b db 11111111b db 11111100b db 11111110b db 00011110b db 00001111b db 00001111b db 00000111b db 00000111b MSIPKA_B ds 30 ; sem se ukládá z VRAM to co šipka překryla ;-------------------------------------------------------------------------------------------------- ; PODPŮRNÉ RUTINY ;-------------------------------------------------------------------------------------------------- RIGHTL ld a,l ; RIGHTL zajištuje posun adresy spritu ve inc l ; VRAM o byte vpravo a jeho spravné vykreslení, xor l ; pokud je jeho levá půlka přímo u pravého bit 5,a ; okraje obrazovky. V takovém případě se ret z ; pravá půlka kreslí do ROM, takže vlastně ld h,0 ; nekreslí / BACHA NA WRITEABLE ROMky!! (nahradit 0 číslem 60, poškodí font) ret ;================================================================================================== ; RUTINA, KTERÁ ZAVOLÁ ŠIPKU A VOLÁ JI TAK DLOUHO DOKUD UŽIVATEL NEKLIKNE ; NA NĚKTEROU PLATNOU IKONU (POLOHA DEFINOVANÁ V TABULCE). V TOM OKAMŽIKU ; RUTINA SKOČÍ NA ADRESU PŘÍSLUŠNÉ RUTINY, KTERÁ IKONĚ ODPOVÍDÁ. ;================================================================================================== NOICON call MOUSE ; zavolej program pro obsluhu HID a kreslení šipky na obrazovku ; rutinu NOICON možno volat pomocí CALL a instrukci ; RET umístit do rutiny reagující na kliknuti na ikonu TSTXY ld de,(MOUSE_XY) ; souřadnice šipky do DE (D = X, E = Y) ld bc,6 ; do BC délku souřadnic v tabulce ikon a adresy příslušné rutiny ld ix,XYIKON-6 ; do IX adresu tabulky ikon a adres rutin mínus jednu položku TSTXY_1 add ix,bc ; pričti BC k registru IX ld a,(ix+0) ; čti X1 cp 255 ; porovnej s 255 - znamená konec tabulky jr z,NOICON ; je-li 255 (Z) nebylo kliknuto na ikonu a bude opakováno kreslení šipky ld a,(ix+0) ; jinak porovnávej dál, dokud není nalezena ikona, nebo konec tabulky cp d jr nc,TSTXY_1 ld a,(ix+1) cp d jr c,TSTXY_1 ld a,(ix+2) cp e jr nc,TSTXY_1 ld a,(ix+3) cp e jr c,TSTXY_1 ld h,(ix+5) ; bylo kliknuto na nějakou ikonu, takže ld l,(ix+4) ; přečti do HL adresu obslužné rutiny jp (hl) ; a skoč na tuto adresu ; TOTO JE JEN UKAZKA - takovato tabulka by mela byt soucasti programu ; ;XYIKON db 0,16,0,16 ; x1,x2,y1,y2 ; defw EXIT_I ; adresa vykonne rutiny ; db 255 ; konec tabulky ikon (NUTNE! Nikdy nesmí chybět!) ; ;EXIT_I ; priklad ; ret ;================================================================================================== DOWNHL inc h ld a,h and 7 ret nz ld a,l add a,32 ld l,a ld a,h jr c,DOWNHL2 sub 8 ld h,a DOWNHL2 cp 88 ret c ld h,0 ; if bottom margin was reached draw sprite in read only ROM ret ;==================================================================================================