80 RECTANGLES

Radek Štěrba, RASTER

Na první ročník 8bitové demoparty Forever 2e3, která se konala v minulém roce v Trenčíně, jsem si připravil příspěvek do kategorie Intro 1024 bytes - tj. demonstrační prográmek limitovaný maximální délkou 1024 bytů. Měl jsem velkou radost, že můj výtvor návštěvníky zaujal a ve své kategorii na Atari zvítězil. Pokud jste si už toto Intro pustili a zajímá Vás, jakým způsobem je tento efekt udělán, čtěte dále.

Program předvádí plynulý (50 snímků za sekundu) pohyb 80 různě velkých obdélníků v nejjemnějším grafickém módu přes sebe, což v součtu představuje přesun 18560 pixelů každou 1/50 sekundy. Pokud znáte alespoň částečně výkonnostní parametry Atárka, je vám jasné, že toto není teoreticky možné stíhat. Ovšem prakticky ano, za pomoci několika triků.

Trik 1.
Vodorovné strany obdélníků nejsou vůbec vykreslovány - na to je použita PMG. X-ová pozice PMG hráče je měněna v každém zobrazovacím řádku, celkem je tedy jediné "PMGéčko" využito na všech 80 horních i 80 dolních stran všech obdélníků. Pokud přemýšlíte, jak posouvám PMG objekt vlevo-vpravo s přesností na jeden bod nejjemnější grafiky, když PMG lze posouvat minimálně po dvou bodech, tak je využito toho, že do pozadí na krajní pozice strany jsou dokreslovány pixely v GR.8. Tyto již jsou posouvány jemně, ale PMG je posouváno jen jednou za dva posuny pixelů, takže se buď s koncem strany jedním bodem překrývají, nebo stranu o jeden bod prodlužují. PMG i GR.8 mají nastaveny stejné barvy, důsledkem je tedy zdánlivý posun po jednom pixelu.

Trik 2.
Jak známo, velikost videopaměťi celé obrazovky je dána vynásobením počtu řádků videopamětí potřebnou pro každý řádek. V případě grafiky 8 je to 40 bytů na řádek. 160 řádků by tedy znamenalo 6400 bytů videopaměti. Ne však v případě tohoto Intra. Pomocí displaylistu je zde totiž definováno, že videopaměť všech řádků začíná na stejném místě - celá obrazovka tedy využívá pouze 40 bytů. Logickým důsledkem je, že vše co namalujeme do "prvního" řádku se zobrazí i na všech dalších. Tudíž v takovém grafickém módu můžeme malovat pouze svislé čáry shora dolů přes celou obrazovku, nic menšího (žádné jednotlivé pixely). Dost nepoužitelná grafika pro normální účely, říkáte si asi, ovšem my přece nepotřebujeme žádnou normální grafiku. A teď přijde jádro triku. Do 40 bytové videopaměti připisujeme postupně až během vykreslování obrazu, takže bodík, který jsme tam zapsali těsně před tím, než se vykresloval na obrazovku první řádek, se zobrazí na prvním řádku. Před druhým řádkem přikreslíme do té samé videopaměti bodík další, což způsobí, že se na druhém řádku objeví jednak opět bodík z prvního řádku a navíc i bodík druhý. A tak dále - před vykreslováním každého řádku na obrazovku vždy dokreslíme do videopaměti další bodík. Ve výsledku dosáhneme zobrazení svislých čar, kde každá bude začínat o 1 řádek níže. X-ovou pozici těchto celých čar přitom ovládáme vždy pouze pozicí příslušných horních bodíků. Aby svislá čára nevedla až úplně dolů, v dolní polovině vykreslování obrazovky naopak jednotlivé bodíky odmazáváme.

Protože svislé strany obdélníků jsou dvě, v horní polovině tedy během vykreslování obrazu v každém řádku přidávám 2 body a v dolní části opět v každém řádku dva odmazávám. Tím mám tedy k dispozici 2 x 80 svislých úseček.

Ve skutečnosti to však není tak jednoduché, jak je zde popsáno, neboť rychlost procesoru nestačí ani na to, aby stíhal v každém řádku změnit pozici PMG a domalovat či smazat dva grafické body. Na to je použit další trik.

Trik 3.
Výpočty pro postupnou změnu obsahu videopaměti nejsou prováděny až během vykreslování obrazu, ale během VBI. Vypočtené hodnoty, obsahující určení které byty se mají měnit a na jaké hodnoty, se průběžně ukládají do polí a jsou použity "právě v čas" při vykreslování obrazu. I tak se to stíhá těsně a spousta věcí musela být maximálně optimalizována. Další optimalizace byly nutné kvůli omezení velikosti na maximálně 1024 bytů, ale nakonec se vše podařilo.