Skip to content

Commit

Permalink
Merge pull request #429 from Daft-Freak/saves
Browse files Browse the repository at this point in the history
SDL metadata strings and save data
  • Loading branch information
Gadgetoid authored Dec 7, 2020
2 parents 896285b + e46e7c6 commit 21250ab
Show file tree
Hide file tree
Showing 25 changed files with 257 additions and 35 deletions.
20 changes: 11 additions & 9 deletions 32blit-sdl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_library(BlitHalSDL STATIC
DefaultMetadata.cpp
File.cpp
Input.cpp
JPEG.cpp
Expand Down Expand Up @@ -88,15 +89,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)
Expand Down Expand Up @@ -195,4 +187,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()
12 changes: 12 additions & 0 deletions 32blit-sdl/DefaultMetadata.cpp
Original file line number Diff line number Diff line change
@@ -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";
18 changes: 18 additions & 0 deletions 32blit-sdl/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "SDL.h"

#include "File.hpp"
#include "UserCode.hpp"

static std::string basePath;

Expand All @@ -36,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;
}

Expand Down Expand Up @@ -178,4 +187,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;
}
3 changes: 2 additions & 1 deletion 32blit-sdl/File.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
bool remove_file(const std::string &path);
std::string get_save_path();
13 changes: 5 additions & 8 deletions 32blit-sdl/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@
#include "System.hpp"
#include "Renderer.hpp"
#include "Audio.hpp"
#include "UserCode.hpp"

#ifdef VIDEO_CAPTURE
#include "VideoCapture.hpp"
#endif

#ifndef WINDOW_TITLE
#define WINDOW_TITLE "32blit development (SDL)"
#endif

static bool running = true;

SDL_Window* window = nullptr;
Expand Down Expand Up @@ -112,13 +109,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;
}
}
Expand Down Expand Up @@ -149,7 +146,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
Expand Down
1 change: 1 addition & 0 deletions 32blit-sdl/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions 32blit-sdl/UserCode.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#pragma once
#include <string>

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;
10 changes: 10 additions & 0 deletions 32blit-stm32/Inc/executable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
};
3 changes: 2 additions & 1 deletion 32blit-stm32/Inc/file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
bool remove_file(const std::string &path);
std::string get_save_path();
12 changes: 10 additions & 2 deletions 32blit-stm32/Src/32blit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -963,7 +964,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();
Expand All @@ -973,8 +981,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
Expand Down
38 changes: 38 additions & 0 deletions 32blit-stm32/Src/file.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include <cstdint>
#include <cstring>
#include <map>

#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();
Expand Down Expand Up @@ -134,4 +137,39 @@ 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(!directory_exists(".blit"))
create_directory(".blit");

if(!blit_user_code_running())
app_name = "_firmware";
else {
// TODO: this probably can be used for other things
auto game_ptr = reinterpret_cast<uint8_t *>(0x90000000 + persist.last_game_offset);

auto header = reinterpret_cast<BlitGameHeader *>(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<RawMetadata *>(end_ptr + 10);
app_name = meta->title;
}
}

if(app_name.empty()) {
// fallback to offset
app_name = std::to_string(persist.last_game_offset);
}
}

// make sure it exists
if(!directory_exists(".blit/" + app_name))
create_directory(".blit/" + app_name);

return ".blit/" + app_name + "/";
}
1 change: 1 addition & 0 deletions 32blit/32blit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion 32blit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions 32blit/engine/api_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)();
Expand Down
31 changes: 31 additions & 0 deletions 32blit/engine/save.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "save.hpp"
#include "api_private.hpp"
#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);
}
}
22 changes: 22 additions & 0 deletions 32blit/engine/save.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <cstdint>

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<class T>
bool read_save(T &data, int slot = 0) {
return read_save(reinterpret_cast<char *>(&data), sizeof(T), slot);
}

/**
* \overload
*/
template<class T>
void write_save(const T &data, int slot = 0) {
write_save(reinterpret_cast<const char *>(&data), sizeof(T), slot);
}
}
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions examples/saves/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
8 changes: 8 additions & 0 deletions examples/saves/metadata.yml
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 21250ab

Please sign in to comment.