Back to Page
Revision 8 (current)
Edited by feos on 8/4/2022 1:59 PM
This page documents memory editing using Lua.
__Warning: TASes for this site are not allowed to use direct memory editing (whether it is Lua or Game Genie codes). Memory editing is for information or planning purposes only! Make sure you are not running a memory-changing script while making the actual TAS.__
!! Memory Overwrite.
Memory overwrite is a useful way to test possibilities when it would be hard to generate otherwise.
Note that often, you can use a cheat code (e.g. Game Genie) in place of memory overwrite. However, memory overwrite is more powerful as you have power over what the value can be changed to, and you can overwrite large sections of memory.
The memory-changing functions are {{memory.writebyte(int addr, int value)}} (one byte), {{memory.writeword}} (two bytes), and {{memory.writedword}} (four bytes).
There are two basic ways to overwrite memory:
! One-time overwrite
To overwrite a desired memory address once, simply use one of the memory-changing functions above, without using a loop. For example, if 0x1000 is the address representing the stage number and you want to jump to stage 9, you run the following script:
%%SRC_EMBED lua
memory.writebyte(0x1000,9)
%%END_EMBED
! Continuous overwrite
To continuously overwrite an address with a value, you now use a loop. For example, if 0x1357 is the address containing the number of lives, chances are you can give yourself infinite lives by fixing its value as, say, 2:
%%SRC_EMBED lua
while true do
memory.writeword(0x1357,2)
emu.frameadvance()
end
%%END_EMBED
The following example compares both one-time overwrite and continuous overwrite. The goal of the following script is to stop the clock in Super Mario Bros. The address 0x07FA is the ones digit of the clock. The first script overwrites the clock value every frame, effectively freezing the clock. The second script overwrites the clock just one time, allowing it to further decrease.
First script:
%%SRC_EMBED lua
local Clock = 0x07FA
local Value = 8
while true do
memory.writebyte(Clock,Value)
emu.frameadvance()
end
%%END_EMBED
Second script:
%%SRC_EMBED lua
local Clock = 0x07FA
local Value = 8
memory.writebyte(Clock,Value)
%%END_EMBED
! Overwriting entire regions
This is where Lua becomes useful, as you would need too many cheat codes to cover a whole region. This is useful if you wanted to void a whole region (say, to remove all obstacles), or you want to easily identify the IDs of tiles in a tileset, or you are a ROM hacker and you want to corrupt regions of memory just to see what happens (note that you can only corrupt RAM, not the ROM itself).
To do this, just use a for loop. For example, overwriting four-byte addresses with 0, 1, 2, 3, ... :
%%SRC_EMBED lua
local i
for i=0, 250, 1 do
memory.writedword(0x3000+4*i, i)
end
%%END_EMBED
And an example to corrupt memory with random garbage:
%%SRC_EMBED lua
local i
for i=0, 1000, 1 do
memory.writebyte(0x3000+i, math.random(0, 255)'''')
end
%%END_EMBED
! Using input.get() to trigger overwrite
It is often desired that a script does not alter memory only once, or keep it a fixed value while it's running. But rather, alter the memory at a precise moment the user desires it. The ability to change the memory at a key press rather than reloading the whole script has a number of useful advantages.
Hold A to force the value at 15:
%%SRC_EMBED lua
while true do
local keys= input.get()
if keys.A then
memory.writebyte(0xA1A1,15)
end
emu.frameadvance()
end
%%END_EMBED
Hold Q to increment the value, and W to reduce it:
%%SRC_EMBED lua
while true do
local keys= input.get()
if keys.Q then
local v= memory.readbyte(0xA1A1) + 1
memory.writebyte(0xA1A1,v)
end
if keys.W then
local v= memory.readbyte(0xA1A1) - 1
memory.writebyte(0xA1A1,v)
end
emu.frameadvance()
end
%%END_EMBED