diff --git a/inc/appStates/backupMenuState.hpp b/inc/appStates/backupMenuState.hpp index 8325bef..fd2962b 100644 --- a/inc/appStates/backupMenuState.hpp +++ b/inc/appStates/backupMenuState.hpp @@ -1,12 +1,10 @@ #pragma once #include -#include "data/userSaveInfo.hpp" -#include "data/titleInfo.hpp" +#include +#include "data/data.hpp" #include "filesystem/filesystem.hpp" -#include "ui/slidePanel.hpp" -#include "ui/menu.hpp" #include "appStates/appState.hpp" -#include "system/task.hpp" +#include "ui/ui.hpp" class backupMenuState : public appState { @@ -33,10 +31,14 @@ class backupMenuState : public appState std::string m_OutputBasePath; // Slide in/out panel std::unique_ptr m_BackupPanel; + // Width of panel/text + int m_PanelWidth; // Folder listing std::unique_ptr m_BackupListing; // Listing to make sure there is a save std::unique_ptr m_SaveListing; // Folder menu std::unique_ptr m_BackupMenu; + // Render target for menu + SDL_Texture *m_BackupMenuRenderTarget = NULL; }; diff --git a/inc/appStates/confirmState.hpp b/inc/appStates/confirmState.hpp new file mode 100644 index 0000000..481d304 --- /dev/null +++ b/inc/appStates/confirmState.hpp @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include "appStates/appState.hpp" +#include "system/timer.hpp" +#include "system/task.hpp" + +class confirmState : public appState +{ + public: + // Message is the question asked. onConfirmation is the function executed if user confirms. Args is the shared_ptr sent to onConfirmation + confirmState(const std::string &message, sys::taskFunction onConfirmation, std::shared_ptr args); + ~confirmState(); + + void update(void); + void render(void); + + private: + // Message being displayed + std::string m_Message; + // Yes and no text + std::string m_Yes; + std::string m_No; + // Timer for holding to confirm + std::unique_ptr m_HoldTimer; + // Int for what stage for holding + int8_t m_HoldStage = 0; + // Function on confirm + sys::taskFunction m_OnConfirmation; + // Args to send m_OnConfirmation + std::shared_ptr m_Args; +}; \ No newline at end of file diff --git a/inc/filesystem/directoryListing.hpp b/inc/filesystem/directoryListing.hpp index 5e499b4..2d784e4 100644 --- a/inc/filesystem/directoryListing.hpp +++ b/inc/filesystem/directoryListing.hpp @@ -15,6 +15,8 @@ namespace fs int getListingCount(void) const; // Returns if item at index is a folder bool itemAtIsDirectory(const int &index) const; + // Returns full path of item at index + std::string getFullPathToItemAt(const int &index) const; // Returns full name + extension of index std::string getItemAt(const int &index) const; // Returns just the file name (no extension) diff --git a/inc/graphics/colors.hpp b/inc/graphics/colors.hpp index 9db3062..748c8cc 100644 --- a/inc/graphics/colors.hpp +++ b/inc/graphics/colors.hpp @@ -12,6 +12,7 @@ #define COLOR_DIALOG_BOX 0x505050FF #define COLOR_WHITE 0xFFFFFFFF #define COLOR_BLACK 0x000000FF +#define COLOR_DARK_GRAY 0xCACACAFF #define COLOR_SLIDE_PANEL_TARGET 0x000000AA #define COLOR_RED 0xFF0000FF #define COLOR_GREEN 0x00FF00FF diff --git a/inc/system/input.hpp b/inc/system/input.hpp index a0c6a77..0b5a40b 100644 --- a/inc/system/input.hpp +++ b/inc/system/input.hpp @@ -15,6 +15,7 @@ namespace sys // Returns if button was pressed bool buttonDown(const HidNpadButton &button); bool buttonHeld(const HidNpadButton &button); + bool buttonReleased(const HidNpadButton &button); // Gets input and returns C++ string std::string getString(const std::string &defaultText, const std::string &headerText, const size_t &maximumLength); diff --git a/inc/system/timer.hpp b/inc/system/timer.hpp index 9a9b345..3ffff93 100644 --- a/inc/system/timer.hpp +++ b/inc/system/timer.hpp @@ -8,6 +8,8 @@ namespace sys public: // Inits timer with current ticks timer(const uint32_t &triggerTicks); + // Restarts timer. Sets starting ticks to current + void restartTimer(void); // Returns if triggerTicks has been reached. bool triggered(void); diff --git a/inc/ui/lang.hpp b/inc/ui/strings.hpp similarity index 98% rename from inc/ui/lang.hpp rename to inc/ui/strings.hpp index c8f0102..4ae8881 100644 --- a/inc/ui/lang.hpp +++ b/inc/ui/strings.hpp @@ -61,7 +61,7 @@ // Thread status strings #define LANG_THREAD_CREATING_SAVE "threadStatusCreatingSaveData" #define LANG_THREAD_COPYING_FILE "threadStatusCopyingFile" -#define LANG_THREAD_STATUS_DELETE "threadStatusDeletingFile" +#define LANG_THREAD_DELETE_FILE "threadStatusDeletingFile" #define LANG_THREAD_OPENING_FOLDER "threadStatusOpeningFolder" #define LANG_THREAD_ADDING_TO_ZIP "threadStatusAddingFolderToZip" #define LANG_THREAD_DECOMPRESSING_FILE "threadStatusDecompressingFile" diff --git a/inc/ui/ui.hpp b/inc/ui/ui.hpp index 1e08382..688dc0c 100644 --- a/inc/ui/ui.hpp +++ b/inc/ui/ui.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "ui/lang.hpp" +#include "ui/strings.hpp" #include "ui/menu.hpp" #include "ui/iconMenu.hpp" #include "ui/progressBar.hpp" diff --git a/src/appStates/backupMenuState.cpp b/src/appStates/backupMenuState.cpp index 0b94c54..746d68d 100644 --- a/src/appStates/backupMenuState.cpp +++ b/src/appStates/backupMenuState.cpp @@ -6,6 +6,7 @@ #include "system/input.hpp" #include "graphics/graphics.hpp" #include "appStates/backupMenuState.hpp" +#include "appStates/confirmState.hpp" #include "appStates/taskState.hpp" #include "filesystem/filesystem.hpp" #include "system/task.hpp" @@ -24,9 +25,11 @@ struct backupArgs : sys::taskArgs }; // This is shared by overwrite and restore -struct pathArg : sys::taskArgs +struct pathArgs : sys::taskArgs { std::string source, destination; + // For reloading folder list + backupMenuState *sendingState = NULL; }; // These are the functions used for tasks @@ -105,7 +108,7 @@ void overwriteBackup(sys::task *task, std::shared_ptr args) // Set status, cast args to type task->setThreadStatus("REPLACE THIS LATER"); - std::shared_ptr argIn = std::static_pointer_cast(args); + std::shared_ptr argIn = std::static_pointer_cast(args); // Get a test listing fs::directoryListing testListing(fs::DEFAULT_SAVE_MOUNT_DEVICE); @@ -143,7 +146,7 @@ void restoreBackup(sys::task *task, std::shared_ptr args) } task->setThreadStatus("REPLACE THIS LATER"); - std::shared_ptr argIn = std::static_pointer_cast(args); + std::shared_ptr argIn = std::static_pointer_cast(args); // Test if there are actually files in the save fs::directoryListing testListing(argIn->source); @@ -154,6 +157,34 @@ void restoreBackup(sys::task *task, std::shared_ptr args) } } +void deleteBackup(sys::task *task, std::shared_ptr args) +{ + if(args == nullptr) + { + task->finished(); + return; + } + + // Set thread status + task->setThreadStatus(ui::strings::getString(LANG_THREAD_DELETE_FILE, 0)); + + // Cast args + std::shared_ptr argsIn = std::static_pointer_cast(args); + + if(std::filesystem::is_directory(argsIn->destination)) + { + std::filesystem::remove_all(argsIn->destination); + } + else + { + std::filesystem::remove(argsIn->destination); + } + + argsIn->sendingState->loadDirectoryList(); + + task->finished(); +} + backupMenuState::backupMenuState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : m_CurrentUser(currentUser), m_CurrentUserSaveInfo(currentUserSaveInfo), m_CurrentTitleInfo(currentTitleInfo) { // This is the path used for all in/output. Create it if it doesn't exist. @@ -162,12 +193,14 @@ backupMenuState::backupMenuState(data::user *currentUser, data::userSaveInfo *cu // Controls displayed at bottom m_BackupMenuControlGuide = ui::strings::getString(LANG_FOLDER_GUIDE, 0); - int panelWidth = graphics::systemFont::getTextWidth(m_BackupMenuControlGuide, 18); + m_PanelWidth = graphics::systemFont::getTextWidth(m_BackupMenuControlGuide, 18); // The actual panel - m_BackupPanel = std::make_unique("backupMenuPanel", panelWidth + 64, ui::slidePanelSide::PANEL_SIDE_RIGHT); + m_BackupPanel = std::make_unique("backupMenuPanel", m_PanelWidth + 64, ui::slidePanelSide::PANEL_SIDE_RIGHT); // The menu of backups - m_BackupMenu = std::make_unique(10, 4, panelWidth + 44, 18, 7); + m_BackupMenu = std::make_unique(10, 4, m_PanelWidth + 44, 18, 6); + // Render target that menu is rendered to + m_BackupMenuRenderTarget = graphics::textureCreate("backupMenuRenderTarget", m_PanelWidth + 64, 647, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET); // Directory listing of backups m_BackupListing = std::make_unique(m_OutputBasePath); // Directory listing of save @@ -192,7 +225,7 @@ void backupMenuState::update(void) if (sys::input::buttonDown(HidNpadButton_A) && selected == 0) { // Check to make sure save data isn't empty before wasting time and space - if (m_BackupListing->getListingCount() > 0) + if (m_SaveListing->getListingCount() > 0) { // Data to send to task std::shared_ptr backupTaskArgs = std::make_shared(); @@ -210,8 +243,53 @@ void backupMenuState::update(void) ui::popMessage::newMessage(ui::strings::getString(LANG_POP_SAVE_EMPTY, 0), ui::popMessage::POPMESSAGE_DEFAULT_TICKS); } } - else if (sys::input::buttonDown(HidNpadButton_Y)) + else if(sys::input::buttonDown(HidNpadButton_A) && selected > 0) { + // Selected item + std::string selectedItem = m_BackupListing->getItemAt(selected - 1); + // Get overwrite string + std::string confirmOverwrite = stringUtil::getFormattedString(ui::strings::getCString(LANG_CONFIRM_OVERWRITE, 0), selectedItem.c_str()); + + // Arg pointer + std::shared_ptr paths = std::make_shared(); + paths->destination = m_BackupListing->getFullPathToItemAt(selected - 1); + + // Create confirmation + std::unique_ptr overwriteConfirmationState = std::make_unique(confirmOverwrite, overwriteBackup, paths); + // Push it real good + jksv::pushNewState(overwriteConfirmationState); + } + else if (sys::input::buttonDown(HidNpadButton_Y) && selected > 0) + { + // Get selected menu item + std::string selectedItem = m_BackupListing->getItemAt(selected - 1); + // Get restoration string + std::string confirmRestore = stringUtil::getFormattedString(ui::strings::getCString(LANG_CONFIRM_RESTORE, 0), selectedItem.c_str()); + + // Setup confirmation arg pointer + std::shared_ptr paths = std::make_shared(); + paths->source = m_BackupListing->getFullPathToItemAt(selected - 1); // Need to subtract one to account for 'New' option + + // Create confirmation + std::unique_ptr restoreConfirmationState = std::make_unique(confirmRestore, restoreBackup, paths); + // Push it to vector + jksv::pushNewState(restoreConfirmationState); + } + else if(sys::input::buttonDown(HidNpadButton_X) && selected > 0) + { + // Get selected + std::string selectedItem = m_BackupListing->getItemAt(selected - 1); + // Get confirmation string + std::string confirmDelete = stringUtil::getFormattedString(ui::strings::getCString(LANG_CONFIRM_DELETE, 0), selectedItem.c_str()); + + // Setup args + std::shared_ptr paths = std::make_shared(); + paths->destination = m_BackupListing->getFullPathToItemAt(selected - 1); + paths->sendingState = this; + + // Create confirm and push + std::unique_ptr deleteConfirmationState = std::make_unique(confirmDelete, deleteBackup, paths); + jksv::pushNewState(deleteConfirmationState); } else if (sys::input::buttonDown(HidNpadButton_B)) { @@ -225,11 +303,24 @@ void backupMenuState::update(void) void backupMenuState::render(void) { + // Get panel's render target and clear it first SDL_Texture *panelTarget = m_BackupPanel->getPanelRenderTarget(); - graphics::textureClear(panelTarget, COLOR_SLIDE_PANEL_TARGET); - m_BackupMenu->render(panelTarget); + // Clear menu render target + graphics::textureClear(m_BackupMenuRenderTarget, COLOR_TRANSPARENT); + + // Render menu to menu render target + m_BackupMenu->render(m_BackupMenuRenderTarget); + + // Render menu target to panel target (this is so the menu can only be draw so far and not cover guider) + graphics::textureRender(m_BackupMenuRenderTarget, panelTarget, 0, 0); + + // Draw divider and guide on bottom + graphics::renderLine(panelTarget, 18, 648, m_PanelWidth + 54, 648, COLOR_WHITE); + graphics::systemFont::renderText(m_BackupMenuControlGuide, panelTarget, 32, 673, 18, COLOR_WHITE); + + // Render panel to framebuffer m_BackupPanel->render(); } diff --git a/src/appStates/confirmState.cpp b/src/appStates/confirmState.cpp new file mode 100644 index 0000000..9a2a615 --- /dev/null +++ b/src/appStates/confirmState.cpp @@ -0,0 +1,92 @@ +#include "appStates/confirmState.hpp" +#include "appStates/taskState.hpp" +#include "graphics/graphics.hpp" +#include "ui/ui.hpp" +#include "system/input.hpp" +#include "jksv.hpp" +#include "log.hpp" + +static const int HOLD_TICKS = 1000; + +confirmState::confirmState(const std::string &message, sys::taskFunction onConfirmation, std::shared_ptr args) : m_Message(message), m_OnConfirmation(onConfirmation), m_Args(args) +{ + // Init timer + m_HoldTimer = std::make_unique(HOLD_TICKS); + // Get Text for yes and no + m_Yes = ui::strings::getString(LANG_DIALOG_YES, 0); + m_No = ui::strings::getString(LANG_DIALOG_NO, 0); +} + +confirmState::~confirmState() { } + +// To do: I don't like the way this looks, but not sure if it can get much better +void confirmState::update(void) +{ + // If A is first pressed, and stage is 0, restart timer + if(sys::input::buttonDown(HidNpadButton_A) && m_HoldStage == 0) + { + m_HoldTimer->restartTimer(); + } + else if(sys::input::buttonHeld(HidNpadButton_A) && m_HoldStage < 3 && m_HoldTimer->triggered()) + { + // Confirmed, create new task. + if(++m_HoldStage == 3) + { + // Create new task + std::unique_ptr confirmationTask = std::make_unique(m_OnConfirmation, m_Args); + jksv::pushNewState(confirmationTask); + // Deactivate this one and pray JKSV catches it + appState::deactivateState(); + } + else + { + // Switch and update yes accordingly + switch (m_HoldStage) + { + case 0: + { + m_Yes = ui::strings::getString(LANG_HOLDING_TEXT, 0); + } + break; + + case 1: + { + m_Yes = ui::strings::getString(LANG_HOLDING_TEXT, 1); + } + break; + + case 2: + { + m_Yes = ui::strings::getString(LANG_HOLDING_TEXT, 2); + } + break; + } + } + } + else if(sys::input::buttonReleased(HidNpadButton_A)) + { + m_Yes = ui::strings::getString(LANG_DIALOG_YES, 0); + } + else if(sys::input::buttonDown(HidNpadButton_B)) + { + // Party's over. Just stop + appState::deactivateState(); + } +} + +void confirmState::render(void) +{ + // Darken underlying + graphics::renderRect(NULL, 0, 0, 1280, 720, COLOR_DIM_BACKGROUND); + + // Calculate X position of m_Yes because it changes on hold + int yesXPosition = 458 - (graphics::systemFont::getTextWidth(m_Yes, 18) / 2); + + // Render dialog box + ui::renderDialogBox(NULL, 280, 262, 720, 256); + graphics::systemFont::renderTextWrap(m_Message, NULL, 312, 288, 18, 656, COLOR_WHITE); + graphics::renderLine(NULL, 280, 454, 999, 454, COLOR_DARK_GRAY); + graphics::renderLine(NULL, 640, 454, 640, 517, COLOR_DARK_GRAY); + graphics::systemFont::renderText(m_Yes, NULL, yesXPosition, 478, 18, COLOR_WHITE); + graphics::systemFont::renderText(m_No, NULL, 782, 478, 18, COLOR_WHITE); +} \ No newline at end of file diff --git a/src/filesystem/directoryListing.cpp b/src/filesystem/directoryListing.cpp index 6518af4..c4e789e 100644 --- a/src/filesystem/directoryListing.cpp +++ b/src/filesystem/directoryListing.cpp @@ -30,6 +30,11 @@ bool fs::directoryListing::itemAtIsDirectory(const int &index) const return std::filesystem::is_directory(m_DirectoryList.at(index)); } +std::string fs::directoryListing::getFullPathToItemAt(const int &index) const +{ + return m_DirectoryList.at(index); +} + std::string fs::directoryListing::getItemAt(const int &index) const { size_t lastSlash = m_DirectoryList.at(index).find_last_of('/') + 1; diff --git a/src/filesystem/fileParser.cpp b/src/filesystem/fileParser.cpp index 772c98a..7be2ba1 100644 --- a/src/filesystem/fileParser.cpp +++ b/src/filesystem/fileParser.cpp @@ -1,3 +1,4 @@ +#include #include "filesystem/fileParser.hpp" #include "stringUtil.hpp" #include "log.hpp" @@ -8,6 +9,8 @@ #define VALUE_TRUE "true" #define VALUE_FALSE "false" +static const int FILE_PARSER_LINE_SIZE_LIMIT = 0x1000; + fs::fileParser::fileParser(const std::string &filePath) { m_File = std::fopen(filePath.c_str(), "r"); @@ -25,30 +28,41 @@ bool fs::fileParser::isOpen(void) const bool fs::fileParser::readLine(void) { + // To return whether a new line was successfully read bool lineRead = false; - char lineBuffer[0x1000]; - while(std::fgets(lineBuffer, 0x1000, m_File)) + // Buffer to read lines into + std::array lineBuffer; + + // Loop until a line isn't a comment or new line + while(std::fgets(lineBuffer.data(), FILENAME_MAX, m_File)) { - char lineStart = lineBuffer[0]; + // Get first char in line. If it's a comment or new line, continue loop + char lineStart = lineBuffer.at(0); if(lineStart == '#' || lineStart == '\n' || lineStart == '\r') { continue; } else { - m_CurrentLine.assign(lineBuffer); + // Assign lineBuffer to current line C++ string + m_CurrentLine.assign(lineBuffer.data()); + // Line read was successful, break the loop lineRead = true; break; } } + // These need to be removed because they can cause issues stringUtil::eraseCharacterFromString('\n', m_CurrentLine); stringUtil::eraseCharacterFromString('\r', m_CurrentLine); + // Find first "word" of line. m_CurrentLinePosition = m_CurrentLine.find_first_of(VALUE_DELIMINATORS); + // Assign it m_ItemName.assign(m_CurrentLine.begin(), m_CurrentLine.begin() + m_CurrentLinePosition); + // Remove spaces stringUtil::eraseCharacterFromString(' ', m_ItemName); - + // Increment after value deliminator ++m_CurrentLinePosition; return lineRead; @@ -59,6 +73,7 @@ std::string fs::fileParser::getCurrentItemName(void) const return m_ItemName; } +// All of these just us getNextValueAsString and converts on return bool fs::fileParser::getNextValueAsBool(void) { std::string value = getNextValueAsString(); @@ -89,10 +104,14 @@ uint64_t fs::fileParser::getNextValueAsUint64(void) std::string fs::fileParser::getNextValueAsString(void) { + // Find the first char that isn't a space or comma m_CurrentLinePosition = m_CurrentLine.find_first_not_of(" ,", m_CurrentLinePosition); + // Starting position of string we're extracting size_t startingPosition = m_CurrentLinePosition; + // Need to test for quotes char firstChar = m_CurrentLine.at(m_CurrentLinePosition); + // If it's a quote, just keep going until the ending quote. if(firstChar == '"') { m_CurrentLinePosition = m_CurrentLine.find_first_of('"', ++startingPosition); @@ -101,5 +120,6 @@ std::string fs::fileParser::getNextValueAsString(void) { m_CurrentLinePosition = m_CurrentLine.find_first_of(STRING_DELIMINATORS); } + // Return the substring return m_CurrentLine.substr(startingPosition, m_CurrentLinePosition++ - startingPosition); } \ No newline at end of file diff --git a/src/graphics/systemFont.cpp b/src/graphics/systemFont.cpp index 504df04..6a38892 100644 --- a/src/graphics/systemFont.cpp +++ b/src/graphics/systemFont.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -11,6 +12,8 @@ #include "graphics/systemFont.hpp" #include "log.hpp" +static const int WORD_WRAP_BUFFER_LENGTH = 0x1000; + //Masks for converting to surface static const uint32_t s_RedMask = 0xFF000000; static const uint32_t s_GreenMask = 0x00FF0000; @@ -226,6 +229,7 @@ void graphics::systemFont::exit(void) FT_Done_Face(s_FTFaces[i]); } FT_Done_FreeType(s_FTLib); + logger::log("systemFont::exit(): Succeeded."); } @@ -265,6 +269,7 @@ void graphics::systemFont::renderText(const std::string &text, SDL_Texture *targ } else if(codepoint == '\n') { + // Break line, reset X, increase Y workingX = x; workingY += fontSize + 8; continue; @@ -273,8 +278,11 @@ void graphics::systemFont::renderText(const std::string &text, SDL_Texture *targ glyphData *gd = getGlyph(codepoint, fontSize); if(gd) { + // Set color just to be sure SDL_SetTextureColorMod(gd->glyph, getRed(workingColor), getGreen(workingColor), getBlue(workingColor)); + // Render glyph texture graphics::textureRender(gd->glyph, target, workingX + gd->left, workingY + (fontSize - gd->top)); + // X update workingX += gd->advanceX; } } @@ -287,7 +295,7 @@ void graphics::systemFont::renderTextWrap(const std::string &text, SDL_Texture * int workingY = y; int stringLength = text.length(); // This buffer is used to calculate if the next word should create a line break - char wordBuffer[0x100]; + std::array wordBuffer = { 0 }; resizeFont(fontSize); @@ -296,21 +304,24 @@ void graphics::systemFont::renderTextWrap(const std::string &text, SDL_Texture * // Find the next char we can break a line at size_t nextBreakpoint = findNextBreakPoint(&text.c_str()[i]); - // Clear and copy string up until that point to wordBuffer - std::memset(wordBuffer, 0x00, 0x100); - std::memcpy(wordBuffer, &text.c_str()[i], nextBreakpoint); + // Copy string up until that point to wordBuffer + std::snprintf(wordBuffer.data(), WORD_WRAP_BUFFER_LENGTH, "%s", text.substr(i, nextBreakpoint).c_str()); // Go to next line if maxWidth is exceeded - int wordWidth = graphics::systemFont::getTextWidth(wordBuffer, fontSize); + int wordWidth = graphics::systemFont::getTextWidth(wordBuffer.data(), fontSize); if(workingX + wordWidth >= x + maxWidth) { workingX = x; workingY += fontSize + 8; } // Render word - graphics::systemFont::renderText(wordBuffer, target, workingX, workingY, fontSize, color); + graphics::systemFont::renderText(wordBuffer.data(), target, workingX, workingY, fontSize, color); + // Increase workingX by word width workingX += wordWidth; + + // Add length to i + i += std::strlen(wordBuffer.data()); } } diff --git a/src/log.cpp b/src/log.cpp index e01dc4e..59f7f56 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -1,7 +1,10 @@ +#include #include #include #include "log.hpp" +static const int LOG_VA_BUFFER_SIZE = 0x1000; + namespace { std::ofstream s_LogFile; @@ -15,14 +18,17 @@ void logger::init(void) void logger::log(const char *format, ...) { - char vaBuffer[0x800]; - va_list args; + // Buffer for va + std::array vaBuffer; + + // VA + std::va_list args; va_start(args, format); - vsnprintf(vaBuffer, 0x800, format, args); + vsnprintf(vaBuffer.data(), LOG_VA_BUFFER_SIZE, format, args); va_end(args); - // JIC because of task threads + // This is because of threading s_LogMutex.lock(); - s_LogFile << vaBuffer << std::endl; // Using std::endl for flush for more reliable logging + s_LogFile << vaBuffer.data() << std::endl; // endl for buffer flushing s_LogMutex.unlock(); } \ No newline at end of file diff --git a/src/system/input.cpp b/src/system/input.cpp index 3083717..99da27b 100644 --- a/src/system/input.cpp +++ b/src/system/input.cpp @@ -30,6 +30,11 @@ bool sys::input::buttonHeld(const HidNpadButton &button) return padGetButtons(&s_PadState) & button; } +bool sys::input::buttonReleased(const HidNpadButton &button) +{ + return padGetButtonsUp(&s_PadState) & button; +} + std::string sys::input::getString(const std::string &defaultText, const std::string &headerText, const size_t &maximumLength) { // Keyboard config diff --git a/src/system/timer.cpp b/src/system/timer.cpp index dba7808..8c7553e 100644 --- a/src/system/timer.cpp +++ b/src/system/timer.cpp @@ -3,7 +3,12 @@ sys::timer::timer(const uint32_t &triggerTicks) : m_TriggerTicks(triggerTicks) { - // Save starting ticks + restartTimer(); +} + +void sys::timer::restartTimer(void) +{ + // Set starting ticks m_StartingTicks = SDL_GetTicks(); } diff --git a/src/ui/lang.cpp b/src/ui/strings.cpp similarity index 99% rename from src/ui/lang.cpp rename to src/ui/strings.cpp index 6be36a5..9d63fe3 100644 --- a/src/ui/lang.cpp +++ b/src/ui/strings.cpp @@ -1,6 +1,6 @@ #include #include -#include "ui/lang.hpp" +#include "ui/strings.hpp" #include "log.hpp" #include "stringUtil.hpp" diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 32b1a23..3ea317f 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -1,5 +1,4 @@ #include "ui/ui.hpp" -#include "ui/lang.hpp" #include "graphics/graphics.hpp" namespace