diff --git a/fw/Core/Hitcon/App/MainMenuApp.h b/fw/Core/Hitcon/App/MainMenuApp.h index 76ea893..81ec6fa 100644 --- a/fw/Core/Hitcon/App/MainMenuApp.h +++ b/fw/Core/Hitcon/App/MainMenuApp.h @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ constexpr menu_entry_t main_menu_entries[] = { {"Snake", &snake_app, &hitcon::app::snake::SetSingleplayer}, {"Dino", &dino_app, nullptr}, {"Tetris", &tetris_app, &hitcon::app::tetris::SetSingleplayer}, + {"Show Scores", &score_hist::g_score_hist, nullptr}, }; constexpr int main_menu_entries_len = diff --git a/fw/Core/Hitcon/App/ScoreHistApp.cc b/fw/Core/Hitcon/App/ScoreHistApp.cc new file mode 100644 index 0000000..60035cd --- /dev/null +++ b/fw/Core/Hitcon/App/ScoreHistApp.cc @@ -0,0 +1,34 @@ +#include +#include +#include + +namespace hitcon { +namespace score_hist { + +char dino_score_str[15] = "Dino "; +char snake_score_str[15] = "Snake "; +char tetris_score_str[15] = "Tetris "; + +ScoreHistApp g_score_hist; + +void ScoreHistApp::SetScores() { + int dino_score = g_game_score.GetScore(GameScoreType::GAME_DINO); + int snake_score = g_game_score.GetScore(GameScoreType::GAME_SNAKE); + int tetris_score = g_game_score.GetScore(GameScoreType::GAME_TETRIS); + + if (dino_score > 9999999) dino_score = 9999999; + if (snake_score > 9999999) snake_score = 9999999; + if (tetris_score > 9999999) tetris_score = 9999999; + + uint_to_chr(&dino_score_str[5], 8, dino_score); + uint_to_chr(&tetris_score_str[7], 8, tetris_score); + uint_to_chr(&snake_score_str[6], 8, snake_score); +} + +void ScoreHistApp::OnEntry() { + SetScores(); + MenuApp::OnEntry(); +} + +} // namespace score_hist +} // namespace hitcon diff --git a/fw/Core/Hitcon/App/ScoreHistApp.h b/fw/Core/Hitcon/App/ScoreHistApp.h new file mode 100644 index 0000000..21dbe87 --- /dev/null +++ b/fw/Core/Hitcon/App/ScoreHistApp.h @@ -0,0 +1,43 @@ +#ifndef APP_SCORE_HIST_APP +#define APP_SCORE_HIST_APP + +#include + +#include "MenuApp.h" + +namespace hitcon { +namespace score_hist { + +extern char dino_score_str[15]; +extern char snake_score_str[15]; +extern char tetris_score_str[15]; + +constexpr menu_entry_t score_hist_app_entries[] = { + {dino_score_str, nullptr, nullptr}, + {tetris_score_str, nullptr, nullptr}, + {snake_score_str, nullptr, nullptr}}; + +constexpr size_t score_hist_app_entries_len = + sizeof(score_hist_app_entries) / sizeof(score_hist_app_entries[0]); + +class ScoreHistApp : public MenuApp { + public: + ScoreHistApp() + : MenuApp(score_hist_app_entries, score_hist_app_entries_len) {} + + void OnEntry() override; + + void OnButtonMode() override {} + void OnButtonBack() override { badge_controller.BackToMenu(this); } + void OnButtonLongBack() override { badge_controller.BackToMenu(this); } + + private: + void SetScores(); +}; + +extern ScoreHistApp g_score_hist; + +} // namespace score_hist +} // namespace hitcon + +#endif // APP_SCORE_HIST_APP diff --git a/fw/Core/Hitcon/Logic/GameScore.cc b/fw/Core/Hitcon/Logic/GameScore.cc index 89e23bc..fdca99a 100644 --- a/fw/Core/Hitcon/Logic/GameScore.cc +++ b/fw/Core/Hitcon/Logic/GameScore.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -92,7 +93,8 @@ constexpr int kBusyRoutineDelay = 100; } // namespace GameScore::GameScore() - : routine_task_delayed(920, (callback_t)&GameScore::Routine, this, 0) {} + : routine_task_delayed(920, (callback_t)&GameScore::Routine, this, 0), + nv_fetched_(false) {} void GameScore::Init() { memset(sent, 0, sizeof(sent)); @@ -115,6 +117,15 @@ void GameScore::Routine(void* args) { } bool GameScore::RoutineInternal() { + if (g_nv_storage.IsStorageValid() && !nv_fetched_) { + for (size_t i = 0; i < static_cast(GameScoreType::GAME_UNUSED_MAX); + i++) { + if (g_nv_storage.GetCurrentStorage().max_scores[i] > scores[i]) { + scores[i] = g_nv_storage.GetCurrentStorage().max_scores[i]; + } + } + nv_fetched_ = true; + } size_t i = last_operation_progress_; size_t end = kAchievementCount; if (kAchievementPerPass < end) end = kAchievementPerPass; @@ -150,7 +161,17 @@ bool GameScore::TryAcceptData(size_t row_id) { } void GameScore::MarkScore(GameScoreType game_type, int score) { - scores[static_cast(game_type)] = score; + const size_t sid = static_cast(game_type); + if (score > scores[sid]) { + scores[sid] = score; + g_nv_storage.GetCurrentStorage().max_scores[sid] = score; + g_nv_storage.MarkDirty(); + } +} + +int GameScore::GetScore(GameScoreType game_type) { + const size_t sid = static_cast(game_type); + return scores[sid]; } } // namespace hitcon diff --git a/fw/Core/Hitcon/Logic/GameScore.h b/fw/Core/Hitcon/Logic/GameScore.h index 32b36b9..ebe83fe 100644 --- a/fw/Core/Hitcon/Logic/GameScore.h +++ b/fw/Core/Hitcon/Logic/GameScore.h @@ -22,6 +22,8 @@ class GameScore { void MarkScore(GameScoreType game_type, int score); + int GetScore(GameScoreType game_type); + private: uint8_t sent[kGameAchievementDataCount / 8 + 1]; int scores[static_cast(GameScoreType::GAME_UNUSED_MAX)]; @@ -29,6 +31,7 @@ class GameScore { hitcon::service::sched::DelayedTask routine_task_delayed; size_t last_operation_progress_; + bool nv_fetched_; void Routine(void* args); bool RoutineInternal(); diff --git a/fw/Core/Hitcon/Logic/NvStorage.h b/fw/Core/Hitcon/Logic/NvStorage.h index 99cff48..99584b6 100644 --- a/fw/Core/Hitcon/Logic/NvStorage.h +++ b/fw/Core/Hitcon/Logic/NvStorage.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,9 @@ typedef struct nv_storage_content_t { // Add any needed data that needs to be persisted here. hitcon::game::game_storage_t game_storage; char name[hitcon::ShowNameApp::NAME_LEN + 1]; + + uint32_t + max_scores[static_cast(hitcon::GameScoreType::GAME_UNUSED_MAX)]; } nv_storage_content; static_assert(sizeof(nv_storage_content) <= MY_FLASH_PAGE_SIZE,