Communicating EEPROM usage / collisions

Lol is this published somewhere else, is this new?

Is there some way to mark if a game has been “audited” yet? or is there some procedure for how to go through and do these?

I think if we made a checkbox or better yet, a sign off for who did the audit completed as well as a real rough “how to” or best practices, only hast to be a few sentences then we could crowdsource this… happy to start digging in myself.

That was the idea in July 2020. We discussed it! :stuck_out_tongue_winking_eye:
See: Arduboy Semi-Official EEPROM Table

It’s been a long few years. So in total Arduboy games use somewhere between 13-14kb in EEPROM?

That’s like, 13-14 times too many. I need to see the problem, gonna try and visualize the findings lol.

Ok I filtered out games that used more than 200 bytes, bringing it down to an almost reasonable 3.2kb over 120 games.

Here are the large games, I see Microcity is in there twice?

Next step will be to add another dimension, and that is the games ranking (number of likes and a few other factors) to look at which of the “favorites” have collision, because if we want to distribute a “collision free” version of the cart some games will have to be trimmed. And I suppose then you could do like A and B (… and C) sides to the cart.

Boris goes skiing, Midnight Wild, and Ardubullets seem to be pretty safe lol.

1 Like

The EEPROM frontier (Meta post)


For any newcomers, a brief history on the topic of EEPROM collisions ~

It’s a near annual topic and I may have missed some relevant posts.

Other discussions

There are plenty more useful discussions too ~
  1. EEPROM backup and restore to PC (with Python) or Android.
  2. EEPROM viewers /editors that run on the Arduboy: One and Two.
  3. Reminder that the EEPROM has a limited life time (100,000 writes).
  4. Adding EEPROM start and end addresses to .arduboy files. Discussion and JSON.
  5. Best coding practices, including checksums and using struct’s.
  6. Abandoned ideas: creating a PC backup format for EEPROM data; Modified boot loader, to allow game saves to be stored in program flash memory space (not EEPROM).
  7. Storing EEPROM metadata in ‘Reserved’ program memory vector area, for use by the FX chip and firmware.

To date, most efforts have been targeted at programmers, to standardise how EEPROM is used, etc. This hasn’t worked and it’s not a problem I’m trying to solve here(!)… I think @Pharap has posted some nice code for best practice and it’d be great if functions were added to Arduboy2 lib.

This effort is focussed on the non-technical, end user: How can we most simply communicate (the chance) that two games may collide?..

Sounds nice. But as @Mr.Blinky hasn’t proposed it- guess it’s not practical, and it doesn’t help owners of the OG units.

I think that was the original 2015 idea. It only needs one program to wreck it, so we have to accept it’s the wild-west frontier of bytes! Each program needs to validate its own data and have little expectations for its preservation.

Quite right! Thank you - I’ve been staring at hexadecimal too long and forgot decimal was an option! :nerd_face: :flushed: I changed my original post (currently hidden) based on your comments.

I’m not attached to ‘Saves’ or ‘Slots’ naming (I think I prefer ‘Blocks’). Not sure about ‘Save data’ :thinking:

This is system wide (not game specific). We don’t need to manage it.

True. It’s still a useful first indicator that there may be a problem. In time programs may migrate to these slot boundaries(?). It’s also true two games using exactly the same EEPROM addresses may not collide: one game may simply not save! All we are communicating is some risk of overwriting save data. Note: The original 2015 proposal used blocks of 16 bytes, so we don’t lose much going to 32 bytes.

True. Good point. I saw this as just a simple first step. Most of us have ~5 favourite games, that we’re likely to swap back and forth between. If one of them is glitchy, I’d look at the forum posts for the 5, and see two using ‘slot C’, which indicates a problem.

On your cart builder, saves slots could be indicated to the user when you are selecting hex files. I’d imagine you’d store actual EEPROM locations in your database for each application. Then at compile time (or earlier), warn the user of collisions?

Getting and maintaining EEPROM addresses is a huge task. It makes sense to put that responsibility on the authors. Hence the idea of a badge system to encourage this behaviour. I think it looks fun / kinda gamification of this essential metadata.

That sounds great. :fire:

Who would be nerdy enough to tweak other people’s code and raise hundreds of PR’s…? :innocent:

Yes. As a separate endeavour, it would be nice if this could be a standard function of the library.

A recent real-world example. The user had 5 favourite games, so knew the issue was between them…
Look at the following, quickly scanning your eyes over the details. What is the simplest and fastest indicator?

EEPROM hexadecimal addresses:
  • - 1nvader (PPOT).
  • - Hollow Seeker (Obono).
  • - Hopper (Obono).
  • - Sirene (Team ARG).
  • - Space Cab (PPOT).

EEPROM decimal addresses:
  • - 1nvader (PPOT).
  • - Hollow Seeker (Obono).
  • - Hopper (Obono).
  • - Sirene (Team ARG).
  • - Space Cab (PPOT).

Save slots:
  • - 1nvader (PPOT).
  • - Hollow Seeker (Obono).
  • - Hopper (Obono).
  • - Sirene (Team ARG).
  • - Space Cab (PPOT).

(Note: Obono’s games use 32 bytes but are not aligned with slot boundaries. They currently occupy X‒Y and Y‒Z).

  • Hexadecimal (:face_with_monocle:)
  • Decimal (:open_hands:)
  • Alphabetic (:capital_abcd:)

0 voters

Simple method using a spreadsheet to determine the ‘slot’ / ‘block’:

 = CHAR( INT((address-16)/32) +65)

So block 0 (system reserved) gives ‘@’. Obviously, need to make sure it returns something sensible between AZ.

Honestly, I think if I turned my graph into javascript you could type in your game and it would list off other games that collide and also show it visually with horizontal shading.

EEPROM management is dead! Long live EEPROM management!

I mean, basically I realized early on it was a mixture of apathy from the developers combined with the fact we probably would run out of space anyways and always deal with collisions. Documentation was the part I really missed.

1 Like

It hasn’t ‘worked’ because it’s not a solvable problem.
You’re looking at a pigeonhole problem - trying to fit several KB of data into a 1KB block simply can’t be done.

The goal of picking different addresses was never really to avoid treading on other game’s data because that’s unavoidable.

The goal was to reduce wear on the EEPROM. If everyone started writing their game data at the first non-reserved byte then that block would wear out quicker than every other block. I.e. the intent of spreading the data is more about wear levelling than preventing collisions.

As @bateske says, the real issue has always been that people haven’t been in the habit of documenting the EEPROM range their game uses.

There could be a system that dynamically allocated ‘blocks’ to games when requested, which would solve the issue of knowing when there isn’t enough room to save more data, but aside from the issue of added complexity, such a system would only work if every game used it. Hence you still end up back at the square one problem of documentation - documenting which games use the ‘safety system’ and which just write data to an arbitrary block.

That’s why I’m reluctant to even attempt considering such a system - it would be a lot of work for something that’s only a partial solution

@Mr.Blinky’s idea of adding backup & restore functionality to the FX bootloader is more practical because it would automatically work for all games. The only real downside to it is the added wear to the EEPROM (which could be mitigated by making it optional and/or only affecting the area that the game header claims to use).

There’s also the difficulty of updating the bootloaders, but at least that would be targeting the people for whom the collisions are a problem rather than trying to target every published game.

@Mr.Blinky’s Python scripts already include a script that can read the contents of the Arduboy’s EEPROM and write them to a file. It might not be as fine-grained as what this thread was proposing, but as long as the user is careful to give thier files decent names it would work.

The only real advantages of something more fine-grained would be wear levelling and possibly ease of use.

Out of these options, decimal, followed by hex.
The letter system omits vital information and, as pointed out by others, can lead to false negatives.

Considering other options, the best option would be to somehow make the cart-building software do the detection and warn the user:

This is what we really need: data + tooling.

For now what would probably be most useful is to try to stuff the game names and EEPROM offsets into some machine-readable format (e.g. CSV, JSON) to make it easy to create tools to analyse it.

To this effect, at least the awareness raised by the multiple posts has been enough so that naturally people seem to have spread their games out.

I mean, at least we aren’t dealing with a nightmare situation where everyone has started at address 0. (which I think is reserved? aren’t people supposted to start at 16?)

A tool that also allows users to submit their game data would be great, but without building some kind of usermodel it is kind of a pain to do.

Fancy way might be to allow a community post where you could write it out and then an api could pull it.

But probably it will need to be actively managed and people can email when it needs an update…

Or it could just be a public csv and allow open edits?

The user-permitted addresses start at 16 because the first 16 bytes (0-15) are reserved, but users aren’t supposed to start there because of the wear levelling issue - if everyone starts at 16, the first block of memory would wear out faster than all the rest.

The problem with making it a single thread is that threads lock after 500 posts.

A better way would be to pull all threads from a specific category (i.e. #games and #games:demos ), or if a thread tagging system were enabled there could be a specific tag that registers a thread for cataloguing.

It would probably be easier to do via GitHub because GitHub has ‘webhooks’ for when repos are updated, but not everyone uses GitHub.

If it were hosted on GitHub then that might work, especially since that would potentially allow the option of having a server auto-update using webhooks.

I’d say avoid CSV for something that people are going to be editing though, because it’s positional rather than named, which makes spotting mistakes and validating the information much more awkward.

Either JSON, XML or something like recfiles would be best, but anything with key-value pairs would work.

Sure I mean we could build an entire framework in sql and develop a react server… battery backup… AI powered… triangulated space satellites. Orbital confirmation network. Sure only take 15 minutes crank that out.

Let’s see how the game jam goes, if it’s a big hit I’ll put a bounty on making a solution to the EEPROM.

I thought the idea was to make it easier to understand. If you ask x out of n users about what EEPROM is and what a savegame is, I’m pretty sure the savegame is better understood.

maybe I misunderstood something. I thought the idea was to document collisions for people to understand. But you’re talking about managin (future) EEPROM ?

I had some ideas for a simple dynamic EEPROM system but the semi-official-eeprom-list showed it couldn’t prevent collisions. Such a system could still reduce EEPROM wear but I don’t really see that as a problem.

Yes, each time you change a game that uses EEPROM, the EEPROM would be restored. But I don’t think it would be really a issue as EEPROM can be rewritten 10 times more than a program can be flashed.

A more wear reducing method that I recently thought up is to patch a game with EEPROM emulation so the FX chip is used instead of EEPROM. This would only work for games stored on FX chip though.

The advantage over the backup/restore method is less EEPROM wear and the bootloader doesn’t need to be updated.

I’ve looked a bit more into the possability of patching games for EEPROM emulation and found out the EEPROM library uses the avr libc eeprom functions and those where created from assembly source files meaning the code will be the same and can be located easily for patching. a EEPROM emulator can also be appended to the game code as there is additional PROGMEM space available because of the Cathy3K bootloader and if there wouldn’t be any space in a worst case scenario. Well then at least the number of collisions with other games has been reduced :slight_smile:

I’m pretty confident a EEPROM emulator is feasible. Maybe something to work on during the upcomming jam…? :wink:

BTW @MLXXXp I recommend to replace with eeprom_read_byte and EEPROM.update with eeprom_update_byte in the Arduboy2 library. These changes can save 18 bytes.

Now you’re talking :money_mouth_face:

1 Like

That would depend on how the allocations happen.

Most allocation systems start at the earliest available memory and work their way forward, and in this case that would lead to earlier blocks being written to more often than later blocks.

To avoid that there would have to be some way of ensuring that allocations spread the wear across the whole address range rather than bunching up around particular areas (or at least in a way that minimises reusing the same areas continually).

That’s also why a file allocation table style system is bad - the table is going to be overwritten more than most other areas.

It would depend on how people use them.

I was under the impression most people are more likely to play the same game long enough for end up with multiple highscores/saves before switching, but I can only really speculate on what people do.

Yes, you mentioned. In terms of doing that via a library it would be a good idea, but I’m not sure how well patching a binary after the fact would work.

Overwriting the eeprom writing instructions with jumps/calls to the new FX-manipulating code probably isn’t too difficult, but surely you’d have to make sure the replacement is equivalent, and you’d have to find an area of progmem that is currently unused?
(That’s probably easier if you’ve got the .elf file than just the .hex file.)

That only solves things for FX units though, not the earlier units.

Surely for earlier units, that could be a problem because it would be attempting to overwrite progmem in use by the bootloader?

I presume you mean internally?
If so, yes, that will be a saving
I stumbled upon this quite a while back and forgot about it - I did the same thing to one of my games at some point.
(I think I mentioned it to Filmote at the time, but I can’t remember if I mentioned it to MLXXXp.)

Arduino’s EEPROM library is quite overengineered for how most people use it (EERef and EEPtr are overkill), and it’s a bit too self-reliant to play well with the optimiser.

All they really needed was a template function that calls eeprom_read_byte/eeprom_read_block and eeprom_update_byte/eeprom_update_block with the appropriate pointer cast and sizeof(T) - i.e. equivalents of get and put with simpler implementations.

EEPROM emulation (and EEPROM backup/restore also) wouldn’t work for the older units as there is no extra memory available. the Patching process would be done by the flash/cart builder tool. so patched games will only be part of a flash image.

Yes. based on an empty sketch using arduboy2::begin();

yes, the line

EERef &update( uint8_t in )          { return  in != *this ? *this = in : *this; }

effectively uses eeprom_read_byte and eeprom_write_byte where they should have made use of the existing eeprom_update_byte function.

1 Like

In that case there’s no issue. I was merely concerned that we might end up with .hex files floating around that would cause problems if someone tried to load them onto an old unit.

Then yes.
I believe the same applies to most games too.

I was envisaging something much simpler that doesn’t involve any patching. Why can’t you simply copy the entire EEPROM to SD when you flash the next game?

That would require a new bootloader with backup and restore feature.

Ah, I see.