Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions VortexEngine/src/Modes/Modes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ bool Modes::init()
return true;
#endif
ByteStream headerBuffer;
Storage::read(0, headerBuffer);
// the save header is stored in the global storage space because it
// contains device-wide settings shared by all profiles
Storage::readGlobal(headerBuffer);
unserializeSaveHeader(headerBuffer);
m_loaded = false;
#ifdef VORTEX_LIB
Expand Down Expand Up @@ -145,11 +147,11 @@ bool Modes::saveHeader()
if (!serializeSaveHeader(headerBuffer)) {
return false;
}
// serialize the number of modes
if (!headerBuffer.serialize8(m_numModes)) {
return false;
}
if (!Storage::write(0, headerBuffer)) {
// NOTE: the save header does not contain the number of modes anymore,
// that is stored in the mode header of each storage page instead
// the save header is written to the global storage space so that it is
// shared by all profiles instead of being duplicated in each one
if (!Storage::writeGlobal(headerBuffer)) {
return false;
}
return true;
Expand All @@ -159,20 +161,15 @@ bool Modes::loadHeader()
{
ByteStream headerBuffer;
// only read storage if the modebuffer isn't filled
if (!Storage::read(0, headerBuffer) || !headerBuffer.size()) {
if (!Storage::readGlobal(headerBuffer) || !headerBuffer.size()) {
DEBUG_LOG("Empty buffer read from storage");
// this kinda sucks whatever they had loaded is gone
return false;
}
// this erases what is stored before we know whether there is data
// but it's the easiest way to just re-load new data from storage
clearModes();
// read the header and load the data
// read the header
if (!unserializeSaveHeader(headerBuffer)) {
return false;
}
// NOTE: We do not bother loading the number of modes because
// we can't really do anything with it anyway
return true;
}

Expand All @@ -182,6 +179,15 @@ bool Modes::saveStorage()
{
DEBUG_LOG("Saving modes...");
saveHeader();
// save the mode header of this page which contains the number of modes
// stored here, the modes themselves are saved in slots 1 and up
ByteStream modeHeader(MAX_MODE_SIZE);
if (!modeHeader.serialize8(m_numModes)) {
return false;
}
if (!Storage::writeModeHeader(modeHeader)) {
return false;
}
// make sure the current mode is saved in case it has changed somehow
saveCurMode();
// uninstantiate cur mode so we have stack space to serialize
Expand Down Expand Up @@ -221,27 +227,21 @@ bool Modes::saveStorage()

bool Modes::loadStorage()
{
// NOTE: We could call loadHeader here but then we wouldn't have the headerBuffer
// and in turn wouldn't be able to unserialize the number of modes. The number
// of modes is a weird case, it's technically part of the mode list not the
// header but it is stored in the same storage slot as the header
ByteStream headerBuffer;
// only read storage if the modebuffer isn't filled
if (!Storage::read(0, headerBuffer) || !headerBuffer.size()) {
// NOTE: The save header is global and was already loaded in init(), the
// mode header at slot 0 of this page holds the number of modes
// stored in this profile
ByteStream modeHeader;
if (!Storage::readModeHeader(modeHeader) || !modeHeader.size()) {
DEBUG_LOG("Empty buffer read from storage");
// this kinda sucks whatever they had loaded is gone
return false;
}
// this erases what is stored before we know whether there is data
// but it's the easiest way to just re-load new data from storage
clearModes();
// read the header and load the data
if (!unserializeSaveHeader(headerBuffer)) {
return false;
}
// unserialize the number of modes next
// unserialize the number of modes out of the mode header
uint8_t numModes = 0;
if (!headerBuffer.unserialize8(&numModes)) {
if (!modeHeader.unserialize8(&numModes)) {
return false;
}
if (!numModes) {
Expand Down Expand Up @@ -740,8 +740,8 @@ bool Modes::setFlag(uint8_t flag, bool enable, bool save)
}
// otherwise need to update the global flags field of the save header in storage
ByteStream headerBuffer;
// read out the storage header so we can update the flag field
if (!Storage::read(0, headerBuffer) || !headerBuffer.size()) {
// read out the global storage header so we can update the flag field
if (!Storage::readGlobal(headerBuffer) || !headerBuffer.size()) {
// if cannot read the save header then just save it normally
return saveHeader();
}
Expand All @@ -762,8 +762,8 @@ bool Modes::setFlag(uint8_t flag, bool enable, bool save)
// need to force the crc to recalc since we modified the data, just mark the
// CRC as dirty and Storage::write() will re-calculate the CRC if it's dirty
headerBuffer.setCRCDirty();
// write the save header back to storage
return Storage::write(0, headerBuffer);
// write the save header back to the global storage space
return Storage::writeGlobal(headerBuffer);
}

#ifdef VORTEX_LIB
Expand Down
50 changes: 46 additions & 4 deletions VortexEngine/src/Storage/Storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@

#define DEFAULT_STORAGE_FILENAME "FlashStorage.flash"

// the storage page reserved for the global storage space where the save
// header is kept, this must be a page number that no profile will ever
// use so that it can never collide with any of the storage pages
#define GLOBAL_STORAGE_PAGE 15

#ifdef VORTEX_LIB
std::string Storage::m_storageFilename;
#define STORAGE_FILENAME m_storageFilename.c_str()
Expand Down Expand Up @@ -63,6 +68,43 @@ uint8_t Storage::getStoragePage()
return m_storagePage;
}

// store a serial buffer to the global storage space, this simply targets
// slot 0 of the reserved global page so that the save header is not
// affected by whichever storage page is currently selected
bool Storage::writeGlobal(ByteStream &buffer)
{
uint8_t currentPage = m_storagePage;
m_storagePage = GLOBAL_STORAGE_PAGE;
bool ok = write(0, buffer);
m_storagePage = currentPage;
return ok;
}

// read a serial buffer from the global storage space
bool Storage::readGlobal(ByteStream &buffer)
{
uint8_t currentPage = m_storagePage;
m_storagePage = GLOBAL_STORAGE_PAGE;
bool ok = read(0, buffer);
m_storagePage = currentPage;
return ok;
}

// store a serial buffer to the mode header slot of the currently selected
// storage page
bool Storage::writeModeHeader(ByteStream &buffer)
{
// slot 0 of each page is the mode header which holds the number of
// modes stored in that page, the modes themselves are in slots 1 and up
return write(0, buffer);
}

// read the mode header from the currently selected storage page
bool Storage::readModeHeader(ByteStream &buffer)
{
return read(0, buffer);
}

// store a serial buffer to storage
bool Storage::write(uint16_t slot, ByteStream &buffer)
{
Expand Down Expand Up @@ -103,7 +145,7 @@ bool Storage::write(uint16_t slot, ByteStream &buffer)
return false;
}
DWORD written = 0;
DWORD offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * MAX_MODES));
DWORD offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * NUM_MODE_SLOTS));
SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
if (!WriteFile(hFile, buffer.rawData(), MAX_MODE_SIZE, &written, NULL)) {
// error
Expand All @@ -115,7 +157,7 @@ bool Storage::write(uint16_t slot, ByteStream &buffer)
if (!f) {
return false;
}
long offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * MAX_MODES));
long offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * NUM_MODE_SLOTS));
fseek(f, offset, SEEK_SET);
if (!fwrite(buffer.rawData(), sizeof(char), MAX_MODE_SIZE, f)) {
return false;
Expand Down Expand Up @@ -169,7 +211,7 @@ bool Storage::read(uint16_t slot, ByteStream &buffer)
return false;
}
DWORD bytesRead = 0;
DWORD offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * MAX_MODES));
DWORD offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * NUM_MODE_SLOTS));
SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
if (!ReadFile(hFile, buffer.rawData(), MAX_MODE_SIZE, &bytesRead, NULL)) {
// error
Expand All @@ -181,7 +223,7 @@ bool Storage::read(uint16_t slot, ByteStream &buffer)
if (!f) {
return false;
}
long offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * MAX_MODES));
long offset = (slot * MAX_MODE_SIZE) + (m_storagePage * (MAX_MODE_SIZE * NUM_MODE_SLOTS));
fseek(f, offset, SEEK_SET);
if (!fread(buffer.rawData(), sizeof(char), MAX_MODE_SIZE, f)) {
return false;
Expand Down
14 changes: 14 additions & 0 deletions VortexEngine/src/Storage/Storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ class Storage
// read a serial buffer from storage
static bool read(uint16_t slot, ByteStream &buffer);

// store a serial buffer to the global storage space which is not affected
// by the selected storage page, this is where the single global save
// header lives as it is shared by all profiles
static bool writeGlobal(ByteStream &buffer);
// read a serial buffer from the global storage space
static bool readGlobal(ByteStream &buffer);

// store a serial buffer to the mode header slot of the currently selected
// storage page, the mode header sits at slot 0 of each page and contains
// the number of modes stored in that page
static bool writeModeHeader(ByteStream &buffer);
// read the mode header from the currently selected storage page
static bool readModeHeader(ByteStream &buffer);

// the last save size (use STORAGE_SIZE For total space)
static uint32_t lastSaveSize();

Expand Down
Loading