Skip to content

Commit

Permalink
port: add basic mod directory support with config files for custom st…
Browse files Browse the repository at this point in the history
…ages

select mod directory with --moddir whatever

these should contain a modconfig.txt that can specify replacements for some stage table fields, etc
  • Loading branch information
fgsfdsfgs committed Sep 26, 2023
1 parent 9b17aaf commit d98575d
Show file tree
Hide file tree
Showing 10 changed files with 598 additions and 83 deletions.
2 changes: 2 additions & 0 deletions port/include/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ FILE *fsFileOpenWrite(const char *name);
FILE *fsFileOpenRead(const char *name);
void fsFileClose(FILE *f);

const char *fsGetModDir(void);

#endif
10 changes: 10 additions & 0 deletions port/include/mod.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _IN_MOD_H
#define _IN_MOD_H

#include <PR/ultratypes.h>

#define MOD_CONFIG_FNAME "modconfig.txt"

s32 modConfigLoad(const char *path);

#endif
3 changes: 3 additions & 0 deletions port/include/romdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ s32 romdataInit(void);
u8 *romdataFileLoad(s32 fileNum, u32 *outSize);
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size);
void romdataFileFree(s32 fileNum);
const char *romdataFileGetName(s32 fileNum);

u8 *romdataFileGetData(s32 fileNum);
s32 romdataFileGetSize(s32 fileNum);

s32 romdataFileGetNumForName(const char *name);

u8 *romdataSegGetData(const char *segName);
u8 *romdataSegGetDataEnd(const char *segName);
u32 romdataSegGetSize(const char *segName);
Expand Down
15 changes: 15 additions & 0 deletions port/include/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef _IN_UTILS_H
#define _IN_UTILS_H

#define UTIL_MAX_TOKEN 1024

#include <PR/ultratypes.h>

char *strRightTrim(char *str);
char *strTrim(char *str);
char *strUnquote(char *str);
char *strParseToken(char *str, char *out, s32 *outCount);
char *strFmt(const char *fmt, ...);
char *strDuplicate(const char *str);

#endif
89 changes: 25 additions & 64 deletions port/src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "fs.h"
#include "config.h"
#include "system.h"
#include "utils.h"

#define CONFIG_MAX_STR 512
#define CONFIG_MAX_SECNAME 128
Expand Down Expand Up @@ -216,84 +217,44 @@ s32 configLoad(const char *fname)

char curSec[CONFIG_MAX_SECNAME + 1] = { 0 };
char keyBuf[CONFIG_MAX_SECNAME * 2 + 2] = { 0 }; // SECTION + . + KEY + \0
char token[UTIL_MAX_TOKEN + 1] = { 0 };
char lineBuf[2048] = { 0 };
char *line = lineBuf;
s32 lineLen = 0;

while (fgets(lineBuf, sizeof(lineBuf), f)) {
line = lineBuf;

// left-trim whitespace
while (*line && isspace(*line)) {
++line;
}

lineLen = strlen(line);
if (!lineLen) {
continue;
}
line = strParseToken(line, token, NULL);

// right-trim whitespace and \n
for (s32 i = lineLen - 1; i >= 0 && isspace(line[i]); --i, --lineLen);
line[lineLen] = '\0';

if (line[0] == ';' || line[0] == '#') {
// comment; skip the rest of the line
continue;
} else if (line[0] == '[') {
// section; skip [ and find matching ]
++line;
char *end = line;
while (*end && *end != ']') {
++end;
}
// found anything?
if (*end != ']') {
// didn't find shit
if (token[0] == '[' && token[1] == '\0') {
// section; get name
line = strParseToken(line, token, NULL);
if (!token[0]) {
sysLogPrintf(LOG_ERROR, "configLoad: malformed section line: %s", lineBuf);
continue;
}
// eat ] and whitespace on the right
while (end > line && isspace(end[-1])) {
--end;
strncpy(curSec, token, CONFIG_MAX_SECNAME);
// eat ]
line = strParseToken(line, token, NULL);
if (token[0] != ']' || token[1] != '\0') {
sysLogPrintf(LOG_ERROR, "configLoad: malformed section line: %s", lineBuf);
}
*end = '\0';
// empty []?
if (end == line) {
} else if (token[0]) {
// probably a key=value pair; append key name to section name
snprintf(keyBuf, sizeof(keyBuf) - 1, "%s.%s", curSec, token);
// eat =
line = strParseToken(line, token, NULL);
if (token[0] != '=' || token[1] != '\0') {
sysLogPrintf(LOG_ERROR, "configLoad: malformed keyvalue line: %s", lineBuf);
continue;
}
// eat whitespace on the left
while (line < end && isspace(*line)) {
++line;
}
// copy out the section name
const s32 len = end - line;
if (len > CONFIG_MAX_SECNAME) {
continue; // too long
}
memcpy(curSec, line, len);
curSec[len] = '\0';
} else {
// probably a key=value pair
char *eq = strchr(line, '=');
if (!eq) {
continue; // garbage
}
char *value = eq + 1;
if (!*value) {
continue; // just a =
}
// trim right whitespace on the key
--eq;
while (eq > line && isspace(*eq)) {
--eq;
}
if (eq == line) {
continue; // = with nothing on the left
// the rest of the line is the value
line = strTrim(line);
if (line[0] == '"') {
line = strUnquote(line);
}
eq[1] = '\0';
// assemble full key name and read the value
snprintf(keyBuf, sizeof(keyBuf) - 1, "%s.%s", curSec, line);
configSetFromString(keyBuf, value);
configSetFromString(keyBuf, line);
}
}

Expand Down
78 changes: 60 additions & 18 deletions port/src/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
#include "config.h"
#include "system.h"
#include "platform.h"
#include "utils.h"
#include "fs.h"

#define DEFAULT_DATADIR_NAME "data"
#define DEFAULT_BASEDIR_NAME "data"

static char dataDir[FS_MAXPATH + 1]; // replaces $D
static char baseDir[FS_MAXPATH + 1]; // replaces $B
static char modDir[FS_MAXPATH + 1]; // replaces $M
static char saveDir[FS_MAXPATH + 1]; // replaces $S
static char homeDir[FS_MAXPATH + 1]; // replaces $H
static char exeDir[FS_MAXPATH + 1]; // replaces $E
Expand Down Expand Up @@ -57,7 +59,8 @@ const char *fsFullPath(const char *relPath)
switch (relPath[1]) {
case 'E': expStr = exeDir; break;
case 'H': expStr = homeDir; break;
case 'D': expStr = dataDir; break;
case 'M': expStr = modDir; break;
case 'B': expStr = baseDir; break;
case 'S': expStr = saveDir; break;
default: break;
}
Expand All @@ -71,13 +74,20 @@ const char *fsFullPath(const char *relPath)
}
// couldn't expand anything, return as is
return relPath;
} else if (!dataDir[0] || fsPathIsAbsolute(relPath) || fsPathIsCwdRelative(relPath)) {
// user explicitly wants working directory or this is an absolute path or we have no dataDir set up yet
} else if (!baseDir[0] || fsPathIsAbsolute(relPath) || fsPathIsCwdRelative(relPath)) {
// user explicitly wants working directory or this is an absolute path or we have no baseDir set up yet
return relPath;
}

// path relative to data dir
snprintf(pathBuf, FS_MAXPATH, "%s/%s", dataDir, relPath);
// path relative to mod or base dir; this will be a read request, so check where the file actually is
if (modDir[0]) {
snprintf(pathBuf, FS_MAXPATH, "%s/%s", modDir, relPath);
if (fsFileSize(pathBuf) >= 0) {
return pathBuf;
}
}
// fall back to basedir
snprintf(pathBuf, FS_MAXPATH, "%s/%s", baseDir, relPath);
return pathBuf;
}

Expand All @@ -93,21 +103,45 @@ s32 fsInit(void)
sysGetHomePath(homeDir, FS_MAXPATH);
}

// get path to data dir and expand it if needed
const char *path = sysArgGetString("--datadir");
// get path to base dir and expand it if needed
const char *path = sysArgGetString("--basedir");
if (!path) {
// check if there's a data directory in working directory or homeDir, otherwise default to exe directory
path = "$E/" DEFAULT_DATADIR_NAME;
// check if there's a `data` directory in working directory or homeDir, otherwise default to exe directory
path = "$E/" DEFAULT_BASEDIR_NAME;
if (!portable) {
if (fsFileSize("./" DEFAULT_DATADIR_NAME) >= 0) {
path = "./" DEFAULT_DATADIR_NAME;
} else if (fsFileSize("$H/" DEFAULT_DATADIR_NAME)) {
path = "$H/" DEFAULT_DATADIR_NAME;
if (fsFileSize("./" DEFAULT_BASEDIR_NAME) >= 0) {
path = "./" DEFAULT_BASEDIR_NAME;
} else if (fsFileSize("$H/" DEFAULT_BASEDIR_NAME)) {
path = "$H/" DEFAULT_BASEDIR_NAME;
}
}
}

strncpy(dataDir, fsFullPath(path), FS_MAXPATH);
strncpy(baseDir, fsFullPath(path), FS_MAXPATH);

// get path to mod dir and expand it if needed
// mod directory is overlaid on top of base directory
path = sysArgGetString("--moddir");
if (path) {
if (fsPathIsAbsolute(path) || fsPathIsCwdRelative(path) || path[0] == '$') {
// path is explicit; check as-is
if (fsFileSize(path) >= 0) {
strncpy(modDir, fsFullPath(path), FS_MAXPATH);
}
} else {
// path is relative to workdir; try to find it
const char *priority[] = { ".", "$E", "$H" };
for (s32 i = 0; i < 2 + (portable != 0); ++i) {
char *tmp = strFmt("%s/%s", priority[i], path);
if (fsFileSize(tmp) >= 0) {
strncpy(modDir, fsFullPath(tmp), FS_MAXPATH);
break;
}
}
}
if (!modDir[0]) {
sysLogPrintf(LOG_WARNING, "could not find specified moddir `%s`", path);
}
}

// get path to save dir and expand it if needed
path = sysArgGetString("--savedir");
Expand Down Expand Up @@ -136,12 +170,20 @@ s32 fsInit(void)

strncpy(saveDir, fsFullPath(path), FS_MAXPATH);

sysLogPrintf(LOG_NOTE, "data dir: %s", dataDir);
if (modDir[0]) {
sysLogPrintf(LOG_NOTE, " mod dir: %s", modDir);
}
sysLogPrintf(LOG_NOTE, "base dir: %s", baseDir);
sysLogPrintf(LOG_NOTE, "save dir: %s", saveDir);

return 0;
}

const char *fsGetModDir(void)
{
return modDir[0] ? modDir : NULL;
}

void *fsFileLoad(const char *name, u32 *outSize)
{
const char *fullName = fsFullPath(name);
Expand Down
5 changes: 5 additions & 0 deletions port/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "fs.h"
#include "romdata.h"
#include "config.h"
#include "mod.h"
#include "system.h"

u32 g_OsMemSize = 0;
Expand Down Expand Up @@ -95,6 +96,10 @@ int main(int argc, const char **argv)

gameLoadConfig();

if (fsGetModDir()) {
modConfigLoad(MOD_CONFIG_FNAME);
}

atexit(cleanup);

bootCreateSched();
Expand Down
Loading

0 comments on commit d98575d

Please sign in to comment.