From bbd74d55da6a77bd0c1c9edad1a61bb35ae81173 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 19:24:59 +0000 Subject: [PATCH 01/12] Include metadata strings in SDL builds Generates a file containing the definitions. The library contains some defaults that are marked weak for GCC and relies on the VS linker behavior of OBJs overriding LIBs. --- 32blit-sdl/CMakeLists.txt | 11 +++++++++++ 32blit-sdl/DefaultMetadata.cpp | 12 ++++++++++++ 32blit-sdl/UserCode.hpp | 11 ++++++++--- vs/32blit-sdl/32blit-sdl.vcxproj | 1 + 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 32blit-sdl/DefaultMetadata.cpp diff --git a/32blit-sdl/CMakeLists.txt b/32blit-sdl/CMakeLists.txt index a3edf3289..8a2ce5705 100644 --- a/32blit-sdl/CMakeLists.txt +++ b/32blit-sdl/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(BlitHalSDL STATIC + DefaultMetadata.cpp File.cpp Input.cpp JPEG.cpp @@ -188,4 +189,14 @@ function(blit_metadata TARGET FILE) target_sources(${TARGET} PRIVATE ${ICON}) set_source_files_properties(${ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) endif() + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/metadata.cpp + CONTENT " +const char *metadata_title = \"${METADATA_TITLE}\"; +const char *metadata_author = \"${METADATA_AUTHOR}\"; +const char *metadata_description = \"${METADATA_DESCRIPTION}\"; +const char *metadata_version = \"${METADATA_VERSION}\"; + " + ) + target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/metadata.cpp) endfunction() diff --git a/32blit-sdl/DefaultMetadata.cpp b/32blit-sdl/DefaultMetadata.cpp new file mode 100644 index 000000000..4eb26bb14 --- /dev/null +++ b/32blit-sdl/DefaultMetadata.cpp @@ -0,0 +1,12 @@ +// Default metadata if there is non compiled into the game +// There should be nothing else in this file so that the VS linker drops it when not needed +#ifdef _MSC_VER +#define WEAK +#else +#define WEAK [[gnu::weak]] +#endif + +WEAK const char *metadata_title = "32Blit Game"; +WEAK const char *metadata_author = "Unknown"; +WEAK const char *metadata_description = ""; +WEAK const char *metadata_version = "v0.0.0"; \ No newline at end of file diff --git a/32blit-sdl/UserCode.hpp b/32blit-sdl/UserCode.hpp index 976b33917..e6df5fd18 100644 --- a/32blit-sdl/UserCode.hpp +++ b/32blit-sdl/UserCode.hpp @@ -1,6 +1,11 @@ #pragma once #include - void init(); - void update(uint32_t time); - void render(uint32_t time); +void init(); +void update(uint32_t time); +void render(uint32_t time); + +extern const char *metadata_title; +extern const char *metadata_author; +extern const char *metadata_description; +extern const char *metadata_version; \ No newline at end of file diff --git a/vs/32blit-sdl/32blit-sdl.vcxproj b/vs/32blit-sdl/32blit-sdl.vcxproj index 4e0a1b90b..29f5e0950 100644 --- a/vs/32blit-sdl/32blit-sdl.vcxproj +++ b/vs/32blit-sdl/32blit-sdl.vcxproj @@ -210,6 +210,7 @@ + From b110cd6a19c12ceec829939d683bf3368585567b Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 19:27:01 +0000 Subject: [PATCH 02/12] Use the metadata title for the SDL window title --- 32blit-sdl/Main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/32blit-sdl/Main.cpp b/32blit-sdl/Main.cpp index a2a078258..bbb9b13ca 100644 --- a/32blit-sdl/Main.cpp +++ b/32blit-sdl/Main.cpp @@ -13,6 +13,7 @@ #include "System.hpp" #include "Renderer.hpp" #include "Audio.hpp" +#include "UserCode.hpp" #ifdef VIDEO_CAPTURE #include "VideoCapture.hpp" @@ -112,13 +113,13 @@ void handle_event(SDL_Event &event) { } else if (event.type == System::timer_event) { switch(event.user.code) { case 0: - SDL_SetWindowTitle(window, WINDOW_TITLE); + SDL_SetWindowTitle(window, metadata_title); break; case 1: - SDL_SetWindowTitle(window, WINDOW_TITLE " [SLOW]"); + SDL_SetWindowTitle(window, (std::string(metadata_title) + " [SLOW]").c_str()); break; case 2: - SDL_SetWindowTitle(window, WINDOW_TITLE " [FROZEN]"); + SDL_SetWindowTitle(window, (std::string(metadata_title) + " [FROZEN]").c_str()); break; } } @@ -149,7 +150,7 @@ int main(int argc, char *argv[]) { } window = SDL_CreateWindow( - WINDOW_TITLE, + metadata_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, System::width*2, System::height*2, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE From 9a862681266a8bf6c21c94931980d28e27c81d20 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 19:34:54 +0000 Subject: [PATCH 03/12] Drop WINDOW_TITLE stuff Unused now --- 32blit-sdl/CMakeLists.txt | 9 --------- 32blit-sdl/Main.cpp | 4 ---- 2 files changed, 13 deletions(-) diff --git a/32blit-sdl/CMakeLists.txt b/32blit-sdl/CMakeLists.txt index 8a2ce5705..dc3b601bc 100644 --- a/32blit-sdl/CMakeLists.txt +++ b/32blit-sdl/CMakeLists.txt @@ -91,15 +91,6 @@ if(SDL2_IMAGE_DLL) install(FILES ${SDL2_IMAGE_DLL} DESTINATION bin) endif() -if(NOT 32BLIT_SDL_TITLE) - set(32BLIT_SDL_TITLE CMake!) -endif() - -target_compile_definitions(BlitHalSDL - PRIVATE - -DWINDOW_TITLE=\"${32BLIT_SDL_TITLE}\" -) - if(DEFINED VIDEO_CAPTURE AND VIDEO_CAPTURE) find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h) find_library(AVCODEC_LIBRARY avcodec) diff --git a/32blit-sdl/Main.cpp b/32blit-sdl/Main.cpp index bbb9b13ca..2349cf4e2 100644 --- a/32blit-sdl/Main.cpp +++ b/32blit-sdl/Main.cpp @@ -19,10 +19,6 @@ #include "VideoCapture.hpp" #endif -#ifndef WINDOW_TITLE -#define WINDOW_TITLE "32blit development (SDL)" -#endif - static bool running = true; SDL_Window* window = nullptr; From da624aa575fed459020c7d070e4fa93c73cadf57 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 24 Nov 2020 20:14:35 +0000 Subject: [PATCH 04/12] Move setting user_tick before calling init So that calling blit_user_code_running returns true --- 32blit-stm32/Src/32blit.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/32blit-stm32/Src/32blit.cpp b/32blit-stm32/Src/32blit.cpp index aa7200326..eaca2ad8b 100644 --- a/32blit-stm32/Src/32blit.cpp +++ b/32blit-stm32/Src/32blit.cpp @@ -963,7 +963,14 @@ void blit_switch_execution(uint32_t address) if(game_header->magic == blit_game_magic) { // load function pointers auto init = (BlitInitFunction)((uint8_t *)game_header->init + address); + + // set these up early so that blit_user_code_running works in code called from init + user_render = (BlitRenderFunction) ((uint8_t *)game_header->render + address); + user_tick = (BlitTickFunction) ((uint8_t *)game_header->tick + address); + if(!init(address)) { + user_render = nullptr; + user_tick = nullptr; // this would just be a return, but qspi is already mapped by this point persist.reset_target = prtFirmware; SCB_CleanDCache(); @@ -973,8 +980,8 @@ void blit_switch_execution(uint32_t address) persist.last_game_offset = address; - blit::render = user_render = (BlitRenderFunction) ((uint8_t *)game_header->render + address); - do_tick = user_tick = (BlitTickFunction) ((uint8_t *)game_header->tick + address); + blit::render = user_render; + do_tick = user_tick; return; } // anything flashed at a non-zero offset should have a valid header From a87acfe350c08fe7f317995f8d08205e3ccf6fe3 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 21:02:51 +0000 Subject: [PATCH 05/12] Move the raw metadata struct somewhere more re-usable --- 32blit-stm32/Inc/executable.hpp | 10 ++++++++++ firmware/metadata.cpp | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/32blit-stm32/Inc/executable.hpp b/32blit-stm32/Inc/executable.hpp index be586a79f..ef80d7412 100644 --- a/32blit-stm32/Inc/executable.hpp +++ b/32blit-stm32/Inc/executable.hpp @@ -17,4 +17,14 @@ struct BlitGameHeader { uint32_t end; uint32_t start; +}; + +// missing the "BLITMETA" header and size +struct RawMetadata { + uint32_t crc32; + char datetime[16]; + char title[25]; + char description[129]; + char version[17]; + char author[17]; }; \ No newline at end of file diff --git a/firmware/metadata.cpp b/firmware/metadata.cpp index fc30fc303..5d08f7ce8 100644 --- a/firmware/metadata.cpp +++ b/firmware/metadata.cpp @@ -9,15 +9,6 @@ using namespace blit; -struct RawMetadata { - uint32_t crc32; - char datetime[16]; - char title[25]; - char description[129]; - char version[17]; - char author[17]; -}; - void parse_metadata(char *data, uint16_t metadata_len, BlitGameMetadata &metadata, bool unpack_images) { metadata.length = metadata_len; From 8c73bb689be36499be8c1606b510d8e25c848c62 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 21:04:37 +0000 Subject: [PATCH 06/12] Add a function to the API for save paths --- 32blit-sdl/File.cpp | 10 ++++++++++ 32blit-sdl/File.hpp | 3 ++- 32blit-sdl/System.cpp | 1 + 32blit-stm32/Inc/file.hpp | 3 ++- 32blit-stm32/Src/32blit.cpp | 1 + 32blit-stm32/Src/file.cpp | 31 +++++++++++++++++++++++++++++++ 32blit/engine/api_private.hpp | 1 + 7 files changed, 48 insertions(+), 2 deletions(-) diff --git a/32blit-sdl/File.cpp b/32blit-sdl/File.cpp index b603dac3f..063dbf4ca 100644 --- a/32blit-sdl/File.cpp +++ b/32blit-sdl/File.cpp @@ -13,6 +13,7 @@ #include "SDL.h" #include "File.hpp" +#include "UserCode.hpp" static std::string basePath; @@ -178,4 +179,13 @@ bool rename_file(const std::string &old_name, const std::string &new_name) { bool remove_file(const std::string &path) { return remove((basePath + path).c_str()) == 0; +} + +std::string get_save_path() { + auto tmp = SDL_GetPrefPath(metadata_author, metadata_title); + std::string ret(tmp); + + SDL_free(tmp); + + return ret; } \ No newline at end of file diff --git a/32blit-sdl/File.hpp b/32blit-sdl/File.hpp index 90c3720ca..fe9abb074 100644 --- a/32blit-sdl/File.hpp +++ b/32blit-sdl/File.hpp @@ -17,4 +17,5 @@ bool file_exists(const std::string &path); bool directory_exists(const std::string &path); bool create_directory(const std::string &path); bool rename_file(const std::string &old_name, const std::string &new_name); -bool remove_file(const std::string &path); \ No newline at end of file +bool remove_file(const std::string &path); +std::string get_save_path(); \ No newline at end of file diff --git a/32blit-sdl/System.cpp b/32blit-sdl/System.cpp index d3c152962..6fc545a65 100644 --- a/32blit-sdl/System.cpp +++ b/32blit-sdl/System.cpp @@ -157,6 +157,7 @@ void System::run() { blit::api.create_directory = ::create_directory; blit::api.rename_file = ::rename_file; blit::api.remove_file = ::remove_file; + blit::api.get_save_path = ::get_save_path; blit::api.enable_us_timer = ::enable_us_timer; blit::api.get_us_timer = ::get_us_timer; diff --git a/32blit-stm32/Inc/file.hpp b/32blit-stm32/Inc/file.hpp index 38eadd045..b2fb84f6c 100644 --- a/32blit-stm32/Inc/file.hpp +++ b/32blit-stm32/Inc/file.hpp @@ -16,4 +16,5 @@ bool file_exists(const std::string &path); bool directory_exists(const std::string &path); bool create_directory(const std::string &path); bool rename_file(const std::string &old_name, const std::string &new_name); -bool remove_file(const std::string &path); \ No newline at end of file +bool remove_file(const std::string &path); +std::string get_save_path(); \ No newline at end of file diff --git a/32blit-stm32/Src/32blit.cpp b/32blit-stm32/Src/32blit.cpp index eaca2ad8b..cfb922e9d 100644 --- a/32blit-stm32/Src/32blit.cpp +++ b/32blit-stm32/Src/32blit.cpp @@ -429,6 +429,7 @@ void blit_init() { blit::api.create_directory = ::create_directory; blit::api.rename_file = ::rename_file; blit::api.remove_file = ::remove_file; + blit::api.get_save_path = ::get_save_path; blit::api.enable_us_timer = ::enable_us_timer; blit::api.get_us_timer = ::get_us_timer; diff --git a/32blit-stm32/Src/file.cpp b/32blit-stm32/Src/file.cpp index 6e8f0082d..2efc7c57b 100644 --- a/32blit-stm32/Src/file.cpp +++ b/32blit-stm32/Src/file.cpp @@ -1,9 +1,12 @@ #include +#include #include #include "fatfs.h" #include "file.hpp" +#include "32blit.h" +#include "executable.hpp" void *open_file(const std::string &file, int mode) { FIL *f = new FIL(); @@ -134,4 +137,32 @@ bool rename_file(const std::string &old_name, const std::string &new_name) { bool remove_file(const std::string &path) { return f_unlink(path.c_str()) == FR_OK; +} + +std::string get_save_path() { + std::string app_name; + + if(!blit_user_code_running()) + app_name = "_firmware"; + else { + // TODO: this probably can be used for other things + auto game_ptr = reinterpret_cast(0x90000000 + persist.last_game_offset); + + auto header = reinterpret_cast(game_ptr); + + if(header->magic == blit_game_magic) { + auto end_ptr = game_ptr + (header->end - 0x90000000); + if(memcmp(end_ptr, "BLITMETA", 8) == 0) { + auto meta = reinterpret_cast(end_ptr + 10); + app_name = meta->title; + } + } + + if(app_name.empty()) { + // fallback to offset + app_name = std::to_string(persist.last_game_offset); + } + } + + return ".blit/" + app_name + "/"; } \ No newline at end of file diff --git a/32blit/engine/api_private.hpp b/32blit/engine/api_private.hpp index 1d59c0bef..7f8a98739 100644 --- a/32blit/engine/api_private.hpp +++ b/32blit/engine/api_private.hpp @@ -54,6 +54,7 @@ namespace blit { bool (*create_directory) (const std::string &path); bool (*rename_file) (const std::string &old_name, const std::string &new_name); bool (*remove_file) (const std::string &path); + std::string (*get_save_path)(); // profiler void (*enable_us_timer)(); From 6c402ee4f59c7c87189ccf89e4914cb686bd3618 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 21:27:38 +0000 Subject: [PATCH 07/12] Make sure dir exists in get_save_path SDL_GetPrefPath already does this --- 32blit-stm32/Src/file.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/32blit-stm32/Src/file.cpp b/32blit-stm32/Src/file.cpp index 2efc7c57b..dd90462b0 100644 --- a/32blit-stm32/Src/file.cpp +++ b/32blit-stm32/Src/file.cpp @@ -142,6 +142,9 @@ bool remove_file(const std::string &path) { std::string get_save_path() { std::string app_name; + if(!directory_exists(".blit")) + create_directory(".blit"); + if(!blit_user_code_running()) app_name = "_firmware"; else { @@ -164,5 +167,9 @@ std::string get_save_path() { } } + // make sure it exists + if(!directory_exists(".blit/" + app_name)) + create_directory(".blit/" + app_name); + return ".blit/" + app_name + "/"; } \ No newline at end of file From e2b131f5da543e96c221dbd8bec4d78f4a117892 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 24 Nov 2020 17:57:08 +0000 Subject: [PATCH 08/12] Allow opening files under the SDL save path --- 32blit-sdl/File.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/32blit-sdl/File.cpp b/32blit-sdl/File.cpp index 063dbf4ca..36c1d211e 100644 --- a/32blit-sdl/File.cpp +++ b/32blit-sdl/File.cpp @@ -37,6 +37,14 @@ void *open_file(const std::string &name, int mode) { return nullptr; auto file = SDL_RWFromFile((basePath + name).c_str(), str_mode); + + if(!file) { + // check if the path is under the save path + auto save_path = get_save_path(); + if(name.compare(0, save_path.length(), save_path) == 0) + file = SDL_RWFromFile(name.c_str(), str_mode); + } + return file; } From ea5a96ff66f69ed775c1b0c2580d02f06e37445c Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 23 Nov 2020 21:31:40 +0000 Subject: [PATCH 09/12] Add a game save API --- 32blit/32blit.hpp | 1 + 32blit/CMakeLists.txt | 3 ++- 32blit/engine/save.cpp | 13 +++++++++++++ 32blit/engine/save.hpp | 16 ++++++++++++++++ vs/32blit/32blit.vcxproj | 2 ++ 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 32blit/engine/save.cpp create mode 100644 32blit/engine/save.hpp diff --git a/32blit/32blit.hpp b/32blit/32blit.hpp index 88a86962d..84a20826a 100644 --- a/32blit/32blit.hpp +++ b/32blit/32blit.hpp @@ -6,6 +6,7 @@ #include "engine/output.hpp" #include "engine/input.hpp" #include "audio/audio.hpp" +#include "engine/save.hpp" #include "engine/timer.hpp" #include "engine/tweening.hpp" #include "graphics/blend.hpp" diff --git a/32blit/CMakeLists.txt b/32blit/CMakeLists.txt index c8900e594..b08e9d0c0 100644 --- a/32blit/CMakeLists.txt +++ b/32blit/CMakeLists.txt @@ -7,7 +7,8 @@ set(SOURCES engine/output.cpp engine/particle.cpp engine/profiler.cpp - engine/running_average.cpp + engine/running_average.cpp + engine/save.cpp engine/timer.cpp engine/tweening.cpp engine/version.cpp diff --git a/32blit/engine/save.cpp b/32blit/engine/save.cpp new file mode 100644 index 000000000..a5ba5995b --- /dev/null +++ b/32blit/engine/save.cpp @@ -0,0 +1,13 @@ +#include "save.hpp" +#include "api_private.hpp" +#include "file.hpp" + +namespace blit { + void read_save(char *data, uint32_t length, int slot) { + File(api.get_save_path() + "save" + std::to_string(slot)).read(0, length, data); + } + + void write_save(const char *data, uint32_t length, int slot) { + File(api.get_save_path() + "save" + std::to_string(slot), OpenMode::write).write(0, length, data); + } +} \ No newline at end of file diff --git a/32blit/engine/save.hpp b/32blit/engine/save.hpp new file mode 100644 index 000000000..c11b3f318 --- /dev/null +++ b/32blit/engine/save.hpp @@ -0,0 +1,16 @@ +#include + +namespace blit { + void read_save(char *data, uint32_t length, int slot = 0); + void write_save(const char *data, uint32_t length, int slot = 0); + + template + void read_save(T &data, int slot = 0) { + read_save(reinterpret_cast(&data), sizeof(T), slot); + } + + template + void write_save(const T &data, int slot = 0) { + write_save(reinterpret_cast(&data), sizeof(T), slot); + } +} \ No newline at end of file diff --git a/vs/32blit/32blit.vcxproj b/vs/32blit/32blit.vcxproj index 5ff57b245..f455af8e2 100644 --- a/vs/32blit/32blit.vcxproj +++ b/vs/32blit/32blit.vcxproj @@ -155,6 +155,7 @@ + @@ -185,6 +186,7 @@ + From f9e8dc06b815ea7b6aecf2c729e57ccbf81c6f0d Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 24 Nov 2020 17:56:33 +0000 Subject: [PATCH 10/12] Return if load was successful --- 32blit/engine/save.cpp | 6 ++++-- 32blit/engine/save.hpp | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/32blit/engine/save.cpp b/32blit/engine/save.cpp index a5ba5995b..53b6a812e 100644 --- a/32blit/engine/save.cpp +++ b/32blit/engine/save.cpp @@ -3,8 +3,10 @@ #include "file.hpp" namespace blit { - void read_save(char *data, uint32_t length, int slot) { - File(api.get_save_path() + "save" + std::to_string(slot)).read(0, length, data); + bool read_save(char *data, uint32_t length, int slot) { + File file(api.get_save_path() + "save" + std::to_string(slot)); + + return file.is_open() && uint32_t(file.read(0, length, data)) == length; } void write_save(const char *data, uint32_t length, int slot) { diff --git a/32blit/engine/save.hpp b/32blit/engine/save.hpp index c11b3f318..7193cac07 100644 --- a/32blit/engine/save.hpp +++ b/32blit/engine/save.hpp @@ -1,12 +1,12 @@ #include namespace blit { - void read_save(char *data, uint32_t length, int slot = 0); + bool read_save(char *data, uint32_t length, int slot = 0); void write_save(const char *data, uint32_t length, int slot = 0); template - void read_save(T &data, int slot = 0) { - read_save(reinterpret_cast(&data), sizeof(T), slot); + bool read_save(T &data, int slot = 0) { + return read_save(reinterpret_cast(&data), sizeof(T), slot); } template From 6388f4df1d948738c21c3eae61a7eefcb74f2ea8 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 24 Nov 2020 20:17:39 +0000 Subject: [PATCH 11/12] Add save example --- examples/CMakeLists.txt | 1 + examples/saves/CMakeLists.txt | 8 ++++++ examples/saves/metadata.yml | 8 ++++++ examples/saves/saves.cpp | 53 +++++++++++++++++++++++++++++++++++ examples/saves/saves.hpp | 9 ++++++ site/examples/index.html | 2 +- 6 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 examples/saves/CMakeLists.txt create mode 100644 examples/saves/metadata.yml create mode 100644 examples/saves/saves.cpp create mode 100644 examples/saves/saves.hpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 79f4febe9..25dd040cb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(profiler-test) #add_subdirectory(racer) add_subdirectory(raycaster) add_subdirectory(rotozoom) +add_subdirectory(saves) add_subdirectory(scrolly-tile) add_subdirectory(serial-debug) add_subdirectory(shmup) diff --git a/examples/saves/CMakeLists.txt b/examples/saves/CMakeLists.txt new file mode 100644 index 000000000..51086c532 --- /dev/null +++ b/examples/saves/CMakeLists.txt @@ -0,0 +1,8 @@ + +cmake_minimum_required(VERSION 3.8) +project (saves) +set(32BLIT_PATH "../../" CACHE PATH "Path to 32blit.cmake") +include (${32BLIT_PATH}/32blit.cmake) + +blit_executable (saves saves.cpp) +blit_metadata (saves metadata.yml) \ No newline at end of file diff --git a/examples/saves/metadata.yml b/examples/saves/metadata.yml new file mode 100644 index 000000000..bebf8d0a6 --- /dev/null +++ b/examples/saves/metadata.yml @@ -0,0 +1,8 @@ +title: Saves +description: Save data example. +author: daft_freak +splash: + file: ../no-image.png +icon: + file: ../no-icon.png +version: v1.0.0 \ No newline at end of file diff --git a/examples/saves/saves.cpp b/examples/saves/saves.cpp new file mode 100644 index 000000000..bf11d0b23 --- /dev/null +++ b/examples/saves/saves.cpp @@ -0,0 +1,53 @@ +#include + +#include "saves.hpp" + +using namespace blit; + +// The data you want to save. Should not contain any pointers or other data that can't be written to a file as-is. +struct MyGameSave { + char name[10]; + int32_t score; +}; + +MyGameSave save_data; + +void init() { + // Attempt to load the first save slot. + if(read_save(save_data)) { + // Loaded sucessfully! + } else { + // No save file or it failed to load, set up some defaults. + strncpy(save_data.name, "My Name", 10); + save_data.score = 0; + } +} + +void render(uint32_t time_ms) { + screen.pen = Pen(20, 30, 40); + screen.clear(); + + screen.alpha = 255; + screen.pen = Pen(255, 255, 255); + screen.rectangle(Rect(0, 0, 320, 14)); + + screen.pen = Pen(0, 0, 0); + screen.text("Saves", minimal_font, Point(5, 4)); + + screen.pen = Pen(255, 255, 255); + char buf[100]; + snprintf(buf, 100, "Hello %s\n\nHold A to win!\n\nCurrent score: %i", save_data.name, save_data.score); + screen.text(buf, minimal_font, Point(screen.bounds.w / 2, screen.bounds.h / 2), false, TextAlign::center_center); +} + +void update(uint32_t time) { + // Give away some points + if(buttons & Button::A) { + save_data.score++; + } + + // Save all those points we gave away + if(buttons.released & Button::A) { + write_save(save_data); + } +} \ No newline at end of file diff --git a/examples/saves/saves.hpp b/examples/saves/saves.hpp new file mode 100644 index 000000000..b791bb454 --- /dev/null +++ b/examples/saves/saves.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +#include "32blit.hpp" + +void init(); +void update(uint32_t time); +void render(uint32_t time); \ No newline at end of file diff --git a/site/examples/index.html b/site/examples/index.html index b32af979a..1be857901 100644 --- a/site/examples/index.html +++ b/site/examples/index.html @@ -46,7 +46,7 @@ const examples = [ "audio-test", "audio-wave", "doom-fire", "fizzlefade", "flight", "geometry", "hardware-test", "logo", "matrix-test", "palette-cycle", "palette-swap", "particle", "platformer", "profiler-test", "raycaster", - "rotozoom", "scrolly-tile", "serial-debug", "shmup", "sprite-test", "text", "tilemap-test", + "rotozoom", "saves", "scrolly-tile", "serial-debug", "shmup", "sprite-test", "text", "tilemap-test", "tilt", "timer-test", "tunnel", "tween-demo", "tween-test", "voxel" ]; From e46e7c6f49bad9d825bb1ce6cebc6064fe6feeaa Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Tue, 24 Nov 2020 20:33:01 +0000 Subject: [PATCH 12/12] Little bit of documentation for saves --- 32blit/engine/save.cpp | 16 ++++++++++++++++ 32blit/engine/save.hpp | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/32blit/engine/save.cpp b/32blit/engine/save.cpp index 53b6a812e..960d12729 100644 --- a/32blit/engine/save.cpp +++ b/32blit/engine/save.cpp @@ -3,12 +3,28 @@ #include "file.hpp" namespace blit { + /** + * Read a block of save data from a save slot. + * + * \param data Pointer to store data into, should be at least `length` bytes + * \param length Expected length of save data + * \param slot Save slot to load, can be any number + * + * \return `true` if a save exists and contains enough data + */ bool read_save(char *data, uint32_t length, int slot) { File file(api.get_save_path() + "save" + std::to_string(slot)); return file.is_open() && uint32_t(file.read(0, length, data)) == length; } + /** + * Write a block of save data to a save slot. + * + * \param data Pointer to data to write, should be `length` bytes + * \param length Length of data to write + * \param slot Save slot to write to, can be any number + */ void write_save(const char *data, uint32_t length, int slot) { File(api.get_save_path() + "save" + std::to_string(slot), OpenMode::write).write(0, length, data); } diff --git a/32blit/engine/save.hpp b/32blit/engine/save.hpp index 7193cac07..5ffa78c4b 100644 --- a/32blit/engine/save.hpp +++ b/32blit/engine/save.hpp @@ -4,11 +4,17 @@ namespace blit { bool read_save(char *data, uint32_t length, int slot = 0); void write_save(const char *data, uint32_t length, int slot = 0); + /** + * \overload + */ template bool read_save(T &data, int slot = 0) { return read_save(reinterpret_cast(&data), sizeof(T), slot); } + /** + * \overload + */ template void write_save(const T &data, int slot = 0) { write_save(reinterpret_cast(&data), sizeof(T), slot);