Na začátku dnešního článku si uvedeme základní informace o tom, jak je spojeno časování mikroprocesoru s časováním použitým při vykreslování snímků. Pro jednoduchost se zaměříme na Atari upravené pro televizní normu PAL (NTSC je odlišná monstrozita, časování snímků a řádků je zde odlišné). Mikroprocesor MOS 6502 má na Atari pro PAL nastavenu frekvenci přibližně 1,77 MHz. Z této frekvence lze (převrácenou hodnotou) vypočítat dobu trvání jednoho cyklu CPU. Z této doby je dalším dělením dvěma odvozena hodnota nazývaná color cycle (důvod pro toto označení si hned řekneme).
Co se dozvíte v článku
- Proč mají GTIA režimy horizontální rozlišení 80 pixelů?
- Programový výběr zvoleného GTIA režimu
- Základ pro další demonstrační příklady: monochromatický grafický režim 320×192 pixelů
- GTIA režim číslo 9: šestnáct intenzit barvy stejného odstínu
- Druhý demonstrační příklad: nastavení GTIA režimu 9 s vykreslením vzorku barev
- GTIA režim 9 není omezen jen na šedou škálu
- Postupná změna základního odstínu barvy
- Třetí demonstrační příklad: nastavení GTIA režimu 9 s postupnou změnou základního odstínu barvy
- GTIA režim číslo 11: šestnáct odstínů barev stejné intenzity
- Čtvrtý demonstrační příklad: nastavení GTIA režimu 11 s vykreslením vzorku barev
- Postupná změna intenzity všech barev na obrazovce
- Pátý demonstrační příklad: nastavení GTIA režimu 11 s postupnou změnou intenzity barev
- GTIA režim číslo 10: devět nezávisle na sobě nastavitelných barev
- Šestý demonstrační příklad: zobrazení barevné škály v režimu GTIA 10
- GTIA režimy založené na odlišném grafickém režimu než ANTIC F (GR.8)
- Sedmý demonstrační příklad: obrazovka s různými textovými režimy, přepnutí do „zobrazení“ GTIA
- Příloha: Makefile pro překlad všech demonstračních příkladů
- Repositář s demonstračními příklady
- Odkazy na Internetu
Zobrazení snímků je do značné míry svázáno s frekvencí CPU a tím pádem i s výše uvedeným barvovým cyklem. Zobrazení jednoho obrazového řádku na televizoru trvá 228 barvových cyklů (a tím pádem 114 cyklů procesoru). Označení color cycle vychází z toho, že barvy na obrazovce lze modifikovat právě v jednotlivých barvových cyklech (nikoli CPU cyklech). Výjimkou jsou monochromatické režimy GR.0 a GR.8, které zobrazují pixely s poloviční šířkou (pixel=1/2 color cycle) a proto se v těchto režimech barvy pixelů nemohou měnit (modifikují se jen jejich intenzity).
Znamená to snad, že na každém televizním řádku je možné zobrazit 228 barevných pixelů nebo dokonce 228×2=456 pixelů monochromatických? Není tomu tak, protože je nutné počítat s vykreslením okrajů, i signály HSYNC a HBLANK trvají určitou dobu atd. Z tohoto důvodu se v barevných režimech zobrazuje 160 pixelů popř. 192 pixelů při nastavení širokého obrazu (viz předchozí článek). V monochromatických režimech jsme pak omezeni na 320 pixelů resp. 384 pixelů na televizním řádku.
Konkrétní časování zobrazení jednoho televizního řádku může vypadat takto (vše je uvedeno v barvových cyklech!):
| Barvový cyklus | Význam |
|---|---|
| 0 | začátek HSYNC (horizontální synchronizace) |
| 14 | konec HSYNC |
| 32 | konec HBLANKu (horizontálního zatemnění), začátek zobrazení pro široké herní pole |
| 34 | běžný začátek zobrazení na televizorech |
| 44 | typicky první viditelný pixel širokého herního pole |
| 48 | první viditelný pixel normálního herního pole |
| 64 | první viditelný pixel úzkého herního pole |
| 160 | polovina šířky obrazovky pro všechny šířky herního pole (obraz je vždy vycentrován) |
| 192 | poslední viditelný pixel úzkého herního pole (192–64=128 barvových cyklů) |
| 208 | poslední viditelný pixel normálního herního pole (208–48=160 barvových cyklů) |
| 220 | běžný konec zobrazení na televizorech |
| 224 | poslední pixel širokého herního pole (224–32=192 barvových cyklů) |
Pro úplnost si ještě uveďme časování vertikální (i když pro dnešní článek není podstatné):
| Řádek | Stručný popis |
|---|---|
| 274 | začátek VSYNC |
| 278 | konec VSYNC |
| 0 | vynulování VCOUNT |
| 8 | začátek zobrazení |
| 248 | konec zobrazení |
Proč mají GTIA režimy horizontální rozlišení 80 pixelů?
GTIA režimy nabízí horizontální rozlišení dosahující pouze 80 pixelů a rozlišení vertikální 192 (200, 224) obrazových řádků. To je poněkud nepraktické, protože při stejné kapacitě obrazové paměti by bývalo lepší mít režimy s rozlišením 160×96 pixelů v šestnácti barvách. Jedná se ovšem o režimy, které vznikly skutečně až společně s čipem GTIA, který je nástupcem čipu CTIA (a ten je ideovým nástupcem TIA z Atari 2600). A v době uvedení GTIA již bylo o všech důležitých hardwarových náležitostech osmibitových Atari rozhodnuto.
GTIA režimy mají z těchto důvodů dvě důležitá omezení. Prvním je právě horizontální rozlišení dosahující pouze 80 pixelů a druhé omezení spočívá v tom, že barvovou paletu lze nastavit jen devíti registry a tudíž lze vybírat jen devět barev z teoreticky zobrazitelných šestnácti barev. To se částečně obchází tím, že GTIA režim není jeden, ale hned tři (s různými „barevnými“ vlastnostmi), ale toto omezení zde stále existuje.
Omezené horizontální rozlišení plyne z toho, že o generování video signálu se sice stará čip GTIA, ovšem na základě dat, které přichází z ANTICu. A pro komunikaci mezi ANTICem a GTIA se používají tři bitové vodiče AN2, AN1, AN0. V každém barvovém cyklu (viz úvodní kapitolu, která do článku nebyla zařazena náhodně) se tedy z ANTICu do GTIA vyšlou tři bity.
Pro NEmonochromatické ANTIC režimy mají tyto bity následující význam:
| AN2 | AN1 | AN0 | Význam |
|---|---|---|---|
| 0 | 0 | 1 | vertikální synchronizace |
| 0 | 1 | 0 | horizontální synchronizace, vypnutí zobrazení režimu s 320 pixely |
| 0 | 1 | 1 | horizontální synchronizace, zapnutí zobrazení režimu s 320 pixely |
| 1 | 0 | 0 | COLOR0 |
| 1 | 0 | 1 | COLOR1 |
| 1 | 1 | 0 | COLOR2 |
| 1 | 1 | 1 | COLOR3 |
Pro monochromatické režimy GR.0 a GR.8 je situace jiná, protože v každém barvovém cyklu je nutné zobrazit dva pixely. GTIA tedy dekóduje přijatá data odlišně – v každém cyklu hodnoty dvou pixelů:
| AN2 | AN1 | AN0 | Význam |
|---|---|---|---|
| 0 | 0 | 1 | vertikální synchronizace |
| 0 | 1 | 0 | horizontální synchronizace, vypnutí zobrazení režimu s 320 pixely |
| 0 | 1 | 1 | horizontální synchronizace, zapnutí zobrazení režimu s 320 pixely |
| 1 | 0 | 0 | dva sousední pixely s hodnotami 0 0 |
| 1 | 0 | 1 | dva sousední pixely s hodnotami 0 1 |
| 1 | 1 | 0 | dva sousední pixely s hodnotami 1 0 |
| 1 | 1 | 1 | dva sousední pixely s hodnotami 1 1 |
Pro GTIA režimy si GTIA ve čtyřech klopných obvodech zapamatuje bity D3, D2, D1, D0 poslané ve dvou po sobě následujících barvových cyklech. Následně se zapsaná čtyřbitová hodnota interpretuje podle nastaveného GTIA režimu (viz další kapitoly):
| AN2 | AN1 | AN0 | Význam |
|---|---|---|---|
| 0 | 0 | 1 | vertikální synchronizace |
| 0 | 1 | 0 | horizontální synchronizace, vypnutí zobrazení režimu s 320 pixely |
| 0 | 1 | 1 | horizontální synchronizace, zapnutí zobrazení režimu s 320 pixely |
| 1 | 0 | 0 | sudý cyklus: D3=AN1, D2=AN0 |
| 1 | 0 | 1 | lichý cyklus: D1=AN1, D0=AN0 |
| 1 | 1 | 0 | D3.D2.D1.D0 je hodnota 0..15 |
| 1 | 1 | 1 | interpretovaná různým způsobem |
Programový výběr zvoleného GTIA režimu
Povolení GTIA režimů a vlastní výběr GTIA se provádí přes řídicí registr PRIOR čipu GTIA nebo přes jeho stínový registr nazvaný GPRIOR. Tento řídicí či stínový registr je pochopitelně osmibitový, přičemž jeho jednotlivé bity mají následující význam:
| Bity | Význam |
|---|---|
| 7–6 | povolení GTIA režimu, výběr GTIA režimu |
| 5 | povolení vícebarevných hráčů (při jejich překryvu) |
| 4 | povolení pátého hráče složeného ze všech čtyř střel |
| 3–0 | priority hráčů a střel |
Priority zobrazení hráčů a střel vůči sobě nebo vůči hracímu poli se nastavují, jak je z výše uvedené tabulky patrné, 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. Vše jsme si již ukázali prakticky:
| 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 |
Taktéž již známe významy bitů číslo 5 a 4. Bit číslo 5 nastavený na jedničku povoluje výpočet nové barvy v těch oblastech obrazovky, v nichž dochází k překryvu dvou hráčů. Výsledkem je barva získaná operací OR barev obou hráčů. Bit 4 nastavený na jedničku povoluje vznik pátého hráče ze čtyř střel. Ve skutečnosti tento bit pouze ovlivní barvu všech čtyř střel – o „postavení“ pátého hráče se musí postarat programátor (taktéž jsme si vyzkoušeli).
Zbývají tedy nejvyšší dva bity, jejichž význam je následující:
| Bit 7 | Bit 6 | Význam |
|---|---|---|
| 0 | 0 | běžný ANTIC režim (již známe) |
| 0 | 1 | GTIA režim číslo 9 |
| 1 | 0 | GTIA režim číslo 10 |
| 1 | 1 | GTIA režim číslo 11 |
To, že je ve stínovém registru GPRIOR umístěno několik bitových polí znamená, že do tohoto registru nemůžeme pouze zapsat konkrétní konstantu, ale typicky je nutné provést operaci OR realizovanou instrukcí ORA. V dalších demonstračních příkladech se setkáme s těmito třemi postupy:
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$40 ; výběr GTIA režimu GR.9
sta GPRIOR
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$c0 ; výběr GTIA režimu GR.11
sta GPRIOR
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$80 ; výběr GTIA režimu GR.10
sta GPRIOR
Základ pro další demonstrační příklady: monochromatický grafický režim 320×192 pixelů
Navazující demonstrační příklady použité v tomto článku jsou založeny na stejném základě. Nejdříve je nastaven grafický režim ANTIC F (GR. 8) s rozlišením 320×192 pixelů, přičemž obrazová paměť je rozdělena na dvě části (do bloků menších než 4kB). Následně je na obrazovku vykreslen následující vzorek, který je tvořen bajty s hodnotami od 0 do 15 (tj. jsou použity všechny možné kombinace čtyř bitů):
Obrázek 1: Bitové vzorky zobrazené ve standardním monochromatickém režimu 320x192.
Výše uvedený vzorek je vykreslen smyčkou, která je prozatím (abych nemusel používat sofistikovanější adresování) napsán dosti naivním způsobem:
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
Následuje výpis úplného zdrojového kódu dnešního demonstračního příkladu:
; ---------------------------------------------------------------------
; Grafický režim 320x192 se dvěma barvami.
; Korektní display list.
; Vykreslení šestnácti různých kombinací pixelů.
; ---------------------------------------------------------------------
.include "atari.inc"
.CODE
; dva bloky RAM využité jako obrazová paměť
screen1 = $7000
screen2 = $8000
; délka obrazového řádku v bajtech
scanline = 320/8
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
lda #0 ; zapisovaná hodnota + počitadlo smyčky
tax ; offset do obrazové paměti
clc ; nechceme přičítat přenos
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
loop: jmp loop
.endproc
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen1, >screen1 ; počáteční adresa obrazové paměti (první blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen2, >screen2 ; počáteční adresa obrazové paměti (druhý blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
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
GTIA režim číslo 9: šestnáct intenzit barvy stejného odstínu
Nejprve se seznámíme s GTIA režimem číslo 9. Toto číslo je odvozeno od BASICového příkazu GRAPHICS 9 nebo GR.9, kterým se tento režim nastavuje. V tomto režimu je možné zobrazit jediný barevný odstín, ovšem v šestnácti úrovních – od nejtmavší po nejsvětlejší. Mimochodem: používá se zde skutečně všech šestnáct úrovní barev, což je výjimka umožňující práci s 256 barvami (běžně je totiž dostupných pouze 128 barev).
Druhý demonstrační příklad: nastavení GTIA režimu 9 s vykreslením vzorku barev
V dnešním druhém demonstračním příkladu se opět použije standardní monochromatický ANTIC režim s rozlišením 320×192 pixelů. Na obrazovku je vykresleno šestnáct bitových vzorků přesně tak, jak tomu bylo v úvodním příkladu:
Obrázek 2: Bitové vzorky zobrazené ve standardním monochromatickém režimu 320x192.
Po stisku klávesy se přes stínový registr GPRIOR nastaví GTIA režim číslo 9 a obrazovka se ihned změní následovně:
Obrázek 3: Situace po přepnutí do GTIA režimu 9. Obrazová paměť stále obsahuje stejné vzorky.
Úplný zdrojový kód takto upraveného demonstračního příkladu vypadá následovně:
; ---------------------------------------------------------------------
; Grafický režim 320x192 se dvěma barvami.
; Nastavení GTIA režimu GR.9
; Korektní display list.
; Vykreslení šestnácti různých kombinací pixelů.
; ---------------------------------------------------------------------
.include "atari.inc"
.CODE
; dva bloky RAM využité jako obrazová paměť
screen1 = $7000
screen2 = $8000
; délka obrazového řádku v bajtech
scanline = 320/8
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
lda #0 ; zapisovaná hodnota + počitadlo smyčky
tax ; offset do obrazové paměti
clc ; nechceme přičítat přenos
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
jsr get_key ; čekání na stisk klávesy
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$40 ; výběr GTIA režimu GR.9
sta GPRIOR
loop: jmp loop
.endproc
; ---------------------------------------------------------------------
; čekání na stisk klávesy
; ---------------------------------------------------------------------
.proc get_key
KBHANDLER = $e424 ; rutina pro cteni klavesy
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
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen1, >screen1 ; počáteční adresa obrazové paměti (první blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen2, >screen2 ; počáteční adresa obrazové paměti (druhý blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
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
GTIA režim 9 není omezen jen na šedou škálu
I když se v předchozím demonstračním příkladu zobrazilo šestnáct úrovní šedé barvy, v žádném případě to neznamená, že GTIA režim číslo 9 nedokáže zobrazit odlišné barevné odstíny. O jaký konkrétní barevný odstín se jedná je určeno obsahem HW registru COLBK nebo do jeho stínového registru COLOR4. V ANTIC režimech se tento registr používá pro specifikaci barvy pozadí (většina režimů) nebo alespoň barvy okraje (GR.0 a GR.8). Ostatní tři barvové registry COLOR0 až COLOR3 nemají na způsob zobrazení žádný vliv.
HUE_COLOR_GRAY = 16 * $0 HUE_COLOR_GOLD = 16 * $1 HUE_COLOR_ORANGE_1 = 16 * $2 HUE_COLOR_PINK = 16 * $3 HUE_COLOR_MAGENTA = 16 * $4 HUE_COLOR_BLUE = 16 * $5 HUE_COLOR_INDIGO = 16 * $6 HUE_COLOR_SKY_BLUE = 16 * $7 HUE_COLOR_ROYAL_BLUE = 16 * $8 HUE_COLOR_LIGHT_BLUE = 16 * $9 HUE_COLOR_TURQOISE = 16 * $A HUE_COLOR_AQUAMARIN = 16 * $B HUE_COLOR_SEA_GREEN = 16 * $C HUE_COLOR_LIGHT_GREEN = 16 * $D HUE_COLOR_OLIVE = 16 * $E HUE_COLOR_ORANGE_2 = 16 * $F
Postupná změna základního odstínu barvy
Připomeňme si, že na osmibitových mikropočítačích Atari se kód barvy skládá z čísla odstínu barvy 0..15 uloženého ve vyšších čtyřech bitech barvových registrů. V nižších čtyřech bitech je zapsána intenzita barvy, která ovšem v režimu GR.9 nemá význam (resp. význam ve skutečnosti má, ale to bychom již zabíhali do zbytečných detailů).
V dalším demonstračním příkladu budeme realizovat postupné zobrazení všech šestnácti dostupných barvových odstínů ve všech šestnácti intenzitách. Samotný program byl upraven jen nepatrně, a to konkrétně přidáním programové smyčky, ve které se hodnota ve stínovém registru COLOR4 po každém stisku klávesy zvyšuje o hodnotu 16 (což znamená přechod k dalšímu odstínu):
; postupná změna globálního odstínu
lda #0 ; barvový registr použití v režimu GR.9
next_color:
sta COLOR4 ; ulozit nový kód barvy do registru COLOR4
clc
adc #16 ; a zvýšit kód barvy pro další iteraci
pha
jsr get_key ; čekání na stisk klávesy
pla
jmp next_color ; změna barvy + další čekání na klávesu
Výsledky, které se na obrazovce postupně ukážou, budou vypadat následovně:
Obrázek 4: GTIA režim 9, barvový odstín číslo 0.
Obrázek 5: GTIA režim 9, barvový odstín číslo 1.
Obrázek 6: GTIA režim 9, barvový odstín číslo 2.
Obrázek 7: GTIA režim 9, barvový odstín číslo 3.
Obrázek 8: GTIA režim 9, barvový odstín číslo 4.
Obrázek 9: GTIA režim 9, barvový odstín číslo 5.
Obrázek 10: GTIA režim 9, barvový odstín číslo 6.
Obrázek 11: GTIA režim 9, barvový odstín číslo 7.
Obrázek 12: GTIA režim 9, barvový odstín číslo 8.
Obrázek 13: GTIA režim 9, barvový odstín číslo 9.
Obrázek 14: GTIA režim 9, barvový odstín číslo 10.
Obrázek 15: GTIA režim 9, barvový odstín číslo 11.
Obrázek 16: GTIA režim 9, barvový odstín číslo 12.
Obrázek 17: GTIA režim 9, barvový odstín číslo 13.
Obrázek 18: GTIA režim 9, barvový odstín číslo 14.
Obrázek 19: GTIA režim 9, barvový odstín číslo 15.
Třetí demonstrační příklad: nastavení GTIA režimu 9 s postupnou změnou základního odstínu barvy
Úplný zdrojový kód dnešního třetího demonstračního příkladu vypadá následovně:
; ---------------------------------------------------------------------
; Grafický režim 320x192 se dvěma barvami.
; Korektní display list.
; Vykreslení šestnácti různých kombinací pixelů.
; Přepnutí do GTIA režimu 9.
; Postupná změna barevného odstínu.
; ---------------------------------------------------------------------
.include "atari.inc"
.CODE
; dva bloky RAM využité jako obrazová paměť
screen1 = $7000
screen2 = $8000
; délka obrazového řádku v bajtech
scanline = 320/8
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
lda #0 ; zapisovaná hodnota + počitadlo smyčky
tax ; offset do obrazové paměti
clc ; nechceme přičítat přenos
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$40 ; výběr GTIA režimu GR.9
sta GPRIOR
; postupná změna globálního odstínu
lda #0 ; barvový registr použití v režimu GR.9
next_color:
sta COLOR4 ; ulozit nový kód barvy do registru COLOR2
clc
adc #16 ; a zvýšit kód barvy pro další iteraci
pha
jsr get_key ; čekání na stisk klávesy
pla
jmp next_color ; změna barvy + další čekání na klávesu
loop: jmp loop
.endproc
; ---------------------------------------------------------------------
; čekání na stisk klávesy
; ---------------------------------------------------------------------
.proc get_key
KBHANDLER = $e424 ; rutina pro cteni klavesy
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
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen1, >screen1 ; počáteční adresa obrazové paměti (první blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen2, >screen2 ; počáteční adresa obrazové paměti (druhý blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
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
GTIA režim číslo 11: šestnáct odstínů barev stejné intenzity
V grafickém režimu GTIA číslo 9 bylo možné zobrazit jeden odstín barvy, ovšem ve všech šestnácti intenzitách (od nejtmavší po nejsvětlejší). GTIA režim číslo 11 se chová přesně opačně, protože se zobrazí všech šestnáct dostupných odstínů barev, ovšem jen s jednou (pro všechny barvy stejnou) intenzitou. Nastavení resp. volba barvového odstínu se opět provádí přes řídicí registr COLBK resp. přes jeho stínový registr COLOR4. Význam ovšem mají jen bity 1 až 3 (včetně), protože v GTIA režimu číslo 11 lze nastavit pouze sudé intenzity 0, 2, 4, … 14. Ostatní tři barvové registry COLOR0 až COLOR3 nemají na způsob zobrazení žádný vliv.
Obrázek 19: GTIA režim 11.
Čtvrtý demonstrační příklad: nastavení GTIA režimu 11 s vykreslením vzorku barev
Použití GTIA režimu číslo 11 se vlastně nijak zásadně neliší od režimu GTIA 9, což je ostatně patrné i při pohledu na zdrojový kód příkladu, který vykreslil obrázek z předchozí kapitoly:
; ---------------------------------------------------------------------
; Grafický režim 320x192 se dvěma barvami.
; Korektní display list.
; Vykreslení šestnácti různých kombinací pixelů.
; Přepnutí do GTIA režimu 11.
; ---------------------------------------------------------------------
.include "atari.inc"
.CODE
; dva bloky RAM využité jako obrazová paměť
screen1 = $7000
screen2 = $8000
; délka obrazového řádku v bajtech
scanline = 320/8
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
lda #0 ; zapisovaná hodnota + počitadlo smyčky
tax ; offset do obrazové paměti
clc ; nechceme přičítat přenos
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
jsr get_key ; čekání na stisk klávesy
lda #15 ; intenzita barev
sta COLOR4 ; ulozit nový kód barvy do registru COLOR2
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$c0 ; výběr GTIA režimu GR.11
sta GPRIOR
loop: jmp loop
.endproc
; ---------------------------------------------------------------------
; čekání na stisk klávesy
; ---------------------------------------------------------------------
.proc get_key
KBHANDLER = $e424 ; rutina pro cteni klavesy
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
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen1, >screen1 ; počáteční adresa obrazové paměti (první blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen2, >screen2 ; počáteční adresa obrazové paměti (druhý blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
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
Postupná změna intenzity všech barev na obrazovce
Tak, jako bylo možné v režimu GTIA 9 postupně měnit odstín zobrazené barvy (se šestnácti možnými intenzitami), je možné v režimu GTIA 11 modifikovat intenzitu všech šestnácti barev. Jak již víme, intenzita se v tomto případě specifikuje sudou hodnotou 0 až 14 zapisovanou do stínového registru COLOR4. Ovšem nemusíte mi věřit, že se jedná o sudé hodnoty – v kódu budeme hodnoty měnit po jedničce, tedy od 0 do 15 s krokem 1:
; postupná změna globálního odstínu
lda #0 ; barvový registr použití v režimu GR.9
next_color:
sta COLOR4 ; ulozit nový kód barvy do registru COLOR2
clc
adc #1 ; a zvýšit kód barvy pro další iteraci
pha
jsr get_key ; čekání na stisk klávesy
pla
jmp next_color ; změna barvy + další čekání na klávesu
Výsledné obrazovky by měly vypadat následovně:
Obrázek 20: GTIA režim 11, intenzita nastavená na hodnotu 0.
Obrázek 21: GTIA režim 11, intenzita nastavená na hodnotu 2.
Obrázek 22: GTIA režim 11, intenzita nastavená na hodnotu 4.
Obrázek 23: GTIA režim 11, intenzita nastavená na hodnotu 6.
Obrázek 24: GTIA režim 11, intenzita nastavená na hodnotu 8.
Obrázek 25: GTIA režim 11, intenzita nastavená na hodnotu 10.
Obrázek 26: GTIA režim 11, intenzita nastavená na hodnotu 12.
Obrázek 27: GTIA režim 11, intenzita nastavená na hodnotu 14.
Pátý demonstrační příklad: nastavení GTIA režimu 11 s postupnou změnou intenzity barev
Opět si ukažme úplný zdrojový kód demonstračního příkladu, který postupně zobrazí všechny intenzity všech dostupných barev v grafickém režimu GTIA 11:
; ---------------------------------------------------------------------
; Grafický režim 320x192 se dvěma barvami.
; Korektní display list.
; Vykreslení šestnácti různých kombinací pixelů.
; ---------------------------------------------------------------------
.include "atari.inc"
.CODE
; dva bloky RAM využité jako obrazová paměť
screen1 = $7000
screen2 = $8000
; délka obrazového řádku v bajtech
scanline = 320/8
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
lda #0 ; zapisovaná hodnota + počitadlo smyčky
tax ; offset do obrazové paměti
clc ; nechceme přičítat přenos
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$c0 ; výběr GTIA režimu GR.11
sta GPRIOR
; postupná změna globálního odstínu
lda #0 ; barvový registr použití v režimu GR.9
next_color:
sta COLOR4 ; ulozit nový kód barvy do registru COLOR2
clc
adc #1 ; a zvýšit kód barvy pro další iteraci
pha
jsr get_key ; čekání na stisk klávesy
pla
jmp next_color ; změna barvy + další čekání na klávesu
loop: jmp loop
.endproc
; ---------------------------------------------------------------------
; čekání na stisk klávesy
; ---------------------------------------------------------------------
.proc get_key
KBHANDLER = $e424 ; rutina pro cteni klavesy
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
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen1, >screen1 ; počáteční adresa obrazové paměti (první blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen2, >screen2 ; počáteční adresa obrazové paměti (druhý blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
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
GTIA režim číslo 10: devět nezávisle na sobě nastavitelných barev
Ze všech tří režimů GTIA je nejužitečnějším, ale taktéž „nejdivnějším“ režim číslo 10. Jedná se o jediný GTIA režim, ve kterém lze nastavit jednotlivé barvy individuálně (což je zajisté skvělé), ovšem na druhou stranu je zde jedno omezení – čip GTIA obsahuje pouze devět registrů určených pro specifikaci barvy (spritů, herního pole atd.). To znamená, že i GTIA režim 10 je omezen na devět barev, i když bychom očekávali barev šestnáct. I přes toto omezení je ovšem možné GTIA 10 využít kromě úvodních obrazovek i k tvorbě reálných her – zde je jedna pěkná ukázka, jak by taková hra mohla vypadat. Z ukázky je patrné, že počet barev není ten největší problém režimů GTIA – tím je velmi malé (skoro až směšné) horizontální rozlišení.
Barvy pixelů mohou obsahovat hodnoty 0 až 15, ovšem pouze devíti hodnotám je přiřazena barva. K tomuto účelu se používá již výše zmíněných devět HW registrů čipu GTIA popř. devět stínových registrů:
| HW registr | Stínový registr | Význam |
|---|---|---|
| COLMP0 | PCOLOR0 | pozadí |
| COLMP1 | PCOLOR1 | pixely |
| COLMP2 | PCOLOR2 | pixely |
| COLMP3 | PCOLOR3 | pixely |
| COLPF0 | COLOR0 | pixely |
| COLPF1 | COLOR1 | pixely |
| COLPF2 | COLOR2 | pixely |
| COLPF3 | COLOR3 | pixely |
| COLBAK | COLOR4 | pixely |
První čtyři barvové registry jsou použity pro sprity (hráče a střely), takže v tomto režimu již není možné využít známého triku se zvýšením počtu barev pouze přidáním spritů na vhodná místa na obrazovce.
Šestý demonstrační příklad: zobrazení barevné škály v režimu GTIA 10
Šestý demonstrační příklad po svém překladu a spuštění vykreslí následující obrázek:
Obrázek 30: Devět různých barev v GTIA režimu číslo 10.
Ovšem po inicializaci operačního systému jsou barvy PMG (spritů) nastaveny na černou barvu, takže je musíme explicitně přenastavit, například takto:
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
Úplný zdrojový kód příkladu vypadá následovně:
; ---------------------------------------------------------------------
; Grafický režim 320x192 se dvěma barvami.
; Korektní display list.
; Vykreslení šestnácti různých kombinací pixelů.
; Přepnutí do GTIA režimu 10.
; ---------------------------------------------------------------------
.include "atari.inc"
.CODE
; dva bloky RAM využité jako obrazová paměť
screen1 = $7000
screen2 = $8000
; délka obrazového řádku v bajtech
scanline = 320/8
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
lda #0 ; zapisovaná hodnota + počitadlo smyčky
tax ; offset do obrazové paměti
clc ; nechceme přičítat přenos
draw:
sta screen1, x ; zápis na první řádek
sta screen1+scanline, x ; buranský zápis do sedmi obrazových řádků pod sebe
sta screen1+scanline*2, x ; pozn: jde použít opakování přes makro
sta screen1+scanline*3, x
sta screen1+scanline*4, x
sta screen1+scanline*5, x
sta screen1+scanline*6, x
sta screen1+scanline*7, x
inx ; další zápis bude proveden o dva bajty dále
inx
adc #1 ; zvýšení hodnoty v akumulátoru
cmp #16 ; konec smyčky?
bne draw ; dokud není nula, pokračovat
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
jsr get_key ; čekání na stisk klávesy
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$80 ; výběr GTIA režimu GR.10
sta GPRIOR
loop: jmp loop
.endproc
; ---------------------------------------------------------------------
; čekání na stisk klávesy
; ---------------------------------------------------------------------
.proc get_key
KBHANDLER = $e424 ; rutina pro cteni klavesy
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
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen1, >screen1 ; počáteční adresa obrazové paměti (první blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_LMS+DL_MAP320x1x1 ; určení počáteční adresy obrazové paměti + jeden řádek režimu F (GR.8)
.byte <screen2, >screen2 ; počáteční adresa obrazové paměti (druhý blok)
.res 95, DL_MAP320x1x1 ; opakovat řádky grafického režimu F (GR.8)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
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
GTIA režimy založené na odlišném grafickém režimu než ANTIC F (GR.8)
GTIA režimy pracují zcela nezávisle na ANTICu. To vlastně znamená, že ANTIC může zobrazovat libovolný režim (nejenom GR.8) a posílat barvy pixelů do čipu GTIA (buď dva bity na pixel, nebo jeden bit na pixel, jiná možnost vlastně neexistuje). A GTIA bude tyto hodnoty interpretovat po svém; viz druhou kapitolu s vysvětlením, jak spolu tyto čipy komunikují. Jak to vypadá v praxi si ukážeme na obrazovce, která obsahuje několik řádků s různými textovými režimy. Display list je následující:
dlist: .byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků .byte DL_LMS+DL_CHR20x16x2 ; určení počáteční adresy obrazové paměti + jeden řádek režimu 7 .byte <screen,>screen ; počáteční adresa obrazové paměti .byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2) .byte DL_CHR40x8x1 ; jeden řádek textového režimu 2 (GR.0) .byte DL_CHR20x8x2 ; jeden řádek textového režimu 6 (GR.1) .byte DL_CHR40x8x1 ; jeden řádek textového režimu 2 (GR.0) .byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2) .byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2) .byte DL_MAP40x8x4 ; jeden řádek grafického režimu 8 (GR.3) .byte DL_MAP40x8x4 ; jeden řádek grafického režimu 8 (GR.3) .byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2) .byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2) .byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2) .byte DL_CHR40x8x1 ; jeden řádek textového režimu 2 (GR.0) .byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
Pokud není GTIA režim povolený bude obrazovka vypadat normálně:
Obrázek 31: Kombinace různých textových režimů na jediné obrazovce.
Ovšem po povolení GTIA režimu (9, 11 či 10) se pochopitelně interpretace bitů posílaných z ANTICu do GTIA radikálně změní:
Obrázek 32: Stejný obsah obrazové paměti, ovšem po povolení GTIA režimu 9.
Obrázek 33: Stejný obsah obrazové paměti, ovšem po povolení GTIA režimu 11.
Obrázek 34: Stejný obsah obrazové paměti, ovšem po povolení GTIA režimu 10.
Sedmý demonstrační příklad: obrazovka s různými textovými režimy, přepnutí do „zobrazení“ GTIA
Úplný zdrojový kód dnešního sedmého a současně i posledního demonstračního příkladu, který vykreslil obrázky z předchozí kapitoly, vypadá následovně:
.include "atari.inc"
.CODE
.proc main
lda #<dlist ; nižší byte adresy display listu
sta SDLSTL
lda #>dlist ; vyšší byte adresy display listu
sta SDLSTH
ldy #0 ; počitadlo zápisů
lda #0 ; kód vypisovaného znaku
fill_screen:
sta screen, y ; tisk znaku na zvolené místo na obrazovce
clc
adc #1
iny ; zvětšit hodnotu počitadla a offsetu
cpy #40*6 ; test na koncovou hodnotu počitadla
bne fill_screen ; skok, pokud Y>40*6
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
jsr get_key ; čekání na stisk klávesy
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$40 ; výběr GTIA režimu GR.9
sta GPRIOR
jsr get_key ; čekání na stisk klávesy
lda #15 ; intenzita barev
sta COLOR4 ; ulozit nový kód barvy do registru COLOR2
lda GPRIOR ; modifikace stínového registru GPRIOR
ora #$c0 ; výběr GTIA režimu GR.11
sta GPRIOR
jsr get_key ; čekání na stisk klávesy
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 GPRIOR ; modifikace stínového registru GPRIOR
and #%00111111
ora #$80 ; výběr GTIA režimu GR.10
sta GPRIOR
loop: jmp loop
.endproc
; ---------------------------------------------------------------------
; čekání na stisk klávesy
; ---------------------------------------------------------------------
.proc get_key
KBHANDLER = $e424 ; rutina pro cteni klavesy
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
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8 ; 3x8=24 prázdných obrazových řádků
.byte DL_LMS+DL_CHR20x16x2 ; určení počáteční adresy obrazové paměti + jeden řádek režimu 7
.byte <screen,>screen ; počáteční adresa obrazové paměti
.byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2)
.byte DL_CHR40x8x1 ; jeden řádek textového režimu 2 (GR.0)
.byte DL_CHR20x8x2 ; jeden řádek textového režimu 6 (GR.1)
.byte DL_CHR40x8x1 ; jeden řádek textového režimu 2 (GR.0)
.byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2)
.byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2)
.byte DL_MAP40x8x4 ; jeden řádek grafického režimu 8 (GR.3)
.byte DL_MAP40x8x4 ; jeden řádek grafického režimu 8 (GR.3)
.byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2)
.byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2)
.byte DL_CHR20x16x2 ; jeden řádek textového režimu 7 (GR.2)
.byte DL_CHR40x8x1 ; jeden řádek textového režimu 2 (GR.0)
.byte DL_JVB, <dlist, >dlist ; skok na začátek display listu
end:
.BSS
screen: .res 20*24
.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říloha: 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:
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 \
pmg_11.xex pmg_12.xex \
pmg_13.xex pmg_14.xex \
pmg_15.xex pong.xex \
pmg_stick_1.xex pmg_stick_2.xex \
pmg_stick_3.xex pmg_stick_4.xex \
pmg_stick_5.xex pmg_stick_6.xex \
pmg_collisions_1.xex pmg_collisions_2.xex \
pmg_collisions_3.xex pmg_collisions_4.xex \
antic_1.xex antic_2.xex \
antic_3.xex antic_4.xex \
antic_5.xex antic_6.xex \
antic_7.xex antic_8.xex \
antic_9.xex antic_A.xex \
antic_B.xex \
antic_bitmap_1.xex antic_bitmap_2.xex \
antic_bitmap_3.xex antic_bitmap_4.xex \
antic_bitmap_5.xex antic_bitmap_6.xex \
antic_bitmap_7.xex antic_bitmap_8.xex \
antic_dli_1.asm antic_dli_2.asm \
antic_dli_3.asm antic_dli_4.asm \
antic_dli_5.asm antic_dli_pmg.asm
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
antic_bitmap_6.xex: antic_bitmap_6.o
ld65 -C linker_image.cfg $< -o $@ -m $(basename $<).map
antic_bitmap_7.xex: antic_bitmap_7.o
ld65 -C linker_image_2.cfg $< -o $@ -m $(basename $<).map
antic: \
antic_1.xex \
antic_2.xex \
antic_3.xex \
antic_4.xex \
antic_5.xex \
antic_6.xex \
antic_7.xex \
antic_8.xex \
antic_9.xex \
antic_A.xex \
antic_B.xex
antic_bitmap: \
antic_bitmap_1.xex \
antic_bitmap_2.xex \
antic_bitmap_3.xex \
antic_bitmap_4.xex \
antic_bitmap_5.xex \
antic_bitmap_6.xex \
antic_bitmap_7.xex \
antic_bitmap_8.xex
antic_dli: \
antic_dli_1.xex \
antic_dli_2.xex \
antic_dli_3.xex \
antic_dli_4.xex \
antic_dli_5.xex \
antic_dli_pmg.xex
antic_vbi: \
antic_vbi_1.xex \
antic_vbi_2.xex \
antic_vbi_3.xex \
antic_vbi_dli_1.xex \
antic_vbi_dli_2.xex \
antic_vbi_dli_3.xex \
antic_vbi_dli_4.xex
antic_scrolling: \
antic_scrolling_1.xex \
antic_scrolling_2.xex \
antic_scrolling_3.xex \
antic_scrolling_4.xex
gtia: \
gtia_mode_1.xex \
gtia_mode_2.xex \
gtia_mode_3.xex \
gtia_mode_4.xex \
gtia_mode_5.xex \
gtia_mode_6.xex \
gtia_mode_7.xex
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:
Odkazy na Internetu
- MOS 6502 instruction set
http://www.6502.org/users/obelisk/6502/instructions.html - EXE File Format Description
https://gury.atari8.info/refs/file_formats_exe.php - XEX Filter – A toolkit to analyze and manipulate Atari binary files
https://www.vitoco.cl/atari/xex-filter/index.html - chkxex.py
https://raw.githubusercontent.com/seban-slt/tcx_tools/refs/heads/master/chkxex.py - ca65 Users Guide
https://cc65.github.io/doc/ca65.html - cc65 Users Guide
https://cc65.github.io/doc/cc65.html - ld65 Users Guide
https://cc65.github.io/doc/ld65.html - da65 Users Guide
https://cc65.github.io/doc/da65.html - Překladače jazyka C pro historické osmibitové mikroprocesory
https://www.root.cz/clanky/prekladace-jazyka-c-pro-historicke-osmibitove-mikroprocesory/ - 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/ - Getting Started Programming in C: Coding a Retro Game with C Part 2
https://retrogamecoders.com/getting-started-with-c-cc65/ - NES game development in 6502 assembly – Part 1
https://kibrit.tech/en/blog/nes-game-development-part-1 - 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/ - Minimal NES example using ca65
https://github.com/bbbradsmith/NES-ca65-example - List of 6502-based Computers and Consoles
https://www.retrocompute.co.uk/list-of-6502-based-computers-and-consoles/ - 6502 – the first RISC µP
http://ericclever.com/6500/ - 3 Generations of Game Machine Architecture
http://www.atariarchives.org/dev/CGEXPO99.html - “Hello, world” from scratch on a 6502 — Part 1
https://www.youtube.com/watch?v=LnzuMJLZRdU - A Tour of 6502 Cross-Assemblers
https://bumbershootsoft.wordpress.com/2016/01/31/a-tour-of-6502-cross-assemblers/ - Adventures with ca65
https://atariage.com/forums/topic/312451-adventures-with-ca65/ - example ca65 startup code
https://atariage.com/forums/topic/209776-example-ca65-startup-code/ - 6502 PRIMER: Building your own 6502 computer
http://wilsonminesco.com/6502primer/ - 6502 Instruction Set
https://www.masswerk.at/6502/6502_instruction_set.html - Chip Hall of Fame: MOS Technology 6502 Microprocessor
https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-mos-technology-6502-microprocessor - Single-board computer
https://en.wikipedia.org/wiki/Single-board_computer - www.6502.org
http://www.6502.org/ - 6502 PRIMER: Building your own 6502 computer – clock generator
http://wilsonminesco.com/6502primer/ClkGen.html - Great Microprocessors of the Past and Present (V 13.4.0)
http://www.cpushack.com/CPU/cpu.html - Jak se zrodil procesor?
https://www.root.cz/clanky/jak-se-zrodil-procesor/ - Osmibitové mikroprocesory a mikrořadiče firmy Motorola (1)
https://www.root.cz/clanky/osmibitove-mikroprocesory-a-mikroradice-firmy-motorola-1/ - 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/ - 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/ - 25 Microchips That Shook the World
https://spectrum.ieee.org/tech-history/silicon-revolution/25-microchips-that-shook-the-world - Comparison of instruction set architectures
https://en.wikipedia.org/wiki/Comparison_of_instruction_set_architectures - How To Start Learning Atari 8 Bit Assembly For Free
https://forums.atariage.com/topic/300732-how-to-start-learning-atari-8-bit-assembly-for-free/ - WUDSN (Demo Group)
https://www.wudsn.com/ - Machine Language For Beginners
https://www.atariarchives.org/mlb/ - Assembly language: all about I/O
https://www.atarimagazines.com/v3n8/AllAbout_IO.html - Sedmdesátiny assemblerů: lidsky čitelný strojový kód
https://www.root.cz/clanky/sedmdesatiny-assembleru-lidsky-citelny-strojovy-kod/ - Color names
https://atariwiki.org/wiki/Wiki.jsp?page=Color%20names - ATASCII
https://en.wikipedia.org/wiki/ATASCII - Put characters in display ram isn't ATASCII?
https://forums.atariage.com/topic/359973-put-characters-in-display-ram-isnt-atascii/ - ATASCII And Internal Character Code Values
https://www.atariarchives.org/mapping/appendix10.php - Reading ATASCII from the keyboard in assembly
https://forums.atariage.com/topic/361733-reading-atascii-from-the-keyboard-in-assembly/ - Why does the 6502 JSR instruction only increment the return address by 2 bytes?
https://retrocomputing.stackexchange.com/questions/19543/why-does-the-6502-jsr-instruction-only-increment-the-return-address-by-2-bytes - Pushing return address to stack off by 1 byte
https://forums.atariage.com/topic/378206-pushing-return-address-to-stack-off-by-1-byte/ - Intel x86 documentation has more pages than the 6502 has transistors
https://www.righto.com/2013/09/intel-x86-documentation-has-more-pages.html - Clearing a Section of Memory
http://www.6502.org/source/general/clearmem.htm - Practical Memory Move Routines by Bruce Clark
http://www.6502.org/source/general/memory_move.html - 6502 Assembly Programming Guide
https://neumont-gamedev.github.io/posts/retrogamedev-6502-guide/ - Off-by-one error
https://en.wikipedia.org/wiki/Off-by-one_error - 6502 cycle times
https://www.nesdev.org/wiki/6502_cycle_times - Atari TIA
http://www.atarihq.com/danb/tia.shtml - TIA Playfield
http://www.atarihq.com/danb/TIA/Playfield.shtml - Atari Inc.:
ANTIC C012296 (NTSC) Revision D
Atari Incorporated, Sunnyvale CA, 1982 - Atari Inc.:
GTIA C014805 (NTSC) Revision A
Atari Incorporated, Sunnyvale CA, 1982 - Atari 5200
http://www.atariage.com/software_search.html?SystemID=5200 - Atari 5200 Hardware and Accessories
http://www.atariage.com/5200/archives/hardware.html - Atari 5200 Screenshots
http://www.atariage.com/system_items.html?SystemID=5200&ItemTypeID=SCREENSHOT - History of video game consoles (second generation): Wikipedia
http://en.wikipedia.org/wiki/History_of_video_game_consoles_(second_generation) - Atari 5200: Wikipedia
http://en.wikipedia.org/wiki/Atari_5200 - Player-Missile Graphics
https://www.atariarchives.org/agagd/chapter5.php - Sprite (computer graphics)
https://en.wikipedia.org/wiki/Sprite_(computer_graphics) - Atari Graphics Demonstrations by Underground Software, 1985 | Atari 8 bit Demo
https://www.youtube.com/watch?v=h7N9EYSyCkw - Atari 8-bit Display List Interrupts: A Complete(ish) Tutorial
https://playermissile.com/dli_tutorial/ - Atari Assembler Editor manual
https://atariwiki.org/wiki/attach/Atari%20Assembler%20Editor/ATARI%20Assembler%20Editor%20User-s%20Manual-OCR.pdf - Atari 8-bit Fine Scrolling: A Complete(ish) Tutorial
https://playermissile.com/scrolling_tutorial/index.html - Atari Fine Scrolling
https://www.atarimagazines.com/compute/issue67/338_1_Atari_Fine_Scrolling.php - CTIA / GTIA Pinout Diagram
https://user.xmission.com/~trevin/atari/gtia_pinout.html - GTIA Modes
https://page6.org/archive/issue02/page10.htm - 56 graphic modes
https://www.atari800×l.eu/docs/kb/kb-hardware-0005-atari-8bit-56-graphic-modes.html - UNLOCKING THE 56 GRAPHIC MODES
https://www.atarimagazines.com/v3n5/allmodes.html - GTIA Modes 9, 10 & 11 + ANTIC data and color clocks
https://forums.atariage.com/topic/366256-gtia-modes-9–10–11-antic-data-and-color-clocks/ - ANTIC, GTIA and timing info
https://atarimax.com/jindroush.atari.org/atanttim.html - 6.10 Cycle timing
https://github.com/AnimaInCorpore/A8E/blob/main/AHRM/6.%20CTIA-GTIA/10.%20Cycle%20timing.md
