1nvader [V1.0]

I guess this is my fault for not going through and fully testing all of the possible EEPROM collisions, this was a project that I tried to start/take on several times but to exhaustively search each game… basically there weren’t enough complaints about it to take the time. So I apologize for that.

But if we can at least do some bug fixes on this and we have a more cleanly working flash cart, I’m happy to promote updating to the latest cart.

It’s something that will likely need to happen after this next game jam as we hope to have at least a few new games that support working on the FX chip.

1 Like

There was some group effort on this. My plan was to make a heat map to indicate where the most issues were.
I thought @Mr.Blinky came up with a nice way to ‘hack’ the EEPROM start/end address into an unused portion of the hex, so that the bootloader could manage EEPROM?
Update: The suggested magic is here.

The best way to save/load to/from the EEPROM is to use an intermediate library, which would be like a file system on the unique identifiers of each game would automatically create a dynamically needed block specifically for the game on the EEPROM for saving/loading.
The only problem is that the EEPROM is quite limited, and some games save quite a lot of data and there just may not be enough for all of the games.
Such “file system in EEPROM” is implemented in Pokitto files PokittoCookie.h/cpp) as far as I understand

It probably wouldn’t be a good idea.

The Pokitto has 4KB of EEPROM.
The Arduboy has only 1KB of EEPROM.

(And to be honest the ‘cookie system’ has always been a bit weird.)

There’s a lot of problems with this (flash wear, memory fragmentation), but the biggest is that EEPROM is only 1KB so the overhead involved would take away a lot of usable data.

You’d also have to retrofit it onto existing games.

Ultimately it would be a lot less effort to just save the entire EEPROM onto the FX chip, regardless of who/what is doing the saving.


If the FX data had included a list of the games that were most recently loaded, it would have been possible to detect when a collision would occur because game entries on the FX are supposed to include the range of EEPROM data that they occupy. (At least, I think they are from what I remember.)

In what way?

I find it works perfectly well.

I haven’t seen that.

This does seem full-proof. No one is going to invest the time to go back and fix all the games that exist.

If only people where interested in maintaining semi official EEPROM table

Yes a flash (erasable) block is 4K minimum so it could fit 4 copies of the entire EEPROM. basically each byte could be stored as 4 bytes that are xored together to allow 4 (0 to 1 bit) changes before the whole block needs to be erased. So a total of 8K of FX data is required for emulation. I wonder if I could cook up a EEPROM emulation patch for games that make use of the above… Sorry just thinking out loud.

  • Using EEPROM to save games when the console has an SD slot is an odd choice to begin with
    • If speed is an issue, a hybrid approach would work better
    • Lack of memory is a fairer argument
  • The documentation that actually explains how it works is buried halfway down a thread (and possibly an outdated draft?)
  • Various implementation oddities
    • It relies on inheritance instead of simply allowing the user to save an arbitrary object (or array of objects)
    • In several cases the interface ints instead of some kind of status enum (or a simple bool)
  • In general it just gives me the nagging feeling that there’s a more efficient way of doing it

There is an EEPROM start and EEPROM end field in the game header.


I started helping, then got sidetracked as per usual. :P

Even if people simply started mentioning these things on their GitHub repos/forum posts it would help a lot.

Anyway, my point was that given a list of games that had been loaded from the FX onto the Arduboy, combined with the EEPROM start and end values in the game headers, you could build a map (a 128 byte bit vector) of occupied EEPROM bytes and detect collisions, thus identifying when a backup is needed.

But that’s probably not practical because of the memory required to maintain the ‘load list’.

I know what you’re thinking of, and I think it would work well, but I think the way you’ve glossed over the details is going to give people the wrong impression (i.e. that the block has to be erased after every fourth write) because A) the erase only needs to happen when a single byte is overwritten four times (i.e. you can have more than four writes if you’re writing to different fields/bytes) and B) you don’t necessarily have to move to a new byte every time because if a previously unchanged bit has changed you may only need to toggle that bit.

(Even after hitting four bytes it’s probably possible to get some extra life out of them with some clever bit flipping, but the code might be too complex to be worth it.)

Now I’m thinking about whether something like Gray code would be more efficient.
Writing numbers to the FX in a way that minimises writes (even at the cost of space) is something I’ve been meaning to look into.

A while back @MLXXXp mentioned the idea of introducing an EEPROM library that had a commit() function to support systems that don’t have EEPROM and have to ‘fake’ it with flash memory (or file systems).

If we had such a system, commit() could possibly have been adapted to save a copy of EEPROM to the FX.

Unfortunately it would be a lot of effort to back-patch into all the existing games.

Guys, im sorry again, but Im not meant to enjoy my Arduboy hahahah… I run into another problem. I was playing a game called “Space Battle” and then it suddenly randomly crashed, I think maybe because I was running out of battery maybe… so then I decided to flash the latest cart builder, and now when I try to play this game It doesn’t even open anymore. it stays in the loading page… so Ill try to flash it again to see if it solves the problem. ill attach photo of where the game crashes.

There are some tools you can use that will allow you to save or back up your EEPROM.

Flashing the cart wouldn’t fix this you’ll need to erase the EEPROM too which, will risk destroying your save data but will also be necessary if you want a full erase.

I hope the quick changes I made to 1nvader haven’t caused this. If you play other games does it work?

I did so many changes yesterday to this game, OBS and other games yesterday that I might have easily copied the 8BitCadeXL into the Arduboy directory on the server.

If so I apologise in advance :grinning:

Hi,

I dl’ed from github (the zip) and loaded that into my windows arduino ide.
So the path is: github (main) → windows ide → sketchbook->compile → upload.
It’s hangs my arduboy (from 2017, bought off amazon).
I’ve loaded it several ways. The last was what I believe is called the flashlight method.
Up arrow/turn on. Uploads … then a blank screen. If I power cycle I get what appears to be random lite pixels.
Any ideas please?

Thanks,
Mike

End of output below:

Summary

Writing | ################################################## | 100% 1.91s

avrdude: 24898 bytes of flash written
avrdude: verifying flash memory against C:\Users\string\AppData\Local\Temp\arduino_build_181111/Invader.ino.hex:
avrdude: load data flash data from input file C:\Users\string\AppData\Local\Temp\arduino_build_181111/Invader.ino.hex:
avrdude: input file C:\Users\string\AppData\Local\Temp\arduino_build_181111/Invader.ino.hex contains 24898 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.23s

avrdude: verifying …
avrdude: 24898 bytes of flash verified

avrdude done. Thank you.

Is ok… full erase means that all high scores are going to be erased and thats all right? or is anything else is going to be missing

It still didnt work with other games… Even after flashing it and play it straight, still got that loading page… but ill try to flash it again soon. thanks!

It sounds like my code ., sorry.

It didn’t open on the navigator either. And don’t worry!!! It must be confusing with dealing with al these codes so I completely understand :smiley:

No problem!
Thanks for your effort, I appreciate it.
I’ll check back at another time, I would like to try it, looks cool.
Mike

1 Like

Ahhhh … what mess I have made!

No worries my friend… Thats why the community is for, for everyone to pitch in and help each other.

The cookie system is for managing the EEPROM - if you are using the SD card to store game state then you manage your own file. There is no risk of conflicts between different games unless someone uses the same file name.

That is my complaint about the Pokitto overall.

It could have been done differently but the initialisation routine allocates enough EEPROM to accommodate the cookie - this might be a single or multiple blocks. Allowing the user to arbitrarily save things could lead to issues with exceeding the size.

1 Like

Which is precisely why, unless there’s a particular speed or size issue or a need for random access, I think using EEPROM when there’s a file system available would be an odd design choice.

Too true.

I’m not saying users should be allowed to save wherever they want, I’m saying they should be allowed to save whatever they want without figuring out how to stuff it into a class. To reserve N bytes and then do with those bytes whatever they choose.

For example:

// The returned object would be a struct specifying
// whether the operation was successful and
// exactly how many bytes were allocated
auto allocation = system.reserve(gameIdentifier, amountOfBytes);

if(isError(allocation.status))
{
	// Handle error
	return;
}

auto writeStatus = system.write(offset, anyValidObject);

if(isError(writeStatus))
{
	// Handle error
	return;
}

// If the code has reached here,
// object was written successfully

Thus you could do things like writing an array of bytes without needing to stuff the array into a class/struct first, and writing a variable amount of data (e.g. writing just the high score entry that has changed) instead of writing (or attempting to write) an entire fixed size chunk (i.e. the entire inheriting class) every time.