mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Stop walking a mod's folders at 32 levels, where each level cost a stack frame of about 18 KB.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,20 +36,24 @@ static char dir[2048];
|
||||
static char start_order[MAX_MODS][256]; // names in the scan's order, for mods_changed
|
||||
|
||||
// 1 when a file lies anywhere under path.
|
||||
// Folders nest at most MOD_DEPTH deep below it: each level costs a stack frame, and the RomFS has no deeper paths.
|
||||
#define MOD_DEPTH 32
|
||||
typedef struct { const char *path; int found, depth; } HasFile;
|
||||
static int has_file_cb(const char *name, int kind, uint64_t size, void *ctx);
|
||||
static int has_file(const char *path) {
|
||||
struct { const char *path; int found; } c = {path, 0};
|
||||
static int has_file_at(const char *path, int depth) {
|
||||
HasFile c = {path, 0, depth};
|
||||
plat_fs_list(path, has_file_cb, &c);
|
||||
return c.found;
|
||||
}
|
||||
static int has_file(const char *path) { return has_file_at(path, 0); }
|
||||
static int has_file_cb(const char *name, int kind, uint64_t size, void *ctx) {
|
||||
(void)size;
|
||||
struct { const char *path; int found; } *c = ctx;
|
||||
HasFile *c = ctx;
|
||||
if (kind == PLAT_FS_FILE) {
|
||||
c->found = 1;
|
||||
} else if (kind == PLAT_FS_DIR) {
|
||||
} else if (kind == PLAT_FS_DIR && c->depth < MOD_DEPTH) {
|
||||
char sub[2100];
|
||||
if (snprintf(sub, sizeof sub, "%s/%s", c->path, name) < (int)sizeof sub) c->found = has_file(sub);
|
||||
if (snprintf(sub, sizeof sub, "%s/%s", c->path, name) < (int)sizeof sub) c->found = has_file_at(sub, c->depth + 1);
|
||||
}
|
||||
return !c->found;
|
||||
}
|
||||
|
||||
@@ -409,9 +409,13 @@ static void restbl_collect(void) {
|
||||
if (restbl_rel[0] && !strcmp(overlays[k].name, restbl_rel)) shipped_add(overlays[k].path, overlays[k].mod, 0);
|
||||
}
|
||||
|
||||
typedef struct { int k, prio; const char *dir, *rel; } ModWalk;
|
||||
typedef struct { int k, prio, depth; const char *dir, *rel; } ModWalk;
|
||||
|
||||
static void mod_walk(int k, int prio, const char *dir, const char *rel);
|
||||
// Folders nest at most this deep in a mod's RomFS folder: each level costs a stack frame (two 4 KiB paths here and
|
||||
// the listing's own), and no RomFS path of the game is deeper.
|
||||
#define MOD_WALK_DEPTH 32
|
||||
|
||||
static void mod_walk(int k, int prio, int depth, const char *dir, const char *rel);
|
||||
|
||||
// One entry of a mod's RomFS folder (mod_walk).
|
||||
static int mod_walk_cb(const char *leaf, int kind, uint64_t size, void *ctx) {
|
||||
@@ -425,7 +429,8 @@ static int mod_walk_cb(const char *leaf, int kind, uint64_t size, void *ctx) {
|
||||
return 1;
|
||||
}
|
||||
if (kind == PLAT_FS_DIR) {
|
||||
mod_walk(w->k, w->prio, file, path);
|
||||
if (w->depth >= MOD_WALK_DEPTH) rt_log("mods: %s: %s nests too deep; left out", m->name, file);
|
||||
else mod_walk(w->k, w->prio, w->depth + 1, file, path);
|
||||
return 1;
|
||||
}
|
||||
if (kind != PLAT_FS_FILE) return 1;
|
||||
@@ -453,8 +458,8 @@ static int mod_walk_cb(const char *leaf, int kind, uint64_t size, void *ctx) {
|
||||
}
|
||||
|
||||
// The files under dir (a mod's RomFS root; rel: the RomFS path of dir, "" at the root) as overlays of mod k.
|
||||
static void mod_walk(int k, int prio, const char *dir, const char *rel) {
|
||||
ModWalk w = {k, prio, dir, rel};
|
||||
static void mod_walk(int k, int prio, int depth, const char *dir, const char *rel) {
|
||||
ModWalk w = {k, prio, depth, dir, rel};
|
||||
// a folder that cannot be listed (no permission, a path longer than Windows allows) loses its files: say so
|
||||
if (plat_fs_list(dir, mod_walk_cb, &w) != PLAT_FS_OK)
|
||||
rt_log("mods: %s: cannot list %s (error %d); its files are left out", mods_at(k)->name, dir,
|
||||
@@ -507,7 +512,7 @@ static void mods_overlay_init(void) {
|
||||
for (int k = 0; k < n; k++) {
|
||||
const ModInfo *m = mods_at(k);
|
||||
// a mod with ExeFS patches waits for the rebuild that applies them: half of a mod is worse than none
|
||||
if (m->enabled && (m->kind & MOD_ROMFS) && m->problem == MOD_OK) mod_walk(k, 2 + (n - k), m->romfs, "");
|
||||
if (m->enabled && (m->kind & MOD_ROMFS) && m->problem == MOD_OK) mod_walk(k, 2 + (n - k), 0, m->romfs, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user