Amstrad CPC programok átírása Enterprise-ra

 

 

Zozosoft és geco instrukciói a POP-UP program átírása kapcsán.

 

No elindult a játék. Mindezt úgy, hogy az eredeti programon sehol nem változtatunk! Csak pár ROM rutin lett megvalósítva... Egyetlen pici módosítás volt csak a 004-es fájlban: a pálya adatait 40H-tól kezdte volna eltárolni, amivel jól aláásná az EXOS jó közérzetét, ez lett átírva 80H-ra. Pici magyarázat: úgy tűnik ez már egy feltört program, így először a crackerek betöltője jön be. A száguldó csillagok megszakításból üzemelnek, ott lenne még zene is közvetlen port bizgatással... na ez még a jövő zenéje. Szintén hiányzik innen még a karakter kiíró ROM rutin, így az örökéletre vonatkozó francia? nyelvű felírat sem látszik 1-2-3 valamelyikével lehet tovább jutni.

Ezután jön az eredeti menü, itt lehet a játékosok lehet kiválasztani, ill. a pályaszerkesztőt (kiválasztás ENTER-rel). Pályaszerkesztőben még nincs sok öröm, amikor ESC-vel átlépünk a menübe, jól lefagy.

Játszani viszont már lehet, bár hang nélkül még nem az igazi... Maga a program ROM rutinnal zenélne... Tessék nézegetni a betöltő forrásszövegét, ez a kupac már elkészített rutin jól jöhet másik programnál is.

Bővebb magyarázkodás az átírás eddigi élményeiről majd alvás után, ha lesz rá igény

 

File-ok kinyerése CPC disk image-ből

 

Kezdjük az elején: először is ki kell szedni a program fájlokat a disk image-ból. Geco ajánlása alapján erre a CPCXFS a legalkalmasabb. Ezt csomagoljuk ki egy könyvtárba, és ebbe a könyvtárba tegyük a .DSK fájlokat is. Indítás után OPEN fájlnév paranccsal tudjuk megnyitni a .DSK fájlt. Ezután DIR-el kilistázható a tartalom. GET fájlnév paranccsal szedhetők ki a fájlok, a CPCXFS könyvtárába kerülnek. Sajnos a *-ot nem ismeri a GET, így a GET *.* helyett minden fájlt egyenként kell kiszedni... Viszont az MGET *.* működik. Kilépés EXIT-tel.

 

 

A fájlok 128 bájtos fejléccel kezdődnek, amelynek itt található a leírása. De a számunkra fontos adatokat már a CPCXFS-ben megszerezhetjük DIR -A paranccsal.

 

 

Ezután azt a módszert választottam, hogy elindítom a programot az első belépési pontjától kezdve, aztán meglátjuk mi lesz. Ehhez kelleni fog egy betöltő program, ami legfoglalja a szükséges memóriát, felépíti a CPC képernyőnek megfelelő LPT-t, betölti a megfelelő helyre az első fájlt és átadja a vezérlést.

 

A betöltő

 

A korábban már bemutatott Spectrum átiratos betöltőmet alakítottam át erre a célra, hiszen egy csomó minden (szegmensigénylés, stb.) felhasználható belőle, minek újra megírni. Lássuk részletesen, mit is csinál a betöltő: A forrásszöveg HEASS-ban van, PC-n is meg lehet nézni Haluska Laci Epdoc.exe progijával. Rögtön egy ugrással kezdődik, ehhez egy kis magyarázat: Spectrum progi esetén sokkal egyszerűbb dolgunk volt, hiszen ott az alsó 16K a ROM helye, tehát ezt nem használhatják a játékok, így átírás esetén a szükséges EP programunk biztonságban terpeszkedhet el itt. CPC esetén nem így van, ott az EP-hez hasonlóan lapozható a memória, így az alsó 16K-ban is RAM látható alapértelmezésben. Amit nyugodtan használhatnak is a programok... ezért az egyes CPC funkciókat utánzó rutinjainkat olyan helyen kell eldugni amit az adott játék nem használ. Ehhez kell tanulmányozni a CPCXFS-ben a DIR -A-val kapott adatokat, abbol nagyjából megsaccolható a program memória térképe, azért csak nagyjából mert késöbb még jöhetnek olyan meglepetések, hogy nem oda lesz töltve egy fájl, mint ahova a fejléc alapján kéne meg persze az is előfordulhat, hogy változókat, egyéb adatokat, vagy akár komplett programrészeket másolnak ki más helyre.

Konkrétan a POPUP esetén van olyan programrész amit 452H-tól kezdve lesz betöltve, így a szükséges rutinjainknak 100H-451H részben kell elférni Ha majd ezt túllépjük (hangrutinok...), akkor a maradéknak kell keresni valami más szabad helyet, ahova majd indulás elött át kell helyezni a rutinok egy részét. Ha valaki olyan programba fut bele ami pl már 100H-tól kezdve használja a RAM-ot, akkor eleve egy ilyen akcióval kell kezdeni. Ahhoz, hogy az "értékes" 100H feletti területbe majd minél több szükséges rutin beférjen, a csak indulásnál, egyszer lefutó programrészek át lettek telepítve a program végére, ezért indul a program ugrással, a CONT cimkénél indul valójában a program. Ezelött látható a PRINTX direktíva, ami arra szolgál, hogy a fordítás közben kiirja, hogy hol a vége a rutinjainknak, azt összevetve a szabad terület végével (jelen esetben 451H), tudhatjuk, mennyit lehet még garázdálkodni.

Nézzük sorban a betöltő program indulását: Elsőként beállítjuk a veremmutatót a program alá, ha ez a lépés elmarad, akkor az első EXOS hívásnál elszáll a program. Következő lépése a melegindítás címet a HIBA nevű rutinra, így biztosítva melegindítás esetén a kilépést a programból. Párszor már emlegettem, hogy roppantul utáltam azokat a programokat, ahol kilépni csak hidegindítással lehetett, ez különösen gyorsteszt nélkül, pláne memóriabővítéses gépen élvezetes... ennél jobban már csak azokat utáltam, ahol csak a tápkábel kihúzásával lehetett kilépni. Ez a HIBA rutin a forrásszöveg elején található, mint a legelső fontos rutin, nem véletlenül, hiszen a rendszer épségének megőrzése elsődleges szempont. Beállítja a veremmutatót a nullás lap végére, a rendszerszegmensben újból beállítja a melegindítási címet, így kontaktos reset gomb vagy gyors kezű felhasználó esetén is csak nagyon csekély esélye marad a teljes hidegindításnak. Ezután elkezd rendet rakni a program után, visszaállítja az EXOS LPT címet a NICK-ben (hopp ezt rendszerszegmensből kéne venni, és akkor EXOS 2.0-val is kompatibilis lesz na mindjárt át is írom ). Visszaállítja a megszakítási rutin kezdetét az eredetire, visszaadja a lefoglalt szegmenseket, majd az EXOS lapozó rutinján keresztül meghívja az 1-es szegmens belépési pontját, 6-os akciókóddal, ami az EP logóhoz ugrást jelenti. Ennek a megoldásnak az a elönye az EXOS 26-os kilépéssel szemben, hogy nem kell foglalkozni azzal, hogy milyen rendszerbővítő van a gépen, (ha nincs EPDOS, akkor hívjuk a BASIC-et, ha az sincs akkor WP-t című történet), az EP logotól mindenki oda fog jutni ahova egyébként is szokott (vagy ha le van tiltva az adott gépen a logo, akkor egyből). Természetesen mivel nem volt hidegindítás (és mert szépen EXOS-tól kértük a szegmenseket ), RAMDISK, betöltött rendszerbővítők, különböző EXOS változó beállítások,stb mind megmaradnak.

Külön már nem fogom emlegetni, de ezen a HIBA eljáráson keresztül lép ki a program, ha nem tud megfelelő szegmenseket lefoglalni, vagy ha hiba történik a fájlműveletek közben.

A kis kitérő után, folytassuk a betöltő indulását: 191-es porton keresztül letiltjuk az összes várakozást memóriahozzáférésnél, használata opcionális, de ajánlott az átírás során gyakran előfordul, hogy egy-egy egyszerű eredetiben 1-2 utasításos dolgot csak egy hosszabb rutinnal lehet megvalósítani EP-n, amitől lelassulhat a játék, így minden kis plusz teljesítményre szükség lehet, ezért ez a beállítás. (Ha valaki nem tudná, az EXOS alapértelmezésben minden utasítás esetén 1 órajel várakozást állít be, ez valószínűleg a legelső EP-kbe szerelt förtelmesen lassú memória IC-khez való alkalmazkodás miatt van).

Ezután következik a BIAS beállítása, a POPUP esetén nincs szerepe, mert ez 4 szín módban fut (nem véletlenül néztem ki pont ezt a progit gyakorlásnak ), így itt még valami Spectrumos érték látható. Természetesen majd egy 16 színű program esetén ki kell okoskodni ide egy megfelelő értéket. A BIAS rendesen EXOS váltózon keresztül van beállítva, ennek az a előnye, a közvetlen NICK port írással szemben, hogy megmarad a belső hangszóró állapota is, aminek pl tigrian nagyon örül én is nagyon örültem volna, ha anno minden programban ezt a módszert alkalmazzák, de mivel elég ritka, így hw kapcsolót szereltem a belső hangszóró drótjára.

BIAS beállítása után jön a szükséges szegmensek lefoglalása. Elöször szükség lesz egy teljes videószegmensre ami majd a képernyő memória lesz a játék számára, ez nem lehet megosztott. Másodszor kell egy videószegmens az LPT számára, mivel ezt nem használjuk ki teljesen, így ez lehet megosztott is, ha van benne elég hely. Mind a két szegmens számából kiszámoljuk, hogy az milyen NICK címen is kezdődik, és ezeket a videó címeket letároljuk az LPT készítő rutin számára, így bármelyik két videószegmenst sikerült megszerezni, helyesen fog működni a program. Ezután még két szegmenst foglalunk le, itt már nem muszály videószegmens, az első két szabad pont jó lesz. Léteznek a POPUP-nál bonyolultabb programok is itt szükség lehet több memória, vagy akár még egy képernyő memória lefoglalására is, azokat is hasonlóan lehet lefoglalni.

 

A CPC képmegjelenítése

 

CPC-n a képernyő memória alpértelmezésben a 3. lapon (azaz C000H-tól) helyezkedik el. Így a két sima memória szegmens az 1-es és a2-es lapra kerül, a 3-ra pedig az LPT-nek szánt szegmens. És indul az LPT készítés...

Itt kezdődnek az izgalmak ahhoz, hogy LPT-t készítsünk, meg kell ismerni a CPC képernyő kezelését. Angolul tudóknak itt a leírás. Azt tudjuk, hogy 27 színből lehet válogatni, ezt a témát pár napja már kielemeztem, az ott látható programmal sikeresen le lettek gyártva a CPC színeknek megfelelő EP színek, ez meg is található a programban COLORS néven futó táblázatban.

Szerencsére a CPC a NICK-hez hasonló módokat ismer (csak kevesebbet), 0-ás módban 16 szín, 1-es módban 4 szín, 2-es módban 2 szín lehetséges. A színek számának növelésével a felbontás csökken, akárcsak a NICK esetén. Konkrétan 160x200, 320x200, 640x200 az egyes módokban. Ezt megvalósítani a NICK-kel gyerekjáték kell egy 200 pixel sor magas 40 karakter széles nagyfelbontású grafikus sort definiálni az LPT-ben a megfelelő színmódban és kész.

Sajnos nem ilyen egyszerű a dolog, mert a videomemória valami elmebeteg módon van szervezve CPC-n. Fel van osztva 8 db 2048 bájtos blokkra: C000H-C7FFH, C800H-CFFFH, stb. A képernyőt 25 db karakter sorra lehet osztani, amelyek egyenként 8 sorosak. Egy sor 80 bájt hosszú. Ezek úgy helyezkednek el, hogy az első karakter sor első sora az első blokk első sora, a második sor a második blokk első sora, stb, tehát: C000H, C800H, D000H, D800H, stb. A második karakter sor első sora az első blokk második sora, a második sora a második blokk második sora, stb., tehát: C050H, C850H, D050H, D850H, stb. És így tovább a 25. sorig. Könnyen ki lehet számolni, hogy egy-egy blokkban 25 sor van, 25x80=2000! tehát blokkonként az utolsó 48 bájt pocsékba megy...

Ezek után már könnyen érthető az LPT generáló program felépítése, 25x8 sor-t generálunk, az előre elkészített sor másolásával, az elsődleges videocím helyére pedig a megfelelő NICK cím kerül. Spectrum-os LPT generálásnál itt jóval egyszerűbb a program, mivel nem kell az attribútum címek kiszámításával vesződni.

A LINE címen található sor a CPC-n alapértelmezett 4 szín módban van, a 8 paletta szín pedig szintén a CPC-n alapértelmezettként beállított első 8 szín. A 200 grafikus sor legenerálása után a befejező rész egyben kerül másolásra. Ebben a részben még van egy szabvány 40 karakteres EP sor, ami a státusz sorra mutat. Ezt azért szoktam betenni az átirataimba, hogy magnóról töltés közben lehessen látni, hogy mi történik (SEARCHING, LOADING, PAUSE, stb), anno egy időben sokat töltöttem be nem távvezérelhető magnóval, ekkor idegesített az olyan betöltő program amiben nem látszik a státusz sor, hiszen így a magnó leállásával se lehetett észrevenni, ha már kész a betöltés, vagy netán hiba miatt leállt (mert persze az EXOS 6 utáni hibaellenőrzéssel se foglalkoztak...)

Miután kész az LPT, a képernyő memóriaként használandó szegmens kerül a 3. lapra, ezután kinullázzuk ezt a 3 szegmenst, nehogy valami benne maradt szeméttől megkergüljön majd a program. (van pl. pár Spectrum átírat is ami meghülyül, ha nem kinullázott memóriával indul, pl. volt egy RAMDISK, ami már meg lett szüntetve, és ez után lett betöltve a játék. Az eredeti gépen fel se merülhetett az, hogy már használt memóriába kerül a program, így abból indulnak ki a programozók, hogy csupa 0 van mindenütt).

 

CPC ROM rutinok

 

CPC-n B900H-tól helyezkedik el a ROM rutinok belépési táblázat, ezért ezt a területet csupa RET-tel töltjük fel, így bármit hív a program, nem fog elszállni, csak éppen nem csinál semmit. Itt lehet angolul olvasgatni a CPC ROM rutinokról.

 

A program indítása

 

Ezután betöltjük az első fájlt a megfelelő helyre. Erről a fájlról már leszedtem a a CPC fejlécet, így pont oda töltjük, mint amit megtudtunk a CPCXFS-ben töltési címnek. Eztán átállítjuk a NICK-et az új LPT-re. DAVE piszkálása a Spectrum betöltő korszakból maradt, jelenleg felesleges. Ezután jön az ugrásipontok elhelyezése, amikor neki kezdtem, még csak kettő volt: a megszakítási rutin (38H), ill. RST 0 (ami CPC-n a RESET rutin), többiről majd késöbb. DAVE-ben engedélyezzük a videómegszakításokat, veremmutató pedig a CPC rendszerveremnek megfelelően beállítva. Ezután nagy levegő, és ráugrunk a program első utasítására, lesz ami lesz

Idáig eljutva, és elindítva a programot, jött az első sikerélmény, már megjelent valami kép a monitoron, persze nem színhelyesen, meg nem is csinált semmi mást a program. Innentől kezdve lehet törni a fejünket azon, hogy mit is csinál a program CPC-n, és azt hogyan lehet EP-n megvalósítani.

Erre kiválóan alkalmas, ha elkezdjük az EP32 debuggerében követni a program végrehajtását (breakpoint-ot rakni a belépési pontra, és onnan lépésenként.), hagyományos módszer hívei nézegethetik FENAS disassemblerében is megfelelő fájlt betöltve. Meg persze célszerű CPC emulátoron is megnézni az eredetit, hogy minek is kéne történni.

A POPUP esetén ez az első programfájl annyit csinál hogy kirak egy képet, alá pár sorban az örökéletre vonatkozó kérdést, és vár az 1-2-3 billentyűk valamelyikére, közben zenél, meg rohangálnak a csillagok. Ebből eddig a képkirakás az ami végre is hajtódott az első EP-n futattásnál.

Debuggolva a programot, az látszott, hogy csinál rengeteg ROM hívást, majd eljut egy végtelen ciklusba, ami gyanúsan billentyű figyelésnek tűnt. Kijegyzeteltem milyen ROM hívások vannak, majd sorban nekiláttam, hogy mit lehet ezekkel kezdeni. Aminek kész a rutinja, annak a címe belekerül a megfelelő helyre a CPC ROM rutin ugrótáblázatban, így ez a funkció mindig működni fog, ha ROM hívással van végrehajtva, a program további részeiben már nem is kell külön foglalkozni vele.

Amikor egy újabb programfájl elindítása jön, akkor megint debugban követés, de már csak az új, eddig ismeretlen ROM hívásokat kell kigyűjteni. Egy újabb program átírásának nekivágva, már sokkal kevesebb meló lesz, mivel egy csomó rutin már kész.

Elsőnek a videómód, paletta színek, és a keret szín beálllítás rutinjai készültek el: SCRSETMODE, SCRSETINK, SCRSETBORDER. A videómód beállításnál először egy táblázatból (MODES) vesszük a a megadott módnak megfelelő típusbájtot, amit aztán az LPT mind a 200 sorában beírunk a megfelelő helyre. A színbeállítás is hasonló, itt is egy táblázatból (COLORS) vesszük elő a megfelelő EP színt, és végigírjuk az LPT 200 sorában a megfelelő paletta helyre. Mivel EP-n csak az első 8 szín választható szabadon, ezért 7-esnél nagyobb paletta érték esetén nem csinálunk semmit, a 16 színű játékokról majd Geco tanár úr tart előadást. Keretszín beállítás szimpla ügy, táblázatból elő a megfelelő színkód, és ki a NICK-nek.

Ezután már színhelyesen jelent meg a POPUP kezdőképe... de még sehol sincsenek a rohangáló csillagok... Találtam egy nagyon elvont nevű (KL NEW FRAME FLY) ROM hívást, amiről némi tűnődés után kiderült, hogy egy olyan felhasználói megszakítási rutin beláncolására szolgál, aminek 50Hz-es videó megszakítás esetén kell lefutni. Hoppá, ilyen megszakítási rutinunk már van! Igaz egyelőre még nem csinált semmi mást, mint újra engedélyezte DAVE-ben a videó megszakítást. Elkészült a SETIRQ meg a RESIRQ rutin, ezzekkel lehet be ill. kiláncolni a megadott rutint, oly módon, hogy a megszakítási rutin utolsó pár bájtját átírjuk. Ezután már a csillagok is előkerültek, végig nézve a program megszakítási rutinját, kiderült, hogy ez zenélne is, közvetlen port birizgálással... na ezt egyelőre hagyjuk.

Következett még egy ROM hívás, karakter kiírása, ez ciklusban van hívogatva, így kerülne ki a három sor szöveg. Ráadásul a szöveg betűin kívül van egy csomó vezérlő karakter is. Ehhez kéne egy CPC karakterkészlet is... egyelőre hagytam ezt is a fenébe, mivel úgy tűnik máshol nincs is ez használva, így szerintem egyszerübb lesz a státusz sorba kiírni az örökélet kérdést.

Végül pedig van egy billentyű lekérdezés, oly módon, hogy egy ASCII kódot vár a program. Ezt esetleg meg lehetne csinálni egy KEYBOARD csatornával, de ha meg akarjuk valósítani a zenélgetést, akkor az EXOS megszakításokat nem lehet működtetni. Így ez kiesik. Mivel csak az 1,2,3 billentyűkre kíváncsi itt a program, ezért csak egy egyszerűsített csak ezt a három gombot figyelő rutin készült, KEY123 néven. (Tigrian féle tasztillesztő jelenlegi változatával való kompatibilitás miatt van benne egy felesleges OUT/IN). Innentől kezdve gombnyomásra tovább tudunk lépni a következő program fájl betöltésére.

Az örökélet-kérdés után a válasznak megfelelően 0003,0004 címekre rakott nullákat. Mivel ez EP-n nem használt cím, így itt eleve nullák voltak, ami azt okozta, hogy mindenképpen örökélet lett. Mondjuk anélkül szerintem max a harmadik pályáig lehet eljutni és most még le is van lassulva egy kicsit az eredetihez képest!

Itt egy fontos részhez érkeztünk, a fájlkezeléshez. Úgy tűnik a CPC programok jó része eleve lemezesre lett tervezve, mivel elég sokat töltögetnek, összevissza válogatva a fájlokból. A fájlkezelés elve némileg hasonlít az EXOS félére, bár jóval primitívebb. Először meg kell nyitni a fájlt, erre készült a FILEOPEN rutin, ez megadott CPC fájlnévből kialakítja az EP-set (erre nyilván programonként eltérő módszert kell kitalálni, attól függően, hogy milyen nevek voltak eredetileg, és milyen neveket szeretnénk). Nyomkövetési célzattal most ki is írja a kész nevet a státusz sorba. Megnyitja a nullás csatornán a fájlt, majd beolvassa a 128 bájtnyi CPC fejlécet egy pufferbe (puffernek az a terület van használva, amit az AMSDOS leírásban találtam, hogy ott tárol fejlécet), a fejlécből a megfelelő értékeket visszaadja a kimeneti regiszterekben. Úgy látom a leírásból, hogy blokk olvasás nincs CPC-n, van olyan, hogy az egész fájl beolvasása, és van karakter olvasás. Az elsőre a FILEREAD szolgál, a másodikra a CHARREAD, és természetesen van még egy FILECLOSE is, ezek azt hiszem értelemszerűek.

Van még egy fontos rutinunk: KMTESTKEY, ennek az a feladata, hogy a megadott kódú billentyűről visszaadja, hogy le van-e nyomva? Ehhez kellett tegnap a billentyű táblázat. A meg valósítás úgy néz ki, hogy egy táblázatban benne van az összes CPC billentyűhöz meg van adva, hogy az EP-n melyik sorban melyik bitet kell lekérdezni. Aminek nincs EP-n megfelelője azt szét szórtam a szabad EP billentyűkre. Majd még ezt a rutint ki kell egészíteni a külső joystickek kezelésével is.

Ezzel eljutottunk a jelenleg látható eredményhez, hogy már megy a játék, persze van még meló bőven, pl. a hang.

 

Hang

 

Hang rutinokból csak annyi lett csinálva, hogy a BCAAH címen hívott rutin visszaküld egy OK-ot (SCF), mert különben végtelen ciklusba került a program, míg várt az OK-ra.

A zenéhez a következők szükségesek (egyenlőre még csak a betöltő zenél):

A közvetlen port műveleteket kicseréltük a geco-tól kapott rutinra amit ha jól sejtem egy Spectrum 128K program átiratából szedett ki. Mondjuk fogalmam sincs hogy mit csinál, lényeg az, hogy működik. A funkciója az, hogy az eredetileg egy megadott AY regiszter írásának az eredményét szimulálja a DAVE-el.

Először is lássuk, hogy néz ki CPC eredetiben egy ilyen regiszter írás, a POPUP.000 fájlban 75B9H-tól helyezkedett el egy ilyen. (Ez fut a megszakítási rutinban.)

 

L75B9           LD      HL,78B6H
               
LD      D,0BH
L75BE           
LD      E,(HL)
               
LD      B,0F4H
               
OUT    (C),D
               
LD      BC,0F600H
               
OUT    (C),C
               
LD      A,0C0H
               
OUT    (C),A
               
OUT    (C),C
               
LD      B,0F4H
               
OUT    (C),E
               
LD      B,0F6H
               
ADD     A,A
               
OUT    (C),A
               
OUT    (C),C
               
DEC     HL
               
DEC     D
               
JP      P,L75BE
               
RET

 

Az LD B,0F4H utasítástól DEC HL előtti OUT-ig történik 1 azaz egy! darab AY regiszter írása! Normális HW-en az ilyesmihez elegendő egy darab OUT utasítás is. A regiszter száma a D-ben van, az ciklikusan csökken, az írandó adatot a HL-el címzett táblázatból veszi. Tehát az R11-től lefelé végig irkálja az összes AY regisztert.

Közvetlen ezután található egy másik port piszkáló rutin:

 

L75DF           LD      DE,0D00H
L75E2           
CALL    L75EC
               
DEC     D
               
JP      P,L75E2
               
LD      DE,L073F
L75EC           
LD      B,0F4H
               
OUT    (C),D
               
LD      BC,0F600H
               
OUT    (C),C
               
LD      A,0C0H
               
OUT    (C),A
               
OUT    (C),C
               
LD      B,0F4H
               
OUT    (C),E
               
LD      B,0F6H
               
ADD     A,A
               
OUT    (C),A
               
OUT    (C),C
                RET

 

Az egy darab AY regiszter írására szolgáló részt ugye most már mindenki felismeri. Megnézve a ciklust, látható, hogy R13-tól lefelé az összes regiszter nullázza, végül az R7-et 3FH-ra állítja. Elég könnyen ki lehet találni, hogy ez egy hang reset rutin lesz. geco-tól kapott rutin bekerült a betöltőbe, PORTOUT címen, ennek a címét induláskor B900H-ra helyezzük el.

Az első program rész így módosul:

 

L75B9           LD      HL,78B6H
               
LD      D,0BH
               
LD      E,(HL)
               
LD      A,D
               
LD      C,E
               
CALL    0B900H
                NOP
                ...
                NOP
                RET

 

Ezután már zenélni fog.

A második, hang reset program részt egy olyanra cseréljük, ami nullázza a DAVE összes hang portját.

 

L75DF           LD      BC,10AFH
               
XOR     A
L75E3           
OUT    (C),A
               
DEC     D
               
DJNZ    L75E3
                NOP
                ...
               
NOP 
                RET

 

Ezután pedig el kéne hallgatnia kilépéskor... de nem teszi, az utolsó hang tutul továbbra is... ami nem véletlen, mert hiába van ez a hang reset rutin itt, soha nem kerül meghívásra... Megnézve, hogy mi történik továbblépésnél, a 8A70H címen található egy ilyen:

 

               LD       HL,8A23H
               
CALL     0BCDDH
               
CALL     0BCA7H

 

Az első két utasítás a felhasználói megszakítási rutint láncolja ki, ez már le van kezelve a betöltőnkben. A második CALL viszont a ROM hang reset rutinja! Olyanunk még nincs... Ezt a CALL-t átírva 75DFH-ra, máris működésbe lép az imént átírt hang reset rutin, és innentől elmarad a végtelen tutulás.

 

Próbálom kigyűjteni a hang rutinokat a CPC ROM-ból, nagyja már úgy tűnik meg van, de valami még el lehet dugva az IRQ rutinban is... a leírás szerint van egy 100Hz-es megszakítás a hang keltéshez. Hogy ez hol kezelődik, azt még nem lelem...

 

soundrom.asm

 

Karakterírás

 

Na már varázsoltam szöveget a kezdőképernyőre. A karakter kiírás ROM hívásról lemondtam, elkezdtem kiszedegetni a ROM-ból, de amikor már vagy 5 oldalnyi programlista gyűlt össze, és még mindig újabb alrutinhívásokat találtam, akkor inkább hagytam a fenébe... Így inkább csináltam 4 színű grafikus lapon szöveget, kimentettem a szükséges bájtkupacot, amit odacsaptam a .000 végére. A francia szöveg kiírásának helyére meg oda tettem egy másoló rutint, ami beteszi a képernyő memóriába. Mondjuk ez se olyan egyszerű a CPC "érdekes" kép tárolása miatt...

Íme a rutin, ami a sima egyszerű grafikus adatot szétszórja a megfelelő formába:

 

                LD    HL,8C00H
               
LD    IX,0C000H+18*80
               
LD    A,4*9
               
LD    B,5
CIK1           
PUSH  BC
               
PUSH  IX
               
LD    B,8
CIK2           
PUSH  BC
               
PUSH  IX
               
POP   DE
               
LD    BC,80
               
OR    A
               
JR    Z,CIK3
                LDIR
               
DEC   A
CIK3           
LD    BC,800H
               
ADD   IX,BC
               
POP   BC
               
DJNZ  CIK2
               
POP   IX
               
LD    BC,80
               
ADD   IX,BC
               
POP   BC
               
DJNZ  CIK1

 

 

Függelék :)

 

 

16 szín esetén én csak annyit csináltam, hogy kiválasztottam egy olyan BIAS-t ami a legjobban hasonlított ( szerintem ) a CPC-n beállított 16 szín közül 8-hoz, és utána elkezdtem kicserélni a grafikát tartalmazó részben a színeket, hogy a végeredmény olyasmi legyen, mint CPC-n. 100%-ig nem lett ua., mert nem sikerült olyan BIAS-t kiválasztani, amiben minden szín ugyanolyan volt, mint CPC-n a 16 közül 8. Egy kicsikét macerás játék, de a végén az sikerélmény is nagyobb volt.

Exolon Esetében könnyű dolgom volt, mert az utolsó két file tartalmazta a grafikát, a főprogramban csak a csillagok kirakását kellett módosítanom, pont a színcserékből adódóan az 5-ös színnel rendelkező csillagok villogtak, ugyanúgy mint az űrhajó lámpája, CPC-n ez eredetileg a 15-ös szín volt. A lövedékek színét nem módosítottam, így az eltérő a CPC-stől.

 

 

Na megfejtettem a 27 szín titkát... leírásokból nem jutottam semmire, ott csak olyanokat találtam magyarázatként, hogy Sea Green meg Pastel Magenta és hasonló elvont fogalmak Smile
CPC emulátorban végig állítgattam a keretet, minden színnél screenshot, aztán megnéztem Photoshoppal az egyes színek RGB kódját Smile
Így rájöttem a rendszerre: Spectrumhoz hasonlóan itt is minden színnek van egy normál meg egy fényes változata. De itt nem globálisan számít a fényesség hanem minden RGB összetevőnek külön lehet megadni. Így gyorsan csináltam is egy kis BASIC progit EP-re, ami sorban 0-26-ig kiköpi az adott CPC szín EP kódját. A programot megnézve azonnal látható a színek logikája:

 

100 PROGRAM "cpccolor.bas"

110 NUMERIC FENY(0 TO 2),PIROS,KEK,ZOLD

120 LET FENY(0)=0

130 LET FENY(2)=1

140 LET FENY(1)=.5

150 FOR ZOLD=0 TO 2

160   FOR PIROS=0 TO 2

170     FOR KEK=0 TO 2

180       PRINT RGB(FENY(PIROS),FENY(ZOLD),FENY(KEK))

190       SET BORDER RGB(FENY(PIROS),FENY(ZOLD),FENY(KEK))

200       IF INKEY$="" THEN GOTO 200

210     NEXT

220   NEXT

230 NEXT