I’ve been playing
Secret of Evermore and
complaining about having to wait for my attack to recharge. The obvious solution would be to switch from my PAL copy to NTSC so everything would be a bit faster, but I decided to hack the ROM to get rid of the recharge time.
This was my first time looking at a SNES ROM, which created a couple of difficulties for me, the first of which was finding a suitable debugging emulator. I started off with bsnes, which I thought had a debugger but if it does I couldn’t find it, so I switched to bsnes plus, a debugging focussed fork of it. I think with my previous hacks I’ve been lucky that my preferred Master System emulator, MEKA, has quite a good, intuitive, and well-documented debugger built in. bsnes plus’s debugger seems pretty good, but there’s not a lot of documentation and I just found it harder to figure out, though maybe it’s just a familiarity issue. One specific issue that I had was that it doesn’t show the actual machine code in the debugger window, just the disassembly generated from it. Having the actual code there would have saved me having to look it up, and also made it easier for me to understand which specific version of the opcodes were in use.
I started off trying to identify the location in memory where the attack recharge is stored. When you attack in the game, a box down the bottom of the screen gets a number in it that counts from zero up to 100%, so I started by using the cheat finder to identify all memory addresses set to 100, then made an attack and found all of those addresses that were no longer set to 100 while it was counting. This got me about five addresses, none of which appeared to be counting up after an attack. So I tried the same thing with FF, which didn’t work either, and then again with 00, which got a promising result - a memory address that appeared to be counting up after an attack, and one next to it that went slowly up from 00 to 04 during the recharge. I tried changing the first value in the memory editor and nothing happened, but setting the 04 one to a lower value would get the percentage counter up, so it appeared I had the right value.
From there I set a breakpoint in the debugger for writes to the 04 address, then used an attack, which helped me find two addresses where the memory was set to zero after an attack and several points where it was counting up. There were also seperate points for running and for the dog’s counter. I had to spend a little time finding the equivalent points in the ROM because the debugger was giving me the address in the CPU memory where the ROM had been loaded. Doing this required translating the assembly from the debugger into machine code so I could search for it in the ROM. The SNES CPU uses different machine code to the SMS’s Z80, so I had to find new resources to help me with that. Once I’d done that I realised I could use the memory editor to see (and modify) the code loaded into the CPU, which might have saved me some time, but oh well.
I went into the memory editor and changed the instructions to set the counter to 00 into three NOP instructions, then tried attacking again. This caused the game to crash. I have since realised that the reason for this was that I was using the machine code for a Z80 NOP, 00, which in the SNES CPU is a BRK instruction. And indeed, it broke. In the SNES, the right code is EA. Whoops! Anyway, not realising that meant I had to pursue a different method, so I looked at the code that made the counter go up, thinking I could increase the value it incremented by or something. I found that the way it was working was by comparing the counter value to 0400, and if it were higher it would set it to 0400 and stop counting. So I just changed the reference value from 0400 to 0000, with the result that the counter would always be higher than the reference (or would be after incrementing once). That seems to have worked - one byte in the ROM changed from 04 to 00 (a single bit change - from 00 00 01 00 to 00 00 00 00).
Now in the game my attack is always at full power, which to me is an unambiguous improvement. I had hoped to stop running decreasing the charge as well, but this was a quick and simple hack and I’m not sure I can be bothered going back in, though it should actually be pretty easy now that I know what the correct code for a NOP is. Running out of stamina while running now just needs a momentary release of the run button to allow an instant refill, so it’s still better than it was.