Programozástechnika: Border multicolor effekt

5 csillagos Cikk értékelése: 5,00 (22 szavazatból)

Először is tisztázzunk néhány alapgondolatot. A Spectrum képernyője két, jól elhatárolt területből áll. Az egyik a háttér (BORDER) a másik a hasznos terület. A teljes képernyő 312 sorból áll, ebből 68 sor a felső és az alsó részen látható. A köztes 176 sor érdekesen épül fel, ugyanis bal és jobb oldalon 48 pixel háttér és közötte 256 pixel hasznos képterület látható. Továbbá a háttérnek egy szín határozható meg, míg a képernyő 256*176 részén 8*8 pixel (1 karakter) kaphat 1 papír és 1 tinta színt. Mégis, hogy lehet becsapni a rendszert multicolornak nevezett effekttel?

Ehhez még egy alapdolog tartozik. Az elektronsugár a képernyő bal felső sarokjából indulva rajzolja meg soronként a képet. 48K-s gép esetében 1 sor kirajzolása 176T időt igényel, majd még 48T időt amíg az elektronsugár visszafut a következő sor elejére. A 'T' idő tulajdonképpen 3.5Mhz-re számított 1 időegység. Ebből következően az első sor végéig 224T telik el, 2. sor végéig 448T, és így tovább. A teljes képernyő kirajzolása 69888T egységbe telik a processzornak.
A 128K-s gép képkezelése eltérő a 48K-tól. Először is 228T egy sor előállítás, vagyis 4T-vel több. Másodsorban 311 sorból áll a képernyő, így 70908T a teljes kép előállítása. A képernyő címzés viszont ugyanaz. Plussz szolgáltatása a 128k-nak, hogy az 5. memórialap első 6912 byte-ja rálapozható a képernyőmemóriára, így gyakorlatilag 2 képernyőnk van egyszerre, ami azért nagyon jó, mert amíg az egyikre rajzolunk, addig a másik látható és fordítva. Ettől teljesen el fog tünni a "mákhatás". Sajnos annak idején ezt nem tudták kihasználni, mert koncepció volt, hogy a játékprogiknak el kell futni 48k-s gépen is. Ez azonban ma, az emulátorok korában már nem szükséges.

Ahogy az elektronsugár halad, folyamatosan figyeli, hogy milyen színnel kell dolgoznia. A háttér készítésekor a BORDER értékét, a képernyőnél az adott sorhoz tartozó PAPER és INK színt.

Már csak egy dolog kell a multicolorhoz. Tudni kellene, mikor indul az elektronsugár a képernyő tetején. Ez szerencsére elég egyszerű, mivel a HALT utasítás is alkalmas a szinkronizálásra, de a 2-es megszakítási rendszer is ezzel egyidőben kapja meg a vezérlést ( a 2-es megszakítás egy olyan programrész, amely minden 50-ed másodpercben következik be és szabadon programozható).

Nincs is más teendő, mint ahogy az elektronsugár halad, a megfelelő pillanatokban megváltoztatni a színt és így az már a megváltozott színnel rajzol tovább! Ha pedig a változtatást minden képváltásnál megcsináljuk, akkor folyamatosan ugyanazt a képet látjuk, így tulajdonképpen becsapjuk vele a rendszert.

Természetesen rengeteg korlátba botlunk, amikor ezt próbálgatjuk. Először is eszünkbe jut, hogy "hohó, akkor nagyon sűrűn kell változtatni és akkor szinte pixel-colort csinálhatunk !". Ez sajnos lehetetlen. Minden gépi kódú utasítás végrehajtásának processzor ideje van (T). Még a legegyszerűbb gépi kódú utasítás végrehajtása is 4 T idejébe kerül a processzornak és eközben az elektronsugár száguld tovább. Nézzünk egy egyszerű példát:

A háttér színe eredetileg sárga.

LD A, 2 beállítjuk a piros színt
OUT (254), A a háttér színét erre állítjuk
LD A, 1 kék szín
OUT (254), A a háttér színét erre állítjuk

Az LD utasítás 7 T, az OUT utasítás 11 T ideig tart. Ha a programunk első utasításánál az elektronsugár a bal felső sarokban van, akkor a következő történik. A háttér 18 T egységig sárga marad (ez 36 pixel). Innentől piros lesz újabb 36 pixelen keresztül, majd kékre vált és a képernyő aljáig az marad. Tehát látható, hiába is igyekszünk nagyon sűrű színváltást a végrahajtási idő miatt nem tudunk csinálni (természetesen ha más utasításokat használunk, ez még rövidíthető, de 12 T alá menni értelmesen nem lehet).

Ha egy színt tovább is szeretnénk kitartani, akkor várakozni kell. Erre egy ciklus is alkalmas, de figyeljük meg, mi okozza a nehézséget:

LD A, 2
OUT (254), A
LD B, 50
c1 DJNZ c1
 
LD A, 1
OUT (254), A

Itt beépült egy várakozás (DJNZ utasítás csökkenti a B regiszter értéket amíg 0 nem lesz és csak azt követően megy tovább), ami végrehajtási idejét pontosan ki kell számítani ahhoz, hogy tudjuk hol vált majd a szín:

7 T + 11 T után 36 pixelen sárga a szín aztán kékre vált és az marad, de meddig is ?

LD B, 6 7 T
DJNZ nos itt már 2 érték is van: B<>0 esetén 13 T, B=0 esetén 8 T

Tehát: 7 T + 49*8 T + 11 T = 410 T vagyis ez a 2. sor vége felé esik (illik pontosan kiszámolni, de most nincs lényege).

így aztán lehet variálni a háttérrel. De mi a helyzet a képernyő PAPER és INK részével ? Hiszen az URIDIUM például egy karakteren belül soronként más színt jelenít meg ?

Az elv hasonló. Amikor az elektronsugár odaér a kívánt ponthoz, kiolvassa a színt és megjeleníti. Ezt követően a következő sorban fogja újra kiolvasni, tehát van időnk átírni a ponthoz tartozó színértéket és így más szín jelenik meg. így is azonban 1 karakteren belül csak soronként lehet színt váltani, 8 pixelen belül nem. Sőt itt még egy apró hardver dolog is közbe szól, ami miatt még időkiesés is van, de ezt most nem ecsetelem.

Programozni természetesen egy álló képet elég egyszerű, de például számos DEMO-ban láthatunk mozgó effektet a háttérben. Ezek mind a pontosan kiszámított időzítéseken alapulnak. Az időzítések az idő rövidsége miatt sajnos nem szervezhetők egyszerűen ciklusokba, sokszor csak látszólag felesleges utasításokkal lehet beállítani a pontos T időegységet. Az is látható, hogy "hasznos" műveletekre ilyen effektnél nemigen marad idő, így általában "csak" a billentyű figyelés marad, majd egy gombnyomás után eltűnik az effekt. Játék alatt pedig összetettebb effektről szó sem lehet (azért láthatunk néhány szépet, pl: AQUAPLANE, ACADEMY háttében látható szép vonala.

Még egy érdekesség, de ezt csak Edy tudja megerősíteni, én csak olvastam róla: Számos újabb készítésű program a képrajzolás során arra is figyel, hogy lehetőleg akkor írjon a képernyőre, amikor az elektronsugár már túlhaladt a pozícióján, mert így el tudják kerülni a zavaró vibrálás, "havazás"-t. Nos ehhez már kell programozni...

Gyakorlati tippek:

  • Ne számoljunk túl pontosan a műveleti időkkel, csak közelítsünk. Ezzel rengeteg időt és energiát spórolhatunk meg.
  • Folyamatosan teszteljünk, és próbáljuk debuggerrel módosítani a késleltetéshez használt ciklusregiszterek értékét mindaddig, amíg a lelhető legközelebb nem kerülünk a kívánt hatásig.
  • A ciklusmag a lehető legkevesebb utasításból álljon.
  • Hosszabb késleltetésekhez érdemes beágyazott ciklusokat használni.
  • A késleltetés tulajdonképpen bármilyen rutin lehet, ami belefér az adott időbe. Így akár beépíthető scroll rutin, hanglejátszás stb.
Néhány példa multicolorra

A csatolt fájl tartalmazza az UpperLine c. effekt részletes leírását és PGyuri általam lektorált elméleti bemutatóját a témáról.
Amit tudni kell:

  • Az effektek PC-n készültek, sosem látta őket igazi Spectrum.
  • Tesztemulátorok: RealSpectrum12, Spectaculator, R80, ES.pectrum.
  • A multicolor.tap kazi egy basic navigátorral kezdődik, melyből betölthetők az egyes effektek. A példaprogramokból a SPACE megnyomásával lehet visszatérni a Basic programhoz. Az effektek 32768 (0x8000) címtől vannak lefordítva, így külön-külön a RANDOMIZE USR 32768 utasítással indíthatók.
  • CSAK 48K-s MODELLEN FOG JÓL MŰKÖDNI!!!

Publikálás a portálon: 2002-06-18 09:33:00