mirror of
https://github.com/notwa/mm
synced 2024-11-05 16:19:03 -08:00
one class per file
...mostly
This commit is contained in:
parent
8701a54159
commit
637abc3684
10 changed files with 427 additions and 379 deletions
|
@ -1,8 +1,8 @@
|
|||
require = require "depend"
|
||||
require "boilerplate"
|
||||
require "addrs.init"
|
||||
require "classes"
|
||||
require "messages"
|
||||
require "classes"
|
||||
|
||||
-- check for errors in the actor linked lists
|
||||
local validate = false
|
||||
|
@ -37,13 +37,6 @@ local debug_watch = mm and {
|
|||
-- using a template to offset from will do for now.
|
||||
local actor_t = Actor(0)
|
||||
|
||||
local suffix = oot and " oot" or ""
|
||||
local actor_names = require("data.actor names"..suffix)
|
||||
local damage_names = require("data.damage names"..suffix)
|
||||
|
||||
-- hack to avoid N64 logo spitting errors
|
||||
local stupid = addrs.actor_counts[0].addr - 0x8
|
||||
|
||||
function sort_by_key(t)
|
||||
local sorted = {}
|
||||
local i = 1
|
||||
|
@ -223,191 +216,17 @@ function collect_actors()
|
|||
return any > 0, actors_by_type, new_counts
|
||||
end
|
||||
|
||||
ActorLister = Class()
|
||||
function ActorLister:init()
|
||||
self.before = 0
|
||||
self.wait = 0
|
||||
self.focus_at = 2
|
||||
self.focus_ai = 0
|
||||
self.seen_once = {}
|
||||
self.seen_strs = {}
|
||||
self.seen_strs_sorted = {}
|
||||
self.input = InputHandler{
|
||||
enter = "P1 L",
|
||||
up = "P1 DPad U",
|
||||
down = "P1 DPad D",
|
||||
left = "P1 DPad L",
|
||||
right = "P1 DPad R",
|
||||
}
|
||||
end
|
||||
local input_handler = InputHandler{
|
||||
enter = "P1 L",
|
||||
up = "P1 DPad U",
|
||||
down = "P1 DPad D",
|
||||
left = "P1 DPad L",
|
||||
right = "P1 DPad R",
|
||||
}
|
||||
|
||||
function ActorLister:wipe()
|
||||
if #self.seen_strs_sorted > 0 then
|
||||
print()
|
||||
print("# actors wiped #")
|
||||
print()
|
||||
end
|
||||
self.seen_once = {}
|
||||
self.seen_strs = {}
|
||||
self.seen_strs_sorted = {}
|
||||
end
|
||||
|
||||
function ActorLister:run(now)
|
||||
local game_counts = nil
|
||||
local seen = {}
|
||||
local cursor, target
|
||||
|
||||
local ctrl, pressed = self.input:update()
|
||||
|
||||
if pressed.left then self.focus_ai = self.focus_ai - 1 end
|
||||
if pressed.right then self.focus_ai = self.focus_ai + 1 end
|
||||
if pressed.down then
|
||||
-- follow Link again
|
||||
self.focus_at = 2
|
||||
self.focus_ai = 0
|
||||
end
|
||||
|
||||
if R4(stupid) ~= 0 then
|
||||
T_BR(0, 0, "red", "stupid")
|
||||
return
|
||||
end
|
||||
|
||||
local any, actors_by_type, new_counts = collect_actors()
|
||||
|
||||
if not any then
|
||||
self:wipe()
|
||||
else
|
||||
while self.focus_ai < 0 do
|
||||
self.focus_at = (self.focus_at - 1) % 12
|
||||
self.focus_ai = new_counts[self.focus_at] - 1
|
||||
end
|
||||
while self.focus_ai >= new_counts[self.focus_at] do
|
||||
self.focus_at = (self.focus_at + 1) % 12
|
||||
self.focus_ai = 0
|
||||
end
|
||||
cursor = deref(addrs.z_cursor_actor())
|
||||
target = deref(addrs.z_target_actor())
|
||||
end
|
||||
|
||||
local focus_link = self.focus_at == 2 and self.focus_ai == 0
|
||||
if debug_mode then focus_link = false end
|
||||
local needs_update = false
|
||||
|
||||
for at, actors in pairs(actors_by_type) do
|
||||
for ai, addr in pairs(actors) do -- FIXME: sorry for this pseudo-indent
|
||||
local var = R2(addr + actor_t.var.addr)
|
||||
local hp = R1(addr + actor_t.hp.addr)
|
||||
local num = R2(addr + actor_t.num.addr)
|
||||
local name = actor_names[num]
|
||||
local fa = addr + actor_t.flags.addr
|
||||
local flags = R4(fa)
|
||||
|
||||
local focus_this = at == self.focus_at and ai == self.focus_ai
|
||||
|
||||
seen[num] = true
|
||||
|
||||
if not name then
|
||||
name = "NEW"
|
||||
actor_names[num] = name
|
||||
dprint(("\t[0x%03X]=\"NEW\","):format(num))
|
||||
end
|
||||
|
||||
if not self.seen_once[num] then
|
||||
self.seen_once[num] = now
|
||||
needs_update = true
|
||||
local str
|
||||
if name:sub(1,1) == "?" then
|
||||
str = ("%s (%03X)"):format(name, num)
|
||||
else
|
||||
str = ("%s"):format(name)
|
||||
end
|
||||
self.seen_strs[num] = str
|
||||
dprint(str)
|
||||
end
|
||||
|
||||
local focal = false
|
||||
if not debug_mode then
|
||||
focal = focal or (focus_this and not focus_link)
|
||||
focal = focal or (focus_link and addr == target)
|
||||
else
|
||||
if target then
|
||||
focal = addr == target
|
||||
else
|
||||
focal = focus_this
|
||||
end
|
||||
end
|
||||
if focal then
|
||||
local actor = {
|
||||
name = name,
|
||||
addr = addr,
|
||||
ai = ai,
|
||||
type_count = new_counts[at],
|
||||
|
||||
at = at,
|
||||
var = var,
|
||||
flags = flags,
|
||||
hp = hp,
|
||||
num = num,
|
||||
}
|
||||
focus(actor, pressed.up)
|
||||
end
|
||||
|
||||
if focus_this then
|
||||
W1(addrs.camera_target.addr, 0x80)
|
||||
W3(addrs.camera_target.addr + 1, addr)
|
||||
end
|
||||
|
||||
-- make all actors z-targetable
|
||||
if not (focus_this and focus_link) then
|
||||
flags = bit.bor(flags, 0x00000001)
|
||||
W4(fa, flags)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if needs_update then
|
||||
self.seen_strs_sorted = sort_by_key(self.seen_strs)
|
||||
end
|
||||
|
||||
if focus_link and not target then
|
||||
for i, t in ipairs(self.seen_strs_sorted) do
|
||||
local color = 'white'
|
||||
if self.seen_once[t.k] and now - 60 <= self.seen_once[t.k] then
|
||||
color = 'lime'
|
||||
end
|
||||
if not seen[t.k] then
|
||||
color = 'orange'
|
||||
end
|
||||
T_TL(0, i - 1, color, t.v)
|
||||
end
|
||||
end
|
||||
|
||||
T_BR(0, 0, nil, "unique:%3i", #self.seen_strs_sorted)
|
||||
|
||||
if any then
|
||||
local z = target or cursor
|
||||
if z then
|
||||
local num = R2(z)
|
||||
T_TR(0, 0, nil, self.seen_strs[num])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: abstract to wrapper class or something
|
||||
function ActorLister:runwrap(now)
|
||||
if now < self.before then self.wait = 2 end
|
||||
self.before = now
|
||||
if self.wait > 0 then
|
||||
-- prevent script from lagging reversing
|
||||
self.wait = self.wait - 1
|
||||
if self.wait == 0 then self:wipe() end
|
||||
else
|
||||
self:run(now)
|
||||
end
|
||||
end
|
||||
|
||||
al = ActorLister()
|
||||
event.onloadstate(function() al:wipe() end, 'actor wipe')
|
||||
local al = ActorLister(input_handler, debug_mode)
|
||||
event.onexit(function() al = nil end, 'actor cleanup')
|
||||
event.onloadstate(function() if al then al:wipe() end end, 'actor wipe')
|
||||
while oot or mm do
|
||||
local now = emu.framecount()
|
||||
al:runwrap(now)
|
||||
|
|
|
@ -57,6 +57,11 @@ function A(addr, atype)
|
|||
end
|
||||
|
||||
Class = function(inherit)
|
||||
--[[ don't entirely like the idea but leaving it here
|
||||
if type(inherit) == 'string' then
|
||||
inherit = require("classes."..inherit)
|
||||
end
|
||||
--]]
|
||||
return setmetatable({}, {
|
||||
__call = function(self, ...)
|
||||
local obj = setmetatable({}, {__index = self})
|
||||
|
|
|
@ -1,72 +1,17 @@
|
|||
require "serialize"
|
||||
-- for lazy people.
|
||||
-- populate the global namespace with all available classes,
|
||||
-- excluding menu/interface classes.
|
||||
|
||||
Monitor = Class()
|
||||
function Monitor:init(name, a)
|
||||
self.name = name
|
||||
self.begin = a.addr
|
||||
self.len = a.type
|
||||
self.once = false
|
||||
self.old_bytes = {}
|
||||
self.modified = {}
|
||||
self.dirty = false
|
||||
end
|
||||
require "boilerplate"
|
||||
|
||||
function Monitor:read()
|
||||
-- bizhawk has an off-by-one bug where this returns length + 1 bytes
|
||||
local raw = mainmemory.readbyterange(self.begin, self.len-1)
|
||||
local bytes = {}
|
||||
local begin = self.begin
|
||||
for k, v in pairs(raw) do
|
||||
bytes[k - begin] = v
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
local classes = {
|
||||
"Monitor",
|
||||
"ByteMonitor",
|
||||
"FlagMonitor",
|
||||
"ActorLister",
|
||||
"InputHandler",
|
||||
}
|
||||
|
||||
function Monitor:diff()
|
||||
local bytes = self:read()
|
||||
local old_bytes = self.old_bytes
|
||||
if self.once then
|
||||
for i, v in pairs(bytes) do
|
||||
local x = v
|
||||
local x1 = old_bytes[i]
|
||||
if x ~= x1 then
|
||||
self:mark(i, x, x1)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.old_bytes = bytes
|
||||
self.once = true
|
||||
end
|
||||
|
||||
function Monitor:load(fn)
|
||||
self.modified = deserialize(fn) or {}
|
||||
self.dirty = false
|
||||
self.fn = fn
|
||||
end
|
||||
|
||||
function Monitor:save(fn)
|
||||
if self.dirty then
|
||||
serialize(fn or self.fn, self.modified)
|
||||
self.dirty = false
|
||||
end
|
||||
end
|
||||
|
||||
InputHandler = Class()
|
||||
function InputHandler:init(binds)
|
||||
self.binds = binds
|
||||
self.old_ctrl = {}
|
||||
end
|
||||
|
||||
function InputHandler:update()
|
||||
local ctrl = {}
|
||||
local pressed = {}
|
||||
local j = joypad.getimmediate()
|
||||
for k, v in pairs(self.binds) do
|
||||
ctrl[k] = j[v]
|
||||
end
|
||||
for k, v in pairs(ctrl) do
|
||||
pressed[k] = ctrl[k] and not self.old_ctrl[k]
|
||||
end
|
||||
self.old_ctrl = ctrl
|
||||
return ctrl, pressed
|
||||
for _, class in ipairs(classes) do
|
||||
_G[class] = require("classes."..class)
|
||||
end
|
||||
|
|
192
Lua/classes/ActorLister.lua
Normal file
192
Lua/classes/ActorLister.lua
Normal file
|
@ -0,0 +1,192 @@
|
|||
local print = dprint or print
|
||||
|
||||
-- hack to avoid N64 logo spitting errors
|
||||
local stupid = addrs.actor_counts[0].addr - 0x8
|
||||
|
||||
-- creating an object every time is a bit slow, so
|
||||
-- using a template to offset from will do for now.
|
||||
local actor_t = Actor(0)
|
||||
|
||||
local suffix = oot and " oot" or ""
|
||||
local actor_names = require("data.actor names"..suffix)
|
||||
local damage_names = require("data.damage names"..suffix)
|
||||
|
||||
local ActorLister = Class()
|
||||
function ActorLister:init(input_handler, debug_mode)
|
||||
self.before = 0
|
||||
self.wait = 0
|
||||
self.focus_at = 2
|
||||
self.focus_ai = 0
|
||||
self.seen_once = {}
|
||||
self.seen_strs = {}
|
||||
self.seen_strs_sorted = {}
|
||||
self.input = input_handler
|
||||
self.debug_mode = debug_mode
|
||||
end
|
||||
|
||||
function ActorLister:wipe()
|
||||
if #self.seen_strs_sorted > 0 then
|
||||
print()
|
||||
print("# actors wiped #")
|
||||
print()
|
||||
end
|
||||
self.seen_once = {}
|
||||
self.seen_strs = {}
|
||||
self.seen_strs_sorted = {}
|
||||
end
|
||||
|
||||
function ActorLister:run(now)
|
||||
local game_counts = nil
|
||||
local seen = {}
|
||||
local cursor, target
|
||||
|
||||
local ctrl, pressed = self.input:update()
|
||||
|
||||
if pressed.left then self.focus_ai = self.focus_ai - 1 end
|
||||
if pressed.right then self.focus_ai = self.focus_ai + 1 end
|
||||
if pressed.down then
|
||||
-- follow Link again
|
||||
self.focus_at = 2
|
||||
self.focus_ai = 0
|
||||
end
|
||||
|
||||
if R4(stupid) ~= 0 then
|
||||
T_BR(0, 0, "red", "stupid")
|
||||
return
|
||||
end
|
||||
|
||||
local any, actors_by_type, new_counts = collect_actors()
|
||||
|
||||
if not any then
|
||||
self:wipe()
|
||||
else
|
||||
while self.focus_ai < 0 do
|
||||
self.focus_at = (self.focus_at - 1) % 12
|
||||
self.focus_ai = new_counts[self.focus_at] - 1
|
||||
end
|
||||
while self.focus_ai >= new_counts[self.focus_at] do
|
||||
self.focus_at = (self.focus_at + 1) % 12
|
||||
self.focus_ai = 0
|
||||
end
|
||||
cursor = deref(addrs.z_cursor_actor())
|
||||
target = deref(addrs.z_target_actor())
|
||||
end
|
||||
|
||||
local focus_link = self.focus_at == 2 and self.focus_ai == 0
|
||||
if self.debug_mode then focus_link = false end
|
||||
local needs_update = false
|
||||
|
||||
for at, actors in pairs(actors_by_type) do
|
||||
for ai, addr in pairs(actors) do -- FIXME: sorry for this pseudo-indent
|
||||
local var = R2(addr + actor_t.var.addr)
|
||||
local hp = R1(addr + actor_t.hp.addr)
|
||||
local num = R2(addr + actor_t.num.addr)
|
||||
local name = actor_names[num]
|
||||
local fa = addr + actor_t.flags.addr
|
||||
local flags = R4(fa)
|
||||
|
||||
local focus_this = at == self.focus_at and ai == self.focus_ai
|
||||
|
||||
seen[num] = true
|
||||
|
||||
if not name then
|
||||
name = "NEW"
|
||||
actor_names[num] = name
|
||||
print(("\t[0x%03X]=\"NEW\","):format(num))
|
||||
end
|
||||
|
||||
if not self.seen_once[num] then
|
||||
self.seen_once[num] = now
|
||||
needs_update = true
|
||||
local str
|
||||
if name:sub(1,1) == "?" then
|
||||
str = ("%s (%03X)"):format(name, num)
|
||||
else
|
||||
str = ("%s"):format(name)
|
||||
end
|
||||
self.seen_strs[num] = str
|
||||
print(str)
|
||||
end
|
||||
|
||||
local focal = false
|
||||
if not self.debug_mode then
|
||||
focal = focal or (focus_this and not focus_link)
|
||||
focal = focal or (focus_link and addr == target)
|
||||
else
|
||||
if target then
|
||||
focal = addr == target
|
||||
else
|
||||
focal = focus_this
|
||||
end
|
||||
end
|
||||
if focal then
|
||||
local actor = {
|
||||
name = name,
|
||||
addr = addr,
|
||||
ai = ai,
|
||||
type_count = new_counts[at],
|
||||
|
||||
at = at,
|
||||
var = var,
|
||||
flags = flags,
|
||||
hp = hp,
|
||||
num = num,
|
||||
}
|
||||
focus(actor, pressed.up) -- FIXME: global
|
||||
end
|
||||
|
||||
if focus_this then
|
||||
W1(addrs.camera_target.addr, 0x80)
|
||||
W3(addrs.camera_target.addr + 1, addr)
|
||||
end
|
||||
|
||||
-- make all actors z-targetable
|
||||
if not (focus_this and focus_link) then
|
||||
flags = bit.bor(flags, 0x00000001)
|
||||
W4(fa, flags)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if needs_update then
|
||||
self.seen_strs_sorted = sort_by_key(self.seen_strs)
|
||||
end
|
||||
|
||||
if focus_link and not target then
|
||||
for i, t in ipairs(self.seen_strs_sorted) do
|
||||
local color = 'white'
|
||||
if self.seen_once[t.k] and now - 60 <= self.seen_once[t.k] then
|
||||
color = 'lime'
|
||||
end
|
||||
if not seen[t.k] then
|
||||
color = 'orange'
|
||||
end
|
||||
T_TL(0, i - 1, color, t.v)
|
||||
end
|
||||
end
|
||||
|
||||
T_BR(0, 0, nil, "unique:%3i", #self.seen_strs_sorted)
|
||||
|
||||
if any then
|
||||
local z = target or cursor
|
||||
if z then
|
||||
local num = R2(z)
|
||||
T_TR(0, 0, nil, self.seen_strs[num])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: abstract to wrapper class or something
|
||||
function ActorLister:runwrap(now)
|
||||
if now < self.before then self.wait = 2 end
|
||||
self.before = now
|
||||
if self.wait > 0 then
|
||||
-- prevent script from lagging reversing
|
||||
self.wait = self.wait - 1
|
||||
if self.wait == 0 then self:wipe() end
|
||||
else
|
||||
self:run(now)
|
||||
end
|
||||
end
|
||||
|
||||
return ActorLister
|
19
Lua/classes/ByteMonitor.lua
Normal file
19
Lua/classes/ByteMonitor.lua
Normal file
|
@ -0,0 +1,19 @@
|
|||
local Monitor = require "classes.Monitor"
|
||||
local ByteMonitor = Class(Monitor)
|
||||
|
||||
function ByteMonitor:mark(i, x, x1)
|
||||
local now = emu.framecount()
|
||||
local str = ('%02i=%02X (%s)'):format(i, x, self.name)
|
||||
if not self.modified[i] then
|
||||
self.modified[i] = {}
|
||||
end
|
||||
if not self.modified[i][x] then
|
||||
self.modified[i][x] = true
|
||||
self.dirty = true
|
||||
str = str..' (NEW!)'
|
||||
end
|
||||
printf('%s @%i', str, now)
|
||||
message(str, 180)
|
||||
end
|
||||
|
||||
return ByteMonitor
|
107
Lua/classes/FlagMonitor.lua
Normal file
107
Lua/classes/FlagMonitor.lua
Normal file
|
@ -0,0 +1,107 @@
|
|||
local printf = dprintf or printf
|
||||
|
||||
local Monitor = require "classes.Monitor"
|
||||
local FlagMonitor = Class(Monitor)
|
||||
|
||||
function FlagMonitor:init(name, a, ignore)
|
||||
Monitor.init(self, name, a)
|
||||
self.ignore = ignore or {}
|
||||
end
|
||||
|
||||
function FlagMonitor:mark(i, x, x1)
|
||||
local now = emu.framecount()
|
||||
local diff = bit.bxor(x, x1)
|
||||
for which = 0, 7 do
|
||||
if bit.band(diff, 2^which) ~= 0 then
|
||||
local state = bit.band(x, 2^which) ~= 0 and 1 or 0
|
||||
local str
|
||||
if self.oot then
|
||||
local row = math.floor(i/2)
|
||||
local col = which + (1 - (i % 2))*8
|
||||
str = ('%02i,%X=%i (%s)'):format(row, col, state, self.name)
|
||||
else
|
||||
str = ('%02i,%i=%i (%s)'):format(i, which, state, self.name)
|
||||
end
|
||||
local ib = i*8 + which
|
||||
local curious = self.modified[ib] == "curious"
|
||||
if not self.modified[ib] or curious then
|
||||
self.modified[ib] = true
|
||||
self.dirty = true
|
||||
if not curious then
|
||||
str = str..' (NEW!)'
|
||||
else
|
||||
str = str..' (!!!)'
|
||||
end
|
||||
end
|
||||
if not self.ignore[str] then
|
||||
printf('%s @%i', str, now)
|
||||
message(str, 180)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function FlagMonitor:dump(current)
|
||||
local t = current and self:read() or self.modified
|
||||
|
||||
local size = self.oot and 16 or 8
|
||||
local rows = math.floor(self.len/size*8)
|
||||
|
||||
local buff = self.name..'\n'
|
||||
|
||||
buff = buff..' \t'
|
||||
for col = size-1, 0, -1 do
|
||||
buff = buff..('%X'):format(col)
|
||||
if col % 4 == 0 then buff = buff..' ' end
|
||||
end
|
||||
|
||||
for row = 0, rows-1 do
|
||||
s = ('%02i\t'):format(row)
|
||||
for col = size-1, 0, -1 do
|
||||
local B, b = row, col
|
||||
if size == 16 then
|
||||
B = row*2 + (col < 8 and 1 or 0)
|
||||
b = col % 8
|
||||
end
|
||||
local ib = B*8 + b
|
||||
local v
|
||||
if current then v = bit.band(t[B], 2^b) > 0 else v = t[ib] end
|
||||
s = s..(v and '1' or '0')
|
||||
if col % 4 == 0 then s = s..' ' end
|
||||
end
|
||||
buff = buff..'\n'..s
|
||||
end
|
||||
|
||||
return buff
|
||||
end
|
||||
|
||||
function FlagMonitor:wipe()
|
||||
for i = self.begin, self.begin+self.len-1 do
|
||||
W1(i, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function FlagMonitor:set_unknowns()
|
||||
self.save = function() end -- no clutter
|
||||
local mod = self.modified_backup
|
||||
if not mod then
|
||||
mod = {}
|
||||
for i, v in pairs(self.modified) do
|
||||
mod[i] = v
|
||||
end
|
||||
self.modified_backup = mod
|
||||
end
|
||||
for i = 0, self.len-1 do
|
||||
local v = R1(self.begin + i)
|
||||
for which = 0, 7 do
|
||||
local ib = i*8 + which
|
||||
if not mod[ib] and bit.band(v, 2^which) == 0 then
|
||||
v = v + 2^which
|
||||
end
|
||||
end
|
||||
--printf("%04X = %02X", self.begin + i, sum)
|
||||
W1(self.begin + i, v)
|
||||
end
|
||||
end
|
||||
|
||||
return FlagMonitor
|
21
Lua/classes/InputHandler.lua
Normal file
21
Lua/classes/InputHandler.lua
Normal file
|
@ -0,0 +1,21 @@
|
|||
local InputHandler = Class()
|
||||
function InputHandler:init(binds)
|
||||
self.binds = binds
|
||||
self.old_ctrl = {}
|
||||
end
|
||||
|
||||
function InputHandler:update()
|
||||
local ctrl = {}
|
||||
local pressed = {}
|
||||
local j = joypad.getimmediate()
|
||||
for k, v in pairs(self.binds) do
|
||||
ctrl[k] = j[v]
|
||||
end
|
||||
for k, v in pairs(ctrl) do
|
||||
pressed[k] = ctrl[k] and not self.old_ctrl[k]
|
||||
end
|
||||
self.old_ctrl = ctrl
|
||||
return ctrl, pressed
|
||||
end
|
||||
|
||||
return InputHandler
|
54
Lua/classes/Monitor.lua
Normal file
54
Lua/classes/Monitor.lua
Normal file
|
@ -0,0 +1,54 @@
|
|||
require "serialize"
|
||||
|
||||
local Monitor = Class()
|
||||
function Monitor:init(name, a)
|
||||
self.name = name
|
||||
self.begin = a.addr
|
||||
self.len = a.type
|
||||
self.once = false
|
||||
self.old_bytes = {}
|
||||
self.modified = {}
|
||||
self.dirty = false
|
||||
end
|
||||
|
||||
function Monitor:read()
|
||||
-- bizhawk has an off-by-one bug where this returns length + 1 bytes
|
||||
local raw = mainmemory.readbyterange(self.begin, self.len-1)
|
||||
local bytes = {}
|
||||
local begin = self.begin
|
||||
for k, v in pairs(raw) do
|
||||
bytes[k - begin] = v
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
function Monitor:diff()
|
||||
local bytes = self:read()
|
||||
local old_bytes = self.old_bytes
|
||||
if self.once then
|
||||
for i, v in pairs(bytes) do
|
||||
local x = v
|
||||
local x1 = old_bytes[i]
|
||||
if x ~= x1 then
|
||||
self:mark(i, x, x1)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.old_bytes = bytes
|
||||
self.once = true
|
||||
end
|
||||
|
||||
function Monitor:load(fn)
|
||||
self.modified = deserialize(fn) or {}
|
||||
self.dirty = false
|
||||
self.fn = fn
|
||||
end
|
||||
|
||||
function Monitor:save(fn)
|
||||
if self.dirty then
|
||||
serialize(fn or self.fn, self.modified)
|
||||
self.dirty = false
|
||||
end
|
||||
end
|
||||
|
||||
return Monitor
|
|
@ -1,10 +1,11 @@
|
|||
require = require "depend"
|
||||
require "boilerplate"
|
||||
require "addrs.init"
|
||||
require "classes"
|
||||
require "messages"
|
||||
require "classes"
|
||||
|
||||
local ignore = {
|
||||
local mm_ignore = {
|
||||
-- TODO: use list of bytes/bits rather than full strings
|
||||
-- every time a scene (un)loads
|
||||
['92,7=0 (weg)'] = true,
|
||||
['92,7=1 (weg)'] = true,
|
||||
|
@ -24,107 +25,9 @@ local ignore = {
|
|||
['28,2=1 (weg)'] = true,
|
||||
}
|
||||
|
||||
FlagMonitor = Class(Monitor)
|
||||
|
||||
function FlagMonitor:mark(i, x, x1)
|
||||
local now = emu.framecount()
|
||||
local diff = bit.bxor(x, x1)
|
||||
for which = 0, 7 do
|
||||
if bit.band(diff, 2^which) ~= 0 then
|
||||
local state = bit.band(x, 2^which) ~= 0 and 1 or 0
|
||||
local str
|
||||
if self.oot then
|
||||
local row = math.floor(i/2)
|
||||
local col = which + (1 - (i % 2))*8
|
||||
str = ('%02i,%X=%i (%s)'):format(row, col, state, self.name)
|
||||
else
|
||||
str = ('%02i,%i=%i (%s)'):format(i, which, state, self.name)
|
||||
end
|
||||
local ib = i*8 + which
|
||||
local curious = self.modified[ib] == "curious"
|
||||
if not self.modified[ib] or curious then
|
||||
self.modified[ib] = true
|
||||
self.dirty = true
|
||||
if not curious then
|
||||
str = str..' (NEW!)'
|
||||
else
|
||||
str = str..' (!!!)'
|
||||
end
|
||||
end
|
||||
if not ignore[str] then
|
||||
dprintf('%s @%i', str, now)
|
||||
message(str, 180)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function FlagMonitor:dump(current)
|
||||
local t = current and self:read() or self.modified
|
||||
|
||||
local size = self.oot and 16 or 8
|
||||
local rows = math.floor(self.len/size*8)
|
||||
|
||||
local buff = self.name..'\n'
|
||||
|
||||
buff = buff..' \t'
|
||||
for col = size-1, 0, -1 do
|
||||
buff = buff..('%X'):format(col)
|
||||
if col % 4 == 0 then buff = buff..' ' end
|
||||
end
|
||||
|
||||
for row = 0, rows-1 do
|
||||
s = ('%02i\t'):format(row)
|
||||
for col = size-1, 0, -1 do
|
||||
local B, b = row, col
|
||||
if size == 16 then
|
||||
B = row*2 + (col < 8 and 1 or 0)
|
||||
b = col % 8
|
||||
end
|
||||
local ib = B*8 + b
|
||||
local v
|
||||
if current then v = bit.band(t[B], 2^b) > 0 else v = t[ib] end
|
||||
s = s..(v and '1' or '0')
|
||||
if col % 4 == 0 then s = s..' ' end
|
||||
end
|
||||
buff = buff..'\n'..s
|
||||
end
|
||||
|
||||
return buff
|
||||
end
|
||||
|
||||
function FlagMonitor:wipe()
|
||||
for i = self.begin, self.begin+self.len-1 do
|
||||
W1(i, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function FlagMonitor:set_unknowns()
|
||||
self.save = function() end -- no clutter
|
||||
local mod = self.modified_backup
|
||||
if not mod then
|
||||
mod = {}
|
||||
for i, v in pairs(self.modified) do
|
||||
mod[i] = v
|
||||
end
|
||||
self.modified_backup = mod
|
||||
end
|
||||
for i = 0, self.len-1 do
|
||||
local v = R1(self.begin + i)
|
||||
for which = 0, 7 do
|
||||
local ib = i*8 + which
|
||||
if not mod[ib] and bit.band(v, 2^which) == 0 then
|
||||
v = v + 2^which
|
||||
end
|
||||
end
|
||||
--printf("%04X = %02X", self.begin + i, sum)
|
||||
W1(self.begin + i, v)
|
||||
end
|
||||
end
|
||||
|
||||
if mm then
|
||||
weg = FlagMonitor('weg', addrs.week_event_reg)
|
||||
inf = FlagMonitor('inf', addrs.event_inf)
|
||||
weg = FlagMonitor('weg', addrs.week_event_reg, mm_ignore)
|
||||
inf = FlagMonitor('inf', addrs.event_inf, mm_ignore)
|
||||
--mmb = FlagMonitor('mmb', addrs.mask_mask_bit) -- 100% known, no point
|
||||
weg:load('data/_weg.lua')
|
||||
inf:load('data/_inf.lua')
|
||||
|
|
|
@ -3,23 +3,6 @@ require "addrs.init"
|
|||
require "classes"
|
||||
require "messages"
|
||||
|
||||
ByteMonitor = Class(Monitor)
|
||||
|
||||
function ByteMonitor:mark(i, x, x1)
|
||||
local now = emu.framecount()
|
||||
local str = ('%02i=%02X (%s)'):format(i, x, self.name)
|
||||
if not self.modified[i] then
|
||||
self.modified[i] = {}
|
||||
end
|
||||
if not self.modified[i][x] then
|
||||
self.modified[i][x] = true
|
||||
self.dirty = true
|
||||
str = str..' (NEW!)'
|
||||
end
|
||||
printf('%s @%i', str, now)
|
||||
message(str, 180)
|
||||
end
|
||||
|
||||
local unk = ByteMonitor('unk', AL(0xF6, 0x37A))
|
||||
unk:load('data/_unk.lua')
|
||||
while mm do
|
||||
|
|
Loading…
Reference in a new issue