1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-06-30 13:57:13 -07:00
mm/Lua/actor lister.lua

283 lines
7.0 KiB
Lua
Raw Normal View History

2015-03-07 07:53:11 -08:00
require "boilerplate"
2015-03-18 10:27:45 -07:00
require "addrs"
2015-03-07 07:53:11 -08:00
2015-03-08 09:38:43 -07:00
-- bizhawk lua has some nasty memory leaks at the moment,
-- so instead of creating an object every time,
-- using a template to offset from will do for now.
2015-03-07 07:53:11 -08:00
local actor_t = Actor(0)
2015-03-17 14:58:07 -07:00
local oot = version:sub(1, 2) == "O "
2015-03-18 10:27:45 -07:00
local actor_names, damage_names
2015-03-17 14:58:07 -07:00
if oot then
actor_names = require "actor names oot"
2015-03-18 10:27:45 -07:00
damage_names = require "damage names oot"
2015-03-17 14:58:07 -07:00
else
actor_names = require "actor names"
2015-03-18 10:27:45 -07:00
damage_names = require "damage names"
2015-03-17 14:58:07 -07:00
end
2015-03-17 19:10:06 -07:00
function T(x, y, s, color, pos)
color = color or "white"
pos = pos or "bottomright"
gui.text(10*x + 2, 16*y + 4, s, nil, color, pos)
end
function T_BR(x, y, s, color) T(x, y, s, color, "bottomright") end
function T_BL(x, y, s, color) T(x, y, s, color, "bottomleft") end
function T_TL(x, y, s, color) T(x, y, s, color, "topleft") end
function T_TR(x, y, s, color) T(x, y, s, color, "topright") end
function pmask(p)
return bit.band(p, 0x7FFFFFFF)
end
2015-03-07 07:53:11 -08:00
function get_actor_count(i)
2015-03-18 21:50:35 -07:00
return R4(addrs.actor_counts[i].addr)
2015-03-07 07:53:11 -08:00
end
function get_first_actor(i)
2015-03-18 21:50:35 -07:00
return pmask(R4(addrs.actor_firsts[i].addr))
2015-03-07 07:53:11 -08:00
end
function get_next_actor(addr)
2015-03-17 19:10:06 -07:00
return pmask(R4(addr + actor_t.next.addr))
2015-03-07 07:53:11 -08:00
end
2015-03-17 19:10:06 -07:00
function count_actors()
local counts = {}
for i = 0, 11 do
counts[i] = get_actor_count(i)
end
return counts
end
function iter_actors(counts)
local at, ai = 0, 0
local once = false
local addr
return function()
2015-03-18 10:27:45 -07:00
if not counts then return nil end
2015-03-17 19:10:06 -07:00
if once then ai = ai + 1 end
once = true
while ai >= counts[at] do
ai = 0
at = at + 1
if at >= 12 then return nil end
end
if ai == 0 then
addr = get_first_actor(at)
else
addr = get_next_actor(addr)
if addr == 0 then
T_TR(0, 0, "no actor found", "yellow")
return nil
end
end
return at, ai, addr
end
2015-03-07 07:53:11 -08:00
end
2015-03-18 10:27:45 -07:00
local ctrl
local pressed = {}
local old_ctrl = {}
function update_input()
local j = joypad.getimmediate()
ctrl = {
enter = j["P1 L"],
up = j["P1 DPad U"],
down = j["P1 DPad D"],
left = j["P1 DPad L"],
right = j["P1 DPad R"],
}
for k, v in pairs(ctrl) do
pressed[k] = ctrl[k] and not old_ctrl[k]
end
old_ctrl = ctrl
end
2015-03-07 07:53:11 -08:00
local seen = {}
local seen_strs = {}
local seen_strs_sorted = {}
2015-03-07 16:02:54 -08:00
local last_any = 0
2015-03-07 07:53:11 -08:00
2015-03-18 10:27:45 -07:00
local focus_at = 2
local focus_ai = 0
2015-03-17 19:10:06 -07:00
-- hack to avoid N64 logo spitting errors
2015-03-18 21:50:35 -07:00
local stupid = addrs.actor_counts[0].addr - 0x8
2015-03-17 14:58:07 -07:00
2015-03-07 07:53:11 -08:00
while true do
local any = 0
2015-03-17 19:10:06 -07:00
local game_count = 0
local counts = nil
2015-03-17 14:58:07 -07:00
2015-03-18 10:27:45 -07:00
update_input()
if pressed.left then
focus_ai = focus_ai - 1
end
if pressed.right then
focus_ai = focus_ai + 1
end
if pressed.down then
-- follow Link again
focus_at = 2
focus_ai = 0
end
2015-03-17 14:58:07 -07:00
if R4(stupid) ~= 0 then
2015-03-17 19:10:06 -07:00
T_BR(0, 14, "stupid", "red")
2015-03-17 14:58:07 -07:00
any = 0
2015-03-17 19:10:06 -07:00
else
counts = count_actors()
for i = 0, 11 do
any = any + counts[i]
T_BR(0, 13 - i, ("#%2i: %2i"):format(i, counts[i]))
end
T_BR(0, 1, ("sum:%3i"):format(any))
if addrs.actor_count then
game_count = R1(addrs.actor_count.addr)
if game_count ~= any then
T_BR(8, 1, "mismatch!", "red")
end
end
2015-03-17 14:58:07 -07:00
end
2015-03-07 07:53:11 -08:00
if any == 0 then
seen = {}
seen_strs = {}
2015-03-07 16:02:54 -08:00
seen_strs_sorted = {}
2015-03-08 09:38:43 -07:00
if last_any ~= any then
print()
print("# actors wiped #")
print()
end
2015-03-18 10:27:45 -07:00
else
while focus_ai < 0 do
focus_at = (focus_at - 1) % 12
focus_ai = counts[focus_at] - 1
end
while focus_ai >= counts[focus_at] do
focus_at = (focus_at + 1) % 12
focus_ai = 0
end
2015-03-07 07:53:11 -08:00
end
2015-03-18 10:27:45 -07:00
local focus_link = focus_at == 2 and focus_ai == 0
2015-03-17 19:10:06 -07:00
local needs_update = false
for at, ai, addr in iter_actors(counts) do
2015-03-18 10:27:45 -07:00
local num = R2(addr + actor_t.num.addr)
2015-03-17 19:10:06 -07:00
local name = actor_names[num]
2015-03-18 10:27:45 -07:00
if not name then
2015-03-17 19:10:06 -07:00
name = "NEW"
actor_names[num] = name
print(("\t[0x%03X]=\"NEW\","):format(num))
end
2015-03-07 07:53:11 -08:00
2015-03-18 10:27:45 -07:00
if not seen[num] then
2015-03-17 19:10:06 -07:00
seen[num] = true
needs_update = true
local str
if name:sub(1,1) == "?" then
str = ("%s (%03X)"):format(name, num)
else
str = ("%s"):format(name)
2015-03-07 07:53:11 -08:00
end
2015-03-17 19:10:06 -07:00
seen_strs[num] = str
print(str)
2015-03-07 07:53:11 -08:00
end
2015-03-18 10:27:45 -07:00
local focus_this = at == focus_at and ai == focus_ai
if focus_this and not focus_link then
T_BL(0, 2, ('type: %02X'):format(at))
T_BL(0, 1, ('index: %02X'):format(ai))
T_BL(0, 0, ('count: %02X'):format(counts[at]))
local var = R2(addr + actor_t.var.addr)
local hp = R1(addr + actor_t.hp.addr)
T_BL(0, 3, ('80%06X'):format(addr))
T_BL(0, 5, ('No.: %03X'):format(num), 'cyan')
T_BL(0, 4, ('Var: %04X'):format(var))
T_BL(0, 6, ('HP: %02X'):format(hp))
local color = name:sub(1,1) == "?" and "red" or "orange"
T_BL(0, 7, name, color)
local dmg = pmask(R4(addr + actor_t.damage_table.addr))
if dmg > 0 then
for i = 0, 31 do
local name = damage_names[i]
local str = ('%9s: %02X'):format(name, R1(dmg + i))
local pos = 'topleft'
if i >= 16 then i = i - 16; pos = 'topright' end
T(0, i, str, nil, pos)
end
end
if pressed.up then
console.clear()
s = ("%04X\t%02X\t%02X"):format(num, at, hp)
if dmg > 0 then
for i = 0, 31 do
s = s..("\t%02X"):format(R1(dmg + i))
end
end
print(s)
end
end
if focus_this then
W1(addrs.camera_target.addr, 0x80)
W3(addrs.camera_target.addr + 1, addr)
2015-03-17 14:58:07 -07:00
end
2015-03-07 07:53:11 -08:00
end
2015-03-07 16:02:54 -08:00
last_any = any
2015-03-07 07:53:11 -08:00
function sort_by_key(t)
local sorted = {}
local i = 1
for k, v in pairs(seen_strs) do
sorted[i] = {k=k, v=v}
i = i + 1
end
table.sort(sorted, function(a, b) return a.k < b.k end)
return sorted
end
2015-03-17 19:10:06 -07:00
if needs_update then
2015-03-07 07:53:11 -08:00
seen_strs_sorted = sort_by_key(seen_strs)
end
2015-03-18 10:27:45 -07:00
if focus_link then
for i, t in ipairs(seen_strs_sorted) do
T_TL(0, i - 1, t.v)
end
2015-03-07 07:53:11 -08:00
end
2015-03-17 19:10:06 -07:00
T_BR(0, 0, ("unique:%3i"):format(#seen_strs_sorted))
2015-03-07 07:53:11 -08:00
2015-03-17 19:10:06 -07:00
if any > 0 then
local cursor = pmask(addrs.z_cursor_actor())
local target = pmask(addrs.z_target_actor())
2015-03-17 14:58:07 -07:00
local z = target or cursor
if z then
local num = R2(z)
2015-03-17 19:10:06 -07:00
T_TR(0, 0, seen_strs[num])
2015-03-17 14:58:07 -07:00
end
2015-03-07 07:53:11 -08:00
end
2015-03-17 14:58:07 -07:00
emu.frameadvance()
2015-03-07 07:53:11 -08:00
end