Saving on NES homebrew

From Pin Eight
Jump to: navigation, search

Saving to flash

The ordinary way to save on NES homebrew is to write to 8 KiB of battery-backed SRAM mapped at $6000-$7FFF. But since the NES days, the price of flash appears to have fallen below the price of nonvolatile RAM. So it appears the target hardware for any new low-volume commercial NES game that can save is something similar to SUROM (MMC1 + CHR RAM + PRG RAM) without battery. So the machine has 10 KiB of RAM, but the 29F040 storage medium has eight 64 KiB sectors: four for the game and four for the save. Some flash has smaller sectors, such as the SST39SF series with 4 KiB sectors.

Erasing a sector erases the whole thing to $FF, but any byte that is still $FF can apparently be written to a byte at a time. This allows appending to a sector, which suggests treating several sectors as a circular buffer containing a log-structured file system. A file is considered superseded when a file with the same name follows it in the circular buffer. When all but one of the sectors fill up, all not-superseded files in the tail sector get copied to the head and then erased. To make sure we don't erase all the time and wear out the flash, we only let the user save enough files to fill half the sectors. Then when the user saves enough files to fill those, the user has to delete some files first.

Implementing such a file system becomes an engineering exercise.

  1. Prototype the algorithms in Python or another high-level language
  2. Translate to 6502 using 2 KiB sectors in an 8 KiB SRAM
  3. Extend the 6502 version to 8 KiB sectors in a 32 KiB SRAM on a SXROM-clone or an FME-7 big RAM board
  4. Figure out how to write to the flash itself, including how to erase a sector, how to program a byte, and how to keep the flash from interpreting flash writes as bank switches
  5. Combine steps 3 and 4

Password save

An 8-character password saves up to 32 bits of game state, as seen in this demo. A fairly railroaded action RPG might split it up as follows:[1]

  • Money (8 bits) nonlinear, possibly quadratic
  • Experience (8 bits)
    • May be divided into 5 bits for character level and 3 bits for fraction of experience needed for the next level
  • Weapon (4 bits)
  • Chapter (4 bits)
  • Event flags for this chapter (8 bits)