Programování pro osmibitová Atari: čip GTIA a práce se sprity

Dnes
Doba čtení: 41 minut

Sdílet

Projekt Atari perex.
Autor: Michal Tauchman, podle licence: CC BY-SA 4.0
Projekt Atari perex.
Dnes si popíšeme způsob práce se sprity (pohyblivými objekty na obrazovce). Tento typ grafiky se u Atari nazývá PMG neboli Player-Missile Graphics. O zobrazení PMG se stará čip GTIA, jenž ideově vychází ze staršího čipu TIA.

Práce se sprity: čip GTIA

Co se dozvíte v článku
  1. Práce se sprity: čip GTIA
  2. Řídicí a stavové registry čipu GTIA
  3. Praktické příklady využití čipu GTIA při práci se sprity
  4. Inicializace PMG, povolení PMG, nastavení pozice a globálního tvaru prvního hráče
  5. Úplný zdrojový kód prvního demonstračního příkladu
  6. Nastavení barvy prvního hráče
  7. Zákaz DMA, pokud se mají zobrazit jen globální tvary hráčů
  8. Modifikace šířky hráčů
  9. Změna globálního tvaru hráče
  10. Priority PMG vůči hracímu poli a pozadí
  11. Zobrazení dvou překrývajících se hráčů současně, režim „multicolor“
  12. Nastavení bitmapy spritů (hráčů i střel)
  13. Demonstrační příklad: naivní nastavení bitmapy prvního hráče
  14. Přečtení bitmapy (tvaru) hráče z pole s daty
  15. Zobrazení čtyř hráčů současně se změnou priorit
  16. Nastavení bitmap všech čtyř hráčů
  17. Příloha A: Seznam všech doposud popsaných instrukcí mikroprocesoru MOS 6502
  18. Příloha B: Makefile pro překlad všech demonstračních příkladů
  19. Repositář s demonstračními příklady
  20. Odkazy na Internetu

Dnes navážeme na předchozí článek, ve kterém jsme se začali zabývat popisem grafického subsystému osmibitových Atari. Dnes si popíšeme způsob práce se sprity (pohyblivými objekty na obrazovce). Tento typ grafiky se u Atari nazývá PMG neboli Player-Missile Graphics. O zobrazení PMG se stará čip GTIA, jenž ideově vychází ze staršího čipu TIA.

Pro porovnání shodných vlastností a rozdílů mezi čipy TIA a GTIA se podívejme na následující dvojici tabulek. V první tabulce jsou vypsány grafické objekty, s nimiž dokázal pracovat původní čip TIA použitý v herní konzoli Atari 2600:

# Typ objektu Orig.název Objem paměti Šířka reprezentovaná jedním bitem
1 Pozadí Background 0 bitů ×
2 Hrací plocha Playground 20 bitů 4× základní šířka pixelu
3 Míč Ball 1 bit 1×, 2×, 4×, 8× šířka pixelu
4 Hráč 0 Player 0 8 bitů 1×, 2×, 4× šířka pixelu
5 Střela 0 Missile 0 1 bit 1×, 2×, 4×, 8× šířka pixelu
6 Hráč 1 Player 1 8 bitů 1×, 2×, 4× šířka pixelu
7 Střela 1 Missile 1 1 bit 1×, 2×, 4×, 8× šířka pixelu

Ve druhé tabulce jsou vypsány grafické objekty, s nimiž dokázal pracovat čip GTIA použitý v herní konzoli Atari 5200 i v prakticky všech osmibitových domácích počítačích Atari (pokud tedy nepočítáme prvních zhruba 100 000 počítačů Atari 400 a Atari 800 s čipy CTIA:

# Typ objektu Orig.název Objem paměti Šířka reprezentovaná jedním bitem
1 Pozadí Background 0 bitů barva v COLBK, přes celou šířku řádku
2 Hrací plocha Playground x bitů generováno v ANTIC
3 Hráč 0 Player 0 8 bitů×128/256 1×, 2×, 4× šířka pixelu
4 Střela 0 Missile 0 2 bity×128/256 1×, 2×, 4×, 8× šířka pixelu
5 Hráč 1 Player 1 8 bitů×128/256 1×, 2×, 4× šířka pixelu
6 Střela 1 Missile 1 2 bity×128/256 1×, 2×, 4×, 8× šířka pixelu
7 Hráč 2 Player 2 8 bitů×128/256 1×, 2×, 4× šířka pixelu
8 Střela 2 Missile 2 2 bity×128/256 1×, 2×, 4×, 8× šířka pixelu
9 Hráč 3 Player 3 8 bitů×128/256 1×, 2×, 4× šířka pixelu
10 Střela 3 Missile 3 2 bity×128/256 1×, 2×, 4×, 8× šířka pixelu
Poznámka: pojem hráč a střela bude použit i v tomto článku.

Řídicí a stavové registry čipu GTIA

Nejprve si uvedeme tabulku se všemi řídicími registry čipu GTIA. Ten byl řízen s využitím registrů, z nichž všechny byly určeny pro zápis a některé taktéž pro čtení, tj. například pro zjišťování kolizí atd. (při čtení mají jiné jméno, než při zápisu). Většina z těchto registrů (konkrétně všechny registry související s grafikou) je vypsána v následující tabulce. Tabulka obsahuje více než 32 položek, protože stejná adresa registru při čtení má jiný význam, než při zápisu:

Registr Režim Význam
COLPM0 W barva hráče číslo 0 a střely číslo 0
COLPM1 W barva hráče číslo 1 a střely číslo 1
COLPM2 W barva hráče číslo 2 a střely číslo 2
COLPM3 W barva hráče číslo 3 a střely číslo 3
COLPF0 W barva pro herní pole číslo 0
COLPF1 W barva pro herní pole číslo 1
COLPF2 W barva pro herní pole číslo 2
COLPF3 W barva pro herní pole číslo 3
COLBK W barva pozadí
     
HPOSP0 W horizontální pozice hráče číslo 0
HPOSP1 W horizontální pozice hráče číslo 1
HPOSP2 W horizontální pozice hráče číslo 2
HPOSP3 W horizontální pozice hráče číslo 3
HPOSM0 W horizontální pozice střely číslo 0
HPOSM1 W horizontální pozice střely číslo 1
HPOSM2 W horizontální pozice střely číslo 2
HPOSM3 W horizontální pozice střely číslo 3
     
SIZEP0 W horizontální zvětšení hráče číslo 0 (1×, 2×, 4×)
SIZEP1 W horizontální zvětšení hráče číslo 1 (1×, 2×, 4×)
SIZEP2 W horizontální zvětšení hráče číslo 2 (1×, 2×, 4×)
SIZEP3 W horizontální zvětšení hráče číslo 3 (1×, 2×, 4×)
SIZEM W horizontální zvětšení všech střel (1×, 2×, 4×)
     
GRAFP0 W bitová data pro hráče číslo 0
GRAFP1 W bitová data pro hráče číslo 1
GRAFP2 W bitová data pro hráče číslo 2
GRAFP3 W bitová data pro hráče číslo 3
GRAFM W bitová data pro všechny střely
     
PRIOR W řízení priority objektů a taktéž výběr grafického režimu
GRACTL W povolení PMG
     
M0PF R kolizní registr mezi střelou číslo 0 a herním polem
M1PF R kolizní registr mezi střelou číslo 1 a herním polem
M2PF R kolizní registr mezi střelou číslo 2 a herním polem
M3PF R kolizní registr mezi střelou číslo 3 a herním polem
P0PF R kolizní registr mezi hráčem číslo 0 a herním polem
P1PF R kolizní registr mezi hráčem číslo 1 a herním polem
P2PF R kolizní registr mezi hráčem číslo 2 a herním polem
P3PF R kolizní registr mezi hráčem číslo 3 a herním polem
M0PL R kolizní registr mezi střelou číslo 0 a hráčem
M1PL R kolizní registr mezi střelou číslo 1 a hráčem
M2PL R kolizní registr mezi střelou číslo 2 a hráčem
M3PL R kolizní registr mezi střelou číslo 3 a hráčem
P0PL R kolizní registr mezi hráčem číslo 0 a dalším hráčem
P1PL R kolizní registr mezi hráčem číslo 1 a dalším hráčem
P2PL R kolizní registr mezi hráčem číslo 2 a dalším hráčem
P3PL R kolizní registr mezi hráčem číslo 3 a dalším hráčem

Praktické příklady využití čipu GTIA při práci se sprity

Práci se sprity si ukážeme na deseti demonstračních příkladech, přičemž další příklady budou ukázány v navazujícím článku. V dnešních příkladech bude ukázán způsob povolení zobrazení PMG, nastavení horizontálních souřadnic hráčů, nastavení jejich barvy, velikosti a tvaru (tj. způsobu zobrazení na obrazovce) a popíšeme si taktéž změnu priorit při zobrazování, tj. způsob řešení překryvu hráčů a střel s pozadím nebo mezi sebou navzájem.

Ovšem to ve skutečnosti není vše, co systém PMG na osmibitových Atari nabízí. Přímo na hardwarové úrovni je řešena i detekce kolizí, což může do značné míry urychlit algoritmy používané ve hrách (v podstatě se mohou zcela odstranit výpočty kolizí). Navíc je hardwarová detekce kolizí provedena s přesností na jednotlivé pixely, takže není nutné provádět optimalizace s využitím takzvaných bounding boxů atd. Ve výsledku může být práce s PMG velmi efektivní z hlediska celkové rychlosti her, a to i přesto, že je nutné softwarově řešit vertikální posuny (naopak například na počítačích Commodore C64 je i tento problém řešitelný přímo na úrovni hardware).

Inicializace PMG, povolení PMG, nastavení pozice a globálního tvaru prvního hráče

Na moderních počítačích a moderních operačních systémech může být inicializace grafiky (například ve hrách) relativně složitá, a to i přesto, že se používají různé vysokoúrovňové knihovny. Na osmibitových Atari tomu tak ovšem není, protože pro zobrazení hráče (řekněme prvního hráče s číslem 0) postačuje provést pouhé dvě operace, konkrétně dva zápisy do HW registrů čipu GTIA:

  1. Je nutné přenastavit horizontální pozici hráče, což je osmibitová hodnota, která se v případě prvního hráče zapisuje do registruHPOS0 (určeno jen pro zápis). Jaký je přesný vztah mezi pozicí hráče a pixelem herního pole, se dozvíme příště.
  2. Taktéž je nutné nastavit bitmapu hráče (má rozlišení 8×128 pixelů), a to buď přímo změnou bitmapy (ukážeme si v dalších kapitolách) nebo zápisem osmi bitů do registru GRAFP0. Tím se nastaví všechny řádky bitmapy na stejnou hodnotu. Bit s hodnotou 1 znamená „kreslí se barva hráče“, nulový bit znamená „pixel je průhledný, tj. kreslí se barva pod hráčem“.

Úplný zdrojový kód prvního demonstračního příkladu

V dnešním prvním demonstračním příkladu nastavíme horizontální pozici hráče na hodnotu 128 (blízko středu obrazovky) a jeho tvar na samé jedničky, takže všechny pixely hráče budou zobrazeny jeho barvou.

Úplný zdrojový kód dnešního prvního demonstračního příkladu, od něhož budou odvozeny i všechny další příklady, vypadá následovně:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice a tvaru prvního hráče.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
 
.proc main
        lda #128                ; horizontální pozice hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #$ff                ; bitová maska hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
loop:   jmp loop
end:
.endproc
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   main::end - 1           ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Po spuštění se na obrazovce ukáže vertikální černý pruh:

Černý pruh představující prvního hráče, který je zobrazený zhruba uprostřed obrazovky.

Obrázek 1: Černý pruh představující prvního hráče. 

Autor: tisnik, podle licence: Rights Managed

Nastavení barvy prvního hráče

Při pohledu do tabulky uvedené ve druhé kapitole snadno zjistíme, že barva prvního hráče je nastavována řídicím registrem COLPM0. Jenže tento registr nelze přečíst (jeho význam je při čtení odlišný). A proto existuje v paměti Atari několik takzvaných stínových registrů, které jsou automaticky (v každém snímku) zapisovány do registrů GTIA (a jejich čtení je tedy možné a je triviální). Pro COLM0 existuje stínový registr nazvaný PCOLR3, kterým (v dalším snímku) změníme barvu prvního hráče:

        lda #HUE_MAGENTA<<4 + 8 ; barva hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA

Nyní bude obrazovka vypadat odlišně:

Barevný pruh představující prvního hráče, který je zobrazený zhruba uprostřed obrazovky.

Obrázek 2: Barevný pruh představující prvního hráče, který je zobrazený zhruba uprostřed obrazovky. 

Autor: tisnik, podle licence: Rights Managed

Výsledný zdrojový kód příkladu:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, tvaru a barvy prvního hráče.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
 
.proc main
        lda #128                ; horizontální pozice hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #HUE_MAGENTA<<4 + 8 ; barva hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #$ff                ; bitová maska hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
loop:   jmp loop
end:
.endproc
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   main::end - 1           ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Zákaz DMA, pokud se mají zobrazit jen globální tvary hráčů

Prozatím nepracujeme s bitmapami spritů a proto můžeme vypnout DMA. Jedná se o technologii, kterou GTIA využívá pro získání tvarů spritů při vykreslování snímků. My ale prozatím pracujeme s hráčem, jehož všechny řádky jsou stejné a proto můžeme DMA vypnout a počítač tak urychlit (více cyklů pro CPU). To se provede následovně:

        lda #0                  ; bitové pole: vše nulové
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA

Výsledek by měl být stejný, jako v příkladu předchozím, ovšem CPU má nyní k dispozici více strojových cyklů:

Barevný pruh představující prvního hráče, který je zobrazený zhruba uprostřed obrazovky. Vypnutí DMA nemá na zobrazení vliv.

Obrázek 3: Barevný pruh představující prvního hráče, který je zobrazený zhruba uprostřed obrazovky. Vypnutí DMA nemá na zobrazení vliv. 

Autor: tisnik, podle licence: Rights Managed

Úplný zdrojový kód třetího demonstračního příkladu:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, tvaru a barvy prvního hráče.
; Zákaz DMA.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
 
.proc main
        lda #128                ; horizontální pozice hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #HUE_MAGENTA<<4 + 8 ; barva hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #$ff                ; bitová maska hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
        lda #0                  ; bitové pole: vše nulové
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
loop:   jmp loop
end:
.endproc
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   main::end - 1           ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Modifikace šířky hráčů

Zajímavé možnosti nabízí registry SIZEPx a SIZEM. Nejnižšími dvěma bity je možné nastavit šířku pixelů hráčů a/nebo střel. Hodnota 00 znamená normální šířku odpovídající dvěma pixelům hracího pole v nejvyšším rozlišení (tato šířka odpovídá jednomu taktu hodin pro generování barvy na TV, více informací bude uvedeno v popisu čipu ANTIC). Hodnota 01 znamená dvojnásobnou šířku a hodnota 11 pak šířku čtyřnásobnou.

V dalším demonstračním příkladu se postupně mění šířka prvního hráče, a to modifikací obsahu HW registru SIZEP0. Mezi jednotlivými změnami velikostí se čeká na stisk klávesy (mimochodem: malou úpravou dosáhnete toho, že se po změně na čtyřnásobnou velikost řízení vrátí zpět na začátek programu – tuto úpravu ponechávám na laskavém čtenáři):

První hráč s&nbsp;výchozí velikostí.

Obrázek 4: První hráč s výchozí velikostí. 

Autor: tisnik, podle licence: Rights Managed

První hráč s&nbsp;dvojnásobnou velikostí.

Obrázek 5: První hráč s dvojnásobnou velikostí. 

Autor: tisnik, podle licence: Rights Managed

První hráč se čtyřnásobnou velikostí.

Obrázek 6: První hráč se čtyřnásobnou velikostí. 

Autor: tisnik, podle licence: Rights Managed

Následuje výpis úplného zdrojového kódu tohoto demonstračního příkladu:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, tvaru a barvy prvního hráče.
; Zákaz DMA. Postupná změna horizontální velikosti hráče.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
KBHANDLER = $e424               ; rutina pro cteni klavesy
 
 
.proc main
        lda #128                ; horizontální pozice hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #HUE_MAGENTA<<4 + 8 ; barva hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #$ff                ; bitová maska hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
        lda #0                  ; bitové pole: vše nulové
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #1                  ; horizontální velikost hráče
        sta SIZEP0              ; uložit do řídicího registru SIZEP0 na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #3                  ; horizontální velikost hráče
        sta SIZEP0              ; uložit do řídicího registru SIZEP0 na čipu GTIA
 
loop:   jmp loop
.endproc
 
.proc get_key
        lda KBHANDLER+1         ; cteni horni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        lda KBHANDLER           ; cteni dolni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        rts                     ; vyber adresy ze zasobniku + skok
                                ; zde neni nutne mit RTS
.endproc
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Změna globálního tvaru hráče

Prozatím jsme do HW registru GRAFP0 zapisovali hodnotu 0×ff, tj. všechny bity byly nastaveny na jedničku. První hráč byl zobrazen formou vertikálního pruhu o šířce 16, 32 nebo 64 pixelů (počítáme v pixelech hracího pole). Ovšem pokud zapíšeme hodnotu odlišnou, budou některé pruhy hráče průhledné. Můžeme například vynechat každý lichý bit a tudíž i každý lichý sloupec bude průhledný:

        lda #128+32+8+2         ; bitová maska hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA

Výsledek pro různě nastavené šířky hráčů:

První hráč má nyní odlišný tvar (všechny jeho řádky jsou však stále totožné).

Obrázek 7: První hráč má nyní odlišný tvar (všechny jeho řádky jsou však stále totožné). 

Autor: tisnik, podle licence: Rights Managed

První hráč má nyní odlišný tvar (všechny jeho řádky jsou však stále totožné), dvojnásobná šířka.

Obrázek 8: První hráč má nyní odlišný tvar (všechny jeho řádky jsou však stále totožné), dvojnásobná šířka. 

Autor: tisnik, podle licence: Rights Managed

První hráč má nyní odlišný tvar (všechny jeho řádky jsou však stále totožné), čtyřnásobná šířka.

Obrázek 9: První hráč má nyní odlišný tvar (všechny jeho řádky jsou však stále totožné), čtyřnásobná šířka. 

Autor: tisnik, podle licence: Rights Managed

Úplný zdrojový kód takto upraveného příkladu:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, tvaru a barvy prvního hráče.
; Zákaz DMA. Postupná změna horizontální velikosti hráče.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
KBHANDLER = $e424               ; rutina pro cteni klavesy
 
 
.proc main
        lda #128                ; horizontální pozice hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #HUE_MAGENTA<<4 + 8 ; barva hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #128+32+8+2         ; bitová maska hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
        lda #0                  ; bitové pole: vše nulové
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #1                  ; horizontální velikost hráče
        sta SIZEP0              ; uložit do řídicího registru SIZEP0 na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #3                  ; horizontální velikost hráče
        sta SIZEP0              ; uložit do řídicího registru SIZEP0 na čipu GTIA
 
loop:   jmp loop
.endproc
 
.proc get_key
        lda KBHANDLER+1         ; cteni horni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        lda KBHANDLER           ; cteni dolni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        rts                     ; vyber adresy ze zasobniku + skok
                                ; zde neni nutne mit RTS
.endproc
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Priority PMG vůči hracímu poli a pozadí

Priority zobrazení hráčů a střel vůči sobě nebo vůči hracímu poli se nastavují modifikací nejnižších čtyř bitů řídicího registru GPRIOR. Existuje celkem devět úrovní priorit, ovšem vybírat si můžeme jen z pěti možností tak, jak je to naznačeno v další tabulce:

Priorita 0001 0010 0100 1000 0000
Nejvyšší PM0 PM0 P5/PF0 P5/PF0 PM0
  PM1 PM1 PF1 PF1 PM1
  PM2 P5/PF0 PF2 PM0 P5/PF0
  PM3 PF1 PF3 PM1 PF1
  P5/PF0 PF2 PM0 PM2 PM2
  PF1 PF3 PM1 PM3 PM3
  PF2 PM2 PM2 PF2 PF2
  PF3 PM3 PM3 PF3 PF3
Nejnižší COLBK COLBK COLBK COLBK COLBK

Význam zkratek z předchozí tabulky:

Zkratka Význam
PMx hráč a střela x (0–3)
P5 pátý hráč složený ze všech střel (viz navazující článek)
PFx barva hracího pole x (0–3)
COLBK barva pozadí
Poznámka: možnosti nastavení priorit se sice zdají být poněkud omezené, ovšem v praxi si s nimi vystačíme; a to mnohdy i takovým způsobem, že postavička ve hře postupně mění svůj způsob zobrazení – který hráč pro to bude použit.

Zobrazení dvou překrývajících se hráčů současně, režim „multicolor“

Šestým bitem registru GPRIOR se povoluje takzvaný režim „multicolor“ (pozor, na Commodore C64 má toto slovo naprosto odlišný význam). Pokud je tento bit nastaven a dva sprity (například hráči) se překrývají, bude barva překryté oblasti vypočtena operací OR. Připomeňme, že na Atari se barva skládá z kódu odstínu a intenzity. Operace OR tedy může vést k zobrazení zcela odlišné barvy – nejedná se o smíchání barev ve smyslu jejich odstínu! Režim „multicolor“ se zapne po spuštění dalšího příkladu a stisku klávesy. Další stisky klávesy mění navíc i prioritu (což si ještě ukážeme v dalších příkladech):

Dva překrývající se hráči, GPRIOR=0.

Obrázek 10: Dva překrývající se hráči, GPRIOR=0. 

Autor: tisnik, podle licence: Rights Managed

Dva překrývající se hráči, GPRIOR=32 (multicolor).

 Obrázek 11: Dva překrývající se hráči, GPRIOR=32 (multicolor).

Autor: tisnik, podle licence: Rights Managed

Dva překrývající se hráči, GPRIOR=37 (změna priorit).

Obrázek 12: Dva překrývající se hráči, GPRIOR=37 (změna priorit). 

Autor: tisnik, podle licence: Rights Managed

Dva překrývající se hráči, GPRIOR=37 (multicolor+změna priorit).

Obrázek 13: Dva překrývající se hráči, GPRIOR=37 (multicolor+změna priorit). 

Autor: tisnik, podle licence: Rights Managed

Úplný zdrojový kód takto upraveného příkladu:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, tvaru a barvy dvou
; hráčů.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
KBHANDLER = $e424               ; rutina pro cteni klavesy
 
 
.proc main
        lda #128                ; horizontální pozice prvního hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #132                ; horizontální pozice druého hráče
        sta HPOSP1              ; uložit do řídicího registru HPOSP1 na čipu GTIA
 
        lda #HUE_GREEN<<4 + 6   ; barva prvního hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #HUE_YELLOW<<4 + 12 ; barva druhého hráče (odstín+intenzita)
        sta PCOLR1              ; uložit do řídicího registru PCOLR1 na čipu GTIA
 
        lda #$ff                ; bitová maska prvního i druhého hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
        sta GRAFP1              ; uložit do řídicího registru GRAFP1 na čipu GTIA
 
        lda #0                  ; bitové pole: vše nulové
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        lda #0                  ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #32                 ; priorita hráčů a pozadí - OR barev
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #31                 ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #37                 ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
loop:   jmp loop
.endproc
 
.proc get_key
        lda KBHANDLER+1         ; cteni horni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        lda KBHANDLER           ; cteni dolni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        rts                     ; vyber adresy ze zasobniku + skok
                                ; zde neni nutne mit RTS
.endproc
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Nastavení bitmapy spritů (hráčů i střel)

Prozatím naše sprity vypadaly jako obdélníky, ovšem systém PMG pochopitelně podporuje i definici hráčů (a střel) pomocí bitmapy. U hráčů je každá bitmapa široká osm pixelů a vysoká 128 pixelů. Pro každého hráče je tedy nutné alokovat paměť 128×8 bitů=128 bajtů. Pro všechny střely současně se jedná o stejnou velikost, tedy 128 bajtů. Celkově tedy potřebujeme:

1 hráč = 128 bajtů
2 hráč = 128 bajtů
3 hráč = 128 bajtů
4 hráč = 128 bajtů
střely = 128 bajtů
------------------
         640 bajtů

K těmto 640 bajtům je přidáno 384 bajtů „výplně“ (můžete je použít pro jiné účely) a celkem tedy potřebujeme 640+384=1024 bajtů, tj. čtyři stránky paměti. Tyto stránky mohou být umístěny kdekoli v paměti, ovšem musí začínat na hodnotě dělitelné čtyřmi.

Offsety bitmap pro hráče se pak vypočtou takto (ve skutečnosti 1024 bajtů začíná bufferem a poté 128 bajty pro střely):

PLAYER_0_OFFSET = 512
PLAYER_1_OFFSET = PLAYER_0_OFFSET + 128
PLAYER_2_OFFSET = PLAYER_1_OFFSET + 128
PLAYER_3_OFFSET = PLAYER_2_OFFSET + 128

V našich demonstračních příkladech použijeme paměťové stránky 152–156. Index první stránky předáme čipu ANTIC (ne GTIA) přes řídicí registr:

        lda #152                ; paměťová stránka číslo 152
        sta PMBASE
Poznámka: aby to nebylo tak jednoduché, můžeme mít i sprity vysoké 256 řádků a ne 128. Potom je zapotřebí dvojnásobek paměti. Podrobnosti si ukážeme příště.

Demonstrační příklad: naivní nastavení bitmapy prvního hráče

V tomto demonstračním příkladu nejprve povolíme definici bitmapy hráčů, povolíme DMA a nastavíme stránky, ve kterých jsou bitmapy uloženy:

        lda #3                  ; bitové pole: povolení hráčů i střel
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        lda #152                ; paměťová stránka číslo 152
        sta PMBASE
 
        lda #46                 ; povolení PMG DMA
        sta SDMCTL

Dále je nutné vyplnit část bitmapy prvního hráče. Nastavíme pouze osm řádků zhruba v polovině výšce hráče (offset 64):

        addr = 152*256
        lda #24                 ; bitová maska jednoho řádku spritu
        sta addr+512+64         ; zapsat do paměti
        lda #60
        sta addr+512+64+1
        lda #126
        sta addr+512+64+2
        lda #126
        sta addr+512+64+3
        lda #219
        sta addr+512+64+4
        lda #255
        sta addr+512+64+5
        lda #36
        sta addr+512+64+6
        lda #90
        sta addr+512+64+7
        lda #165
        sta addr+512+64+8
 

Výsledek by měl vypadat takto:

Hráč s definovanou bitmapou.

Obrázek 14: První hráč s definovanou bitmapou. 

Autor: tisnik, podle licence: Rights Managed

; ---------------------------------------------------------------------
; Initializace PMG, nastavení barvy, pozice a bitmapy prvního hráče.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
 
.proc main
        lda #128                ; horizontální pozice prvního hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #HUE_YELLOW<<4 + 12 ; barva prvního hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #$ff                ; bitová maska prvního i druhého hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
        lda #3                  ; bitové pole: povolení hráčů i střel
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        lda #152                ; paměťová stránka číslo 152
        sta PMBASE
 
        addr = 152*256
        lda #24                 ; bitová maska jednoho řádku spritu
        sta addr+512+64         ; zapsat do paměti
        lda #60
        sta addr+512+64+1
        lda #126
        sta addr+512+64+2
        lda #126
        sta addr+512+64+3
        lda #219
        sta addr+512+64+4
        lda #255
        sta addr+512+64+5
        lda #36
        sta addr+512+64+6
        lda #90
        sta addr+512+64+7
        lda #165
        sta addr+512+64+8
 
        lda #46                 ; povolení PMG DMA
        sta SDMCTL
 
loop:   jmp loop
.endproc
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Přečtení bitmapy (tvaru) hráče z pole s daty

Předchozí způsob nastavení bitmapy hráče byl pochopitelně poměrně naivní, už jen z toho důvodu, že vyžadoval pro každý řádek pět bajtů strojového kódu. Existuje pochopitelně elegantnější způsob. Nejdříve uložíme data hráče (tedy bitmapu či její část) přímo do zdrojového kódu v assembleru. V našem konkrétním případě je postavička vysoká osm řádků a proto potřebujeme osm bajtů:

; data
sprite:   .byte 24, 60, 126, 219, 255, 36, 90, 165

Dále je nutné implementovat počítanou programovou smyčku, která přenese oněch osm bajtů na vypočtenou adresu, tedy v našem případě do paměťového bloku začínajícího na stránce číslo 152. Adresa této stránky je rovna:

        addr = 152*256

Samotná počítaná programová smyčka může vypadat takto:

        ldx #8                  ; začneme na hodnotě o 1 vyšší
next_line:
        lda sprite-1, x         ; načíst
        sta addr+512+64, x      ; uložit byte
        dex                     ; snížit offset + nastavit příznaky
        bne next_line           ; další byte spritu
 
        lda #46                 ; povolení PMG DMA
        sta SDMCTL
Poznámka: důležité je správně určit zdrojovou adresu, protože počitadlo dosahuje hodnot 8–1 a nikoli 7–0!

Výsledek by měl být stejný, jako je tomu v předchozím příkladu:

Hráč s definovanou bitmapou.

Obrázek 15: Hráč s definovanou bitmapou. 

Autor: tisnik, podle licence: Rights Managed

Opět následuje výpis zdrojového kódu:

; ---------------------------------------------------------------------
; Initializace PMG, nastavení barvy, pozice a bitmapy prvního hráče.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
 
.proc main
        lda #128                ; horizontální pozice prvního hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #HUE_YELLOW<<4 + 12 ; barva prvního hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #$ff                ; bitová maska prvního i druhého hráče
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
 
        lda #3                  ; bitové pole: povolení hráčů i střel
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        lda #152                ; paměťová stránka číslo 152
        sta PMBASE
 
        addr = 152*256
        ldx #8                  ; začneme na hodnotě o 1 vyšší
next_line:
        lda sprite-1, x         ; načíst
        sta addr+512+64, x      ; uložit byte
        dex                     ; snížit offset + nastavit příznaky
        bne next_line           ; další byte spritu
 
        lda #46                 ; povolení PMG DMA
        sta SDMCTL
 
loop:   jmp loop
.endproc
 
; data
sprite:   .byte 24, 60, 126, 219, 255, 36, 90, 165
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Zobrazení čtyř hráčů současně se změnou priorit

V dnešním předposledním demonstračním příkladu, který si ukážeme, se vrátíme k registru GPRIOR, kterým je možné nastavit priority PMG vůči sobě (první hráč vs. třetí hráč atd.) či vůči hernímu poli (playground). V příkladu zobrazíme všechny čtyři hráče tak, aby se nepřekrývaly, a posléze bude provedeno přepnutí priorit na hodnoty 0000, 0001, 0010 a 0100 (binárně). Přepínání se opět provádí stiskem klávesy. Vizuální výsledky při postupné změně priorit by měly vypadat takto:

Registr GPRIOR=0.

Obrázek 16: Registr GPRIOR=0. 

Autor: tisnik, podle licence: Rights Managed

Registr GPRIOR=1.

Obrázek 17: Registr GPRIOR=1. 

Autor: tisnik, podle licence: Rights Managed

Registr GPRIOR=2.

Obrázek 18: Registr GPRIOR=2. 

Autor: tisnik, podle licence: Rights Managed

Registr GPRIOR=4.

Obrázek 19: Registr GPRIOR=4. 

Autor: tisnik, podle licence: Rights Managed

Opět následuje výpis celého zdrojového kódu tohoto demonstračního příkladu:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, tvaru a barvy všech
; hráčů.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
KBHANDLER = $e424               ; rutina pro cteni klavesy
 
 
.proc main
        lda #80                 ; horizontální pozice prvního hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #100                ; horizontální pozice druhého hráče
        sta HPOSP1              ; uložit do řídicího registru HPOSP1 na čipu GTIA
 
        lda #120                ; horizontální pozice třetího hráče
        sta HPOSP2              ; uložit do řídicího registru HPOSP2 na čipu GTIA
 
        lda #140                ; horizontální pozice čtvrtého hráče
        sta HPOSP3              ; uložit do řídicího registru HPOSP3 na čipu GTIA
 
        lda #HUE_GREEN<<4 + 6   ; barva prvního hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #HUE_YELLOW<<4 + 12 ; barva druhého hráče (odstín+intenzita)
        sta PCOLR1              ; uložit do řídicího registru PCOLR1 na čipu GTIA
 
        lda #HUE_MAGENTA<<4 + 12 ; barva třetího hráče (odstín+intenzita)
        sta PCOLR2              ; uložit do řídicího registru PCOLR2 na čipu GTIA
 
        lda #HUE_CYAN<<4 + 12   ; barva čtvrtého hráče (odstín+intenzita)
        sta PCOLR3              ; uložit do řídicího registru PCOLR3 na čipu GTIA
 
        lda #$ff                ; bitová maska všech hráčů
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
        sta GRAFP1              ; uložit do řídicího registru GRAFP1 na čipu GTIA
        sta GRAFP2              ; uložit do řídicího registru GRAFP2 na čipu GTIA
        sta GRAFP3              ; uložit do řídicího registru GRAFP3 na čipu GTIA
 
        lda #0                  ; bitové pole: vše nulové
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        lda #0                  ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #1                  ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #2                  ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        jsr get_key             ; čekání na stisk klávesy
 
        lda #4                  ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
loop:   jmp loop
.endproc
 
.proc get_key
        lda KBHANDLER+1         ; cteni horni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        lda KBHANDLER           ; cteni dolni casti adresy ulozene v ROM
        pha                     ; ulozeni na zasobnik
        rts                     ; vyber adresy ze zasobniku + skok
                                ; zde neni nutne mit RTS
.endproc
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito

Nastavení bitmap všech čtyř hráčů

V dnešním posledním demonstračním příkladu opět zobrazíme všechny čtyři hráče, tentokrát však budou hráči definovaní svou bitmapou (polem 128×8 bitů). Pro jednoduchost nastavíme všechny bitmapy podobným způsobem, pouze s odlišným offsetem (což odpovídá vertikální pozici hráče na obrazovce). Výsledek by měl vypadat následovně:

Všichni čtyři hráči s definovanou bitmapou.

Obrázek 20: Všichni čtyři hráči s definovanou bitmapou. 

Autor: tisnik, podle licence: Rights Managed

Úplný zdrojový kód tohoto příkladu, na který navážeme v příštím článku, vypadá následovně:

; ---------------------------------------------------------------------
; Initializace PMG, povolení PMG, nastavení pozice, bitmapy a barvy všech
; objektů.
; ---------------------------------------------------------------------
 
.include "atari.inc"
 
.CODE
 
PLAYER_0_OFFSET = 512
PLAYER_1_OFFSET = PLAYER_0_OFFSET + 128
PLAYER_2_OFFSET = PLAYER_1_OFFSET + 128
PLAYER_3_OFFSET = PLAYER_2_OFFSET + 128
 
 
.proc main
        lda #80                 ; horizontální pozice prvního hráče
        sta HPOSP0              ; uložit do řídicího registru HPOSP0 na čipu GTIA
 
        lda #100                ; horizontální pozice druhého hráče
        sta HPOSP1              ; uložit do řídicího registru HPOSP1 na čipu GTIA
 
        lda #120                ; horizontální pozice třetího hráče
        sta HPOSP2              ; uložit do řídicího registru HPOSP2 na čipu GTIA
 
        lda #140                ; horizontální pozice čtvrtého hráče
        sta HPOSP3              ; uložit do řídicího registru HPOSP3 na čipu GTIA
 
        lda #HUE_GREEN<<4 + 12  ; barva prvního hráče (odstín+intenzita)
        sta PCOLR0              ; uložit do řídicího registru PCOLR0 na čipu GTIA
 
        lda #HUE_YELLOW<<4 + 12 ; barva druhého hráče (odstín+intenzita)
        sta PCOLR1              ; uložit do řídicího registru PCOLR1 na čipu GTIA
 
        lda #HUE_MAGENTA<<4 + 12 ; barva třetího hráče (odstín+intenzita)
        sta PCOLR2              ; uložit do řídicího registru PCOLR2 na čipu GTIA
 
        lda #HUE_CYAN<<4 + 12   ; barva čtvrtého hráče (odstín+intenzita)
        sta PCOLR3              ; uložit do řídicího registru PCOLR3 na čipu GTIA
 
        lda #$ff                ; bitová maska všech hráčů
        sta GRAFP0              ; uložit do řídicího registru GRAFP0 na čipu GTIA
        sta GRAFP1              ; uložit do řídicího registru GRAFP1 na čipu GTIA
        sta GRAFP2              ; uložit do řídicího registru GRAFP2 na čipu GTIA
        sta GRAFP3              ; uložit do řídicího registru GRAFP3 na čipu GTIA
 
        lda #3                  ; bitové pole: povolení hráčů i střel
        sta GRACTL              ; uložit do řídicího registru GRACTL na čipu GTIA
 
        lda #0                  ; priorita hráčů a pozadí
        sta GPRIOR              ; uložit do řídicího registru GPRIOR na čipu GTIA
 
        lda #152                ; paměťová stránka číslo 152
        sta PMBASE
 
        addr = 152*256
        ldx #8                  ; začneme na hodnotě o 1 vyšší
next_line:
        lda sprite-1, x         ; načíst
        sta addr+PLAYER_0_OFFSET+30, x  ; uložit byte - první hráč
        sta addr+PLAYER_1_OFFSET+50, x  ; uložit byte - druhý hráč
        sta addr+PLAYER_2_OFFSET+70, x  ; uložit byte - třetí hráč
        sta addr+PLAYER_3_OFFSET+90, x  ; uložit byte - čtvrtý hráč
        dex                     ; snížit offset + nastavit příznaky
        bne next_line           ; další byte spritu
 
        lda #46                 ; povolení PMG DMA
        sta SDMCTL
 
loop:   jmp loop
.endproc
 
; data
sprite:   .byte 24, 60, 126, 219, 255, 36, 90, 165
 
end:
 
 
.segment "EXEHDR"
.word   $ffff                   ; uvodni sekvence bajtu v souboru XEX
.word   main                    ; zacatek kodoveho segmentu
.word   end - 1                 ; konec kodoveho segmentu
 
 
.segment "AUTOSTRT"             ; segment s pocatecni adresou
.word   RUNAD                   ; naplni se pouze adresy RUNAD a RUNAD+1
.word   RUNAD+1
.word   main                    ; adresa vstupniho bodu do programu
 
; finito
Poznámka: povšimněte si, že bitmapy všech čtyř hráčů nastavujeme v jedné počítané programové smyčce.

Příloha A: Seznam všech doposud popsaných instrukcí mikroprocesoru MOS 6502

Všechny doposud popsané instrukce mikroprocesoru MOS 6502 jsou vypsány v následující tabulce:

# Instrukce Plné jméno Popis
1 ADC add with carry součet hodnoty s akumulátorem (včetně přetečení)
2 SBC subtract with carry odečtení hodnoty od akumulátoru (včetně výpůjčky)
       
3 AND and with accumulator logické AND s akumulátorem
4 ORA or with accumulator logické OR s akumulátorem
5 EOR exclusive or with accumulator logické XOR s akumulátorem
       
6 INC increment zvýšení hodnoty o 1 (kupodivu nelze s akumulátorem, ovšem s pamětí ano)
7 INX increment X zvýšení hodnoty index registru X o 1
8 INY increment Y zvýšení hodnoty index registru Y o 1
9 DEC decrement snížení hodnoty o 1 (opět nelze s akumulátorem)
10 DEX decrement X snížení hodnoty index registru X o 1
11 DEY decrement Y snížení hodnoty index registru Y o 1
       
12 CMP compare with accumulator odečtení hodnoty od akumulátoru bez zápisu výsledku
13 CPX compare with X odečtení hodnoty od index registru X bez zápisu výsledku
14 CPY compare with Y odečtení hodnoty od index registru Y bez zápisu výsledku
15 BIT bit test logické AND bez uložení výsledků (změní se jen příznakové bity)
       
16 ASL arithmetic shift left aritmetický posun doleva o jeden bit
17 LSR logical shift right logický posun doprava o jeden bit
18 ROL rotate left rotace doleva o jeden bit
19 ROR rotate right rotace doprava o jeden bit
       
20 JMP jump skok (existuje několik adresovacích režimů)
21 JSR jump to subroutine skok do podprogramu s uložením návratové adresy na zásobník
22 RTS return from subroutine návrat z podprogramu
23 RTI return from interrupt návrat z prerušovací rutiny
       
24 BCC branch on carry clear rozvětvení za podmínky C==0
25 BCS branch on carry set rozvětvení za podmínky C==1
26 BEQ branch on equal (zero set) rozvětvení za podmínky Z==1
27 BMI branch on minus (negative set) rozvětvení za podmínky N==1
28 BNE branch on not equal (zero clear) rozvětvení za podmínky Z==0
29 BPL branch on plus (negative clear) rozvětvení za podmínky N==0
30 BVC branch on overflow clear rozvětvení za podmínky O==0
31 BVS branch on overflow set rozvětvení za podmínky O==1
       
32 PHA push accumulator on stack uložení obsahu akumulátoru na zásobník
33 PLA pull accumulator from stack obnovení obsahu akumulátoru ze zásobníku

Příloha B: Makefile pro překlad všech demonstračních příkladů

Všechny minule i dnes popsané demonstrační příklady, pro jejichž překlad je zapotřebí použít assembler ca65 a linker ld65, je možné přeložit s využitím souboru Makefile, jehož obsah je vypsán pod tímto odstavcem:

Školení Zabbix

execs := dummy.xex print_a.xex \
         background_color_1.xex  background_color_2.xex \
         color_computation_1.xex color_computation_2.xex \
         subroutine_1.xex        subroutine_2.xex \
         hex_number_1.xex        hex_number_2.xex \
         hex_number_3.xex        hex_number_4.xex \
         hex_number_5.xex        hex_number_6.xex \
         hex_number_7.xex        hex_number_8.xex \
         hex_number_9.xex \
         fill_block_1.xex        fill_block_2.xex \
         fill_block_3.xex        fill_block_4.xex \
         fill_block_5.xex \
         pmg_01.xex              pmg_02.xex \
         pmg_03.xex              pmg_04.xex \
         pmg_05.xex              pmg_06.xex \
         pmg_07.xex              pmg_08.xex \
         pmg_09.xex              pmg_10.xex

all: $(execs)

clean:
        rm -f *.o
        rm -f *.xex

.PHONY: all clean

%.o: %.asm
        ca65 $< -t atari -o $@ -l $(basename $<)_list.asm --list-bytes 100

%.xex: %.o
        ld65 -C linker.cfg $< -o $@ -m $(basename $<).map

Výsledkem překladu jsou soubory s koncovkou .xex, které je možné přímo spustit v emulátoru osmibitových počítačů Atari.

Repositář s demonstračními příklady

Všechny demonstrační příklady, s nimiž jsme se v předchozích článcích i v článku dnešním seznámili a které jsou určeny pro překlad s využitím assembleru ca65, jsou dostupné, jak je zvykem, na GitHubu. V tabulce níže jsou uvedeny odkazy na jednotlivé zdrojové kódy příkladů psané v assembleru i „listingy“ vygenerované samotným assemblerem, ze kterých je patrné, jakým způsobem se jednotlivé příklady přeložily do výsledného XEX souboru:

# Příklad Stručný popis příkladu Adresa
1 Makefile definice cílů pro překlad všech demonstračních příkladů z této tabulky https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/Makefile
2 linker.cfg konfigurační soubor pro linker https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/linker.cfg
       
3 dummy.asm pouze nekonečná smyčka https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/dummy.asm
4 dummy_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/dummy_list.asm
5 dummy_list.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/dummy.map
       
6 background_color1.asm změna barvy pozadí – základní varianta příkladu https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/background_color1.asm
7 background_color1_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/background_color1_list.asm
8 background_color1.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/background_color1.map
       
9 background_color2.asm změna barvy pozadí – využití předdefinovaných konstant https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/background_color2.asm
10 background_color2_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/background_color2_list.asm
11 background_color2.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/background_color2.map
       
12 print_a.asm tisk znaku přímo do obrazové paměti https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/print_a.asm
13 print_a_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/print_a_list.asm
14 print_a.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/print_a.map
       
15 color_computation1.asm výpočet barvy, varianta bez bitových posunů https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/color_computation1.asm
16 color_computation1_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/color_computation1_list.asm
17 color_computation1.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/color_computation1.map
       
18 color_computation2.asm výpočet barvy, varianta s bitovými posuny https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/color_computation2.asm
19 color_computation2_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/color_computation2_list.asm
20 color_computation2.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/color_computation2.map
       
21 subroutine1.asm skok do podprogramu bez předávání parametrů https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/subroutine1.asm
22 subroutine1_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/subroutine1_list.asm
23 subroutine1.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/subroutine1.map
       
24 subroutine2.asm skok do podprogramu s předáním parametru https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/subroutine2.asm
25 subroutine2_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/subroutine2_list.asm
26 subroutine2.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/subroutine2.map
       
27 hex_number1.asm tisk jedné hexadecimální číslice (nekorektní varianta) https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number1.asm
28 hex_number1_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number1_list.asm
29 hex_number1.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number1.map
       
30 hex_number2.asm tisk jedné hexadecimální číslice (korektní varianta) https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number2.asm
31 hex_number2_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number2_list.asm
32 hex_number2.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number2.map
       
33 hex_number3.asm tisk jedné hexadecimální číslice (korektní varianta po refaktoringu) https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number3.asm
34 hex_number3_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number3_list.asm
35 hex_number3.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number3.map
       
36 hex_number4.asm tisk jedné hexadecimální číslice, varianta postavená na makrech https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number4.asm
37 hex_number4_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number4_list.asm
38 hex_number4.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number4.map
       
39 hex_number5.asm tisk jedné hexadecimální číslice, varianta postavená na makrech, lokální automaticky generovaná návěští https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number5.asm
40 hex_number5_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number5_list.asm
41 hex_number5.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number5.map
       
42 hex_number6.asm příprava pro tisk dvouciferné hexadecimální hodnoty https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number6.asm
43 hex_number6_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number6_list.asm
44 hex_number6.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number6.map
       
45 hex_number7.asm realizace tisku dvouciferné hexadecimální hodnoty https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number7.asm
46 hex_number7_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number7_list.asm
47 hex_number7.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number7.map
       
48 hex_number8.asm makro pro logický posun doprava o zadaný počet bitů https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number8.asm
49 hex_number8_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number8_list.asm
50 hex_number8.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number8.map
       
51 hex_number9.asm čekání na stisk klávesy https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number8.asm
52 hex_number9_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number8_list.asm
53 hex_number9.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/hex_number8.map
       
54 fill_block1.asm vyplnění bloku, varianta se dvěma index registry https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block1.asm
55 fill_block1_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block1_list.asm
56 fill_block1.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block1.map
       
57 fill_block2.asm vyplnění bloku, nekorektní varianta využívající jeden index registr https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block2.asm
58 fill_block2_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block2_list.asm
59 fill_block2.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block2.map
       
60 fill_block3.asm vyplnění bloku, korektní varianta využívající jeden index registr https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block3.asm
61 fill_block3_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block3_list.asm
62 fill_block3.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block3.map
       
63 fill_block4.asm vyplnění bloku delšího než 256 bajtů https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block4.asm
64 fill_block4_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block4_list.asm
65 fill_block4.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block4.map
       
66 fill_block5.asm vyplnění bloku, čítání směrem nahoru https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block5.asm
67 fill_block5_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block5_list.asm
68 fill_block5.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/fill_block5.map
       
69 pmg01.asm inicializace PMG, povolení PMG, nastavení pozice a tvaru prvního hráče https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg01.asm
70 pmg01_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg01_list.asm
71 pmg01.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg01.map
       
72 pmg02.asm nastavení pozice, tvaru a barvy prvního hráče https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg02.asm
73 pmg02_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg02_list.asm
74 pmg02.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg02.map
       
75 pmg03.asm vliv zákazu DMA na zobrazení PMG https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg03.asm
76 pmg03_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg03_list.asm
77 pmg03.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg03.map
       
78 pmg04.asm postupná změna horizontální velikosti hráče https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg04.asm
79 pmg04_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg04_list.asm
80 pmg04.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg04.map
       
81 pmg05.asm odlišná bitová maska tvaru hráče https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg05.asm
82 pmg05_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg05_list.asm
83 pmg05.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg05.map
       
84 pmg06.asm inicializace a zobrazení dvou hráčů, kteří se překrývají https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg06.asm
84 pmg06_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg06_list.asm
86 pmg06.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg06.map
       
87 pmg07.asm naivní způsob nastavení bitmapy prvního hráče https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg07.asm
88 pmg07_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg07_list.asm
89 pmg07.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg07.map
       
90 pmg08.asm elegantnější způsob nastavení bitmapy prvního hráče https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg08.asm
91 pmg08_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg08_list.asm
92 pmg08.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg08.map
       
93 pmg09.asm zobrazení všech čtyř hráčů, změna priority zobrazení https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg09.asm
94 pmg09_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg09_list.asm
95 pmg09.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg09.map
       
96 pmg10.asm nastavení bitmap všech čtyř hráčů https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg10.asm
97 pmg10_list.asm „listing“ vygenerovaný assemblerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg10_list.asm
98 pmg10.map mapa paměti; soubor vytvořený linkerem https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/pmg10.map
       
99 chars.bas tisk všech znaků na obrazovku (varianta naprogramovaná v BASICu) https://github.com/tisnik/8bit-fame/blob/master/Atari800-ca65/chars.bas

Odkazy na Internetu

  1. MOS 6502 instruction set
    http://www.6502.org/users/o­belisk/6502/instructions.html
  2. EXE File Format Description
    https://gury.atari8.info/ref­s/file_formats_exe.php
  3. XEX Filter – A toolkit to analyze and manipulate Atari binary files
    https://www.vitoco.cl/atari/xex-filter/index.html
  4. chkxex.py
    https://raw.githubusercon­tent.com/seban-slt/tcx_tools/refs/heads/mas­ter/chkxex.py
  5. ca65 Users Guide
    https://cc65.github.io/doc/ca65.html
  6. cc65 Users Guide
    https://cc65.github.io/doc/cc65.html
  7. ld65 Users Guide
    https://cc65.github.io/doc/ld65.html
  8. da65 Users Guide
    https://cc65.github.io/doc/da65.html
  9. Překladače jazyka C pro historické osmibitové mikroprocesory
    https://www.root.cz/clanky/prekladace-jazyka-c-pro-historicke-osmibitove-mikroprocesory/
  10. Překladače programovacího jazyka C pro historické osmibitové mikroprocesory (2)
    https://www.root.cz/clanky/prekladace-programovaciho-jazyka-c-pro-historicke-osmibitove-mikroprocesory-2/
  11. Getting Started Programming in C: Coding a Retro Game with C Part 2
    https://retrogamecoders.com/getting-started-with-c-cc65/
  12. NES game development in 6502 assembly – Part 1
    https://kibrit.tech/en/blog/nes-game-development-part-1
  13. NES 6502 Programming Tutorial – Part 1: Getting Started
    https://dev.xenforo.relay­.cool/index.php?threads/nes-6502-programming-tutorial-part-1-getting-started.858389/
  14. Minimal NES example using ca65
    https://github.com/bbbradsmith/NES-ca65-example
  15. List of 6502-based Computers and Consoles
    https://www.retrocompute.co.uk/list-of-6502-based-computers-and-consoles/
  16. 6502 – the first RISC µP
    http://ericclever.com/6500/
  17. 3 Generations of Game Machine Architecture
    http://www.atariarchives.or­g/dev/CGEXPO99.html
  18. “Hello, world” from scratch on a 6502 — Part 1
    https://www.youtube.com/wat­ch?v=LnzuMJLZRdU
  19. A Tour of 6502 Cross-Assemblers
    https://bumbershootsoft.wor­dpress.com/2016/01/31/a-tour-of-6502-cross-assemblers/
  20. Adventures with ca65
    https://atariage.com/forum­s/topic/312451-adventures-with-ca65/
  21. example ca65 startup code
    https://atariage.com/forum­s/topic/209776-example-ca65-startup-code/
  22. 6502 PRIMER: Building your own 6502 computer
    http://wilsonminesco.com/6502primer/
  23. 6502 Instruction Set
    https://www.masswerk.at/6502/6502_in­struction_set.html
  24. Chip Hall of Fame: MOS Technology 6502 Microprocessor
    https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-mos-technology-6502-microprocessor
  25. Single-board computer
    https://en.wikipedia.org/wiki/Single-board_computer
  26. www.6502.org
    http://www.6502.org/
  27. 6502 PRIMER: Building your own 6502 computer – clock generator
    http://wilsonminesco.com/6502pri­mer/ClkGen.html
  28. Great Microprocessors of the Past and Present (V 13.4.0)
    http://www.cpushack.com/CPU/cpu.html
  29. Jak se zrodil procesor?
    https://www.root.cz/clanky/jak-se-zrodil-procesor/
  30. Osmibitové mikroprocesory a mikrořadiče firmy Motorola (1)
    https://www.root.cz/clanky/osmibitove-mikroprocesory-a-mikroradice-firmy-motorola-1/
  31. Mikrořadiče a jejich použití v jednoduchých mikropočítačích
    https://www.root.cz/clanky/mikroradice-a-jejich-pouziti-v-jednoduchych-mikropocitacich/
  32. Mikrořadiče a jejich aplikace v jednoduchých mikropočítačích (2)
    https://www.root.cz/clanky/mikroradice-a-jejich-aplikace-v-jednoduchych-mikropocitacich-2/
  33. 25 Microchips That Shook the World
    https://spectrum.ieee.org/tech-history/silicon-revolution/25-microchips-that-shook-the-world
  34. Comparison of instruction set architectures
    https://en.wikipedia.org/wi­ki/Comparison_of_instructi­on_set_architectures
  35. How To Start Learning Atari 8 Bit Assembly For Free
    https://forums.atariage.com/to­pic/300732-how-to-start-learning-atari-8-bit-assembly-for-free/
  36. WUDSN (Demo Group)
    https://www.wudsn.com/
  37. Machine Language For Beginners
    https://www.atariarchives.org/mlb/
  38. Assembly language: all about I/O
    https://www.atarimagazines­.com/v3n8/AllAbout_IO.html
  39. Sedmdesátiny assemblerů: lidsky čitelný strojový kód
    https://www.root.cz/clanky/sed­mdesatiny-assembleru-lidsky-citelny-strojovy-kod/
  40. Color names
    https://atariwiki.org/wiki/Wi­ki.jsp?page=Color%20names
  41. ATASCII
    https://en.wikipedia.org/wiki/ATASCII
  42. Put characters in display ram isn't ATASCII?
    https://forums.atariage.com/to­pic/359973-put-characters-in-display-ram-isnt-atascii/
  43. ATASCII And Internal Character Code Values
    https://www.atariarchives­.org/mapping/appendix10.php
  44. Reading ATASCII from the keyboard in assembly
    https://forums.atariage.com/to­pic/361733-reading-atascii-from-the-keyboard-in-assembly/
  45. Why does the 6502 JSR instruction only increment the return address by 2 bytes?
    https://retrocomputing.stac­kexchange.com/questions/19543/why-does-the-6502-jsr-instruction-only-increment-the-return-address-by-2-bytes
  46. Pushing return address to stack off by 1 byte
    https://forums.atariage.com/to­pic/378206-pushing-return-address-to-stack-off-by-1-byte/
  47. Intel x86 documentation has more pages than the 6502 has transistors
    https://www.righto.com/2013/09/intel-x86-documentation-has-more-pages.html
  48. Clearing a Section of Memory
    http://www.6502.org/source/ge­neral/clearmem.htm
  49. Practical Memory Move Routines by Bruce Clark
    http://www.6502.org/source/ge­neral/memory_move.html
  50. 6502 Assembly Programming Guide
    https://neumont-gamedev.github.io/posts/retrogamedev-6502-guide/
  51. Off-by-one error
    https://en.wikipedia.org/wiki/Off-by-one_error
  52. 6502 cycle times
    https://www.nesdev.org/wi­ki/6502_cycle_times
  53. Atari TIA
    http://www.atarihq.com/danb/tia.shtml
  54. TIA Playfield
    http://www.atarihq.com/dan­b/TIA/Playfield.shtml
  55. Atari Inc.:
    ANTIC C012296 (NTSC) Revision D
    Atari Incorporated, Sunnyvale CA, 1982
  56. Atari Inc.:
    GTIA C014805 (NTSC) Revision A
    Atari Incorporated, Sunnyvale CA, 1982
  57. Atari 5200
    http://www.atariage.com/sof­tware_search.html?SystemID=5200
  58. Atari 5200 Hardware and Accessories
    http://www.atariage.com/5200/ar­chives/hardware.html
  59. Atari 5200 Screenshots
    http://www.atariage.com/sys­tem_items.html?SystemID=5200&I­temTypeID=SCREENSHOT
  60. History of video game consoles (second generation): Wikipedia
    http://en.wikipedia.org/wi­ki/History_of_video_game_con­soles_(second_generation)
  61. Atari 5200: Wikipedia
    http://en.wikipedia.org/wi­ki/Atari_5200
  62. Player-Missile Graphics
    https://www.atariarchives­.org/agagd/chapter5.php
  63. Sprite (computer graphics)
    https://en.wikipedia.org/wi­ki/Sprite_(computer_graphic­s)

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.



Nejnovější články