MazeRider [PreRelease]


(Scott) #21

If you’re concerned, you could calculate a checksum and save and check it against the data, for a bit more security (along with also setting a “signature” if desired).


(Scott) #22

Correct. Originally, Arduino only provided EEPROM.write, which always writes to EEPROM, even when unnecessary because the value to be written is what was already last saved at that location. EEPROM.update was added later to avoid that situation, thus sometimes speeding things up and saving wear on the EEPROM if you blindly use values to write.

Note that EEPROM.put is also “intelligent”, like EEPROM.update.

I’m sorry but I’m kind of busy, so haven’t spent time analysing some of your more complicated expressions. I’ve just been reporting more obvious things that I’ve seen.

:+1:


#23

That’s fine, its irrelevant if update can tell not to write the same data twice I don’t need to handle that manually.


(Pharap) #24

This is exactly what I did in Minesweeper.

There’s other benefits to using a checksum as well though.
One of the reasons I used a checksum is because it can be used to detect when another game has overwritten your game’s save data.

My implementation is probably a bit overkill for this game because of it’s backwards and forwards compatibility features (and I still need to fix the undefined behaviour) but the checksum approach solves all the problems of the ‘2 byte id’ approach.

Should we ignore the syntax errors?

Sylistically mixing unsigned char and uint8_t is a bad idea.
On the Arduboy they are implemented the same but they actually have different semantics.

uint8_t means “this absolutely must be 8 bits”.
unsigned char means “the smallest addressable unit of memory”.

If in doubt, pretend unsigned char is actually 9 bits (or 10 bits, or 16 bits etc.) rather than 8 bits,
and then ask yourself if the code is still correct.

Also look at what the function actually returns (EEPROM.read returns a uint8_t).

(Also using macro case for anything other than macros is probably a bad idea.)

Yes, but possibly not like that.
Assuming you have an array of uint8_t called array:

EEPROM.update(address + (index * sizeof(array[0])), array[index]);

(Technically the sizeof(array[0]) part isn’t strictly necessary because it should be 1 if your array is an array of uint8_t, but it’s good practise to ‘say what you mean’ and it will be optimised away anyway.)

Personally I try to avoid the EEPROM class and use the eeprom_update_x and eeprom_read_x functions because I’ve found it results in less progmem usage in some situations.

I even wrote my own handy eeprom functions to make it easier to use.
(E.g. it’s possible to do Eeprom::update(address, array) and have the whole array handled without needing sizeof.)

avr-libc has (as far as I’m aware) always provided eeprom_update_byte (et al).

As far as I’m aware EEPROM has never actually been needed,
it’s just a wrapper that introduces (in my opinion) too much indirection and clutter.

Not to say that a wrapper couldn’t be useful,
but the EEPROM library is a very flawed implementation.


(Scott) #25

I suspect that Arduino provides the EEPROM class as an attempt to make EEPROM functions standard across various processor architectures. There no guarantee that the EEPROM functions in avr-libc will be available for other Arduino supported processors.


(Pharap) #26

Had the EEPROMClass class not existed,
all the other architectures would have had to do is implement the missing functions from avr-libc.

There’s only a handful of functions from avr-libc that are surplus to what an implementation of the C standard library would have.
(I say that from experience - I’ve reimplemented almost all of avr-libc for the Pokitto.)