Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Game Cheats (ROM HACKS)

Reply to topic
Author Message
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Game Cheats (ROM HACKS)
Post Posted: Tue Jun 08, 2021 11:27 am
Last edited by L10N37 on Tue Jun 08, 2021 3:04 pm; edited 1 time in total
**WARNING, VERY AMATEUR STUFF FOLLOWS - This is for people wanting to LEARN the EXTREME basics of ROM hacking, and how I added a cheat to a ROM****


Been very interested in learning some assembly lately and even taking a programming course, have only dabbled in the past with some simple loading of arbitrary values into registers and adding register values together etc.. very simple things.

Its been quite a few years since my last dabble and I figured a good little project would be adding unlimited lives to sonic without a cheat device, so altering the ROM. Maybe next, making him jump twice as high (if it's possible)

The challenge was in finding where on earth the lives value was kept in RAM - but I ended up cheating.

Figured I would share how I did this for people wanting to learn, because If I can do it ....anyone can. Surprisingly didn't take long!

Also a thread where people can share their ROM cheats hacks

Sonic was chosen because I got to the final boss many months ago with heaps of lives and somehow still messed up and didn't clock it, I know a lot of people use save states ...heck, it's how i got through my most torturous childhood NES games as a teen - but as mentioned, this is a learning experience.


So how i cheated was I realised there was a very slim chance of finding where in the RAM my lives (starting at 03) were decrementing by scrolling through the memory editor on Emulicous and stepping my way through a death... I mean... yeah - it would have worked - eventually. Just look for a set value of 03 that drops to 02 then 01 on death, but I found the pictured GameShark website.

Boom thats a HEX address for where lives are kept in RAM! Can't be on the ROM because that's obviously read only, until we hack it on the computer. Not sure on the "09" bit after the semicolon.. that would give you 9 lives (which it did when I changed it live). I then figured oh I'll make it 99 and sure enough, although it only displayed 9 for some reason, the RAM location decremented to 98, then to 97 and so forth. Then I remembered after 9 we have A through F (Maxim has an excellent guide, never made it past basics) so obviously 2 FF's gives us the maximum value we can store in a byte which is 255 lives! Not quite "unlimited" ...close enough though.

After that I figured I would only need to adjust the ROM to stick a higher value in that RAM location, so I disassembled the ROM in emulicious and just searched for the RAM location $D246 until (from my understanding) I saw it assign "a" with the value of $03 and then load (LD) that into the RAM location $D246

So that's it, I just adjusted the value from $03 to $FF and the game starts off with a funny graphical symbol with a 5 next to it, but then in game we have 255 lives! (just visually shows 9 though)

**I had to use emulicous again, then go to the label where that code was, then find that location in a hex editor and edit it that way, as for some reason WLA DX has issues recompiling this game


As basic as this hack was, I hope this can teach someone something anyway

** feel free to correct this, as I don't really understand assembly and how that command works - but this just happened to work.
1Sonichack.png (36.62 KB)
1Sonichack.png
Sonichack.png (53.75 KB)
Sonichack.png

  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 13724
  • Location: London
Reply with quote
Post Posted: Tue Jun 08, 2021 2:39 pm
You can often find the RAM locations from Pro Action Replay cheat codes. It’s better to distribute the IPS patch than the full patched ROM.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Tue Jun 08, 2021 3:06 pm
Maxim wrote
You can often find the RAM locations from Pro Action Replay cheat codes. It’s better to distribute the IPS patch than the full patched ROM.


This should do it, made with lunar. Theres another IPS app somewhere but that came up first.

Figured it's good practice to hack roms for a while to help me get my head around some of the basics whilst feeling like I actually achieved something at the same time.
  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 546
Reply with quote
Post Posted: Tue Jun 08, 2021 3:33 pm
L10N37 wrote
So how i cheated was I realised there was a very slim chance of finding where in the RAM my lives (starting at 03) were decrementing by scrolling through the memory editor on Emulicous and stepping my way through a death... I mean... yeah - it would have worked - eventually. Just look for a set value of 03 that drops to 02 then 01 on death, but I found the pictured GameShark website.

What you describe here is pretty much the manual approach of what the Cheat/RAM Search (Debugger->Tools->RAM Search) tool is doing.
You'd first specify that the value you are interested in equals to 3. That would reduce the set to all RAM addresses that hold the value 3. After that you'd go die and either let it search for the value 2 or for any value that has decreased since the last check. By this time, you'd have like 1-4 addresses left. You could now just die again and search again or just try to see what effect changes of these addresses has.

L10N37 wrote
**I had to use emulicous again, then go to the label where that code was, then find that location in a hex editor and edit it that way, as for some reason WLA DX has issues recompiling this game

This step does not make much sense because you can directly save the modified ROM from Emulicious's Memory Editor.
You can also save the changes made directly as an ips patch.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Tue Jun 08, 2021 3:34 pm
Calindro wrote
L10N37 wrote
So how i cheated was I realised there was a very slim chance of finding where in the RAM my lives (starting at 03) were decrementing by scrolling through the memory editor on Emulicous and stepping my way through a death... I mean... yeah - it would have worked - eventually. Just look for a set value of 03 that drops to 02 then 01 on death, but I found the pictured GameShark website.

What you describe here is pretty much the manual approach of what the Cheat/RAM Search (Debugger->Tools->RAM Search) tool is doing.
You'd first specify that the value you are interested in equals to 3. That would reduce the set to all RAM addresses that hold the value 3. After that you'd go die and either let it search for the value 2 or for any value that has decreased since the last check. By this time, you'd have like 1-4 addresses left. You could now just die again and search again or just try to see what effect changes of these addresses has.

L10N37 wrote
**I had to use emulicous again, then go to the label where that code was, then find that location in a hex editor and edit it that way, as for some reason WLA DX has issues recompiling this game

This step does not make much sense because you can directly save the modified ROM from Emulicious's Memory Editor.
You can also save the changes made directly as an ips patch.


Thanks Calindro, didn't know that.

Theres something wrong with this hack anyway, I watched the timer count down from FF before playing it, but I put it on an everdrive and somehow got a gameover even though it was still on 9....

I think maxed out at 255 plus lives goes back to zero then starts again, so i got 200 coins then died twice.

Anyway, good to know these extra functions on Emulicious
  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 546
Reply with quote
Post Posted: Tue Jun 08, 2021 5:27 pm
L10N37 wrote
Calindro wrote
L10N37 wrote
So how i cheated was I realised there was a very slim chance of finding where in the RAM my lives (starting at 03) were decrementing by scrolling through the memory editor on Emulicous and stepping my way through a death... I mean... yeah - it would have worked - eventually. Just look for a set value of 03 that drops to 02 then 01 on death, but I found the pictured GameShark website.

What you describe here is pretty much the manual approach of what the Cheat/RAM Search (Debugger->Tools->RAM Search) tool is doing.
You'd first specify that the value you are interested in equals to 3. That would reduce the set to all RAM addresses that hold the value 3. After that you'd go die and either let it search for the value 2 or for any value that has decreased since the last check. By this time, you'd have like 1-4 addresses left. You could now just die again and search again or just try to see what effect changes of these addresses has.

L10N37 wrote
**I had to use emulicous again, then go to the label where that code was, then find that location in a hex editor and edit it that way, as for some reason WLA DX has issues recompiling this game

This step does not make much sense because you can directly save the modified ROM from Emulicious's Memory Editor.
You can also save the changes made directly as an ips patch.


Thanks Calindro, didn't know that.

Theres something wrong with this hack anyway, I watched the timer count down from FF before playing it, but I put it on an everdrive and somehow got a gameover even though it was still on 9....

I think maxed out at 255 plus lives goes back to zero then starts again, so i got 200 coins then died twice.

Anyway, good to know these extra functions on Emulicious

It would make sense that they don't have an overflow check because I don't think it's possible to collect that many lives in the game.
You could instead of changing the number of initial lives, find the code that decreases the lives on death. For that you could either search all references to the variable and figure out which of the code you find decreases the number of lives or set a write watchpoint on the RAM address of lives and see where it breaks when you die.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Tue Jun 08, 2021 6:01 pm
Already onto it..
Just search for more references to that ram location and find where it Decs in increments of one and just nop it. Will give it a go tomorrow. I'm excited about it for some reason hahaha.

°°just re read your message
A write watch point sounds extremely useful to know how. I will look into that for sure ! It's so hard to tell on debugger whats for what. I mean graphics I've noticed H and V for what I assume are horizontal and vertical and are referenced with VDP calls but other bits of code could be for anything so I really appreciate the feedback and tips to help learn some things
  View user's profile Send private message
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Wed Jun 09, 2021 7:38 am
got it

Heres the code I NOP'd (just right clicked to the memory editor in the ROM section and filled the byte with two zeroes)


/*Load contents of register HL into RAM location $246 then decrease the value stored in HL register by one.*/

ld hl, _RAM_D246_
dec (hl)


(correct me if the way I commented that isn't correct)

I thought I nailed it in the first 10 minutes but my first change just made it always show a value of 9 lives in the corner, the change was only visual. The RAM search function won't work for me, so i can't search and watch RAM values,

I ended up just searching for every reference to the variable as you mentioned and pasting it elsewhere from the assembly, from there it seemed obvious. It took about half an hour. Now your lives never change.

IPS patch attached



** nope that's buggy too! i didn't get a gameover but i died deliberately and it skipped gameover and sent me back to the title screen, then died deliberately again and the game froze!

its fine on Emulicious whilst watching the RAM location, it stays on 3 and works fine on the emulator. Not on a real system though.
unlimited lives.png (176.57 KB)
unlimited lives.png

  View user's profile Send private message
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Wed Jun 09, 2021 8:30 am
Instead of nopping I put a value in the byte, "20"
now some sort of calculation is happening instead of nothing at all.

It will roll between 3 and 9 lives on death usually setting on 9 (which could be any value at the life RAM location i would guess)

sometimes it settles on 3
but its working fine as unlimited lives on a real system.

Has a strange side effect of permanent ring of protection that usually fades in time, you have to take a hit for that sprite to go away once its picked up now.

  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 546
Reply with quote
Post Posted: Wed Jun 09, 2021 12:27 pm
Please excuse my wording but what the hell are you doing?? :D

Both of your patches break the code...
The first patch puts a single nop where
ld hl, _RAM_D246_

is. This causes the operand ($d246) which is $46 $d2 in ROM to be interpreted as instructions. That makes the code

nop
ld b, (hl)
jp nc, $FD35

as can be seen in my screenshot FirstPatch.png.
So in case carry is not set, the code jumps somewhere into RAM where likely some data is stored, so it starts executing data as instructions, which can have whatever effects depending on the data that is currently stored there.
When it does not follow the jump, it also executes some wrong instructions because due to the different alignment of instructions, even more operands are interpreted as instructions (including a jump - so even some control flow is broken).
Apparently, this behaves exactly the same on hardware and on emulators and can cause whatever glitches or crashes depending on the data that is currently stored in RAM at that place.

The other patch actually patches the correct address, i.e., the instruction that decrements the number of lives. But this time you replace a single byte instruction by a conditional relative jump. The following instructions (including the jump) are affected in the same way due to different alignment of instructions now and the relative jump does not jump to an instruction boundary so whenever that one is taken, another mess is produced. For this you can see the screenshot SecondPatch.png that I've attached.

What you actually want to do is replace the
dec (hl)

by
nop

to get what is shown in the attached screenshot ThirdPatch.png.
Replacing the dec (hl) by nop avoids the decrease of the number of lives.
I have attached this patch to the post as well.
FirstPatch.png (44.33 KB)
FirstPatch.png
SecondPatch.png (54.66 KB)
SecondPatch.png
ThirdPatch.png (86.02 KB)
ThirdPatch.png

  View user's profile Send private message Visit poster's website
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Wed Jun 09, 2021 1:15 pm
I'm a little confused here, the first patch was only to NOP the DEC command, this is when it stayed at a value of 3 lives permanently but i still managed to trigger a reset to title screen AND lock ups (obviously i viewed memory manager on the wrong line)

the 2nd patch definitely work as I finished the entire game with that and died about 1000 times, it ended up finishing the game with "74 lives" so i got 5000 bonus points for each

Not sure how that works but the "20" didn't break the code, it just made my lives always a random, but positive amount. I once got "1" life shown, then died again and it just went to another random positive amount.

I will look at your patch however, I don't know how the 2nd patch works? 20 is just my preference for when doing a full header patch in the reserved space (sometimes contains zeroes or F's)

**Im not including the initial patch where it loads the value $FF instead of $03

So basically your patch is what i was meant to do on that post above where i said it ended up being buggy - i appreciate you showing me where i went wrong as that really confused me!
  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 546
Reply with quote
Post Posted: Wed Jun 09, 2021 3:41 pm
L10N37 wrote
I'm a little confused here, the first patch was only to NOP the DEC command, this is when it stayed at a value of 3 lives permanently but i still managed to trigger a reset to title screen AND lock ups (obviously i viewed memory manager on the wrong line)

It's not surprising that the lives stayed at 3 because when you look at the code, you will noticed that the dec (hl) is gone. This is because due to the misalignment of the instructions the opcode of the dec (hl) has become part of the operand of the conditional jump (It's the 35 of the $FD35 operand).

L10N37 wrote
the 2nd patch definitely work as I finished the entire game with that and died about 1000 times, it ended up finishing the game with "74 lives" so i got 5000 bonus points for each

Not sure how that works but the "20" didn't break the code, it just made my lives always a random, but positive amount. I once got "1" life shown, then died again and it just went to another random positive amount.

For the 2nd patch you were lucky. The conditional relative jump would jump to the operand of the previous instruction which would become a conditional jump somewhere to RAM (like the first patch). And this jump to RAM is actually the severe issue that made the first patch crash. But your luck was that before reaching this code there is a conditional relative jump with the same condition that prevents the control from ever reaching your malicious jump with the condition met.
The other point where you were lucky is that the misalignment of instructions with the 2nd patch created an rlc (hl) instrcution which only rotates the bits of the lives variable in a circular manner, so it would never reach 0.

L10N37 wrote
I will look at your patch however, I don't know how the 2nd patch works? 20 is just my preference for when doing a full header patch in the reserved space (sometimes contains zeroes or F's)

Having FF for unused bytes makes total sense for several reasons. One of them being that it's better for flash memory. Using 20 on the other hand does not make any sense. For code it's a conditional relative jump that only if you're lucky doesn't cause harm and for unused data it won't affect program flow for the apparent reason that it's unused but it's not good for flash memory.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Thu Jun 10, 2021 12:17 am
Thanks for that info. When doing 16kb SG1000 games I actually pad the entire 2nd half up to 32kb with F's then insert a full 32kb export ROM header at the normal header location but I will have to change it to F in the reserved space as well. 20 is just blank ASCII where as F = a full stop. Learning a lot already thanks to this forum , members of this forum and a little bit of ChibiAkumas.

So far the only game that's been a bit disappointing is the 16kb version (there's also a 40kb version) of Sega Galaga.

The blue bullets are almost invisible and the blue stars in the background don't seem to render what so ever, on the emulators it's fine but not a real master system. I had a 5 minute crack changing the palette information for where colours were stored in memory but just got random blue squares on the screen.
  View user's profile Send private message
  • Joined: 27 Jun 2020
  • Posts: 171
Reply with quote
Post Posted: Thu Jun 10, 2021 3:05 am
mucking around with another system for the time being, but just wondering if you knew which checksum algorithm is used for the header as the hack throws the checksum out and won't boot on a normal BIOS. (I used an everdrive)

I usually use maxims header reader but HXD has the inbuilt feature to calculate checksums and i went through every algorithm and didn't get one showing what header reader calculates.
  View user's profile Send private message
  • Joined: 04 Jul 2010
  • Posts: 362
  • Location: Angers, France
Reply with quote
Post Posted: Thu Jun 10, 2021 5:00 am
Checksum is just a "stupid" 16bits addition between $0 and $7FEF (exclude the header $7FF0-$7FFF) on a 32k cartridge. For a bigger declared value, same thing. Just bypass the header part.

The best thing is to change the rom size to 32k (byte @7FFF) checksum is easier and quicker (resulting in a fast boot)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 2943
Reply with quote
Post Posted: Fri Jun 11, 2021 2:12 pm
ichigobankai wrote
Checksum is just a "stupid" 16bits addition between $0 and $7FEF


more precisely the modulus 65536 (16 bit) sum of each (unsigned) byte in that range.
  View user's profile Send private message Visit poster's website
Reply to topic



Back to the top of this page

Back to SMS Power!