The game stores the current number of saves in 0x03006200 and does a mod 2 on it to figure out if the current save is in slot 0 or 1. I modified those calculations to always select slot 0, even though I'm not entirely sure what some of the functions are used for.
1x @ 0xD98B0 -> Always select the first save slot when determining the slot to write to.
1x @ 0xD9B90 -> Always select the first save slot in this undetermined function.
1x @ 0xD9D28 -> Always select the first save slot in this undetermined function.
1x @ 0xD9DC0 -> Always select the first save slot in this undetermined function.
1x @ 0xD9E76 -> Always select the first save slot in this undetermined function.
On game init, the game reads both save slots, determines which of them are valid and which one is newer then the other (via the save counter).
5x @ 0xD9FD4 -> The read of the second save slot has been replaced to always report that the second slot is the same validity as the first slot (so you still get correct system messages for corruption and stuff), and that the second slot is always one save older than the first slot, so the game will never pick it when deciding which slot to load.
2 * 48 bytes @ 0xD9FDB -> The second save slot read code that is now skipped over has been repurposed as storage for two extra flash chip identification structures.
After the Elite 4, the game calls a special function to save the game and record the current team in the Hall of Fame. Normally, the Hall of Fame occupies two sectors of flash memory, 0x1C and 0x1D, and stores a maximum of 50 teams. With a 512K flash, we only have two spare sectors for extra data, and we still need a place to hold the recorded battles from the Battle Frontier, so I've modified the Hall of Fame reads and writes to only store 32 teams and only use one flash sector, 0x0E.
1x @ 0xDA29C, 2x @ 0xDA2AE -> When Hall of Fame data has to be erased for whatever reason, only erase sector 0xE.
1x @ 0xDA2CA -> Save the first half of the Hall of Fame to sector 0xE instead of 0x1C.
2x @ 0xDA2D0 -> Remove the write to sector 0x1D. By limiting the Hall of Fame to 32 teams, the second half is always empty and doesn't need to be written.
1x @ 0xDA338, 2x @ 0xDA34A -> Again, when Hall of Fame data has to be erased for whatever reason, only erase sector 0xE.
1x @ 0xDA56E -> Load the first half of the Hall of Fame from sector 0xE instead of 0x1C.
7x @ 0xDA580 -> memset the second half of the Hall of Fame to 0 instead of reading it from sector 0x1D.
The Battle Frontier battle recording usually saves to sector 0x1F. I remapped it to sector 0xF.
2x @ 0xDA5AC -> This seems like a sanity check that determines if the requested sector is either 0x1E or 0x1F and returns from the function with failure if it's not. Since 0xF is outside that range, I modified the check to just check for sector 0xF.
2x @ 0xDA604 -> Same sanity check.
1x @ 0xF21F6 -> Change the maximum amount of saved hall of fame records from 50 to 32.
1x @ 0xF2204 -> Same as above.
1x @ 0xF2B84 -> Change the maximum amount of loaded hall of fame records from 50 to 32.
1x @ 0xF2B92 -> Same as above.
1x @ 0xF2BBC -> Same as above.
Functions that directly access Flash memory:
11x @ 0x1DE894 -> Completely rewrite SwitchFlashBank. It now does nothing if bank 0 is selected, but hangs the game when a higher bank is selected, so we can figure out if we missed a place where the save file is accessed. This also serves as a protection for writes that would hit flash bank 1, since on devices/emulators that don't understand flash banks they would hit bank 0 and corrupt the data in it.
1x @ 0x1DEB2C, 1x @ 0x1DEB30 -> ReadFlash checks for a 1M Flash size before calling SwitchFlashBank. This check has been modified so that SwitchFlashBank is called for effectively all flash sizes.
1x @ 0x1DEBF4, 1x @ 0x1DEBF8 -> Same as above for VerifyFlashSector.
1x @ 0x1DEC80, 1x @ 0x1DEC84 -> Same as above for VerifyFlashSectorNBytes.
Note that the Program and Erase functions always call SwitchFlashBank regardless of Flash size, probably because they're supposed to be flash type specific.
String @ 0x6FBF74 -> Change the Flash identification string to claim a 512K flash (I suspect these are unused on actual hardware, but some emulators use them to detect save type).
*Not Ported from Emerald Version*
-V1.0
1x @ 0x152E1E -> Always select the first save slot in this undetermined function.
1x @ 0x15359A -> Always select the first save slot in this undetermined function.
1x @ 0x1795D2 (Possibly 0xF55CE?) -> Modify function that (re?)initializes the entire save file to only write to 0x10 sectors we now have instead of the 0x20 sectors we had.
1x @ 0x18531C -> Write to sector 0xF instead of 0x1F for the Battle Frontier's battle recording.
1x @ 0x185A58 -> Read from sector 0xF instead of 0x1F for the Battle Frontier's battle recording.
2x @ 0x1D3A92 -> If, somehow, the Trainer Hill save write function is ever called, don't call the flash write function and just claim the write failed.
2x @ 0x1D3AE0 -> Likewise, if the Trainer Hill save read function is called, don't call the flash read and just claim the read failed. This function is actually still called when Trainer Hill starts in the English version, but doesn't seem to do anything.
-V1.1
32 bit pointer @ 0x2E1D84 -> Change pointer to the location of the array of flash chip identification structures in IdentifyFlash to a new, bigger one.
5x @ 0x2E1D8C -> Change the loop that identifies the flash chip the hardware reported so it reports failure once it encounters a nullptr, rather than reporting a failure once it finds a flash chip structure with an ID of zero.
32 bit pointer @ 0x9A30DC -> Change pointer to the location of the array of flash chip identification structures in IdentifyFlash to a new, bigger one.
1 byte @ 0x9A3166, 1 byte @ 0x9A316E, 2 bytes @ 0x9A3178 -> Modify the fallback flash chip identification structure to another valid one.
24 bytes @ 0x9A31A0 -> This space is now used as a bigger array of pointers to flash chip identification structures, as the original was just 3 entries large. The original array at 0x9A30D0 is still there unmodified, but now unused, and could be repurposed if the need arises for a little bit of extra memory.
The six entries are, in order:
- Pointer to 0x8152F88, data for the SST 512K flash chip. (was instructions for read of second save slot)
- Pointer to 0x8152FB8, data for the Macronix 512K flash chip. (was instructions for read of second save slot)
- Pointer to 0x89A314C, data for the Panasonic 512K flash chip. (was fallback structure)
- Pointer to 0x89A311C, data for the Macronix 1M flash chip. (unchanged from original game)
- Pointer to 0x89A31C8, data for the Sanyo 1M flash chip. (effectively unchanged from original game)
- Null pointer to indicate end of array.