News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Kid Icarus, adding SRAM save function  (Read 5903 times)

frsj8112

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Kid Icarus, adding SRAM save function
« on: January 04, 2016, 08:24:27 am »
Hi guys!

I've been away for a while, my family has had me occupied  ;)

One of my favorite NES games is Kid Icarus, but the password system is so tedious to use.
So I wanted to get more in to NES hacking other than text altering.

I've followed some of our forum friends hacks (Retrorain, umaggot) and I do understand the principle of storing information in the $6000-$8FFF RAM range.

I've managed to hijack a routine in the ROM (bank 7, always available in Kid Icarus if I've understood it correctly) and moved it inside a new routine, made by me, just to see if it works.

So everytime I collect a heart that's been left when an enemy has been killed, the heart counter will increase and that value will be stored at $6200. I used $6200 because there seemed to be values written to$6000-$60AC.

And that is now working successfully.

But now I would like to try and load data from SRAM.
I was thinking of hacking the menu after you press start at the title screen. If i push the start button at Continue, how can I then hijack into my load-routine and then start my game with hearts loaded from my SRAM?

Sorry for the newbie questions, but we're all newbs at the beginning right?  ;)

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #1 on: January 04, 2016, 11:16:08 am »
Just a quick fix:  On-cartridge RAM is in range 6000-7FFF (not 8FFF)


For saved games you typically need 2 copies for everything:
1)  The value the game actually uses
2)  The "saved" value

When you save a game, you just copy all of #1's values to #2.  And when you load a game, you copy all of #2's values to #1.

In your case, your continue code would copy the heart value from SRAM to regular RAM, then would just jump to the game's normal starting code.  The only thing to note is that you'll have to jump to AFTER the point where it zero's out the initial heart value.

frsj8112

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #2 on: January 04, 2016, 12:34:27 pm »
Thanks Disch, I missed that about the SRAM range :)


snarfblam

  • Submission Reviewer
  • Hero Member
  • *****
  • Posts: 589
  • CANT HACK METROID
    • View Profile
    • snarfblam
Re: Kid Icarus, adding SRAM save function
« Reply #3 on: January 04, 2016, 06:12:41 pm »
All I did in Metroid + Saving was copy the password to SRAM when a gameover occurred, and copy it back to the password RAM and jump to the routine that decodes it when the player starts. On top of that, you can copy any additional variables to SRAM you see fit and copy them back when the player starts, e.g. I saved the player's health in addition to information encoded in the password.

dACE

  • Sr. Member
  • ****
  • Posts: 353
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #4 on: January 05, 2016, 02:20:59 am »
Now - this is interesting. Kid Icarus is the only physical cartridge I actually still own.

Have you looked anything at the FDS version? It has a zelda-style save feature (if im not misstaken).

Snarfblam: about how many bytes, as an absolute minimum, of custom ASM would you need to allocate space for inside a Rom - to be able to implement a 'simple' password to sram feature (approximately)?

/dACE

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #5 on: January 05, 2016, 11:43:37 am »
Typical copy loop:

Code: [Select]
LDX #length_of_bytes_to_copy - 1
loop:
  lda source, X
  sta dest, X
  dex
  bpl loop  ; only works if copying 128 bytes or less
jmp back_to_original_game_code

Assuming source and dest are 16 bit addresses, that's 14 bytes for a one-way copy.  You'll need 2 (one for saving and one for loading), so that's 28 bytes.

You'd be able to combine both into a single routine by using pointers, but prepping the pointers would take more space than the above code.


Also, the password idea is pretty neat.  I hadn't even considered that.


EDIT:

I suppose you could shave 2 bytes off that code if you RTS out of it rather than JMP back.  =P
« Last Edit: January 05, 2016, 12:29:33 pm by Disch »

frsj8112

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #6 on: January 05, 2016, 02:26:48 pm »
So i'm back again after a while of studying read and writes to RAM and "Password SRAM" :)

I did follow snarfblam's advice do use the password system to dump the "Password SRAM" in between 600D-6027 to the range 610D-6127. And now that data is saved between resets, yay :)

Now to hijack the screen where the password's are entered. I've sorted out the loading from the new range 610D-6127, but i want to skip the password screen entirely.

I'll be back.

January 07, 2016, 04:58:07 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Darn, this hijacking the menu screen to jump into my loading routine was hard!

does anyone of you guru's have any tips on how to do this?
i can see that the RAM values 00B1 and 00B2 are used but then it gets too complicated understand where the password screen is fetched from :/
« Last Edit: January 07, 2016, 04:58:07 pm by frsj8112 »

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #7 on: January 08, 2016, 02:38:07 pm »
My approach here would be:

1)  Go to the continue screen and start inputting a password.  Watch RAM to see where the password is being stored as you input it.

2)  Set a read breakpoint on the first password byte.  Then press start to finish.  The breakpoint will trip as the game analyzes your password.

3)  Find the start of the routine (this is typically where I have a copy of the full game disassembly -- so I can disect it and take notes).

4)  Do the same thing for when the game gives you a password.  Get to such a screen, look at RAM to see where the password is stored.

5)  Set write breakpoint on that area of RAM, then rewind/load state and get the game to show the password again, triggering the breakpoint.

6)  Find the start of the routine



The idea here being... to save the game, you'd change whatever code is calling the #6 routine and change it so instead of actually drawing the password screen, you'd just have it save the password to SRAM.  Then to load the game, you'd change the #3 routine so instead of taking the user to an input screen, it just loads the password from SRAM.


Free space shouldn't be an issue, as you're effectively stripping the entire password display and input screens, so you can wipe all of that code and replace it with your own.  Though you will want to keep the password generation/parsing code in tact.

dACE

  • Sr. Member
  • ****
  • Posts: 353
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #8 on: January 08, 2016, 06:32:14 pm »
Also, regarding space - there is a MMC3 patch for Kid Icarus.
If I understand it correctly - that would free up a heap-load of free space for custom ASM.

/dACE

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #9 on: January 08, 2016, 07:34:51 pm »
Cart before the horse.  There's no point in changing mappers unless you gain something from it.  Replacing the password screen with a simple save mechanism should not require ROM expansion or a mapper change.  If you find yourself needing that, you are doing something very wrong.

Plus, honestly... if you're going to change mappers to make more space for asm hacks, you're better off doing it yourself so you can know what changes are made and what the implications of calling swap routines are.  Slapping on an external patch introduces a bunch of potential compatibility issues.  That patch might be using space that you're using for your asm hacks... or maybe it moves the swap routine around, or maybe it uses some extra area in RAM, etc, etc.  I hold that pre-made mapper hacks are all but worthless.

snarfblam

  • Submission Reviewer
  • Hero Member
  • *****
  • Posts: 589
  • CANT HACK METROID
    • View Profile
    • snarfblam
Re: Kid Icarus, adding SRAM save function
« Reply #10 on: January 09, 2016, 12:47:12 pm »
I hold that pre-made mapper hacks are all but worthless.

If they came with source and documentation, they would at least be usable (though still of questionable benefit). I wonder how many of these mapper hacks do things like safeguard against corrupted register writes and unexpected bank configurations when NMI jumps into the middle of things.

Regarding space, I would think that if you're adding a save feature, you're going to have some stuff that won't be needed anymore. The first thing that comes to mind is nametable data for password display and entry screens. Find that and you easily have enough space for a minimal SRAM hack.

Kea

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #11 on: January 09, 2016, 01:57:41 pm »
People upload mapper hacks without including source+doc? That's missing 90% of the point...

But in general, it's best to work with the original mapper if at all possible. Using a different mapper can complicate your work and introduce new bugs, especially if you're using a mapper patch and don't know what it's actually modifying.

dACE

  • Sr. Member
  • ****
  • Posts: 353
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #12 on: January 09, 2016, 03:29:23 pm »
Yeah - mapper conversion or rom-expansion was a terrible idea for getting more space...

What was I thinking!

FYI - Here is the patch I was referring to:
http://www.romhacking.net/hacks/2455/

I have not downloaded it - but the author is reassuring that: Documentation is included

EDIT

So - I took a look at the documentation and it's not very much.

Still - infidelity (the author) is probably still around if there are any questions about what's been done (and how it has been done).
/dACE
« Last Edit: January 09, 2016, 07:22:18 pm by dACE »

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #13 on: January 09, 2016, 07:24:54 pm »
I just downloaded the patch to look.  Documentation is spotty at best.  He lists a bunch of offsets and what he changed the values to, and tells you where the swap routine is... but there aren't really comments on what any of the changes really do.

I guess it's useful in making sure it doesn't clobber offsets you've already modified, but apart from that you're left just as much in the dark as you would be if you just applied the patch blindly.

People upload mapper hacks without including source+doc?

I don't get why people do it at all.  There have been discussions on this on these boards in the past, and I'll say here what I've said there:  Mapper hacks are completely useless to casual hackers.  The only person that is going to get any use out of a mapper change is someone who is doing heavy code writes and who has a decent understanding of mappers and NES architecture.  And that kind of hacker would not only have no problem doing the mapper hack themselves -- but they'd be better off for it because it would expose them to internal mechanics of the game they're hacking.

I honestly can't fathom how these kinds of hacks would be of use to anyone.

A document?  Sure.  Trace some code and throw it up as a doc, or put it on datacrystal or something.  But I just don't see the value of a patch.

But maybe that's just be being a grouchy old curmudgeon.

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 6861
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #14 on: January 09, 2016, 10:42:34 pm »
Note that when saving/loading a password from SRAM, you'd probably want to avoid an error by adding a checksum to the password itself to ensure a valid password is stored. And maybe if the test fails, load a default "new game" password.
"My watch says 30 chickens" Google, 2018

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #15 on: January 09, 2016, 11:07:37 pm »
Passwords are checksummed already -- that's the mechanic that prevents you from just inputting random garbage and having it launch you into the game.

But yeah, you're right... when loading a game, you'll want to check for a failed password load just in case, and probably jump to new game code as a fallback.

frsj8112

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #16 on: January 12, 2016, 05:49:21 pm »
Ok guys, this is how far I've come with this.

https://youtu.be/hDOA7-xtcmc

The save to sram runs in the same way as the password generator. Which means that the items, arrow strength, amount of hearts etc etc, when you enter a new stage, will be added to the SRAM at $6200.

Then when I reset and choose Continue and the press Start, the values from the $6200 range will be copied over to the range $600D and then re-using the password loading routine to copy those values to the in-game CPU RAM (see the almightyguru document for the value locations).

So I think I'm getting somewhere. But i still need to get rid of the password screen when continuing a game. And when selecting a new game, the same routines are called, so the game loads from SRAM, but starts at the first level, so I need to have some check to see if Im selecting New game or Continue.

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #17 on: January 12, 2016, 06:43:07 pm »
New Game and Continue code should fork at some point -- probably immediately after the 'Start' button is processed from the new game/continue screen.

New Game will have 2 basic steps:
1)  var initialization... resetting hearts to zero, strength to 1, etc)
2)  JMP/JSR to somewhere I'll call "Entry", which is where it actually starts running the game.

Continue will have a different set of steps:
1)  It will draw the password screen
2)  It will have a big routine to get the password input from the user
3)  It will run that input and run it through a password decrypter, which verifies it and converts it to # hearts, life, level, etc
4)  It will JMP/JSR to the same 'Entry' spot that the New Game code jumps to.



You do not want to disrupt anything with the New Game path.  It sounds like you are, so your changes are probably a little screwy.

Instead, you want to hijack the Continue code to completely cut out steps 1 and 2... and replace it with a small routine that copies the password from SRAM to whatever spot the password screen uses to hold the input password.  Then you just let step 3 take over and decrypt the password normally.



The 'Entry' spot shouldn't be too hard to find... as it might be the only point at which the NewGame/Continue code rejoins after forking.

frsj8112

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #18 on: January 18, 2016, 06:53:49 pm »
Hi again, I've corrected the issues with selecting New game and SRAM being loaded.

Also I've followed your advice Disch and I managed to find where to hijack the menu, so that when selecting Continue, the game loads the values from SRAM and then bypasses the password screen and starts up the game.

Now i only have to tackle the Game over screen, so it skips the zero's and says like:
GAME SAVED
PRESS START TO CONTINUE

Video to see the current result: https://youtu.be/DOPzZdyE2qk

Disch

  • Hero Member
  • *****
  • Posts: 2713
  • NES Junkie
    • View Profile
Re: Kid Icarus, adding SRAM save function
« Reply #19 on: January 18, 2016, 08:47:03 pm »
Now i only have to tackle the Game over screen, so it skips the zero's and says like:
GAME SAVED
PRESS START TO CONTINUE

Text changes are pretty straightforward.

As for removing the password display --- that's as simple as NOP'ing out a JSR.  When the game draws this screen it's almost certainly doing a JSR to a routine that writes the password to the display.  NOP that JSR out and you'll prevent it from drawing it.

1)  Save a state just before dying
2)  Die
3)  At the game-over screen, fire up the PPU editor and hover over the first '0' in the password to see what PPU address it's located at
4)  Set a write breakpoint at that address in PPU memory
5)  Load state
6)  Die again
7)  Breakpoint should trigger exactly twice:  Once for when the game clears the screen, and again for when it draws the password.  (but you might want to repeat steps 5-7 until you know it's drawing the password)
8 )  Trace the code that leads to that breakpoint (you can use FCEUX's trace logger) to find the JSR you're interested in.