sm64coopdx/src/pc/fs/fs.h
djoslin0 81af37eef6
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
Regenerate DynOS assets when source files are modified (#873)
Previously to recompile DynOS assets you had to remove the
bin/lvl/bhv/tex/col/etc files. Now the game will compare the
last-modified-timestamps of the generated/compiled assets vs
the other files that are within those directories. If the presumed-
source files have a later modified timestamp DynOS will regenerate
those assets.

While this results in scanning the attributes of files more, it
also prevents parsing files unnecessarily. Previously actors
would always parse their source files and build up GfxData
unnecessarily.

---------

Co-authored-by: MysterD <myster@d>
2025-07-02 23:24:35 +10:00

113 lines
4.6 KiB
C

#ifndef _SM64_FS_H_
#define _SM64_FS_H_
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "../platform.h"
#define SAVE_FILENAME "sm64_save_file.bin"
extern char fs_writepath[];
// receives the full path
// should return `true` if traversal should continue
// first arg is user data
typedef bool (*walk_fn_t)(void *, const char *);
typedef enum {
FS_WALK_SUCCESS = 0,
FS_WALK_INTERRUPTED = 1,
FS_WALK_NOTFOUND = 2,
FS_WALK_ERROR = 4,
} fs_walk_result_t;
// opaque searchpath directory type
typedef struct fs_dir_s fs_dir_t;
// virtual file handle
typedef struct fs_file_s {
void *handle; // opaque packtype-defined data
fs_dir_t *parent; // directory containing this file
} fs_file_t;
// list of paths; returned by fs_enumerate()
typedef struct {
char **paths;
int numpaths;
int listcap;
} fs_pathlist_t;
typedef struct {
const char *extension; // file extensions of this pack type
void *(*mount)(const char *rpath); // open and initialize pack at real path `rpath`
void (*unmount)(void *pack); // free pack
// walks the specified directory inside this pack, calling walkfn for each file
// returns FS_WALK_SUCCESS if the directory was successfully opened and walk() didn't ever return false
// returns FS_WALK_INTERRUPTED if the traversal started but walk() returned false at some point
// if recur is true, will recurse into subfolders
fs_walk_result_t (*walk)(void *pack, const char *base, walk_fn_t walkfn, void *user, const bool recur);
bool (*is_file)(void *pack, const char *path); // returns true if `path` exists in this pack and is a file
bool (*is_dir)(void *pack, const char *path); // returns true if `path` exists in this pack and is a directory
// file I/O functions; paths are virtual
fs_file_t *(*open)(void *pack, const char *path); // opens a virtual file contained in this pack for reading, returns NULL in case of error
int64_t (*read)(void *pack, fs_file_t *file, void *buf, const uint64_t size); // returns -1 in case of error
bool (*seek)(void *pack, fs_file_t *file, const int64_t ofs); // returns true if seek succeeded
int64_t (*tell)(void *pack, fs_file_t *file); // returns -1 in case of error, current virtual file position otherwise
int64_t (*size)(void *pack, fs_file_t *file); // returns -1 in case of error, size of the (uncompressed) file otherwise
bool (*eof)(void *pack, fs_file_t *file); // returns true if there's nothing more to read
void (*close)(void *pack, fs_file_t *file); // closes a virtual file previously opened with ->open()
} fs_packtype_t;
// mounts `writepath`
bool fs_init(const char *writepath);
// mounts the pack at physical path `realpath` to the root of the filesystem
// packs mounted later take priority over packs mounted earlier
bool fs_mount(const char *realpath);
/* generalized filesystem functions that call matching packtype functions for each pack in the searchpath */
// FIXME: this can walk in unorthodox patterns, since it goes through mountpoints linearly
fs_walk_result_t fs_walk(const char *base, walk_fn_t walkfn, void *user, const bool recur);
// returns a list of files in the `base` directory
fs_pathlist_t fs_enumerate(const char *base, const bool recur);
// call this on a list returned by fs_enumerate() to free it
void fs_pathlist_free(fs_pathlist_t *pathlist);
fs_file_t *fs_open(const char *vpath);
void fs_close(fs_file_t *file);
int64_t fs_read(fs_file_t *file, void *buf, const uint64_t size);
const char *fs_readline(fs_file_t *file, char *dst, const uint64_t size);
int64_t fs_size(fs_file_t *file);
bool fs_eof(fs_file_t *file);
void *fs_load_file(const char *vpath, uint64_t *outsize);
const char *fs_readline(fs_file_t *file, char *dst, uint64_t size);
// takes a virtual path and prepends the write path to it
const char *fs_get_write_path(const char *vpath);
// expands special chars in paths and changes backslashes to forward slashes
const char *fs_convert_path(char *buf, const size_t bufsiz, const char *path);
bool fs_sys_filename_is_portable(char const *filename);
/* these operate on the real filesystem and are used by fs_packtype_dir */
bool fs_sys_walk(const char *base, walk_fn_t walk, void *user, const bool recur);
bool fs_sys_path_exists(const char *name);
bool fs_sys_file_exists(const char *name);
bool fs_sys_dir_exists(const char *name);
bool fs_sys_dir_is_empty(const char *name);
bool fs_sys_mkdir(const char *name); // creates with 0777 by default
bool fs_sys_rmdir(const char *name); // removes an empty directory
uint64_t fs_sys_get_modified_time(const char *path);
#endif // _SM64_FS_H_