game_settings.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Copyright 2025 Ivan Barsukov
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "game_settings.h"
  18. #include <flipper_format/flipper_format.h>
  19. #include <storage/storage.h>
  20. #define SETTINGS_FILE_NAME "settings.txt"
  21. #define SETTING_FILE_TYPE "Quadrastic Game Setting File"
  22. #define SETTING_FILE_VERSION 1
  23. #define KEY_DIFFICULTY "Difficulty"
  24. #define KEY_BEST_SCORE "Best score"
  25. #define KEY_SOUND "Sound"
  26. #define KEY_VIBRO "Vibro"
  27. #define KEY_LED "LED"
  28. static bool
  29. game_read_bool_setting(FlipperFormat* flipper_format,
  30. const char* key,
  31. State* setting)
  32. {
  33. if (!flipper_format_rewind(flipper_format)) {
  34. FURI_LOG_E(GAME_NAME, "Rewind error");
  35. return false;
  36. }
  37. bool temp_bool = *setting;
  38. if (!flipper_format_read_bool(flipper_format, key, &temp_bool, 1)) {
  39. FURI_LOG_E(GAME_NAME, "Can't read %s setting", key);
  40. return false;
  41. }
  42. *setting = temp_bool ? StateOn : StateOff;
  43. return true;
  44. }
  45. void
  46. game_read_settings(GameContext* game_context)
  47. {
  48. // Default settings
  49. game_context->score = 0;
  50. game_context->best_score = 0;
  51. game_context->difficulty = DifficultyNormal;
  52. game_context->sound = StateOn;
  53. game_context->vibro = StateOn;
  54. game_context->led = StateOn;
  55. // Read settings
  56. Storage* storage = furi_record_open(RECORD_STORAGE);
  57. FlipperFormat* flipper_format = flipper_format_file_alloc(storage);
  58. FuriString* temp_string = furi_string_alloc();
  59. uint32_t temp_uint32;
  60. do {
  61. // Check settings file
  62. if (!flipper_format_file_open_existing(
  63. flipper_format, APP_DATA_PATH(SETTINGS_FILE_NAME))) {
  64. FURI_LOG_D(GAME_NAME, "Settings file is not used");
  65. break;
  66. }
  67. if (!flipper_format_read_header(
  68. flipper_format, temp_string, &temp_uint32)) {
  69. FURI_LOG_E(GAME_NAME, "Missing or incorrect header");
  70. break;
  71. }
  72. if ((!strcmp(furi_string_get_cstr(temp_string), SETTING_FILE_TYPE)) &&
  73. temp_uint32 == SETTING_FILE_VERSION) {
  74. } else {
  75. FURI_LOG_E(GAME_NAME, "Type or version mismatch");
  76. break;
  77. }
  78. // Read difficulty
  79. temp_uint32 = (uint32_t)game_context->difficulty;
  80. if (!flipper_format_read_uint32(
  81. flipper_format, KEY_DIFFICULTY, &temp_uint32, 1)) {
  82. FURI_LOG_E(GAME_NAME, "Can't read " KEY_DIFFICULTY " setting");
  83. break;
  84. }
  85. if (temp_uint32 >= DifficultyCount) {
  86. temp_uint32 = DifficultyCount - 1;
  87. }
  88. game_context->difficulty = temp_uint32;
  89. // Read best score
  90. temp_uint32 = game_context->best_score;
  91. if (!flipper_format_read_uint32(
  92. flipper_format, KEY_BEST_SCORE, &temp_uint32, 1)) {
  93. FURI_LOG_E(GAME_NAME, "Can't read " KEY_BEST_SCORE " setting");
  94. break;
  95. }
  96. game_context->best_score = temp_uint32;
  97. // Read sound
  98. if (!game_read_bool_setting(
  99. flipper_format, KEY_SOUND, &game_context->sound)) {
  100. break;
  101. }
  102. // Read vibro
  103. if (!game_read_bool_setting(
  104. flipper_format, KEY_VIBRO, &game_context->vibro)) {
  105. break;
  106. }
  107. // Read led
  108. if (!game_read_bool_setting(
  109. flipper_format, KEY_LED, &game_context->led)) {
  110. break;
  111. }
  112. } while (false);
  113. furi_string_free(temp_string);
  114. flipper_format_free(flipper_format);
  115. furi_record_close(RECORD_STORAGE);
  116. FURI_LOG_I(GAME_NAME, "Settings read");
  117. }
  118. void
  119. game_save_settings(GameContext* game_context)
  120. {
  121. Storage* storage = furi_record_open(RECORD_STORAGE);
  122. FlipperFormat* flipper_format = flipper_format_file_alloc(storage);
  123. bool temp_bool;
  124. uint32_t temp_uint32;
  125. do {
  126. // Write settings meta
  127. if (!flipper_format_file_open_always(
  128. flipper_format, APP_DATA_PATH(SETTINGS_FILE_NAME))) {
  129. FURI_LOG_E(GAME_NAME, "Settings file can't be saved");
  130. break;
  131. }
  132. if (!flipper_format_write_header_cstr(
  133. flipper_format, SETTING_FILE_TYPE, SETTING_FILE_VERSION)) {
  134. FURI_LOG_E(GAME_NAME, "Settings header can't be saved");
  135. break;
  136. }
  137. // Write difficulty
  138. temp_uint32 = game_context->difficulty;
  139. if (!flipper_format_write_uint32(
  140. flipper_format, KEY_DIFFICULTY, &temp_uint32, 1)) {
  141. FURI_LOG_E(GAME_NAME, "Difficulty state can't be saved");
  142. break;
  143. }
  144. // Write best score
  145. temp_uint32 = game_context->best_score;
  146. if (!flipper_format_write_uint32(
  147. flipper_format, KEY_BEST_SCORE, &temp_uint32, 1)) {
  148. FURI_LOG_E(GAME_NAME, "Best score state can't be saved");
  149. break;
  150. }
  151. // Write sound
  152. temp_bool = game_context->sound == StateOn;
  153. if (!flipper_format_write_bool(
  154. flipper_format, "Sound", &temp_bool, 1)) {
  155. FURI_LOG_E(GAME_NAME, "Sound state can't be saved");
  156. break;
  157. }
  158. // Write vibro
  159. temp_bool = game_context->vibro == StateOn;
  160. if (!flipper_format_write_bool(
  161. flipper_format, "Vibro", &temp_bool, 1)) {
  162. FURI_LOG_E(GAME_NAME, "Vibro state can't be saved");
  163. break;
  164. }
  165. // Write led
  166. temp_bool = game_context->led == StateOn;
  167. if (!flipper_format_write_bool(flipper_format, "LED", &temp_bool, 1)) {
  168. FURI_LOG_E(GAME_NAME, "LED state can't be saved");
  169. break;
  170. }
  171. } while (false);
  172. flipper_format_free(flipper_format);
  173. furi_record_close(RECORD_STORAGE);
  174. FURI_LOG_I(GAME_NAME, "Settings saved");
  175. }