Efekciarskie Efekciki
W tym artykule będę opisywać sposoby na uzyskanie różnych efektów (głównie graficznych). Dziś zacznę od najprostszego, a mianowicie od sinus-scrolla. Przede wszystkim do stworzenia powyższego efektu wymagana jest znajomość (ass)emblera.
Zacznijmy od uzyskania efektu "fali", do którego potrzebne są:
- ekran graficzny (BASIC 8, ANTIC $F);
- Display List zorganizowany tak, aby każda linia miała długość 64 bajtów, np. $4F ekran, 4F ekran+$40, itd.;
- dowolny zestaw znaków (może być spod $E000);
- tablica sinusów o długości 256 bajtów, czyli jednej strony pamięci (sposób uzyskania w artykule "Total Trash");
- mnóstwo chęci oraz cierpliwości.
Gdy uzbroiliśmy się we wszystkie wspomniane akcesoria, możemy przystąpić do pracy. Najpierw napiszemy procedurkę rysującą "coś" (w tej chwili nie jest dla nas ważne, co będziemy rysować) na ekranie:
ldy #$00 * w komórkach adr, +1
lda #$AA * powinien znajdować
loop1 sta (adr),y * się adres dowolnej
tya * komórki na ekranie
clc
adc #$40
tay
bne loop1
Jeżeli DList jest dobrze zorganizowany,to powinniśmy zobaczyć pionowe paseczki o wysokości czterech linii.Teraz zajmijmy się rysowaniem znaków po tzw. "sinusie". Najpierw musimy zdefiniować zmienną o nazwie "licznik". Licznik ten będzie wskazywać pozycję pierwszego znaku w tablicy sinusów. Następnie przygotowujemy dwie tablice o długości 256 bajtów każda (długość ta ulegnie zmianie, ale o tym później). W pierwszej tablicy umieścimy młodsze adresy linii ekranu. Powinno to wyglądać mniej więcej tak : $00,$40,$80,$C0,...
W drugiej tablicy umieścimy starsze adresy tych samych linii. Teraz możemy przystąpić do rysowania znaku układającego się w kształt fali. Procedura wygląda mniej więcej tak:
ldx licznik * wg tablicy sinusów
ldy tabsin,x * pobieramy nr linii
lda tablica1,y * (od której zaczniemy
sta adr * rysować) i jej adres
lda tablica2,y * na ekranie
sta adr+1
ldy #$00 * następnie w miarę
lda $e010 * szybką procedurą
sta (adr),y * rysujemy "cudzysłów",
ldy #$40 * zestaw znaków
lda $e011 * znajduje się od $e000
sta (adr),y
ldy #$80
lda $e012
sta (adr),y
ldy #$c0
lda $e013
sta (adr),y
inc adr+1 * ponieważ narysowany
ldy #$00 * znak zajmuje na
lda $e014 * ekranie więcej niż
sta (adr),y * stronę musimy
ldy #$40 * zwiększyć adres na
lda $e015 * ekranie o jedną
sta (adr),y * stronę
ldy #$80
lda $e016
sta (adr),y
ldy #$c0
lda $e017 * tu procedura rysująca
sta (adr),y * znak kończy się
Jeżeli ktoś wie jak ta procedura rysuje na ekranie znak to może od razu przerzucić się na następną stronę...
Procedura ta miała za zadanie narysować na ekranie znak -"-, a ponieważ linie są długości 64 bajtów, to rejestr Y podczas przepisywania kolejnych bajtów zawierał: $00 dla pierwszej linii; $40 dla drugiej linii, czyli 64 bajty dalej; $80 dla trzeciej linii itd...
Teraz powinniśmy zwiększyć licznik o 1, czyli: inc licznik. Jeżeli będziemy wykonywać naszą procedurę co jedno przerwanie VBLanku, np. w ten sposób:
loop lda $14 *
cmp $14 * czekanie na wykonanie VBL
beq *-2 *
jsr rysuj
jmp loop
to nasz -"- będzie poruszać się w górę i w dół po sinusie.
Jeżeli to już nam działa to przejdźmy do rysowania fali złożonej z -"-. Definiujemy nową zmienną, czyli: counter. Jego początkową wartością będzie: $00. Poznaną wcześniej procedurę nazwijmy "rysuj". Teraz wykorzystajmy ją w następujący sposób:
fala lda counter
sta licznik
lda #$28 * ilość cudzysłowów
sta pomoc
petla jsr rysuj
dec pomoc
bne petla
Jeżeli procedura działa, to na ekranie powinien ukazać się rysunek fali złożonej z -"- i jeśli dopiszemy: inc counter lub dec counter oraz jeżeli całość będziemy wykonywać co VBL, to fala powinna się ruszać, czyli:
l0 lda $14
cmp $14
beq *-2
jsr fala
inc counter
jmp l0
Teraz powinniśmy zadbać oto, aby narysowaną wcześniej falę wyczyścić. Zasada jest prosta: narysować falę, zanim ANTIC zdąży ją wyświetlić, a następnie poczekać, aż ją wyświetli i dopiero wtedy ją wyczyścić. Można to zrobić tak:
k0 lda $14
cmp $14
beq *-2
jsr fala
k1 lda $d40b
cmp #nrliniikońcafali
bne k1
jsr czyść
inc counter
jmp k0
Procedura "czyść" będzie korzystać z tych samych danych i wygląda mniej więcej tak:
czysc lda counter
sta licznik
lda #$28
sta pomoc
czys jsr kasuj
dec pomoc
bne czys
rts
Jak łatwo zauważyć procedura "kasuj" będzie wyczyszczać dane poszczególnego znaku wg tablicy sinusów.
kasuj ldx licznik
ldy tabsin,x
lda tablica1,y
sta adr
lda tablica2,y
sta adr+1
ldy #$00 * podczas czyszczenia
lda #$00 * wystarczy zmieniać
sta (adr),y * rejestr Y, gdyż w A
ldy #$40 * będzie zawsze zero
sta (adr),y
ldy #$80
sta (adr),y
ldy #$c0
sta (adr),y
inc adr+1
ldy #$00
sta (adr),y
ldy #$40
sta (adr),y
ldy #$80
sta (adr),y
ldy #$c0
sta (adr),y
Teraz fala nie powinna pozostawiać żadnych śladów.
Gdy już opanowaliśmy (a raczej zrozumieliśmy) poruszanie falą, przejdźmy do falowania tekstem. O ile dobrze pamiętam rysowaliśmy tylko literę -"- pobierając dane bezpośrednio z zestawu znaków (adres $e010). Niestety takie pobieranie wyglądu litery jest zbyt prymitywne, więc skomplikujmy sobie sprawę zmieniając organizację zestawu znaków. Załóżmy, że zestaw zawiera 256 znaków. Daje to 8 stron pamięci, czyli 2 KB. Jak są zorganizowane te znaki wiedzą wszyscy, my natomiast to zmienimy. Powiedzmy, że w rejestrze X mamy nr litery (np. $21 = "A"). Co robiliśmy standardowo, aby uzyskać jej wygląd?
adres = X * 8 + początek zestawu
ldy #$00
lda (adres),y
sta pierwszybajt
My skomplikujemy sprawę i postąpimy następująco:
lda pierszebajty,x
sta pierwszybajt
lda drugiebajty,x
sta drugibajt
Prawda, że szybkie? Mamy wygląd litery bez liczenia jej adresu oraz bez zmiany rejestru Y. I to właśnie wykorzystamy. Trzeba sobie jednak przygotować zestaw tak, aby składał się z ośmiu części, każda po 256 bajtów, czyli po stronie:
- pierwsza strona, to pierwsze bajty wyglądu wszystkich znaków;
- druga strona, to drugie bajty wyglądu wszystkich znaków itd.
Procedurę zmieniającą zestaw standardowy na nasz pozostawiam jako ćwiczenie zgrzanym umysłom.
Teraz procedura rysująca znak będzie wyglądać tak:
rysuj ldx licznik
ldy tabsin,x
lda tablica1,y
sta adr
lda tablica2,y
sta adr+1
ldy liczniktekstu
ldx tekst,y * tekst w kodach
ldy #$00 * ekranowych (of
lda strona1,x * course!)
sta (adr),y
ldy #$40
lda strona2,x
sta (adr),y
ldy #$80
lda strona3,x
sta (adr),y
ldy #$c0
lda strona4,x
sta (adr),y
inc adr+1
ldy #$00
lda strona5,x
sta (adr),y
ldy #$40
lda strona6,x
sta (adr),y
ldy #$80
lda strona7,x
sta (adr),y
ldy #$c0
lda strona8,x
sta (adr),y
No i koniec całej filozofii. Oczywiście nie powinniśmy zapomnieć o zadeklarowaniu zmiennej "liczniktekstu" oraz o samym tekście, np. tekst dta 'Ala ma kota'
Teraz "Ala ma kota" powinno falować po sinusie.
Co nam teraz pozostało, to skrolowanie (od filmu "Krol"). Włączamy przesuw poziomy w DLiście oraz cyklicznie zmieniamy rejestr HSCROL ANTIC-a - $D404 (to powinien umieć każdy). To co otrzymamy nazywam żelibomem wzdłużnym...
Teraz tylko powinniśmy rysować sinus - scrolla niezależnie od $D404, a licznik tekstu musimy zwiększać o jeden po zliczeniu $D404 do zera.
Ten "skromny opis" chyba powinien wystarczyć, a jeśli jest w nim jakaś niejasność, to sami dojdźmy jak należy to zrobić, żeby mieć radość z uwieńczonego sukcesem grzania kopary.