Hogyan ne írjunk át Spectrum programot?

 

 

Izé, na, szóval az én szerény képességeimmel nekiálltam programot átírni Spectrumról...

 

Választásom tárgya a C64-en Gyalogkakukk néven is futott BC's Quest for Tires nevű remekmű, a Sierra On Line egyik első programja. egy ősember elindul egykerekű kőbiciklijén kiszabadítani kedvesét.

 

1. lépés: World of Spectrumról letölteni a TAP/TZX file-t.

Zozo intelmei szerint ildomosabb a TAP...

 

2. lépés: EP32 alatt futtatott Spectrum emulátor ROM-al szétszedni a TAP filet.

(Eredeti gépen is lehet, de PC-n praktikusabb, pl. mindjárt lehet kérdezni a fórumon...)

Az én módszerem: Winimage-val új imaget kreálni majd a TAP filet importálni, ezt megetetni EP32-vel, ide lehet majd menteni a művünket is.

SCOPY program használata aránylag nyilvánvaló (nekem is sikerült másodszorra...), adott esetben képződik 3 fejléc file és 3 "érdemi" file:

 

 

Mindjárt ki is próbáltam emulátoron, a bootscreent szépen betöltötte majd még szebben elszállt.

 

3. lépés: Nézzük meg a loadert.

MERGE "":

 

 

Némi "színszabályozás" meg memóriafoglalás után betölt egy gépi kódú programot és elindítja. A VAL "4e4" értékét a PRINT VAL"4e4" utasítás árulja el: 40000 vagyis 9C40H-ra tölt, Asmonnal kideríthető, hogy A555H-ig. Ha az ez utáni részeket töröljük, kiderül, hogy ez a rész tölti be a bootscreent, viszont annál jóval rövidebb, máshova töltődik és határozottan programnak látszó résszel kezdődik... Szóval ez egy tömörített kép + kitömörítő program lenne. Mindjárt az elején van egy ROM hívás... :(

Okos enged, szamár szenved alapon töltsük le a WoS-ról a .SCR formátumú betöltőképet és reménykedjünk, hogy a kitömörítő progi nem állít be semmi fontosat a főprogramhoz.

A főprogram betöltőutasításában viszont nincs sem kezdőcím, sem hossz, csak az indítási cím a RANDOMIZE USR után: 47936 (0BB40H). A hiányzó adatok a fejlécből (quest.400) deríthetők fel: 11.-12. byte a hossz (A000h, 40960), 13.-14. byte a betöltési cím (6000h, 24576), ez utóbbi meglepő módon azonos a lefoglalt RAM terület kezdetével... :).

 

4. lépés: Loader.

Elővettem a Zozo-féle "hiperszonikus" loadert... Aztán előástam az SpV-féle loadert, mert aki eddig csak biciklizett, az biztos összetöri az első autót, aminek a volánja mögé ül (+ ez utóbbiban van némi programozásban kevéssé járatosaknak szóló komment)...

Röpke módosítás után (majd hibakeresés, mert kissé elírtam a screen nevét... :$) gyönyörködni lehet a nem konvertált színű betöltőképben:

 

 

A módosított betöltő forrása

 

Mondjuk színkonverzió után sem lett jobb a helyzet, viszont kiderült, hogy a konvertáló program megúszta a javítatlan OCR hibákat:

 

 

Mondjuk eddig az egész tulajdonképpen nem jó semmire, de látni szerettem volna már valami kézzelfoghatót...

 

5. lépés: Interrupt "kétvállra fektetése"

 

Na itt kezdődnek a gondok. Az SpV cikkben van egy említés egy JP XXXX utasításról, amit az interrupt rutin elejére kéne tenni, csak sajna szerény képességeim egyenlőre még abban is akadályoznak, hogy felismerjem, a betöltő melyik rutinjára kéne mutatnia...

 

Mindenesetre a program a következőképp indul:

 

BB40 DI

     LD SP,0BBB7H

     LD A,0FEH

     LD I,A          ;IT VEKTOR-TÁBLÁZAT KEZDŐCÍME 0FE00H

     IM 2

     JP 8000

 

     ...

 

8000 LD HL,9000H

     LD DE,6000H

     LD BC,1400H

     LDIR            ;NA ERRŐL EGYENLŐRE FOGALMAM SINCS, MIÉRT

                     ;CSINÁLJA... MINDENESETRE A PROGRAM

                     ;KÖZEPÉT BEMÁSOLJA AZ ELEJÉRE, FELÜLÍRVA

                     ;AZ OTTANI ADATOKAT HA MINDEN IGAZ...

     LD HL,0FE00H

     LD DE,0FE01H

     LD BC,0100H

     LD A,0FDH

     LD (HL),A

     LDIR            ;HOPP, EZ IT VEKTOR-TÁBLÁZATNAK TŰNIK!

                     ;IT RUTIN CÍME EZ ALAPJÁN 0FDFDH, HA

                     ;MINDEN IGAZ...

     LD HL,0BD93H

     LD DE,0FDFDH

     LD BC,0003H

     LDIR            ;NAAA... ITT MÁSOLJA BE AZ IT RUTINRA UGRÓ

                     ;UTASÍTÁST A HELYÉRE...

                     ;AZ ÉRDEKES AZ, HOGY AZ MÁR BETÖLTÉSKOR A

                     ;HELYÉN VAN, SŐT AZ IT VEKTOR TÁBLÁZAT IS

                     ;KÉSZEN VAN... LEHET EZ A CRACK NYOMA?

     LD HL,62D0H

     LD DE,72D0H

     LD BC,0008H

     LDIR

     LD A,06H

     LD (0BD92H),A

     EI

     HALT

 

     ...

 

FDFD JP 0BBBEH       ;EZ VISZ A VALÓDI IT RUTINRA, AMI NAGYON

                     ;ÚGY NÉZ KI, MINT EGY IT RUTIN, MERT

                     ;ELMENT MINDEN REGISZTERT. MELLÉKESEN

                     ;MEGJEGYZEM, HOGY UGYANEZ VAN 0BD93 CÍMEN

                     ;IS...

 

Azt hiszem közben rájöttem a lényegre (mit tesz egy kánikulai éjszakai műszak...). Az egyszerűbb, de kevésbé elegáns megoldás: az IT rutin elé befűzni egy IT tároló törlése és IT engedélyezése rutinocskát:

 

ENABLE PUSH AF

       LD A,30H

       OUT (0B4H),A

       POP AF

       JP 0BBBEH

 

       ...

 

FDFD   JP ENABLE

 

(Nagyvonalúbb megoldás: törölni az IM 2 beállítást a programból, beállítani IM 1-et, 38h-ra berakni JP ENABLE-t...)

 

A fejlesztett betöltő forrása

 

Mindezen machinációk ellenére a program nem működik rendeltetésszerűen... Ilyenkor jön a dilemma: én csesztem el, vagy más miatt gajdul meg... Na a fene egye meg, az első utasítások egyike a képernyőtörlés, ami nem történik meg... Valami mégsem kóser... (portírás/olvasás vagy rom-rutin hívásnak kinéző dolog az meg nincs közte...)

 

Na akkor legyünk nagyvonalúak. ENABLE rutin ugyanaz. 0BB40h indítási címtől birizgálja az IT-t a progi, úgyhogy ezt nagyvonalúan kihagyjuk, induljon 8000h-tól, akkor csak a LD SP,0BBB7H utasítással leszünk szegényebbek, ezt berakjuk saját indítórutinunkba:

 

         DI

         LD HL,ENABLE

         LD A,195

         LD (0038h),A

         LD (0039h),HL

         LD A,48

         OUT (0B4H),A

         IM 1

         LD SP,0BBB7H

         JP 8000H

 

Forrásszöveg

 

És az eredmény:

 

 

 

6. lépés: billentyűzetfigyelés

 

"FEH portolvasást egy helyen találni:" írta Zozo a Bumpy kapcsán...

Na itt FE portolvasást vagy 28 helyen lehet találni ha végigkeressük a billentyűzet mind a 8 sorát (LD A,xx IN A,(0FEH) - 3EH, xxH, 0DBH, 0FEH) + a teljes leolvasást (XOR A, IN A,(0FEH) - 0AFH, 0DBH, 0FEH), ez utóbbiból csak 1 van.

Röpke módon az ENTER sorának (erre indulna) olvasásait meg a teljes billentyűzetolvasást saját ill. SpV-s rutinra cserélve még mindig nem indul tovább a progi. Viszont Spectrumon indulás után mindjárt hangot is ad, amit lehet a BEEP rutinnal tesz, szóval előre a ROM rutin kereséshez... A fenébe, egy BEEP rutin hívás sincs... a kezdeti DI-t átugorva sem...

 

Na akkor jöjjön a Zozo-féle POTFE. Az általános betöltőjéből kimásoltam a PORTFE címkétől TABL címkéig tartó részt, bemásoltam a betöltőbe (mire nem jó a NOTEPAD PC-n? :) ), 0028H-ra beraktam egy JP PORTFE utasítást és nekiálltam az IN A,(0FEH) utasításokat lecserélni RST 28 DB 0DBH kombóra. Azt hiszem a már említett 28-on kívül találtam még néhányat. Ez volt a programfile első módosítása...

 

Az eredmény nem lett egészen tökéletes... Lehet már bőszen állítgatni az irányítást, játékosok számát, szintet csak épp elindítani nem lehet, melyre az Enter lenne hivatott... :(

 

A betöltő forrásszövege

 

Az eredmény:

 

 

 

Ó, a fene egye meg, valahogy az egyik EF-et elírtam 28-nak... Pont az egyik Enter lekérdezésnél... :$

Na így már indul a progi... :) Csak a sprite villog, de nagyon, +időnként részben vagy egészben eltűnik, minél többet megy, annál inkább, mintha le lenne lassulva a háttérhez képes... meg a bicaj pattog össze-vissza esés után... mondjuk az S-et (pause) nyomogatva előbb-utóbb ez utóbbit abbahagyja... Na a név beírásánál előjött egy újabb billentyűfigyelés, melyet az EP32 Debug Break/go árult el: 7C57. Ide RST 28 DB 0EDh komó került. Így már menne a névbeírás, csak a betűk nagy részét nem fogadja el, amit igen, az is tudathasadásosan működik...

 

Na itt van a tulajdonképpen már majdnem működő program, nevezzük mondjuk public alfának... PORTFE.COM-al mindul... :)

 

Irányítás:

P:       Irányítás (csak keyboard megy)

O:       Játékosok száma

I:       Szint

S:       Pause

Q:       Hátra

W:       Előre

M:       Fejbehúzás

K:       Ugrás

Enter:   Indítás

Enter+Q: Lassítás

Enter+W: Gyorsítás

 

 

8. lépés: Joystick

Elég meglepő módon ez bizonyult eddig a legkönnyebbnek. 2 helyen van IN A,(1FH) utasítás, mindkettő egy bonyolult szubrutin része:

 

IN A,(1FH)

LD (HL),A

RET

 

Módosítva:

 

RST 10

NOP

LD (HL),A

RET

 

Ezenkívül készült egy KEMPSTON szubrutin melyre egy JP KEMPSTON utasítás ugrik 0010h címről.

 

KEMPSTON PUSH BC
         LD B,0
         LD A,7
         OUT (0B5H),A
         IN A,(0B5H)
         BIT 2,A
         JR NZ,KEMP1
         SET 0,B
KEMP1    BIT 5,A
         JR NZ,KEMP2
         SET 1,B
KEMP2    BIT 1,A
         JR NZ,KEMP3
         SET 2,B
KEMP3    BIT 3,A
         JR NZ,KEMP4
         SET 3,B
KEMP4    BIT 7,A
         JR NZ,KEMP5
         SET 4,B
KEMP5    LD A,B
         POP BC
         RET

 

Ez most nem forrás, hanem a disk image, mely a programot jelen állapotában tartalmazza, valamint az eddigi forrásokat, betöltőket is. Jelen állapot kemp.com-al indul. Legalább itt biztos helyen van :) .

 

Na itt eljutottam ahhoz a ponthoz, amikor bármit csinálok az nem változtat a helyzeten, vagy ront. Mentségemre legyen mondva, hogy Zozo (akit annyit nyaggattam az átírósdi közben, hogy közben maga is elkezdte átírni) is belefutott a spritevillogás problémába, és  egyenlőre szintén nem látja a kiutat. A program irogat a Page 0-ra (ami ugye Spectrumon ROM)... szóval nem egyszerű eset, esetleg nem is lehet átírni vagy szinte újból meg kéne írni vagy teljesen visszafejteni...

Közben rájöttem az IT igazi lényegére, mivel a programok mind IM 1-et mind IM 2-t alkalmazzák gyakran. A nagy felismerés teljesen benne van a Moon Crtesta SpV-s loaderében is...

IM 2 lekezelése: IM rutinra ugrás utasítását le kell cserélni saját ENABLE rutinra, mely törli az IT tárolót és engedélyezi az IT-t és a program IT rutinjára ugrik. Mivel ezen program össze-vissza kavar az SP-vel, nem feltétlenül működik a dolog....

IM 1 lekezelése: 38H-ra egy IT tároló törlése + IT engedélyező kód + RETI (vagy RET)

 

Innentől Zozo folytatja:

Észrevételek:

Tele van döglött kóddal, ami soha nem használ, talán a krakkolás maradványai... Az elejéről ki is dobtam az az 1400H bájtot, amit amúgy is egyből oda másol. IM1 IM2 külön van kezelve, bár szerintem soha nem tér vissza az 1-es módra.

A furcsaság oka: nem igazán van szinkronizálva a program a videó megszakítással, inkább csak futási idővel, azaz pont jó lesz mikor rajzol... Na de egyrészt az EP kicsit gyorsabb, másrészt az általunk betett emulációs rutinok lassítanak, néhol jelentősen. Na ettől totál felborul az egyensúly... jönnek a villogások. Alapvető megoldás: out 191,12, ahogy a CPC-nél írtam is:

"191-es porton keresztül letiltjuk az összes várakozást memória-hozzá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. "

A hangnál a BC06, BC5A, BC89 címen lévő OUT-ok játszanak. Főleg a második kettőnél látható igen gusztustalan önmagát felülíró kód, ami ráadásul a veremmutatót is össze-vissza variálja. Ezért száll el ez, ha az RST-s módszert alkalmazzuk. Először átírtam ezeket OUT A8-ra, ami végül is megteszi (sokan megelégednének vele), de egyrészt ott a csak egyik oldal szól probléma, másrészt időnként keretszínt is használ a program, ami nem kívánatos szörcsögést okoz, ha azt is kiküldjük hangnak. Erre születtek OUT1-2-3 rutinuk, amik szétszedik a keret és hang információt, és külön küldik ki. Ezek úgy lettek megírva, hogy vermet ne használjon. Mivel RST-t nem lehet használni csak JP-t, ami nem fér be az OUT helyére, ezért az OUT utáni utasítást is pótolni kell a rutin végén. Ezért lett 3 külön OUT rutin, minden egyes helyre külön. Az OUT pótló JP-ket a betöltő helyezi el a programban.

Így már nagyon jó a hang meg a keret, csak épp már annyira lelassult a program, hogy az out 191,12 ellenére is villog. Ekkor álltam neki, hogy az általános billentyű RST helyett az egész irányítást újra írjam EP-sre.

Alapvetően KEMPSTON irányításra íródott a program, a többi esetben a beolvasott értékekből az ezt szimuláló bájtot állítja elő.

 

BFCE: KEYBOARD

BFF1: KEMPSTON

BFF5: PROTEK

C014: INTERFACE 2

 

Ezeknek a rutinoknak a címe C03C-n lévő táblázatban van. C044 a fő irányítás rutin, ez hívja meg a kiválasztott eszköznek megfelelő beolvasó rutint. 7E35-ön kerül letárolásra a kiválasztott eszköz kódja, átírva a C044-en lévő LD utasítás paraméterét.

Én készítettem KEYBOARD, INTERNAL, EXT1, EXT2 rutinokat, és az eredetihez hasonló kiválasztó rutint ami 200H környékén terül el. A PRG-ben pedig módosítottam az LD (0C045H),A és a CALL 0C044H utasításokat a saját rutinnak megfelelően. Ily módon egyrészt megy már mind 3 joystick, másrészt felgyorsult annyira a program, hogy ne villogjon :-)

Attributum konvertálás még csak két helyen lett piszkálva:

C6B5-ön egy LD (HL),C, ami KONV2 RST-vel lett kiváltva

E4A4 egy LD (HL),A ami pedig KONV lett.

Bonuszként raktam bele örökélet lehetőséget is :-) És új trükköt: reset (kilépés) esetén kimenti a Hisghscore-t, ami következő indításnál visszatölt. Csalókat nem támogatjuk, örökélettel szerzett pontoknál nincs mentés :-)

És, hogy neked is maradjon egy kis meló, a fickó attributumait még meg kéne keresni.

:-)

 

Üdv:

Zozo

 

És a program jelenlegi állapota.

 

 

Folytatom (ezt tekintse mindenki fenyegetésnek :) )!

 

 

 

A szövegben található valamennyi fontos információ Zozosofttól származik...

gafz