Paweł "Pavros" Rosowski (dawniej ksywa Ikplus):
Ramka (ang. border) to obszar na obrzeżach ekranu, otaczający
właściwe pole obrazu. Z założenia jest to obszar, gdzie nic się nie
wyświetla. Ramka pełni funkcję marginesu i jest (a w zasadzie była)
konieczna ze względu na krągłości kineskopu oraz to, że rożne
monitory i telewizory mają różnie poustawiane wysokości i
szerokości wyświetlanego pola obrazu czy jego przesuniecie w pionie
i poziomie. Komputery 8- i 16-bitowe posiadają zazwyczaj oddzielny
rejestr do ustawiania koloru ramki, dzięki czemu jest on niezależny
od kolorów właściwego obrazu. Tak jest na przykład w C64.
Ze względu na swoją niedostępność narzuconą przez konstruktorów
sprzętu ramka stanowiła wielkie wyzwanie i była częstym celem
ataków różnych koderów, którzy udowadniali, że jak najbardziej
można na jej obszarze wyświetlać obraz. Powstawały nawet dema
dedykowane tej kwestii, np. „Death of the left border” na Atari ST.
Efekt osiągano różnymi metodami. Na ogół udawało się wymusić DMA
obrazu (Atari ST) albo używało się sprite’ów (C64) po uprzednich
zręcznych zmianach zawartości odpowiednich rejestrów w odpowiednim
czasie . Wyłączenie ramki górnej i dolnej jest mało kosztowne
czasowo, ponieważ dla jednej i drugiej czynność tą wykonuje się raz
na klatkę obrazu. Pozbycie się ramek bocznych jest za to bardzo
kosztowne, ponieważ trzeba wyłączać je w każdej linii obrazu.
Ramka w Atari
Ramka w małym Atari nigdy nie budziła wielu emocji ponieważ jej
istnienie bądź nieistnienie jest kwestią odpowiedniej konfiguracji
ekranu. Aby pozbyć się ramki lewej i prawej wystarczy włączyć tak
zwane "szerokie pole" poprzez ustawienie odpowiedniej wartości w
rejestrze DMACTL ($D400). Natomiast aby pozbyć się ramki górnej i
dolnej należy zmodyfikować DisplayList tak, aby pokrywał ona
wszystkie dostępne linie obrazu czyli 240. O ile jednak w
komputerach z NTSC ta liczba linii pokrywa cały ekran, o tyle w
komputerach PAL nie. Mamy więc na górze i dole ekranu nieduży
niedostępny obszar ramki, zawsze w kolorze czarnym.
Z ramką w Atari jest pewien problem, gdy jednak zależy nam żeby
była. A dokładnie gdy chcemy ją mieć w trybach 4 kolorowych, w
szczególności w trybie E Antica (GR.15). Na przykład chcemy mieć
czarną ramkę oraz obrazek 160x200 w 4 kolorach, ale żaden z nich
nie jest czarny. Albo chcemy w trakcie wyświetlania takiego obrazka
wizualizować proces dekompresji w tle jakichś danych poprzez
wyświetlanie kolorowych pasków na ramce. Tego się nie da zrobić.
Problem polega na tym, że nie można ustawić koloru ramki
niezależnie od kolorów obrazu, tak jak w C64. Kolor ramki jest
bowiem ustawiany w rejestrze colbak ($D01A) i jest on jednocześnie
jednym z czterech kolorów obrazu. Nie ma takiego problemu jedynie w
trybach hires gdzie są tylko dwa kolory obrazu ustawiane w colpf1
($D017) i colpf2 ($D018) oraz właśnie niezależny kolor ramki w
colbak.
Tryb E+
Na szczęście okazuje się, że w Atari można uzyskać niezależny kolor
ramki w trybach 4-kolorowch. W tym celu trzeba wykorzystać znany
trick polegający na włączeniu trybu GTIA (dowolnego), a następnie
wyłączeniu go w trakcie trwania linii obrazu. Niestety jest to dość
kosztowny trick, ponieważ to podwójne przełączenie należy wykonywać
w każdej linii obrazu. Trick ten stosowany jest przeważnie do
uzyskania jednocześnie trzech różnych trybów graficznych obok
siebie: hires – GTIA – lores 4-kolorowy. Nas interesuje jednak
tylko ten ostatni i dlatego przełączenia na tryb GTIA i z powrotem
dokonujemy w trakcie tak zwanej "przerwy poziomej", pomiędzy dwoma
liniami obrazu. W DisplayList ustawiamy tryb hires czyli na
przykład tryb F Antica, jeżeli chcemy uzyskać tryb E. Oczywiście to
co uzyskujemy to nie jest prawdziwy tryb E tylko bardzo do niego
zbliżony. Ja nazwałem go wstępnie E+ (ponieważ mamy w nim 4 kolory
+ niezależny kolor ramki) albo też F2E (ponieważ powstaje on przez
zamianę trybu F na E). Różnica jest taka, że ANTIC nadaje dane w
formacie dla trybu F, a GTIA interpretuje je jako dane dla trybu E.
Dzięki temu zmieniają się przypisania rejestrów kolorów do
konkretnych kombinacji bitów obrazu. Tabela poniżej obrazuje te
przypisania a także stan magistrali pomiędzy układami ANTIC i GTIA
(AN2,AN1,AN0):
kombinacja bitów obrazu - kolor |
rejestr trybu E |
AN2-AN0 trybu E |
rejestr trybu E+ |
AN2-AN0 trybu E+ |
00 – kolor 0 |
colbak ($D01A) |
000 |
colpf0 ($D016) |
100 |
01 – kolor 1 |
colpf0 ($D016) |
100 |
colpf1 ($D017) |
101 |
10 – kolor 2 |
colpf1 ($D017) |
101 |
colpf2 ($D018) |
110 |
11 – kolor 3 |
colpf2 ($D018) |
110 |
colpf3 ($D019) |
111 |
ramka |
colbak ($D01A) |
000 |
colbak ($D01A) |
000 |
Zdjęcia poniżej ukazują efekt wyświetlania różnokolorowych pasków
na ramce poprzez zmianę wartości rejestru colbak w trybie E oraz
E+:
Paski z użyciem rejestru colbak w trybie E
(GR.15)
Paski z użyciem rejestru colbak w trybie
E+
Tryb E+ nie jest jakimś nowym odkryciem, raczej stanowi odmienne
podejście do trybu 4-kolorowego. Emulatory, które pozwalają
wyświetlić wspomniany trick z trzema trybami graficznymi w linii, z
pewnością wyświetlą też poprawnie ten tryb. Praktyczne zastosowanie
trybu E+ jest bardzo ograniczone ze względu na wspomniany koszt
czasowy. Ponadto ramkę można też zasymulować przy pomocy obiektów
PMG co, wydawałoby się, czyni ten tryb zupełnie niepotrzebnym, no
ale może przecież wystąpić sytuacja, w której wszystkie PMG są
wykorzystane do podkolorowania obrazka i wtedy E+ będzie jedynym
wyjściem. Na koniec jedna dość ważna uwaga techniczna. Teoretycznie
do włączenia E+ należy włączyć na chwilę dowolny tryb GTIA. W
praktyce należy zawsze włączać tryb GR.11 (wartość $C0 w rejestrze
$D01B), ponieważ przy pozostałych dwóch trybach występują pewne
niestabilności w miarę nagrzewania się układu GTIA.
Wysoka ramka 300/i600 w PAL
Całkiem niedawno
Gary "Rybags" Ryan wyjaśnił na czym polega
bug ANTIC-a objawiający się zrywaniem synchronizacji pionowej, gdy
ostatnia 240-sta linia ekranu jest wyświetlana w trybie hires (tryb
2, 3 albo F ANTIC-a). Okazało się, że linie AN2, AN1 i AN0
magistrali między układami ANTIC i GTIA w momencie uaktywnienia
bugu zostają ustawione na stałe na 1 (stan wysoki) i utrzymują taką
wartość wtedy, gdy włączone jest DMA obrazu. Oznacza to, że ANTIC
nadaje do GTIA informację, że wyświetlanie obrazu nadal jest
aktywne. GTIA odbierając 1 z linii AN2 nadal jest skłonna
wyświetlać treść odbieraną od ANTIC-a na liniach AN1 i AN0.
Ostatecznie to co jest wyświetlane po linii 240 to obraz w trybie
hires składający się z samych jedynek. DMA obrazu niestety nie
działa, choć jest włączone. Nie można więc wyświetlić normalnego
obrazu, ale przynajmniej można wpływać na wyświetlany kolor. To
oznacza, że jednak można ingerować w niedostępny dotąd obszar
poniżej, a także powyżej środkowych 240-stu linii. Powyżej też,
ponieważ działanie bugu rozciąga się aż do przekręcenia licznika
linii ANTIC-a na 0, czyli do pierwszej linii z DisplayList
następnej klatki. Oczywiście należy pamiętać, że z powodu bugu
ANTIC-a nie jest generowany sygnał synchronizacji pionowej i trzeba
go wygenerować programowo – podobnie jak robi to Rybags dla trybu
interlace. W naszym przypadku trzeba to jednak robić w każdej
klatce, a nie w co drugiej.
W systemie PAL w trybie interlace klatka obrazu składa się z 625
linii, z czego 25 jest zawsze wygaszonych (w Atari mamy 624 linie w
trybie interlace sprzętowym i 312 normalnie). Pozostałe 600 zawiera
treść obrazu, choć w praktyce widoczne jest jakieś 520-580 zależnie
od monitora/telewizora. Oznacza to, że w trybie bez interlace’u,
czyli takim jaki mamy standardowo w Atari, treść obrazu może być
wyświetlana aż w 300 liniach. W załączonych przykładach faktyczna
wysokość obrazu to 296 linii w trybie standardowym i 592 linii w
trybie interlace. Dokładnie tyle udało się zobaczyć na monitorze
Commodore 1084S po maksymalnym zwężeniu obrazu w pionie. Takiej
ilości linii nie da się wyświetlić raczej na żadnym telewizorze.
Nie ma jednak problemu (w kodzie), by zwiększyć tę ilość do
odpowiednio 300 i 600, a nawet więcej, choć to pewnie zakończyłoby
się zerwaniem synchronizacji. Można zatem uznać, że
w Atari mamy
możliwość ingerencji w treść obrazu na jego pełnej wysokości
zdefiniowanej dla systemu PAL.
W przypadku wysokiej ramki w trybie interlace (sprzętowym) sprawa
jest nieco bardziej skomplikowana niż w trybie standardowym,
ponieważ konieczne jest generowanie sygnału synchronizacji pionowej
na dwa sposoby – w zależności od tego, który półobraz ma być
wyświetlany. Zdjęcie poniżej pokazuje przebieg złożonego sygnału
synchronizacji dla obu półobrazów. Kod, który zaprezentował Rybags,
generuje dokładnie taki sygnał, jaki widzimy w liniach 313-315. Na
podstawie zależności czasowych w jego kodzie udało mi się napisać
analogiczny dla linii 1-3. Co ciekawe, linie drugiego półobrazu
(„Drugie pole”) czyli tego rozpoczynanego przez kod Rybagsa
wyświetlane są o pół linii wyżej niż linie pierwszego półobrazu.
Wydawałoby się że powinno być odwrotnie, ale tak nie jest. Być może
ma to związek z faktem, że Atari generuje 624 a nie 625 linii.
Złożony sygnał synchronizacji w systemie
PAL
Jest pewna wada wysokiej ramki na którą nie ma rady. Mianowicie
jest ona tylko tak szeroka jak szerokie pole wyświetlania. Jak
wiadomo, szerokie pole nie jest symetryczne względem standardowego.
Z lewej strony jest go trochę mniej niż z prawej. To powoduje, że
mamy lekkie ubytki wysokiej ramki, oczywiście tylko w obszarze poza
standardowymi 240-stoma liniami. Widać to na zdjęciach w lewym
górnym i lewym dolnym rogu. Obraz na monitorze 1084S jest jednak
trochę zwężony. Na większości monitorów/telewizorów nie powinno być
widać tej niedogodności.
Wysoka ramka a obiekty PMG
Okazuje się, że GTIA może wyświetlać obiekty PMG (sprite’y) na
wysokiej ramce. Oczywiście poza standardowymi 240-stu liniami DMA
sprite’ów nie działa podobnie jak DMA obrazu. Można jednak wpływać
na kształt sprite’ów poprzez rejestry $D00D-$D011. To daje
możliwość wyświetlania nieskomplikowanej grafiki na wysokiej ramce.
Należy pamiętać, że wysoka ramka to tryb hires z samymi jedynkami.
To oznacza, że wszystkie piksele ramki mają zawsze priorytet nad
sprite’ami jeżeli chodzi o jasność, natomiast przejmują barwę
sprite’ów. Aby uzyskać pełną niezależność kolorów sprite’ów od
koloru ramki oraz ich wyższy priorytet należy użyć jednego z trybów
GTIA lub opisanego wcześniej E+. W trybach GR.9 i GR.11 nie można
uzyskać dowolnego koloru ramki, co wynika ze specyfiki tych trybów
oraz z faktu, że treść obrazu ramki stanowią same jedynki. W trybie
GR.10 oraz w E+ możemy ustawić dowolny kolor ramki. W trybie E+
kolor wysokiej ramki ustawiamy w rejestrze colpf3 ($D019). W trybie
GR.10 również w rejestrze colpf3 dla większości powierzchni ramki
oraz dodatkowo w colbak($D01A) dla pierwszego piksela (kolumny) od
lewej. Powiązanie pierwszego piksela z rejestrem colbak ma związek
z faktem przesunięcia o jeden piksel właśnie całego obrazu w trybie
GR.10 względem obrazu w trybach GR.9 i GR.11. W trybie GR.9 jasność
wysokiej ramki jest maksymalna (15) a o barwie decyduje rejestr
colbak. W trybie GR.11 barwa wysokiej ramki jest
pomarańczowo-brązowa (15) a o jasności decyduje rejestr colbak. W
załączonych przykładach używany jest tryb GR.10.
Paski i sprite’y na wysokiej ramce
Sprite’y na wysokiej ramce
Paski i sprite’y na wysokiej ramce w
sprzętowym trybie interlace
Sprite’y na wysokiej ramce w sprzętowym
trybie interlace
Praktyczne wykorzystanie wysokiej ramki jest dość ograniczone.
Przede wszystkim dlatego, że nie można założyć takiej jej
wysokości, dla której byłaby pewność, że jest ona widoczna na
wszystkich monitorach/telewizorach. Niemniej jednak cieszy fakt, że
w małym Atari możemy mieć kontrolę nad całą powierzchnią ekranu, a
nie tylko nad 240 liniami. Niestety efektu wysokiej ramki nie
zobaczymy na żadnym z istniejących emulatorów. Przykładowe programy
wyświetlające wysoką ramkę nie będą też działać poprawnie na
komputerach w systemie NTSC.
Uwaga! Powyższe zdjęcia w wyższej rozdzielczości (1024x768) oraz
pliki ilustrujące efekty opisane w artykule dostępne są
tutaj.
-----
Update z dnia 9 września 2009 roku: Pavros podesłał
źródła użytych programów.