Post subject: Making Advanced Cheats with Lua Scripts
Player (98)
Joined: 3/20/2008
Posts: 466
Location: Montreal, Quebec, Canada
There's a lot of simple hacking (eg/ infinite hp, lv 99, max gold) you can do just by using RAM search and changing memory values. But what if you want to do something more elaborate, like messing with your character's acceleration? That's where lua comes in. To illustrate, I had some fun messing around with Super Mario World. This simple lua script makes Mario go at full speed the frame you press left or right. Mario also floats upwards at full speed by holding B, and will fall just as fast by pressing down. It's a lot of fun to try out and there's some hilarious unintended side-effects, such as dying when touching a green ! block. Download SMWCheat.lua
Language: lua

local buttons = {} while true do buttons = joypad.get(1) xspd = 0x7E007B yspd = 0x7E007D rxspd = memory.readbyte(xspd) ryspd = memory.readbyte(yspd) gui.text(190,40,"horz spd: "..rxspd) gui.text(190,50,"vert spd: "..ryspd) if buttons.right then memory.writebyte(xspd,50) end if buttons.left then memory.writebyte(xspd,-50) end if buttons.B then memory.writebyte(yspd,-56) end if buttons.down then memory.writebyte(yspd,56) end snes9x.frameadvance() end
Since I'm not very proficient in lua, I'm hoping other members will get on board with this idea, since there's tiny gameplay hacks that can make games dramatically more enjoyable to play. Some ideas off the top of my head: Super Mario World: -Able to fly with the cape without charging (ie running until you build enough speed) -Increase the rate at which fireballs are released -Press a button to make a P-switch fall out of the sky -Make a duplicate of every enemy on-screen Super Metroid: -Instant shinespark charge -Shinesparks don't cost hp: In fact, maybe they even increase hp! -Double Samus' natural jumping height -Beam shoots backwards (Samus must face away from the enemy to hit) -Power bombs activate without the long explode animation -A simple morph ball bomb sends Samus flying -Samus' ship appears in the boss room after the boss is defeated -Shoot missiles and super missiles simultaneously Most of those ideas involve making the game easier, but of course you can manipulate the game into becoming harder. For instance, making the main character die in 1 hit. I think it would be really fun, both from a coding standpoint (better understanding ram search and lua), and obviously the end result of a game on steroids. For now I'd put emphasis on lua scripts that could apply to a broad range of games, such as making the main character move faster.
Player (98)
Joined: 3/20/2008
Posts: 466
Location: Montreal, Quebec, Canada
Thanks to gocha's amazing utility script, I figured out how to get Mario to fly without charging! Download SMW.lua
Language: lua

local buttons = {} while true do buttons = joypad.get(1) xspd = 0x7E007B yspd = 0x7E007D rxspd = memory.readbyte(xspd) ryspd = memory.readbyte(yspd) flight_charge = 0x7E13E4 gui.text(190,40,"horz spd: "..rxspd) gui.text(190,50,"vert spd: "..ryspd) joypad.set(1,{Y=1}) memory.writebyte(flight_charge,112) if rxspd >= 0 and rxspd <30>= 0 and ryspd <= 6 then if buttons.right then memory.writebyte(xspd,50) end if buttons.left then memory.writebyte(xspd,-50) end end if buttons.down then memory.writebyte(xspd,50) memory.writebyte(yspd,56) end if buttons.up then memory.writebyte(xspd,50) memory.writebyte(yspd,-56) end snes9x.frameadvance() end
There's still some annoyances, like dying whenever you fly too far into a wall, which makes water levels nearly impossible to beat with these controls. *Note that line 19 of the code isn't coming out correctly :( rxspd is less than or equal to 30 and ryspd is greater than equal to 0.
Hoe
Joined: 7/31/2004
Posts: 183
Location: USA
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
One of the main problem for making "advanced cheat" cheat script with lua is that you can't hook/freeze some value like a normal cheat utility or gameshark. So far, you can only replace at every frame, but that's doesn't mean that the game won't change the value several time between two frames.
AnS
Emulator Coder, Experienced player (724)
Joined: 2/23/2006
Posts: 682
BadPotato wrote:
One of the main problem for making "advanced cheat" cheat script with lua is that you can't hook/freeze some value like a normal cheat utility or gameshark. So far, you can only replace at every frame, but that's doesn't mean that the game won't change the value several time between two frames.
Why, there's memory.registerwrite() function for that.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
AnS wrote:
Why, there's memory.registerwrite() function for that.
Well, I'll be damned. I just tried with memory.register and memory.registerwrite. It seem I had to use both to get it work on a walk through wall(that I couldn't get it work with the regular way). Thanks a lot for that tip :)
Player (98)
Joined: 3/20/2008
Posts: 466
Location: Montreal, Quebec, Canada
Can you give an example of memory.registerwrite being used? I tried it and got an error "bad argument #3 to 'registerwrite' (function expected, got no value)". In the documentation, it says:
memory.registerwrite (address, [size,] [cpuname,] func) Calls the function whenever the given address is written to. Function can be nil.
I tried passing a simple test function that simply returns the value 8, but got the same error message. What exactly are you supposed to do with that 2nd parameter?
Joined: 12/31/2009
Posts: 174
Here is a sample of how I use it in Desmume: (for newbies, this is specifically for TWEWY's rng)
RNG._routinePtr = 0x020067EC
function _RNGExec()
	-- Get value passed to RNG
	local modValue = emu.getregister("arm9.r0")
	-- Get return address
	local returnAdr = emu.getregister("arm9.r14")
	
	-- Calculate result
	local lowState, highState = RNG:getState()
	lowState, highState = RNG.nextState(lowState, highState)
	local result = RNG.getResult(lowState, modValue)
	
	-- Code here to handle RNG execution
end
memory.registerexec(RNG._routinePtr, 4, _RNGExec)
This tracks code execution but the concept is the same for both read and write.