Points of Required Attention™
Smaghetti, a new Super Mario Advance 4 editor, is currently in development! Check out the thread HERE!

Please chime in on a proposed restructuring of the ROM hacking sections.
Views: 88,319,813
Main | FAQ | Uploader | IRC chat | Radio | Memberlist | Active users | Latest posts | Calendar | Stats | Online users | Search 03-29-24 02:09 PM
Guest: Register | Login

0 users currently in ROM Hacking | 3 guests

Main - ROM Hacking - Fire 'n Ice, with sram saving New thread | New reply


Drakon
Posted on 02-23-14 02:06 AM (rev. 6 of 02-23-14 02:25 AM) Link | Quote | ID: 155752


Red Paragoomba
Compromised account. Please contact staff for a password reset.
Level: 18

Posts: 11/62
EXP: 29757
Next: 140

Since: 01-26-14
From: Toronto Canada

Last post: 3676 days
Last view: 3359 days
I decided to test my new found nes asm skills that I gained from working on other projects. I worked last night and this morning and hacked in fully functional sram saving to the fire 'n ice rom:

For something done in a night and a bit of a morning I'm pretty proud.



I haven't had time to test the full game yet. I'll get around to that when I feel like playing it more.

My goal is to eventually hack sram into all the longer nes games I like that I feel should have it. I'm starting with password system games since I wouldn't have to add a menu option to the title screen I can just hijack the password option.

____________________
http://16bitgamer.forumotion.ca/

NARFNra
Posted on 02-23-14 06:10 AM Link | Quote | ID: 155753


Koopa
Level: 25

Posts: 63/114
EXP: 87415
Next: 2205

Since: 02-13-10
From: Texas

Last post: 1778 days
Last view: 1778 days
Wow, impressive work. I'm curious, I don't need technical details on a "i could do it myself" level, but what do you really do to add SRAM? Tell the game to save at predetermined points to a location in the SRAM memory, and look it up on startup?

Drakon
Posted on 02-23-14 12:46 PM (rev. 31 of 02-23-14 01:41 PM) Link | Quote | ID: 155755


Red Paragoomba
Compromised account. Please contact staff for a password reset.
Level: 18

Posts: 12/62
EXP: 29757
Next: 140

Since: 01-26-14
From: Toronto Canada

Last post: 3676 days
Last view: 3359 days
Posted by NARFNra
Wow, impressive work. I'm curious, I don't need technical details on a "i could do it myself" level, but what do you really do to add SRAM? Tell the game to save at predetermined points to a location in the SRAM memory, and look it up on startup?


This is a guide on how I did it for this game. How you do it depends on how the game is programmed as well as how you want to handle saving and loading which is completely up to you since you're writing the code.

First I fished through the ram using the fceux ram search option to find the values I wanted to back up when sram saving being sure to write them all down in my notes. Once I found everything I needed to back up I found in the code where the values get updated once you clear a stage by setting breakpoints. Once I found the code that updates the last value I changed that code to a jsr command to free space at the end of the bank (luckily this particular game had good amounts of free space at the end of every bank so I didn't have to do bankswitching like I did with castlevania). Of course the first line of code I execute after the jsr command is whatever code I overwrote with that jsr, so I basically relocate that code to wherever I've jsr'd to (jsr is jump with return capability, like calling a sub-routine).

Now that I'm in an area of rom with lots of free space and I've executed everything that needs executing I can start adding my own code. How I program the saving and loading routines depends on what ram areas I'm backing up. Fire 'n ice was a bit easier to work with since the game has most of the ram I'm backing up in sequential order. Before I back up my ram in my auto-save routine to be sure the original game code doesn't get thrown off I push everything that I'm going to be using for my code into the stack. For this game I used values a and x so the way the nes works is you push a into the stack, transfer x into a, and then push a into the stack again. When you're done executing your code you pull a from the stack, transfer a into x, and then pull a from the stack again and that restores everything to exactly the state it was in before executing my code.

For this game two ram addresses that needed backing up were not in sequential order so after I pushed everything to the stack I just manually loaded each value into a and then stored a into whatever part of sram I felt like saving it into. Saving to s-ram just requires storing data in address range 6000-7fff for a standard 8k sram chip. If you're ever unsure you can just read the nes memory map here:

http://en.wikibooks.org/wiki/NES_Programming/Memory_Map

This link was found on google by typing "nes memory map".

The rest of the ram data I wanted to back up was in sequential order in the regular ram so instead of manually copying each individual piece I could write a loop that copies a certain range. First I set value x to 1. Then I copy from memory range (wherever I want to start copying from), x so it takes that address and adds value x to the end. Meaning if I'm loading from 0200, x and x = 1 it'll load from 0201. If x = 2 it'll load from 0202 etc etc. Then I write a store command in the same format as my load command so I store in address, x. Sram range starts at 6000 but I already used locations 6000 and 6001 so I told it to store at 6001, x. Since x = 1 it starts saving at location 6002. After the load and save commands I increase x by 1. I next do a command that compares x to a certain value, if x != (not equal) that value then it branches back to the beginning of my loop and and keeps copying data and incrementing x by 1 until x reaches whatever value I set. Since x increments by 1 every loop it copies the next piece of data from the ram to the next area in sram until x reaches the number I specified. Meaning the number I specified is the number of times this function loops and increments x which determines how much data in the ram gets copied into sram. Since I could code this in a loop format my added code was relatively small and could easily fit into the free space at the end of the bank with plenty of room to spare.

That took care of auto-saving which in this game I only needed to do after values get updated once you clear a stage. In castlevania I had to call my auto-save function in more than one place because I wanted to update my sram when I started a new stage, when I started a new sub-stage (going through a sub-stage door) and after I died and my number of lives was updated. For a loading routine I literally write the reverse of my auto-saving code. I pasted the disassembled auto-saving code into my notes and just wrote the complete reverse in hex. Again it's important that before and after I execute my added code that I push and pull every value that I'm changing so the normal game code doesn't get thrown off. Once my loading routine was written I needed to stick it somewhere in the rom and call it somehow. I reverse engineered how the game main menu selection determines where to jump to through trial and error breakpoint work. I changed the code so when you select the "continue" option instead of jumping to the password screen it jumps me to yet another block of free space at the end of the rom back. Then I just insert my sram loading code to wherever I jump. I also looked up where the game jumps to when you select "new game" and traced to the rom area after it resets all the values. This is important because after executing my sram loading code I need to jump to this area so it starts the game instead of going into the password screen. It's important to jump to the area of code after it resets the ram values for a new game otherwise it would just reset all the data I loaded from sram defeating the purpose.

For a hijack like this I want to menu to default to the "continue" option, this way you have to change your menu selection to start a new game making it harder to erase your saved game by accident. First I found the ram data that determines where the menu cursor is. I changed the routine that sets the cursor to set it to the second slot. Unfortunately the game draws the menu cursor before reading what slot it's in so I needed to add an extra jump to the cursor drawing routine after the menu loads so it would draw the cursor in my relocated location. After getting that working I just used winhex to change the menu text to whatever I want it to say.

The last bit (very important otherwise it won't run on hardware or a flash cart) of this is changing the settings. I changed the ines header in nestopia for the game to have prg sram saving enabled with a 8k chip. Fire 'n ice uses the mmc3 mapper so I read the mmc3 mapper document here:

http://wiki.nesdev.com/w/index.php/MMC3

This document tells you what value to write to what memory range to set the mmc3 to enable sram saving. As a lazy time saver I just checked the value that was written to this address in the mario 3 sram hack by infidelity because mario 3 is also a mmc3 game. I changed fire 'n ice to write the mario 3 sram hack value to this address and bam, sram saving was up and running.

For a list of nes hex codes and what they do I just used this:

http://en.wikibooks.org/wiki/6502_Assembly

Not exactly some super obscure document, I found it on google by typing "nes asm". To figure out how these work I just looked at how the retail roms used this code in the fceux debug disassembly and figured out what the commands do and how to use them by looking at the disassembled code of the retail rom.

____________________
http://16bitgamer.forumotion.ca/

RetroRain
Posted on 02-23-14 01:11 PM (rev. 2 of 02-23-14 01:20 PM) Link | Quote | ID: 155756


Fuzz Ball
Level: 66

Posts: 707/994
EXP: 2432578
Next: 29273

Since: 09-30-07

Last post: 1907 days
Last view: 929 days
Very nice Drakon! I'm glad to see that the ROM hacking scene is still alive.
Posted by NARFNra
Wow, impressive work. I'm curious, I don't need technical details on a "i could do it myself" level, but what do you really do to add SRAM? Tell the game to save at predetermined points to a location in the SRAM memory, and look it up on startup?
There are a few things you have to do.

1. Change the ines mapper offset 6 so that the ROM becomes "battery-backed." You're simply toggling on the bit that enables SRAM. See the bottom of the document nestech.txt.

2. Depending on the mapper the ROM uses, you may have to enable the SRAM Address. For instance, Mega Man uses Mapper 2, UNROM, which is a very easy mapper to work with. However, there are no special mapper registers with UNROM. So you don't have to enable anything. If the game is Mapper 4, MMC3, you would have to enable $A001, by setting it to 1. $A001 is Mapper 4's SRAM (SaveRAM) Toggle Address. And you would have to enable this at start-up. To figure this out, you need mapper documents. A must-have document is Firebug's Comprehensive Mapper Document.

You can get nestech.txt and Firebug's Mapper Document both at Zophar's Domain if you need them. You NEED documents when hacking. There is no way around it.

3. If you take a look at nestech.txt, you will see that the NES SRAM addresses is between $6000 and $7FFF. It is the final RAM location in the ROM before you get to the PRG banks.

Now, I haven't actually done a SRAM hack yet, but I would imagine it would be pretty easy. Basically, you have to figure out what it is you want saved for when you turn the game off.

Let's say you want the game to save your lives. What I might do is find where the game's frame counter is (a counter that is incremented every step), and read the lives address (LDA LivesAddress), and store it to a free RAM address (STA). Since you have $6000 to $7FFF work with, you have a lot of addresses to choose from. However, if the game already uses SRAM, you have to make sure that you aren't using an address that is already being used.

So, if you are constantly reading and storing the lives to SRAM, because you have it by the game's frame counter, aren't you essentially saving the lives to RAM?

Yes. So, part 1 is done. Now, part 2. Not that hard either. When you boot up the game, you want to read what you stored, and store that into the lives address.

So let's say you want to quit playing the game, and you have 5 lives.

Save Lives:

LDA Lives_Address
STA $6000

Load Lives:

LDA $6000
STA Lives_Address

Presto!

You can do it! It really is that easy. I haven't done a SRAM hack yet, but I did a whole conversion with Megaman 1, so I have a pretty good idea of how it would be done.

Just make sure you have documentation. If you are serious about doing any kind of NES ASM hacking, get all of the documentation you can get on the NES.

nestech.txt and firebug's mapper document are a must. Also, get 6502.txt. Those give you the opcodes in hexadecimal form, so you can ASM hack in hex. But beware. Some of the opcodes may be wrong in the document. I have found errors in 6502.txt, and in the mapper document.

For instance, in firebug's mapper document, for Mapper 4, where it deals with the mirroring, I found out through a nesdev wiki page that the information was backwards.

Taken from Firebug's Mapper Document
 +-------+   +----------------------------------------------+

¦ $A000 +---¦ xxxxxxxM ¦
+-------+ ¦ ¦ ¦
¦ ¦ ¦
¦ ¦ ¦
¦ +--- Mirroring Select ¦
¦ 0 - Horizontal mirroring ¦
¦ 1 - Vertical mirroring ¦
¦ NOTE: I don't have any confidence in the ¦
¦ accuracy of this information. ¦
+----------------------------------------------+
I found out that the Vertical Mirroring is really 0, adn that the Horizontal Mirroring is 1, when I made the latest version of my Mega Man Upgrade Patch.

Anyway NARFNra, I hope this information helps you.

____________________
My YouTube Channel

Drakon
Posted on 02-23-14 01:21 PM (rev. 4 of 02-23-14 01:24 PM) Link | Quote | ID: 155757


Red Paragoomba
Compromised account. Please contact staff for a password reset.
Level: 18

Posts: 13/62
EXP: 29757
Next: 140

Since: 01-26-14
From: Toronto Canada

Last post: 3676 days
Last view: 3359 days
In reply to retrorain instead of updating the sram constantly I just update the sram at certain points, no need to constantly save progress. I didn't load my data on booting, I just hacked the main menu so I could load when a certain menu option is selected (usually a replaced password option since I'm no longer using passwords I can hijack this).

Before doing this stuff I contacted snarfblam and asked him for his suggestion on the easiest way to add sram. He was the one who suggested that I just have one save bank and hijack the main menu password option to be a load option.

Of course how you handle saving and loading is completely up to you, you're writing the code so you can do it however you like.

____________________
http://16bitgamer.forumotion.ca/

RetroRain
Posted on 02-23-14 01:27 PM Link | Quote | ID: 155758


Fuzz Ball
Level: 66

Posts: 708/994
EXP: 2432578
Next: 29273

Since: 09-30-07

Last post: 1907 days
Last view: 929 days
It depends on what you're saving I suppose. I would imagine a game like Super Mario Bros. 3, if you only made it so that the game saves RAM on the map screen, anything you get in the level before you turn the power off would not be saved. But if you had the RAM constantly being checked and saved, you could save things you obtain in a level before turning the power off. I guess it depends on what you are going for. But yeah, I would agree that saving constantly, for the most part, would be too much. But I don't think there is any harm in doing it.

I might be doing a SRAM hack of my own now, thanks to you! Seriously, nice work man!

____________________
My YouTube Channel

Drakon
Posted on 02-23-14 01:28 PM (rev. 6 of 02-23-14 04:00 PM) Link | Quote | ID: 155759


Red Paragoomba
Compromised account. Please contact staff for a password reset.
Level: 18

Posts: 14/62
EXP: 29757
Next: 140

Since: 01-26-14
From: Toronto Canada

Last post: 3676 days
Last view: 3359 days
Posted by RetroRain
It depends on what you're saving I suppose. I would imagine a game like Super Mario Bros. 3, if you only made it so that the game saves RAM on the map screen, anything you get in the level before you turn the power off would not be saved. But if you had the RAM constantly being checked and saved, you could save things you obtain in a level before turning the power off. I guess it depends on what you are going for. But yeah, I would agree that saving constantly, for the most part, would be too much. But I don't think there is any harm in doing it.

I might be doing a SRAM hack of my own now, thanks to you! Seriously, nice work man!


Thanks! I really want to thank snarfblam and infidelity for doing some of the first sram hacks to games that seriously needed it and giving me the idea that this can be done.

How often you save is completely a preference. I prefer my data being backed up when I die or finish a stage, but that's me. I like having the option of resetting the console and going back a little. Heck if you wanted to you could reprogram the game to just update the data you want backed up into the sram address instead of normal ram, no need to make a save and load routine. However then you'd have no control over when the data gets saved or loaded.

____________________
http://16bitgamer.forumotion.ca/

RetroRain
Posted on 02-23-14 01:50 PM Link | Quote | ID: 155760


Fuzz Ball
Level: 66

Posts: 709/994
EXP: 2432578
Next: 29273

Since: 09-30-07

Last post: 1907 days
Last view: 929 days
I already have a SRAM hack in mind that I want to do!

____________________
My YouTube Channel

Chaobomr
Posted on 02-23-14 05:47 PM (rev. 2 of 02-23-14 05:48 PM) Link | Quote | ID: 155761


Buster Beetle
Banned: Spammer takeover?
Level: 45

Posts: 228/467
EXP: 636573
Next: 23591

Since: 05-07-13
From: The dirty south

Last post: 3452 days
Last view: 3451 days
Wouldn't constantly saving be detrimental to the hardware? Such as, if you were using one of those blank carts, wouldn't constant saving wear out the battery? And if it's anything like newer consoles, wouldn't the constant saving corrupt information if you turned it off while the saving was taking place?

____________________
Sorry for the stupidity. That jerk will be dealt with in the most insane way possible.

Drakon
Posted on 02-23-14 06:05 PM (rev. 6 of 02-23-14 06:11 PM) Link | Quote | ID: 155763


Red Paragoomba
Compromised account. Please contact staff for a password reset.
Level: 18

Posts: 15/62
EXP: 29757
Next: 140

Since: 01-26-14
From: Toronto Canada

Last post: 3676 days
Last view: 3359 days
Posted by Chaobomr
Wouldn't constantly saving be detrimental to the hardware? Such as, if you were using one of those blank carts, wouldn't constant saving wear out the battery? And if it's anything like newer consoles, wouldn't the constant saving corrupt information if you turned it off while the saving was taking place?


Nothing would be worn out. I'm fairly certain that when the cartridge is being fed power from the system the battery isn't being drained. It's only when the system is off that the battery keeps the sram chip going. I've been to arcades where they had arcade boards from the 90s with suicide battery systems still running with the original battery because they left the machines on all the time so the batteries were never being drained.

Constant saving won't be "corrupted" if you turn it off when the ram is being updated whatever was written should load fine. This isn't like modern hardware it's a completely different beast, low level, low power consumption and small amounts of info and ultra fast access speeds. All the programming is does in assembly because anything else would be too inefficient and too much of a a space hog. Older cartridge based hardware is basically indestructible compared to today's hardware and it's impossible to corrupt a read only maskrom / eprom / flash chip or these older ram chips. The only thing that could go wrong is if you programmed something wrong which is easy to do if you don't know how to properly push and pull with the stack or how to bankswitch properly.

I find technical documents for assembly programming for these older systems aren't beginner friendly at all I learned what I learned by asking around and doing a lot of reading.

____________________
http://16bitgamer.forumotion.ca/

Chaobomr
Posted on 02-24-14 04:03 AM Link | Quote | ID: 155766


Buster Beetle
Banned: Spammer takeover?
Level: 45

Posts: 229/467
EXP: 636573
Next: 23591

Since: 05-07-13
From: The dirty south

Last post: 3452 days
Last view: 3451 days
Gotta love the NES. Programming it may be a pain in the ass, but is certainly worth it.

____________________
Sorry for the stupidity. That jerk will be dealt with in the most insane way possible.

Drakon
Posted on 02-25-14 12:50 AM (rev. 2 of 02-25-14 12:50 AM) Link | Quote | ID: 155773


Red Paragoomba
Compromised account. Please contact staff for a password reset.
Level: 18

Posts: 16/62
EXP: 29757
Next: 140

Since: 01-26-14
From: Toronto Canada

Last post: 3676 days
Last view: 3359 days
Just cleared the game, works fine start to finish with sram saving. I really don't find nes programming a "pain", just the documentation about it isn't very clear for beginners.

____________________
http://16bitgamer.forumotion.ca/

Chaobomr
Posted on 02-25-14 03:07 AM Link | Quote | ID: 155774


Buster Beetle
Banned: Spammer takeover?
Level: 45

Posts: 230/467
EXP: 636573
Next: 23591

Since: 05-07-13
From: The dirty south

Last post: 3452 days
Last view: 3451 days
Well, this is coming from someone who just started, and has looked at the code without knowing what it all means.

____________________
Sorry for the stupidity. That jerk will be dealt with in the most insane way possible.

Main - ROM Hacking - Fire 'n Ice, with sram saving New thread | New reply

Acmlmboard 2.1+4δ (2023-01-15)
© 2005-2023 Acmlm, blackhole89, Xkeeper et al.

Page rendered in 0.026 seconds. (348KB of memory used)
MySQL - queries: 97, rows: 129/130, time: 0.018 seconds.