Welcome, Guest. Please login or register.


Author Topic: CPC (Read 458132 times)

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14723
  • Country: hu
    • http://enterprise.iko.hu/
Re: CPC
« Reply #360 on: 2010.July.03. 10:47:30 »
És arra mi a megoldás, ha túl sok ROM rutint használ a program, és ezért célszerû lenne az egész ROM-ot berakni alá? Ha jól emlékszem kb itt akadtem el a Pop-up-pal  :oops:

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #361 on: 2010.July.03. 11:21:13 »
És arra mi a megoldás, ha túl sok ROM rutint használ a program, és ezért célszerû lenne az egész ROM-ot berakni alá? Ha jól emlékszem kb itt akadtem el a Pop-up-pal

Jobb megoldás hiányában esetleg átírni a ROM-ot, vagy legalábbis a fontosabb részeit. De talán másik játékkal is lehetne próbálkozni :oops:, a legtöbb nem használ ennyi ROM rutint (amiket eddig átírtam, azokban a file I/O-n kívül esetleg csak video mód és paletta/keretszín beállítás van), a Pop-Up pedig fut az EP-s CPC emulátoron, éppen azért, mert csak ROM rutinokat használ.

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #362 on: 2010.July.03. 17:47:07 »
A Cybernoid 2 átírás előtt itt egy rövid (nem biztos, hogy hibátlan) leírás a betöltőben használt rutinokról és változókról, illetve a forráskód kissé módosított változata.

  [ Guests cannot view attachments ]

----------------------------------------

COMPRESSED_PRG (2. sor)

Tömörített formátumú program engedélyezése. Ha ez nem 0, akkor a betöltőt, a betöltőképet, és a játékot "dtf -cp" paranccsal csomagolni kell.

LOADER_ON_PAGE_2 (3. sor)

Ha 0, akkor a betöltő kódja a játékból végzett hívások és megszakítások közben a 0. lapon fut, egyébként a 2. lapon.

ENABLE_300HZ_IRQ (4. sor)

Nem 0 értékre állítva engedélyezi a 300 Hz-es video megszakítás emulációját 50 Hz helyett. Ilyenkor minden megszakításnál lefut a nextVideoInterrupt rutin, amely a következő megszakítási pozíciónak megfelelően módosítja az LPT-t.

loaderCallAddress (5. sor)

A loaderCall rutin kezdőcíme a CPC memóriában. Ez 54 byte területet igényel, és nem lehet a betöltő LOADER_ON_PAGE_2 változóval beállított lapján.

irqWrapperAddress (6. sor)

Az irqRoutineWrapper rutin kezdőcíme a CPC memóriában. Szintén nem lehet a betöltő lapján, ha abból bármit (pl. nextVideoInterrupt vagy envelopeInterrupt) használ.

gameStartAddress (7. sor)

A játék főprogramjának a belépési címe.

gameStackPointer (8. sor)

A veremmutató értéke a játék indításakor.

gameIRQRoutineAddress (9. sor)

A játék IRQ rutinjának a címe, ahova az irqRoutineWrapper ugrik.

----------------------------------------

main (27-122. sor)

A betöltő főprogramja, amely a 100H címen kezdődik.

setCheats (124-161. sor)

A file-ok betöltése után a 40 karakteres cheatMessage üzenetet jeleníti meg a státuszsorban, és billentyűlenyomásra vár. A billentyűtől függően engedélyezhet csalást, amit visszatéréskor a Z jelzőbit törlése jelez. A 3. lapra a rendszerszegmenst lapozza.

allocateMemory (165-269. sor)

Memória foglalása a CPC program és az LPT számára. A memóriafoglalást a segmentAllocTable táblázat vezérli, itt adható meg, hogy melyik CPC lapokhoz (0-7) kell szegmenst foglalni. A lapszámhoz 80h-t adva video szegmens kérhető. A táblázatot FFh byte zárja le. A legtöbb, 64K memóriában futó játékhoz a "83h, 00h, 01h, 02h, 0FFh" táblázat használható, amely a 0-3. lapot foglalja le, amiből a 3. lap (C000h-FFFFh) lesz video memória. A lefoglalt CPC szegmenseket 0 byte-okkal tölti fel, és a szegmensszámokat a cpcSegments táblázatban tárolja. Ez a táblázat 8 byte méretű (128K-s CPC emulációjához), és 8 byte-ra igazított címen kezdődik. A cpcSegments cím a 2. lapon van, ha a LOADER_ON_PAGE_2 nem 0.
Ha nincs elég szabad szegmens, akkor megpróbálja a 0. lapot a betöltővel és az LPT-vel együtt a rendszerszegmens elejére másolni és azt használni 0. lapnak, és az eredeti 0. lapot pedig a CPC program használhatja. Ehhez azonban a betöltő és az LPT mérete miatt többnyire nincs elég hely a rendszerszegmensen.
Az LPT-hez külön szegmenst foglal, ha erre van lehetőség, egyébként pedig a rendszerszegmens elejére kerül, ha ott elfér.
Ha nem sikerül minden CPC memóriát és az LPT-t lefoglalni, akkor a resetRoutine-ra ugrik, és kilép az ENTERPRISE logóhoz.
Visszatéréskor a 3. lapon az utolsó lefoglalt CPC szegmens van.


clearSegment (302-320. sor)

Belapozza az A regiszterben megadott szegmenst a 3. lapra, és feltölti 0 byte-okkal. Visszatéréskor az A, B, és HL regiszterek értéke 0 lesz, és engedélyezi a megszakításokat.

resetRoutine (322-365. sor)

A rendszer újraindítása hiba vagy melegindítás esetén. Felszabadítja az összes lefoglalt memóriát, menti a pontszámtáblázatot (ez csak lemezes gépen sikeres betöltés után csalások nélkül történik), visszaállítja az eredeti 0. lapot ha az a játék idejére a rendszerszegmensre került, és kilép az ENTERPRISE logóhoz.

----------------------------------------

A következő rutinok mind a LOADER_ON_PAGE_2 változónak megfelelő lapon futnak.

createLPT (371-429.sor)

LPT létrehozása és megjelenítése a CPC emulációhoz. Az LPT 240 sora lesz használható CPC képernyő megjelenítésére (ezekhez 240 külön LPB-t hoz létre), amelyek az LPT elején találhatók. Az LPT kezdőcíme az lptBaseAddr változóból olvasható (ez video RAM cím), a szegmense pedig az lptSegment-ből. Alapértelmezés szerint minden sor keretszínű, az initializeCPCScreen rutinnal lehet CPC képernyőt megjeleníteni.
Az LPT tartalmazza az EXOS státuszsorát is, ez a CPC képernyő felett jelenik meg (9 sor keret van a státuszsor és a 0. CPC sor között). A státuszsor LPB-jének a kezdőcíme lptBaseAddr + lptTotalSize - 32.
Az LPT-ben mindig egy video megszakítás található. Ha nincs 300 Hz-es megszakítás emuláció, akkor ez 242 sorral a CPC képernyő kezdete után történik, egyébként a nextVideoInterrupt minden megszakítás után 52 sorral módosítja a pozícióját.
Visszatéréskor a 3. lapon az LPT szegmense található.

setLPTAddress (431-444. sor)

Az LPT kezdőcímét állítja be a HL regiszterben megadott video RAM címre, a következő sorban már az új LPT jelenik meg. Az A, B, és H regiszterek tartalmát elrontja.

initializeCPCScreen (460-598. sor)

CPC képernyő létrehozása a HL regiszterben megadott kezdőcímű táblázat alapján, amely nem lehet a 3. lapon. A táblázat tetszőleges számú részre oszthatja a képernyőt, amelyek különböző video módot, margókat, palettát, és video RAM kezdőcímet használhatnak, de összesen mindig 240 sort kell definiálni. Az egyes blokkok formátuma:
  - 0. byte: sorok száma (nem 2-es komplemens formátumú, nem lehet 0)
  - 1. byte:
      - 7. bit: utolsó blokk jelzőbit (ha 1, akkor ez az utolsó blokk)
      - 5-6. bit: NICK szín mód (nem lehet 256 színű)
      - 0-4. bit: CRTC sor cím (karakteren belüli pozíció), ez általában 0
  - 2. byte: CRTC memória cím (nem video memória cím); általában 3000h
  - 4. byte: bal margó (40 karakter szélességű képernyőnél 11)
  - 5. byte: szélesség karakterekben (keretszínű sornál 0, és bal margó = 3Fh)
  - 6. byte-: paletta színek (a byte-ok száma a módtól függően 2, 4, vagy 8)
Visszatéréskor a megszakítások tiltottak, az A, BC, DE, és HL regisztereket elrontja, a többi regisztert és a lapozást nem változtatja.

writeLPBByte (603-656. sor)

Az L sortól (0-239) kezdődően B sorban (nem lehet 0) az E LPB byte-ot (0-15) C-re állítja. Általában a paletta módosítására használható, de több szín egyidejű állítására hatékonyabb lehet külön erre a célra írt rutint használni. Hívásakor a 3. lapon az LPT szegmensének kell lennie. Az A, B, DE, és HL regisztereket elrontja, a C nem változik.

nextVideoInterrupt (660-682. sor)

A megszakítási rutinból hívható 300 Hz-es megszakítás emulációja esetén, és az LPT-t módosítja a következő megszakításhoz. A futásideje kb. 230 ciklus a CALL utasítással és video memória várakozással együtt (~1.75% CPU használat 4 MHz-es gépen). Elrontja az A és HL regisztereket.
Figyelni kell arra, hogy ha a megszakítások túl hosszú ideig tiltottak, vagy egy megszakítás feldolgozása túl hosszú ideig tart, akkor előfordulhat, hogy a következő megszakítás csak egy teljes 50 Hz-es képkocka után történik.

videoInterruptNum (685. sor)

300 Hz-es megszakítás emulációjakor ebből a változóból kiolvasható a megszakítás száma (0-5). A 0 a 242. sort, azaz CPC-n a VSync alatti megszakítást jelenti. A nextVideoInterrupt hívása előtt ez az aktuális, utána pedig a következő megszakítás száma.

scanKeyboard (696-730. sor)

Billentyűzet lekérdezése. Az A regiszter alsó 4 bitjében adható meg a billentyűzetmátrix sor száma (0-9). Visszatéréskor az A regiszterben található az olvasott érték (FFh: nincs billentyű lenyomva ebben a sorban), az S és Z jelzőbiteket ennek megfelelően állítja, és elrontja a HL regisztert.

scanJoysticks (1162-1236.sor)

Joystick lekérdezése. A 9. billentyűzetmátrix sor olvasásához hasonló, de csak ajoystick irányokat és tűzgombot emulálja, viszont használható a beépített (a SPACE billentyű a tűzgomb) és bármelyik külső joystick is.

scanKeyboardAll (1244-1334. sor)

A teljes billentyűzetmátrix lekérdezése a DE regiszterben megadott kezdőcímű 10 byte-os táblázatba. A billentyűk lenyomott állapotát a megfelelő bit 0 értéke jelzi, azonban néhány egyszerű módosítással 1-es komplemens formátumra is lehetőség van. Ehhez a 1249. sorban az "LD A, 0FFH" helyére "XOR A"-t kell írni, az 1328. sorban az "OR 86H" helyett "OR 0C6H"-t, az 1332. sorban pedig a "RES 0, (HL)" helyére "SET 0, (HL)"-t.
A 1284-1288. sorban az F1, F2, F5, F7, és F8 billentyűket vizsgáló és setToneAndNoiseMode rutint hívó kód játék specifikus, és törölhető.
Visszatéréskor a DE regiszter a táblázat utáni byte-ra (kezdőcím + 10) mutat, az A és HL tartalma meghatározatlan.
Az Enterprise billentyűkhöz rendelt CPC billentyűk a keyboardConvTable és joystickConvTable táblázatokban állíthatók be. Minden byte-ban a 0-3. bit a billentyűzetmátrix sor száma, a 4-6. bit pedig az oszlop (bit).

----------------------------------------

ENABLE_STEREO (1340. sor)

Sztereó AY emuláció engedélyezése, ha nem 0. Valamivel nagyobb méretű és lassabb.

IRQ_BORDER_FX (1343. sor)

Ez csak debug célra használható, a megszakítási rutin futása alatt megváltoztatja a keret színét.

ENV_SRATE_DIV (1346. sor)

Burkológörbe emuláció frekvencia osztó. A nagyobb érték rosszabb minőséget de alacsonyabb CPU fogyasztást eredményez.

MIN_ENV_FREQVAL (1349. sor)

A burkológörbe frekvenciáját (11-12. regiszter) korlátozza. Az alacsony érték (nagy frekvencia) beállítása növelheti a CPU használatot. Nem lehet nagyobb, mint 255.

TONE_AND_NOISE_MODE (1354. sor)

Ha egy AY csatornán egyszerre engedélyezett a négyszögjel és a zaj, akkor ez a változó határozza meg az emuláció módját:
  - 0: csak négyszögjel
  - 1: csak zaj
  - 10h-F0h: négyszögjel torzítással (pl. 20h = 5 bites polinom számláló)

NO_ENVELOPE_IRQ (1356. sor)

Burkológörbe emuláció letiltása, ha nem 0. Ez kisebb méretet és CPU fogyasztást tesz lehetővé. Ha egy program mégis engedélyezi a burkológörbét egy csatornán ilyenkor, akkor az 0 hangerőt eredményez.

ayDaveChnA (1358. sor)
ayDaveChnB (1359. sor)
ayDaveChnC (1360. sor)

Az egyes AY csatornákhoz rendelt DAVE csatorna száma. Ugyanaz a DAVE csatorna nem használható egynél több AY csatornához. Ezeket a változókat csak akkor van értelme használni, ha a TONE_AND_NOISE_MODE 6. vagy 7. bitje 1 (felüláteresztő szűrő és/vagy gyűrűmoduláció másik csatornával).

envelopeInterrupt (1364-1469. sor)

A burkológörbét emuláló rutin, amely megszakításból hívható. Elrontja az AF regisztert. Ha a 300 Hz-es megszakítás engedélyezett, akkor feltételezi, hogy a HL regiszter található a veremben, és csak utána a visszatérési cím. Ha nincs 300 Hz-es megszakítás, akkor 1 kHz-es burkológörbe megszakítást tételez fel, amit a B4h I/O porton töröl is.

ayReset (1727-1786. sor)

AY emuláció és DAVE regiszterek inicializálása. Minden emulált AY regisztert 0-ra állít, a 7. regiszter kivételével, ami 3Fh lesz. Beállítja a BFh I/O portot is a DAVE órajelének megfelelően. A burkológörbe és 300 Hz-es megszakítás engedélyezésétől függően csak video megszakítást, vagy 300 Hz-es megszakítás nélküli burkológörbe emuláció esetén video és 1 kHz-es megszakítást engedélyez.

ayRegisterRead (1790-1797. sor)

Az A regiszterben megadott AY regiszter (0-13) olvasása. Az olvasott értéket az A regiszterben adja vissza, a HL-t elrontja.

ayRegisterWrite (1802-1948. sor)

Az A regiszterben megadott AY regiszter (0-13) írása C értékkel. A Z80 regisztereket a HL kivételével nem változtatja.

ayRegisterWriteAllI (1952-1961. sor)

Minden AY regiszter írása a DE-ben megadott kezdőcímű 14 byte-os táblázatból. Visszatéréskor a DE a táblázat utáni első byte-ra (kezdőcím + 14) mutat, az A és HL meghatározatlan, a többi regiszter nem változik.

ayRegisterWriteAllD (1965-2024. sor)

Hasonló az ayRegisterWriteAllI-hez, de a DE híváskor a táblázat utolsó byte-jára mutat, visszatéréskor pedig az első előtti byte-ra. Kis mértékben gyorsabb is.
Mindkét rutin egyszerűen módosítható 13 vagy 11 byte-os táblázatra:
  - az 1953., 1969., és 1970. sorban a 14 helyére a táblázat méretét kell írni
  - az 1971. sorban a 0004h helyére 2^(16-N)-t (pl. 0020h = 11 byte)
  - 13 byte-os táblázatnál törölhető az 1994-1995. sor
  - 11 byte-os táblázatnál törölhető az 1989-1996. sor

setToneAndNoiseMode (2028-2065. sor)

Ezt csak a Cybernoid 1-2 használja a TONE_AND_NOISE_MODE játék közbeni állítására az F1-F8 billentyűkkel. A 2026-2099. sor általában törölhető.

loaderCall (2107-2140. sor)

Ezen a rutinon keresztül történik a betöltő hívása. 54 byte területet igényel a CPC memóriában, és nem lehet azon a lapon (0. vagy 2.), ahol a betöltő fut, de video memóriába sem célszerű másolni.
A hívása a CPC programból a következő módon történik:
        CALL  loaderCall
        DEFB  n
ahol 'n' a hívott rutin kezdőcíme a betöltő szegmensének az első 256 byte-ján. Ennek a hívása előtt a következők történnek:
  - a HL regiszter mentése a loaderCallHL változóba
  - megszakítások engedélyezésének az elmentése, megszakítások tiltása
  - a betöltő belapozása a 0. vagy 2. lapra
  - veremmutató mentése, és a hívott rutin számára 30 byte-os verem beállítása a betöltő lapján
A hívás elrontja a jelzőbiteket és a HL regisztert, de az utóbbi kiolvasható a loaderCallHL-ből. A többi regiszter nem változik.
A hívott rutin egyszerű RET utasítással térhet vissza, amely után a loaderCall visszatérési kódja visszaállítja az eredeti veremmutatót, belapozza a CPC memóriát a 0. vagy 2. lapra, visszaállítja a HL-t a loaderCallHL változóból, és újra engedélyezi a megszakításokat (csak akkor, ha azok a hívás előtt is engedélyezettek voltak). A visszatérés is csak a HL regisztert és a jelzőbiteket változtatja, azonban az S és Z bitet nem rontja el, ha azok "OR A" utasításnak megfelelően voltak beállítva.

loaderCallHL (2144. sor)

A HL regiszter elmentett értéke loaderCall hívása alatt.

getCPCPageForDE (2150-2167. sor)

A DE regiszter felső 2 bitjének megfelelő CPC szegmenst belapozza a 0. vagy 2. lapra (amelyiken nem a betöltő kódja van), és a DE-t módosítja, hogy erre a lapra mutasson. Elsősorban a scanKeyboardAll, ayRegisterWriteAllI, és ayRegisterWriteAllD rutinokban használható, amelyek a CPC memóriában írnak vagy olvasnak táblázatot.
Az A és HL regiszterek tartalma elveszik.

restoreCPCPaging (2169-2176. sor)

Visszaállítja a DE regisztert és a lapozást getCPCPageForDE után. Elrontja az A regisztert.

irqRoutineWrapper (2184-2262. sor)

A megszakítási rutin CPC memóriába másolt része. Ez változhat az adott játéktól, és a borkológörbe emuláció és 300 Hz-es megszakítás engedélyezésétől függően.

resetRoutine_ (2274-2279. sor)

A resetRoutine-ra ugrik a betöltő játék közben használt lapjáról.

startGame (2281-2383. sor)

A játék indítása: beállítja a lapozást és veremmutatót, létrehozza a loaderCall hívásához az ugrótáblázatot a 0. lap első 48 byte-ján, és ayReset és egyéb inicializálás után a loaderCall visszatérési kódján keresztül elindítja a CPC programot.
A Cybernoid 1-2-ben használt setToneAndNoiseMode nélkül a 2381-2383. sor helyére "JP ayReset" írható.

keyboardConvTable (2430-2446. sor)
joystickConvTable (2448-2451. sor)

Billetyűzet és joystick konvertáló táblázat (a részletes leírást lásd a scanKeyboardAll-nál).

loaderCallTable (2453-2460. sor)

Ugrási címek loaderCall-hoz. Itt legfeljebb 15 cím adható meg (loaderCall 03h, loaderCall 06h, ..., loaderCall 2Dh), a loaderCall 00h mindig újraindítást végez.

segmentAllocTable (2469-2470. sor)

Memóriafoglalási táblázat, részletes leírás az allocateMemory-nál.
« Last Edit: 2010.July.04. 15:32:41 by IstvanV, Reason: Javított forráskód »

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14723
  • Country: hu
    • http://enterprise.iko.hu/
Re: CPC
« Reply #363 on: 2010.July.03. 18:05:19 »
A Cybernoid 2 átírás elõtt itt egy rövid (nem biztos, hogy hibátlan) leírás a betöltõben használt rutinokról és változókról, illetve a forráskód kissé módosított változata.
Köszönjük!!!

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #364 on: 2010.July.04. 15:07:23 »
Cybernoid 2 átírása CPC-ről

Az átíráshoz felhasznált file-ok:
  [ Guests cannot view attachments ]     (az eredeti CPC program .CDT formátumban)
  [ Guests cannot view attachments ]     (a CPC ROM rutinok rövid leírása)
  [ Guests cannot view attachments ]     (segédprogram CPC színek konvertálásához)
  [ Guests cannot view attachments ]     (a segédprogram forráskódja)
  [ Guests cannot view attachments ]     (Lua segédprogram pixel adatok kereséséhez)
  [ Guests cannot view attachments ]     (a betöltő forráskódja, részletesen lásd itt)
     ep128emu 2.0.8.1

Hasznos információk a CPC-ről:
  Rövid AY-3-8912 leírás
  CPC portkiosztás
  CPC Gate Array (memórialapozás, színek, video módok)
  8255 PPI használata CPC-n
  Egyéb információk, CRTC, színek
  Sok hasznos CPC dokumentáció (angolul), néhány segédprogram (cpcxfs stb.)

Az első lépés a játék betöltése az ep128emu CPC emuláció módjában. A magnó image file-t Alt+T-vel lehet megnyitni, majd a CPC BASIC-ben RUN" parancsot kell beírni, lenyomni az Enter-t, és végül elindítani a lejátszást Alt+P-vel. De ezek előtt még célszerű töréspontot beállítani a 4000h-B5FFh területre (még nem ismert, hol van a program belépési pontja, ez játékonként változhat), amit a debugger (Alt+B) második lapján a jobb felső ablakba 4000-b5ffx beírásával lehet megtenni.
A lejátszás elindítása után röidesen meg is jelenik a debugger, az A000h címen, tehát itt indul a játék betöltője. A töréspontok most már törölhetők. Érdemes átnézni a betöltő kódját, amely az A000h-A0ACh területen található:

Code: ZiLOG Z80 Assembler
  1. .   A000  21 06 A0     LD    HL, A006
  2. .   A003  CD 16 BD     CALL  BD16
  3. .   A006  AF           XOR   A
  4. .   A007  CD 0E BC     CALL  BC0E
  5. .   A00A  01 00 00     LD    BC, 0000
  6. .   A00D  CD 38 BC     CALL  BC38
  7. .   A010  3E FF        LD    A, FF
  8. .   A012  CD 6B BC     CALL  BC6B
  9. .   A015  21 BD A0     LD    HL, A0BD
  10. .   A018  3E 10        LD    A, 10
  11. .   A01A  46           LD    B, (HL)
  12. .   A01B  23           INC   HL
  13. .   A01C  48           LD    C, B
  14. .   A01D  E5           PUSH  HL
  15. .   A01E  F5           PUSH  AF
  16. .   A01F  D6 10        SUB   10
  17. .   A021  ED 44        NEG
  18. .   A023  CD 32 BC     CALL  BC32
  19. .   A026  F1           POP   AF
  20. .   A027  E1           POP   HL
  21. .   A028  3D           DEC   A
  22. .   A029  20 EF        JR    NZ, A01A
  23. .   A02B  21 00 C0     LD    HL, C000
  24. .   A02E  11 00 40     LD    DE, 4000
  25. .   A031  3E 16        LD    A, 16
  26. .   A033  CD A1 BC     CALL  BCA1
  27. .   A036  21 AD A0     LD    HL, A0AD
  28. .   A039  3E 10        LD    A, 10
  29. .   A03B  46           LD    B, (HL)
  30. .   A03C  23           INC   HL
  31. .   A03D  48           LD    C, B
  32. .   A03E  E5           PUSH  HL
  33. .   A03F  F5           PUSH  AF
  34. .   A040  D6 10        SUB   10
  35. .   A042  ED 44        NEG
  36. .   A044  CD 32 BC     CALL  BC32
  37. .   A047  F1           POP   AF
  38. .   A048  E1           POP   HL
  39. .   A049  3D           DEC   A
  40. .   A04A  20 EF        JR    NZ, A03B
  41. .   A04C  21 00 01     LD    HL, 0100
  42. .   A04F  11 00 40     LD    DE, 4000
  43. .   A052  3E 16        LD    A, 16
  44. .   A054  CD A1 BC     CALL  BCA1
  45. .   A057  21 00 41     LD    HL, 4100
  46. .   A05A  11 00 5F     LD    DE, 5F00
  47. .   A05D  3E 16        LD    A, 16
  48. .   A05F  CD A1 BC     CALL  BCA1
  49. .   A062  21 BD A0     LD    HL, A0BD
  50. .   A065  3E 10        LD    A, 10
  51. .   A067  46           LD    B, (HL)
  52. .   A068  23           INC   HL
  53. .   A069  48           LD    C, B
  54. .   A06A  E5           PUSH  HL
  55. .   A06B  F5           PUSH  AF
  56. .   A06C  D6 10        SUB   10
  57. .   A06E  ED 44        NEG
  58. .   A070  CD 32 BC     CALL  BC32
  59. .   A073  F1           POP   AF
  60. .   A074  E1           POP   HL
  61. .   A075  3D           DEC   A
  62. .   A076  20 EF        JR    NZ, A067
  63. .   A078  21 00 C0     LD    HL, C000
  64. .   A07B  11 00 1F     LD    DE, 1F00
  65. .   A07E  3E 16        LD    A, 16
  66. .   A080  CD A1 BC     CALL  BCA1
  67. .   A083  21 91 A0     LD    HL, A091
  68. .   A086  11 42 00     LD    DE, 0042
  69. .   A089  01 BD 00     LD    BC, 00BD
  70. .   A08C  ED B0        LDIR
  71. .   A08E  C3 42 00     JP    0042
  72. .   A091  F3           DI  
  73. .   A092  21 00 C0     LD    HL, C000
  74. .   A095  11 00 A0     LD    DE, A000
  75. .   A098  01 FF 1F     LD    BC, 1FFF
  76. .   A09B  ED B0        LDIR
  77. .   A09D  21 00 C0     LD    HL, C000
  78. .   A0A0  11 01 C0     LD    DE, C001
  79. .   A0A3  01 FF 3F     LD    BC, 3FFF
  80. .   A0A6  36 00        LD    (HL), 00
  81. .   A0A8  ED B0        LDIR
  82. .   A0AA  C3 00 01     JP    0100

A fenti ROM rutin leírás segítségével megállapítható, hogy a következők történnek:
  - inicializálás program indításához (BD16h)
  - 0-s (azaz 16 színű) video mód beállítása (BC0Eh)
  - keretszín feketére (ROM szín = 0) állítása (BC38h)
  - magnó üzenetek letiltása (BC6Bh)
  - minden paletta szín feketére állítása (BC32h 16-szor az A0BDh táblázatból)
  - 4000h byte méretű adatblokk betöltése a C000h-FFFFh területre (BCA1h) - ez lesz a betöltőkép
Itt érdemes töréspontot beállítani az A036h címre (a036x), ami közvetlenül a BCA1h hívás után van, hogy menteni lehessen a betöltőképet, majd a debugger Continue gombjával folytatni az emulációt. A töréspont elérésekor az S "CYBNOID2.SCR" 0 C000 FFFF monitor paranccsal (a második lapon a bal felső ablakban) menthető a betöltőkép az emulátor file I/O könyvtárába (ez Alt+F-el állítható be, amikor a debugger nem aktív).
  - paletta beállítása a betöltőképhez (BC32h 16-szor az A0ADh táblázatból)
  - 4000h byte méretű adatblokk betöltése a 0100h-40FFh területre (BCA1h)
  - 5F00h byte méretű adatblokk betöltése a 4100h-9FFFh területre (BCA1h)
Ezen a ponton már látható a betöltőkép, a CPC ROM megszakítási rutinja beállította az új palettát. Érdemes tehát újabb töréspontot állítani az A062h címre (a062x, az előző törölhető), és ennek elérésekor kiíratni a hardver palettát az IO 20 2F monitor paranccsal:
    IO 20 2F
    O 0020  14 0B 0C 06 14 1A 04 0A
    O 0028  0E 1C 07 16 00 19 15 13

Erre a táblázatra később még szükség lesz a betöltőkép színeinek a konvertálásához. A betöltő futása ezzel folytatódik:
  - minden paletta szín feketére állítása (BC32h 16-szor az A0BDh táblázatból)
  - újabb, 1F00h byte méretű adatblokk betöltése, a C000h-DEFFh területre (BCA1h); ezért kellett feketére állítani a palettát, hogy legyen a betöltőkép helyén szemét látható
  - a betöltő kódjának a befejezése a 0042h-00FEh területre másolódik, és itt folytatódik a futása
  - a C000h-DFFFh területet átmásolja A000h-BFFFh-ra
  - törli a video memóriát (C000h-FFFFh)
  - elindítja a játékot a 0100h címen
Ennek elérésekor tehát már befejeződött a betöltés, és minden adat a memóriában van. A 0000h-BFFFh területet akár már menteni is lehetne egy CYBNOID2.PRG file-ba, előbb azonban még néhány módosítást kell végezni a programon, hogy Enterprise-on futtatható legyen.

Az első teendő az I/O port műveletek megkeresése és konvertálása. Ezt két lehetséges módon lehet megtenni: vagy töréspontot kell beállítani minden I/O címre (00-ffrw), vagy pedig disassembly listát készíteni az egész programról (D "CYBNOID2.S" 0 BFFF monitor parancs a 0100x töréspont elérése után), és abban megkeresni az IN és OUT utasításokat (célszerűen olyan szövegszerkesztővel, ami tud egész szavakat vagy regular expression-t keresni, hogy meg lehessen különböztetni az IN és INC utasításokat). Az első megoldás hátránya, hogy sokat kell tesztelni a játékot ahhoz, hogy minden I/O műveletet biztosan sikerüljön megtalálni. A másodiknál pedig az okozhat problémát, hogy az adatterületen sok "hamis" I/O műveletet lehet találni, illetve (ritkán) előfordulhat, hogy közvetlenül egy I/O utasítás előtt adatbyte-ok vannak, és ezért hibás a disassembly lista.
ROM rutinokat ez a játék szerencsére nem használ (nem is lenne rá lehetőség, mert a RAM adatterületüket a betöltő felülírta), így azok átírásával nem kell foglalkozni. Egyébként a BB00h-BDFFh területre történő CALL és JP utasításokat kellene megkeresni.

Lássuk tehát az I/O műveleteket, a disassembly módszerrel:

Code: ZiLOG Z80 Assembler
  1. .   0342  01 0D BC     LD    BC, BC0D
  2. .   0345  ED 49        OUT   (C), C
  3. .   0347  01 00 BD     LD    BC, BD00
  4. .   034A  ED 49        OUT   (C), C
  5. .   034C  01 0C BC     LD    BC, BC0C
  6. .   034F  ED 49        OUT   (C), C
  7. .   0351  01 30 BD     LD    BC, BD30
  8. .   0354  ED 49        OUT   (C), C
  9. .   0356  01 01 BC     LD    BC, BC01
  10. .   0359  ED 49        OUT   (C), C
  11. .   035B  01 20 BD     LD    BC, BD20
  12. .   035E  ED 49        OUT   (C), C
  13. .   0360  01 02 BC     LD    BC, BC02
  14. .   0363  ED 49        OUT   (C), C
  15. .   0365  01 2B BD     LD    BC, BD2B
  16. .   0368  ED 49        OUT   (C), C
  17. .   036A  01 06 BC     LD    BC, BC06
  18. .   036D  ED 49        OUT   (C), C
  19. .   036F  01 18 BD     LD    BC, BD18
  20. .   0372  ED 49        OUT   (C), C
  21. .   0374  01 07 BC     LD    BC, BC07
  22. .   0377  ED 49        OUT   (C), C
  23. .   0379  01 1D BD     LD    BC, BD1D
  24. .   037C  ED 49        OUT   (C), C

Ez a CRTC-t inicializálja, amiről részletes leírás például itt olvasható. A lényeg, hogy 32x24 karakter méretű képernyőt állít be (ami Spectrum átiratnál nem meglepő), és a video memória kezdőcímét a 3000h CRTC (azaz valójában C000h) címre állítja - ez szabványos a CPC programoknál. Az átiratban az egészet egyszerűen felül lehet írni NOP utasításokkal (F 342 37D 0 monitor parancs), mert a betöltő elvégzi majd a képernyő beállítását.

Code: ZiLOG Z80 Assembler
  1. .   037E  06 7F        LD    B, 7F
  2. .   0380  0E 10        LD    C, 10
  3. .   0382  ED 49        OUT   (C), C
  4. .   0384  0E 54        LD    C, 54
  5. .   0386  ED 49        OUT   (C), C

Keretszín feketére állítása (Gate Array leírás itt). Ez már korábban megtörtént, és a játékban végig fekete is marad, tehát ide szintén NOP utasítások kerülhetnek (F 37E 387 0).

Code: ZiLOG Z80 Assembler
  1. .   0388  21 A1 03     LD    HL, 03A1
  2. .   038B  0E 00        LD    C, 00
  3. .   038D  16 10        LD    D, 10
  4. .   038F  ED 49        OUT   (C), C
  5. .   0391  7E           LD    A, (HL)
  6. .   0392  23           INC   HL
  7. .   0393  F6 40        OR    40
  8. .   0395  ED 79        OUT   (C), A
  9. .   0397  0C           INC   C
  10. .   0398  15           DEC   D
  11. .   0399  20 F4        JR    NZ, 038F

Paletta beállítása a 03A1h-03B0h táblázatból. A táblázatot érdemes kiíratni a színek későbbi konvertálásához:

M 3A1 3B0
>03A1  14 0B 1C 13 15 16 0D 0A
>03A9  0E 1D 0C 00 19 12 17 07


A színek beállítását azonban a betöltő végzi majd el, és a játék közben nem változnak, tehát újabb NOP utasítások következnek: F 388 39A 0.

Code: ZiLOG Z80 Assembler
  1. .   039B  01 8C 7F     LD    BC, 7F8C
  2. .   039E  ED 49        OUT   (C), C
  3. .   03A0  C9           RET

Letiltja a ROM-ot a 0. és 3. lapon is, és 16 színű video módot állít be. Ezekre sincs szükség az átiratban, tehát F 39B 39F 0.
Mivel az eddig leírt I/O kód mind egy összefüggő rutin volt a 0342h címtől, a NOP utasítások helyett akár már az elején is vissza lehet térni: F 342 39F C9.

Code: ZiLOG Z80 Assembler
  1. .   045B  21 51 04     LD    HL, 0451
  2. .   045E  01 0E F4     LD    BC, F40E
  3. .   0461  ED 49        OUT   (C), C
  4. .   0463  06 F6        LD    B, F6
  5. .   0465  ED 78        IN    A, (C)
  6. .   0467  E6 30        AND   30
  7. .   0469  4F           LD    C, A
  8. .   046A  F6 C0        OR    C0
  9. .   046C  ED 79        OUT   (C), A
  10. .   046E  ED 49        OUT   (C), C
  11. .   0470  04           INC   B
  12. .   0471  3E 92        LD    A, 92
  13. .   0473  ED 79        OUT   (C), A
  14. .   0475  C5           PUSH  BC
  15. .   0476  CB F1        SET   6, C
  16. .   0478  06 F6        LD    B, F6
  17. .   047A  ED 49        OUT   (C), C
  18. .   047C  06 F4        LD    B, F4
  19. .   047E  ED 78        IN    A, (C)
  20. .   0480  77           LD    (HL), A
  21. .   0481  23           INC   HL
  22. .   0482  0C           INC   C
  23. .   0483  79           LD    A, C
  24. .   0484  E6 0F        AND   0F
  25. .   0486  FE 0A        CP    0A
  26. .   0488  20 EE        JR    NZ, 0478
  27. .   048A  C1           POP   BC
  28. .   048B  3E 82        LD    A, 82
  29. .   048D  ED 79        OUT   (C), A
  30. .   048F  05           DEC   B
  31. .   0490  ED 49        OUT   (C), C
  32. .   0492  C9           RET

Ez a billentyűzet olvasását végzi egy 10 byte-os táblázatba a 0451h címtől kezdődően (lásd itt). Erre szerencsére már van is kész rutin a betöltőben, a scanKeyboardAll tehát azt egyszerűen csak meg kell hívni a loaderCall-on keresztül. A program többi részét átnézve, ahonnan erre a rutinra hívás történik, megállapítható, hogy a regiszterek értéke visszatéréskor nem lényeges, így azzal nem kell foglalkozni. A módosítás tehát:

A 045B LD DE, 451
       CALL 360
       NOP
       RET
>461 06
F 463 491 C9


Ugyanis a scanKeyboardAll-t a loaderCall 06h hívja, és a loaderCall az előbb törölt hosszú video inicializáló rutin helyére kerül a 0360h-0395h területre (a betöltő másolja majd oda) - ezért is kellett a NOP utasítások helyett az elején RET-el visszatérni.

Code: ZiLOG Z80 Assembler
  1. .   0D11  3E C3        LD    A, C3
  2. .   0D13  32 38 00     LD    (0038), A
  3. .   0D16  21 1D 0D     LD    HL, 0D1D
  4. .   0D19  22 39 00     LD    (0039), HL
  5. .   0D1C  C9           RET
  6. .   0D1D  F5           PUSH  AF
  7. .   0D1E  C5           PUSH  BC
  8. .   0D1F  D5           PUSH  DE
  9. .   0D20  E5           PUSH  HL
  10. .   0D21  DD E5        PUSH  IX
  11. .   0D23  FD E5        PUSH  IY
  12. .   0D25  D9           EXX
  13. .   0D26  08           EX    AF, AF'
  14. .   0D27  F5           PUSH  AF
  15. .   0D28  C5           PUSH  BC
  16. .   0D29  D5           PUSH  DE
  17. .   0D2A  E5           PUSH  HL
  18. .   0D2B  01 00 F5     LD    BC, F500
  19. .   0D2E  ED 78        IN    A, (C)
  20. .   0D30  1F           RRA
  21. .   0D31  D2 3E 0D     JP    NC, 0D3E
  22. .   0D34  21 50 0D     LD    HL, 0D50
  23. .   0D37  34           INC   (HL)
  24. .   0D38  CD 8E B1     CALL  B18E
  25. .   0D3B  CD 5B 04     CALL  045B
  26. .   0D3E  E1           POP   HL
  27. .   0D3F  D1           POP   DE
  28. .   0D40  C1           POP   BC
  29. .   0D41  F1           POP   AF
  30. .   0D42  08           EX    AF, AF'
  31. .   0D43  D9           EXX
  32. .   0D44  FD E1        POP   IY
  33. .   0D46  DD E1        POP   IX
  34. .   0D48  E1           POP   HL
  35. .   0D49  D1           POP   DE
  36. .   0D4A  C1           POP   BC
  37. .   0D4B  F1           POP   AF
  38. .   0D4C  FB           EI  
  39. .   0D4D  ED 4D        RETI

Ez a megszakítási rutin, illetve az arra ugró JP utasítás 0038h címre másolása. Itt több változtatást is kell végezni:
  - a JP utasítás írását törölni kell (F D11 D1B C9), mert a 0038h címre a betöltő fog majd kódot másolni; ezzel együtt az ott található, egyébként nem használt terület akár törölhető is (F 38 5E 0)
  - az IN utasítás a VSync állapotát vizsgálja (lásd itt); itt látható, hogy a megszakítási rutin valójában csak 50-szer fut másodpercenként, mert a VSync alatti megszakítás kivételével mindig egyszerűen visszatér. Azonban - a CPU használat csökkentése céljából - a betöltő megszakítási kódja ilyenkor nem is fog ide ugrani, tehát a VSync figyelése törölhető:
    A D2E JP D34
          NOP
          NOP
          NOP

  - érdemes megjegyezni a 0D1Eh címet, ez lesz a betöltőben a gameIRQRoutineAddr; az első, PUSH AF utasítás átugorható, mert az már a 0038h címen megtörténik

Code: ZiLOG Z80 Assembler
  1. .   B26B  AF           XOR   A
  2. .   B26C  21 84 B4     LD    HL, B484
  3. .   B26F  11 0D F4     LD    DE, F40D
  4. .   B272  42           LD    B, D
  5. .   B273  ED 59        OUT   (C), E
  6. .   B275  01 C0 F6     LD    BC, F6C0
  7. .   B278  ED 49        OUT   (C), C
  8. .   B27A  ED 79        OUT   (C), A
  9. .   B27C  42           LD    B, D
  10. .   B27D  4E           LD    C, (HL)
  11. .   B27E  2B           DEC   HL
  12. .   B27F  ED 49        OUT   (C), C
  13. .   B281  01 80 F6     LD    BC, F680
  14. .   B284  ED 49        OUT   (C), C
  15. .   B286  ED 79        OUT   (C), A
  16. .   B288  1D           DEC   E
  17. .   B289  F2 72 B2     JP    P, B272
  18. .   B28C  C9           RET

Ez az AY-3-8912 regisztereit (leírás itt) írja egy 14 byte-os táblázatból, amelynek az utolsó byte-ja a B484h címen található. Erre a célra is van már kész rutin a betöltőben, az ayRegisterWriteAllD, amelyet loaderCall 12h segítségével lehet hívni. A regiszterek értéke itt sem lényeges visszatéréskor, tehát a módosított kód:

A B26B LD DE, B484
       CALL 360
       NOP
       RET
>B271 12
F B273 B28B C9


Ezzel, és a betöltővel tulajdonképpen már működőképes is az átirat, amiről a .prg file mentésével könnyen meg lehet győződni: S "CYBNOID2.PRG" 0 0 BFFF. A betöltő lefordítása (sjasm segítségével) után már elindítható a játék, de a színek még nem jók. Ez lesz tehát a leírás következő részének a témája, a színek konvertálása.

Néhány további megjegyzés:
  - mivel a loaderCall (0360h) és a megszakítási rutin kiegészítése (0038h) is a 0. lapon van, a betöltőben engedélyezni kell a LOADER_ON_PAGE_2-t
  - a játék elején a veremmutató 0100h, ennek megfelelően a gameStackPointer is 0100h
  - bár a játék valójában csak 50 Hz-es megszakítást használ, a betöltő emulálja a CPC 300 Hz-es megszakítását a burkológörbe emuláció (igaz, ez itt csak ritkán használt) miatt, és mert néhány helyen HALT utasításokkal történik időzítés. Ezeket azonban konvertálni lehetne, és mivel csak egy hangeffektusnál van burkológörbe, az átirat továbbfejleszthető lenne valamivel gyorsabb, 300 Hz-es megszakítás nélküli változatra
  - a billentyűzet olvasás táblázata (0451h-045Ah) nem a 2. lapon van, ezért a scanKeyboardAll-ban nem kell használni a getCPCPageForDE-t és restoreCPCPaging-et
  - az ayRegisterWriteAllD-ben viszont igen, a B477h-B484h területről olvasott táblázat miatt
  - a legmagasabb pontszámok táblázata a 319Ah címen kezdődik
  - az életek kezdeti számát a 0129h címen található LD A, 4 utasítás állítja be
  - ennek a csökkentését a 2B6Bh címen a DEC (HL) végzi
  - 2B0Ch-nél a JP Z utasítás helyére JP-t írva lehet sérthetetlenséget elérni
« Last Edit: 2010.July.04. 15:31:30 by IstvanV »

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14723
  • Country: hu
    • http://enterprise.iko.hu/
Re: CPC
« Reply #365 on: 2010.July.04. 16:04:34 »
Az elsõ lépés a játék betöltése az ep128emu CPC emuláció módjában. A magnó image file-t Alt+T-vel lehet megnyitni, majd a CPC BASIC-ben RUN" parancsot kell beírni, lenyomni az Enter-t, és végül elindítani a lejátszást Alt+P-vel.
Ide szúrjuk be amit már korábban kitapasztaltunk: Alt+P lenyomása elõtt várjunk pár másodpercet, mert különben néha "nem kapja el" az elsõ fájlt.

Offline geco

  • EP addict
  • *
  • Posts: 7082
  • Country: hu
    • Támogató Támogató
Re: CPC
« Reply #366 on: 2010.July.04. 16:46:45 »
Ha valaki olyan programot szeretne átírni, amiről magnós változat nincs, akkor a CPCXFS segítségével nyerheti ki a file-okat a disk image-ből, az így kinyert fájlok egy 80h byte-os headerrel rendelkeznek, ahol számunkra két fontos információ van, a header 18-19h byte-ja határozza meg a file hosszát (header nélküli hossz, és low byte, high byte sorrendben, tehát ha 74 59 ez a két érték, akkor a file hossza 5974h), és 15-16h határozza meg a töltési címet, hacsak a betöltőben nem adtunk meg más értéket, számunkra kevésbé fontos, de a 12h. byte adja meg a file típusát.
1 érdekes infó, ASCII file-ok esetén nincs header.

A disk image-ből kinyert header nélküli file-ok is betölthetők EP128emuba az ' l "file név" 0 xxxx ' paranccsal, ahol xxxx a file töltési címe

Most, hogy megtaláltam nagy nehezen a header leíró táblázatot, be is vágom :)


Byte (Hex)     Meaning:
00             user number (0 , possible values 0-15)
01 - 0F        filename+extension (possibly filled with 0)
10             block number (0)
11             last block flag (0)
12             file type (0=basic, 1=protected basic, 2=binary,...)
13 - 14        length of block (0)
15 - 16        load address (0-FFFF)
17             first block flag (0)
18 - 19        logical length (0-FFFF)
1A - 1B        entry address (0-FFFF)
1C - 3F        free for the user (0)
40 - 42        real length of file (1-FFFFFF)
43 - 44        checksum of bytes 00-42
45 - 7F        unused (random values from sector buffer)

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #367 on: 2010.July.04. 17:54:30 »
Ide szúrjuk be amit már korábban kitapasztaltunk: Alt+P lenyomása elõtt várjunk pár másodpercet, mert különben néha "nem kapja el" az elsõ fájlt.

Valóban, ezért is írtam elsőnek az Enter lenyomását, és csak aztán az Alt+P-t :)

Cybernoid 2 átírás, 2. rész (az 1. rész itt olvasható):

A színek konvertálásához először azt kell megkeresni, hogy hol történik írás a video memória látható területére. Ehhez a játék indításánál (0100h) töréspontokat kell beállítani a következő memóriaterületek írására:

  c000-c5ffw
  c800-cdffw
  d000-d5ffw
  d800-ddffw
  e000-e5ffw
  e800-edffw
  f000-f5ffw
  f800-fdffw


Ugyanis a képernyő mérete 32*2*24*8 byte, ami 8 32*2*24 (azaz 600h) byte-os területre van osztva C000h és FFFFh között 800h egész számú többszöröseitől kezdődően. A nem látható részeket egyébként a program felhasználja adatok tárolására.

A töréspontokkal a következő címeket sikerül találni (érdemes a megtalálás után mindegyikre azonnal 'i' (ignore) típusú töréspontot beállítani, hogy ezek már ne jelenítsék meg újra a debugger ablakot):
  - 04A0h, 04A4h: ezek a teljes képernyőt 0 byte-okkal töltik fel; mivel a 0. szín - az átírást egyszerűsítendő - a konvertálás után is 0. marad, így itt nincs semmi teendő
  - 42B4h, 42B8h, 42BCh, 42C0h: 2x2 karakteres fix (nem sprite) grafika rajzolása; ezek építik fel a menü és a pályák nagy részét. Az adatok a 6E66h címen kezdődnek (lásd 4299h), és a 4289h címen található CP utasítás alapján 226 különböző elem jeleníthető meg, azaz a konvertálandó terület elvileg 6E66h-A6E5h
  - 092Fh, 0933h: karakter rajzolása; a karakterkészlet a 0919h-nél található utasítás szerint A4E6h-nál kezdődik, ami átfedné az előbb megtalált területet. Azonban a 00h-1Fh kódú karakterek valójában nem használtak, így a karakterkészlet kezdőcíme A6E6h. Azt majd a fenti pixeldisp.lua segédprogrammal lehet megállapítani, hogy pontosan mekkora területet kell konvertálni, mert a karakterek száma nem ismert
  - az előbbi karakter rajzolás egyébként történhet 5DA6h kezdőcímű karakterkészlettel is a 0919h utasítás felülírása miatt
  - 41B6h, 41BBh, 41C0h, 41C5h, 41CAh, 41CFh, 41DFh, 41E4h, 41E9h, 41EEh, 41F3h, 41F8h: 3x2 karakteres sprite rajzolása; a pixel adatok kezdőcíme 6026h a 40EFh címen levő LD BC, 6026H utasítás alapján
  - 3F74h, 3F79h, 3F7Eh, 3F83h, 3F88h, 3F8Dh, 3F9Ch, 3FA1h, 3FA6h, 3FABh, 3FB0h, 3FB5h: szintén 3x2 karakteres sprite rajzolása a 6026h-nál kezdődő táblázatból
  - 02A9h: ez valójában nem rajzol semmit, hanem egy LDIR utasítással megvalósított várakozás, amely 0000h-tól kezdve minden címre visszaírja az eredetileg ott található byte-ot. Mivel CPC-n az LDIR futásideje (az utolsó byte kivételével) 24 ciklus, ezt akár át is lehet alakítani, hogy pontos legyen az időzítés:
    A 2A0 PUSH AF
          PUSH BC
          DEC BC
          LD A, C
          OR B
          JP NZ, 2A2
          POP BC
          POP AF
          RET

  - 04C0h, 04C4h: ez is képernyő törlés (00h byte-okkal), tehát nem lényeges
  - 4309h, 430Eh, 4313h, 4318h, 431Dh, 4322h, 4327h, 432Ch, 433Bh, 4340h, 4345h, 434Ah, 434Fh, 4354h, 4359h, 435Eh: újabb sprite rajzoló rutin, ezúttal 4x2 karakter a sprite méret, és 5AA6h az adatok kezdőcíme
  - 4241h, 4246h, 424Bh, 4250h, 425Fh, 4264h, 4269h, 426Eh: itt 2x2 karakteres sprite rajzolása történik, a már ismert 6E66h-A6E5h területről olvasva
  - 13B4h, 13B9h: a játékos lövéseit jeleníti meg, a konvertálandó pixel byte-ok a 13B2h és 13B7h címeken találhatók
  - 1B7Fh, 1B84h, 1B89h, 1B98h, 1B9Dh, 1BA2h: 2x1 karakteres sprite rajzolása, a pixel adatok kezdőcíme AAD6h
  - 1380h: itt AND 55H vagy AND 0AAH művelet történik egy pixel byte-on (az egyik pixel feketére színezése), amit nem kell konvertálni
  - 4022h, 4027h, 402Ch, 4031h, 4036h, 403Bh, 404Ah, 404Fh, 4054h, 4059h, 405Eh, 4063h: újabb 6026h táblázatból 3x2 karakteres sprite-ot rajzoló rutin

A pixel adatok meg is jeleníthetők a pixeldisp.lua segédprogrammal. Ezt a játék indítása után lehet futtatni, és az elején beállítható a megjelenítendő terület kezdőcíme, a sprite-ok mérete, és száma. Ezeket a billentyűzet segítségével is módosítani lehet:
  - Z, X, C, V, B: kezdőcím csökkentése (4096, 512, 64, 8, vagy 1 byte-al)
  - N, M, ,, ., /: kezdőcím növelése (1, 8, 64, 512, vagy 4096 byte-al)
  - G, J: kezdőcím csökkentése vagy növelése egy sprite méretével
  - BAL, JOBB: sprite szélesség csökkentése vagy növelése fél karakterenként
  - LE, FEL: sprite magasság csökkentése vagy növelése pixelenként
  - A, Q: sprite magasság csökkentése vagy növelése karakterenként
  - U, I: megjelenített sprite-ok számának csökkentése 8-al vagy 1-el
  - O, P: megjelenített sprite-ok számának növelése 1-el vagy 8-al
  - D: soronként váltakozó irány be- és kikapcsolása (itt nincs jelentősége)
A módosított paramétereket ki is írja a monitor ablakba.

A fentiek alapján ezeket érdemes megnézni:

addr = 0x6E66
sw = 4
sh = 16

addr = 0xA6E6
sw = 2
sh = 8

addr = 0x5DA6
sw = 2
sh = 8

addr = 0x6026
sw = 6
sh = 16

addr = 0x5AA6
sw = 8
sh = 16

addr = 0xAAD6
sw = 4
sh = 8


Így megállapítható, hogy valójában a teljes 5AA6h-AE95h terület konvertálható pixel adatként. Ezen kívül csak a 13B2h és 13B7h byte-okat kell konvertálni.

A konverzióhoz azonban előbb még szükség van Enterprise paletta és FIXBIAS keresésére is. Ezt segíti a cpccolor program, amelynek a használata kiíratható paraméterek nélkül futtatva:

cpccolor.exe

Usage: F:\cpccolor.exe [OPTIONS...] <COLOR0> ... <COLOR15>
CPC colors can be specified in the format [=[=]]<COLOR>[:WEIGHT], where
COLOR is then color number (0 to 31), and WEIGHT is a floating point
value that defaults to 1.0. If the = prefix is used, the palette index
of the color will not be changed, while == will also prevent that index
from being used by other colors.
Options:
    -chromaerr <N>
        scale squared chrominance error by N (default: 0.275)
    -gamma <R> <G> <B>
        apply gamma correction to CPC colors (default: 1.001)
    -pixelmap <FILENAME>
        write pixel byte conversion table (256 bytes) to FILENAME
    -pixelmapfmt <N>
        select pixel conversion table format: 0 (default): binary,
        1: assembler table (defb), 2: Lua table
    -bias <N>
        force FIXBIAS=N (0 to 31); the default (-1) finds optimal value


A CPC paletta már ismert a leírás első részéből a betöltőképnél és a játék közben is. Először a betöltőkép palettája:

cpccolor.exe =0x14 0x0B 0x0C 0x06 0x14 0x1A 0x04 0x0A 0x0E 0x1C 0x07 0x16 0x00 0x19 0x15 0x13 -pixelmapfmt 2 -pixelmap pixconv1.lua

CPC palette:
   0: 20 (Black         ): mapped to  0 (0x00), err = 0.0000
   1: 11 (Bright White  ): mapped to 15 (0xFF), err = 0.0000
   2: 12 (Bright Red    ): mapped to  2 (0x49), err = 0.0000
   3:  6 (Cyan          ): mapped to  3 (0x06), err = 0.1055
   4: 20 (Black         ): mapped to  0 (0x00), err = 0.0000
   5: 26 (Lime          ): mapped to 10 (0xFA), err = 0.1000
   6:  4 (Blue          ): mapped to  6 (0x04), err = 0.1189
   7: 10 (Bright Yellow ): mapped to 11 (0xFB), err = 0.0908
   8: 14 (Orange        ): mapped to  7 (0xD9), err = 0.0579
   9: 28 (Red           ): mapped to  5 (0x01), err = 0.0562
  10:  7 (Pink          ): mapped to  9 (0xF9), err = 0.1084
  11: 22 (Green         ): mapped to  1 (0x02), err = 0.0734
  12:  0 (White         ): mapped to  8 (0xF8), err = 0.1090
  13: 25 (Pastel Green  ): mapped to 10 (0xFA), err = 0.1013
  14: 21 (Bright Blue   ): mapped to  4 (0x24), err = 0.0000
  15: 19 (Bright Cyan   ): mapped to 14 (0xFE), err = 0.0526
Enterprise palette: 0x00, 0x02, 0x49, 0x06, 0x24, 0x01, 0x04, 0xD9
Enterprise bias:    31 (0 to 31) / 0xF8 (0 to 0xF8)


Az első szín előtt a '=' azt jelenti, hogy ennek a színnek a pozíciója nem változhat a palettán. A '-pixelmapfmt 2' Lua script formátumú pixel byte konvertáló táblázatot kér, a '-pixelmap pixconv1.lua' pedig megadja a kimeneti file nevét. A paletta a betöltő forráskódjában a loadingScreenLPT-be kerül (2421. sor), a BIAS pedig a 46. sorba.

Következik a játék közben használt paletta:

cpccolor.exe =0x14 0x0B 0x1C 0x13 0x15 0x16 0x0D 0x0A 0x0E 0x1D:0.1 0x0C 0x00 0x19 0x12 0x17 0x07 -pixelmapfmt 2 -pixelmap pixconv2.lua

CPC palette:
   0: 20 (Black         ): mapped to  0 (0x00), err = 0.0000
   1: 11 (Bright White  ): mapped to 15 (0xFF), err = 0.0000
   2: 28 (Red           ): mapped to  2 (0x01), err = 0.0562
   3: 19 (Bright Cyan   ): mapped to 14 (0xFE), err = 0.0526
   4: 21 (Bright Blue   ): mapped to  4 (0x64), err = 0.0113
   5: 22 (Green         ): mapped to  5 (0x02), err = 0.0734
   6: 13 (Bright Magenta): mapped to  6 (0x6D), err = 0.0000
   7: 10 (Bright Yellow ): mapped to 11 (0xFB), err = 0.0908
   8: 14 (Orange        ): mapped to  3 (0xD9), err = 0.0579
   9: 29 (Mauve         ): mapped to  4 (0x64), err = 0.1050
  10: 12 (Bright Red    ): mapped to  1 (0x49), err = 0.0000
  11:  0 (White         ): mapped to  8 (0xF8), err = 0.1090
  12: 25 (Pastel Green  ): mapped to 10 (0xFA), err = 0.1013
  13: 18 (Bright Green  ): mapped to  7 (0x92), err = 0.0000
  14: 23 (Sky Blue      ): mapped to 12 (0xFC), err = 0.1136
  15:  7 (Pink          ): mapped to  9 (0xF9), err = 0.1084
Enterprise palette: 0x00, 0x49, 0x01, 0xD9, 0x64, 0x02, 0x6D, 0x92
Enterprise bias:    31 (0 to 31) / 0xF8 (0 to 0xF8)


Itt a "Mauve" (0x1D) színnél azért van ':0.1', mert azt csak ritkán (illetve talán egyáltalán nem) használja a program, így azt a többi szín jobb minősége érdekében kisebb súlyozással lehet figyelembe venni az optimális paletta és BIAS keresésekor (az alapértelmezés minden színnél 1.0). Érdemes azonban tovább kísérletezni, valószínűleg lehet még javítani a színeken.
Ez a paletta és BIAS is a betöltő forráskódjába kerül tehát, a gameScreenLPT-be (2427. sor) és a 118. sorba.

Most már csak a pixel konverziót kell elvégezni a .scr és .prg file-on. Ezt a célt szolgálja a következő Lua script:

Code: Lua
  1. -- a pixconv1.lua file-bol masolt tablazat
  2. pixelConvTable1 = {
  3.   0x00, 0x54, 0xA8, 0xFC, 0x04, 0x41, 0xAC, 0xE9, 0x08, 0x5C, 0x82, 0xD6,
  4.   0x0C, 0x49, 0x86, 0xC3, 0x00, 0x01, 0xA8, 0xA9, 0x14, 0x10, 0xBC, 0xB8,
  5.   0x08, 0x09, 0x82, 0x83, 0x1C, 0x18, 0x96, 0x92, 0x00, 0x54, 0x02, 0x56,
  6.   0x04, 0x41, 0x06, 0x43, 0x28, 0x7C, 0x20, 0x74, 0x2C, 0x69, 0x24, 0x61,
  7.   0x00, 0x01, 0x02, 0x03, 0x14, 0x10, 0x16, 0x12, 0x28, 0x29, 0x20, 0x21,
  8.   0x3C, 0x38, 0x34, 0x30, 0x55, 0x50, 0xFD, 0xF8, 0x44, 0x40, 0xEC, 0xE8,
  9.   0x5D, 0x58, 0xD7, 0xD2, 0x4C, 0x48, 0xC6, 0xC2, 0x05, 0x05, 0xAD, 0xAD,
  10.   0x45, 0x15, 0xED, 0xBD, 0x0D, 0x0D, 0x87, 0x87, 0x4D, 0x1D, 0xC7, 0x97,
  11.   0x55, 0x50, 0x57, 0x52, 0x44, 0x40, 0x46, 0x42, 0x7D, 0x78, 0x75, 0x70,
  12.   0x6C, 0x68, 0x64, 0x60, 0x05, 0x05, 0x07, 0x07, 0x45, 0x15, 0x47, 0x17,
  13.   0x2D, 0x2D, 0x25, 0x25, 0x6D, 0x3D, 0x65, 0x35, 0xAA, 0xFE, 0xA0, 0xF4,
  14.   0xAE, 0xEB, 0xA4, 0xE1, 0x88, 0xDC, 0x80, 0xD4, 0x8C, 0xC9, 0x84, 0xC1,
  15.   0xAA, 0xAB, 0xA0, 0xA1, 0xBE, 0xBA, 0xB4, 0xB0, 0x88, 0x89, 0x80, 0x81,
  16.   0x9C, 0x98, 0x94, 0x90, 0x0A, 0x5E, 0x0A, 0x5E, 0x0E, 0x4B, 0x0E, 0x4B,
  17.   0x8A, 0xDE, 0x2A, 0x7E, 0x8E, 0xCB, 0x2E, 0x6B, 0x0A, 0x0B, 0x0A, 0x0B,
  18.   0x1E, 0x1A, 0x1E, 0x1A, 0x8A, 0x8B, 0x2A, 0x2B, 0x9E, 0x9A, 0x3E, 0x3A,
  19.   0xFF, 0xFA, 0xF5, 0xF0, 0xEE, 0xEA, 0xE4, 0xE0, 0xDD, 0xD8, 0xD5, 0xD0,
  20.   0xCC, 0xC8, 0xC4, 0xC0, 0xAF, 0xAF, 0xA5, 0xA5, 0xEF, 0xBF, 0xE5, 0xB5,
  21.   0x8D, 0x8D, 0x85, 0x85, 0xCD, 0x9D, 0xC5, 0x95, 0x5F, 0x5A, 0x5F, 0x5A,
  22.   0x4E, 0x4A, 0x4E, 0x4A, 0xDF, 0xDA, 0x7F, 0x7A, 0xCE, 0xCA, 0x6E, 0x6A,
  23.   0x0F, 0x0F, 0x0F, 0x0F, 0x4F, 0x1F, 0x4F, 0x1F, 0x8F, 0x8F, 0x2F, 0x2F,
  24.   0xCF, 0x9F, 0x6F, 0x3F
  25. }
  26. -- a pixconv2.lua file-bol masolt tablazat
  27. pixelConvTable2 = {
  28.   0x00, 0x44, 0x88, 0xCC, 0x04, 0x40, 0x8C, 0xC8, 0x08, 0x4C, 0x80, 0xC4,
  29.   0x0C, 0x48, 0x84, 0xC0, 0x10, 0x05, 0x98, 0x8D, 0x14, 0x11, 0x9C, 0x99,
  30.   0x18, 0x0D, 0x90, 0x85, 0x1C, 0x19, 0x94, 0x91, 0x20, 0x64, 0x0A, 0x4E,
  31.   0x24, 0x60, 0x0E, 0x4A, 0x28, 0x6C, 0x22, 0x66, 0x2C, 0x68, 0x26, 0x62,
  32.   0x30, 0x25, 0x1A, 0x0F, 0x34, 0x31, 0x1E, 0x1B, 0x38, 0x2D, 0x32, 0x27,
  33.   0x3C, 0x39, 0x36, 0x33, 0x55, 0x10, 0xDD, 0x98, 0x15, 0x01, 0x9D, 0x89,
  34.   0x5D, 0x18, 0xD5, 0x90, 0x1D, 0x09, 0x95, 0x81, 0x50, 0x54, 0xD8, 0xDC,
  35.   0x45, 0x41, 0xCD, 0xC9, 0x58, 0x5C, 0xD0, 0xD4, 0x4D, 0x49, 0xC5, 0xC1,
  36.   0x75, 0x30, 0x5F, 0x1A, 0x35, 0x21, 0x1F, 0x0B, 0x7D, 0x38, 0x77, 0x32,
  37.   0x3D, 0x29, 0x37, 0x23, 0x70, 0x74, 0x5A, 0x5E, 0x65, 0x61, 0x4F, 0x4B,
  38.   0x78, 0x7C, 0x72, 0x76, 0x6D, 0x69, 0x67, 0x63, 0xAA, 0xEE, 0x20, 0x64,
  39.   0xAE, 0xEA, 0x24, 0x60, 0x2A, 0x6E, 0x02, 0x46, 0x2E, 0x6A, 0x06, 0x42,
  40.   0xBA, 0xAF, 0x30, 0x25, 0xBE, 0xBB, 0x34, 0x31, 0x3A, 0x2F, 0x12, 0x07,
  41.   0x3E, 0x3B, 0x16, 0x13, 0xA0, 0xE4, 0xA8, 0xEC, 0xA4, 0xE0, 0xAC, 0xE8,
  42.   0x8A, 0xCE, 0x82, 0xC6, 0x8E, 0xCA, 0x86, 0xC2, 0xB0, 0xA5, 0xB8, 0xAD,
  43.   0xB4, 0xB1, 0xBC, 0xB9, 0x9A, 0x8F, 0x92, 0x87, 0x9E, 0x9B, 0x96, 0x93,
  44.   0xFF, 0xBA, 0x75, 0x30, 0xBF, 0xAB, 0x35, 0x21, 0x7F, 0x3A, 0x57, 0x12,
  45.   0x3F, 0x2B, 0x17, 0x03, 0xFA, 0xFE, 0x70, 0x74, 0xEF, 0xEB, 0x65, 0x61,
  46.   0x7A, 0x7E, 0x52, 0x56, 0x6F, 0x6B, 0x47, 0x43, 0xF5, 0xB0, 0xFD, 0xB8,
  47.   0xB5, 0xA1, 0xBD, 0xA9, 0xDF, 0x9A, 0xD7, 0x92, 0x9F, 0x8B, 0x97, 0x83,
  48.   0xF0, 0xF4, 0xF8, 0xFC, 0xE5, 0xE1, 0xED, 0xE9, 0xDA, 0xDE, 0xD2, 0xD6,
  49.   0xCF, 0xCB, 0xC7, 0xC3
  50. }
  51. -- .scr es .prg file betoltese a memoriaba
  52. loadMemory("cybnoid2.scr", false, false, 0x00C000)
  53. loadMemory("cybnoid2.prg", false, false, 0x000000)
  54. -- .scr konvertalasa
  55. for i = 0x00C000, 0x00FFFF do
  56.   if AND(i, 0x07FF) < 0x07D0 then
  57.     -- tablazat index = pixel byte + 1
  58.     writeMemoryRaw(i, pixelConvTable1[readMemoryRaw(i) + 1])
  59.   else
  60.     -- nem lathato byte-ok torlese
  61.     writeMemoryRaw(i, 0x00)
  62.   end
  63. end
  64. -- .prg konvertalasa
  65. for i = 0x0013B2, 0x00AE95 do
  66.   if i == 0x0013B3 then
  67.     -- 13B3h-13B6h atugrasa
  68.     i = 0x0013B7
  69.   elseif i == 0x0013B8 then
  70.     -- 13B8h-5AA5h atugrasa
  71.     i = 0x005AA6
  72.   end
  73.   writeMemoryRaw(i, pixelConvTable2[readMemoryRaw(i) + 1])
  74. end
  75. -- modositott file-ok mentese
  76. saveMemory("cybnoid2.scr", false, false, 0x00C000, 0x00FFFF)
  77. saveMemory("cybnoid2.prg", false, false, 0x000000, 0x00BFFF)
  78. -- reset
  79. setIFF1(0)
  80. setIFF2(0)
  81. writeIOPort(0x7FFF, 0x91)
  82. setPC(0x0000)

Ennek a CPC emulátorból történő futtatása (a cybnoid2.scr és cybnoid2.prg file-oknak természetesen elérhetőnek kell lenni a file I/O könyvtárban) után elvileg már kész a játék.

Lehetőség van azonban a program tömörítésére is. Ehhez a betöltő forráskódjának az elején a COMPRESSED_PRG változót 1-re kell állítani, és a file-okat a következő módon csomagolni:
  dtf.exe -cp -lz2 -9 cybnoid2.prg cybnoid2.ldr cybnoid2.scr cybnoid2.prg
Ez feltételezi, hogy a lefordított betöltő file neve cybnoid2.ldr, és felülírja az eredeti .prg file-t. A tömörített program betölthető a :DL2 bővítéssel, de egyszerűen készíthető külön betöltő is:
  dtf.exe -cl -lz2 cybnoid2.com cybnoid2.prg
Valamivel nagyobb méretű, de lényegesen gyorsabban betöltődő file-t lehet készíteni mindkét fenti parancsnál az -lz2 helyére -lz-t írva. Az -lz2 formátum betöltésén is lehet valamennyit gyorsítani az itt található forráskódot használva (a file végén lehet beállítani a .prg nevét).
A "dtf" segédprogram aktuális verziója itt található.
« Last Edit: 2010.July.04. 18:04:30 by IstvanV »

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #368 on: 2010.July.05. 17:34:00 »
Elkezdtem átírni a leírásokat a wiki-re. Bár nem tudom, valóban érdemes-e, mert valószínűleg nem fogja olvasni senki.

Offline szipucsu

  • Global Moderator
  • EP addict
  • *
  • Posts: 9898
  • Country: hu
    • Támogató Támogató
    • Webnyelv.hu - Tanuljunk nyelveket!
Re: CPC
« Reply #369 on: 2010.July.05. 19:24:07 »
Elkezdtem átírni a leírásokat a wiki-re. Bár nem tudom, valóban érdemes-e, mert valószínûleg nem fogja olvasni senki.
Nekem teljesen kínai ez a téma, de fogok belõle olvasgatni azért. :D
És amúgy tudománytörténeti szempontból teljesen egyedülálló lesz ez a számítástechnika történetében, mert ilyen témában valószínûleg a világon senki nem írt még semmit. Ha akár valami retro számítógép vagy Z80 mániákus erre rábukkan, csak nézni fog, mint a moziban, hogy ilyen is van. :D
100 SOUND SOURCE 2,STYLE 128,PITCH 25.2,SYNC 1
110 SOUND PITCH 25,SYNC 1
120 ! Videos

Offline geco

  • EP addict
  • *
  • Posts: 7082
  • Country: hu
    • Támogató Támogató
Re: CPC
« Reply #370 on: 2010.July.06. 09:21:20 »
Elkezdtem átírni a leírásokat a wiki-re. Bár nem tudom, valóban érdemes-e, mert valószínűleg nem fogja olvasni senki.

Ne legyél ennyire pesszimista, sose lehet tudni :)
Azt sejtette volna bárki is, hogy ennyien összejövünk itt a fórumon?
Mert én nem, már annak is örültem, amikor rátaláltam az azóta eltűnt www.mumm.ac.be -n egy EP-s honlapra, az eredeti nevére nem emlékszem (ez kb 1996-ban lehetett)
« Last Edit: 2010.July.06. 11:49:53 by geco »

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #371 on: 2010.July.06. 11:31:53 »
Ne legyél ennyire pesszimista, sose lehet tudni :)

Valószínűleg csak reálisan látom a helyzetet :) Mindenesetre egyelőre csak a portkiosztást és a Gate Array-t konvertáltam wiki formátumra (az utóbbi elég sok munka volt a táblázatok miatt, és a színek a konvertált EP-s megfelelőkkel együtt láthatók is). Ezek nem túl jól néznek ki, tehát aki jobban ért a wiki szerkesztéshez, az valószínűleg tudna javítani rajta. Minden más csak link a fórumon a hozzászólásokra, illetve egyéb remélhetőleg hasznos helyekre.
Szintén kiegészítettem az EP programozás-t, de ide is csak néhány link került (Spectrum programok átírása, EXOS 2.1 leírás, Z80 dokumentációk, DAVE kiegészítés a fórumon).

Offline Lacika

  • EP addict
  • *
  • Posts: 3191
  • Country: hu
    • http://www.ep128.hu
Re: CPC
« Reply #372 on: 2010.July.06. 13:01:10 »
Nekem jó lett volna sima txt is, az alapján kiraknám az oldalamra. De a wiki-ből is kiszedhetem majd, ha elkészül.

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: CPC
« Reply #373 on: 2010.July.06. 13:08:58 »
Nekem jó lett volna sima txt is, az alapján kiraknám az oldalamra. De a wiki-ből is kiszedhetem majd, ha elkészül.

Nem biztos, hogy elkészül :oops: A fórumon már megvan, a wikire konvertálás pedig nem tudom, megéri-e a ráfordított időt. Az esetleges hibákat (szinte biztosan vannak, mert nem teszteltem/ellenőriztem semmit) még később kijavíthatom, de ettől eltekintve már most is felkerülhet az ep128.hu-ra.

Offline nyuzga

  • EP addict
  • *
  • Posts: 2280
  • Country: hu
Re: CPC
« Reply #374 on: 2010.July.13. 08:01:59 »
Castle master II. C64-es végigjátszás.
[ Guests cannot view attachments ]
[ Guests cannot view attachments ]
[ Guests cannot view attachments ]