Wielu z Was zapewne słyszało o pewnym
programie graficznym, zwanym skrótowo
GED. Napisany został on w 1993 roku przez
Johna Harrisa. Jest to program, który pod
względem możliwości graficznych znajduje
się gdzieś w pierwszej piątce wszystkich
programów graficznych na Atari. Również
pod względem ilości wbudowanych opcji
ten program znajduje się w pierwszej
piątce, tyle że od tyłu.
Jednak, mimo braku nawet najbardziej
elementarnych opcji, program jest szeroko
używany przez grafików różnych maści.
Jest to spowodowane tym, że program
udostępnia chyba najwięcej (na oko jakieś
20%) możliwości graficznych Atari, spośród
wszystkich innych programów graficznych.
Pomysł, aby nie tylko zmieniać kolory co
linię, ale również w jej środku, a ponadto
dodać pełnię możliwośći PMG, oddzielne dla
każdego ghosta kolory i szerokości,
priorytety i inne zabawki, jest wspaniały.
Naprawdę wielkie brawa dla Johna Harrisa.
Ach gdyby nie ta zapierająca dech obsługa.
Program niestety posiada również inną
wadę, ujawniającą się niestety najpóźniej,
bo już po narysowaniu całego obrazka.
Do programu mianowicie nie dołączono
procedury, którą można by umieścić we
własnym programie, aby pokazać w nim
własny obrazek narysowany w GED-zie. Tą
niedogodnością jakiś czas temu zaciekawił
mnie Dracon/USG/Taquart. Poprosił mnie
mianowicie (po tym jak odmówił mu Konop i
paru innych koderów) o napisanie takiej
procedury, gdyż potrzebował jej do
swojego slideshowu. Po przejrzeniu GED-a
za pomocą wszystkich dostępnych mi
debuggerów (z których każdy niestety
pokazywał to samo) zabrałem się do pracy.
Oto wynik moich poszukiwań. (Pełny tekst
programu znajduje się w zarchiwizowanym
pliku jako GEDVIEW.ASM.)
Dane program trzyma od adresu $5330,
do adresu $7F4F. Zapisywane jest to
jednym ciągiem w formacie DOS-owym to
znaczy z bajtami $FFFF, $5330, $7F4F na
początku.
Zmieniając adres danych można zmieniać
tylko pierwszą cyfrę, gdyż Antic ma głupi
zwyczaj dane obrazka pobierać tylko z
czterech kilobajtów.
Kilka linii przed początkiem obrazka
zaczyna się przerwanie. Jest ono
docyklowane z dokładnością do 0.001 cykla,
tak więc należy zwracać uwagę na to, że:
Mój program został przystosowany do
umieszczenia na początku strony. Wszelkie
zmiany tego położenia, a także wszelkie
zmiany w programie mogą zmienić położenie
pętli umieszczonych w przerwaniu. Pętla,
której początek i koniec znajdują się na
dwu różnych stronach może znaleźć się na
jednej stronie, a tym samym rozkaz skoku
na początek pętli (bpl) będzie działać o 1
cykl krócej. Należy również uważać na to,
że display list musi znaleźć się cały w
jednym kilobajcie. Ponadto zaraz za
programem należy zostawić 10KB wolnego,
gdyż umieszczany jest tam program
przerwania generowany dopiero po
uruchomieniu mojej procedury.
Oto skrócony opis programu, dla tych,
którzy chcieliby poznać sposób, w jaki
pokazuje się obrazki z GED-a.
Najpierw opis danych:
Osiem tablic po 200 bajtów zawiera
dane zmian kolorów itp. robionych co linię:
- tb2, tb3, tb4, tb5, tb6, tb7, tb8, tb9 dane
ośmiu zmian kolorów w linii, kolejno:
kolor 1, 2, 3, 1, 2, 3, 1, 2.
Oprócz tych zmian można dokonywać
również co linię jednej ze zmian w ghostach
(kolor, szerokość itp.) lub koloru tła.
Wartości tych zmian zawiera tablica tb0, zaś
komórki, które trzeba zmieniać tablica tb1.
-dane- szesnaście komórek:
0,1,2,3
4
5
6
7
8
9,10,11,12
13
14
15
|
kolory wpisywane do $d012-$d015
szerokości playerów (po dwa bity od najstarszych wpisywane do $d008-$d00b)
szerokości missilów ($d00c)
priorytety ($d01b)
kolor missilów (do $d019)
kolor tła ($2c8 lub $d01a)
położenia poziome graczy (komórki od $d000 do $d003)
położenie poziome pierwszego missila, do pozycji następnych dodawana jest szerokość poprzedników
numer opóźnienia przerwania i tym samym miejsca zmiany kolorów. W GED-dzie ustawia się to klawiszami [,] i [.])
nieużywane.
|
-obr1,obr2- dane obrazka podzielone na
dwie części z powodu pewnej wady Antica.
A teraz opis kilku części programu:
lda >pmg-$300 pierwsze 3 strony nie są
sta $D407 używane, więc stąd ten adres.
lda <end Generuje początkowe
sta addr bajty umieszczane za
lda >end etykietą END. Najpierw
sta addr+1 na podstawie dane+14
lda dane+14 umieszczane są 4 bajty,
asl @ które nic nie robią, ale
asl @ dają różne opóźnienie.
adc #3 Owe czwórki bajtów
tax umieszczone są pod
ldy #3 etykietą proc3.
s1 lda proc3,x
sta (addr),y
dex
dey
bpl s1
Teraz adres jest zwiększany o 4:
lda <end+4
sta addr
lda >end+4
sta addr+1
i dalej będzie procedura generująca 200
razy prog. zmieniający kolory w każdej linii.
(Jest za długa aby ją tu umieszczać.)
Składa się ona ze zwykłego przepisania
wartości z tablic, tak aby przerwanie nie
marnowało czasu na długie rozkazy typu:
lda tb4+175
ale zadowalało się rozkazami typu:
lda #$16
(wartość $16 została wcześniej pobrana z
tablicy tb4+175). Zysk: 1 cykl.
Każdy fragment przerwania kończy się
rozkazem inc 0, które nie ma niczego robić,
ale tylko zająć 5 cykli, tak aby czas
tworzenia 1 linii przez Antic był równy
czasowi wykonywania tego fragmentu
przerwania przez procesor. Jednakże,
pamięć obrazka została podzielona na dwie
części i kiedy Anticowi podaje się do żarcia
tę drugą część (w dliście wygląda to jak:
dta b($4e),a(obr2)), to procesor ma o 2
pla cykle mniej czasu.
clc Należy więc zmienić ten
adc #1 rozkaz na lda 0, który
cmp #$66 zajmuje 3 cykle.
bne s4 Ten program rozpoznaje
pha właściwy wiersz i
dec addr+1 dokonuje drobnej zmiany
ldy #$fe (bajt $a5) w już wygene-
lda #$a5 rowanym fregmencie
sta (addr),y programu.
inc addr+1
pla
s4 cmp #$c8 a tu sprawdza, czy to już
bne s2 wszystkie linie.
ldy <proc3-proc2 z kolei tutaj
s5 lda proc2,y generowana jest
sta (addr),y procedura
dey wyjścia z
bpl s5 przerwania.
lda dane+5 Ten fragment programu
ldx #0 jest o tyle ciekawy, że
ldy #$ff wykorzystany jest tutaj
s6 iny nic nie robiący rozkaz
s7 lsr @ bit $4a. Kiedy jednak
bcc s9+1 wykonamy skok w bajt
lsr @ stanowiący operand $4a
bcc s8 to wykona się rozkaz
inx lsr @. Pozwala to znacznie
inx skrócić program. Polecam
inx tę sztuczkę każdemu.
inx Ten fragment akurat
s8 inx dokonuje ustawienia
inx położeń pocisków na
s9 bit $4a podstawie dane+5 oraz
inx ich szerokości. Ponieważ
inx to nieistotne część
pha programu wyrzuciłem:
...
...
pla (akurat tę zapisującą
cpy #3 już wartości) i zostawiłem
bne s6 wyjście z pętli.
Teraz rzecz najgorsza, czyli programy
pracujące w przerwaniach. Na początek
procedury przepisywane. (Patrz wyżej.)
-PROC1 to procedura wygenerowywana 200
razy. Była już o niej mowa wcześniej.
-PROC2 to procedura kończąca przerwanie.
-PROC3 zawiera kilka 4-bajtowych procedur
służących ustawieniu (z dokładnością do 1
cyklu) miejsca zmian kolorów. Kazda 4-ka
bajtów różni się czasem wykonywania.
-DL tu się zaczyna przerwanie. Zwykłe
ustawianie wartości itp. Jedyny ciekawy
fragment to:
ldx #11 ciekawy dlatego, że nic nie
dex robi. Chodzi tutaj jedynie o
bne *-1 przeczekanie trochę cykli
lda (0,x) aż sprawa nie przycichnie...
lda 0 tfu... co ja mówię!!!
end equ *
od tego miejsca wpisywane
są poszczególne procedury: 4 bajty wzięte
z PROC3, następnie 200*PROC1, a w końcu
PROC2.
Jak widziecie metoda pokazywania
obrazków stworzonych GED-em (gadem?)
jest dość prosta.
JASKIER/TAQUART