atari.area
twoje polskie źródło informacji o Atari

Kurs Assemblera cz. 4

Autor: TeBe / MadTeam

Po długiej przerwie spowodowanej zmasowanym atakiem wirusów kurs powraca .

Jak dotąd nie omawialiśmy struktury programu dla Antica (układ generujący obraz), zapoznamy się z nim na podstawie przykładów.

Teraz jednak fragment z książki Wojtka Zientary 'Mapa pamięci Atari XL/XE' na temat ANTIC-a.

TWORZENIE OBRAZU

Tworzeniem obrazu na monitorze zajmuje się w komputerach Atari specjalizowany układ scalony - ANTIC (Alphanumeric Television Interface Controller). Jest to specjalnie zaprojektowany dla Atari mikroprocesor, który posiada własny zestaw rozkazów i własny program. Według tego programu ANTIC pobiera z pamięci komputera dane umieszczone tam przez jednostkę centralną (procesor 6502) i po odpowiedniej interpretacji przesyła je do monitora.

Obraz telewizyjny generowany przez ANTIC jest jednak monochromatyczny. Kolory są dodawane przez inny układ specjalny - GTIA (Graphics Television Interface Adaptor), który także został zaprojektowany specjalnie dla Atari. Poza kolorem GTIA tworzy jeszcze ruchome obiekty ekranowe zwane popularnie duszkami, a według nomenklatury Atari - grafiką graczy i pocisków (PM6 - Player/Missile Graphics).

Spośród układów graficznych stosownych w komputerach domowych ANTIC wyróżnia się dwoma cechami. Przede wszystkim może bezpośrednio korzystać z pamięci komputera poprzez tzw. DMA (Direct Memory Access). Odciąża więc w ten sposób procesor centralny, co pozwala znacznie przyspieszyć jego pracę. Ponadto ANTIC posiada kompletną 16-bitową szynę adresową, dzięki czemu ma dostęp do całych 64KB pamięci. Umożliwia to umieszczenie danych dla obrazu oraz programu ANTIC-a w dowolnym miejscu pamięci.

Przed przejściem do dalszego opisu trzeba wiedzieć, jak wygląda obraz telewizyjny tworzony przez ANTIC. 0braz ten jest wyświetlany na ekranie przez wiązkę elektronów poruszającą się poziomo od lewej do prawej krawędzi ekranu (patrząc od strony użytkownika) i tworzącą jedną linię ekranu. Wiązka jest wygaszana na czas przejścia do początku nowej linii - ten okres nazywamy synchronizacją poziomą. Po utworzeniu całego obrazu wiązka jest wygaszana na czas przejścia z prawego, dolnego rogu ekranu do lewego, górnego. Nazywa się to synchronizacją pionową. Cała operacja powtarza się co 1/50 sekundy, a więc 50 razy na sekundę.

Pozioma wielkość linii ekranu jest mierzona w specjalnych jednostkach zwanych cyklami koloru. Jest to czas wykonywania przez procesor 6302 połowy cyklu maszynowego. Pełna linia ekranu ma 228 cykli koloru, co pozwala na przedstawienie 456 pojedynczych punktów, a pełny obraz zawiera 310 linii (w systemie PAL). Jednak tak utworzony obraz nie mieściłby się w całości na ekranie telewizora. Aby uniknąć utraty części informacji, obraz tworzony przez ANTIC ma nieco ograniczone wymiary.

Maksymalna wielkość obrazu generowanego przez ANTIC może wynosić 216 linii, ponieważ na więcej nie wystarcza czasu. Utworzenie większej liczby linii spowoduje "zerwanie" synchronizacji czyli pionowe przesuwanie się obrazu. Aby górna krawędź obrazu nie wychodziła poza ekran, w górnej części ANTIC tworzy 24 linie puste. Pozostają więc 192 linie i taka właśnie jest maksymalna rozdzielczość pionowa obrazu. Można ją nieco zwiększyć przez zmniejszenie liczby pustych liny i zwiększenie liczby linii obrazu, lecz suma wszystkich linii nigdy nie może przekraczać 216.

Także w poziomie nie jest wykorzystywana cała długość linii. W tym przypadku możliwe są jedynie trzy rozwiązania. Wyświetlana linia obrazu może posiadać 128, l60, 192 cykle koloru. Normalnie używany jest obraz o szerokości 160 cykli koloru, co daje 320 punktów ekranu. Zmiana szerokości linii jest dokonywana przez zmianę zawartości odpowiedniego rejestru ANTIC-a i programista nie może jej ustalić dowolnie.

Pozostaje jeszcze wyjaśnienie różnicy między linią ekranu i linią obrazu oraz między punktem ekranu i pixelem (punktem obrazu). Wszystko to, co zostało napisane wyżej dotyczy linii i punktów ekranu, ponieważ stanowią one podstawowe elementy ekranu (niezależne od komputera). Natomiast najmniejszy element obrazu (PICture Element = pixel), na którego wygląd może wpływać programista zależy od wybranego trybu graficznego. Ogólnie można powiedzieć, że linia obrazu składa się z jednej lub kilku linii ekranu, zaś pixel z jednego lub kilku punktów ekranu.

ANTIC posiada kilkanaście rejestrów, które sterują jego pracą. Poprzez zmianę ich zawartości można wpływać na wygląd obrazu. Najważniejszym rejestrem jest DMACTL (DMA ControL - $D400) kontrolujący dostęp ANTIC-a do pamięci komputera. Bity 6 i 7 tego rejestru są niewykorzystane, a znaczenie pozostałych jest następujące:

Bit 5 włącza (gdy jest ustawiony) bezpośredni dostęp ANTIC-a do pamięci w celu czytania programu. Skasowanie tego bitu uniemożliwia więc wyświetlanie obrazu pomimo tego, że znajduje się on w pamięci.

Bity 2-4 są wykorzystywane do sterowania grafiką graczy i pocisków.

Bity 0 i 1 regulują dostęp ANTiC-a do pamięci w celu odczytu danych obrazu. Gdy oba są równe zero, to ANTIC nie może odczytywać danych i nie wyświetla obrazu. Inny kombinacje ustalają szerokość wyświetlanego obrazu: 01 - obraz wąski (128 cykli koloru), 10 - obraz normalny (160 cykli koloru) i 11 - obraz szeroki (192 cykle koloru).

Podczas wykonywania programu często zachodzi konieczność przeprowadzenia jakiejś operacji (np. zmiany koloru) między liniami ekranu, a nie w trakcie tworzenia linii. Pomocny jest w tym rejestr WSYNC (Wait for SYNChronisataon - $D40A). Wpisanie dowolnej wartości do tego rejestru powoduje zatrzymanie pracy CPU (6502) do zakończenia tworzenia na ekranie aktualnej linii.

Także licznik linii ekranu VCOUNT (Vertical COUNT - $D40B) jest zwykle wykorzystywany podczas przerwań DLI. Zawiera on numer aktualnie tworzonej linii ekranu podzielony przez dwa. Podczas tworzenia obrazu VCOUNT zlicza więc od O do 155.

Stosunkowo najrzadziej wykorzystywane są dwa następne rejestry - LPENH (Light PEN Horizontal - $D40C) i LPENV (LPEN Vertical). Wskazują one aktualną pozycję pióra świetlnego na ekranie. Rejestr LPENH zawiera numer cyklu koloru (od 0 do 227), a LPENV numer linii podzielony przez dwa (jak VCOUNT).

PROGRAM ANTIC-A

ANTIC tworzy obraz według programu zawartego w pamięci RAM komputera, oznaczanego skrótem DL (Display List). Adres tego programu jest wpisywany do wektora DLPTRS (Display List PoinTeR Shadow register), a następnie podczas przerwania synchronizacji pionowej VBLK (w tym czasie obraz nie jest generowany) przepisywany do DLPTR.

Program ANTIC-a jest układany przez system operacyjny i zapisywany w pamięci podczas procedury otwarcia ekranu (SCOPN) dla każdego trybu program ANTTC-a jest inny, ale jest tylko jeden. Użytkownik może ingerować w jego treść, aby mieszać między sobą różne tryby oraz dla uzyskania innych specjalnych efektów.

ROZKAZY ANTIC-A

Aby zmieniać program ANTIC-a trzeba przede wszystkim znać kody jego rozkazów i ich znaczenie. Wszystkie rozkazy, którymi dysponuje ANTIC, można podzielić na trzy zasadnicze grupy: rozkazy tworzenia pustych linii, rozkazy skoków i rozkazy tworzenia linii trybu. Rodzaj rozkazu jest rozpoznawany według czterech młodszych bitów. Cztery starsze bity służą do modyfikacji podstawowego rozkazu.

We wszystkich rozkazach ustawienie najstarszego bitu powoduje wywołanie przez ANTIC (po wykonaniu rozkazu) przerwania niemaskowalnego. Przerwanie to nazywane jest przerwaniem programu ANTIC-a (DLI - Display List Interrupt). Nie należy przez to rozumieć, że przerywany jest program ANTIC-a, lecz, że wywołuje on przerwanie. Po otrzymaniu żądania przerwania DLI procesor wykonuje procedurę przerwania, której adres znajduje się w rejestrze DLIV (DLI Vector - $0200).

Rozkazy tworzenia pustych linii mają cztery młodsze bity skasowane, są więc postaci $x0. Pozostałe bity (4-6, bo bit 7 sygnalizuje przerwanie DLI) zawierają liczbę tworzonych pustych linii zmniejszoną o jeden. Pełna lista rozkazów tworzących puste linie jest następująca:

                      bez DLI           z DLI
1 pusta linia           $00              $80
2 puste linie           $10              $90
3 pusta linie           $20              $A0
4 puste linie           $30              $80
5 pustych linii         $40              $C0
6 pustych linii         $50              $D0
7 pustych linii         $60              $E0
8 pustych linii         $70              $F0

Rozkazy skoków mają najmłodszy bit równy jeden, są więc postaci $x1. Bity 4 i 5 są niewykorzystane, zaś bit 6 określa rodzaj skoku. Gdy bit 6 jest skasowany, to tworzona jest jedna pusta linia, a dwa następne bajty programu przepisywane są do licznika programu w kolejności LSB/MSB. Powoduje to wykonywanie dalszej części programu od wskazanego adresu, czyli po prostu skok bezwzględny (JMP). Rozkaz ten jest podobny do rozkazu JMP procesora 6502.

Gdy bit 6 jest ustawiony, to ANTIC wykonuje te same czynności, lecz dalsza realizacja programu jest zatrzymywana, aż do synchronizacji pionowej. Jest to więc skok z oczekiwaniem na synchronizacje VBLK (JVB) i musi on występować na końcu programu ANTIC-a (i tylko tam).

Kody rozkazów skoku przedstawia poniższa tabela:

                      bez DLI           z DLI
JMP                     $01              $81
JVB                     $41              $C1

Rozkazy tworzenia linii trybu zawierają w czterech młodszych bitach numer trybu (od $02 do $0F), który określa sposób interpretacji danych z pamięci obrazu. Chodzi tu oczywiście o numery trybów ANTIC-a, które są inne niż numery stosowane przez OS. Wszystkie numery trybów w tym rozdziale oznaczają tryby ANTIC-a, o ile nie zostało specjalnie zaznaczone, że chodzi o tryb OS. Pozostałe cztery bity oznaczają modyfikacje rozkazu. Znaczenie bitu 7 (DLI) zostało już opisane, teraz kolej na pozostałe modyfikacje.

  • Bit 4 (HSC - Horizontal SCrolling) oznacza, gdy jest ustawiony, włączenie poziomego przesuwu tworzonej linii obrazu.
  • Bit 5 (VSC - Vertical SCrolling) oznacza gdy jest ustawiony, włączenie pionowego przesuwu tworzonej linii obrazu.
  • Bit 6 (LMS - Load Memory Scan) powoduje, qdy jest ustawiony przepisania dwóch następnych bajtów programu do licznika pamięci obrazu. Licznik obrazu wskazuje ANTIC-owi miejsce w pamięci, z którego ma on pobrać dane obrazu. Ta modyfikacja rozkazu jest bardzo ważna i wymaga szerszego omówienia. ANTIC po rozpoznaniu rozkazu tworzenia linii pobiera z pamięci obrazu odpowiednią liczbę bajtów (zależną od trybu) i po zinterpretowaniu wyświetla na ekranie. Pobieranie danych dla następnej linii rozpoczyna się od następnego bajtu po ostatnio odczytanym. Trzeba więc na początku programu odpowiednio ustawić adres tych danych i to z dwóch powodów. Po pierwsze dlatego, aby ANTIC wiedział skąd ma pobierać dane. Po drugie dlatego, że program ANTIC-a jest wykonywany w całości 50 razy na sekundę i po pobraniu danych dla jednego obrazu, dane dla następnego byłyby pobierane z innego miejsca pamięci.

Licznik obrazu ma specyficzną konstrukcję, która wpływa na sposób jego działania. Posiada on szesnaście bitów ustalanych przez wpisanie adresu odczytanego z programu ANTIC-a. Podczas pobierania danych z pamięci zmieniane jest jednak tylko 12 młodszych bitów. Ogranicza to zakres działania licznika do bloku 4 KB. Jeżeli dane obrazu zajmują więcej niż 4KB, to licznik musi być ponownie ustawiony. W przeciwnym razie po osiągnięciu końca bloku 4KB następne dane będą pobierane z początku tego samego bloku. Trzeba przy tym uważać, aby dane żadnej linii obrazu nie przekraczały granicy bloku, gdyż nie można zmienić stanu licznika w środku tworzonej linii. Sytuacja taka występuje w trybach E i F. Normalnie rozkaz LMS występuje w programie ANTIC-a razem z rozkazem tworzenia pierwszej linii obrazu i razem z rozkazem tworzenia pierwszej linii okna tekstowego (jeśli ono jest).

Poniższe tabele zawierają kody wszystkich rozkazów ANTIC-a tworzących linie trybu.

                      Bez przerwania DLI                
             -    HSC    -    HSC    -    HSC    -    HSC
modyfikacje  -     -    V5C   VSC    -     -    VSC   VSC
             -     -     -     -    LMS   LMS   LMS   LMS
tryb                                           
       2    $02   $12   $22   $32   $42   $52   $62   $72
       3    $03   $13   $23   $33   $43   $53   $63   $73
       4    $04   $14   $24   $34   $44   $54   $64   $74
       5    $05   $15   $25   $35   $45   $55   $65   $75
       6    $06   $16   $26   $36   $46   $56   $66   $76
       7    $07   $17   $27   $37   $47   $57   $67   $77
       8    $08   $18   $28   $38   $48   $58   $68   $78
       9    $09   $19   $29   $39   $49   $59   $69   $79
       A    $0A   $1A   $2A   $3A   $4A   $5A   $6A   $7A
       B    $0B   $1B   $2B   $3B   $4B   $5B   $6B   $7B
       C    $0C   $1C   $2C   $3C   $4C   $5C   $6C   $7C
       D    $0D   $1D   $2D   $3D   $4D   $5D   $6D   $7D
       E    $0E   $1E   $2E   $3E   $4E   $5E   $6E   $7E
       F    $0F   $iF   $2F   $3F   $4F   $5F   $6F   $7F
                   Z przerwaniem DLI
             -    HSC    -    HSC    -    HSC    -    HSC
modyfikacje  -     -    VSC   VSC    -     -    VSC   VSL
             -     -     -     -    LMS   LMS   LMS   LMS
tryb                                          
       2    $82   $92   $A2   $B2   $C2   $D2   $E2   $F2
       3    $83   $93   $A3   $B3   $C3   $D3   $E3   $F3
       4    $84   $94   $A4   $B4   $C4   $D4   $E4   $F4
       5    $85   $95   $A5   $B5   $C5   $D5   $E5   $F5
       6    $86   $96   $A6   $B6   $C6   $D6   $E6   $F6
       7    $87   $97   $A7   $B7   $C7   $D7   $E7   $F7
       8    $88   $98   $A8   $B8   $C8   $D8   $E8   $F8
       9    $89   $99   $A9   $B9   $C9   $D9   $E9   $F9
       A    $8A   $9A   $AA   $BA   $CA   $DA   $EA   $FA
       B    $8B   $9B   $AB   $BB   $CB   $DB   $EB   $FB
       C    $8C   $9C   $AC   $BC   $CC   $DC   $EC   $FC
       D    $8D   $9D   $AD   $BD   $CD   $DD   $ED   $FD
       E    $8E   $9E   $AE   $BE   $CE   $DE   $EE   $FE
       F    $8F   $9F   $AF   $BF   $CF   $DF   $EF   $FF

STRUKTURA PROGRAMU ANTIC-A

Program ANTIC-a musi spełniać kilka warunków, aby jego wykonanie dało na ekranie pożądany efekt. Przede wszystkim musi koniecznie zawierać rozkaz LMS na początku oraz rozkaz JVB na końcu. Aby górna krawędź obrazu nie wychodziła poza ekran, przed rozkazami tworzenia linii trybu powinny znaleźć się rozkazy tworzenia pustych linii (może być ich mniej niż 24). Przykładowy program ANTIC-a tworzony przez system operacyjny jest przedstawiony poniżej.

START       $70    \          
            $70     > 3*8=24 puste linie
            $70    /   
            $4x    linia trybu + LMS     
            <SCRM  \adres pamięci obrazu
            >SCRM  /w kolejności LSB/MSB
            $0x    \
            $0x     |  
            ...     : linie trybu  
            $0x     |
            $0x    /
            $42    linia trybu 2 + LMS
            <TXTM  \ adres pamięci okna 
            >TXTM  / tekstowego (LSB/MSB)
            $02
            $02
            $02
            $41      JVB
            <START  \ adres początku    
            >START  /programu ANTIC-a

Oczywiście fragment programu dotyczący okna tekstowego występuje tylko wtedy, gdy to okno istnieje. Najkrótsze programy ANTIC-a są ustalane dla trybów 5 (tryb 13 OS) i 7 (2) bez okna tekstowego, mają one po 20 bajtów. Tryby E (15) i F (8) bez okna mają najdłuższe programy - po 202 bajty. Jak widać, czym większa rozdzielczość, tym dłuższy program ANTIC-a.

KOLORY

Informacja o obrazie utworzona przez ANTIC przed wysłaniem do monitora jest jeszcze uzupełniana informacją o kolorze. Ta czynność jest wykonywana przez GTIA. Do realizacji tego zadania GTIA wykorzystuje dziewięć rejestrów, w których przechowywane są wartości kolorów. Znajdują się one w obszarze od $D012 do $DO1A, a ich rejestry-cienie od $02C0 do $02C8.

Wszystkie rejestry koloru maja jednakową strukturę. Cztery starsze bity zawierają numer barwy, a cztery młodsze stopień jasności. Ponieważ bit O nie jest odczytywany, to mamy do dyspozycji l6 barw w 8 jasnościach. Daje to razem 128 kolorów, a we wszystkich informacjach o Atari jest napisane, że można wybierać z palety 256 kolorów. Skąd ta różnica? Obie podane wyżej informacje są prawdziwe. Rzeczywiście do wyboru jest l28 kolorów. Natomiast szczególna interpretacja danych obrazu w trybie 9 (tryb systemu operacyjnego) pozwala na uzyskanie szesnastu zamiast ośmiu stopni jasności i teraz można wybierać z 256 kolorów. Tak więc we wszystkich trybach mamy dostępne 128 kolorów, a tylko w trybie 9 (OS) - 256.

Teraz wypada przedstawić kolory, które odpowiadają różnym wartościom umieszczanym w rejestrach koloru. Ze stopniami jasności sprawa jest prosta wartość najmniejsza ($00) oznacza kolor najciemniejszy, a największa ($0F) - najjaśniejszy. Znacznie trudniejsze jest przedstawienie barw. Przede wszystkim dlatego, że barwa zależy także od jasności, np. barwa $00 z jasnością $00 to kolor czarny, zaś z jasnością $0E - biały. Poza tym kolory w dużym stopniu zależą od konkretnego egzemplarza monitora, nie mówiąc już o systemie telewizyjnym (wszystkie źródła podają barwy w systemie NTSC, a nie PAL). Po przedstawieniu tych zastrzeżeń, czas na wykaz barw (x oznacza jasność).

kod kolor
$0x szary
$lx złoty
$2x pomarańczowy
$3x czerwony
$4x różowy
$5x purpurowy
$6x fioletowy
$7x niebieski zimny
$8x niebieski
$9x błękitny
$Ax turkusowy
$Bx niebiesko-zielony
$Cx zielony
$Dx żółto-zielony
$Ex pomarańczowp-zielony
$Fx żółty

Na zakończenie jeszcze jedna ważna informacja. Podczas tworzenia obrazu kolor jest określany zawsze według rejestru sprzętowego. Ten kolei jest zapisywany wartością z rejestru-cienia podczas każdego przerwania VBLK, czyli 50 razy na sekundę. Po zmianie koloru w rejestrze-cieniu kolor na ekranie zmieni się więc najpóźniej po 1/50 sekundy. Jeśli zmiana zostanie dokonana w rejestrze sprzętowym, to kolor zmieni się natychmiast lecz nie da się tego zobaczyć. Najpóźniej bowiem po 1/50 sekundy kolor zostanie odtworzony według starej wartości z rejestru-cienia. Gdy jednak kolor w rejestrze sprzętowym będzie zmieniany podczas każdego tworzenia obrazu (np. przez procedurę przerwania DLI), to zmiana będzie trwała, ale tylko w tej części obrazu, która jest tworzona po przerwaniu. Podczas przerwania VBLK stara wartość zostanie odtworzona i część obrazu do ponownego wywołania procedury DLI będzie miała stary, kolor. Jest to najczęstsze zastosowanie przerwań DLI.

To tyle na temat ANTIC-a, dowiemy się teraz jak możemy modyfikować nasz program w czasie rzeczywistym, porównamy liczby 2bajtowe(word), wyświetlimy 8KB grafikę, poscrolujemy i pofalujemy text.

Pamiętacie że kompilacja zamienia nasz assemblerowy program na ciąg liczb, które są odpowiednikami zastosowanych mnemoników, np.:

lda #$70    ;oznacza bezwzględny rozkaz załadowania do akumulatora wartości $70
            ;po kompilacji mamy $a9 $70

Teraz dorzucimy etykiete 'test':

Test  lda #$70    ;czyli pod adresem 'test' mamy wartość $a9
                  ;pod adresem 'test+1' wartość $70

Jak sprawić aby zamiast $70 było $10:

lda #$10
sta test+1

Prawda, że zrozumiałe .

Po tym przydługim wstępie zabieramy się za przykłady.

Prg 1.

      opt h+          ;generuj plik z naglówkiem, naglówek jest 6-bajtowy, ma postac:
                      ; dta b($FF),b($FF),l(start),h(start),l(start+end-1),h(start+end-1)
                      ;opt h- wygeneruje plik bez naglowka
      org $8000       ;adres pod którym znajdzie sie nasz program
      ldx <antic      ;mlodszy bajt adresu ANTIC do rejestru X
      ldy >antic      ;starszy bajt adresu ANTIC do rejestru Y
      stx 560         ;bajt z rejestru X wpisz pod adres 560
      sty 561         ;bajt z rejestru Y wpisz pod adres 561

; w bajtach 560, 561 znajduje sie cien adresu pod którym uklad Antic znajdzie dla
; siebie programik, który opisuje wyglad wyswietlanego obrazu
; podczas przerwania VBL (co 1 ramke, czyli 1/50 sekundy) wartosci spod 560, 561
; zostana przepisane do $d402, $d403

petla jmp petla       ;petla, tak zeby nie wrócil do DOS'a
antic dta b($70),b($70)      ;$70 - oznacza 7 pustych linii
      dta b($42),a(obraz)
      dta d'"""""""""""""""' ;kod " to tryb 2 - znakowy
      dta b($41),a(antic)    ;$41 czyli czekaj na koniec ramki i wtedy zacznij od adresu...
obraz dta d'To jest text przykladowy'

end

W/w programik wyświetli nam obraz w trybie 2, oraz nasz tekst, chyba proste .

Niektórzy pewnie chcieliby trochę poanimować. Ten programik sprawi ze nasz txt będzie falował.

Prg 2.

      opt h+          ;generuj plik z naglówkiem, naglówek jest 6-bajtowy, ma postac:
                      ;dta b($FF),b($FF),l(start),h(start),l(start+end-1),h(start+end-1)


      org $8000       ;adres pod którym znajdzie sie nasz program


      ldx <antic      ;mlodszy bajt adresu ANTIC do rejestru X
      ldy >antic      ;starszy bajt adresu ANTIC do rejestru Y
      stx 560         ;bajt z rejestru X wpisz pod adres 560
      sty 561         ;bajt z rejestru Y wpisz pod adres 561

lop   ldy #0            ;tzn lda #0 = po kompliacji $a9 $00
      lda tablica,y
      sta f0            ;pierwsza linia z textem
      sec
      lda #$70    ;odejmujemy od $70, nastepne linie
      sbc f0      ;beda nieruchome
      sta f1
      lda tablica+8,y   ;animacja drugiej linii z textem
      sta f2
      lda 20      ;czekaj 1 ramke
      cmp 20
      beq *-2
      inc lop+1   ;zwiekszamy o 1
      lda lop+1
      cmp #28     ;sprawdzamy czy jest = 28
      bne lop     ;jesli nie to petl sie dalej
      lda #0      ;w przeciwnym razie wyzeruj i od poczatku
      sta lop+1
      jmp lop

antic dta b($70),b($70)         ;$70 - oznacza 7 pustych linii
      dta b($42),a(title),d'""'
f0    dta b($70)
      dta b($42),a(txt1)
f1    dta b($70)
f2    dta b($70)
      dta b($42),a(txt2)     
      dta b($41),a(antic) ;$41 czyli czekaj na koniec ramki i wtedy zacznij od adresu...

title   dta d'                                        '
        dta d'             TeBe presents              '
        dta d'                                        '
txt1    dta d'                Text 1                  '
txt2    dta d'                Text 2                  '

tablica dta b($10,$10,$10,$20,$30,$30,$40,$40,$50,$50,$50,$60,$60,$60,$70)
        dta b($70,$70,$60,$60,$60,$50,$50,$50,$40,$40,$30,$30,$20)
        dta b($10,$10,$10,$20,$30,$30,$40,$40)

end

Ten programik modyfikuje w czasie rzeczywistym program Antica na podstawie predefiniowanych danych 'tablica'. Analiza należy do Was.

Prg 3. Przykład falującego scrolla w high-res

         org $8000


obraz    equ $a150
obr1     equ 203
obr2     equ 205
znaki    equ $e000
hscrol   equ $d404
         ldx <antic
         ldy >antic
         stx 560
         sty 561
         lda #%00100010
         sta 559
         jsr a_obr1     ;obr1,obr1+1 = obraz
maz      ldx #3         ;czyscimy obszar 'obraz' - 768bajtow (3*256)
         ldy #0
         tya
m_1      sta (obr1),y
         dey
         bne m_1
         inc obr1+1
         dex
         bne m_1
         jsr ad_tex     ;tex+1,tex+2 = text (sprawdz procedurke 'ad_tex')
         lda #3
         sta scrol      ;scrol = 3
start    ldy #80
         lda adr_ek,y   ;mlodszy bajt adresu obrazu
         sta obr1
         lda adr_ek+1,y ;starszy bajt adresu obrazu
         sta obr1+1     ;adr_ek to tablica adresow okreslajaca ksztalt scrolla
         ldy #0
tex      lda $ffff,y    ;tutaj jest 'lda text,y', adres naszego scrolowanego tekstu
         pha
         and #$7f       ;tutaj obliczymy adres naszej literki w pamieci Atari
         lsr @
         lsr @
         lsr @
         lsr @
         lsr @
         clc
         adc >znaki     ;starszy bajt adresu zestawu znakow
         sta znak+2     ;znak opisany jest przez 8 nastepujacych po sobie bajtow
         pla
         and #$1f
         asl @
         asl @
         asl @
         sta znak+1     ;ok, w znak+1, znak+2 mamy adres 8 bajtowej paczuszki
                        ;opisujacej ksztalt znaku
znak     lda $ffff,y    ;to tutaj znak+1, znak+2 zmodyfikowalo adres
         sta (obr1),y   ;przepisujemy 8 bajtow na ekran (adres ekranu w obr1, obr1+1)
         lda #47        ;nasz ekran ma wlaczony poziomy scrol wiec ma szerokosc 48 bajtow
         jsr d_obr1
         iny
         cpy #8
         bne znak
         lda #3
         sta scrol      ;zmienna scrol znowu ustawiona na 3
przesuw  lda scrol
         sta hscrol     ;przepisujemy wartosc ze scrol do sprzetowego rejestru HSCROL
         jsr wait ;dzieki temu sprzetowo przesuwamy obraz w lewo o cykl koloru (4x)
         dec scrol
         bpl przesuw
         lda #1         ;ok, teraz musimy przepisac caly widoczny ekran w lewo
         sta licz
p_0      asl @
         tay
         lda adr_ek,y
         sta obr1
         lda adr_ek+1,y
         sta obr1+1
         lda adr_ek-2,y
         sta obr2
         lda adr_ek-1,y
         sta obr2+1
p_1      ldy #0
         lda (obr1),y
         sta (obr2),y
         ldy #48
         lda (obr1),y
         sta (obr2),y
         ldy #96
         lda (obr1),y
         sta (obr2),y
         ldy #144
         lda (obr1),y
         sta (obr2),y
         ldy #192
         lda (obr1),y
         sta (obr2),y
         ldy #240
         lda (obr1),y
         sta (obr2),y
         inc obr1+1
         inc obr2+1
         ldy #32
         lda (obr1),y
         sta (obr2),y
         ldy #80
         lda (obr1),y
         sta (obr2),y
         inc licz
         lda licz
         cmp #41
         bne p_0
         inc tex+1      ;zwiekszamy adres naszego scrola, bedzie wskazywal nastepna literke
         bne t_1
         inc tex+2
t_1      lda tex+1
         cmp <over      ;sprawdzamy czy koniec scrola, zwroccie uwage jak sie porownuje 
         lda tex+2      ;liczby 2bajtowe (word)
         sbc >over
         bcc run
         jsr ad_tex     ;ustawiamy adres na poczatek tekstu
run      jmp start
wait     lda 20         ;czekamy 1 ramke
q_1      cmp 20
         beq q_1
         rts
ad_tex   lda <text
         sta tex+1
         lda >text
         sta tex+2
         rts
d_obr1   sta hlp  ;dodawanko liczba 2bajtowa + 1bajt
         lda obr1
         clc
         adc hlp
         sta obr1
         bcc do_1
         inc obr1+1
do_1     rts
d_obr2   sta hlp
         lda obr2
         clc
         adc hlp
         sta obr2
         bcc do_1
         inc obr2+1
do_2     rts
a_obr1   lda <obraz
         sta obr1
         lda >obraz
         sta obr1+1
         rts
text     dta d'To jest tekst '
         dta d'probny moi mili ! No '
         dta d'i co mam tu pisac !'
         dta d' Moze to ze mecze sie z falujacym scrolem '
         dta d'i jeszcze go nie skonczylem.'
over     equ *
antic    dta b($70),b($70),b($70)
         dta b($70),b($70),b($70)
         dta b($5f),a(obraz)
         dta b($1f),b($1f),b($1f)
         dta b($1f),b($1f),b($1f)
         dta b($1f),b($1f),b($1f)
         dta b($1f),b($1f),b($1f)
         dta b($1f),b($1f)
         dta b($41),a(antic)
adr_ek   dta a($a150+147)
         dta a($a150+196),a($a150+245)
         dta a($a150+294),a($a150+295)
         dta a($a150+248),a($a150+201)
         dta a($a150+154),a($a150+107)
         dta a($a150+60),a($a150+13)
         dta a($a150+14),a($a150+63)
         dta a($a150+112),a($a150+161)
         dta a($a150+210),a($a150+259)
         dta a($a150+308),a($a150+309)
         dta a($a150+262),a($a150+215)
         dta a($a150+168),a($a150+121)
         dta a($a150+74),a($a150+27)
         dta a($a150+28),a($a150+77)
         dta a($a150+126),a($a150+175)
         dta a($a150+224),a($a150+273)
         dta a($a150+322),a($a150+323)
         dta a($a150+276),a($a150+229)
         dta a($a150+182),a($a150+135)
         dta a($a150+88),a($a150+41)
         dta a($a150+42),a($a150+91)
         dta a($a150+140),a($a150+189)
hlp      dta b(0)
licz     dta b(0)
scrol    dta b(0)
adres1   dta b(0),b(0)
adres2   dta b(0),b(0)

Prg 4. Wyświetlenie grafiki wiekszęj niż 4KB

W przypadku Antica należy zwrócić uwagę że może on zaadresować tylko 4KB danych. Aby wyświetlić 8KB obrazek musimy niejako kazać mu pokazać dwa 4KB obszary. 4KB=4096 / 40 = 102,4

Wiersz ma 40 bajtów w klasycznej szerokości obrazu, czyli w 4KB zmieścimy 102 linie. Obrazek wczytamy od adresu $X010, np. $a010, $2010, $8010, dzięki temu nie będziemy musieli dzielić grafiki na części, zostanie zachowana ciągłość.

Antic musi wyświetlić naszą grafikę od $X010 4KB i od $X010+$1000 4KB. W przypadku większych obrazków jak np. RIP, trzeba niestety dzielić grafikę na 4KB bloki.

Obr   equ $a010   ;adres z danymi obrazka


; tutaj procedurka
; która spowoduje ze antic wyswietli obraz,
; analogicznie jak w poprzednich przykladach


Ant equ *


    dta d'ppp'                   ;24 puste linie
    dta b($4e),a(obr)            ;1 linia
    dta d'................'      ;17
    dta d'................'      ;33
    dta d'................'      ;49
    dta d'................'      ;65
    dta d'................'      ;81
    dta d'................'      ;97
    dta d'.....'                 ;102 linie = 1 obszar 4KB
    dta b($4e),l(0),h(obr+$1000) ;103
    dta d'................'      ;119
    dta d'................'      ;135
    dta d'................'      ;151
    dta d'................'      ;167
    dta d'................'      ;183
    dta d'.........'             ;192 linie - cały obraz
    dta b($41),a(ant)

Prg 5. Animacja z buforowaniem

W naszych przyszłych graficznych efektach, które będą zajmowały więcej niż jedną ramkę zajdzie potrzeba buforowania wyświetlanych obrazów. Pierwszy obraz będzie pokazywał pierwszą fazę animacji, w tym samym czasie nasz program będzie wyliczał drugą fazę, gdy skończy pokażemy ją na drugim obrazie. Znowu wyliczamy, obraz2 ciągle jest wyświetlany, a my już liczymy trzecią fazę, którą pokażemy na obrazie1 i tak dalej.

Potrzebujemy dwa obszary pamięci o zadanej wielkości, np. $a000-$afff obraz1, $b000-$bfff obraz2. Czyli w sumie 2 obszary po 4KB.

ob1   equ $a000
ob2   equ $b000
frame equ $80


      org $8000


main  lda >ob1    ;obliczymy sobie wartosc, przy pomocy ktorej bedziemy
      eor >ob2    ;eor-owac ob1 i ob2, czyli przelanczac
      sta switch+1
      ldx <ant
      ldy >ant
      stx 560
      sty 561

petla lda >ob1    ;nasz parametr, starszy bajt adresu obrazu
      jsr czysc   ;czysci zadany obszar 4KB
      jsr oblicz  ;procedurka OBLICZ, cos tam liczy
      jsr pokaz   ;procedurka pokazujaca kolejne klatki
                  ;teraz pokaze obraz1
      lda >ob2    ;mieszamy w obszarze obrazu drugiego
      jsr czysc
      jsr oblicz
      jsr pokaz   ;pokazemy obraz2
      jmp petla

;----------

czysc sta hlp
      sta czy+2   ;zmodyfikuj bajt pod adresem czy+2
      ldx #16     ;czyli starszy bajt adresu obrazu
      ldy #0
      sty 20      ;zerujemy bajt, ktory VBL zwieksza o 1
      tya
czy   sta $ff00,y
      iny
      bne czy
      inc czy+2
      dex
      bne czy
      rts

;---

; wypelniamy ekrany po kolei wartosciami 0..255

;-

oblicz lda #0
       inc oblicz+1
       ldx #16
       ldy #0
       lda hlp
       sta czy+2
       lda oblicz+1
       jmp czy           ;skorzystamy z fragmentu procedurki 'czysc'

;--

pokaz  lda 20
       sta frame         ;tutaj ile ramek trwalo rysowanie tak na prawde
wait   lda 20
       cmp #32           ;max czekamy 32 ramki
       bne wait
       lda adr+1
switch eor #0
       sta adr+1
       rts

       org $0600   ;tutaj nasz programik dla Antica
                   ;adres powinien byc parzysty, inaczej moga wyjsc krzaczki, dziwaczki

ant   dta d'ppp',b($4e)
adr   dta a(ob2)              ;na poczatek pokazemy obraz2, bo liczymy na poczatku obraz1
      dta d'................'
      dta d'................'
      dta d'................'
      dta d'................'
      dta d'................'
      dta d'................'
      dta d'.....'
      dta b($41),a(ant)
hlp   brk

      org $2e0          ;adres startu programu po wczytaniu
      dta a(main)       ;do pamieci

end

Następnym razem zajmiemy się przerwaniami. Jeśli macie jakieś pytania, propozycje tematu napiszcie.


Komentarze (0)

Brak komentarzy. Bądź pierwszy!

Dodaj komentarz

Musisz się zalogować, aby dodać komentarz.