Nem tudom, hogy ez hasznos-e valakinek, de itt egy részletesebb leírás a Spectrum programok attribútum és I/O műveleteit figyelő
zxiolog.lua script működéséről:
for i = 0x5800, 0x5AFF do
setBreakPoint(1, i, 3)
setBreakPoint(2, i, 3)
end
Ez a ciklus töréspontot állít be 5800h és 5AFFh között - azaz az attribútum területen - minden byte olvasására (bpType=1) és írására (bpType=2) is. A "prioritás" paraméter 3, azaz a legnagyobb.
A "for" ciklus használata részletesebben:
for VÁLTOZÓ = ÉRTÉK1, ÉRTÉK2[, LÉPÉS] do
...
endHa a lépés nincs megadva, akkor az alapértelmezése 1. A változó "local" típusú, azaz csak a ciklusban lesz elérhető, és a kezdőértéke az első paraméter. A ciklusmag addig fut, amíg a változó kisebb vagy egyenlő (ha a lépés pozitív), vagy nagyobb vagy egyenlő (ha a lépés negatív) a második paraméterrel, és minden futása után a változóhoz hozzáadja a lépésnek megadott értéket. A "break" utasítással korábban is ki lehet lépni a ciklusból.
setBreakPoint(5, 0xFE, 3)
setBreakPoint(6, 0xFE, 3)
I/O olvasás (5) és írás (6) töréspont beállítása az FEh portra, 3-as prioritással. A billentyűzet és hang kezelését figyeli.
setBreakPoint(4, 0x0000, 3)
Z80 utasítás olvasás (4) töréspont a 0000h címen, a RESET gomb megnyomásához (arra fejeződik majd be a script futása).
attrReadMap = {}
attrWriteMap = {}
ioFEReadMap = {}
ioFEWriteMap = {}
Ez létrehoz 4 üres táblázatot (tömböt) annak tárolására, hogy milyen címeken történtek ilyen műveletek.
for i = 0x0000, 0xFFFF do
attrReadMap[i] = false
attrWriteMap[i] = false
ioFEReadMap[i] = false
ioFEWriteMap[i] = false
end
A fenti ciklus inicializálja a tömböket. A Lua nyelvben a táblázatok címzésére valójában bármilyen adattípus használható, akár törtek vagy szöveg is, és az egyes elemeknek a típusa is tetszőleges lehet (akár ugyanazon a táblázaton belül keverve is). Ezek a táblázatok a 0 és FFFFh közötti egész számokhoz rendelnek "boolean" értéket, amely azt jelzi, hogy az adott Z80 címről történt-e az adott művelet (pl. attribútum írás).
function breakPointCallback(t, a, v)
if t == 1 or t == 2 then
if a >= 0x5800 and a < 0x5B00 then
if (getMemoryPage(1) == 0xFD or getMemoryPage(1) == 0xFE) and
getMemoryPage(SHR(getPC(), 14)) >= 0x80 then
if t == 1 then
attrReadMap[getPC()] = true
else
attrWriteMap[getPC()] = true
end
end
return false
end
A töréspontok elérésekor meghívandó függvény eleje.
Itt, ha a hozzáférés típusa (t) 1 (memória olvasás) vagy 2 (memória írás), akkor:
ha a cím (a) 5800h és 5AFFh között van, akkor:
ha az 1. lapon az FDh vagy FEh szegmens van, és a Z80 programszámláló nem a 0-7Fh szegmenseken van (az SHR() függvény az első megadott paramétert lépteti jobbra a másodiknak megadott számú bittel, ugyanez balra az SHL() lenne; a getMemoryPage() a megadott lapon (0-3) levő szegmenst adja vissza):
a megfelelő táblázatban megjelöli a programszámláló aktuális pozícióját;
visszatér false értékkel, azaz nem jelenik meg a debugger ablak
elseif t == 5 or t == 6 then
if AND(a, 0xFF) == 0xFE then
if getMemoryPage(SHR(getPC(), 14)) >= 0x80 then
if t == 5 then
ioFEReadMap[getPC()] = true
else
ioFEWriteMap[getPC()] = true
end
end
return false
end
Az előbbi "if" utasítás folytatása, ezúttal 5 (I/O olvasás) és 6 (I/O írás) típusú hozzáférésekhez:
ha a cím alsó 8 bitje FEh:
ha a Z80 programszámláló nem a 0-7Fh szegmenseken van:
megjelöli a programszámlálónak megfelelő címet az I/O olvasás vagy írás táblázatban;
visszatér false értékkel, azaz nem jelenik meg a debugger ablak
elseif t == 0 and a == 0x0000 then
clearBreakPoints()
f = io.open("zxiolog.txt", "w")
for i = 0x0000, 0xFFFF do
if attrReadMap[i] then
f:write(string.format("%04X: AR\n", i))
end
if attrWriteMap[i] then
f:write(string.format("%04X: AW\n", i))
end
if ioFEReadMap[i] then
f:write(string.format("%04X: IOR\n", i))
end
if ioFEWriteMap[i] then
f:write(string.format("%04X: IOW\n", i))
end
end
f:close()
return true
Végül a RESET figyelése: ha Z80 utasítás olvasás (t=0) történik a 0000h címről, akkor törli a töréspontokat, hogy a script ne fusson le újra, megnyitja a "zxiolog.txt" nevű file-t írásra szöveges módban (bináris file-hoz "w" helyett "wb" kellene), majd kiírja a táblázatok tartalmát.
Az f:write() az "f" file-ba írja a paraméternek megadott szöveg típusú adatot (egy byte (N) írásához f:write(string.char(N)) kellene). A string.format() formázott szöveget hoz létre a megadott (C sprintf() függvényhez hasonló) formátum alapján. A "%04X" azt jelenti, hogy a megfelelő paramétert (i) nagybetűs hexadecimális formában (X), balról nullákkal 4 számjegyre kiegészítve kell kiírni.
Végül bezárja a file-t (f:close()), és true értékkel visszatér, tehát megjelenik a debugger ablak.
A töréspont típusát vizsgáló "if" utasítás lezárása; ha a töréspont nem a script által figyelt típusú vagy című, akkor true a visszatérési érték, azaz a debugger ablak megjelenik.