1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-11-05 00:29:02 -08:00

update scripts with more addresses and such

This commit is contained in:
Connor Olding 2015-03-04 21:38:30 -08:00
parent 43ce5f0d7e
commit 749170ea5c
19 changed files with 1448 additions and 0 deletions

12
Lua/A EU10.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1E6B50
local global = 0x3DDFC0
local actor = 0x3F7250
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

12
Lua/A EU11.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1E6EF0
local global = 0x3DE360
local actor = 0x3F75F0
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

48
Lua/A EUDB.lua Executable file
View file

@ -0,0 +1,48 @@
local link = 0x23F790
local global = 0x448700
local actor = 0x4619D0
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
checksum = AL(0x100A, 2),
disable_pause = AL(0x100D, 1),
hookshot_ba = AL(0x100E, 1),
disable_c_buttons_2 = AL(0x100F, 1),
disable_items = AL(0x1010, 1),
rock_sirloin = AL(0x1014, 1),
sword_disabler = AL(0x1015, 1),
bubble_timer = AL(0x1016, 2),
rupee_accumulator = AL(0x1018, 2),
spring_water_timers = AL(0x1020, 0xC0),
spring_water_time_1 = AL(0x1020, 0x20),
spring_water_time_2 = AL(0x1040, 0x20),
spring_water_time_3 = AL(0x1060, 0x20),
spring_water_time_4 = AL(0x1080, 0x20),
spring_water_time_5 = AL(0x10A0, 0x20),
spring_water_time_6 = AL(0x10C0, 0x20),
pictograph_picture = AL(0x10E0, 0x2BC0),
title_screen_mod = AL(0x3CA8, 4),
entrance_mod = AL(0x3CAC, 4),
timer_crap = AL(0x3DD0, 4),
timer_x = AL(0x3EFA, 2),
timer_y = AL(0x3F08, 2),
buttons_enabled = AL(0x3F18, 4),
magic_modifier = AL(0x3F28, 4),
magic_max = AL(0x3F2E, 2),
weird_a_graphic = AL(0x3F42, 1),
target_style = AL(0x3F45, 1),
music_mod = AL(0x3F46, 2),
entrance_mod_setter = AL(0x3F4A, 2),
title_screen_thing = AL(0x3F4C, 1),
transition_mod = AL(0x3F55, 2),
suns_song_effect = AL(0x3F58, 2),
health_mod = AL(0x3F5A, 2),
screen_scale_enable = AL(0x3F60, 1),
screen_scale = AL(0x3F64, 'f'),
scene_flags_ingame = AL(0x3F68, 0x960),
})

12
Lua/A EUGC.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1E5480
local global = 0x378EB0
local actor = 0x392140
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

64
Lua/A JP10.lua Executable file
View file

@ -0,0 +1,64 @@
local link = 0x1EF460
local global = 0x3E6CF0
local actor = 0x3FFFA0
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
checksum = AL(0x138E, 2),
--disable_pause = AL(, 1),
--hookshot_ba = AL(, 1),
--disable_c_buttons_2 = AL(, 1),
--disable_items = AL(, 1),
--rock_sirloin = AL(, 1),
--sword_disabler = AL(, 1),
--bubble_timer = AL(, 2),
rupee_accumulator = AL(0x4078, 2),
spring_water_timers = AL(0x41D8, 0xC0),
spring_water_time_1 = AL(0x41F8, 0x20),
spring_water_time_2 = AL(0x4218, 0x20),
spring_water_time_3 = AL(0x4238, 0x20),
spring_water_time_4 = AL(0x4258, 0x20),
spring_water_time_5 = AL(0x4278, 0x20),
spring_water_time_6 = AL(0x4298, 0x20),
pictograph_picture = AL(0x1390, 0x2BC0),
title_screen_mod = AL(0x3F5C, 4),
--entrance_mod = AL(, 4),
timer_crap = AL(0x408C, 4),
timer_x = AL(0x41B8, 2),
timer_y = AL(0x41C6, 2),
buttons_enabled = AL(0x429C, 4),
magic_modifier = AL(0x42AC, 4),
magic_max = AL(0x42B2, 2),
weird_a_graphic = AL(0x42CE, 1),
--target_style = AL(, 1),
--music_mod = AL(, 2),
--entrance_mod_setter = AL(, 2),
title_screen_thing = AL(0x42D8, 1),
--transition_mod = AL(, 2),
suns_song_effect = AL(0x42E4, 2),
health_mod = AL(0x42E6, 2),
screen_scale_enable = AL(0x42EC, 1),
screen_scale = AL(0x42F0, 'f'),
--scene_flags_ingame = AL(, 0x960),
--random = A(, 4),
--visibility = A(, 2),
stored_epona = A(0x1B892F, 1),
stored_song = A(0x1C18ED, 1),
--buttons_3 = A(, 2),
--buttons_4 = A(, 2),
--text_open = A(, 1),
--text_status = A(, 1),
room_number = A(0x3FF3B0, 1),
room_ptr = A(0x3FF3BC, 4),
--actor_disable = A(, 2),
--warp_begin = A(, 1),
--screen_dim = A(, 1),
--warp_destination = A(, 2),
})

12
Lua/A JP11.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1EF710
local global = 0x3E6FB0
local actor = 0x400260
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

12
Lua/A JPGC.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1ED820
local global = 0x381250
local actor = 0x39A4E0
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

64
Lua/A US10.lua Executable file
View file

@ -0,0 +1,64 @@
local link = 0x1EF670
local global = 0x3E6B20
local actor = 0x3FFDB0
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
checksum = AL(0x100A, 2),
disable_pause = AL(0x100D, 1),
hookshot_ba = AL(0x100E, 1),
disable_c_buttons_2 = AL(0x100F, 1),
disable_items = AL(0x1010, 1),
rock_sirloin = AL(0x1014, 1),
sword_disabler = AL(0x1015, 1),
bubble_timer = AL(0x1016, 2),
rupee_accumulator = AL(0x1018, 2),
spring_water_timers = AL(0x1020, 0xC0),
spring_water_time_1 = AL(0x1020, 0x20),
spring_water_time_2 = AL(0x1040, 0x20),
spring_water_time_3 = AL(0x1060, 0x20),
spring_water_time_4 = AL(0x1080, 0x20),
spring_water_time_5 = AL(0x10A0, 0x20),
spring_water_time_6 = AL(0x10C0, 0x20),
pictograph_picture = AL(0x10E0, 0x2BC0),
title_screen_mod = AL(0x3CA8, 4),
entrance_mod = AL(0x3CAC, 4),
timer_crap = AL(0x3DD0, 4),
timer_x = AL(0x3EFA, 2),
timer_y = AL(0x3F08, 2),
buttons_enabled = AL(0x3F18, 4),
magic_modifier = AL(0x3F28, 4),
magic_max = AL(0x3F2E, 2),
weird_a_graphic = AL(0x3F42, 1),
target_style = AL(0x3F45, 1),
music_mod = AL(0x3F46, 2),
entrance_mod_setter = AL(0x3F4A, 2),
title_screen_thing = AL(0x3F4C, 1),
transition_mod = AL(0x3F55, 2),
suns_song_effect = AL(0x3F58, 2),
health_mod = AL(0x3F5A, 2),
screen_scale_enable = AL(0x3F60, 1),
screen_scale = AL(0x3F64, 'f'),
scene_flags_ingame = AL(0x3F68, 0x960),
random = A(0x097530, 4),
visibility = A(0x166118, 2),
stored_epona = A(0x1BDA9F, 1),
stored_song = A(0x1C6A7D, 1),
buttons_3 = A(0x1FB870, 2),
buttons_4 = A(0x1FB876, 2),
text_open = A(0x3FD33B, 1),
text_status = A(0x3FD34A, 1),
room_number = A(0x3FF200, 1),
room_ptr = A(0x3FF20C, 4),
actor_disable = A(0x3FF366, 2),
warp_begin = A(0x3FF395, 1),
screen_dim = A(0x3FF397, 1),
warp_destination = A(0x3FF39A, 2),
})

12
Lua/A USDE.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1EEE80
local global = 0x3E63B0
local actor = 0x3FF680
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

12
Lua/A USGC.lua Executable file
View file

@ -0,0 +1,12 @@
local link = 0x1ED830
local global = 0x381260
local actor = 0x39A4F0
function AL(a, s) return A(link+a, s) end
function AG(a, s) return A(global+a, s) end
function AA(a, s) return A(actor+a, s) end
local common = dofile("A common.lua")
return merge(common, {
})

187
Lua/A common.lua Executable file
View file

@ -0,0 +1,187 @@
-- version-agnostic addresses
function merge(t1, t2)
for k, v in pairs(t1) do
t2[k] = v
end
return t2
end
function Actor(addr)
local function AA(a, s) return A(addr+a, s) end
return {
number = AA(0x0, 2),
type = AA(0x2, 1),
flags = AA(0x4, 4),
x_copy = AA(0x8, 'f'),
y_copy = AA(0xC, 'f'),
z_copy = AA(0x10, 'f'),
x = AA(0x24, 'f'),
y = AA(0x28, 'f'),
z = AA(0x2C, 'f'),
angle_old = AA(0x4A, 2),
x_scale = AA(0x58, 'f'),
y_scale = AA(0x5C, 'f'),
z_scale = AA(0x60, 'f'),
x_vel = AA(0x64, 'f'),
y_vel = AA(0x68, 'f'),
z_vel = AA(0x6C, 'f'),
lin_vel_old = AA(0x70, 'f'),
ground_y = AA(0x88, 'f'),
angle = AA(0xBA, 2),
foot_left_x = AA(0xD4, 'f'),
foot_left_y = AA(0xD8, 'f'),
foot_left_z = AA(0xDC, 'f'),
foot_right_x = AA(0xE0, 'f'),
foot_right_y = AA(0xE4, 'f'),
foot_right_z = AA(0xE8, 'f'),
camera_rel_x = AA(0xEC, 'f'),
camera_rel_y = AA(0xF0, 'f'),
camera_rel_z = AA(0xF4, 'f'),
unknown_z = AA(0xF8, 'f'),
x_old = AA(0x108, 'f'),
y_old = AA(0x10C, 'f'),
z_old = AA(0x108, 'f'),
prev = AA(0x128, 4),
next = AA(0x12C, 4),
}
end
return {
link = A(link, 0x4000),
area_mod = AL(0x02, 2),
cutscene_status = AL(0x0A, 2),
time = AL(0x0C, 2),
time_speed = AL(0x16, 2),
day = AL(0x1B, 1),
transformation = AL(0x20, 1),
zeroth_day = AL(0x23, 1),
sot_count = AL(0x2A, 2),
name = AL(0x2C, 8),
max_hearts = AL(0x34, 2),
hearts = AL(0x36, 2),
magic_1 = AL(0x39, 1),
rupees = AL(0x3A, 2),
magic_2 = AL(0x40, 2),
owls_hit = AL(0x46, 2),
sword_shield = AL(0x6D, 1),
inventory_items = AL(0x70, 24),
inventory_masks = AL(0x88, 24),
inventory_counts = AL(0xA0, 24),
wallet_flags = AL(0xBA, 1),
quiver_bag = AL(0xBB, 1),
status_items = AL(0xBD, 3),
scene_flags_save = AL(0x470, 0x960),
area_map = AL(0xEB2, 1),
banked_rupees = AL(0xEDE, 2),
archery = AL(0xF00, 1),
chateau_romani = AL(0xF06, 1),
disable_c_buttons = AL(0xF4A, 1),
sword_disable_c = AL(0xF52, 1),
map_visited = AL(0xF5E, 2),
map_visible = AL(0xF62, 2),
inventory = {
b_button = AL(0x4C, 1),
ocarina = AL(0x70, 1),
bow = AL(0x71, 1),
fire_arrows = AL(0x72, 1),
ice_arrows = AL(0x73, 1),
light_arrows = AL(0x74, 1),
event_1 = AL(0x75, 1),
bombs = AL(0x76, 1),
bombchu = AL(0x77, 1),
deku_stick = AL(0x78, 1),
deku_nut = AL(0x79, 1),
magic_beans = AL(0x7A, 1),
event_2 = AL(0x7B, 1),
powder_keg = AL(0x7C, 1),
pictograph = AL(0x7D, 1),
lens_of_truth = AL(0x7E, 1),
hookshot = AL(0x7F, 1),
fairy_sword = AL(0x80, 1),
event_3 = AL(0x81, 1),
bottle_1 = AL(0x82, 1),
bottle_2 = AL(0x83, 1),
bottle_3 = AL(0x84, 1),
bottle_4 = AL(0x85, 1),
bottle_5 = AL(0x86, 1),
bottle_6 = AL(0x87, 1),
},
masks = {
postman = AL(0x88, 1),
all_night = AL(0x89, 1),
blast = AL(0x8A, 1),
stone = AL(0x8B, 1),
great_fairy = AL(0x8C, 1),
deku = AL(0x8D, 1),
keaton = AL(0x8E, 1),
bremen = AL(0x8F, 1),
bunny = AL(0x90, 1),
don_gero = AL(0x91, 1),
scents = AL(0x92, 1),
goron = AL(0x93, 1),
romani = AL(0x94, 1),
troupe_leader = AL(0x95, 1),
kafei = AL(0x96, 1),
couples = AL(0x97, 1),
truth = AL(0x98, 1),
zora = AL(0x99, 1),
kamaro = AL(0x9A, 1),
gibdo = AL(0x9B, 1),
garos = AL(0x9C, 1),
captains = AL(0x9D, 1),
giants = AL(0x9E, 1),
fierce_deity = AL(0x9F, 1),
},
counts = {
arrows = AL(0xA1, 1),
bombs = AL(0xA6, 1),
bombchu = AL(0xA7, 1),
sticks = AL(0xA8, 1),
nuts = AL(0xA9, 1),
beans = AL(0xAA, 1),
kegs = AL(0xAC, 1),
},
buttons_1 = AG(0x1A, 1),
buttons_2 = AG(0x1B, 1),
framerate_limiter = AG(0xA2, 1),
camera_target = AG(0x2B0, 4),
actor_count_0 = AG(0x1CB0, 4),
actor_first_0 = AG(0x1CB4, 4),
actor_count_1 = AG(0x1CBC, 4),
actor_first_1 = AG(0x1CC0, 4),
actor_count_2 = AG(0x1CC8, 4),
actor_first_2 = AG(0x1CCC, 4),
actor_count_3 = AG(0x1CD4, 4),
actor_first_3 = AG(0x1CD8, 4),
actor_count_4 = AG(0x1CE0, 4),
actor_first_4 = AG(0x1CE4, 4),
actor_count_5 = AG(0x1CEC, 4),
actor_first_5 = AG(0x1CF0, 4),
actor_count_6 = AG(0x1CF8, 4),
actor_first_6 = AG(0x1CFC, 4),
actor_count_7 = AG(0x1D04, 4),
actor_first_7 = AG(0x1D08, 4),
actor_count_8 = AG(0x1D10, 4),
actor_first_8 = AG(0x1D14, 4),
actor_count_9 = AG(0x1D1C, 4),
actor_first_9 = AG(0x1D20, 4),
actor_count_10 = AG(0x1D28, 4),
actor_first_10 = AG(0x1D2C, 4),
actor_count_11 = AG(0x1D34, 4),
actor_first_11 = AG(0x1D38, 4),
bomb_counter = AG(0x1CD4, 1),
z_cursor_actor = AG(0x1DF8, 4),
z_target_actor = AG(0x1DFC, 4),
link_actor = merge(Actor(AA(0,0).addr), {
item_in_hand = AA(0x148, 1),
animation_id = AA(0x24A, 2),
link_flags = AA(0xA6C, 0xC),
lin_vel = AA(0xAD0, 'f'),
movement_angle = AA(0xAD4, 2),
active_sword = AA(0xADB, 1),
}),
}

95
Lua/actor change.lua Executable file
View file

@ -0,0 +1,95 @@
require "boilerplate"
local addrs = require "addrs"
local actor_type = 2
local actor_index = 0
local pressed = {}
local old_ctrl = {}
function get_actor_count(i)
return R4(addrs.actor_count_0.addr + i*0xC)
end
function get_first_actor(i)
return bit.band(R4(addrs.actor_first_0.addr + i*0xC), 0x7FFFFFFF)
end
function get_next_actor(a)
return bit.band(R4(a + 0x12C), 0x7FFFFFFF)
end
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
while true do
local j = joypad.getimmediate()
local 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
if pressed.left then
actor_index = actor_index - 1
end
if pressed.right then
actor_index = actor_index + 1
end
if pressed.down then
-- follow Link again
actor_type = 2
actor_index = 0
end
local any = 0
for i = 0, 11 do
local count = get_actor_count(i)
T(0, 11 - i, ("#%2i: %2i"):format(i, count), "white", "bottomleft")
any = any + count
end
local actor_count = get_actor_count(actor_type)
if any > 0 then
while actor_index < 0 do
actor_type = (actor_type - 1) % 12
actor_count = get_actor_count(actor_type)
actor_index = actor_count - 1
end
while actor_index >= actor_count do
actor_type = (actor_type + 1) % 12
actor_count = get_actor_count(actor_type)
actor_index = 0
end
local actor = get_first_actor(actor_type)
T(0, 2, ('type: %02X'):format(actor_type))
T(0, 1, ('index: %02X'):format(actor_index))
T(0, 0, ('count: %02X'):format(actor_count))
if actor_index > 0 then
for i = 0, actor_index do
actor = get_next_actor(actor)
if actor == 0 then
T(0, 3, "no actor found", "yellow")
break
end
end
end
if actor ~= 0 then
addrs.camera_target(0x80000000 + actor)
end
end
old_ctrl = ctrl
emu.yield()
end

19
Lua/addrs.lua Executable file
View file

@ -0,0 +1,19 @@
require "boilerplate"
local versions = {
['D6133ACE5AFAA0882CF214CF88DABA39E266C078'] = require "A US10",
['2F0744F2422B0421697A74B305CB1EF27041AB11'] = require "A USDE",
['9743AA026E9269B339EB0E3044CD5830A440C1FD'] = require "A USGC",
['C04599CDAFEE1C84A7AF9A71DF68F139179ADA84'] = require "A EU10",
['BB4E4757D10727C7584C59C1F2E5F44196E9C293'] = require "A EU11",
['B38B71D2961DFFB523020A67F4807A4B704E347A'] = require "A EUDB",
['A849A65E56D57D4DD98B550524150F898DF90A9F'] = require "A EUGC",
['5FB2301AACBF85278AF30DCA3E4194AD48599E36'] = require "A JP10",
['41FDB879AB422EC158B4EAFEA69087F255EA8589'] = require "A JP11",
['1438FD501E3E5B25461770AF88C02AB1E41D3A7E'] = require "A JPGC",
}
local hash = gameinfo.getromhash()
local addrs = versions[hash]
return addrs

65
Lua/boilerplate.lua Executable file
View file

@ -0,0 +1,65 @@
-- boilerplate convenience functions
-- TODO: respect little endian consoles too
local mm = mainmemory
R1 = mm.readbyte
R2 = mm.read_u16_be
R3 = mm.read_u24_be
R4 = mm.read_u32_be
RF = function(addr) return mm.readfloat(addr, true) end
W1 = mm.writebyte
W2 = mm.write_u16_be
W3 = mm.write_u24_be
W4 = mm.write_u32_be
WF = function(addr, value) mm.writefloat(addr, value, true) end
local readers = {
[1] = R1,
[2] = R2,
[3] = R3,
[4] = R4,
['f'] = RF,
}
local writers = {
[1] = W1,
[2] = W2,
[3] = W3,
[4] = W4,
['f'] = WF,
}
local mt = {
__call = function(self, value)
return value and self.write(self.addr, value) or self.read(self.addr)
end
}
function A(addr, atype)
return setmetatable({
addr=addr,
type=atype,
read=readers[atype],
write=writers[atype]
}, mt)
end
--[[
-- now we can just write:
handle = A(0x123456, 1)
print(handle()) -- get 1 byte at address
handle(0xFF) -- set 1 byte at address
-- or just:
A(0x123456, 1)(0xFF) -- set address value
-- and taking advantage of A returning a table and not just a function:
A(handle.addr + 1, handle.type)(0x00) -- set the byte after our address
-- this doesn't limit us to just the type we initially specified. eg:
A(handle.addr, 2)(0x1234) -- set 2 bytes as opposed to our original 1
--]]
return A

234
Lua/cheat menu.lua Executable file
View file

@ -0,0 +1,234 @@
require "boilerplate"
local addrs = require "addrs"
local close = {text="close", type="close"}
local menu = {
{
close,
{text="hey"},
{text="L to levitate", type="toggle", id="levitate"},
{text="levitate", type="hold", call_id="levitate"},
{text="everything", type="oneshot", call_id="everything"},
active = 1,
},
{
close,
{text="kill link", type="oneshot", call_id="kill"},
{text="some flags", type="control"}, -- how to handle this?
-- i guess with a function like update_text
-- and self_render and handle_input basically
-- or call_id="submenu" options={yada yada}
{text="k"},
active = 1,
},
active = 1,
}
local active_menu = nil
local menu_state = {
levitate = false,
}
local menu_calls = {
levitate = function(item, state)
addrs.z_vel(16)
end,
kill = function(item, state)
addrs.hearts(0)
end,
set = function(item, state)
A(item.addr, item.type)(item.value)
end,
everything = function(item, state)
local inv = addrs.inventory
local masks = addrs.masks
local counts = addrs.counts
--addrs.target_style (1)
--addrs.buttons_enabled (0)
--addrs.infinite_sword(1)
addrs.zeroth_day (1)
addrs.sot_count (0)
addrs.bubble_timer (0)
--
addrs.sword_shield (0x23)
addrs.quiver_bag (0x1B)
addrs.hearts (16*20)
addrs.max_hearts (16*20)
addrs.owls_hit (0xFFFF)
addrs.map_visible (0xFFFF)
addrs.map_visited (0xFFFF)
addrs.rupees (0xFFFF)
addrs.magic_1 (0x60) -- fixme
addrs.magic_2 (0x101) -- fixme
addrs.status_items (0xFFFFFF)
inv.b_button (0x4F)
inv.ocarina (0x00)
inv.bow (0x01)
inv.fire_arrows (0x02)
inv.ice_arrows (0x03)
inv.light_arrows (0x04)
inv.bombs (0x06)
inv.bombchu (0x07)
inv.deku_stick (0x08)
inv.deku_nut (0x09)
inv.magic_beans (0x0A)
inv.powder_keg (0x0C)
inv.pictograph (0x0D)
inv.lens_of_truth (0x0E)
inv.hookshot (0x0F)
inv.fairy_sword (0x10)
inv.bottle_1 (0x12)
inv.bottle_2 (0x1B)
inv.bottle_3 (0x1A)
inv.bottle_4 (0x18)
inv.bottle_5 (0x16)
inv.bottle_6 (0x25)
--addrs.event_1 (0x05)
--addrs.event_2 (0x0B)
--addrs.event_3 (0x11)
masks.postman (0x3E)
masks.all_night (0x38)
masks.blast (0x47)
masks.stone (0x45)
masks.great_fairy (0x40)
masks.deku (0x32)
masks.keaton (0x3A)
masks.bremen (0x46)
masks.bunny (0x39)
masks.don_gero (0x42)
masks.scents (0x48)
masks.goron (0x33)
masks.romani (0x3C)
masks.troupe_leader (0x3D)
masks.kafei (0x37)
masks.couples (0x3F)
masks.truth (0x36)
masks.zora (0x34)
masks.kamaro (0x43)
masks.gibdo (0x41)
masks.garos (0x3B)
masks.captains (0x44)
masks.giants (0x49)
masks.fierce_deity (0x35)
counts.arrows (69)
counts.bombs (69)
counts.bombchu (69)
counts.sticks (69)
counts.nuts (69)
counts.beans (69)
counts.kegs (69)
end,
}
function T(x, y, s, color)
color = color or "white"
gui.text(10*x + 2, 16*y + 4, s, nil, color, "bottomright")
end
function draw_row(row, row_number, is_active)
local color = is_active and "cyan" or "white"
if row.type == "toggle" then
T(4, row_number, row.text, color)
T(0, row_number, "[ ]", "yellow")
if menu_state[row.id] then
T(1, row_number, "x", "cyan")
end
else
T(0, row_number, row.text, color)
end
end
function run_row(row, hold)
local rt = row.type
if rt == "hold" then
if row.call_id then
menu_calls[row.call_id](row, menu_state)
end
if row.id then
menu_state[row.id] = true -- TODO: set to false later
end
end
if hold then return end
if rt == "toggle" then
menu_state[row.id] = not menu_state[row.id]
if row.call_id then
menu_calls[row.call_id](row, menu_state)
end
elseif rt == "close" then
active_menu = nil
elseif rt == "oneshot" then
menu_calls[row.call_id](row, menu_state)
end
end
function run_mainmenu(ctrl, pressed)
local active_submenu = menu.active
if pressed.left then
active_submenu = active_submenu - 1
end
if pressed.right then
active_submenu = active_submenu + 1
end
active_submenu = (active_submenu - 1) % #menu + 1
menu.active = active_submenu
local submenu = menu[active_submenu]
local active_row = submenu.active
if pressed.down then
active_row = active_row - 1
end
if pressed.up then
active_row = active_row + 1
end
active_row = (active_row - 1) % #submenu + 1
submenu.active = active_row
local row = submenu[active_row]
if pressed.enter then
run_row(row)
elseif ctrl.enter then
run_row(row, true)
end
T(0, 0, ("menu %02i/%02i"):format(active_submenu, #menu), "yellow")
for i, row in ipairs(submenu) do
draw_row(row, i, i == active_row)
end
end
local pressed = {}
local old_ctrl = {}
while true do
local j = joypad.getimmediate()
local 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
gui.clearGraphics()
if pressed.enter and not active_menu then
active_menu = menu
pressed.enter = false
end
if active_menu == menu then
run_mainmenu(ctrl, pressed)
end
old_ctrl = ctrl
emu.yield()
end

195
Lua/movement tests.lua Executable file
View file

@ -0,0 +1,195 @@
-- movement speed testing in Majora's Mask
-- by notwa, for Bizhawk 1.9.1, ROM version US 1.0
--
-- go to the fairy's fountain in clock town as human link and run this script.
local length = 70 -- in frames
local print_each = true
local tests = {
optimal_roll = {
[ 1]={ Y=127},
[ 2]={Z=true, Y=127, A=true},
[17]={Z=true, Y=127},
[18]={Z=true, Y=127, A=true},
[33]={goto=17},
},
mash_roll = {
[ 1]={ Y=127},
[ 2]={Z=true, Y=127, A=true},
[13]={Z=true, Y=127},
[14]={Z=true, Y=127, A=true},
[25]={goto=13},
},
sidehop = {
[ 1]={ X=127},
[ 2]={Z=true},
[ 8]={Z=true, X=-127, A=true},
[ 9]={Z=true, X=-127},
[15]={goto=8},
},
quick_turnaround = {
[1]={Z=true},
[2]={},
[5]={ Y=-127},
[6]={Z=true, Y=-127},
},
backwalk = {
[1]={ Y=-127},
[2]={Z=true},
[8]={Z=true, Y=-127},
},
walk = {
[1]={Y=127},
},
inverse_backwalk = {
[1]={Z=true, Y=127},
[4]={},
[7]={ Y=-127},
[8]={Z=true, Y=127},
},
}
local x_ptr = 0x3FFDD4 -- my x and y pointers
local y_ptr = 0x3FFDDC -- might be backwards
local z_ptr = 0x3FFDD8
local a_ptr = 0x3FFE6E
local pos = {2400, 375, 20}
local angle = 180/360*65536
local fn = 'lua movement test'
function pythag(x, y)
return math.sqrt(x*x + y*y)
end
function reset_stick()
joypad.setanalog({["X Axis"]=false, ["Y Axis"]=false}, 1)
end
function find_displacement()
local x = mainmemory.readfloat(x_ptr, true)
local y = mainmemory.readfloat(y_ptr, true)
return pythag(pos[1] - x, pos[2] - y)
end
function setup()
client.unpause()
for _=1, 2 do
reset_stick()
mainmemory.write_s16_be(a_ptr, angle)
mainmemory.writefloat(x_ptr, pos[1], true)
mainmemory.writefloat(y_ptr, pos[2], true)
mainmemory.writefloat(z_ptr, pos[3], true)
for i=1, 3*21 do
emu.frameadvance()
joypad.set({A=i % 4 > 0, Z=i > 9 and i <= 12}, 1)
end
end
savestate.save(fn)
end
function reload()
savestate.load(fn)
end
function finish()
reset_stick()
client.pause()
end
function preprocess(inputs)
for f, j in pairs(inputs) do
if type(f) == 'number' then
j['Start'] = j['S']
j['C Down'] = j['CD']
j['C Left'] = j['CL']
j['C Right'] = j['CR']
j['C Up'] = j['CU']
j['X Axis'] = j['X']
j['Y Axis'] = j['Y']
end
end
end
function test_inputs(name, inputs, length)
preprocess(inputs)
reload()
local to = length or inputs.length
local frame = 0
local latest, action
for _=1, to do
frame = frame + 1
for _=1, 10 do -- limit number of goto's to follow
latest = 0
action = nil
for f, j in pairs(inputs) do
if type(f) == 'number' and frame >= f and f > latest then
latest = f
action = j
end
end
if action == nil or type(action.goto) ~= 'number' then
break
else
frame = action.goto
end
end
if action ~= nil then
for _=1, 3 do
joypad.setanalog(action, 1)
joypad.set(action, 1)
emu.frameadvance()
end
end
reset_stick()
end
return x
end
function run_tests(length)
setup()
local fmt = '%20s: %10.5f'
local spd_fmt = '%20.5f units/frame'
print('# testing')
if tests['testme'] ~= nil then
local key = 'testme'
local x = test_inputs(key, tests[key], length)
local distance = find_displacement()
print(fmt:format(key, distance))
print(spd_fmt:format(distance/length))
else
local furthest = nil
local distance = 0
for k, v in pairs(tests) do
local x = test_inputs(k, v, length)
local new_distance = find_displacement()
if print_each then
print(fmt:format(k, new_distance))
end
if new_distance > distance then
furthest = k
distance = new_distance
end
end
if furthest ~= nil then
print()
print(('## and the winner for %i frames is...'):format(length))
print(fmt:format(furthest, distance))
print(spd_fmt:format(distance/length))
end
end
print()
finish()
end
run_tests(length)

139
Lua/room debug.lua Executable file
View file

@ -0,0 +1,139 @@
local A = require "boilerplate"
local addrs = require "addrs"
function printf(fmt, ...)
print(fmt:format(...))
end
function gs2(addr, value)
printf("81%06X %04X", addr, value)
W2(addr, value)
end
function is_ptr(ptr)
local head = bit.band(0xFF000000, ptr)
return head == 0x80000000
end
function deref(ptr)
return is_ptr(ptr) and ptr - 0x80000000
end
function dump_half_row(addr)
printf("%04X %04X %04X %04X", R2(addr), R2(addr+2), R2(addr+4), R2(addr+6))
end
function dump_room(start)
local addr = start
printf("start: %08X", start)
local object_n, objects
local actor_n, actors
for _ = 1,128 do -- give up after a while
local cmd = R1(addr)
if cmd == 0x14 then break end
local dumpy = function()
local bank = R1(addr+4)
local offset = R3(addr+5)
if bank ~= 3 then
printf(" in bank %i at %06X", bank, offset)
return
else
local new_addr = start + offset
printf(" at %08X (+%06X)", new_addr, offset)
return new_addr
end
end
if cmd == 0x18 then
printf("alt:")
dumpy()
elseif cmd == 0x01 then
actor_n = R1(addr+1)
printf("actors: %2i", actor_n)
actors = dumpy()
elseif cmd == 0x02 then
printf("cameras: %2i", R1(addr+1))
dumpy()
elseif cmd == 0x03 then
printf("collisions:")
dumpy()
elseif cmd == 0x04 then
printf("maps: %2i", R1(addr+1))
dumpy()
elseif cmd == 0x06 then
printf("entrances:")
dumpy()
elseif cmd == 0x08 then
print("[room behaviour]")
dump_half_row(addr)
elseif cmd == 0x0A then
printf("mesh:")
dumpy()
elseif cmd == 0x0B then
object_n = R1(addr+1)
printf("objects: %2i", object_n)
objects = dumpy()
elseif cmd == 0x0D then
printf("pathways: %2i", R1(addr+1))
dumpy()
elseif cmd == 0x10 then
print("[time]")
elseif cmd == 0x12 then
print("[skybox]")
elseif cmd == 0x13 then
printf("exits:")
dumpy()
elseif cmd == 0x16 then
printf("echo: %2i", R1(addr+7))
elseif cmd == 0x17 then
printf("cutscenes: %2i", R1(addr+1))
dumpy()
else
dump_half_row(addr)
end
addr = addr + 8
end
--[[
local obj_i = 0
local act_i = 1
if objects and object_n > obj_i and actors and actor_n > act_i then
gs2(objects + 2*obj_i, 0x00FC)
gs2(actors + 16*act_i+0x0, 0x00A8)
gs2(actors + 16*act_i+0xE, 0x0010)
end
--]]
if objects and actors then
for i = 0, object_n - 1 do
--printf('O: %04X', R2(objects + 2*i))
--gs2(objects+2*i, 0x00FC)
end
for i = 0, actor_n - 1 do
--print('A:')
--dump_half_row(actors+16*i+0)
--dump_half_row(actors+16*i+8)
--gs2(actors+16*i+0x0, 0x00A8)
--gs2(actors+16*i+0xE, 0x0010)
end
end
end
local last_addr
while true do
local addr = deref(addrs.room_ptr())
if addr and addr ~= last_addr then
print('# new room loaded #')
dump_room(addr)
print('')
end
last_addr = addr
gui.clearGraphics()
emu.yield()
end

100
Lua/test chests.lua Executable file
View file

@ -0,0 +1,100 @@
-- go to a grotto with a red rupee chest, stand in front of it and run this script
local hash = gameinfo.getromhash()
local versions = {
['D6133ACE5AFAA0882CF214CF88DABA39E266C078'] = 'US10',
}
local version = versions[hash]
local JP = version ~= 'US10'
local index = 84
local start, ours, text
if not JP then
-- US 1.0
start = 0x779884 -- the get item table
ours = 0x779896 -- the chest we're standing in front of
text = 0x3FCE10 -- ascii text buffer
else
start = 0x7797E4 -- the get item table
ours = 0x7797F6 -- the chest we're standing in front of
text = 0x3FD660 -- ascii text buffer (not quite but close enough)
end
function draw_index()
gui.text(304, 8, ("%03i"):format(index), nil, nil, 'bottomleft')
end
function advance()
draw_index()
emu.frameadvance()
draw_index()
emu.frameadvance()
draw_index()
emu.frameadvance()
end
function read_ascii(addr, len)
local begin = addr
local bytes = mainmemory.readbyterange(begin, 0x100)
local str = ""
-- pairs() won't give us the bytes in order
-- so we'll set up a table we can use ipairs() on
local ordered_bytes = {}
for a, v in pairs(bytes) do
ordered_bytes[tonumber(a, 16) - begin + 1] = v
end
local seq = false
for i, v in ipairs(ordered_bytes) do
local c = tonumber(v, 16)
if c == 9 or c == 10 or c == 13 or (c >= 32 and c < 127) then
str = str..string.char(c)
seq = false
elseif seq == false then
str = str..' '
seq = true
end
end
return str
end
local fn = 'lua chest test'
client.unpause()
savestate.save(fn)
for off=index*6, 185*6, 6 do
index = index + 1
for i=0, 5 do
local byte = mainmemory.readbyte(start + off + i)
mainmemory.writebyte(ours + i, byte)
end
joypad.set({A=true}, 1)
advance()
joypad.set({A=false}, 1)
local good = false
for i=1, 9*20 do
if JP and (
(index >= 85 and index <= 88)
) then break end -- crashes
advance()
if mainmemory.readbyte(text + 0xA) == 0xFF then
if not JP then
local begin = text + 0xC
print(off/6 + 1, read_ascii(begin))
good = true
else
for _=1, 40 do
advance()
end
end
break
end
end
if not good then
print(off/6 + 1, '[error]')
end
savestate.load(fn)
end
client.pause()

154
Lua/watch animations.lua Executable file
View file

@ -0,0 +1,154 @@
local addrs = require "addrs"
local anim_addr = addrs.link_actor.animation_id.addr
local anims_seen = {
[0xCF68] = true,
[0xCF70] = true,
[0xCFE0] = true,
[0xCFE8] = true,
[0xD068] = true,
[0xD088] = true,
[0xD090] = true,
[0xD098] = true,
[0xD0A8] = true,
[0xD0C8] = true,
[0xD0D0] = true,
[0xD0D8] = true,
[0xD140] = true,
[0xD148] = true,
[0xD308] = true,
[0xD448] = true,
[0xD450] = true,
[0xD5A0] = true,
[0xD5A8] = true,
[0xD5B0] = true,
[0xD698] = true,
[0xD6A0] = true,
[0xD6A8] = true,
[0xD720] = true,
[0xD728] = true,
[0xD730] = true,
[0xD770] = true,
[0xD780] = true,
[0xD788] = true,
[0xD790] = true,
[0xD7A8] = true,
[0xD7B8] = true,
[0xD7F0] = true,
[0xD800] = true,
[0xD858] = true,
[0xD868] = true,
[0xD878] = true,
[0xD890] = true,
[0xD898] = true,
[0xD8B0] = true,
[0xD8C8] = true,
[0xD8D8] = true,
[0xD918] = true,
[0xD920] = true,
[0xD928] = true,
[0xD930] = true,
[0xD938] = true,
[0xD988] = true,
[0xD990] = true,
[0xD998] = true,
[0xD9A0] = true,
[0xDA60] = true,
[0xDA68] = true,
[0xDA70] = true,
[0xDA78] = true,
[0xDA80] = true,
[0xDAC0] = true,
[0xDB10] = true,
[0xDB18] = true,
[0xDB28] = true,
[0xDC00] = true,
[0xDC08] = true,
[0xDC30] = true,
[0xDC40] = true,
[0xDCD8] = true,
[0xDCE0] = true,
[0xDCE8] = true,
[0xDCF0] = true,
[0xDCF8] = true,
[0xDD10] = true,
[0xDD18] = true,
[0xDD20] = true,
[0xDD28] = true,
[0xDD30] = true,
[0xDDB0] = true,
[0xDDB8] = true,
[0xDE40] = true,
[0xDE48] = true,
[0xDE50] = true,
[0xDE68] = true,
[0xDE70] = true,
[0xDE78] = true,
[0xDE80] = true,
[0xDE88] = true,
[0xDE90] = true,
[0xDEA0] = true,
[0xDEA8] = true,
[0xDEB8] = true,
[0xDEC8] = true,
[0xDED0] = true,
[0xDEE0] = true,
[0xDEE8] = true,
[0xDF20] = true,
[0xDF28] = true,
[0xDF30] = true,
[0xDF48] = true,
[0xDF50] = true,
[0xDF58] = true,
[0xDF60] = true,
[0xDF68] = true,
[0xDF70] = true,
[0xDFC8] = true,
[0xDFD0] = true,
[0xDFD8] = true,
[0xDFE0] = true,
[0xDFE8] = true,
[0xE000] = true,
[0xE0B0] = true,
[0xE0B8] = true,
[0xE0D8] = true,
[0xE0E0] = true,
[0xE0E8] = true,
[0xE0F0] = true,
[0xE208] = true,
[0xE210] = true,
[0xE218] = true,
[0xE228] = true,
[0xE230] = true,
[0xE240] = true,
[0xE248] = true,
[0xE258] = true,
[0xE260] = true,
[0xE270] = true,
[0xE2E0] = true,
[0xE308] = true,
[0xE320] = true,
[0xE338] = true,
[0xE348] = true,
[0xE3A8] = true,
[0xE3F0] = true,
[0xE3F8] = true,
[0xE400] = true,
[0xE410] = true,
[0xE450] = true,
}
while true do
local anim_id = mainmemory.read_u16_be(anim_addr)
local actor_loaded = mainmemory.read_u8(anim_addr - 2) == 4
local hexid = ('%04X'):format(anim_id)
local frame = emu.framecount()
if actor_loaded then
gui.text(2, 4, hexid, nil, 'white', "bottomleft")
if not anims_seen[anim_id] then
anims_seen[anim_id] = true
print(frame, hexid)
end
end
emu.yield()
end