WIP virtual filesystem
This commit is contained in:
parent
02f1c935ff
commit
471f30083e
49 changed files with 1496 additions and 348 deletions
|
@ -11,7 +11,6 @@ else()
|
|||
endif()
|
||||
|
||||
option(RELATIVE "Use only relative paths to the executable and install everything in the same directory." ${RELATIVE_DEFAULT})
|
||||
option(USE_SDL2_PATHS "Use the SDL2 filesystem API to determine where to save settings." ON)
|
||||
option(NO_AUDIO "Build without audio support" OFF)
|
||||
option(DEBUG_USE_UBSAN "Enable the Undefined Behaviour Sanitizer (UBSan) in debug builds. Only disable if the compiler or target platform doesn't support it." ON)
|
||||
option(DEBUG_USE_ASAN "Enable the Address Sanitizer (ASan) and leak detection in debug builds." OFF)
|
||||
|
|
|
@ -87,16 +87,14 @@ set(SRCs
|
|||
rwops/rwops_zlib.c
|
||||
rwops/rwops_segment.c
|
||||
rwops/rwops_autobuf.c
|
||||
vfs/private.c
|
||||
vfs/public.c
|
||||
vfs/pathutil.c
|
||||
vfs/syspath_posix.c # TODO: write a win32 version of this
|
||||
vfs/union.c
|
||||
vfs/vdir.c
|
||||
)
|
||||
|
||||
if(USE_SDL2_PATHS)
|
||||
set(SRCs ${SRCs} paths/sdl.c)
|
||||
elseif(RELATIVE)
|
||||
set(SRCs ${SRCs} paths/relative.c)
|
||||
else()
|
||||
set(SRCs ${SRCs} paths/static.c)
|
||||
endif()
|
||||
|
||||
if(NO_AUDIO)
|
||||
set(SRCs ${SRCs}
|
||||
audio_null.c
|
||||
|
|
|
@ -67,9 +67,7 @@ static void bgm_cfg_volume_callback(ConfigIndex idx, ConfigValue v) {
|
|||
}
|
||||
|
||||
static void load_bgm_descriptions(void) {
|
||||
char *fullname = strjoin(get_prefix(), "bgm/bgm.conf", NULL);
|
||||
bgm_descriptions = parse_keyvalue_file(fullname, 16);
|
||||
free(fullname);
|
||||
bgm_descriptions = parse_keyvalue_file(BGM_PATH_PREFIX "bgm.conf", HT_DYNAMIC_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
|
||||
#include <SDL_mixer.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "global.h"
|
||||
|
@ -111,9 +109,8 @@ void audio_backend_set_bgm_volume(float gain) {
|
|||
char* audio_mixer_sound_path(const char *prefix, const char *name) {
|
||||
for(const char **ext = mixer_audio_exts; *ext; ++ext) {
|
||||
char *p = strjoin(prefix, name, *ext, NULL);
|
||||
struct stat statbuf;
|
||||
|
||||
if(!stat(p, &statbuf)) {
|
||||
if(vfs_query(p).exists) {
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ int cli_args(int argc, char **argv, CLIAction *a) {
|
|||
{{"shotmode", required_argument, 0, 's'}, "Select a shotmode (marisaA/youmuA/marisaB/youmuB)", "SMODE"},
|
||||
{{"frameskip", optional_argument, 0, 'f'}, "Disable FPS limiter, render only every %s frame", "FRAME"},
|
||||
{{"dumpstages", no_argument, 0, 'u'}, "Print a list of all stages in the game", 0},
|
||||
{{"vfs-tree", required_argument, 0, 't'}, "Print the virtual filesystem tree starting from %s", "PATH"},
|
||||
#endif
|
||||
{{"help", no_argument, 0, 'h'}, "Display this help."},
|
||||
{{0,0,0,0},0,0}
|
||||
|
@ -144,6 +145,10 @@ int cli_args(int argc, char **argv, CLIAction *a) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
a->type = CLI_DumpVFSTree,
|
||||
a->filename = strdup(optarg ? optarg : "");
|
||||
break;
|
||||
default:
|
||||
log_fatal("Unknown option (this shouldn’t happen)");
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ typedef enum {
|
|||
CLI_PlayReplay,
|
||||
CLI_SelectStage,
|
||||
CLI_DumpStages,
|
||||
CLI_DumpVFSTree,
|
||||
CLI_Quit,
|
||||
} CLIActionType;
|
||||
|
||||
|
|
35
src/config.c
35
src/config.c
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "global.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
static bool config_initialized = false;
|
||||
|
||||
|
@ -263,25 +262,18 @@ static void config_delete_unknown_entries(void) {
|
|||
delete_all_elements((void**)&unknowndefs, config_delete_unknown_entry);
|
||||
}
|
||||
|
||||
static char* config_path(const char *filename) {
|
||||
return strjoin(get_config_path(), "/", filename, NULL);
|
||||
}
|
||||
|
||||
static SDL_RWops* config_open(const char *filename, const char *mode) {
|
||||
char *buf = config_path(filename);
|
||||
SDL_RWops *out = SDL_RWFromFile(buf, mode);
|
||||
|
||||
free(buf);
|
||||
static SDL_RWops* config_open(const char *filename, VFSOpenMode mode) {
|
||||
SDL_RWops *out = vfs_open(CONFIG_FILE, mode);
|
||||
|
||||
if(!out) {
|
||||
log_warn("SDL_RWFromFile() failed: %s", SDL_GetError());
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void config_save(const char *filename) {
|
||||
SDL_RWops *out = config_open(filename, "w");
|
||||
void config_save(void) {
|
||||
SDL_RWops *out = config_open(CONFIG_FILE, VFS_MODE_WRITE);
|
||||
ConfigEntry *e = configdefs;
|
||||
|
||||
if(!out)
|
||||
|
@ -317,7 +309,10 @@ void config_save(const char *filename) {
|
|||
}
|
||||
|
||||
SDL_RWclose(out);
|
||||
log_info("Saved config '%s'", filename);
|
||||
|
||||
char *sp = vfs_syspath_or_repr(CONFIG_FILE);
|
||||
log_info("Saved config '%s'", sp);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
#define INTOF(s) ((int)strtol(s, NULL, 10))
|
||||
|
@ -362,12 +357,14 @@ static void config_set(const char *key, const char *val, void *data) {
|
|||
#undef INTOF
|
||||
#undef FLOATOF
|
||||
|
||||
void config_load(const char *filename) {
|
||||
char *path = config_path(filename);
|
||||
void config_load(void) {
|
||||
config_init();
|
||||
log_info("Loading configuration from %s", path);
|
||||
if(!parse_keyvalue_file_cb(path, config_set, NULL)) {
|
||||
|
||||
char *sp = vfs_syspath_or_repr(CONFIG_FILE);
|
||||
log_info("Loading configuration from %s", sp);
|
||||
free(sp);
|
||||
|
||||
if(!parse_keyvalue_file_cb(CONFIG_FILE, config_set, NULL)) {
|
||||
log_warn("Errors occured while parsing the configuration file");
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <SDL_keycode.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONFIG_FILE "storage/config"
|
||||
|
||||
/*
|
||||
Define these macros, then use CONFIGDEFS to expand them all for all config entries, or KEYDEFS for just keybindings.
|
||||
Don't forget to undef them afterwards.
|
||||
|
@ -180,8 +182,8 @@ KeyIndex config_key_from_gamepad_button(int btn);
|
|||
void config_reset(void);
|
||||
void config_init(void);
|
||||
void config_uninit(void);
|
||||
void config_load(const char *filename);
|
||||
void config_save(const char *filename);
|
||||
void config_load(void);
|
||||
void config_save(void);
|
||||
void config_set_callback(ConfigIndex idx, ConfigCallback callback);
|
||||
|
||||
#ifndef DEBUG
|
||||
|
|
|
@ -46,9 +46,6 @@
|
|||
#include "rwops/all.h"
|
||||
#include "cli.h"
|
||||
|
||||
#define FILE_PREFIX PREFIX "/share/taisei/"
|
||||
#define CONFIG_FILE "config"
|
||||
|
||||
enum {
|
||||
// defaults
|
||||
RESX = 800,
|
||||
|
|
114
src/main.c
114
src/main.c
|
@ -5,8 +5,6 @@
|
|||
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "global.h"
|
||||
|
@ -14,18 +12,20 @@
|
|||
#include "audio.h"
|
||||
#include "stage.h"
|
||||
#include "menu/mainmenu.h"
|
||||
#include "paths/native.h"
|
||||
#include "gamepad.h"
|
||||
#include "resource/bgm.h"
|
||||
#include "progress.h"
|
||||
#include "hashtable.h"
|
||||
#include "log.h"
|
||||
#include "cli.h"
|
||||
#include "vfs/public.h"
|
||||
|
||||
void taisei_shutdown(void) {
|
||||
#define STATIC_RESOURCE_PREFIX PREFIX "/share/taisei/"
|
||||
|
||||
static void taisei_shutdown(void) {
|
||||
log_info("Shutting down");
|
||||
|
||||
config_save(CONFIG_FILE);
|
||||
config_save();
|
||||
progress_save();
|
||||
progress_unload();
|
||||
|
||||
|
@ -37,6 +37,7 @@ void taisei_shutdown(void) {
|
|||
gamepad_shutdown();
|
||||
stage_free_array();
|
||||
config_uninit();
|
||||
vfs_uninit();
|
||||
|
||||
log_info("Good bye");
|
||||
SDL_Quit();
|
||||
|
@ -44,25 +45,23 @@ void taisei_shutdown(void) {
|
|||
log_shutdown();
|
||||
}
|
||||
|
||||
void init_log(void) {
|
||||
const char *pref = get_config_path();
|
||||
char *logpath = strfmt("%s/%s", pref, "log.txt");
|
||||
|
||||
static void init_log(void) {
|
||||
LogLevel lvls_console = log_parse_levels(LOG_DEFAULT_LEVELS_CONSOLE, getenv("TAISEI_LOGLVLS_CONSOLE"));
|
||||
LogLevel lvls_stdout = lvls_console & log_parse_levels(LOG_DEFAULT_LEVELS_STDOUT, getenv("TAISEI_LOGLVLS_STDOUT"));
|
||||
LogLevel lvls_stderr = lvls_console & log_parse_levels(LOG_DEFAULT_LEVELS_STDERR, getenv("TAISEI_LOGLVLS_STDERR"));
|
||||
LogLevel lvls_file = log_parse_levels(LOG_DEFAULT_LEVELS_FILE, getenv("TAISEI_LOGLVLS_FILE"));
|
||||
LogLevel lvls_backtrace = log_parse_levels(LOG_DEFAULT_LEVELS_BACKTRACE, getenv("TAISEI_LOGLVLS_BACKTRACE"));
|
||||
|
||||
log_init(LOG_DEFAULT_LEVELS, lvls_backtrace);
|
||||
log_add_output(lvls_stdout, SDL_RWFromFP(stdout, false));
|
||||
log_add_output(lvls_stderr, SDL_RWFromFP(stderr, false));
|
||||
log_add_output(lvls_file, SDL_RWFromFile(logpath, "w"));
|
||||
|
||||
free(logpath);
|
||||
}
|
||||
|
||||
int run_tests(void) {
|
||||
static void init_log_file(void) {
|
||||
LogLevel lvls_file = log_parse_levels(LOG_DEFAULT_LEVELS_FILE, getenv("TAISEI_LOGLVLS_FILE"));
|
||||
log_add_output(lvls_file, vfs_open("storage/log.txt", VFS_MODE_WRITE));
|
||||
}
|
||||
|
||||
static int run_tests(void) {
|
||||
if(tsrand_test()) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -101,6 +100,54 @@ static void init_sdl(void) {
|
|||
log_info("Using SDL %u.%u.%u", v.major, v.minor, v.patch);
|
||||
}
|
||||
|
||||
static void get_core_paths(char **res, char **storage) {
|
||||
#ifdef RELATIVE
|
||||
*res = SDL_GetBasePath();
|
||||
strappend(res, "data/");
|
||||
#else
|
||||
*res = strdup(STATIC_RESOURCE_PREFIX);
|
||||
#endif
|
||||
|
||||
*storage = SDL_GetPrefPath("", "taisei");
|
||||
}
|
||||
|
||||
static void init_vfs(bool silent) {
|
||||
char *res_path, *storage_path;
|
||||
get_core_paths(&res_path, &storage_path);
|
||||
|
||||
if(!silent) {
|
||||
log_info("Resource path: %s", res_path);
|
||||
log_info("Storage path: %s", storage_path);
|
||||
}
|
||||
|
||||
char *p = NULL;
|
||||
|
||||
struct mpoint_t {
|
||||
const char *dest; const char *syspath; bool mkdir;
|
||||
} mpts[] = {
|
||||
{"storage", storage_path, true},
|
||||
{"res", res_path, false},
|
||||
{"res", p = strfmt("%s/resources", storage_path), true},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
vfs_init();
|
||||
vfs_create_union_mountpoint("res");
|
||||
|
||||
for(struct mpoint_t *mp = mpts; mp->dest; ++mp) {
|
||||
if(!vfs_mount_syspath(mp->dest, mp->syspath, mp->mkdir)) {
|
||||
log_fatal("Failed to mount '%s': %s", mp->dest, vfs_get_error());
|
||||
}
|
||||
}
|
||||
|
||||
vfs_mkdir_required("storage/replays");
|
||||
vfs_mkdir_required("storage/screenshots");
|
||||
|
||||
free(p);
|
||||
free(res_path);
|
||||
free(storage_path);
|
||||
}
|
||||
|
||||
static void log_lib_versions(void) {
|
||||
log_info("Compiled against zlib %s", ZLIB_VERSION);
|
||||
log_info("Using zlib %s", zlibVersion());
|
||||
|
@ -114,7 +161,6 @@ int main(int argc, char **argv) {
|
|||
Replay replay = {0};
|
||||
int replay_idx = 0;
|
||||
|
||||
init_paths();
|
||||
init_log();
|
||||
|
||||
if(run_tests()) {
|
||||
|
@ -136,7 +182,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
return 0;
|
||||
} else if(a.type == CLI_PlayReplay) {
|
||||
if(!replay_load(&replay, a.filename, REPLAY_READ_ALL | REPLAY_READ_RAWPATH)) {
|
||||
if(!replay_load_syspath(&replay, a.filename, REPLAY_READ_ALL)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -144,26 +190,30 @@ int main(int argc, char **argv) {
|
|||
if(replay_idx < 0) {
|
||||
return 1;
|
||||
}
|
||||
} else if(a.type == CLI_DumpVFSTree) {
|
||||
init_vfs(true);
|
||||
|
||||
SDL_RWops *rwops = SDL_RWFromFP(stdout, false);
|
||||
|
||||
if(!rwops) {
|
||||
log_fatal("SDL_RWFromFP() failed: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
if(!vfs_print_tree(rwops, a.filename)) {
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
SDL_RWclose(rwops);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_RWclose(rwops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free_cli_action(&a);
|
||||
init_vfs(false);
|
||||
init_log_file();
|
||||
|
||||
log_info("Content path: %s", get_prefix());
|
||||
log_info("Userdata path: %s", get_config_path());
|
||||
|
||||
MKDIR(get_config_path());
|
||||
MKDIR(get_screenshots_path());
|
||||
MKDIR(get_replays_path());
|
||||
|
||||
if(chdir(get_prefix())) {
|
||||
log_fatal("chdir() failed: %s", strerror(errno));
|
||||
} else {
|
||||
char cwd[1024]; // i don't care if this is not enough for you, getcwd is garbage
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
log_info("Changed working directory to %s", cwd);
|
||||
}
|
||||
|
||||
config_load(CONFIG_FILE);
|
||||
config_load();
|
||||
|
||||
log_lib_versions();
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "global.h"
|
||||
#include "video.h"
|
||||
#include "stage.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
void enter_options(MenuData *menu, void *arg) {
|
||||
MenuData m;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "options.h"
|
||||
#include "global.h"
|
||||
#include "video.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
// --- Menu entry <-> config option binding stuff --- //
|
||||
|
||||
|
|
|
@ -6,14 +6,12 @@
|
|||
* Copyright (C) 2012, Alexeyew Andrew <https://github.com/nexAkari>
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include "global.h"
|
||||
#include "menu.h"
|
||||
#include "options.h"
|
||||
#include "mainmenu.h"
|
||||
#include "replayview.h"
|
||||
#include "paths/native.h"
|
||||
#include "plrmodes.h"
|
||||
#include "video.h"
|
||||
#include "common.h"
|
||||
|
@ -257,24 +255,24 @@ int replayview_cmp(const void *a, const void *b) {
|
|||
}
|
||||
|
||||
int fill_replayview_menu(MenuData *m) {
|
||||
DIR *dir = opendir(get_replays_path());
|
||||
struct dirent *e;
|
||||
VFSDir *dir = vfs_dir_open("storage/replays");
|
||||
const char *filename;
|
||||
int rpys = 0;
|
||||
|
||||
if(!dir) {
|
||||
log_warn("Could't read %s", get_replays_path());
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
char ext[5];
|
||||
snprintf(ext, 5, ".%s", REPLAY_EXTENSION);
|
||||
|
||||
while((e = readdir(dir))) {
|
||||
if(!strendswith(e->d_name, ext))
|
||||
while((filename = vfs_dir_read(dir))) {
|
||||
if(!strendswith(filename, ext))
|
||||
continue;
|
||||
|
||||
Replay *rpy = malloc(sizeof(Replay));
|
||||
if(!replay_load(rpy, e->d_name, REPLAY_READ_META)) {
|
||||
if(!replay_load(rpy, filename, REPLAY_READ_META)) {
|
||||
free(rpy);
|
||||
continue;
|
||||
}
|
||||
|
@ -283,14 +281,13 @@ int fill_replayview_menu(MenuData *m) {
|
|||
memset(ictx, 0, sizeof(ReplayviewItemContext));
|
||||
|
||||
ictx->replay = rpy;
|
||||
ictx->replayname = malloc(strlen(e->d_name) + 1);
|
||||
strcpy(ictx->replayname, e->d_name);
|
||||
ictx->replayname = strdup(filename);
|
||||
|
||||
add_menu_entry(m, " ", replayview_run, ictx)->transition = rpy->numstages < 2 ? TransFadeBlack : NULL;
|
||||
++rpys;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
vfs_dir_close(dir);
|
||||
|
||||
if(m->entries) {
|
||||
qsort(m->entries, m->ecount, sizeof(MenuEntry), replayview_cmp);
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT-License
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
||||
*/
|
||||
|
||||
#ifndef NATIVE_H
|
||||
#define NATIVE_H
|
||||
|
||||
const char *get_prefix(void);
|
||||
const char *get_config_path(void);
|
||||
const char *get_screenshots_path(void);
|
||||
const char *get_replays_path(void);
|
||||
|
||||
void init_paths(void);
|
||||
|
||||
#endif
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT-License
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
||||
*/
|
||||
|
||||
#include "native.h"
|
||||
|
||||
const char *get_prefix(void) {
|
||||
return "./data/";
|
||||
}
|
||||
|
||||
const char *get_config_path(void) {
|
||||
return ".";
|
||||
}
|
||||
|
||||
const char *get_screenshots_path(void) {
|
||||
return "./screenshots";
|
||||
}
|
||||
|
||||
const char *get_replays_path(void) {
|
||||
return "./replays";
|
||||
}
|
||||
|
||||
void init_paths(void) {
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT-License
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
||||
*/
|
||||
|
||||
#include "native.h"
|
||||
#include "global.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DATA_DIR "data/"
|
||||
|
||||
#define SCR_DIR "screenshots"
|
||||
#define RPY_DIR "replays"
|
||||
|
||||
char *content_path;
|
||||
char *conf_path;
|
||||
char *scr_path;
|
||||
char *rpy_path;
|
||||
|
||||
const char *get_prefix(void) {
|
||||
return content_path;
|
||||
}
|
||||
|
||||
const char *get_config_path(void) {
|
||||
return conf_path;
|
||||
}
|
||||
|
||||
const char *get_screenshots_path(void) {
|
||||
return scr_path;
|
||||
}
|
||||
|
||||
const char *get_replays_path(void) {
|
||||
return rpy_path;
|
||||
}
|
||||
|
||||
void init_paths(void) {
|
||||
#ifdef RELATIVE
|
||||
char *basedir = SDL_GetBasePath();
|
||||
content_path = strjoin(basedir, DATA_DIR, NULL);
|
||||
free(basedir);
|
||||
#else
|
||||
content_path = FILE_PREFIX;
|
||||
#endif
|
||||
|
||||
conf_path = SDL_GetPrefPath("", "taisei");
|
||||
scr_path = strjoin(conf_path, SCR_DIR, NULL);
|
||||
rpy_path = strjoin(conf_path, RPY_DIR, NULL);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT-License
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
||||
*/
|
||||
|
||||
#include "native.h"
|
||||
#include "global.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CFG_DIR "/.taisei"
|
||||
#define SCR_DIR "/screenshots"
|
||||
#define RPY_DIR "/replays"
|
||||
|
||||
char *conf_path;
|
||||
char *scr_path;
|
||||
char *rpy_path;
|
||||
|
||||
const char *get_prefix(void) {
|
||||
return FILE_PREFIX;
|
||||
}
|
||||
|
||||
const char *get_config_path(void) {
|
||||
return conf_path;
|
||||
}
|
||||
|
||||
const char *get_screenshots_path(void) {
|
||||
return scr_path;
|
||||
}
|
||||
|
||||
const char *get_replays_path(void) {
|
||||
return rpy_path;
|
||||
}
|
||||
|
||||
void init_paths(void) {
|
||||
conf_path = strjoin(getenv("HOME"), CFG_DIR, NULL);
|
||||
scr_path = strjoin(conf_path, SCR_DIR, NULL);
|
||||
rpy_path = strjoin(conf_path, RPY_DIR, NULL);
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
#include <zlib.h>
|
||||
|
||||
#include "progress.h"
|
||||
#include "paths/native.h"
|
||||
#include "stage.h"
|
||||
|
||||
/*
|
||||
|
@ -68,10 +67,6 @@ static uint8_t progress_magic_bytes[] = {
|
|||
0x00, 0x67, 0x74, 0x66, 0x6f, 0xe3, 0x83, 0x84
|
||||
};
|
||||
|
||||
static char* progress_getpath(void) {
|
||||
return strfmt("%s/%s", get_config_path(), PROGRESS_FILENAME);
|
||||
}
|
||||
|
||||
static uint32_t progress_checksum(uint8_t *buf, size_t num) {
|
||||
return crc32(0xB16B00B5, buf, num);
|
||||
}
|
||||
|
@ -573,31 +568,25 @@ void progress_load(void) {
|
|||
progress_save();
|
||||
#endif
|
||||
|
||||
char *p = progress_getpath();
|
||||
SDL_RWops *file = SDL_RWFromFile(p, "rb");
|
||||
SDL_RWops *file = vfs_open(PROGRESS_FILE, VFS_MODE_READ);
|
||||
|
||||
if(!file) {
|
||||
log_warn("Couldn't open the progress file: %s", SDL_GetError());
|
||||
free(p);
|
||||
log_warn("Couldn't open the progress file: %s", vfs_get_error());
|
||||
return;
|
||||
}
|
||||
|
||||
free(p);
|
||||
progress_read(file);
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
|
||||
void progress_save(void) {
|
||||
char *p = progress_getpath();
|
||||
SDL_RWops *file = SDL_RWFromFile(p, "wb");
|
||||
SDL_RWops *file = vfs_open(PROGRESS_FILE, VFS_MODE_WRITE);
|
||||
|
||||
if(!file) {
|
||||
log_warn("Couldn't open the progress file: %s", SDL_GetError());
|
||||
free(p);
|
||||
log_warn("Couldn't open the progress file: %s", vfs_get_error());
|
||||
return;
|
||||
}
|
||||
|
||||
free(p);
|
||||
progress_write(file);
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <SDL.h>
|
||||
#include "ending.h"
|
||||
|
||||
#define PROGRESS_FILENAME "progress.dat"
|
||||
#define PROGRESS_FILE "storage/progress.dat"
|
||||
#define PROGRESS_MAXFILESIZE 4096
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
88
src/replay.c
88
src/replay.c
|
@ -14,7 +14,6 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
static uint8_t replay_magic_header[] = REPLAY_MAGIC_HEADER;
|
||||
|
||||
|
@ -137,7 +136,7 @@ static void replay_write_string(SDL_RWops *file, char *str) {
|
|||
SDL_RWwrite(file, str, 1, strlen(str));
|
||||
}
|
||||
|
||||
static int replay_write_stage_event(ReplayEvent *evt, SDL_RWops *file) {
|
||||
static bool replay_write_stage_event(ReplayEvent *evt, SDL_RWops *file) {
|
||||
SDL_WriteLE32(file, evt->frame);
|
||||
SDL_WriteU8(file, evt->type);
|
||||
SDL_WriteLE16(file, evt->value);
|
||||
|
@ -166,7 +165,7 @@ static uint32_t replay_calc_stageinfo_checksum(ReplayStage *stg) {
|
|||
return cs;
|
||||
}
|
||||
|
||||
static int replay_write_stage(ReplayStage *stg, SDL_RWops *file) {
|
||||
static bool replay_write_stage(ReplayStage *stg, SDL_RWops *file) {
|
||||
SDL_WriteLE16(file, stg->stage);
|
||||
SDL_WriteLE32(file, stg->seed);
|
||||
SDL_WriteU8(file, stg->diff);
|
||||
|
@ -188,7 +187,7 @@ static int replay_write_stage(ReplayStage *stg, SDL_RWops *file) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int replay_write(Replay *rpy, SDL_RWops *file, bool compression) {
|
||||
bool replay_write(Replay *rpy, SDL_RWops *file, bool compression) {
|
||||
uint16_t version = REPLAY_STRUCT_VERSION;
|
||||
int i, j;
|
||||
|
||||
|
@ -271,7 +270,7 @@ static void replay_read_string(SDL_RWops *file, char **ptr) {
|
|||
SDL_RWread(file, *ptr, 1, len);
|
||||
}
|
||||
|
||||
static int replay_read_header(Replay *rpy, SDL_RWops *file, int64_t filesize, size_t *ofs) {
|
||||
static bool replay_read_header(Replay *rpy, SDL_RWops *file, int64_t filesize, size_t *ofs) {
|
||||
uint8_t header[sizeof(replay_magic_header)];
|
||||
(*ofs) += sizeof(header);
|
||||
|
||||
|
@ -298,7 +297,7 @@ static int replay_read_header(Replay *rpy, SDL_RWops *file, int64_t filesize, si
|
|||
return true;
|
||||
}
|
||||
|
||||
static int replay_read_meta(Replay *rpy, SDL_RWops *file, int64_t filesize) {
|
||||
static bool replay_read_meta(Replay *rpy, SDL_RWops *file, int64_t filesize) {
|
||||
replay_read_string(file, &rpy->playername);
|
||||
PRINTPROP(rpy->playername, s);
|
||||
|
||||
|
@ -341,7 +340,7 @@ static int replay_read_meta(Replay *rpy, SDL_RWops *file, int64_t filesize) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static int replay_read_events(Replay *rpy, SDL_RWops *file, int64_t filesize) {
|
||||
static bool replay_read_events(Replay *rpy, SDL_RWops *file, int64_t filesize) {
|
||||
for(int i = 0; i < rpy->numstages; ++i) {
|
||||
ReplayStage *stg = rpy->stages + i;
|
||||
|
||||
|
@ -365,8 +364,8 @@ static int replay_read_events(Replay *rpy, SDL_RWops *file, int64_t filesize) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int replay_read(Replay *rpy, SDL_RWops *file, ReplayReadMode mode) {
|
||||
int64_t filesize; // must be signed
|
||||
bool replay_read(Replay *rpy, SDL_RWops *file, ReplayReadMode mode) {
|
||||
ssize_t filesize; // must be signed
|
||||
SDL_RWops *vfile = file;
|
||||
|
||||
mode &= REPLAY_READ_ALL;
|
||||
|
@ -478,58 +477,73 @@ int replay_read(Replay *rpy, SDL_RWops *file, ReplayReadMode mode) {
|
|||
#undef CHECKPROP
|
||||
#undef PRINTPROP
|
||||
|
||||
char* replay_getpath(const char *name, bool ext) {
|
||||
return ext ? strfmt("%s/%s.%s", get_replays_path(), name, REPLAY_EXTENSION) :
|
||||
strfmt("%s/%s", get_replays_path(), name);
|
||||
static char* replay_getpath(const char *name, bool ext) {
|
||||
return ext ? strfmt("storage/replays/%s.%s", name, REPLAY_EXTENSION) :
|
||||
strfmt("storage/replays/%s", name);
|
||||
}
|
||||
|
||||
int replay_save(Replay *rpy, const char *name) {
|
||||
bool replay_save(Replay *rpy, const char *name) {
|
||||
char *p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
|
||||
log_info("Saving %s", p);
|
||||
char *sp = vfs_syspath_or_repr(p);
|
||||
log_info("Saving %s", sp);
|
||||
free(sp);
|
||||
|
||||
SDL_RWops *file = SDL_RWFromFile(p, "wb");
|
||||
SDL_RWops *file = vfs_open(p, VFS_MODE_WRITE);
|
||||
free(p);
|
||||
|
||||
if(!file) {
|
||||
log_warn("SDL_RWFromFile() failed: %s", SDL_GetError());
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = replay_write(rpy, file, REPLAY_WRITE_COMPRESSED);
|
||||
bool result = replay_write(rpy, file, REPLAY_WRITE_COMPRESSED);
|
||||
SDL_RWclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
int replay_load(Replay *rpy, const char *name, ReplayReadMode mode) {
|
||||
char *p;
|
||||
bool replay_load(Replay *rpy, const char *name, ReplayReadMode mode) {
|
||||
char *p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
|
||||
char *sp = vfs_syspath_or_repr(p);
|
||||
log_info("Loading %s (mode %i)", sp, mode);
|
||||
free(sp);
|
||||
|
||||
if(mode & REPLAY_READ_RAWPATH) {
|
||||
p = (char*)name;
|
||||
} else {
|
||||
p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
|
||||
SDL_RWops *file = vfs_open(p, VFS_MODE_READ);
|
||||
free(p);
|
||||
|
||||
if(!file) {
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("replay_load(): loading %s (mode %i)", p, mode);
|
||||
bool result = replay_read(rpy, file, mode);
|
||||
|
||||
if(!result) {
|
||||
replay_destroy(rpy);
|
||||
}
|
||||
|
||||
SDL_RWclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool replay_load_syspath(Replay *rpy, const char *path, ReplayReadMode mode) {
|
||||
log_info("Loading %s (mode %i)", path, mode);
|
||||
SDL_RWops *file;
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
if(!strcmp(name,"-"))
|
||||
if(!strcmp(path, "-"))
|
||||
file = SDL_RWFromFP(stdin,false);
|
||||
else
|
||||
file = SDL_RWFromFile(p, "rb");
|
||||
file = SDL_RWFromFile(path, "rb");
|
||||
#else
|
||||
file = SDL_RWFromFile(p, "rb");
|
||||
file = SDL_RWFromFile(path, "rb");
|
||||
#endif
|
||||
|
||||
if(!(mode & REPLAY_READ_RAWPATH)) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
if(!file) {
|
||||
log_warn("SDL_RWFromFile() failed: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = replay_read(rpy, file, mode);
|
||||
bool result = replay_read(rpy, file, mode);
|
||||
|
||||
if(!result) {
|
||||
replay_destroy(rpy);
|
||||
|
@ -690,13 +704,3 @@ void replay_play(Replay *rpy, int firstidx) {
|
|||
global.replay_stage = NULL;
|
||||
free_resources(false);
|
||||
}
|
||||
|
||||
void replay_play_path(const char *path, int firstidx) {
|
||||
replay_destroy(&global.replay);
|
||||
|
||||
if(!replay_load(&global.replay, path, REPLAY_READ_ALL | REPLAY_READ_RAWPATH)) {
|
||||
return;
|
||||
}
|
||||
|
||||
replay_play(&global.replay, firstidx);
|
||||
}
|
||||
|
|
13
src/replay.h
13
src/replay.h
|
@ -139,7 +139,6 @@ typedef enum ReplayReadMode {
|
|||
REPLAY_READ_META = 1,
|
||||
REPLAY_READ_EVENTS = 2,
|
||||
REPLAY_READ_ALL = 3, // includes the other two
|
||||
REPLAY_READ_RAWPATH = 4, // only used by replay_load()
|
||||
} ReplayReadMode;
|
||||
|
||||
void replay_init(Replay *rpy);
|
||||
|
@ -152,18 +151,16 @@ void replay_stage_event(ReplayStage *stg, uint32_t frame, uint8_t type, int16_t
|
|||
void replay_stage_check_desync(ReplayStage *stg, int time, uint16_t check, ReplayMode mode);
|
||||
void replay_stage_sync_player_state(ReplayStage *stg, Player *plr);
|
||||
|
||||
int replay_write(Replay *rpy, SDL_RWops *file, bool compression);
|
||||
int replay_read(Replay *rpy, SDL_RWops *file, ReplayReadMode mode);
|
||||
bool replay_write(Replay *rpy, SDL_RWops *file, bool compression);
|
||||
bool replay_read(Replay *rpy, SDL_RWops *file, ReplayReadMode mode);
|
||||
|
||||
int replay_save(Replay *rpy, const char *name);
|
||||
int replay_load(Replay *rpy, const char *name, ReplayReadMode mode);
|
||||
bool replay_save(Replay *rpy, const char *name);
|
||||
bool replay_load(Replay *rpy, const char *name, ReplayReadMode mode);
|
||||
bool replay_load_syspath(Replay *rpy, const char *path, ReplayReadMode mode);
|
||||
|
||||
void replay_copy(Replay *dst, Replay *src, bool steal_events);
|
||||
|
||||
char* replay_getpath(const char *name, bool ext); // must be freed
|
||||
|
||||
void replay_play(Replay *rpy, int firstidx);
|
||||
void replay_play_path(const char *path, int firstidx);
|
||||
|
||||
int replay_find_stage_idx(Replay *rpy, uint8_t stageid);
|
||||
|
||||
|
|
|
@ -21,6 +21,6 @@ void* load_music_begin(const char *path, unsigned int flags);
|
|||
void* load_music_end(void *opaque, const char *path, unsigned int flags);
|
||||
void unload_music(void *snd);
|
||||
|
||||
#define BGM_PATH_PREFIX "bgm/"
|
||||
#define BGM_PATH_PREFIX "res/bgm/"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,7 +23,14 @@ bool check_music_path(const char *path) {
|
|||
}
|
||||
|
||||
void* load_music_begin(const char *path, unsigned int flags) {
|
||||
Mix_Music *music = Mix_LoadMUS(path);
|
||||
SDL_RWops *rwops = vfs_open(path, VFS_MODE_READ);
|
||||
|
||||
if(!rwops) {
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Mix_Music *music = Mix_LoadMUS_RW(rwops, true);
|
||||
|
||||
if(!music) {
|
||||
log_warn("Mix_LoadMUS() failed: %s", Mix_GetError());
|
||||
|
|
|
@ -7,25 +7,30 @@
|
|||
|
||||
#include "font.h"
|
||||
#include "global.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
struct Fonts _fonts;
|
||||
|
||||
TTF_Font* load_font(char *name, int size) {
|
||||
char *buf = strjoin(get_prefix(), name, NULL);
|
||||
TTF_Font* load_font(char *vfspath, int size) {
|
||||
char *syspath = vfs_syspath_or_repr(vfspath);
|
||||
|
||||
SDL_RWops *rwops = vfs_open(vfspath, VFS_MODE_READ);
|
||||
|
||||
if(!rwops) {
|
||||
log_fatal("VFS error: %s", vfs_get_error());
|
||||
}
|
||||
|
||||
// XXX: what would be the best rounding strategy here?
|
||||
size = rint(size * resources.fontren.quality);
|
||||
|
||||
TTF_Font *f = TTF_OpenFont(buf, size);
|
||||
TTF_Font *f = TTF_OpenFontRW(rwops, true, size);
|
||||
|
||||
if(!f) {
|
||||
log_fatal("Failed to load font '%s' @ %i: %s", buf, size, TTF_GetError());
|
||||
log_fatal("Failed to load font '%s' @ %i: %s", syspath, size, TTF_GetError());
|
||||
}
|
||||
|
||||
log_info("Loaded '%s' @ %i", buf, size);
|
||||
log_info("Loaded '%s' @ %i", syspath, size);
|
||||
|
||||
free(buf);
|
||||
free(syspath);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
@ -125,9 +130,9 @@ void uninit_fonts(void) {
|
|||
|
||||
void load_fonts(float quality) {
|
||||
fontrenderer_init(&resources.fontren, quality);
|
||||
_fonts.standard = load_font("gfx/LinBiolinum.ttf", 20);
|
||||
_fonts.mainmenu = load_font("gfx/immortal.ttf", 35);
|
||||
_fonts.small = load_font("gfx/LinBiolinum.ttf", 14);
|
||||
_fonts.standard = load_font("res/gfx/LinBiolinum.ttf", 20);
|
||||
_fonts.mainmenu = load_font("res/gfx/immortal.ttf", 35);
|
||||
_fonts.small = load_font("res/gfx/LinBiolinum.ttf", 14);
|
||||
}
|
||||
|
||||
void reload_fonts(float quality) {
|
||||
|
|
|
@ -131,10 +131,10 @@ static void free_obj(ObjFileData *data) {
|
|||
}
|
||||
|
||||
static void parse_obj(const char *filename, ObjFileData *data) {
|
||||
SDL_RWops *rw = SDL_RWFromFile(filename, "r");
|
||||
SDL_RWops *rw = vfs_open(filename, VFS_MODE_READ);
|
||||
|
||||
if(!rw) {
|
||||
log_warn("SDL_RWFromFile() failed: %s", SDL_GetError());
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ Model* get_model(const char *name);
|
|||
void draw_model_p(Model *model);
|
||||
void draw_model(const char *name);
|
||||
|
||||
#define MDL_PATH_PREFIX "models/"
|
||||
#define MDL_PATH_PREFIX "res/models/"
|
||||
#define MDL_EXTENSION ".obj"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
*/
|
||||
|
||||
#include "resource.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "paths/native.h"
|
||||
#include "config.h"
|
||||
#include "video.h"
|
||||
#include "menu/mainmenu.h"
|
||||
|
@ -274,7 +271,9 @@ static Resource* load_resource_finish(void *opaque, ResourceHandler *handler, co
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Resource *res = insert_resource(handler->type, name, raw, flags, path);
|
||||
char *sp = vfs_syspath_or_repr(path);
|
||||
Resource *res = insert_resource(handler->type, name, raw, flags, sp);
|
||||
free(sp);
|
||||
|
||||
free(allocated_path);
|
||||
free(allocated_name);
|
||||
|
@ -387,11 +386,11 @@ const char* resource_util_filename(const char *path) {
|
|||
|
||||
void load_resources(void) {
|
||||
if(glext.draw_instanced) {
|
||||
load_shader_snippets("shader/laser_snippets", "laser_", RESF_PERMANENT);
|
||||
load_shader_snippets(SHA_PATH_PREFIX "laser_snippets", "laser_", RESF_PERMANENT);
|
||||
}
|
||||
|
||||
menu_preload();
|
||||
resources.stage_postprocess = postprocess_load("shader/postprocess.conf");
|
||||
resources.stage_postprocess = postprocess_load(SHA_PATH_PREFIX "postprocess.conf");
|
||||
}
|
||||
|
||||
void free_resources(bool all) {
|
||||
|
@ -408,9 +407,9 @@ void free_resources(bool all) {
|
|||
if(!all && res->flags & RESF_PERMANENT)
|
||||
continue;
|
||||
|
||||
ResourceFlags flags = res->flags;
|
||||
ResourceFlags flags __attribute__((unused)) = res->flags;
|
||||
unload_resource(res);
|
||||
log_info("Unloaded %s '%s' (%s)", resource_type_names[type], name,
|
||||
log_debug("Unloaded %s '%s' (%s)", resource_type_names[type], name,
|
||||
(flags & RESF_PERMANENT) ? "permanent" : "transient"
|
||||
);
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "model.h"
|
||||
#include "postprocess.h"
|
||||
#include "hashtable.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
typedef enum ResourceType {
|
||||
RES_TEXTURE,
|
||||
|
@ -39,21 +38,18 @@ typedef enum ResourceFlags {
|
|||
|
||||
#define RESF_DEFAULT 0
|
||||
|
||||
// All paths are relative to the current working directory, which can assumed to be the resources directory,
|
||||
// unless mentioned otherwise.
|
||||
|
||||
// Converts a path into an abstract resource name to be used as the hashtable key.
|
||||
// Converts a vfs path into an abstract resource name to be used as the hashtable key.
|
||||
// This method is optional, the default strategy is to take the path minus the prefix and extension.
|
||||
// The returned name must be free()'d.
|
||||
typedef char* (*ResourceNameFunc)(const char *path);
|
||||
|
||||
// Converts an abstract resource name into a path from which a resource with that name could be loaded.
|
||||
// Converts an abstract resource name into a vfs path from which a resource with that name could be loaded.
|
||||
// The path may not actually exist or be usable. The load function (see below) shall deal with such cases.
|
||||
// The returned path must be free()'d.
|
||||
// May return NULL on failure, but does not have to.
|
||||
typedef char* (*ResourceFindFunc)(const char *name);
|
||||
|
||||
// Tells whether the resource handler should attempt to load a file, specified by a path.
|
||||
// Tells whether the resource handler should attempt to load a file, specified by a vfs path.
|
||||
typedef bool (*ResourceCheckFunc)(const char *path);
|
||||
|
||||
// Begins loading a resource specified by path.
|
||||
|
|
|
@ -21,6 +21,6 @@ void* load_sound_begin(const char *path, unsigned int flags);
|
|||
void* load_sound_end(void *opaque, const char *path, unsigned int flags);
|
||||
void unload_sound(void *snd);
|
||||
|
||||
#define SFX_PATH_PREFIX "sfx/"
|
||||
#define SFX_PATH_PREFIX "res/sfx/"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,7 +23,14 @@ bool check_sound_path(const char *path) {
|
|||
}
|
||||
|
||||
void* load_sound_begin(const char *path, unsigned int flags) {
|
||||
Mix_Chunk *sound = Mix_LoadWAV(path);
|
||||
SDL_RWops *rwops = vfs_open(path, VFS_MODE_READ);
|
||||
|
||||
if(!rwops) {
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Mix_Chunk *sound = Mix_LoadWAV_RW(rwops, true);
|
||||
|
||||
if(!sound) {
|
||||
log_warn("Mix_LoadWAV() failed: %s", Mix_GetError());
|
||||
|
|
|
@ -30,7 +30,7 @@ Shader* get_shader_optional(const char *name);
|
|||
|
||||
int uniloc(Shader *sha, const char *name);
|
||||
|
||||
#define SHA_PATH_PREFIX "shader/"
|
||||
#define SHA_PATH_PREFIX "res/shader/"
|
||||
#define SHA_EXTENSION ".sha"
|
||||
|
||||
#define SHA_DELIM "%% -- FRAG"
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "texture.h"
|
||||
#include "resource.h"
|
||||
#include "global.h"
|
||||
#include "paths/native.h"
|
||||
#include "vbo.h"
|
||||
|
||||
char* texture_path(const char *name) {
|
||||
|
@ -86,10 +85,6 @@ Texture* prefix_get_tex(const char *name, const char *prefix) {
|
|||
|
||||
static ImageData* load_png_p(const char *filename, SDL_RWops *rwops) {
|
||||
#define PNGFAIL(msg) { log_warn("Couldn't load '%s': %s", filename, msg); return NULL; }
|
||||
if(!rwops) {
|
||||
PNGFAIL(SDL_GetError())
|
||||
}
|
||||
|
||||
png_structp png_ptr;
|
||||
if(!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) {
|
||||
PNGFAIL("png_create_read_struct() failed")
|
||||
|
@ -150,13 +145,16 @@ static ImageData* load_png_p(const char *filename, SDL_RWops *rwops) {
|
|||
}
|
||||
|
||||
static ImageData* load_png(const char *filename) {
|
||||
SDL_RWops *rwops = SDL_RWFromFile(filename, "r");
|
||||
ImageData *img = load_png_p(filename, rwops);
|
||||
SDL_RWops *rwops = vfs_open(filename, VFS_MODE_READ);
|
||||
|
||||
if(rwops) {
|
||||
SDL_RWclose(rwops);
|
||||
if(!rwops) {
|
||||
log_warn("VFS error: %s", vfs_get_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImageData *img = load_png_p(filename, rwops);
|
||||
|
||||
SDL_RWclose(rwops);
|
||||
return img;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ void loop_tex_line(complex a, complex b, float w, float t, const char *texture);
|
|||
Texture* get_tex(const char *name);
|
||||
Texture* prefix_get_tex(const char *name, const char *prefix);
|
||||
|
||||
#define TEX_PATH_PREFIX "gfx/"
|
||||
#define TEX_PATH_PREFIX "res/gfx/"
|
||||
#define TEX_EXTENSION ".png"
|
||||
|
||||
#endif
|
||||
|
|
18
src/util.c
18
src/util.c
|
@ -129,6 +129,16 @@ void strip_trailing_slashes(char *buf) {
|
|||
*c = 0;
|
||||
}
|
||||
|
||||
char* strappend(char **dst, char *src) {
|
||||
if(!*dst) {
|
||||
return *dst = strdup(src);
|
||||
}
|
||||
|
||||
*dst = realloc(*dst, strlen(*dst) + strlen(src) + 1);
|
||||
strcat(*dst, src);
|
||||
return *dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* public domain strtok_r() by Charlie Gordon
|
||||
*
|
||||
|
@ -310,10 +320,10 @@ char* read_all(const char *filename, int *outsize) {
|
|||
char *text;
|
||||
size_t size;
|
||||
|
||||