Refactor data storage into separate source file

This commit is contained in:
ROllerozxa 2025-03-22 20:46:08 +01:00
commit ac2efc7cf3
15 changed files with 184 additions and 401 deletions

View file

@ -676,7 +676,7 @@ gui_spritesheet::init_atlas()
text_factor = (float)_tms.xppcm / (float)text_xppcm;
snprintf(cache_path, 511, "%s/textures.cache", tbackend_get_storage_path());
snprintf(cache_path, 511, "%s/textures.cache", tms_storage_cache_path());
gui_spritesheet::use_cache = false;
tms_infof("Textures cache path: %s", cache_path);
@ -723,7 +723,7 @@ gui_spritesheet::init_loading_font()
return;
}
snprintf(font_cache_path, 511, "%s/fonts.cache", tbackend_get_storage_path());
snprintf(font_cache_path, 511, "%s/fonts.cache", tms_storage_cache_path());
lvlbuf lb;

View file

@ -35,18 +35,8 @@
#include "gui.hh"
#include <ctime>
#include <errno.h>
#include <unistd.h>
#ifdef TMS_BACKEND_WINDOWS
#include <direct.h>
#define mkdir(dirname, ...) _mkdir(dirname)
#define create_dir(dirname, ...) _create_dir(dirname, 0)
#else
#define create_dir _create_dir
#endif
#ifdef BUILD_VALGRIND
#include <valgrind/valgrind.h>
#endif
@ -1729,43 +1719,13 @@ static const char *load_step_name[] = {
/* 16 */ "Save settings",
};
bool
_create_dir(const char *path, mode_t mode)
{
if (mkdir(path, mode) != 0) {
switch (errno) {
case EACCES:
tms_errorf("We lack permissions to create folder %s", path);
return false;
case EEXIST:
/* this should not be considered an error */
return true;
case ENAMETOOLONG:
tms_errorf("Name of directory %s is too long.", path);
return false;
case ENOENT:
tms_errorf("Parent directory for %s not found.", path);
return false;
default:
tms_errorf("An unknown error occurs when attempting to create directory %s (%d)", path, errno);
return false;
}
}
return true;
}
static void
populate_community_host()
{
P.community_host = "principia-web.se";
char path[1024];
snprintf(path, 1023, "%s/community_host.txt", tbackend_get_storage_path());
snprintf(path, 1023, "%s/community_host.txt", tms_storage_path());
FILE *fh = fopen(path, "r");
if (!fh) return;
@ -1788,7 +1748,6 @@ initial_loader(int step)
{
static uint32_t last_time = SDL_GetTicks();
char tmp[512];
int retval = LOAD_CONT;
switch (step) {
@ -1796,19 +1755,6 @@ initial_loader(int step)
{
populate_community_host();
static const char *s_dirs[]={
"",
"/cache", "/cache/db", "/cache/local", "/cache/main", "/cache/sav",
"/lvl", "/lvl/db", "/lvl/local", "/lvl/main",
"/pkg", "/pkg/db", "/pkg/local", "/pkg/main",
"/sav"
};
for (int x=0; x<sizeof(s_dirs)/sizeof(const char*); x++) {
sprintf(tmp, "%s%s", tbackend_get_storage_path(), s_dirs[x]);
create_dir(tmp, S_IRWXU | S_IRWXG | S_IRWXO);
}
/**
* We must init the recipes for the factories "dynamically" like this,
* because we have to make sure the item worths are already initialized.

View file

@ -508,7 +508,7 @@ save_cache(lvlbuf *lb)
void
mesh_factory::init_models(void)
{
snprintf(cache_path, 511, "%s/models.cache", tbackend_get_storage_path());
snprintf(cache_path, 511, "%s/models.cache", tms_storage_cache_path());
GLuint err = glGetError();
if (err != 0) {

View file

@ -92,7 +92,7 @@ init_curl()
exit(1);
}
snprintf(cookie_file, 1024, "%s/c", tbackend_get_storage_path());
snprintf(cookie_file, 1024, "%s/c", tms_storage_path());
lock_curl("initial_loader-curl_init");
P.curl = curl_easy_init();
@ -377,7 +377,7 @@ _get_featured_levels(void *_num)
CURLcode r;
char featured_data_path[1024];
snprintf(featured_data_path, 1023, "%s/fl.cache", tbackend_get_storage_path());
snprintf(featured_data_path, 1023, "%s/fl.cache", tms_storage_cache_path());
struct MemoryStruct chunk;
chunk.memory = (char*)malloc(1);
@ -920,7 +920,7 @@ _submit_score(void *p)
char data_path[1024];
const char *storage = tbackend_get_storage_path();
const char *storage = tms_storage_path();
snprintf(data_path, 1023, "%s/data.bin", storage);
int highscore_level_offset = highscore_offset(W->level.community_id);

View file

@ -16,9 +16,8 @@
#define tms_fatalf(...)
#define tms_errorf(...)
static const char *tbackend_get_storage_path() {
return "/tmp/";
}
static const char *tms_storage_path() { return "/tmp/"; }
static const char *tms_storage_cache_path() { return "/tmp/"; }
#else
#include <tms/bindings/cpp/cpp.hh>
#endif
@ -672,9 +671,13 @@ pkgman::get_pkg_path(int type)
/* main levels are stored internally in data/ */
snprintf((char*)_pkg_path[type], 1023, "data/pkg/%s",
_dir_names[type]);
} else if (type == LEVEL_DB) {
snprintf((char*)_pkg_path[type], 1023, "%s/pkg/%s",
tms_storage_cache_path(),
_dir_names[type]);
} else {
snprintf((char*)_pkg_path[type], 1023, "%s/pkg/%s",
tbackend_get_storage_path(),
tms_storage_path(),
_dir_names[type]);
}
}
@ -700,7 +703,7 @@ pkgman::get_level_path(int level_type)
_state_path = (char*)malloc(1024); /* XXX free this somewhere */
snprintf((char*)_state_path, 1023,
"%s/sav",
tbackend_get_storage_path());
tms_storage_path());
}
return _state_path;
@ -722,11 +725,16 @@ pkgman::get_level_path(int level_type)
} else if (level_type == LEVEL_SYS) {
snprintf((char*)_level_path[level_type], 1023,
"%s/cache/local",
tbackend_get_storage_path());
tms_storage_cache_path());
} else if (level_type == LEVEL_DB) {
snprintf((char*)_level_path[level_type], 1023,
"%s/lvl/%s",
tms_storage_cache_path(),
_dir_names[level_type]);
} else {
snprintf((char*)_level_path[level_type], 1023,
"%s/lvl/%s",
tbackend_get_storage_path(),
tms_storage_path(),
_dir_names[level_type]);
}
}
@ -769,7 +777,7 @@ pkgman::get_cache_path(int level_type)
snprintf((char*)_cache_state_path, 1023,
"%s/cache/sav",
tbackend_get_storage_path());
tms_storage_cache_path());
}
return _cache_state_path;
@ -785,7 +793,7 @@ pkgman::get_cache_path(int level_type)
snprintf((char*)_cache_path[level_type], 1023,
"%s/cache/%s",
tbackend_get_storage_path(),
tms_storage_cache_path(),
_dir_names[level_type]);
}

View file

@ -53,7 +53,7 @@ progress::init(char *custom_path/*=0*/)
#ifdef _NO_TMS
return;
#else
const char *storage = tbackend_get_storage_path();
const char *storage = tms_storage_path();
snprintf(tmp, 1023, "%s/data.bin", storage);
#endif
}
@ -230,7 +230,7 @@ progress::commit()
}
char filename[1024];
const char *storage = tbackend_get_storage_path();
const char *storage = tms_storage_path();
snprintf(filename, 1023, "%s/data.bin", storage);
long crc_pos[4]={0,0,0,0};

View file

@ -122,11 +122,10 @@ _settings::init()
this->add("score_ask_before_submitting", S_BOOL, false);
this->add("score_automatically_submit", S_BOOL, true);
char filename[1024];
sprintf(filename, "%s/settings.ini", tbackend_get_storage_path());
sprintf(this->filename, "%s/settings.ini", tms_storage_path());
FILE *fh;
if ((fh = fopen(filename, "r")) == NULL) {
if ((fh = fopen(this->filename, "r")) == NULL) {
if (errno == ENOENT) {
tms_infof("file doesn't exist, create it!");
this->save();
@ -142,9 +141,7 @@ _settings::init()
bool
_settings::load(void)
{
char filename[1024];
sprintf(filename, "%s/settings.ini", tbackend_get_storage_path());
FILE *fh = fopen(filename, "r");
FILE *fh = fopen(this->filename, "r");
if (!fh) {
tms_errorf("Unable to open settings file for reading.");
@ -260,11 +257,7 @@ _settings::save(void)
if (RUNNING_ON_VALGRIND) return true;
#endif
/* TODO: store filename in the class, char[1024] settings_file, to be
* set in init*/
char filename[1024];
sprintf(filename, "%s/settings.ini", tbackend_get_storage_path());
FILE *fh = fopen(filename, "w+");
FILE *fh = fopen(this->filename, "w+");
if (!fh) {
tms_errorf("An error occured when attempting to open settings file.");

View file

@ -121,6 +121,8 @@ extern class _settings {
return this->_data.end();
}
char filename[1024];
public:
setting*& operator[] (const char* key) {

View file

@ -38,19 +38,15 @@
FILE *_f_out = stdout;
static int _storage_type = 0;
SDL_Window *_window;
int keys[235];
int mouse_down;
static char *_storage_path = 0;
static int T_intercept_input(SDL_Event ev);
static void mainloop();
extern "C" int tbackend_init_surface();
extern "C" const char *tbackend_get_storage_path(void);
static void _catch_signal(int signal)
{
@ -103,18 +99,14 @@ int main(int argc, char **argv)
// Switch to portable if ./portable.txt exists next to binary
if (access("portable.txt", F_OK) == 0) {
tms_infof("We're becoming portable!");
_storage_type = 1;
tms_storage_set_portable(true);
}
#ifdef TMS_BACKEND_WINDOWS
mkdir(tbackend_get_storage_path());
#else
mkdir(tbackend_get_storage_path(), S_IRWXU | S_IRWXG | S_IRWXO);
#endif
tms_storage_create_dirs();
#if !defined(DEBUG) && !defined(__EMSCRIPTEN__)
char logfile[1024];
snprintf(logfile, 1023, "%s/run.log", tbackend_get_storage_path());
snprintf(logfile, 1023, "%s/run.log", tms_storage_path());
tms_infof("Redirecting log output to %s", logfile);
FILE *log = fopen(logfile, "w+");
@ -631,34 +623,3 @@ T_intercept_input(SDL_Event ev)
return T_OK;
}
const char *tbackend_get_storage_path(void)
{
#ifdef __EMSCRIPTEN__
return SDL_GetPrefPath("Bithack", "Principia");
#endif
if (!_storage_path) {
char *path = (char*)malloc(512);
if (_storage_type == 0) { // System (Installed)
#ifdef TMS_BACKEND_WINDOWS
strcpy(path, getenv("USERPROFILE"));
strcat(path, "\\Principia");
#else
struct passwd *pw = getpwuid(getuid());
strcpy(path, pw->pw_dir);
strcat(path, "/.principia");
#endif
} else if (_storage_type == 1) { // Portable
char* exedir = SDL_GetBasePath();
strcpy(path, exedir);
strcat(path, "userdata");
}
_storage_path = path;
tms_infof("Storage path: %s", path);
}
return _storage_path;
}

View file

@ -7,6 +7,7 @@
#include <tms/core/event.h>
#include <tms/core/tms.h>
#include <tms/backend/opengl.h>
#include <tms/core/storage.h>
#include "SDL.h"
#include <jni.h>
@ -18,7 +19,6 @@ int keys[235];
int mouse_down[64];
extern "C" int tbackend_init_surface();
extern "C" const char *tbackend_get_storage_path(void);
static int T_intercept_input(SDL_Event ev);
@ -29,6 +29,8 @@ SDL_main(int argc, char **argv)
int done = 0;
int do_step = 1;
tms_storage_create_dirs();
tms_init();
if (_tms.screen == 0)
@ -207,8 +209,3 @@ T_intercept_input(SDL_Event ev)
return T_OK;
}
const char *tbackend_get_storage_path(void)
{
return SDL_AndroidGetExternalStoragePath();
}

View file

@ -1,262 +0,0 @@
// iOS backend
// (we have absolutely no idea if this still works)
#include <unistd.h>
#include <sys/time.h>
#include <tms/core/project.h>
#include <tms/core/event.h>
#include <tms/core/tms.h>
#include "opengl.h"
#include <SDL.h>
SDL_Window *_window;
int keys[235];
int mouse_down[64];
static int T_intercept_input(SDL_Event ev);
int
SDL_main(int argc, char **argv)
{
SDL_Event ev;
int done = 0;
int do_step = 1;
tms_init();
if (tms.screen == 0)
tms_fatalf("context has no initial screen, bailing out");
do {
int i;
if (do_step) {
for (i = 0; i < 235; ++i) {
if (keys[i] == 1) {
struct tms_event spec;
spec.type = TMS_EV_KEY_DOWN;
spec.data.key.keycode = i;
tms_event_push(spec);
}
}
}
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_WINDOWEVENT:
{
switch (ev.window.event) {
//case SDL_WINDOWEVENT_FOCUS_LOST:
case SDL_WINDOWEVENT_MINIMIZED:
tproject_soft_pause();
tms_infof("FOCUS LOST ---------------");
do_step = 0;
break;
//case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_RESTORED:
tms_infof("FOCUS GAINED");
do_step = 1;
tproject_soft_resume();
break;
}
}
break;
case SDL_QUIT:
tms.state = TMS_STATE_QUITTING;
//done = 1;
break;
case SDL_KEYDOWN:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 1;
break;
case SDL_KEYUP:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 0;
break;
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
case SDL_FINGERUP:
T_intercept_input(ev);
break;
case SDL_TEXTINPUT:
T_intercept_input(ev);
break;
}
}
if (do_step) {
tms_step();
tms_begin_frame();
tms_render();
SDL_GL_SwapWindow(_window);
tms_end_frame();
} else {
SDL_Delay(100);
}
// usleep(15000);
} while (tms.state != TMS_STATE_QUITTING);
return 0;
}
int
tbackend_init_surface()
{
/* Set up SDL, create a window */
tms_infof("Creating window...");
SDL_Init(SDL_INIT_VIDEO);
SDL_SetHint("SDL_HINT_ORIENTATIONS", "LandscapeRight");
SDL_SetHint("SDL_IOS_ORIENTATIONS", "LandscapeRight");
SDL_DisplayMode mode;
int num_modes = SDL_GetNumDisplayModes(0);
int min_displ = 2000000000;
int max_displ = 0;
int min_displ_w, min_displ_h, max_displ_w, max_displ_h;
for (int x=0; x<num_modes; x++) {
SDL_GetDisplayMode(0, x, &mode);
tms_infof("display mode %d %d", mode.w, mode.h);
int displ = mode.w*mode.h;
if (displ < min_displ) {
min_displ = displ;
min_displ_w = mode.w;
min_displ_h = mode.h;
}
if (displ > max_displ) {
max_displ = displ;
max_displ_w = mode.w;
max_displ_h = mode.h;
}
}
if (max_displ_w < max_displ_h) {
int tmp = max_displ_w;
max_displ_w = max_displ_h;
max_displ_h = tmp;
}
if (min_displ_w < min_displ_h) {
int tmp = min_displ_w;
min_displ_w = min_displ_h;
min_displ_h = tmp;
}
SDL_GetDesktopDisplayMode(0, &mode);
tms_infof("max display mode: %d %d", max_displ_w, max_displ_h);
tms_infof("min display mode: %d %d", min_displ_w, min_displ_h);
_window = SDL_CreateWindow("Principia", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
//mode.w, mode.h,
min_displ_w, min_displ_h,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN*/ | SDL_WINDOW_BORDERLESS);
//SDL_GetWindowSize(_window, &_tms.window_width, &_tms.window_height);
#if 0
tms.opengl_width = min_displ_w;
tms.opengl_height = min_displ_h;
#else
tms.opengl_width = max_displ_w;
tms.opengl_height = max_displ_h;
#endif
tms.window_width = max_displ_w;
tms.window_height = max_displ_h;
tms._window = _window;
tms.xppcm = IOS_density_x / 2.54;
tms.yppcm = IOS_density_y / 2.54;
tms_infof("OpenGL dimensions: %d %d", tms.opengl_width, tms.opengl_height);
tms_infof("Window dimensions: %d %d", _tms.window_width, _tms.window_height);
tms_infof("Device PPCM: %f %f", tms.xppcm, tms.yppcm);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_CreateContext(_window);
//#include "glhacks/definc.h"
return T_OK;
}
int
T_intercept_input(SDL_Event ev)
{
struct tms_event spec;
spec.type = -1;
switch (ev.type) {
case SDL_KEYDOWN:
if (keys[ev.key.keysym.scancode] == 1) {
return T_OK;
}
spec.type = TMS_EV_KEY_PRESS;
spec.data.key.keycode = ev.key.keysym.scancode;
spec.data.key.mod = ev.key.keysym.mod;
break;
case SDL_KEYUP:
spec.type = TMS_EV_KEY_UP;
spec.data.key.keycode = ev.key.keysym.scancode;
spec.data.key.mod = ev.key.keysym.mod;
break;
case SDL_FINGERDOWN:
spec.type = TMS_EV_POINTER_DOWN;
spec.data.button.pointer_id = ev.tfinger.fingerId;
tms_infof("event: %d %d", ev.tfinger.x, ev.tfinger.y);
spec.data.button.x = ((float)ev.tfinger.x / 65536.f)*(float)_tms.window_width;
spec.data.button.y = tms.window_height - ((float)ev.tfinger.y / 65536.f) * (float)_tms.window_height;
//tms_infof("event: %f %f", spec.data.button.x, spec.data.button.y);
break;
case SDL_FINGERUP:
spec.type = TMS_EV_POINTER_UP;
spec.data.button.pointer_id = ev.tfinger.fingerId;
spec.data.button.x = ((float)ev.tfinger.x / 65536.f)*(float)_tms.window_width;
spec.data.button.y = tms.window_height - ((float)ev.tfinger.y / 65536.f) * (float)_tms.window_height;
break;
case SDL_FINGERMOTION:
spec.type = TMS_EV_POINTER_DRAG;
spec.data.button.pointer_id = ev.tfinger.fingerId;
spec.data.motion.x = ((float)ev.tfinger.x / 65536.f)*(float)_tms.window_width;
spec.data.motion.y = tms.window_height - ((float)ev.tfinger.y / 65536.f) * (float)_tms.window_height;
break;
case SDL_TEXTINPUT:
spec.type = TMS_EV_TEXT_INPUT;
memcpy(spec.data.text.text, ev.text.text, 32);
break;
}
tms_event_push(spec);
return T_OK;
}
const char *tbackend_get_storage_path(void)
{
return "../Documents";
}

View file

@ -56,7 +56,6 @@ static uint32_t snap_step_num = 0;
int screenshot(char *file_name, unsigned int x, unsigned int y, unsigned long width, unsigned long height);
extern "C" int tbackend_init_surface();
extern "C" const char *tbackend_get_storage_path(void);
void
@ -146,7 +145,7 @@ main(int argc, char **argv)
tms_infof("chdirring to %s", exedir);
(void)chdir(exedir);
mkdir(tbackend_get_storage_path(), S_IRWXU | S_IRWXG | S_IRWXO);
tms_storage_create_dirs();
tms_infof("Initializing SDL...");
SDL_Init(SDL_INIT_VIDEO);
@ -386,11 +385,6 @@ tbackend_init_surface()
return T_OK;
}
const char *tbackend_get_storage_path(void)
{
return "storage";
}
int
screenshot(char *path, unsigned int x, unsigned int y, unsigned long width, unsigned long height)
{

View file

@ -14,7 +14,7 @@ extern "C" {
int tbackend_init_surface(void);
const char *tbackend_get_storage_path();
#include "storage.h"
#ifdef __cplusplus
}

126
src/tms/core/storage.c Normal file
View file

@ -0,0 +1,126 @@
#include "storage.h"
#include "tms/backend/print.h"
#include <SDL.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef TMS_BACKEND_WINDOWS
#include <direct.h>
#define mkdir(dirname, ...) _mkdir(dirname)
#define create_dir(dirname, ...) _create_dir(dirname, 0)
#else
#include <pwd.h>
#include <sys/stat.h>
#define create_dir _create_dir
#endif
static char *_storage_path = 0;
static bool _storage_portable = false;
void tms_storage_set_portable(bool portable)
{
_storage_portable = portable;
}
bool
_create_dir(const char *path, mode_t mode)
{
if (mkdir(path, mode) != 0) {
switch (errno) {
case EACCES:
tms_errorf("We lack permissions to create folder %s", path);
return false;
case EEXIST:
/* this should not be considered an error */
return true;
case ENAMETOOLONG:
tms_errorf("Name of directory %s is too long.", path);
return false;
case ENOENT:
tms_errorf("Parent directory for %s not found.", path);
return false;
default:
tms_errorf("An unknown error occurs when attempting to create directory %s (%d)", path, errno);
return false;
}
}
return true;
}
const char *tms_storage_path(void)
{
#ifdef __ANDROID__
return SDL_AndroidGetExternalStoragePath();
#elif defined(__EMSCRIPTEN__)
return SDL_GetPrefPath("Bithack", "Principia");
#elif defined(SCREENSHOT_BUILD)
return "storage";
#else
if (_storage_path)
return _storage_path;
char *path = (char *)malloc(1024);
if (_storage_portable) { // Portable
char* exedir = SDL_GetBasePath();
strcpy(path, exedir);
strcat(path, "userdata");
} else { // System
#ifdef TMS_BACKEND_WINDOWS
strcpy(path, getenv("USERPROFILE"));
strcat(path, "\\Principia");
#else
struct passwd *pw = getpwuid(getuid());
strcpy(path, pw->pw_dir);
strcat(path, "/.principia");
#endif
}
_storage_path = path;
tms_infof("Storage path: %s", path);
return _storage_path;
#endif
}
const char *tms_storage_cache_path(void)
{
return tms_storage_path();
}
void tms_storage_create_dirs(void)
{
char tmp[1024];
static const char *s_dirs[]={
"",
"/lvl", "/lvl/local",
"/pkg", "/pkg/local",
"/sav"
};
for (int x=0; x<sizeof(s_dirs)/sizeof(const char*); x++) {
sprintf(tmp, "%s%s", tms_storage_path(), s_dirs[x]);
create_dir(tmp, S_IRWXU | S_IRWXG | S_IRWXO);
}
static const char *c_dirs[]={
"",
"/cache", "/cache/db", "/cache/local", "/cache/main", "/cache/sav",
"/lvl", "/lvl/db",
"/pkg", "/pkg/db"
};
for (int x=0; x<sizeof(c_dirs)/sizeof(const char*); x++) {
sprintf(tmp, "%s%s", tms_storage_cache_path(), c_dirs[x]);
create_dir(tmp, S_IRWXU | S_IRWXG | S_IRWXO);
}
}

18
src/tms/core/storage.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
void tms_storage_set_portable(bool portable);
const char *tms_storage_path(void);
const char *tms_storage_cache_path(void);
void tms_storage_create_dirs(void);
#ifdef __cplusplus
}
#endif