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
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.