Tajemnice ATARI

MAPA PAMIĘCI


   W każdym komputerze prędzej, czy później spotykamy się z przerwaniami. Urządzenia firmy ATARI oczywiście nie są pod tym względem wyjątkiem. W nich także występuje cała gama przerwań, używanych do różnych celów przez system operacyjny oraz programy użytkowe. Przerwania, ogólnie rzecz biorąc, dzieli się na maskowalne (tzw. IRQ, z ang. Interrupt ReQuest), oraz niemaskowalne (NMI. z ang. Non-Maskable Interrupt). Podstawową różnicą pomiędzy nimi jest to, jak procesor może je potraktować. Przerwania maskowalne mogą zostać zignorowane przez jednostkę centralną dzięki rozkazowi SEI, a ten stan obojętności trwa dotąd, aż w programie pojawi się rozkaz CLI. Jak łatwo się domyślić, przerwania niemaskowalne nie mogą zostać przez procesor nie zauważone, chociaż w większości systemów istnieje możliwość zablokowania ich poprzez zapisanie odpowiednich rejestrów sprzętowych.

   Przerwanie VBLANK należy do grupy przerwań niemaskowalnych i jest najważniejszym spośród wszystkich przerwań, występujących w ATARI. Co oznacza nazwa VBLANK? Otóż oznacza ona przerwanie wygaszania pionowego, czyli zgłaszane wtedy, gdy strumień elektronów, 'rysujący' obraz na monitorze dociera do prawego dolnego rogu ekranu. Zasada jest prosta: komputer około 50 razy na sekundę tworzy obraz, rysując po kolei poziome linie na ekranie, od lewej do prawej strony. Po narysowaniu pewnej liczby takich linii (tzw. rozdzielczość pionowa komputera) cały proces zaczyna się od początku, ale wtedy układy sprzętowe (w tym wypadku ANTIC - koprocesor graficzny ATARI) zgłaszają ten fakt procesorowi, generując sygnał przerwania, którego nie może on nie zauważyć. Gwoli ścisłości należy dodać, że przez chwilkę po zakończeniu rysowania całego obrazu ekran monitora jest wygaszony, co usprawiedliwia nazwę przerwania VBLANK.

   Dwa kolejne słowa pamięci używane są jako wektory wskazujące adresy procedur, wywoływanych przez przerwanie wygaszania pionowego. Potrzebne są aż dwa adresy skoków, ponieważ obsługa tego wydarzenia przebiega w dwóch etapach, z których pierwszy jest wykonywany zawsze, natomiast drugi tylko wtedy, gdy system nie wykonuje akurat operacji krytycznych czasowo, o czym Informuje stan komórki CRITIC (adres 66, $42). Ograniczenie takie wynika z faktu, że wykonywanie procedur przerwań zajmuje trochę czasu, którego mogłoby zabraknąć np. na "dogadanie się" komputera z urządzeniami peryferyjnymi.

   W pierwszym etapie systemowej obsługi VBLANK zwiększane są wartości, zawarte w komórkach zegara systemowego (adres 18-20, $12-$14). obsługiwany jest tzw. "tryb przyciągania uwagi" (patrz adres 77, $4d) oraz licznik programowy nr 1.

   W drugim etapie obsługi przerwania wygaszania pionowego aktualizowane są liczniki o numerach od 2 do 5, w komórce CH (adres 764, $02fc) umieszczany jest kod naciśniętego klawisza oraz, co ważne, do rejestrów sprzętowych przepisywane są wartości z tzw. rejestrów-cieni.    Tu drobna uwaga: ponieważ niektóre z rejestrów sprzętowych ATARI wymagają odświeżania, to wartości, które powinny być do nich zapisywane przechowuje się w pamięci RAM i stamtąd też są one przenoszone do rejestrów sprzętowych. Wiedząc, że takie przenoszenie zachodzi podczas każdego przerwania VBLANK łatwo się domyślić, że nie ma większego sensu modyfikacja bezpośrednio rejestrów przypisanych układom komputera - i tak system zmienia je w zależności od cieni.

$0222, $0223 00546, 00547 VVBLKI

   Wektor pierwszej, tak zwanej natychmiastowej, fazy obsługi przerwania VBLANK.

$0224, $0225 00548, 00549 VVBLKD

   Wektor drugiej, tak zwanej opóźnionej, fazy obsługi przerwania VBLANK. Oczywiście nic nie stoi na przeszkodzie temu, aby zainstalować własną procedurę obsługi przerwania wygaszania pionowego, trzeba jedynie pamiętać o kilku, związanych z tym regułach. Przede wszystkim pamiętajmy, że nie jesteśmy sami, nie wolno nam postępować tak, jak zaleca większość "fachowców", którzy twierdzą, że obsługę opisywanego przerwania należy kończyć skokiem pod adres, odpowiednio, $e45f (faza pierwsza) lub $e462 (faza druga). Byłoby to niezłe rozwiązanie, ponieważ, o czym dotąd nie wspomniałem, systemowa procedura rozpoznania źródła przerwania odkłada na stos rejestry procesora, a wyżej wymienione procedury odtwarzają te rejestry w odpowiedniej kolejności, gdyby nie pewne ale. W pamięci komputera może znajdować się program rezydentny, który zainstalował własną procedurę obsługi przerwania VBLANK i jej wykonanie należy umożliwić. Na wszelki wypadek trzeba więc przy tworzeniu naszych procedur zapamiętać adresy, wskazywane przez wektory VVBLKI i WBLKD i kończyć własne procedury skokiem właśnie do nich. Jest to o tyle bezpieczne, że nawet jeśli żaden program nie zmodyfikował dotąd wektorów procedur obsługi przerwania, wykonamy skok pod adresy $e45f i $e462, zainicjowane przez OS podczas włączania komputera.

   W jaki sposób ustawić własne adresy procedur? Pytanie, wbrew pozorom, nie jest tak banalne, na jakie wygląda. Nie wystarczy po prostu wpisać w odpowiednie komórki pamięci adresów naszych procedur. Trzeba liczyć się z tym, że pomiędzy wpisaniem jednego i drugiego bajtu adresu może wystąpić przerwanie wygaszania pionowego. Oczywiście zostanie wywołana procedura obsługi, której adres nie został jeszcze prawidłowo ustawiony i system "pójdzie w maliny"...

   Rozwiązania są w tym wypadku dwa. Po pierwsze, można skorzystać z systemowej procedury ustawiania adresu przerwania VBLANK, o nazwie SETVBV (adres $e45c), która zatroszczy się o to, by nie zaszła opisana wyżej, makabryczna sytuacja. Oto. Jak to zrobić:

vvblkd equ $0224
setvbv equ $e45c

ustaw  lda vvblkd
       sta stary
       lda vvblkd+1
       sta stary+1      zapamiętaj adres
       lda #7           chodzi o WBLKD
       ldy <moja        młodszy bajt adresu
       ldx >moja        starszy bajt adresu
       jsr setvbv
* tu dalsza część programu
* ...
oddaj  lda #7
       ldy stary
       ldx stary+l
       jmp setvbv

moja   equ *
* ...
* tu procedura obsługi VBLANK
* zakończona rozkazem...
       jmp (stary)
stary  org *+2
       end

   Drugie rozwiązanie, to samodzielne ustawienie adresu tak, aby przerwanie nie "złapało" nas w połowie roboty:
clock  equ $14
vvblkd equ $0224

ustaw  lda vvblkd

       sta stary
       lda vvblkd+1
       sta stary+l      zapamiętaj adres
       lda clock
czekaj cmp clock
       beq czekaj       czekaj, aż się zmieni
       lda <moja
       sta vvblkd
       lda >moja
       sta vvblkd+1     ustaw nowy adres
* tu dalsza część programu
* ...
oddaj  lda clock
czeko  cmp clock
       beq czeko
       lda stary
       sta vvblkd
       lda stary+l
       sta vvblkd+1

moja   equ *
* ...
* tu procedura obsługi VBLANK
* zakończona rozkazem...
       jmp (stary)

stary  org *+2
       end
   Być może ten sposób nie jest tak elegancki, jak odwoływanie się do procedur systemowych, ale równie skuteczny. Dlaczego? Jak napisałem powyżej, podczas obsługi przerwania VBLANK system między innymi zwiększa trzybajtowy zegar systemowy, którego najmniej znaczący (tzn. zwiększany przez każde przerwanie wygaszania pionowego) bajt jest pod adresem 20 czyli $14. Wystarczy odczytać ten bajt i porównywać przechowaną wartość ze świeżo odczytaną dopóki są one równe, nie wolno nic zrobić. Kiedy wskazanie zegara się zmieni, oznacza to, że włanie skończyło się przerwanie VBLANK, a następne będzie dopiero za chwilę. Oczywiście, mówiąc "chwilę", mam na myśli czas, w którym procesor spokojnie zdąży podmienić wektor i nie należy się obawiać żadnych, nieprzewidzianych konsekwencji.

   W przerwaniu VBLANK można robić wiele interesujących rzeczy, np. obsługiwać animację, sprawdzać ruchy joysticka, czy też po prostu mrugać kursorem. Sposób jego wykorzystania zależy od inwencji programisty. Ja zaś chciałbym wspomnieć o jeszcze jednym zagadnieniu, związanym z przerwaniem wygaszania pionowego. Jeśli w programie, który piszemy, zmieniamy dynamicznie wygląd ekranu, warto synchronizować procedury wyświetlania z przerwaniem VBLANK, ponieważ zapobiegnie to efektowi mrugania wyświetlanego obrazu.

   I na koniec limity czasowe dla obu faz obsługi VBLANK. Etap pierwszy powinien trwać nie dłużej niż 3800 cykli maszynowych, drugi zaś nie dłużej niż 20000 cykli maszynowych. Dane te podaję za I. Chadwick "Mapping The Atari".

Jarosław Syrylak



Powrót na start | Powrót do spisu treści | Powrót na stronę główną

Pixel 2001