Retrocomputing by Macc

2015 Február 20.

Bele is vágnék a közepébe: kb. 8 éve egy akkori kollégám szerzett nekem egy régi Mac-et kerek 2500 Forintért, pontosabban egy Mac Classic II-t. Mivel mindig is szerettem a Macintosh gépeket, így nagy örömmel fedeztem fel a régi kis gépet, volt rajta egy használható rendszer, szépen boot-olt, bár programok nem nagyon voltak hozzá, de elsőre megkedveltem a kis fekete-fehér kijelzőt. Mivel nem sokat tudtam a gépről, így kicsit meglepődtem, hogy még szürke árnyalatokat sem tudott megjeleníteni, csak fekete v. fehér pixeleket. Na abban a pillanatban kapott el az az érzés, hogy régi nagy c64-es kedvencemet a Head over Heels-t jó lenne portolni erre a gépre. A gond csak az volt, hogy kb. semmit nem tudtam arról, hogy hogyan is lehetne ehhez hozzálátni...

Azóta eltelt jó néhány év, a gép egy szekrény alján porosodott, mikor újra elővettem már be sem kapcsolt... Azaz bekapcsolt, de csak néhány zavaros csík volt a képernyőn, a boot-gong meg sem szólalt. :(

Ekkor kezdődött el egy kisebb kutató munka, hogy mit is lehet kezdeni a helyzettel, és kiderült, hogy ezekben a gépekben szeretnek elfolyni az elöregedett elektrolit-kondenzátorok(?) - Tehát rendeltem újakat, a gépet szépen alkatrészeire szedtem, megpucoltam, régi kondikat leforrasztottam, újakat a megtisztított helyükre tettem, és láss csodát, újra működött szépen! Bla-bla-bla, mielőtt túl unalmas lenne az egész történet, átugranám az elhalálozó régi SCSI vinyók kálváriáját, a lényeg, hogy most már van négy öt tökéletesen működő öreg Mac-em (Mac Classic II, Mac LC, Mac LC III, Mac IIci, saját 13" RGB Apple Display-el + Mac LC 475), ebből kettőben vinyó helyett egy AztecMonster SCSI-CF CARD adapter dolgozik, ezeket használom most fejlesztésre...

Hosszas kutatómunka után, most már működő telepített fejlesztői környezet fut a régi gépeken (Metrowerks CodeWarrior 4), az online elérhető dokumentációkat mind letöltöttem, amit nem lehetett, megrendeltem (Inside Macintosh Volume IV, V, VI).

Jelenleg ott tartok, hogy elkészült első c64 intro jellegű programom Mac-re. Itt most tennék egy rövid kitérőt: c64-en tanultam programozni, csináltam rá sok intro-t, pár bénább demo-t, a lényeg hogy a hardver közvetlen kódolása, a spórolás a RAM-mal, és a bitek közvetlen manipulációja az agyamba égett. Ezek a dolgok máig hiányoznak a mai munkáimból. Éppen ezért ezeken a régi gépeken nem izgat különösebben egy ablakos program létrehozása gombokkal, listákkal, lassú recegős animációkkal. Ezek tonnaszám elérhetőek, a régi Mac-es játékok egyáltalán nem nyűgöznek le (azért akad persze 1-2 kivétel, de azok sem a jó vizuális effektjeikkel hatottak rám). Mivel az ősi c64-en szinte minden játék gyönyörűen, vaj sima animációkkal futott (50fps), nagyon hiányoltam a képernyővel szinkronban futó sima, gyors animációkat. Már-már beképzeltem, hogy ezeken a gépeken ilyet nem is lehet csinálni, de mint hamarosan kiderül, lehet...

Ugye C64-en, Amigán, vagy egy Game-Boy-on van egy csomó hardveres opciónk, hogy hogyan is manipuláljuk a képernyőn megjelenő tartalmat, eltolhatjuk bitenként erre vagy arra, csak egy pár bitet kell megváltoztatnunk egy regiszterben, vagy ugyanilyen egyszerűen váltogatunk képernyő üzemmódok között, megfelelő raszterpozíciónál megszakítást válthatunk ki, és lám kész is vannak a szép rasztertrükkök, de Mac-en (és most a régi motorola 68k procis szériáról beszélek) ezekből nincsen semmi, van egy halom képpontunk, egy felbontásunk (monitor függő), és a legjobb amit tehetünk ha az oprendszert megkerülve, közvetlen a Video RAM-ba irkálva, elfoglaljuk a terepet. Szóval bármi lehetséges, csak számoljon a proci jó gyorsan. Én 2 gépre koncentrálok most fejlesztés közben, az egyik (a munkaállomás) egy Mac LC III (1993-ból, 36 MB RAM, motorola 68030 25 MHz, 640x480 max. 32 bit/pixel kijelzővel) és egy Mac Classic II (1991-es, 10 MB RAM, motorola 68030 16 MHz, 512x342 1 bit/pixel), és az első benyomások elég meggyőzőek, már ami a sebességet illeti, pedig még teljesen optimalizálatlan a kódom, azaz sima C-ben íródott minimális assemblyvel keverve. Meggyőző alatt azt értem, hogy egy félképernyős stretch effekt 60 fps sebességgel fut, és még a rendelkezésre álló erőforrás felet sem használtam ki.

A Head over Heels port projekt

A mozgatórugója annak a sok mindennek amit most csinálok, a címben szereplő régi kedvenc portolásának megvalósíthatóságára való törekvés. Magyarul, ahhoz, hogy megszülethessen a játék Mac-en (Ha elkészül, szerintem a platform egyik legjobb játéka lesz, ami elsősorban az eredeti játék készítőinek érdeme), először is meg kell tanulnom gyorsan manipulálni a pixeleket a képernyőn, és büszkén jelenthetem ki, hogy ez meg is történt. Ez rengeteg elfeledett dokumentum átolvasásának az eredménye, amit még több on-line kutatás előzött meg.

Az egészben az volt a legproblémásabb, hogy amit akarok, az abból a szempontból rendhagyó, hogy a képernyő közvetlen módosítását legtöbben kifejezetten nem ajánlják (érthető okokból), ezért ezekről nagyon kevés információ áll rendelkezésre, valamint egy régi elfeledett, amúgy sem a legnépszerűbb platformról van szó. Az én szívemhez viszont nagyon közel áll, mégiscsak ugyan az a szív dobog benne mint egy Amigában:)

Szóval minden adott, a HOH pont egy olyan játék, amihez nem kell semmi spéci video effekt, csak egy 2 bites képernyő, és némi erőforrás, mert a c64 azért rendesen megizzadt az izometrikus pálya renderelésével. Az eredeti játékból a grafikáját könnyen ki lehetett szedni, a felbontás különbség viszont kicsit gondolkodóba ejt: 320x200-ra optimalizált grafikát 512x342-n nem egyszerű megjeleníteni. 1:1-ben egyszerűen apró lenne az amúgy is kicsi (9") kijelzőn, 2-szeres felbontásban (ami viszont ideális a 640x480-hoz) meg már nem férünk el, úgyhogy jelenleg egy 150%-os nagyításon gondolkozom, ami egy sor további problémát vet fel, de ezt majd később.

Na kicsit átugranék a C64-es vonalra, mert ugye a portolni kívánt játék eredetije azon fut. Sok szempontból szerencsém van, mert a játék kb. 45 KB, így egy sima memória snapshot-tal kinyerhető minden információ. Kis ügyeskedéssel gyorsan meg lehet szabadítani a kinyert adatokat a feleslegtől, megvan a belépési pont is ($5B03). Kis matatás árán rögtön megvoltak a grafikai elemek (Jelen pillanatban a pislogás és a pálya pereme meg nincs meg), valamint a teljes disassembly. Ezt jókedvemben ki is nyomtattam, lett kb. 150 oldal. Jegyzetelni, átfutni jó lesz. A következő fázis a programkód értelmezése, vagyis visszafejtése. Ez egy igen jópofa feladat, és hozzá sem látnék, ha nem ismernem jól a c64-es gépikódját. Na de amitől ez a rész érdekes, hogy a kinyomtatott listán, főleg egy 8000 soros assembly programlistán eligazodni nem egyszerű. Ezt megkönnyítendő, írtam egy speciális c64 emulatort...

Saját c64 emulator

Na szóval, biztos sok hasonló létezik, nem tudom, nem találtam, de nekem egy olyan emulator kellett, amivel futás közben látom a teljes C64 memóriáját, nyomon követhessem a program futását, írást/olvasást, a regiszterek állapotát, a Stack-et oly módon, hogy a program belépési pontjától nyomon követhető legyen milyen szubrutinokat hívott meg a kód, ezt log-olja, disassembly-t keszit kommenttel (hogy éppen pontosan milyen érteket honnan, hova mozgat). Na most ez az emulator már eddig is sokat segített, pedig még szinte el sem készült. Segített megérteni, hogyan építi fel az izometrikus tér részleteit a kód, valamint, hogy a kód melyik része fut mikor épp ez történik, stb.

A terv

A folyamat neheze most következik, és ez válaszút elé állít... Két lehetőségem van: vagy vert izzadok hosszú időn át, és megfejtem a program működését, vagy az alapján amit látok, érzékelek megírom a játékot.

Nyilván egyik sem egyszerű, a kérdés az, van-e értelme az eredeti kódot visszafejteni, és ha igen, milyen mértékben. Mi az amit meg lehet figyelni egy játékon, és mi az amihez pontos számszerű adatok kellenek, hogy klónozni lehessen. Kérdés az is, hogy mennyire ragaszkodjak az eredetihez, és min kellene javítani?

Mivel a játék úgy jó, ahogy van, a legjobb lenne mindent úgy hagyni, ahogy van, de van pár dolog amin azért mégis szeretnék illetve változtatni kell:

Kódolas Mac-en

Miután félkész állapotba került az emulator, kis klíma változásként elkezdtem a kódolást a Mac-en. Nehezen vettem rá magam, mivel teljesen idegen környezet volt. Egyrészt sosem programoztam C-ben. Régebben sok forráskódot olvastam már, néhányon módosítgattam pár dolgot, de sosem írtam C programot, főleg nem a semmiből. Szerencsémre viszont a Mac-en futó CodeWarrior 4 eddig teljesen stabilnak bizonyult (korábban kínlódtam egy sort az MPW-vel, de szerencsére sokat fagyott, mert a CW jobb, és kisebb kódot is generál*), így viszonylag gyorsan eljutottam arra a szintre, hogy OS-ből indítható app, közvetlenül és zavartalanul írjon a képernyőre, VBL azaz Vertical Blanking Interrupt (megszakítást) használjak a sima animációkhoz, és szépen kilépjek a programból vissza a rendszerbe. Ennek a tesztelésnek lett az eredménye egy kis intro (amiről korábban már említést tettem), egy scroller-rel, és egy hullámzó "logo"-val vagy nevezzük annak aminek akarjuk... * Valamiért szeretek tudni minden byte-rol a programjaimban (már ahol ez lehetséges), és kifejezetten zavar, ha olyan kód van benne, amit nem is futtatok soha.

2015 Március 04.

Egy kis idő eltelt az utolsó mondat óta, közben létrejött pár dolog ami a projekthez tartozik. Folytatva a Mac-en kódolást, megszületett a 2-es számú Mac Intro is, melyben egy kicsit nagyobb grafikát sikerült szép gyorsan megmozgatni a képernyőn, (Mac Classic-on meg nem az igazi) valamint egy DYCP scroller is készült. Lásd majd a kepéken, JS demo-ban...

Kódvisszafejtés II.

Nagy lökést adott a kódvisszafejtésnek, hogy egy egyszerű script segítségével, az összes rutin kapott egy hívás listát, a kód és adatblokkok szét lettek választva és sorszámoztattam őket, valamint egy másik kis script-tel a program összes változóját is listába szedtem kiemelve azok elérésének helyét módját, ez utóbbi egy 5000 soros lista lett, kb. így kell elképzelni:

       7743 - STA $5B2C        ; $5b2c-be visszairas.
       a60a - LDA $5B2C
       a60f - STA $5B2C
5B2D:  796d - LDA $5B2D
5B2E:  5c1f - LDA $5B2E        ;4. frame-re var... (ill 4 frame utan nullazodik)
       5c26 - STA $5B2E
       95f9 - DEC $5B2E        ; csokkentjuk $5b2e-t, a frame counter-t
       95fe - INC $5B2E        ; ha negativ lett vissza 0-ra

; CODE block 3 ---------------------------------------------
5C6F:  5c54 - STA $5C6F
5C73:  5c4e - STA $5C73

; DATA block 4 ---------------------------------------------
5CE2:  5ccc - LDX $5CE2
5CE3:  5ccf - LDY $5CE3
5CE4:  5cd5 - LDX $5CE4
5CE5:  5cd8 - LDY $5CE5

Az előző kódrészlet értelmezése: Változó címe: hivatkozás címé - kód ami a változóra hivatkozik (írja és/v. olvassa).

A Rutinok hívás listájának összeállítása egyszerűen úgy történik, hogy a kódban megkeressük minden JSR, JMP és Bcc utasítást, és megnézzük hova mutat. A mutatott címnél feljegyezzük, hogy honnan ugrottunk oda. Végigfutva az egész kódon az eredmény egy hosszú lista amiben minden hivatkozott cím után van egy sor címünk, ahonnan hivatkoztunk rá. A kódban a hivatkozott kódrészlet elé raktam zárójelbe a hivatkozás helyet: [JMP] (JSR) {Bcc}

; CODE block 32 ---------------------------------------------
[7846, 8af1]				; JMP hivatkozas
(7bea, 7d9a, 8685, 8a82, 8ac4)		; JSR hivatkozas
.C:84d0  8D AF 84    STA $84AF		; szubrutin kod
.C:84d3  0A          ASL A
.C:84d4  0A          ASL A
.C:84d5  6D CE 84    ADC $84CE

Vannak meg indirekt ugrások a kódban, valamint táblázatból vett értékkel átírt ugró utasítások is, azokat majd a kód behatóbb elemzése után fogom tudni csak feltárni, de hát ugye ez egy nagy kirakós...

A változók (nevezzük így őket) összegyűjtése hasonló módon történik, azaz a kódot átnézzük, és kigyűjtünk minden olyan memória címet ahova ír/olvas a kód, és extraként feljegyezzük, hogy hol is történt ez a kódban, és milyen utasítással. Itt szintén marad egy vakfolt, mégpedig a táblázatokból feltöltött indirekt változók, ezeknek pontos műveleti területe (a változónak nevezett memóriaterület) egy ideig meg rejtély marad. A létrehozott lista nagyon hasznos, egyrészt átlátható melyik változóval hol és mit dolgozik a program, azt is lehet látni, hogy mennyire sűrűn használt egy változó, továbbá, megkönnyíti a konstansok megtalálását is (amiket sehol nem írunk, csak kiolvassuk az értekét). Ezek az információk mind-mind közelebb visznek a program megértéséhez. Csak érdekességképpen megjegyezném, hogy 952 változót használ a játék, továbbá 693 szubrutin hivast, 304 elágazást, és 1274 feltételes elágazást, mindezt 12299 kódsorban...

Apple Macintosh LC475

2015 Március 09.

Közben meglett az új Mac-em is, egy LC 475. Ez a pizzás doboz formájú LC sorozat legerősebb tagja. Azonos, 25 MHz-es órajelen átlagosan 3x gyorsabb mindenben mint az LC III-as, kivéve a lebegőpontos számításokat, mivel jelenleg egy M68LC040-es processzor van a gépben, amiből hiányzik az integrált FPU. A fullos proci, amiből semmi nem hiányzik, már úton van Németországból. Itt jegyezném meg, hogy ez a processzor, az utódjával együtt (68060) szerintem a valaha készített legszebb processzorok.

Motorola 68LC040

Na most a közvetlen VRAM manipulációs terveim kicsit megdőlni látszanak. Egyrészt tetszik, hogy amit a memóriába írok az rögtön meg is jelenik a képernyőn, másfelől viszont mivel az LC475 teljesen másképp kezeli a video memóriát, felvetődik a kérdés, érdemes-e a sok különböző architektúrára optimalizálni a kódot? Mivel a Head over Heels nem igényli az extrém gyors VRAM manipulálást, ezért egyértelműen NEM. Ezt a technikát inkább megtartom intro-k és demo effektek írásához. Tehát sokkal jobban járok, ha a rendszer kompatibilis képernyőkezelést választom (Offscreen GWorld), sebességben sokat nem vesztek, a játékban lévő animációkkal valószínűleg a Mac Classic is bőven elbír. Pont.

Izometrikus pálya renderelése

2015 Március 17.

Bármennyire is szórakoztató a c64-es kódvisszafejtés, rá kellett döbbennem, hogy túl hosszadalmas ezen a módon reprodukálni a játékot. Persze jó érzés, amikor pár órás kutatással megfejtek 1-2 algoritmust, és néhány ködös részlet kitisztul, mégis egy olyan komplex kód megfejtése ami egy izometrikus pályát tárol/renderel kihámozni az ismeretlenség homályából igencsak időigényes lenne, és annak hosszútávon már a munkám látná kárát.

Éppen ezért (és Krissz munkásságát, hatékonyságát látva) a talán hagyományosabb módját választottam a játékátírásnak: nézni, és leprogramozni:) Szóval legelőször az általam legrejtélyesebbnek ítélt problémát akartam megoldani, mégpedig az izometrikus pálya renderelését. Biztos vagyok benne, hogy sokfelé megoldása létezik a dolognak, így hat próbáltam valami használható információt fellelni a neten, ám a legrészletesebb leírás sem érintette az általam kérdéses részleteket. Leginkább sík, azaz 2 dimenziós tile-alapú pályák leképzéséről olvastam csak, azok meg teljesen egyszerűen 2 egymásba ágyazott for ciklussal megoldhatók. Viszont amikor függőleges irányba mozdul el egy test, akkor a for ciklusok kudarcot vallanak.

Két nap fejtörés után meglett a megoldás, és utólag nagyon örülök, hogy nem találtam meg más megoldását, mert sokkal jobb érzés mindig ha az ember maga jön rá a titok nyitjára. A megoldás fájdalmasan egyszerű: az egymásba ágyazott for ciklusokat, amik az éppen aktuális elem renderelő funkcióját hívják meg, nem is kell piszkálni. A renderelő rutinon kell csak kicsit változtatni úgy, hogy abban az esetben, ha az éppen kirajzolandó elem mögött van egy még le nem renderelt elem, akkor azt rendereljuk le először, és így tovább. Megpróbálom a problémát és megoldását vizuálisan is részletezni.

Az izometrikus nézettel sima 2D technológiával jeleníthetünk meg 3d-s teret, vagy egyszerű 2D-s játékteret jeleníthetünk meg kvázi 3d-ben. A szépsége a dolognak az egyszerűsége. Egy sima 2D-s tile alapú játékteret így alakítunk izometrikussá:

iso_1

Izometrikus térben, a sima 2D-s felülnézeti pályánk 3D hatasúvá válik. Ha az elemeket egymás tetejére pakoljuk, akkor valódi 3D-s teret alkothatunk, aminek megjelenítésére tökéletesen alkalmas az izometrikus nézet:

iso_2

Amíg minden elem rácsra van igazítva, addig a renderelés is pofon egyszerű, csak hátulról előre, és lentről felfelé kell haladni a rajzolással. Tehát például 3 egymásba ágyazott for ciklus szépen teszi a dolgát. Ha viszont mozgásnál szép folyamatos animációt akarunk látni, akkor nem ugorhatunk egyik pontról a másikra, hanem két rácspont között az utat több lepésben kell megtennünk, ahol a korábbi módszer már kudarcot vall:

iso_3

Ahhoz, hogy az elemeket minden helyzetben és kombinációban le tudjuk renderelni, csak annyi kell, hogy mielőtt bármelyik objektumot kirajzolnánk, ellenőrizni kell, hogy nincs-e mögötte olyan elem, ami meg nincs kirajzolva a képernyőre, ha van, akkor először azt kell kirakni. Hogy az átfedések vizsgálatát leegyszerűsítsem, és a renderelés ténylegesen a kamerához közeledve haladjon, a koordináta rendszert kicsit átalakítottam: isoX és isoY gyakorlatilag képernyő koordináták, míg az isoZ a képernyőtől való távolságot jelzi (példánkban minél nagyobb az isoZ, annál közelebb van hozzánk).

iso_4

Az új koordinátarendszerben számolva, a kirajzolandó objektumainkat sorba rendezzük Z,Y,X koordináták alapján növekvő sorrendben. Így a listában az első elem a leghátsó, legalsó elem lesz: tökéletes kiindulási pont. Egy ciklusra van csak szükségünk (a előbbi rendezés miatt), amely az elemek listáján végigmegy, és meghívja a renderelő funkciót az adott elem kirajzolásához. A renderelő funkció mielőtt kirajzolná az elemet, megnézi, van-e a fedésében olyan elem, ami esetleg még nincs kirajzolva, és ha igen, meghívja önmagát hogy az új elemet rajzolja ki előbb (és mivel rekurzív a függvény, az új elemnél is megnézi először, hogy van-e valami mögötte, és így tovább...).

Az izometrikus pálya renderelésének nehezén túl vagyok (legalábbis jól esik így hinni), most már csak az olyan apróságok kellenek, mint padlók, falak, ajtók renderelése. Majd azután jöhet a mozgás és animáció. De az nem ma lesz...

Grafika Remake 1.

2015 Március 21.

Most már biztos, hogy csak 2-szeres felbontás lesz! Sajnos kicsit nagy lesz 512x342-es felbontásnál, viszont a mozgások és az animációk időzítése miatt, irreális többletmunkát igényelne, ha 150%-os méretben is meg kéne csinálnom... Na ezen felbuzdulva, elkészítettem a falak remake-jét, lásd alább - A képre húzva az egeret, felsejlik az eredeti.

head over heels walls after
head over heels walls before

A törekvésemen, miszerint az eredeti játékot a lehető legkevesebb módosítással reprodukáljam, egyre több csorba esik: először megpróbáltam a grafikát úgy felhúzni, hogy szinte azonos maradjon az eredetivel, csak az íveket, ferde vonalakat akartam simítani. Az eredmény elég kiábrándító lett: a vonalak túl vastagok voltak, és hiányolta a szemem a felbontástól elvárható részleteket. Ráadásul bizonyos elemeket kénytelen voltam részletezni, az meg nagyon elütött a korábbi technikával készített részektől. Ezért inkább elkezdtem következetesen elvékonyítani egyes vonalakat, és hozzáadni némi pixel koszt.

A pixelezés közben folyamatosan váltogattam az eredeti és új változat között és próbáltam úgy dolgozni, hogy hunyorítva szinte észrevehetetlen legyen a változás. Legalább úgy... Sokszor próbálkoztam 1-1 pixel hozzáadásával, törlésével, hogy az adott részlet kivehető legyen, térben jól helyezkedjen el. Bármilyen hihetetlen, de egy-egy pixel nagyon nagy jelentőséggel tud bírni, ha rossz helyen van simán előfordulhat, hogy megtörik egy ív, elváltozik egy arc, vagy csak megváltozik egy hossz. Tisztelem nagyon Bernie Drummond -ot aki negyed ennyi pixelből kihozta a grafikát, ott az előbb említettek hatványozottan érvényesek.

Volt egy olyan álmom is, hogy a készülő játék az eredetihez hűen szintén a lehető legkisebb futtatható állomány legyen. Magyarul legyen kicsi a file mérete. Az eredeti, kitömörítve is csupán 48 KB. Na most ez sok dolog miatt nem fog sikerülni. Kapásból duplázzuk a felbontást, ez ugye rögtön négyszeres növekedés a grafikai adatoknál. Ha még az animációkat is bővíteni akarom, az megint plusz adat. Ehhez hozzájön még az is, hogy az eredeti játék kényszerből (mert hogy nem volt több rendelkezésre álló RAM, és ragaszkodtak az 1 file-hoz, amiért áldom őket) olyan megoldásokat alkalmazott, hogy a 4 irányba néző objektumoknak csak 2 változatát tárolták, és futás közben tükrözték a figurát ha épp kellett. Ezzel is spóroltak sok memóriát, és file méretet. Ugyanez igaz a fal elemekre is, ajtókra... Na most 8 bites processzornál, frappáns módszerrel, egy 256 elemből álló fordító táblát generáltak, így kiolvasva a grafika egy byte-ját és azt indexként használva ezen a táblán, megkapták a 8 képpont tükörképet. Ez egy 68k processzornál szívás, mert a byte műveletek sok időt elpazarolnak, a grafika 4x annyi byte-ból van. 16 bites, 64 KB-os fordítótáblát is kellemetlennek tartanám, szóval 2 lehetőség tűnik ésszerűnek: eltárolom a grafikák tükörképét is, vagy a lassú byte alapú tükrözést elvégzem a program indításánál. Ez utóbbi nem csökkenti a program memória igényét, de legalább a file méret kisebb lesz, végül is ezt akartam... A lényeg, hogy futás időben nem tükrözök, mert nagyon lassítaná a játékot!

Néhány szó arról, miért is nem jó a 150%-os grafika méretnövelés: az eredeti játék pixelméretei, és sebessége tökéletes összhangban van a képernyő felbontásával. A képernyőn egy egységnyi terület bármely pontja a szomszédos terület azonos pontjától 16 pixelre van vízszintesen, és 8 pixelre függőlegesen. A térbeli függőleges egység 12 pixel magas. Ebből következik, hogy egységnyi távolságot az eredeti játék 8 lépésben tesz(tehet) meg síkban, és 6 lépésben függőlegesen, mindezt 12,5 fps sebességgel (50 Hz-es képfrissítésnél, minden negyedik frame-en volt mozgás). Ha duplázzuk a felbontást, akkor minden tökéletesen reprodukálható, csak duplázzuk a pixel elmozdulásokat. Ha finomítani akarom a mozgásokat, akkor ha minden második frame-en animálok, akkor arra is lehetőség van, mivel a dupla felbontásnál a lépésközöket tudom felezni. Tehát az eredeti játékban, a mozgás 1 fázisa alatt 2 pixelt lepek X, és 1 pixelt Y irányban, dupla felbontásnál ez 4 és 2 pixel, tehát tudom felezni, hogy növelhessem a másodpercenkénti képkockák számát. 150%-kal nagyított grafikánál, az alapegységek 24, 12 és 18 pixelre változnak. ezeket a távolságokat 8 egyenlő lépésben nehéz megtenni. Ha csak az lenne a cél hogy azonos idő alatt tegyen meg 1 egységnyi távolságot az ami mozog, meg lehetne oldani az fps módosításával, de akkor az animációink sebessége változna. Szóval megoldható, de sok módosítás és extra munka árán. "Nekem ez a kutya nem kell, ez gúnyolódik"

HOH Render Engine

2015 Április 1.

Az elmúlt tíz nap elég eseménydúsra sikeredett: először is nagyjából megterveztem a renderelőt, és a teljes játéklogikát, majd mikor már az utolsó kérdéses részlet is megoldódott, elkezdtem a programozást. Első körben kicsit átírtam a korábbi izometrikus objektum renderelőt, megváltozott a koordináta rendszer kissé, hogy egyes játék funkciókat mint például az összekapcsolt szobák, könnyebb legyen megvalósítani. Utána jött a maradék: padló, falak, ajtók. Bár semmiségnek tűnhet a tetszőleges elemekből álló izometrikus tér rendereléséhez képest, mégis legalább 2x olyan hosszú lett a kódja. Ezt bemutatandó, itt van ez a kis játszószoba:

North
door
East
door
South
door
West
door
X
size
Y
size
Main Room

Amit itt látunk, az gyakorlatilag egy háttér (kivéve persze az ajtókat), amit a renderelő 32 pixel széles oszlopokból allít össze, 2 menetben. Az egyik az északi fal mentén halad (bal felső) és magába foglalja a függőlegesen alatta levő padló és szegély részletet, a másik meg a keleti fal mentén halad hasonló módon. A renderelésen csavar egy kicsikét az tény, hogy a renderelő max 128x128 pixel meretű négyzetekből rakja ki a képet. Ez a "viewPort" módszer (ahogyan az eredeti játék is dolgozik) azért fontos, mert később, amikor majd kis elemek mozognak és animálódnak a játékban, ezeket a képernyő lehető legkissebb részletének frissítésével kell megoldani. Böngészőben, javascript-tel simán ki lehetne rajzolni a teljes kepernyőt minden frissítéskor, de a cél még mindíg a Mac Classic, ahol nem dúskálunk az erőforrásokban. A JS alapú verzó, amit be is fogok fejezni tulajdonképpen egy prototípus, ami alapjan majd elkészítem a C + ASM változatot. Ez persze a javascript kódban is meglátszik majd, hiszen sok programrészlet a végleges célplatform jellemzői alapján készül. Ugyanakkor vannak olyan részletek is, tipikusan a változók tárolásánál, ahol javascript-ben nem akartam bajlódni az utolsó bitek kispórolásával, ezekkel elég lesz játszadozni majd a CodeWarrior-ban.

A következő fázis most a renderelő befejezése lesz, olyan funkciók hozzáadásával mint a szövegek, grafikak képernyőre másolása, ami után elkészűlhet a menü rendszer, es a játék alatt a pontszámok/életek/stb. kiírása (OSD mint On Screen Display).

Bár az előző kis demón annyira nem látszik, de a renderelő lényege kész és nagyon jól működik (tökéleteset nem merek írni, 1 kis apró hibát már a demóban is észrevettem, és még tesztelnem kell berendezett szobában való mozgást is) képes az összes lehetséges szoba alaprajzot megjeleníteni az összes grafikai témában, képes bármilyen legális berendezést megjeleníteni, és abban a mozgó elemeket bárhol megjeleníteni úgy, hogy mindig a megfelelő elemek vannak takarásban. Legális alatt azt értem, hogy minden elemnek úgy kell elhelyezkednie, hogy ne lógjon bele más tárgyakba. A jaték során, erről az ütközésvizsgálat fog gondoskodni.

Helyzetjelentés

2015 Április 20.

Az elmúlt közel három hétben sokminden történt, többek között, elkészült a grafika 90%-a, már csak az animációk vannak hátra. Miután siketült belefáradni a kb 10 nap folyamatos pixelrajzolgatásba, hozzáláttam a következő fázisként beharangozott renderelő befejezéséhez - az gyorsan elkészült, nem volt egy komplex feladat, a lényeg már megvolt elötte is. Ezek után, elkezdtem a játék menürendszerét lekódolni, és örömmel jelentem, hogy ez is elkészült tegnap éjszaka. A program 640x480 es 512x342-es felbontasokra optimalizálva készül, a menüt is úgy állítottam össze, hogy ezen a két felbontáson legyen használható. A színektől eltekintve, gyakorlatilag teljesen azonos lett az eredetivel.

Lényegében már "csak" a játékmenet van hátra, és ez elég jó érzés, hiszen az összes olyan sallangot letudtam, amit más esetben a végére szoktam hagyni. Szóval a játékmenet: Játékosok irányítása, váltás a játékosok között, a pályák, azok adatainak tárolása, az ellenfelek mozgatása. Ezek lesznek a következő hullám főszereplői. Itt jegyezném meg, hogy ha ezt mind befejeztem, akkor következik a lényeg, hiszen amiről eddig beszéltem, az a Javascript verziója a játéknak, ami magától még nem fog Mac 68k platformon futni, tehát ezek után kezdődik egy kemény menet: C-ben újra létrehozni az egészet.