A nejtezsi cast nakonec. Prevod YX na adresu v HL. Najit efektivni cestu je tak slozity, ze jsem se rovnou podival jak jsem to resil nekdy predtim... .) Taky jsou v mem pasmu 4 rano... .)
https://github.com/DW0RKiN/M4_FORTH/blob/master/M4/graphic_runtime.m4
Po "drobne" uprave se da usetrit rovnych 6 bajtu!
calc_pixel_address:
; parametry:
; B - x-ová souřadnice (v pixelech)
; C - y-ová souřadnice (v pixelech)
;
; návratové hodnoty:
; HL - adresa pro zápis pixelu
;
; pozměněné registry:
; A
;
; vzor adresy:
; 0 1 0 Y7 Y6 Y2 Y1 Y0 | Y5 Y4 Y3 X4 X3 X2 X1 X0
if 1
ld A, C ; 1:4 bbrrrsss = Y
or 0x01 ; 2:7 bbrrrss1 carry = 0
rra ; 1:4 0bbrrrss carry = 1
rra ; 1:4 10bbrrrs carry = s?
and A ; 1:4 10bbrrrs carry = 0
rra ; 1:4 010bbrrr
ld L, A ; 1:4 .....rrr
xor C ; 1:4 ????????
and 0xF8 ; 2:7 ?????000
xor C ; 1:4 010bbsss
ld H, A ; 1:4 H = 64+8*INT (b/64)+(b mod 8)
ld A, L ; 1:4 .....rrr
xor B ; 1:4 ???????? provede se 2x takze zadna zmena, mezitim ale vynulujeme hornich 5 bitu
and 0x07 ; 2:7 00000???
xor B ; 1:4 cccccrrr
rrca ; 1:4 rcccccrr
rrca ; 1:4 rrcccccr
rrca ; 1:4 rrrccccc
ld L, A ; 1:4 L = 32*INT (b/(b mod 64)/8)+INT (x/8).
ret ; 1:10 návrat z podprogramu
else
ld a, c ; všech osm bitů Y-ové souřadnice
and %00000111 ; pouze spodní tři bity y-ové souřadnice (Y2 Y1 Y0)
; A: 0 0 0 0 0 Y2 Y1 Y0
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld h, a ; část horního bajtu adresy je vypočtena
; H: 0 1 0 0 0 Y2 Y1 Y0
ld a, c ; všech osm bitů Y-ové souřadnice
rra
rra
rra ; rotace doprava -> Y1 Y0 xx Y7 Y6 Y5 Y4 Y3
and %00011000 ; zamaskovat
; A: 0 0 0 Y7 Y6 0 0 0
or h ; a přidat k vypočtenému mezivýsledku
ld h, a ; H: 0 1 0 Y7 Y6 Y2 Y1 Y0
ld a, c ; všech osm bitů Y-ové souřadnice
rla
rla ; A: Y5 Y4 Y3 Y2 Y1 Y0 xx xx
and %11100000 ; A: Y5 Y4 Y3 0 0 0 0 0
ld l, a ; část spodního bajtu adresy je vypočtena
ld a, b ; všech osm bitů X-ové souřadnice
rra
rra
rra ; rotace doprava -> 0 0 0 X7 X6 X5 X4
and %00011111 ; A: 0 0 0 X7 X6 X5 X4 X3
or l ; A: Y5 Y3 Y3 X7 X6 X5 X4 X3
ld l, a ; spodní bajt adresy je vypočten
ret ; návrat z podprogramu
endif
Tak nějak se mi potvrzuje hláška kolegy sinclairisty před 35 lety - "grafika na Sinclairu je peklo". Pamatuju, že díky "lineárnímu" mapování VRAM na C64 se při unrollingu všech 4 variant vykreslování obecné přímky podle Bresenhama vystačilo snad s 6 instrukcemi na pixel v 320 x 200 (jo, požralo to par kB).
Imho je tohle spis ukazka jak lze obtizne psat na Z80.
Ale ta grafika je podle me teda peklo taky. Zjednodusenim v jednom smeru, to ve vsech ostatnich udelali slozitejsi...
Preferoval bych, kdyby to slo pekne za sebou:
+256 o 8 pixelu dolu a nebo -256 o 8 pixelu nahoru.
+32 o pixel dolu a nebo -32 (+FFE0) o pixel nahoru.
Nemusi se resit zadne up/down rutiny, kdyz pisete uz sam o sobe nejaky komplikovany algoritmus na kruznici/usecku.
Znaky se komplikuji na to, ze problem prechodu tretin se meni na problem prechodu radku.
Na radku je to stale jen +-1 pro spodni bajt. Jakmile to preleze pres 5 bitu tak se meni +-horni bajt.
Neco jako pro znak "vpravo/nasledujici znak/+1":
L = X
L |= 0xC0
H = Y
HL++
L &= 0x1F
A pro znak "vlevo/predchozi/-1":
L = X
H = Y
HL--
L &= 0x1F
Timhle se da vlastne resit prechod pro tretiny i ted. U H |=3 a H &=F8.
TAB x, ktere nastavi kurzor na x znak na radku (pouhe prirazeni) a nebo pokud je to posun doleva tak snizi radek (+256) by byl o dost snazsi.
YX ve znacich na adresu v HL:
H = Y
L = X
add HL, HL
add HL, HL
add HL, HL
YX v pixelech na adresu v HL?
H = Y
L = X
a ted potrebujeme HL >>= 3
takze asi neco jako
A = L
xor H
and 0xF8
xor H
rrca
rrca
rrca
L = A
A = H
rrca
rrca
rrca
H = A
Hmm to je 12+2 bajtu (12*4+7 = 55 taktu)
Takze na 12 bajtu (3*16 = 48 taktu) to jde udelat primo pres shift H a L.
PS: Mit to linearne by pro me asi nejvic zmenilo ten pocit z pomaleho nacitani obrazovky her. Pokud by to neemulovala primo ta nacitaci rutina.
Souhlas, v minulosti jsem nechápal, proč měl Sinclair takto (z mého pohledu) komplikovanou VRAM. Já jsem měl Commodore Plus/4 a tam byla VRAM lineární. Používalo se několik různých režimu (vše zajišťoval obvod TED):
Character: 40x25 znaků + volně měnitelná znaková sada v RAM/ROM (hw kurzor, flash, inverzní znaky).
Bitmap: 320x200
Bitmap Multicolor (MCM): 160x200
plus ještě existoval režim Extended Color Mode.
+ hw scrolling.
Všechny režimy byly lineární a jejích umístění na stránku v RAM se dalo měnit, takže jste mohli používat double-buffering. Žádné zpomalení běhu programů v určité části RAM nebylo (jako to má ZX Spectrum).
A programování v MOS 6502 bylo velmi jednoduché (oproti Zilog Z80).
Takže obdivuji všechny Spektristy. Kudos!