Skip to content

Commit

Permalink
Merge branch 'master' into gloves
Browse files Browse the repository at this point in the history
  • Loading branch information
Unreal-Dan committed Apr 30, 2024
2 parents dd8801d + a1def7f commit c7aee86
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 94 deletions.
199 changes: 112 additions & 87 deletions VortexEngine/src/Modes/Modes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,112 +83,95 @@ void Modes::play()
}
// shortclick cycles to the next mode
if (g_pButton->onShortClick()) {
nextModeSkipEmpty();
nextMode();
}
// play the current mode
m_pCurModeLink->play();
}

bool Modes::serializeSaveHeader(ByteStream &saveBuffer)
// full save/load to/from buffer
bool Modes::saveToBuffer(ByteStream &modesBuffer)
{
// serialize the engine version into the modes buffer
if (!VortexEngine::serializeVersion(saveBuffer)) {
// first write out the header
if (!serializeSaveHeader(modesBuffer)) {
return false;
}
// NOTE: instead of global brightness the duo uses this to store the
// startup mode ID. The duo doesn't offer a global brightness option
if (!saveBuffer.serialize8(m_globalFlags)) {
// serialize all modes data into the modesBuffer
if (!serialize(modesBuffer)) {
return false;
}
// serialize the global brightness
if (!saveBuffer.serialize8((uint8_t)Leds::getBrightness())) {
DEBUG_LOGF("Serialized all modes, uncompressed size: %u", modesBuffer.size());
if (!modesBuffer.compress()) {
return false;
}
DEBUG_LOGF("Serialized all modes, uncompressed size: %u", saveBuffer.size());
return true;
}

bool Modes::unserializeSaveHeader(ByteStream &saveHeader)
// load modes from a save buffer
bool Modes::loadFromBuffer(ByteStream &modesBuffer)
{
// reset the unserializer index before unserializing anything
saveHeader.resetUnserializer();
uint8_t major = 0;
uint8_t minor = 0;
// unserialize the vortex version
if (!saveHeader.unserialize8(&major)) {
return false;
}
if (!saveHeader.unserialize8(&minor)) {
return false;
}
// check the version for incompatibility
if (!VortexEngine::checkVersion(major, minor)) {
// incompatible version
ERROR_LOGF("Incompatible savefile version: %u.%u", major, minor);
if (!modesBuffer.decompress()) {
// failed to decompress?
return false;
}
// NOTE: instead of global brightness the duo uses this to store the
// startup mode ID. The duo doesn't offer a global brightness option
// unserialize the global brightness
if (!saveHeader.unserialize8(&m_globalFlags)) {
// read out the header first
if (!unserializeSaveHeader(modesBuffer)) {
return false;
}
// unserialize the global brightness
uint8_t brightness = 0;
if (!saveHeader.unserialize8(&brightness)) {
// now just unserialize the list of modes
if (!unserialize(modesBuffer)) {
return false;
}
if (brightness) {
Leds::setBrightness(brightness);
if (oneClickModeEnabled()) {
// set the current mode to the startup mode
switchToStartupMode();
}
return true;
}

// full save/load to/from buffer
bool Modes::saveToBuffer(ByteStream &modesBuffer)
bool Modes::saveHeader()
{
// first write out the header
if (!serializeSaveHeader(modesBuffer)) {
ByteStream headerBuffer(MAX_MODE_SIZE);
if (!serializeSaveHeader(headerBuffer)) {
return false;
}
// serialize all modes data into the modesBuffer
if (!serialize(modesBuffer)) {
// serialize the number of modes
if (!headerBuffer.serialize8(m_numModes)) {
return false;
}
DEBUG_LOGF("Serialized all modes, uncompressed size: %u", modesBuffer.size());
if (!modesBuffer.compress()) {
if (!Storage::write(0, headerBuffer)) {
return false;
}
return true;
}

// load modes from a save buffer
bool Modes::loadFromBuffer(ByteStream &modesBuffer)
bool Modes::loadHeader()
{
if (!modesBuffer.decompress()) {
// failed to decompress?
return false;
}
// read out the header first
if (!unserializeSaveHeader(modesBuffer)) {
ByteStream headerBuffer;
// only read storage if the modebuffer isn't filled
if (!Storage::read(0, headerBuffer) || !headerBuffer.size()) {
DEBUG_LOG("Empty buffer read from storage");
// this kinda sucks whatever they had loaded is gone
return false;
}
// now just unserialize the list of modes
if (!unserialize(modesBuffer)) {
// 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;
}
// startupMode is 1-based offset that encodes both the index to start at and
// whether the system is enabled, hence why 0 cannot be used as an offset
uint8_t startupMode = (m_globalFlags & 0xF0) >> 4;
if (oneClickModeEnabled() && startupMode > 0) {
// set the current mode to the startup mode
setCurMode(startupMode);
}
// NOTE: We do not bother loading the number of modes because
// we can't really do anything with it anyway
return true;
}

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()) {
Expand Down Expand Up @@ -221,21 +204,9 @@ bool Modes::loadStorage()
return false;
}
}
return true;
}

bool Modes::saveHeader()
{
ByteStream headerBuffer(MAX_MODE_SIZE);
if (!serializeSaveHeader(headerBuffer)) {
return false;
}
// serialize the number of modes
if (!headerBuffer.serialize8(m_numModes)) {
return false;
}
if (!Storage::write(0, headerBuffer)) {
return false;
if (oneClickModeEnabled()) {
// set the current mode to the startup mode
switchToStartupMode();
}
return true;
}
Expand All @@ -245,24 +216,14 @@ bool Modes::saveHeader()
bool Modes::saveStorage()
{
DEBUG_LOG("Saving modes...");
ByteStream headerBuffer(MAX_MODE_SIZE);
if (!serializeSaveHeader(headerBuffer)) {
return false;
}
// serialize the number of modes
if (!headerBuffer.serialize8(m_numModes)) {
return false;
}
if (!Storage::write(0, headerBuffer)) {
return false;
}
saveHeader();
// make sure the current mode is saved in case it has changed somehow
saveCurMode();
// uninstantiate cur mode so we have stack space to serialize
if (m_pCurModeLink) {
m_pCurModeLink->uninstantiate();
}
uint16_t i = 0;
uint8_t i = 0;
ModeLink *ptr = m_storedModes;
while (ptr && i < MAX_MODES) {
ByteStream modeBuffer(MAX_MODE_SIZE);
Expand Down Expand Up @@ -293,6 +254,65 @@ bool Modes::saveStorage()
return true;
}

bool Modes::serializeSaveHeader(ByteStream &saveBuffer)
{
// serialize the engine version into the modes buffer
if (!VortexEngine::serializeVersion(saveBuffer)) {
return false;
}
// NOTE: instead of global brightness the duo uses this to store the
// startup mode ID. The duo doesn't offer a global brightness option
if (!saveBuffer.serialize8(m_globalFlags)) {
return false;
}
// serialize the global brightness
if (!saveBuffer.serialize8((uint8_t)Leds::getBrightness())) {
return false;
}
DEBUG_LOGF("Serialized all modes, uncompressed size: %u", saveBuffer.size());
return true;
}

bool Modes::unserializeSaveHeader(ByteStream &saveHeader)
{
if (!saveHeader.decompress()) {
// failed to decompress?
return false;
}
// reset the unserializer index before unserializing anything
saveHeader.resetUnserializer();
uint8_t major = 0;
uint8_t minor = 0;
// unserialize the vortex version
if (!saveHeader.unserialize8(&major)) {
return false;
}
if (!saveHeader.unserialize8(&minor)) {
return false;
}
// check the version for incompatibility
if (!VortexEngine::checkVersion(major, minor)) {
// incompatible version
ERROR_LOGF("Incompatible savefile version: %u.%u", major, minor);
return false;
}
// NOTE: instead of global brightness the duo uses this to store the
// startup mode ID. The duo doesn't offer a global brightness option
// unserialize the global brightness
if (!saveHeader.unserialize8(&m_globalFlags)) {
return false;
}
// unserialize the global brightness
uint8_t brightness = 0;
if (!saveHeader.unserialize8(&brightness)) {
return false;
}
if (brightness) {
Leds::setBrightness(brightness);
}
return true;
}

// Save all of the modes to a serial buffer
bool Modes::serialize(ByteStream &modesBuffer)
{
Expand Down Expand Up @@ -692,6 +712,11 @@ uint8_t Modes::startupMode()
return (m_globalFlags & 0xF0) >> 4;
}

Mode *Modes::switchToStartupMode()
{
return setCurMode(startupMode());
}

bool Modes::setFlag(uint8_t flag, bool enable, bool save)
{
// then actually if it's enabled ensure the upper nibble is set
Expand Down
14 changes: 8 additions & 6 deletions VortexEngine/src/Modes/Modes.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,17 @@ class Modes
static bool saveToBuffer(ByteStream &saveBuffer);
static bool loadFromBuffer(ByteStream &saveBuffer);

// save the header to storage
// save/load the global settings to/from storage
static bool saveHeader();
static bool loadHeader();

// full save/load to/from storage
static bool loadStorage();
static bool saveStorage();
static bool loadStorage();

// save load the savefile header from storage
static bool serializeSaveHeader(ByteStream &saveBuffer);
static bool unserializeSaveHeader(ByteStream &saveBuffer);

// saves all modes to a buffer
static bool serialize(ByteStream &buffer);
Expand Down Expand Up @@ -110,6 +115,7 @@ class Modes
// set the startup mode index (which mode will be displayed on startup)
static void setStartupMode(uint8_t index);
static uint8_t startupMode();
static Mode *switchToStartupMode();

// set or get flags
static bool setFlag(uint8_t flag, bool enable, bool save = true);
Expand Down Expand Up @@ -208,10 +214,6 @@ class Modes
ModeLink *m_prev;
};

// save load the savefile header from storage
static bool serializeSaveHeader(ByteStream &saveBuffer);
static bool unserializeSaveHeader(ByteStream &saveBuffer);

// fetch a link from the chain by index
static ModeLink *getModeLink(uint32_t index);

Expand Down
2 changes: 1 addition & 1 deletion VortexEngine/src/VortexEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ void VortexEngine::runMainLogic()
// if auto cycle is enabled and the last switch was more than the delay ago
if (m_autoCycle && (Modes::lastSwitchTime() + AUTO_RANDOM_DELAY < now)) {
// then switch to the next mode automatically
Modes::nextModeSkipEmpty();
Modes::nextMode();
}

// otherwise just play the modes
Expand Down

0 comments on commit c7aee86

Please sign in to comment.