From 7134a1f30bf3d6f2f0fb597d33000bc13354633f Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sun, 3 Nov 2024 11:22:58 +0200 Subject: [PATCH 01/16] fixed bug with not saving unlocked tracks and levels --- .gitignore | 10 ++ CMakeLists.txt | 3 +- notes.md | 20 ++++ src/MenuManager.cpp | 163 +++++++++++++++--------------- src/MenuManager.h | 14 +-- src/RecordManager.cpp | 9 +- src/lcdui/CanvasImpl.cpp | 20 ++-- src/lcdui/CanvasImpl.h | 9 +- src/rms/RecordEnumerationImpl.cpp | 4 + src/rms/RecordStore.cpp | 6 +- 10 files changed, 160 insertions(+), 98 deletions(-) create mode 100644 notes.md diff --git a/.gitignore b/.gitignore index 0236496..8038126 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,13 @@ build .cache .vscode + +__cmrc_Assets +_cmrc +CMakeCache.txt +CMakeFiles +GravityDefied +Makefile +cmake_install.cmake +libAssets.a + diff --git a/CMakeLists.txt b/CMakeLists.txt index 06f1426..8015864 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.24) project(gravity_defied_cpp C CXX) +set(CMAKE_VERBOSE_MAKEFILE TRUE) unset(ENV{PKG_CONFIG_PATH}) @@ -77,7 +78,7 @@ endif() add_executable(GravityDefied ${SOURCES}) target_compile_features(GravityDefied PRIVATE cxx_std_17) -target_compile_options(GravityDefied PRIVATE -Wall -Wextra) +target_compile_options(GravityDefied PRIVATE -Wall -Wextra -fsigned-char) target_include_directories(GravityDefied PRIVATE ${SDL2_INCLUDE_DIRS} diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..092ddf0 --- /dev/null +++ b/notes.md @@ -0,0 +1,20 @@ +Settings (bytes) +0 - perspective (on-off) +1 - shadows (on-off) +2 - driver sprite (on-off) +3 - bike sprite (on-off) +4 - look ahead (on-off) +5 - enabled leagues count (0-3) (4 leagues in total) +6 - enabled levels count (0-2) (3 levels in total) +7 - number of enabled easy level tracks +8 - number of enabled medium level tracks +9 - number of enabled hard level tracks +10 - level ? +11 - track ? +12 - league ? +13 - ? +14 - inputSetting ? +15 - ? +16 - player name (char) +17 - player name (char) +18 - player name (char) diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index caff4e0..f6616ac 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -23,7 +23,7 @@ void MenuManager::initPart(int var1) int var4; switch (var1) { case 1: - field_341 = defaultInputString; + playerName = defaultName; field_374 = { "On", "Off" }; field_375 = { "Keyset 1", "Keyset 2", "Keyset 3" }; recordManager = new RecordManager(); @@ -32,10 +32,10 @@ void MenuManager::initPart(int var1) field_339 = -1; field_340.clear(); isRecordStoreOpened = false; - field_278 = std::vector(19); + savedData = std::vector(19); - for (int var11 = 0; var11 < 19; ++var11) { - field_278[var11] = -127; + for (int idx = 0; idx < 19; ++idx) { + savedData[idx] = -127; } try { @@ -68,56 +68,57 @@ void MenuManager::initPart(int var1) if (var3.size() <= 19) { for (std::size_t i = 0; i < var3.size(); ++i) { - field_278[i] = var3[i]; + savedData[i] = var3[i]; } } - records->destroy(); + // records->destroy(); } var3 = method_216(16, (int8_t)-1); if (!var3.empty() && var3[0] != -1) { for (var4 = 0; var4 < 3; ++var4) { - field_341[var4] = var3[var4]; + playerName[var4] = var3[var4]; } } - if (field_341[0] == 82 && field_341[1] == 75 && field_341[2] == 69) { + // cheat code: set name to RKE to enable all leagues ??? + if (playerName[0] == 82 && playerName[1] == 75 && playerName[2] == 69) { availableLeagues = 3; - field_344 = 2; - field_342[0] = (int8_t)(micro->levelLoader->levelNames[0].size() - 1); - field_342[1] = (int8_t)(micro->levelLoader->levelNames[1].size() - 1); - field_342[2] = (int8_t)(micro->levelLoader->levelNames[2].size() - 1); + availableLevels = 2; + availableTracks[0] = (int8_t)(micro->levelLoader->levelNames[0].size() - 1); + availableTracks[1] = (int8_t)(micro->levelLoader->levelNames[1].size() - 1); + availableTracks[2] = (int8_t)(micro->levelLoader->levelNames[2].size() - 1); return; } availableLeagues = 0; - field_344 = 1; - field_342[0] = 0; - field_342[1] = 0; - field_342[2] = -1; + availableLevels = 0; + availableTracks[0] = 0; + availableTracks[1] = 0; + availableTracks[2] = -1; } return; case 3: - isDisablePerspective = method_217(0, isDisablePerspective); - isDisabledShadows = method_217(1, isDisabledShadows); - isDisabledDriverSprite = method_217(2, isDisabledDriverSprite); - isDisabledBikeSprite = method_217(3, isDisabledBikeSprite); - field_367 = method_217(14, field_367); - isDisableLookAhead = method_217(4, isDisableLookAhead); - field_369 = method_217(11, field_369); - field_370 = method_217(10, field_370); - field_371 = method_217(12, field_371); - field_373 = method_217(15, field_373); + isDisablePerspective = getSettingOrDefault(0, isDisablePerspective); + isDisabledShadows = getSettingOrDefault(1, isDisabledShadows); + isDisabledDriverSprite = getSettingOrDefault(2, isDisabledDriverSprite); + isDisabledBikeSprite = getSettingOrDefault(3, isDisabledBikeSprite); + field_367 = getSettingOrDefault(14, field_367); + isDisableLookAhead = getSettingOrDefault(4, isDisableLookAhead); + field_369 = getSettingOrDefault(11, field_369); + field_370 = getSettingOrDefault(10, field_370); + field_371 = getSettingOrDefault(12, field_371); + field_373 = getSettingOrDefault(15, field_373); field_354 = field_370; field_355 = field_369; - if (field_341[0] != 82 || field_341[1] != 75 || field_341[2] != 69) { - availableLeagues = method_217(5, availableLeagues); - field_344 = method_217(6, field_344); + if (playerName[0] != 82 || playerName[1] != 75 || playerName[2] != 69) { + availableLeagues = getSettingOrDefault(5, availableLeagues); + availableLevels = getSettingOrDefault(6, availableLevels); for (var4 = 0; var4 < 3; ++var4) { - field_342[var4] = method_217(7 + var4, field_342[var4]); + availableTracks[var4] = getSettingOrDefault(7 + var4, availableTracks[var4]); } } @@ -169,7 +170,7 @@ void MenuManager::initPart(int var1) return; case 5: gameMenuIngame = new GameMenu("Ingame", micro, gameMenuPlay); - gameMenuEnterName = new GameMenu("Enter Name", micro, gameMenuFinished, field_341); + gameMenuEnterName = new GameMenu("Enter Name", micro, gameMenuFinished, playerName); gameMenuConfirmClear = new GameMenu("Confirm Clear", micro, gameMenuOptions); gameMenuConfirmReset = new GameMenu("Confirm Reset", micro, gameMenuConfirmClear); taskPlayMenu = new TimerOrMotoPartOrMenuElem("Play Menu", gameMenuPlay, this); @@ -187,12 +188,12 @@ void MenuManager::initPart(int var1) settingsStringLeague = new SettingsStringRender("League", field_371, this, leagueNames, false, micro, gameMenuPlay, false); try { - settingsStringTrack->setAvailableOptions(field_342[field_370]); + settingsStringTrack->setAvailableOptions(availableTracks[field_370]); } catch (std::exception& var5) { settingsStringTrack->setAvailableOptions(0); } - settingStringLevel->setAvailableOptions(field_344); + settingStringLevel->setAvailableOptions(availableLevels); settingsStringLeague->setAvailableOptions(availableLeagues); gameTimerTaskHighscore = new TimerOrMotoPartOrMenuElem("Highscore", gameMenuHighscore, this); gameMenuHighscore->addMenuElement(settingStringBack); @@ -301,7 +302,7 @@ void MenuManager::initPart(int var1) gameMenuIngame->addMenuElement(taskHelp); gameMenuIngame->addMenuElement(settingStringPlayMenu); field_335 = new SettingsStringRender("Ok", 0, this, std::vector(), false, micro, gameMenuMain, true); - field_336 = new SettingsStringRender("Name - " + std::string(field_341), 0, this, std::vector(), false, micro, gameMenuMain, true); + field_336 = new SettingsStringRender("Name - " + std::string(playerName), 0, this, std::vector(), false, micro, gameMenuMain, true); commandOk = new Command("Ok", 4, 1); commandBack = new Command("Back", 2, 1); method_1(gameMenuMain, false); @@ -344,7 +345,7 @@ bool MenuManager::method_196() void MenuManager::method_197() { - recordManager->method_17(settingsStringLeague->getCurrentOptionPos(), field_341, field_337); + recordManager->method_17(settingsStringLeague->getCurrentOptionPos(), playerName, field_337); recordManager->writeRecordInfo(); field_356 = false; gameMenuFinished->clearVector(); @@ -360,8 +361,8 @@ void MenuManager::method_197() recordManager->closeRecordStore(); int8_t availableLeagues = -1; if (settingsStringTrack->getMaxAvailableOptionPos() >= settingsStringTrack->getCurrentOptionPos()) { - settingsStringTrack->setAvailableOptions(settingsStringTrack->getCurrentOptionPos() + 1 < field_342[settingStringLevel->getCurrentOptionPos()] ? field_342[settingStringLevel->getCurrentOptionPos()] : settingsStringTrack->getCurrentOptionPos() + 1); - field_342[settingStringLevel->getCurrentOptionPos()] = (int8_t)settingsStringTrack->getMaxAvailableOptionPos() < field_342[settingStringLevel->getCurrentOptionPos()] ? field_342[settingStringLevel->getCurrentOptionPos()] : (int8_t)settingsStringTrack->getMaxAvailableOptionPos(); + settingsStringTrack->setAvailableOptions(settingsStringTrack->getCurrentOptionPos() + 1 < availableTracks[settingStringLevel->getCurrentOptionPos()] ? availableTracks[settingStringLevel->getCurrentOptionPos()] : settingsStringTrack->getCurrentOptionPos() + 1); + availableTracks[settingStringLevel->getCurrentOptionPos()] = (int8_t)settingsStringTrack->getMaxAvailableOptionPos() < availableTracks[settingStringLevel->getCurrentOptionPos()] ? availableTracks[settingStringLevel->getCurrentOptionPos()] : (int8_t)settingsStringTrack->getMaxAvailableOptionPos(); } if (settingsStringTrack->getCurrentOptionPos() == settingsStringTrack->getMaxOptionPos()) { @@ -369,21 +370,18 @@ void MenuManager::method_197() switch (settingStringLevel->getCurrentOptionPos()) { case 0: if (availableLeagues < 1) { - availableLeagues = 1; availableLeagues = 1; settingsStringLeague->setAvailableOptions(availableLeagues); } break; case 1: if (availableLeagues < 2) { - availableLeagues = 2; availableLeagues = 2; settingsStringLeague->setAvailableOptions(availableLeagues); } break; case 2: if (availableLeagues < 3) { - availableLeagues = 3; availableLeagues = 3; settingsStringLeague->setOptionsList(leagueNamesAll4); leagueNames = leagueNamesAll4; @@ -392,8 +390,8 @@ void MenuManager::method_197() } settingStringLevel->setAvailableOptions(settingStringLevel->getMaxAvailableOptionPos() + 1); - if (field_342[settingStringLevel->getMaxAvailableOptionPos()] == -1) { - field_342[settingStringLevel->getMaxAvailableOptionPos()] = 0; + if (availableTracks[settingStringLevel->getMaxAvailableOptionPos()] == -1) { + availableTracks[settingStringLevel->getMaxAvailableOptionPos()] = 0; } } @@ -406,7 +404,7 @@ void MenuManager::method_197() if (settingStringLevel->getCurrentOptionPos() < settingStringLevel->getMaxOptionPos()) { settingStringLevel->setCurentOptionPos(settingStringLevel->getCurrentOptionPos() + 1); settingsStringTrack->setCurentOptionPos(0); - settingsStringTrack->setAvailableOptions(field_342[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); } if (availableLeagues != -1) { @@ -420,7 +418,7 @@ void MenuManager::method_197() bool var4 = true; for (int var5 = 0; var5 < 3; ++var5) { - if (field_342[var5] != static_cast(micro->levelLoader->levelNames[var5].size() - 1)) { + if (availableTracks[var5] != static_cast(micro->levelLoader->levelNames[var5].size() - 1)) { var4 = false; } } @@ -678,15 +676,15 @@ void MenuManager::method_1(GameMenu* gm, bool var2) field_360 = settingsStringLeague->getCurrentOptionPos(); method_207(field_360); } else if (gm == gameMenuFinished) { - field_341 = gameMenuEnterName->getStrArr(); - field_336->setText("Name - " + std::string(field_341)); + playerName = gameMenuEnterName->getStrArr(); + field_336->setText("Name - " + std::string(playerName)); } else if (gm == gameMenuPlay) { settingsStringTrack->setOptionsList(micro->levelLoader->levelNames[settingStringLevel->getCurrentOptionPos()]); if (currentGameMenu == field_299) { field_345[settingStringLevel->getCurrentOptionPos()] = settingsStringTrack->getCurrentOptionPos(); } - settingsStringTrack->setAvailableOptions(field_342[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->setCurentOptionPos(field_345[settingStringLevel->getCurrentOptionPos()]); } @@ -743,6 +741,7 @@ void MenuManager::saveSmthToRecordStoreAndCloseIt() recordStore->closeRecordStore(); isRecordStoreOpened = false; } catch (RecordStoreException& var1) { + std::cout << var1.what() << std::endl; } } @@ -751,7 +750,7 @@ void MenuManager::saveSmthToRecordStoreAndCloseIt() void MenuManager::method_208() { - copyThreeBytesFromArr(16, field_341); + // copyThreeBytesFromArr(16, playerName); setValue(0, (int8_t)perspectiveSetting->getCurrentOptionPos()); setValue(1, (int8_t)shadowsSetting->getCurrentOptionPos()); @@ -765,21 +764,29 @@ void MenuManager::method_208() setValue(11, (int8_t)settingsStringTrack->getCurrentOptionPos()); setValue(12, (int8_t)settingsStringLeague->getCurrentOptionPos()); + setValue(16, (int8_t)playerName[0]); + setValue(17, (int8_t)playerName[1]); + setValue(18, (int8_t)playerName[2]); + for (int i = 0; i < 3; ++i) { - setValue(7 + i, field_342[i]); + setValue(7 + i, availableTracks[i]); } if (recorcStoreRecordId == -1) { try { - recorcStoreRecordId = recordStore->addRecord(field_278, 0, 19); + recorcStoreRecordId = recordStore->addRecord(savedData, 0, 19); } catch (RecordStoreNotOpenException& var2) { + std::cout << var2.what() << std::endl; } catch (RecordStoreException& var3) { + std::cout << var3.what() << std::endl; } } else { try { - recordStore->setRecord(recorcStoreRecordId, field_278, 0, 19); + recordStore->setRecord(recorcStoreRecordId, savedData, 0, 19); } catch (RecordStoreNotOpenException& var4) { + std::cout << var4.what() << std::endl; } catch (RecordStoreException& var5) { + std::cout << var5.what() << std::endl; } } } @@ -871,7 +878,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == settingStringPlayMenu) { settingStringLevel->setCurentOptionPos(field_354); - settingsStringTrack->setAvailableOptions(field_342[field_354]); + settingsStringTrack->setAvailableOptions(availableTracks[field_354]); settingsStringTrack->setCurentOptionPos(field_355); method_1(currentGameMenu->getGameMenu(), false); return; @@ -890,7 +897,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == field_333) { if (settingsStringLeague->getCurrentOptionPos() <= settingsStringLeague->getMaxAvailableOptionPos()) { settingStringLevel->setCurentOptionPos(field_354); - settingsStringTrack->setAvailableOptions(field_342[field_354]); + settingsStringTrack->setAvailableOptions(availableTracks[field_354]); settingsStringTrack->setCurentOptionPos(field_355); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); field_357 = true; @@ -930,7 +937,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == settingsStringTrack) { if (settingsStringTrack->method_114()) { - settingsStringTrack->setAvailableOptions(field_342[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->init(); field_299 = settingsStringTrack->getGameMenu(); method_1(field_299, false); @@ -949,7 +956,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) } settingsStringTrack->setOptionsList(micro->levelLoader->levelNames[settingStringLevel->getCurrentOptionPos()]); - settingsStringTrack->setAvailableOptions(field_342[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->setCurentOptionPos(field_345[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->init(); return; @@ -1013,39 +1020,39 @@ void MenuManager::method_215(int64_t var1) field_337 = var1; } -std::vector MenuManager::method_216(int var1, int8_t var2) +std::vector MenuManager::method_216(int var1, int8_t defaultValue) { switch (var1) { case 16: { - std::vector var3 = std::vector(3); + std::vector difficultySetting = std::vector(3); - for (int var4 = 0; var4 < 3; ++var4) { - var3[var4] = field_278[16 + var4]; + for (int idx = 0; idx < 3; ++idx) { + difficultySetting[idx] = savedData[16 + idx]; } - if (var3[0] == -127) { - var3[0] = var2; + if (difficultySetting[0] == -127) { + difficultySetting[0] = defaultValue; } - return var3; + return difficultySetting; } default: return std::vector(); } } -int8_t MenuManager::method_217(int var1, int8_t var2) +int8_t MenuManager::getSettingOrDefault(int idx, int8_t defaultValue) { - return field_278[var1] == -127 ? var2 : field_278[var1]; + return savedData[idx] == -127 ? defaultValue : savedData[idx]; } -void MenuManager::copyThreeBytesFromArr(int var1, char* var2) -{ - if (isRecordStoreOpened && var1 == 16) { - for (int i = 0; i < 3; ++i) { - field_278[16 + i] = var2[i]; - } - } -} +// void MenuManager::copyThreeBytesFromArr(int var1, char* var2) +// { +// if (isRecordStoreOpened && var1 == 16) { +// for (int i = 0; i < 3; ++i) { +// savedData[16 + i] = var2[i]; +// } +// } +// } std::string MenuManager::timeToString(int64_t time) { @@ -1076,7 +1083,7 @@ std::string MenuManager::timeToString(int64_t time) void MenuManager::setValue(int pos, int8_t value) { if (isRecordStoreOpened) { - field_278[pos] = value; + savedData[pos] = value; } } @@ -1093,13 +1100,11 @@ void MenuManager::exit() settingStringLevel->setAvailableOptions(1); settingsStringTrack->setCurentOptionPos(0); - field_341[0] = 65; - field_341[1] = 65; - field_341[2] = 65; + playerName = defaultName; inputSetting->setCurentOptionPos(0); - field_342[0] = 0; - field_342[1] = 0; - field_342[2] = -1; + availableTracks[0] = 0; + availableTracks[1] = 0; + availableTracks[2] = -1; availableLeagues = 0; method_208(); recordManager->deleteRecordStores(); diff --git a/src/MenuManager.h b/src/MenuManager.h index 45fae25..330d512 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -21,7 +21,7 @@ class IGameMenuElement; class MenuManager : public IMenuManager { private: - std::vector field_278; + std::vector savedData; Micro* micro; RecordManager* recordManager; Command* commandOk; @@ -82,11 +82,11 @@ class MenuManager : public IMenuManager { int field_338; int field_339; std::string field_340; - char* field_341; - char field_342[4]; - char defaultInputString[4] = "AAA"; + char* playerName; + char availableTracks[4]; + char defaultName[4] = "AAA"; int8_t availableLeagues = 0; - int8_t field_344 = 0; + int8_t availableLevels = 0; std::vector field_345 = { 0, 0, 0 }; std::vector> levelNames; std::vector leagueNames = std::vector(3); @@ -123,8 +123,8 @@ class MenuManager : public IMenuManager { void fillCanvasWithImage(Graphics* graphics); void processNonFireKeyCode(int keyCode); std::vector method_216(int var1, int8_t var2); - int8_t method_217(int var1, int8_t var2); - void copyThreeBytesFromArr(int var1, char* var2); + int8_t getSettingOrDefault(int var1, int8_t var2); + // void copyThreeBytesFromArr(int var1, char* var2); std::string timeToString(int64_t time); void setValue(int pos, int8_t value); void exit(); diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index 3a4f57d..9b51a26 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -7,6 +7,7 @@ void RecordManager::method_8(int var1, int var2) { + std::cout << "method_8 " << var1 << " " << var2 << std::endl; resetRecordsTime(); try { @@ -40,7 +41,7 @@ void RecordManager::method_8(int var1, int var2) } loadRecordInfo(var4); - recordEnum->destroy(); + // recordEnum->destroy(); } } @@ -161,13 +162,17 @@ void RecordManager::writeRecordInfo() try { packedRecordInfoRecordId = recordStore->addRecord(packedRecordInfo, 0, 96); } catch (RecordStoreNotOpenException& var1) { + return; } catch (RecordStoreException& var2) { + return; } } else { try { recordStore->setRecord(packedRecordInfoRecordId, packedRecordInfo, 0, 96); } catch (RecordStoreNotOpenException& var3) { + return; } catch (RecordStoreException& var4) { + return; } } } @@ -220,6 +225,7 @@ void RecordManager::deleteRecordStores() // RecordStore *var10000 = recordStore; RecordStore::deleteRecordStore(names[i]); } catch (RecordStoreException& var3) { + return; } } } @@ -232,6 +238,7 @@ void RecordManager::closeRecordStore() recordStore->closeRecordStore(); return; } catch (RecordStoreException& var1) { + return; } } } diff --git a/src/lcdui/CanvasImpl.cpp b/src/lcdui/CanvasImpl.cpp index 7f1c807..4f758dd 100644 --- a/src/lcdui/CanvasImpl.cpp +++ b/src/lcdui/CanvasImpl.cpp @@ -28,20 +28,20 @@ CanvasImpl::CanvasImpl(Canvas* canvas) 0, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - width, height, - SDL_WINDOW_SHOWN); + defaultWidth, defaultHeight, + SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP); if (!window) { throw std::runtime_error(SDL_GetError()); } - renderer = SDL_CreateRenderer( - window, -1, SDL_RENDERER_ACCELERATED); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (!renderer) { throw std::runtime_error(SDL_GetError()); } + SDL_GetRendererOutputSize(renderer, &windowWidth, &windowHeight); SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_RenderClear(renderer); } @@ -62,12 +62,20 @@ void CanvasImpl::repaint() int CanvasImpl::getWidth() { - return width; + if (windowWidth < 0) { + return defaultWidth; + } + + return windowWidth; } int CanvasImpl::getHeight() { - return height; + if (windowHeight < 0) { + return defaultHeight; + } + + return windowHeight; } SDL_Renderer* CanvasImpl::getRenderer() diff --git a/src/lcdui/CanvasImpl.h b/src/lcdui/CanvasImpl.h index 90c4763..481abd4 100644 --- a/src/lcdui/CanvasImpl.h +++ b/src/lcdui/CanvasImpl.h @@ -10,14 +10,17 @@ class Canvas; class CanvasImpl { private: + const int defaultWidth = 640; + const int defaultHeight = 480; + + int windowWidth = -1; + int windowHeight = -1; + Canvas* canvas; SDL_Window* window; SDL_Renderer* renderer; - const int width = 640; - const int height = 480; - static int convertKeyCharToKeyCode(SDL_Keycode keyCode); public: diff --git a/src/rms/RecordEnumerationImpl.cpp b/src/rms/RecordEnumerationImpl.cpp index 33880a0..45c2ac9 100644 --- a/src/rms/RecordEnumerationImpl.cpp +++ b/src/rms/RecordEnumerationImpl.cpp @@ -36,6 +36,7 @@ void RecordEnumerationImpl::setRecord(int index, std::vector bytes) if (static_cast(data.size()) <= index) { throw RecordStoreException(); } + data[index] = bytes; } @@ -49,6 +50,7 @@ int RecordEnumerationImpl::nextRecordId() if (currentPos >= static_cast(data.size())) { throw RecordStoreException(); } + return currentPos; } @@ -65,6 +67,7 @@ void RecordEnumerationImpl::serialize(FileStream* outStream) for (auto i = data.cbegin(); i != data.cend(); i++) { outStream->writeVariable(&(temp = i->size())); + for (auto j = i->cbegin(); j != i->cend(); j++) { int8_t buffer; outStream->writeVariable(&(buffer = *j)); @@ -82,6 +85,7 @@ void RecordEnumerationImpl::deserialize(FileStream* inStream) for (size_t i = 0; i < data.size(); ++i) { inStream->readVariable(&temp); data[i].resize(temp); + for (size_t j = 0; j < data[i].size(); ++j) { inStream->readVariable(&data[i][j]); } diff --git a/src/rms/RecordStore.cpp b/src/rms/RecordStore.cpp index 8237ee5..b6f32eb 100644 --- a/src/rms/RecordStore.cpp +++ b/src/rms/RecordStore.cpp @@ -40,10 +40,11 @@ void RecordStore::closeRecordStore() int RecordStore::addRecord(std::vector arr, int offset, int numBytes) { - log("addRecord()"); + log("addRecord(" + std::to_string(arr.size()) + "," + std::to_string(offset) + "," + std::to_string(numBytes) + ")"); assert(static_cast(arr.size()) == numBytes); assert(offset == 0); int id = records->addRecord(arr); + log("record id = " + std::to_string(id)); save(); return id; } @@ -72,6 +73,8 @@ RecordEnumerationImpl* RecordStore::load(std::filesystem::path filePath) RecordStore* RecordStore::openRecordStore(std::string name, bool createIfNecessary) { + log("openRecordStore(" + name + ", " + std::to_string(createIfNecessary) + ")"); + if (opened.find(name) == opened.end()) { opened[name] = createRecordStore(name, createIfNecessary); } @@ -95,6 +98,7 @@ std::unique_ptr RecordStore::createRecordStore(std::string name, bo rs->save(); return rs; } else { + log("can't create record, file is missing"); throw RecordStoreException(); } } From 356d6fabfe8f19b77fd951bf96fdfaa420ec23b6 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sun, 3 Nov 2024 11:40:42 +0200 Subject: [PATCH 02/16] changed cmake min version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8015864..fcc7d5f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.10) project(gravity_defied_cpp C CXX) set(CMAKE_VERBOSE_MAKEFILE TRUE) From 153f603901cf3d69ad365bd3a7085a526ff2584e Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sun, 3 Nov 2024 20:52:24 +0200 Subject: [PATCH 03/16] show FPS, added scaling to splash and logo, added global configs --- .gitignore | 1 + CMakeLists.txt | 7 +++- levels.mrg | Bin 0 -> 5123 bytes src/GameCanvas.cpp | 77 +++++++++++++++++++++++++------------- src/GameCanvas.h | 5 +-- src/GamePhysics.cpp | 1 - src/GamePhysics.h | 1 - src/LevelLoader.cpp | 13 ++++++- src/MenuManager.cpp | 14 +++---- src/Micro.cpp | 24 +++++++----- src/Micro.h | 22 +++++------ src/class_10.h | 1 - src/config.cpp | 11 ++++++ src/config.h | 18 +++++++++ src/lcdui/Canvas.cpp | 1 - src/lcdui/CanvasImpl.cpp | 13 ++++++- src/lcdui/FontStorage.cpp | 2 - src/lcdui/Graphics.cpp | 11 +++++- src/lcdui/Graphics.h | 1 + src/main.cpp | 1 - src/rms/RecordStore.cpp | 20 +++++++--- src/rms/RecordStore.h | 1 - src/tests/test_Graphics.h | 1 - src/tests/test_rms.cpp | 1 - src/utils/Hashing.cpp | 50 +++++++++++++++++++++++++ src/utils/Hashing.h | 14 +++++++ todo.md | 3 ++ 27 files changed, 238 insertions(+), 76 deletions(-) create mode 100644 levels.mrg create mode 100644 src/config.cpp create mode 100644 src/config.h create mode 100644 src/utils/Hashing.cpp create mode 100644 src/utils/Hashing.h create mode 100644 todo.md diff --git a/.gitignore b/.gitignore index 8038126..5350cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ GravityDefied Makefile cmake_install.cmake libAssets.a +saves diff --git a/CMakeLists.txt b/CMakeLists.txt index fcc7d5f..61cbbaa 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ if(WIN32) endif() find_package(PkgConfig REQUIRED) +find_package(OpenSSL REQUIRED) pkg_search_module(SDL2 REQUIRED IMPORTED_TARGET sdl2) pkg_search_module(SDL2_TTF REQUIRED IMPORTED_TARGET SDL2_ttf) @@ -21,7 +22,9 @@ pkg_search_module(SDL2_IMAGE REQUIRED IMPORTED_TARGET SDL2_image) # Create a sources variable with a link to all cpp files to compile set(SOURCES + src/config.cpp src/utils/Time.cpp + src/utils/Hashing.cpp src/utils/EmbedFileStream.cpp src/main.cpp src/MathF16.cpp @@ -98,14 +101,16 @@ if(WIN32) ${SDL2_STATIC_LIBRARIES} ${SDL2_TTF_STATIC_LIBRARIES} ${SDL2_IMAGE_STATIC_LIBRARIES} + OpenSSL::SSL Assets::Assets) else() target_link_libraries(GravityDefied ${SDL2_LIBRARIES} ${SDL2_TTF_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} + OpenSSL::SSL Assets::Assets) endif() # Copy assets to the build directory -file(COPY assets/levels.mrg DESTINATION ${CMAKE_BINARY_DIR}) +# file(COPY assets/levels.mrg DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/levels.mrg b/levels.mrg new file mode 100644 index 0000000000000000000000000000000000000000..e495c2a359c51ae3feb064f0f79e2f9a6ea7736e GIT binary patch literal 5123 zcmY*dX^>sjaqhdGyKnDqZ(nBLmp7x45E28DKtjlXB|tIQl0d?Yk!P@wO&mK_s>)Kh z5?3le;z}xIM|SLT65H6=CV(+S!r0g-ECLD12uY)5_KjKIn>TN}>4#jEqF?nreeS#G z^w-^|`<#0LKmwq?x?}k0kr6;?cK2f=M~;3KMf#!Lhew_`gc6h4a^%1xk01V6{_f7< zk;8|d#M|tit%nXhQ4=n1IXv{}qbPBAZXfyhG4A!dj|_c&X!yWkyvzUX?gL->N^Q=X zG9vC6J~%RR1bgI5yPp_({Lo`KrZ%CF**fyn@MA-VYlDQ7+fjJr@X!|@#-8}-u91U> zp8Ob?_xH=tns+nyr_hK7fRKfmwbf!b4{ zPwzQ0bl~v51E0s+kPX&G(X)7eT?#Kq9YIk2Yiyt1SxGN?W74=aWzU6kTZ`?WF&U0<_ljAvL4QJA)ut8@Sy4QA9PZhRO6|0#e`=jJ(4|43A?M2t^rT@K#e( z4WqHix`o(UlyOWioJ>g)vmizc;_yACG*vHW!kwXRD!`?48Yf-O2ERakKOP0xg%z3Otgx+VwDt-MTNJk9*-WB+8{w$Y)TM_k>U7$jpvmnmhYFd!Pyh=aj;sCe{2MX zE~p$s3(j<}GzYheHgUAnZ0meSHO$!sw`@ovrxqOECgEjqSt%HeWa;L%B%`ScRVqh zfG`X|7F14AWThR%pEIwrFOawSIc*EKoqm+IMbGpNBP7_AQ?QnVIpKRaNANt_zhbu5 z#B<0OlB6D5xwKH{i`-2h6*C_Q<;?}29!O<_@j(c3#{gRP-#}7_V;LOuSIE`B!OQc; zuj}c^j#k?LpaI$;5l(~n&+)Q2)WgZ&j1l;zXxW8LpFj3SjWq4Q0Kk!^gj7pA;Gwlh?YhC6-e-+O&Nw1>|ZZAC))c zeJ-j|?<(i`l<-q_8~3Jo8^0+k`WZi#_A}A6qhvhBU6L-^SE9wZE9)jBU5r%gNduR$ z+nfj!i&=FK^kjoyqNP7U`ZEp$zI7o<`)NJ9pqrWcXIB8U^- zn7?SzIu|i*UEwu~In@b7i-Vy0;Lp}kv8dB3h#F1LqY=R=j3HGM&Z6)w+S03};JxEd zyQL(UjITzih{+mpDk&qhxv_n|CccK^Gxb&9jq%~4OqrHySyqhPzSzel`)(4n zwf3|9bJH$uHa$7=YG-MFYW!zM7C4YD|@gVMKw zB1;3J=-EwNG;j1CNY`_Uuju(uh!`;1<&R^pM;)?+~X97pLPYWLhIK;JQdttos2X$vl`moQvCUweH+KK_RO z{w~H3)UuQ_=dD?NUMVoY(7Wwf|8i);n5SMPa;_L?C=la&P#T|uC-r-##X(@WT zzx_UEb2j+#F^pRZ;O-MOZ~(U>yxXw-(*0L%J>UP@Eth?!Ip4>$1a0*^y$Seg_b-U`YDMBkgU0bjeS;gN+OF&8+*NH%N zKaR+dFg+_D)Y>7c4O*xkAVu$DA1K8r7oo)n!!ooDT!k)@%l5cK^IZ`^)d|O!xmj}B z2GYgZ0!vEjQl=6*l?W78k#tTHc~J}thH#R)m1X6n`dRKh{v8c0jtnHVSVnMop7|{` z$a3CT^R)AOmtuTTt>+v0G^Ztaz7?7&Els#bXsjo=N*7PyQ6YsWk!oK32Cj_1ydxei ztiQjnkofjGNJB40SWa%Hd4|ZXG{+D%QjsfN_jq7~`djWgDah4kD&dQHwW1NTQ3ml+ zFC{H_fseaxL!Gi@q*>rrLUjxX%UT@^WXY^^1vzBOYM2m(d6?Y}I^{I-l(-!4;6VMT za~%&t{=s3~8utT45ZwA>ctPsMOl`;Z?7GY*y@5?H`fr#sQOB5x%W+mU!mIYAIpx1D zw}-$PZMNx;LX%=S9=695zEzepdR4X!+njVfomEW#eZh0)qE+3K{m59?a$7{YC(x!L)O{Emn6Zbj)*w74DFKgC~dN~J@qHDUAZ(&*bf$*PAd+i6B@@6^8*|HPTBcTY-ZCra$ z+uoMl_H_{>hKTa}0si7x4G+L(j99JUOx+jUe=0T8peHP2yd!9VtkSDm6H;I`bmZl$ z8pN9#BtbW6^<@eCaA(1q7s1VBx%34Ey#98H=mw?zObe7`63BHWh%~oS+!;A&y1QF; zzHd;C%>%2>r~-DXi|uE;j?Rj9O5r*lUys}3bNeB5SGeT_?w<)N2?DUW`+m51{5GIxn-r?p#p_#AawyN?(9E>nxf+tfL$ z%*KeYagko(XB3+DC}l?*vtnKj32HZ`eac`LqZ0~_+!3Nyn)nXFuI_r1Q+hA3;_U{# zcFQKVuoG*?|Bga1Gl-{WS>D<61ldI3QKoh=c z>?+WUcgJY`E|uVD=aUrQ-l!8?31ZxEF)=Gy=E~v7-qy5d-atJr$XkUa{Je zYw=2kj|%2l-Uxupv2X4F;FM8iO{t0f;JFeiIrkP zR8voBTm6vZ>){ya6Yf-UAsd`Nfxa6BxCyyNo6vVpA@s$kPTFTOo80Txn=R+k5Q9X$ znNX(XoN`f_&{feEu1WLh<#bt}Q|DAxBt}6gs(Jj0Set@4)zD_ zA6pE0{c(LhOcKfZYnC3x982Xo>s!V$nM6mjx%=fiu(Do4NR?v%UC1@shmbB}EAD-# zQSj`L5f&p=XV$&ugM%k4bv0J;D4nrb6A18SdW!mxd6}#U0v(}0O%sMEv{dGonP<5% zk|Q!5WujD=G8k3h2yQD(j>^*~nQ=ZZ@U+Th=pI(*IGz$pOpZIno{`H&S!Gp07c63M zMwu&cC*&8z905_*w)2CchzIbpyyiogI6{JMp@?Iw=Rfx=uvpG4>O~{f_l38JjnZ?6rNn^$L z^lM&D8~4lRFO`Z;)OG{kU>#Mp$u-i&tL{1Rx&vaFBjPF%<=4%k!wWB96l7;fdprD= zx)?5pc~4aZMGBebd8*q!&v%*Um3H|(y@P$nY^L6}n(MAL6}!RdkS;4-`WZQ4f3PvX zXZuFnOwOSJtAhaj$7=8aK811l4Ys}gW8w34te6weI;BW2Pw|E58;Nq9a#dXyLp&A9 zQIqt%q=_+}aAi6tuIMZEj5IDaXo^)8OI)7$(2bfz_=Wv`=!>QpI>~GjMB7$@nUyD< zO?p86z|2v1Ta5LrMj_;U=zlbj!X{@fD6y!aDK>AeSL#Mgshp(BE+69gBt;79zs6RqCqhSr`R1@EB zuBg|L=P_<~Pi%$$;%-dLkQjMS70@krD`dy>`oF{+s@l2-Mw?J4}Q55&c7_ zO0u0|w|n>AWkEWQF+u)W4KEU&^{TI9`|W+u2h4l@ z_<01|nO@-CUSQpJXn{81!u`M^GvW0>zl(Ld3;C^ec*^bv>g^_I26{XS)K%(tJAjVh zc1~IAm5gfYCegqfZww=Q@Bp(*x|@4L}`4 I-g^`LAMNqoy#N3J literal 0 HcmV?d00001 diff --git a/src/GameCanvas.cpp b/src/GameCanvas.cpp index 46aec65..a8e23ae 100644 --- a/src/GameCanvas.cpp +++ b/src/GameCanvas.cpp @@ -4,6 +4,8 @@ #include "MenuManager.h" #include "lcdui/Image.h" #include "lcdui/FontStorage.h" +#include "utils/Time.h" +#include "config.h" #include #include @@ -85,7 +87,7 @@ int GameCanvas::loadSprites(int flags) fenderImage = nullptr; engineImage = nullptr; } - + if (flags & 2) { if (!bodyPartsImages[1]) { bodyPartsImages[1] = std::make_unique("blueleg.png"); @@ -251,12 +253,12 @@ void GameCanvas::drawTime(int64_t time10Ms) if (time10Ms > 3600000L) { setColor(0, 0, 0); - graphics->drawString("0:00.", width - defaultFontWidth00, height2 - 5, 40); - graphics->drawString("00", width - defaultFontWidth00, height2 - 5, 36); + graphics->drawString("0:00.", width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 40); + graphics->drawString("00", width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 36); } else { setColor(0, 0, 0); - graphics->drawString(stringWithTime, width - defaultFontWidth00, height2 - 5, 40); - graphics->drawString(time10MsToStringCache[time10MsPart], width - defaultFontWidth00, height2 - 5, 36); + graphics->drawString(stringWithTime, width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 40); + graphics->drawString(time10MsToStringCache[time10MsPart], width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 36); } } @@ -384,7 +386,7 @@ void GameCanvas::setColor(int red, int green, int blue) void GameCanvas::drawGame(Graphics* g) { // synchronized (objectForSyncronization) { - if (Micro::field_249 && !micro->field_242) { + if (micro->gameStarted && !micro->gameDestroyed) { graphics = g; int var3; @@ -393,20 +395,33 @@ void GameCanvas::drawGame(Graphics* g) graphics->setColor(255, 255, 255); graphics->fillRect(0, 0, getWidth(), getHeight()); if (logoImage != nullptr) { - graphics->drawImage(logoImage.get(), getWidth() / 2, getHeight() / 2, 3); + graphics->drawImage( + logoImage.get(), + getWidth() / 2, + getHeight() / 2, + logoImage->getWidth() * GlobalSetting::LogoMultiplier, + logoImage->getHeight() * GlobalSetting::LogoMultiplier, + 3); drawSprite(graphics, 16, getWidth() - spriteSizeX[16] - 5, getHeight() - spriteSizeY[16] - 7); drawSprite(graphics, 17, getWidth() - spriteSizeX[17] - 4, getHeight() - spriteSizeY[17] - spriteSizeY[16] - 9); } } else { graphics->setColor(255, 255, 255); graphics->fillRect(0, 0, getWidth(), getHeight()); + if (splashImage != nullptr) { - graphics->drawImage(splashImage.get(), getWidth() / 2, getHeight() / 2, 3); + graphics->drawImage( + splashImage.get(), + getWidth() / 2, + getHeight() / 2, + splashImage->getWidth() * GlobalSetting::SplashMultiplier, + splashImage->getHeight() * GlobalSetting::SplashMultiplier, + 3); } } var3 = (int)(((int64_t)(Micro::gameLoadingStateStage << 16) << 32) / 655360L >> 16); - method_161(var3, true); + drawProgressBar(var3, true); } else { if (height != getHeight()) { updateSizeAndRepaint(); @@ -435,12 +450,12 @@ void GameCanvas::drawGame(Graphics* g) } // print fps to screen - // setColor(0, 0, 0); - // graphics->setFont(font); - // graphics->drawString("FPS: " + std::to_string(fps), defaultFontWidth00, height2 - 5, 36); + setColor(0, 0, 0); + graphics->setFont(font); + graphics->drawString("FPS: " + std::to_string(fps), defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 36); var3 = gamePhysics->method_52(); - method_161(var3, false); + drawProgressBar(var3, false); } graphics = nullptr; @@ -448,13 +463,23 @@ void GameCanvas::drawGame(Graphics* g) // } } -void GameCanvas::method_161(int var1, bool mode) +// draw progressbar +void GameCanvas::drawProgressBar(int var1, bool mode) { - int h = mode ? height : height2; + const int h = mode ? height : height2; + const int barX = 1; + const int barY = h - GlobalSetting::BarScreenOffset - GlobalSetting::BarH; + setColor(0, 0, 0); - graphics->fillRect(1, h - 4, width - 2, 3); + graphics->fillRect(barX, barY, width - (2 * barX), GlobalSetting::BarH); + setColor(255, 255, 255); - graphics->fillRect(2, h - 3, (int)((int64_t)((width - 4) << 16) * (int64_t)var1 >> 16) >> 16, 1); + const int loadingBarX = barX + GlobalSetting::LoadingBarPadding; + graphics->fillRect( + loadingBarX, + barY + GlobalSetting::LoadingBarPadding, + (int)((int64_t)((width - 2 * loadingBarX) << 16) * (int64_t)var1 >> 16) >> 16, + GlobalSetting::BarH - (2 * GlobalSetting::LoadingBarPadding)); } void GameCanvas::method_163(int var1) @@ -464,15 +489,15 @@ void GameCanvas::method_163(int var1) void GameCanvas::paint(Graphics* graphics) { - // static int64_t time = 0; - // int64_t now = Time::currentTimeMillis(); - // int64_t delta = now - time; - // time = now; - // if (delta != 0) { - // fps = 1000 / delta; - // // std::cout << "FPS: " << fps << std::endl; - // //setWindowTitle(std::string("Gravity Defied. FPS: ") + std::to_string(fps)); - // } + static int64_t time = 0; + int64_t now = Time::currentTimeMillis(); + int64_t delta = now - time; + time = now; + if (delta != 0) { + fps = 1000 / delta; + // std::cout << "FPS: " << fps << std::endl; + // setWindowTitle(std::string("Gravity Defied. FPS: ") + std::to_string(fps)); + } processTimers(); // We need to call this function as often as we can. It might be better to move this call somewhere. if (Micro::isInGameMenu && menuManager != nullptr) { diff --git a/src/GameCanvas.h b/src/GameCanvas.h index 9ab971c..cdc3941 100644 --- a/src/GameCanvas.h +++ b/src/GameCanvas.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include "lcdui/Graphics.h" @@ -66,7 +65,7 @@ class GameCanvas : public Canvas, public CommandListener { std::vector activeActions = std::vector(7); std::vector activeKeys = std::vector(10); - // int fps; + int fps; public: GameCanvas(Micro* micro); @@ -101,7 +100,7 @@ class GameCanvas : public Canvas, public CommandListener { void clearScreenWithWhite(); void setColor(int red, int green, int blue); void drawGame(Graphics* g); - void method_161(int var1, bool mode); + void drawProgressBar(int var1, bool mode); void method_163(int var1); void paint(Graphics* g); void init(GamePhysics* gamePhysics); diff --git a/src/GamePhysics.cpp b/src/GamePhysics.cpp index d776b18..169a6e7 100644 --- a/src/GamePhysics.cpp +++ b/src/GamePhysics.cpp @@ -3,7 +3,6 @@ #include "LevelLoader.h" #include "class_10.h" #include "MathF16.h" -#include GamePhysics::GamePhysics(LevelLoader* levelLoader) { diff --git a/src/GamePhysics.h b/src/GamePhysics.h index ed62c64..9cf1d5d 100644 --- a/src/GamePhysics.h +++ b/src/GamePhysics.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include "TimerOrMotoPartOrMenuElem.h" class LevelLoader; diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index fa3d73c..1bf607d 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -3,7 +3,6 @@ #include "utils/EmbedFileStream.h" #include -#include int LevelLoader::field_133 = 0; int LevelLoader::field_134 = 0; @@ -27,9 +26,11 @@ LevelLoader::LevelLoader(const std::filesystem::path& mrgFilePath) if (!mrgFilePath.string().empty()) { FileStream* fileStream = new FileStream(mrgFilePath, std::ios::in | std::ios::binary); + if (!fileStream->isOpen()) { throw std::system_error(errno, std::system_category(), "Failed to open " + mrgFilePath.string()); } + levelFileStream = fileStream; } else { EmbedFileStream* embedFileStream = new EmbedFileStream("levels.mrg"); @@ -62,6 +63,7 @@ void LevelLoader::loadLevels() for (int var8 = 0; var8 < 40; ++var8) { levelFileStream->readVariable(&var3[var8], true); + if (var3[var8] == 0) { std::string s = std::string(reinterpret_cast(var3.data()), var8); std::replace(s.begin(), s.end(), '_', ' '); @@ -142,6 +144,7 @@ void LevelLoader::method_96(GameLevel* gameLevel) field_131 = INT_MIN; this->gameLevel = gameLevel; int var2 = gameLevel->pointsCount; + if (field_121.empty() || field_132 < var2) { field_132 = var2 < 100 ? 100 : var2; field_121.assign(field_132, std::vector(2)); @@ -155,6 +158,7 @@ void LevelLoader::method_96(GameLevel* gameLevel) for (int var3 = 0; var3 < var2; ++var3) { int var4 = gameLevel->pointPositions[(var3 + 1) % var2][0] - gameLevel->pointPositions[var3][0]; int var5 = gameLevel->pointPositions[(var3 + 1) % var2][1] - gameLevel->pointPositions[var3][1]; + if (var3 != 0 && var3 != var2 - 1) { field_131 = field_131 < gameLevel->pointPositions[var3][0] ? gameLevel->pointPositions[var3][0] : field_131; } @@ -163,6 +167,7 @@ void LevelLoader::method_96(GameLevel* gameLevel) int var8 = GamePhysics::getSmthLikeMaxAbs(var6, var4); field_121[var3][0] = (int)(((int64_t)var6 << 32) / (int64_t)var8 >> 16); field_121[var3][1] = (int)(((int64_t)var4 << 32) / (int64_t)var8 >> 16); + if (gameLevel->startFlagPoint == 0 && gameLevel->pointPositions[var3][0] > gameLevel->startPosX) { gameLevel->startFlagPoint = var3 + 1; } @@ -206,6 +211,7 @@ void LevelLoader::method_100(int var1, int var2, int var3) var1 >>= 1; field_134 = field_134 < gameLevel->pointsCount - 1 ? field_134 : gameLevel->pointsCount - 1; field_133 = field_133 < 0 ? 0 : field_133; + if (var2 > field_136) { while (field_134 < gameLevel->pointsCount - 1 && var2 > gameLevel->pointPositions[++field_134][0]) { } @@ -236,6 +242,7 @@ int LevelLoader::method_101(TimerOrMotoPartOrMenuElem* var1, int var2) int8_t var17 = 2; int var18 = var1->xF16 >> 1; int var19 = var1->yF16 >> 1; + if (isEnabledPerspective) { var19 -= 65536; } @@ -247,6 +254,7 @@ int LevelLoader::method_101(TimerOrMotoPartOrMenuElem* var1, int var2) int var5 = gameLevel->pointPositions[var22][1]; int var6 = gameLevel->pointPositions[var22 + 1][0]; int var7; + if ((var7 = gameLevel->pointPositions[var22 + 1][1]) < var5) { ; } @@ -257,6 +265,7 @@ int LevelLoader::method_101(TimerOrMotoPartOrMenuElem* var1, int var2) int var10 = (int)((int64_t)var8 * (int64_t)var8 >> 16) + (int)((int64_t)var9 * (int64_t)var9 >> 16); int var11 = (int)((int64_t)(var18 - var4) * (int64_t)(-var8) >> 16) + (int)((int64_t)(var19 - var5) * (int64_t)(-var9) >> 16); int var12; + if ((var10 < 0 ? -var10 : var10) >= 3) { var12 = (int)(((int64_t)var11 << 32) / (int64_t)var10 >> 16); } else { @@ -277,6 +286,7 @@ int LevelLoader::method_101(TimerOrMotoPartOrMenuElem* var1, int var2) var9 = var19 - var14; int8_t var3; int64_t var23; + if ((var23 = ((int64_t)var8 * (int64_t)var8 >> 16) + ((int64_t)var9 * (int64_t)var9 >> 16)) < (int64_t)field_123[var2]) { if (var23 >= (int64_t)field_124[var2]) { var3 = 1; @@ -296,6 +306,7 @@ int LevelLoader::method_101(TimerOrMotoPartOrMenuElem* var1, int var2) if (var3 == 1 && (int)((int64_t)field_121[var22][0] * (int64_t)var1->field_382 >> 16) + (int)((int64_t)field_121[var22][1] * (int64_t)var1->field_383 >> 16) < 0) { ++var16; var17 = 1; + if (var16 == 1) { var20 = field_121[var22][0]; var21 = field_121[var22][1]; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index f6616ac..a0329ca 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -519,7 +519,7 @@ void MenuManager::method_201(int var1) micro->gamePhysics->method_53(); micro->gameToMenu(); - while (Micro::isInGameMenu && Micro::field_249 && currentGameMenu != nullptr) { + while (Micro::isInGameMenu && Micro::gameStarted && currentGameMenu != nullptr) { int64_t var20; if (micro->gamePhysics->isGenerateInputAI) { int var9; @@ -568,7 +568,7 @@ void MenuManager::method_201(int var1) micro->timeMs += Time::currentTimeMillis() - currentTimeMillis; micro->gameCanvas->isDrawingTime = true; if (currentGameMenu == nullptr) { - Micro::field_249 = false; + Micro::gameStarted = false; } } @@ -602,10 +602,10 @@ void MenuManager::processKeyCode(int keyCode) { if (currentGameMenu != nullptr) { switch (micro->gameCanvas->getGameAction(keyCode)) { - case 1: // UP + case Canvas::Keys::UP: // UP currentGameMenu->processGameActionUp(); return; - case 2: // LEFT + case Canvas::Keys::LEFT: // LEFT currentGameMenu->processGameActionUpd(3); if (currentGameMenu == gameMenuHighscore) { --field_360; @@ -620,7 +620,7 @@ void MenuManager::processKeyCode(int keyCode) case 7: default: break; - case 5: // RIGHT + case Canvas::Keys::RIGHT: // RIGHT currentGameMenu->processGameActionUpd(2); if (currentGameMenu == gameMenuHighscore) { ++field_360; @@ -632,10 +632,10 @@ void MenuManager::processKeyCode(int keyCode) return; } break; - case 6: // DOWN + case Canvas::Keys::DOWN: // DOWN currentGameMenu->processGameActionDown(); return; - case 8: // FIRE + case Canvas::Keys::FIRE: // FIRE currentGameMenu->processGameActionUpd(1); return; } diff --git a/src/Micro.cpp b/src/Micro.cpp index 13f1bee..67f7fd3 100644 --- a/src/Micro.cpp +++ b/src/Micro.cpp @@ -5,10 +5,12 @@ #include "MenuManager.h" #include "LevelLoader.h" #include "utils/Time.h" +#include "utils/Hashing.h" #include "lcdui/CanvasImpl.h" #include "rms/RecordStore.h" +#include "config.h" -bool Micro::field_249 = false; +bool Micro::gameStarted = false; int Micro::gameLoadingStateStage = 0; Micro::Micro() @@ -45,7 +47,7 @@ int64_t Micro::goLoadingStep() int64_t startTimeMillis = Time::currentTimeMillis(); switch (gameLoadingStateStage) { case 1: - levelLoader = new LevelLoader(mrgFilePath); + levelLoader = new LevelLoader(GlobalSetting::MrgFilePath); break; case 2: gamePhysics = new GamePhysics(levelLoader); @@ -138,8 +140,8 @@ void Micro::restart(bool var1) void Micro::destroyApp(bool var1) { (void)var1; - field_249 = false; - field_242 = true; + gameStarted = false; + gameDestroyed = true; menuManager->saveSmthToRecordStoreAndCloseIt(); } @@ -153,12 +155,16 @@ void Micro::startApp(int argc, char** argv) return; } - this->mrgFilePath = argv1; + GlobalSetting::MrgFilePath = argv1; } + std::cout << "path: " << GlobalSetting::MrgFilePath << std::endl; + GlobalSetting::SavesPrefix = Hashing::HashFileMD5(GlobalSetting::MrgFilePath.string()); + std::cout << "hash: " << GlobalSetting::SavesPrefix << std::endl; + RecordStore::setRecordStoreDir(argv[0]); - field_249 = true; + gameStarted = true; // if (thread == null) { // thread = new Thread(this); // thread.start(); @@ -182,7 +188,7 @@ void Micro::run() int64_t var3 = 0L; - while (field_249) { + while (gameStarted) { int var5; if (gamePhysics->method_21() != menuManager->method_210()) { var5 = gameCanvas->loadSprites(menuManager->method_210()); @@ -260,7 +266,7 @@ void Micro::run() restart(true); } - if (!field_249) { + if (!gameStarted) { break; } } @@ -268,7 +274,7 @@ void Micro::run() field_248 = var5 != 4; } - var10000 = field_249; + var10000 = gameStarted; } catch (std::exception& var15) { continue; } diff --git a/src/Micro.h b/src/Micro.h index 073617c..9fcceed 100644 --- a/src/Micro.h +++ b/src/Micro.h @@ -12,23 +12,23 @@ class Micro { private: int64_t goLoadingStep(); void destroyApp(bool var1); - std::filesystem::path mrgFilePath; public: - GameCanvas* gameCanvas; - LevelLoader* levelLoader; - GamePhysics* gamePhysics; - MenuManager* menuManager; - bool field_242 = false; + inline static bool isInGameMenu; + static bool gameStarted; + static int gameLoadingStateStage; + + bool gameDestroyed = false; + bool isInited = false; + bool field_248 = false; int numPhysicsLoops = 2; int64_t timeMs = 0; int64_t gameTimeMs = 0; int64_t field_246 = 0; - bool isInited = false; - bool field_248 = false; - static bool field_249; - inline static bool isInGameMenu; - static int gameLoadingStateStage; + GameCanvas* gameCanvas; + LevelLoader* levelLoader; + GamePhysics* gamePhysics; + MenuManager* menuManager; Micro(); ~Micro(); diff --git a/src/class_10.h b/src/class_10.h index b72d09f..736d77b 100644 --- a/src/class_10.h +++ b/src/class_10.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include "TimerOrMotoPartOrMenuElem.h" diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..2b74456 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,11 @@ +#include "config.h" + +bool GlobalSetting::WindowFullscreen = true; +uint8_t GlobalSetting::LogoMultiplier = 3; +uint8_t GlobalSetting::SplashMultiplier = 3; +uint8_t GlobalSetting::TimerFpsTextOffset = 14; +uint8_t GlobalSetting::LoadingBarPadding = 2; +uint8_t GlobalSetting::BarScreenOffset = 2; +uint8_t GlobalSetting::BarH = 10; +std::string GlobalSetting::SavesPrefix = ""; +std::filesystem::path GlobalSetting::MrgFilePath = "levels.mrg"; \ No newline at end of file diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..1230d17 --- /dev/null +++ b/src/config.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include + +struct GlobalSetting { + static bool WindowFullscreen; + static uint8_t LogoMultiplier; + static uint8_t SplashMultiplier; + static uint8_t TimerFpsTextOffset; + static uint8_t LoadingBarPadding; + static uint8_t BarScreenOffset; + static uint8_t BarH; + static std::string SavesPrefix; + static std::filesystem::path MrgFilePath; +}; \ No newline at end of file diff --git a/src/lcdui/Canvas.cpp b/src/lcdui/Canvas.cpp index db42151..209b489 100644 --- a/src/lcdui/Canvas.cpp +++ b/src/lcdui/Canvas.cpp @@ -1,7 +1,6 @@ #include "Canvas.h" #include -#include #include "CanvasImpl.h" #include "Graphics.h" diff --git a/src/lcdui/CanvasImpl.cpp b/src/lcdui/CanvasImpl.cpp index 4f758dd..2d8e1cb 100644 --- a/src/lcdui/CanvasImpl.cpp +++ b/src/lcdui/CanvasImpl.cpp @@ -7,6 +7,7 @@ #include #include "Canvas.h" +#include "../config.h" CanvasImpl::CanvasImpl(Canvas* canvas) { @@ -24,12 +25,18 @@ CanvasImpl::CanvasImpl(Canvas* canvas) throw std::runtime_error(TTF_GetError()); } + uint32_t windowFlags = SDL_WINDOW_SHOWN; + + if (GlobalSetting::WindowFullscreen) { + windowFlags = windowFlags | SDL_WINDOW_FULLSCREEN_DESKTOP; + } + window = SDL_CreateWindow( 0, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, defaultWidth, defaultHeight, - SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP); + windowFlags); if (!window) { throw std::runtime_error(SDL_GetError()); @@ -124,12 +131,16 @@ int CanvasImpl::convertKeyCharToKeyCode(SDL_Keycode keyCode) case SDLK_RETURN: return Canvas::Keys::FIRE; case SDLK_LEFT: + case SDLK_a: return Canvas::Keys::LEFT; case SDLK_RIGHT: + case SDLK_d: return Canvas::Keys::RIGHT; case SDLK_UP: + case SDLK_w: return Canvas::Keys::UP; case SDLK_DOWN: + case SDLK_s: return Canvas::Keys::DOWN; default: std::cout << "unknown keyEvent: " << keyCode << std::endl; diff --git a/src/lcdui/FontStorage.cpp b/src/lcdui/FontStorage.cpp index 068f8e3..4e6edd5 100644 --- a/src/lcdui/FontStorage.cpp +++ b/src/lcdui/FontStorage.cpp @@ -1,5 +1,3 @@ -#include - #include "Font.h" #include "FontStorage.h" diff --git a/src/lcdui/Graphics.cpp b/src/lcdui/Graphics.cpp index bbdf747..8dd8bfe 100644 --- a/src/lcdui/Graphics.cpp +++ b/src/lcdui/Graphics.cpp @@ -1,5 +1,4 @@ #include "Graphics.h" -#include Graphics::Graphics(SDL_Renderer* renderer) { @@ -243,6 +242,16 @@ void Graphics::drawImage(Image* const image, int x, int y, int anchor) SDL_DestroyTexture(texture); } +void Graphics::drawImage(Image* const image, int x, int y, int customW, int customH, int anchor) +{ + SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, image->getSurface()); + x = getAnchorX(x, customW, anchor); + y = getAnchorY(y, customH, anchor); + SDL_Rect dstRect { x, y, customW, customH }; + SDL_RenderCopy(renderer, texture, 0, &dstRect); + SDL_DestroyTexture(texture); +} + int Graphics::getAnchorX(int x, int size, int anchor) { if ((anchor & LEFT) != 0) { diff --git a/src/lcdui/Graphics.h b/src/lcdui/Graphics.h index 481e68c..1862cb7 100644 --- a/src/lcdui/Graphics.h +++ b/src/lcdui/Graphics.h @@ -45,6 +45,7 @@ class Graphics { void drawArc(int x, int y, int w, int h, int startAngle, int arcAngle); void drawLine(int x1, int y1, int x2, int y2); void drawImage(Image* const image, int x, int y, int anchor); + void drawImage(Image* const image, int x, int y, int w, int h, int anchor); static int getAnchorX(int x, int size, int anchor); static int getAnchorY(int y, int size, int anchor); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ff84b9b..f86da93 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/rms/RecordStore.cpp b/src/rms/RecordStore.cpp index b6f32eb..f8fa4bf 100644 --- a/src/rms/RecordStore.cpp +++ b/src/rms/RecordStore.cpp @@ -15,6 +15,7 @@ #endif #include "RecordStoreException.h" +#include "../config.h" #include "../utils/FileStream.h" #include "../utils/String.h" @@ -73,6 +74,13 @@ RecordEnumerationImpl* RecordStore::load(std::filesystem::path filePath) RecordStore* RecordStore::openRecordStore(std::string name, bool createIfNecessary) { + if (name.empty()) + { + log("empty name"); + return nullptr; + } + + name = GlobalSetting::SavesPrefix + "_" + name; log("openRecordStore(" + name + ", " + std::to_string(createIfNecessary) + ")"); if (opened.find(name) == opened.end()) { @@ -132,13 +140,13 @@ void RecordStore::setRecordStoreDir([[maybe_unused]] const char* progName) const char* base = dirname(strdup(progName)); recordStoreDir = std::filesystem::path(base) / "recordStore"; #else - const char* homeDir = getenv("HOME"); - if (!homeDir) - homeDir = getpwuid(getuid())->pw_dir; + // const char* homeDir = getenv("HOME"); + // if (!homeDir) + // homeDir = getpwuid(getuid())->pw_dir; - if (!homeDir) - throw std::system_error(errno, std::system_category(), "Error getting home directory"); + // if (!homeDir) + // throw std::system_error(errno, std::system_category(), "Error getting home directory"); - recordStoreDir = std::filesystem::path(homeDir) / ".GravityDefied"; + recordStoreDir = std::filesystem::path("./saves"); #endif } diff --git a/src/rms/RecordStore.h b/src/rms/RecordStore.h index 821c532..10e5007 100644 --- a/src/rms/RecordStore.h +++ b/src/rms/RecordStore.h @@ -2,7 +2,6 @@ #include #include -#include #include #include "RecordEnumerationImpl.h" diff --git a/src/tests/test_Graphics.h b/src/tests/test_Graphics.h index 369b6d2..4852021 100644 --- a/src/tests/test_Graphics.h +++ b/src/tests/test_Graphics.h @@ -3,7 +3,6 @@ #include #include #include -#include #include "../lcdui/Graphics.h" #include "../lcdui/Image.h" diff --git a/src/tests/test_rms.cpp b/src/tests/test_rms.cpp index 49c3a45..096a38c 100644 --- a/src/tests/test_rms.cpp +++ b/src/tests/test_rms.cpp @@ -1,6 +1,5 @@ #include "test_rms.h" -#include #include #include #include diff --git a/src/utils/Hashing.cpp b/src/utils/Hashing.cpp new file mode 100644 index 0000000..8d5e1f8 --- /dev/null +++ b/src/utils/Hashing.cpp @@ -0,0 +1,50 @@ +#include "Hashing.h" + +namespace Hashing { +std::string hexStr(const uint8_t* data, int len) +{ + std::stringstream ss; + ss << std::hex << std::setfill('0'); + + for (int i(0); i < len; ++i) + ss << std::setw(2) << (int)data[i]; + + return ss.str(); +} + +std::string HashFileMD5(const std::string& filename) +{ + std::ifstream file(filename, std::ios::binary); + + if (!file) { + throw std::runtime_error("Failed to open file: " + filename); + } + + EVP_MD_CTX* md5Context = EVP_MD_CTX_new(); + EVP_MD_CTX_init(md5Context); + EVP_DigestInit_ex(md5Context, EVP_md5(), nullptr); + + const size_t bufferSize = 4096; + char buffer[bufferSize]; + + while (!file.eof()) { + file.read(buffer, bufferSize); + EVP_DigestUpdate(md5Context, buffer, file.gcount()); + } + + std::array result; + EVP_DigestFinal_ex(md5Context, result.data(), nullptr); + file.close(); + + EVP_MD_CTX_free(md5Context); + + std::stringstream ss; + ss << std::hex << std::setfill('0'); + + for (const uint8_t i : result) { + ss << std::setw(2) << (int)i; + } + + return ss.str(); +} +} diff --git a/src/utils/Hashing.h b/src/utils/Hashing.h new file mode 100644 index 0000000..4c08278 --- /dev/null +++ b/src/utils/Hashing.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace Hashing { + std::string HashFileMD5(const std::string& filename); +}; \ No newline at end of file diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..9140dc9 --- /dev/null +++ b/todo.md @@ -0,0 +1,3 @@ +- [ ] scaling font +- [ ] fix another problem with saving highscore +- [ ] change keybinds \ No newline at end of file From ce10fc59a5840e3ca8b84da1bab5b7e2a1550a36 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Mon, 4 Nov 2024 21:50:27 +0200 Subject: [PATCH 04/16] code refactor --- src/GameCanvas.cpp | 37 ++--------------- src/GameCanvas.h | 3 -- src/MenuManager.cpp | 48 +++++----------------- src/MenuManager.h | 8 ++-- src/Micro.cpp | 9 ++++ src/RecordManager.cpp | 96 ++++++++++++++++++++++++++----------------- src/RecordManager.h | 25 +++++++++-- src/config.cpp | 2 +- src/utils/Time.cpp | 18 +++++++- src/utils/Time.h | 8 +++- 10 files changed, 130 insertions(+), 124 deletions(-) diff --git a/src/GameCanvas.cpp b/src/GameCanvas.cpp index a8e23ae..4bb2af2 100644 --- a/src/GameCanvas.cpp +++ b/src/GameCanvas.cpp @@ -226,40 +226,9 @@ void GameCanvas::drawHelmet(int x, int y, int angleF16) void GameCanvas::drawTime(int64_t time10Ms) { - int seconds = (int)(time10Ms / 100L); - int time10MsPart = (int)(time10Ms % 100L); - if (timeInSeconds != seconds || stringWithTime.empty()) { - std::string zeroPadding; - if (seconds % 60 >= 10) { - zeroPadding = ""; - } else { - zeroPadding = "0"; - } - - stringWithTime = std::to_string(seconds / 60) + ":" + zeroPadding + std::to_string(seconds % 60) + "."; - timeInSeconds = seconds; - } - - if (time10MsToStringCache[time10MsPart].empty()) { - std::string zeroPadding; - if (time10MsPart >= 10) { - zeroPadding = ""; - } else { - zeroPadding = "0"; - } - - time10MsToStringCache[time10MsPart] = zeroPadding + std::to_string(time10Ms % 100L); - } - - if (time10Ms > 3600000L) { - setColor(0, 0, 0); - graphics->drawString("0:00.", width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 40); - graphics->drawString("00", width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 36); - } else { - setColor(0, 0, 0); - graphics->drawString(stringWithTime, width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 40); - graphics->drawString(time10MsToStringCache[time10MsPart], width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 36); - } + const std::string timeStr = Time::timeToString(time10Ms); + setColor(0, 0, 0); + graphics->drawString(timeStr, width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 40); } void GameCanvas::method_150(int var1) diff --git a/src/GameCanvas.h b/src/GameCanvas.h index cdc3941..6d64736 100644 --- a/src/GameCanvas.h +++ b/src/GameCanvas.h @@ -52,9 +52,6 @@ class GameCanvas : public Canvas, public CommandListener { int timerId = 0; std::vector timers; Command* commandMenu; - inline static std::string stringWithTime = ""; - std::vector time10MsToStringCache = std::vector(100); - int timeInSeconds = -1; inline static int flagAnimationTime = 0; inline static int field_226 = 0; const int startFlagAnimationTimeToSpriteNo[4] = { 12, 10, 11, 10 }; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index a0329ca..69a286e 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -11,7 +11,6 @@ #include "SettingsStringRender.h" #include "utils/Time.h" - MenuManager::MenuManager(Micro* var1) { micro = var1; @@ -27,10 +26,8 @@ void MenuManager::initPart(int var1) field_374 = { "On", "Off" }; field_375 = { "Keyset 1", "Keyset 2", "Keyset 3" }; recordManager = new RecordManager(); - field_337 = -1L; - field_338 = -1; - field_339 = -1; - field_340.clear(); + trackTimeMs = -1L; + trackTimeFormatted.clear(); isRecordStoreOpened = false; savedData = std::vector(19); @@ -155,7 +152,7 @@ void MenuManager::initPart(int var1) settingStringGoToMain = new SettingsStringRender("Go to Main", 0, this, std::vector(), false, micro, gameMenuMain, true); settingStringContinue = new SettingsStringRender("Continue", 0, this, std::vector(), false, micro, gameMenuMain, true); settingStringPlayMenu = new SettingsStringRender("Play Menu", 0, this, std::vector(), false, micro, gameMenuMain, true); - + std::shared_ptr boldSmallFont = FontStorage::getFont(Font::STYLE_BOLD, Font::SIZE_SMALL); if (gameMenuAbout->xPos + boldSmallFont->stringWidth("http://www.codebrew.se/") >= getCanvasWidth()) { textRenderCodeBrewLink = new TextRender("www.codebrew.se", micro); @@ -345,11 +342,12 @@ bool MenuManager::method_196() void MenuManager::method_197() { - recordManager->method_17(settingsStringLeague->getCurrentOptionPos(), playerName, field_337); + std::cout << "method_197 " << playerName << " " << trackTimeMs << std::endl; + recordManager->method_17(settingsStringLeague->getCurrentOptionPos(), playerName, trackTimeMs); recordManager->writeRecordInfo(); field_356 = false; gameMenuFinished->clearVector(); - gameMenuFinished->addMenuElement(new TextRender("Time: " + field_340, micro)); + gameMenuFinished->addMenuElement(new TextRender("Time: " + trackTimeFormatted, micro)); std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); for (std::size_t var2 = 0; var2 < var1.size(); ++var2) { @@ -476,8 +474,8 @@ void MenuManager::method_201(int var1) field_354 = settingStringLevel->getCurrentOptionPos(); field_355 = settingsStringTrack->getCurrentOptionPos(); recordManager->method_8(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); - int var2 = recordManager->getPosOfNewRecord(settingsStringLeague->getCurrentOptionPos(), field_337); - field_340 = timeToString(field_337); + int var2 = recordManager->getPosOfNewRecord(settingsStringLeague->getCurrentOptionPos(), trackTimeMs); + trackTimeFormatted = Time::timeToString(trackTimeMs); if (var2 >= 0 && var2 <= 2) { TextRender* var3 = new TextRender("", micro); var3->setDx(GameCanvas::spriteSizeX[5] + 1); @@ -496,7 +494,7 @@ void MenuManager::method_201(int var1) } gameMenuFinished->addMenuElement(var3); - TextRender* var4 = new TextRender("" + field_340, micro); + TextRender* var4 = new TextRender(trackTimeFormatted, micro); var4->setDx(GameCanvas::spriteSizeX[5] + 1); gameMenuFinished->addMenuElement(var4); gameMenuFinished->addMenuElement(field_335); @@ -1017,7 +1015,7 @@ int MenuManager::method_214() void MenuManager::method_215(int64_t var1) { - field_337 = var1; + trackTimeMs = var1; } std::vector MenuManager::method_216(int var1, int8_t defaultValue) @@ -1054,32 +1052,6 @@ int8_t MenuManager::getSettingOrDefault(int idx, int8_t defaultValue) // } // } -std::string MenuManager::timeToString(int64_t time) -{ - field_338 = (int)(time / 100L); - field_339 = (int)(time % 100L); - std::string timeStr; - if (field_338 / 60 < 10) { - timeStr = " 0" + std::to_string(field_338 / 60); - } else { - timeStr = " " + std::to_string(field_338 / 60); - } - - if (field_338 % 60 < 10) { - timeStr = timeStr + ":0" + std::to_string(field_338 % 60); - } else { - timeStr = timeStr + ":" + std::to_string(field_338 % 60); - } - - if (field_339 < 10) { - timeStr = timeStr + ".0" + std::to_string(field_339); - } else { - timeStr = timeStr + "." + std::to_string(field_339); - } - - return timeStr; -} - void MenuManager::setValue(int pos, int8_t value) { if (isRecordStoreOpened) { diff --git a/src/MenuManager.h b/src/MenuManager.h index 330d512..f4335f0 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -78,10 +78,8 @@ class MenuManager : public IMenuManager { SettingsStringRender* field_334; SettingsStringRender* field_335; SettingsStringRender* field_336; - int64_t field_337; - int field_338; - int field_339; - std::string field_340; + int64_t trackTimeMs; + std::string trackTimeFormatted; char* playerName; char availableTracks[4]; char defaultName[4] = "AAA"; @@ -125,7 +123,7 @@ class MenuManager : public IMenuManager { std::vector method_216(int var1, int8_t var2); int8_t getSettingOrDefault(int var1, int8_t var2); // void copyThreeBytesFromArr(int var1, char* var2); - std::string timeToString(int64_t time); + // std::string timeToString(int64_t time); void setValue(int pos, int8_t value); void exit(); int getCountOfRecordStoresWithPrefix(int prefixNumber); diff --git a/src/Micro.cpp b/src/Micro.cpp index 67f7fd3..01fc2d6 100644 --- a/src/Micro.cpp +++ b/src/Micro.cpp @@ -182,6 +182,7 @@ void Micro::run() gameCanvas->setCommandListener(gameCanvas); restart(false); menuManager->method_201(0); + if (menuManager->method_196()) { restart(true); } @@ -190,6 +191,7 @@ void Micro::run() while (gameStarted) { int var5; + if (gamePhysics->method_21() != menuManager->method_210()) { var5 = gameCanvas->loadSprites(menuManager->method_210()); gamePhysics->method_22(var5); @@ -200,6 +202,7 @@ void Micro::run() try { if (isInGameMenu) { menuManager->method_201(1); + if (menuManager->method_196()) { restart(true); } @@ -242,6 +245,7 @@ void Micro::run() // } catch (InterruptedException var12) { // } int64_t var7 = 1000L; + if (field_246 > 0L) { var7 = std::min(field_246 - Time::currentTimeMillis(), static_cast(1000)); } @@ -262,6 +266,7 @@ void Micro::run() goalLoop(); menuManager->method_215(gameTimeMs / 10L); menuManager->method_201(2); + if (menuManager->method_196()) { restart(true); } @@ -286,6 +291,7 @@ void Micro::run() try { gamePhysics->method_53(); int64_t var1; + if ((var1 = Time::currentTimeMillis()) - var3 < 30L) { // try { // synchronized (this) { @@ -311,6 +317,7 @@ void Micro::run() void Micro::goalLoop() { int64_t var4 = 0L; + if (!gamePhysics->field_69) { gameCanvas->scheduleGameTimerTask("Wheelie!", 1000); } else { @@ -336,6 +343,7 @@ void Micro::goalLoop() // return; // } int64_t deltaTime; + if ((deltaTime = timeMs - Time::currentTimeMillis()) > 0L) { Time::sleep(deltaTime); } @@ -346,6 +354,7 @@ void Micro::goalLoop() gamePhysics->method_53(); int64_t var2; + if ((var2 = Time::currentTimeMillis()) - var4 < 30L) { // try { // synchronized (this) { diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index 9b51a26..9d659a3 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -5,13 +5,19 @@ #include "rms/RecordStoreNotOpenException.h" #include "rms/InvalidRecordIDException.h" -void RecordManager::method_8(int var1, int var2) +// method_8 0 9 +// openRecordStore(ecff3f91391c012620ea3f638ef4f21d_09, 1) +// createRecordStore(ecff3f91391c012620ea3f638ef4f21d_09, 1) +// enumerateRecords() +// method_197 AAA 2476 + +void RecordManager::method_8(const int level, const int track) { - std::cout << "method_8 " << var1 << " " << var2 << std::endl; + std::cout << "method_8 " << level << track << std::endl; resetRecordsTime(); try { - str = std::to_string(var1) + std::to_string(var2); + const std::string str = std::to_string(level) + std::to_string(track); recordStore = RecordStore::openRecordStore(str, true); } catch (RecordStoreException& var9) { return; @@ -70,9 +76,9 @@ void RecordManager::pushLongAs5Bytes(std::vector var1, int var2, int64_t void RecordManager::loadRecordInfo(std::vector var1) { int offset = 0; - int league; int pos; + for (league = 0; league < 4; ++league) { for (pos = 0; pos < 3; ++pos) { recordTimeMs[league][pos] = load5BytesAsLong(var1, offset); @@ -92,9 +98,9 @@ void RecordManager::loadRecordInfo(std::vector var1) void RecordManager::getLevelInfo(std::vector var1) { int shift = 0; + uint8_t league; + uint8_t recordNo; - int league; - int recordNo; for (league = 0; league < 4; ++league) { for (recordNo = 0; recordNo < 3; ++recordNo) { pushLongAs5Bytes(var1, shift, recordTimeMs[league][recordNo]); @@ -120,44 +126,49 @@ void RecordManager::resetRecordsTime() } } -std::vector RecordManager::getRecordDescription(int var1) +std::vector RecordManager::getRecordDescription(const int league) { - std::vector var2 = std::vector(3); - - for (int var3 = 0; var3 < 3; ++var3) { - if (recordTimeMs[var1][var3] != 0L) { - int var4 = (int)recordTimeMs[var1][var3] / 100; - int var5 = (int)recordTimeMs[var1][var3] % 100; - var2[var3] = "" + std::string(recordName[var1][var3]) + " "; - - if (var4 / 60 < 10) { - var2[var3] = var2[var3] + " 0" + std::to_string(var4 / 60); - } else { - var2[var3] = var2[var3] + " " + std::to_string(var4 / 60); - } - - if (var4 % 60 < 10) { - var2[var3] = var2[var3] + ":0" + std::to_string(var4 % 60); - } else { - var2[var3] = var2[var3] + ":" + std::to_string(var4 % 60); - } - - if (var5 < 10) { - var2[var3] = var2[var3] + ".0" + std::to_string(var5); - } else { - var2[var3] = var2[var3] + "." + std::to_string(var5); - } + std::vector recordsDescription = std::vector(3); + + for (uint8_t record_number = 0; record_number < 3; ++record_number) { + if (recordTimeMs[league][record_number] != 0L) { + std::stringstream ss; + ss << recordName[league][record_number] << ' ' + << Time::timeToString(recordTimeMs[league][record_number]); + recordsDescription[record_number] = ss.str(); + // int var4 = (int)recordTimeMs[var1][var3] / 100; + // int var5 = (int)recordTimeMs[var1][var3] % 100; + // var2[var3] = "" + std::string(recordName[var1][var3]) + " "; + + // if (var4 / 60 < 10) { + // var2[var3] = var2[var3] + " 0" + std::to_string(var4 / 60); + // } else { + // var2[var3] = var2[var3] + " " + std::to_string(var4 / 60); + // } + + // if (var4 % 60 < 10) { + // var2[var3] = var2[var3] + ":0" + std::to_string(var4 % 60); + // } else { + // var2[var3] = var2[var3] + ":" + std::to_string(var4 % 60); + // } + + // if (var5 < 10) { + // var2[var3] = var2[var3] + ".0" + std::to_string(var5); + // } else { + // var2[var3] = var2[var3] + "." + std::to_string(var5); + // } } else { - var2[var3].clear(); + recordsDescription[record_number].clear(); } } - return var2; + return recordsDescription; } void RecordManager::writeRecordInfo() { getLevelInfo(packedRecordInfo); + if (packedRecordInfoRecordId == -1) { try { packedRecordInfoRecordId = recordStore->addRecord(packedRecordInfo, 0, 96); @@ -188,10 +199,13 @@ int RecordManager::getPosOfNewRecord(int league, int64_t timeMs) return 3; } -void RecordManager::method_17(int league, char* values, int64_t timeMs) +void RecordManager::method_17(int league, char* playerName, int64_t timeMs) { - int newRecordPos; - if ((newRecordPos = getPosOfNewRecord(league, timeMs)) != 3) { + std::cout << "method_17 " << league << " " << playerName << " " << timeMs << std::endl; + const int newRecordPos = getPosOfNewRecord(league, timeMs); + std::cout << "record pos " << newRecordPos << std::endl; + + if (newRecordPos < 3) { if (timeMs > 16777000L) { timeMs = 16777000L; // 3 int8_ts, not five, wtf? } @@ -200,13 +214,19 @@ void RecordManager::method_17(int league, char* values, int64_t timeMs) recordTimeMs[league][newRecordPos] = timeMs; for (auto i = 0; i < PLAYER_NAME_MAX; ++i) { - recordName[league][newRecordPos][i] = values[i]; + recordName[league][newRecordPos][i] = playerName[i]; } } } void RecordManager::addNewRecord(int gameLevel, int position) { + if (position <= 0) { + return; + } + + std::cout << "addNewRecord " << gameLevel << " " << position << std::endl; + for (auto pos = 2; pos > position; --pos) { recordTimeMs[gameLevel][pos] = recordTimeMs[gameLevel][pos - 1]; for (auto i = 0; i < PLAYER_NAME_MAX; ++i) { diff --git a/src/RecordManager.h b/src/RecordManager.h index d4cc618..d46fc02 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -4,6 +4,8 @@ #include #include +#include "utils/Time.h" + class RecordStore; class RecordManager { @@ -16,8 +18,8 @@ class RecordManager { inline static const int unused = 3; - void method_8(int var1, int var2); - std::vector getRecordDescription(int var1); + void method_8(const int level, const int track); + std::vector getRecordDescription(const int league); void writeRecordInfo(); int getPosOfNewRecord(int league, int64_t timeMs); void method_17(int league, char* values, int64_t timeMs); @@ -25,6 +27,24 @@ class RecordManager { void closeRecordStore(); private: + // struct Record { + // int64_t timeMs; + // // uint8_t timeMs[5]; + // char playerName[3]; + // }; + // static_assert(sizeof(Record) == 16); + + // struct LeagueRecords { + // Record records[3]; + // }; + // struct RecordsSaveData { + // LeagueRecords leagueRecors[4]; + // }; + + // static_assert(sizeof(char[4]) == 4); + // static_assert(sizeof(int64_t) == 8); + // static_assert(sizeof(RecordsSaveData) == 96); + std::vector> recordTimeMs = std::vector>(4, std::vector(3)); // 4: league, 100, 175, 225, 350, // 3: three best times @@ -32,7 +52,6 @@ class RecordManager { RecordStore* recordStore = nullptr; int packedRecordInfoRecordId = -1; std::vector packedRecordInfo = std::vector(96); - std::string str; int64_t load5BytesAsLong(std::vector var1, int offset); void pushLongAs5Bytes(std::vector var1, int var2, int64_t var3); diff --git a/src/config.cpp b/src/config.cpp index 2b74456..07e39a0 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,6 +1,6 @@ #include "config.h" -bool GlobalSetting::WindowFullscreen = true; +bool GlobalSetting::WindowFullscreen = false; uint8_t GlobalSetting::LogoMultiplier = 3; uint8_t GlobalSetting::SplashMultiplier = 3; uint8_t GlobalSetting::TimerFpsTextOffset = 14; diff --git a/src/utils/Time.cpp b/src/utils/Time.cpp index d8c2c4d..5b34818 100644 --- a/src/utils/Time.cpp +++ b/src/utils/Time.cpp @@ -1,4 +1,4 @@ -#include "time.h" +#include "Time.h" #include #include @@ -10,6 +10,22 @@ int64_t currentTimeMillis() std::chrono::system_clock::now().time_since_epoch()).count(); } +std::string timeToString(const int64_t time) +{ + const int minutes = (int)(time / 100L / 60L); + const int seconds = (int)(time / 100L % 60L); + const int subseconds = (int)(time % 100L); + + std::stringstream ss; + ss << std::setfill('0') + << std::setw(2) << minutes + << ':' + << std::setw(2) << seconds + << '.' + << std::setw(2) << subseconds; + return ss.str(); +} + void sleep(int64_t ms) { SDL_Delay(ms); diff --git a/src/utils/Time.h b/src/utils/Time.h index 328f3d1..9da5fa7 100644 --- a/src/utils/Time.h +++ b/src/utils/Time.h @@ -1,8 +1,14 @@ #pragma once -#include +#include +#include +#include +#include +#include +#include namespace Time { int64_t currentTimeMillis(); +std::string timeToString(const int64_t time); void sleep(int64_t ms); }; \ No newline at end of file From 709daf84d41581fb3f427060910bdfd17ca1a823 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Mon, 4 Nov 2024 23:35:54 +0200 Subject: [PATCH 05/16] rewrote RecordManager in a c/c++ way --- src/LevelLoader.cpp | 5 ++ src/MenuManager.cpp | 6 +- src/RecordManager.cpp | 189 ++++++++++++--------------------------- src/RecordManager.h | 60 ++++++------- src/config.cpp | 3 + src/config.h | 3 + src/lcdui/CanvasImpl.cpp | 6 +- src/lcdui/CanvasImpl.h | 3 - 8 files changed, 103 insertions(+), 172 deletions(-) diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index 1bf607d..beb7f4f 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -87,8 +87,10 @@ void LevelLoader::method_87() int LevelLoader::method_88(int var1, int var2) { + std::cout << "method_88 " << var1 << " " << var2 << std::endl; field_125 = var1; field_126 = var2; + if (field_126 >= static_cast(levelNames[field_125].size())) { field_126 = 0; } @@ -99,10 +101,13 @@ int LevelLoader::method_88(int var1, int var2) void LevelLoader::method_89(int var1, int var2) { + std::cout << "method_89 " << var1 << " " << var2 << std::endl; levelFileStream->setPos(levelOffsetInFile[var1 - 1][var2 - 1]); + if (gameLevel == nullptr) { gameLevel = new GameLevel(); } + gameLevel->load(levelFileStream); method_96(gameLevel); } diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 69a286e..828bb6c 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -10,6 +10,7 @@ #include "GameMenu.h" #include "SettingsStringRender.h" #include "utils/Time.h" +#include "config.h" MenuManager::MenuManager(Micro* var1) { @@ -36,7 +37,7 @@ void MenuManager::initPart(int var1) } try { - recordStore = RecordStore::openRecordStore("GDTRStates", true); + recordStore = RecordStore::openRecordStore(GlobalSetting::GlobalSaveFileName, true); isRecordStoreOpened = true; return; } catch (RecordStoreException& var9) { @@ -474,8 +475,9 @@ void MenuManager::method_201(int var1) field_354 = settingStringLevel->getCurrentOptionPos(); field_355 = settingsStringTrack->getCurrentOptionPos(); recordManager->method_8(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); - int var2 = recordManager->getPosOfNewRecord(settingsStringLeague->getCurrentOptionPos(), trackTimeMs); + const uint8_t var2 = recordManager->getPosOfNewRecord(settingsStringLeague->getCurrentOptionPos(), trackTimeMs); trackTimeFormatted = Time::timeToString(trackTimeMs); + if (var2 >= 0 && var2 <= 2) { TextRender* var3 = new TextRender("", micro); var3->setDx(GameCanvas::spriteSizeX[5] + 1); diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index 9d659a3..a02ada8 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -5,19 +5,14 @@ #include "rms/RecordStoreNotOpenException.h" #include "rms/InvalidRecordIDException.h" -// method_8 0 9 -// openRecordStore(ecff3f91391c012620ea3f638ef4f21d_09, 1) -// createRecordStore(ecff3f91391c012620ea3f638ef4f21d_09, 1) -// enumerateRecords() -// method_197 AAA 2476 - -void RecordManager::method_8(const int level, const int track) +void RecordManager::method_8(const uint8_t level, const uint8_t track) { - std::cout << "method_8 " << level << track << std::endl; + std::cout << "method_8 " << (int)level << (int)track << std::endl; resetRecordsTime(); try { const std::string str = std::to_string(level) + std::to_string(track); + std::cout << "str " << str << std::endl; recordStore = RecordStore::openRecordStore(str, true); } catch (RecordStoreException& var9) { return; @@ -33,9 +28,9 @@ void RecordManager::method_8(const int level, const int track) } if (recordEnum->numRecords() > 0) { - std::vector var4; + std::vector saveFileBytes; try { - var4 = recordEnum->nextRecord(); + saveFileBytes = recordEnum->nextRecord(); recordEnum->reset(); packedRecordInfoRecordId = recordEnum->nextRecordId(); } catch (RecordStoreNotOpenException& var5) { @@ -46,119 +41,40 @@ void RecordManager::method_8(const int level, const int track) return; } - loadRecordInfo(var4); + loadRecordInfo(saveFileBytes); // recordEnum->destroy(); } } -int64_t RecordManager::load5BytesAsLong(std::vector var1, int offset) +void RecordManager::loadRecordInfo(std::vector dataBytes) { - int64_t result = 0L; - int64_t mult = 1L; - - for (int var7 = offset; var7 < 5 + offset; ++var7) { - int var8 = (var1[var7] + 256) % 256; - result += mult * (int64_t)var8; - mult *= 256L; - } - - return result; -} - -void RecordManager::pushLongAs5Bytes(std::vector var1, int var2, int64_t var3) -{ - for (int var5 = var2; var5 < 5 + var2; ++var5) { - var1[var5] = (int8_t)((int)(var3 % 256L)); - var3 /= 256L; - } -} - -void RecordManager::loadRecordInfo(std::vector var1) -{ - int offset = 0; - int league; - int pos; - - for (league = 0; league < 4; ++league) { - for (pos = 0; pos < 3; ++pos) { - recordTimeMs[league][pos] = load5BytesAsLong(var1, offset); - offset += 5; - } - } - - for (league = 0; league < LEAGUES_MAX; ++league) { - for (pos = 0; pos < RECORD_NO_MAX; ++pos) { - for (auto i = 0; i < PLAYER_NAME_MAX; ++i) { - recordName[league][pos][i] = var1[offset++]; - } - } - } -} - -void RecordManager::getLevelInfo(std::vector var1) -{ - int shift = 0; - uint8_t league; - uint8_t recordNo; - - for (league = 0; league < 4; ++league) { - for (recordNo = 0; recordNo < 3; ++recordNo) { - pushLongAs5Bytes(var1, shift, recordTimeMs[league][recordNo]); - shift += 5; - } - } - - for (league = 0; league < LEAGUES_MAX; ++league) { - for (recordNo = 0; recordNo < RECORD_NO_MAX; ++recordNo) { - for (auto i = 0; i < PLAYER_NAME_MAX; ++i) { - var1[shift++] = recordName[league][recordNo][i]; - } - } - } + RecordsSaveDataConverter converter; + std::copy(dataBytes.begin(), dataBytes.end(), converter.bytes); + recordsSaveData = converter.recordsSaveData; } void RecordManager::resetRecordsTime() { - for (int league = 0; league < 4; ++league) { - for (int pos = 0; pos < 3; ++pos) { - recordTimeMs[league][pos] = 0L; + for (uint8_t league = 0; league < LEAGUES_MAX; ++league) { + for (uint8_t pos = 0; pos < RECORD_NO_MAX; ++pos) { + recordsSaveData.leagueRecords[league].records[pos].timeMs = 0L; } } } -std::vector RecordManager::getRecordDescription(const int league) +std::vector RecordManager::getRecordDescription(const uint8_t league) { - std::vector recordsDescription = std::vector(3); - - for (uint8_t record_number = 0; record_number < 3; ++record_number) { - if (recordTimeMs[league][record_number] != 0L) { - std::stringstream ss; - ss << recordName[league][record_number] << ' ' - << Time::timeToString(recordTimeMs[league][record_number]); - recordsDescription[record_number] = ss.str(); - // int var4 = (int)recordTimeMs[var1][var3] / 100; - // int var5 = (int)recordTimeMs[var1][var3] % 100; - // var2[var3] = "" + std::string(recordName[var1][var3]) + " "; - - // if (var4 / 60 < 10) { - // var2[var3] = var2[var3] + " 0" + std::to_string(var4 / 60); - // } else { - // var2[var3] = var2[var3] + " " + std::to_string(var4 / 60); - // } + std::vector recordsDescription = std::vector(RECORD_NO_MAX); - // if (var4 % 60 < 10) { - // var2[var3] = var2[var3] + ":0" + std::to_string(var4 % 60); - // } else { - // var2[var3] = var2[var3] + ":" + std::to_string(var4 % 60); - // } + for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { + Record record = recordsSaveData.leagueRecords[league].records[i]; - // if (var5 < 10) { - // var2[var3] = var2[var3] + ".0" + std::to_string(var5); - // } else { - // var2[var3] = var2[var3] + "." + std::to_string(var5); - // } + if (record.timeMs != 0L) { + std::stringstream ss; + ss << record.playerName << ' ' << Time::timeToString(record.timeMs); + recordsDescription[i] = ss.str(); } else { - recordsDescription[record_number].clear(); + recordsDescription[i].clear(); } } @@ -167,7 +83,10 @@ std::vector RecordManager::getRecordDescription(const int league) void RecordManager::writeRecordInfo() { - getLevelInfo(packedRecordInfo); + RecordsSaveDataConverter converter = { + .recordsSaveData = recordsSaveData + }; + std::vector packedRecordInfo(std::begin(converter.bytes), std::end(converter.bytes)); if (packedRecordInfoRecordId == -1) { try { @@ -188,10 +107,12 @@ void RecordManager::writeRecordInfo() } } -int RecordManager::getPosOfNewRecord(int league, int64_t timeMs) +uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t timeMs) { - for (int i = 0; i < 3; ++i) { - if (recordTimeMs[league][i] > timeMs || recordTimeMs[league][i] == 0L) { + for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { + const Record record = recordsSaveData.leagueRecords[league].records[i]; + + if (record.timeMs > timeMs || record.timeMs <= 0L) { return i; } } @@ -199,38 +120,39 @@ int RecordManager::getPosOfNewRecord(int league, int64_t timeMs) return 3; } -void RecordManager::method_17(int league, char* playerName, int64_t timeMs) +void RecordManager::method_17(const uint8_t league, char* playerName, int64_t timeMs) { - std::cout << "method_17 " << league << " " << playerName << " " << timeMs << std::endl; - const int newRecordPos = getPosOfNewRecord(league, timeMs); - std::cout << "record pos " << newRecordPos << std::endl; + std::cout << "method_17 " << (int)league << " " << playerName << " " << timeMs << std::endl; + const uint8_t newRecordPos = getPosOfNewRecord(league, timeMs); + std::cout << "record pos " << (int)newRecordPos << std::endl; - if (newRecordPos < 3) { - if (timeMs > 16777000L) { - timeMs = 16777000L; // 3 int8_ts, not five, wtf? - } + if (newRecordPos >= 3) { + // out of scope, we save only first 3 records + return; + } - addNewRecord(league, newRecordPos); - recordTimeMs[league][newRecordPos] = timeMs; + if (timeMs > 16777000L) { + timeMs = 16777000L; // 3 int8_ts, not five, wtf? + } - for (auto i = 0; i < PLAYER_NAME_MAX; ++i) { - recordName[league][newRecordPos][i] = playerName[i]; - } + addNewRecord(league, newRecordPos); + recordsSaveData.leagueRecords[league].records[newRecordPos].timeMs = timeMs; + + for (uint8_t i = 0; i < PLAYER_NAME_MAX; ++i) { + recordsSaveData.leagueRecords[league].records[newRecordPos].playerName[i] = playerName[i]; } } -void RecordManager::addNewRecord(int gameLevel, int position) +void RecordManager::addNewRecord(const uint8_t league, const uint8_t position) { - if (position <= 0) { - return; - } + std::cout << "addNewRecord " << (int)league << " " << (int)position << std::endl; + LeagueRecords leagueRecs = recordsSaveData.leagueRecords[league]; - std::cout << "addNewRecord " << gameLevel << " " << position << std::endl; + for (uint8_t i = 2; i > position; --i) { + leagueRecs.records[i].timeMs = leagueRecs.records[i - 1].timeMs; - for (auto pos = 2; pos > position; --pos) { - recordTimeMs[gameLevel][pos] = recordTimeMs[gameLevel][pos - 1]; - for (auto i = 0; i < PLAYER_NAME_MAX; ++i) { - recordName[gameLevel][pos][i] = recordName[gameLevel][pos - 1][i]; + for (uint8_t i = 0; i < PLAYER_NAME_MAX; ++i) { + leagueRecs.records[i].playerName[i] = leagueRecs.records[i - 1].playerName[i]; } } } @@ -240,9 +162,8 @@ void RecordManager::deleteRecordStores() std::vector names = RecordStore::listRecordStores(); for (std::size_t i = 0; i < names.size(); ++i) { - if (names[i] != "GDTRStates") { + if (names[i] != GlobalSetting::GlobalSaveFileName) { try { - // RecordStore *var10000 = recordStore; RecordStore::deleteRecordStore(names[i]); } catch (RecordStoreException& var3) { return; diff --git a/src/RecordManager.h b/src/RecordManager.h index d46fc02..b16e813 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -4,6 +4,7 @@ #include #include +#include "config.h" #include "utils/Time.h" class RecordStore; @@ -16,47 +17,46 @@ class RecordManager { PLAYER_NAME_MAX = 3, }; - inline static const int unused = 3; + // inline static const int unused = 3; - void method_8(const int level, const int track); - std::vector getRecordDescription(const int league); + void method_8(const uint8_t level, const uint8_t track); + std::vector getRecordDescription(const uint8_t league); void writeRecordInfo(); - int getPosOfNewRecord(int league, int64_t timeMs); - void method_17(int league, char* values, int64_t timeMs); + uint8_t getPosOfNewRecord(const uint8_t league, const int64_t timeMs); + void method_17(const uint8_t league, char* playerName, int64_t timeMs); void deleteRecordStores(); void closeRecordStore(); private: - // struct Record { - // int64_t timeMs; - // // uint8_t timeMs[5]; - // char playerName[3]; - // }; - // static_assert(sizeof(Record) == 16); - - // struct LeagueRecords { - // Record records[3]; - // }; - // struct RecordsSaveData { - // LeagueRecords leagueRecors[4]; - // }; - - // static_assert(sizeof(char[4]) == 4); - // static_assert(sizeof(int64_t) == 8); - // static_assert(sizeof(RecordsSaveData) == 96); - - std::vector> recordTimeMs = std::vector>(4, std::vector(3)); // 4: league, 100, 175, 225, 350, // 3: three best times - char recordName[LEAGUES_MAX][RECORD_NO_MAX][PLAYER_NAME_MAX + 1]; + struct __attribute__((packed)) Record { + int64_t timeMs : 40; + char playerName[PLAYER_NAME_MAX]; + }; + static_assert(sizeof(Record) == 8); + + struct __attribute__((packed)) LeagueRecords { + Record records[RECORD_NO_MAX]; + }; + static_assert(sizeof(LeagueRecords) == 24); + + struct __attribute__((packed)) RecordsSaveData { + LeagueRecords leagueRecords[LEAGUES_MAX]; + }; + static_assert(sizeof(RecordsSaveData) == 96); + + union RecordsSaveDataConverter { + RecordsSaveData recordsSaveData; + int8_t bytes[sizeof(RecordsSaveData)]; + }; + static_assert(sizeof(RecordsSaveDataConverter) == sizeof(RecordsSaveData)); + RecordStore* recordStore = nullptr; int packedRecordInfoRecordId = -1; - std::vector packedRecordInfo = std::vector(96); + RecordsSaveData recordsSaveData; - int64_t load5BytesAsLong(std::vector var1, int offset); - void pushLongAs5Bytes(std::vector var1, int var2, int64_t var3); void loadRecordInfo(std::vector var1); - void getLevelInfo(std::vector var1); void resetRecordsTime(); - void addNewRecord(int gameLevel, int position); + void addNewRecord(const uint8_t league, const uint8_t position); }; diff --git a/src/config.cpp b/src/config.cpp index 07e39a0..81f346d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -7,5 +7,8 @@ uint8_t GlobalSetting::TimerFpsTextOffset = 14; uint8_t GlobalSetting::LoadingBarPadding = 2; uint8_t GlobalSetting::BarScreenOffset = 2; uint8_t GlobalSetting::BarH = 10; +uint16_t GlobalSetting::DefaultScreenWidth = 640; +uint16_t GlobalSetting::DefaultScreenHeight = 480; std::string GlobalSetting::SavesPrefix = ""; +std::string GlobalSetting::GlobalSaveFileName = "GDTRStates"; std::filesystem::path GlobalSetting::MrgFilePath = "levels.mrg"; \ No newline at end of file diff --git a/src/config.h b/src/config.h index 1230d17..9d991b0 100644 --- a/src/config.h +++ b/src/config.h @@ -13,6 +13,9 @@ struct GlobalSetting { static uint8_t LoadingBarPadding; static uint8_t BarScreenOffset; static uint8_t BarH; + static uint16_t DefaultScreenWidth; + static uint16_t DefaultScreenHeight; static std::string SavesPrefix; + static std::string GlobalSaveFileName; static std::filesystem::path MrgFilePath; }; \ No newline at end of file diff --git a/src/lcdui/CanvasImpl.cpp b/src/lcdui/CanvasImpl.cpp index 2d8e1cb..b539f2a 100644 --- a/src/lcdui/CanvasImpl.cpp +++ b/src/lcdui/CanvasImpl.cpp @@ -35,7 +35,7 @@ CanvasImpl::CanvasImpl(Canvas* canvas) 0, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - defaultWidth, defaultHeight, + GlobalSetting::DefaultScreenWidth, GlobalSetting::DefaultScreenHeight, windowFlags); if (!window) { @@ -70,7 +70,7 @@ void CanvasImpl::repaint() int CanvasImpl::getWidth() { if (windowWidth < 0) { - return defaultWidth; + return GlobalSetting::DefaultScreenWidth; } return windowWidth; @@ -79,7 +79,7 @@ int CanvasImpl::getWidth() int CanvasImpl::getHeight() { if (windowHeight < 0) { - return defaultHeight; + return GlobalSetting::DefaultScreenHeight; } return windowHeight; diff --git a/src/lcdui/CanvasImpl.h b/src/lcdui/CanvasImpl.h index 481abd4..bcdf6e4 100644 --- a/src/lcdui/CanvasImpl.h +++ b/src/lcdui/CanvasImpl.h @@ -10,9 +10,6 @@ class Canvas; class CanvasImpl { private: - const int defaultWidth = 640; - const int defaultHeight = 480; - int windowWidth = -1; int windowHeight = -1; From 1a1a5ea3fca44f19783d803e272e1b7478315d2a Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Tue, 5 Nov 2024 21:05:05 +0200 Subject: [PATCH 06/16] added addOrUpdateRecord method --- src/MenuManager.cpp | 22 ++++++---------------- src/RecordManager.cpp | 22 ++++++---------------- src/rms/RecordStore.cpp | 10 ++++++++++ src/rms/RecordStore.h | 1 + 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 828bb6c..de031e5 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -772,22 +772,12 @@ void MenuManager::method_208() setValue(7 + i, availableTracks[i]); } - if (recorcStoreRecordId == -1) { - try { - recorcStoreRecordId = recordStore->addRecord(savedData, 0, 19); - } catch (RecordStoreNotOpenException& var2) { - std::cout << var2.what() << std::endl; - } catch (RecordStoreException& var3) { - std::cout << var3.what() << std::endl; - } - } else { - try { - recordStore->setRecord(recorcStoreRecordId, savedData, 0, 19); - } catch (RecordStoreNotOpenException& var4) { - std::cout << var4.what() << std::endl; - } catch (RecordStoreException& var5) { - std::cout << var5.what() << std::endl; - } + try { + recorcStoreRecordId = recordStore->addOrUpdateRecord(recorcStoreRecordId, savedData, 0, 19); + } catch (RecordStoreNotOpenException& var4) { + std::cout << var4.what() << std::endl; + } catch (RecordStoreException& var5) { + std::cout << var5.what() << std::endl; } } diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index a02ada8..be4a33a 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -88,22 +88,12 @@ void RecordManager::writeRecordInfo() }; std::vector packedRecordInfo(std::begin(converter.bytes), std::end(converter.bytes)); - if (packedRecordInfoRecordId == -1) { - try { - packedRecordInfoRecordId = recordStore->addRecord(packedRecordInfo, 0, 96); - } catch (RecordStoreNotOpenException& var1) { - return; - } catch (RecordStoreException& var2) { - return; - } - } else { - try { - recordStore->setRecord(packedRecordInfoRecordId, packedRecordInfo, 0, 96); - } catch (RecordStoreNotOpenException& var3) { - return; - } catch (RecordStoreException& var4) { - return; - } + try { + packedRecordInfoRecordId = recordStore->addOrUpdateRecord(packedRecordInfoRecordId, packedRecordInfo, 0, 96); + } catch (RecordStoreNotOpenException& var3) { + return; + } catch (RecordStoreException& var4) { + return; } } diff --git a/src/rms/RecordStore.cpp b/src/rms/RecordStore.cpp index f8fa4bf..c0b0c8a 100644 --- a/src/rms/RecordStore.cpp +++ b/src/rms/RecordStore.cpp @@ -39,6 +39,16 @@ void RecordStore::closeRecordStore() // nothing } +int RecordStore::addOrUpdateRecord(int recordId, std::vector arr, int offset, int numBytes) +{ + if (recordId == -1) { + return this->addRecord(arr, offset, numBytes); + } + + this->setRecord(recordId, arr, offset, numBytes); + return recordId; +} + int RecordStore::addRecord(std::vector arr, int offset, int numBytes) { log("addRecord(" + std::to_string(arr.size()) + "," + std::to_string(offset) + "," + std::to_string(numBytes) + ")"); diff --git a/src/rms/RecordStore.h b/src/rms/RecordStore.h index 10e5007..0d46ded 100644 --- a/src/rms/RecordStore.h +++ b/src/rms/RecordStore.h @@ -31,4 +31,5 @@ class RecordStore { RecordEnumeration* enumerateRecords(RecordFilter* filter, RecordComparator* comparator, bool keepUpdated); int addRecord(std::vector arr, int offset, int numBytes); void setRecord(int recordId, std::vector arr, int offset, int numBytes); + int addOrUpdateRecord(int recordId, std::vector arr, int offset, int numBytes); }; \ No newline at end of file From 0c2caad71cbe77c669e9434dc447c25545b08552 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Thu, 7 Nov 2024 22:49:52 +0200 Subject: [PATCH 07/16] overhauled record saving logic --- .gitignore | 1 + src/LevelLoader.cpp | 4 +- src/MRGLoader.cpp | 191 +++++++++++++++++++++++++++++++++++++++ src/MRGLoader.h | 40 ++++++++ src/MenuManager.cpp | 92 ++++++++++++++----- src/MenuManager.h | 34 ++++++- src/RecordManager.cpp | 145 +++++++++-------------------- src/RecordManager.h | 43 +++++---- src/SavesManager.cpp | 2 + src/SavesManager.h | 16 ++++ src/lcdui/CanvasImpl.cpp | 2 +- src/levels.mrg | Bin 0 -> 5123 bytes 12 files changed, 421 insertions(+), 149 deletions(-) create mode 100644 src/MRGLoader.cpp create mode 100644 src/MRGLoader.h create mode 100644 src/SavesManager.cpp create mode 100644 src/SavesManager.h create mode 100644 src/levels.mrg diff --git a/.gitignore b/.gitignore index 5350cb3..9c96343 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ Makefile cmake_install.cmake libAssets.a saves +a.out diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index beb7f4f..dbdd5f1 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -87,7 +87,7 @@ void LevelLoader::method_87() int LevelLoader::method_88(int var1, int var2) { - std::cout << "method_88 " << var1 << " " << var2 << std::endl; + // std::cout << "method_88 " << var1 << " " << var2 << std::endl; field_125 = var1; field_126 = var2; @@ -101,7 +101,7 @@ int LevelLoader::method_88(int var1, int var2) void LevelLoader::method_89(int var1, int var2) { - std::cout << "method_89 " << var1 << " " << var2 << std::endl; + // std::cout << "method_89 " << var1 << " " << var2 << std::endl; levelFileStream->setPos(levelOffsetInFile[var1 - 1][var2 - 1]); if (gameLevel == nullptr) { diff --git a/src/MRGLoader.cpp b/src/MRGLoader.cpp new file mode 100644 index 0000000..976a739 --- /dev/null +++ b/src/MRGLoader.cpp @@ -0,0 +1,191 @@ +#include "MRGLoader.h" + +static MRGLoader::LevelTracks loadLevel(FileStream& levelFileStream, const uint8_t level) +{ + MRGLoader::LevelTracks levelTracks; + levelFileStream.readVariable(&levelTracks.tracksCount, true); + + for (uint32_t trackNo = 0; trackNo < levelTracks.tracksCount; ++trackNo) { + MRGLoader::Track track; + levelFileStream.readVariable(&track.offset, true); + + std::stringstream ss; + char nameCh; + + do { + levelFileStream.readVariable(&nameCh, true); + ss << nameCh; + } while (nameCh > 0); + + track.trackName = ss.str(); + + levelTracks.tracks.push_back(track); + } + + std::cout << "LEVEL " << (uint32_t)level << std::endl; + std::cout << levelTracks.tracksCount << " TRACKS" << std::endl; + + for (auto& i : levelTracks.tracks) { + std::cout << i.offset << " " << i.trackName << std::endl; + } + + return levelTracks; +} + +static std::array MRGLoader::loadLevels(const std::filesystem::path& mrgFilePath) +{ + FileStream levelFileStream(mrgFilePath, std::ios::in | std::ios::binary); + std::array levels; + + for (uint8_t level = 0; level < 3; ++level) { + levels[level] = loadLevel(levelFileStream, level); + } + + return levels; +} + +static MRGLoader::TrackInfo MRGLoader::loadTrack(const std::filesystem::path& mrgFilePath, const uint32_t fileOffset) +{ + FileStream levelFileStream(mrgFilePath, std::ios::in | std::ios::binary); + levelFileStream.setPos(fileOffset); + + uint8_t c; + levelFileStream.readVariable(&c, true); + std::cout << (int)c << std::endl; + // if (c == 50) { + // char var3[20]; + // inStream->readVariable(var3, false, 20); + // } + + int32_t pointX, pointY; + int8_t tempDX, tempDY; + + MRGLoader::TrackInfo trackInfo; + levelFileStream.readVariable(&trackInfo.startPosX, true); + levelFileStream.readVariable(&trackInfo.startPosY, true); + levelFileStream.readVariable(&trackInfo.finishPosX, true); + levelFileStream.readVariable(&trackInfo.finishPosY, true); + levelFileStream.readVariable(&trackInfo.pointsCount, true); + levelFileStream.readVariable(&pointX, true); + levelFileStream.readVariable(&pointY, true); + std::cout << trackInfo.pointsCount << std::endl; + std::cout << trackInfo.startPosX << " " << trackInfo.startPosY << std::endl; + std::cout << trackInfo.finishPosX << " " << trackInfo.finishPosY << std::endl; + + // l.startPosX = l.startPosX >> 16 << 3; + // l.startPosY = l.startPosY >> 16 << 3; + // l.finishPosX = l.finishPosX >> 16 << 3; + // l.finishPosY = l.finishPosY >> 16 << 3; + // l.pointX = l.pointX >> 16 << 3; + // l.pointY = l.pointY >> 16 << 3; + + // std::cout << l.pointsCount << std::endl; + // std::cout << l.startPosX << " " << l.startPosY << std::endl; + // std::cout << l.finishPosX << " " << l.finishPosY << std::endl; + // std::cout << l.pointX << " " << l.pointY << std::endl; + + int32_t offsetX = pointX; + int32_t offsetY = pointY; + trackInfo.points.push_back({ .x = offsetX, .y = offsetY }); + + for (uint16_t i = 1; i < trackInfo.pointsCount; ++i) { + levelFileStream.readVariable(&tempDX, true); + + if (tempDX == -1) { + offsetY = 0; + offsetX = 0; + levelFileStream.readVariable(&pointX, true); + levelFileStream.readVariable(&pointY, true); + } else { + pointX = tempDX; + levelFileStream.readVariable(&tempDY, true); + pointY = tempDY; + } + + offsetX += pointX; + offsetY += pointY; + trackInfo.points.push_back({ .x = offsetX, .y = offsetY }); + // addPointSimple(offsetX, offsetY); + } + + for (auto& i : trackInfo.points) { + std::cout << "X: " << i.x << " Y: " << i.y << std::endl; + } + + return trackInfo; +} + +// void GameLevel::load(FileStream* inStream) +// { +// init(); +// int8_t c; +// inStream->readVariable(&c, true); +// if (c == 50) { +// char var3[20]; +// inStream->readVariable(var3, false, 20); +// } + +// finishFlagPoint = 0; +// startFlagPoint = 0; +// int pointX, pointY; +// short pointsCount; +// inStream->readVariable(&startPosX, true); +// inStream->readVariable(&startPosY, true); +// inStream->readVariable(&finishPosX, true); +// inStream->readVariable(&finishPosY, true); +// inStream->readVariable(&pointsCount, true); +// inStream->readVariable(&pointX, true); +// inStream->readVariable(&pointY, true); +// int offsetX = pointX; +// int offsetY = pointY; +// addPointSimple(pointX, pointY); + +// for (int i = 1; i < pointsCount; ++i) { +// int8_t modeOrDx; +// inStream->readVariable(&modeOrDx, true); +// if (modeOrDx == -1) { +// offsetY = 0; +// offsetX = 0; +// inStream->readVariable(&pointX, true); +// inStream->readVariable(&pointY, true); +// } else { +// pointX = modeOrDx; +// int8_t temp; +// inStream->readVariable(&temp, true); +// pointY = temp; +// } + +// offsetX += pointX; +// offsetY += pointY; +// addPointSimple(offsetX, offsetY); +// } +// } + +// void GameLevel::addPointSimple(int var1, int var2) +// { +// addPoint(var1 << 16 >> 3, var2 << 16 >> 3); +// } + +// void GameLevel::addPoint(int x, int y) +// { +// if (pointPositions.empty() || static_cast(pointPositions.size()) <= pointsCount) { +// int var3 = 100; +// if (!pointPositions.empty()) { +// var3 = var3 < static_cast(pointPositions.size()) + 30 ? pointPositions.size() + 30 : var3; +// } +// pointPositions.resize(var3, std::vector(2)); // ABOBA +// } + +// if (pointsCount == 0 || pointPositions[pointsCount - 1][0] < x) { +// pointPositions[pointsCount][0] = x; +// pointPositions[pointsCount][1] = y; +// ++pointsCount; +// } +// } + +int main(void) +{ + std::array levels = MRGLoader::loadLevels("./levels.mrg"); + MRGLoader::loadTrack("./levels.mrg", levels[0].tracks[0].offset); + return 0; +} diff --git a/src/MRGLoader.h b/src/MRGLoader.h new file mode 100644 index 0000000..9dcf06c --- /dev/null +++ b/src/MRGLoader.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils/FileStream.h" + +namespace MRGLoader { +struct TrackPoint { + int32_t x; + int32_t y; +}; +struct TrackInfo { + int32_t startPosX; + int32_t startPosY; + int32_t finishPosX; + int32_t finishPosY; + uint16_t pointsCount; + // int32_t pointX; + // int32_t pointY; + std::vector points; +}; +struct Track { + uint32_t offset; + std::string trackName; +}; +struct LevelTracks { + uint32_t tracksCount; + std::vector tracks; +}; + +static std::array loadLevels(const std::filesystem::path& mrgFilePath); +static MRGLoader::TrackInfo loadTrack(const std::filesystem::path& mrgFilePath, const uint32_t fileOffset); +}; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index de031e5..7497378 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -107,7 +107,7 @@ void MenuManager::initPart(int var1) field_369 = getSettingOrDefault(11, field_369); field_370 = getSettingOrDefault(10, field_370); field_371 = getSettingOrDefault(12, field_371); - field_373 = getSettingOrDefault(15, field_373); + // field_373 = getSettingOrDefault(15, field_373); field_354 = field_370; field_355 = field_369; @@ -343,9 +343,34 @@ bool MenuManager::method_196() void MenuManager::method_197() { - std::cout << "method_197 " << playerName << " " << trackTimeMs << std::endl; - recordManager->method_17(settingsStringLeague->getCurrentOptionPos(), playerName, trackTimeMs); - recordManager->writeRecordInfo(); + // std::cout << "method_197 " << playerName << " " << trackTimeMs << std::endl; + recordManager->loadRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); + { + std::cout << "AFTER LOAD" << std::endl; + std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); + + for (auto &i: var1) { + std::cout << i << std::endl; + } + } + recordManager->addNewRecord(settingsStringLeague->getCurrentOptionPos(), playerName, trackTimeMs); + { + std::cout << "ADD NEW RECORD" << std::endl; + std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); + + for (auto &i: var1) { + std::cout << i << std::endl; + } + } + recordManager->writeRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); + { + std::cout << "AFTER WRITE" << std::endl; + std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); + + for (auto &i: var1) { + std::cout << i << std::endl; + } + } field_356 = false; gameMenuFinished->clearVector(); gameMenuFinished->addMenuElement(new TextRender("Time: " + trackTimeFormatted, micro)); @@ -357,7 +382,7 @@ void MenuManager::method_197() } } - recordManager->closeRecordStore(); + // recordManager->closeRecordStore(); int8_t availableLeagues = -1; if (settingsStringTrack->getMaxAvailableOptionPos() >= settingsStringTrack->getCurrentOptionPos()) { settingsStringTrack->setAvailableOptions(settingsStringTrack->getCurrentOptionPos() + 1 < availableTracks[settingStringLevel->getCurrentOptionPos()] ? availableTracks[settingStringLevel->getCurrentOptionPos()] : settingsStringTrack->getCurrentOptionPos() + 1); @@ -407,7 +432,7 @@ void MenuManager::method_197() } if (availableLeagues != -1) { - addTextRender(gameMenuFinished, "Congratultions! You have successfully unlocked a new league: " + leagueNames[availableLeagues]); + addTextRender(gameMenuFinished, "Congratulations! You have successfully unlocked a new league: " + leagueNames[availableLeagues]); if (availableLeagues == 3) { gameMenuFinished->addMenuElement(new TextRender("Enjoy...", micro)); } @@ -474,11 +499,11 @@ void MenuManager::method_201(int var1) gameMenuFinished->clearVector(); field_354 = settingStringLevel->getCurrentOptionPos(); field_355 = settingsStringTrack->getCurrentOptionPos(); - recordManager->method_8(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); + recordManager->loadRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); const uint8_t var2 = recordManager->getPosOfNewRecord(settingsStringLeague->getCurrentOptionPos(), trackTimeMs); trackTimeFormatted = Time::timeToString(trackTimeMs); - if (var2 >= 0 && var2 <= 2) { + if (var2 < RecordManager::RECORD_NO_MAX) { TextRender* var3 = new TextRender("", micro); var3->setDx(GameCanvas::spriteSizeX[5] + 1); switch (var2) { @@ -703,7 +728,7 @@ void MenuManager::method_1(GameMenu* gm, bool var2) void MenuManager::method_207(int var1) { gameMenuHighscore->clearVector(); - recordManager->method_8(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); + recordManager->loadRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); gameMenuHighscore->addMenuElement(new TextRender(micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()), micro)); gameMenuHighscore->addMenuElement(new TextRender("LEAGUE: " + settingsStringLeague->getOptionsList()[var1], micro)); std::vector var2 = recordManager->getRecordDescription(var1); @@ -724,7 +749,7 @@ void MenuManager::method_207(int var1) } } - recordManager->closeRecordStore(); + // recordManager->closeRecordStore(); if (var2[0] == "") { gameMenuHighscore->addMenuElement(new TextRender("No Highscores", micro)); } @@ -738,7 +763,7 @@ void MenuManager::saveSmthToRecordStoreAndCloseIt() method_208(); try { - recordStore->closeRecordStore(); + // recordStore->closeRecordStore(); isRecordStoreOpened = false; } catch (RecordStoreException& var1) { std::cout << var1.what() << std::endl; @@ -751,6 +776,27 @@ void MenuManager::saveSmthToRecordStoreAndCloseIt() void MenuManager::method_208() { // copyThreeBytesFromArr(16, playerName); + Settings settingToSave = { + .perspective = (int8_t)perspectiveSetting->getCurrentOptionPos(), + .shadows = (int8_t)shadowsSetting->getCurrentOptionPos(), + .driverSprite = (int8_t)driverSpriteSetting->getCurrentOptionPos(), + .bikeSprite = (int8_t)bikeSpriteSetting->getCurrentOptionPos(), + .lookAhead = (int8_t)lookAheadSetting->getCurrentOptionPos(), + .league = (int8_t)settingsStringLeague->getMaxAvailableOptionPos(), + .level = (int8_t)settingStringLevel->getMaxAvailableOptionPos(), + .availableEasyTracks = (int8_t)availableTracks[0], + .availableMediumTracks = (int8_t)availableTracks[1], + .availableHardTracks = (int8_t)availableTracks[2], + .unknown = (int8_t)settingStringLevel->getMaxAvailableOptionPos(), + .selectedTrack = (int8_t)settingsStringTrack->getCurrentOptionPos(), + .selectedLeague = (int8_t)settingsStringLeague->getCurrentOptionPos(), + .unknown2 = -127, + .input = (int8_t)inputSetting->getCurrentOptionPos(), + .unknown3 = -127, + .playerName = {} + }; + strcpy(settingToSave.playerName, playerName); + SettingsConverter settingsConverter = { .settings = settingToSave }; setValue(0, (int8_t)perspectiveSetting->getCurrentOptionPos()); setValue(1, (int8_t)shadowsSetting->getCurrentOptionPos()); @@ -990,20 +1036,20 @@ void MenuManager::method_211(int var1) } } -int MenuManager::method_212() -{ - return settingStringLevel->getCurrentOptionPos(); -} +// int MenuManager::method_212() +// { +// return settingStringLevel->getCurrentOptionPos(); +// } -int MenuManager::method_213() -{ - return settingsStringTrack->getCurrentOptionPos(); -} +// int MenuManager::method_213() +// { +// return settingsStringTrack->getCurrentOptionPos(); +// } -int MenuManager::method_214() -{ - return settingsStringLeague->getCurrentOptionPos(); -} +// int MenuManager::method_214() +// { +// return settingsStringLeague->getCurrentOptionPos(); +// } void MenuManager::method_215(int64_t var1) { diff --git a/src/MenuManager.h b/src/MenuManager.h index f4335f0..4eb52d6 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -21,6 +21,32 @@ class IGameMenuElement; class MenuManager : public IMenuManager { private: + struct Settings { + int8_t perspective; + int8_t shadows; + int8_t driverSprite; + int8_t bikeSprite; + int8_t lookAhead; + int8_t league; + int8_t level; + int8_t availableEasyTracks; + int8_t availableMediumTracks; + int8_t availableHardTracks; + int8_t unknown; + int8_t selectedTrack; + int8_t selectedLeague; + int8_t unknown2; + int8_t input; + int8_t unknown3; + char playerName[3]; + }; + static_assert(sizeof(Settings) == 19); + + union SettingsConverter { + Settings settings; + int8_t bytes[sizeof(Settings)]; + }; + std::vector savedData; Micro* micro; RecordManager* recordManager; @@ -110,7 +136,7 @@ class MenuManager : public IMenuManager { int8_t field_370 = 0; int8_t field_371 = 0; int8_t field_372 = 0; - int8_t field_373 = 0; + // int8_t field_373 = 0; std::vector field_374; std::vector field_375; std::unique_ptr field_376; @@ -153,9 +179,9 @@ class MenuManager : public IMenuManager { void processMenu(IGameMenuElement* menuElement); int method_210(); void method_211(int var1); - int method_212(); - int method_213(); - int method_214(); + // int method_212(); + // int method_213(); + // int method_214(); void method_215(int64_t var1); void removeOkAndBackCommands(); void addOkAndBackCommands(); diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index be4a33a..c04998a 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -1,65 +1,23 @@ #include "RecordManager.h" -#include "rms/RecordStore.h" -#include "rms/RecordStoreException.h" -#include "rms/RecordStoreNotOpenException.h" -#include "rms/InvalidRecordIDException.h" - -void RecordManager::method_8(const uint8_t level, const uint8_t track) -{ - std::cout << "method_8 " << (int)level << (int)track << std::endl; - resetRecordsTime(); - - try { - const std::string str = std::to_string(level) + std::to_string(track); - std::cout << "str " << str << std::endl; - recordStore = RecordStore::openRecordStore(str, true); - } catch (RecordStoreException& var9) { - return; - } - - packedRecordInfoRecordId = -1; - - RecordEnumeration* recordEnum; - try { - recordEnum = recordStore->enumerateRecords(nullptr, nullptr, false); - } catch (RecordStoreNotOpenException& var8) { - return; - } - - if (recordEnum->numRecords() > 0) { - std::vector saveFileBytes; - try { - saveFileBytes = recordEnum->nextRecord(); - recordEnum->reset(); - packedRecordInfoRecordId = recordEnum->nextRecordId(); - } catch (RecordStoreNotOpenException& var5) { - return; - } catch (InvalidRecordIDException& var6) { - return; - } catch (RecordStoreException& var7) { - return; - } - - loadRecordInfo(saveFileBytes); - // recordEnum->destroy(); - } -} - -void RecordManager::loadRecordInfo(std::vector dataBytes) +void RecordManager::loadRecordInfo(const uint8_t level, const uint8_t track) { - RecordsSaveDataConverter converter; - std::copy(dataBytes.begin(), dataBytes.end(), converter.bytes); - recordsSaveData = converter.recordsSaveData; + // resetRecordsTime(); + std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + std::to_string(level) + std::to_string(track); + std::cout << "loadRecordInfo " << saveFileName << std::endl; + + FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); + levelFileStream.readVariable(&recordsSaveDataConverter.bytes, false, sizeof(RecordsSaveData)); } void RecordManager::resetRecordsTime() { - for (uint8_t league = 0; league < LEAGUES_MAX; ++league) { - for (uint8_t pos = 0; pos < RECORD_NO_MAX; ++pos) { - recordsSaveData.leagueRecords[league].records[pos].timeMs = 0L; - } - } + recordsSaveDataConverter = { .bytes = {} }; + // for (uint8_t league = 0; league < LEAGUES_MAX; ++league) { + // for (uint8_t pos = 0; pos < RECORD_NO_MAX; ++pos) { + // recordsSaveData.leagueRecords[league].records[pos].timeMs = 0L; + // } + // } } std::vector RecordManager::getRecordDescription(const uint8_t league) @@ -67,7 +25,7 @@ std::vector RecordManager::getRecordDescription(const uint8_t leagu std::vector recordsDescription = std::vector(RECORD_NO_MAX); for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { - Record record = recordsSaveData.leagueRecords[league].records[i]; + Record record = recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[i]; if (record.timeMs != 0L) { std::stringstream ss; @@ -81,26 +39,19 @@ std::vector RecordManager::getRecordDescription(const uint8_t leagu return recordsDescription; } -void RecordManager::writeRecordInfo() +void RecordManager::writeRecordInfo(const uint8_t level, const uint8_t track) { - RecordsSaveDataConverter converter = { - .recordsSaveData = recordsSaveData - }; - std::vector packedRecordInfo(std::begin(converter.bytes), std::end(converter.bytes)); + std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + std::to_string(level) + std::to_string(track); + std::cout << "writeRecordInfo " << saveFileName << std::endl; - try { - packedRecordInfoRecordId = recordStore->addOrUpdateRecord(packedRecordInfoRecordId, packedRecordInfo, 0, 96); - } catch (RecordStoreNotOpenException& var3) { - return; - } catch (RecordStoreException& var4) { - return; - } + FileStream levelFileStream(saveFileName, std::ios::out | std::ios::binary); + levelFileStream.writeVariable(&recordsSaveDataConverter.bytes, sizeof(RecordsSaveData)); } -uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t timeMs) +uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t timeMs) const { for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { - const Record record = recordsSaveData.leagueRecords[league].records[i]; + const Record record = recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[i]; if (record.timeMs > timeMs || record.timeMs <= 0L) { return i; @@ -110,9 +61,9 @@ uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t tim return 3; } -void RecordManager::method_17(const uint8_t league, char* playerName, int64_t timeMs) +void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t timeMs) { - std::cout << "method_17 " << (int)league << " " << playerName << " " << timeMs << std::endl; + std::cout << "addNewRecord " << (int)league << " " << playerName << " " << timeMs << std::endl; const uint8_t newRecordPos = getPosOfNewRecord(league, timeMs); std::cout << "record pos " << (int)newRecordPos << std::endl; @@ -125,26 +76,18 @@ void RecordManager::method_17(const uint8_t league, char* playerName, int64_t ti timeMs = 16777000L; // 3 int8_ts, not five, wtf? } - addNewRecord(league, newRecordPos); - recordsSaveData.leagueRecords[league].records[newRecordPos].timeMs = timeMs; - - for (uint8_t i = 0; i < PLAYER_NAME_MAX; ++i) { - recordsSaveData.leagueRecords[league].records[newRecordPos].playerName[i] = playerName[i]; + if (newRecordPos < (RECORD_NO_MAX - 1)) { + std::rotate( + std::begin(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records) + newRecordPos, + std::end(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records) - 1, + std::end(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records)); } -} - -void RecordManager::addNewRecord(const uint8_t league, const uint8_t position) -{ - std::cout << "addNewRecord " << (int)league << " " << (int)position << std::endl; - LeagueRecords leagueRecs = recordsSaveData.leagueRecords[league]; - for (uint8_t i = 2; i > position; --i) { - leagueRecs.records[i].timeMs = leagueRecs.records[i - 1].timeMs; - - for (uint8_t i = 0; i < PLAYER_NAME_MAX; ++i) { - leagueRecs.records[i].playerName[i] = leagueRecs.records[i - 1].playerName[i]; - } - } + recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos] = { + .timeMs = timeMs, + .playerName = {} + }; + strcpy(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos].playerName, playerName); } void RecordManager::deleteRecordStores() @@ -162,14 +105,14 @@ void RecordManager::deleteRecordStores() } } -void RecordManager::closeRecordStore() -{ - if (recordStore != nullptr) { - try { - recordStore->closeRecordStore(); - return; - } catch (RecordStoreException& var1) { - return; - } - } -} +// void RecordManager::closeRecordStore() +// { +// // if (recordStore != nullptr) { +// // try { +// // recordStore->closeRecordStore(); +// // return; +// // } catch (RecordStoreException& var1) { +// // return; +// // } +// // } +// } diff --git a/src/RecordManager.h b/src/RecordManager.h index b16e813..78ca962 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -3,11 +3,18 @@ #include #include #include +#include +#include #include "config.h" #include "utils/Time.h" -class RecordStore; +#include "rms/RecordStore.h" +#include "rms/RecordStoreException.h" +#include "rms/RecordStoreNotOpenException.h" +#include "rms/InvalidRecordIDException.h" + +// class RecordStore; class RecordManager { public: @@ -19,32 +26,32 @@ class RecordManager { // inline static const int unused = 3; - void method_8(const uint8_t level, const uint8_t track); + void loadRecordInfo(const uint8_t level, const uint8_t track); std::vector getRecordDescription(const uint8_t league); - void writeRecordInfo(); - uint8_t getPosOfNewRecord(const uint8_t league, const int64_t timeMs); - void method_17(const uint8_t league, char* playerName, int64_t timeMs); + uint8_t getPosOfNewRecord(const uint8_t league, const int64_t timeMs) const; + void writeRecordInfo(const uint8_t level, const uint8_t track); + void addNewRecord(const uint8_t league, char* playerName, int64_t timeMs); void deleteRecordStores(); - void closeRecordStore(); + // void closeRecordStore(); private: // 4: league, 100, 175, 225, 350, // 3: three best times - struct __attribute__((packed)) Record { - int64_t timeMs : 40; + struct /*__attribute__((packed))*/ Record { + int64_t timeMs; char playerName[PLAYER_NAME_MAX]; }; - static_assert(sizeof(Record) == 8); + static_assert(sizeof(Record) == 16); - struct __attribute__((packed)) LeagueRecords { + struct /*__attribute__((packed))*/ LeagueRecords { Record records[RECORD_NO_MAX]; }; - static_assert(sizeof(LeagueRecords) == 24); + static_assert(sizeof(LeagueRecords) == 48); - struct __attribute__((packed)) RecordsSaveData { + struct /*__attribute__((packed))*/ RecordsSaveData { LeagueRecords leagueRecords[LEAGUES_MAX]; }; - static_assert(sizeof(RecordsSaveData) == 96); + static_assert(sizeof(RecordsSaveData) == 192); union RecordsSaveDataConverter { RecordsSaveData recordsSaveData; @@ -52,11 +59,11 @@ class RecordManager { }; static_assert(sizeof(RecordsSaveDataConverter) == sizeof(RecordsSaveData)); - RecordStore* recordStore = nullptr; - int packedRecordInfoRecordId = -1; - RecordsSaveData recordsSaveData; + // RecordStore* recordStore = nullptr; + // int packedRecordInfoRecordId = -1; + RecordsSaveDataConverter recordsSaveDataConverter; + // RecordsSaveData recordsSaveData; - void loadRecordInfo(std::vector var1); void resetRecordsTime(); - void addNewRecord(const uint8_t league, const uint8_t position); + // void shiftRecords(const uint8_t league, const uint8_t position); }; diff --git a/src/SavesManager.cpp b/src/SavesManager.cpp new file mode 100644 index 0000000..0d47064 --- /dev/null +++ b/src/SavesManager.cpp @@ -0,0 +1,2 @@ +#include "SavesManager.h" + diff --git a/src/SavesManager.h b/src/SavesManager.h new file mode 100644 index 0000000..90f1bc0 --- /dev/null +++ b/src/SavesManager.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils/FileStream.h" + +namespace SavesManager { + +} \ No newline at end of file diff --git a/src/lcdui/CanvasImpl.cpp b/src/lcdui/CanvasImpl.cpp index b539f2a..e748c9c 100644 --- a/src/lcdui/CanvasImpl.cpp +++ b/src/lcdui/CanvasImpl.cpp @@ -113,7 +113,7 @@ void CanvasImpl::processEvents() if (keyCode != 0) { canvas->publicKeyReleased(keyCode); } else { - if (sdlCode == SDLK_ESCAPE) { + if (sdlCode == SDLK_ESCAPE || sdlCode == SDLK_BACKSPACE) { // std::cout << "ESC released" << std::endl; canvas->pressedEsc(); } diff --git a/src/levels.mrg b/src/levels.mrg new file mode 100644 index 0000000000000000000000000000000000000000..e495c2a359c51ae3feb064f0f79e2f9a6ea7736e GIT binary patch literal 5123 zcmY*dX^>sjaqhdGyKnDqZ(nBLmp7x45E28DKtjlXB|tIQl0d?Yk!P@wO&mK_s>)Kh z5?3le;z}xIM|SLT65H6=CV(+S!r0g-ECLD12uY)5_KjKIn>TN}>4#jEqF?nreeS#G z^w-^|`<#0LKmwq?x?}k0kr6;?cK2f=M~;3KMf#!Lhew_`gc6h4a^%1xk01V6{_f7< zk;8|d#M|tit%nXhQ4=n1IXv{}qbPBAZXfyhG4A!dj|_c&X!yWkyvzUX?gL->N^Q=X zG9vC6J~%RR1bgI5yPp_({Lo`KrZ%CF**fyn@MA-VYlDQ7+fjJr@X!|@#-8}-u91U> zp8Ob?_xH=tns+nyr_hK7fRKfmwbf!b4{ zPwzQ0bl~v51E0s+kPX&G(X)7eT?#Kq9YIk2Yiyt1SxGN?W74=aWzU6kTZ`?WF&U0<_ljAvL4QJA)ut8@Sy4QA9PZhRO6|0#e`=jJ(4|43A?M2t^rT@K#e( z4WqHix`o(UlyOWioJ>g)vmizc;_yACG*vHW!kwXRD!`?48Yf-O2ERakKOP0xg%z3Otgx+VwDt-MTNJk9*-WB+8{w$Y)TM_k>U7$jpvmnmhYFd!Pyh=aj;sCe{2MX zE~p$s3(j<}GzYheHgUAnZ0meSHO$!sw`@ovrxqOECgEjqSt%HeWa;L%B%`ScRVqh zfG`X|7F14AWThR%pEIwrFOawSIc*EKoqm+IMbGpNBP7_AQ?QnVIpKRaNANt_zhbu5 z#B<0OlB6D5xwKH{i`-2h6*C_Q<;?}29!O<_@j(c3#{gRP-#}7_V;LOuSIE`B!OQc; zuj}c^j#k?LpaI$;5l(~n&+)Q2)WgZ&j1l;zXxW8LpFj3SjWq4Q0Kk!^gj7pA;Gwlh?YhC6-e-+O&Nw1>|ZZAC))c zeJ-j|?<(i`l<-q_8~3Jo8^0+k`WZi#_A}A6qhvhBU6L-^SE9wZE9)jBU5r%gNduR$ z+nfj!i&=FK^kjoyqNP7U`ZEp$zI7o<`)NJ9pqrWcXIB8U^- zn7?SzIu|i*UEwu~In@b7i-Vy0;Lp}kv8dB3h#F1LqY=R=j3HGM&Z6)w+S03};JxEd zyQL(UjITzih{+mpDk&qhxv_n|CccK^Gxb&9jq%~4OqrHySyqhPzSzel`)(4n zwf3|9bJH$uHa$7=YG-MFYW!zM7C4YD|@gVMKw zB1;3J=-EwNG;j1CNY`_Uuju(uh!`;1<&R^pM;)?+~X97pLPYWLhIK;JQdttos2X$vl`moQvCUweH+KK_RO z{w~H3)UuQ_=dD?NUMVoY(7Wwf|8i);n5SMPa;_L?C=la&P#T|uC-r-##X(@WT zzx_UEb2j+#F^pRZ;O-MOZ~(U>yxXw-(*0L%J>UP@Eth?!Ip4>$1a0*^y$Seg_b-U`YDMBkgU0bjeS;gN+OF&8+*NH%N zKaR+dFg+_D)Y>7c4O*xkAVu$DA1K8r7oo)n!!ooDT!k)@%l5cK^IZ`^)d|O!xmj}B z2GYgZ0!vEjQl=6*l?W78k#tTHc~J}thH#R)m1X6n`dRKh{v8c0jtnHVSVnMop7|{` z$a3CT^R)AOmtuTTt>+v0G^Ztaz7?7&Els#bXsjo=N*7PyQ6YsWk!oK32Cj_1ydxei ztiQjnkofjGNJB40SWa%Hd4|ZXG{+D%QjsfN_jq7~`djWgDah4kD&dQHwW1NTQ3ml+ zFC{H_fseaxL!Gi@q*>rrLUjxX%UT@^WXY^^1vzBOYM2m(d6?Y}I^{I-l(-!4;6VMT za~%&t{=s3~8utT45ZwA>ctPsMOl`;Z?7GY*y@5?H`fr#sQOB5x%W+mU!mIYAIpx1D zw}-$PZMNx;LX%=S9=695zEzepdR4X!+njVfomEW#eZh0)qE+3K{m59?a$7{YC(x!L)O{Emn6Zbj)*w74DFKgC~dN~J@qHDUAZ(&*bf$*PAd+i6B@@6^8*|HPTBcTY-ZCra$ z+uoMl_H_{>hKTa}0si7x4G+L(j99JUOx+jUe=0T8peHP2yd!9VtkSDm6H;I`bmZl$ z8pN9#BtbW6^<@eCaA(1q7s1VBx%34Ey#98H=mw?zObe7`63BHWh%~oS+!;A&y1QF; zzHd;C%>%2>r~-DXi|uE;j?Rj9O5r*lUys}3bNeB5SGeT_?w<)N2?DUW`+m51{5GIxn-r?p#p_#AawyN?(9E>nxf+tfL$ z%*KeYagko(XB3+DC}l?*vtnKj32HZ`eac`LqZ0~_+!3Nyn)nXFuI_r1Q+hA3;_U{# zcFQKVuoG*?|Bga1Gl-{WS>D<61ldI3QKoh=c z>?+WUcgJY`E|uVD=aUrQ-l!8?31ZxEF)=Gy=E~v7-qy5d-atJr$XkUa{Je zYw=2kj|%2l-Uxupv2X4F;FM8iO{t0f;JFeiIrkP zR8voBTm6vZ>){ya6Yf-UAsd`Nfxa6BxCyyNo6vVpA@s$kPTFTOo80Txn=R+k5Q9X$ znNX(XoN`f_&{feEu1WLh<#bt}Q|DAxBt}6gs(Jj0Set@4)zD_ zA6pE0{c(LhOcKfZYnC3x982Xo>s!V$nM6mjx%=fiu(Do4NR?v%UC1@shmbB}EAD-# zQSj`L5f&p=XV$&ugM%k4bv0J;D4nrb6A18SdW!mxd6}#U0v(}0O%sMEv{dGonP<5% zk|Q!5WujD=G8k3h2yQD(j>^*~nQ=ZZ@U+Th=pI(*IGz$pOpZIno{`H&S!Gp07c63M zMwu&cC*&8z905_*w)2CchzIbpyyiogI6{JMp@?Iw=Rfx=uvpG4>O~{f_l38JjnZ?6rNn^$L z^lM&D8~4lRFO`Z;)OG{kU>#Mp$u-i&tL{1Rx&vaFBjPF%<=4%k!wWB96l7;fdprD= zx)?5pc~4aZMGBebd8*q!&v%*Um3H|(y@P$nY^L6}n(MAL6}!RdkS;4-`WZQ4f3PvX zXZuFnOwOSJtAhaj$7=8aK811l4Ys}gW8w34te6weI;BW2Pw|E58;Nq9a#dXyLp&A9 zQIqt%q=_+}aAi6tuIMZEj5IDaXo^)8OI)7$(2bfz_=Wv`=!>QpI>~GjMB7$@nUyD< zO?p86z|2v1Ta5LrMj_;U=zlbj!X{@fD6y!aDK>AeSL#Mgshp(BE+69gBt;79zs6RqCqhSr`R1@EB zuBg|L=P_<~Pi%$$;%-dLkQjMS70@krD`dy>`oF{+s@l2-Mw?J4}Q55&c7_ zO0u0|w|n>AWkEWQF+u)W4KEU&^{TI9`|W+u2h4l@ z_<01|nO@-CUSQpJXn{81!u`M^GvW0>zl(Ld3;C^ec*^bv>g^_I26{XS)K%(tJAjVh zc1~IAm5gfYCegqfZww=Q@Bp(*x|@4L}`4 I-g^`LAMNqoy#N3J literal 0 HcmV?d00001 From b8ddec3a7eae8ed43a35077e0d52b89aa36af903 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Fri, 8 Nov 2024 21:55:53 +0200 Subject: [PATCH 08/16] overhauled global settings saving --- CMakeLists.txt | 1 + src/MenuManager.cpp | 452 ++++++++++++++++++++-------------------- src/MenuManager.h | 85 ++++---- src/SavesManager.cpp | 2 - src/SavesManager.h | 16 -- src/SettingsManager.cpp | 25 +++ src/SettingsManager.h | 48 +++++ 7 files changed, 332 insertions(+), 297 deletions(-) delete mode 100644 src/SavesManager.cpp delete mode 100644 src/SavesManager.h create mode 100644 src/SettingsManager.cpp create mode 100644 src/SettingsManager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 61cbbaa..1c59db4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ set(SOURCES src/SettingsStringRender.cpp src/MenuManager.cpp src/RecordManager.cpp + src/SettingsManager.cpp src/Timer.cpp src/lcdui/CanvasImpl.cpp src/lcdui/Canvas.cpp diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 7497378..a7f2a4b 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -1,16 +1,4 @@ #include "MenuManager.h" -#include "rms/RecordStoreException.h" -#include "rms/RecordStoreNotOpenException.h" -#include "rms/RecordStore.h" -#include "lcdui/FontStorage.h" -#include "TextRender.h" -#include "RecordManager.h" -#include "Micro.h" -#include "LevelLoader.h" -#include "GameMenu.h" -#include "SettingsStringRender.h" -#include "utils/Time.h" -#include "config.h" MenuManager::MenuManager(Micro* var1) { @@ -20,128 +8,130 @@ MenuManager::MenuManager(Micro* var1) void MenuManager::initPart(int var1) { - int var4; + // int var4; switch (var1) { case 1: - playerName = defaultName; - field_374 = { "On", "Off" }; - field_375 = { "Keyset 1", "Keyset 2", "Keyset 3" }; + // playerName = defaultName; + onOffLabels = { "On", "Off" }; + inputLabels = { "Keyset 1", "Keyset 2", "Keyset 3" }; recordManager = new RecordManager(); trackTimeMs = -1L; trackTimeFormatted.clear(); - isRecordStoreOpened = false; - savedData = std::vector(19); - - for (int idx = 0; idx < 19; ++idx) { - savedData[idx] = -127; - } - - try { - recordStore = RecordStore::openRecordStore(GlobalSetting::GlobalSaveFileName, true); - isRecordStoreOpened = true; - return; - } catch (RecordStoreException& var9) { - isRecordStoreOpened = false; - return; - } + // isRecordStoreOpened = false; + // savedData = std::vector(19); + + // for (int idx = 0; idx < 19; ++idx) { + // savedData[idx] = -127; + // } + + // try { + // recordStore = RecordStore::openRecordStore(GlobalSetting::GlobalSaveFileName, true); + // isRecordStoreOpened = true; + // return; + // } catch (RecordStoreException& var9) { + // isRecordStoreOpened = false; + // return; + // } case 2: { - recorcStoreRecordId = -1; - - RecordEnumeration* records; - try { - records = recordStore->enumerateRecords(nullptr, nullptr, false); - } catch (RecordStoreNotOpenException& var8) { - return; - } - - std::vector var3; - if (records->numRecords() > 0) { - try { - var3 = records->nextRecord(); - records->reset(); - recorcStoreRecordId = records->nextRecordId(); - } catch (RecordStoreException& var7) { - return; - } - - if (var3.size() <= 19) { - for (std::size_t i = 0; i < var3.size(); ++i) { - savedData[i] = var3[i]; - } - } - - // records->destroy(); - } - - var3 = method_216(16, (int8_t)-1); - if (!var3.empty() && var3[0] != -1) { - for (var4 = 0; var4 < 3; ++var4) { - playerName[var4] = var3[var4]; - } - } + // recorcStoreRecordId = -1; + + // RecordEnumeration* records; + // try { + // records = recordStore->enumerateRecords(nullptr, nullptr, false); + // } catch (RecordStoreNotOpenException& var8) { + // return; + // } + + settings = SettingsManager::loadSettings(); + + // std::vector var3; + // if (records->numRecords() > 0) { + // try { + // var3 = records->nextRecord(); + // records->reset(); + // recorcStoreRecordId = records->nextRecordId(); + // } catch (RecordStoreException& var7) { + // return; + // } + + // if (var3.size() <= 19) { + // for (std::size_t i = 0; i < var3.size(); ++i) { + // savedData[i] = var3[i]; + // } + // } + + // // records->destroy(); + // } + + // var3 = method_216(16, (int8_t)-1); + // if (!var3.empty() && var3[0] != -1) { + // for (var4 = 0; var4 < 3; ++var4) { + // playerName[var4] = var3[var4]; + // } + // } // cheat code: set name to RKE to enable all leagues ??? - if (playerName[0] == 82 && playerName[1] == 75 && playerName[2] == 69) { - availableLeagues = 3; - availableLevels = 2; - availableTracks[0] = (int8_t)(micro->levelLoader->levelNames[0].size() - 1); - availableTracks[1] = (int8_t)(micro->levelLoader->levelNames[1].size() - 1); - availableTracks[2] = (int8_t)(micro->levelLoader->levelNames[2].size() - 1); + if (settings.playerName[0] == 82 && settings.playerName[1] == 75 && settings.playerName[2] == 69) { + settings.availableLeagues = 3; + settings.availableLevels = 2; + settings.availableTracks[0] = (int8_t)(micro->levelLoader->levelNames[0].size() - 1); + settings.availableTracks[1] = (int8_t)(micro->levelLoader->levelNames[1].size() - 1); + settings.availableTracks[2] = (int8_t)(micro->levelLoader->levelNames[2].size() - 1); return; } - availableLeagues = 0; - availableLevels = 0; - availableTracks[0] = 0; - availableTracks[1] = 0; - availableTracks[2] = -1; + settings.availableLeagues = 0; + settings.availableLevels = 0; + settings.availableTracks[0] = 0; + settings.availableTracks[1] = 0; + settings.availableTracks[2] = -1; } return; case 3: - isDisablePerspective = getSettingOrDefault(0, isDisablePerspective); - isDisabledShadows = getSettingOrDefault(1, isDisabledShadows); - isDisabledDriverSprite = getSettingOrDefault(2, isDisabledDriverSprite); - isDisabledBikeSprite = getSettingOrDefault(3, isDisabledBikeSprite); - field_367 = getSettingOrDefault(14, field_367); - isDisableLookAhead = getSettingOrDefault(4, isDisableLookAhead); - field_369 = getSettingOrDefault(11, field_369); - field_370 = getSettingOrDefault(10, field_370); - field_371 = getSettingOrDefault(12, field_371); + // isDisablePerspective = getSettingOrDefault(0, isDisablePerspective); + // isDisabledShadows = getSettingOrDefault(1, isDisabledShadows); + // isDisabledDriverSprite = getSettingOrDefault(2, isDisabledDriverSprite); + // isDisabledBikeSprite = getSettingOrDefault(3, isDisabledBikeSprite); + // field_367 = getSettingOrDefault(14, field_367); + // isDisableLookAhead = getSettingOrDefault(4, isDisableLookAhead); + // field_369 = getSettingOrDefault(11, field_369); + // field_370 = getSettingOrDefault(10, field_370); + // field_371 = getSettingOrDefault(12, field_371); // field_373 = getSettingOrDefault(15, field_373); - field_354 = field_370; - field_355 = field_369; + field_354 = settings.selectedLevel; + field_355 = settings.selectedTrack; - if (playerName[0] != 82 || playerName[1] != 75 || playerName[2] != 69) { - availableLeagues = getSettingOrDefault(5, availableLeagues); - availableLevels = getSettingOrDefault(6, availableLevels); + // if (settings.playerName[0] != 82 || settings.playerName[1] != 75 || settings.playerName[2] != 69) { + // // availableLeagues = getSettingOrDefault(5, availableLeagues); + // // availableLevels = getSettingOrDefault(6, availableLevels); - for (var4 = 0; var4 < 3; ++var4) { - availableTracks[var4] = getSettingOrDefault(7 + var4, availableTracks[var4]); - } - } + // // for (var4 = 0; var4 < 3; ++var4) { + // // availableTracks[var4] = getSettingOrDefault(7 + var4, availableTracks[var4]); + // // } + // } try { - field_345.at(field_370) = field_369; + field_345.at(settings.selectedLevel) = settings.selectedTrack; } catch (std::exception& var6) { - field_370 = 0; - field_369 = 0; - field_345[field_370] = field_369; + settings.selectedLevel = 0; + settings.selectedTrack = 0; + field_345[settings.selectedLevel] = settings.selectedTrack; } - LevelLoader::isEnabledPerspective = isDisablePerspective == 0; - LevelLoader::isEnabledShadows = isDisabledShadows == 0; - micro->gamePhysics->setEnableLookAhead(isDisableLookAhead == 0); - micro->gameCanvas->method_163(field_367); + LevelLoader::isEnabledPerspective = settings.perspective == 0; + LevelLoader::isEnabledShadows = settings.shadows == 0; + micro->gamePhysics->setEnableLookAhead(settings.lookAhead == 0); + micro->gameCanvas->method_163(settings.input); micro->gameCanvas->method_124(field_372 == 0); leagueNamesAll4 = { "100cc", "175cc", "220cc", "325cc" }; levelNames = micro->levelLoader->levelNames; - if (availableLeagues < 3) { + if (settings.availableLeagues < 3) { this->leagueNames = { "100cc", "175cc", "220cc" }; } else { this->leagueNames = leagueNamesAll4; } - field_360 = field_371; + field_360 = settings.selectedLeague; return; case 4: { gameMenuMain = new GameMenu("Main", micro, nullptr); @@ -168,7 +158,7 @@ void MenuManager::initPart(int var1) return; case 5: gameMenuIngame = new GameMenu("Ingame", micro, gameMenuPlay); - gameMenuEnterName = new GameMenu("Enter Name", micro, gameMenuFinished, playerName); + gameMenuEnterName = new GameMenu("Enter Name", micro, gameMenuFinished, settings.playerName); gameMenuConfirmClear = new GameMenu("Confirm Clear", micro, gameMenuOptions); gameMenuConfirmReset = new GameMenu("Confirm Reset", micro, gameMenuConfirmClear); taskPlayMenu = new TimerOrMotoPartOrMenuElem("Play Menu", gameMenuPlay, this); @@ -181,18 +171,18 @@ void MenuManager::initPart(int var1) gameMenuMain->addMenuElement(taskHelp); gameMenuMain->addMenuElement(taskAbout); gameMenuMain->addMenuElement(settingStringExitGame); - settingStringLevel = new SettingsStringRender("Level", field_370, this, field_361, false, micro, gameMenuPlay, false); - settingsStringTrack = new SettingsStringRender("Track", field_345[field_370], this, levelNames[field_370], false, micro, gameMenuPlay, false); - settingsStringLeague = new SettingsStringRender("League", field_371, this, leagueNames, false, micro, gameMenuPlay, false); + settingStringLevel = new SettingsStringRender("Level", settings.selectedLevel, this, levelLabels, false, micro, gameMenuPlay, false); + settingsStringTrack = new SettingsStringRender("Track", field_345[settings.selectedLevel], this, levelNames[settings.selectedLevel], false, micro, gameMenuPlay, false); + settingsStringLeague = new SettingsStringRender("League", settings.selectedLeague, this, leagueNames, false, micro, gameMenuPlay, false); try { - settingsStringTrack->setAvailableOptions(availableTracks[field_370]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[settings.selectedLevel]); } catch (std::exception& var5) { settingsStringTrack->setAvailableOptions(0); } - settingStringLevel->setAvailableOptions(availableLevels); - settingsStringLeague->setAvailableOptions(availableLeagues); + settingStringLevel->setAvailableOptions(settings.availableLevels); + settingsStringLeague->setAvailableOptions(settings.availableLeagues); gameTimerTaskHighscore = new TimerOrMotoPartOrMenuElem("Highscore", gameMenuHighscore, this); gameMenuHighscore->addMenuElement(settingStringBack); taskStart = new SettingsStringRender("Start>", 0, this, std::vector(), false, micro, gameMenuMain, true); @@ -203,12 +193,12 @@ void MenuManager::initPart(int var1) gameMenuPlay->addMenuElement(gameTimerTaskHighscore); gameMenuPlay->addMenuElement(settingStringGoToMain); - perspectiveSetting = new SettingsStringRender("Perspective", isDisablePerspective, this, field_374, true, micro, gameMenuOptions, false); - shadowsSetting = new SettingsStringRender("Shadows", isDisabledShadows, this, field_374, true, micro, gameMenuOptions, false); - driverSpriteSetting = new SettingsStringRender("Driver sprite", isDisabledDriverSprite, this, field_374, true, micro, gameMenuOptions, false); - bikeSpriteSetting = new SettingsStringRender("Bike sprite", isDisabledBikeSprite, this, field_374, true, micro, gameMenuOptions, false); - inputSetting = new SettingsStringRender("Input", field_367, this, field_375, false, micro, gameMenuOptions, false); - lookAheadSetting = new SettingsStringRender("Look ahead", isDisableLookAhead, this, field_374, true, micro, gameMenuOptions, false); + perspectiveSetting = new SettingsStringRender("Perspective", settings.perspective, this, onOffLabels, true, micro, gameMenuOptions, false); + shadowsSetting = new SettingsStringRender("Shadows", settings.shadows, this, onOffLabels, true, micro, gameMenuOptions, false); + driverSpriteSetting = new SettingsStringRender("Driver sprite", settings.driverSprite, this, onOffLabels, true, micro, gameMenuOptions, false); + bikeSpriteSetting = new SettingsStringRender("Bike sprite", settings.bikeSprite, this, onOffLabels, true, micro, gameMenuOptions, false); + inputSetting = new SettingsStringRender("Input", settings.input, this, inputLabels, false, micro, gameMenuOptions, false); + lookAheadSetting = new SettingsStringRender("Look ahead", settings.lookAhead, this, onOffLabels, true, micro, gameMenuOptions, false); clearHighscoreSetting = new TimerOrMotoPartOrMenuElem("Clear highscore", gameMenuConfirmClear, this); return; case 6: @@ -239,13 +229,13 @@ void MenuManager::initPart(int var1) gameMenuHelp->addMenuElement(field_318); field_319 = new GameMenu("Keys", micro, gameMenuHelp); field_320 = new TimerOrMotoPartOrMenuElem("Keys", field_319, this); - addTextRender(field_319, "- " + field_375[0] + " -"); + addTextRender(field_319, "- " + inputLabels[0] + " -"); addTextRender(field_319, "UP accelerates, DOWN brakes, RIGHT leans forward and LEFT leans backward. 1 accelerates and leans backward. 3 accelerates and leans forward. 7 brakes and leans backward. 9 brakes and leans forward."); field_319->addMenuElement(field_376.get()); - addTextRender(field_319, "- " + field_375[1] + " -"); + addTextRender(field_319, "- " + inputLabels[1] + " -"); addTextRender(field_319, "1 accelerates, 4 brakes, 6 leans forward and 5 leans backward."); field_319->addMenuElement(field_376.get()); - addTextRender(field_319, "- " + field_375[2] + " -"); + addTextRender(field_319, "- " + inputLabels[2] + " -"); addTextRender(field_319, "3 accelerates, 6 brakes, 5 leans forward and 4 leans backward."); field_319->addMenuElement(settingStringBack); gameMenuHelp->addMenuElement(field_320); @@ -300,7 +290,7 @@ void MenuManager::initPart(int var1) gameMenuIngame->addMenuElement(taskHelp); gameMenuIngame->addMenuElement(settingStringPlayMenu); field_335 = new SettingsStringRender("Ok", 0, this, std::vector(), false, micro, gameMenuMain, true); - field_336 = new SettingsStringRender("Name - " + std::string(playerName), 0, this, std::vector(), false, micro, gameMenuMain, true); + field_336 = new SettingsStringRender("Name - " + std::string(settings.playerName), 0, this, std::vector(), false, micro, gameMenuMain, true); commandOk = new Command("Ok", 4, 1); commandBack = new Command("Back", 2, 1); method_1(gameMenuMain, false); @@ -348,17 +338,17 @@ void MenuManager::method_197() { std::cout << "AFTER LOAD" << std::endl; std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - - for (auto &i: var1) { + + for (auto& i : var1) { std::cout << i << std::endl; } } - recordManager->addNewRecord(settingsStringLeague->getCurrentOptionPos(), playerName, trackTimeMs); + recordManager->addNewRecord(settingsStringLeague->getCurrentOptionPos(), settings.playerName, trackTimeMs); { std::cout << "ADD NEW RECORD" << std::endl; std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - - for (auto &i: var1) { + + for (auto& i : var1) { std::cout << i << std::endl; } } @@ -366,8 +356,8 @@ void MenuManager::method_197() { std::cout << "AFTER WRITE" << std::endl; std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - - for (auto &i: var1) { + + for (auto& i : var1) { std::cout << i << std::endl; } } @@ -385,8 +375,8 @@ void MenuManager::method_197() // recordManager->closeRecordStore(); int8_t availableLeagues = -1; if (settingsStringTrack->getMaxAvailableOptionPos() >= settingsStringTrack->getCurrentOptionPos()) { - settingsStringTrack->setAvailableOptions(settingsStringTrack->getCurrentOptionPos() + 1 < availableTracks[settingStringLevel->getCurrentOptionPos()] ? availableTracks[settingStringLevel->getCurrentOptionPos()] : settingsStringTrack->getCurrentOptionPos() + 1); - availableTracks[settingStringLevel->getCurrentOptionPos()] = (int8_t)settingsStringTrack->getMaxAvailableOptionPos() < availableTracks[settingStringLevel->getCurrentOptionPos()] ? availableTracks[settingStringLevel->getCurrentOptionPos()] : (int8_t)settingsStringTrack->getMaxAvailableOptionPos(); + settingsStringTrack->setAvailableOptions(settingsStringTrack->getCurrentOptionPos() + 1 < settings.availableTracks[settingStringLevel->getCurrentOptionPos()] ? settings.availableTracks[settingStringLevel->getCurrentOptionPos()] : settingsStringTrack->getCurrentOptionPos() + 1); + settings.availableTracks[settingStringLevel->getCurrentOptionPos()] = (int8_t)settingsStringTrack->getMaxAvailableOptionPos() < settings.availableTracks[settingStringLevel->getCurrentOptionPos()] ? settings.availableTracks[settingStringLevel->getCurrentOptionPos()] : (int8_t)settingsStringTrack->getMaxAvailableOptionPos(); } if (settingsStringTrack->getCurrentOptionPos() == settingsStringTrack->getMaxOptionPos()) { @@ -414,13 +404,13 @@ void MenuManager::method_197() } settingStringLevel->setAvailableOptions(settingStringLevel->getMaxAvailableOptionPos() + 1); - if (availableTracks[settingStringLevel->getMaxAvailableOptionPos()] == -1) { - availableTracks[settingStringLevel->getMaxAvailableOptionPos()] = 0; + if (settings.availableTracks[settingStringLevel->getMaxAvailableOptionPos()] == -1) { + settings.availableTracks[settingStringLevel->getMaxAvailableOptionPos()] = 0; } } int var3 = getCountOfRecordStoresWithPrefix(settingStringLevel->getCurrentOptionPos()); - addTextRender(gameMenuFinished, var3 + " of " + std::to_string(levelNames[settingStringLevel->getCurrentOptionPos()].size()) + " tracks in " + field_361[settingStringLevel->getCurrentOptionPos()] + " completed."); + addTextRender(gameMenuFinished, var3 + " of " + std::to_string(levelNames[settingStringLevel->getCurrentOptionPos()].size()) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); if (!field_356) { field_333->setText("Restart: " + micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos())); field_334->setText("Next: " + micro->levelLoader->getName(field_354, field_355 + 1)); @@ -428,7 +418,7 @@ void MenuManager::method_197() if (settingStringLevel->getCurrentOptionPos() < settingStringLevel->getMaxOptionPos()) { settingStringLevel->setCurentOptionPos(settingStringLevel->getCurrentOptionPos() + 1); settingsStringTrack->setCurentOptionPos(0); - settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[settingStringLevel->getCurrentOptionPos()]); } if (availableLeagues != -1) { @@ -442,7 +432,7 @@ void MenuManager::method_197() bool var4 = true; for (int var5 = 0; var5 < 3; ++var5) { - if (availableTracks[var5] != static_cast(micro->levelLoader->levelNames[var5].size() - 1)) { + if (settings.availableTracks[var5] != static_cast(micro->levelLoader->levelNames[var5].size() - 1)) { var4 = false; } } @@ -701,15 +691,16 @@ void MenuManager::method_1(GameMenu* gm, bool var2) field_360 = settingsStringLeague->getCurrentOptionPos(); method_207(field_360); } else if (gm == gameMenuFinished) { - playerName = gameMenuEnterName->getStrArr(); - field_336->setText("Name - " + std::string(playerName)); + // settings.playerName = gameMenuEnterName->getStrArr(); + strncpy(settings.playerName, gameMenuEnterName->getStrArr(), std::size(settings.playerName)); + field_336->setText("Name - " + std::string(settings.playerName)); } else if (gm == gameMenuPlay) { settingsStringTrack->setOptionsList(micro->levelLoader->levelNames[settingStringLevel->getCurrentOptionPos()]); if (currentGameMenu == field_299) { field_345[settingStringLevel->getCurrentOptionPos()] = settingsStringTrack->getCurrentOptionPos(); } - settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->setCurentOptionPos(field_345[settingStringLevel->getCurrentOptionPos()]); } @@ -759,16 +750,16 @@ void MenuManager::method_207(int var1) void MenuManager::saveSmthToRecordStoreAndCloseIt() { - if (isRecordStoreOpened) { - method_208(); + // if (isRecordStoreOpened) { + method_208(); - try { - // recordStore->closeRecordStore(); - isRecordStoreOpened = false; - } catch (RecordStoreException& var1) { - std::cout << var1.what() << std::endl; - } - } + // try { + // // recordStore->closeRecordStore(); + // isRecordStoreOpened = false; + // } catch (RecordStoreException& var1) { + // std::cout << var1.what() << std::endl; + // } + // } currentGameMenu = nullptr; } @@ -776,55 +767,54 @@ void MenuManager::saveSmthToRecordStoreAndCloseIt() void MenuManager::method_208() { // copyThreeBytesFromArr(16, playerName); - Settings settingToSave = { - .perspective = (int8_t)perspectiveSetting->getCurrentOptionPos(), - .shadows = (int8_t)shadowsSetting->getCurrentOptionPos(), - .driverSprite = (int8_t)driverSpriteSetting->getCurrentOptionPos(), - .bikeSprite = (int8_t)bikeSpriteSetting->getCurrentOptionPos(), - .lookAhead = (int8_t)lookAheadSetting->getCurrentOptionPos(), - .league = (int8_t)settingsStringLeague->getMaxAvailableOptionPos(), - .level = (int8_t)settingStringLevel->getMaxAvailableOptionPos(), - .availableEasyTracks = (int8_t)availableTracks[0], - .availableMediumTracks = (int8_t)availableTracks[1], - .availableHardTracks = (int8_t)availableTracks[2], - .unknown = (int8_t)settingStringLevel->getMaxAvailableOptionPos(), - .selectedTrack = (int8_t)settingsStringTrack->getCurrentOptionPos(), - .selectedLeague = (int8_t)settingsStringLeague->getCurrentOptionPos(), - .unknown2 = -127, - .input = (int8_t)inputSetting->getCurrentOptionPos(), - .unknown3 = -127, - .playerName = {} - }; - strcpy(settingToSave.playerName, playerName); - SettingsConverter settingsConverter = { .settings = settingToSave }; - - setValue(0, (int8_t)perspectiveSetting->getCurrentOptionPos()); - setValue(1, (int8_t)shadowsSetting->getCurrentOptionPos()); - setValue(2, (int8_t)driverSpriteSetting->getCurrentOptionPos()); - setValue(3, (int8_t)bikeSpriteSetting->getCurrentOptionPos()); - setValue(14, (int8_t)inputSetting->getCurrentOptionPos()); - setValue(4, (int8_t)lookAheadSetting->getCurrentOptionPos()); - setValue(5, (int8_t)settingsStringLeague->getMaxAvailableOptionPos()); - setValue(6, (int8_t)settingStringLevel->getMaxAvailableOptionPos()); - setValue(10, (int8_t)settingStringLevel->getCurrentOptionPos()); - setValue(11, (int8_t)settingsStringTrack->getCurrentOptionPos()); - setValue(12, (int8_t)settingsStringLeague->getCurrentOptionPos()); - - setValue(16, (int8_t)playerName[0]); - setValue(17, (int8_t)playerName[1]); - setValue(18, (int8_t)playerName[2]); - - for (int i = 0; i < 3; ++i) { - setValue(7 + i, availableTracks[i]); - } + settings.perspective = (int8_t)perspectiveSetting->getCurrentOptionPos(); + settings.shadows = (int8_t)shadowsSetting->getCurrentOptionPos(); + settings.driverSprite = (int8_t)driverSpriteSetting->getCurrentOptionPos(); + settings.bikeSprite = (int8_t)bikeSpriteSetting->getCurrentOptionPos(); + settings.lookAhead = (int8_t)lookAheadSetting->getCurrentOptionPos(); + settings.availableLeagues = (int8_t)settingsStringLeague->getMaxAvailableOptionPos(); + settings.availableLevels = (int8_t)settingStringLevel->getMaxAvailableOptionPos(); + // settings.availableEasyTracks = (int8_t)availableTracks[0]; + // settings.availableMediumTracks = (int8_t)availableTracks[1]; + // settings.availableHardTracks = (int8_t)availableTracks[2]; + settings.selectedLevel = (int8_t)settingStringLevel->getMaxAvailableOptionPos(); + settings.selectedTrack = (int8_t)settingsStringTrack->getCurrentOptionPos(); + settings.selectedLeague = (int8_t)settingsStringLeague->getCurrentOptionPos(); + settings.unknown2 = -127; + settings.input = (int8_t)inputSetting->getCurrentOptionPos(); + settings.unknown3 = -127; + + // strcpy(settingToSave.playerName, playerName); + // SettingsManager::SettingsConverter settingsConverter = { .settings = settings }; + + SettingsManager::saveSettings(settings); + // setValue(0, (int8_t)perspectiveSetting->getCurrentOptionPos()); + // setValue(1, (int8_t)shadowsSetting->getCurrentOptionPos()); + // setValue(2, (int8_t)driverSpriteSetting->getCurrentOptionPos()); + // setValue(3, (int8_t)bikeSpriteSetting->getCurrentOptionPos()); + // setValue(14, (int8_t)inputSetting->getCurrentOptionPos()); + // setValue(4, (int8_t)lookAheadSetting->getCurrentOptionPos()); + // setValue(5, (int8_t)settingsStringLeague->getMaxAvailableOptionPos()); + // setValue(6, (int8_t)settingStringLevel->getMaxAvailableOptionPos()); + // setValue(10, (int8_t)settingStringLevel->getCurrentOptionPos()); + // setValue(11, (int8_t)settingsStringTrack->getCurrentOptionPos()); + // setValue(12, (int8_t)settingsStringLeague->getCurrentOptionPos()); + + // setValue(16, (int8_t)settings.playerName[0]); + // setValue(17, (int8_t)settings.playerName[1]); + // setValue(18, (int8_t)settings.playerName[2]); + + // for (int i = 0; i < 3; ++i) { + // setValue(7 + i, availableTracks[i]); + // } - try { - recorcStoreRecordId = recordStore->addOrUpdateRecord(recorcStoreRecordId, savedData, 0, 19); - } catch (RecordStoreNotOpenException& var4) { - std::cout << var4.what() << std::endl; - } catch (RecordStoreException& var5) { - std::cout << var5.what() << std::endl; - } + // try { + // recorcStoreRecordId = recordStore->addOrUpdateRecord(recorcStoreRecordId, savedData, 0, 19); + // } catch (RecordStoreNotOpenException& var4) { + // std::cout << var4.what() << std::endl; + // } catch (RecordStoreException& var5) { + // std::cout << var5.what() << std::endl; + // } } void MenuManager::run() @@ -914,7 +904,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == settingStringPlayMenu) { settingStringLevel->setCurentOptionPos(field_354); - settingsStringTrack->setAvailableOptions(availableTracks[field_354]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[field_354]); settingsStringTrack->setCurentOptionPos(field_355); method_1(currentGameMenu->getGameMenu(), false); return; @@ -933,7 +923,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == field_333) { if (settingsStringLeague->getCurrentOptionPos() <= settingsStringLeague->getMaxAvailableOptionPos()) { settingStringLevel->setCurentOptionPos(field_354); - settingsStringTrack->setAvailableOptions(availableTracks[field_354]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[field_354]); settingsStringTrack->setCurentOptionPos(field_355); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); field_357 = true; @@ -973,7 +963,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == settingsStringTrack) { if (settingsStringTrack->method_114()) { - settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->init(); field_299 = settingsStringTrack->getGameMenu(); method_1(field_299, false); @@ -992,7 +982,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) } settingsStringTrack->setOptionsList(micro->levelLoader->levelNames[settingStringLevel->getCurrentOptionPos()]); - settingsStringTrack->setAvailableOptions(availableTracks[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setAvailableOptions(settings.availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->setCurentOptionPos(field_345[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->init(); return; @@ -1056,30 +1046,30 @@ void MenuManager::method_215(int64_t var1) trackTimeMs = var1; } -std::vector MenuManager::method_216(int var1, int8_t defaultValue) -{ - switch (var1) { - case 16: { - std::vector difficultySetting = std::vector(3); +// std::vector MenuManager::method_216(int var1, int8_t defaultValue) +// { +// switch (var1) { +// case 16: { +// std::vector difficultySetting = std::vector(3); - for (int idx = 0; idx < 3; ++idx) { - difficultySetting[idx] = savedData[16 + idx]; - } +// for (int idx = 0; idx < 3; ++idx) { +// difficultySetting[idx] = savedData[16 + idx]; +// } - if (difficultySetting[0] == -127) { - difficultySetting[0] = defaultValue; - } - return difficultySetting; - } - default: - return std::vector(); - } -} +// if (difficultySetting[0] == -127) { +// difficultySetting[0] = defaultValue; +// } +// return difficultySetting; +// } +// default: +// return std::vector(); +// } +// } -int8_t MenuManager::getSettingOrDefault(int idx, int8_t defaultValue) -{ - return savedData[idx] == -127 ? defaultValue : savedData[idx]; -} +// int8_t MenuManager::getSettingOrDefault(int idx, int8_t defaultValue) +// { +// return savedData[idx] == -127 ? defaultValue : savedData[idx]; +// } // void MenuManager::copyThreeBytesFromArr(int var1, char* var2) // { @@ -1090,12 +1080,12 @@ int8_t MenuManager::getSettingOrDefault(int idx, int8_t defaultValue) // } // } -void MenuManager::setValue(int pos, int8_t value) -{ - if (isRecordStoreOpened) { - savedData[pos] = value; - } -} +// void MenuManager::setValue(int pos, int8_t value) +// { +// if (isRecordStoreOpened) { +// savedData[pos] = value; +// } +// } void MenuManager::exit() { @@ -1110,12 +1100,12 @@ void MenuManager::exit() settingStringLevel->setAvailableOptions(1); settingsStringTrack->setCurentOptionPos(0); - playerName = defaultName; + // playerName = defaultName; inputSetting->setCurentOptionPos(0); - availableTracks[0] = 0; - availableTracks[1] = 0; - availableTracks[2] = -1; - availableLeagues = 0; + // availableTracks[0] = 0; + // availableTracks[1] = 0; + // availableTracks[2] = -1; + // availableLeagues = 0; method_208(); recordManager->deleteRecordStores(); } diff --git a/src/MenuManager.h b/src/MenuManager.h index 4eb52d6..5b6affd 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -4,7 +4,20 @@ #include #include +#include "rms/RecordStoreException.h" +#include "rms/RecordStoreNotOpenException.h" +#include "rms/RecordStore.h" +#include "lcdui/FontStorage.h" +#include "TextRender.h" +#include "RecordManager.h" +#include "Micro.h" +#include "LevelLoader.h" +#include "GameMenu.h" +#include "SettingsStringRender.h" +#include "utils/Time.h" +#include "config.h" #include "IMenuManager.h" +#include "SettingsManager.h" class Micro; class RecordManager; @@ -21,33 +34,9 @@ class IGameMenuElement; class MenuManager : public IMenuManager { private: - struct Settings { - int8_t perspective; - int8_t shadows; - int8_t driverSprite; - int8_t bikeSprite; - int8_t lookAhead; - int8_t league; - int8_t level; - int8_t availableEasyTracks; - int8_t availableMediumTracks; - int8_t availableHardTracks; - int8_t unknown; - int8_t selectedTrack; - int8_t selectedLeague; - int8_t unknown2; - int8_t input; - int8_t unknown3; - char playerName[3]; - }; - static_assert(sizeof(Settings) == 19); + SettingsManager::Settings settings; - union SettingsConverter { - Settings settings; - int8_t bytes[sizeof(Settings)]; - }; - - std::vector savedData; + // std::vector savedData; Micro* micro; RecordManager* recordManager; Command* commandOk; @@ -106,39 +95,39 @@ class MenuManager : public IMenuManager { SettingsStringRender* field_336; int64_t trackTimeMs; std::string trackTimeFormatted; - char* playerName; - char availableTracks[4]; + // char* playerName; + // char availableTracks[4]; char defaultName[4] = "AAA"; - int8_t availableLeagues = 0; - int8_t availableLevels = 0; + // int8_t availableLeagues = 0; + // int8_t availableLevels = 0; std::vector field_345 = { 0, 0, 0 }; std::vector> levelNames; std::vector leagueNames = std::vector(3); std::vector leagueNamesAll4; - RecordStore* recordStore; - int recorcStoreRecordId = -1; - bool isRecordStoreOpened; + // RecordStore* recordStore; + // int recorcStoreRecordId = -1; + // bool isRecordStoreOpened; std::unique_ptr rasterImage; TextRender* textRenderCodeBrewLink; int field_354 = 0; int field_355 = 0; bool field_356 = false; bool field_357 = false; - std::vector field_361 = { "Easy", "Medium", "Pro" }; + std::vector levelLabels = { "Easy", "Medium", "Pro" }; int64_t field_362 = 0L; - int8_t isDisablePerspective = 0; - int8_t isDisabledShadows = 0; - int8_t isDisabledDriverSprite = 0; - int8_t isDisabledBikeSprite = 0; - int8_t field_367 = 0; - int8_t isDisableLookAhead = 0; - int8_t field_369 = 0; - int8_t field_370 = 0; - int8_t field_371 = 0; + // int8_t isDisablePerspective = 0; + // int8_t isDisabledShadows = 0; + // int8_t isDisabledDriverSprite = 0; + // int8_t isDisabledBikeSprite = 0; + // int8_t field_367 = 0; + // int8_t isDisableLookAhead = 0; + // int8_t field_369 = 0; + // int8_t field_370 = 0; + // int8_t field_371 = 0; int8_t field_372 = 0; // int8_t field_373 = 0; - std::vector field_374; - std::vector field_375; + std::vector onOffLabels; + std::vector inputLabels; std::unique_ptr field_376; // Alert alert = nullptr; // TODO @@ -146,11 +135,11 @@ class MenuManager : public IMenuManager { void method_197(); void fillCanvasWithImage(Graphics* graphics); void processNonFireKeyCode(int keyCode); - std::vector method_216(int var1, int8_t var2); - int8_t getSettingOrDefault(int var1, int8_t var2); + // std::vector method_216(int var1, int8_t var2); + // int8_t getSettingOrDefault(int var1, int8_t var2); // void copyThreeBytesFromArr(int var1, char* var2); // std::string timeToString(int64_t time); - void setValue(int pos, int8_t value); + // void setValue(int pos, int8_t value); void exit(); int getCountOfRecordStoresWithPrefix(int prefixNumber); diff --git a/src/SavesManager.cpp b/src/SavesManager.cpp deleted file mode 100644 index 0d47064..0000000 --- a/src/SavesManager.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "SavesManager.h" - diff --git a/src/SavesManager.h b/src/SavesManager.h deleted file mode 100644 index 90f1bc0..0000000 --- a/src/SavesManager.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils/FileStream.h" - -namespace SavesManager { - -} \ No newline at end of file diff --git a/src/SettingsManager.cpp b/src/SettingsManager.cpp new file mode 100644 index 0000000..04ab2dd --- /dev/null +++ b/src/SettingsManager.cpp @@ -0,0 +1,25 @@ +#include "SettingsManager.h" + +SettingsManager::Settings SettingsManager::loadSettings() +{ + std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + GlobalSetting::GlobalSaveFileName; + std::cout << "loadSettings " << saveFileName << std::endl; + + FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); + + SettingsManager::SettingsConverter settingsConverter; + levelFileStream.readVariable(&settingsConverter.bytes, false, sizeof(SettingsManager::Settings)); + + return settingsConverter.settings; +} + +void SettingsManager::saveSettings(SettingsManager::Settings settings) +{ + std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + GlobalSetting::GlobalSaveFileName; + std::cout << "saveSettings " << saveFileName << std::endl; + + SettingsManager::SettingsConverter settingsConverter = { .settings = settings }; + + FileStream levelFileStream(saveFileName, std::ios::out | std::ios::binary); + levelFileStream.writeVariable(&settingsConverter.bytes, sizeof(SettingsManager::Settings)); +} \ No newline at end of file diff --git a/src/SettingsManager.h b/src/SettingsManager.h new file mode 100644 index 0000000..f10d02c --- /dev/null +++ b/src/SettingsManager.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "utils/FileStream.h" + +class SettingsManager { +public: + struct Settings { + int8_t perspective; // 0 + int8_t shadows; // 1 + int8_t driverSprite; // 2 + int8_t bikeSprite; // 3 + int8_t lookAhead; // 4 + int8_t availableLeagues; // 5 + int8_t availableLevels; // 6 + int8_t availableTracks[3]; // 7-9 + // int8_t availableEasyTracks; // 7 + // int8_t availableMediumTracks; // 8 + // int8_t availableHardTracks; // 9 + int8_t selectedLevel; // 10 + int8_t selectedTrack; // 11 + int8_t selectedLeague; // 12 + int8_t unknown2; // 13 + int8_t input; // 14 + int8_t unknown3; //15 + char playerName[3]; //16-19 + }; + static_assert(sizeof(Settings) == 19); + + union SettingsConverter { + Settings settings; + int8_t bytes[sizeof(Settings)]; + }; + + static SettingsManager::Settings loadSettings(); + static void saveSettings(SettingsManager::Settings settings); +private: + +}; \ No newline at end of file From 2ce0fb8df41bdd126b78fa6d52d70319e3b1c3cd Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Fri, 8 Nov 2024 22:38:27 +0200 Subject: [PATCH 09/16] overhauled level header loading --- CMakeLists.txt | 5 +- src/LevelLoader.cpp | 160 +++++++++++++++++++++++---------------- src/LevelLoader.h | 31 +++++--- src/MRGLoader.cpp | 16 ++-- src/MRGLoader.h | 6 +- src/MenuManager.cpp | 162 +++++++++++++++++++--------------------- src/MenuManager.h | 43 +++++------ src/Micro.cpp | 4 +- src/RecordManager.cpp | 46 +++++------- src/RecordManager.h | 21 +----- src/SettingsManager.h | 5 +- src/config.h | 8 ++ src/rms/RecordStore.cpp | 5 +- 13 files changed, 264 insertions(+), 248 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c59db4..e404d74 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(SOURCES src/class_10.cpp src/GameLevel.cpp src/LevelLoader.cpp + src/MRGLoader.cpp src/Micro.cpp src/TextRender.cpp src/GameMenu.cpp @@ -49,8 +50,8 @@ set(SOURCES src/lcdui/Font.cpp src/lcdui/Command.cpp src/lcdui/FontStorage.cpp - src/rms/RecordEnumerationImpl.cpp - src/rms/RecordStore.cpp + # src/rms/RecordEnumerationImpl.cpp + # src/rms/RecordStore.cpp ) include(cmake/CMakeRC.cmake) diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index dbdd5f1..f249c94 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -1,8 +1,4 @@ #include "LevelLoader.h" -#include "utils/FileStream.h" -#include "utils/EmbedFileStream.h" - -#include int LevelLoader::field_133 = 0; int LevelLoader::field_134 = 0; @@ -17,101 +13,137 @@ const int LevelLoader::field_118 = 1; bool LevelLoader::isEnabledPerspective = true; bool LevelLoader::isEnabledShadows = true; -LevelLoader::LevelLoader(const std::filesystem::path& mrgFilePath) +LevelLoader::LevelLoader(const std::filesystem::path& path) { for (int i = 0; i < 3; ++i) { field_123[i] = (int)((int64_t)((GamePhysics::const175_1_half[i] + 19660) >> 1) * (int64_t)((GamePhysics::const175_1_half[i] + 19660) >> 1) >> 16); field_124[i] = (int)((int64_t)((GamePhysics::const175_1_half[i] - 19660) >> 1) * (int64_t)((GamePhysics::const175_1_half[i] - 19660) >> 1) >> 16); } - if (!mrgFilePath.string().empty()) { - FileStream* fileStream = new FileStream(mrgFilePath, std::ios::in | std::ios::binary); + this->mrgFilePath = path; + // if (!mrgFilePath.string().empty()) { + // FileStream* fileStream = new FileStream(mrgFilePath, std::ios::in | std::ios::binary); - if (!fileStream->isOpen()) { - throw std::system_error(errno, std::system_category(), "Failed to open " + mrgFilePath.string()); - } + // if (!fileStream->isOpen()) { + // throw std::system_error(errno, std::system_category(), "Failed to open " + mrgFilePath.string()); + // } - levelFileStream = fileStream; - } else { - EmbedFileStream* embedFileStream = new EmbedFileStream("levels.mrg"); - levelFileStream = static_cast(embedFileStream); - } + // levelFileStream = fileStream; + // } else { + // EmbedFileStream* embedFileStream = new EmbedFileStream("levels.mrg"); + // levelFileStream = static_cast(embedFileStream); + // } - loadLevels(); - method_87(); + // loadLevels(); + trackHeaders = MRGLoader::loadLevels(this->mrgFilePath); + loadNextTrack(); } -LevelLoader::~LevelLoader() +// LevelLoader::~LevelLoader() +// { +// delete levelFileStream; +// } + +// void LevelLoader::loadLevels() +// { +// std::vector var3(40); +// std::vector var4(3); + +// for (int league = 0; league < 3; ++league) { +// levelFileStream->readVariable(&var4[league], true); +// levelOffsetInFile[league] = std::vector(var4[league]); +// levelNames[league] = std::vector(var4[league]); + +// for (int levelNp = 0; levelNp < var4[league]; ++levelNp) { +// int var7; +// levelFileStream->readVariable(&var7, true); +// levelOffsetInFile[league][levelNp] = var7; + +// for (int var8 = 0; var8 < 40; ++var8) { +// levelFileStream->readVariable(&var3[var8], true); + +// if (var3[var8] == 0) { +// std::string s = std::string(reinterpret_cast(var3.data()), var8); +// std::replace(s.begin(), s.end(), '_', ' '); +// levelNames[league][levelNp] = s; +// break; +// } +// } +// } +// } +// } + +std::string LevelLoader::getName(const int level, const int track) const { - delete levelFileStream; -} + const MRGLoader::LevelTracks l = trackHeaders.at(level); + const int tracksCount = static_cast(l.tracks.size()); -void LevelLoader::loadLevels() -{ - std::vector var3(40); - std::vector var4(3); - - for (int league = 0; league < 3; ++league) { - levelFileStream->readVariable(&var4[league], true); - levelOffsetInFile[league] = std::vector(var4[league]); - levelNames[league] = std::vector(var4[league]); - - for (int levelNp = 0; levelNp < var4[league]; ++levelNp) { - int var7; - levelFileStream->readVariable(&var7, true); - levelOffsetInFile[league][levelNp] = var7; - - for (int var8 = 0; var8 < 40; ++var8) { - levelFileStream->readVariable(&var3[var8], true); - - if (var3[var8] == 0) { - std::string s = std::string(reinterpret_cast(var3.data()), var8); - std::replace(s.begin(), s.end(), '_', ' '); - levelNames[league][levelNp] = s; - break; - } - } - } + if (level < 3 && track < tracksCount) { + return l.tracks.at(track).trackName; } -} -std::string LevelLoader::getName(int league, int level) -{ - return league < 3 && level < static_cast(levelNames[league].size()) ? levelNames[league][level] : "---"; + return "---"; } -void LevelLoader::method_87() +int LevelLoader::getTracksCount(const int level) const { - method_88(field_125, field_126 + 1); + const MRGLoader::LevelTracks l = trackHeaders.at(level); + return static_cast(l.tracks.size()); } -int LevelLoader::method_88(int var1, int var2) +std::vector LevelLoader::GetTrackNames(const int level) const { - // std::cout << "method_88 " << var1 << " " << var2 << std::endl; - field_125 = var1; - field_126 = var2; + const MRGLoader::LevelTracks levelTracks = trackHeaders.at(level); + std::vector trackNames{}; - if (field_126 >= static_cast(levelNames[field_125].size())) { - field_126 = 0; + for (auto &track: levelTracks.tracks) { + trackNames.push_back(track.trackName); } - method_89(field_125 + 1, field_126 + 1); - return field_126; + return trackNames; } -void LevelLoader::method_89(int var1, int var2) +void LevelLoader::loadNextTrack() { - // std::cout << "method_89 " << var1 << " " << var2 << std::endl; - levelFileStream->setPos(levelOffsetInFile[var1 - 1][var2 - 1]); + loadTrack(loadedLevel, loadedTrack + 1); +} + +int LevelLoader::loadTrack(const int level, const int track) +{ + std::cout << "loadTrack " << level << " " << track << std::endl; + loadedLevel = level; + loadedTrack = track; + + const MRGLoader::LevelTracks l = trackHeaders.at(level); + const int tracksCount = static_cast(l.tracks.size()); + + if (loadedTrack >= tracksCount) { + loadedTrack = 0; + } + + const MRGLoader::Track t = l.tracks.at(loadedTrack); + FileStream levelFileStream{mrgFilePath, std::ios::in | std::ios::binary}; + levelFileStream.setPos(t.offset); if (gameLevel == nullptr) { gameLevel = new GameLevel(); } - gameLevel->load(levelFileStream); + gameLevel->load(&levelFileStream); method_96(gameLevel); + // method_89(loadedLevel + 1, loadedTrack + 1); + return loadedTrack; } +// void LevelLoader::method_89(const int level, const int track) +// { +// std::cout << "method_89 " << level << " " << track << std::endl; + +// const MRGLoader::LevelTracks l = trackHeaders.at(level); +// const MRGLoader::Track t = l.tracks.at(track); + +// } + void LevelLoader::method_90(int var1) { (void)var1; diff --git a/src/LevelLoader.h b/src/LevelLoader.h index 66c6912..337edbe 100644 --- a/src/LevelLoader.h +++ b/src/LevelLoader.h @@ -5,7 +5,12 @@ #include #include #include +#include +#include "config.h" +#include "utils/FileStream.h" +#include "utils/EmbedFileStream.h" +#include "MRGLoader.h" #include "GamePhysics.h" #include "GameCanvas.h" #include "GameLevel.h" @@ -17,7 +22,9 @@ class LevelLoader { std::vector> field_121; int field_123[3]; int field_124[3]; - inline static std::vector> levelOffsetInFile = std::vector>(3); + // inline static std::vector> levelOffsetInFile = std::vector>(3); + std::array trackHeaders; + std::filesystem::path mrgFilePath; int field_132 = 0; static int field_133; @@ -25,8 +32,8 @@ class LevelLoader { static int field_135; static int field_136; - FileStream* levelFileStream; - void loadLevels(); + // FileStream* levelFileStream; + // void loadLevels(); public: static const int field_114; @@ -37,9 +44,9 @@ class LevelLoader { static bool isEnabledPerspective; static bool isEnabledShadows; GameLevel* gameLevel = nullptr; - int field_125 = 0; - int field_126 = -1; - std::vector> levelNames = std::vector>(3); + int loadedLevel = 0; + int loadedTrack = -1; + // std::vector> levelNames = std::vector>(3); int field_129; int field_130; int field_131; @@ -47,13 +54,15 @@ class LevelLoader { int field_138; LevelLoader(const std::filesystem::path& mrgFilePath); - ~LevelLoader(); + // ~LevelLoader(); - std::string getName(int league, int level); + std::string getName(const int level, const int track) const; + int getTracksCount(const int level) const; - void method_87(); - int method_88(int var1, int var2); - void method_89(int var1, int var2); + void loadNextTrack(); + int loadTrack(const int level, const int track); + std::vector GetTrackNames(const int level) const; + // void method_89(int var1, int var2); void method_90(int var1); int method_91(); diff --git a/src/MRGLoader.cpp b/src/MRGLoader.cpp index 976a739..de8c5a9 100644 --- a/src/MRGLoader.cpp +++ b/src/MRGLoader.cpp @@ -32,7 +32,7 @@ static MRGLoader::LevelTracks loadLevel(FileStream& levelFileStream, const uint8 return levelTracks; } -static std::array MRGLoader::loadLevels(const std::filesystem::path& mrgFilePath) +std::array MRGLoader::loadLevels(const std::filesystem::path& mrgFilePath) { FileStream levelFileStream(mrgFilePath, std::ios::in | std::ios::binary); std::array levels; @@ -44,7 +44,7 @@ static std::array MRGLoader::loadLevels(const std::fi return levels; } -static MRGLoader::TrackInfo MRGLoader::loadTrack(const std::filesystem::path& mrgFilePath, const uint32_t fileOffset) +MRGLoader::TrackInfo MRGLoader::loadTrack(const std::filesystem::path& mrgFilePath, const uint32_t fileOffset) { FileStream levelFileStream(mrgFilePath, std::ios::in | std::ios::binary); levelFileStream.setPos(fileOffset); @@ -183,9 +183,9 @@ static MRGLoader::TrackInfo MRGLoader::loadTrack(const std::filesystem::path& mr // } // } -int main(void) -{ - std::array levels = MRGLoader::loadLevels("./levels.mrg"); - MRGLoader::loadTrack("./levels.mrg", levels[0].tracks[0].offset); - return 0; -} +// int main(void) +// { +// std::array levels = MRGLoader::loadLevels("./levels.mrg"); +// MRGLoader::loadTrack("./levels.mrg", levels[0].tracks[0].offset); +// return 0; +// } diff --git a/src/MRGLoader.h b/src/MRGLoader.h index 9dcf06c..3358562 100644 --- a/src/MRGLoader.h +++ b/src/MRGLoader.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "utils/FileStream.h" @@ -35,6 +35,6 @@ struct LevelTracks { std::vector tracks; }; -static std::array loadLevels(const std::filesystem::path& mrgFilePath); -static MRGLoader::TrackInfo loadTrack(const std::filesystem::path& mrgFilePath, const uint32_t fileOffset); +std::array loadLevels(const std::filesystem::path& mrgFilePath); +MRGLoader::TrackInfo loadTrack(const std::filesystem::path& mrgFilePath, const uint32_t fileOffset); }; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index a7f2a4b..8a91479 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -12,8 +12,6 @@ void MenuManager::initPart(int var1) switch (var1) { case 1: // playerName = defaultName; - onOffLabels = { "On", "Off" }; - inputLabels = { "Keyset 1", "Keyset 2", "Keyset 3" }; recordManager = new RecordManager(); trackTimeMs = -1L; trackTimeFormatted.clear(); @@ -44,6 +42,9 @@ void MenuManager::initPart(int var1) settings = SettingsManager::loadSettings(); + if (settings.playerName[0] < 'A' || settings.playerName[0] > 'Z') { + strncpy(settings.playerName, defaultName, PLAYER_NAME_MAX); + } // std::vector var3; // if (records->numRecords() > 0) { // try { @@ -71,20 +72,20 @@ void MenuManager::initPart(int var1) // } // cheat code: set name to RKE to enable all leagues ??? - if (settings.playerName[0] == 82 && settings.playerName[1] == 75 && settings.playerName[2] == 69) { + if (strncmp(settings.playerName, cheatCode, PLAYER_NAME_MAX) == 0) { settings.availableLeagues = 3; settings.availableLevels = 2; - settings.availableTracks[0] = (int8_t)(micro->levelLoader->levelNames[0].size() - 1); - settings.availableTracks[1] = (int8_t)(micro->levelLoader->levelNames[1].size() - 1); - settings.availableTracks[2] = (int8_t)(micro->levelLoader->levelNames[2].size() - 1); + settings.availableTracks[0] = (int8_t)(micro->levelLoader->getTracksCount(0)); + settings.availableTracks[1] = (int8_t)(micro->levelLoader->getTracksCount(1)); + settings.availableTracks[2] = (int8_t)(micro->levelLoader->getTracksCount(2)); return; } - settings.availableLeagues = 0; - settings.availableLevels = 0; - settings.availableTracks[0] = 0; - settings.availableTracks[1] = 0; - settings.availableTracks[2] = -1; + // settings.availableLeagues = 0; + // settings.availableLevels = 0; + // settings.availableTracks[0] = 0; + // settings.availableTracks[1] = 0; + // settings.availableTracks[2] = -1; } return; case 3: @@ -124,7 +125,9 @@ void MenuManager::initPart(int var1) micro->gameCanvas->method_163(settings.input); micro->gameCanvas->method_124(field_372 == 0); leagueNamesAll4 = { "100cc", "175cc", "220cc", "325cc" }; - levelNames = micro->levelLoader->levelNames; + // levelNames = micro->levelLoader->levelNames; + // levelNames = micro->levelLoader->GetTrackNames(settingStringLevel->getCurrentOptionPos()); + if (settings.availableLeagues < 3) { this->leagueNames = { "100cc", "175cc", "220cc" }; } else { @@ -172,7 +175,7 @@ void MenuManager::initPart(int var1) gameMenuMain->addMenuElement(taskAbout); gameMenuMain->addMenuElement(settingStringExitGame); settingStringLevel = new SettingsStringRender("Level", settings.selectedLevel, this, levelLabels, false, micro, gameMenuPlay, false); - settingsStringTrack = new SettingsStringRender("Track", field_345[settings.selectedLevel], this, levelNames[settings.selectedLevel], false, micro, gameMenuPlay, false); + settingsStringTrack = new SettingsStringRender("Track", field_345[settings.selectedLevel], this, micro->levelLoader->GetTrackNames(settingStringLevel->getCurrentOptionPos()), false, micro, gameMenuPlay, false); settingsStringLeague = new SettingsStringRender("League", settings.selectedLeague, this, leagueNames, false, micro, gameMenuPlay, false); try { @@ -290,7 +293,7 @@ void MenuManager::initPart(int var1) gameMenuIngame->addMenuElement(taskHelp); gameMenuIngame->addMenuElement(settingStringPlayMenu); field_335 = new SettingsStringRender("Ok", 0, this, std::vector(), false, micro, gameMenuMain, true); - field_336 = new SettingsStringRender("Name - " + std::string(settings.playerName), 0, this, std::vector(), false, micro, gameMenuMain, true); + field_336 = new SettingsStringRender("Name - " + std::string(settings.playerName, PLAYER_NAME_MAX), 0, this, std::vector(), false, micro, gameMenuMain, true); commandOk = new Command("Ok", 4, 1); commandBack = new Command("Back", 2, 1); method_1(gameMenuMain, false); @@ -361,7 +364,7 @@ void MenuManager::method_197() std::cout << i << std::endl; } } - field_356 = false; + currentLevelFinished = false; gameMenuFinished->clearVector(); gameMenuFinished->addMenuElement(new TextRender("Time: " + trackTimeFormatted, micro)); std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); @@ -380,38 +383,48 @@ void MenuManager::method_197() } if (settingsStringTrack->getCurrentOptionPos() == settingsStringTrack->getMaxOptionPos()) { - field_356 = true; - switch (settingStringLevel->getCurrentOptionPos()) { - case 0: - if (availableLeagues < 1) { - availableLeagues = 1; - settingsStringLeague->setAvailableOptions(availableLeagues); - } - break; - case 1: - if (availableLeagues < 2) { - availableLeagues = 2; - settingsStringLeague->setAvailableOptions(availableLeagues); - } - break; - case 2: - if (availableLeagues < 3) { - availableLeagues = 3; - settingsStringLeague->setOptionsList(leagueNamesAll4); - leagueNames = leagueNamesAll4; - settingsStringLeague->setAvailableOptions(availableLeagues); - } + currentLevelFinished = true; + + // switch (settingStringLevel->getCurrentOptionPos()) { + // case 0: + // if (availableLeagues < 1) { + // availableLeagues = 1; + // settingsStringLeague->setAvailableOptions(availableLeagues); + // } + // break; + // case 1: + // if (availableLeagues < 2) { + // availableLeagues = 2; + // settingsStringLeague->setAvailableOptions(availableLeagues); + // } + // break; + // case 2: + // if (availableLeagues < 3) { + // availableLeagues = 3; + // settingsStringLeague->setOptionsList(leagueNamesAll4); + // leagueNames = leagueNamesAll4; + // settingsStringLeague->setAvailableOptions(availableLeagues); + // } + // } + + availableLeagues = settingStringLevel->getCurrentOptionPos() + 1; + + if (availableLeagues == 3) { + settingsStringLeague->setOptionsList(leagueNamesAll4); + leagueNames = leagueNamesAll4; } + settingsStringLeague->setAvailableOptions(availableLeagues); settingStringLevel->setAvailableOptions(settingStringLevel->getMaxAvailableOptionPos() + 1); + if (settings.availableTracks[settingStringLevel->getMaxAvailableOptionPos()] == -1) { settings.availableTracks[settingStringLevel->getMaxAvailableOptionPos()] = 0; } } int var3 = getCountOfRecordStoresWithPrefix(settingStringLevel->getCurrentOptionPos()); - addTextRender(gameMenuFinished, var3 + " of " + std::to_string(levelNames[settingStringLevel->getCurrentOptionPos()].size()) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); - if (!field_356) { + addTextRender(gameMenuFinished, var3 + " of " + std::to_string(micro->levelLoader->getTracksCount(settingStringLevel->getCurrentOptionPos())) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); + if (!currentLevelFinished) { field_333->setText("Restart: " + micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos())); field_334->setText("Next: " + micro->levelLoader->getName(field_354, field_355 + 1)); } else { @@ -432,7 +445,7 @@ void MenuManager::method_197() bool var4 = true; for (int var5 = 0; var5 < 3; ++var5) { - if (settings.availableTracks[var5] != static_cast(micro->levelLoader->levelNames[var5].size() - 1)) { + if (settings.availableTracks[var5] != micro->levelLoader->getTracksCount(var5)) { var4 = false; } } @@ -443,7 +456,7 @@ void MenuManager::method_197() } } - if (!field_356) { + if (!currentLevelFinished) { gameMenuFinished->addMenuElement(field_334); } @@ -485,7 +498,7 @@ void MenuManager::method_201(int var1) method_1(gameMenuIngame, false); break; case 2: { - field_362 = Time::currentTimeMillis(); + // field_362 = Time::currentTimeMillis(); gameMenuFinished->clearVector(); field_354 = settingStringLevel->getCurrentOptionPos(); field_355 = settingsStringTrack->getCurrentOptionPos(); @@ -493,7 +506,7 @@ void MenuManager::method_201(int var1) const uint8_t var2 = recordManager->getPosOfNewRecord(settingsStringLeague->getCurrentOptionPos(), trackTimeMs); trackTimeFormatted = Time::timeToString(trackTimeMs); - if (var2 < RecordManager::RECORD_NO_MAX) { + if (var2 < RECORD_NO_MAX) { TextRender* var3 = new TextRender("", micro); var3->setDx(GameCanvas::spriteSizeX[5] + 1); switch (var2) { @@ -692,10 +705,11 @@ void MenuManager::method_1(GameMenu* gm, bool var2) method_207(field_360); } else if (gm == gameMenuFinished) { // settings.playerName = gameMenuEnterName->getStrArr(); - strncpy(settings.playerName, gameMenuEnterName->getStrArr(), std::size(settings.playerName)); - field_336->setText("Name - " + std::string(settings.playerName)); + strncpy(settings.playerName, gameMenuEnterName->getStrArr(), PLAYER_NAME_MAX); + field_336->setText("Name - " + std::string(settings.playerName, PLAYER_NAME_MAX)); } else if (gm == gameMenuPlay) { - settingsStringTrack->setOptionsList(micro->levelLoader->levelNames[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setOptionsList(micro->levelLoader->GetTrackNames(settingStringLevel->getCurrentOptionPos())); + if (currentGameMenu == field_299) { field_345[settingStringLevel->getCurrentOptionPos()] = settingsStringTrack->getCurrentOptionPos(); } @@ -766,7 +780,6 @@ void MenuManager::saveSmthToRecordStoreAndCloseIt() void MenuManager::method_208() { - // copyThreeBytesFromArr(16, playerName); settings.perspective = (int8_t)perspectiveSetting->getCurrentOptionPos(); settings.shadows = (int8_t)shadowsSetting->getCurrentOptionPos(); settings.driverSprite = (int8_t)driverSpriteSetting->getCurrentOptionPos(); @@ -841,7 +854,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (menuElement == taskStart) { if (settingStringLevel->getCurrentOptionPos() <= settingStringLevel->getMaxAvailableOptionPos() && settingsStringTrack->getCurrentOptionPos() <= settingsStringTrack->getMaxAvailableOptionPos() && settingsStringLeague->getCurrentOptionPos() <= settingsStringLeague->getMaxAvailableOptionPos()) { micro->gamePhysics->disableGenerateInputAI(); - micro->levelLoader->method_88(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); + micro->levelLoader->loadTrack(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); field_357 = true; micro->menuToGame(); @@ -932,11 +945,11 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) } } else { if (menuElement == field_334) { - if (!field_356) { + if (!currentLevelFinished) { settingsStringTrack->menuElemMethod(2); } - micro->levelLoader->method_88(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); + micro->levelLoader->loadTrack(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); method_208(); field_357 = true; @@ -981,7 +994,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) gameMenuStringLevel->method_83(settingStringLevel->getCurrentOptionPos()); } - settingsStringTrack->setOptionsList(micro->levelLoader->levelNames[settingStringLevel->getCurrentOptionPos()]); + settingsStringTrack->setOptionsList(micro->levelLoader->GetTrackNames(settingStringLevel->getCurrentOptionPos())); settingsStringTrack->setAvailableOptions(settings.availableTracks[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->setCurentOptionPos(field_345[settingStringLevel->getCurrentOptionPos()]); settingsStringTrack->init(); @@ -1066,27 +1079,6 @@ void MenuManager::method_215(int64_t var1) // } // } -// int8_t MenuManager::getSettingOrDefault(int idx, int8_t defaultValue) -// { -// return savedData[idx] == -127 ? defaultValue : savedData[idx]; -// } - -// void MenuManager::copyThreeBytesFromArr(int var1, char* var2) -// { -// if (isRecordStoreOpened && var1 == 16) { -// for (int i = 0; i < 3; ++i) { -// savedData[16 + i] = var2[i]; -// } -// } -// } - -// void MenuManager::setValue(int pos, int8_t value) -// { -// if (isRecordStoreOpened) { -// savedData[pos] = value; -// } -// } - void MenuManager::exit() { perspectiveSetting->setCurentOptionPos(0); @@ -1127,18 +1119,20 @@ void MenuManager::addOkAndBackCommands() int MenuManager::getCountOfRecordStoresWithPrefix(int prefixNumber) { - std::vector storeNames = RecordStore::listRecordStores(); - if (recordManager != nullptr && !storeNames.empty()) { - int count = 0; - - for (std::size_t i = 0; i < storeNames.size(); ++i) { - if (storeNames[i].find(std::to_string(prefixNumber), 0) == 0) { - ++count; - } - } + // TODO: + // std::vector storeNames = RecordStore::listRecordStores(); + // if (recordManager != nullptr && !storeNames.empty()) { + // int count = 0; + + // for (std::size_t i = 0; i < storeNames.size(); ++i) { + // if (storeNames[i].find(std::to_string(prefixNumber), 0) == 0) { + // ++count; + // } + // } - return count; - } else { - return 0; - } + // return count; + // } else { + // return 0; + // } + return 0; } diff --git a/src/MenuManager.h b/src/MenuManager.h index 5b6affd..2b10e55 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -4,9 +4,6 @@ #include #include -#include "rms/RecordStoreException.h" -#include "rms/RecordStoreNotOpenException.h" -#include "rms/RecordStore.h" #include "lcdui/FontStorage.h" #include "TextRender.h" #include "RecordManager.h" @@ -19,18 +16,18 @@ #include "IMenuManager.h" #include "SettingsManager.h" -class Micro; -class RecordManager; -class Command; -class GameMenu; -class TimerOrMotoPartOrMenuElem; -class SettingsStringRender; -class RecordStore; -class Image; -class TextRender; -class Graphics; -class Displayable; -class IGameMenuElement; +// class Micro; +// class RecordManager; +// class Command; +// class GameMenu; +// class TimerOrMotoPartOrMenuElem; +// class SettingsStringRender; +// class RecordStore; +// class Image; +// class TextRender; +// class Graphics; +// class Displayable; +// class IGameMenuElement; class MenuManager : public IMenuManager { private: @@ -97,11 +94,10 @@ class MenuManager : public IMenuManager { std::string trackTimeFormatted; // char* playerName; // char availableTracks[4]; - char defaultName[4] = "AAA"; // int8_t availableLeagues = 0; // int8_t availableLevels = 0; std::vector field_345 = { 0, 0, 0 }; - std::vector> levelNames; + // std::vector> levelNames; std::vector leagueNames = std::vector(3); std::vector leagueNamesAll4; // RecordStore* recordStore; @@ -111,10 +107,9 @@ class MenuManager : public IMenuManager { TextRender* textRenderCodeBrewLink; int field_354 = 0; int field_355 = 0; - bool field_356 = false; + bool currentLevelFinished = false; bool field_357 = false; - std::vector levelLabels = { "Easy", "Medium", "Pro" }; - int64_t field_362 = 0L; + // int64_t field_362 = 0L; // int8_t isDisablePerspective = 0; // int8_t isDisabledShadows = 0; // int8_t isDisabledDriverSprite = 0; @@ -126,10 +121,13 @@ class MenuManager : public IMenuManager { // int8_t field_371 = 0; int8_t field_372 = 0; // int8_t field_373 = 0; - std::vector onOffLabels; - std::vector inputLabels; std::unique_ptr field_376; + // Alert alert = nullptr; // TODO + char defaultName[4] = "AAA"; + std::vector onOffLabels = { "On", "Off" };; + std::vector inputLabels = { "Keyset 1", "Keyset 2", "Keyset 3" }; + std::vector levelLabels = { "Easy", "Medium", "Pro" }; void addTextRender(GameMenu* gameMenu, std::string text); void method_197(); @@ -137,7 +135,6 @@ class MenuManager : public IMenuManager { void processNonFireKeyCode(int keyCode); // std::vector method_216(int var1, int8_t var2); // int8_t getSettingOrDefault(int var1, int8_t var2); - // void copyThreeBytesFromArr(int var1, char* var2); // std::string timeToString(int64_t time); // void setValue(int pos, int8_t value); void exit(); diff --git a/src/Micro.cpp b/src/Micro.cpp index 01fc2d6..70fbe78 100644 --- a/src/Micro.cpp +++ b/src/Micro.cpp @@ -7,7 +7,6 @@ #include "utils/Time.h" #include "utils/Hashing.h" #include "lcdui/CanvasImpl.h" -#include "rms/RecordStore.h" #include "config.h" bool Micro::gameStarted = false; @@ -162,7 +161,8 @@ void Micro::startApp(int argc, char** argv) GlobalSetting::SavesPrefix = Hashing::HashFileMD5(GlobalSetting::MrgFilePath.string()); std::cout << "hash: " << GlobalSetting::SavesPrefix << std::endl; - RecordStore::setRecordStoreDir(argv[0]); + // TODO: + // RecordStore::setRecordStoreDir(argv[0]); gameStarted = true; // if (thread == null) { diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index c04998a..e0816dd 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -2,24 +2,14 @@ void RecordManager::loadRecordInfo(const uint8_t level, const uint8_t track) { - // resetRecordsTime(); + recordsSaveDataConverter = { .bytes = {} }; std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + std::to_string(level) + std::to_string(track); std::cout << "loadRecordInfo " << saveFileName << std::endl; - + FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); levelFileStream.readVariable(&recordsSaveDataConverter.bytes, false, sizeof(RecordsSaveData)); } -void RecordManager::resetRecordsTime() -{ - recordsSaveDataConverter = { .bytes = {} }; - // for (uint8_t league = 0; league < LEAGUES_MAX; ++league) { - // for (uint8_t pos = 0; pos < RECORD_NO_MAX; ++pos) { - // recordsSaveData.leagueRecords[league].records[pos].timeMs = 0L; - // } - // } -} - std::vector RecordManager::getRecordDescription(const uint8_t league) { std::vector recordsDescription = std::vector(RECORD_NO_MAX); @@ -29,7 +19,9 @@ std::vector RecordManager::getRecordDescription(const uint8_t leagu if (record.timeMs != 0L) { std::stringstream ss; - ss << record.playerName << ' ' << Time::timeToString(record.timeMs); + ss << std::string(record.playerName, PLAYER_NAME_MAX) + << ' ' + << Time::timeToString(record.timeMs); recordsDescription[i] = ss.str(); } else { recordsDescription[i].clear(); @@ -85,24 +77,26 @@ void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos] = { .timeMs = timeMs, - .playerName = {} + .playerName = {}, + .padding = {0, 0, 0, 0, 0} }; - strcpy(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos].playerName, playerName); + strncpy(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos].playerName, playerName, PLAYER_NAME_MAX); } void RecordManager::deleteRecordStores() { - std::vector names = RecordStore::listRecordStores(); - - for (std::size_t i = 0; i < names.size(); ++i) { - if (names[i] != GlobalSetting::GlobalSaveFileName) { - try { - RecordStore::deleteRecordStore(names[i]); - } catch (RecordStoreException& var3) { - return; - } - } - } + // TODO: + // std::vector names = RecordStore::listRecordStores(); + + // for (std::size_t i = 0; i < names.size(); ++i) { + // if (names[i] != GlobalSetting::GlobalSaveFileName) { + // try { + // RecordStore::deleteRecordStore(names[i]); + // } catch (RecordStoreException& var3) { + // return; + // } + // } + // } } // void RecordManager::closeRecordStore() diff --git a/src/RecordManager.h b/src/RecordManager.h index 78ca962..10f9116 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -8,21 +8,11 @@ #include "config.h" #include "utils/Time.h" - -#include "rms/RecordStore.h" -#include "rms/RecordStoreException.h" -#include "rms/RecordStoreNotOpenException.h" -#include "rms/InvalidRecordIDException.h" - -// class RecordStore; +#include "utils/FileStream.h" class RecordManager { public: - enum { - LEAGUES_MAX = 4, - RECORD_NO_MAX = 3, - PLAYER_NAME_MAX = 3, - }; + // inline static const int unused = 3; @@ -40,6 +30,7 @@ class RecordManager { struct /*__attribute__((packed))*/ Record { int64_t timeMs; char playerName[PLAYER_NAME_MAX]; + uint8_t padding[5]; }; static_assert(sizeof(Record) == 16); @@ -59,11 +50,5 @@ class RecordManager { }; static_assert(sizeof(RecordsSaveDataConverter) == sizeof(RecordsSaveData)); - // RecordStore* recordStore = nullptr; - // int packedRecordInfoRecordId = -1; RecordsSaveDataConverter recordsSaveDataConverter; - // RecordsSaveData recordsSaveData; - - void resetRecordsTime(); - // void shiftRecords(const uint8_t league, const uint8_t position); }; diff --git a/src/SettingsManager.h b/src/SettingsManager.h index f10d02c..195b814 100644 --- a/src/SettingsManager.h +++ b/src/SettingsManager.h @@ -23,16 +23,13 @@ class SettingsManager { int8_t availableLeagues; // 5 int8_t availableLevels; // 6 int8_t availableTracks[3]; // 7-9 - // int8_t availableEasyTracks; // 7 - // int8_t availableMediumTracks; // 8 - // int8_t availableHardTracks; // 9 int8_t selectedLevel; // 10 int8_t selectedTrack; // 11 int8_t selectedLeague; // 12 int8_t unknown2; // 13 int8_t input; // 14 int8_t unknown3; //15 - char playerName[3]; //16-19 + char playerName[PLAYER_NAME_MAX]; //16-19 }; static_assert(sizeof(Settings) == 19); diff --git a/src/config.h b/src/config.h index 9d991b0..3cb5be3 100644 --- a/src/config.h +++ b/src/config.h @@ -5,6 +5,14 @@ #include #include +enum { + LEAGUES_MAX = 4, + RECORD_NO_MAX = 3, + PLAYER_NAME_MAX = 3, +}; + +const char cheatCode[] = "RKE"; + struct GlobalSetting { static bool WindowFullscreen; static uint8_t LogoMultiplier; diff --git a/src/rms/RecordStore.cpp b/src/rms/RecordStore.cpp index c0b0c8a..a33ac14 100644 --- a/src/rms/RecordStore.cpp +++ b/src/rms/RecordStore.cpp @@ -43,7 +43,7 @@ int RecordStore::addOrUpdateRecord(int recordId, std::vector arr, int of { if (recordId == -1) { return this->addRecord(arr, offset, numBytes); - } + } this->setRecord(recordId, arr, offset, numBytes); return recordId; @@ -84,8 +84,7 @@ RecordEnumerationImpl* RecordStore::load(std::filesystem::path filePath) RecordStore* RecordStore::openRecordStore(std::string name, bool createIfNecessary) { - if (name.empty()) - { + if (name.empty()) { log("empty name"); return nullptr; } From f54578ec2ffe2c89ea81005b228fb17a9c32af24 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sat, 9 Nov 2024 22:05:34 +0200 Subject: [PATCH 10/16] overhauled game controls --- README.md | 17 ++++ notes.md | 20 ----- src/GameCanvas.cpp | 107 ++++++++++------------ src/GameCanvas.h | 33 ++++--- src/MRGLoader.cpp | 6 +- src/MenuManager.cpp | 185 ++++++++++++++++++--------------------- src/MenuManager.h | 22 +---- src/Micro.cpp | 8 +- src/config.h | 49 +++++++++++ src/lcdui/Canvas.cpp | 27 +----- src/lcdui/Canvas.h | 25 +++--- src/lcdui/CanvasImpl.cpp | 58 ++++-------- src/lcdui/CanvasImpl.h | 8 +- todo.md | 3 - 14 files changed, 270 insertions(+), 298 deletions(-) delete mode 100644 notes.md delete mode 100644 todo.md diff --git a/README.md b/README.md index f96a492..cefba7f 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,23 @@ This is the C++ & SDL2 port of Gravity Defied, which includes all the features o ***This Project is not associated with Codebrew Software in any fashion. All rights to the original Gravity Defied, it's name, logotype, brand and all that stuff belong to Codebrew Software.*** +# About the fork + +- overhauled saving data to files (simplified, changed it to a C/C++ way) +- fixed: game does not save progress after the first save +- fixed: saving high score +- overhauled controls logic (simplified, per key setting instead of predefined key sets) +- added fullscreen and proper scaling for different aspect ratios +- renamed portions of a code to something meaningful + +# TODO + +- [ ] config file +- [ ] command line flags +- [ ] level file selector +- [ ] further refactoring +- [ ] scaling game (or at least font) + # Authors ### Gravity Defied Cpp authors diff --git a/notes.md b/notes.md deleted file mode 100644 index 092ddf0..0000000 --- a/notes.md +++ /dev/null @@ -1,20 +0,0 @@ -Settings (bytes) -0 - perspective (on-off) -1 - shadows (on-off) -2 - driver sprite (on-off) -3 - bike sprite (on-off) -4 - look ahead (on-off) -5 - enabled leagues count (0-3) (4 leagues in total) -6 - enabled levels count (0-2) (3 levels in total) -7 - number of enabled easy level tracks -8 - number of enabled medium level tracks -9 - number of enabled hard level tracks -10 - level ? -11 - track ? -12 - league ? -13 - ? -14 - inputSetting ? -15 - ? -16 - player name (char) -17 - player name (char) -18 - player name (char) diff --git a/src/GameCanvas.cpp b/src/GameCanvas.cpp index 4bb2af2..300b99a 100644 --- a/src/GameCanvas.cpp +++ b/src/GameCanvas.cpp @@ -1,14 +1,4 @@ #include "GameCanvas.h" -#include "MathF16.h" -#include "GamePhysics.h" -#include "MenuManager.h" -#include "lcdui/Image.h" -#include "lcdui/FontStorage.h" -#include "utils/Time.h" -#include "config.h" - -#include -#include GameCanvas::GameCanvas(Micro* micro) { @@ -116,7 +106,7 @@ int GameCanvas::loadSprites(int flags) void GameCanvas::method_129() { - method_164(); + resetActions(); } void GameCanvas::setViewPosition(int dx, int dy) @@ -451,10 +441,10 @@ void GameCanvas::drawProgressBar(int var1, bool mode) GlobalSetting::BarH - (2 * GlobalSetting::LoadingBarPadding)); } -void GameCanvas::method_163(int var1) -{ - field_232 = var1; -} +// void GameCanvas::method_163(int var1) +// { +// field_232 = var1; +// } void GameCanvas::paint(Graphics* graphics) { @@ -476,40 +466,47 @@ void GameCanvas::paint(Graphics* graphics) } } -void GameCanvas::method_164() +void GameCanvas::resetActions() { - int var1; - for (var1 = 0; var1 < 10; ++var1) { - activeKeys[var1] = false; - } - - for (var1 = 0; var1 < 7; ++var1) { - activeActions[var1] = false; - } + activeActions[Keys::UP] = false; + activeActions[Keys::DOWN] = false; + activeActions[Keys::LEFT] = false; + activeActions[Keys::RIGHT] = false; + activeActions[Keys::FIRE] = false; + activeActions[Keys::BACK] = false; } void GameCanvas::handleUpdatedInput() { - int var1 = 0; - int var2 = 0; - int var3 = field_232; + int verticalMovement = 0; // var1 + int horizontalMovement = 0; // var2 + // int var3 = field_232; - int var4; - for (var4 = 0; var4 < 10; ++var4) { - if (activeKeys[var4]) { - var1 += field_231[var3][var4][0]; - var2 += field_231[var3][var4][1]; - } - } + // int var4; + // for (var4 = 0; var4 < 10; ++var4) { + // if (activeKeys[var4]) { + // var1 += field_231[var3][var4][0]; + // var2 += field_231[var3][var4][1]; + // } + // } - for (var4 = 0; var4 < 7; ++var4) { - if (activeActions[var4]) { - var1 += field_230[var4][0]; - var2 += field_230[var4][1]; + // for (var4 = 0; var4 < 7; ++var4) { + // if (activeActions[var4]) { + // var1 += field_230[var4][0]; + // var2 += field_230[var4][1]; + // } + // } + + for (const auto& [action, isActive] : activeActions) { + if (!isActive) { + continue; } + + verticalMovement += availableActions[action][0]; + horizontalMovement += availableActions[action][1]; } - gamePhysics->method_30(var1, var2); + gamePhysics->method_30(verticalMovement, horizontalMovement); } void GameCanvas::processTimers() @@ -524,30 +521,15 @@ void GameCanvas::processTimers() } } -void GameCanvas::processKeyPressed(int keyCode) +void GameCanvas::processKeyPressed(const Keys keyCode) { - int action = getGameAction(keyCode); - int numKey; - // KEY_NUM0 - KEY_NUM10 is 48-58 - if ((numKey = keyCode - 48) >= 0 && numKey < 10) { - activeKeys[numKey] = true; - } else if (action >= 0 && action < 7) { - activeActions[action] = true; - } - + activeActions[keyCode] = true; handleUpdatedInput(); } -void GameCanvas::processKeyReleased(int keyCode) +void GameCanvas::processKeyReleased(const Keys keyCode) { - int action = getGameAction(keyCode); - int numKey; - if ((numKey = keyCode - 48) >= 0 && numKey < 10) { - activeKeys[numKey] = false; - } else if (action >= 0 && action < 7) { - activeActions[action] = false; - } - + activeActions[keyCode] = false; handleUpdatedInput(); } @@ -579,17 +561,22 @@ void GameCanvas::method_168(Command* var1, Displayable* var2) } } -void GameCanvas::keyPressed(int var1) +void GameCanvas::keyPressed(const Keys var1) { if (Micro::isInGameMenu && menuManager != nullptr) { menuManager->processKeyCode(var1); + return; } processKeyPressed(var1); } -void GameCanvas::keyReleased(int var1) +void GameCanvas::keyReleased(const Keys var1) { + if (var1 == Keys::BACK) { + pressedEsc(); + } + processKeyReleased(var1); } diff --git a/src/GameCanvas.h b/src/GameCanvas.h index 6d64736..d9dd6ba 100644 --- a/src/GameCanvas.h +++ b/src/GameCanvas.h @@ -2,6 +2,7 @@ #include #include +#include #include "lcdui/Graphics.h" #include "lcdui/Command.h" @@ -10,13 +11,24 @@ #include "Micro.h" #include "Timer.h" +#include "config.h" +#include "MathF16.h" +#include "GamePhysics.h" +#include "MenuManager.h" +#include "lcdui/Image.h" +#include "lcdui/FontStorage.h" +#include "utils/Time.h" +#include "config.h" + +#include +#include class GamePhysics; class MenuManager; class GameCanvas : public Canvas, public CommandListener { private: - void method_164(); + void resetActions(); void handleUpdatedInput(); void processTimers(); @@ -56,11 +68,12 @@ class GameCanvas : public Canvas, public CommandListener { inline static int field_226 = 0; const int startFlagAnimationTimeToSpriteNo[4] = { 12, 10, 11, 10 }; const int finishFlagAnumationTimeToSpriteNo[4] = { 14, 13, 15, 13 }; - int field_230[7][2] = { { 0, 0 }, { 1, 0 }, { 0, -1 }, { 0, 0 }, { 0, 0 }, { 0, 1 }, { -1, 0 } }; - int field_231[3][10][2] = { { { 0, 0 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, -1 }, { -1, 0 }, { 0, 1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } }, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 0, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }, { -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } } }; - int field_232 = 2; - std::vector activeActions = std::vector(7); + // int field_230[7][2] = { { 0, 0 }, { 1, 0 }, { 0, -1 }, { 0, 0 }, { 0, 0 }, { 0, 1 }, { -1, 0 } }; + // int field_231[3][10][2] = { { { 0, 0 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, -1 }, { -1, 0 }, { 0, 1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } }, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 0, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }, { -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } } }; + // int field_232 = 2; + // std::vector activeActions = std::vector(7); std::vector activeKeys = std::vector(10); + std::map activeActions = std::map(); int fps; @@ -98,16 +111,16 @@ class GameCanvas : public Canvas, public CommandListener { void setColor(int red, int green, int blue); void drawGame(Graphics* g); void drawProgressBar(int var1, bool mode); - void method_163(int var1); + // void method_163(int var1); void paint(Graphics* g); void init(GamePhysics* gamePhysics); - void processKeyPressed(int keyCode); - void processKeyReleased(int keyCode); + void processKeyPressed(const Keys keyCode); + void processKeyReleased(const Keys keyCode); void scheduleGameTimerTask(std::string var1, int delayMs); void setMenuManager(MenuManager* menuManager); void method_168(Command* var1, Displayable* var2); - void keyPressed(int var1); - void keyReleased(int var1); + void keyPressed(const Keys var1); + void keyReleased(const Keys var1); void commandAction(Command* var1, Displayable* var2); void removeMenuCommand(); void addMenuCommand(); diff --git a/src/MRGLoader.cpp b/src/MRGLoader.cpp index de8c5a9..8c6c9f2 100644 --- a/src/MRGLoader.cpp +++ b/src/MRGLoader.cpp @@ -26,9 +26,10 @@ static MRGLoader::LevelTracks loadLevel(FileStream& levelFileStream, const uint8 std::cout << levelTracks.tracksCount << " TRACKS" << std::endl; for (auto& i : levelTracks.tracks) { - std::cout << i.offset << " " << i.trackName << std::endl; + std::cout << i.offset << " " << i.trackName << '\n'; } + std::cout << std::endl; return levelTracks; } @@ -109,9 +110,10 @@ MRGLoader::TrackInfo MRGLoader::loadTrack(const std::filesystem::path& mrgFilePa } for (auto& i : trackInfo.points) { - std::cout << "X: " << i.x << " Y: " << i.y << std::endl; + std::cout << "X: " << i.x << " Y: " << i.y << '\n'; } + std::cout << std::endl; return trackInfo; } diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 8a91479..67629fa 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -10,7 +10,7 @@ void MenuManager::initPart(int var1) { // int var4; switch (var1) { - case 1: + case 1: { // playerName = defaultName; recordManager = new RecordManager(); trackTimeMs = -1L; @@ -30,6 +30,8 @@ void MenuManager::initPart(int var1) // isRecordStoreOpened = false; // return; // } + return; + } case 2: { // recorcStoreRecordId = -1; @@ -86,9 +88,9 @@ void MenuManager::initPart(int var1) // settings.availableTracks[0] = 0; // settings.availableTracks[1] = 0; // settings.availableTracks[2] = -1; - } return; - case 3: + } + case 3: { // isDisablePerspective = getSettingOrDefault(0, isDisablePerspective); // isDisabledShadows = getSettingOrDefault(1, isDisabledShadows); // isDisabledDriverSprite = getSettingOrDefault(2, isDisabledDriverSprite); @@ -122,7 +124,7 @@ void MenuManager::initPart(int var1) LevelLoader::isEnabledPerspective = settings.perspective == 0; LevelLoader::isEnabledShadows = settings.shadows == 0; micro->gamePhysics->setEnableLookAhead(settings.lookAhead == 0); - micro->gameCanvas->method_163(settings.input); + // micro->gameCanvas->method_163(settings.input); micro->gameCanvas->method_124(field_372 == 0); leagueNamesAll4 = { "100cc", "175cc", "220cc", "325cc" }; // levelNames = micro->levelLoader->levelNames; @@ -136,6 +138,7 @@ void MenuManager::initPart(int var1) field_360 = settings.selectedLeague; return; + } case 4: { gameMenuMain = new GameMenu("Main", micro, nullptr); gameMenuPlay = new GameMenu("Play", micro, gameMenuMain); @@ -157,9 +160,9 @@ void MenuManager::initPart(int var1) textRenderCodeBrewLink->setFont(boldSmallFont); gameMenuHighscore = new GameMenu("Highscore", micro, gameMenuPlay); gameMenuFinished = new GameMenu("Finished!", micro, gameMenuPlay); - } return; - case 5: + } + case 5: { gameMenuIngame = new GameMenu("Ingame", micro, gameMenuPlay); gameMenuEnterName = new GameMenu("Enter Name", micro, gameMenuFinished, settings.playerName); gameMenuConfirmClear = new GameMenu("Confirm Clear", micro, gameMenuOptions); @@ -200,16 +203,17 @@ void MenuManager::initPart(int var1) shadowsSetting = new SettingsStringRender("Shadows", settings.shadows, this, onOffLabels, true, micro, gameMenuOptions, false); driverSpriteSetting = new SettingsStringRender("Driver sprite", settings.driverSprite, this, onOffLabels, true, micro, gameMenuOptions, false); bikeSpriteSetting = new SettingsStringRender("Bike sprite", settings.bikeSprite, this, onOffLabels, true, micro, gameMenuOptions, false); - inputSetting = new SettingsStringRender("Input", settings.input, this, inputLabels, false, micro, gameMenuOptions, false); + // inputSetting = new SettingsStringRender("Input", settings.input, this, inputLabels, false, micro, gameMenuOptions, false); lookAheadSetting = new SettingsStringRender("Look ahead", settings.lookAhead, this, onOffLabels, true, micro, gameMenuOptions, false); clearHighscoreSetting = new TimerOrMotoPartOrMenuElem("Clear highscore", gameMenuConfirmClear, this); return; - case 6: + } + case 6: { gameMenuOptions->addMenuElement(perspectiveSetting); gameMenuOptions->addMenuElement(shadowsSetting); gameMenuOptions->addMenuElement(driverSpriteSetting); gameMenuOptions->addMenuElement(bikeSpriteSetting); - gameMenuOptions->addMenuElement(inputSetting); + // gameMenuOptions->addMenuElement(inputSetting); gameMenuOptions->addMenuElement(lookAheadSetting); gameMenuOptions->addMenuElement(clearHighscoreSetting); gameMenuOptions->addMenuElement(settingStringBack); @@ -230,18 +234,18 @@ void MenuManager::initPart(int var1) addTextRender(field_317, "Race to the finish line as fast as you can without crashing. By leaning forward and backward you can adjust the rotation of your bike. By landing on both wheels after jumping, your bike won't crash as easily. Beware, the levels tend to get harder and harder..."); field_317->addMenuElement(settingStringBack); gameMenuHelp->addMenuElement(field_318); - field_319 = new GameMenu("Keys", micro, gameMenuHelp); - field_320 = new TimerOrMotoPartOrMenuElem("Keys", field_319, this); - addTextRender(field_319, "- " + inputLabels[0] + " -"); - addTextRender(field_319, "UP accelerates, DOWN brakes, RIGHT leans forward and LEFT leans backward. 1 accelerates and leans backward. 3 accelerates and leans forward. 7 brakes and leans backward. 9 brakes and leans forward."); - field_319->addMenuElement(field_376.get()); - addTextRender(field_319, "- " + inputLabels[1] + " -"); - addTextRender(field_319, "1 accelerates, 4 brakes, 6 leans forward and 5 leans backward."); - field_319->addMenuElement(field_376.get()); - addTextRender(field_319, "- " + inputLabels[2] + " -"); - addTextRender(field_319, "3 accelerates, 6 brakes, 5 leans forward and 4 leans backward."); - field_319->addMenuElement(settingStringBack); - gameMenuHelp->addMenuElement(field_320); + // field_319 = new GameMenu("Keys", micro, gameMenuHelp); + // field_320 = new TimerOrMotoPartOrMenuElem("Keys", field_319, this); + // addTextRender(field_319, "- " + inputLabels[0] + " -"); + // addTextRender(field_319, "UP accelerates, DOWN brakes, RIGHT leans forward and LEFT leans backward. 1 accelerates and leans backward. 3 accelerates and leans forward. 7 brakes and leans backward. 9 brakes and leans forward."); + // field_319->addMenuElement(field_376.get()); + // addTextRender(field_319, "- " + inputLabels[1] + " -"); + // addTextRender(field_319, "1 accelerates, 4 brakes, 6 leans forward and 5 leans backward."); + // field_319->addMenuElement(field_376.get()); + // addTextRender(field_319, "- " + inputLabels[2] + " -"); + // addTextRender(field_319, "3 accelerates, 6 brakes, 5 leans forward and 4 leans backward."); + // field_319->addMenuElement(settingStringBack); + // gameMenuHelp->addMenuElement(field_320); field_321 = new GameMenu("Unlocking", micro, gameMenuHelp); field_322 = new TimerOrMotoPartOrMenuElem("Unlocking", field_321, this); addTextRender(field_321, "By completing the easier levels, new levels will be unlocked. You will also gain access to higher leagues where more advanced bikes with different characteristics are available."); @@ -253,7 +257,8 @@ void MenuManager::initPart(int var1) gameMenuOptionsHighscoreDescription->addMenuElement(settingStringBack); gameMenuHelp->addMenuElement(taskHighscore); return; - case 7: + } + case 7: { gameMenuOptions2 = new GameMenu("Options", micro, gameMenuHelp); field_326 = new TimerOrMotoPartOrMenuElem("Options", gameMenuOptions2, this); @@ -268,9 +273,9 @@ void MenuManager::initPart(int var1) gameMenuOptions2->addMenuElement(field_376.get()); addTextRender(gameMenuOptions2, "Bike Sprite: On / Off"); addTextRender(gameMenuOptions2, "Default: . uses a texture for the bike. uses line graphics."); - gameMenuOptions2->addMenuElement(field_376.get()); - addTextRender(gameMenuOptions2, "Input: Keyset 1,2,3 "); - addTextRender(gameMenuOptions2, "Default: <1>. Determines which type of input should be used when playing. See \"Keys\" in the help menu for more info."); + // gameMenuOptions2->addMenuElement(field_376.get()); + // addTextRender(gameMenuOptions2, "Input: Keyset 1,2,3 "); + // addTextRender(gameMenuOptions2, "Default: <1>. Determines which type of input should be used when playing. See \"Keys\" in the help menu for more info."); gameMenuOptions2->addMenuElement(field_376.get()); addTextRender(gameMenuOptions2, "Look ahead: On/Off"); addTextRender(gameMenuOptions2, "Default: . Turns on and off smart camera movement."); @@ -299,7 +304,8 @@ void MenuManager::initPart(int var1) method_1(gameMenuMain, false); rasterImage = std::make_unique("raster.png"); - + return; + } default: break; } @@ -336,34 +342,10 @@ bool MenuManager::method_196() void MenuManager::method_197() { - // std::cout << "method_197 " << playerName << " " << trackTimeMs << std::endl; recordManager->loadRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); - { - std::cout << "AFTER LOAD" << std::endl; - std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - - for (auto& i : var1) { - std::cout << i << std::endl; - } - } recordManager->addNewRecord(settingsStringLeague->getCurrentOptionPos(), settings.playerName, trackTimeMs); - { - std::cout << "ADD NEW RECORD" << std::endl; - std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - - for (auto& i : var1) { - std::cout << i << std::endl; - } - } recordManager->writeRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); - { - std::cout << "AFTER WRITE" << std::endl; - std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - for (auto& i : var1) { - std::cout << i << std::endl; - } - } currentLevelFinished = false; gameMenuFinished->clearVector(); gameMenuFinished->addMenuElement(new TextRender("Time: " + trackTimeFormatted, micro)); @@ -618,55 +600,57 @@ void MenuManager::fillCanvasWithImage(Graphics* graphics) } } -void MenuManager::processNonFireKeyCode(int keyCode) +void MenuManager::processKeyCode(const Keys keyCode) { - if (micro->gameCanvas->getGameAction(keyCode) != 8) { - // if not fire - processKeyCode(keyCode); + if (currentGameMenu == nullptr) { + return; } -} -void MenuManager::processKeyCode(int keyCode) -{ - if (currentGameMenu != nullptr) { - switch (micro->gameCanvas->getGameAction(keyCode)) { - case Canvas::Keys::UP: // UP - currentGameMenu->processGameActionUp(); - return; - case Canvas::Keys::LEFT: // LEFT - currentGameMenu->processGameActionUpd(3); - if (currentGameMenu == gameMenuHighscore) { - --field_360; - if (field_360 < 0) { - field_360 = 0; - } + switch (keyCode) { + case Keys::UP: { + currentGameMenu->processGameActionUp(); + return; + } + case Keys::LEFT: { + currentGameMenu->processGameActionUpd(3); - method_207(field_360); + if (currentGameMenu == gameMenuHighscore) { + --field_360; + if (field_360 < 0) { + field_360 = 0; } - case 3: - case 4: - case 7: - default: - break; - case Canvas::Keys::RIGHT: // RIGHT - currentGameMenu->processGameActionUpd(2); - if (currentGameMenu == gameMenuHighscore) { - ++field_360; - if (field_360 > settingsStringLeague->getMaxAvailableOptionPos()) { - field_360 = settingsStringLeague->getMaxAvailableOptionPos(); - } - method_207(field_360); - return; + method_207(field_360); + } + + return; + } + case Keys::RIGHT: { + currentGameMenu->processGameActionUpd(2); + + if (currentGameMenu == gameMenuHighscore) { + ++field_360; + if (field_360 > settingsStringLeague->getMaxAvailableOptionPos()) { + field_360 = settingsStringLeague->getMaxAvailableOptionPos(); } - break; - case Canvas::Keys::DOWN: // DOWN - currentGameMenu->processGameActionDown(); - return; - case Canvas::Keys::FIRE: // FIRE - currentGameMenu->processGameActionUpd(1); + + method_207(field_360); return; } + + return; + } + case Keys::DOWN: { + currentGameMenu->processGameActionDown(); + return; + } + case Keys::FIRE: { + currentGameMenu->processGameActionUpd(1); + return; + } + default: { + return; + } } } @@ -794,7 +778,8 @@ void MenuManager::method_208() settings.selectedTrack = (int8_t)settingsStringTrack->getCurrentOptionPos(); settings.selectedLeague = (int8_t)settingsStringLeague->getCurrentOptionPos(); settings.unknown2 = -127; - settings.input = (int8_t)inputSetting->getCurrentOptionPos(); + // settings.input = (int8_t)inputSetting->getCurrentOptionPos(); + settings.input = 0; settings.unknown3 = -127; // strcpy(settingToSave.playerName, playerName); @@ -878,14 +863,14 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) return; } } else { - if (menuElement == inputSetting) { - if (inputSetting->method_114()) { - inputSetting->setCurentOptionPos(inputSetting->getCurrentOptionPos() + 1); - } + // if (menuElement == inputSetting) { + // if (inputSetting->method_114()) { + // inputSetting->setCurentOptionPos(inputSetting->getCurrentOptionPos() + 1); + // } - micro->gameCanvas->method_163(inputSetting->getCurrentOptionPos()); - return; - } + // micro->gameCanvas->method_163(inputSetting->getCurrentOptionPos()); + // return; + // } if (menuElement == lookAheadSetting) { micro->gamePhysics->setEnableLookAhead(lookAheadSetting->getCurrentOptionPos() == 0); @@ -1093,11 +1078,12 @@ void MenuManager::exit() settingsStringTrack->setCurentOptionPos(0); // playerName = defaultName; - inputSetting->setCurentOptionPos(0); // availableTracks[0] = 0; // availableTracks[1] = 0; // availableTracks[2] = -1; // availableLeagues = 0; + + // inputSetting->setCurentOptionPos(0); method_208(); recordManager->deleteRecordStores(); } @@ -1119,6 +1105,7 @@ void MenuManager::addOkAndBackCommands() int MenuManager::getCountOfRecordStoresWithPrefix(int prefixNumber) { + (void)prefixNumber; // TODO: // std::vector storeNames = RecordStore::listRecordStores(); // if (recordManager != nullptr && !storeNames.empty()) { diff --git a/src/MenuManager.h b/src/MenuManager.h index 2b10e55..beb71b2 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -16,19 +16,6 @@ #include "IMenuManager.h" #include "SettingsManager.h" -// class Micro; -// class RecordManager; -// class Command; -// class GameMenu; -// class TimerOrMotoPartOrMenuElem; -// class SettingsStringRender; -// class RecordStore; -// class Image; -// class TextRender; -// class Graphics; -// class Displayable; -// class IGameMenuElement; - class MenuManager : public IMenuManager { private: SettingsManager::Settings settings; @@ -63,7 +50,7 @@ class MenuManager : public IMenuManager { SettingsStringRender* shadowsSetting; SettingsStringRender* driverSpriteSetting; SettingsStringRender* bikeSpriteSetting; - SettingsStringRender* inputSetting; + // SettingsStringRender* inputSetting; SettingsStringRender* lookAheadSetting; TimerOrMotoPartOrMenuElem* clearHighscoreSetting; TimerOrMotoPartOrMenuElem* field_313; @@ -124,15 +111,10 @@ class MenuManager : public IMenuManager { std::unique_ptr field_376; // Alert alert = nullptr; // TODO - char defaultName[4] = "AAA"; - std::vector onOffLabels = { "On", "Off" };; - std::vector inputLabels = { "Keyset 1", "Keyset 2", "Keyset 3" }; - std::vector levelLabels = { "Easy", "Medium", "Pro" }; void addTextRender(GameMenu* gameMenu, std::string text); void method_197(); void fillCanvasWithImage(Graphics* graphics); - void processNonFireKeyCode(int keyCode); // std::vector method_216(int var1, int8_t var2); // int8_t getSettingOrDefault(int var1, int8_t var2); // std::string timeToString(int64_t time); @@ -172,5 +154,5 @@ class MenuManager : public IMenuManager { void removeOkAndBackCommands(); void addOkAndBackCommands(); /* synchronized */ void method_202(Graphics* var1); - void processKeyCode(int keyCode); + void processKeyCode(const Keys keyCode); }; diff --git a/src/Micro.cpp b/src/Micro.cpp index 70fbe78..a299b65 100644 --- a/src/Micro.cpp +++ b/src/Micro.cpp @@ -378,9 +378,9 @@ void Micro::setMode(int mode) void Micro::showHelp(const char* progName) { - std::cout << "Usage: " << progName << " " << std::endl - << "Example:" << std::endl - << " " << progName << " levels.mrg # A path to a custom levels file could be specified" << std::endl - << " " << progName << " # When no path is specified, the built-in levels file will be used" << std::endl + std::cout << "Usage: " << progName << " \n" + << "Example:\n" + << " " << progName << " levels.mrg # A path to a custom levels file could be specified\n" + << " " << progName << " # When no path is specified, the built-in levels file will be used\n" << std::endl; } \ No newline at end of file diff --git a/src/config.h b/src/config.h index 3cb5be3..b2b1e68 100644 --- a/src/config.h +++ b/src/config.h @@ -1,9 +1,13 @@ #pragma once +#include #include #include #include #include +#include +#include +#include enum { LEAGUES_MAX = 4, @@ -11,7 +15,52 @@ enum { PLAYER_NAME_MAX = 3, }; +enum Keys { + NONE = 0, + UP = 1, + DOWN = 6, + LEFT = 2, + RIGHT = 5, + FIRE = 8, + BACK = 9, + // MENU = 10 +}; + +static std::map gameKeyMappings = { + { SDLK_LEFT, Keys::LEFT }, + { SDLK_RIGHT, Keys::RIGHT }, + { SDLK_UP, Keys::UP }, + { SDLK_DOWN, Keys::DOWN }, + + { SDLK_RETURN, Keys::UP}, + { SDLK_ESCAPE, Keys::BACK }, + { SDLK_BACKSPACE, Keys::DOWN }, +}; +static std::map menuKeyMappings = { + { SDLK_LEFT, Keys::LEFT }, + { SDLK_RIGHT, Keys::RIGHT }, + { SDLK_UP, Keys::UP }, + { SDLK_DOWN, Keys::DOWN }, + + { SDLK_RETURN, Keys::FIRE}, + { SDLK_ESCAPE, Keys::BACK }, + { SDLK_BACKSPACE, Keys::BACK }, +}; + +static std::map> availableActions = { + { Keys::UP, {1, 0} }, + { Keys::DOWN, {-1, 0} }, + { Keys::LEFT, {0, -1} }, + { Keys::RIGHT, {0, 1} }, + // { Keys::FIRE, {1, 0} }, + // { Keys::BACK, {-1, 0} }, +}; +static std::vector onOffLabels = { "On", "Off" };; +static std::vector inputLabels = { "Keyset 1", "Keyset 2", "Keyset 3" }; +static std::vector levelLabels = { "Easy", "Medium", "Pro" }; + const char cheatCode[] = "RKE"; +const char defaultName[] = "AAA"; struct GlobalSetting { static bool WindowFullscreen; diff --git a/src/lcdui/Canvas.cpp b/src/lcdui/Canvas.cpp index 209b489..e5f5060 100644 --- a/src/lcdui/Canvas.cpp +++ b/src/lcdui/Canvas.cpp @@ -1,12 +1,5 @@ #include "Canvas.h" -#include - -#include "CanvasImpl.h" -#include "Graphics.h" -#include "Command.h" -#include "CommandListener.h" - Canvas::Canvas() { impl = std::make_unique(this); @@ -55,20 +48,6 @@ void Canvas::serviceRepaints() { } -int Canvas::getGameAction(int keyCode) -{ - switch (keyCode) { - case Keys::UP: - case Keys::DOWN: - case Keys::LEFT: - case Keys::RIGHT: - case Keys::FIRE: - return keyCode; - default: - throw std::runtime_error("getGameAction(" + std::to_string(keyCode) + ") isn't implemented!"); - } -} - void Canvas::removeCommand(Command* command) { currentCommands.erase(command); @@ -84,12 +63,12 @@ void Canvas::setCommandListener(CommandListener* listener) commandListener = listener; } -void Canvas::publicKeyPressed(int keyCode) +void Canvas::publicKeyPressed(const Keys keyCode) { keyPressed(keyCode); } -void Canvas::publicKeyReleased(int keyCode) +void Canvas::publicKeyReleased(const Keys keyCode) { keyReleased(keyCode); } @@ -97,7 +76,7 @@ void Canvas::publicKeyReleased(int keyCode) void Canvas::pressedEsc() { for (const auto& command : currentCommands) { - if (command->type == Command::Type::BACK || currentCommands.size() == 1) { + if (command->type == Command::Type::BACK || (!Micro::isInGameMenu && currentCommands.size() == 1)) { commandListener->commandAction(command, this); return; } diff --git a/src/lcdui/Canvas.h b/src/lcdui/Canvas.h index 3ec7ec1..fbc3274 100644 --- a/src/lcdui/Canvas.h +++ b/src/lcdui/Canvas.h @@ -3,12 +3,18 @@ #include #include #include +#include +#include "CanvasImpl.h" +#include "Graphics.h" +#include "Command.h" +#include "CommandListener.h" #include "Displayable.h" #include "Command.h" +#include "../Micro.h" +#include "../config.h" class CanvasImpl; -class Graphics; class Canvas : public Displayable { private: @@ -19,14 +25,6 @@ class Canvas : public Displayable { std::unordered_set currentCommands; public: - enum Keys { - UP = 1, - DOWN = 6, - LEFT = 2, - RIGHT = 5, - FIRE = 8 - }; - Canvas(); ~Canvas(); bool isShown() override; @@ -36,14 +34,13 @@ class Canvas : public Displayable { CanvasImpl* getCanvasImpl(); void repaint(); void serviceRepaints(); - int getGameAction(int keyCode); void removeCommand(Command* command); void addCommand(Command* command); void setCommandListener(CommandListener* listener); - void publicKeyPressed(int keyCode); - void publicKeyReleased(int keyCode); + void publicKeyPressed(const Keys keyCode); + void publicKeyReleased(const Keys keyCode); void pressedEsc(); virtual void paint(Graphics* g) = 0; - virtual void keyPressed(int keyCode) = 0; - virtual void keyReleased(int keyCode) = 0; + virtual void keyPressed(const Keys keyCode) = 0; + virtual void keyReleased(const Keys keyCode) = 0; }; \ No newline at end of file diff --git a/src/lcdui/CanvasImpl.cpp b/src/lcdui/CanvasImpl.cpp index e748c9c..cb541b3 100644 --- a/src/lcdui/CanvasImpl.cpp +++ b/src/lcdui/CanvasImpl.cpp @@ -1,14 +1,5 @@ #include "CanvasImpl.h" -#include -#include -#include -#include -#include - -#include "Canvas.h" -#include "../config.h" - CanvasImpl::CanvasImpl(Canvas* canvas) { this->canvas = canvas; @@ -100,23 +91,17 @@ void CanvasImpl::processEvents() exit(0); // IMPROVE This is a super dumb way to finish the game, but it works break; case SDL_KEYDOWN: { - int keyCode = convertKeyCharToKeyCode(e.key.keysym.sym); - // std::cout << "Key pressed: " << keyCode << std::endl; - if (keyCode != 0) { + const Keys keyCode = convertKeyCharToKeyCode(e.key.keysym.sym); + + if (keyCode != Keys::NONE) { canvas->publicKeyPressed(keyCode); } } break; case SDL_KEYUP: { - int sdlCode = e.key.keysym.sym; - int keyCode = convertKeyCharToKeyCode(sdlCode); - // std::cout << "Key released: " << keyCode << std::endl; - if (keyCode != 0) { + const Keys keyCode = convertKeyCharToKeyCode(e.key.keysym.sym); + + if (keyCode != Keys::NONE) { canvas->publicKeyReleased(keyCode); - } else { - if (sdlCode == SDLK_ESCAPE || sdlCode == SDLK_BACKSPACE) { - // std::cout << "ESC released" << std::endl; - canvas->pressedEsc(); - } } } break; default: @@ -125,27 +110,20 @@ void CanvasImpl::processEvents() } } -int CanvasImpl::convertKeyCharToKeyCode(SDL_Keycode keyCode) +Keys CanvasImpl::convertKeyCharToKeyCode(const SDL_Keycode keyCode) { - switch (keyCode) { - case SDLK_RETURN: - return Canvas::Keys::FIRE; - case SDLK_LEFT: - case SDLK_a: - return Canvas::Keys::LEFT; - case SDLK_RIGHT: - case SDLK_d: - return Canvas::Keys::RIGHT; - case SDLK_UP: - case SDLK_w: - return Canvas::Keys::UP; - case SDLK_DOWN: - case SDLK_s: - return Canvas::Keys::DOWN; - default: - std::cout << "unknown keyEvent: " << keyCode << std::endl; - return 0; + std::cout << "KEY " << keyCode << "; MENU " << Micro::isInGameMenu << std::endl; + + if (Micro::isInGameMenu && menuKeyMappings.count(keyCode) > 0) { + return menuKeyMappings[keyCode]; + } + + if (!Micro::isInGameMenu && gameKeyMappings.count(keyCode) > 0) { + return gameKeyMappings[keyCode]; } + + std::cout << "unknown keyEvent: " << keyCode << std::endl; + return Keys::NONE; } void CanvasImpl::setWindowTitle(const std::string& title) diff --git a/src/lcdui/CanvasImpl.h b/src/lcdui/CanvasImpl.h index bcdf6e4..c96b63d 100644 --- a/src/lcdui/CanvasImpl.h +++ b/src/lcdui/CanvasImpl.h @@ -1,10 +1,14 @@ #pragma once #include - #include #include #include +#include +#include + +#include "Canvas.h" +#include "../config.h" class Canvas; @@ -18,7 +22,7 @@ class CanvasImpl { SDL_Window* window; SDL_Renderer* renderer; - static int convertKeyCharToKeyCode(SDL_Keycode keyCode); + static Keys convertKeyCharToKeyCode(const SDL_Keycode keyCode); public: CanvasImpl(Canvas* canvas); diff --git a/todo.md b/todo.md deleted file mode 100644 index 9140dc9..0000000 --- a/todo.md +++ /dev/null @@ -1,3 +0,0 @@ -- [ ] scaling font -- [ ] fix another problem with saving highscore -- [ ] change keybinds \ No newline at end of file From 70ed69c2d4ae650dd05ba127b28c143ddd9c4ff1 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Mon, 11 Nov 2024 22:23:16 +0200 Subject: [PATCH 11/16] added CLI parameters, added logs with levels, code cleanup --- CMakeLists.txt | 3 +- README.md | 1 + src/GameCanvas.cpp | 2 +- src/LevelLoader.cpp | 12 +- src/LevelLoader.h | 2 +- src/MRGLoader.cpp | 81 +---------- src/MRGLoader.h | 1 + src/MenuManager.cpp | 186 +------------------------- src/MenuManager.h | 27 ---- src/Micro.cpp | 31 +---- src/Micro.h | 2 +- src/RecordManager.cpp | 17 ++- src/RecordManager.h | 3 +- src/SettingsManager.cpp | 41 +++++- src/SettingsManager.h | 2 + src/config.cpp | 3 +- src/config.h | 45 ++++--- src/lcdui/CanvasImpl.cpp | 4 +- src/lcdui/CanvasImpl.h | 1 + src/lcdui/Command.cpp | 2 +- src/lcdui/Command.h | 6 +- src/main.cpp | 90 ++++++++++++- src/rms/InvalidRecordIDException.h | 4 - src/rms/RecordComparator.h | 4 - src/rms/RecordEnumeration.h | 13 -- src/rms/RecordEnumerationImpl.cpp | 93 ------------- src/rms/RecordEnumerationImpl.h | 31 ----- src/rms/RecordFilter.h | 4 - src/rms/RecordStore.cpp | 161 ---------------------- src/rms/RecordStore.h | 35 ----- src/rms/RecordStoreException.h | 4 - src/rms/RecordStoreNotOpenException.h | 4 - src/tests/test_rms.cpp | 33 ----- src/tests/test_rms.h | 3 - src/utils/Log.cpp | 18 +++ src/utils/Log.h | 20 +++ 36 files changed, 224 insertions(+), 765 deletions(-) delete mode 100644 src/rms/InvalidRecordIDException.h delete mode 100644 src/rms/RecordComparator.h delete mode 100644 src/rms/RecordEnumeration.h delete mode 100644 src/rms/RecordEnumerationImpl.cpp delete mode 100644 src/rms/RecordEnumerationImpl.h delete mode 100644 src/rms/RecordFilter.h delete mode 100644 src/rms/RecordStore.cpp delete mode 100644 src/rms/RecordStore.h delete mode 100644 src/rms/RecordStoreException.h delete mode 100644 src/rms/RecordStoreNotOpenException.h delete mode 100644 src/tests/test_rms.cpp delete mode 100644 src/tests/test_rms.h create mode 100644 src/utils/Log.cpp create mode 100644 src/utils/Log.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e404d74..265a4fc 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ pkg_search_module(SDL2_IMAGE REQUIRED IMPORTED_TARGET SDL2_image) # Create a sources variable with a link to all cpp files to compile set(SOURCES src/config.cpp + src/utils/Log.cpp src/utils/Time.cpp src/utils/Hashing.cpp src/utils/EmbedFileStream.cpp @@ -50,8 +51,6 @@ set(SOURCES src/lcdui/Font.cpp src/lcdui/Command.cpp src/lcdui/FontStorage.cpp - # src/rms/RecordEnumerationImpl.cpp - # src/rms/RecordStore.cpp ) include(cmake/CMakeRC.cmake) diff --git a/README.md b/README.md index cefba7f..76b8f5d 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ This is the C++ & SDL2 port of Gravity Defied, which includes all the features o # TODO +- [ ] create saves directory and global setting file when missing - [ ] config file - [ ] command line flags - [ ] level file selector diff --git a/src/GameCanvas.cpp b/src/GameCanvas.cpp index 300b99a..dac3c15 100644 --- a/src/GameCanvas.cpp +++ b/src/GameCanvas.cpp @@ -21,7 +21,7 @@ GameCanvas::GameCanvas(Micro* micro) dx = 0; dy = height2; - commandMenu = new Command("Menu", 1, 1); + commandMenu = new Command("Menu", Command::Type::SCREEN, 1); defaultFontWidth00 = defaultFont->stringWidth("00") + 3; } diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index f249c94..30c0adc 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -110,7 +110,7 @@ void LevelLoader::loadNextTrack() int LevelLoader::loadTrack(const int level, const int track) { - std::cout << "loadTrack " << level << " " << track << std::endl; + Log::write(Log::LogLevel::Info, "loadTrack %d %d\n", level, track); loadedLevel = level; loadedTrack = track; @@ -131,19 +131,9 @@ int LevelLoader::loadTrack(const int level, const int track) gameLevel->load(&levelFileStream); method_96(gameLevel); - // method_89(loadedLevel + 1, loadedTrack + 1); return loadedTrack; } -// void LevelLoader::method_89(const int level, const int track) -// { -// std::cout << "method_89 " << level << " " << track << std::endl; - -// const MRGLoader::LevelTracks l = trackHeaders.at(level); -// const MRGLoader::Track t = l.tracks.at(track); - -// } - void LevelLoader::method_90(int var1) { (void)var1; diff --git a/src/LevelLoader.h b/src/LevelLoader.h index 337edbe..1ee0590 100644 --- a/src/LevelLoader.h +++ b/src/LevelLoader.h @@ -15,6 +15,7 @@ #include "GameCanvas.h" #include "GameLevel.h" #include "TimerOrMotoPartOrMenuElem.h" +#include "utils/Log.h" #include "utils/FileStream.h" class LevelLoader { @@ -62,7 +63,6 @@ class LevelLoader { void loadNextTrack(); int loadTrack(const int level, const int track); std::vector GetTrackNames(const int level) const; - // void method_89(int var1, int var2); void method_90(int var1); int method_91(); diff --git a/src/MRGLoader.cpp b/src/MRGLoader.cpp index 8c6c9f2..68432b1 100644 --- a/src/MRGLoader.cpp +++ b/src/MRGLoader.cpp @@ -22,14 +22,12 @@ static MRGLoader::LevelTracks loadLevel(FileStream& levelFileStream, const uint8 levelTracks.tracks.push_back(track); } - std::cout << "LEVEL " << (uint32_t)level << std::endl; - std::cout << levelTracks.tracksCount << " TRACKS" << std::endl; + Log::write(Log::LogLevel::Info, "Level %d, Tracks %d\n", level, levelTracks.tracksCount); for (auto& i : levelTracks.tracks) { - std::cout << i.offset << " " << i.trackName << '\n'; + Log::write(Log::LogLevel::Info, "%d %s\n", i.offset, i.trackName.c_str()); } - std::cout << std::endl; return levelTracks; } @@ -116,78 +114,3 @@ MRGLoader::TrackInfo MRGLoader::loadTrack(const std::filesystem::path& mrgFilePa std::cout << std::endl; return trackInfo; } - -// void GameLevel::load(FileStream* inStream) -// { -// init(); -// int8_t c; -// inStream->readVariable(&c, true); -// if (c == 50) { -// char var3[20]; -// inStream->readVariable(var3, false, 20); -// } - -// finishFlagPoint = 0; -// startFlagPoint = 0; -// int pointX, pointY; -// short pointsCount; -// inStream->readVariable(&startPosX, true); -// inStream->readVariable(&startPosY, true); -// inStream->readVariable(&finishPosX, true); -// inStream->readVariable(&finishPosY, true); -// inStream->readVariable(&pointsCount, true); -// inStream->readVariable(&pointX, true); -// inStream->readVariable(&pointY, true); -// int offsetX = pointX; -// int offsetY = pointY; -// addPointSimple(pointX, pointY); - -// for (int i = 1; i < pointsCount; ++i) { -// int8_t modeOrDx; -// inStream->readVariable(&modeOrDx, true); -// if (modeOrDx == -1) { -// offsetY = 0; -// offsetX = 0; -// inStream->readVariable(&pointX, true); -// inStream->readVariable(&pointY, true); -// } else { -// pointX = modeOrDx; -// int8_t temp; -// inStream->readVariable(&temp, true); -// pointY = temp; -// } - -// offsetX += pointX; -// offsetY += pointY; -// addPointSimple(offsetX, offsetY); -// } -// } - -// void GameLevel::addPointSimple(int var1, int var2) -// { -// addPoint(var1 << 16 >> 3, var2 << 16 >> 3); -// } - -// void GameLevel::addPoint(int x, int y) -// { -// if (pointPositions.empty() || static_cast(pointPositions.size()) <= pointsCount) { -// int var3 = 100; -// if (!pointPositions.empty()) { -// var3 = var3 < static_cast(pointPositions.size()) + 30 ? pointPositions.size() + 30 : var3; -// } -// pointPositions.resize(var3, std::vector(2)); // ABOBA -// } - -// if (pointsCount == 0 || pointPositions[pointsCount - 1][0] < x) { -// pointPositions[pointsCount][0] = x; -// pointPositions[pointsCount][1] = y; -// ++pointsCount; -// } -// } - -// int main(void) -// { -// std::array levels = MRGLoader::loadLevels("./levels.mrg"); -// MRGLoader::loadTrack("./levels.mrg", levels[0].tracks[0].offset); -// return 0; -// } diff --git a/src/MRGLoader.h b/src/MRGLoader.h index 3358562..50eee8c 100644 --- a/src/MRGLoader.h +++ b/src/MRGLoader.h @@ -9,6 +9,7 @@ #include #include +#include "utils/Log.h" #include "utils/FileStream.h" namespace MRGLoader { diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 67629fa..ffc7374 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -8,71 +8,21 @@ MenuManager::MenuManager(Micro* var1) void MenuManager::initPart(int var1) { - // int var4; switch (var1) { case 1: { - // playerName = defaultName; recordManager = new RecordManager(); trackTimeMs = -1L; trackTimeFormatted.clear(); - // isRecordStoreOpened = false; - // savedData = std::vector(19); - - // for (int idx = 0; idx < 19; ++idx) { - // savedData[idx] = -127; - // } - - // try { - // recordStore = RecordStore::openRecordStore(GlobalSetting::GlobalSaveFileName, true); - // isRecordStoreOpened = true; - // return; - // } catch (RecordStoreException& var9) { - // isRecordStoreOpened = false; - // return; - // } + return; } case 2: { - // recorcStoreRecordId = -1; - - // RecordEnumeration* records; - // try { - // records = recordStore->enumerateRecords(nullptr, nullptr, false); - // } catch (RecordStoreNotOpenException& var8) { - // return; - // } - settings = SettingsManager::loadSettings(); if (settings.playerName[0] < 'A' || settings.playerName[0] > 'Z') { strncpy(settings.playerName, defaultName, PLAYER_NAME_MAX); } - // std::vector var3; - // if (records->numRecords() > 0) { - // try { - // var3 = records->nextRecord(); - // records->reset(); - // recorcStoreRecordId = records->nextRecordId(); - // } catch (RecordStoreException& var7) { - // return; - // } - - // if (var3.size() <= 19) { - // for (std::size_t i = 0; i < var3.size(); ++i) { - // savedData[i] = var3[i]; - // } - // } - - // // records->destroy(); - // } - - // var3 = method_216(16, (int8_t)-1); - // if (!var3.empty() && var3[0] != -1) { - // for (var4 = 0; var4 < 3; ++var4) { - // playerName[var4] = var3[var4]; - // } - // } - + // cheat code: set name to RKE to enable all leagues ??? if (strncmp(settings.playerName, cheatCode, PLAYER_NAME_MAX) == 0) { settings.availableLeagues = 3; @@ -83,36 +33,12 @@ void MenuManager::initPart(int var1) return; } - // settings.availableLeagues = 0; - // settings.availableLevels = 0; - // settings.availableTracks[0] = 0; - // settings.availableTracks[1] = 0; - // settings.availableTracks[2] = -1; return; } case 3: { - // isDisablePerspective = getSettingOrDefault(0, isDisablePerspective); - // isDisabledShadows = getSettingOrDefault(1, isDisabledShadows); - // isDisabledDriverSprite = getSettingOrDefault(2, isDisabledDriverSprite); - // isDisabledBikeSprite = getSettingOrDefault(3, isDisabledBikeSprite); - // field_367 = getSettingOrDefault(14, field_367); - // isDisableLookAhead = getSettingOrDefault(4, isDisableLookAhead); - // field_369 = getSettingOrDefault(11, field_369); - // field_370 = getSettingOrDefault(10, field_370); - // field_371 = getSettingOrDefault(12, field_371); - // field_373 = getSettingOrDefault(15, field_373); field_354 = settings.selectedLevel; field_355 = settings.selectedTrack; - // if (settings.playerName[0] != 82 || settings.playerName[1] != 75 || settings.playerName[2] != 69) { - // // availableLeagues = getSettingOrDefault(5, availableLeagues); - // // availableLevels = getSettingOrDefault(6, availableLevels); - - // // for (var4 = 0; var4 < 3; ++var4) { - // // availableTracks[var4] = getSettingOrDefault(7 + var4, availableTracks[var4]); - // // } - // } - try { field_345.at(settings.selectedLevel) = settings.selectedTrack; } catch (std::exception& var6) { @@ -124,11 +50,8 @@ void MenuManager::initPart(int var1) LevelLoader::isEnabledPerspective = settings.perspective == 0; LevelLoader::isEnabledShadows = settings.shadows == 0; micro->gamePhysics->setEnableLookAhead(settings.lookAhead == 0); - // micro->gameCanvas->method_163(settings.input); micro->gameCanvas->method_124(field_372 == 0); leagueNamesAll4 = { "100cc", "175cc", "220cc", "325cc" }; - // levelNames = micro->levelLoader->levelNames; - // levelNames = micro->levelLoader->GetTrackNames(settingStringLevel->getCurrentOptionPos()); if (settings.availableLeagues < 3) { this->leagueNames = { "100cc", "175cc", "220cc" }; @@ -299,8 +222,8 @@ void MenuManager::initPart(int var1) gameMenuIngame->addMenuElement(settingStringPlayMenu); field_335 = new SettingsStringRender("Ok", 0, this, std::vector(), false, micro, gameMenuMain, true); field_336 = new SettingsStringRender("Name - " + std::string(settings.playerName, PLAYER_NAME_MAX), 0, this, std::vector(), false, micro, gameMenuMain, true); - commandOk = new Command("Ok", 4, 1); - commandBack = new Command("Back", 2, 1); + commandOk = new Command("Ok", Command::Type::OK, 1); + commandBack = new Command("Back", Command::Type::BACK, 1); method_1(gameMenuMain, false); rasterImage = std::make_unique("raster.png"); @@ -367,28 +290,6 @@ void MenuManager::method_197() if (settingsStringTrack->getCurrentOptionPos() == settingsStringTrack->getMaxOptionPos()) { currentLevelFinished = true; - // switch (settingStringLevel->getCurrentOptionPos()) { - // case 0: - // if (availableLeagues < 1) { - // availableLeagues = 1; - // settingsStringLeague->setAvailableOptions(availableLeagues); - // } - // break; - // case 1: - // if (availableLeagues < 2) { - // availableLeagues = 2; - // settingsStringLeague->setAvailableOptions(availableLeagues); - // } - // break; - // case 2: - // if (availableLeagues < 3) { - // availableLeagues = 3; - // settingsStringLeague->setOptionsList(leagueNamesAll4); - // leagueNames = leagueNamesAll4; - // settingsStringLeague->setAvailableOptions(availableLeagues); - // } - // } - availableLeagues = settingStringLevel->getCurrentOptionPos() + 1; if (availableLeagues == 3) { @@ -406,6 +307,7 @@ void MenuManager::method_197() int var3 = getCountOfRecordStoresWithPrefix(settingStringLevel->getCurrentOptionPos()); addTextRender(gameMenuFinished, var3 + " of " + std::to_string(micro->levelLoader->getTracksCount(settingStringLevel->getCurrentOptionPos())) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); + if (!currentLevelFinished) { field_333->setText("Restart: " + micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos())); field_334->setText("Next: " + micro->levelLoader->getName(field_354, field_355 + 1)); @@ -480,7 +382,6 @@ void MenuManager::method_201(int var1) method_1(gameMenuIngame, false); break; case 2: { - // field_362 = Time::currentTimeMillis(); gameMenuFinished->clearVector(); field_354 = settingStringLevel->getCurrentOptionPos(); field_355 = settingsStringTrack->getCurrentOptionPos(); @@ -688,7 +589,6 @@ void MenuManager::method_1(GameMenu* gm, bool var2) field_360 = settingsStringLeague->getCurrentOptionPos(); method_207(field_360); } else if (gm == gameMenuFinished) { - // settings.playerName = gameMenuEnterName->getStrArr(); strncpy(settings.playerName, gameMenuEnterName->getStrArr(), PLAYER_NAME_MAX); field_336->setText("Name - " + std::string(settings.playerName, PLAYER_NAME_MAX)); } else if (gm == gameMenuPlay) { @@ -738,7 +638,6 @@ void MenuManager::method_207(int var1) } } - // recordManager->closeRecordStore(); if (var2[0] == "") { gameMenuHighscore->addMenuElement(new TextRender("No Highscores", micro)); } @@ -748,17 +647,7 @@ void MenuManager::method_207(int var1) void MenuManager::saveSmthToRecordStoreAndCloseIt() { - // if (isRecordStoreOpened) { method_208(); - - // try { - // // recordStore->closeRecordStore(); - // isRecordStoreOpened = false; - // } catch (RecordStoreException& var1) { - // std::cout << var1.what() << std::endl; - // } - // } - currentGameMenu = nullptr; } @@ -782,37 +671,7 @@ void MenuManager::method_208() settings.input = 0; settings.unknown3 = -127; - // strcpy(settingToSave.playerName, playerName); - // SettingsManager::SettingsConverter settingsConverter = { .settings = settings }; - SettingsManager::saveSettings(settings); - // setValue(0, (int8_t)perspectiveSetting->getCurrentOptionPos()); - // setValue(1, (int8_t)shadowsSetting->getCurrentOptionPos()); - // setValue(2, (int8_t)driverSpriteSetting->getCurrentOptionPos()); - // setValue(3, (int8_t)bikeSpriteSetting->getCurrentOptionPos()); - // setValue(14, (int8_t)inputSetting->getCurrentOptionPos()); - // setValue(4, (int8_t)lookAheadSetting->getCurrentOptionPos()); - // setValue(5, (int8_t)settingsStringLeague->getMaxAvailableOptionPos()); - // setValue(6, (int8_t)settingStringLevel->getMaxAvailableOptionPos()); - // setValue(10, (int8_t)settingStringLevel->getCurrentOptionPos()); - // setValue(11, (int8_t)settingsStringTrack->getCurrentOptionPos()); - // setValue(12, (int8_t)settingsStringLeague->getCurrentOptionPos()); - - // setValue(16, (int8_t)settings.playerName[0]); - // setValue(17, (int8_t)settings.playerName[1]); - // setValue(18, (int8_t)settings.playerName[2]); - - // for (int i = 0; i < 3; ++i) { - // setValue(7 + i, availableTracks[i]); - // } - - // try { - // recorcStoreRecordId = recordStore->addOrUpdateRecord(recorcStoreRecordId, savedData, 0, 19); - // } catch (RecordStoreNotOpenException& var4) { - // std::cout << var4.what() << std::endl; - // } catch (RecordStoreException& var5) { - // std::cout << var5.what() << std::endl; - // } } void MenuManager::run() @@ -1024,46 +883,11 @@ void MenuManager::method_211(int var1) } } -// int MenuManager::method_212() -// { -// return settingStringLevel->getCurrentOptionPos(); -// } - -// int MenuManager::method_213() -// { -// return settingsStringTrack->getCurrentOptionPos(); -// } - -// int MenuManager::method_214() -// { -// return settingsStringLeague->getCurrentOptionPos(); -// } - void MenuManager::method_215(int64_t var1) { trackTimeMs = var1; } -// std::vector MenuManager::method_216(int var1, int8_t defaultValue) -// { -// switch (var1) { -// case 16: { -// std::vector difficultySetting = std::vector(3); - -// for (int idx = 0; idx < 3; ++idx) { -// difficultySetting[idx] = savedData[16 + idx]; -// } - -// if (difficultySetting[0] == -127) { -// difficultySetting[0] = defaultValue; -// } -// return difficultySetting; -// } -// default: -// return std::vector(); -// } -// } - void MenuManager::exit() { perspectiveSetting->setCurentOptionPos(0); diff --git a/src/MenuManager.h b/src/MenuManager.h index beb71b2..13d28fd 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -20,7 +20,6 @@ class MenuManager : public IMenuManager { private: SettingsManager::Settings settings; - // std::vector savedData; Micro* micro; RecordManager* recordManager; Command* commandOk; @@ -79,35 +78,16 @@ class MenuManager : public IMenuManager { SettingsStringRender* field_336; int64_t trackTimeMs; std::string trackTimeFormatted; - // char* playerName; - // char availableTracks[4]; - // int8_t availableLeagues = 0; - // int8_t availableLevels = 0; std::vector field_345 = { 0, 0, 0 }; - // std::vector> levelNames; std::vector leagueNames = std::vector(3); std::vector leagueNamesAll4; - // RecordStore* recordStore; - // int recorcStoreRecordId = -1; - // bool isRecordStoreOpened; std::unique_ptr rasterImage; TextRender* textRenderCodeBrewLink; int field_354 = 0; int field_355 = 0; bool currentLevelFinished = false; bool field_357 = false; - // int64_t field_362 = 0L; - // int8_t isDisablePerspective = 0; - // int8_t isDisabledShadows = 0; - // int8_t isDisabledDriverSprite = 0; - // int8_t isDisabledBikeSprite = 0; - // int8_t field_367 = 0; - // int8_t isDisableLookAhead = 0; - // int8_t field_369 = 0; - // int8_t field_370 = 0; - // int8_t field_371 = 0; int8_t field_372 = 0; - // int8_t field_373 = 0; std::unique_ptr field_376; // Alert alert = nullptr; // TODO @@ -115,10 +95,6 @@ class MenuManager : public IMenuManager { void addTextRender(GameMenu* gameMenu, std::string text); void method_197(); void fillCanvasWithImage(Graphics* graphics); - // std::vector method_216(int var1, int8_t var2); - // int8_t getSettingOrDefault(int var1, int8_t var2); - // std::string timeToString(int64_t time); - // void setValue(int pos, int8_t value); void exit(); int getCountOfRecordStoresWithPrefix(int prefixNumber); @@ -147,9 +123,6 @@ class MenuManager : public IMenuManager { void processMenu(IGameMenuElement* menuElement); int method_210(); void method_211(int var1); - // int method_212(); - // int method_213(); - // int method_214(); void method_215(int64_t var1); void removeOkAndBackCommands(); void addOkAndBackCommands(); diff --git a/src/Micro.cpp b/src/Micro.cpp index a299b65..222fd06 100644 --- a/src/Micro.cpp +++ b/src/Micro.cpp @@ -5,7 +5,6 @@ #include "MenuManager.h" #include "LevelLoader.h" #include "utils/Time.h" -#include "utils/Hashing.h" #include "lcdui/CanvasImpl.h" #include "config.h" @@ -144,26 +143,9 @@ void Micro::destroyApp(bool var1) menuManager->saveSmthToRecordStoreAndCloseIt(); } -void Micro::startApp(int argc, char** argv) +void Micro::startApp() { - if (argc > 1) { - std::string argv1(argv[1]); - - if (argv1 == "-h" || argv1 == "--help") { - showHelp(argv[0]); - return; - } - - GlobalSetting::MrgFilePath = argv1; - } - - std::cout << "path: " << GlobalSetting::MrgFilePath << std::endl; - GlobalSetting::SavesPrefix = Hashing::HashFileMD5(GlobalSetting::MrgFilePath.string()); - std::cout << "hash: " << GlobalSetting::SavesPrefix << std::endl; - - // TODO: - // RecordStore::setRecordStoreDir(argv[0]); - + SettingsManager::initSettings(); gameStarted = true; // if (thread == null) { // thread = new Thread(this); @@ -374,13 +356,4 @@ void Micro::goalLoop() void Micro::setMode(int mode) { gamePhysics->setMode(mode); -} - -void Micro::showHelp(const char* progName) -{ - std::cout << "Usage: " << progName << " \n" - << "Example:\n" - << " " << progName << " levels.mrg # A path to a custom levels file could be specified\n" - << " " << progName << " # When no path is specified, the built-in levels file will be used\n" - << std::endl; } \ No newline at end of file diff --git a/src/Micro.h b/src/Micro.h index 9fcceed..41c9961 100644 --- a/src/Micro.h +++ b/src/Micro.h @@ -33,7 +33,7 @@ class Micro { Micro(); ~Micro(); - void startApp(int argc, char** argv); + void startApp(); void gameToMenu(); void menuToGame(); diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index e0816dd..e0231a8 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -3,8 +3,10 @@ void RecordManager::loadRecordInfo(const uint8_t level, const uint8_t track) { recordsSaveDataConverter = { .bytes = {} }; - std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + std::to_string(level) + std::to_string(track); - std::cout << "loadRecordInfo " << saveFileName << std::endl; + + const std::string trackSaveName = std::to_string(level) + std::to_string(track) + ".dat"; + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / trackSaveName; + Log::write(Log::LogLevel::Info, "loadRecordInfo %s\n", saveFileName.c_str()); FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); levelFileStream.readVariable(&recordsSaveDataConverter.bytes, false, sizeof(RecordsSaveData)); @@ -33,8 +35,9 @@ std::vector RecordManager::getRecordDescription(const uint8_t leagu void RecordManager::writeRecordInfo(const uint8_t level, const uint8_t track) { - std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + std::to_string(level) + std::to_string(track); - std::cout << "writeRecordInfo " << saveFileName << std::endl; + const std::string trackSaveName = std::to_string(level) + std::to_string(track) + ".dat"; + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / trackSaveName; + Log::write(Log::LogLevel::Info, "writeRecordInfo %s\n", saveFileName.c_str()); FileStream levelFileStream(saveFileName, std::ios::out | std::ios::binary); levelFileStream.writeVariable(&recordsSaveDataConverter.bytes, sizeof(RecordsSaveData)); @@ -55,9 +58,9 @@ uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t tim void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t timeMs) { - std::cout << "addNewRecord " << (int)league << " " << playerName << " " << timeMs << std::endl; + Log::write(Log::LogLevel::Info, "addNewRecord %d %s %d\n", (int)league, playerName, timeMs); const uint8_t newRecordPos = getPosOfNewRecord(league, timeMs); - std::cout << "record pos " << (int)newRecordPos << std::endl; + Log::write(Log::LogLevel::Info, "Record pos %d\n", (int)newRecordPos); if (newRecordPos >= 3) { // out of scope, we save only first 3 records @@ -78,7 +81,7 @@ void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos] = { .timeMs = timeMs, .playerName = {}, - .padding = {0, 0, 0, 0, 0} + .padding = { 0, 0, 0, 0, 0 } }; strncpy(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos].playerName, playerName, PLAYER_NAME_MAX); } diff --git a/src/RecordManager.h b/src/RecordManager.h index 10f9116..fd4be59 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -7,13 +7,12 @@ #include #include "config.h" +#include "utils/Log.h" #include "utils/Time.h" #include "utils/FileStream.h" class RecordManager { public: - - // inline static const int unused = 3; void loadRecordInfo(const uint8_t level, const uint8_t track); diff --git a/src/SettingsManager.cpp b/src/SettingsManager.cpp index 04ab2dd..671b9e0 100644 --- a/src/SettingsManager.cpp +++ b/src/SettingsManager.cpp @@ -1,9 +1,42 @@ #include "SettingsManager.h" +void SettingsManager::initSettings() +{ + if (!std::filesystem::exists(GlobalSetting::SavesPath)) { + Log::write(Log::LogLevel::Info, "Creating directory %s\n", GlobalSetting::SavesPath.c_str()); + std::filesystem::create_directory(GlobalSetting::SavesPath); + } + + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / GlobalSetting::GlobalSaveFileName; + + if (!std::filesystem::exists(saveFileName)) { + Log::write(Log::LogLevel::Info, "Creating global settings file %s\n", saveFileName.c_str()); + SettingsManager::Settings settings = { + .perspective = 0, + .shadows = 0, + .driverSprite = 0, + .bikeSprite = 0, + .lookAhead = 0, + .availableLeagues = 0, + .availableLevels = 0, + .availableTracks = { 0, 0, -1 }, + .selectedLevel = 0, + .selectedTrack = 0, + .selectedLeague = 0, + .unknown2 = -127, + .input = 0, + .unknown3 = -127, + .playerName = {} + }; + strncpy(settings.playerName, defaultName, PLAYER_NAME_MAX); + saveSettings(settings); + } +} + SettingsManager::Settings SettingsManager::loadSettings() { - std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + GlobalSetting::GlobalSaveFileName; - std::cout << "loadSettings " << saveFileName << std::endl; + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / GlobalSetting::GlobalSaveFileName; + Log::write(Log::LogLevel::Info, "loadSettings %s\n", saveFileName.c_str()); FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); @@ -15,8 +48,8 @@ SettingsManager::Settings SettingsManager::loadSettings() void SettingsManager::saveSettings(SettingsManager::Settings settings) { - std::string saveFileName = "./saves/" + GlobalSetting::SavesPrefix + "_" + GlobalSetting::GlobalSaveFileName; - std::cout << "saveSettings " << saveFileName << std::endl; + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / GlobalSetting::GlobalSaveFileName; + Log::write(Log::LogLevel::Info, "saveSettings %s\n", saveFileName.c_str()); SettingsManager::SettingsConverter settingsConverter = { .settings = settings }; diff --git a/src/SettingsManager.h b/src/SettingsManager.h index 195b814..ae7e2d7 100644 --- a/src/SettingsManager.h +++ b/src/SettingsManager.h @@ -10,6 +10,7 @@ #include #include "config.h" +#include "utils/Log.h" #include "utils/FileStream.h" class SettingsManager { @@ -38,6 +39,7 @@ class SettingsManager { int8_t bytes[sizeof(Settings)]; }; + static void initSettings(); static SettingsManager::Settings loadSettings(); static void saveSettings(SettingsManager::Settings settings); private: diff --git a/src/config.cpp b/src/config.cpp index 81f346d..226077b 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -10,5 +10,6 @@ uint8_t GlobalSetting::BarH = 10; uint16_t GlobalSetting::DefaultScreenWidth = 640; uint16_t GlobalSetting::DefaultScreenHeight = 480; std::string GlobalSetting::SavesPrefix = ""; -std::string GlobalSetting::GlobalSaveFileName = "GDTRStates"; +std::filesystem::path GlobalSetting::SavesPath = "./saves"; +std::filesystem::path GlobalSetting::GlobalSaveFileName = "GDTRStates.dat"; std::filesystem::path GlobalSetting::MrgFilePath = "levels.mrg"; \ No newline at end of file diff --git a/src/config.h b/src/config.h index b2b1e68..90426f2 100644 --- a/src/config.h +++ b/src/config.h @@ -9,21 +9,20 @@ #include #include -enum { - LEAGUES_MAX = 4, - RECORD_NO_MAX = 3, - PLAYER_NAME_MAX = 3, -}; -enum Keys { - NONE = 0, - UP = 1, - DOWN = 6, - LEFT = 2, - RIGHT = 5, - FIRE = 8, - BACK = 9, - // MENU = 10 +constexpr int LEAGUES_MAX = 4; +constexpr int RECORD_NO_MAX = 3; +constexpr int PLAYER_NAME_MAX = 3; + + +enum class Keys { + NONE, // = 0, + UP, // = 1, + DOWN, // = 6, + LEFT, // = 2, + RIGHT, // = 5, + FIRE, // = 8, + BACK, // = 9, }; static std::map gameKeyMappings = { @@ -32,7 +31,7 @@ static std::map gameKeyMappings = { { SDLK_UP, Keys::UP }, { SDLK_DOWN, Keys::DOWN }, - { SDLK_RETURN, Keys::UP}, + { SDLK_RETURN, Keys::UP }, { SDLK_ESCAPE, Keys::BACK }, { SDLK_BACKSPACE, Keys::DOWN }, }; @@ -42,20 +41,21 @@ static std::map menuKeyMappings = { { SDLK_UP, Keys::UP }, { SDLK_DOWN, Keys::DOWN }, - { SDLK_RETURN, Keys::FIRE}, + { SDLK_RETURN, Keys::FIRE }, { SDLK_ESCAPE, Keys::BACK }, { SDLK_BACKSPACE, Keys::BACK }, }; static std::map> availableActions = { - { Keys::UP, {1, 0} }, - { Keys::DOWN, {-1, 0} }, - { Keys::LEFT, {0, -1} }, - { Keys::RIGHT, {0, 1} }, + { Keys::UP, { 1, 0 } }, + { Keys::DOWN, { -1, 0 } }, + { Keys::LEFT, { 0, -1 } }, + { Keys::RIGHT, { 0, 1 } }, // { Keys::FIRE, {1, 0} }, // { Keys::BACK, {-1, 0} }, }; -static std::vector onOffLabels = { "On", "Off" };; +static std::vector onOffLabels = { "On", "Off" }; + static std::vector inputLabels = { "Keyset 1", "Keyset 2", "Keyset 3" }; static std::vector levelLabels = { "Easy", "Medium", "Pro" }; @@ -73,6 +73,7 @@ struct GlobalSetting { static uint16_t DefaultScreenWidth; static uint16_t DefaultScreenHeight; static std::string SavesPrefix; - static std::string GlobalSaveFileName; + static std::filesystem::path GlobalSaveFileName; + static std::filesystem::path SavesPath; static std::filesystem::path MrgFilePath; }; \ No newline at end of file diff --git a/src/lcdui/CanvasImpl.cpp b/src/lcdui/CanvasImpl.cpp index cb541b3..1093e33 100644 --- a/src/lcdui/CanvasImpl.cpp +++ b/src/lcdui/CanvasImpl.cpp @@ -112,7 +112,7 @@ void CanvasImpl::processEvents() Keys CanvasImpl::convertKeyCharToKeyCode(const SDL_Keycode keyCode) { - std::cout << "KEY " << keyCode << "; MENU " << Micro::isInGameMenu << std::endl; + Log::write(Log::LogLevel::Debug, "KEY %d; Menu: %d\n", keyCode, Micro::isInGameMenu); if (Micro::isInGameMenu && menuKeyMappings.count(keyCode) > 0) { return menuKeyMappings[keyCode]; @@ -122,7 +122,7 @@ Keys CanvasImpl::convertKeyCharToKeyCode(const SDL_Keycode keyCode) return gameKeyMappings[keyCode]; } - std::cout << "unknown keyEvent: " << keyCode << std::endl; + Log::write(Log::LogLevel::Warning, "unknown keyEvent: %d\n", keyCode); return Keys::NONE; } diff --git a/src/lcdui/CanvasImpl.h b/src/lcdui/CanvasImpl.h index c96b63d..0c35c72 100644 --- a/src/lcdui/CanvasImpl.h +++ b/src/lcdui/CanvasImpl.h @@ -9,6 +9,7 @@ #include "Canvas.h" #include "../config.h" +#include "../utils/Log.h" class Canvas; diff --git a/src/lcdui/Command.cpp b/src/lcdui/Command.cpp index 8cb9f73..3644665 100644 --- a/src/lcdui/Command.cpp +++ b/src/lcdui/Command.cpp @@ -1,6 +1,6 @@ #include "Command.h" -Command::Command(std::string name, int type, int priority) +Command::Command(const std::string name, const Command::Type type, const int priority) : name(name) , type(type) , priority(priority) diff --git a/src/lcdui/Command.h b/src/lcdui/Command.h index c5705df..fafe54a 100644 --- a/src/lcdui/Command.h +++ b/src/lcdui/Command.h @@ -11,7 +11,7 @@ inline void hash_combine(std::size_t& seed, const T& v) class Command { public: - enum Type { + enum class Type { SCREEN = 1, BACK = 2, CANCEL = 3, @@ -40,10 +40,10 @@ class Command { } }; - Command(std::string name, int type, int priority); + Command(const std::string name, const Command::Type type, const int priority); ~Command(); const std::string name; - const int type; + const Command::Type type; const int priority; }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f86da93..ff9f862 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,18 +1,104 @@ #include #include #include +#include +#include "utils/Hashing.h" +#include "utils/Log.h" +#include "config.h" #include "Micro.h" +void showHelp(const char* progName) +{ + Log::write(Log::LogLevel::None, "Usage %s [options]\n", progName); + Log::write(Log::LogLevel::None, " -f, --fullscreen Enable fullscreen\n", progName); + Log::write(Log::LogLevel::None, " -w, --width INT Set screen width in px\n", progName); + Log::write(Log::LogLevel::None, " -h, --height INT Set screen height in px\n", progName); + Log::write(Log::LogLevel::None, " -?, --help Show this help screen\n", progName); + Log::write(Log::LogLevel::None, " -v, --verbose INT Set log level (0-6)\n", progName); +} + +bool parseArguments(int argc, char** argv) +{ + int opt; + static struct option long_options[] = { + { "fullscreen", no_argument, nullptr, 'f' }, + { "width", optional_argument, nullptr, 'w' }, + { "height", optional_argument, nullptr, 'h' }, + { "verbose", optional_argument, nullptr, 'v' }, + { "help", no_argument, nullptr, '?' }, + { nullptr, 0, nullptr, 0 } + }; + + Log::logLevel = Log::LogLevel::All; + + while ((opt = getopt_long(argc, argv, "fhw:v:?", long_options, nullptr)) != -1) { + switch (opt) { + case 'f': { + Log::write(Log::LogLevel::None, "Setting fullscreen\n"); + GlobalSetting::WindowFullscreen = true; + break; + } + case 'w': { + GlobalSetting::DefaultScreenWidth = atoi(optarg); + Log::write(Log::LogLevel::None, "Setting width %d\n", GlobalSetting::DefaultScreenWidth); + break; + } + case 'h': { + GlobalSetting::DefaultScreenHeight = atoi(optarg); + Log::write(Log::LogLevel::None, "Setting height %d\n", GlobalSetting::DefaultScreenHeight); + break; + } + case 'v': { + uint logLevelFromArg = 6 - atoi(optarg); + + if (logLevelFromArg > static_cast(Log::LogLevel::None)) { + Log::logLevel = Log::LogLevel::All; + } else { + Log::logLevel = static_cast(logLevelFromArg); + } + + Log::write(Log::LogLevel::None, "Setting logs verbosity to %u\n", Log::logLevel); + break; + } + case '?': + default: { + showHelp(argv[0]); + return false; + } + } + } + + // Handle any remaining arguments + if (optind < argc) { + std::stringstream ss("Remaining arguments: "); + + for (int i = optind; i < argc; i++) { + ss << argv[i] << " "; + } + + Log::write(Log::LogLevel::Error, ss.str().c_str()); + } + + Log::write(Log::LogLevel::Info, "Path: %s\n", GlobalSetting::MrgFilePath.c_str()); + GlobalSetting::SavesPrefix = Hashing::HashFileMD5(GlobalSetting::MrgFilePath.string()); + Log::write(Log::LogLevel::Info, "MRG file hash: %s\n", GlobalSetting::SavesPrefix.c_str()); + return true; +} + int main(int argc, char** argv) { + if (!parseArguments(argc, argv)) { + return EXIT_FAILURE; + } + try { std::unique_ptr micro = std::make_unique(); - micro->startApp(argc, argv); + micro->startApp(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; -}; +}; \ No newline at end of file diff --git a/src/rms/InvalidRecordIDException.h b/src/rms/InvalidRecordIDException.h deleted file mode 100644 index a4074ef..0000000 --- a/src/rms/InvalidRecordIDException.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -class InvalidRecordIDException : public std::exception { -}; \ No newline at end of file diff --git a/src/rms/RecordComparator.h b/src/rms/RecordComparator.h deleted file mode 100644 index 951dce2..0000000 --- a/src/rms/RecordComparator.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -class RecordComparator { -}; \ No newline at end of file diff --git a/src/rms/RecordEnumeration.h b/src/rms/RecordEnumeration.h deleted file mode 100644 index 8fc3859..0000000 --- a/src/rms/RecordEnumeration.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -class RecordEnumeration { -public: - virtual int numRecords() = 0; - virtual std::vector nextRecord() = 0; - virtual void reset() = 0; - virtual int nextRecordId() = 0; - virtual void destroy() = 0; -}; diff --git a/src/rms/RecordEnumerationImpl.cpp b/src/rms/RecordEnumerationImpl.cpp deleted file mode 100644 index 45c2ac9..0000000 --- a/src/rms/RecordEnumerationImpl.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "RecordEnumerationImpl.h" -#include "RecordStoreException.h" - -RecordEnumerationImpl::RecordEnumerationImpl(std::vector> data) -{ - this->data = data; -} - -RecordEnumerationImpl::RecordEnumerationImpl() -{ -} - -RecordEnumerationImpl::~RecordEnumerationImpl() -{ - data.clear(); -} - -int RecordEnumerationImpl::numRecords() -{ - return data.size(); -} - -std::vector RecordEnumerationImpl::nextRecord() -{ - return data[currentPos++]; -} - -int RecordEnumerationImpl::addRecord(std::vector bytes) -{ - data.push_back(bytes); - return data.size() - 1; -} - -void RecordEnumerationImpl::setRecord(int index, std::vector bytes) -{ - if (static_cast(data.size()) <= index) { - throw RecordStoreException(); - } - - data[index] = bytes; -} - -void RecordEnumerationImpl::reset() -{ - currentPos = 0; -} - -int RecordEnumerationImpl::nextRecordId() -{ - if (currentPos >= static_cast(data.size())) { - throw RecordStoreException(); - } - - return currentPos; -} - -void RecordEnumerationImpl::destroy() -{ - data.clear(); -} - -void RecordEnumerationImpl::serialize(FileStream* outStream) -{ - size_t temp = data.size(); - outStream->writeVariable(¤tPos); - outStream->writeVariable(&(temp = data.size())); - - for (auto i = data.cbegin(); i != data.cend(); i++) { - outStream->writeVariable(&(temp = i->size())); - - for (auto j = i->cbegin(); j != i->cend(); j++) { - int8_t buffer; - outStream->writeVariable(&(buffer = *j)); - } - } -} - -void RecordEnumerationImpl::deserialize(FileStream* inStream) -{ - size_t temp; - inStream->readVariable(¤tPos); - inStream->readVariable(&temp); - data.resize(temp); - - for (size_t i = 0; i < data.size(); ++i) { - inStream->readVariable(&temp); - data[i].resize(temp); - - for (size_t j = 0; j < data[i].size(); ++j) { - inStream->readVariable(&data[i][j]); - } - } -} diff --git a/src/rms/RecordEnumerationImpl.h b/src/rms/RecordEnumerationImpl.h deleted file mode 100644 index 8db27f1..0000000 --- a/src/rms/RecordEnumerationImpl.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include - -#include "RecordEnumeration.h" -#include "../utils/FileStream.h" - -class RecordEnumerationImpl : public RecordEnumeration { -private: - // static const int64_t serialVersionUID = 123; - int currentPos = 0; - -public: - RecordEnumerationImpl(std::vector> data); - RecordEnumerationImpl(); - ~RecordEnumerationImpl(); - - int numRecords(); - std::vector nextRecord(); - int addRecord(std::vector bytes); - void setRecord(int index, std::vector bytes); - void reset(); - int nextRecordId(); - void destroy(); - - void serialize(FileStream* outStream); - void deserialize(FileStream* inStream); - - std::vector> data; -}; diff --git a/src/rms/RecordFilter.h b/src/rms/RecordFilter.h deleted file mode 100644 index 5e40044..0000000 --- a/src/rms/RecordFilter.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -class RecordFilter { -}; \ No newline at end of file diff --git a/src/rms/RecordStore.cpp b/src/rms/RecordStore.cpp deleted file mode 100644 index a33ac14..0000000 --- a/src/rms/RecordStore.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "RecordStore.h" - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#else -#include -#include -#endif - -#include "RecordStoreException.h" -#include "../config.h" -#include "../utils/FileStream.h" -#include "../utils/String.h" - -RecordStore::RecordStore(std::filesystem::path filePath, RecordEnumerationImpl* records) -{ - this->filePath = filePath; - this->records.reset(records); -} - -RecordEnumeration* RecordStore::enumerateRecords(RecordFilter* filter, RecordComparator* comparator, bool keepUpdated) -{ - assert(filter == nullptr); - assert(comparator == nullptr); - assert(!keepUpdated); - log("enumerateRecords()"); - return records.get(); -} - -void RecordStore::closeRecordStore() -{ - // nothing -} - -int RecordStore::addOrUpdateRecord(int recordId, std::vector arr, int offset, int numBytes) -{ - if (recordId == -1) { - return this->addRecord(arr, offset, numBytes); - } - - this->setRecord(recordId, arr, offset, numBytes); - return recordId; -} - -int RecordStore::addRecord(std::vector arr, int offset, int numBytes) -{ - log("addRecord(" + std::to_string(arr.size()) + "," + std::to_string(offset) + "," + std::to_string(numBytes) + ")"); - assert(static_cast(arr.size()) == numBytes); - assert(offset == 0); - int id = records->addRecord(arr); - log("record id = " + std::to_string(id)); - save(); - return id; -} - -void RecordStore::setRecord(int recordId, std::vector arr, int offset, int numBytes) -{ - (void)offset; - (void)numBytes; - records->setRecord(recordId, arr); - save(); -} - -void RecordStore::save() -{ - FileStream outStream(filePath, std::ios::out | std::ios::binary); - records->serialize(&outStream); -} - -RecordEnumerationImpl* RecordStore::load(std::filesystem::path filePath) -{ - RecordEnumerationImpl* temp = new RecordEnumerationImpl(); - FileStream inStream(filePath, std::ios::in | std::ios::binary); - temp->deserialize(&inStream); - return temp; -} - -RecordStore* RecordStore::openRecordStore(std::string name, bool createIfNecessary) -{ - if (name.empty()) { - log("empty name"); - return nullptr; - } - - name = GlobalSetting::SavesPrefix + "_" + name; - log("openRecordStore(" + name + ", " + std::to_string(createIfNecessary) + ")"); - - if (opened.find(name) == opened.end()) { - opened[name] = createRecordStore(name, createIfNecessary); - } - - return opened[name].get(); -} - -std::unique_ptr RecordStore::createRecordStore(std::string name, bool createIfNecessary) -{ - log("createRecordStore(" + name + ", " + std::to_string(createIfNecessary) + ")"); - std::filesystem::path filePath = recordStoreDir / std::filesystem::path(name); - - if (std::filesystem::exists(filePath)) { - return std::unique_ptr(new RecordStore(filePath, load(filePath))); - } - - if (createIfNecessary) { - std::filesystem::create_directories(filePath.parent_path()); - - std::unique_ptr rs(new RecordStore(filePath, new RecordEnumerationImpl())); - rs->save(); - return rs; - } else { - log("can't create record, file is missing"); - throw RecordStoreException(); - } -} - -std::vector RecordStore::listRecordStores() -{ - std::vector result; - - for (const auto& entry : recordStoreDir) - result.push_back(entry.filename().string()); - - log("listRecordStores() = {" + String::join(result, ", ") + "}"); - - return result; -} - -void RecordStore::deleteRecordStore(std::string name) -{ - log("deleteRecordStore(" + name + ")"); - throw std::runtime_error("deleteRecordStore is not implemented"); -} - -void RecordStore::log(std::string s) -{ - std::cout << s << std::endl; -} - -void RecordStore::setRecordStoreDir([[maybe_unused]] const char* progName) -{ -#ifdef WIN32 - const char* base = dirname(strdup(progName)); - recordStoreDir = std::filesystem::path(base) / "recordStore"; -#else - // const char* homeDir = getenv("HOME"); - // if (!homeDir) - // homeDir = getpwuid(getuid())->pw_dir; - - // if (!homeDir) - // throw std::system_error(errno, std::system_category(), "Error getting home directory"); - - recordStoreDir = std::filesystem::path("./saves"); -#endif -} diff --git a/src/rms/RecordStore.h b/src/rms/RecordStore.h deleted file mode 100644 index 0d46ded..0000000 --- a/src/rms/RecordStore.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "RecordEnumerationImpl.h" - -class RecordFilter; -class RecordComparator; - -class RecordStore { -private: - RecordStore(std::filesystem::path filePath, RecordEnumerationImpl* records); - void save(); - static RecordEnumerationImpl* load(std::filesystem::path filePath); - static std::unique_ptr createRecordStore(std::string name, bool createIfNecessary); - static void log(std::string s); - - inline static std::filesystem::path recordStoreDir; - inline static std::unordered_map> opened; - std::filesystem::path filePath; - std::unique_ptr records; - -public: - static void setRecordStoreDir(const char* progName); - static RecordStore* openRecordStore(std::string name, bool createIfNecessary); - void closeRecordStore(); - static void deleteRecordStore(std::string name); - static std::vector listRecordStores(); - RecordEnumeration* enumerateRecords(RecordFilter* filter, RecordComparator* comparator, bool keepUpdated); - int addRecord(std::vector arr, int offset, int numBytes); - void setRecord(int recordId, std::vector arr, int offset, int numBytes); - int addOrUpdateRecord(int recordId, std::vector arr, int offset, int numBytes); -}; \ No newline at end of file diff --git a/src/rms/RecordStoreException.h b/src/rms/RecordStoreException.h deleted file mode 100644 index 51f8d38..0000000 --- a/src/rms/RecordStoreException.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -class RecordStoreException : public std::exception { -}; \ No newline at end of file diff --git a/src/rms/RecordStoreNotOpenException.h b/src/rms/RecordStoreNotOpenException.h deleted file mode 100644 index af44314..0000000 --- a/src/rms/RecordStoreNotOpenException.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -class RecordStoreNotOpenException : public std::exception { -}; \ No newline at end of file diff --git a/src/tests/test_rms.cpp b/src/tests/test_rms.cpp deleted file mode 100644 index 096a38c..0000000 --- a/src/tests/test_rms.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "test_rms.h" - -#include -#include -#include - -#include "../rms/RecordStore.h" -#include "../utils/String.h" - -void test_rms() -{ - std::vector records = RecordStore::listRecordStores(); - - RecordStore* rs = RecordStore::openRecordStore("GDTRStat", true); - - const bool create = false; // to test the rms you have to toggle this variable manually - - if (create) { - std::vector v1 = { 12, 54, 25, -23 }; - std::vector v2 = { 1, 17, 45, -23, -100 }; - rs->addRecord(v1, 0, v1.size()); - rs->addRecord(v2, 0, v2.size()); - } else { - RecordEnumeration* re = rs->enumerateRecords(nullptr, nullptr, false); - re->reset(); - - for (int i = 0; i < re->numRecords(); ++i) { - int recordId = re->nextRecordId(); - std::vector record = re->nextRecord(); - std::cout << "Record " << std::to_string(recordId) << ": {" << String::join(record, ", ") << "}" << std::endl; - } - } -} \ No newline at end of file diff --git a/src/tests/test_rms.h b/src/tests/test_rms.h deleted file mode 100644 index 797f070..0000000 --- a/src/tests/test_rms.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void test_rms(); \ No newline at end of file diff --git a/src/utils/Log.cpp b/src/utils/Log.cpp new file mode 100644 index 0000000..187fc06 --- /dev/null +++ b/src/utils/Log.cpp @@ -0,0 +1,18 @@ +#include "Log.h" + +Log::LogLevel Log::logLevel = Log::LogLevel::Error; + +void Log::write(const Log::LogLevel level, const char* szFormat, ...) +{ + if (level < Log::logLevel) { + return; + } + + va_list args; + va_start(args, szFormat); + vprintf(szFormat, args); + va_end(args); +} + + + diff --git a/src/utils/Log.h b/src/utils/Log.h new file mode 100644 index 0000000..0e5adcb --- /dev/null +++ b/src/utils/Log.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +struct Log { + enum class LogLevel { + All = 0, + Debug = 1, + Info = 2, + Warning = 3, + Error = 4, + Fatal = 5, + None = 6 + }; + + static Log::LogLevel logLevel; + static void write(const Log::LogLevel level, const char* szFormat, ...); +}; \ No newline at end of file From 380d2bc7445cc557bc840528eeb546e4eeaeb5fe Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Fri, 15 Nov 2024 23:48:27 +0200 Subject: [PATCH 12/16] code cleanup --- README.md | 4 +-- src/GameCanvas.cpp | 2 +- src/GameCanvas.h | 2 +- src/GameLevel.h | 1 - src/GameMenu.cpp | 64 +++++++++++++++++++++++----------- src/GameMenu.h | 8 ++--- src/LevelLoader.cpp | 48 ------------------------- src/LevelLoader.h | 6 ---- src/MenuManager.cpp | 77 ++++++++++++++++++++++------------------- src/MenuManager.h | 8 ++--- src/Micro.cpp | 12 +++---- src/Micro.h | 1 - src/RecordManager.cpp | 32 +++++------------ src/RecordManager.h | 22 +++++------- src/SettingsManager.cpp | 19 +++++++--- src/class_10.cpp | 5 --- src/class_10.h | 1 - src/lcdui/Canvas.cpp | 4 --- src/lcdui/Canvas.h | 1 - src/lcdui/Command.cpp | 4 --- src/lcdui/Command.h | 1 - src/utils/Time.cpp | 10 +++--- src/utils/Time.h | 4 +-- 23 files changed, 139 insertions(+), 197 deletions(-) diff --git a/README.md b/README.md index 76b8f5d..6b27cd1 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ This is the C++ & SDL2 port of Gravity Defied, which includes all the features o # TODO -- [ ] create saves directory and global setting file when missing +- [X] create saves directory and global setting file when missing - [ ] config file -- [ ] command line flags +- [X] command line flags - [ ] level file selector - [ ] further refactoring - [ ] scaling game (or at least font) diff --git a/src/GameCanvas.cpp b/src/GameCanvas.cpp index dac3c15..4c20537 100644 --- a/src/GameCanvas.cpp +++ b/src/GameCanvas.cpp @@ -214,7 +214,7 @@ void GameCanvas::drawHelmet(int x, int y, int angleF16) } } -void GameCanvas::drawTime(int64_t time10Ms) +void GameCanvas::drawTime(uint64_t time10Ms) { const std::string timeStr = Time::timeToString(time10Ms); setColor(0, 0, 0); diff --git a/src/GameCanvas.h b/src/GameCanvas.h index d9dd6ba..e71b015 100644 --- a/src/GameCanvas.h +++ b/src/GameCanvas.h @@ -98,7 +98,7 @@ class GameCanvas : public Canvas, public CommandListener { void fillRect(int x, int y, int w, int h); void drawForthSpriteByCenter(int centerX, int centerY); void drawHelmet(int var1, int var2, int var3); - void drawTime(int64_t time10Ms); + void drawTime(uint64_t time10Ms); void method_150(int var1); static void method_151(); void renderStartFlag(int x, int y); diff --git a/src/GameLevel.h b/src/GameLevel.h index 42b9de8..7cf883c 100644 --- a/src/GameLevel.h +++ b/src/GameLevel.h @@ -29,7 +29,6 @@ class GameLevel { std::vector> pointPositions; GameLevel(); - ~GameLevel(); void init(); void method_174(int var1, int var2, int var3, int var4); int getStartPosX(); diff --git a/src/GameMenu.cpp b/src/GameMenu.cpp index b3b4bd1..69783e0 100644 --- a/src/GameMenu.cpp +++ b/src/GameMenu.cpp @@ -11,13 +11,13 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputString) { - field_94 = var1; + name = var1; field_95 = -1; this->micro = micro; gameMenu = var3; canvasWidth = micro->gameCanvas->getWidth(); canvasHeight = micro->gameCanvas->getHeight(); - + font = FontStorage::getFont(Font::STYLE_BOLD, Font::SIZE_LARGE); font3 = FontStorage::getFont(Font::STYLE_PLAIN, Font::SIZE_SMALL); @@ -30,6 +30,7 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt TextRender::setDefaultFont(font3); TextRender::setMaxArea(canvasWidth, canvasHeight); field_101 = 1; + if (canvasWidth <= 100) { xPos = 6; } else { @@ -37,13 +38,14 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt } if (canvasHeight <= 100) { - field_94 = ""; + name = ""; } field_104 = xPos + 7; field_103 = 2; field_110 = 0; - if (field_94 != "") { + + if (name != "") { field_107 = (canvasHeight - (field_101 << 1) - 10 - font->getBaselinePosition()) / (font2->getBaselinePosition() + field_103); } else { field_107 = (canvasHeight - (field_101 << 1) - 10) / (font2->getBaselinePosition() + field_103); @@ -63,15 +65,15 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt } } -void GameMenu::method_68(int var1) -{ - field_103 = var1; -} +// void GameMenu::method_68(int var1) +// { +// field_103 = var1; +// } -void GameMenu::method_69(std::string var1) -{ - field_94 = var1; -} +// void GameMenu::method_69(std::string var1) +// { +// name = var1; +// } void GameMenu::method_70() { @@ -90,6 +92,7 @@ void GameMenu::method_70() field_105 = 0; field_106 = vector.size() - 1; + if (field_106 > field_107 - 1) { field_106 = field_107 - 1; } @@ -109,11 +112,13 @@ void GameMenu::method_71() } field_105 = vector.size() - field_107; + if (field_105 < 0) { field_105 = 0; } field_106 = vector.size() - 1; + if (field_106 > field_95 + field_107) { field_106 = field_95 + field_107; } @@ -124,7 +129,8 @@ void GameMenu::addMenuElement(IGameMenuElement* var1) int var2 = field_101; field_107 = 1; vector.push_back(var1); - if (field_94 != "") { + + if (name != "") { var2 = font->getBaselinePosition() + 2; } @@ -164,6 +170,7 @@ void GameMenu::processGameActionDown() } --strArr[nameCursorPos]; + if (strArr[nameCursorPos] < 65) { strArr[nameCursorPos] = 32; return; @@ -177,6 +184,7 @@ void GameMenu::processGameActionDown() } ++field_95; + if (field_95 > static_cast(vector.size()) - 1) { method_70(); return; @@ -185,6 +193,7 @@ void GameMenu::processGameActionDown() bool var3 = false; int var2; + for (var2 = field_95; var2 <= field_106 + 1; ++var2) { if (vector[var2]->isNotTextRender()) { var3 = true; @@ -204,6 +213,7 @@ void GameMenu::processGameActionDown() if (field_95 > field_106) { ++field_105; ++field_106; + if (field_106 > static_cast(vector.size()) - 1) { field_106 = vector.size() - 1; } @@ -222,20 +232,22 @@ void GameMenu::processGameActionUp() } ++strArr[nameCursorPos]; + if (strArr[nameCursorPos] > 90) { strArr[nameCursorPos] = 32; return; } } else if (vector.size() != 0) { --field_95; + if (field_95 < 0) { method_71(); return; } bool var3 = false; - int var2; + for (var2 = field_95; var2 >= field_105; --var2) { if (vector[var2]->isNotTextRender()) { var3 = true; @@ -246,6 +258,7 @@ void GameMenu::processGameActionUp() if (!var3) { if (field_105 > 0) { --field_105; + if (static_cast(vector.size()) > field_107 - 1) { --field_106; return; @@ -258,8 +271,10 @@ void GameMenu::processGameActionUp() } field_95 = var2; + if (field_95 < field_105) { --field_105; + if (field_105 < 0) { field_95 = 0; field_105 = 0; @@ -286,13 +301,16 @@ void GameMenu::processGameActionUpd(int var1) return; case 2: ++nameCursorPos; + if (nameCursorPos > 2) { nameCursorPos = 2; return; } + break; case 3: --nameCursorPos; + if (nameCursorPos < 0) { nameCursorPos = 0; } @@ -302,6 +320,7 @@ void GameMenu::processGameActionUpd(int var1) if (field_95 != -1) { for (int var2 = field_95; var2 < static_cast(vector.size()); ++var2) { IGameMenuElement* var3; + if ((var3 = vector[var2]) != nullptr && var3->isNotTextRender()) { var3->menuElemMethod(var1); return; @@ -315,6 +334,7 @@ void GameMenu::render_76(Graphics* graphics) { int var2; int i; + if (field_111) { graphics->setColor(0, 0, 20); graphics->setFont(font); @@ -325,6 +345,7 @@ void GameMenu::render_76(Graphics* graphics) for (i = 0; i < 3; ++i) { graphics->drawChar((char)strArr[i], xPos + i * font2->charWidth('W') + 1, var2, 17); + if (i == nameCursorPos) { graphics->drawChar('^', xPos + i * font2->charWidth('W') + 1, var2 + font2->getHeight(), 17); } @@ -333,9 +354,10 @@ void GameMenu::render_76(Graphics* graphics) } else { graphics->setColor(0, 0, 0); var2 = field_101; - if (field_94 != "") { + + if (name != "") { graphics->setFont(font); - graphics->drawString(field_94, xPos, var2, 20); + graphics->drawString(name, xPos, var2, 20); var2 += font->getBaselinePosition() + 2; } @@ -355,6 +377,7 @@ void GameMenu::render_76(Graphics* graphics) IGameMenuElement* var4 = vector[i]; graphics->setColor(0, 0, 0); var4->render(graphics, var2, field_104); + if (i == field_95 && var4->isNotTextRender()) { int var5 = xPos - micro->gameCanvas->helmetSpriteWidth / 2; int var6 = var2 + font2->getBaselinePosition() / 2 - micro->gameCanvas->helmetSpriteHeight / 2; @@ -362,6 +385,7 @@ void GameMenu::render_76(Graphics* graphics) graphics->drawImage(micro->gameCanvas->helmetImage.get(), var5 - micro->gameCanvas->helmetSpriteWidth * (field_110 % 6), var6 - micro->gameCanvas->helmetSpriteHeight * (field_110 / 6), 20); graphics->setClip(0, 0, canvasWidth, canvasHeight); ++field_110; + if (field_110 > 30) { field_110 = 0; } @@ -395,10 +419,10 @@ GameMenu* GameMenu::getGameMenu() return gameMenu; } -int GameMenu::method_79() -{ - return field_95; -} +// int GameMenu::method_79() +// { +// return field_95; +// } void GameMenu::clearVector() { diff --git a/src/GameMenu.h b/src/GameMenu.h index fed448e..316ab38 100644 --- a/src/GameMenu.h +++ b/src/GameMenu.h @@ -13,7 +13,7 @@ class Graphics; class GameMenu { private: GameMenu* gameMenu; - std::string field_94; + std::string name; int field_95; std::vector vector; Micro* micro; @@ -37,8 +37,8 @@ class GameMenu { int xPos; GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputString = nullptr); - void method_68(int var1); - void method_69(std::string var1); + // void method_68(int var1); + // void method_69(std::string var1); void method_70(); void method_71(); void addMenuElement(IGameMenuElement* var1); @@ -48,7 +48,7 @@ class GameMenu { void render_76(Graphics* graphics); void setGameMenu(GameMenu* gameMenu); GameMenu* getGameMenu(); - int method_79(); + // int method_79(); void clearVector(); std::string makeString(); char* getStrArr() const; diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index 30c0adc..a849462 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -21,58 +21,10 @@ LevelLoader::LevelLoader(const std::filesystem::path& path) } this->mrgFilePath = path; - // if (!mrgFilePath.string().empty()) { - // FileStream* fileStream = new FileStream(mrgFilePath, std::ios::in | std::ios::binary); - - // if (!fileStream->isOpen()) { - // throw std::system_error(errno, std::system_category(), "Failed to open " + mrgFilePath.string()); - // } - - // levelFileStream = fileStream; - // } else { - // EmbedFileStream* embedFileStream = new EmbedFileStream("levels.mrg"); - // levelFileStream = static_cast(embedFileStream); - // } - - // loadLevels(); trackHeaders = MRGLoader::loadLevels(this->mrgFilePath); loadNextTrack(); } -// LevelLoader::~LevelLoader() -// { -// delete levelFileStream; -// } - -// void LevelLoader::loadLevels() -// { -// std::vector var3(40); -// std::vector var4(3); - -// for (int league = 0; league < 3; ++league) { -// levelFileStream->readVariable(&var4[league], true); -// levelOffsetInFile[league] = std::vector(var4[league]); -// levelNames[league] = std::vector(var4[league]); - -// for (int levelNp = 0; levelNp < var4[league]; ++levelNp) { -// int var7; -// levelFileStream->readVariable(&var7, true); -// levelOffsetInFile[league][levelNp] = var7; - -// for (int var8 = 0; var8 < 40; ++var8) { -// levelFileStream->readVariable(&var3[var8], true); - -// if (var3[var8] == 0) { -// std::string s = std::string(reinterpret_cast(var3.data()), var8); -// std::replace(s.begin(), s.end(), '_', ' '); -// levelNames[league][levelNp] = s; -// break; -// } -// } -// } -// } -// } - std::string LevelLoader::getName(const int level, const int track) const { const MRGLoader::LevelTracks l = trackHeaders.at(level); diff --git a/src/LevelLoader.h b/src/LevelLoader.h index 1ee0590..4faad27 100644 --- a/src/LevelLoader.h +++ b/src/LevelLoader.h @@ -23,7 +23,6 @@ class LevelLoader { std::vector> field_121; int field_123[3]; int field_124[3]; - // inline static std::vector> levelOffsetInFile = std::vector>(3); std::array trackHeaders; std::filesystem::path mrgFilePath; @@ -33,9 +32,6 @@ class LevelLoader { static int field_135; static int field_136; - // FileStream* levelFileStream; - // void loadLevels(); - public: static const int field_114; static const int field_115; @@ -47,7 +43,6 @@ class LevelLoader { GameLevel* gameLevel = nullptr; int loadedLevel = 0; int loadedTrack = -1; - // std::vector> levelNames = std::vector>(3); int field_129; int field_130; int field_131; @@ -55,7 +50,6 @@ class LevelLoader { int field_138; LevelLoader(const std::filesystem::path& mrgFilePath); - // ~LevelLoader(); std::string getName(const int level, const int track) const; int getTracksCount(const int level) const; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index ffc7374..1dde2e5 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -11,9 +11,9 @@ void MenuManager::initPart(int var1) switch (var1) { case 1: { recordManager = new RecordManager(); - trackTimeMs = -1L; + trackTimeMs = 0; trackTimeFormatted.clear(); - + return; } case 2: { @@ -22,7 +22,7 @@ void MenuManager::initPart(int var1) if (settings.playerName[0] < 'A' || settings.playerName[0] > 'Z') { strncpy(settings.playerName, defaultName, PLAYER_NAME_MAX); } - + // cheat code: set name to RKE to enable all leagues ??? if (strncmp(settings.playerName, cheatCode, PLAYER_NAME_MAX) == 0) { settings.availableLeagues = 3; @@ -253,14 +253,14 @@ int MenuManager::getCurrentTrack() return settingsStringTrack->getCurrentOptionPos(); } -bool MenuManager::method_196() +bool MenuManager::isRestartNeeded() { - if (field_357) { - field_357 = false; + if (restartNeeded) { + restartNeeded = false; return true; - } else { - return false; } + + return false; } void MenuManager::method_197() @@ -272,16 +272,20 @@ void MenuManager::method_197() currentLevelFinished = false; gameMenuFinished->clearVector(); gameMenuFinished->addMenuElement(new TextRender("Time: " + trackTimeFormatted, micro)); - std::vector var1 = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); + const std::array recordDescriptions = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); - for (std::size_t var2 = 0; var2 < var1.size(); ++var2) { - if (var1[var2] != "") { - gameMenuFinished->addMenuElement(new TextRender(std::to_string(var2 + 1) + "." + var1[var2], micro)); + for (uint8_t i = 0; i < recordDescriptions.size(); ++i) { + if (recordDescriptions[i].empty()) { + continue; } + + std::stringstream ss; + ss << (i + 1) << "." << recordDescriptions[i]; + gameMenuFinished->addMenuElement(new TextRender(ss.str(), micro)); } - // recordManager->closeRecordStore(); int8_t availableLeagues = -1; + if (settingsStringTrack->getMaxAvailableOptionPos() >= settingsStringTrack->getCurrentOptionPos()) { settingsStringTrack->setAvailableOptions(settingsStringTrack->getCurrentOptionPos() + 1 < settings.availableTracks[settingStringLevel->getCurrentOptionPos()] ? settings.availableTracks[settingStringLevel->getCurrentOptionPos()] : settingsStringTrack->getCurrentOptionPos() + 1); settings.availableTracks[settingStringLevel->getCurrentOptionPos()] = (int8_t)settingsStringTrack->getMaxAvailableOptionPos() < settings.availableTracks[settingStringLevel->getCurrentOptionPos()] ? settings.availableTracks[settingStringLevel->getCurrentOptionPos()] : (int8_t)settingsStringTrack->getMaxAvailableOptionPos(); @@ -307,7 +311,7 @@ void MenuManager::method_197() int var3 = getCountOfRecordStoresWithPrefix(settingStringLevel->getCurrentOptionPos()); addTextRender(gameMenuFinished, var3 + " of " + std::to_string(micro->levelLoader->getTracksCount(settingStringLevel->getCurrentOptionPos())) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); - + if (!currentLevelFinished) { field_333->setText("Restart: " + micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos())); field_334->setText("Next: " + micro->levelLoader->getName(field_354, field_355 + 1)); @@ -372,13 +376,13 @@ void MenuManager::method_201(int var1) case 0: method_1(gameMenuMain, false); micro->gamePhysics->enableGenerateInputAI(); - field_357 = true; + restartNeeded = true; break; case 1: field_354 = settingStringLevel->getCurrentOptionPos(); field_355 = settingsStringTrack->getCurrentOptionPos(); field_333->setText("Restart: " + micro->levelLoader->getName(field_354, field_355)); - field_357 = false; + restartNeeded = false; method_1(gameMenuIngame, false); break; case 2: { @@ -581,6 +585,7 @@ GameMenu* MenuManager::getGameMenu() void MenuManager::method_1(GameMenu* gm, bool var2) { micro->gameCanvas->removeCommand(commandBack); + if (gm != gameMenuMain && gm != gameMenuFinished && gm != nullptr) { micro->gameCanvas->addCommand(commandBack); } @@ -607,6 +612,7 @@ void MenuManager::method_1(GameMenu* gm, bool var2) } currentGameMenu = gm; + if (currentGameMenu != nullptr && !var2) { currentGameMenu->method_70(); } @@ -620,25 +626,22 @@ void MenuManager::method_207(int var1) recordManager->loadRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); gameMenuHighscore->addMenuElement(new TextRender(micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()), micro)); gameMenuHighscore->addMenuElement(new TextRender("LEAGUE: " + settingsStringLeague->getOptionsList()[var1], micro)); - std::vector var2 = recordManager->getRecordDescription(var1); - - for (std::size_t var3 = 0; var3 < var2.size(); ++var3) { - if (var2[var3] != "") { - TextRender* var4 = new TextRender(std::to_string(var3 + 1) + "." + var2[var3], micro); - var4->setDx(GameCanvas::spriteSizeX[5] + 1); - if (var3 == 0) { - var4->setDrawSprite(true, 5); - } else if (var3 == 1) { - var4->setDrawSprite(true, 6); - } else if (var3 == 2) { - var4->setDrawSprite(true, 7); - } + const std::array recordDescription = recordManager->getRecordDescription(var1); - gameMenuHighscore->addMenuElement(var4); + for (uint8_t i = 0; i < recordDescription.size(); ++i) { + if (recordDescription[i].empty()) { + continue; } + + std::stringstream ss; + ss << (i + 1) << '.' << recordDescription[i]; + TextRender* var4 = new TextRender(ss.str(), micro); + var4->setDx(GameCanvas::spriteSizeX[5] + 1); + var4->setDrawSprite(true, 5 + i); + gameMenuHighscore->addMenuElement(var4); } - if (var2[0] == "") { + if (recordDescription[0].empty()) { gameMenuHighscore->addMenuElement(new TextRender("No Highscores", micro)); } @@ -700,7 +703,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) micro->gamePhysics->disableGenerateInputAI(); micro->levelLoader->loadTrack(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); - field_357 = true; + restartNeeded = true; micro->menuToGame(); } else { showAlert("GDTR", "Complete more tracks to unlock this track/league combo.", nullptr); @@ -783,7 +786,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) settingsStringTrack->setAvailableOptions(settings.availableTracks[field_354]); settingsStringTrack->setCurentOptionPos(field_355); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); - field_357 = true; + restartNeeded = true; micro->menuToGame(); return; } @@ -796,7 +799,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) micro->levelLoader->loadTrack(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); micro->gamePhysics->setMotoLeague(settingsStringLeague->getCurrentOptionPos()); method_208(); - field_357 = true; + restartNeeded = true; micro->menuToGame(); return; } @@ -859,6 +862,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) int MenuManager::method_210() { int var1 = 0; + if (driverSpriteSetting->getCurrentOptionPos() == 0) { var1 |= 2; } @@ -874,6 +878,7 @@ void MenuManager::method_211(int var1) { bikeSpriteSetting->setCurentOptionPos(1); driverSpriteSetting->setCurentOptionPos(1); + if ((var1 & 1) > 0) { bikeSpriteSetting->setCurentOptionPos(0); } @@ -883,9 +888,9 @@ void MenuManager::method_211(int var1) } } -void MenuManager::method_215(int64_t var1) +void MenuManager::setGameTimeMs(const uint64_t timeMs) { - trackTimeMs = var1; + trackTimeMs = timeMs; } void MenuManager::exit() diff --git a/src/MenuManager.h b/src/MenuManager.h index 13d28fd..2526800 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -76,7 +76,7 @@ class MenuManager : public IMenuManager { SettingsStringRender* field_334; SettingsStringRender* field_335; SettingsStringRender* field_336; - int64_t trackTimeMs; + uint64_t trackTimeMs; std::string trackTimeFormatted; std::vector field_345 = { 0, 0, 0 }; std::vector leagueNames = std::vector(3); @@ -86,7 +86,7 @@ class MenuManager : public IMenuManager { int field_354 = 0; int field_355 = 0; bool currentLevelFinished = false; - bool field_357 = false; + bool restartNeeded = false; int8_t field_372 = 0; std::unique_ptr field_376; @@ -107,7 +107,7 @@ class MenuManager : public IMenuManager { void initPart(int var1); int getCurrentLevel(); int getCurrentTrack(); - bool method_196(); + bool isRestartNeeded(); void repaint(); int getCanvasHeight(); int getCanvasWidth(); @@ -123,7 +123,7 @@ class MenuManager : public IMenuManager { void processMenu(IGameMenuElement* menuElement); int method_210(); void method_211(int var1); - void method_215(int64_t var1); + void setGameTimeMs(const uint64_t var1); void removeOkAndBackCommands(); void addOkAndBackCommands(); /* synchronized */ void method_202(Graphics* var1); diff --git a/src/Micro.cpp b/src/Micro.cpp index 222fd06..29f65a4 100644 --- a/src/Micro.cpp +++ b/src/Micro.cpp @@ -15,10 +15,6 @@ Micro::Micro() { } -Micro::~Micro() -{ -} - void Micro::setNumPhysicsLoops(int value) { numPhysicsLoops = value; @@ -165,7 +161,7 @@ void Micro::run() restart(false); menuManager->method_201(0); - if (menuManager->method_196()) { + if (menuManager->isRestartNeeded()) { restart(true); } @@ -185,7 +181,7 @@ void Micro::run() if (isInGameMenu) { menuManager->method_201(1); - if (menuManager->method_196()) { + if (menuManager->isRestartNeeded()) { restart(true); } } @@ -246,10 +242,10 @@ void Micro::run() } goalLoop(); - menuManager->method_215(gameTimeMs / 10L); + menuManager->setGameTimeMs(gameTimeMs / 10L); menuManager->method_201(2); - if (menuManager->method_196()) { + if (menuManager->isRestartNeeded()) { restart(true); } diff --git a/src/Micro.h b/src/Micro.h index 41c9961..a89901b 100644 --- a/src/Micro.h +++ b/src/Micro.h @@ -31,7 +31,6 @@ class Micro { MenuManager* menuManager; Micro(); - ~Micro(); void startApp(); diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index e0231a8..c37b5ee 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -12,12 +12,12 @@ void RecordManager::loadRecordInfo(const uint8_t level, const uint8_t track) levelFileStream.readVariable(&recordsSaveDataConverter.bytes, false, sizeof(RecordsSaveData)); } -std::vector RecordManager::getRecordDescription(const uint8_t league) +std::array RecordManager::getRecordDescription(const uint8_t league) const { - std::vector recordsDescription = std::vector(RECORD_NO_MAX); + std::array recordsDescription; for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { - Record record = recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[i]; + const Record record = recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[i]; if (record.timeMs != 0L) { std::stringstream ss; @@ -26,7 +26,7 @@ std::vector RecordManager::getRecordDescription(const uint8_t leagu << Time::timeToString(record.timeMs); recordsDescription[i] = ss.str(); } else { - recordsDescription[i].clear(); + recordsDescription[i] = ""; } } @@ -43,12 +43,12 @@ void RecordManager::writeRecordInfo(const uint8_t level, const uint8_t track) levelFileStream.writeVariable(&recordsSaveDataConverter.bytes, sizeof(RecordsSaveData)); } -uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t timeMs) const +uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const uint64_t timeMs) const { for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { const Record record = recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[i]; - if (record.timeMs > timeMs || record.timeMs <= 0L) { + if (record.timeMs > timeMs || record.timeMs == 0L) { return i; } } @@ -56,7 +56,7 @@ uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const int64_t tim return 3; } -void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t timeMs) +void RecordManager::addNewRecord(const uint8_t league, const char* playerName, const uint64_t timeMs) { Log::write(Log::LogLevel::Info, "addNewRecord %d %s %d\n", (int)league, playerName, timeMs); const uint8_t newRecordPos = getPosOfNewRecord(league, timeMs); @@ -67,10 +67,6 @@ void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t return; } - if (timeMs > 16777000L) { - timeMs = 16777000L; // 3 int8_ts, not five, wtf? - } - if (newRecordPos < (RECORD_NO_MAX - 1)) { std::rotate( std::begin(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records) + newRecordPos, @@ -86,7 +82,7 @@ void RecordManager::addNewRecord(const uint8_t league, char* playerName, int64_t strncpy(recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[newRecordPos].playerName, playerName, PLAYER_NAME_MAX); } -void RecordManager::deleteRecordStores() +void RecordManager::deleteRecordStores() const { // TODO: // std::vector names = RecordStore::listRecordStores(); @@ -101,15 +97,3 @@ void RecordManager::deleteRecordStores() // } // } } - -// void RecordManager::closeRecordStore() -// { -// // if (recordStore != nullptr) { -// // try { -// // recordStore->closeRecordStore(); -// // return; -// // } catch (RecordStoreException& var1) { -// // return; -// // } -// // } -// } diff --git a/src/RecordManager.h b/src/RecordManager.h index fd4be59..1847c4a 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "config.h" #include "utils/Log.h" @@ -13,32 +14,27 @@ class RecordManager { public: - // inline static const int unused = 3; - void loadRecordInfo(const uint8_t level, const uint8_t track); - std::vector getRecordDescription(const uint8_t league); - uint8_t getPosOfNewRecord(const uint8_t league, const int64_t timeMs) const; + std::array getRecordDescription(const uint8_t league) const; + uint8_t getPosOfNewRecord(const uint8_t league, const uint64_t timeMs) const; void writeRecordInfo(const uint8_t level, const uint8_t track); - void addNewRecord(const uint8_t league, char* playerName, int64_t timeMs); - void deleteRecordStores(); - // void closeRecordStore(); + void addNewRecord(const uint8_t league, const char* playerName, const uint64_t timeMs); + void deleteRecordStores() const; private: - // 4: league, 100, 175, 225, 350, - // 3: three best times - struct /*__attribute__((packed))*/ Record { - int64_t timeMs; + struct Record { + uint64_t timeMs; char playerName[PLAYER_NAME_MAX]; uint8_t padding[5]; }; static_assert(sizeof(Record) == 16); - struct /*__attribute__((packed))*/ LeagueRecords { + struct LeagueRecords { Record records[RECORD_NO_MAX]; }; static_assert(sizeof(LeagueRecords) == 48); - struct /*__attribute__((packed))*/ RecordsSaveData { + struct RecordsSaveData { LeagueRecords leagueRecords[LEAGUES_MAX]; }; static_assert(sizeof(RecordsSaveData) == 192); diff --git a/src/SettingsManager.cpp b/src/SettingsManager.cpp index 671b9e0..5b79af2 100644 --- a/src/SettingsManager.cpp +++ b/src/SettingsManager.cpp @@ -2,12 +2,21 @@ void SettingsManager::initSettings() { - if (!std::filesystem::exists(GlobalSetting::SavesPath)) { - Log::write(Log::LogLevel::Info, "Creating directory %s\n", GlobalSetting::SavesPath.c_str()); - std::filesystem::create_directory(GlobalSetting::SavesPath); + std::filesystem::path saveFileName = GlobalSetting::SavesPath; + + if (!std::filesystem::exists(saveFileName)) { + Log::write(Log::LogLevel::Info, "Creating directory %s\n", saveFileName.c_str()); + std::filesystem::create_directory(saveFileName); } - const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / GlobalSetting::GlobalSaveFileName; + saveFileName = saveFileName / GlobalSetting::SavesPrefix; + + if (!std::filesystem::exists(saveFileName)) { + Log::write(Log::LogLevel::Info, "Creating directory %s\n", saveFileName.c_str()); + std::filesystem::create_directory(saveFileName); + } + + saveFileName = saveFileName / GlobalSetting::GlobalSaveFileName; if (!std::filesystem::exists(saveFileName)) { Log::write(Log::LogLevel::Info, "Creating global settings file %s\n", saveFileName.c_str()); @@ -55,4 +64,4 @@ void SettingsManager::saveSettings(SettingsManager::Settings settings) FileStream levelFileStream(saveFileName, std::ios::out | std::ios::binary); levelFileStream.writeVariable(&settingsConverter.bytes, sizeof(SettingsManager::Settings)); -} \ No newline at end of file +} diff --git a/src/class_10.cpp b/src/class_10.cpp index a454d49..25648ab 100644 --- a/src/class_10.cpp +++ b/src/class_10.cpp @@ -9,11 +9,6 @@ class_10::class_10() reset(); } -class_10::~class_10() -{ - // -} - void class_10::reset() { field_257 = field_259 = field_260 = 0; diff --git a/src/class_10.h b/src/class_10.h index 736d77b..396f5b5 100644 --- a/src/class_10.h +++ b/src/class_10.h @@ -14,6 +14,5 @@ class class_10 { std::vector> motoComponents = std::vector>(6); class_10(); - ~class_10(); void reset(); }; \ No newline at end of file diff --git a/src/lcdui/Canvas.cpp b/src/lcdui/Canvas.cpp index e5f5060..12772e5 100644 --- a/src/lcdui/Canvas.cpp +++ b/src/lcdui/Canvas.cpp @@ -6,10 +6,6 @@ Canvas::Canvas() graphics = std::make_unique(impl->getRenderer()); } -Canvas::~Canvas() -{ -} - int Canvas::getWidth() { return impl->getWidth(); diff --git a/src/lcdui/Canvas.h b/src/lcdui/Canvas.h index fbc3274..0e6a783 100644 --- a/src/lcdui/Canvas.h +++ b/src/lcdui/Canvas.h @@ -26,7 +26,6 @@ class Canvas : public Displayable { public: Canvas(); - ~Canvas(); bool isShown() override; int getWidth() override; int getHeight() override; diff --git a/src/lcdui/Command.cpp b/src/lcdui/Command.cpp index 3644665..29c790d 100644 --- a/src/lcdui/Command.cpp +++ b/src/lcdui/Command.cpp @@ -5,8 +5,4 @@ Command::Command(const std::string name, const Command::Type type, const int pri , type(type) , priority(priority) { -} - -Command::~Command() -{ } \ No newline at end of file diff --git a/src/lcdui/Command.h b/src/lcdui/Command.h index fafe54a..3fe78fb 100644 --- a/src/lcdui/Command.h +++ b/src/lcdui/Command.h @@ -41,7 +41,6 @@ class Command { }; Command(const std::string name, const Command::Type type, const int priority); - ~Command(); const std::string name; const Command::Type type; diff --git a/src/utils/Time.cpp b/src/utils/Time.cpp index 5b34818..af1086f 100644 --- a/src/utils/Time.cpp +++ b/src/utils/Time.cpp @@ -10,11 +10,11 @@ int64_t currentTimeMillis() std::chrono::system_clock::now().time_since_epoch()).count(); } -std::string timeToString(const int64_t time) +std::string timeToString(const uint64_t time) { - const int minutes = (int)(time / 100L / 60L); - const int seconds = (int)(time / 100L % 60L); - const int subseconds = (int)(time % 100L); + const uint32_t minutes = (uint32_t)(time / 100L / 60L); + const uint32_t seconds = (uint32_t)(time / 100L % 60L); + const uint32_t subseconds = (uint32_t)(time % 100L); std::stringstream ss; ss << std::setfill('0') @@ -26,7 +26,7 @@ std::string timeToString(const int64_t time) return ss.str(); } -void sleep(int64_t ms) +void sleep(const uint64_t ms) { SDL_Delay(ms); } diff --git a/src/utils/Time.h b/src/utils/Time.h index 9da5fa7..5bc4634 100644 --- a/src/utils/Time.h +++ b/src/utils/Time.h @@ -9,6 +9,6 @@ namespace Time { int64_t currentTimeMillis(); -std::string timeToString(const int64_t time); -void sleep(int64_t ms); +std::string timeToString(const uint64_t time); +void sleep(const uint64_t ms); }; \ No newline at end of file From 3062f175f5e83a8b45dd3ab96668902d85d35624 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sat, 16 Nov 2024 18:56:54 +0200 Subject: [PATCH 13/16] renamed variables in menu component, added font multiplier --- src/GameMenu.cpp | 62 ++++++++++++++++++------------------------- src/GameMenu.h | 13 ++++----- src/MenuManager.cpp | 29 +++----------------- src/MenuManager.h | 1 - src/RecordManager.cpp | 57 +++++++++++++++++++++++++++++---------- src/RecordManager.h | 3 ++- src/config.cpp | 1 + src/config.h | 1 + src/lcdui/Font.cpp | 8 +++--- src/lcdui/Font.h | 2 ++ 10 files changed, 87 insertions(+), 90 deletions(-) diff --git a/src/GameMenu.cpp b/src/GameMenu.cpp index 69783e0..6bae876 100644 --- a/src/GameMenu.cpp +++ b/src/GameMenu.cpp @@ -29,7 +29,7 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt TextRender::setDefaultFont(font3); TextRender::setMaxArea(canvasWidth, canvasHeight); - field_101 = 1; + menuOffsetY = 1; if (canvasWidth <= 100) { xPos = 6; @@ -41,23 +41,23 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt name = ""; } - field_104 = xPos + 7; - field_103 = 2; - field_110 = 0; + menuOffsetX = xPos + 7; + menuSpacing = 2; + selectedMenuItemTickSpriteNo = 0; if (name != "") { - field_107 = (canvasHeight - (field_101 << 1) - 10 - font->getBaselinePosition()) / (font2->getBaselinePosition() + field_103); + field_107 = (canvasHeight - (menuOffsetY << 1) - 10 - font->getBaselinePosition()) / (font2->getBaselinePosition() + menuSpacing); } else { - field_107 = (canvasHeight - (field_101 << 1) - 10) / (font2->getBaselinePosition() + field_103); + field_107 = (canvasHeight - (menuOffsetY << 1) - 10) / (font2->getBaselinePosition() + menuSpacing); } if (inputString) { - field_111 = true; + isTextInput = true; nameCursorPos = 0; xPos = 8; strArr = inputString; } else { - field_111 = false; + isTextInput = false; } if (field_107 > 13) { @@ -65,19 +65,9 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt } } -// void GameMenu::method_68(int var1) -// { -// field_103 = var1; -// } - -// void GameMenu::method_69(std::string var1) -// { -// name = var1; -// } - void GameMenu::method_70() { - if (field_111) { + if (isTextInput) { nameCursorPos = 0; } else { if (!vector.empty()) { @@ -126,7 +116,7 @@ void GameMenu::method_71() void GameMenu::addMenuElement(IGameMenuElement* var1) { - int var2 = field_101; + int var2 = menuOffsetY; field_107 = 1; vector.push_back(var1); @@ -142,12 +132,12 @@ void GameMenu::addMenuElement(IGameMenuElement* var1) for (int var3 = 0; var3 < static_cast(vector.size()) - 1; ++var3) { if (vector[var3]->isNotTextRender()) { - var2 += font2->getBaselinePosition() + field_103; + var2 += font2->getBaselinePosition() + menuSpacing; } else { - var2 += (TextRender::getBaselinePosition() < GameCanvas::spriteSizeY[5] ? GameCanvas::spriteSizeY[5] : TextRender::getBaselinePosition()) + field_103; + var2 += (TextRender::getBaselinePosition() < GameCanvas::spriteSizeY[5] ? GameCanvas::spriteSizeY[5] : TextRender::getBaselinePosition()) + menuSpacing; } - if (var2 > canvasHeight - (field_101 << 1) - 10) { + if (var2 > canvasHeight - (menuOffsetY << 1) - 10) { break; } @@ -163,7 +153,7 @@ void GameMenu::addMenuElement(IGameMenuElement* var1) void GameMenu::processGameActionDown() { - if (field_111) { + if (isTextInput) { if (strArr[nameCursorPos] == 32) { strArr[nameCursorPos] = 90; return; @@ -225,7 +215,7 @@ void GameMenu::processGameActionDown() void GameMenu::processGameActionUp() { - if (field_111) { + if (isTextInput) { if (strArr[nameCursorPos] == 32) { strArr[nameCursorPos] = 65; return; @@ -289,7 +279,7 @@ void GameMenu::processGameActionUp() void GameMenu::processGameActionUpd(int var1) { - if (field_111) { + if (isTextInput) { switch (var1) { case 1: if (nameCursorPos == 2) { @@ -335,12 +325,12 @@ void GameMenu::render_76(Graphics* graphics) int var2; int i; - if (field_111) { + if (isTextInput) { graphics->setColor(0, 0, 20); graphics->setFont(font); int8_t var7 = 1; graphics->drawString("Enter Name", xPos, var7, 20); - var2 = var7 + font->getHeight() + (field_103 << 2); + var2 = var7 + font->getHeight() + (menuSpacing << 2); graphics->setFont(font2); for (i = 0; i < 3; ++i) { @@ -353,7 +343,7 @@ void GameMenu::render_76(Graphics* graphics) } else { graphics->setColor(0, 0, 0); - var2 = field_101; + var2 = menuOffsetY; if (name != "") { graphics->setFont(font); @@ -376,25 +366,25 @@ void GameMenu::render_76(Graphics* graphics) for (i = field_105; i < field_106 + 1; ++i) { IGameMenuElement* var4 = vector[i]; graphics->setColor(0, 0, 0); - var4->render(graphics, var2, field_104); + var4->render(graphics, var2, menuOffsetX); if (i == field_95 && var4->isNotTextRender()) { int var5 = xPos - micro->gameCanvas->helmetSpriteWidth / 2; int var6 = var2 + font2->getBaselinePosition() / 2 - micro->gameCanvas->helmetSpriteHeight / 2; graphics->setClip(var5, var6, micro->gameCanvas->helmetSpriteWidth, micro->gameCanvas->helmetSpriteHeight); - graphics->drawImage(micro->gameCanvas->helmetImage.get(), var5 - micro->gameCanvas->helmetSpriteWidth * (field_110 % 6), var6 - micro->gameCanvas->helmetSpriteHeight * (field_110 / 6), 20); + graphics->drawImage(micro->gameCanvas->helmetImage.get(), var5 - micro->gameCanvas->helmetSpriteWidth * (selectedMenuItemTickSpriteNo % 6), var6 - micro->gameCanvas->helmetSpriteHeight * (selectedMenuItemTickSpriteNo / 6), 20); graphics->setClip(0, 0, canvasWidth, canvasHeight); - ++field_110; + ++selectedMenuItemTickSpriteNo; - if (field_110 > 30) { - field_110 = 0; + if (selectedMenuItemTickSpriteNo > 30) { + selectedMenuItemTickSpriteNo = 0; } } if (var4->isNotTextRender()) { - var2 += font2->getBaselinePosition() + field_103; + var2 += font2->getBaselinePosition() + menuSpacing; } else { - var2 += (TextRender::getBaselinePosition() < GameCanvas::spriteSizeY[5] ? GameCanvas::spriteSizeY[5] : TextRender::getBaselinePosition()) + field_103; + var2 += (TextRender::getBaselinePosition() < GameCanvas::spriteSizeY[5] ? GameCanvas::spriteSizeY[5] : TextRender::getBaselinePosition()) + menuSpacing; } } diff --git a/src/GameMenu.h b/src/GameMenu.h index 316ab38..e161122 100644 --- a/src/GameMenu.h +++ b/src/GameMenu.h @@ -20,16 +20,16 @@ class GameMenu { std::shared_ptr font; std::shared_ptr font2; std::shared_ptr font3; - int field_101; - int field_103; - int field_104; + int menuOffsetY; + int menuSpacing; + int menuOffsetX; int field_105; int field_106; int field_107; int canvasWidth; int canvasHeight; - int field_110; - bool field_111; + int selectedMenuItemTickSpriteNo; + bool isTextInput; int nameCursorPos; char* strArr; @@ -37,8 +37,6 @@ class GameMenu { int xPos; GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputString = nullptr); - // void method_68(int var1); - // void method_69(std::string var1); void method_70(); void method_71(); void addMenuElement(IGameMenuElement* var1); @@ -48,7 +46,6 @@ class GameMenu { void render_76(Graphics* graphics); void setGameMenu(GameMenu* gameMenu); GameMenu* getGameMenu(); - // int method_79(); void clearVector(); std::string makeString(); char* getStrArr() const; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 1dde2e5..f540bf1 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -272,7 +272,7 @@ void MenuManager::method_197() currentLevelFinished = false; gameMenuFinished->clearVector(); gameMenuFinished->addMenuElement(new TextRender("Time: " + trackTimeFormatted, micro)); - const std::array recordDescriptions = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); + const std::array recordDescriptions = recordManager->getRecordDescription(settingsStringLeague->getCurrentOptionPos()); for (uint8_t i = 0; i < recordDescriptions.size(); ++i) { if (recordDescriptions[i].empty()) { @@ -309,8 +309,8 @@ void MenuManager::method_197() } } - int var3 = getCountOfRecordStoresWithPrefix(settingStringLevel->getCurrentOptionPos()); - addTextRender(gameMenuFinished, var3 + " of " + std::to_string(micro->levelLoader->getTracksCount(settingStringLevel->getCurrentOptionPos())) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); + const uint32_t numberOfRecords = RecordManager::getNumberOfRecordsForLevel(settingStringLevel->getCurrentOptionPos()); + addTextRender(gameMenuFinished, std::to_string(numberOfRecords) + " of " + std::to_string(micro->levelLoader->getTracksCount(settingStringLevel->getCurrentOptionPos())) + " tracks in " + levelLabels[settingStringLevel->getCurrentOptionPos()] + " completed."); if (!currentLevelFinished) { field_333->setText("Restart: " + micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos())); @@ -626,7 +626,7 @@ void MenuManager::method_207(int var1) recordManager->loadRecordInfo(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()); gameMenuHighscore->addMenuElement(new TextRender(micro->levelLoader->getName(settingStringLevel->getCurrentOptionPos(), settingsStringTrack->getCurrentOptionPos()), micro)); gameMenuHighscore->addMenuElement(new TextRender("LEAGUE: " + settingsStringLeague->getOptionsList()[var1], micro)); - const std::array recordDescription = recordManager->getRecordDescription(var1); + const std::array recordDescription = recordManager->getRecordDescription(var1); for (uint8_t i = 0; i < recordDescription.size(); ++i) { if (recordDescription[i].empty()) { @@ -931,24 +931,3 @@ void MenuManager::addOkAndBackCommands() micro->gameCanvas->addCommand(commandOk); } - -int MenuManager::getCountOfRecordStoresWithPrefix(int prefixNumber) -{ - (void)prefixNumber; - // TODO: - // std::vector storeNames = RecordStore::listRecordStores(); - // if (recordManager != nullptr && !storeNames.empty()) { - // int count = 0; - - // for (std::size_t i = 0; i < storeNames.size(); ++i) { - // if (storeNames[i].find(std::to_string(prefixNumber), 0) == 0) { - // ++count; - // } - // } - - // return count; - // } else { - // return 0; - // } - return 0; -} diff --git a/src/MenuManager.h b/src/MenuManager.h index 2526800..7fdab36 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -96,7 +96,6 @@ class MenuManager : public IMenuManager { void method_197(); void fillCanvasWithImage(Graphics* graphics); void exit(); - int getCountOfRecordStoresWithPrefix(int prefixNumber); public: GameMenu* currentGameMenu; diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index c37b5ee..1ef6195 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -12,9 +12,9 @@ void RecordManager::loadRecordInfo(const uint8_t level, const uint8_t track) levelFileStream.readVariable(&recordsSaveDataConverter.bytes, false, sizeof(RecordsSaveData)); } -std::array RecordManager::getRecordDescription(const uint8_t league) const +std::array RecordManager::getRecordDescription(const uint8_t league) const { - std::array recordsDescription; + std::array recordsDescription; for (uint8_t i = 0; i < RECORD_NO_MAX; ++i) { const Record record = recordsSaveDataConverter.recordsSaveData.leagueRecords[league].records[i]; @@ -84,16 +84,45 @@ void RecordManager::addNewRecord(const uint8_t league, const char* playerName, c void RecordManager::deleteRecordStores() const { - // TODO: - // std::vector names = RecordStore::listRecordStores(); - - // for (std::size_t i = 0; i < names.size(); ++i) { - // if (names[i] != GlobalSetting::GlobalSaveFileName) { - // try { - // RecordStore::deleteRecordStore(names[i]); - // } catch (RecordStoreException& var3) { - // return; - // } - // } - // } + Log::write(Log::LogLevel::Info, "deleteRecordStores\n"); + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix; + + for (const auto& file : std::filesystem::directory_iterator(saveFileName)) { + const std::string filename = file.path().filename().string(); + Log::write(Log::LogLevel::Debug, "Found record %s\n", filename.c_str()); + + if (GlobalSetting::GlobalSaveFileName == filename) { + Log::write(Log::LogLevel::Debug, "Skipped deletion for %s\n", file.path().c_str()); + continue; + } + + std::filesystem::remove(file); + } } + +uint32_t RecordManager::getNumberOfRecordsForLevel(const uint8_t level) +{ + Log::write(Log::LogLevel::Info, "getNumberOfRecordsForLevel %d\n", level); + + const std::string prefix = std::to_string(level); + const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix; + + uint32_t count = 0; + + for (const auto& file : std::filesystem::directory_iterator(saveFileName)) { + const std::string filename = file.path().filename().string(); + Log::write(Log::LogLevel::Debug, "Found record %s\n", filename.c_str()); + + if (!file.is_regular_file()) { + Log::write(Log::LogLevel::Debug, "Skipped record %s\n", file.path().c_str()); + continue; + } + + if (filename.rfind(prefix, 0) == 0) { + Log::write(Log::LogLevel::Debug, "Included record %s\n", file.path().c_str()); + ++count; + } + } + + return count; +} \ No newline at end of file diff --git a/src/RecordManager.h b/src/RecordManager.h index 1847c4a..ae7c527 100644 --- a/src/RecordManager.h +++ b/src/RecordManager.h @@ -15,11 +15,12 @@ class RecordManager { public: void loadRecordInfo(const uint8_t level, const uint8_t track); - std::array getRecordDescription(const uint8_t league) const; + std::array getRecordDescription(const uint8_t league) const; uint8_t getPosOfNewRecord(const uint8_t league, const uint64_t timeMs) const; void writeRecordInfo(const uint8_t level, const uint8_t track); void addNewRecord(const uint8_t league, const char* playerName, const uint64_t timeMs); void deleteRecordStores() const; + static uint32_t getNumberOfRecordsForLevel(const uint8_t level); private: struct Record { diff --git a/src/config.cpp b/src/config.cpp index 226077b..0614c53 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -3,6 +3,7 @@ bool GlobalSetting::WindowFullscreen = false; uint8_t GlobalSetting::LogoMultiplier = 3; uint8_t GlobalSetting::SplashMultiplier = 3; +uint8_t GlobalSetting::FontMultiplier = 4; uint8_t GlobalSetting::TimerFpsTextOffset = 14; uint8_t GlobalSetting::LoadingBarPadding = 2; uint8_t GlobalSetting::BarScreenOffset = 2; diff --git a/src/config.h b/src/config.h index 90426f2..cdf3505 100644 --- a/src/config.h +++ b/src/config.h @@ -66,6 +66,7 @@ struct GlobalSetting { static bool WindowFullscreen; static uint8_t LogoMultiplier; static uint8_t SplashMultiplier; + static uint8_t FontMultiplier; static uint8_t TimerFpsTextOffset; static uint8_t LoadingBarPadding; static uint8_t BarScreenOffset; diff --git a/src/lcdui/Font.cpp b/src/lcdui/Font.cpp index 547c4ee..29f4f43 100644 --- a/src/lcdui/Font.cpp +++ b/src/lcdui/Font.cpp @@ -1,7 +1,5 @@ #include "Font.h" -#include - CMRC_DECLARE(assets); Font::Font(FontStyle style, FontSize pointSize) @@ -66,11 +64,11 @@ int Font::getRealFontSize(FontSize size) { switch (size) { case SIZE_LARGE: - return 32; + return 8 * GlobalSetting::FontMultiplier; case SIZE_MEDIUM: - return 16; + return 4 * GlobalSetting::FontMultiplier; case SIZE_SMALL: - return 12; + return 3 * GlobalSetting::FontMultiplier; default: throw std::runtime_error("unknown font size: " + std::to_string(size)); } diff --git a/src/lcdui/Font.h b/src/lcdui/Font.h index 8d138ba..4ccb52a 100644 --- a/src/lcdui/Font.h +++ b/src/lcdui/Font.h @@ -3,8 +3,10 @@ #include #include #include +#include #include +#include "../config.h" class Font { public: From 8f77d0b28b23335f2f3375bd25c01f5d8cef1aed Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sun, 17 Nov 2024 12:33:02 +0200 Subject: [PATCH 14/16] added more command line arguments + refactor --- src/GameCanvas.cpp | 102 ++++++++++++++++++------------ src/GameCanvas.h | 6 +- src/GameMenu.cpp | 46 ++++++++++---- src/LevelLoader.cpp | 2 +- src/MRGLoader.cpp | 4 +- src/MenuManager.cpp | 10 ++- src/MenuManager.h | 2 +- src/RecordManager.cpp | 12 ++-- src/SettingsManager.cpp | 4 +- src/SettingsStringRender.cpp | 26 ++++++-- src/TextRender.cpp | 7 +- src/TimerOrMotoPartOrMenuElem.cpp | 6 +- src/config.cpp | 5 +- src/config.h | 1 + src/lcdui/Graphics.h | 4 +- src/main.cpp | 72 ++++++++++++++------- src/utils/Log.cpp | 5 +- 17 files changed, 205 insertions(+), 109 deletions(-) diff --git a/src/GameCanvas.cpp b/src/GameCanvas.cpp index 4c20537..ee70698 100644 --- a/src/GameCanvas.cpp +++ b/src/GameCanvas.cpp @@ -29,7 +29,11 @@ void GameCanvas::drawSprite(Graphics* g, int spriteNo, int x, int y) { if (spritesImage) { g->setClip(x, y, spriteSizeX[spriteNo], spriteSizeY[spriteNo]); - g->drawImage(spritesImage.get(), x - spriteOffsetX[spriteNo], y - spriteOffsetY[spriteNo], 20); + g->drawImage( + spritesImage.get(), + x - spriteOffsetX[spriteNo], + y - spriteOffsetY[spriteNo], + Graphics::TOP | Graphics::LEFT); g->setClip(0, 0, getWidth(), getHeight()); } } @@ -162,7 +166,11 @@ void GameCanvas::renderBodyPart(int x1F16, int y1F16, int x2F16, int y2F16, int x -= bodyPartsSpriteWidth[bodyPartNo] / 2; y -= bodyPartsSpriteHeight[bodyPartNo] / 2; graphics->setClip(x, y, bodyPartsSpriteWidth[bodyPartNo], bodyPartsSpriteHeight[bodyPartNo]); - graphics->drawImage(bodyPartsImages[bodyPartNo].get(), x - bodyPartsSpriteWidth[bodyPartNo] * (spriteNo % 6), y - bodyPartsSpriteHeight[bodyPartNo] * (spriteNo / 6), 20); + graphics->drawImage( + bodyPartsImages[bodyPartNo].get(), + x - bodyPartsSpriteWidth[bodyPartNo] * (spriteNo % 6), + y - bodyPartsSpriteHeight[bodyPartNo] * (spriteNo / 6), + Graphics::TOP | Graphics::LEFT); graphics->setClip(0, 0, width, getHeight()); } } @@ -209,7 +217,11 @@ void GameCanvas::drawHelmet(int x, int y, int angleF16) int var5 = addDx(x) - helmetSpriteWidth / 2; int var6 = addDy(y) - helmetSpriteHeight / 2; graphics->setClip(var5, var6, helmetSpriteWidth, helmetSpriteHeight); - graphics->drawImage(helmetImage.get(), var5 - helmetSpriteWidth * (var4 % 6), var6 - helmetSpriteHeight * (var4 / 6), 20); + graphics->drawImage( + helmetImage.get(), + var5 - helmetSpriteWidth * (var4 % 6), + var6 - helmetSpriteHeight * (var4 / 6), + Graphics::TOP | Graphics::LEFT); graphics->setClip(0, 0, width, getHeight()); } } @@ -218,7 +230,11 @@ void GameCanvas::drawTime(uint64_t time10Ms) { const std::string timeStr = Time::timeToString(time10Ms); setColor(0, 0, 0); - graphics->drawString(timeStr, width - defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 40); + graphics->drawString( + timeStr, + width - defaultFontWidth00, + height2 - GlobalSetting::TimerFpsTextOffset, + Graphics::BOTTOM | Graphics::RIGHT); } void GameCanvas::method_150(int var1) @@ -297,7 +313,11 @@ void GameCanvas::renderEngine(int x, int y, int angleF16) int centerY = addDy(y) - engineSpriteHeight / 2; if (engineImage != nullptr) { graphics->setClip(centerX, centerY, engineSpriteWidth, engineSpriteHeight); - graphics->drawImage(engineImage.get(), centerX - engineSpriteWidth * (spriteNo % 6), centerY - engineSpriteHeight * (spriteNo / 6), 20); + graphics->drawImage( + engineImage.get(), + centerX - engineSpriteWidth * (spriteNo % 6), + centerY - engineSpriteHeight * (spriteNo / 6), + Graphics::TOP | Graphics::LEFT); graphics->setClip(0, 0, width, getHeight()); } } @@ -309,7 +329,11 @@ void GameCanvas::renderFender(int x, int y, int angleF16) int centerX = addDx(x) - fenderSpriteWidth / 2; int centerY = addDy(y) - fenderSpriteHeight / 2; graphics->setClip(centerX, centerY, fenderSpriteWidth, fenderSpriteHeight); - graphics->drawImage(fenderImage.get(), centerX - fenderSpriteWidth * (spriteNo % 6), centerY - fenderSpriteHeight * (spriteNo / 6), 20); + graphics->drawImage( + fenderImage.get(), + centerX - fenderSpriteWidth * (spriteNo % 6), + centerY - fenderSpriteHeight * (spriteNo / 6), + Graphics::TOP | Graphics::LEFT); graphics->setClip(0, 0, width, getHeight()); } } @@ -360,7 +384,7 @@ void GameCanvas::drawGame(Graphics* g) getHeight() / 2, logoImage->getWidth() * GlobalSetting::LogoMultiplier, logoImage->getHeight() * GlobalSetting::LogoMultiplier, - 3); + Graphics::HCENTER | Graphics::VCENTER); drawSprite(graphics, 16, getWidth() - spriteSizeX[16] - 5, getHeight() - spriteSizeY[16] - 7); drawSprite(graphics, 17, getWidth() - spriteSizeX[17] - 4, getHeight() - spriteSizeY[17] - spriteSizeY[16] - 9); } @@ -375,7 +399,7 @@ void GameCanvas::drawGame(Graphics* g) getHeight() / 2, splashImage->getWidth() * GlobalSetting::SplashMultiplier, splashImage->getHeight() * GlobalSetting::SplashMultiplier, - 3); + Graphics::HCENTER | Graphics::VCENTER); } } @@ -397,9 +421,17 @@ void GameCanvas::drawGame(Graphics* g) setColor(0, 0, 0); graphics->setFont(font); if (height2 <= 128) { - graphics->drawString(timerMessage, width / 2, 1, 17); + graphics->drawString( + timerMessage, + width / 2, + 1, + Graphics::TOP | Graphics::HCENTER); } else { - graphics->drawString(timerMessage, width / 2, height2 / 4, 33); + graphics->drawString( + timerMessage, + width / 2, + height2 / 4, + Graphics::BOTTOM | Graphics::HCENTER); } if (timerTriggered) { @@ -408,10 +440,15 @@ void GameCanvas::drawGame(Graphics* g) } } - // print fps to screen - setColor(0, 0, 0); - graphics->setFont(font); - graphics->drawString("FPS: " + std::to_string(fps), defaultFontWidth00, height2 - GlobalSetting::TimerFpsTextOffset, 36); + if (GlobalSetting::ShowFPS) { + setColor(0, 0, 0); + graphics->setFont(font); + graphics->drawString( + "FPS: " + std::to_string(fps), + defaultFontWidth00, + height2 - GlobalSetting::TimerFpsTextOffset, + Graphics::BOTTOM | Graphics::LEFT); + } var3 = gamePhysics->method_52(); drawProgressBar(var3, false); @@ -449,13 +486,16 @@ void GameCanvas::drawProgressBar(int var1, bool mode) void GameCanvas::paint(Graphics* graphics) { static int64_t time = 0; - int64_t now = Time::currentTimeMillis(); - int64_t delta = now - time; - time = now; - if (delta != 0) { - fps = 1000 / delta; - // std::cout << "FPS: " << fps << std::endl; - // setWindowTitle(std::string("Gravity Defied. FPS: ") + std::to_string(fps)); + + if (GlobalSetting::ShowFPS) { + const int64_t now = Time::currentTimeMillis(); + const int64_t delta = now - time; + time = now; + + if (delta != 0) { + fps = 1000 / delta; + // setWindowTitle(std::string("Gravity Defied. FPS: ") + std::to_string(fps)); + } } processTimers(); // We need to call this function as often as we can. It might be better to move this call somewhere. @@ -478,24 +518,8 @@ void GameCanvas::resetActions() void GameCanvas::handleUpdatedInput() { - int verticalMovement = 0; // var1 - int horizontalMovement = 0; // var2 - // int var3 = field_232; - - // int var4; - // for (var4 = 0; var4 < 10; ++var4) { - // if (activeKeys[var4]) { - // var1 += field_231[var3][var4][0]; - // var2 += field_231[var3][var4][1]; - // } - // } - - // for (var4 = 0; var4 < 7; ++var4) { - // if (activeActions[var4]) { - // var1 += field_230[var4][0]; - // var2 += field_230[var4][1]; - // } - // } + int verticalMovement = 0; + int horizontalMovement = 0; for (const auto& [action, isActive] : activeActions) { if (!isActive) { diff --git a/src/GameCanvas.h b/src/GameCanvas.h index e71b015..edd7163 100644 --- a/src/GameCanvas.h +++ b/src/GameCanvas.h @@ -68,14 +68,10 @@ class GameCanvas : public Canvas, public CommandListener { inline static int field_226 = 0; const int startFlagAnimationTimeToSpriteNo[4] = { 12, 10, 11, 10 }; const int finishFlagAnumationTimeToSpriteNo[4] = { 14, 13, 15, 13 }; - // int field_230[7][2] = { { 0, 0 }, { 1, 0 }, { 0, -1 }, { 0, 0 }, { 0, 0 }, { 0, 1 }, { -1, 0 } }; - // int field_231[3][10][2] = { { { 0, 0 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, -1 }, { -1, 0 }, { 0, 1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } }, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 0, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }, { -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } } }; - // int field_232 = 2; - // std::vector activeActions = std::vector(7); std::vector activeKeys = std::vector(10); std::map activeActions = std::map(); - int fps; + uint16_t fps; public: GameCanvas(Micro* micro); diff --git a/src/GameMenu.cpp b/src/GameMenu.cpp index 6bae876..82d86ab 100644 --- a/src/GameMenu.cpp +++ b/src/GameMenu.cpp @@ -329,15 +329,27 @@ void GameMenu::render_76(Graphics* graphics) graphics->setColor(0, 0, 20); graphics->setFont(font); int8_t var7 = 1; - graphics->drawString("Enter Name", xPos, var7, 20); + graphics->drawString( + "Enter Name", + xPos, + var7, + Graphics::TOP | Graphics::LEFT); var2 = var7 + font->getHeight() + (menuSpacing << 2); graphics->setFont(font2); for (i = 0; i < 3; ++i) { - graphics->drawChar((char)strArr[i], xPos + i * font2->charWidth('W') + 1, var2, 17); + graphics->drawChar( + (char)strArr[i], + xPos + i * font2->charWidth('W') + 1, + var2, + Graphics::TOP | Graphics::HCENTER); if (i == nameCursorPos) { - graphics->drawChar('^', xPos + i * font2->charWidth('W') + 1, var2 + font2->getHeight(), 17); + graphics->drawChar( + '^', + xPos + i * font2->charWidth('W') + 1, + var2 + font2->getHeight(), + Graphics::TOP | Graphics::HCENTER); } } @@ -347,7 +359,11 @@ void GameMenu::render_76(Graphics* graphics) if (name != "") { graphics->setFont(font); - graphics->drawString(name, xPos, var2, 20); + graphics->drawString( + name, + xPos, + var2, + Graphics::TOP | Graphics::LEFT); var2 += font->getBaselinePosition() + 2; } @@ -368,11 +384,20 @@ void GameMenu::render_76(Graphics* graphics) graphics->setColor(0, 0, 0); var4->render(graphics, var2, menuOffsetX); + // TODO: field_95 - selected menu items idx ?? if (i == field_95 && var4->isNotTextRender()) { - int var5 = xPos - micro->gameCanvas->helmetSpriteWidth / 2; - int var6 = var2 + font2->getBaselinePosition() / 2 - micro->gameCanvas->helmetSpriteHeight / 2; - graphics->setClip(var5, var6, micro->gameCanvas->helmetSpriteWidth, micro->gameCanvas->helmetSpriteHeight); - graphics->drawImage(micro->gameCanvas->helmetImage.get(), var5 - micro->gameCanvas->helmetSpriteWidth * (selectedMenuItemTickSpriteNo % 6), var6 - micro->gameCanvas->helmetSpriteHeight * (selectedMenuItemTickSpriteNo / 6), 20); + const int selectedMenuItemTickX = xPos - micro->gameCanvas->helmetSpriteWidth / 2; + const int selectedMenuItemTickY = var2 + font2->getBaselinePosition() / 2; // - micro->gameCanvas->helmetSpriteHeight / 2; + graphics->setClip( + selectedMenuItemTickX, + selectedMenuItemTickY, + micro->gameCanvas->helmetSpriteWidth, + micro->gameCanvas->helmetSpriteHeight); + graphics->drawImage( + micro->gameCanvas->helmetImage.get(), + selectedMenuItemTickX - micro->gameCanvas->helmetSpriteWidth * (selectedMenuItemTickSpriteNo % 6), + selectedMenuItemTickY - micro->gameCanvas->helmetSpriteHeight * (selectedMenuItemTickSpriteNo / 6), + Graphics::TOP | Graphics::LEFT); graphics->setClip(0, 0, canvasWidth, canvasHeight); ++selectedMenuItemTickSpriteNo; @@ -409,11 +434,6 @@ GameMenu* GameMenu::getGameMenu() return gameMenu; } -// int GameMenu::method_79() -// { -// return field_95; -// } - void GameMenu::clearVector() { vector.clear(); diff --git a/src/LevelLoader.cpp b/src/LevelLoader.cpp index a849462..f70c490 100644 --- a/src/LevelLoader.cpp +++ b/src/LevelLoader.cpp @@ -62,7 +62,7 @@ void LevelLoader::loadNextTrack() int LevelLoader::loadTrack(const int level, const int track) { - Log::write(Log::LogLevel::Info, "loadTrack %d %d\n", level, track); + Log::write(Log::LogLevel::Debug, "loadTrack %d %d\n", level, track); loadedLevel = level; loadedTrack = track; diff --git a/src/MRGLoader.cpp b/src/MRGLoader.cpp index 68432b1..61bd909 100644 --- a/src/MRGLoader.cpp +++ b/src/MRGLoader.cpp @@ -22,10 +22,10 @@ static MRGLoader::LevelTracks loadLevel(FileStream& levelFileStream, const uint8 levelTracks.tracks.push_back(track); } - Log::write(Log::LogLevel::Info, "Level %d, Tracks %d\n", level, levelTracks.tracksCount); + Log::write(Log::LogLevel::Debug, "Level %d, Tracks %d\n", level, levelTracks.tracksCount); for (auto& i : levelTracks.tracks) { - Log::write(Log::LogLevel::Info, "%d %s\n", i.offset, i.trackName.c_str()); + Log::write(Log::LogLevel::Debug, "%d %s\n", i.offset, i.trackName.c_str()); } return levelTracks; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index f540bf1..9da7575 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -10,7 +10,7 @@ void MenuManager::initPart(int var1) { switch (var1) { case 1: { - recordManager = new RecordManager(); + recordManager = std::make_unique(); trackTimeMs = 0; trackTimeFormatted.clear(); @@ -500,7 +500,11 @@ void MenuManager::fillCanvasWithImage(Graphics* graphics) { for (int y = 0; y < getCanvasHeight(); y += rasterImage->getHeight()) { for (int x = 0; x < getCanvasWidth(); x += rasterImage->getWidth()) { - graphics->drawImage(rasterImage.get(), x, y, 20); + graphics->drawImage( + rasterImage.get(), + x, + y, + Graphics::TOP | Graphics::LEFT); } } } @@ -666,7 +670,7 @@ void MenuManager::method_208() // settings.availableEasyTracks = (int8_t)availableTracks[0]; // settings.availableMediumTracks = (int8_t)availableTracks[1]; // settings.availableHardTracks = (int8_t)availableTracks[2]; - settings.selectedLevel = (int8_t)settingStringLevel->getMaxAvailableOptionPos(); + settings.selectedLevel = (int8_t)settingStringLevel->getCurrentOptionPos(); settings.selectedTrack = (int8_t)settingsStringTrack->getCurrentOptionPos(); settings.selectedLeague = (int8_t)settingsStringLeague->getCurrentOptionPos(); settings.unknown2 = -127; diff --git a/src/MenuManager.h b/src/MenuManager.h index 7fdab36..c5fc460 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -21,7 +21,7 @@ class MenuManager : public IMenuManager { SettingsManager::Settings settings; Micro* micro; - RecordManager* recordManager; + std::unique_ptr recordManager; Command* commandOk; Command* commandBack; GameMenu* gameMenuMain; diff --git a/src/RecordManager.cpp b/src/RecordManager.cpp index 1ef6195..0a5b93a 100644 --- a/src/RecordManager.cpp +++ b/src/RecordManager.cpp @@ -6,7 +6,7 @@ void RecordManager::loadRecordInfo(const uint8_t level, const uint8_t track) const std::string trackSaveName = std::to_string(level) + std::to_string(track) + ".dat"; const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / trackSaveName; - Log::write(Log::LogLevel::Info, "loadRecordInfo %s\n", saveFileName.c_str()); + Log::write(Log::LogLevel::Debug, "loadRecordInfo %s\n", saveFileName.c_str()); FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); levelFileStream.readVariable(&recordsSaveDataConverter.bytes, false, sizeof(RecordsSaveData)); @@ -37,7 +37,7 @@ void RecordManager::writeRecordInfo(const uint8_t level, const uint8_t track) { const std::string trackSaveName = std::to_string(level) + std::to_string(track) + ".dat"; const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / trackSaveName; - Log::write(Log::LogLevel::Info, "writeRecordInfo %s\n", saveFileName.c_str()); + Log::write(Log::LogLevel::Debug, "writeRecordInfo %s\n", saveFileName.c_str()); FileStream levelFileStream(saveFileName, std::ios::out | std::ios::binary); levelFileStream.writeVariable(&recordsSaveDataConverter.bytes, sizeof(RecordsSaveData)); @@ -58,9 +58,9 @@ uint8_t RecordManager::getPosOfNewRecord(const uint8_t league, const uint64_t ti void RecordManager::addNewRecord(const uint8_t league, const char* playerName, const uint64_t timeMs) { - Log::write(Log::LogLevel::Info, "addNewRecord %d %s %d\n", (int)league, playerName, timeMs); + Log::write(Log::LogLevel::Debug, "addNewRecord %d %s %d\n", (int)league, playerName, timeMs); const uint8_t newRecordPos = getPosOfNewRecord(league, timeMs); - Log::write(Log::LogLevel::Info, "Record pos %d\n", (int)newRecordPos); + Log::write(Log::LogLevel::Debug, "Record pos %d\n", (int)newRecordPos); if (newRecordPos >= 3) { // out of scope, we save only first 3 records @@ -84,7 +84,7 @@ void RecordManager::addNewRecord(const uint8_t league, const char* playerName, c void RecordManager::deleteRecordStores() const { - Log::write(Log::LogLevel::Info, "deleteRecordStores\n"); + Log::write(Log::LogLevel::Debug, "deleteRecordStores\n"); const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix; for (const auto& file : std::filesystem::directory_iterator(saveFileName)) { @@ -102,7 +102,7 @@ void RecordManager::deleteRecordStores() const uint32_t RecordManager::getNumberOfRecordsForLevel(const uint8_t level) { - Log::write(Log::LogLevel::Info, "getNumberOfRecordsForLevel %d\n", level); + Log::write(Log::LogLevel::Debug, "getNumberOfRecordsForLevel %d\n", level); const std::string prefix = std::to_string(level); const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix; diff --git a/src/SettingsManager.cpp b/src/SettingsManager.cpp index 5b79af2..ea55a86 100644 --- a/src/SettingsManager.cpp +++ b/src/SettingsManager.cpp @@ -45,7 +45,7 @@ void SettingsManager::initSettings() SettingsManager::Settings SettingsManager::loadSettings() { const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / GlobalSetting::GlobalSaveFileName; - Log::write(Log::LogLevel::Info, "loadSettings %s\n", saveFileName.c_str()); + Log::write(Log::LogLevel::Debug, "loadSettings %s\n", saveFileName.c_str()); FileStream levelFileStream(saveFileName, std::ios::in | std::ios::binary); @@ -58,7 +58,7 @@ SettingsManager::Settings SettingsManager::loadSettings() void SettingsManager::saveSettings(SettingsManager::Settings settings) { const std::filesystem::path saveFileName = GlobalSetting::SavesPath / GlobalSetting::SavesPrefix / GlobalSetting::GlobalSaveFileName; - Log::write(Log::LogLevel::Info, "saveSettings %s\n", saveFileName.c_str()); + Log::write(Log::LogLevel::Debug, "saveSettings %s\n", saveFileName.c_str()); SettingsManager::SettingsConverter settingsConverter = { .settings = settings }; diff --git a/src/SettingsStringRender.cpp b/src/SettingsStringRender.cpp index 9962e23..338fae4 100644 --- a/src/SettingsStringRender.cpp +++ b/src/SettingsStringRender.cpp @@ -180,9 +180,18 @@ void SettingsStringRender::render(Graphics* graphics, int y, int x) { if (useColon) { if (!hasSprite) { - graphics->drawString(text, x, y, 20); + graphics->drawString( + text, + x, + y, + Graphics::TOP | Graphics::LEFT); } else { - graphics->drawString(text, x + GameCanvas::spriteSizeX[8] + 3, y, 20); + graphics->drawString( + text, + x + GameCanvas::spriteSizeX[8] + 3, + y, + Graphics::TOP | Graphics::LEFT); + if (isDrawSprite8) { micro->gameCanvas->drawSprite(graphics, 8, x, y - GameCanvas::spriteSizeY[8] / 2 + graphics->getFont()->getHeight() / 2); } else { @@ -190,15 +199,24 @@ void SettingsStringRender::render(Graphics* graphics, int y, int x) } } } else { - graphics->drawString(text, x, y, 20); + graphics->drawString( + text, + x, + y, + Graphics::TOP | Graphics::LEFT); int shiftedX = x + graphics->getFont()->stringWidth(text); + if (currentOptionPos > maxAvailableOption && !field_146) { micro->gameCanvas->drawSprite(graphics, 8, shiftedX + 1, y - GameCanvas::spriteSizeY[8] / 2 + graphics->getFont()->getHeight() / 2); shiftedX += GameCanvas::spriteSizeX[9] + 1; } shiftedX += 2; - graphics->drawString(selectedOptionName, shiftedX, y, 20); + graphics->drawString( + selectedOptionName, + shiftedX, + y, + Graphics::TOP | Graphics::LEFT); } } diff --git a/src/TextRender.cpp b/src/TextRender.cpp index a4a8a87..783ee02 100644 --- a/src/TextRender.cpp +++ b/src/TextRender.cpp @@ -58,7 +58,12 @@ void TextRender::render(Graphics* graphics, int y, int x) graphics->setFont(font); } - graphics->drawString(text, x + dx, y, 20); + graphics->drawString( + text, + x + dx, + y, + Graphics::TOP | Graphics::LEFT); + if (isDrawSprite) { micro->gameCanvas->drawSprite(graphics, spriteNo, x, y); } diff --git a/src/TimerOrMotoPartOrMenuElem.cpp b/src/TimerOrMotoPartOrMenuElem.cpp index 48e4c68..a774efd 100644 --- a/src/TimerOrMotoPartOrMenuElem.cpp +++ b/src/TimerOrMotoPartOrMenuElem.cpp @@ -65,5 +65,9 @@ void TimerOrMotoPartOrMenuElem::setGameMenu(GameMenu* gameMenu) void TimerOrMotoPartOrMenuElem::render(Graphics* graphics, int y, int x) { - graphics->drawString(text, x, y, 20); + graphics->drawString( + text, + x, + y, + Graphics::TOP | Graphics::LEFT); } \ No newline at end of file diff --git a/src/config.cpp b/src/config.cpp index 0614c53..2fca34f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,8 +1,9 @@ #include "config.h" bool GlobalSetting::WindowFullscreen = false; -uint8_t GlobalSetting::LogoMultiplier = 3; -uint8_t GlobalSetting::SplashMultiplier = 3; +bool GlobalSetting::ShowFPS = false; +uint8_t GlobalSetting::LogoMultiplier = 1; +uint8_t GlobalSetting::SplashMultiplier = 1; uint8_t GlobalSetting::FontMultiplier = 4; uint8_t GlobalSetting::TimerFpsTextOffset = 14; uint8_t GlobalSetting::LoadingBarPadding = 2; diff --git a/src/config.h b/src/config.h index cdf3505..a780544 100644 --- a/src/config.h +++ b/src/config.h @@ -64,6 +64,7 @@ const char defaultName[] = "AAA"; struct GlobalSetting { static bool WindowFullscreen; + static bool ShowFPS; static uint8_t LogoMultiplier; static uint8_t SplashMultiplier; static uint8_t FontMultiplier; diff --git a/src/lcdui/Graphics.h b/src/lcdui/Graphics.h index 1862cb7..44586f5 100644 --- a/src/lcdui/Graphics.h +++ b/src/lcdui/Graphics.h @@ -22,6 +22,8 @@ class Graphics { SDL_Color currentColor; // void _ellipse(int cx, int cy, int xradius, int yradius); void _putpixel(int x, int y); + static int getAnchorX(int x, int size, int anchor); + static int getAnchorY(int y, int size, int anchor); public: enum Anchors { @@ -46,6 +48,4 @@ class Graphics { void drawLine(int x1, int y1, int x2, int y2); void drawImage(Image* const image, int x, int y, int anchor); void drawImage(Image* const image, int x, int y, int w, int h, int anchor); - static int getAnchorX(int x, int size, int anchor); - static int getAnchorY(int y, int size, int anchor); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ff9f862..a565c33 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,12 +10,17 @@ void showHelp(const char* progName) { - Log::write(Log::LogLevel::None, "Usage %s [options]\n", progName); - Log::write(Log::LogLevel::None, " -f, --fullscreen Enable fullscreen\n", progName); - Log::write(Log::LogLevel::None, " -w, --width INT Set screen width in px\n", progName); - Log::write(Log::LogLevel::None, " -h, --height INT Set screen height in px\n", progName); - Log::write(Log::LogLevel::None, " -?, --help Show this help screen\n", progName); - Log::write(Log::LogLevel::None, " -v, --verbose INT Set log level (0-6)\n", progName); + Log::write(Log::LogLevel::None, R"usage( +Usage %s [options] + -f, --fullscreen Enable fullscreen + --fps Show FPS + --width INT Set screen width in px (default: 640) + --height INT Set screen height in px (default: 480) + -h, --help Show this help screen + -v, --verbose INT Set log level [0-6] (default: 2) + --font-mult Set font multiplier (default: 4) + --logo-mult Set logo multiplier (default: 1) +)usage", progName); } bool parseArguments(int argc, char** argv) @@ -23,34 +28,55 @@ bool parseArguments(int argc, char** argv) int opt; static struct option long_options[] = { { "fullscreen", no_argument, nullptr, 'f' }, - { "width", optional_argument, nullptr, 'w' }, - { "height", optional_argument, nullptr, 'h' }, { "verbose", optional_argument, nullptr, 'v' }, - { "help", no_argument, nullptr, '?' }, + { "help", no_argument, nullptr, 'h' }, + { "width", required_argument, nullptr, 0 }, + { "height", required_argument, nullptr, 0 }, + { "fps", no_argument, nullptr, 0 }, + { "font-mult", required_argument, nullptr, 0 }, + { "logo-mult", required_argument, nullptr, 0 }, { nullptr, 0, nullptr, 0 } }; - Log::logLevel = Log::LogLevel::All; + int option_index = 0; + Log::logLevel = Log::LogLevel::Info; - while ((opt = getopt_long(argc, argv, "fhw:v:?", long_options, nullptr)) != -1) { + while ((opt = getopt_long(argc, argv, "fhv:", long_options, &option_index)) != -1) { switch (opt) { + case 0: { + if (long_options[option_index].flag != 0) + break; + + Log::write(Log::LogLevel::Debug, "Got parameter %d %s %s\n", option_index, long_options[option_index].name, optarg); + + if (strncmp(long_options[option_index].name, "fps", 3) == 0) { + GlobalSetting::ShowFPS = true; + Log::write(Log::LogLevel::None, "Showing FPS\n"); + } else if (strncmp(long_options[option_index].name, "width", 5) == 0) { + GlobalSetting::DefaultScreenWidth = atoi(optarg); + Log::write(Log::LogLevel::None, "Setting width %d\n", GlobalSetting::DefaultScreenWidth); + } else if (strncmp(long_options[option_index].name, "height", 6) == 0) { + GlobalSetting::DefaultScreenHeight = atoi(optarg); + Log::write(Log::LogLevel::None, "Setting height %d\n", GlobalSetting::DefaultScreenHeight); + } else if (strncmp(long_options[option_index].name, "font-mult", 9) == 0) { + GlobalSetting::FontMultiplier = atoi(optarg); + Log::write(Log::LogLevel::None, "Setting font multiplier to %d\n", GlobalSetting::FontMultiplier); + } else if (strncmp(long_options[option_index].name, "logo-mult", 9) == 0) { + const int value = atoi(optarg); + GlobalSetting::LogoMultiplier = value; + GlobalSetting::SplashMultiplier = value; + Log::write(Log::LogLevel::None, "Setting logo multiplier to %d\n", GlobalSetting::LogoMultiplier); + } + + break; + } case 'f': { Log::write(Log::LogLevel::None, "Setting fullscreen\n"); GlobalSetting::WindowFullscreen = true; break; } - case 'w': { - GlobalSetting::DefaultScreenWidth = atoi(optarg); - Log::write(Log::LogLevel::None, "Setting width %d\n", GlobalSetting::DefaultScreenWidth); - break; - } - case 'h': { - GlobalSetting::DefaultScreenHeight = atoi(optarg); - Log::write(Log::LogLevel::None, "Setting height %d\n", GlobalSetting::DefaultScreenHeight); - break; - } case 'v': { - uint logLevelFromArg = 6 - atoi(optarg); + const uint logLevelFromArg = 6 - atoi(optarg); if (logLevelFromArg > static_cast(Log::LogLevel::None)) { Log::logLevel = Log::LogLevel::All; @@ -61,7 +87,7 @@ bool parseArguments(int argc, char** argv) Log::write(Log::LogLevel::None, "Setting logs verbosity to %u\n", Log::logLevel); break; } - case '?': + case 'h': default: { showHelp(argv[0]); return false; diff --git a/src/utils/Log.cpp b/src/utils/Log.cpp index 187fc06..035591c 100644 --- a/src/utils/Log.cpp +++ b/src/utils/Log.cpp @@ -12,7 +12,4 @@ void Log::write(const Log::LogLevel level, const char* szFormat, ...) va_start(args, szFormat); vprintf(szFormat, args); va_end(args); -} - - - +} \ No newline at end of file From 281015fc85d85fd85a5c9d47e82e4239eca4a1bf Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sun, 17 Nov 2024 17:34:32 +0200 Subject: [PATCH 15/16] refactored menu object --- src/GameMenu.cpp | 320 +++++++++++++++++--------------------------- src/GameMenu.h | 23 ++-- src/MenuManager.cpp | 10 +- 3 files changed, 145 insertions(+), 208 deletions(-) diff --git a/src/GameMenu.cpp b/src/GameMenu.cpp index 82d86ab..6140b09 100644 --- a/src/GameMenu.cpp +++ b/src/GameMenu.cpp @@ -11,8 +11,8 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputString) { + clearVector(); name = var1; - field_95 = -1; this->micro = micro; gameMenu = var3; canvasWidth = micro->gameCanvas->getWidth(); @@ -31,25 +31,12 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt TextRender::setMaxArea(canvasWidth, canvasHeight); menuOffsetY = 1; - if (canvasWidth <= 100) { - xPos = 6; - } else { - xPos = 9; - } - - if (canvasHeight <= 100) { - name = ""; - } - + xPos = 9; menuOffsetX = xPos + 7; menuSpacing = 2; selectedMenuItemTickSpriteNo = 0; - if (name != "") { - field_107 = (canvasHeight - (menuOffsetY << 1) - 10 - font->getBaselinePosition()) / (font2->getBaselinePosition() + menuSpacing); - } else { - field_107 = (canvasHeight - (menuOffsetY << 1) - 10) / (font2->getBaselinePosition() + menuSpacing); - } + numberOfItemsToFit = getNumberOfItemToFitOnScreen(); if (inputString) { isTextInput = true; @@ -59,96 +46,55 @@ GameMenu::GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputSt } else { isTextInput = false; } - - if (field_107 > 13) { - field_107 = 13; - } } -void GameMenu::method_70() +void GameMenu::rolloverMenuToBottom() { if (isTextInput) { nameCursorPos = 0; } else { - if (!vector.empty()) { - field_95 = 0; + if (menuItems.empty()) { + return; + } - for (int var1 = 0; var1 < static_cast(vector.size()) && var1 < field_107; ++var1) { - if (vector[var1]->isNotTextRender()) { - field_95 = var1; - break; - } - } + viewItemIdx = 0; - field_105 = 0; - field_106 = vector.size() - 1; + int itemsToShowWindowStart = 0; + int itemsToShowWindowEnd = 0; + calculateMenuWindowBoundaries(&itemsToShowWindowStart, &itemsToShowWindowEnd); - if (field_106 > field_107 - 1) { - field_106 = field_107 - 1; + for (int i = itemsToShowWindowStart; i <= itemsToShowWindowEnd; ++i) { + if (menuItems[i]->isNotTextRender()) { + selectedItemIdx = i; + viewItemIdx = i; + return; } } } } -void GameMenu::method_71() +void GameMenu::rolloverMenuToTop() { - field_95 = vector.size() - 1; + viewItemIdx = menuItems.size() - 1; - for (int var1 = vector.size() - 1; var1 > 0; --var1) { - if (vector[var1]->isNotTextRender()) { - field_95 = var1; - break; - } - } + int itemsToShowWindowStart = 0; + int itemsToShowWindowEnd = 0; + calculateMenuWindowBoundaries(&itemsToShowWindowStart, &itemsToShowWindowEnd); - field_105 = vector.size() - field_107; - - if (field_105 < 0) { - field_105 = 0; - } - - field_106 = vector.size() - 1; - - if (field_106 > field_95 + field_107) { - field_106 = field_95 + field_107; + for (int i = itemsToShowWindowEnd; i >= itemsToShowWindowStart; --i) { + if (menuItems[i]->isNotTextRender()) { + selectedItemIdx = i; + viewItemIdx = i; + return; + } } } void GameMenu::addMenuElement(IGameMenuElement* var1) { - int var2 = menuOffsetY; - field_107 = 1; - vector.push_back(var1); - - if (name != "") { - var2 = font->getBaselinePosition() + 2; - } - - if (canvasHeight < 100) { - ++var2; - } else { - var2 += 4; - } - - for (int var3 = 0; var3 < static_cast(vector.size()) - 1; ++var3) { - if (vector[var3]->isNotTextRender()) { - var2 += font2->getBaselinePosition() + menuSpacing; - } else { - var2 += (TextRender::getBaselinePosition() < GameCanvas::spriteSizeY[5] ? GameCanvas::spriteSizeY[5] : TextRender::getBaselinePosition()) + menuSpacing; - } - - if (var2 > canvasHeight - (menuOffsetY << 1) - 10) { - break; - } - - ++field_107; - } - - if (field_107 > 13) { - field_107 = 13; - } - - method_70(); + menuItems.push_back(var1); + numberOfItemsToFit = getNumberOfItemToFitOnScreen(); + rolloverMenuToBottom(); } void GameMenu::processGameActionDown() @@ -165,51 +111,27 @@ void GameMenu::processGameActionDown() strArr[nameCursorPos] = 32; return; } - } else if (vector.size() != 0) { - if (!(vector[field_95]->isNotTextRender())) { - ++field_106; - field_95 = field_106; - ++field_105; + } else if (menuItems.size() != 0) { + const int lastMenuItemIdx = static_cast(menuItems.size()) - 1; + const int itemsToShowWindowStart = std::min(viewItemIdx + 1, lastMenuItemIdx); + const int itemsToShowWindowEnd = std::min(viewItemIdx + numberOfItemsToFit, lastMenuItemIdx); + ++viewItemIdx; + + if (viewItemIdx > lastMenuItemIdx) { + rolloverMenuToBottom(); return; } - ++field_95; - - if (field_95 > static_cast(vector.size()) - 1) { - method_70(); - return; - } - - bool var3 = false; - - int var2; - - for (var2 = field_95; var2 <= field_106 + 1; ++var2) { - if (vector[var2]->isNotTextRender()) { - var3 = true; - break; + for (int i = itemsToShowWindowStart; i <= itemsToShowWindowEnd; ++i) { + if (menuItems[i]->isNotTextRender()) { + selectedItemIdx = i; + viewItemIdx = i; + return; } } - if (var3) { - field_95 = var2; - } else if (field_106 < static_cast(vector.size()) - 1) { - ++field_106; - ++field_105; - } else { - --field_95; - } - - if (field_95 > field_106) { - ++field_105; - ++field_106; - - if (field_106 > static_cast(vector.size()) - 1) { - field_106 = vector.size() - 1; - } - - field_95 = field_106; - } + selectedItemIdx = itemsToShowWindowEnd; + viewItemIdx = itemsToShowWindowEnd; } } @@ -227,53 +149,26 @@ void GameMenu::processGameActionUp() strArr[nameCursorPos] = 32; return; } - } else if (vector.size() != 0) { - --field_95; + } else if (menuItems.size() != 0) { + const int itemsToShowWindowStart = std::max(viewItemIdx - numberOfItemsToFit, 0); + const int itemsToShowWindowEnd = std::max(viewItemIdx - 1, 0); + --viewItemIdx; - if (field_95 < 0) { - method_71(); + if (viewItemIdx < 0) { + rolloverMenuToTop(); return; } - bool var3 = false; - int var2; - - for (var2 = field_95; var2 >= field_105; --var2) { - if (vector[var2]->isNotTextRender()) { - var3 = true; - break; - } - } - - if (!var3) { - if (field_105 > 0) { - --field_105; - - if (static_cast(vector.size()) > field_107 - 1) { - --field_106; - return; - } - } else { - method_71(); + for (int i = itemsToShowWindowEnd; i >= itemsToShowWindowStart; --i) { + if (menuItems[i]->isNotTextRender()) { + selectedItemIdx = i; + viewItemIdx = i; + return; } - - return; } - field_95 = var2; - - if (field_95 < field_105) { - --field_105; - - if (field_105 < 0) { - field_95 = 0; - field_105 = 0; - } - - if (static_cast(vector.size()) > field_107 - 1) { - --field_106; - } - } + selectedItemIdx = itemsToShowWindowStart; + viewItemIdx = itemsToShowWindowStart; } } @@ -307,11 +202,11 @@ void GameMenu::processGameActionUpd(int var1) } } else { - if (field_95 != -1) { - for (int var2 = field_95; var2 < static_cast(vector.size()); ++var2) { + if (selectedItemIdx != -1) { + for (int var2 = selectedItemIdx; var2 < static_cast(menuItems.size()); ++var2) { IGameMenuElement* var3; - if ((var3 = vector[var2]) != nullptr && var3->isNotTextRender()) { + if ((var3 = menuItems[var2]) != nullptr && var3->isNotTextRender()) { var3->menuElemMethod(var1); return; } @@ -354,10 +249,25 @@ void GameMenu::render_76(Graphics* graphics) } } else { + int itemsToShowWindowStart = 0; + int itemsToShowWindowEnd = 0; + calculateMenuWindowBoundaries(&itemsToShowWindowStart, &itemsToShowWindowEnd); + + Log::write( + Log::LogLevel::Debug, + "%s, selectedItemIdx: %d, viewItemIdx: %d, window start: %d, window end: %d, number of items to fit: %d, menu items count: %d\n", + name.c_str(), + selectedItemIdx, + viewItemIdx, + itemsToShowWindowStart, + itemsToShowWindowEnd, + numberOfItemsToFit, + menuItems.size()); + graphics->setColor(0, 0, 0); var2 = menuOffsetY; - if (name != "") { + if (!name.empty()) { graphics->setFont(font); graphics->drawString( name, @@ -367,25 +277,20 @@ void GameMenu::render_76(Graphics* graphics) var2 += font->getBaselinePosition() + 2; } - if (field_105 > 0) { + // scrolling text: draw top range cursor + if (itemsToShowWindowStart > 0) { micro->gameCanvas->drawSprite(graphics, 2, xPos - 3, var2); } - if (canvasHeight < 100) { - ++var2; - } else { - var2 += 4; - } - graphics->setFont(font2); - for (i = field_105; i < field_106 + 1; ++i) { - IGameMenuElement* var4 = vector[i]; + for (i = itemsToShowWindowStart; i <= itemsToShowWindowEnd; ++i) { + IGameMenuElement* var4 = menuItems[i]; graphics->setColor(0, 0, 0); var4->render(graphics, var2, menuOffsetX); - // TODO: field_95 - selected menu items idx ?? - if (i == field_95 && var4->isNotTextRender()) { + // draw helmet icon near selected item + if (i == selectedItemIdx && var4->isNotTextRender()) { const int selectedMenuItemTickX = xPos - micro->gameCanvas->helmetSpriteWidth / 2; const int selectedMenuItemTickY = var2 + font2->getBaselinePosition() / 2; // - micro->gameCanvas->helmetSpriteHeight / 2; graphics->setClip( @@ -413,7 +318,8 @@ void GameMenu::render_76(Graphics* graphics) } } - if (static_cast(vector.size()) > field_106 && field_106 != static_cast(vector.size()) - 1) { + // scrolling text: draw bottom range cursor + if (static_cast(menuItems.size()) > itemsToShowWindowEnd && itemsToShowWindowEnd != static_cast(menuItems.size()) - 1) { if (GameCanvas::spriteSizeY[3] + var2 > canvasHeight) { micro->gameCanvas->drawSprite(graphics, 3, xPos - 3, canvasHeight - GameCanvas::spriteSizeY[3]); return; @@ -436,31 +342,57 @@ GameMenu* GameMenu::getGameMenu() void GameMenu::clearVector() { - vector.clear(); - field_105 = 0; - field_106 = 0; - field_95 = -1; + menuItems.clear(); + viewItemIdx = -1; + selectedItemIdx = -1; } -std::string GameMenu::makeString() +char* GameMenu::getStrArr() const { - return std::string(strArr); + return strArr; } -char* GameMenu::getStrArr() const +void GameMenu::startAtPosition(const int pos) { - return strArr; + rolloverMenuToBottom(); + viewItemIdx = pos; + selectedItemIdx = pos; } -void GameMenu::method_83(int var1) +int GameMenu::getNumberOfItemToFitOnScreen() const { - method_70(); + int screenHeightForMenuItems = canvasHeight - (menuOffsetY << 1); + + if (!name.empty()) { + screenHeightForMenuItems -= font->getBaselinePosition() + 10; + } - while (field_95 < var1) { - ++field_95; - if (field_95 > field_106) { - ++field_105; - ++field_106; + const int menuItemHeight = font2->getBaselinePosition() + menuSpacing; + return std::floor(screenHeightForMenuItems / menuItemHeight) - 1; +} + +void GameMenu::calculateMenuWindowBoundaries(int* itemsToShowWindowStart, int* itemsToShowWindowEnd) { + if (menuItems.empty()) { + return; + } + + if (static_cast(menuItems.size()) <= numberOfItemsToFit) { + *itemsToShowWindowStart = 0; + *itemsToShowWindowEnd = menuItems.size() - 1; + } else { + *itemsToShowWindowStart = viewItemIdx; + *itemsToShowWindowEnd = *itemsToShowWindowStart + numberOfItemsToFit - 1; + + if (*itemsToShowWindowEnd > static_cast((menuItems.size() - 1))) { + *itemsToShowWindowEnd = menuItems.size() - 1; + } + + if (*itemsToShowWindowEnd - *itemsToShowWindowStart < numberOfItemsToFit) { + *itemsToShowWindowStart = *itemsToShowWindowEnd - numberOfItemsToFit + 1; } } + + *itemsToShowWindowStart = std::max(*itemsToShowWindowStart, 0); + *itemsToShowWindowEnd = std::min(*itemsToShowWindowEnd, static_cast(menuItems.size() - 1)); + } diff --git a/src/GameMenu.h b/src/GameMenu.h index e161122..9c536eb 100644 --- a/src/GameMenu.h +++ b/src/GameMenu.h @@ -14,8 +14,10 @@ class GameMenu { private: GameMenu* gameMenu; std::string name; - int field_95; - std::vector vector; + int selectedItemIdx; + int viewItemIdx; + + std::vector menuItems; Micro* micro; std::shared_ptr font; std::shared_ptr font2; @@ -23,9 +25,9 @@ class GameMenu { int menuOffsetY; int menuSpacing; int menuOffsetX; - int field_105; - int field_106; - int field_107; + // int itemsToShowWindowStart; + // int itemsToShowWindowEnd; + int numberOfItemsToFit; int canvasWidth; int canvasHeight; int selectedMenuItemTickSpriteNo; @@ -33,12 +35,15 @@ class GameMenu { int nameCursorPos; char* strArr; + int getNumberOfItemToFitOnScreen() const; + void calculateMenuWindowBoundaries(int* itemsToShowWindowStart, int* itemsToShowWindowEnd); + public: int xPos; GameMenu(std::string var1, Micro* micro, GameMenu* var3, char* inputString = nullptr); - void method_70(); - void method_71(); + void rolloverMenuToBottom(); + void rolloverMenuToTop(); void addMenuElement(IGameMenuElement* var1); void processGameActionDown(); void processGameActionUp(); @@ -47,7 +52,7 @@ class GameMenu { void setGameMenu(GameMenu* gameMenu); GameMenu* getGameMenu(); void clearVector(); - std::string makeString(); + // std::string makeString(); char* getStrArr() const; - void method_83(int var1); + void startAtPosition(const int pos); }; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 9da7575..22cd868 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -618,7 +618,7 @@ void MenuManager::method_1(GameMenu* gm, bool var2) currentGameMenu = gm; if (currentGameMenu != nullptr && !var2) { - currentGameMenu->method_70(); + currentGameMenu->rolloverMenuToBottom(); } field_377 = false; @@ -815,7 +815,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) } if (menuElement == field_336) { - gameMenuEnterName->method_70(); + gameMenuEnterName->rolloverMenuToBottom(); method_1(gameMenuEnterName, false); return; } @@ -831,7 +831,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) settingsStringTrack->init(); field_299 = settingsStringTrack->getGameMenu(); method_1(field_299, false); - field_299->method_83(settingsStringTrack->getCurrentOptionPos()); + field_299->startAtPosition(settingsStringTrack->getCurrentOptionPos()); } field_345[settingStringLevel->getCurrentOptionPos()] = settingsStringTrack->getCurrentOptionPos(); @@ -842,7 +842,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) if (settingStringLevel->method_114()) { gameMenuStringLevel = settingStringLevel->getGameMenu(); method_1(gameMenuStringLevel, false); - gameMenuStringLevel->method_83(settingStringLevel->getCurrentOptionPos()); + gameMenuStringLevel->startAtPosition(settingStringLevel->getCurrentOptionPos()); } settingsStringTrack->setOptionsList(micro->levelLoader->GetTrackNames(settingStringLevel->getCurrentOptionPos())); @@ -856,7 +856,7 @@ void MenuManager::processMenu(IGameMenuElement* menuElement) gameMenuLeague = settingsStringLeague->getGameMenu(); settingsStringLeague->setParentGameMenu(currentGameMenu); method_1(gameMenuLeague, false); - gameMenuLeague->method_83(settingsStringLeague->getCurrentOptionPos()); + gameMenuLeague->startAtPosition(settingsStringLeague->getCurrentOptionPos()); } } } From d17a228f6f524652c61d4ff7644930416d5488c9 Mon Sep 17 00:00:00 2001 From: Vitalii-Ohol Date: Sun, 17 Nov 2024 18:21:49 +0200 Subject: [PATCH 16/16] reverted README changes --- CMakeLists.txt | 2 +- README.md | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 265a4fc..e3eab91 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,4 +114,4 @@ else() endif() # Copy assets to the build directory -# file(COPY assets/levels.mrg DESTINATION ${CMAKE_BINARY_DIR}) +file(COPY assets/levels.mrg DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/README.md b/README.md index 6b27cd1..f96a492 100644 --- a/README.md +++ b/README.md @@ -8,24 +8,6 @@ This is the C++ & SDL2 port of Gravity Defied, which includes all the features o ***This Project is not associated with Codebrew Software in any fashion. All rights to the original Gravity Defied, it's name, logotype, brand and all that stuff belong to Codebrew Software.*** -# About the fork - -- overhauled saving data to files (simplified, changed it to a C/C++ way) -- fixed: game does not save progress after the first save -- fixed: saving high score -- overhauled controls logic (simplified, per key setting instead of predefined key sets) -- added fullscreen and proper scaling for different aspect ratios -- renamed portions of a code to something meaningful - -# TODO - -- [X] create saves directory and global setting file when missing -- [ ] config file -- [X] command line flags -- [ ] level file selector -- [ ] further refactoring -- [ ] scaling game (or at least font) - # Authors ### Gravity Defied Cpp authors