Diky za clanek! Jeste jsem to nedocetl, ale nedalo mi ukazat u tretiho prikladu maly trik.
To ze jsi to dal do maker, je asi prehlednejsi co to ma delat, ale ne jak to dela a pak ti snadno uniknou optimalizace.
Takhle to vypada kdyz provedu makra:
next_key:
srl a ; přesunout kód stisku klávesy do příznaku carry
jr nc, key_pressed ; test stisku klávesy
ld (hl), WHITE_COLOR << 3
inc hl
jr next ; test další klávesy
key_pressed:
ld (hl), INTENSITY_BIT | (RED_COLOR << 3)
inc hl
next:
djnz next_key ; opakovat celou smyčku 5x
1 bajt usetrim kdyz zamenim dvoubajtove "srl a" za treba "rra", pokud me zajima jen carry.
1 bajt usetrim kdyz si uvedomim, ze obe vetve provadi spolecny kod "inc hl"
next_key:
rra ; přesunout kód stisku klávesy do příznaku carry
jr nc, key_pressed ; test stisku klávesy
ld (hl), WHITE_COLOR << 3
jr next ; test další klávesy
key_pressed:
ld (hl), INTENSITY_BIT | (RED_COLOR << 3)
next:
inc hl
djnz next_key ; opakovat celou smyčku 5x
Tim jsem se dostal do situace, kdy obe vetve maji jen 2 bajty a tak lze proves jeste dalsi optimalizaci a usetrit jeden bajt tim, ze zamenim "jr next" za 3 bajtovy jp. Trik je v tom, ze nastavim priznaky tak, ze se nikdy neprovede a adresa skoku bude kod druhe vetve. Podobneho efektu lze docilit ze si zaspinim nejaky dvouregistr napr "ld DE,xxxx", ale tady mam jasne definovany stav priznaku takze to jde udelat ciste.
next_key:
rra ; přesunout kód stisku klávesy do příznaku carry
jr nc, key_pressed ; test stisku klávesy
ld (hl), WHITE_COLOR << 3
db 0xD2 ; jp nc,nn
key_pressed:
ld (hl), INTENSITY_BIT | (RED_COLOR << 3)
next:
inc hl
djnz next_key ; opakovat celou smyčku 5x
Tohle by se dalo jeste prepsat, ze zrusim uplne to "jr nc" a "jp" a umistim za prvni vetev, ktera se vykona vzdy opacny priznak, aby se druha vetev vykonala jen kdyz ma. Tim by se usetril dalsi bajt.
next_key:
rra ; přesunout kód stisku klávesy do příznaku carry
ld (hl), WHITE_COLOR << 3
jr c, next ; test stisku klávesy
ld (hl), INTENSITY_BIT | (RED_COLOR << 3)
next:
inc hl
djnz next_key ; opakovat celou smyčku 5x
Tohle ma ale hacek! Bude to videt, protoze sahame do atributove pameti v nahodnem case a nekdy trefime paprsek a tak se nam muze u zobrazeni objevit bila cara. Bude se to chvet. Udelame 3 barvy v jednom znaku, kdybychom to spravne sesynchronizovali s paprskem.
Pekne, tohle je jako evoluce toho posledniho reseni, aby to neblikalo? .)
Kdyz se zameni registr A za napr. E tak to bude funkcni, protoze A si drzi stav toho radku/sloupce matice klaves..
Porovnal jsem to s predposlednim, protoze oba maji 11 bajtu a JP reseni je rychlejsi.
JP:
White: 7+10+10=27
Red: 12+10=22
White: 7+12+7=26
Red: 7+7+7+7=28
Jo mas pravdu, dobry postreh. Dopredu vedet, ktere vetve jsou pravdepodobnejsi je dalsi informace diky ktere muze mit clovek navrh nad prekladaci (aspon na Z80, pokud to neni neco jako java).
Ale realne v tomto pripade to nic nezmeni, protoze se ten atribut stejne prepise...ted to jeste spocitat
;[: 8*(52+225)=2216+200?] 1448x pomala vetev ;[: 8*(52+250)=2416+200?] 1337x rychla vetev
nez se to jednou prekresli na obrazovce.
Tohle teda plati pro tu moji verzi ve smycce. To +200 si cucam z prstu, protoze nemam tuseni o kolik se to zpomali tim ze se saha pod 0x8000.
Dal jsem, ze misto ld (HL),nn 2:10 to je 2:15. A 5*(5*8)=200
Pridal jsem do kodu mensi zpomaleni o 176 taktu pro nastaveni barvy pozadi
ld A, 7 ; 2:7 zx_border
and B ; 1:4 zx_border
out (254),A ; 2:11 zx_border 0=blk,1=blu,2=red,3=mag,4=grn,5=cyn,6=yel,7=wht
;[: 8*(52+225)=2216+200?+176] 70000/2592=27.007x
;[: 8*(52+250)=2416+200?+176] 70000/2792=25.072x
jp keypress ; 3:10 další test stisku kláves
A vysledek je asi 22x a 20x? oproti vypoctu 27x a 25x.
Fast:
https://ibb.co/bmRqnYk
Slow:
https://ibb.co/18GVBkS
PS: U te slow (puvodni verze) je zajimavy efekt jak se stiskne klavesa. Bez ni se ty pruhy pomalu pohybuji nahoru a po stisku to zacne ruzne klesat a nebo zase stoupat.
18. 5. 2023, 21:55 editováno autorem komentáře
Prepsal jsem jeste posledni program z kapitoly 15 do smycky. Takze jsem to stahnul ze 168 bajtu na 90 bajtu.
ENTRY_POINT equ $8000
ROM_CLS equ $0DAF
org ENTRY_POINT
BLINK_BIT equ %10000000
INTENSITY_BIT equ %01000000
BLACK_COLOR equ %000
BLUE_COLOR equ %001
RED_COLOR equ %010
MAGENTA_COLOR equ %011
GREEN_COLOR equ %100
CYAN_COLOR equ %101
YELLOW_COLOR equ %110
WHITE_COLOR equ %111
start:
call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen)
ld BC, str_keys_size ; 3:10 print Length of string
ld DE, str_keys ; 3:10 print Address of string
call 0x203C ; 3:17 print Print our string with ZX 48K ROM
ld bc, 0xfef0 ; adresa portu, ze kterého budeme číst údaje
ld hl, 0x5800 ; adresa, od které budeme měnit barvové atributy
keypress:
in a, (c) ; vlastní čtení z portu (5 bitů)
ld e, 5 ; počet atributů + počet testovaných kláves
next_key:
rra ; přesunout kód stisku klávesy do příznaku carry
jr nc, key_pressed ; test stisku klávesy
ld (hl), WHITE_COLOR << 3
db 0xD2 ; jp nc,nn
key_pressed:
ld (hl), INTENSITY_BIT | (RED_COLOR << 3)
next:
inc l
dec e
jr nz, next_key ; opakovat celou smyčku 5x
ld a, l
add a, 32-5
ld l, a
rlc b
jp keypress ; další test stisku kláves
str_keys: ; layout klávesnice z pohledu čipů ZX Spectra
NEW_LINE equ 13
DB "^ZXCV", NEW_LINE
DB "ASDFG", NEW_LINE
DB "QWERT", NEW_LINE
DB "12345", NEW_LINE
DB "09876", NEW_LINE
DB "POIUY", NEW_LINE
DB $7f, "LKJH", NEW_LINE
DB "_", $60, "MNB"
str_keys_size equ $-str_keys
end ENTRY_POINT
PS: U Fuse mam problem, ze me to nebere u ceske klavesnice cisla a naopak u anglicke to v basicu vyvolava spatne prikazy.
PPS: Jinak muj notebook zvladne ASDW (asi optimalizovano) + napriklad C+K+T a + space
One ten kod je napsany velmi chytre a vysledek vypada efektivne. V podstate nezjistuje co si zmackl, ve smyslu ze zjistujes co ti uzivatel stiskl a mas znak.
50x za vterinu ti probehne prekresleni obrazovky.
Pres to jedno prekresleni ti hodnekrat probehne ta smycka co ti nastavi atribut pri stisku.
Takze nic dalsiho nemusis a obraz bude vypadat stabilne.
Jestli pred zacatkem stisku tam probehne nejaky zakmit co by pri spatnem zpusobu cteni vyvolal opakovane zmacknuti, zda je tlacitko stale drzeno nebo opakovane rychle mackano atd. Vubec nic te nemusi zajimat, v nejhorsim moznem scenari ti to jednou blikne na 1/50s pri stisku a jednou pri uvolneni.
PS: Ke vsemu to ani netestujeme na realnem ZX, ale emulatoru.
Tak me napadlo - nektere spectracke hry se pri ovladani klavesnici daji ovladat hodne kombinacemi klaves. Myslel jsem si, ze je to tak naprogramovano, ale ted me napada, jestli tu klavesnici nectou nejakym trikem - ze napriklad povoli vic adresovych linek zaraz a proste se nesnazi o rozeznani vsech klaves, ale jen toho, ve kterem radku (0-4) jsou. Je to tak?
K te hadance v 14. kapitole se jeste nikdo nevyjadril:
.)08Z an( utkat 23=)01-41(*8=01*8-)7*8+7*8( o kedelsyv olilamops ela ,utjab 6=)2+8*2(-8*3 olirtesu yb oT .enitur v taled edub es H a rtsiger L nej ivatsan ecazilaicini ez ,kat ot tiledzor a "0085x0 lh" s i taledu sezum elhot elA
. ":noitceted_sserpyek" az denh sitsimu ot dukop cebuv tadirp olemen ot yb ytkat a x8 salov ot zydk ,utjab 8*2 tirtesu olem ot yb ezkaT
."ef$+trop*652,cb,dl" ohisjenvitkefe itizuop otsim itumjyv an enevarpirp ecnokod sam zu ot ezotorP
.yniturbus od inezolv a ecazilaicini z "ef$ ,c dl" ytondoh intnatsnok itumjyv ilsym an sam ez ,milsym is aJ
Jen zpusob jak nekomu nechtene nevyzradit mozne reseni hadanky. a mel sanci si na to prijit sam. Kdybych to chtel "sifrovat" tak bych zvolil
-<<<--<++<---<--<---<+++<+++++++++[>----->+>->>>---->+>-><[>++++++++++++<<]>-]>[.>]
=
+++++++++[>++>+++++>+++++++>++++>++++++>+>+>++++>++>++++[-<]>]>+[>--->>+>>+++++>+>+++>+++>++<[>++++++<<]>-]>[.>]
=
++[<-<<<<++<<<<<+++[>+]>-------]<++++[<-<---<++<-<<-<---<+<--[>]<-]<+<+<-<<<-<-<<[.>]
=
++[<+<+<+<+++<+<+<+<+<+++[>]<-------]++++[<-<---<++<-<<-<---<+<--[>]<-]<+<+<-<<<-<-<<[.>]
To by pak bylo o neco slozitejsi, zvlast kdybych nechal jen nejkratsi reseni, to by uz nebylo tak zadarmo a spustu lidi by to vyselektovalo (az na ty co by nasli francouzske stranky).
Zkouším si příklady, a všiml jsem si že v prvních dvou příkladech se před in a, (c) vkládá do regisru C hodnota F0 a v posledním FE. Funguje obojí, zkoušel jsem i jiné hodnoty: F2 funguje, F1 nefunguje. (adresa musí být sudá?) Jaká je tedy správná hodnota portu?
Jestli jsem to ze schématu správně pochopil, tak jde o osmibitovou adresu vstupního portu který je součástí ULA a využívá se triku že vyšší část adresní sběrnice se použije pro výběr sloupce, což je pěkný trik.
Zkusil jsem si napsat podprogram pro získání kodu klavesy. V akumulátoru je vrácen poziční kod - není to nijak zvlášt optimalizované. Formát je 5 bitů sloupec a 3 bity číslo řádku.
keyb: push bc ;A - kod klavesy
push de
ld d,8 ;pocitadlo radku
ld c,0xF0 ;adresa portu
ld b,0xFE ;adresa prvniho radku
keyb01: in a,(c) ;nacteni portu
cpl ;negace
and 0x1F ;nastaveni hornich bitu
jp nz,keyb02 ;je stisknuta
ld a,b ;adresa dalsiho radku
rla
ld b,a
dec d ;pocitadlo radku
jp nz,keyb01 ;dalsi radek
pop de
pop bc
ret ;neni stisknuta zadna (A=00)
keyb02: rla ;nalezena prvni stisknuta klavesa
rla ;posun o 3 bity
rla
dec d
add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
Pro otestovvání kodů klaves jsem využil "print_hex_number"
ENTRY_POINT equ $8000
ROM_OPEN_CHANNEL equ $1601
AT equ $16
;-------------------------------------------------------------------------------
GOTO_XY macro X,Y
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
ZNAK_XY macro X,Y,kod
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, kod ; kód znaku '*' pro tisk
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
org ENTRY_POINT
start:
ld A,2 ; číslo kanálu
call ROM_OPEN_CHANNEL ; otevření kanálu číslo 2 (screen)
main: GOTO_XY 5,5
call keyb
call print_hex_number
jp main
;-------------------------------------------------------------------------------
keyb: push bc ;A - kod klavesy
push de
ld d,8 ;pocitadlo radku
ld c,0xF0 ;adresa portu
ld b,0xFE ;adresa prvniho radku
keyb01: in a,(c) ;nacteni portu
cpl ;negace
and 0x1F ;nastaveni hornich bitu
jp nz,keyb02 ;je stisknuta
ld a,b ;adresa dalsiho radku
rla
ld b,a
dec d ;pocitadlo radku
jp nz,keyb01 ;dalsi radek
pop de
pop bc
ret ;neni stisknuta zadna (A=00)
keyb02: rla ;nalezena prvni stisknuta klavesa
rla ;posun o 3 bity
rla
dec d
add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
;-------------------------------------------------------------------------------
print_hex_number:
push AF ; uschovat A pro pozdější využití
rrca ; rotace o čtyři bity doprava
rrca
rrca
rrca
and $0f ; zamaskovat horní čtyři bity
call print_hex_digit; vytisknout hexa číslici
pop AF ; obnovit A
and $0f ; zamaskovat horní čtyři bity
call print_hex_digit; vytisknout hexa číslici
ret ; a návrat z podprogramu
;-------------------------------------------------------------------------------
print_hex_digit:
cp 0x0a ; test, jestli je číslice menší než 10
jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici
add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD)
print_0_to_9:
add A, 48 ; ASCII kód znaku '0'
rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku
ret ; návrat ze subrutiny
;-------------------------------------------------------------------------------
end ENTRY_POINT
No a ještě jeden program: klávesy E, S, D, X pohybují znakem po obrazovce
ENTRY_POINT equ $8000
ROM_OPEN_CHANNEL equ $1601
ROM_CLS equ $0DAF
AT equ $16
X0 equ 15
Y0 equ 10
XMIN equ 0
XMAX equ 31
YMIN equ 0
YMAX equ 21
ZNAK equ "#"
MEZERA equ " "
;-------------------------------------------------------------------------------
GOTO_XY macro X,Y
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
ZNAK_XY macro X,Y,kod
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, kod ; kód znaku '*' pro tisk
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
org ENTRY_POINT
start: call ROM_CLS
ld h,X0 ;pocatecni nastaveni X,Y
ld l,Y0
ZNAK_XY h,l,ZNAK
main: call delay
m01: call keyb
cp 0x26
call z,vpravo
cp 0x16
call z,vlevo
cp 0x25
call z,nahoru
cp 0x27
call z,dolu
jp main
;-------------------------------------------------------------------------------
keyb: push bc ;A - kod klavesy
push de
ld d,8 ;pocitadlo radku
ld c,0xF0 ;adresa portu
ld b,0xFE ;adresa prvniho radku
keyb01: in a,(c) ;nacteni portu
cpl ;negace
and 0x1F ;nastaveni hornich bitu
jp nz,keyb02 ;je stisknuta
ld a,b ;adresa dalsiho radku
rla
ld b,a
dec d ;pocitadlo radku
jp nz,keyb01 ;dalsi radek
pop de
pop bc
ret ;neni stisknuta zadna (A=00)
keyb02: rla ;nalezena prvni stisknuta klavesa
rla ;posun o 3 bity
rla
dec d
add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
;-------------------------------------------------------------------------------
vpravo:
ZNAK_XY h,l,MEZERA
ld a,h
cp XMAX
jr Z,vp0
inc h
vp0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
vlevo:
ZNAK_XY h,l,MEZERA
ld a,h
cp XMIN
jr Z,vl0
dec h
vl0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
dolu:
ZNAK_XY h,l,MEZERA
ld a,l
cp YMAX
jr Z,do0
inc l
do0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
nahoru:
ZNAK_XY h,l,MEZERA
ld a,l
cp YMIN
jr Z,na0
dec l
na0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
delay: push bc
push de
ld d,40
ld e,0
d01: dec e
jr nz, d01
dec d
jr nz, d01
pop de
pop bc
ret
end ENTRY_POINT
Ta keyb rutina jde napsat mnohem kratsi
;-------------------------------------------------------------------------------
keyb: push bc ;A - kod klavesy
push de
ld d,7 ;pocitadlo radku
ld bc,0xFEF0 ;adresa prvniho radku & adresa portu
keyb01: in a,(c) ;nacteni portu
cpl ;negace
add a,a ;posun o 3 bity
add a,a
add a,a
jp nz,keyb02 ;je stisknuta
dec d ;pocitadlo radku
rl b ; 0xFE->FD->FB->F7->EF->DF->BF->7F
jp c,keyb01 ;dalsi radek
ld d,a ;neni stisknuta zadna (D=A=00)
keyb02: add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
A u toho CASE vetveni ktera klavesa je stiskla muzes usetrit taky nejake bajty kdyz mas rozdily mezi vetvemi nekdy jedna.
Misto:
cp 0x26 call z,vpravo cp 0x16 call z,vlevo cp 0x25 call z,nahoru cp 0x27 call z,dolu
To napis:
sub 0x16 call z,vlevo ; 0x16 cp 0x25-0x16 call z,nahoru ; 0x25 dec a call z,vpravo ; 0x26 dec a call z,dolu ; 0x27
Ale mas tam chybu, ze v tech podrutinach prepisujes registr A. Takze ti to funguje jen nahodou.
Kdyz se nad tim zamyslis, tak ten zpusob cteni klavesnice neni idealni. Protoze najdes prvni stisklou klavesu a ukoncis cteni klavesnice, ale ty pro tu hru spis potrebujes zjistit i vic klaves, napriklad nahoru+doprava+fire. Takze bud nejake 40 bitove pole a nebo jeste lepe pro kazdou konkretni klavesu mit znovu cteni. Mas tam 4 az 5 klaves.
Nejak takto treba na 110 bajtu (z puvodnich 203):
ENTRY_POINT equ $8000
ROM_CLS equ $0DAF
AT equ $16
X0 equ 15
Y0 equ 10
XMIN equ 0
XMAX equ 31
YMIN equ 0
YMAX equ 21
ZNAK equ "#"
MEZERA equ " "
org ENTRY_POINT
start: call ROM_CLS
ld hl,256*X0+Y0 ;pocatecni nastaveni X,Y
ld de,ZNAK*257 ;D=E=znak
call print_yx_hl_e
main: halt
halt
ld bc,0xFB02 ; Q
call checkpress
call nz,nahoru
ld b,0xFD ; A, C=0x02
call checkpress
call nz,dolu
ld bc,0xDF04 ; O
call checkpress
call nz,vlevo
ld c,0x02 ; P, B=0xEF
call checkpress
call nz,vpravo
jr main
;-------------------------------------------------------------------------------
;in:
;B=0x7F C= ..BNMs_.
;B=0xBF C= ..HJKLe.
;B=0xDF C= ..YUIOP.
;B=0xEF C= ..67890.
;B=0xF7 C= ..54321.
;B=0xFB C= ..TREWQ.
;B=0xFD C= ..GFDSA.
;B=0xFE C= ..VCXZc.
;out: nz=press
checkpress:
in a,(c) ;nacteni portu
cpl ;negace
add a,a ;posun o 3 bity
and c
ret
;-------------------------------------------------------------------------------
vpravo:
ld a,h
cp XMAX
ret Z
call print_yx_hl_space
inc h
ld e,d
jr print_yx_hl_e
;-------------------------------------------------------------------------------
vlevo:
if (XMIN=0)
inc h
dec h
else
ld a,h
cp XMIN
endif
ret Z
call print_yx_hl_space
dec h
ld e,d
jr print_yx_hl_e
;-------------------------------------------------------------------------------
dolu:
ld a,l
cp YMAX
ret Z
call print_yx_hl_space
inc l
ld e,d
jr print_yx_hl_e
;-------------------------------------------------------------------------------
nahoru:
if (XMIN=0)
inc l
dec l
else
ld a,l
cp YMIN
endif
ret Z
call print_yx_hl_space
dec l
ld e,d
jr print_yx_hl_e
;-------------------------------------------------------------------------------
print_yx_hl_space:
ld E,' ' ; 1e20
print_yx_hl_e:
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, L ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, H ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, E ; kód znaku '*' pro tisk
rst 0x10 ; zavolání rutiny v ROM
ret
;-------------------------------------------------------------------------------
end ENTRY_POINT
PS: Ja zase pouzivam v C masku klavesy co chci tisknout vynasobenou dvema. V emulatorou to funguje, ale na realnem ZX netusim... Z toho obrazku obvodu a ze jsou pri nejakych kombinacich vyvolany duchove je uz mimo muj level. Proste HW...
Nemám s Z80 tolik zkušeností a ani neznám všechny instrukce, tak jsem si nebyl jistý jak to vlastně je. Jestli můžu instrukce rotací použít i na jiný instrukce než akumulátor. Je nějaká rozumná tabulka s instrukcemi? Když jsem to na internetu hledal, tak na mne vylezla buď moc podrobná (odstavec na každou instrukci) nebo zas jen tabulka kde zjistím maximálně hex kod. Používám to od p. Tišnovského co je v lekcích, ale je to po kouskách a myslím že ne kompletní.
To že přečtu jen jednu klávesu je mi jasný, neměl jsem v tuhle chvíli ambice to udělat líp. S tím že v podprogramech přepisuju A máš pravdu, nevšimnul jsem si toho. Funguje to jen proto, že kódy zvolených kláves jsou větší než souřadnice X.Y.
Ja osobne pouzivam 5. odkaz uvedeny v clanku v odkazech.
Asi pred pul rokem prosel web nejakym designovym updatem a uz to neni ono. Plus ma (nebo mel) tam asi nejake drobne chyby, ze ma spatne zacervenene instrukce.
Popisky jsou v nahledu. Nekdy je stejne potreba vetsi popisek, protoze nektere instrukce jsou matouci.
Nejdulezitejsi je prvni tabulka, protoze je bez prefixu, takze nejkratsi instrukce a nejrychlejsi.
Pak muze byt uzitecna CB a ED.
Zbytek v nejakych specialnich pripadech, bud slozity algoritmus, nebo mas vsechno obsazene, ale je otazka zda to nejde napsat jinak.
Nekdy instrukce, ktere vypadaji jako kopie z prvni tabulky se ale lisi priznaky (ruzne posuny a rotace A).
Ale treba LD (adr),HL ma dve varianty "22 lo hi" a "ED 63 lo hi". Uplne zbytecne, ale... nekdy by se to treba mohlo hodit kdyz provadis nektere triky, kdy se snazis eliminovat nejaky skok, nebo se snazis mit 2 kody v sobe, jen posunuty o bajt (Z80 ti to skoro okamzite ale slouci diky tomu jak ma udelane opcody).
PS: U keyb si pouzil 3x "rla" a fungovalo ti to protoze si pred prvni "rla" mel vynulovany carry po "and" a pri druhem a tretim, protoze jsi mel vynulovany carry, protoze si zaroven tim "and" odmazal 3 nejvyssi bity z A.
Pokud by si ale rovnou pouzil "add A,A", nemusel bys carry resit, kdyz tam chces jen nuly.
PPS: Dobra prace.
Protoze prvni je spatne a je to mysleno jako oprava. Narazil jsem na to v nejakem dalsim kodu.
Prvni dela:
rl b ; 0xFE->FC->F8->F0->E0->C0->80->00
"rl b" = "adc b,b", ale v kodu je vzdy vynulovany carry takze je to "add b,b" (Pak ze Z80 umi pocitat jen s A(HL)).
Premyslel jsem proc to fungovalo a dospel jsem k nazoru, ze...
Tomu prvne predhodite spravnou hodnotu a on otestuje stisk klaves na radku 0xFE a zjisti ze je nejaka stiskla a ukonci se a nebo neni zadna stiskla a pokracuje.
Dalsi hodnota je 0xFC a program provede znovu kontrolu jako v FE kde nic neni pokud to nahodou neni stiskle prave v ten moment (opakovane zmacknuti Z (3.bit 0xFE) by asi melo obcas vyvolat stisk S (3.bit 0xFD)) a provede kontrolu i pro 0xFD (dela asi proste zaroven kontrolu 0xFE a 0xFD kdyz ma dva bity nulove)
Atd pro zbytek.