diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.c b/applications/plugins/snake_game/helpers/snake_file_handler.c index 3a1ea7455..569bd8738 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.c +++ b/applications/plugins/snake_game/helpers/snake_file_handler.c @@ -23,6 +23,17 @@ static FlipperFormat* snake_game_open_file() { return NULL; } } else { + if(storage_common_stat(storage, APPS_DATA, NULL) == FSE_NOT_EXIST) { + if(!storage_simply_mkdir(storage, APPS_DATA)) { + return NULL; + } + } + if(storage_common_stat(storage, SNAKE_GAME_FILE_DIR_PATH, NULL) == FSE_NOT_EXIST) { + if(!storage_simply_mkdir(storage, SNAKE_GAME_FILE_DIR_PATH)) { + return NULL; + } + } + if(!flipper_format_file_open_new(file, SNAKE_GAME_FILE_PATH)) { snake_game_close_file(file); return NULL; @@ -37,125 +48,134 @@ static FlipperFormat* snake_game_open_file() { void snake_game_save_score_to_file(int16_t highscore) { FlipperFormat* file = snake_game_open_file(); - uint32_t temp = highscore; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) { + if(file != NULL) { + uint32_t temp = highscore; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) { + snake_game_close_file(file); + return; + } snake_game_close_file(file); - return; } - snake_game_close_file(file); } void snake_game_save_game_to_file(SnakeState* const snake_state) { FlipperFormat* file = snake_game_open_file(); - uint32_t temp = snake_state->len; - if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { - snake_game_close_file(file); - return; - } + if(file != NULL) { + uint32_t temp = snake_state->len; + if(!flipper_format_insert_or_update_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { + snake_game_close_file(file); + return; + } - uint16_t array_size = snake_state->len * 2; - uint32_t temp_array[array_size]; - for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { - temp_array[a++] = snake_state->points[i].x; - temp_array[a++] = snake_state->points[i].y; - } - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { - snake_game_close_file(file); - return; - } + uint16_t array_size = snake_state->len * 2; + uint32_t temp_array[array_size]; + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { + temp_array[a++] = snake_state->points[i].x; + temp_array[a++] = snake_state->points[i].y; + } + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { + snake_game_close_file(file); + return; + } - temp = snake_state->currentMovement; - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return; - } + temp = snake_state->currentMovement; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return; + } - temp = snake_state->nextMovement; - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return; - } + temp = snake_state->nextMovement; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return; + } - array_size = 2; - uint32_t temp_point_array[array_size]; - temp_point_array[0] = snake_state->fruit.x; - temp_point_array[1] = snake_state->fruit.y; - if(!flipper_format_insert_or_update_uint32( - file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { - snake_game_close_file(file); - return; - } + array_size = 2; + uint32_t temp_point_array[array_size]; + temp_point_array[0] = snake_state->fruit.x; + temp_point_array[1] = snake_state->fruit.y; + if(!flipper_format_insert_or_update_uint32( + file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { + snake_game_close_file(file); + return; + } - snake_game_close_file(file); + snake_game_close_file(file); + } } bool snake_game_init_game_from_file(SnakeState* const snake_state) { FlipperFormat* file = snake_game_open_file(); - FuriString* file_type = furi_string_alloc(); - uint32_t version = 1; - if(!flipper_format_read_header(file, file_type, &version)) { + if(file != NULL) { + FuriString* file_type = furi_string_alloc(); + uint32_t version = 1; + if(!flipper_format_read_header(file, file_type, &version)) { + furi_string_free(file_type); + snake_game_close_file(file); + return false; + } furi_string_free(file_type); + + uint32_t temp; + snake_state->highscore = + (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; + flipper_format_rewind(file); + + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { + snake_game_close_file(file); + return false; + } + snake_state->len = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_LEN); + + uint16_t array_size = snake_state->len * 2; + uint32_t temp_array[array_size]; + if(!flipper_format_read_uint32( + file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { + snake_game_close_file(file); + return false; + } + + for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { + snake_state->points[i].x = temp_array[a++]; + snake_state->points[i].y = temp_array[a++]; + } + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_POINTS); + + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return false; + } + snake_state->currentMovement = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT); + + if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { + snake_game_close_file(file); + return false; + } + snake_state->nextMovement = temp; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT); + + array_size = 2; + uint32_t temp_point_array[array_size]; + if(!flipper_format_read_uint32( + file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { + snake_game_close_file(file); + return false; + } + snake_state->fruit.x = temp_point_array[0]; + snake_state->fruit.y = temp_point_array[1]; + flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS); + snake_game_close_file(file); - return false; - } - furi_string_free(file_type); - uint32_t temp; - snake_state->highscore = - (flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_HIGHSCORE, &temp, 1)) ? temp : 0; - flipper_format_rewind(file); - - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_LEN, &temp, 1)) { - snake_game_close_file(file); - return false; - } - snake_state->len = temp; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_LEN); - - uint16_t array_size = snake_state->len * 2; - uint32_t temp_array[array_size]; - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_POINTS, temp_array, array_size)) { - snake_game_close_file(file); - return false; + return true; } - for(int16_t i = 0, a = 0; a < array_size && i < snake_state->len; i++) { - snake_state->points[i].x = temp_array[a++]; - snake_state->points[i].y = temp_array[a++]; - } - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_POINTS); - - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return false; - } - snake_state->currentMovement = temp; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_CURRENT_MOVEMENT); - - if(!flipper_format_read_uint32(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT, &temp, 1)) { - snake_game_close_file(file); - return false; - } - snake_state->nextMovement = temp; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_NEXT_MOVEMENT); - - array_size = 2; - uint32_t temp_point_array[array_size]; - if(!flipper_format_read_uint32( - file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS, temp_point_array, array_size)) { - snake_game_close_file(file); - return false; - } - snake_state->fruit.x = temp_point_array[0]; - snake_state->fruit.y = temp_point_array[1]; - flipper_format_delete_key(file, SNAKE_GAME_CONFIG_KEY_FRUIT_POINTS); - - snake_game_close_file(file); - - return true; + return false; } diff --git a/applications/plugins/snake_game/helpers/snake_file_handler.h b/applications/plugins/snake_game/helpers/snake_file_handler.h index 25cda4506..178d5d8e0 100644 --- a/applications/plugins/snake_game/helpers/snake_file_handler.h +++ b/applications/plugins/snake_game/helpers/snake_file_handler.h @@ -4,7 +4,9 @@ #include #include -#define SNAKE_GAME_FILE_PATH "/ext/apps/games/.snake" +#define APPS_DATA EXT_PATH("apps_data") +#define SNAKE_GAME_FILE_DIR_PATH APPS_DATA "/snake_game" +#define SNAKE_GAME_FILE_PATH SNAKE_GAME_FILE_DIR_PATH "/.snake" #define SNAKE_GAME_FILE_HEADER "Flipper Snake plugin run file" #define SNAKE_GAME_FILE_ACTUAL_VERSION 1 diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 362e4f1bf..d4db04936 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -300,7 +300,9 @@ int32_t snake_game_app(void* p) { SnakeState* snake_state = malloc(sizeof(SnakeState)); snake_state->isNewHighscore = false; snake_state->highscore = 0; - if(!snake_game_init_game_from_file(snake_state)) snake_game_init_game(snake_state); + if(!snake_game_init_game_from_file(snake_state)) { + snake_game_init_game(snake_state); + } ValueMutex state_mutex; if(!init_mutex(&state_mutex, snake_state, sizeof(SnakeState))) { @@ -356,8 +358,9 @@ int32_t snake_game_app(void* p) { } break; case InputKeyBack: - if(snake_state->state == GameStateLife) + if(snake_state->state == GameStateLife) { snake_game_save_game_to_file(snake_state); + } processing = false; break; default: @@ -375,7 +378,9 @@ int32_t snake_game_app(void* p) { release_mutex(&state_mutex, snake_state); } - if(snake_state->isNewHighscore) snake_game_save_score_to_file(snake_state->highscore); + if(snake_state->isNewHighscore) { + snake_game_save_score_to_file(snake_state->highscore); + } // Wait for all notifications to be played and return backlight to normal state notification_message_block(notification, &sequence_display_backlight_enforce_auto);