1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2025-02-05 13:23:23 -08:00

refactor inject as a function

This commit is contained in:
Connor Olding 2015-12-18 15:18:08 -08:00
parent faa95f6285
commit 4e6f6a114b

View file

@ -3,40 +3,37 @@ require "boilerplate"
require "addrs.init" require "addrs.init"
local assemble = require "inject.lips" local assemble = require "inject.lips"
if version ~= "M US10" then function inject(fn)
print("Sorry, inject.lua is unimplemented for your version.") local asm_dir = bizstring and 'inject/' or './mm/Lua/inject/'
local asm_path = asm_dir..fn
local inject_addr -- seemingly unused region of memory
local inject_maxlen -- how much room we have to work with
local ow_addr -- the jal instruction to overwrite with our hook
local ow_before -- what its value is normally supposed to be
if version == 'M US10' then
inject_addr = 0x780000
inject_maxlen = 0x5A800
ow_addr = 0x1749D0
ow_before = 0x0C05CEC6
else
print("Sorry, inject.lua is unimplemented for your game version.")
return return
end end
local asm_path -- encode our jal instruction
if bizstring then local ow_after = 0x0C000000 + math.floor(inject_addr/4)
asm_path = "inject/spawn.asm" if R4(ow_addr) ~= ow_before and R4(ow_addr) ~= ow_after then
else
asm_path = "./mm/Lua/inject/spawn.asm"
end
local inject_addr, inject_maxlen, ow_addr, ow_before
inject_addr = 0x780000
inject_maxlen = 0x5A800
ow_addr = 0x1749D0
ow_before = 0x0C05CEC6
--ow_addr = 0x174750
--ow_before = 0x0C05D06A
local ss_fn = 'inject temp.State'
-- do it
local ow_after = 0x0C000000 + math.floor(inject_addr/4)
if R4(ow_addr) ~= ow_before and R4(ow_addr) ~= ow_after then
print("Can't inject -- game code is different!") print("Can't inject -- game code is different!")
return return
end end
local ow_before_addr = (ow_before % 0x4000000)*4 -- decode the original address
local ow_before_addr = (ow_before % 0x4000000)*4
local header = ("[overwritten]: 0x%08X\n"):format(ow_before_addr) -- set up a header to handle calling our function and the original
header = header..[[ local header = ("[overwritten]: 0x%08X\n"):format(ow_before_addr)
header = header..[[
// TODO: optimize for size // TODO: optimize for size
// TODO: fix case where overwritten function takes 5+ args // TODO: fix case where overwritten function takes 5+ args
push ra push ra
@ -47,37 +44,44 @@ header = header..[[
jal @overwritten jal @overwritten
nop nop
jpop ra jpop ra
start: start:
]] ]]
local inject = {} local inject_words = {}
local length = 0 local length = 0
local add_inject = function(line) local function add_word(line)
-- takes assembled code, up to 4 bytes at a time, as hex strings
length = length + #line/2 length = length + #line/2
table.insert(inject, tonumber(line, 16)) table.insert(inject_words, tonumber(line, 16))
end end
local true_offset = 0x80000000 + inject_addr
assemble(header, add_inject, {unsafe=true, offset=true_offset})
assemble(asm_path, add_inject, {unsafe=true, offset=true_offset + length})
printf("length: %i words", length/4)
if #inject > inject_maxlen then -- offset assembly labels so they work properly, and assemble!
local true_offset = 0x80000000 + inject_addr
assemble(header, add_word, {unsafe=true, offset=true_offset})
assemble(asm_path, add_word, {unsafe=true, offset=true_offset + length})
printf("length: %i words", length/4)
if #inject_words > inject_maxlen then
print("Assembly too large!") print("Assembly too large!")
return return
end end
for i, v in ipairs(inject) do for i, v in ipairs(inject_words) do
W4(inject_addr + (i - 1)*4, v) W4(inject_addr + (i - 1)*4, v)
end end
-- finally, inject over jal -- finally, write our new jump over the original
printf('%08X: %08X', ow_addr, ow_after) printf('%08X: %08X', ow_addr, ow_after)
W4(ow_addr, ow_after) W4(ow_addr, ow_after)
-- force code cache to be reloaded -- force code cache to be reloaded
if bizstring then if bizstring then
local ss_fn = 'inject temp.State'
savestate.save(ss_fn) savestate.save(ss_fn)
savestate.load(ss_fn) savestate.load(ss_fn)
else else
m64p.reloadCode() m64p.reloadCode()
end
end end
inject('spawn.asm')