Tuti, nem néztem ugyan meg, de úgy sejtem, hogy billentyűzetre, és hangra is egy általános rutint írtál, így a programba majdnem csak egy CALL-t kell betenni, meg elé, és mögé egy lapozást, ami belapozza a rutinokat tartalmazó lapot.
Ennél valamivel bonyolultabb és lassabb
Van egy "loaderCall" rutin, amely az EXOS n hívásokhoz hasonlóan használható, és ezen keresztül hívható az eredeti (EXOS) 0. lapon található betöltő kód.
Hátrányai:
- 54 byte méretű
- 259 ciklus tiltott megszakításoknál, 260 ciklus engedélyezett megszakításoknál (ez tartalmazza az összes CALL, JP, és RET utasítás idejét is)
Előnyei:
- egyszerűen használható:
CALL loaderCall
DEFB n
ahol 'n' az EXOS 0. lap első 256 byte-ján tetszőleges cím (a fenti 259/260 ciklus tartalmazza az onnan elugró JP utasítást is, de ez rövid rutinnál el is kerülhető)
- elmenti és visszaállítja a megszakítások engedélyezését, a hívott rutin futása közben a megszakítások tiltottak (ez a lapozás miatt kell, hogy ne fagyhasson le)
- belapozza a betöltőt a 0. vagy 2. lapra, visszatéréskor pedig visszalapozza a CPC memóriát (természetesen a "loaderCall" nem lehet ezen a lapon)
- a hívott rutin számára külön 30 byte-os vermet állít be az EXOS 0. lapon, hogy ne okozhasson lefagyást a CPC verem esetleges kilapozása; RET utasítással vissza lehet térni
- a jelzőbitek kivételével semmilyen regisztert nem ront el (az eredeti HL-t azonban a "loaderCallHL" változóban tárolja - így azt ott lehet elérni, viszont esetleg megtakaríthatók PUSH HL/POP HL utasítások)
- a CALL utasítás 2 byte-ján kívül nem használ CPC vermet
Ez valószínűleg elég rossz és pazarló megoldás, de az eddigi átirataimban elfogadható eredményt lehetett elérni ezzel is, és nagyon egyszerűen használható.
A megszakításokhoz is van hasonló rutin a betöltőben, de az kevésbé egységes, és minden átiratban többé-kevésbé eltérő (attól függően, hogy kell-e burkológörbe emuláció és/vagy 300 Hz-es megszakítás, illetve hogyan lehet a legjobban megoldani az eredeti rutinnal való egybeépítést).
A betöltőben mindig megtalálhatók a következők:
- memóriafoglalás (táblázatban megadható a lefoglalandó CPC szegmensek listája, és hogy ezek közül meylik legyen video memória - de ez többnyire csak a "szabványos" 64K memória, amiből a 3. lap video RAM)
- LPT generálás (szintén táblázat alapján - tetszőleges méretű, módú, stb., és akár osztott CPC képernyő is egyszerűen létrehozható)
- billentyűzet emuláció: egy sor olvasása (ezt a gyakorlatban még egyszer sem használtam)
- billentyűzet emuláció: minden sor olvasása 10 byte-os táblázatba (ez viszont nagyon hasznos; 2 sor módosításával állítható, hogy normál, vagy 1-es komplemens formátumú legyen a táblázat)
- teljes AY emuláció, amely feltételes fordítással konfigurálható
- AY regiszter olvasása (ezt még nem használtam)
- egy AY regiszter írása (ez lassú megoldás, ha a játék sokat hívja)
- minden AY regiszter írása táblázatból (ez előnyösebb, és szerencsére talán valamivel gyakoribb is)
- a fenti loaderCall és megszakítás rutin
- 300 Hz-es megszakítás emulációja a VSync-hez való szinkronizálással (ez kissé lassú, mert minden megszakításnál módosítja az LPT-t; ha nem kell a szinkronizálás - mint pl. az ATF-ben - akkor jobb megoldás fixen beállítani a megszakítást a megfelelő 6 LPB-re)
- inicializálás, file-ok betöltése, "Press SPACE" kiírása, a játék futásának az előkészítése, stb.
Ezek nem minden játéknál találhatók meg:
- paletta szín(ek) átdefiniálása; főleg a 4 színű játékok használják, bár kevésbé szerencsés esetben 16 színnél is előfordulhat (pl. ATF)
- a képernyő kezdőcímének az állítása (Super Hero)
- csalás menü (Dark Side)
- file I/O játék közben (Castle Master 1-2, Dark Side)
- egyéb rutinok, mint például az ATF-ben a képernyő remegése
A 4. bit segítségével késleltethetjük a megszakítást, 1-esre állítva a Gate Array számlálója nullázódik, ez a számláló felelős a megszakításgenerálásért, nullától 52-ig számol el, utána nullázza, és kezdődik minden elölről, ha a számláló 32 alatt van, akkor megszakításgenerálás elnyomva, ha felette, akkor generál megszakítást a Gate Array.
Pontosan így működik a megszakítás, ha jól tudom:
- a Gate Array számlálója 0-tól 51-ig fut soronként 1-el növelve, amikor elérné az 52-t, akkor megszakítást generál, és 52 helyett újra 0 lesz a számláló
- a megszakításkérést az törli, ha a Z80 elfogadja a megszakítást (azaz amikor a megszakítási rutinra ugrik); ilyenkor egyben törlődik a számláló 5. bitje is, hogy ne történhessen újabb megszakítás nagyon rövid időn belül
- a VSync kezdete után 2 sorral (tehát általában a 242. sornál) ez történik:
- ha a számláló értéke kisebb, mint 32, akkor csak nullázódik a számláló
- egyébként a számláló nullázásán kívül megszakításkérés is generálódik
- a fent említett 4. bit-be 1-et írva nullára állítódik a számláló, és törlődik az esetleges megszakításkérés
A gyakorlatban a lényeg általában csak az, hogy megszakítás van ezknek a soroknak az elején: 34, 86, 138, 190, 242, 294
sőt ha jól emlékszem láttam példát OUT (x),a-ra is.
Ennek talán akkor van értelme, ha a cím és az érték ugyanaz, például egy szín "pastel blue"-ra állítása ?