Programowanie: Plot w Graphics 0
From Atariki
Procedury poniżej opisują, jak w trybie Graphics 0 zrobić plota o precyzji podpixelowej - o rozdzielczości 80x48 używając standardowego zestawu znaków. W całym artykule operuję na kodach wewnętrznych Antica.
Odrobina teorii
Tryb ten nie był pomyślany do wyświetlania rastrowej grafiki, co wiąże się z kilkoma problemami. Głównym jest nieliniowość pamięci - podobnie jak w trybach bitowych jeden bajt określa stan kilku pixli (tutaj: czterech), jednakże w przeciwieństwie do nich tutaj jeden bajt określa stan pixli sąsiadujących ze sobą w poziomie jak i w pionie (a nie tylko w poziomie jak to zwykle bywa). Zakładając, ze lewy, górny pixel ma pozycje 0.0 a prawy dolny - 79.47 to pierwszy bajt pamięci określa pixle: 0.0, 1.0, 0.1, 1.1, drugi bajt: 2.0, 3.0, 2.1 i 3.1 itd... Kolejny problem to nieliniowość samego zestawu znaków. Bajt wyszyszczony to $00 (spacja). Chcąc zapalić pixel 0.0 - wpisujemy wartość $4c (kod znaku z jedną ćwiartką) do pierwszej komórki pamięci obrazu. Jeśli następnie zapalimy pixel 1.0 - pod ten sam adres trzeba wpisać wartość $d5 (górna połowa znaku jest zapalona), itd..
W ten sposób mamy już koncepcję, jak podbić rozdzielczość. Jest jeszcze jeden drobny problem: jaki znak wyświetlić dla dwóch układów pixli: 0.0 i 1.1 oraz 0.1 i 1.0. Atari nie ma znaku szachownicy. Ja (ze względu na podobieństwo wyglądu) wybrałem znaki o kodach: $47 oraz $46 (grube wersje znaków \ oraz /).
Praktyka, czyli mięso
Plot używa czterech tablic, każda o rozmiarze 256 bajtów. Dokładniej rzecz biorąc, nie całe 256 bajtów jest zajęte, tylko wybrane 16 bajtów. Pomiędzy nimi są dziury - można je użyć do własnych celów. Są jeszcze dwie mniejsze tablice, każda o długości 48 bajtów (lub innej, jeśli operujemy na niestandardowym ekranie) - młodsze oraz starsze bajty adresów linii ekranu. Każdy wiersz w tablicy jest podwojony.
Stałe używane przez procedury:
addr - wektor (2 kolejne bajty) na stronie 0 screen - adres ekranu screen_lo - tablica na młodsze bajty adresów dla kolejnych linii ekrany, screen_hi - jak wyżej, ale dla starszych bajtów, plot00 do plot11 - tablice do zapalania kolejnych ćwiartek.
Do wygenerowania wspomnianych tablic można użyć poniższej procedury:
plot0_init equ * lda <screen ; wartości początkowe sta addr lda >screen sta addr+1 ldx #$00 init_1 equ * lda addr ; dwukrotnie zapisz adres wiersza do tablic screen_lo i screen_hi sta screen_lo,x lda addr+1 sta screen_hi,x inx lda addr sta screen_lo,x lda addr+1 sta screen_hi,x clc ; przesun sie na nastepny wiersz pamieci ekranu lda addr adc #$28 ; szerokość ekranu w bajtach sta addr lda addr+1 adc #$00 sta addr+1 inx cpx #$30 ; wysokość ekranu w bajtach*2 bne init_1 ; 00 10 - układ pixli w bajcie ; 01 11 ; plot00 lda #$4c ; ustaw poprawne wartości dla zapalania poszczególnych ćwiartek sta plot00+$00 sta plot00+$4c lda #$d5 sta plot00+$4b sta plot00+$d5 lda #$47 sta plot00+$49 sta plot00+$47 lda #$59 sta plot00+$4f sta plot00+$59 lda #$80 sta plot00+$cc sta plot00+$80 lda #$cb sta plot00+$55 sta plot00+$cb lda #$cf sta plot00+$d9 sta plot00+$cf lda #$c9 sta plot00+$46 sta plot00+$c9 ; plot10 lda #$4b sta plot10+$00 sta plot10+$4b lda #$d5 sta plot10+$4c sta plot10+$d5 lda #$d9 sta plot10+$49 sta plot10+$d9 lda #$46 sta plot10+$4f sta plot10+$46 lda #$cc sta plot10+$55 sta plot10+$cc lda #$c9 sta plot10+$59 sta plot10+$c9 lda #$80 sta plot10+$cb sta plot10+$80 lda #$cf sta plot10+$47 sta plot10+$cf ; plot01 lda #$4f sta plot01+$00 sta plot01+$4f lda #$59 sta plot01+$4c sta plot01+$59 lda #$46 sta plot01+$4b sta plot01+$46 lda #$55 sta plot01+$49 sta plot01+$55 lda #$c9 sta plot01+$d5 sta plot01+$c9 lda #$cc sta plot01+$d9 sta plot01+$cc lda #$cb sta plot01+$47 sta plot01+$cb lda #$80 sta plot01+$cf sta plot01+$80 ; plot11 lda #$49 sta plot11+$00 sta plot11+$49 lda #$47 sta plot11+$4c sta plot11+$47 lda #$d9 sta plot11+$4b sta plot11+$d9 lda #$55 sta plot11+$4f sta plot11+$55 lda #$cf sta plot11+$d5 sta plot11+$cf lda #$cb sta plot11+$59 sta plot11+$cb lda #$cc sta plot11+$46 sta plot11+$cc lda #$80 sta plot11+$c9 sta plot11+$80 rts
Teraz możemy użyć plota właściwego:
; parametry: ; rejestry x, y - własciwa pozycja pixla do zapalenia plot0 equ * lda screen_lo,y ; zapisz adres wiersza pamieci ekranu w addr sta addr lda screen_hi,y sta addr+1 tya ; określ, o którą ćwiartkę chodzi (tutaj badamy współrzędną Y) lsr @ bcs plot0_0 txa ; jak wyżej, ale badamy współrzędna X lsr @ tay bcc plot0_1 lda (addr),y ; używając wcześniej przygotowanych tablic zapisz odpowiednią wartość do pamięci ekranu. tax lda plot10,x sta (addr),y rts plot0_1 equ * lda (addr),y tax lda plot00,x sta (addr),y rts plot0_0 equ * txa lsr @ tay bcc plot0_2 lda (addr),y tax lda plot11,x sta (addr),y rts plot0_2 equ * lda (addr),y tax lda plot01,x sta (addr),y rts
Jak to działa w praktyce, można zobaczyć w demach: Unplugged oraz Unfused.