Az ENTERPRISE gép piacra kerülésekor, és azóta is nagy probléma a programok hiánya (akár játék-, akár felhasználói programról is legyen szó). Ezzel szemben ott van pl. a SPECTRUM, amely a maga néhány ezer (!) software termékével a viszonylag jól ellátott gépek közé tartozik. Előbb-utóbb mindenkiben felvetődik a kérdés: hogy lehet a SPECTRUM programokat futtatni az ENTERPRISE gépen?
A futtatásra több módszer is lehetséges
• A legegyszerűbb venni egy SPECTRUM-EMULÁTOR-t. Ennek a módszernek vannak előnyei, de vannak hátrányai is. Előnye, hogy egyszerű, különösebb szakértelmet nem igényel. Hátránya, hogy egyrészt relatíve drága, másrészt nem kezeli a floppy egységet, így aki rendelkezik lemezmeghajtó egységgel, kénytelen minden alkalommal EMULÁTOR-EXDOS cserét végrehajtani, ez pedig jelentősen igénybe veszi a gép fólia-érintkezőit, arról nem is beszélve, hogy aki hozzászokott a floppy sebességéhez, az elég nehezen tűri a 'hosszú, méla lest'. Mindemellett a programoknak csak bizonyos százaléka futtatható ezzel a módszerrel.
• Bonyolultabb, de eredményesebb módszer az, amikor a felhasználó fogja a SPECTRUM programot, és elmélyült programozással futtathatóvá teszi azt az ENTERPRISE gépen. Ennek a módszernek is van hátránya, történetesen az, hogy elég jól kell ismerni a gépi kódú programozást, valamint mindkét gép lelkivilágát (HARDWARE), viszont sokkal több előnye van, mint hátránya: bármilyen program átírható ezzel a módszerrel, az átírt programok lemezről is betölthetők, és nem utolsó sorban a program-átíró szellemi épülését is segíti.
Mi a most induló módszertani segédletben a második módszerrel szeretnénk foglalkodni, hasznos tanácsokat adva a kedves Olvasónak, azoknak akik elég önbizalommal (és tudással) rendelkeznek ahhoz, hogy egyénileg nekivágjanak egy ilyen mélységű munkának.
Általános áttekintés
Mindenekelőtt azt kell tisztáznunk, hogy mi szükséges egy valamely gépen futó program másik gépre történő átkonvertálásához:
• Gépi kódú program esetén a két gép központi egységének ugyanolyan nyelven kell 'beszélnie', vagy a fogadógépnek legalább szimulálnia kell tudni a forrásgép nyelvét (ettől eltérő esetben is átírható egy program, de a módszer sokkal bonyolultabb). Más (magas szintű) nyelvek esetén nem fontos a kód-kompatibilitás, elég, ha a két fordítóprogram (legyen az akár interpreter, akár compiler) azonos nyelvjárást ismer (Ilyen pl. a CP/M alatt, és az IBM PC-n is futó TURBO-PASCAL is. Az IBM PC-n futó TURBO PASCAL megérti a CP/M alatt futó TURBO PASCAL forrásszövegét, fordítás után futtatható is.) Visszatérve a gépi kódhoz, ez a mi esetünkben biztosítva van, mivel mindkét gép szíve egy Z-80-as mikroprocesszor. Ez azt jelenti, hogy a SPECTRUM-ról átvitt kód minden változtatás nélkül futtatható az ENTERPRISE-on is, természetesen ez még nem jelenti azt, hogy működni is fog. A működés biztosításához több feltételnek teljesülnie kell.
• Amennyiben a két gép gépi kódja megegyezik, a következő probléma a program átvitele egyik gépről a másikra. Esetünkben a megoldást a két gép magnetofon-illesztőjének hasonlósága adja. Tekintettel arra, hogy a SPECTRUM programok nagy része audio kazettán terjed, kézenfekvő az, hogy az átírni kívánt programot magnetofonról olvassuk be.
• Ha a kód már a célgépen található, újabb probléma vetődik fel: a gépek közötti hardware különbség. Ez a mi esetünkben is probléma. Ez az oka annak, hogy programunkat erőteljesen módosítani kell.
• A felépítésbeli különbség maga után vonja az operációs rendszerek különbségét is. A SPECTRUM programok esetében elég népszerű a BASIC-ROM egyes szubrutinjainak hívása. ENTERPRISE gépen ez másképp van megoldva, így más utat kell választanunk. A ROM rutinok hívása különösen a felhasználói programok esetében elterjedt. Játékprogramok ritkán hívják meg ezeket a rutinokat, így a játékprogramok átírásához kijelölhetjük a követendő irányvonalat:
1. A program kódját át kell vinnünk az ENTERPRISE gépre.
2. Az átvitt kódot hardware szempontból módosítanunk kell.
3. A módosított programot el kell látni egy betöltővel, amely hivatott a programot beolvasni a megfelelő memóriahelyekre, valamint az alapvető hardware emulációt végrehajtani.
Módosítás hardware oldalról
Egy játékprogram esetében három dolgot kell megfelelően átalakítanunk: grafika, hang, irányítás.
Grafika: Készíteni kell egy olyan képernyő üzemmódot, ami megegyezik a SPECTRUM-éval. Mint bizonyára minden Olvasó tudja, a SPECTRUM ún. attribútum üzemmódban dolgozik. Ez azt jelenti, hogy van egy bittérképe, ahol minden képpontnak egy bit felel meg. Azt, hogy az 1-es ill. 0-ás bit milyen színű legyen, az attribútum byte határozza meg. Nyolc egymás alatti képernyő byte-hoz tartozik egy attribútum byte, vagyis egy attribútum bytetal egyidőben 8x8=64 bit színét állíthatjuk be. A bittérképben lévő 0 biteket háttér, vagy papír színnek (PAPER), az 1 biteket pedig kiíró, vagy tinta színnek (INK) nevezzük.
Legnagyobb szerencsénkre az ENTERPRISE gép video chip-je (NICK chip) szintén ismeri az attribútum üzemmódot, igaz egy kicsit másképpen. Ezentúl - hogy ne legyen azért olyan egyszerű a dolgunk - a SPECTRUM meglehetősen egyéni módon helyezi el a memóriában a képpont sorokat, valamint speciális a színösszeállítása is.
Készítenünk kell egy olyan LPT-t (Line Parameter Table - sorparaméter tábla), amely ilyen felbontással, ilyen színösszeállítással, stb. generál egy SPECTRUM képernyőt. A színek miatt később még egy elég nehéz konvertálás is vár ránk.
Hang: A SPECTRUM (a normál 48K-s gép) egy egyszerű BEEP hangkeltéssel rendelkezik, vagyis egy biten történik a hanggenerálás. Ha a bit 1 értékű, akkor a hangszóró kimozdul, míg ha 0, akkor visszahúzódik, így ha ezt a bitet valaki megfelelő frekvenciával billentgeti, akkor megszólal a gép. Ezt az ENTERPRISE gépen elég egyszerű szimulálni, mivel a hanggenerálásért felelős alkatrész (DAVE chip) rendelkezik egy un. D/A üzemmóddal. Ez azt jelenti, hogy ilyenkor a hangerőregiszterben megadott nagyságú szint rákerül a hangszóróra, és ott is marad. Gyakorlatilag ez ugyanaz, mint a SPECTRUM módszere, de itt nem egy bitet kell billegtetni, hanem felváltva 0, és egy 0-nál nagyobb szintet kell a hangerőregiszterbe írni, így még a hangerő is módosítható. Természetesen a programban meg kell keresni az összes hanggenerálással foglalkozó rutint, és a fent leírtaknak megfelelő formára kell hozni.
Irányítás: Ez természetesen már egy extra szolgáltatás, annak van rá szüksége, aki használni is szeretné a programot. A problémát itt is az okozza, hogy a SPECTRUM egyéni billentyűzet-figyelést alkalmaz. Itt többféle megoldást is alkalmazhatunk: írhatunk egy általános szubrutint, amely szimulálja az eredeti billentyűzetet, vagy pedig magában a programban kielemezzük a billentyűzet-figyelő rutin működését, és írunk helyette egy másikat. Az utóbbi megoldás elegánsabb, gyorsabb és jobban próbára teszi a programozó képességeit. Az első megoldás kényelmesebb, de alacsonyabb színvonalú.
Egyéb akadályok
Fejtörést okozhat több dolog is, pl. az IM2-es megszakítás szimulálása. Ez az a dolog, ami miatt több program nem fut az EMULÁTOR-on sem. Problémát okoz az 'EI' utasítás is (ENTERPRISE-on másképp kell végrehajtani), a 128K memórialapozás, a 128K zene (AY-3 8912 chip szimulálása), egyes ROM hívások, stb. Az ilyen speciális problémákra egy-egy aktuális rész kifejtése során fogunk kitérni.
Hasznos tanácsok
A program átírási manipulációhoz nem árt beszerezni egy disassembler-monitor programot, mivel e nélkül kicsit nehézkes lenne a dolgunk. Mi a SIMON (ASMON) nevű Z-80 fejlesztő-rendszert használtuk, ugyanis ez nem csak disassembler, hanem assembler is. Minden - később ismertetésre kerülő - példaprogram ezzel a rendszerrel lett előállítva.
Az sem árt, ha van a közelünkben egy SPECTRUM, persze ez nem létszükséglet, csak az eredetivel való egybevetéshez, ill. a BASIC betöltök listázásához kell. Célszerű egy software SPECTRUM EMULÁTOR beszerzése is, mivel a BASIC listázására ez is alkalmas.
Miért kell listázni a SPECTRUM verzió BASIC betöltőjét? Nos, a SPECTRUM programok általában egy BASIC betöltővel indulnak, a betöltő (LOADER) tölti be a program további részét (részeit). Ez egyrészt kényelmi szempontból jó (elég a LOAD"" utasítás, nem kell kiírni mögé a CODE függvényt), másrészt így egyszerien biztosítható az AUTOSTART). Ha nem listázzuk ki a BASIC betöltőt, akkor nem tudjuk a blokkok számát, az egyes blokkok betöltési címét, hosszát, s nem utolsó sorban a legfontosabbat, a program indítási címét. Természetesen a programok többsége nem engedi magát listázni, esetleg a betöltő maga is gépi kódú, vagy rejtett, ezekre a speciális esetekre is a megfelelő módszer ismertetésénél fogunk kitérni.
A következő részben az első lépésről, a SPECTRUM program ENTERPRISE gépbe való átgyötréséről fogjuk a fátylat lerántani.
A SPECTRUM programok átírásának első lépcsőfoka magának a kódnak az átvitele egyik gépről a másikra. Ez esetünkben kézenfekvő, mivel a programok elnyomó többsége kazettán kerül az amatőrök kezébe. A feladat tehát az, hogy a SPECTRUM által felírt kazettákat elolvassuk. Szerencsére mindkét gépnek hasonló a kazettás magnót kezelő hardware felépítése.
Kicsit konkrétabban: a SPECTRUM 254-es (0FEH) porijának 5. bitje a kazettás adatrögzítés bemeneti bitje. A szalagról bejövő jel nagyságától függően vagy 1-be, vagy 0-ba állítja ezt a bitet.
ENTERPRISE-on a 182-es (0B6H) porton a 7. bit nagyjából hasonló feladatot lát el. Vagyis feladatunk eléggé leegyszerűsödik, mivel az eredeti loader-t kivehetjük a SPECTRUM ROM programjából, csak a hardware különbségeket kell korrigálni. Mi is ezt tettük a közölt programban. A példaprogram egy kicsit bonyolultabb, mert különböző luxusszolgáltatásai is vannak. Megértéséhez szükséges az EXOS (az ENTERPRISE operációs rendszere) ismerete.
Az EXOS használata a csatornák használatán alapul. Erre a SPECTRUM BASIC esetében is történtek próbálkozások, de korántsem sikerült annyira logikusan. A csatornák lényege az, hogy ha valamilyen egységet kezelni akarunk, akkor nem kezdünk el szeleburdi módon ROM-rutinokat hívni, hanem nyitunk számára egy kommunikációs csatornát. Azt, hogy milyen egységgel akarunk "szót váltani" a rendszer onnan tudja, hogy a csatorna megnyitásakor megadjuk az eszköz nevét. Ilyen eszközök a billentyűzet (KEYBOARD:), a nyomtató (PRINTER:) stb. Az EXOS onnan ismeri fel az eszközt, hogy kettőspont van a végén. Vannak olyan eszközök, amelyek file alapúak, és vannak olyanok is, amelyeknek csak a csatorna létrejötte szükséges. Például, ha kazettán létrehozunk egy file-t, akkor annak meg kell adnunk a nevét, adatokat kell beleírnunk, majd le kell zárni. A billentyűzet esetén nem akarunk file-t sem olvasni, sem írni, mi csak az éppen leütött billentyűre vagyunk kíváncsiak.
Egy csatorna, ha már létrejött, sok mindenre jó. Tudunk bele adatokat írni, adatokat olvasni. Csatornát EXOS funkcióhívással tehet megnyitni. Az EXOS funkcióhívás a következőképpen néz ki:
RST 30H
DEFB funkciókód
Általában az A regiszter tartalmazza a csaturna számot, DE-ben és BC-ben adunk át paramétereket. Visszatéréskor az "A" regiszter egy hibakódot tartalmaz, ami 0, ha sikeres volt a művelet. Mivel így elég nehézkes használni, ezért erre létrehoztak az ASMON-ban egy előre definiált makrót EXOS néven. Ennek használata: "EXOS funkciókód" ahol a funkciókód értelemszerűen a kívánt operációsrendszer szolgáltatás száma.
A programban használt EXOS hívások:
EXOS 1 - Csatorna megnyitás. Az "A" regiszterben a megnyitni kívánt csatorna száma, a "DE" regiszterpárban a nevének címe van. DE egy karaktersorozatra mutat, amelynek első byte-ja egy hosszúságbyte, ami megadja az utána következő karakterek számát. Ez a módszer általánosan használt az EXOS-ban, tehát jó vele tisztában lenni. Ez a név tartalmazhatja az eszköz nevét és a file-nevet egyaránt. Ha hiányzik az eszköznév, akkor kazettás rendszerben a "TAPE:" eszköz lesz behelyettesítve (ez a magnóillesztő). File alapú eszközök esetén ez a hívás olvasásra nyitja meg a csatornát.
EXOS 2 - Csatorna létrehozás. Hasonló, mint az előző hívás, de file alapú eszközök esetén írásra nyitja meg a csatornát. A programban ezt a hívást használjuk a betöltött SPECTRUM file-ok ENTERPRISE formában történő kimentésére.
EXOS 3 - Csatorna lezárása. Az "A" regiszterben van a csatornaszám.
EXOS 5 - Karakter olvasása. Az "A" regiszterben van a csatornaszám, visszatéréskor a "B" regiszter tartalmazza a beolvasott byte-ot.
EXOS 8 - Blokk írása. Ez nem egy byte-ot ír a csatornába, hanem egy byte-halmazt. A csatornaszám megadása hasonló az eddigiekhez. A DE regiszterpár tartalmazza azt a memóriacímet, ahol a kiírni kívánt adatok vannak, BC pedig ezen adatok számát tartalmazza.
EXOS 11 - Speciális funkció. Bizonyos feladatokat nem - vagy csak nagyon nehézkesen - lehet megoldani a csatorna írás-olvasás műveletekkel. Ilyen műveletek lebonyolítására szolgál ez a funkcióhívás. Programunk az 1. számú speciális funkciót használja egy video-lap képernyőn való megjelenítésére. A hívás paraméterei:
A a csatornaszám
B=1 Az 1. funkció kijelölése
C=1 A videolapon az 1.sortól kezdve legyen megjelenítés
D=20 20 sort kell kijelezni
E=1 A képernyőn az 1. sorban kezdődjön a videolap
EXOS 16 - EXOS változó írása/olvasása/átbillentése. A program a video és a szövegszerkesztő paramétereinek beállítására használja. Paraméterei:
B=1 A változót írni óhajtjuk
C=v C regiszterben az EXOS változó száma
D=új érték. A hívás után ez lesz a változó új értéke.
EXOS 24 - Szegmens kijelölés. Memóriát célszerű az EXOS-tól kérni, mivel így biztosan nem kezd el más program is az általunk használni kívánt memóriában dolgozni. C regiszterben a kiutalt szegmens száma lesz. Programunk 3 db szegmenst foglal le, ez 48k, így minden SPECTRUM program belefér a tárba.
EXOS 26 - Rendszerbővítő letapogatás. DE egy karaktersorozatra mutat. A BASIC is ezt a funkciót használja, amikor a felhasználó beüt például egy :HELP parancsot. Ez a kettőspont utáni parancshívás esetünkben is működik.
EXOS 28 - Hibakód értelmezése. Ha valakinek nem mond eleget az A regiszterben visszakapott hibakód, az EXOS mint egy jó tündér, a segítségére siet. A hívás előtt meg kell adni DE-ben egy olyan címet - ami lehetőleg másra nem használt -, ahová a rendszer nyugodt lélekkel felírhatja (a gyengébbek kedvéért) a hibakód magyarázó szövegét.
Az operációs rendszer nagy vívmánya a szövegszerkesztő (EDITOR:). Nagysága abban áll, hogy ha valaki valamilyen szöveget akar a felhasználótól kicsikarni, nem kell új adatbekérő programot írnia. Ilyen esetekben elég, ha nyit egy csatornát "EDITOR:" néven, és máris javában olvashat a felhasználótól. Csatornamegnyitás előtt be kell állítani néhány paramétert (EXOS változót). Ezek:
29 (VID EDIT) Itt kell megadni, hogy a szerkesztés során a szerkesztő melyik video-lapot használja.
30 (KEY EDIT) Hasonlóan a használt billentyűzetcsatornát kell megadni.
31 (BUF EDIT) A pufferméret 256 byte-os alapegységben. Tehát a pufferméret az itt megadott szám*256 byte lesz. Ez határozza meg, hogy hány karakter fér bele a szövegszerkesztőbe.
32 (FLG EDIT) A kiolvasás módját adja meg. A programban ez hasonló a BASIC sorbeolvasásához.
Ennyi kitérő után lássuk, mit is tud a program:
Indítás után megkérdezi az átvitel módját, folyamatos, vagy nem folyamatos. Folyamatos mód esetén betölt egy SPECTRUM file-t, majd ezt kimenti, és ezt addig csinálja, amíg le nem lövik. A nem folyamatos mód abban tér el, hogy minden kimentés előtt vár egy billentyűleütésre, így ilyenkor lehet kazettát cserélni. A program bekér egy nevet, mögé tesz egy kiterjesztést formában, ahol y és xx szimbólikus jelölés. "y" helyére egy 1 karakteres jelet tesz, ami az első file esetén 0, ezután 1,2 stb. "xx" a beolvasott blokk típusát adja hexadecimálisan. Innen lehet felismerni, hogy ez most fejléc volt avagy programblokk.
A program az "ASMON" nevű assemblerrel készült, ha valaki csak "HISOFT GEN ASSEMBELER"-rel rendelkezik, ne csüggedjen, hanem az első sorok elé írja be a következőket:
EXOS MACRO@1
RST 30H
DEFB @1
ENDM
Az EXOS a sor elején kezdődjön, a többi sor egy (vagy több) karakterrel beljebb. Ez érvényes az egész programban is. A szimbólumokat bevezető SPACE nélkül írjuk be, míg a többi sorban lévő utasítások elé legalább egy SPACE-t tegyünk. Ez a programlistából is előtűnik. A szimbólumok és a mögötte álló utasítások közé szintén legalább egy SPACE szükséges. A bevitel módja ASMON-ra: a program bejelentkezése után nyomjuk meg az "E" billentyűt. Ekkor bekerülünk egy szövegszerkesztőbe. Itt írjuk be programunkat, majd nyomjuk meg az "F8" funkcióbillentyűt. Ekkor visszakerülünk a monitorba. Itt a "Z" billentyű lenyomásával beállíthatjuk az assembler opciókat. Addig nyomjuk az ENTER-t, amíg el nem jutunk az "Object file name:" kérdéshez. Ekkor írjuk be a program nevét (mindenkinek az ízlésére van bízva a névválasztás). Ezután újra ENTER, ekkor az "EXOS module header NO" üzenet látható. Nyomjunk meg egy fekete billentyűt (tehát nem a STOP-ot!!!), ekkor változik a kép, most már az "EXOS module header YES" szöveg olvasható. Adjunk ENTER-t. Most azt olvashatjuk, hogy "EXOS module type 0". Üssük be az "5" számot, majd újra az ENTER-t. Visszatértünk a "Command>" módba. Már csak egy teendőnk van, lefordítani a forrásszöveget. Ezt az "A" billentyű leütésével eszközölhetjük. Előtte ne felejtsük el felvételre állítani a magnót. Ha lemezegységünk van, akkor készüljünk fel arra, hogy a lemezen létrejön a programunk olyan néven, amit megadtunk neki. Ha az assembler valamilyen hibaüzenettel leáll, akkor nézzük meg, mit rontottunk el. A forrásszöveget is kimenthetjük a "W" paranccsal. Ekkor meg kell adnunk a file nevét, majd ENTER-t kell nyomni. A kimentett forrásszöveg a "K" paranccsal tölthető vissza. A GEN esetén be kell írni a forrásszöveget, majd "A,,R 5" és ENTER, ekkor lefordítja. Ha rendben ment a fordítás, akkor beírhatjuk: "O„név" és kimentődik a használható program.
Eme módfelett magasröptű program beírása után már akadálytalanul tudunk áthozni mindenféle programterméket. Ez így nagyon szép, de még ezzel sem tudunk működő SPECTRUM átiratokat gyártani, mert egyrészt még SPECTRUM képernyőnk sincsen, másrészt nem tudjuk betölteni sem. Ez a nemes feladatot megvalósító programocska lesz következő értekezésünk tárgya.
Miután már mindenki profi módon tud SPECTRUM programokat beolvasni, jogosan vetődik fel a tisztelt felhasználókban a kérdés, hogy az átmenekített adatokkal mit kezdjen. Egyszóval: hogyan tovább? A következő lépcsőfok az előző részben leírt módon emberközelibbé tett programok olyan környezetbe helyezése, ami minél inkább emlékeztet egy SPECTRUM-ra. A környezet legfontosabb eleme a képernyő. Enélkül a programok nagy része meglehetősen egysíkúvá válik. Első és egyben legmagasztosabb feladatunk elkövetni egy olyan képernyő formációt, ami kísértetiesen hasonlít a SPECTRUM-ra. Ez meglehetősen nehéz feladat, mivel a SINCLAIR gép eléggé Istentől elrugaszkodott módon végzi a kép kirakását. Vegyük sorra a jellegzetességeket:
• Attributum üzemmód. Ez magyarra fordítva annyit jelent, hogy a megjelenített kép két helyről épül fel. Az egyik hely az un. bittérkép. Ez a képernyőn látható információ kétszínű levonata. Mivel - mint köztudomású - a SPECTRUM színes számítógép, így kell egy másik adatmező is, ami a színinformációkat hordozza. Ezt a memóriaterületet hívják attribútummemóriának. Esetünkben nyolc egymás alatt elhelyezkedő bittérkép byte-hoz tartozik egy attribútum-byte. Ebből következően nyolcszor annyi bittérkep byte van, mint attribútum-byte. Az attribútum-byte megadja, hogy a bittérkép byte-okban lévő 0 és 1 értékű bitek milyen színt képviseljenek. A 0 értékű bitek színét szokás papírszínnek (PAPER), az 1 értékű bitek színét pedig tintaszínnek (INK) nevezni. Az ENTERPRISE szerencsére ismeri ezt a színüzemmódot.
• A sorok elhelyezkedése. Nos, itt kezdődnek a problémák! Míg az ENTERPRISE esetében az első sor a 0-31 tartományban, a második a 32-63 tartományban van, addig a SPECTRUM egy sajátságos logika szerint kezeli a sorokat. Itt a képernyő fel van bontva látszólagos karakterekre, egy ilyen karaktersor függőlegesen 8 pixelsorból áll, a karaktersoron belül a sorok között 256 byte különbség van. Ez így szép és jó lenne, ha csak egy ilyen karaktersorból állna a képernyő (8 pixelsorból). A valóságban 192 pixel a függőleges felbontás, azaz 24 ilyen ál karaktersor van a képernyőn. Ez azért jó, mert osztható nyolccal, ily módon lehetőség volt a képernyőt harmadokra osztani. Egy harmadon belül az egyes karaktersorok első pixelsorai között pontosan 32 byte a különbség.
Ha ez így nem volt egészen világos - amit meg lehet érteni - tanulmányozzuk át ezt a kis táblázatot:
0.sor 0 8.sor 32
1.sor 256 9.sor 288
2.sor 512 10.sor 544
3.sor 768 11.sor 800
4.sor 1024 12.sor 1056
5.sor 1280 13.sor 1312
6.sor 1536 14.sor 1568
7.sor 1792 15.sor 1824
Ez két karaktersorra lebontva tartalmazza a pixelsorok relatív címeit.
• A VIDEO memória címe. Az előzőekben bemutatott bittérkép a 16384-es (4000H), az attribútummemória a 22528 (5800H) címen helyezkedik el. A bittérkép hossza 6144, az attribútummemória hossza pedig 768 byte.
• A papír- és a tintaszín byte-on belüli megoszlása:
b5-b3 papírszín
b2-b0 tintaszín.
A b6 bit az un. BRIGHT,
a b7 bit pedig a FLASH bit.
Ha a BRIGHT bit be van állítva, a megjelenő színek nem a normál színek lesznek, hanem valamivel fényesebbek. Ha a FLASH bit van beállítva, akkor a tinta és a papírszín ciklikusan váltakozik (villog).
Ennyi bevezető után térjünk rá programunk muködésére:
Először szerez egy kis memóriát, majd emulálja a SPECTRUM video üzemmódját. Ezt 192 db LPB segítségével teszi (az LPT felépítéséről már volt szó e hasábokon). Ezután betölt két file-t. Az ADDR1, BYTE1 ill. ADDR2, BYTE2 címkéket a betöltendő programtól függően kell értékkel feltölteni.
ADDR1 az első blokk, ADDR2 a második blokk betöltési címe. BYTE1 az első blokk, BYTE2 a második blokk hossza. A betöltött program indítási címe a USR szimbólumban kell hogy legyen tárolva.
Ha ezzel a betöltővel felfegyverkezve a vállalkozóbb szellemű Olvasó betölt egy játékprogramot, a betöltési képet meglátva valószínűleg elátkozza eme sorok íróját. Annak, hogy a tapasztalt szépséghibának mi az oka, hogyan lehet kiküszöbölni, a következő részben olvashatják a téma iránt érdeklődők!
Az eddigiek során elfutottunk odáig, hogy fel tudunk építeni a SPECTRUM képernyőjéhez nagymértékben hasonlító SCREEN-t. Hogy ez miért csak hasonlító, és miért nem azonos, annak több oka van. Az előzőekben már volt szó az attribútum üzemmódról. Az attribútum memória az 5800H-5AFFH címtartományban helyezkedik el. Eme tartománynak a programátírások során igen nagy szerepe van, ezért érdemes jól megjegyezni. Vizsgáljunk meg egy attribútumbyte-ot! Kezdjük a legmagasabb helyiértékkel, a 7. bittel (b7)! Ha ez a bit be van állítva (értéke 1), akkor a papír és a tinta szín rövid időközönként invertálódik (magyarán: az adott karakter villog). Na ez az, amit az ENTERPRISE nem tud. Ha egyszer a sors szeszélye folytán olyan program kerül kezeink köze, amelyben létfontosságú a FLASH, akkor készüljünk fel a legrosszabbra. Nem lehetetlen ezt is szimulálni, de ez általában a programfutás sebességének rovására megy.) Tovább haladva, nézzük a 6. bitet (b6)! Ez a bit az un. BRIGHT (fényesség) bit. Ha ennek értéke 0, akkor a normál színek, míg a bit beállítása esetén a fényes színek jelennek meg. Az esetek túlnyomó többségében ez a bit okozza a galibát. A következő bitcsoport (b5,b4,b3) a papír színét (a nullás bitek a bittérképben), míg a legalsó 3 bit (b2,b1,b0) a tintaszínt (az egyes bitek a bittérképben) adja meg. Mivel ez 3 bit, így 8 szín kijelölésére van lehetőség. Ehhez jön még a BRIGHT bit, így kis jóindulattal azt mondhatjuk, hogy 16 szín között válogathat a felhasználó. A színképzést egyszerűen oldották meg: a három alapszínhez (vörös, zöld, kék) hozzárendeltek egy-egy bitet. A hozzárendelés: b0=kék: b1 =vörös, b2=zöld. (Ez így természetesen csak a tintaszínre igaz, papírszín esetén b0 helyett b3, b1 helyett b4 és b2 helyett b5 értendő.) Miután tisztáztuk a SPECTRUM színképzését, most a másik oldal következik. Az ENTERPRISE attribútum üzemmódja lényegesen egyszerűbb, nincsenek benne helyi specialitások (FLASH, BRIGHT). Az attribútumbyte két részre oszlik: alsó 4 bit és felső 4 bit. A felső 4 bit a papír, az alsó 4 bit a tinta színét jelöli ki (ahogy azt a logika diktálja). Látható tehát, hogy itt valóban 16 szín használatára van lehetőség. Ebből a 16 színből az alsó 8 (a 0xxx értékek) tetszőleges lehet. (A sorparaméter táblában, az LPB utolsó nyolc byte-ja éppen ezt a nyolc színt tartalmazza.) Előző mintaprogramunkban alkalmazott paletta jó közelítéssel megfelel a SPECTRUM normál színeinek. Amennyiben csak normál (nem fényes) színek fordulnak elő, akkor az egyedüli problémát az okozza, hogy a papír színek egy bittel alacsonyabban vannak, mint ahogy azt az ENTERPRISE megkívánná. Mielőtt bárki is fellelkesülne, sajnos le kell hűteni a kedélyeket. Már említettük a BRIGHT bitet. Nos, ha egy programban fényes színek is előfordulnak, akkor (mivel a b6 bit egyes állapotú) a fekete háttér helyett egy kellemes zöld alapszínt kapunk (no meg frászt, mivel semmit nem látunk a programból). Ilyen szempontból nagyon kellemes a fényes zöld tinta és a fekete papír kombinációja, ugyanis ennek értéke 44H. Ez azért jó, mert ez ENTERPRISE-on zöld papíron zöld tintát jelent, magyarán semmit. A megoldás bizonyára több olvasóban is felötlött: a fényes színeknek feleltessük meg a fennmaradó 8 színt (az 1xxx kombinációkat). Igen ám, de ez nem olyan egyszerű! Ezt a nyolc színt nem lehet csak úgy beállítani, használni kell a FIXBIAS regisztert. Ez a nevezetes regiszter a 128 (80h) port nagy részén terpeszkedik. Ez a port is bitenként értelmezett:
b7: ha értéke 1, akkor a belső hangszóró néma.
b6,b5: a külső színbemenetek prioritását szabályozza.
b4-b0: FIXBIAS regiszter.
Mint látjuk ez a regiszter 5 bites. Tudni kell még azt is, hogy az ENTERPRISE a színeket 8 biten ábrázolja, így 256 színt képes használni. A felső nyolc szín (az 1xxx kombinációk) úgy képződik, hogy a FIXBIAS regiszter lesz a színbyte felső 5, míg a kiválasztott szín 3 bites érteke az alsó 3 bitje. A már említett programunk a FIXBIAS regiszterbe 0-t tölt. Az így előálló színkombinációk megfelelnek a SPECTRUM BRIGHT színeknek. A NICK-chip bit-szín hozzárendelése azonban különbözik a SPECTRUM-étól: b0-vörös. b1-zöld, b2-kék. Vagyis ami SPECTRUM-on kék, az ENTERPRISE-on vörös. A megoldás egyszerű: a biteket úgy kell megcserélni, hogy a színek azonosak legyenek. Ez annyit jelent, hogy a programban el kell mélyedni, a színkezeléseket felderíteni, majd a kívánt értékre módosítani. Általában a programátírásban ez a mozzanat tart a legtovább, ez igényli a legnagyobb gyakorlatot. Tehát összefoglalva: ahhoz, hogy egy SCREEN hasonló színekben pompázzon, mint az eredeti, a következő módosítások kellenek:
1. Ha az attribútumban a BRIGHT nincs beállítva, akkor a b3, b4, b5 biteket el kell mozdítani felfelé egy bittel, úgy, hogy az alsó 3 bit ne változzon.
2. Ha a BRIGHT bit be van állítva, akkor hasonló a procedúra, csak biteket is kell cserélgetni.
b7 b6 b5 b4 b3 b2 b1 b0
SPECTRUM attribútumbyte 0 1 s5 s4 s3 s2 s1 s0
ENTERPRISE attribútumbyte 1 s3 s5 s4 1 s0 s2 s1
E kis ábra után bizonyára mindenki tudna kreálni egy táblázatot, azonban, hogy az Olvasó idejét kíméljük íme az összes attribútumérték és a kiszámított ENTERPRISE megfelelő (forma: SPECTRUM-> Enterprise):
00=>00 01=>01 02=>02 03=>03 04=>04
05=>O5 06=>06 07=>07 08=>1O 09=>11
0A=>12 0B=>13 0C=>14 0D=>15 0E=>16
0F=>17 10=>20 11=>21 12=>22 13=>23
14=>24 15=>25 16=>26 17=>27 18=>30
19=>31 1A=>32 1B=>33 1C=>34 1D=>35
1E=>36 1F=>37 20=>40 21=>41 22=>42
23=>43 24=>44 25=>45 26=>46 27=>47
28=>50 29=>51 2A=>52 2B=>53 2C=>54
2D=>55 2E=>56 2F=>57 30=>60 31=>61
32=>62 33=>63 34=>64 35=>65 36=>66
37=>67 38=>70 39=>71 3A=>72 3B=>73
3C=>74 3D=>75 3E=>76 3F=>77 40=>88
41=>8C 42=>89 43=>8D 44=>8A 45=>8E
46=>8B 47=>8F 48=>C8 49=>CC 4A=>C9
4B=>CD 4C=>CA 4D=>CE 4E=>CB 4F=>CF
50=>98 51=>9C 52=>99 53=>9D 54=>9A
55=>9E 56=>9B 57=>9F 58=>D8 59=>DC
5A=>D9 5B=>DD 5C=>DA 5D=>DE 5E=>DB
5F=>DF 60=>A8 61=>AC 62=>A9 63=>AD
64=>AA 65=>AE 66=>AB 67=>AF 68=>E8
69=>EC 6A=>E9 6B=>ED 6C=>EA 6D=>EE
6E=>EB 6F=>EF 70=>B8 71=>BC 72=>B9
73=>BD 74=>BA 75=>BE 76=>BB 77=>BF
78=>F8 79=>FC 7A=>F9 7B=>FD 7C=>FA
7D=>FE 7E=>FB 7F=>FF
Ennek segítségével már lehetséges a színek átalakítása, azonban hosszabb adatmezőket már nem érdemes kézzel konvertálni. Mivel a számítógép az ember barátja, illő, hogy dolgozzon is egy kicsit. Az alábbi kis programmal SPECTRUM SCREEN-eket lehet konvertálni:
A program használata: írjuk be az ASMON szerkesztőjébe. Amennyiben nem akarjuk minden egyes alkalommal újragépelni, akkor mentsük ki a <W> billentyű segítségével. Ekkor a "File name:" kérdésre adjunk egy nevet (ezt az Olvasó fantáziájára bízzuk). Célszerű egy külön kazettát (vagy lemezt) fenntartani a segédprogramoknak. Ha már kimentettek, legközelebbi alkalommal a begépelés helyett töltsük be ASMON-ba a "K" parancs segítségével. Az ismételten megjelenő "File name:" kérdésre adjuk meg az általunk kreált fantázianevet. Betöltődés után állítsuk be az assembler opciókat ("Z' parancs) az alábbiakra:
Assembly listing OFF
List conditions NO
Force PASS 2 NO
Memory assembly YES
Memory offset 0
Object file name:
Ez utóbbi esetben egyszerűen adjunk <ENTER>-t a kérdésre. Ezután fordítsuk le ("A" parancs) a programot, majd töltsünk be egy SPECTRUM SCREEN-t. Ez a SPECTRUM-on a 4000H címre töltődik be ás 1B00H hosszú (6912). A betöltés az <R> (Read BIN file) billentyű leütésével kezdhető el. Ekkor megjelenik a "Start:" kérdés. Erre a 4000 begépelésével válaszoljunk, majd <ENTER>. Ezután a "End:" kérdésre 5AFF-el válaszoljunk, majd ismét <ENTER>. Most már csak a "File name:"-re kell megadnunk a SCREEN nevét, és elindul a betöltés. A töltés végén megjelenik az "End of file" hibaüzenet, alatta pedig (ha jó csináltunk mindent) a "Last address:5AFF" szöveg. Ekkor futtassuk a programunkat: "G". majd a "Start:" kérdésre válaszoljuk a kezdőcímet, vagyis a 3000-et, ismét <ENTER>. Ha jól fordítottunk, akkor rövidesen a "Returned from CALL at 3000" választ kapjuk. Ekkor a memóriában már ott a konvertált SCREEN, csak ki kell menteni. Nyomjuk le az <S> gombot (Save BIN file). A "Start"-ra adjuk meg a 4000-et, "Stop"-ra 5AFF-et,"File name:"-re egy nevet. Az így kimentett SCREEN-t visszatölthetjük az előző részben ismertetett LOADER-rel. Végezetül annyit, hogy a program nem csak SCREEN-ek konvertalására jó, de minden más esetben módosítani kell a kezdőcímet és a hosszt. Természetesen csak SPECTRUM formátumról már ENTERPRISE file-formátumra hozott SCREEN-ek konvertálhatók a leírt módszerrel.
Az eddigi számokban megpróbáltuk az alapokat tisztázni. Ezek megértése fontos a továbblépéshez. Az ASMON assembler-monitor program kezelését célszerű mihamarabb elsajátítani. Ezután a további fogásokat már egy konkrét példán keresztül fogjuk bemutatni. Az általunk választott program a "MOONCRESTA" nevet viseli, egy nemes mondanivalóval bíró űrhajós játékprogram. A választásnak több oka van:
1. A program 1984-ben készült, a programozástechnikája ember közeli, ami az újabb, "hiperszonikus" programokról már nem mondható el.
2. Terjedelme 20 kbyte alatt van, ami főleg a kazettás rendszerben dolgozók számára előnyösebb.
3. Bizonyos mértékben hasonlít az állatorvosi lóra, mivel a programátírás fő buktatói benne vannak.
4. Mivel régi program, így régi, rutinos SPECTRUM-osok való színűleg birtokolják.
Első lépésként próbáljuk kilistázni a BASIC részt (ha van rá lehetőségünk). Itt kezdődnek a problémák: a programot nem tudjuk leállítani. Ha valaki SPECTRUM-on próbálkozik, akkor szakirodalomban utána tud nézni az ilyen piszkos trükkök elleni védekezésnek. Mi ENTERPRISE-on, egy software SPECTRUM-emulátorral próbálkoztunk, ezeknek megvan az a jó tulajdonságuk, hogy le lehet BREAK-elni a programot közvetlenül betöltés után. Ha ez sikerült, még mindig nem érünk vele semmit, mert programlista helyett egy "O.K. boy" feliratot, és egy telefonszámot látunk. Megsúgjuk, hogy a sorszám nullára van állítva, ezért nem lehet vele mit kezdeni. Ezt a huncutságot egy POKE 23755,0:POKE 23756,1 parancssorral kivédhetjük. Ekkor az első sor száma 1 lesz. Ezt nyugodtan törölhetjük, mivel csak az üzenetet tartalmazza. Ha ezt megcsináltuk, akkor ismét nem tudunk mit kezdeni a programunkkal, mivel a védelem készítője a második sor sorszámát is kinullázta. Ezen a naivságon már csak gúnyosan mosolygunk, és megismételjük az előbbi POKE-okat. Most már van egy 1. sorszámú sorunk. Ezt a sort immáron önfeledten javíthatjuk. A sor elejéről a nem oda való grafikus karaktereket törölve előtűnik teljes pompájában a BASIC loader.
1 CLS: PRINT AT 10,10; FLASH 1;
"loading"; FLASH 0;AT 12,9;"plea
se wait ;TAB 7;"cracked by zec":
POKE PEEK 23633+256*PEEK 23634,P
EEK 23647:POKE (PEEK 23633+256*P
EEK 23634)+1,PE K 23648
Ebből megtudjuk azt a fontos információt, hogy egy "zec" nevű úriember törte fel az eredeti védelmet. Megnyugodhatunk tehát, a tolvajtól lopni nem bún. Ha ezt a sort is töröljük, akkor még mindig marad egy sor, amivel viszont már nem tudunk elbánni. Nem hát, mivel ez a gépi kódú loader, amit a BASIC igen rafináltan elindít. Disassemblálva a gépi kódú loader-t, a következű lista tárul ámuló szemünk elé:
LD SP,5BFFH
LD A,0FFH
SCF
LD IX,0B3B0H
LD DE,0100H
CALL 0556H
JP 0B3B0H
Egy ROM-listát előszedve tapasztalhatjuk, hogy ez nem csinál egyebet, mint beolvas egy fejléc nélküli programot a 0B3B0H címre, és ráugrik. Csavaros eszű Olvasóink bizonyára sejtik, hogy ez ismét egy loader lesz. A loader és az ezután következő viszontagságok ismertetésére legközelebb kerítünk alkalmat.
Elszántabb olvasóink okulva az előző részben leírtakból, már bizonyára betekintést nyertek a nevezetes 256 byte hosszú LOADER lelkivilágába. Aki még - kellő önbizalom hiányában - visszariadt ettől a lépéstől, annak megvilágítjuk e probléma hát terét. Mielőtt belemélyednénk, szeretnénk néhány tanácsot adni:
• Az ASMON-ban a gépi kódú programok betöltésére az "R", kimentésére az "S" parancs szolgál. Mindkettő rákérdez a start és a végcímre, valamint a betöltendő file nevére. A SPECTRUM programok átírásánál gondot okoz, hogy SPECTRUM-on a RAM terület 4000H és FFFFH között helyezkedik el, míg az ASMON csak 0801H-tól 0BFFFH-ig tud file-okat betölteni. A probléma abból származik, hogy ilyen felállásban az abszolút címhivatkozások nem érvényesek, nehezebb megtalálni az egyes szubrutinokat. A címek megtalálásának könnyítése érdekében érdemes 4000H-val alacsonyabb címre tölteni a programot. Ebben az esetben pl. a "CALL 7800H" utasítás által hívott szubrutin kezdőcíme esetünkben nem 7800H lesz, hanem ennél 4000H-val kevesebb, vagyis 3800H. Természetesen nem ez az egyedüli és üdvözítő megoldás, viszont a későbbiekben ilyen módszerrel fogjuk ismertetni az átírás egyes fázisait.
• Az "R" parancs végrehajtása után a monitor ad egy "Last address:" üzenetet, valamint egy címet. Ezt a címet érdemes felírni, a kimentéskor ez a cím lesz a végcím.
• Ha kazettás rendszerben dolgozunk, a javított programrészleteket ne az előző változat helyére mentsük ki. Az így előálló többletkereséseket a több kazettás módszerrel védhetjük ki, nevezetesen: külön kazettán legyen a betöltő, a forrásszöveg, a SCREEN, a program. Ez annyi kényelmetlenséget okoz, hogy kipróbáláskor cserélgetni kell a kazettákat, de ez mégis a kisebb baj. Ha lemezes rendszerünk van, akkor mindig készítsünk biztonsági másolatot, mivel a floppy az az eszköz, ahol kevés munkával igen sok adatot lehet elrontani. Ez csak az egyik ok. Előfordulhat olyan is, hogy az általunk kijavított program nem azonosul a feladatával, és utána nem is tudjuk visszajavítani a javítást. Ekkor kell visszamenni az előző, kevésbé jó, de még üzemképes változathoz.
Ennyi kis kitérő után térjünk rá a lényegre:
Töltsük be az eredeti helyére a LOADER-t (ez az a kivétel ami a szabályt erősíti). Az eredeti hely esetünkben 0B3B0H, ez még a szabad memória területen belül van. A betöltött programot listázzuk ki ("L" parancs). Mivel tudjuk az indítási címét, érdemes itt próbálkozni (aki kőkemény egyéniség, természetesen próbálkozhat máshol is, de kijelentjük, hogy igazat szóltunk). Az indítási cím esetünkben adódik magától, mivel megegyezik a betöltési címmel. Ha elkezdjük listázni, akkor a következő látvány tárul ámuló szemeink elé:
B3B0 31 FF 5B LD SP,5BFF ;A verem beállítása
B3B3 3E FF LD A,FF ;Annak jelzése, hogy nem fejléc
;következik
B3B5 37 SCF ;A töltés jelzése (ha CY=0, akkor
;VERIFY)
B3B6 DD 21 00 40 LD IX,4000 ;Blokk kezdocíme
83BA 11 00 1B LD DE,1B00 ;Blokk hossza
B3BD CD El B3 CALL B3E1 ;LOAD
B3C0 3E FF LD A,FF
83C2 37 SCF
B3C3 DD 21 C4 E8 LD IX,E8C4 ;A lényeget lásd fent!
B3C7 11 3C 17 LD DE,173C
B3CA CD El B3 CALL B3E1
B3CD 3E FF LD A,FF
B3CF 37 SCF
B3D0 DD 21 76 77 LD IX,7776
B304 11 A4 38 LD DE,38A4
B307 CD El B3 CALL B3E1
B3DA 31 77 E6 LD SP,E677 ;A verem bállítása (ismét)
B3DD F3 DI ;Megszakítás tiltása
B30E C3 E8 EA JP EAE8 ;Indítás
B3E1 14 INC D ;Ez itt a LOAD szubrutín
Mielőtt valaki a szavahihetőségünket kétségbe vonná, sietünk leszögezni, hogy a megjegyzések, valamint a logikai egységelv szétválasztása a mi merényletünk. Látható, hogy a LOADER 6 logikai egységből áll. Az első egy normál vagy mezei LD SP,5BFF utasítás. Ennek a verem állításán kívül semmi szerepe sincs. A második egység már érdekesebb. Mivel látjuk, hogy 4000H-re töltődik, ráadásul 1B00H a hossza, besorolhatjuk a SCREEN skatulyába. A konvertálására az előző epizódban leírt játékszabályok érvényesek.
A harmadik és a negyedik egység végzi a munka oroszlánrészét: ők töltik be a tulajdonképpeni programot, ráadásul két részletben. Az egyik E8C4H-ra 173CH, a másik 7776H-ra 38A4H mennyiségű byte-ot tölt.
Az ötödik egység végzi a program végleges elindítását, érdemes megfigyelni, hogy EAE8H-n indul a MOONCRESTA.
Végül a hatodik egység, a LOAD szubrutin, amely a kazettáról betölti az egyes file-okat. Tévedés ne essék, ez nem egy sorból áll, sőt ez a leghosszabb szubrutin a LOADER-ben, viszont nerr láttuk értelmét teljes egészében közölni.
Akit érdekel, az tanulmányozhatja, nincs benne semmi extravagáns.
Ha valaki ennyi balszerencse ás sok-sok viszály után már a hetedik menyországban érezné magát, azt ki kelt ábrándítani. A cracker nagy showman lehetett, mivel még egy kis meglepetést tartogat a tarsolyában.
Töltsük be a két modult! Az elsőt A8C4H-ra (ez már a 4000H-va alacsonyabb cím!), a másodikat 3776H-ra. Az első BFFFH-ic tart, a második 7018H-ig, erre a kimentésnél legyünk tekintettel! Listázzuk ki a programot az indítási címtől kezdve!
AAE8 3E 00 LD A,00
AAEA D3 FE OUT (FE),A ;A keret (BORDER) fekete
AAEC CD C4 E8 CALL E8C4 ;Ellenorzo byte a SCREEN-bol
AAEF 21 D6 E8 LD HL,E8DE ;Összehasonlítja az E8D6H
AAF2 BE CP (HL) ;memóriarekesz tartalmával
AAF3 CA 01 EB JP Z,EB01 ;Ha egyezik,
;EB01H-ra (AB01H) ugrik
AAF6 21 48 EE LD HL,EE48 ;Ha nem egyezik
;(változtattunk a SCREEN-en)
AAF9 01 FF FF LD BC,FFFF ;öngyilkos lesz
AAFC 11 49 EE LD DE,EE49
AAFF ED B0 LDIR
ABO1 21 11 EB LD HL,EB11 ;Itt folytatja, ha helyes
;a SCREEN
AB04 01 4A 00 LD BC,004A ;EB11H-n 4AH mennyiségű byte-ot
;XOR-ol
AB07 7A LD A,D ;az ellenőrző összeggel
ABO8 AE XOR (HL)
AB09 77 LD (HL),A
ABOA 23 INC HL
ABOB OB DEC BC
ABOC 78 LD A,B
ABOD B1 OR C
ABOE C2 07 EB JP NZ,EBO7
AB11 03 INC BC ;Látszólag értelmetlen rész,
;ezt a területet
AB12 55 LD D,L ;módosítja az előző rutin
A8C4 21 00 40 LD HL,4000 ;Az ellenőrző összeget
;képző szubrutin
A8C7 01 00 1B LD BC,1B00
A8CA AF XOR A
A8CB AE XOR (HL)
ABCC 57 LD D,A ;D-ben az ellenőrző összeg
A8CD 23 INC HL
A8CE 0B DEC BC
A8CF 78 LD A,B
A8D0 B1 OR C
A8D1 7A LD A,D
A8D2 C2 CB E8 JP NZ,E8CB
A8D5 C9 RET
Ezek után láthatjuk, milyen gonosz volt az illető. Nézzük végig a programot. Az E8C4H-n található rutin előállít egy számot. Ezt kiszámolhatjuk az eredeti SCREEN-ből, de felesleges, elég megnézni az E8D6H címen levő byte-ot. Az első néhány sort mindjárt megspórolhatjuk. EB01H-n van az első lényeges rész, a XORolás. Mivel tudjuk az ellenőrző kódot (ha valaki nem tudná, 22H), cselesen írhatunk egy kis szubrutint, ami elvégzi helyettünk eme nemes cselekedetet.
Mazochisták persze kézzel is megpróbálhatják. Mivel az elején található programrészre nem lesz szükségünk, ide beírhatjuk alkotásunkat. Ehhez szálljunk ki a listázásból (STOP vagy az ESC billentyű), majd nyomjuk meg az "M"-et. A módosítás címének kérésére adjuk az AAE8-at. Az ENTER lenyomása után kiíródik egy memóriadump, amiben tudunk módosítani. Szép sorban, az ENTER lenyomása nélkül írjuk be a következő számokat:
21 11 AB 06 4A 7E EE 22 77 23 10 F9 C9
Majd szálljunk ki a módosításból (STOP vagy ESC). Ha kilistázzuk ezt a kis programocskát, a következőket láthatjuk:
AAES 21 11 AB LD HL,AB11
AAEB 06 4A LD B,4A
AAED 7E LD A,(HL)
AAEE EE 22 XOR 22
AAFO 77 LD (HL),A
AAF1 23 INC HL
AAF2 10 F9 DJNZ AAED
AAF4 C9 RET
Futtassuk le ("G" parancs, majd AAE8, ENTER), majd ha rendesen megkaptuk a "Retumed from CALL at AAE8" üzenetet, listázzuk ki az AB11 H címet. Micsoda változás!!
AB11 21 77 77 LD HL,7777
AB14 01 A4 38 LD BC,38A4
AB17 CD 47 EB CALL EB47
AB1A 21 00 EE LD HL,EEOO
AB1D 01 00 12 LD BC,1200
AB20 CO 47 EB CALL EB47
AB23 21 77 77 LD HL,7777
AB26 01 A4 38 LD BC,38A4
AB29 CD 51 EB CALL EB51
AB2C 21 00 EE LD HL,EEOO
AB2F 01 00 12 LD BC,1200
AB32 CD 51 EB CALL EB51
AB35 21 10 A7 LD HL,A710 ;A karakterkészlet kezdőcíme
AB38 22 36 5C LD (506),H1 ;a megfelelő változóba
AB3B 01 5E 2F LD BC,2F5E
AB3E AF XOR A
AB3F ED 42 SBC HL,BC
AB41 31 2F 75 LD SP,752F
AB44 C3 6F 00 JP 006F
Tanulságul álljon itt a program által használt két szubrutin is!
AB47 7E LD A,(HL)
AB48 ED 67 RRD
AB4A 23 INC HL
AB48 OB DEC BC
AB4C 78 LD A,B
AB4D B1 OR C
AB4E 20 F7 JR NZ,AB47
AB50 C9 RET
AB51 7A LD A,D
AB52 AE XOR (HL)
AB53 77 LD (HL),A
AB54 23 INC HL
AB55 OB DEC BC
AB56 78 LD A,B
AB57 B1 OR C
AB58 20 F7 JR NZ,AB51
AB5A C9 RET
Látható, hogy a program többi része itt is el van rejtve. Ismét módosítani vagyunk kénytelenek.
A módszer hasonló az előző programocska beviteléhez, de itt az AB0F címet kell módosítanunk az alábbi byte-okra:
16 22 21 77 37 01 A4 38
CD 47 AB 21 00 AE 01 00
12 CD 47 AB 21 77 37 01
A4 38 CD 51 AB 21 00 AE
01 00 12 0 51 AB C9
Ha ezt kilistázzuk, a következőket kell látnunk:
AB0F 16 22 LD D,22
AB11 21 77 37 LD HL,3777
AB14 01 A4 38 LD BC,38A4
AB17 CD 47 AB CALL AB47
AB1A 21 00 AE LD HL,AE00
AB1D 01 00 12 LD BC,1200
AB20 CD 47 AB CALL AB47
AB23 21 77 37 LD HL,3777
AB26 01 A4 38 LD BC,38A4
AB29 CD 51 AB CALL AB51
AB2C 21 00 AE LD HL,AE00
AB2F 01 00 12 LD BC,1200
AB32 CD 51 AB CALL AB51
AB35 C9 RET
Ha nem ezt látjuk, akkor vagy valami belerepült a szemünkbe, vagy elírtunk valamit (minden bizonnyal a Tisztelt Olvasó). Miután ezzel megvagyunk, futtassuk le ezt is ("G" AB0F, ENTER), és már meg is van a futtatható (átírható) programunk. Már csak egy akadály van hátra, nevezetesen az indítási cím. Aki azt hiszi, hogy ilyet már találtunk eleget, téved. Meg kell keresnünk a - sorrendben a harmadik - helyes belépési pontot. További tortúrák helyett ezt már a tudomására hozzuk azoknak a fanatikus programozóknak, akik idáig kitartottak (jutalom): 77B2H (illetve a 4000H eltolásos módszer esetében 37B2H). Hogy ez honnan származik? Ezt az Olvasóra bízzuk (csak annyit segítségül, hogy A710H-2F5EH az pontosan 77B2H, valamint a SPECTRUM ROM-ban a 6FH címen egy szál utasítás van, ez pediglen egy JP (HL) ).
Miután így sikerült lefegyvereznünk a védelmet, akár rá is térhetnénk a program tulajdonképpeni átírására. Sajnos azonban ez a kis ujjgyakorlás sok helyet elvett, így a lényeg legközelebbre marad. Addig is, senki ne feledje el kimenteni a verejtékes munkával feltört programrészeket. Míg mindenki szívszorongva várja következő próféciánkat, el lehet kezdeni az ismerkedést a programozók stílusával, meg lehet próbálkozni egy ENTERPRISE LOADER készítésével.
Végezetül érdemes összefoglalni az eddigi file-ok adatait.
SCREEN 4000H-ra kell tölteni, 1B00H hosszban.
CODE1 7776H-ra kell tölteni, 38A4H hosszban.
CODE2 E8C4H-ra kell tölteni, 173CH hosszban.
Ha mindent betöltöttünk, el kell ugrani a 77B2H címre.
Kellemes bogarászást!
Ha valaki vette a fáradságot és előállította a program két blokkját, valamint átalakította a közölt betöltőt, csodálkozva tapasztalta, hogy a program nem igazán rendeltetésszerűen működik. Általánosságban elmondhatjuk, hogy ha egy program "elszáll", akkor annak két oka van:
1. A SPECTRUM ROM-ban lévő szubrutint hív.
2. Megszakítást alkalmaz.
Esetünkben mindkét esetre látunk majd példát, most foglalkozzunk a fontosabbal, a felhasználói megszakítással. A megszakítás olyan alprogram, amely a főprogram futása közben egy előre meghatározott esemény bekövetkeztekor hajtódik végre. Ez az esendő esemény esetünkben esetlegesen esik meg (jó mi?) mégpedig minden 1/50-ed másodpercben. A megszakítás elfogadásakor a processzor elmenti az aktuális programszámlálót (a PC regisztert), majd reagál, az üzemmódtól függően más ás más módon.
A Z80-as mikroprocesszornak 3 féle megszakításkezelése van:
1. A nullás üzemmód. Ekkor a processzor a következő utasításbyte-ot nem az aktuális memóriacímről veszi, hanem a megszakítást generáló eszköz adja. A Z80 felhasználók ezt a módszert szinte nem is használják, az INTEL 8080 miroprocesszorral való kompatibilitás miatt építették be. Beállítása az "IM 0" Z80 utasítással történik.
2. Az egyes üzemmód. Ekkor végrehajtódik egy "RST 38H" utasítás, vagyis meghívja a 38H-n lévő szubrutint. A SPECTRUM BASIC ezt használja. (Valamint az ENTERPRISE EXOS is!) Beállítása egy IM 1" (ED 56) utasítással történik.
3. A kettes üzemmód. Ez a legcifrább, de a leghasznosabb is. A megszakítási alprogram címének megtalálásához meg kell néznünk egy speciális Z80 regisztert, az "Interrupt vector register" névre hallató "I" regisztert. Ebben az üzemmódban ugyanis megszakításkérés esetén a mikroprocesszor beolvas az adatvezetékekről egy byte-ot, a felső 8 bitnek megfelelteti az "I" regiszter 8 bitjét, majd az így létrehozott 16 bites címről kiolvas egy byte-ot, majd a 16 bites címet megnövelve még egyet. Az első byte lesz az alprogram címének alsó, a második pedig a felső byte-ja. Mire jó ez? Például arra, hogy ha több egység kérhet megszakítást, akkor nem a processzor kezdi el találgatni a megszakítani kívánó személyét, hanem a periféria azonosítja magát az adatbuszra küldött byte-al. A beállítása az "IM 2" (ED 5E) utasítással történik. Ezt az utasítást mindenki jól jegyezze meg, ugyanis a programok 80-90 százaléka ilyen üzemmódot állít be.
FONTOS! A megszakítást kiszolgáló alprogramnak nem szabad megváltoztatni EGYETLEN regiszter értéket sem, amelyet a főprogram használ! A megszakítás elfogadásakor tiltódik a további megszakítások elfogadása, ezt általában az interrupt alprogram végén szokták engedélyezni. Ez mind nagyon szép - mondhatja az Olvasó - de mi szükség van ennek ismeretére? Nagyon is van, mivel az ENTERPRISE bonyolultabb megszakítás elektronikával rendelkezik. Nem egy-, hanem mindjárt négyféle megszakítási forrás áll rendelkezésre, amelyek külön-külön tilthatok, engedélyezhetők. Erre egy külön perifériacím szolgál, melynek címe a 0B4H. Ez különbözik OUT és IN műveletek esetén. Minket csak az OUT érdekel, ezért csak ezt részletezzük.
A port bitenként értelmezett:
b0 A hanggenerátor által adott megszakítás engedélyezése. (1 érték által)
b1 A hanggenerátor megszakítás tároló törlése.
b2 Az 1 Hz-es megszakítás engedélyezése.
b3 Az 1 Hz-es megszakítás tároló törlése.
b4 A video-megszakítás engedélyezése.
b5 A video-megszakítás tároló törlése.
b6 A soros vonal megszakításának engedélyezése.
b7 A soros vonal megszakítás tárolójának törlése.
Az, hogy az engedélyezésnek mi a szerepe, elég egyértelmű, ha a megfelelő helyre egy egyes bitet írunk, akkor az a forrás képes megszakítást generálni. Ha nullát írunk, akkor letiltottuk az eszközt. Az 50 Hz-es megszakítás generálásához célszerű a NICKchip által generált megszakítást használni, amit az LPT generálásakor beállítottunk.
A másik feladat - a megszakítás tároló törlése - már nem ilyen egyértelmű. A DAVE-chip (amely a megszakításrendszert istápolja) tárolja az interrupt kéréseket. Amíg nem töröltük a tárolóját, addig elnyom minden ilyen irányú próbálkozást. Tehát: ha azt akarjuk, hogy az 1/50 másodpercenként érkező megszakítások ne vesszenek el (vagyis ne "fagyjon le" a program), minden megszakítást kiszolgáló alprogram végén (vagy elején) törölnünk kell a DAVE-chip megfelelő tárolóját. A video-megszakítás újraengedélyezését végző rutin az alábbi:
LD A,30H ;b4 +b5, video IT. engedélyezés, tároló törlése
OUT (OB4H),A ;A DAVE-chip megfelelo regisztere
Arra természetesen figyeljünk, hogy mentsük az "A" regiszter a művelet előtt.
Most nézzük meg, hogy a nagy fáradsággal átmentett "MOON CRESTA" hogyan csinálja. A program indítási címe 77B2H.
7782 F3 DI ;Megszakítás tiltása.
77B3 31 43 F6 LD SP,F643 ;Verem állítás.
77B6 21 10 A7 LD HL,A710 ;Karakterkészlet helyének
7789 22 36 5C LD (5C36),HL ;tárolása az 5C36H címen.
77BC 21 05 40 LD HL,4005 ;A betöltőkép tárolása
77BF 11 1B 5C LD DE,5C7B
77C2 01 FB 1A LD BC,lAFB
77C5 ED B0 LDIR
77C7 21 00 F5 LD HL,F500 ;Interrupt cím beállítása.
77CA 11 01 F5 LD DE,F501
77CD 01 01 01 LD BC,0101
77D0 36 77 LD (HL),77 ;A megszakítási rutin 7777H-n.
77D2 ED B0 LDIR
77D4 3E F5 LD A,F5 ;A táblázat felső byte-ja (F5H)
77D6 ED 47 LD I,A ;az "I" regiszterben.
77D8 ED 5E IM 2 ;Kettes mód beállítás.
77DA FB EI ;Megszakítás engedélyezése.
Biztos mindenki megdöbbent a 257 elemű táblázaton. Erre azért van szükség, mivel a táblázat alsó byte-ja (amit a periféria ad) nem eléggé biztos. (Általában FFH) Ezzel a módszerrel minden kombinációra bebiztosították magukat a programozók. Az ilyen táblázatos módszerek leggonoszabbja az, amikor a táblazat csupa 255-bol áll, tehát a megszakítási rutin címe 65535 (FFFFH). Erre az egy byte-ra leraknak egy "JR" utasításnak megfelelő 18H-t, amelynek operandusa a 0 címen lévő (SPECTRUM BASIC) 0F3H. Ez a relatív ugrás visszaugrik a 0FFF4H címre, ahol egy ugró utasítás visz a tulajdonképpeni megszakítási alprogramra. A következő LOADER a kész játék végső betöltője, ezért érdemes beírni. A megszakítási problémát úgy küzdöttek le, hogy 7777H-ra (az IT rutin) letettünk egy "JP" utasítást, előbb engedélyezzük a DAVE-chipben az interruptot, majd ráugrunk a tulajdonképpeni rutinra.
Mint látható, a program két blokkját nemes egyszerűséggel csak "ALSO" és "FELSO" névvel illettük, ezáltal is jelezve az elhelyezkedésüket. A betöltő elején található rutinok méltatására a későbbiekben visszatérünk. Ezzel a betöltővel futtatva a "MOON CRESTA"-t már hajlandó elindulni. (Igaz sok köszönet nincs benne!)
És most essék néhány szó a SPECTRUM billentyűzetfigyeléséről: Az összes gomb egy mátrixba van kötve. A mátrix sorát mi közöljük a géppel igen ravasz módon, az oszlopot pedig szerény kérésünkre válaszként kapjuk. A sor kiválasztását igen érdekesen oldották meg. Kihasználták a mikroprocesszor ama tulajdonságát, hogy IN/OUT műveletek esetén a címbusz felső 8 bitjén is értékes adat van. Vegyünk példának egy IN A,(0FEH) utasítást!
Ekkor a címbusz alsó 8 bitje a periféria címét (jelen esetben a 0FEH-t), míg a felső 8 bit az "A" regiszter beolvasás előtti értékét tartalmazza. A másik fajta "IN" utasításcsoport esetén (az IN r,(C) ) a "B" regiszter kerül hasonló helyzetbe.
A SPECTRUM a billentyűket egy 8*5 elemű mátrixban kezeli. A 8 sor eléggé sokatmondó, mivel pontosan ennyi bit van egy byteban. A 8 sornak tehát megfelel 8 bit, amelyik bit 0 értékű, azt a sort olvassa be a processzor. Mivel egy byte-on belül bármelyik bit lehet 0, ezért egy utasítással több sort is le lehet kérdezni. A kiválasztott sort a 254-es (0FEH) porton lehet beolvasni, az alsó 5 bit hordozza a billentyűzet információit. Konkrétan: az 1,2,3,4,5 gombok vizsgálata az alábbi kis programocskával történhet.
1.variáció 2.variáció
LD A,0F7H LD BC,OF7FEH
IN A,(0FEH) IN A,(C)
Működés szempontjából a két módozat egyenértékű, a 2. variáció azonban használja a "BC" regiszterpárt. A gyakorlatban mindkét variáció előfordul.
Ha billentyűfigyelést keresünk egy programban, akkor a következő utasításokra figyeljünk fokozottan:
Utasítás HEXA kód
IN A,(OFEH) DB FE
IN A,(C) E0 78
IN B,(C) ED 40
IN C,(C) ED 48
IN D,(C) ED 50
IN E,(C) ED 58
1N H,(C) ED 60
IN L,(C) ED 68
Mielőtt bárki azt hinné, hogy az első két utasításon kívül mást nem használnak, az nem jár messze az igazságtól, viszont elrettentésül megjegyeznénk, hogy leltünk mar IN C,(C) utasítást is, amely az irányítás nemes feladatát volt hivatva betölteni. Gyakran előfordul a teljes klaviatura lekérdezése is. Ez SPECTRUM-on egyszerű, ENTERPRISE-on viszont már nem. (Ha valaki nem tudna, egy
XOR A
IN A,(0FEH)
nagyon megfelelő ilyen célokra.)
A téma lezárásaként itt van a sokat emlegetett mátrix.
A SPECTRUM billentyűzetmátrix:
BIN DEC HEX 1 2 4 8 16
b0 b1 b2 b3 b4
11111110 254 FE Caps Z X C V
11111101 253 FD A S D F G
11111011 251 FB Q W E R T
11110111 247 F7 1 2 3 4 5
11101111 239 EF 0 9 8 7 6
11011111 223 DF P 0 I U Y
10111111 191 BF Enter L K J H
01111111 127 7F Space Symbol M N B
Miután a SPECTRUM klaviatura-kérdést ilyen jól helybenhagytuk, rátérhetünk az ENTERPRISE oldalára. A mátrix módszer itt is alkalmazott, viszont - a több gomb miatt - némileg eltér a fent említettől. Először is, nem 8 sor van, hanem 10. Ez előrevetíti ama szomorú tény árnyékát, hogy nem fér egy byte-ban (vagyis csak a külön bites módszerrel nem). Másodszor: nem 5 oszlopot olvasunk be, hanem 8-at. Ezzel a módszerrel 80 gomb figyelésére van mód, ebből néhány nem használt. Azt, hogy melyik sort (0-tól 9-ig számozva) akarjuk olvasni, a 0B5H című porton kell közölnünk. Miután ezt közöltük, rendelkezésünkre áll ugyanezen a porton az adat. Előző példánknál maradva az 1-5 billentyűket az
LD A,3
OUT (0B5H),A
IN A,(0B5H)
utasításokkal figyelhetjük. Látható, hogy az előbbi 4 byte-tal szemben most ugyanez 6 byte hosszan sikerült. Vagyis nem fér be az eredeti helyére. Itt három dolgot tehetünk:
1. Hagyjuk az egészet és elmegyünk dominózni.
2. A memória egy nem használt helyére megírjuk szubrutinként, majd az eredeti programrészt lecseréljük egy "CALL" utasításra.
3. Addig erőltetjük (jó VOGON szokás szerint) amíg nem sikerül begyurna az eredeti helyére.
Kétségkívül az első módszer a legegyszerűbb, viszont a harmadik a legszimpatikusabb, ennek ellenére mi a másodikat fogjuk bemutatni. Ennek okai: minek riasszuk el az Olvasót ilyen korai stádiumban? Végezetül íme, az ENTERPRISE billentyűzetmátrix:
b7 b6 b5 b4 b3 b2 b1 b0
128 64 32 16 8 4 2 1
Sor 80H 40H 20H 10H 08H 04H 02H 01H
0 B.SH. Z X V C B \ N
1 CTRL A S F D G LOCK H
2 TAB W E T R Y Q U
3 ESC 2 3 5 4 6 1 7
4 F1 F2 F7 F5 F6 F3 F8 F4
5 ERASE ^ 0 - 9 8
6 ] : L ; K J
7 ALT ENTER BAL HOLD FEL JOBB LE STOP
8 INS SPACE J.SH. . / , DEL M
9 [ P @ 0 I
Miután sikerült leimádkoznunk a védelmet a programról, valamint tisztáztunk néhány alapfogalmat, rátérhetünk munkánk érdemi részére.
Az előző részben már elindítottuk a "MOON CRESTA"-t, de egy kis DEMO-n kívül mást nem hajlandó csinálni. Az ok kézenfekvő: azért nem reagál a billentyűkre, mivel még a SPECTRUM módszerével figyeli azokat!
Tehát a feladat:
1. Felkutatni a vitás részeket és
2. módosítani ENTERPRISE formára.
Töltsük be a két a programfile-t, majd használjuk az ASMON keresés funkcióját. (A funkció aktivizálására szolgáló billentyűt legcélszerűbb a "H" (HELP) billentyű lenyomása után megjelenő menüből kinézni. Angol gépeken a hatványjel.)
Először próbálkozzunk a legkézenfekvőbbel, az IN A,(0FEH) utasítással. A keresés billentyűjének lenyomása után megjelenik egy "Start:" kérdés, majd utána egy szám. Első kereséskor ide írjuk be a kezdőcímet, további keresésekhez elegendő "ENTER"-t nyomni, ekkor folytatja a keresést.
Miután kijelöltük a kezdőcímet, a "Search:" kérdésre írjuk be az IN utasítás Z80 kódját. Aki olvasta az előző részt, már fejből tudja, aki nem olvasta, az szégyellje magát! De már-már közmondásos nagylelkűségünknek engedve eláruljuk, hogy 0DBH. Tehát a "Search:" kérdésre gépeljük be azt, hogy "DB FE". Az idézőjel természetesen nem kell, mivel ha kitesszük az idézőjeleket, akkor azt a karaktersorozatot fogja keresni.
Miután leütöttük az "ENTER"-t, kis gondolkozás után a "Found at:" üzenet ás egy memóriacím, alatta pedig három sorban memóriadump jelenik meg. Ha nem ez történne, akkor áldásos tevékenységünk mégsem volt annyira áldásos.
Most vegyük a kedvezőbb esetet, tételezzük fel, hogy sikeres volt az akciónk. Közbevetőleg egy jótanács! Keresésnél a kiírt címnél mindig néhány byte-tal alacsonyabb címtől kezdjük a listázást!
Nos, nézzük, mit találtunk.
3887 06 00 LD B,00
3889 AF XOR A
388A DB FE IN A,(FE)
388C E6 1F AND 1F
388E FE 1F CP 1F
3890 C2 E3 79 JP NZ,79E3
3893 76 HALT
3894 10 F3 DJNZ 3889
(A memóriacímek természetesen 4000H-val magasabban értendők!)
Mit is csinál ez a kis rutin?
A lényeg a
XOR A
IN A,(FE)
rész. A "XOR A" utasítás saját magával végez "kizáró VAGY" kapcsolatot. Ezt bitenként végzi, vagyis a 0.bitet a 0.bittel stb... A "XOR" művelet akkor ad "1" értéket, ha a két bit különböző. Mivel az "A" regiszter teljesen illogikus módon megegyezik saját magával, ezért a "XOR A" művelet eredménye mindig 0-t ad. Egyébként ez a módszer nagyon elterjedt a "LD A,0" (2 byte) utasítás helyett (mivel ez csak egy byte). Az "IN A,(FE)" utasításról volt már szó. Ha az "A" regiszterben nulla van, az az összes sort kijelöli, vagyis a teljes billentyűzetet leolvassa.
A következő, "AND 1F" utasítás csak a billentyűzetről származó adatokat tartja meg. Ezután megnézi, hogy volt-e lenyomott billentyű (CP 1F). Ha volt, akkor az "A" nem 1FH lesz, ekkor elugrik a 79E3H címre, ha nem volt lenyomott billentyű, akkor vár 1/50 másodpercet, majd újra leolvassa a klaviatúrát, és ez így megy 256-szor. (A "DJNZ" utasítást illik ismerni!)
Miután így a felderítést letudtuk, a következő feladat a probléma leküzdése.
Ez már kicsit bonyolultabb, de nem kell kétségbe esni! Az valószínűleg világos, hogy ide nem fér be az általunk elkészíteni szándékozott helyettesítő szubrutin. Az előző számban közöltünk egy LOADER-t a programhoz. Annak az elején volt néhány szubrutin, amit nem részleteztünk kellőképpen (mondhatni sehogyan). Örömmel közöljük, hogy ez a felemelő pillanat most érkezett el! (Legalábbis részben.)
A betöltő így kezdődik:
ORG 256
JP CONT ;100H
JP KEY ;103H
JP ALLKEY ;106H
JP JOY ;109H
JP BEEP ;10CH
A megjegyzés rovatban az egyes JP utasítások címei lettek feltüntetve hexadecimálisan. Az ilyen JP utasításokból álló programrészt hívják ugrótáblázatnak. Kicsit nagyképűen mi is ilyen névvel fogjuk illetni. Mint látható, mindegyik egy-egy rutinra ugrik. Teljesen jogos a kérdés, hogy mi szükség van erre, amikor a rutinokat direkten is lehetne hívni? Ez teljesen igaz, viszont, ha egy rutint megváltoztatunk (például beszúrunk egy byte-ot), az összes többi is megváltozik. Ekkor az összes hivatkozást meg kellene változtatni, ami esetünkben pI., az "ALLKEY" nevű szubrutin esetén eléggé munkaigényes (és felesleges). Az ugrótáblázat alkalmazásával ez a probléma elveszti jelentőségét, mivel itt csak az egyes JP-okat kell módosítani.
Természetesen, ha valaki úgy írja meg a kellő részeket, hogy azokat később nem kell módosítani, akkor nincs szükség az itt leírtakra. Azonban - minden ellenkező híreszteléssel ellentétben - senki sem tökéletes, mindenki követhet el hibákat (sőt, csak azt!), így szerény véleményünk szerint az általunk eloadott módszer a legkevésbé fáradságos!
Az imént már emlegettük az "ALLKEY" szubrutint, a szemfülesebbek biztosan kitalálták, hogy nem véletlenül! Mint neve is sejtetni engedi, ez a teljes billentyűzetet lekérdező rutin. vizsgáljuk meg a működését!
ALLKEY PUSH BC ;A BC regiszterpár elmentése
LD BC,0AFFH ;B=0AH, C=0FFH
;B: 10 sor van a billentyűzeten
;C: minden oszlop inaktív
;(kezdetben)
A1 LD A,B ;A=sor
DEC A ;A=A-1, mivel nem 10-től l-ig,
;hanem 9-tol 0-ig van a
;billentyűzet sorszámozása
OUT (0B5H),A ;A sorszám kiküldése a megfelelő
;portra
IN A,(0B5H) ;Az oszlop érték visszaolvasása
;0FFH, ha nincs lenyomva gomb
AND C
LD C,A ;Ha valamelyik sorban volt lenyomva
;billentyű, akkor a "C" regiszter
;nem lehet 0FFH
DJNZ A1 ;Mind a 10 sor leolvasása
;Az "A" regiszterben is
;megtalálható a végérték
POP BC ;A "BC" regiszterpár
;visszatöltése
RET ;Visszatérés
Ezzel a kis programmal szimuláljuk a teljes billentyűzetleolvasást, egy "CALL 106H' utasítással hívhatjuk. Látható, hogy ez is három byte a
XOR A
IN A,(FE)
-hez hasonlóan, tehát gond nélkül elhelyezhető elődje helyén.
A "CALL 106H" utasítás gépi kódja: CD 06 01 (hexában), tehát az elozo programrészt módosítsuk a következőre:
3887 06 00 LD B,00
3889 CD 06 01 CALL 0106
388C E6 FF AND FF
388E FE FF CP FF
3890 C2 E3 79 JP NZ,79E3
3893 76 HALT
3894 10 F3 DJNZ 3889
Talán feltűnt, hogy az "AND 1F" utasítást "AND FF"-re és a "CP 1F"-et "CP FF"-re cseréltük, ez a teljes billentyűzet figyelése miatt szükséges.
Miután ily módon átestünk a tűzkeresztségen, folytathatjuk a keresést.
3967 06 14 LD B,14
3969 AF XOR A
396A DB FE IN A,(FE)
396C E6 1F AND 1F
396E FE 1F CP 1F
3970 C2 E3 79 JP NZ,79E3
3973 76 HALT
3974 10 F3 DJNZ 3969
3994 06 1E LD B,1E
3996 AF XOR A
3997 DB FE IN A,(FE)
3999 E6 1F AND 1F
399B FE 1F CP 1F
399D C2 E3 79 JP NZ,79E3
39A0 76 HALT
39A1 10 F3 DJNZ 3996
39BF 06 64 LD B,64
39C1 AF XOR A
39C2 DB FE IN A,(FE)
39C4 E6 1F AND 1F
39C6 FE 1F CP 1F
39C8 C2 E3 79 JP NZ,79E3
39CB 76 HALT
39CC 10 F3 DJNZ 39C1
39D4 06 00 LD B,00
39D6 76 HALT
39D7 AF XOR A
39D8 DB FE IN A,(FE)
39DA E6 1F AND 1F
39DC FE 1F CP 1F
39DE C2 E3 79 JP NZ,79E3
39E1 10 F3 DJNZ 39D6
Ezek mind egy kaptafára készültek, kár is rájuk több szót vesztegetni, az eddigiek alapján csak rutinmunka az átírásuk.
A most következő viszont annál érdekesebb!
3C10 AF XOR A
3C11 DB FE IN A,(FE)
3C13 E6 1F AND 1F
3C15 FE 1F CP 1F
3C17 C2 10 7C JP NZ,7C10
Ez, ugyebár ismerős?
3C1A 06 00 LD B,00
3C1C 3E EF LD A,EF
3C1E DB FE IN A,(FE)
3C20 CB 67 BIT 4,A
3C22 CA 31 81 JP Z,8131
Akik rendelkeznek az előző számban szereplő, nagy kaliberű SPECTRUM billentyű-táblázattal, már tudhatják, hogy ez a "6" billentyűt figyeli.
3C25 3E F7 LD A,F7
3C27 DB FE IN A,(FE)
Az "A" regiszterben az "12345" billentyűknek megfelelő sor.
3C29 CB 47 BIT 0,A
3C2B C2 36 7C JP NZ,7C36
3C2E 3E 01 LD A,01
3C30 32 C2 87 LD (87C2),A
3C33 C3 5E 7B JP 7B5E
Az "1" billentyű esetén a 87C2H memóriacímre betölt 01H-t, majd ráugrik a 7B5EH címre.
3C36 CB 4F BIT 1,A
3C38 C2 43 7C JP NZ,7C43
3C3B 3E 02 LD A,02
3C3D 32 C2 87 LD (87C2),A
3C40 C3 5E 7B JP 7B5E
A "2" billentyű hasonlóképpen.
3C43 CB 57 BIT 2,A
3C45 C2 4E 7C JP NZ,7C4E
3C48 32 5E F3 LD (F35E),A
3C4B C3 5E 7B JP 7B5E
A "3" billentyű.
3C4E CB 5F BIT 3,A
3C50 C2 5A 7C JP NZ,7C5A
3C53 AF XOR A
3C54 32 5E F3 LD (F35E),A
3C57 C3 5E 7B JP 7B5E
A "4" billentyű.
3C5A CB 67 BIT 4,A
3C5C CA DB 7C JP Z,7CDB
"5" esetén folytatja a 7CDBH címen, egyébként várakozik, majd újraolvassa a billentyűzetet 256-szor.
3C5F 76 HALT
3C60 10 BA DJNZ 3C1C
3C62 C3 52 78 JP 7852
7852H-n folytatja, ha több mint 5 másodpercig nem nyomjuk meg az 1-6 billentyűk közül valamelyiket.
Talán kitalálták már, hogy ez itt a menü volt.
Most mit tegyünk?
Az látható, hogy itt sem fér be a módosított rutin az eredeti helyére, viszont van a mi kis betöltőnkben egy "KEY" nevű szubrutin (103H a belépési pontja). Eléggé furcsán néz ki:
KEY EX (SP),HL ;HL és a STACK-ban lévő 16 bites
;adat kicserélése
;Ekkor (ha CALL-al hívjuk meg) a
;visszatérési cím található itt
LD A,(HL) ;A visszatérési címen található
;byte betöltése "A"-ba
INC HL ;A visszatérési cím növelése eggyel.
EX (SP),HL ;HL visszatöltése
OUT (0B5H),A
IN A,(0B5H)
RET
A szubrutin hívása némi hasonlóságot mutat az EXOS hívásával:
CALL 103H
DEFB SOR
Például, ha a számok sorát akarjuk beolvasni, adjuk ki a
CALL 103H
DEFB 3
utasításokat.
Előző programrészletünk módosítva:
3C10 CD 06 01 CALL 0106
3C13 E6 FF AND FF
3C15 FE FF CP FF
3C17 C2 10 7C JP NZ,7C10
3C1A 06 00 LD B,00
3C1C CD 03 01 CALL 0103
3C1F 03 INC BC ;ADAT
3C20 CB 57 BIT 2,A ;Megváltozik a ;bitkiosztás
3C22 CA 31 81 JP Z,8131
3C25 CD 03 01 CALL 0103
3C28 03 INC BC ;ADAT
3C29 CB 4F BIT 1,A ;Az "1" billentyű
3C2B C2 36 7C JP NZ,7C36
3C2E 3E 01 LD A,01
3C30 32 C2 87 LD (87C2),A
3C33 C3 5E 7B JP 7B5E
3C36 CB 77 BIT 6,A ;A "2" billentyű
3C38 C2 43 7C JP NZ,7C43
3C3B 3E 02 LD A,02
3C3D 32 C2 87 LD (87C2),A
3C40 C3 SE 7B JP 7B5E
3C43 CB 6F BIT 5,A ;A "3" billentyű
3C45 C2 4E 7C JP NZ,7C4E
3C48 32 5E F3 LD (F35E),A
3C4B C3 5E 7B JP 7B5E
3C4E CB 5F BIT 3,A ;A "4" billentyű
3C50 C2 5A 7C JP NZ,7C5A
3C53 AF XOR A
3C54 32 5E F3 LD (F35E),A
3C57 C3 5E 7B JP 7B5E
3C5A CB 67 BIT 4,A ;Az "5" billentyű
3C5C CA DB 7C JP Z,7CDB
3C5F 76 HALT
3C60 10 BA DJNZ 3C1C
3C62 C3 52 78 JP 7852
Ha ezzel is megvagyunk, folytathatjuk önfeledt módosítgatásainkat:
3D15 06 19 LD B,19
3D17 76 HALT
3D18 AF XOR A
3D19 DB FE IN A,(FE)
3D1B E6 1F AND 1F
3D1D FE 1F CP 1F
3D1F C2 27 7D JP NZ,7D27
3D22 10 F3 DJNZ 3D17
3D24 C3 FE 7C JP 7CFE
3DA2 06 19 LD B,19
3DA4 76 HALT
3DA5 AF XOR A
3DA6 DB FE IN A,(FE)
3DA8 E6 1F AND 1F
3DAA FE 1F CP 1F
3DAC C2 B4 7D JP NZ,7DB4
3DAF 10 F3 DJNZ 3DA4
3DB1 C3 8A 7D JP 7D8A
3E2F 06 19 LD B,19
3E31 76 HALT
3E32 AF XOR A
3E33 DB FE IN A,(FE)
3E35 E6 1F AND 1F
3E37 FE 1F CP 1F
3E39 C2 41 7E JP NZ,7E41
3E3C 10 F3 DJNZ 3E31
3E3E C3 18 7E JP 7E18
3EBB 06 19 LD B,19
3EBD 76 HALT
3EBE AF XOR A
3EBF DB FE IN A,(FE)
3EC1 E6 1F AND 1F
3EC3 FE 1F CP 1F
3EC5 C2 CD 7E JP NZ,7ECD
3EC8 10 F3 DJNZ 3EBD
3ECA C3 A4 7E JP 7EA4
3F4C 06 19 LD B,19
3F4E 76 HALT
3F4F AF XOR A
3F50 DB FE IN A,(FE)
3F52 E6 1F AND 1F
3F54 FE 1F CP 1F
3F56 C2 5E 7F JP NZ,7F5E
3F59 10 F3 DJNZ 3F4E
3F5B C3 34 7F JP 7F34
És most ismét kizökkent bennünket valami kedvenc szórakozásunkból!
3FD9 06 19 LD B,19
3FDB 76 HALT
3FDC 3E DF LD A,DF
3FDE DB FE IN A,(FE)
3FE0 CB 67 BIT 4,A
3FE2 CA F3 7F JP Z,7FF3 ;Az "Y" billentyű
3FE5 3E 7F LD A,7F
3FE7 DB FE IN A,(FE)
3FE9 CB 5F BIT 3,A
3FEB CA DB 7C JP Z,7CDB ;Az "N" billentyu
3FEE 10 EB DJNZ 3FDB
3FFO C3 C3 7F JP 7FC3
Ezt már akár bekötött szemmel is meg lehet csinálni!
3FD9 06 19 LD B,19
3FDB 76 HALT
3FDC CD 03 01 CALL 0103
3FDF 02 LD (BC),A ;ADAT
3FEO CB 57 BIT 2,A ;Az "Y" billentyű
3FE2 CA F3 7F JP Z,7FF3
3FE5 CD 03 01 CALL 0103
3FE8 00 NOP ;ADAT
3FE9 CB 47 BIT 0,A ;A "N" billentyű
3FEB CA DB 7C JP Z,7CDB
3FEE 10 EB DJNZ 3FDB
3FFO C3 C3 7F JP 7FC3
Ezután már csak egy fontos dolgunk van:
42A4 AF XOR A
42A5 DB FE IN A,(FE)
42A7 E6 1F AND 1F
42A9 FE 1F CP 1F
42AB CA B3 82 JP Z,82B3
Még ezután is van billentyűzetfigyelés, de azt már legközelebbre hagyjuk.
Ha az imént leírt módosításokat elvégezzük (és ki is mentjük!), már be tudjuk állítani a vezérlés módját, a játékosok számát, valamint mindezek méltó megkoronázásaként el is tudjuk indítani a programot. Játszani ugyan nem tudunk vele - mivel igen gyorsan lefagy -, de megtettük az első fontos lépést. Azt, hogy miért fagy le, valamint az egyéb ROM-hívások előtalálásának módozatait legközelebb ecseteljük.
Örömmel közölhetjük, hogy sorozatunk egy történelmi pillanathoz érkezett!
Az alábbiakban leírtak szerint eljárva végre működőképessé varázsolhatjuk mindenki szeretett MOON CRESTA-ját. Legutóbb odáig jutottunk, hogy elindul a játék, de rögvest meg is dermed. Már említettük - valamikor a múlt ködébe veszően - a "lefagyás" lehetséges okait. Mivel az első számú közellenséget (az interruptot) már kétvállra fektettük, marad a nem kevésbé alattomos ROM hívás. (Természetesen más ok előfordulhat, például elfelejtettük bekapcsolni a gépet.) Miután a követendő utat szellemünk lángoló fáklyaként már bevilágította, már csak elő kellene találni a hívások helyeit. Erre alkalmas az itt következő kis program:
ORG 1000H ;Ide fordítjuk
L1 LD A,(IX)
INC IX
CP 0CDH ;CALL utasítás?
JR Z,L2 ;Ha igen, akkor L2
CP 0C3H ;JP utasítás?
JR NZ,L1 ;Ha nem, akkor következő byte
L2 LD L,(IX+0) ;Operandusok vizsgálata
LD H,(IX+1)
LD BC,4000H ;Ha nem a ROM-ra vonatkoznak
OR A
SBC HL,BC
JR NC,L1 ;következő utasítás keresése
RET ;Ha egy ROM hívás, visszatérés
A program megértéséhez annyit kell tudni. hogy SPECTRUM-on a ROM a 0000H-3FFFH címtartományban helyezkedik el. A "CALL" Z80 utasítás kódja HEXA 0CDH, a "JP" kódja pedig 0C3H. Fordítsuk le a programot a memóriába 0 oflsettel. IX regiszterbe írjuk be a program kezdőcímét ("X" parancs, majd a "Registerpair:" kérdesre írjuk be az "IX"-et, a "Value:" kérdésre pedig a program kezdőcímét.) Ezután "G", majd a "Start:" kérdésre adjunk 1000-et. Amennyiben a program talált valamit, egy hanghatás után visszatér az ASMON-ba. Ekkor IX a ROM hívás operandusára fog mutatni.
FIGYELEM!
Nem mind arany, ami fénylik! Véletlenszemen is előfordulhatnak olyan byte kombinációk, amik megegyeznek a ROM hívással. Ezért amint találtunk valamit, a reménybeli hívás címétől számoljunk vissza néhány byte-ot, majd innen listázzuk ki a programot. Ha a listázás során értelmes kódot latunk, valamint a ROM hívás is látható, akkor valószínűleg megtaláltuk. A programban szereplő ÖSSZES hívást javítsuk ki.
Leggyakrabban eloforduló hívások:
006FH Egy "JP (HL)" utasítás.
007CH Egy "RET" utasítás.
028EH KEY-SCAN rutin (billentyűzet leolvasó)
03R5H BEEP rutin (hangkiadó rutin)
04C2H SAVE rutin
055CH LOAD rutin
22B0H PIXEL-ADD rutin (képpont címének kiszámítása)
Kanyarodjunk vissza kedvenc MOON CRESTA programunkhoz. Ha itt keressük a ROM hívásokat, elég sokat találunk. Köszönhető ez annak, hogy a billentyű figyeléseket már kijavítottuk saját rutin hívásokra, amik az alsó 16k területen vannak, imigyen kimerítve a SPECTRUM ROM fogalmát. Viszont a sok álhívás mögött meglapulva akad néhány igazi is. Ezek:
5398 2A C4 87 LD HL,(87C4)
5398 23 INC HL
539C 22 C4 87 LD (87C4),HL
539F 11 01 00 LD DE,0001
53A2 CD B6 03 CALL 03B6
53A5 FD 21 48 89 LD IY,8948
(A címekhez 4000H-t hozzá kell adni!)
A 03B6H ugyan kimaradt a felsorolásból, de ez mégis a BEEP rutin, csak a kezdeti "DI" utasítást ugorja át a program. A LOADER-ben a 010CH címen kezdődik egy rutin amely feladatáról nem szóltunk, ez a BEEP rutin ENTERPRISE környezetre honosítva. Tehát a javítás így néz ki:
53A2 CD 0C 01 CALL 0100
Még két ilyen ilyen hívás van, ezeket nem részletezzük:
561A 11 01 00 LD DE,0001
561D 21 58 02 LD HL,0258
5620 CD B6 03 CALL 0386
5623 FO 6E 00 LD L,(IY)
5626 26 FF LD H,FF
5620 CD OC 01 CALL 010C
6594 7A LD A,D
6595 83 OR E
6596 CA A7 A5 JP Z,A5A7
6599 CB 7A BIT 1,0
b59B CO RET NZ
659C CD B6 03 CALL J3B6
659F 11 04 00 LD DE,0004
65A2 FD 19 ADD IY,DE
659C CD OC 01 CALL 010C
Ha a javításokat kimentjük, majd betöltjük a programot, már elindul, zenél és játszana, ha tudnánk irányítani. (A zene idézőjelben értendő, nem sokkal múlja felül pl. a BROS színvonalát)
Előfordulhat olyan Olvasó is, aki maga is szeretne aktív részese lenni a játéknak (elégedetlenek mindig vannak). Az ilyen extrém kívánságok teljesítését szolgálja a betöltőben lévő "JOY" nevezetű szubrutin. Működésérői csak annyit, hogy ENTERPRISE-on a két külső joystick leolvasása a 0B6H porton lehetséges. A módszer teljesen hasonló, mint a billentyűzet esetében. A kívánt iránynak megfelelő értéket a 0B5H portra kell kiküldeni, majd a választ a 0B6H port 0.bitjén olvashatjuk be. Ha aktív az irány, akkor a bit 0 értékű. Az irányoknak megfelelő értékek (a külső 1. joystick az EXT1, a külső 2. pedig az EXT2 nevet viseli).
0 EXT1 tűz
1 EXT1 fel
2 EXT1 le
3 EXT1 balra
4 EXT1 jobbra
5 EXT2 tűz
6 EXT2 fel
7 EXT2 le
8 EXT2 balra
9 EXT2 jobbra
A JOY rutin leolvassa mindkét joystick állapotát, majd ezt az értéket visszaadja az "A" regiszterben, a következő bitkiosztásban:
b0 jobbra
b1 balra
b2 le
b3 fel
b4 tűz
A rutin az "RST 28H" utasítással hívható, az aktív irányt a bit 1 állapota jelzi. Az egyszerűség kedvéért a játékban csak a joystick vezérlést írtuk át. A program SPECTRUM-on a KEMPSTON-rendszerű illesztővel üzemel (a JOYSTICK CONTROL územmódban). KEMPSTON joystick esetében a botkormány állapotát a decimális 31 (HEXA 1 FH) portról lehet beolvasni. A bitkiosztás megegyezik rutinunk bitkiosztásával, itt is az 1 állapot az aktív. Tehát nincs más teendőnk, mint előkeresni az összes "IN A,(1FH)" utasítást (2 byte) és kicserélni egy "RST 28H" utasításra (1 byte, a másik byte-ot 0-ra írjuk át).
A joystick figyelés előfordulási helyei:
502BH 6246H Ezek az "ALSO" file-ban vannak
5032H 6259H
5039H 626EH
B023H Ezek a "FELSO" file-ban vannak.
B053H
Például:
5028 DB lE IN A,(1F)
Ezt kell
5028 EF 00 RST 28-ra
javítani.
Ha így felszereljük programunkat, betöltjük, majd a '4' billentyűvel JOYSTICK CONTROL opcióba állítjuk, végezetül pedig a '6' billentyűvel elindítjuk a játékot, már lőhetjük is önfeledten a gonosz ellenséges űrhajókat. Azaz...
A színek nem mondhatók éppen ideálisnak - sőt - és a harmadik pályán zöld alapon zöld szín adódik, amitől a zöld csillagokat is vörösnek látjuk. Ezen probléma (amely egyben az utolsó) leküzdéséhez legközelebb adunk tanácsokat...
Örömmel tudatjuk Olvasóinkkal, hogy elérkeztünk az utolsó, és egyben legnehezebb feladatunkhoz, Talán még emlékeznek, hogy kedvenc MOON CRESTA nevű programunk már elindul, játszani lehet vele, de a színek összeállítása meglehetősen avantgard. Az alábbiakban eme kellemetlenség megszüntetéséhez szeretnénk néhány ötletet közölni.
A színek megváltozásának okáról a betöltőkép javítása során már volt szó, így ezt nem részletezzük. A program által generált színek esetében csak annyival bonyolultabb a helyzet, hogy ilyenkor nem tudni, a program melyik részében foglalkozik az attributum memóriával. A sikeres színjavítás feltétele, hogy képesek legyünk a vitális részeket megkeresni a programban.
Hogyan lássunk neki?
Először is: meg kell keresni minden abszolút címhivatkozást, amely az attribútummemóriára mutat, pI.: LD HL,5800H stb. Általában a HL regiszterpárra hivatkoznak, a DE kevésbé népszerű, a BC pedig szinte elhanyagolható. A megfelelő hivatkozásokat a ROM hívás kereső programunk megfelelő átalakításával tehetjük meg. A LD HL,nn utasítás Z80 kódja: 21H. Ha megvan a hivatkozás, utána végig kell követni, mikor tölt adatot erre a helyre, Ez az adat az attribútum-byte. Kijavítása a korábbi számban közölt színtáblázat segítségével történik.
Másodszor: a színbeállítás történhet direkt töltéssel is (pI.: LD (5800H),A). Ezek keresésére és javítására ugyanazok vonatkoznak, mint az előzőekre.
Harmadszor: a bitmap címéből számítják ki a hozzátartozó attribútum címet.
Ennek két leggyakoribb változata (HL pixelcím):
LD A,H
RRA
RRA
RRA
AND 3
OR 58H
LD H,A
avagy
LD A,H
AND 18H
RRA
RRA
RRA
OR 58H
LD H,A
Ezt a módszert leggyakrabban a szövegkiíráskor használják. Megjegyeznénk, hogy az "OR 58H" utasítás helyett az "ADD A,58H" utasítást is előszeretettel alkalmazzák.
Természetesen akadnak ettől eltérő (klinikai) esetek is, de ezek a leggyakoribbak. Persze ez nem vigasztalja azt, aki mindjárt az elegyen egy ilyet fog ki.
Ennyi bevezető után lássuk konkrétan, szeretett programunk milyen módszerrel dolgozik.
Először próbálkozzunk az attribútumcím számolás keresésével. A jól ismert "FIND" parancs segítségével kereshetünk egy kombinációt. Az "OR 58H" utasítás gépi kódja: F6 58. Az alábbi rutinra bukkanunk: (a teljes rutin)
65AD El POP HL ;visszatérési cím
65AE D9 EXX
65AF D9 EXX
65B0 7E LD A,(HL) ;első karakter
65B1 23 INC HL
6582 A7 AND A
6583 CA FB A5 JP Z,A5FB
6586 FE 20 CP 20
6588 DA FC A5 JP C,A5FC ;a SPACE
6588 D9 EXX ;karakternél kisebb
65BC 6F LD L,A
65BD 26 00 LD H,00
65BF 29 ADD HL,HL
65C0 29 ADD HL,HL
65C1 29 ADD HL,HL
65C2 ED 5B 36 5C LD DE,(5C36)
65C6 19 ADD HL,DE
65C7 EB EX DE,HL
65C8 2A CF 87 LD HL,(87CF)
65CB 06 08 LD B,0
65CD 1A LD A,(DE) ;egy karakter
65CE AE XOR (HL) ;kiírása
65CF 77 LD (HL),A
65D0 13 INC E
65D1 24 INC H
65D2 10 F9 DJNZ 65CD
65D4 7C LD A,H
65D5 OF RRCA
65D6 OF RRCA
65D7 OF RRCA
65D8 3D DEC A
65D9 E6 03 AND 03
65DB F6 58 OR 58 ;attribútumcím
65DD 67 LD H,A
65DE 3A BE 87 LD A,(87BE) ;attr. byte
65E1 77 LD HL ,A ;attr. tárolása
65E2 21 CF 87 LD HL, 87CF
65E5 34 INC (HL)
65E6 C2 AF A5 JP NZ,A5AF
65E9 23 INC HL
65EA 7E LD A,(HL)
65EB C6 08 ADD A, 8
65ED 77 LD (HL),A
65EE E6 18 AND 18
65F0 FE 18 CP 18
65F2 C2 AF A5 JP NZ,A5AF
65F5 3E 40 LD A,40
65F7 77 LD (HL),A
65F8 C3 AF A5 JP A5AF
65FB E9 JP (HL)
65FC 7E LD A,(HL) ;a 20H-nál kisebb
65FD 32 BE 87 LD (87BE),A ;karakter utáni byte
6600 23 INC HL ;attribútumbyte
6601 09 EXX
6602 C3 AF A5 JP A5AF
Talán mindenki rájött, hogy ez egy kiíratórutin (PRINT), Hívása a "CALL A5AD" utasítással történik, utána DEFB utasításokkal definiálja a szöveget. A szövegben a 20H-nál kisebb karakterek után áll egy attribútumbyte. Esetünkben a programozók az 1 kódú karaktert használták kizárólagosan. Tehát adott a következő pont: fel kell deríteni a hívásokat, majd ki kell javítani a színeket.
Célszerűnek látszik az attribútumbyte tárolására szolgáló memóriaváltozó értékadásait is megvizsgálni. És valóban, találunk is ilyet:
5216 3E 43 LD A,43
5218 32 BE 87 LD (87BE),A
Miután kijavítottuk a szubrutinhívásokat, térjünk át a másik módszerre.
Ebből is akad néhány:
389B 21 00 58 LD HL,5800
389E 11 01 58 LD DE,5801
38A1 01 FF 2F LD BC,02FF
38A4 36 47 LD (HL),47
38A6 ED B0 LDIR
Majd egy bonyolultabb:
385E 21 60 58 LD HL,5860
3B61 11 61 58 LD DE,5861
3B64 36 00 LD (HL),00
3B66 01 FF 00 LD C,00FF
3B69 ED B0 LDIR
3B6B 21 77 58 LD HL,5877
386E FD 21 81 58 LD IY,5881
3B72 06 12 LD B,12
3874 3A C2 87 LD A,(87C2)
3B77 CB 47 BIT 0,A
3B79 CA 91 7B JP Z,7B91
3B7C FD 36 00 F8 LD (IY),F8 ;villogó fehér
3B80 FD 36 20 46 LD IY+20),46 ;sárga
3B84 FD 23 INC IY
3B86 10 F4 DJNZ 3B7C
3888 1E 03 LD E,03
3B8A 3E 47 LD A,47 ;fehér
3B8C OE 1D LD C,1D
3B8E C3 A3 7B JP 7BA3
3B91 FD 36 00 47 LD (IY),47 ;fehér
3B95 FD 36 20 FO LD (IY+20),F0 ;villogó sárga
3899 FD 23 INC IY
3B9B 10 F4 DJNZ 3B91
3B9D 1E 07 LD E,07
3B9F 3E 46 LD A,46 ;sárga
3BA1 OE 19 LD C,19
3BA3 06 04 LD B,04
3BA5 50 LD D,B
3BA6 43 LD B,E
3BA7 77 LD (HL),A
3BA8 2C INC L
3BA9 10 FC DJNZ 3BA7
3BAB 09 ADD HL,BC
3BAC 42 LD B,D
3BAD 10 F6 DJNZ 3BA5
3BAF 21 17 59 LD HL,5917
3BB2 FD 21 21 59 LD IY,5921
3BB6 06 13 LD B,13
3BB8 3A 5E F3 LD A,(F35E)
3BBB A7 AND A
3BBC CA D4 7B JP Z,7BD4
3BBF FO 36 00 C5 LD (IY),C5 ;villogó kék
3BC3 FD 36 20 44 LD (IY+20),44 ;zöld
3BC7 FD 23 INC IY
3BC9 10 F4 DJNZ 3BBF
3BCB 1E 05 LD E,05
3BCD 3E 45 LD A,45 ;kék
3BCF OE 1B LD C,1B
3BD1 C3 EA 7B JP 7BEA
3BD4 FD 36 00 45 LD (IY),45 ;kék
3BD8 FD 36 20 C4 LD (IY+20),C4 ;villogó zöld
3BDC FD 23 INC IY
3BDE 10 F4 DJNZ 3BD4
3BEO 3E 44 LD A,44 ;zöld
3BE2 OE 1D LD C,1D
3BE4 11 06 00 LD DE,0006
3BE7 19 ADD HL,DE
3BE8 1E 03 LD E,03
3BEA 06 03 LD B,03
3BEC 50 LD D,B
3BED 43 LD B,E
3BEE 77 LD (HL),A
3BEF 2C INC L
3BFO 10 FC DJNZ 3BEE
3BF2 09 ADD HL,BC
3BF3 42 LD B,D
3BF4 10 F6 DJNZ 3BEC
3BF6 21 9C 59 LD HL,599C
3BF9 11 90 59 LD DE,599D
3BFC 01 AO 00 LD BC,00A0
3BFF 36 43 LD (HL),43
3C01 ED BO LDIR
3C03 21 57 5A LD HL,5A57
3C06 11 58 5A LD DE,5A58
3C09 36 42 LD (HL),42
3COB 01 84 00 LD BC,0084
3COE ED B0 LDIR
A rutin első fele az opciók beállítását szolgálja. A kiválasztott opció villog. (FLASH bit beállítva) Ezt úgy tudjuk kiküszöbölni a legegyszerűbben, hogy inverz hátteret állítunk be A második fél egyszerű színbeállítást végez.
Még van egy rejtett színállítás a 6643 címen:
6643 E6 47 AND 47
A programsor környezetének megvizsgálása után nyilvánvalóbb lesz a dolog, ezt az Olvasókra bízzuk. Ezek után a MOON CRESTA már színhelyesen kezdődik, de játék közben még bőven akadnak színhibák (a SPRITE-ok). A játék így még eléggé élvezhetetlen, de úgy gondoljuk, aki idáig szorgalmasan kitartott, annak egy egyszerű ujjgyakorlat a további munka, így nem lőjük le a poént.
Végezetül néhány szó a 128k SPECTRUM-ra írt programokról: Két nagy csoportra oszthatjuk a mezőnyt.
Egyrészt vannak a 48/128 fedőnevű programok. Ezek a mezei 48k-s SPECTRUM-on is működnek, általában a pályákat külön-külön töltik be. Ezek a 128-ason egy részletben betöltődnek, gyakran zenét, beszédet, plusz animációt stb. tartalmaznak. Ilyen pl. a ROBOCOP, amely zenét, valamint digitalizált (igen jó minőségű) beszédet is tartalmaz amellett, hogy minden szint a memóriában tartózkodik (nem ideiglenesen).
A másik csoport, amely kizárólag 128k-s gépen fut, esetleg 48k-s változata nem is létezik. Ezek a programok a legjobbak, mivel hosszuk többszöröse az előző csoporténak, így bonyolultabb a játék. Ezen csoport éllovasa a "WHERE TIME STOOD STILL" című program, amely bonyolultsága, grafikai kidolgozása. zenéje igazi mestermunka. Ide sorolható még a BEDLAM, THE MUNCHER, GHOULS 'n' GHOSTS, valamint a STARGLIDER 2 című program is.
Az ENTERPRISE szemszögéből az első csoport könnyen átírható, a második csoport pedig rizikós. Nehézséget az okoz, hogy míg SPECTRUM-on a teljes 128k kihasználható, addig ENTERPRISE-on az LPT-nek kell helyet hagyni. Ha nincs ennyi memória sem: akkor a reménybeli átíró makacsságán múlik a dolog.
Példaképpen: az említett WHERE TIME STODD STILL programban nem volt 200 byte szabad hely sem, de azért...
A 128k SPECTRUM memóriakezeléséről már volt szó. Ezt úgy lehet átírni, hogy minden SPECTRUM szegmenshez hozzárendelünk egy ENTERPRISE szegmenst, a
LD BC,7FFDH
LD A,x
OUT (C),A
utasításokat pedig átírjuk egy
LD A,y
OUT (0B3H),A
utasításcsoportra. x az eredeti, y a módosított szegmensszám.
A zene átírása már keményebb dió. Az AY-3-8912 regisztereinek leírása a SINCLAIR SPECTRUM JÁTÉK ÉS PROGRAM V. c. kötetében található (LSI ATSz. 1988.). A feladat az hogy olyan szubrutint készítsünk, amely a megfelelo AY és DAVE regisztereket egymáshoz rendeli. Ezt a problémát még egyeduli és údvozíto modon nem sikerült megoldani.
A problémák:
• Hardware burkológörbe. Na ez az, ahol még nem Sikerült igazi áttörést végrehajtani. Szomorú tény, de ebben jobb az AY chip. Sajnos a "XENON" című játék ENTERPRISE zenéje csak nyomokban emlékeztet az eredetire.
• Zajgenerátor. Abban az esetben, ha egy csatornán csak zaj szol, akkor majdnem teljes mértékben emulálható a zajeffekt. Ha egy csatornán egyszerre szól a zaj és a tiszta hang, akkor egyenlőre megáll a tudományunk.
Nos, ennyi lett volna ez a bűvös tudomány. Ha valaki végigolvasott minden részt, attól még nem biztos, hogy képes is önállóan végrehajtani egy ilyen műveletet (sőt!), de a kiindulás talán világosabb lett. Akit hidegen hagyott az a perspektíva, hogy saját maga írhat át programokat, esetleg az egyes rutinok programozási módszereibol okulhatott valamit, hiszen eléggé átfogó jelleggel kellett használni mind a gépet, mind az operációs rendszert.
Utolsó gondolatként annyit, hogy reményeink szerint sokan kaptak kedvet a témához, és futószalagon szállítják a jobbnál-jobb átiratokat. Mivel eredeti ENTERPRISE programok már nemigen készülnek és sok embernek van ilyen gépe, napjainkban egyre nagyobb szerepe lesz az amatőröknek.
VÉGE