]> FriiDump Source - friidump.git/blobdiff - src/redump_dat.c
FriiDump 0.5.3.15: close XGD1 geometry and lead-in capture
[friidump.git] / src / redump_dat.c
index 6231679b06a0964c0928c3c6e170770092881037..028aa1362938c89f25c67aed0b951b2e0b46bca0 100644 (file)
@@ -5,6 +5,93 @@
 #include <stdlib.h>
 #include <string.h>
 
+static int redump_path_exists(const char *path) {
+    FILE *f;
+    if (!path || !path[0])
+        return 0;
+    f = fopen(path, "rb");
+    if (!f)
+        return 0;
+    fclose(f);
+    return 1;
+}
+
+static int redump_join_path(
+    const char *dir,
+    const char *child_dir,
+    const char *basename,
+    char *out_path,
+    size_t out_path_size
+) {
+    int written;
+
+    if (!dir || !dir[0] || !basename || !basename[0] ||
+        !out_path || out_path_size == 0)
+        return 0;
+
+    if (child_dir && child_dir[0])
+        written = snprintf(out_path, out_path_size, "%s/%s/%s",
+                           dir, child_dir, basename);
+    else
+        written = snprintf(out_path, out_path_size, "%s/%s",
+                           dir, basename);
+
+    if (written < 0 || (size_t)written >= out_path_size) {
+        out_path[0] = '\0';
+        return 0;
+    }
+
+    return 1;
+}
+
+int redump_resolve_dat_path(
+    const char *explicit_dir,
+    const char *executable_dir,
+    const char *basename,
+    char *out_path,
+    size_t out_path_size
+) {
+    char candidate[1024];
+
+    if (!basename || !basename[0] || !out_path || out_path_size == 0)
+        return 0;
+
+    out_path[0] = '\0';
+
+    if (explicit_dir && explicit_dir[0]) {
+        if (!redump_join_path(explicit_dir, NULL, basename,
+                              out_path, out_path_size))
+            return 0;
+        return redump_path_exists(out_path);
+    }
+
+    if (executable_dir && executable_dir[0] &&
+        redump_join_path(executable_dir, "redump_dat", basename,
+                         candidate, sizeof(candidate))) {
+        if (redump_path_exists(candidate)) {
+            snprintf(out_path, out_path_size, "%s", candidate);
+            return 1;
+        }
+
+        /* Retain the executable-relative path as the preferred diagnostic
+         * candidate if neither automatic location exists. */
+        snprintf(out_path, out_path_size, "%s", candidate);
+    }
+
+    if (redump_join_path(".", "redump_dat", basename,
+                         candidate, sizeof(candidate))) {
+        if (redump_path_exists(candidate)) {
+            snprintf(out_path, out_path_size, "%s", candidate);
+            return 1;
+        }
+
+        if (!out_path[0])
+            snprintf(out_path, out_path_size, "%s", candidate);
+    }
+
+    return 0;
+}
+
 static int redump_ascii_equal(const char *a, const char *b) {
     unsigned char ca, cb;
     if (!a || !b)