Obsah
1. Vykreslování spritů a animací na ZX Spectru (2. část)
2. Urychlení vykreslování – optimalizace subrutiny draw8_lines
3. Úplný zdrojový kód dnešního druhého demonstračního příkladu
4. Nedostatky podprogramu pro vykreslení spritu na obrazovku ZX Spectra
5. Chybějící kontrola, zda sprite nepřesahuje pravý či levý okraj obrazovky
6. Úplný zdrojový kód dnešního druhého demonstračního příkladu
7. Chybějící kontrola, zda sprite nepřesahuje dolní okraj obrazovky
8. Úplný zdrojový kód dnešního třetího demonstračního příkladu
9. Sprite, jehož maska přesahuje přes třetinu obrazovky
10. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu
11. Chyby při zobrazení spritu na nekonstantním pozadí
12. Vykreslení statického obrázku na obrazovku ZX Spectra
13. Zobrazení spritů ve scéně s obrázkem na pozadí
14. Úplný zdrojový kód dnešního šestého demonstračního příkladu
15. Korektní výpočet adres zapisovaných bajtů při zobrazení spritu
16. Úplný zdrojový kód dnešního sedmého demonstračního příkladu
18. Příloha: upravený soubor Makefile pro překlad demonstračních příkladů
19. Repositář s demonstračními příklady
1. Vykreslování spritů a animací na ZX Spectru (2. část)
Na předchozí část seriálu o tvorbě her i dalších aplikací určených pro slavné ZX Spectrum dnes navážeme. Připomeňme si, že minule jsme si ukázali, jakým způsobem je možné na obrazovku ZX Spectra vykreslit takzvaný sprite, což je v kontextu osmibitových mikropočítačů a herních konzolí termín označující pohyblivý a většinou i animovaný obrázek nějaké herní postavičky. Prozatím umíme vykreslit sprite o libovolné velikosti, i když – jak uvidíme dále – má náš postup prozatím velmi mnoho problémů a bude ho nutné v mnoha ohledech vylepšit a taktéž opravit.
Základní verze programu napsaného v assembleru mikroprocesoru Zilog Z80, který je určen pro vykreslení postavičky o rozměru 24×24 pixelů (v tomto případě navíc bez podpory plynulého posunu o jednotlivé pixely) vypadala následovně. Samotná data s maskou spritu jsou v této variantě součástí zdrojového kódu:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 15 ; x-ová souřadnice
ld c, 3 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 29 ; x-ová souřadnice
ld c, 21 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
draw_8_lines:
ld b, 8 ; počitadlo zapsaných řádků
loop:
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
inc e
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
inc e
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
inc d ; posun na definici dalšího obrazového řádku
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; dtto
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
end ENTRY_POINT
Tento program po svém spuštění vykreslí na obrazovku ZX Spectra dvojici spritů (postaviček). Výsledná scéna bude vypadat následovně:
Obrázek 1: Dvojice spritů vykreslená dnešním prvním demonstračním příkladem na obrazovku ZX Spectra.
2. Urychlení vykreslování – optimalizace subrutiny draw8_lines
Podprogram určený pro vykreslení spritu o rozměrech 24×24 pixelů třikrát volá subrutinu nazvanou draw8_lines, která vykreslí „pouze“ osm obrazových řádků spritu, přičemž na každém řádku se zobrazí 24 pixelů. Tato subrutina interně obsahuje programovou smyčku opakovanou pro každý obrazový řádek. Původní varianta této subrutiny s programovou smyčkou vypadá následovně:
draw_8_lines:
ld b, 8 ; počitadlo zapsaných řádků
loop:
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
inc e
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
inc e
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
inc d ; posun na definici dalšího obrazového řádku
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; dtto
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
V této subrutině se dvojice registrů HL používá pro načtení bajtu z masky spritu a dvojice registrů DE pro zápis (přenos dat je pochopitelně prováděn přes akumulátor). Tuto subrutinu lze ovšem optimalizovat náhradou sekvence instrukcí ld (load) za „blokové“ přenosy (nyní ovšem s počitadlem obsahujícím jak počitadlo smyčky, tak i nižší nepoužitý bajt):
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; korekce
inc d ; posun na definici dalšího obrazového řádku (+256)
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
Výsledek je jak kratší, tak i rychlejší (opět díky _dw!).
Původní strojový kód:
803E: label draw_8_lines 803E:0608 LD B, 08 8040: label loop 8040:7E LD A, (HL) 8041:12 LD (DE), A 8042:23 INC HL 8043:1C INC E 8044:7E LD A, (HL) 8045:12 LD (DE), A 8046:23 INC HL 8047:1C INC E 8048:7E LD A, (HL) 8049:12 LD (DE), A 804A:23 INC HL 804B:14 INC D 804C:1D DEC E 804D:1D DEC E 804E:10F0 DJNZ 8040 8050:C9 RET
Strojový kód po optimalizaci zdrojového kódu:
8040: label draw_8_lines 8040:011008 LD BC, 0810 8043: label loop 8043:EDA0 LDI 8045:EDA0 LDI 8047:7E LD A, (HL) 8048:12 LD (DE), A 8049:23 INC HL 804A:1D DEC E 804B:1D DEC E 804C:14 INC D 804D:10F4 DJNZ 8043 804F:C9 RET
3. Úplný zdrojový kód dnešního druhého demonstračního příkladu
Po výše uvedené úpravě získáme program, po jehož spuštění se zobrazí stejná scéna, jako v případě programu předchozího:
Obrázek 2: Dvojice spritů vykreslená dnešním druhým demonstračním příkladem na obrazovku ZX Spectra. Samotná scéna by měla být totožná s prvním obrázkem (až na rozdílný řádek s hlavičkou načítaných dat).
Pro úplnost se podívejme, jak vypadá úplný zdrojový kód takto upraveného příkladu:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 15 ; x-ová souřadnice
ld c, 3 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 29 ; x-ová souřadnice
ld c, 21 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
ld b, 8 ; počitadlo zapsaných řádků
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; korekce
inc d ; posun na definici dalšího obrazového řádku (+256)
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
end ENTRY_POINT
4. Nedostatky podprogramu pro vykreslení spritu na obrazovku ZX Spectra
Podprogram nazvaný draw_sprite, který jsme si ukázali, sice pracuje zdánlivě korektně (ostatně nám umožnil na obrazovku vykreslit několik postaviček), ale v navazujících kapitolách si ukážeme, že ve skutečnosti má poměrně velké množství problémů, které bude nutné vyřešit. Některé z těchto problémů souvisí s tím, že jsme si práci až příliš zjednodušili, další problémy pak vychází ze specifické struktury obrazové paměti ZX Spectra. Každý z dále zmíněných problémů bude demonstrován v samostatném příkladu:
- Chybějící kontrola, zda sprite nepřesahuje pravý či levý okraj obrazovky
- Chybějící kontrola, zda sprite nepřesahuje dolní okraj obrazovky
- Chybně vykreslený sprite, jehož maska přesahuje přes třetinu obrazovky
- Chyby při zobrazení spritu na nekonstantním pozadí
5. Chybějící kontrola, zda sprite nepřesahuje pravý či levý okraj obrazovky
Vykreslovací subrutina prozatím vůbec neprovádí kontrolu, zda sprite nepřesahuje pravý či levý okraj obrazovky (přesněji řečeno pravý okraj obrazovky, protože oba případy mají, pokud se nad tím zamyslíme, naprosto stejné vstupy). Můžeme si to ostatně velmi snadno otestovat tak, že vykreslíme několik spritů blízko pravého okraje obrazovky (povšimněte si x-ových souřadnic předávaných v pracovním registru B):
ld b, 29 ; x-ová souřadnice ld c, 2 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy spritu call draw_sprite ld b, 30 ; x-ová souřadnice ld c, 5 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy call draw_sprite ld b, 31 ; x-ová souřadnice ld c, 9 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy call draw_sprite
Výsledek bude vypadat následovně:
Obrázek 3: Trojice spritů, z nichž dva přesahují přes pravý okraj obrazovky.
Jak je možné tento problém vyřešit? Například tak, že se logikou hry zajistí, že žádná z postaviček nepřesáhne okraj obrazovky (nebo se ho jen dotkne), což je případ velkého množství skutečných her, které pro ZX Spectrum vznikly. Nebo postavička může okrajem „projít“ podobně, jako v našem případě. Korektní ořezání spritu tak, aby mohl být zobrazen jen částečně, je pochopitelně možné, ale dosti pomalé. Podívejme se na příklady:
Obrázek 4: Postavička ve hře JetPac prochází okrajem a zobrazuje se na druhém okraji obrazovky. Podobně přes okraj prochází i NPC, výbuchy atd.
Obrázek 5: Ve hře Starquake se postavička okraje pouze může dotknout. Při dalším pohybu se ihned přejde do další místnosti.
Obrázek 6: Ve hře Draconus je sprite korektně ořezáván, ovšem jen na chvíli, než se přepne místnost. Povšimněte si, že ořezání není provedeno na samotném okraji obrazovky, čímž se problematika zjednodušuje.
6. Úplný zdrojový kód dnešního druhého demonstračního příkladu
Úplný zdrojový kód dnešního druhého demonstračního příkladu vypadá následovně:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 29 ; x-ová souřadnice
ld c, 2 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 30 ; x-ová souřadnice
ld c, 5 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 31 ; x-ová souřadnice
ld c, 9 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
ld b, 8 ; počitadlo zapsaných řádků
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; korekce
inc d ; posun na definici dalšího obrazového řádku (+256)
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
end ENTRY_POINT
7. Chybějící kontrola, zda sprite nepřesahuje dolní okraj obrazovky
V případě, že sprite přesáhne přes pravý okraj obrazovky, nemusí být tento problém (a většinou se jedná o problém) příliš viditelný. Obraz sice může být na levém okraji poškozen, ale jedná se o lokální problém, který navíc může u některých her (střílečky) zaniknout v celkovém „chaosu“ na obrazovce. Ovšem zajímavější problém nastane ve chvíli, kdy sprite přesáhne spodní okraj obrazovky. Proč tomu tak je? Připomeňme si, jaká je vlastně organizace obrazové paměti ZX Spectra:
| Od | Do | Délka | Stručný popis |
|---|---|---|---|
| 4000 | 47ff | 2048 | prvních 64 obrazových řádků |
| 4800 | 5000 | 2048 | obrazové řádky 64–127 |
| 5000 | 57ff | 2048 | obrazové řádky 128–191 |
| 5800 | 5aff | 768 | 32×24=768 atributů |
Z této tabulky je patrné, že ihned za posledním obrazovým řádkem s indexem 191 (čísluje se od nuly) se nachází začátek atributové paměti. U spritu s výškou 24 obrazových řádků se nám může velmi dobře stát, že přepíšeme část této paměti či že dokonce zasáhneme až do adresního prostoru za touto pamětí. Pojďme si to vyzkoušet:
ld b, 14 ; x-ová souřadnice ld c, 2 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy spritu call draw_sprite ld b, 14 ; x-ová souřadnice ld c, 5 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy call draw_sprite ld b, 31 ; x-ová souřadnice ld c, 23 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy call draw_sprite
Poslední sprite leží až na dolním okraji obrazovky, takže při zápisu jeho masky přepíšeme i část atributové paměti:
Obrázek 7: Trojice spritů, z nichž poslední přesahuje před spodní okraj obrazovky a při jehož vykreslování se zasáhlo do oblasti atributové paměti (bílý atribut dokonce bliká, což na statickém screenshotu není patrné).
Obrázek 8: Elegantní řešení výše uvedeného problému v legendární hře – šílený horník se nedostane přes spodní okraj obrazovky, protože se do této oblasti nemůže díky designu celé scény ani přiblížit.
8. Úplný zdrojový kód dnešního třetího demonstračního příkladu
Opět si ukažme úplný zdrojový kód příkladu, jenž po svém překladu a následném spuštění zobrazí tři sprity, z nichž jeden překračuje dolní okraj obrazovky a tím pádem zasahuje do oblasti atributové paměti:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 14 ; x-ová souřadnice
ld c, 2 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 14 ; x-ová souřadnice
ld c, 5 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 31 ; x-ová souřadnice
ld c, 23 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
ld b, 8 ; počitadlo zapsaných řádků
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; korekce
inc d ; posun na definici dalšího obrazového řádku (+256)
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
end ENTRY_POINT
9. Sprite, jehož maska přesahuje přes třetinu obrazovky
Z předchozích článků již víme, že obrazová paměť je rozdělena do čtyř oblastí:
| Od | Do | Délka | Stručný popis |
|---|---|---|---|
| 4000 | 47ff | 2048 | prvních 64 obrazových řádků |
| 4800 | 5000 | 2048 | obrazové řádky 64–127 |
| 5000 | 57ff | 2048 | obrazové řádky 128–191 |
| 5800 | 5aff | 768 | 32×24=768 atributů |
V každé oblasti jsou navíc řádky uspořádány tak, že za řádkem číslo 1 následuje řádek číslo 8, potom řádek číslo 16 atd. (nejlépe je to patrné při načítání obrázků z kazety). Tento problém jsme už poměrně uspokojivě vyřešili ve vykreslovací rutině, a to i pro sprity vyšší než osm obrazových řádků. Ovšem prozatím jsme „zapomněli“ na to, že pokud sprite přesáhne přes okraj třetiny obrazovky (64 řádek nebo 128 řádek), nebudou výpočty adresy pracovat korektně a zbytek spritu se vykreslí v aktuální třetině obrazovky, a to na jejím horním okraji. Můžeme si to poměrně snadno otestovat na spritech s následujícími souřadnicemi (stále pro jednoduchost počítáme souřadnice v násobcích osmi – to také budeme muset změnit):
ld b, 15 ; x-ová souřadnice ld c, 3 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy spritu call draw_sprite ld b, 15 ; x-ová souřadnice ld c, 6 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy call draw_sprite
Výsledkem bude následující scéna. Povšimněte si, že spodní sprite, který přesáhl přes třetinu obrazovky, je vykreslen chybně – jeho spodní část ve skutečnosti „přetekla“ na prvních osm řádků na obrazovce.
Obrázek 9: Pokus o vykreslení spritu, který přesahuje přes třetinu obrazovky (jedná se o v pořadí druhý sprite, jehož „nohy“ přeskočily až nahoru).
10. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu
Opět si ukažme úplný zdrojový kód demonstračního příkladu, jenž byl popsán v předchozí kapitole. Tento kód vypadá následovně:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 15 ; x-ová souřadnice
ld c, 3 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 15 ; x-ová souřadnice
ld c, 6 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
ld b, 8 ; počitadlo zapsaných řádků
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; korekce
inc d ; posun na definici dalšího obrazového řádku (+256)
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
end ENTRY_POINT
11. Vykreslení spritu na různorodé pozadí
Všechny demonstrační příklady určené pro vykreslení spritů prozatím pracovaly s prázdnou obrazovkou (to ve skutečnosti není zcela přesné, protože na prvním textovém řádku zůstávají zprávy z načítací rutiny). Co se však stane ve chvíli, kdy se pokusíme sprite vykreslit oproti nějakému různorodému pozadí? Uvidíme hned celou řadu problémů, zejména však:
- Sprite „zdědí“ původní barvové atributy, a to jak atributy pozadí (což je v pořádku), tak i popředí (+ příznak blikání atd.)
- Sprite překreslí pozadí i na těch pozicích, v nichž by měly být jeho pixely průhledné (což odpovídá nulovým bitům v masce pixelu).
Obrázek 10: Manic miner nejenom že prochází stropem, ale navíc jeho sprite přebírá atributy herního pozadí (což ovšem není grafické pozadí, ale naopak popředí) i NPC (robota).
12. Vykreslení statického obrázku na obrazovku ZX Spectra
Ještě předtím, než se pokusíme o vykreslení spritu oproti již připravenému statickému pozadí, si ukažme, jak lze na obrazovku ZX Spectra vykreslit nějaký statický obrázek, který se nachází v jiné oblasti operační paměti. V praxi se můžeme setkat s přímým načtením obrázku (loading screen) do obrazové paměti, nyní ovšem budeme postupovat jinak – data obrázku, tedy jak bitmapu, tak i atributy, triviálně zkopírujeme do obrazové paměti instrukcí pro blokový přenos LDIR, s níž jsme se již v tomto seriálu setkali:
SCREEN_ADR equ $4000
BITMAP_SIZE equ 32*192
ATTRIBUTE_BLOCK_SIZE equ 32*64
SCREEN_SIZE equ BITMAP_SIZE + ATTRIBUTE_BLOCK_SIZE
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
; nejprve přeneseme celý obrázek do obrazové paměti
ld hl, LOADING_SCREN ; adresa zdrojového bloku
ld de, SCREEN_ADR ; adresa cílového bloku
ld bc, SCREEN_SIZE ; velikost přenášených dat
ldir ; provést blokový přenos
finish:
jr finish ; žádný návrat do systému
LOADING_SCREN incbin "Alien8.scr"
end ENTRY_POINT
Výsledná scéna by po načtení do ZX Spectra či jeho emulátoru měla vypadat následovně:
Obrázek 11: Statický obrázek vykreslený na obrazovku ZX Spectra.
13. Zobrazení spritů ve scéně s obrázkem na pozadí
Nyní zkombinujeme zobrazení pozadí (statického obrázku) se zobrazením spritů. Oproti předchozím demonstračním příkladům ve skutečnosti pouze upravíme začátek kódu, v němž nejprve na obrazovku zkopírujeme statický obrázek a potom přes něj nakreslíme trojici spritů (na vhodná místa):
; nejprve přeneseme celý obrázek do obrazové paměti ld hl, LOADING_SCREN ; adresa zdrojového bloku ld de, SCREEN_ADR ; adresa cílového bloku ld bc, SCREEN_SIZE ; velikost přenášených dat ldir ; provést blokový přenos ld b, 15 ; x-ová souřadnice ld c, 4 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy spritu call draw_sprite ld b, 15 ; x-ová souřadnice ld c, 18 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy spritu call draw_sprite ld b, 9 ; x-ová souřadnice ld c, 12 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy call draw_sprite
Na výsledku jsou velmi dobře patrné oba problémy zmíněné v předchozí kapitole, tj. jak překreslení i těch pixelů, které měly zůstat zachovány, tak i „zdědění“ původních barvových atributů (nejvíce je to patrné na nejvyšším spritu, který zdědil hned tři různé barvy popředí):
Obrázek 12: Zobrazení trojice spritů ve scéně s obrázkem na pozadí.
14. Úplný zdrojový kód dnešního šestého demonstračního příkladu
Úplný zdrojový kód dnešního šestého demonstračního příkladu vypadá následovně:
SCREEN_ADR equ $4000
BITMAP_SIZE equ 32*192
ATTRIBUTE_BLOCK_SIZE equ 32*64
SCREEN_SIZE equ BITMAP_SIZE + ATTRIBUTE_BLOCK_SIZE
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
; nejprve přeneseme celý obrázek do obrazové paměti
ld hl, LOADING_SCREN ; adresa zdrojového bloku
ld de, SCREEN_ADR ; adresa cílového bloku
ld bc, SCREEN_SIZE ; velikost přenášených dat
ldir ; provést blokový přenos
ld b, 15 ; x-ová souřadnice
ld c, 4 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 15 ; x-ová souřadnice
ld c, 18 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 9 ; x-ová souřadnice
ld c, 12 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
ld b, 8 ; počitadlo zapsaných řádků
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
dec e ; korekce - posun zpět pod první osmici pixelů
dec e ; korekce
inc d ; posun na definici dalšího obrazového řádku (+256)
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
LOADING_SCREN incbin "Alien8.scr"
end ENTRY_POINT
15. Korektní výpočet adres zapisovaných bajtů při zobrazení spritu
Některé problémy lze ve skutečnosti opravit relativně snadno. Podívejme se například na řešení problému korektního výpočtu adres zapisovaných bajtů (3 bajty na obrazový řádek, 24 obrazových řádků). Prozatím vypadá vykreslení spritu v nejvyšší úrovni abstrakce takto:
ld b, 0 ; x-ová souřadnice ld c, 3 ; y-ová souřadnice call calc_sprite_address ; výpočet adresy spritu call draw_sprite
To je v pořádku – adresu vypočteme (mimochodem: složitým způsobem s mnoha bitovými operacemi) jen jedenkrát a poté se již volá subrutina pro vykreslení celého spritu. Ta vypadá následovně:
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
push de
call draw_8_lines ; vykreslit prvních 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
push de
call draw_8_lines ; vykreslit druhých 8 řádků spritu
pop de
add_e 32 ; zvýšit E o hodnotu 32
call draw_8_lines ; vykreslit třetích 8 řádků spritu
ret ; návrat z podprogramu
A zde nastává problém – posun adresy o 32 bajtů skutečně odpovídá přechodu o osm obrazových řádků (ano – obrazová paměť má takový formát), jenže to neplatí u přechodu na další třetinu obrazovky, tj. přes hranici 2048 bajtů. Ovšem můžeme využít triku, který již popsal kolega dw (ještě jednou díky); necháme si adresu vypočítat přímo subrutinou draw8_lines. Tím se nám subrutina pro vykreslení spritu zjednoduší na pouhých pět instrukcí:
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
call draw_8_lines ; vykreslit prvních 8 řádků spritu + upravit DE pro následující řádek
call draw_8_lines ; vykreslit druhých 8 řádků spritu + upravit DE pro následující řádek
call draw_8_lines ; vykreslit třetích 8 řádků spritu + upravit DE pro následující řádek
ret ; návrat z podprogramu
Naproti tomu ovšem musíme měnit dvojregistr DE v subrutině draw8_lines. On se zde ve skutečnosti modifikoval již předtím, ovšem musíme to nyní provést správně. Budeme zjišťovat, zda se nepřekročila oblast 2048 bajtů a pokud ne, bude DE zvýšeno o 32 (tedy přeskok na další obrazový řádek) a pokud ano, musí se upravit i vyšší bajt adresy, tedy registr D (přeskočíme do další třetiny obrazovky, ovšem na její začátek, přesněji řečeno na jeden z řádků 0 až 7):
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
; nyní je vykresleno všech 24 pixelů na řádku
dec e ; korekce (po prvním LDI)
dec e ; korekce (po druhém LDI)
inc d ; posun na definici dalšího obrazového řádku
; nyní DE ukazuje správně na první bajt na dalším řádku
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ld a, e ; \
add a, 32 ; > E += 32
ld e, a ; /
ret c ; návrat při přenosu (další stránka)
ld a, d ; \
sub 8 ; > D -= 8
ld d, a ; /
ret ; návrat z podprogramu
Rozdíly jsou patrné na první pohled:
Obrázek 13: Nekorektní přechody mezi třetinami obrazovky.
Obrázek 14: Korektní přechody mezi třetinami obrazovky.
16. Úplný zdrojový kód dnešního sedmého demonstračního příkladu
Úplný zdrojový kód dnešního sedmého a současně i posledního demonstračního příkladu vypadá následovně:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 0 ; x-ová souřadnice
ld c, 3 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_sprite
ld b, 4 ; x-ová souřadnice
ld c, 4 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 8 ; x-ová souřadnice
ld c, 5 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 12 ; x-ová souřadnice
ld c, 6 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 16 ; x-ová souřadnice
ld c, 7 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 20 ; x-ová souřadnice
ld c, 8 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
ld b, 24 ; x-ová souřadnice
ld c, 9 ; y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_sprite
finish:
jr finish ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
add_e MACRO n ; zvýšení hodnoty regitru E
ld a, e
add a, n
ld e, a
endm
draw_sprite:
ld hl, SPRITE_ADR ; adresa, od níž začíná maska spritu
call draw_8_lines ; vykreslit prvních 8 řádků spritu + upravit DE pro následující řádek
call draw_8_lines ; vykreslit druhých 8 řádků spritu + upravit DE pro následující řádek
call draw_8_lines ; vykreslit třetích 8 řádků spritu + upravit DE pro následující řádek
ret ; návrat z podprogramu
draw_8_lines:
ld bc, 8*(256+2) ; počitadlo zapsaných řádků
loop:
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ldi ; přesun jednoho bajtu + úprava stavu počitadla [DE++] = [HL++]; BC--
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc hl ; posun na další bajt masky
; nyní je vykresleno všech 24 pixelů na řádku
dec e ; korekce (po prvním LDI)
dec e ; korekce (po druhém LDI)
inc d ; posun na definici dalšího obrazového řádku
; nyní DE ukazuje správně na první bajt na dalším řádku
djnz loop ; vnitřní smyčka: blok s 3x osmi zápisy
ld a, e ; \
add a, 32 ; > E += 32
ld e, a ; /
ret c ; návrat při přenosu (další stránka)
ld a, d ; \
sub 8 ; > D -= 8
ld d, a ; /
ret ; návrat z podprogramu
SPRITE_ADR
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11110000, %00010000
db %00000011, %00111000, %00010000
db %00000101, %11010111, %00010000
db %00000101, %11001100, %00010000
db %00000101, %00110000, %00010000
db %00000100, %11001000, %00010000
db %00000111, %00110110, %00010000
db %00001100, %11111110, %00111000
db %00011111, %11111000, %00000000
db %00000000, %00000000, %00110000
db %00000011, %11111111, %10110000
db %00000101, %11111110, %11100000
db %00001110, %11111101, %11000000
db %00011000, %11111100, %00000000
db %00011000, %00000000, %00000000
db %00000001, %11111000, %00000000
db %00000011, %11111100, %00000000
db %00000001, %10110000, %00000000
db %00000010, %00001100, %00000000
db %00000111, %00001110, %00000000
db %00011110, %00000111, %10000000
db %00000000, %00000000, %00000000
end ENTRY_POINT
17. Jak dále?
Nejpalčivější problém tedy máme vyřešen, ale zbývá nám dořešit ještě několik dalších problémů, zejména pak:
- Výpočet jemného posunu spritu v SW, nikoli jeho předpočítáním.
- Správné „proložení“ spritu s bitmapovým pozadím.
- Správné zobrazení barvových atributů (to nevyřešíme :-).
18. Příloha: upravený soubor Makefile pro překlad demonstračních příkladů
Výše uvedené demonstrační příklady i příklady, které již byly popsány v předchozích osmnácti článcích [1] [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], je možné přeložit s využitím souboru Makefile, jehož aktuální verze vypadá následovně (pro překlad a slinkování je, jak je již v tomto seriálu zvykem, použit assembler Pasmo):
ASSEMBLER := pasmo
all: 01.tap 02.tap 03.tap 04.tap 05.tap 06.tap 07.tap 08.tap 09.tap 10.tap \
11.tap 12.tap 13.tap 14.tap 15.tap 16.tap 17.tap 18.tap 19.tap 20.tap \
21.tap 22.tap 23.tap 24.tap 25.tap 26.tap 27.tap 28.tap 29.tap 30.tap \
31.tap 32.tap 33.tap 34.tap 35.tap 36.tap 37.tap 38.tap 39.tap 40.tap \
41.tap 42.tap 43.tap 44.tap 45.tap 46.tap 47.tap 48.tap 49.tap 50.tap \
51.tap 52.tap 53.tap 54.tap 55.tap 56.tap 57.tap 58.tap 59.tap 60.tap \
61.tap 62.tap 63.tap 64.tap 65.tap 66.tap 67.tap 68.tap 69.tap 70.tap \
71.tap 72.tap 73.tap 74.tap 75.tap 76.tap 77.tap 78.tap 79.tap 80.tap \
81.tap 82.tap 83.tap 84.tap 85.tap 86.tap 87.tap 88.tap 80.tap 90.tap \
91.tap 92.tap 93.tap 94.tap 95.tap 96.tap 97.tap 98.tap 99.tap 100.tap \
101.tap 102.tap 103.tap 104.tap 105.tap 106.tap 107.tap 108.tap 109.tap \
110.tap 111.tap 112.tap 113.tap 114.tap 115.tap 116.tap 117.tap 118.tap \
119.tap 120.tap 121.tap 122.tap 123.tap 124.tap 125.tap 126.tap 127.tap \
128.tap 129.tap 130.tap 131.tap 132.tap 133.tap
clean:
rm -f *.tap
.PHONY: all clean
01.tap: 01-color-attribute.asm
$(ASSEMBLER) -v -d --tap $< $@ > 01-color-attribute.lst
02.tap: 02-blinking-attribute.asm
$(ASSEMBLER) -v -d --tap $< $@ > 02-blinking-attribute.lst
03.tap: 03-symbolic-names.asm
$(ASSEMBLER) -v -d --tap $< $@ > 03-symbolic-names.lst
04.tap: 04-operators.asm
$(ASSEMBLER) -v -d --tap $< $@ > 04-operators.lst
05.tap: 05-better-symbols.asm
$(ASSEMBLER) -v -d --tap $< $@ > 05-better-symbols.lst
06.tap: 06-tapbas-v1.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 06-tapbas-v1.lst
07.tap: 07-tapbas-v2.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 07-tapbas-v2.lst
08.tap: 08-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 08-loop.lst
09.tap: 09-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 09-loop.lst
10.tap: 10-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 10-loop.lst
11.tap: 11-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 11-loop.lst
12.tap: 12-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 12-loop.lst
13.tap: 13-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 13-loop.lst
14.tap: 14-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 14-loop.lst
15.tap: 15-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 15-loop.lst
16.tap: 16-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 16-loop.lst
17.tap: 17-loop.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 17-loop.lst
18.tap: 18-cls.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 18-cls.lst
19.tap: 19-print-char-call.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 19-print-char-call.lst
20.tap: 20-print-char-rst.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 20-print-char-rst.lst
21.tap: 21-print-char.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 21-print-char.lst
22.tap: 22-print-all-chars.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 22-print-all-chars.lst
23.tap: 23-print-all-chars.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 23-print-all-chars.lst
24.tap: 24-change-color.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 24-change-color.lst
25.tap: 25-change-flash.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 25-change-flash.lst
26.tap: 26-print-at.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 26-print-at.lst
27.tap: 27-print-string.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 27-print-string.lst
28.tap: 28-print-string.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 28-print-string.lst
29.tap: 29-print-colorized-string.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 29-print-colorized-string.lst
30.tap: 30-print-string-ROM.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 30-print-string-ROM.lst
31.tap: 31-attributes.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 31-attributes.lst
32.tap: 32-fill-in-vram.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 32-fill-in-vram.lst
33.tap: 33-fill-in-vram-no-ret.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 33-fill-in-vram-no-ret.lst
34.tap: 34-fill-in-vram-pattern.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 34-fill-in-vram-pattern.lst
35.tap: 35-slow-fill-in-vram.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 35-slow-fill-in-vram.lst
36.tap: 36-slow-fill-in-vram-no-ret.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 36-slow-fill-in-vram-no-ret.lst
37.tap: 37-fill-block.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 37-fill-block.lst
38.tap: 38-fill-block-with-pattern.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 38-fill-block-with-pattern.lst
39.tap: 39-fill-block-optimized.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 39-fill-block-optimized.lst
40.tap: 40-draw-char.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 40-draw-char.lst
41.tap: 41-draw-any-char.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 41-draw-any-char.lst
42.tap: 42-block-anywhere.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 42-block-anywhere.lst
43.tap: 43-block-anywhere-rrca.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 43-block-anywhere-rrca.lst
44.tap: 44-better-draw-char.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 44-better-draw-char.lst
45.tap: 45-even-better-draw-char.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 45-even-better-draw-char.lst
46.tap: 46-draw-char-at.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 46-draw-char-at.lst
47.tap: 47-draw-char-at-unrolled.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 47-draw-char-at-unrolled.lst
48.tap: 48-incorrect-print-string.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 48-incorrect-print-string.lst
49.tap: 49-correct-print-string.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 49-correct-print-string.lst
50.tap: 50-ascii-table.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 50-ascii-table.lst
51.tap: 51-plot-block.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 51-plot-block.lst
52.tap: 52-plot-pixel.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 52-plot-pixel.lst
53.tap: 53-plot-pixel.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 53-plot-pixel.lst
54.tap: 54-plot-pixel-on-background.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 54-plot-pixel-on-background.lst
55.tap: 55-plot-pixel-on-background.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 55-plot-pixel-on-background.lst
56.tap: 56-inverse-ascii-table.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 56-inverse-ascii-table.lst
57.tap: 57-plot-pixel-on-inverse-background.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 57-plot-pixel-on-inverse-background.lst
58.tap: 58-plot-inverse-pixel-on-inverse-background.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 58-plot-inverse-pixel-on-inverse-background.lst
59.tap: 59-configurable-ascii-table.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 59-configurable-ascii-table.lst
60.tap: 60-plot-over.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 60-plot-over.lst
61.tap: 61-print-number-A.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 61-print-number-A.lst
62.tap: 62-print-number-B.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 62-print-number-B.lst
63.tap: 63-print-number-C.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 63-print-number-C.lst
64.tap: 64-print-number-D.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 64-print-number-D.lst
65.tap: 65-more-numbers-A.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 65-more-numbers-A.lst
66.tap: 66-more-numbers-B.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 66-more-numbers-B.lst
67.tap: 67-print-flags-1.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 67-print-flags-1.lst
68.tap: 68-print-flags-2.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 68-print-flags-2.lst
69.tap: 69-print-flags-3.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 69-print-flags-3.lst
70.tap: 70-print-flags-4.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 70-print-flags-4.lst
71.tap: 71-print-flags-5.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 71-print-flags-5.lst
72.tap: 72-print-flags-6.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 72-print-flags-6.lst
73.tap: 73-print-flags-7.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 73-print-flags-7.lst
74.tap: 74-print-hex-number.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 74-print-hex-number.lst
75.tap: 75-print-hex-number.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 75-print-hex-number.lst
76.tap: 76-print-hex-numbers.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 76-print-hex-numbers.lst
77.tap: 77-add-hex-numbers.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 77-add-hex-numbers.lst
78.tap: 78-add-bcd-numbers.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 78-add-bcd-numbers.lst
79.tap: 79-print-hex-digit-jmp.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 79-print-hex-digit-jmp.lst
80.tap: 80-print-hex-digit-overflow.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 80-print-hex-digit-overflow.lst
81.tap: 81-print-hex-digit-daa.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 81-print-hex-digit-daa.lst
82.tap: 82-print-hex-numbers-daa.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 82-print-hex-numbers-daa.lst
83.tap: 83-print-fp-numbers.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 83-print-fp-numbers.lst
84.tap: 84-print-ascii-table.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 84-print-ascii-table.lst
85.tap: 85-copy-ascii-table.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 85-copy-ascii-table.lst
86.tap: 86-copy-ascii-table-B.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 86-copy-ascii-table-B.lst
87.tap: 87-copy-ascii-table-C.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 87-copy-ascii-table-C.lst
88.tap: 88-copy-ascii-table-D.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 88-copy-ascii-table-D.lst
89.tap: 89-copy-ascii-table-E.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 89-copy-ascii-table-E.lst
90.tap: 90-copy-ascii-table-F.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 90-copy-ascii-table-F.lst
91.tap: 91-copy-ascii-table-G.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 91-copy-ascii-table-G.lst
92.tap: 92-copy-ascii-table-H.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 92-copy-ascii-table-H.lst
93.tap: 93-copy-ascii-table-I.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 93-copy-ascii-table-I.lst
94.tap: 94-color-attribute.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 94-color-attribute.lst
95.tap: 95-keypress.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 95-keypress.lst
96.tap: 96-keypress-row.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 96-keypress-row.lst
97.tap: 97-keypress-all-rows.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 97-keypress-all-rows.lst
98.tap: 98-game-character.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 98-game-character.lst
99.tap: 99-game-character-2.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 99-game-character-2.lst
100.tap: 100-cursor-joystick.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 100-cursor-joystick.lst
101.tap: 101-sinclair-joystick.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 101-sinclair-joystick.lst
102.tap: 102-kempston-joystick.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 102-kempston-joystick.lst
103.tap: 103-beep.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 103-beep.lst
104.tap: 104-music-scale.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 104-music-scale.lst
105.tap: 105-direct-speaker.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 105-direct-speaker.lst
106.tap: 106-direct-speaker-di.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 106-direct-speaker-di.lst
107.tap: 107-direct-speaker-border.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 107-direct-speaker-border.lst
108.tap: 108-direct-speaker-border-di.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 108-direct-speaker-border-di.lst
109.tap: 109-ay-note-a.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 109-ay-note-a.lst
110.tap: 110-ay-note-a.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 110-ay-note-a.lst
111.tap: 111-ay-two-notes.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 111-ay-two-notes.lst
112.tap: 112-ay-noise.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 112-ay-noise.lst
113.tap: 113-ay-low-frequency.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 113-ay-low-frequency.lst
114.tap: 114-ay-high-frequency.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 114-ay-high-frequency.lst
115.tap: 115-ay-low-noise.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 115-ay-low-noise.lst
116.tap: 116-ay-envelope.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 116-ay-envelope.lst
117.tap: 117-ay-envelope.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 117-ay-envelope.lst
118.tap: 118-ay-envelope.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 118-ay-envelope.lst
119.tap: 119-noise-envelope.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 119-noise-envelope.lst
120.tap: 120-8x8-sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 120-8x8-sprite.lst
121.tap: 121-24x24-sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 121-24x24-sprite.lst
122.tap: 122-24x24-sprite.asm sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 122-24x24-sprite.lst
123.tap: 123-24x24-sprite.asm sprite.bin
$(ASSEMBLER) -v -d --tapbas $< $@ > 123-24x24-sprite.lst
124.tap: 124-shifted-sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 124-shifted-sprite.lst
125.tap: 125-shifted-sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 125-shifted-sprite.lst
126.tap: 126-24x24-faster-sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 126-24x24-faster-sprite.lst
127.tap: 127-margins.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 127-margins.lst
128.tap: 128-margins.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 128-margins.lst
129.tap: 129-screen-addressing.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 129-screen-addressing.lst
130.tap: 130-screen-background.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 130-screen-background.lst
131.tap: 131-screen-background-and-sprite.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 131-screen-background-and-sprite.lst
132.tap: 132-improper-sprite-addressing.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 132-improper-sprite-addressing.lst
133.tap: 133-proper-sprite-addressing.asm
$(ASSEMBLER) -v -d --tapbas $< $@ > 133-proper-sprite-addressing.lst
19. Repositář s demonstračními příklady
V tabulce zobrazené pod tímto odstavcem jsou uvedeny odkazy na všechny prozatím popsané demonstrační příklady určené pro překlad a spuštění na osmibitovém domácím mikropočítači ZX Spectrum (libovolný model či jeho klon), které jsou psány v assembleru mikroprocesoru Zilog Z80. Pro překlad těchto demonstračních příkladů je možné použít například assembler Pasmo (viz též úvodní článek):
| # | Soubor | Stručný popis | Adresa |
|---|---|---|---|
| 1 | 01-color-attribute.asm | modifikace jednoho barvového atributu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/01-color-attribute.asm |
| 2 | 02-blinking-attribute.asm | barvový atribut s nastavením bitů pro blikání a vyšší intenzitu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/02-blinking-attribute.asm |
| 3 | 03-symbolic-names.asm | symbolická jména v assembleru | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/03-symbolic-names.asm |
| 4 | 04-operators.asm | operátory a operace se symbolickými hodnotami | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/04-operators.asm |
| 5 | 05-better-symbols.asm | tradičnější symbolická jména | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/05-better-symbols.asm |
| 6 | 06-tapbas-v1.asm | vygenerování BASICovského loaderu (neúplný příklad) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/06-tapbas-v1.asm |
| 7 | 07-tapbas-v2.asm | vygenerování BASICovského loaderu (úplný příklad) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/07-tapbas-v2.asm |
| 8 | 08-loop.asm | jednoduchá počítaná programová smyčka: naivní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/08-loop.asm |
| 9 | 09-loop.asm | programová smyčka: zkrácení kódu pro vynulování použitých pracovních registrů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/09-loop.asm |
| 10 | 10-loop.asm | programová smyčka: optimalizace skoku na konci smyčky (instrukce DJNZ) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/10-loop.asm |
| 11 | 11-loop.asm | programová smyčka: optimalizace využití pracovních registrů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/11-loop.asm |
| 12 | 12-loop.asm | programová smyčka: použití pracovního registru IX | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/12-loop.asm |
| 13 | 13-loop.asm | programová smyčka: použití pracovního registru IY | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/13-loop.asm |
| 14 | 14-loop.asm | programová smyčka se šestnáctibitovým počitadlem, základní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/14-loop.asm |
| 15 | 15-loop.asm | programová smyčka se šestnáctibitovým počitadlem, vylepšená varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/15-loop.asm |
| 16 | 16-loop.asm | použití relativního skoku a nikoli skoku absolutního | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/16-loop.asm |
| 17 | 17-loop.asm | programová smyčka: inc l namísto inc hl | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/17-loop.asm |
| 18 | 18-cls.asm | smazání obrazovky a otevření kanálu číslo 2 (screen) přes funkci v ROM | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/18-cls.asm |
| 19 | 19-print-char-call.asm | smazání obrazovky a výpis jednoho znaku na obrazovku přes funkci v ROM (použití instrukce CALL) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/19-print-char-call.asm |
| 20 | 20-print-char-rst.asm | smazání obrazovky a výpis jednoho znaku na obrazovku přes funkci v ROM (použití instrukce RST) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/20-print-char-rst.asm |
| 21 | 21-print-char.asm | pouze výpis jednoho znaku na obrazovku bez jejího smazání | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/21-print-char.asm |
| 22 | 22-print-all-chars.asm | výpis znakové sady znak po znaku (nekorektní verze příkladu) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/22-print-all-chars.asm |
| 23 | 23-print-all-chars.asm | výpis znakové sady znak po znaku (korektní verze příkladu) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/23-print-all-chars.asm |
| 24 | 24-change-color.asm | změna barvových atributů (popředí a pozadí) vypisovaných znaků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/24-change-color.asm |
| 25 | 25-change-flash.asm | povolení či zákaz blikání vypisovaných znaků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/25-change-flash.asm |
| 26 | 26-print-at.asm | výpis znaku či znaků na určené místo na obrazovce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/26-print-at.asm |
| 27 | 27-print-string.asm | výpis celého řetězce explicitně zapsanou programovou smyčkou (základní varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/27-print-string.asm |
| 28 | 28-print-string.asm | výpis celého řetězce explicitně zapsanou programovou smyčkou (vylepšená varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/28-print-string.asm |
| 29 | 29-print-colorized-string.asm | výpis řetězce, který obsahuje i řídicí znaky pro změnu barvy atd. | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/29-print-colorized-string.asm |
| 30 | 30-print-string-ROM.asm | výpis řetězce s využitím služby/subrutiny uložené v ROM ZX Spectra | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/30-print-string-ROM.asm |
| 31 | 31-attributes.asm | modifikace atributů pro tisk řetězce subrutinou uloženou v ROM | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/31-attributes.asm |
| 32 | 32-fill-in-vram.asm | vyplnění celé bitmapy barvou popředí, návrat do systému | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/32-fill-in-vram.asm |
| 33 | 33-fill-in-vram-no-ret.asm | vyplnění celé bitmapy barvou popředí, bez návratu do systému | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/33-fill-in-vram-no-ret.asm |
| 34 | 34-fill-in-vram-pattern.asm | vyplnění celé bitmapy zvoleným vzorkem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/34-fill-in-vram-pattern.asm |
| 35 | 35-slow-fill-in-vram.asm | pomalé vyplnění celé bitmapy, vizualizace struktury bitmapy | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/35-slow-fill-in-vram.asm |
| 36 | 36-slow-fill-in-vram-no-ret.asm | pomalé vyplnění celé bitmapy, vizualizace struktury bitmapy, bez návratu do systému | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/36-slow-fill-in-vram-no-ret.asm |
| 37 | 37-fill-block.asm | vykreslení bloku 8×8 pixelů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/37-fill-block.asm |
| 38 | 38-fill-block-with-pattern.asm | vykreslení bloku 8×8 pixelů zvoleným vzorkem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/38-fill-block-with-pattern.asm |
| 39 | 39-fill-block-optimized.asm | optimalizace předchozího příkladu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/39-fill-block-optimized.asm |
| 40 | 40-draw-char.asm | vykreslení znaku do levého horního rohu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/40-draw-char.asm |
| 41 | 41-draw-any-char.asm | podprogram pro vykreslení libovolně zvoleného znaku do levého horního rohu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/41-draw-any-char.asm |
| 42 | 42-block-anywhere.asm | podprogramy pro vykreslení bloku 8×8 pixelů kamkoli na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/42-block-anywhere.asm |
| 43 | 43-block-anywhere-rrca.asm | podprogramy pro vykreslení bloku 8×8 pixelů kamkoli na obrazovku, vylepšená varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/43-block-anywhere-rrca.asm |
| 44 | 44-better-draw-char.asm | vykreslení znaku v masce 8×8 pixelů, vylepšená varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/44-better-draw-char.asm |
| 45 | 45-even-better-draw-char.asm | posun offsetu pro vykreslení dalšího znaku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/45-even-better-draw-char.asm |
| 46 | 46-draw-char-at.asm | vykreslení znaku v masce 8×8 pixelů kamkoli na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/46-draw-char-at.asm |
| 47 | 47-draw-char-at-unrolled.asm | vykreslení znaku v masce 8×8 pixelů kamkoli na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/47-draw-char-at-unrolled.asm |
| 48 | 48-incorrect-print-string.asm | tisk řetězce, nekorektní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/48-incorrect-print-string.asm |
| 49 | 49-correct-print-string.asm | tisk řetězce, korektní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/49-correct-print-string.asm |
| 50 | 50-ascii-table.asm | tisk několika bloků ASCII tabulky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/50-ascii-table.asm |
| 51 | 51-plot-block.asm | vykreslení pixelu verze 1: zápis celého bajtu na pozici pixelu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/51-plot-block.asm |
| 52 | 52-plot-pixel.asm | vykreslení pixelu verze 2: korektní vykreslení jednoho pixelu, ovšem překreslení celého bajtu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/52-plot-pixel.asm |
| 53 | 53-plot-pixel.asm | vykreslení pixelu verze 3: vylepšená verze předchozího demonstračního příkladu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/53-plot-pixel.asm |
| 54 | 54-plot-pixel-on-background.asm | vykreslení pixelu vůči pozadí (nekorektní varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/54-plot-pixel-on-background.asm |
| 55 | 55-plot-pixel-on-background.asm | vykreslení pixelu vůči pozadí (korektní varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/55-plot-pixel-on-background.asm |
| 56 | 56-inverse-ascii-table.asm | vykreslení ASCII tabulky inverzní barvou (inkoust vs. papír) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/56-inverse-ascii-table.asm |
| 57 | 57-plot-pixel-on-inverse-background.asm | vykreslení pixelů barvou papíru proti inverzní ASCII tabulce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/57-plot-pixel-on-inverse-background.asm |
| 58 | 58-plot-inverse-pixel-on-inverse-background.asm | vykreslení pixelů inverzní barvou proti inverzní ASCII tabulce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm58-plot-inverse-pixel-on-inverse-background.asm/ |
| 59 | 59-configurable-ascii-table.asm | vykreslení ASCII tabulky buď přímo inkoustem nebo inverzně | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/59-configurable-ascii-table.asm |
| 60 | 60-plot-over.asm | přibližná implementace příkazu PLOT OVER | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/60-plot-over.asm |
| 61 | 61-print-number-A.asm | ukázka použití podprogramu pro tisk celého čísla | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/61-print-number-A.asm |
| 62 | 62-print-number-B.asm | pokus o vytištění záporných čísel | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/62-print-number-B.asm |
| 63 | 63-print-number-C.asm | tisk maximální podporované hodnoty 9999 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/63-print-number-C.asm |
| 64 | 64-print-number-D.asm | tisk vyšší než podporované hodnoty 10000 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/64-print-number-D.asm |
| 65 | 65-more-numbers-A.asm | vytištění číselné řady | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/65-more-numbers-A.asm |
| 66 | 66-more-numbers-B.asm | kombinace tisku celočíselných hodnot s dalšími subrutinami | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/66-more-numbers-B.asm |
| 67 | 67-print-flags-1.asm | příznakové bity po provedení celočíselné operace 1+2 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/67-print-flags-1.asm |
| 68 | 68-print-flags-2.asm | příznakové bity po provedení celočíselné operace 0+0 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/68-print-flags-2.asm |
| 69 | 69-print-flags-3.asm | příznakové bity po provedení operace 255+1 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/69-print-flags-3.asm |
| 70 | 70-print-flags-4.asm | příznakové bity po provedení operace 254+1 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/70-print-flags-4.asm |
| 71 | 71-print-flags-5.asm | příznakové bity po provedení operace 255+255 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/71-print-flags-5.asm |
| 72 | 72-print-flags-6.asm | výsledek operace 100+100, nastavení příznakových bitů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/72-print-flags-6.asm |
| 73 | 73-print-flags-7.asm | výsledek operace 128+128, nastavení příznakových bitů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/73-print-flags-7.asm |
| 74 | 74-print-hex-number.asm | tisk hexadecimálního čísla v rozsahu 0×00 až 0×ff (neoptimalizovaná varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/74-print-hex-number.asm |
| 75 | 75-print-hex-number.asm | tisk hexadecimálního čísla v rozsahu 0×00 až 0×ff (optimalizovaná varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/75-print-hex-number.asm |
| 76 | 76-print-hex-numbers.asm | tisk několika hexadecimálních hodnot | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/76-print-hex-numbers.asm |
| 77 | 77-add-hex-numbers.asm | součet dvou osmibitových hexadecimálních hodnot s tiskem všech výsledků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/77-add-hex-numbers.asm |
| 78 | 78-add-bcd-numbers.asm | součet dvou osmibitových BCD hodnot s tiskem všech výsledků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/78-add-bcd-numbers.asm |
| 79 | 79-print-hex-digit-jmp.asm | tisk jedné hexadecimální cifry s využitím podmíněného skoku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/79-print-hex-digit-jmp.asm |
| 80 | 80-print-hex-digit-overflow.asm | otestování, jaký znak je vytištěn pro hodnoty větší než 15 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/80-print-hex-digit-overflow.asm |
| 81 | 81-print-hex-digit-daa.asm | tisk jedné hexadecimální cifry s využitím instrukce DAA | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/81-print-hex-digit-daa.asm |
| 82 | 82-print-hex-numbers-daa.asm | tisk série hexadecimálních hodnot s využitím instrukce DAA | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/82-print-hex-numbers-daa.asm |
| 83 | 83-print-fp-numbers.asm | tisk numerických hodnot reprezentovaných v systému plovoucí řádové tečky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/83-print-fp-numbers.asm |
| 84 | 84-print-ascii-table.asm | tisk jednoho bloku s ASCII tabulkou | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/84-print-ascii-table.asm |
| 85 | 85-copy-ascii-table.asm | kopie bloku bajt po bajtu založená na naivní programové smyčce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/85-copy-ascii-table.asm |
| 86 | 86-copy-ascii-table-B.asm | kopie bloku s využitím instrukce LDIR | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/86-copy-ascii-table-B.asm |
| 87 | 87-copy-ascii-table-C.asm | kopie bloku bajt po bajtu založená na programové smyčce a instrukci LDI | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/87-copy-ascii-table-C.asm |
| 88 | 88-copy-ascii-table-D.asm | rozbalení programové smyčky s instrukcí LDI | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/88-copy-ascii-table-D.asm |
| 89 | 89-copy-ascii-table-E.asm | korektní smyčka pro všechny možné velikosti bloků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/89-copy-ascii-table-E.asm |
| 90 | 90-copy-ascii-table-F.asm | kostra programu, který pro kopii bloků (16 bajtů) využívá zásobník | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/90-copy-ascii-table-F.asm |
| 91 | 91-copy-ascii-table-G.asm | definice makra a několikeré použití (aplikace) tohoto makra | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/91-copy-ascii-table-G.asm |
| 92 | 92-copy-ascii-table-H.asm | opakování makra založené na REPT | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/92-copy-ascii-table-H.asm |
| 93 | 93-copy-ascii-table-I.asm | vícenásobná kopie části obrazovky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/93-copy-ascii-table-I.asm |
| 94 | 94-color-attribute.asm | modifikace jednoho barvového atributu na obrazovce ZX Spectra | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/94-color-attribute.asm |
| 95 | 95-keypress.asm | detekce stisku jedné klávesy s vizualizací stisku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/95-keypress.asm |
| 96 | 96-keypress-row.asm | detekce stisku kláves v jednom fyzickém řádku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/96-keypress-row.asm |
| 97 | 97-keypress-all-rows.asm | detekce stisku všech kláves klávesnice ZX Spectra 48k | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/97-keypress-all-rows.asm |
| 98 | 98-game-character.asm | zajištění pohybu hráče v herní scéně s využitím klávesnice | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/98-game-character.asm |
| 99 | 99-game-character-2.asm | vylepšení předchozího demonstračního příkladu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/99-game-character-2.asm |
| 100 | 100-cursor-joystick.asm | zajištění pohybu hráče v herní scéně kurzorovým joystickem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/100-cursor-joystick.asm |
| 101 | 101-sinclair-joystick.asm | zajištění pohybu hráče v herní scéně joystickem připojeným přes Interface 2 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/101-sinclair-joystick.asm |
| 102 | 102-kempston-joystick.asm | zajištění pohybu hráče v herní scéně joystickem připojeným přes rozhraní Kempston | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/102-kempston-joystick.asm |
| 103 | 103-beep.asm | využití subrutiny v ROM s implementací příkazu BEEP | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/103-beep.asm |
| 104 | 104-music-scale.asm | přehrání celé stupnice | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/104-music-scale.asm |
| 105 | 105-direct-speaker.asm | přímé programové ovládání beeperu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/105-direct-speaker.asm |
| 106 | 106-direct-speaker-di.asm | zakázání přerušení při přehrávání | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/106-direct-speaker-di.asm |
| 107 | 107-direct-speaker-border.asm | vizualizace frekvence přehrávání změnou okraje v reálném čase | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/107-direct-speaker-border.asm |
| 108 | 108-direct-speaker-border-di.asm | vizualizace frekvence přehrávání změnou okraje v reálném čase | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/108-direct-speaker-border-di.asm |
| 109 | 109-ay-note-a.asm | přehrání komorního A na čipu AY-3–8912 na ZX Spectru | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/109-ay-note-a.asm |
| 110 | 110-ay-note-a.asm | přehrání komorního A na čipu AY-3–8912 na ZX Spectru | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/110-ay-note-a.asm |
| 111 | 111-ay-two-notes.asm | souběžné přehrání dvojice not | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/111-ay-two-notes.asm |
| 112 | 112-ay-noise.asm | vygenerování šumu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/112-ay-noise.asm |
| 113 | 113-ay-low-frequency.asm | čistý tón s nízkou frekvencí | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/113-ay-low-frequency.asm |
| 114 | 114-ay-high-frequency.asm | čistý tón s vysokou frekvencí | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/114-ay-high-frequency.asm |
| 115 | 115-ay-low-noise.asm | vygenerování šumu s nízkou frekvencí | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/115-ay-low-noise.asm |
| 116 | 116-ay-envelope.asm | použití obálky založené na trojúhelníkovém signálu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/116-ay-envelope.asm |
| 117 | 117-ay-envelope.asm | použití obálky založené na trojúhelníkovém signálu s vysokou frekvencí | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/117-ay-envelope.asm |
| 118 | 118-ay-envelope.asm | použití obálky založené na trojúhelníkovém signálu s nízkou frekvencí | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/118-ay-envelope.asm |
| 119 | 119-noise-envelope.asm | použití obálky společně se šumem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/119-noise-envelope.asm |
| 120 | 120–8×8-sprite.asm | vykreslení spritu o velikosti 8×8 pixelů na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/120–8×8-sprite.asm |
| 121 | 121–24×24-sprite.asm | vykreslení spritu o velikosti 24×24 pixelů na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/121–24×24-sprite.asm |
| 122 | 122–24×24-sprite.asm | načtení spritu o velikosti 24×24 pixelů z include souboru a jeho vykreslení na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/122–24×24-sprite.asm |
| 123 | 123–24×24-sprite.asm | načtení spritu o velikosti 24×24 pixelů z binárního souboru a jeho vykreslení na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/123–24×24-sprite.asm |
| 124 | 124-shifted-sprite.asm | načtení spritů posunutých o 0 až 7 pixelů z binárních souborů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/124-shifted-sprite.asm |
| 125 | 125-shifted-sprite.asm | načtení spritů posunutých o 0 až 7 pixelů z include souborů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/125-shifted-sprite.asm |
| 126 | 126–24×24-faster-sprite.asm | úprava příkladu 121–24×24-sprite.asm do rychlejší podoby | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/126–24×24-faster-sprite.asm |
| 127 | 127-margins.asm | pokus o vykreslení spritu blízko pravého okraje obrazovky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/127-margins.asm |
| 128 | 128-margins.asm | pokus o vykreslení spritu blízko spodního okraje obrazovky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/128-margins.asm |
| 129 | 129-screen-addressing.asm | problém uspořádání obrazových řádků na ZX Spectru | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/129-screen-addressing.asm |
| 130 | 130-screen-background.asm | vykreslení statického obrázku na obrazovku ZX Spectra | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/130-screen-background.asm |
| 131 | 131-screen-background-and-sprite.asm | vykreslení spritu na obrazovku se statickým obrázkem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/131-screen-background-and-sprite.asm |
| 132 | 132-improper-sprite-addresing.asm | větší množství spritů, nekorektní výpočty adres řádků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/132-improper-sprite-addresing.asm |
| 133 | 133-proper-sprite-addresing.asm | větší množství spritů, korektní výpočty adres řádků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/133-proper-sprite-addresing.asm |
| 134 | Makefile | Makefile pro překlad a slinkování všech demonstračních příkladů do podoby obrazu magnetické pásky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/Makefile |
20. Odkazy na Internetu
- z80 standalone assembler
https://www.asm80.com/onepage/asmz80.html - The ZX BASIC Compiler
https://www.boriel.com/pages/the-zx-basic-compiler.html - Z80 Assembly programming for the ZX Spectrum
https://www.chibiakumas.com/z80/ZXSpectrum.php - 8-BIT SMACKDOWN! 65C02 vs. Z80: slithy VLOGS #6
https://www.youtube.com/watch?v=P1paVoFEvyc - Instrukce mikroprocesoru Z80
https://clrhome.org/table/ - Z80 instructions: adresní režimy atd.
https://jnz.dk/z80/instructions.html - Z80 Instruction Groups
https://jnz.dk/z80/instgroups.html - Elena, New programming language for the ZX Spectrum Next
https://vintageisthenewold.com/elena-new-programming-language-for-the-zx-spectrum-next/ - Sinclair BASIC
https://worldofspectrum.net/legacy-info/sinclair-basic/ - Grafika na osmibitových počítačích firmy Sinclair
https://www.root.cz/clanky/grafika-na-osmibitovych-pocitacich-firmy-sinclair/ - Grafika na osmibitových počítačích firmy Sinclair II
https://www.root.cz/clanky/grafika-na-osmibitovych-pocitacich-firmy-sinclair-ii/ - HiSoft BASIC
https://worldofspectrum.net/infoseekid.cgi?id=0008249 - YS MegaBasic
https://worldofspectrum.net/infoseekid.cgi?id=0008997 - Beta Basic
https://worldofspectrum.net/infoseekid.cgi?id=0007956 - BASIC+
https://worldofspectrum.net/infoseekid.php?id=0014277 - Spectrum ROM Memory Map
https://skoolkit.ca/disassemblies/rom/maps/all.html - Goto subroutine
https://skoolkit.ca/disassemblies/rom/asm/7783.html - Spectrum Next: The Evolution of the Speccy
https://www.specnext.com/about/ - Sedmdesátiny assemblerů: lidsky čitelný strojový kód
https://www.root.cz/clanky/sedmdesatiny-assembleru-lidsky-citelny-strojovy-kod/ - Programovací jazyk BASIC na osmibitových mikropočítačích
https://www.root.cz/clanky/programovaci-jazyk-basic-na-osmibitovych-mikropocitacich/ - Programovací jazyk BASIC na osmibitových mikropočítačích (2)
https://www.root.cz/clanky/programovaci-jazyk-basic-na-osmibitovych-mikropocitacich-2/#k06 - Programovací jazyk BASIC na osmibitových mikropočítačích (3)
https://www.root.cz/clanky/programovaci-jazyk-basic-na-osmibitovych-mikropocitacich-3/ - Sinclair BASIC (Wikipedia CZ)
http://cs.wikipedia.org/wiki/Sinclair_BASIC - Assembly Language: Still Relevant Today
http://wilsonminesco.com/AssyDefense/ - Programovani v assembleru na OS Linux
http://www.cs.vsb.cz/grygarek/asm/asmlinux.html - Why Assembly Language Programming? (Why Learning Assembly Language Is Still a Good Idea)
https://wdc65×x.com/markets/education/why-assembly-language-programming/ - Low Fat Computing
http://www.ultratechnology.com/lowfat.htm - Assembly Language
https://www.cleverism.com/skills-and-tools/assembly-language/ - Why do we need assembly language?
https://cs.stackexchange.com/questions/13287/why-do-we-need-assembly-language - Assembly language (Wikipedia)
https://en.wikipedia.org/wiki/Assembly_language#Historical_perspective - Assembly languages
https://curlie.org/Computers/Programming/Languages/Assembly/ - vasm
http://sun.hasenbraten.de/vasm/ - B-ELITE
https://jsj.itch.io/b-elite - ZX-Spectrum Child
http://www.dotkam.com/2008/11/19/zx-spectrum-child/ - Speccy.cz
http://www.speccy.cz/ - Planet Sinclair
http://www.nvg.ntnu.no/sinclair/ - World of Spectrum
http://www.worldofspectrum.org/ - The system variables
https://worldofspectrum.org/ZXBasicManual/zxmanchap25.html - ZX Spectrum manual: chapter #17 Graphics
https://worldofspectrum.org/ZXBasicManual/zxmanchap17.html - Why does Sinclair BASIC have two formats for storing numbers in the same structure?
https://retrocomputing.stackexchange.com/questions/8834/why-does-sinclair-basic-have-two-formats-for-storing-numbers-in-the-same-structu - Plovoucí řádová čárka na ZX Spectru
https://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/#k05 - Norma IEEE 754 a příbuzní: formáty plovoucí řádové tečky
https://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/#k05 - 1A1B: THE ‚REPORT AND LINE NUMBER PRINTING‘ SUBROUTINE
https://skoolkid.github.io/rom/asm/1A1B.html - 2DE3: THE ‚PRINT A FLOATING-POINT NUMBER‘ SUBROUTINE
https://skoolkid.github.io/rom/asm/2DE3.html - 5C63: STKBOT – Address of bottom of calculator stack
https://skoolkid.github.io/rom/asm/5C63.html - 5C65: STKEND – Address of start of spare space
https://skoolkid.github.io/rom/asm/5C65.html - Why does Sinclair BASIC have two formats for storing numbers in the same structure?
https://retrocomputing.stackexchange.com/questions/8834/why-does-sinclair-basic-have-two-formats-for-storing-numbers-in-the-same-structu - Chapter 24: The memory
https://worldofspectrum.org/ZXBasicManual/zxmanchap24.html - Survey of Floating-Point Formats
https://mrob.com/pub/math/floatformats.html - Convert an 8bit number to hex in z80 assembler
https://stackoverflow.com/questions/22838444/convert-an-8bit-number-to-hex-in-z80-assembler - 80 MICROPROCESSOR Instruction Set Summary
http://www.textfiles.com/programming/CARDS/z80 - Extended Binary Coded Decimal Interchange Code
http://en.wikipedia.org/wiki/EBCDIC - ASCII/EBCDIC Conversion Table
http://docs.hp.com/en/32212–90008/apcs01.html - EBCDIC
http://www.hansenb.pdx.edu/DMKB/dict/tutorials/ebcdic.php - EBCDIC tables
http://home.mnet-online.de/wzwz.de/temp/ebcdic/cc_en.htm - The Mainframe Blog
http://mainframe.typepad.com/blog/2006/11/my_personal_mai.html - Binary-coded decimal
https://en.wikipedia.org/wiki/Binary-coded_decimal - BCD
https://cs.wikipedia.org/wiki/BCD - Z80 heaven: Floating Point
http://z80-heaven.wikidot.com/floating-point - Z80, the 8-bit Number Cruncher
http://www.andreadrian.de/oldcpu/Z80_number_cruncher.html - Floating-point library for Z80
https://github.com/DW0RKiN/Floating-point-Library-for-Z80 - z80float
https://github.com/Zeda/z80float - Fixed point arithmetic
https://www.root.cz/clanky/fixed-point-arithmetic/ - ZX Spectrum BASIC Programming – 2nd Edition
https://archive.org/details/zx-spectrum-basic-programming/page/n167/mode/2up - ZX Spectrum BASIC Programming – 2nd Edition
https://archive.org/details/zx-spectrum-basic-programming/page/n169/mode/2up - How fast is memcpy on the Z80?
https://retrocomputing.stackexchange.com/questions/4744/how-fast-is-memcpy-on-the-z80 - How do Z80 Block Transfer instructions work?
https://retrocomputing.stackexchange.com/questions/5416/how-do-z80-block-transfer-instructions-work - Retro Programming Made Simple: Keyboard
http://www.breakintoprogram.co.uk/hardware/computers/zx-spectrum/keyboard - How ZX Spectrum avoided key ghosting
https://retrocomputing.stackexchange.com/questions/16235/how-zx-spectrum-avoided-key-ghosting - ZX Spectrum Keyboard Visualized
http://www.kameli.net/marq/?p=2055 - Sinclair ZX Spectrum Joysticks Explained
https://www.retroisle.com/general/spectrum_joysticks.php - When A Single Bit Was Enough, Into The Sound Of The ZX Spectrum
https://hackaday.com/2022/01/20/when-a-single-bit-was-enough-into-the-sound-of-the-zx-spectrum/ - 03B5: THE ‚BEEPER‘ SUBROUTINE
https://skoolkid.github.io/rom/asm/03B5.html - How To Write ZX Spectrum Games – Chapter 3
https://chuntey.wordpress.com/2013/02/28/how-to-write-zx-spectrum-games-chapter-3/ - Understanding computer sound
https://www.youtube.com/playlist?list=PL0qES-IQZC8w4vqeQhxHxKgxYYqs3CEOx - Understanding Computer Sound. 5. ZX Spectrum
https://www.youtube.com/watch?v=N5ACJd2LvbY - Dark Fusion (Gremlin Graphics, 1988)
https://www.youtube.com/watch?v=ADL3mdRMzoA - Arkanoid Spectrum Title Music
https://www.youtube.com/watch?v=TymO0Lj7Vp8 - Tim Follin – „Chronos“ (ZX Spectrum) [Oscilloscope Visualization]
https://www.youtube.com/watch?v=yJy45MHrPjc - [60 FPS] Wally Beben – „Sanxion Loader“ [ZX Spectrum (Beeper)] (Oscilloscope View)
https://www.youtube.com/watch?v=JwMxOfQVl7A - Understanding Computer Sound
http://forgottencomputer.com/retro/sound/ - AY-3–8912
https://sinclair.wiki.zxnet.co.uk/wiki/AY-3–8912 - AY-3–8912
https://github.com/topics/ay-3–8912 - Z80 Assembly programming for the ZX Spectrum
https://www.chibiakumas.com/z80/ZXSpectrum.php?noui=1 - AY-3–8910
http://vgmpf.com/Wiki/index.php/AY-3–8910 - AY-3–8910/8912 Programmable sound generator data manual
https://f.rdw.se/AY-3–8910-datasheet.pdf - Sprite (computer graphics)
https://en.wikipedia.org/wiki/Sprite_(computer_graphics) - Piskel is a free online editor for animated sprites & pixel art
https://www.piskelapp.com/ - TAP format
https://sinclair.wiki.zxnet.co.uk/wiki/TAP_format