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ą:

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:

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.

HEJ!!!
Soused Teat