Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych.Autor: Wilf Rigter Tłumaczył z angielskiego: mgr Jerzy Wałaszek Wersja 1.0 - zakończono 9.I.2009, odwiedzono 5008 razy. Aktualizacja 18.07.2022
Uwaga: przy czytaniu poniższego artykułu zalecana
jest wiedza o sposobach |
©2009 mgr
Jerzy Wałaszek |
Gdy przypadkowe okoliczności połączą nowatorskie pomysły techniczne z ekonomicznym projektem i zapotrzebowaniem rynkowym na produkt, zawsze zdarzają się ciekawe rzeczy. W roku 1980 Sinclair nie zawitał jeszcze szeroko pod przysłowiowe strzechy i był bardziej znany być może za sprawą swojego zegarka cyfrowego i kalkulatora niż komputera osobistego ZX80. Jednakże doświadczenie rynkowe zdobyte na sprzedaży ZX80 oraz pojawienie się taniej technologii układów scalonych o dużej skali integracji olśniło go i dało mu możliwość wprowadzenia dostępnej dla wszystkich, łatwej w użyciu i masowo produkowanej wersji komputera ZX80, która posiadała arytmetykę zmiennoprzecinkową oraz stabilny obraz. Narodził się ZX81, a "reszta to historia".
Kluczem taniego projektu ZX81 było połączenie systemu tworzenia obrazu z ZX80, który wykorzystywał mikroprocesor Z80 do większości swoich zadań, z małym obwodem elektronicznym, dostępnym również dla ZX80, tworzącym tryb wyświetlania SLOW - jednoczesne obliczenia oraz generacja obrazu telewizyjnego. Gdy obwód ten został wstawiony do układu logicznego ULA, stał się on nie tylko tani w produkcji, lecz okazał się bardzo wszechstronny i z możliwościami wyświetlania obrazu wykraczającymi znacznie poza pierwotne cele jego twórców.
Standardowy ekran wideo dla ZX81 wyświetla 24 wiersze po 32 znaki. Każdy znak posiada wysokość 8 lini skanujących i szerokość 8 pikseli. Znaki do wyświetlenia są zlokalizowane w bloku pamięci zwanym DFILE. Zestaw 128 możliwych do wyświetlenia znaków zawiera 64 zwykłe (tzn. nie w negatywie) duże litery, cyfry, symbole i znaki graficzne oraz ich negatywy. Kody znakowe komputera ZX81 CHR$ 0-63, CHR$ 118 i CHR$ 128-191 są niestandardowe (nie ASCII). Pewien zbiór kodów jest stosowany również dla słów kluczowych, funkcji oraz rozkazów, lecz one zawsze są rozwijane do znaków drukowalnych przed ich wydrukiem w bloku DFILE.
Blok DFILE jest sformatowany poczynając od Sinclairowskiego odpowiednika znaku-CR (powrót karetki - ang. carriage return) o kodzie CHR$ 118, za którym następuje do 32 kodów znakowych, co jest powtarzane 24 razy, a na końcu znów umieszczany jest kod CHR$ 118.
początek DFILE: | CHR$ 118 | |
wiersz nr 0: | do 32 znaków | CHR$ 118 |
wiersz nr 1: | do 32 znaków | CHR$ 118 |
... | do 32 znaków | CHR$ 118 |
wiersz nr 22: | do 32 znaków | CHR$ 118 |
wiersz nr 23: | do 32 znaków | |
koniec DFILE: | CHR$ 118 |
Znak CHR$ 118 jest kodem instrukcji HALT mikroprocesora Z80 z powodów wyjaśnionych dalej w tym artykule. Pozostałe kody znaków są niedozwolone i jeśli zostaną załadowane do bloku DFILE, najprawdopodobniej spowodują krach systemu (pod symulatorem może się to nie zdarzyć, chyba że masz bardzo dobry symulator, który dokładnie emuluje sprzęt wideo ZX81 - np. eightyOne)..
Zwinięty blok DFILE jest używany w komputerach ZX81 posiadających pamięć RAM o pojemności 1KB lub 2KB w celu minimalizacji wymagań pamięciowych przez obraz. Jeśli na ekranie nic nie jest wyświetlane, to zwinięty blok DFILE składa się jedynie z 25 kodów CHR$ 118. Każdy wiersz jest odpowiednio rozwijany, gdy są drukowane w nim znaki. Powoduje to możliwość powstania błędu braku pamięci przy prostej próbie wyświetlenia czegoś na ekranie!
Jeśli ZX81 posiada 4KB lub więcej pamięci RAM, DFILE jest inicjowane na pełny rozmiar 24 wierszy po 32 znaki CHR$ 0 (spacja) oraz 25 znaków CHR$ 118 kończących każdy wiersz plus jeden na początku bloku.
Kody znaków nie są wy świetlane bezpośrednio lecz raczej używa się ich jako wskaźników adresowych w tablicy matryc znaków przechowywanej na końcu pamięci ROM. Bajty tych matryc są adresowane przez kombinację kodów znaków odczytanych z DFILE oraz układów ZX81 i ładowane do rejestru przesuwnego wideo, skąd trafiają do modulatora telewizyjnego przesyłającego obraz do telewizora. Bit 7 kodu znaku w DFILE jest wykorzystywany przez sprzęt tworzący obraz wideo do odwracania pikseli wyprowadzanych z rejestru przesuwnego do modulatora - jeśli jest ustawiony na 1 (kod znaku > 127), otrzymujemy negatyw matrycy znaku.
Obraz na ekranie powstaje ze strumienia bitowego pikseli wyprowadzanych z rejestru przesuwnego, który włącza i wyłącza strumień elektronów w lampie kineskopowej odbiornika telewizyjnego, gdy ten przebiega po powierzchni ekranu pokrytej wewnątrz luminoforem powodując zaświecanie i gaszenie odpowiednich punktów obrazu. W pełni rozwinięty blok DFILE z 24 wierszami po 32 znaki na wiersz wyświetla 6144 bajtów matrycowych lub 49152 pikseli na jednym obrazie. W ciągu jednej sekundy tworzone jest 50 takich obrazów.
W trybie SLOW mikroprocesor dzieli swój czas na wykonywanie
programu oraz tworzenie obrazu wideo. Do obsługi wideo i klawiatury zużywa on
około 80% czasu, a pozostałe 20% przeznaczone jest dla uruchomionych aplikacji.
W rzeczywistości czas pracy procesora podzielony jest na cztery oddzielne
zadania przy każdej ramce obrazu tv, co pokazano w tablicy 1. Zadania są
przełączane za pomocą generatora Przerwań Niemaskowalnych
(NMI), który wywołuje procedurę obsługi przerwań NMI kontrolującą
przełączanie zadań od asynchronicznego programu aplikacji do procedur tworzenia
wideo w czasie rzeczywistym.
1. | Tworzenie VSYNC, liczenie ramek, obsługa klawiatury | NMI wyłączone |
2. | Wyświetlanie górnego marginesu i wykonywanie programu aplikacji | NMI włączone |
3. | Procedura Wyświetlania Obrazu Wideo | NMI wyłączone |
4. | Wyświetlanie dolnego marginesu i wykonywanie programu aplikacji | NMI włączone |
Tab.1 Operacje wykonywane w trakcie tworzenia ramki obrazu
Każde z zadań możemy opisać bardziej szczegółowo w sposób następujący:
W kompatybilnym z ZX80 trybie FAST mikroprocesor wykonuje albo procedurę obsługi wideo, albo dowolny inny program, lecz nie oba jednocześnie, co jest powodem znanego skakania obrazu przy przełączaniu się pomiędzy tymi zadaniami. Gdy zostaje uruchomiony program aplikacji, jest on wykonywany ze 100% szybkością procesora. Jedynie przy zatrzymaniu aplikacji (w trybie rozkazowym) lub przy oczekiwaniu na wprowadzenie danych z klawiatury dla INPUT, albo w trybie PAUSE, obraz telewizyjny jest wyświetlany. Sprzęt wideo jest aktywowany w identyczny sposób jak w trybie SLOW, lecz przerwania NMI są zawsze wyłączone. Dodatkowo puste linie u góry i u dołu obrazu są również generowane programowo, co powoduje kompatybilność pamięci ROM ZX81 ze sprzętem komputera ZX80.
Obwód wideo w ZX81 składa się z mikroprocesora Z80, pamięci stałej ROM, pamięci RAM oraz większej części układu scalonego ZX81 Sinclair Logic Chip (zwykle zwanego ULA), co pokazuje Rys.3, na którym znajdują się wszystkie istotne połączenia, łącznie z rezystorami separującymi R. Dla prostoty pokazana jest tylko pamięć RAM 2KB. Układ ULA zawiera kwarcowy oscylator 6,5MHz oraz dzielnik częstotliwości, który generuje impulsy synchronizacji poziomej na wyjściu wideo oraz impulsy przerwań NMI na wyjściu NMI. Wyjścia HSYNC oraz NMI można kontrolować za pomocą następujących operacji wejścia/wyjścia:
Wyjście wideo z układu ULA przełącza się pomiędzy 3 poziomami napięć. Zwykle znajduje się na poziomie +5V, który odpowiada bieli i jest wykorzystywany do kreślenia pustych linii poza obrazem. Znaki są wyświetlane jako czarne piksele, gdy poziom napięcia spadnie do +2,5V. Wąskie impulsy synchronizacji poziomej oraz szerokie impulsy synchronizacji pionowej mają poziom 0V, co pokazano na przebiegu fali na rys.1 Podane poziomy logiczne zostają zmniejszone przez dzielnik oporowy do 1V, 0,5V i 0V (Anglia/USA) na wejściu modulatora sygnału telewizyjnego.
Rys.1 Przebieg sygnału telewizyjnego na wyjściu ULA
Impulsy synchronizacji poziomej HSYNC trwają przez 5µs, a odstęp pomiędzy nimi
wynosi 64µs. Impuls synchronizacji pionowej VSYNC ma szerokość 400µs i występuje
co 16,6ms (USA) lub co 20ms
(Europa). Impuls VSYNC wykorzystywany jest do
synchronizacji generatora obrazu w odbiorniku telewizyjnym oraz rozpoczęcia
wyświetlania linii obrazu u góry ekranu. Impuls ten rozpoczyna się w momencie
wykonania rozkazu
Rys.2 Obraz generowany przez ZX81
Mikroprocesor wykonuje kod aplikacji podczas wyświetlania pustych linii u góry i u dołu ekranu, gdy generator przerwań NMI przerywa CPU co 64µs, a ten w procedurze obsługi tego przerwania zwiększa licznik pustych linii w celu określenia, czy nadszedł już czas dla procedur wyświetlania obrazu wideo lub generacji impulsu synchronizacji pionowej VSYNC.
Generator wyświetlania znaków w ZX81 składa się z mikroprocesora Z80, pamięci stałej ROM, pamięci RAM oraz większej części układu scalonego ZX81 Sinclair Logic Chip (zwykle zwanego ULA), co pokazuje Rys.3, na którym znajdują się wszystkie istotne połączenia, łącznie z rezystorami separującymi R. Dla prostoty pokazana jest tylko pamięć RAM 2KB.
Rys.3 Obwód wyświetlania znaków w ZX81
Na obwód wyświetlania pseudografiki w ZX81 składają się mikroprocesor Z80, pamięć stała ROM, pamięć RAM oraz większa część układu scalonego ULA, co pokazuje Rys.4, na którym znajdują się wszystkie istotne połączenia, łącznie z rezystorami separującymi R. Dla prostoty pokazana jest tylko pamięć RAM 2KB.
Rys.4 Obwód wyświetlania pseudo grafiki
Jedyną różnicą pomiędzy obwodem pseudo hires a obwodem wyświetlania znaków jest rejestr LCNTR oraz wykorzystanie wejścia INT. Większość procedur obsługi pseudografiki nie wykorzystuje wejścia INT (normalnie służy ono do wznawiania pracy procesora po zatrzymaniu rozkazem HALT - CHR$ 118 na końcu wyświetlanego wiersza) a licznik linii znaku LCNTR jest resetowany na 0 przy każdej linii poziomej obrazu (normalnie adresuje on kolejne bajty w matrycy znaku w zależności od numeru linii ekranowej w wierszu znaków). Jedynym wyjątkiem jest XTRICATOR, która wykorzystuje INT i korzysta podwójnie z rejestru I w trybie INT 2 jako część adresu wektora RST, gdy pojawi się przerwanie na końcu każdej pionowej linii oraz w czasie odświeżania jako wskaźnik tablicy wzorców.
Elementami układów ZX81 wymaganymi do pracy w trybie TRUE HIRES są mikroprocesor Z80, pamięć RAM, rejestr przesuwny wideo oraz układ synchronizacji w ULA, co pokazano na rys.5 wraz ze wszystkimi istotnymi połączeniami. Znów dla prostoty ograniczyliśmy się do pokazania połączeń z pamięcią RAM 2KB, lecz ten sam schemat odnosi się do większej pamięci statycznej. Jeśli będzie zastosowane rozszerzenie 16KB RAM, to układ pamięci musi być nieco zmodyfikowany, co przedstawimy później, w celu umożliwienia odczytu danych z pamięci w trakcie cyklu odświeżania, gdyż wymaga tego zastosowana metoda tworzenia obrazu.
Rys.5 Obwód wyświetlania pełnej grafiki
Z wyjątkiem metody WRX1K, która tworzy miniaturowy ekran na komputerze ZX81 z 1KB pamięci RAM, wszystkie programy hires wymagają 6KB pamięci na dane graficzne (HFILE). Niezbędną dla tego trybu pamięć możemy zaimplementować przez modyfikację standardowego rozszerzenia 16KB stosując parę diod oraz rezystor.
W celu umożliwienia odczytu danych w cyklu odświeżania moduł pamięci jest modyfikowany przez przerwanie linii RD i RFSH na złączu krawędziowym i zainstalowanie jedynie dwóch diod germanowych 1N34A oraz rezystora podciągającego 4.7K. Przeróbkę wykonaj na własne ryzyko.
Rys.6 Modyfikacja modułu RAMPACK dla celów grafiki hires
Wyświetlanie obrazu zbudowanego ze znaków w komputerze ZX81 rozpoczyna się po wyświetleniu ostatniej pustej linii górnego marginesu ekranu. Wtedy procedura obsługująca tworzenie obrazu wideo wykonuje skok do adresu DFILE+32K. Adres taki ma zawsze ustawioną linię adresową A15 na 1. Układ ULA rozpoznaje wykonywanie przez mikroprocesor kodu maszynowego w górnej połówce pamięci RAM właśnie po stanie tej linii adresowej oraz po stanie niskim na linii M1, która zeruje się na początku każdego cyklu maszynowego. Pamięć zostaje przeadresowana przez układ ULA dla procesora z powrotem do oryginalnego obszaru DFILE. Jest to konieczne, ponieważ pod adresem > 32K w zwykłym ZX81 nie znajduje się żadna pamięć. Wykonywanie programu w górnej połówce pamięci jest zawsze traktowane przez ULA jako generacja obrazu wideo. Wynika z tego, iż w obszarze tym nie mogą być umieszczane procedury w języku maszynowym mikroprocesora Z80, jednakże dane można tam przechowywać bez problemu - na tej zasadzie opierają się rozszerzenia pamięci ZX81 większe niż 16KB. Poniżej podajemy skrótową procedurę pobierania danych do wyświetlenia na ekranie telewizora:
Można by zatem powiedzieć, iż blok DFILE jest dosłownie wykonywany za pomocą instrukcji NOP, które zastępują każdy kod znaku. Instrukcja NOP jest wykonywana przez mikroprocesor Z80 w czterech cyklach zegarowych przy częstotliwości 3,25MHz lub w czasie przesunięcia 8 pikseli w rejestrze przesuwnym wideo przy częstotliwości 6,5MHz.
Rys.7 Przebiegi czasowe sygnałów dla trybu znakowego w ZX81
Dokładny ciąg operacji dla każdego znaku jest pokazany na rys. 7 oraz opisany poniżej:
Do pracy w trybie pseudo hires wymagane jest układ pokazany na rys.4, który różni się od standardowego obwodu drobnymi modyfikacjami wymaganymi do otrzymania standardowego ekranu zbudowanego ze 192 linii po 32 wzory pseudografiki. Tryb ten różni się od zwykłego wyświetlania znaków tym, iż każdy znak ma wysokość jedynie jednej linii zamiast normalnych 8. Osiągane to jest przez zerowanie licznika LINECTR przy każdej wyświetlonej linii. W efekcie z tablicy matryc znaków pobierany jest tylko pierwszy bajt każdej matrycy. Standardowa matryca nie bardzo się nadaje do pracy w tym trybie, ponieważ większość pierwszych bajtów matryc znaków jest zerowa. Dlatego tablicę tę lokalizuje się w innym miejscu pamięci ROM. Programista ma wtedy dla każdego z 64 możliwych do wyświetlenia znaków różne układy bitów, które jednakże mogą się powtarzać. Oprócz podstawowych 64 wzorów dostępne jest również 64 negatywy przy ustawionym na 1 najstarszym bicie kodu znaku.
Wyświetlanie rozpoczyna się gdy zostanie zakończona ostatnia pusta linia górnego marginesu. Procedura tworzenia obrazu wykonuje skok do echa 6KB bloku DFILE zlokalizowanego ponad adresem 32K. Układ ULA przejmuje kontrolę nad każdym wykonywanym przez mikroprocesor kodem rozkazu o adresie w górnej połowie przestrzeni adresowej (A15=1 i M1 = 0) oraz z wyzerowanym bitem nr 6. W rzeczywistości blok DFILE musi się znajdować poniżej adresu 32K - ULA przeadresowuje pamięć przy pobieraniu przez mikroprocesor kodu rozkazu - uwaga ta dotyczy komputera ZX81 z rozszerzeniem pamięci ponad 16KB. Echo bloku DFILE nie istnieje fizycznie w obszarze ponad 32K, jest tam tylko "widziane" przez mikroprocesor dzięki temu, iż ULA wyłącza linię A15 dla kodów rozkazów. Dla danych linia A15 pełni swoją normalną funkcję, zatem w obszarze ponad 32K można przechowywać wszelkie zmienne. ULA rozpoznaje cykl rozkazowy procesora po stanie linii M1 - M1=0 - procesor wykonuje pierwszy cykl maszynowy, czyli pobranie z pamięci kodu rozkazu.
W skrócie dane wideo są ładowane do układu ULA w pięciu krokach:
Każda instrukcja NOP jest wykonywana w czasie 4 taktów zegara przy częstotliwości 3,25MHz lub 8 pikseli wyprowadzanych z rejestru przesuwnego w ULA przy częstotliwości 6,5MHz.
Rys.8 Przebiegi czasowe dla pseudografiki
Dokładny ciąg operacji dla każdego znaku jest następujący.
Chociaż w opisie będę się opierał na procedurze hires WRX, to inne procedury opracowane niezależnie są bardzo podobne. Wyświetlanie w trybie TRUE HIRES rozpoczyna się, gdy zostanie wyświetlona ostatnia pusta linia górnego marginesu obrazu. Wtedy procedura obsługi NMI skacze poprzez rejestr IX do procedury obsługującej rzeczywistą grafikę hires. Procedura ta ustawia odpowiednio rejestry I oraz R, aby wskazywały blok z danymi graficznymi w pamięci - HFILE, a następnie skacze do echa procedury LBUF ponad adresem 32K i ładuje rejestr R oraz przechodzi do wykonania pierwszej instrukcji NOP. ULA ładuje rejestr przesuwny wideo danymi spod adresu I:R w trakcie cyklu odświeżania pamięci RAM, gdy kod wykonanej instrukcji miał ustawiony na 0 bit nr 6.
Dane hires są ładowane w 3 krokach:
LBUF składa się z 32 kodów NOP, każdy wykonywany w czasie 4 cykli zegarowych mikroprocesora. Podczas wykonania drugiej części rozkazu rejestry I oraz R adresują bajt hires w HFILE, który ULA ładuje do rejestru przesuwnego wideo. Adres dla tablicy matryc wygenerowany przez ULA nie jest tutaj wykorzystywany, gdyż nie powstaje sygnał ROMCS - rejestr I (linie adresowe A8-A15) wskazuje lokację w pamięci RAM, wewnątrz HFILE.
Rys.9 Przebiegi czasowe dla pełnej grafiki
Dokładny ciąg operacji dla każdego bajtu hires jest następujący:
Podobnie do innych procedur hires, procedura WRX przechwytuje obsługę wideo Sinclaira przez załadowanie nowego wektora procedury wideo do rejestru IX.
Jak pokazano w tab.1, mikroprocesor dokonuje podziału czasu wykonania procedur wideo i programu aplikacji w 4 przedziałach czasu.
0229 DISPLAY_1: ;zmniejszenie licznika ramek FRAME 023E DISPLAY_2: ;sprawdzenie klawiatury (początek impulsu VSYNC) 0277 OUT 0FFH,A ;koniec impulsu synchronizacji VSYNC 0292 DISPLAY_3: ;umieszczanie wskaźnika procedury wideo w IX (0281), powrót do aplikacji
0066 NMI: ;zliczanie pustych linii, powrót do aplikacji lub poprzez JP (IX) do 0281
0281 VIDEO_1: ;ustawianie parametrów wyświetlania, wywołanie 2B5 (Powrót poprzez INT) 02B5 DISPLAY_5: ;ustawienie parametrów wyświetlania, włączenie przerwań, JP (DFILE) XXXX (DFILE) ;wykonanie instrukcji HALT oraz wymuszonych NOP w DFILE 0038 INT: ;zmniejszenie liczników wierszy/linii, powrót do DFILE lub do 028B 0292 DISPLAY_3: ;zabezpieczenie wskaźnika procedury wideo (028F)
0066 NMI: ;zliczanie pustych linii, powrót do aplikacji lub przez JP (IX) do 028F 028F VIDEO_2: JP 229H ;powrót do licznika ramek w bloku 1
Poniżej zamieściłem w pełni skomentowany listing ROM ZX81 procedur związanych z wyświetlaniem obrazu wideo.
L0038: ;PROCEDURA OBSŁUGI PRZERWAŃ INT DEC C ;zmniejsz licznik linii skanujących w rejestrze C JP NZ,0045H ;skocz do SCAN-LINE : powtarzane 8 razy dla każdego wiersza znaków w DFILE POP HL ;pobierz adres początku następnego wiersza DFILE ze stosu (adres powrotny za HALT) DEC B ;zmniejsz licznik wierszy w rejestrze B RET Z ;jeśli się wyzerował, wróć do 028B SET 3,C ;załaduj licznik linii skanujących w rejestrze C wartością 8 L0041: ;WAIT-INT LD R,A ;w rejestrze R umieść wartość DDH EI ;włącz przerwania INT JP (HL) ;wykonaj sekwencję instrukcji NOP w echu DFILE L0045: ;SCAN-LINE POP DE ;porzuć adres powrotny, ponieważ ten sam wiersz musi być wykonany 8 razy RET Z ;opóźnienie (powrót nigdy nie następuje) JR 0041H ;przejdź do WAIT-INT ;---------------------------------------------------------- L0066: ;PROCEDURA OBSŁUGI PRZERWAŃ NMI ;Przerywa program aplikacji co każde 64µs (HSYNC) EX AF,AF' ;odzyskaj w A licznik pustych linii marginesu ekranu INC A ;następna pusta linia JP M,006DH ;powróć poprzez 006D (do NMI-EXIT), jeśli A jest liczbą ujemną U2 JR Z,006FH ;Przy ostatniej linii skocz do NMI-CONT L006D: EX AF,AF' ;zapamiętaj licznik pustych linii RET ;powróć do aplikacji lub do NMI-EXIT L006F: ;NMI-CONT EX AF,AF' ;przełącz na główny zestaw rejestrów AF PUSH AF ;zapisz rejestry programu aplikacji na stosie PUSH BC PUSH DE PUSH HL LD HL,(DFILE) ;pobierz wskaźnik DFILE SET 7,H ;ustaw w HL adres echa DFILE powyżej adresu 32K HALT ;synchronizacja do jednego taktu: ten rozkaz HALT używany jest ze specjalnym ;obwodem podłączonym do linii mikroprocesora WAIT i HALT, i zostaje zwolniony ;oraz zsynchronizowany z opadającym zboczem impulsu NMI L007A: ;NMI-EXIT OUT 0FDH,A ;wyłącz generator NMI JP (IX) ;skocz do VIDEO-1 lub VIDEO-2 ;--------------------------------------------------------- L0229: ;DISPLAY-1 LD HL,(FRAMES) ;pobierz zmienną systemową FRAMES DEC HL ;zmniejsz ją przy każdej ramce ..... LD (FRAMES),HL ;i zachowaj wynik w pamięci L023E: ;DISPLAY-2 CALL 02BBH ;odczytaj stan klawiatury i załaduj MARGIN liczbą pustych linii ..... ;rozpocznij również impuls synchronizacji pionowej VSYNC L0277: OUT 0FFH,A ;zakończ impuls VSYNC LD HL,(DFILE) ;(tylko dla FAST VIDEO) - ustaw HL tna pierwszą instrukcję HALT dla pustych linii SET 7,H ;(tylko dla FAST VIDEO) - ustaw adres echa DFILE ponad 32K L027E: CALL 0292H L0281: ;VIDEO-1 ;ten wektor jest zapisywany w rejestrze IX w punkcie 0292 LD A,R ;opóźnienie LD BC,1901H ;ustaw parametry INT dla pierwszego rozkazu HALT w (DFILE) LD A,0F5H ;ustaw rejestr R dla pierwszego HALT w (DFILE) CALL 02B5H ;kontynuuj ustawienia dla obrazu z DFILE i powróć poprzez INT L028B: ;tutaj powróć z ostatniego INT DEC HL ;(tylko dla FAST VIDEO) - ustaw HL na ostatni rozkaz HALT dla pustych linii CALL 0292H ;zapisz wektor VIDEO w IX, oblicz puste linie, pobierz rejestry ze stosu L028F: JP 0229H ;VIDEO-2 ;ten wektor jest zapisywany w rejestrze IX w 0292 L0292: ;DISPLAY-3 POP IX ;IX=0281H lub 028FH jako wektor do VIDEO-1 lub VIDEO-2 LD C,(IY+56H) ;pobierz liczbę pustych linii z MARGIN (1F dla opcji 60Hz) BIT 7,(IY+59H) ;sprawdź bit FAST/SLOW JR Z,02A9H ;(FAST VIDEO) skocz do generacji pustych linii LD A,C ;C=(MARGIN)=1F dla 60 Hz NEG ;utwórz liczbę ujemną U2 INC A EX AF,AF' ;podczas NMI w 0066 - AF' jest zwiększane i testowane na zero OUT (0FEH),A ;włącz generator NMI POP HL ;odtwórz rejestry programu aplikacji POP DE POP BC POP AF RET ;powróć do programu aplikacji przerywanego przy każdym impulsie HSYNC przez NMI ;----------------------------------------------------------- L02B5: ;DISPLAY-5 LD R,A ;R zwiększa się o 1 przy każdym rozkazie na liniach od A0 do A7 podczas RFSH ;aż linia A6 przyjmie stan niski, co wygeneruje sygnał INT. LD A,0DDH ;ustaw lewy margines dla wszystkich pozostałych linii, ładowany do R w 0041 EI ;gdy jest ustawiony R, włącz reagowanie na INT JP (HL) ;"wykonaj" DFILE poczynając od HALT i czekając na pierwsze przerwanie INT ;-----------------------------------------------------------
W celu przyspieszenia czasu wykonania programu aplikacji tryb FAST przeznacza dla niego 100% czasu mikroprocesora, lecz są chwile, gdy program aplikacji wykonuje operacje jałowe. Gdy program jest zatrzymany, wykonuje polecenie PAUSE lub czeka na dane z klawiatury dla INPUT, klawiatura jest sprawdzana i jeśli żaden klawisz nie jest wciśnięty, generowany jest obraz niezależnie od impulsów NMI. W rzeczywistości procedurę wideo w trybie FAST opracowano, tak aby była kompatybilna ze sprzętem ZX80 i pamięć ROM z kodem mogła być stosowana jako uaktualnienie pamięci ROM w ZX80. Ponieważ ZX81 tworzy programowo puste linie, tak samo postępuje w trybie FAST ROM komputera ZX81.
Pętla procedur VIDEO dla trybu FAST rozpoczyna się od procedury FRAME/KBD/VSYNC pod adresem 229H:
0229 ZMNIEJSZANIE LICZNIKA RAMEK 023D WYJŚCIE, JEŚLI FRAMES=0 (KONIEC PAUSE) 023E SPRAWDZENIE KLAWIATURY 0260 WYJŚCIE, JEŚLI NACIŚNIĘTO NOWY KLAWISZ 0292 UMIESZCZENIE WSKAŹNIKA WIDEO W IX (0281) 029B JR Z 02A9 DO PROCEDURY RYSOWANIA PUSTEJ LINII 02A9 TWORZENIE PUSTYCH LINII 02B3 JP (IX) DO 0281 0281 TWORZENIE OBRAZU DFILE 0292 ZACHOWANIE WSKAŹNIKA VIDEO (028F) 029B JR Z 02A9 DO PROCEDURY RYSOWANIA PUSTEJ LINII 02A9 TWORZENIE PUSTYCH LINII 02B3 JP (IX) DO 028F 028F JP 229 Z POWROTEM DO LICZNIKA RAMEK
Ponieważ większość z tych procedur opisałem w poprzednim podrozdziale, tutaj opiszę jedynie różnice. Przy wejściu do tej pętli w trybie SLOW z końca procedury rysowania pustych linii zapamiętywane na stosie są rejestry programu aplikacji, a przy wyjściu są one odtwarzane na końcu procedury 0292. Natomiast w trybie FAST nie są zapamiętywane żadne rejestry, a procedura 0292 jest pomijana. Wykonywane jest to w 029B po sprawdzeniu znacznika trybu FAST i skoku do mniej znanej procedury zwanej DISPLAY-4.
L02A9: ;DISPLAY-4 LD A,0FCH ;najpierw opóźnienie R do INT LD B,01H ;jeden wiersz CALL 02B5H ;wyświetl puste linie DEC HL ;wskaż z powrotem na HALT EX (SP),HL ;opóźnienie 19 T EX (SP),HL ;opóźnienie 19 T JP (IX) ;IX = 0281 lub 028F
Procedura pod adresem 02A9H jest wywoływana dwukrotnie przy każdej ramce do utworzenie pustych linii w górnym i dolnym marginesie obrazu z zawartością HL wskazującą albo na pierwszy rozkaz HALT na początku DFILE lub na ostatni HALT na końcu DFILE. Rejestr C zawiera liczbę pustych linii a rejestr B jest ustawiany na 1 wiersz. Po VSYNC tworzone jest 31 górnych linii marginesu przez wywołanie procedury wyświetlania pod adresem 02B5 i wykonanie 31 razy pierwszego HALT na początku DFILE. Po powrocie z procedury wyświetlania para HL wskazuje na adres ostatniego HALT + 1 i wymagane jest DEC HL, aby wskaźnik wrócił z powrotem na ostatnie HALT w DFILE. Po zapisie adresu w IX procedura 02A9H jest ponownie wywoływana z HL wskazującym na ostatnie HALT i tworzy 31 pustych linii dolnego marginesu wykonując tą instrukcję HALT na końcu DFILE.
Procedury trybu true hires różnią się od opisanych głównie tym, ią jako wskaźnik danych graficznych wykorzystuje się parę rejestrów I oraz R. Jedynym pozostałym warunkiem jest wykonanie 32 instrukcji NOP (lub podobnych) na jedną linię poziomą, a następnie uaktualnienie rejestrów i oraz R w czasie impulsu synchronizacji poziomej HSYNC. W celu zwiększenia szybkości pracy programu aplikacji może być użytych więcej linii marginesu nad oraz pod obrazem.
Tutaj przedstawiam procedury stosowane w programach autorstwa Freda Nachbaura i Grefa Hardera. Tworzą one obraz o rozdzielczości 256x192 w tablicy o długości 6144 bajtów, która rozpoczyna się ponad obszarem RAMTOP. W tablicy tej można umieszczać dane za pomocą rozkazu POKE z poziomu języka BASIC.
START jest używane do rozpoczęcia wyświetlania hires a STOP przywraca standardowy obraz Sinclaira.
Część 1 wywołuje 192 razy LBUF wyświetlając 256x192 pikseli, oblicza liczbę pustych linii do wyświetlenia w marginesach ekranu, zapisuje wskaźnik do Części 2 w rejestrze IX i powraca do kodu aplikacji.
Część 2 wywołuje VSYNC itp., zlicza puste linie, zapisuje wskaźnik do Części 2 w IX i powraca do wykonania kodu aplikacji
.ORG 16516 ;szesnastkowo 4084 HFILE .EQU $4004 ;HFILE umieszczone jest ponad używaną pamięcią
LBUF: ;Wyświetla linię 256 pikseli ;------------------------------ ;podobnie jak w przypadku DFILE, procedura ta jest wywoływana ponad ;z adresem 32K like DFILE w celu aktywacji układów wideo w ULA ;ustawiając bit nr 7 kodów NOP mozna uzyskiwać negatyw grafiki. ;dane graficzne są umieszczane w rejestrze przesuwnym wideo w ULA ;podczas cykli odświeżania przy wykonywaniu 32 instrukcji NOP ;przy sekwencyjnym adresowaniu rejestrami I oraz R wskazującymi ;zawartość bloku HFILE o długości 6144 bajtów LD R,A ;ładuj młodszy bajt adresu HFILE do rejestru R .BYTE 0,0,0,0,0,0,0,0 ;32 instrukcje NOP .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 JP (IX) ;powróć do HR HR: ;PROCEDURA HIRES - CZĘŚĆ 1 ;------------------------- LD B,4 ;opóźnienie w celu synchronizacji z impulsami HSYNC HR0: DJNZ HR0 LD HL,(HFILE) ;RAMTOP wskazuje pierwszy bajt HFILE LD B,0C0H ;192 linii poziomych LD IX,HR1 ;zapisz wektor powrotu w IX (dla JP (IX) na końcu LBUF) JR HR2 ;przy pierwszym obiegu pętli przeskocz do HR1 HR1: LD DE,0020H ;długość linii 256 pikseli w HFILE - 32 bajty ADD HL,DE ;dodaj do HL, aby wskazać początek następnej linii w HFILE DEC B ;powtarzaj 192 razy JP Z,HR3 ;jeśli jest to ostatnia linia, skocz do HR3 HR2: LD A,H ;adres w HL jest umieszczany w rejestrze I LD I,A LD A,L ;a podczas wykonywania LBUF również w rejestrze R JP LBUF+8000H ;skocz do LBUF w górnej połówce pamięci, aby uruchomić ULA HR3: LD IX,HR4 ;zapisz wektor wideo, aby procedura NMI powróciła do HR4 JR HR5 ;rysuj pustą linię i powróć do kodu aplikacji HR4: ;PROCEDURA HIRES - CZĘŚĆ 2 ;------------------------- CALL 220H ;zapisz najpierw rejestry na stosie i skocz do VSYNC LD IX,HR ;zapisz wektor wideo do IX, aby NMI powróciło do HR HR5: LD A,(4028H) ;33 lub 19 pustych linii w zmiennej systemowej MARGIN JP 29EH ;zapisz liczbę pustych linii, uruchom NMI, pobierz rejestry ze stosu i powróć ;--------------------- koniec listingu ---------------------
Procedura hires jest uaktywniana i zatrzymywana przez zmianę adresu w rejestrze IX, który wykorzystuje NMI, aby skoczyć JP (IX) do procedury wideo. Poniższe procedury są zsynchronizowane z wyświetlaniem, aby zmiana trybu wideo odbywała się bez przerw w wyświetlaniu.
STOP: ;zatrzymuje hires wideo i powraca do wideo Sinclaira ;--------------------------------------------------- LD HL,0281H ;wskaźnik do procedury wideo Sinclaira LD A,1EH ;adres tablicy z matrycami znaków w ROM (1E00) LD I,A ;trafia do rejestru I JR SYNC START: ;Start procedury hires wideo ;---------------------------- LD HL,HR ;wskaźnik procedury hires wideo SYNC: ;używane przez START i STOP do płynnej zmiany trybu wideo ;--------------------------------------------------------- PUSH HL LD HL,4034H ;licznik ramek - FRAMES LD A,(HL) ;pobierz stare FRAMES SYNC1: CP A,(HL) ;porównuj z nowym FRAMES JR Z,SYNC1 ;powtarzaj, aż będą się różnić POP IX ;procedura wideo Sinclaira. ;-------------- koniec listingu ---------------
Ta procedura hires używa genialnego sposobu na przechwycenie wektora wideo. Zamiast zmieniania zawartości rejestru IX, GUUS-FLATER przechwytuje wykonanie na początku DFILE przez zmianę pierwszych 4 bajtów łącznie z HALT na DI i JP 409FH, co jest startem procedury hires. Na końcu ekranu hires program po prostu powraca do procedury ROM pod adresem xxxx. DFILE posiada charakterystyczną zawartość rozpoczynającą się od DI i JP 409FH, a HFILE zaczyna się od (4004H).
(400C) DI ;te bajty zostają załadowane do DFILE JP 409FH ;jako wektor do procedury hires .ORG 409FH L409F: LD B,08 ;opóźnienie LP1: DJNZ LP1 ;opóźnienie LD A,R ;opóźnienie LD B,0C0H ;192 linie LD DE,20H ;32 bajty na linię LD HL,(4004) ;plik hires (HFILE) rozpoczyna się od adresu RAMTOP L40AD: LD A,H ;MSB adresu HFILE LD I,A ;ładuj MSB wskaźnika HFILE LD A,L ;LSB adresu HFILE JP 0C0B6H ;skok ponad 32K L40B6: LD R,A ;ładuj LSB wskaźnika HFILE .BYTE "COPYRIGHT 1984 ENNO BORGESTEEDE " ; to samo co 32 instrukcje NOP JP 40DBH ;skocz poniżej 32K L40DB: ADD HL,DE ;następna linia hires DJNZ 40ADH ;linia hires powtarza się 192 trazy LD A,1EH ;przywróć wskaźnik tablicy matryc znaków w ROM LD I,A ;załaduj go do rejestru I RET ;połącz się z procedurą wideo Sinclair'a w toku
Oryginalne procedury grafiki hires WRX napisano w 1984 roku, lecz ostatni wzrost zainteresowania tym tematem wymusił opracowanie nowszej i bardziej wydajnej wersji. WRX16K 1996 jest najbardziej zoptymalizowaną wersją procedur WRX, a pomimo swojej niewielkiej objętości obsługuję grafikę hires w rozdzielczości ekranu 256x192 piksele. Została opracowana do pracy ze zmodyfikowanym modułem pamięci 16K RAMPACK lub z 16K pamięcią SRAM. Przed jej załadowaniem należy najpierw obniżyć RAMTOP rozkazem POKE 16389,96 oraz wykonać polecenie NEW.
Tryb hires można uruchomić i zatrzymać przy pomocy tych samych procedur, które pojawiły się na listingu WRX16 powyżej. Proste START jest używane do uruchomienia trybu hires poprzez zmianę adresu wektora wideo w rejestrze IX. Tryb hires jest zatrzymywany przez wywołanie wewnętrznej procedury BREAK, która synchronicznie powraca do trybu wideo Sinclaira po naciśnięciu klawisza spacji. HFILE jest liniowym buforem rozpoczynającym się pod adresem (4004H), lecz można je łatwo umieścić w innym obszarze pamięci. Pamiętaj jednakże, iż HFILE musi się rozpoczynać od adresu podzielnego przez 32 z uwagi na to, iż rejestr R posiada jedynie 7 aktywnych bitów.
.ORG 16516 ;hex 4084 START: LD IX,HR ;prosty start trybu hires RET LBUF: LD R,A ;załaduj LSB adresu HFILE .BYTE 0,0,0,0 ;32 instrukcje NOP = 256 pikseli .BYTE 0,0,0,0 .BYTE 0,0,0,0 .BYTE 0,0,0,0 .BYTE 0,0,0,0 .BYTE 0,0,0,0 .BYTE 0,0,0,0 .BYTE 0,0,0,0 RET NZ ;zawsze następuje powrót HR: LD B,7 ;opóźnienie HR0: DJNZ HR0 ;opóźnienie DEC B ;wyzeruj znacznik Z LD HL,(4004H) ;HFILE rozpoczyna się pod adresem RAMTOP lub HSCRN (notka poniżej) LD DE,20H ;32 bajtów na linię LD B,0C0H ;192 linii na ekran hires HR1: LD A,H ;pobierz MSB adresu HFILE LD I,A ;i umieść go w rejestrze I LD A,L ;pobierz LSB adresu HFILE CALL LBUF+8000H ADD HL,DE ;następna linia DEC B ;zmniejsz licznik linii JP NZ,HR1 ;kontynuuj wyświetlanie HR2: CALL 292H ;powróć do programu aplikacji CALL 220H ;dodatkowe umieszczenie rejestrów na stosie oraz VSYNC BREAK: ;ten kod jest opcjonalny CALL 0F46H ;sprawdź, czy naciśnięto BREAK LD A,1EH ;odtwórz wektor tablicy matryc znaków w ROM LD I,A JR NC,STOP ;jeśli naciśnięto BREAK, pomiń ładowanie wektora HR do IX LD IX,HR ;załaduj wektor do HR STOP : JP 2A4H ;powróć do kodu aplikacji HSCRN .WORD 2000H ;używane z pamięcią SRAM w obszarze 8K - 16K ;Uwaga: ;HFILE można przemieścić w przypadku posiadania pamięci SRAM w obszarze 8 do 16K zmieniając ;LD HL,(4004) na LD HL,(HSCRN). ;------------------ koniec listingu ------------------
Ten malutki program hires jest specjalny, ponieważ działa na zwykłym ZX81 z pamięcią 1K/2K RAM. Tworzy on miniaturowy obraz o rozdzielczości 64x48 pikseli w tablicy 384 bajtów, która umieszczona jest pod adresem (RAMTOP) i w której wartości można umieszczać przy pomocy polecenia POKE z poziomu języka BASIC. Przy wywołaniu START zostaje zwinięty bufor DFILE Sinclaira i rozwinięty bufor hires ponad RAMTOP w celu efektywnego wykorzystania pamięci 1K. Przy wywołaniu STOP odzyskiwana jest pamięć ponad RAMTOP, aby otrzymać więcej miejsca dla DFILE.
.ORG 16516 ;hex 4084 LBUF: ;Plik obrazowy ;------------- ;podobnie jak dla DFILE, wywoływany jest pod adresem w górnej połówce pamięci ;ponad 32K w celu aktywacji układu ULA. Z kodów wykorzystywany jest jedynie ;bit nr 7 do tworzenia negatywu. Dane hires są ładowane do rejestru przesuwnego ;wideo w ULA podczas cyklu odświeżania przy wykonywaniu 8 instrukcji NOP, gdy ;zawartość rejestrów I oraz R sekwencyjnie adresuje 8 bajtów danych hires w ;obrębie 384-bajtowego bufora HFILE. ;Uwaga: w tym szczególnym przypadku krótkich (8 bajtów) linii wideo opóźnienia ;(E3 i 40) posiadają ustawiony na 1 bit 6 w celu uniemożliwienia wyświetlania ;obrazu na początku i na końcu każdej linii poziomej. .BYTE 0E3H,0E3H,0E3H,0E3H ;opóźnienie 76 cykli zegara LD R,A ;teraz załaduj rejestr R LSB adresu HFILE LBYTE: .BYTE 0,0,0,0,0,0,0,0 ;8 bajtów po 8 pikseli .BYTE 40H,40H,40H,40H ;opóźnienie 20 cykli zegara .BYTE 40H ;opóźnienie 4 cykli zegara JP (IX) ;powróć do HR START: ;robi miejsce ponad RAMTOP i włącza procedurę hires ;-------------------------------------------------- LD IX,HR ;początek nowej procedury wideo LD BC,180H ;dla obrazu 64x48 potrzeba 384 bajtów CALL 0EC5H ;czy jest miejsce, aby obniżyć RAMTOP? LD HL,(4004H) ;pobierz stare RAMTOP (1K/2K) CCF ;oblicz wartość nowego RAMTOP SBC HL,BC ;odejmując długość HFILE STACK: ;używane przez START i STOP do zmiany RAMTOP bez NEW OUT 0FDH,A ;wyłącz generator NMI podczas przesuwania stosu LD (4004H),HL ;uaktualnij RAMTOP DEC HL ;HL wskazuje pierwszy bajt poniżej RAMTOP LD (HL),3EH ;zaznacz go przy pomocy 3E DEC HL LD SP,HL ;umieść stos pod RAMTOP DEC HL DEC HL LD (4002),HL ;zapisz wskaźnik błędu na stosie OUT 0FEH,A ;włącz NMI JP 676H ;wznów wykonywanie BASICU od następnej linii HR: ;CZĘŚĆ 1 wywołuje LBUF 48 razy wyświetlając 64x48 pikseli, oblicza puste linie ;zapisuje wskaźnik do CZĘŚCI 2 w IX i powraca do kodu aplikacji. ;CZĘŚĆ 2 wywołuje VSYNC itp., sprawdza klawisz BREAK, oblicza puste linie, ;zapisuje wskaźnik do CZĘŚCI 1 w IX i powraca do kodu aplikacji. LD B,04 ;załaduj opóźnienie HR0: DJNZ HR0 ;opóźnienie 56 taktów w celu synchronizacji z impulsami HSYNC. LD HL,(4004H) ;RAMTOP wskazuje na pierwszy bajt HFILE LD B,30H ;48 linii poziomych LD IX,HR1 ;zapisz wektor powrotu w IX (dla JP (IX) na końcu LBUF) JR HR2 ;przy pierwszym obiegu pętli pomiń HR1 HR1: LD DE,08 ;ta wartość jest dla 8 bajtów lub 64 pikseli na linię ADD HL,DE ;dodaj ją do HL, aby wskazać na początek następnej linii poziomej DEC B ;powtórz to 48 razy JP Z,HR3 ;przy ostatniej linii skocz do HR3 HR2: LD A,H ;Adres z HL zostaje przeniesiony do LD I,A ;rejestru I LD A,L ;a podczas LBUF również do rejestru R JP LBUF+8000H ;skocz do echa LBUF w górnej połówce pamięci, aby rozpocząć obraz wideo HR3: LD IX,HR4 ;zapisz wektor wideo, aby NMI powróciło do CZĘŚCI 2 JR HR5 ;wyświetl puste linie i powróć do kodu aplikacji HR4: ;CZĘŚĆ 2 CALL 0220H ;umieść na stosie rejestry i skocz do VSYMC CALL 0F46H ;testuj klawisz BREAK JR NC,STOP ;i wyjdź z HR, jeśli naciśnięto ten klawisz LD IX,HR ;zapisz wektor wideo w IX, aby NMI powróciło do CZĘŚCI 1 HR5: LD A,(4028H) ;33 lub 19 pustych linii ze zmiennej systemowej MARGIN ADD A,47H ;dodatkowe 71 pustych linii w celu szybszego wykonywania aplikacji JP 29EH ;zapisz puste linie, rozpocznij NMI, pobierz rejestry ze stosu i powróć STOP: ;wychodzi z procedury hires odtwarzając RAMTOP oraz wideo Sinclaira LD A,1EH ;adres tablicy matryc znakowych w ROM (1E00) LD I,A ;zapisujemy go w rejestrze I LD HL,(4004H) ;pobierz bieżące RAMTOP LD DE,180H ;długość HFILE ADD HL,DE ;jest dodawana do bieżącego RAMTOP LD IX,0281H ;procedura wideo Sinclaira JR STACK ;wyjdź z HR poprzez STACK, aby zmienić RAMTOP ;------------------ koniec listingu ------------------
Oprogramowanie trybu pseudo hires wykorzystuje kody znaków oraz rejestr I do adresowania jednego z 64 bajtów z wzorem w pamięci ROM. Kody znaków są ograniczone do przedziału od 0 do 63 oraz do ich negatywów (kody od 128 do 191), natomiast zawartość rejestru I jest tak wybrana, aby wskazywała blok bajtów z wzorkami w ROM o dużej przypadkowości i z jak najmniejszą liczbą duplikatów. Metoda ta nosi nazwę "pseudo" hires, ponieważ dostępne jest do wyświetlania mniej niż 50% z 256 wymaganych dla true hires układów bitów. Powoduje to, iż pewnych układów pikseli brakuje w generowanej grafice, lecz dla wieli zastosowań (np. gier) nie stanowi to problemu. Zaletą tej metody jest to, iż działa ona w standardowym systemie ZX81 z pamięcią 16K RAMPACK bez żadnych modyfikacji. Wiele emulatorów obsługuje ten tryb wyświetlania obrazu - np. eightyOne.
W tym przykładzie procedur pseudo hires rozwinięty blok DFILE znajduje się pod adresem 6700H.
START: LD A,4 ;wybierz interesującą tablicę wzorków LD I,A ;zapisz wektor tej tablicy w rejestrze I LD IX,PHR ;załaduj wektor procedury pseudo hires do rejestru IX RET PHR: LD HL,0E6DFH ;HL jest używane w charakterze wskaźnika DFILE LD DE,21H ;32 znaków + RET = 33 bajty na linię DI ;INT nieużywane LD C,0FEH ;wyzeruj licznik linectr w ULA LD B,16H ;opóźnienie LP1: DJNZ LP1 ;opóźnienie LD B,0C0H ;192 linie po 33 bajty PHR1: IN A,(C) ;zastosuj reset w liczniku linii OUT 0FFH,A ;zwolnij licznik linii ADD HL,DE ;następna linia z DFILE (E700,E721, itd.) CALL PHR2 ;"wykonaj" "DFILE" poprzez JP (HL) pod adresem PHR2 DEC B ;zmniejsz licznik linii JP NZ,PHR1 ;ostatnia? powtarzaj 192 razy. CALL 292H ;odtwórz ze stosu główne rejestry, powróć do aplikacji CALL 220H ;umieść na stosie rejestry i wykonaj VSYNC LD IX,PHR ;wektor procedury pseudo hires do IX JP 2A4H ;odtwórz pierwotne rejestry, powróć do aplikacji PHR2: JP (HL) ;skocz do echa obszaru hires "DFILE" ponad 32K
Ta niezwykła procedura tworzenia pseudografiki przechwytuje obsługę wideo ustawiając tryb przerwań 2, w którym generujące przerwanie urządzenie dostarcza część adresu procedury obsługi. Ponieważ nieaktywna magistrala danych znajduje się w stanie 0FFH, a rejestr I jest ustawiony na 40, to wektor obsługi INT wynosi 4000, gdy linia A6 wyzwala przerwanie na końcu linii poziomej.
4083 LD HL,40A5H ;wektor powrotu 4086 PUSH HL ;zapisz go na stosie 4087 LD HL,0E500H ;bufor grafiki hires 408A PUSH HL ;zapisz wektor na stosie 408B LD B,7 ;opóźnienie 408D DJNZ 408DH ;opóźnienie 408F LD A,1EH ;wzorki z Sinclair ROM 4091 LD I,A ;załaduj wektor tablicy wzorków 4093 LD DE,0C201H ;D = 194 linie 4096 DEC E ;ustaw znacznik Z 4097 JP Z,409AH ;opóźnienie 409A POP HL ;HL = E500 409B DEC D ;zmniejsz licznik linii 409C RET Z ;po ostatniej linii powróć do 40A5 409D SET 0,E ;E = 01 409F JP 40A2H ;opóźnienie 40A2 LD A,0 ;opóźnienie 40A4 JP (HL) ;skocz do echa bufora 6500 ponad 32K 40A5 LD A,4 ;"specjale" wzorki z ROM 40A7 LD I,A ;załaduj wskaźnik tablicy wzorków 40A9 RET 40AA LD A,40H ;MSB adresu obsługi tryby 2 przerwań INT 40AC LD I,A ;umieść MSB wektora obsługi przerwań w trybie 2 40AE IM2 ;włącz tryb 2 przerwań INT 40B0 RET 40B1 LD A,1EH ;wzorki Sinclaira w ROM 40B3 LD I,A ;załaduj wskaźnik tablicy wzorków do rejestru I 40B5 IM1 ;przywróć tryb INT 1 40B7 RET 40B8 LD HL,6500H ;na początku HFILE umieść instrukcję: 40BB LD B,0C1H 408D LD (HL),0CDH ;CALL 4096H 408F INC HL 40C0 LD (HL),96H 40C2 INC HL 40C3 LD (HL),40H 40C5 INC HL 40C6 LD A,20H ;wygeneruj 6144 spacji poczynając od 40C8 LD (HL),0 ;adresu 6503H 40CA INC HL 40CB DEC A 40CC JR NZ,40C8H 40CE DJNZ 40C6H 40D0 RET
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe