Artykuły

    Kurs Assemblera cz. 4

    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.

    Prg1:

          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ł.

    Prg2:

          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.

    Prg3 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)

    Prg4 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)

    Prg5 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 gości atari.area

    Momencik, uaktualniam...  

    Nie jesteś zalogowany. Tylko zarejestrowani i zalogowani użytkownicy mog± dodawać komentarze.

Lotharek.pl
Retronics
Sikor Soft

Szukaj

Wyszukiwarka przeszukuje zasoby atari.area, atariki oraz forum.

Twoliner

Momencik, uaktualniam...  .

Pamiętaj, żeby linki do Twolinera dodawać wyłącznie po skróceniu za pomocą serwisu tiny.pl. Jeśli coś Ciebie ominęło - skorzystaj z archiwum.

Network

konto

Nie jesteś zalogowany. Zaloguj się lub załóż konto

forum

Artykuły

Wywiady

Allegro

Jako, że Allegro.pl jest bardzo często odwiedzanym serwisem przez Atarowców, umiejscowiłem poniżej wyszukiwarkę produktów związanych z naszym kochanym Atari. Chcesz coś kupić - wystarczy wpisać w okienko poniżej.


Wystarczy wpisac czego szukamy i po chwili znajdujemy sie juz na Allegro.pl.