mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Started rewriting the mod table
This commit is contained in:
parent
edf06bede0
commit
0a3d0b2033
8 changed files with 535 additions and 1 deletions
2
Makefile
2
Makefile
|
|
@ -455,7 +455,7 @@ SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels
|
||||||
BIN_DIRS := bin bin/$(VERSION)
|
BIN_DIRS := bin bin/$(VERSION)
|
||||||
|
|
||||||
# PC files
|
# PC files
|
||||||
SRC_DIRS += src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes src/pc/network src/pc/network/packets src/pc/network/socket src/pc/utils src/pc/djui src/pc/lua src/pc/lua/utils
|
SRC_DIRS += src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes src/pc/mods src/pc/network src/pc/network/packets src/pc/network/socket src/pc/utils src/pc/djui src/pc/lua src/pc/lua/utils
|
||||||
|
|
||||||
#ifeq ($(DISCORDRPC),1)
|
#ifeq ($(DISCORDRPC),1)
|
||||||
# SRC_DIRS += src/pc/discord
|
# SRC_DIRS += src/pc/discord
|
||||||
|
|
|
||||||
290
src/pc/mods/mod.c
Normal file
290
src/pc/mods/mod.c
Normal file
|
|
@ -0,0 +1,290 @@
|
||||||
|
#include "mod.h"
|
||||||
|
#include "mods.h"
|
||||||
|
#include "mods_utils.h"
|
||||||
|
#include "pc/utils/misc.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void mod_clear(struct Mod* mod) {
|
||||||
|
for (int j = 0; j < mod->fileCount; j++) {
|
||||||
|
struct ModFile* file = &mod->files[j];
|
||||||
|
file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod->name != NULL) {
|
||||||
|
free(mod->name);
|
||||||
|
mod->name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod->incompatible != NULL) {
|
||||||
|
free(mod->incompatible);
|
||||||
|
mod->incompatible = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod->description != NULL) {
|
||||||
|
free(mod->description);
|
||||||
|
mod->description = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod->files != NULL) {
|
||||||
|
free(mod->files);
|
||||||
|
}
|
||||||
|
|
||||||
|
mod->fileCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ModFile* mod_allocate_file(struct Mod* mod, char* relativePath) {
|
||||||
|
// actual allocation
|
||||||
|
u16 fileIndex = mod->fileCount++;
|
||||||
|
mod->files = realloc(mod->files, sizeof(struct ModFile) * mod->fileCount);
|
||||||
|
if (mod->files == NULL) {
|
||||||
|
LOG_ERROR("Failed to allocate file: '%s'", relativePath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear memory
|
||||||
|
struct ModFile* file = &mod->files[fileIndex];
|
||||||
|
memset(file, 0, sizeof(struct ModFile));
|
||||||
|
|
||||||
|
// set relative path
|
||||||
|
if (snprintf(file->relativePath, SYS_MAX_PATH - 1, "%s", relativePath) < 0) {
|
||||||
|
LOG_ERROR("Failed to remember relative path '%s'", relativePath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) {
|
||||||
|
// read single lua file
|
||||||
|
if (!mod->isDirectory) {
|
||||||
|
return (mod_allocate_file(mod, modName) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// deal with mod directory
|
||||||
|
{
|
||||||
|
// open mod directory
|
||||||
|
struct dirent* dir = NULL;
|
||||||
|
DIR* d = opendir(fullPath);
|
||||||
|
if (!d) {
|
||||||
|
LOG_ERROR("Could not open directory '%s'", fullPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate mod directory
|
||||||
|
char path[SYS_MAX_PATH] = { 0 };
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
// sanity check / fill path[]
|
||||||
|
if (!directory_sanity_check(dir, fullPath, path)) { continue; }
|
||||||
|
|
||||||
|
// only consider lua files
|
||||||
|
if (!str_ends_with(path, ".lua")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate file
|
||||||
|
struct ModFile* file = mod_allocate_file(mod, dir->d_name);
|
||||||
|
if (file == NULL) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// deal with actors directory
|
||||||
|
{
|
||||||
|
// concat actors directory
|
||||||
|
char actorsPath[SYS_MAX_PATH] = { 0 };
|
||||||
|
if (!concat_path(actorsPath, fullPath, "actors")) {
|
||||||
|
LOG_ERROR("Could not concat directory '%s' + '%s'", fullPath, "actors");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open actors directory
|
||||||
|
struct dirent* dir = NULL;
|
||||||
|
DIR* d = opendir(actorsPath);
|
||||||
|
if (!d) {
|
||||||
|
LOG_ERROR("Could not open directory '%s'", actorsPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate mod directory
|
||||||
|
char path[SYS_MAX_PATH] = { 0 };
|
||||||
|
char relativePath[SYS_MAX_PATH] = { 0 };
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
// sanity check / fill path[]
|
||||||
|
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
|
||||||
|
if (snprintf(relativePath, SYS_MAX_PATH - 1, "%s/actors/%s", modName, dir->d_name) < 0) {
|
||||||
|
LOG_ERROR("Could not concat actor path!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only consider bin files
|
||||||
|
if (!str_ends_with(path, ".bin")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate file
|
||||||
|
struct ModFile* file = mod_allocate_file(mod, relativePath);
|
||||||
|
if (file == NULL) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mod_extract_fields(struct Mod* mod) {
|
||||||
|
// get full path
|
||||||
|
char path[SYS_MAX_PATH] = { 0 };
|
||||||
|
char* relativePath = NULL;
|
||||||
|
if (mod->isDirectory) {
|
||||||
|
for (int i = 0; i < mod->fileCount; i++) {
|
||||||
|
struct ModFile* file = &mod->files[i];
|
||||||
|
if (!strcmp(file->relativePath, "main.lua")) {
|
||||||
|
relativePath = file->relativePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
relativePath = mod->files[0].relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relativePath == NULL || !concat_path(path, mod->basePath, relativePath)) {
|
||||||
|
LOG_ERROR("Failed to find main lua file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open file
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
LOG_ERROR("Failed to open '%s'", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
// default to null
|
||||||
|
mod->name = NULL;
|
||||||
|
mod->incompatible = NULL;
|
||||||
|
mod->description = NULL;
|
||||||
|
|
||||||
|
// read line-by-line
|
||||||
|
char buffer[512] = { 0 };
|
||||||
|
while (!feof(f)) {
|
||||||
|
file_get_line(buffer, 512, f);
|
||||||
|
|
||||||
|
// no longer in header
|
||||||
|
if (buffer[0] != '-' || buffer[1] != '-') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract the field
|
||||||
|
char* extracted = NULL;
|
||||||
|
if (mod->name == NULL && (extracted = extract_lua_field("-- name:", buffer))) {
|
||||||
|
mod->name = calloc(33, sizeof(char));
|
||||||
|
if (snprintf(mod->name, 32, "%s", extracted) < 0) {
|
||||||
|
LOG_INFO("Truncated mod name field '%s'", mod->name);
|
||||||
|
}
|
||||||
|
} else if (mod->incompatible == NULL && (extracted = extract_lua_field("-- incompatible:", buffer))) {
|
||||||
|
mod->incompatible = calloc(257, sizeof(char));
|
||||||
|
if (snprintf(mod->incompatible, 256, "%s", extracted) < 0) {
|
||||||
|
LOG_INFO("Truncated mod incompatible field '%s'", mod->incompatible);
|
||||||
|
}
|
||||||
|
} else if (mod->description == NULL && (extracted = extract_lua_field("-- description:", buffer))) {
|
||||||
|
mod->description = calloc(513, sizeof(char));
|
||||||
|
if (snprintf(mod->description, 512, "%s", extracted) < 0) {
|
||||||
|
LOG_INFO("Truncated mod description field '%s'", mod->description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// close file
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mod_load(struct Mods* mods, char* basePath, char* modName) {
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
char fullPath[SYS_MAX_PATH] = { 0 };
|
||||||
|
if (!concat_path(fullPath, basePath, modName)) {
|
||||||
|
LOG_ERROR("Failed to concat path '%s' + '%s'", basePath, modName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDirectory = is_directory(fullPath);
|
||||||
|
|
||||||
|
// make sure mod is valid
|
||||||
|
if (str_ends_with(modName, ".lua")) {
|
||||||
|
valid = true;
|
||||||
|
} else if (is_directory(fullPath)) {
|
||||||
|
char tmpPath[SYS_MAX_PATH] = { 0 };
|
||||||
|
if (!concat_path(tmpPath, fullPath, "main.lua")) {
|
||||||
|
LOG_ERROR("Failed to concat path '%s' + '%s'", fullPath, "main.lua");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
valid = path_exists(tmpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
LOG_ERROR("Found invalid mod '%s'", fullPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure mod is unique
|
||||||
|
for (int i = 0; i < mods->modCount; i++) {
|
||||||
|
struct Mod* compareMod = &mods->entries[i];
|
||||||
|
if (!strcmp(compareMod->relativePath, modName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate mod
|
||||||
|
u16 modIndex = mods->modCount++;
|
||||||
|
mods->entries = realloc(mods->entries, sizeof(struct Mod) * mods->modCount);
|
||||||
|
if (mods->entries == NULL) {
|
||||||
|
LOG_ERROR("Failed to allocate entries!");
|
||||||
|
mods_clear(mods);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct Mod* mod = &mods->entries[modIndex];
|
||||||
|
memset(mod, 0, sizeof(struct Mod));
|
||||||
|
|
||||||
|
// set paths
|
||||||
|
char* cpyPath = isDirectory ? fullPath : basePath;
|
||||||
|
if (snprintf(mod->basePath, SYS_MAX_PATH - 1, "%s", cpyPath) < 0) {
|
||||||
|
LOG_ERROR("Failed to remember mod path '%s'!", cpyPath);
|
||||||
|
mods_clear(mods);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (snprintf(mod->relativePath, SYS_MAX_PATH - 1, "%s", modName) < 0) {
|
||||||
|
LOG_ERROR("Failed to remember mod path '%s'!", modName);
|
||||||
|
mods_clear(mods);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set directory
|
||||||
|
mod->isDirectory = isDirectory;
|
||||||
|
|
||||||
|
// read files
|
||||||
|
if (!mod_load_files(mod, modName, fullPath)) {
|
||||||
|
LOG_ERROR("Failed to load mod files for '%s'", modName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract fields
|
||||||
|
mod_extract_fields(mod);
|
||||||
|
|
||||||
|
// set name
|
||||||
|
if (mod->name == NULL) {
|
||||||
|
mod->name = strdup(modName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print
|
||||||
|
LOG_INFO(" %s", mod->name);
|
||||||
|
if (isDirectory) {
|
||||||
|
for (int i = 0; i < mod->fileCount; i++) {
|
||||||
|
struct ModFile* file = &mod->files[i];
|
||||||
|
LOG_INFO(" - %s", file->relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
29
src/pc/mods/mod.h
Normal file
29
src/pc/mods/mod.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef MOD_H
|
||||||
|
#define MOD_H
|
||||||
|
|
||||||
|
#include "PR/ultratypes.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include "src/pc/platform.h"
|
||||||
|
|
||||||
|
struct Mods;
|
||||||
|
|
||||||
|
struct ModFile {
|
||||||
|
char relativePath[SYS_MAX_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Mod {
|
||||||
|
char* name;
|
||||||
|
char* incompatible;
|
||||||
|
char* description;
|
||||||
|
char relativePath[SYS_MAX_PATH];
|
||||||
|
char basePath[SYS_MAX_PATH];
|
||||||
|
struct ModFile* files;
|
||||||
|
u16 fileCount;
|
||||||
|
bool isDirectory;
|
||||||
|
bool enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
void mod_clear(struct Mod* mod);
|
||||||
|
bool mod_load(struct Mods* mods, char* basePath, char* modName);
|
||||||
|
|
||||||
|
#endif
|
||||||
85
src/pc/mods/mods.c
Normal file
85
src/pc/mods/mods.c
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "mods.h"
|
||||||
|
#include "mods_utils.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
#define MOD_DIRECTORY "mods"
|
||||||
|
|
||||||
|
static struct Mods gLocalMods = { 0 };
|
||||||
|
|
||||||
|
void mods_clear(struct Mods* mods) {
|
||||||
|
for (int i = 0; i < mods->modCount; i ++) {
|
||||||
|
struct Mod* mod = &mods->entries[i];
|
||||||
|
mod_clear(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mods->entries != NULL) {
|
||||||
|
free(mods->entries);
|
||||||
|
mods->entries = NULL;
|
||||||
|
}
|
||||||
|
mods->modCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mods_load(struct Mods* mods, char* modsBasePath) {
|
||||||
|
// sanity check
|
||||||
|
if (modsBasePath == NULL) {
|
||||||
|
LOG_ERROR("Trying to load from NULL path!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the path normal
|
||||||
|
normalize_path(modsBasePath);
|
||||||
|
|
||||||
|
// check for existence
|
||||||
|
if (!is_directory(modsBasePath)) {
|
||||||
|
LOG_ERROR("Could not find directory '%s'", modsBasePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Loading mods in '%s':", modsBasePath);
|
||||||
|
|
||||||
|
// open directory
|
||||||
|
struct dirent* dir = NULL;
|
||||||
|
DIR* d = opendir(modsBasePath);
|
||||||
|
if (!d) {
|
||||||
|
LOG_ERROR("Could not open directory '%s'", modsBasePath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate
|
||||||
|
char path[SYS_MAX_PATH] = { 0 };
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
// sanity check / fill path[]
|
||||||
|
if (!directory_sanity_check(dir, modsBasePath, path)) { continue; }
|
||||||
|
|
||||||
|
// load the mod
|
||||||
|
if (!mod_load(mods, modsBasePath, dir->d_name)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(d);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void mods_init(void) {
|
||||||
|
// figure out user path
|
||||||
|
bool hasUserPath = true;
|
||||||
|
char userModPath[SYS_MAX_PATH] = { 0 };
|
||||||
|
if (snprintf(userModPath, SYS_MAX_PATH - 1, "%s", fs_get_write_path(MOD_DIRECTORY)) < 0) {
|
||||||
|
hasUserPath = false;
|
||||||
|
}
|
||||||
|
if (!fs_sys_dir_exists(userModPath)) {
|
||||||
|
hasUserPath = fs_sys_mkdir(userModPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear mods
|
||||||
|
mods_clear(&gLocalMods);
|
||||||
|
|
||||||
|
// load mods
|
||||||
|
if (hasUserPath) { mods_load(&gLocalMods, userModPath); }
|
||||||
|
mods_load(&gLocalMods, "./" MOD_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mods_shutdown(void) {
|
||||||
|
mods_clear(&gLocalMods);
|
||||||
|
}
|
||||||
18
src/pc/mods/mods.h
Normal file
18
src/pc/mods/mods.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef MODS_H
|
||||||
|
#define MODS_H
|
||||||
|
|
||||||
|
#include "PR/ultratypes.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include "src/pc/platform.h"
|
||||||
|
#include "mod.h"
|
||||||
|
|
||||||
|
struct Mods {
|
||||||
|
struct Mod* entries;
|
||||||
|
u16 modCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
void mods_clear(struct Mods* mods);
|
||||||
|
void mods_init(void);
|
||||||
|
void mods_shutdown(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
90
src/pc/mods/mods_utils.c
Normal file
90
src/pc/mods/mods_utils.c
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "mods_utils.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
bool str_ends_with(char* string, char* suffix) {
|
||||||
|
if (string == NULL || suffix == NULL) { return false; }
|
||||||
|
|
||||||
|
size_t stringLength = strlen(string);
|
||||||
|
size_t suffixLength = strlen(suffix);
|
||||||
|
|
||||||
|
if (suffixLength > stringLength) { return false; }
|
||||||
|
|
||||||
|
return !strcmp(&string[stringLength - suffixLength], suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* extract_lua_field(char* fieldName, char* buffer) {
|
||||||
|
size_t length = strlen(fieldName);
|
||||||
|
if (strncmp(fieldName, buffer, length) == 0) {
|
||||||
|
char* s = &buffer[length];
|
||||||
|
while (*s == ' ' || *s == '\t') { s++; }
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool path_exists(char* path) {
|
||||||
|
struct stat sb = { 0 };
|
||||||
|
return (stat(path, &sb) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_directory(char* path) {
|
||||||
|
struct stat sb = { 0 };
|
||||||
|
return (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize_path(char* path) {
|
||||||
|
// replace slashes
|
||||||
|
char* p = path;
|
||||||
|
while (*p) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (*p == '/') { *p = '\\'; }
|
||||||
|
#else
|
||||||
|
if (*p == '\\') { *p = '/'; }
|
||||||
|
#endif
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool concat_path(char* destination, char* path, char* fname) {
|
||||||
|
return (snprintf(destination, SYS_MAX_PATH - 1, "%s/%s", path, fname) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* path_basename(char* path) {
|
||||||
|
char* base = path;
|
||||||
|
while (*path != '\0') {
|
||||||
|
if (*(path + 1) != '\0') {
|
||||||
|
if (*path == '\\' || *path == '/') {
|
||||||
|
base = path + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool directory_sanity_check(struct dirent* dir, char* dirPath, char* outPath) {
|
||||||
|
// skip anything that contains \ or /
|
||||||
|
if (strchr(dir->d_name, '/') != NULL) { return false; }
|
||||||
|
if (strchr(dir->d_name, '\\') != NULL) { return false; }
|
||||||
|
|
||||||
|
// skip anything that starts with .
|
||||||
|
if (dir->d_name == NULL || dir->d_name[0] == '.') { return false; }
|
||||||
|
|
||||||
|
// build path
|
||||||
|
if (!concat_path(outPath, dirPath, dir->d_name)) {
|
||||||
|
LOG_ERROR("Failed to concat path '%s' + '%s'", dirPath, dir->d_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
normalize_path(outPath);
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if (!path_exists(outPath)) {
|
||||||
|
LOG_ERROR("Path doesn't exist: '%s'", outPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
19
src/pc/mods/mods_utils.h
Normal file
19
src/pc/mods/mods_utils.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef MODS_UTILS_H
|
||||||
|
#define MODS_UTILS_H
|
||||||
|
|
||||||
|
#include "PR/ultratypes.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include "src/pc/platform.h"
|
||||||
|
|
||||||
|
bool str_ends_with(char* string, char* suffix);
|
||||||
|
|
||||||
|
char* extract_lua_field(char* fieldName, char* buffer);
|
||||||
|
|
||||||
|
bool path_exists(char* path);
|
||||||
|
bool is_directory(char* path);
|
||||||
|
void normalize_path(char* path);
|
||||||
|
bool concat_path(char* destination, char* path, char* fname);
|
||||||
|
char* path_basename(char* path);
|
||||||
|
bool directory_sanity_check(struct dirent* dir, char* dirPath, char* outPath);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
#include "pc/djui/djui.h"
|
#include "pc/djui/djui.h"
|
||||||
|
|
||||||
#include "pc/mod_list.h"
|
#include "pc/mod_list.h"
|
||||||
|
#include "pc/mods/mods.h"
|
||||||
|
|
||||||
OSMesg D_80339BEC;
|
OSMesg D_80339BEC;
|
||||||
OSMesgQueue gSIEventMesgQueue;
|
OSMesgQueue gSIEventMesgQueue;
|
||||||
|
|
@ -171,6 +172,7 @@ void game_deinit(void) {
|
||||||
network_shutdown(true);
|
network_shutdown(true);
|
||||||
smlua_shutdown();
|
smlua_shutdown();
|
||||||
mod_list_shutdown();
|
mod_list_shutdown();
|
||||||
|
mods_shutdown();
|
||||||
inited = false;
|
inited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,6 +223,7 @@ void main_func(void) {
|
||||||
fs_init(sys_ropaths, gamedir, userpath);
|
fs_init(sys_ropaths, gamedir, userpath);
|
||||||
|
|
||||||
mod_list_init();
|
mod_list_init();
|
||||||
|
mods_init();
|
||||||
configfile_load(configfile_name());
|
configfile_load(configfile_name());
|
||||||
if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; }
|
if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; }
|
||||||
if (configPlayerPalette >= PALETTE_MAX) { configPlayerPalette = 0; }
|
if (configPlayerPalette >= PALETTE_MAX) { configPlayerPalette = 0; }
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue