• Announcements

    • Spaff

      These Forums are closing!   10/04/2019

      After more than a decade of serving this community well, these forums have finally run their course and it's time to close them down. That doesn't mean we want to close the doors on our community, quite the opposite!
      Our discord server grows ever busier by the day, and we encourage all Double Fine fans to meet us over there www.discord.gg/doublefine In a short time these forums will become a read only archive and will remain that way until they become needed again.
      You never know, it might happen.  There is... a prophecy. Thank you all for being part of these forums, and remember that the fun is definitely not over - so please join us on Discord! Love ya, Spaff, Tim, Info Cow, and all of Double Fine.
aschepler

Changing code in mods

Recommended Posts

In a game mod, is it possible to change the actual code in a game asset? I mean the disassembled instructions, as opposed to just replacing globals and such things (as in this example). All my attempts have just resulted in a failure to load the overwritten asset file, "Failed to load {file} (room may be corrupted)".

A simple example:

local fileName = "Data/Content/Game/DorkForest/Rooms/BobTrap.lua"
local disasm = scripts.disassemble(scripts.load(fileName))

local code = disasm.proto.protos[4].code
if #code ~= 305 then error("Wrong proto?") end
for i = 95,305 do
   code[i-5] = code[i]
end
for i = 301,305 do
   code[i] = nil
end

assets.overwrite(fileName, scripts.reassemble(disasm))

protos[4] is the closure assigned to BobTrap.playMumbles. The deleted instructions 90 to 94 are

-- SELF 10 1 291
-- MOVE 12 8
-- LOADK 13 43
-- LOADK 14 44
-- CALL 10 5 1

scene:speakLineLeft(alicePortrait, "Hey! You're a sprite, right?", "Default3")

I checked that no JMP instructions jump past this code in either direction. So I expected this would just result in skipping one line of dialogue when Bob is freed. But entering the second room just gives the "(room may be corrupted)" error.

Also, if I do get replaced code working, is there a good way to insert my own assembly instructions? They appear to be some class-like object, at least to support inst:GET_OPCODE_NAME() etc., but there's no obvious interface to create new objects of that type. Can I just copy one with the correct opcode type from another disassembled function and do inst:SETARG_A() etc.?

Share this post


Link to post
Share on other sites

Progress! It looks like the issue with that example was the mismatch between code and debug.lineinfo. This version does work:

local fileName = "Data/Content/Game/DorkForest/Rooms/BobTrap.lua"
local disasm = scripts.disassemble(scripts.load(fileName))
local playMumbles = disasm.proto.protos[4]

local code = playMumbles.code
if #code ~= 305 then error("Wrong proto?") end
for i = 95,305 do
   code[i-5] = code[i]
end
for i = 301,305 do
   code[i] = nil
end

local lineinfo = playMumbles.debug.lineinfo
for i = 95,305 do
   lineinfo[i-5] = lineinfo[i]
end
for i = 301,305 do
   lineinfo[i] = nil
end

assets.overwrite(fileName, scripts.reassemble(disasm))

I figure a truly additive mod should also adjust debug.locvars in case some other mod examining the same function depends on that. (Not that there seem to be many mods doing this sort of thing, or that anybody is still trying to write new mods.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now