I don’t entirely understand how the keys and the crumbs join up.
Having 48 keys in the key table but 128 crumbs in the crumb table seems a bit odd.
What are the values in the crumb table?
A key index?
In terms of implementation I think a template could possibly work better than inheritance.
class SaveData
{
public:
int highScore;
};
Cookie<SaveData> cookie = Pokitto::acquireCookie<SaveData>("ASTEROCK");
I assume the writing is going to be something along the lines of:
template< typename Type >
class Cookie
{
private:
std::uint32_t address;
Type type;
public:
void write(void)
{
const char * data = reinterpret_cast<const char *>(&type);
write_eeprom(address, data, sizeof(Type));
}
};
As for the other bits:
(For the sake of argument, ignore access modifiers).
class SaveKey
{
constexpr const std::size_t bytesPerKey = 8;
uint8_t values[bytesPerKey];
};
class SaveCrumb
{
uint8_t value;
uint8_t getValue(void) const
{
return (this->value & 0x7F);
}
};
class SaveHeader
{
constexpr const std::size_t keyCount = 48;
constexpr const std::size_t crumbCount = 128;
SaveKey keyTable[keyCount];
SaveCrumb crumbTable[crumbCount];
};
The only outright complaint I have about that system is the name ‘crumb’.
All I can imagine from ‘crumb’ is a small piece of bread, which I don’t think makes a very good analogy.
Something like ‘block’ or ‘chunk’ would work better.
Otherwise it mostly sounds good (though I’m still not sure how the key-crumb relationship works.)
For what it’s worth, I was working on a similar idea earlier.
I’ll pitch it anyway in case there are aspects of both ideas that could be good:
- EEPROM is divided into 32 byte ‘blocks’
- An allocated block has a 16 byte heading (of which 9 bytes are used.*)
- Each allocated block has a header consisting of:
- A
checksum
field (4 byte/32 bit)
- The checksum is calculated using all the header data, plus the entire contents of the allocated block(s)
- A
gameid
field (4 byte/32 bit)
- I’m not sure how this would be allocated, but it should be unique per game
- A
size
field (1 byte/8 bit)
- The value is the number of contiguous blocks allocated, e.g. a value of 8 is 8 blocks, which is
32 * 8 = 256
bytes
The blocks can be navigated by examining their size field and using that as the offset to the next block.
The first block (or two) is specifically for Pokitto system use.
Advantages:
- Good use of the available space
- Easy to understand
- Built-in data integrity checking
Disadvantages
- Allocating unique game ids would be hard
- Traversing EEPROM might be slow
- Can only traverse one way
* The remaining 7 are reserved for future modifications. That could be dropped to 12 bytes allocated, 9 used and 3 reserved if need be.
I didn’t get very far with making a code demo though:
#include <cstddef>
#include <cstdint>
namespace BlockSystem
{
constexpr const uint32_t BytesPerBlock = 32;
class SaveId;
class BlockCount;
class SaveBlockSettings;
struct SaveId
{
private:
std::uint32_t value;
public:
constexpr SaveId(uint32_t value)
: value(value)
{
constexpr SaveId(char c0, char c1, char c2, char c3)
: value(c0 << 24 | c1 << 16 | c2 << 8 | c3 << 0)
{
}
SaveId(const char (&data)[4])
{
for(uint32_t i = 0; i < 4; ++i)
{
this->value <<= 8;
this->value |= static_cast<uint8_t>(data[i]);
}
}
operator uint32_t(void)
{
return this->value;
}
};
struct BlockCount
{
private:
std::uint8_t size = 0;
public:
constexpr BlockCount(void) = default;
constexpr BlockCount(uint8_t size) : size(size) {}
std::uint16_t getSizeInBytes(void) const
{
return static_cast<uint16_t>(size) * static_cast<uint16_t>(BytesPerBlock);
}
operator std::uint8_t(void) const
{
return this.size;
}
};
struct SaveBlockSettings
{
public:
std::uint32_t checksum;
SaveId saveId;
BlockCount size;
private:
constexpr const std::size_t targetSpace = 16;
constexpr const std::size_t usedSpace = sizeof(checksum) + sizeof(saveId) + sizeof(size);
constexpr const std::size_t reservedSpace = targetSpace - usedSpace;
static_assert(targetSpace > usedSpace, "Error: SaveBlockHeader usedSpace exceeds targetSpace");
// Pad it out to 16 bytes
std::uint8_t reserved[reservedSpace];
};
}