]> FriiDump Source - friidump.git/blobdiff - src/friidump.c
FriiDump 0.5.3.15: close XGD1 geometry and lead-in capture
[friidump.git] / src / friidump.c
index e30b553f8be6f56c8b5d645e8e887d20567f5cdb..292f658039302c82d08f63de712963ddb6ac91b8 100644 (file)
@@ -28,6 +28,7 @@
 #include "dumper.h"
 #include "unscrambler.h"
 #include "xbox_ref/xbox_ref_log.h"
 #include "dumper.h"
 #include "unscrambler.h"
 #include "xbox_ref/xbox_ref_log.h"
+#include "xbox_ref_bridge.h"
 #include "redump_dat.h"
 
 #ifdef WIN32
 #include "redump_dat.h"
 
 #ifdef WIN32
@@ -77,6 +78,7 @@ static redump_verify_result g_redump_result;
 static bool g_redump_attempted = false;
 static bool g_operation_duration_override_valid = false;
 static double g_operation_duration_override = 0.0;
 static bool g_redump_attempted = false;
 static bool g_operation_duration_override_valid = false;
 static double g_operation_duration_override = 0.0;
+static char g_executable_dir[1024];
 
 static void friidump_summary_copy(char *dst, size_t dst_size, const char *src) {
        if (!dst || dst_size == 0)
 
 static void friidump_summary_copy(char *dst, size_t dst_size, const char *src) {
        if (!dst || dst_size == 0)
@@ -195,7 +197,7 @@ static void friidump_print_validation_summary(double duration, bool have_duratio
 #define PACKAGE_NAME "FriiDump"
 
 /* Define to the version of this package. */
 #define PACKAGE_NAME "FriiDump"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "0.5.3.10"
+#define PACKAGE_VERSION "0.5.3.15"
 
 
 #ifdef WIN32
 
 
 #ifdef WIN32
@@ -245,6 +247,10 @@ struct {
        char *redump_dat_dir;
        char *redump_report;
        bool no_redump_verify;
        char *redump_dat_dir;
        char *redump_report;
        bool no_redump_verify;
+       bool xgd1_layout_probe;
+       char *xgd1_layout_probe_report;
+       bool xgd1_raw_id_probe;
+       char *xgd1_raw_id_probe_report;
 } options;
 
 
 } options;
 
 
@@ -267,6 +273,8 @@ static char friidump_drive_letter_from_device(const char *device) {
 
 
 static const char *friidump_requested_output_target(void) {
 
 
 static const char *friidump_requested_output_target(void) {
+       if (options.xgd1_raw_id_probe_report && options.xgd1_raw_id_probe_report[0]) return options.xgd1_raw_id_probe_report;
+       if (options.xgd1_layout_probe_report && options.xgd1_layout_probe_report[0]) return options.xgd1_layout_probe_report;
        if (options.iso_out && options.iso_out[0]) return options.iso_out;
        if (options.xiso_out && options.xiso_out[0]) return options.xiso_out;
        if (options.raw_out && options.raw_out[0]) return options.raw_out;
        if (options.iso_out && options.iso_out[0]) return options.iso_out;
        if (options.xiso_out && options.xiso_out[0]) return options.xiso_out;
        if (options.raw_out && options.raw_out[0]) return options.raw_out;
@@ -486,6 +494,59 @@ void welcome (void) {
 
 
 
 
 
 
+static void friidump_init_executable_dir(const char *argv0) {
+    char path[1024];
+    size_t length = 0;
+    char *slash;
+    char *backslash;
+    char *separator;
+
+    g_executable_dir[0] = '\0';
+    path[0] = '\0';
+
+#ifdef WIN32
+    {
+        DWORD result = GetModuleFileNameA(NULL, path, (DWORD)sizeof(path));
+        if (result > 0 && result < sizeof(path)) {
+            path[result] = '\0';
+            length = (size_t)result;
+        }
+    }
+#else
+#if defined(__linux__)
+    {
+        ssize_t result = readlink("/proc/self/exe", path, sizeof(path) - 1);
+        if (result > 0 && (size_t)result < sizeof(path)) {
+            path[result] = '\0';
+            length = (size_t)result;
+        }
+    }
+#endif
+    if (length == 0 && argv0 && argv0[0] &&
+        (strchr(argv0, '/') || strchr(argv0, '\\'))) {
+        char *resolved = realpath(argv0, path);
+        if (resolved)
+            length = strlen(path);
+    }
+#endif
+
+    if (length == 0)
+        return;
+
+    slash = strrchr(path, '/');
+    backslash = strrchr(path, '\\');
+    separator = slash;
+    if (backslash && (!separator || backslash > separator))
+        separator = backslash;
+
+    if (!separator)
+        return;
+
+    *separator = '\0';
+    if (path[0])
+        snprintf(g_executable_dir, sizeof(g_executable_dir), "%s", path);
+}
+
 static const char *friidump_redump_dat_basename(disc_type type_id) {
     switch (type_id) {
         case DISC_TYPE_GAMECUBE:
 static const char *friidump_redump_dat_basename(disc_type type_id) {
     switch (type_id) {
         case DISC_TYPE_GAMECUBE:
@@ -673,7 +734,7 @@ static void friidump_verify_redump_values(disc_type type_id,
     redump_verify_result_init(&g_redump_result);
     g_redump_attempted = false;
     representation_note = (type_id == DISC_TYPE_XBOX)
     redump_verify_result_init(&g_redump_result);
     g_redump_attempted = false;
     representation_note = (type_id == DISC_TYPE_XBOX)
-        ? "XGD1 acquisition success and exact Redump hash identity are separate claims; documented synthetic reconstruction ranges may prevent an exact match."
+        ? "XGD1 acquisition success and exact Redump hash identity are separate claims; unresolved zero-filled pregame/postgame content may prevent an exact match."
         : "";
 
     if (options.no_redump_verify) {
         : "";
 
     if (options.no_redump_verify) {
@@ -699,8 +760,11 @@ static void friidump_verify_redump_values(disc_type type_id,
         return;
     }
 
         return;
     }
 
-    dat_dir = (options.redump_dat_dir && options.redump_dat_dir[0]) ? options.redump_dat_dir : "redump_dat";
-    snprintf(dat_path, sizeof(dat_path), "%s/%s", dat_dir, basename);
+    dat_dir = (options.redump_dat_dir && options.redump_dat_dir[0])
+        ? options.redump_dat_dir
+        : NULL;
+    redump_resolve_dat_path(dat_dir, g_executable_dir, basename,
+                            dat_path, sizeof(dat_path));
     if (output_size == 0)
         output_size = friidump_file_size(output_path);
 
     if (output_size == 0)
         output_size = friidump_file_size(output_path);
 
@@ -901,9 +965,13 @@ void help (void) {
                "     --scan-dump-prefix <prefix>       Optional raw 0xE7 window dump prefix for --hlds-e7-scan\n"
                "     --hlds-profile-report <file> Write selected HLDS profile/evidence JSON\n"
                "     --redump-dat-dir <dir> Directory containing canonical Redump DAT files\n"
                "     --scan-dump-prefix <prefix>       Optional raw 0xE7 window dump prefix for --hlds-e7-scan\n"
                "     --hlds-profile-report <file> Write selected HLDS profile/evidence JSON\n"
                "     --redump-dat-dir <dir> Directory containing canonical Redump DAT files\n"
-               "                              (default: redump_dat)\n"
+               "                              (default: executable-relative redump_dat, then current directory)\n"
                "     --redump-report <file>   Write atomic Redump evidence JSON\n"
                "     --no-redump-verify       Disable automatic post-dump DAT verification\n"
                "     --redump-report <file>   Write atomic Redump evidence JSON\n"
                "     --no-redump-verify       Disable automatic post-dump DAT verification\n"
+               "     --xgd1-layout-probe <file> Read-only locked/unlocked XGD1 boundary probe;\n"
+               "                              writes atomic JSON and does not create an ISO\n"
+               "     --xgd1-raw-id-probe <file> Modified-firmware cache-flushed, block-aligned raw-ID probe;\n"
+               "                              maps logical LBAs to decoded physical sector IDs\n"
                " -A, --allmethods              Try all known command/method combinations until\n"
                "                               one works. Reopens the drive for each command so\n"
                "                               command-specific vendor handlers are rebound.\n"
                " -A, --allmethods              Try all known command/method combinations until\n"
                "                               one works. Reopens the drive for each command so\n"
                "                               command-specific vendor handlers are rebound.\n"
@@ -962,6 +1030,8 @@ bool optparse (int argc, char **argv) {
                {"redump-dat-dir", 1, 0, 1006},
                {"redump-report", 1, 0, 1007},
                {"no-redump-verify", 0, 0, 1008},
                {"redump-dat-dir", 1, 0, 1006},
                {"redump-report", 1, 0, 1007},
                {"no-redump-verify", 0, 0, 1008},
+               {"xgd1-layout-probe", 1, 0, 1009},
+               {"xgd1-raw-id-probe", 1, 0, 1010},
 #ifdef DEBUG
                /* We don't want newbies to generate and put into circulation bad dumps, so this options are disabled for releases */
                {"donottunscramble", 0, 0, 'n'},
 #ifdef DEBUG
                /* We don't want newbies to generate and put into circulation bad dumps, so this options are disabled for releases */
                {"donottunscramble", 0, 0, 'n'},
@@ -1010,6 +1080,10 @@ bool optparse (int argc, char **argv) {
        options.redump_dat_dir = NULL;
        options.redump_report = NULL;
        options.no_redump_verify = false;
        options.redump_dat_dir = NULL;
        options.redump_report = NULL;
        options.no_redump_verify = false;
+       options.xgd1_layout_probe = false;
+       options.xgd1_layout_probe_report = NULL;
+       options.xgd1_raw_id_probe = false;
+       options.xgd1_raw_id_probe_report = NULL;
 
        do {
 #ifdef DEBUG
 
        do {
 #ifdef DEBUG
@@ -1165,6 +1239,16 @@ bool optparse (int argc, char **argv) {
                        case 1008:
                                options.no_redump_verify = true;
                                break;
                        case 1008:
                                options.no_redump_verify = true;
                                break;
+                       case 1009:
+                               options.xgd1_layout_probe = true;
+                               my_strdup (options.xgd1_layout_probe_report, optarg);
+                               options.disctype = DISC_TYPE_XBOX;
+                               break;
+                       case 1010:
+                               options.xgd1_raw_id_probe = true;
+                               my_strdup (options.xgd1_raw_id_probe_report, optarg);
+                               options.disctype = DISC_TYPE_XBOX;
+                               break;
                        case -1:
                                break;
                        default:
                        case -1:
                                break;
                        default:
@@ -1179,6 +1263,9 @@ bool optparse (int argc, char **argv) {
                fprintf (stderr, "WARNING: Extra parameters ignored\n");
        }
 
                fprintf (stderr, "WARNING: Extra parameters ignored\n");
        }
 
+       if (options.xgd1_layout_probe || options.xgd1_raw_id_probe)
+               options.disctype = DISC_TYPE_XBOX;
+
        /* Sanity checks... */
        out = false;
        if (!options.device && !options.raw_in) {
        /* Sanity checks... */
        out = false;
        if (!options.device && !options.raw_in) {
@@ -1192,6 +1279,13 @@ bool optparse (int argc, char **argv) {
                fprintf (stderr, "The -r, -i and -X options cannot be used together with -a.\n");
        } else if (options.xiso_requested && (options.raw_out || options.iso_requested)) {
                fprintf (stderr, "The -X/--xiso option is a separate Xbox output mode and cannot be combined with -r or -i.\n");
                fprintf (stderr, "The -r, -i and -X options cannot be used together with -a.\n");
        } else if (options.xiso_requested && (options.raw_out || options.iso_requested)) {
                fprintf (stderr, "The -X/--xiso option is a separate Xbox output mode and cannot be combined with -r or -i.\n");
+       } else if ((options.xgd1_layout_probe || options.xgd1_raw_id_probe) &&
+                  (options.autodump || options.raw_in || options.raw_out ||
+                   options.iso_requested || options.xiso_requested ||
+                   options.allmethods || options.hlds_e7_scan ||
+                   options.hlds_e7_subcmd_sweep || options.hlds_e7_memrange_sweep ||
+                   (options.xgd1_layout_probe && options.xgd1_raw_id_probe))) {
+               fprintf (stderr, "XGD1 probe modes are mutually exclusive read-only diagnostics and cannot be combined with dump, conversion, all-methods, or HLDS 0xE7 probe options.\n");
        } else {
                /* Specified options seem to make sense */
                out = true;
        } else {
                /* Specified options seem to make sense */
                out = true;
@@ -1212,7 +1306,7 @@ int dologic (disc *d, progstats *stats) {
        u_int32_t current_sector = 0;
        
        xbox_forced = (options.disctype == DISC_TYPE_XBOX);
        u_int32_t current_sector = 0;
        
        xbox_forced = (options.disctype == DISC_TYPE_XBOX);
-       xbox_output_requested = xbox_forced || options.xiso_requested;
+       xbox_output_requested = xbox_forced || options.xiso_requested || options.xgd1_layout_probe || options.xgd1_raw_id_probe;
        dump_attempted = false;
        
        
        dump_attempted = false;
        
        
@@ -1327,6 +1421,67 @@ int dologic (disc *d, progstats *stats) {
                                                fprintf (stderr, "OK\n");
                                }
 
                                                fprintf (stderr, "OK\n");
                                }
 
+                               if (options.xgd1_layout_probe || options.xgd1_raw_id_probe) {
+#ifdef WIN32
+                                       int media_rc;
+                                       int media_sense_key;
+                                       int media_asc;
+                                       int media_ascq;
+                                       int probe_status;
+                                       bool stop_ok;
+                                       const char *probe_name;
+
+                                       probe_name = options.xgd1_raw_id_probe ? "XGD1 raw-sector ID" : "XGD1 logical-boundary";
+
+                                       if (!disc_is_xbox_challenge_drive (d)) {
+                                               fprintf (stderr,
+                                                        "%s probe currently supports only the GDR-8050L challenge-handshake profile.\n",
+                                                        probe_name);
+                                               return false;
+                                       }
+
+                                       if (options.xgd1_raw_id_probe &&
+                                           !(disc_get_hlds_e7_type (d) == 44 ||
+                                             disc_get_hlds_e7_type (d) == 45 ||
+                                             disc_get_hlds_e7_type (d) == 442 ||
+                                             disc_get_hlds_e7_type (d) == 443 ||
+                                             disc_get_hlds_e7_type (d) == 445)) {
+                                               fprintf (stderr,
+                                                        "--xgd1-raw-id-probe requires the modified GDR-8050L HIT 0xE7 memdump profile.\n");
+                                               return false;
+                                       }
+
+                                       fprintf (stderr, "\nChecking for ready Xbox media before %s probing... ", probe_name);
+                                       media_rc = disc_media_preflight (d, 15000, &media_sense_key, &media_asc, &media_ascq);
+                                       if (media_rc <= 0) {
+                                               fprintf (stderr,
+                                                        "Failed (sense %02X/%02X/%02X). Insert the disc, wait for spin-up, close AutoPlay/File Explorer, and retry.\n",
+                                                        media_sense_key, media_asc, media_ascq);
+                                               return false;
+                                       }
+                                       fprintf (stderr, "OK\n");
+
+                                       gettimeofday (&(stats -> start_time), NULL);
+                                       if (options.xgd1_raw_id_probe)
+                                               probe_status = xbox_ref_xgd1_raw_id_probe_with_handle (
+                                                               disc_get_native_handle (d), disc_get_device (d), options.xgd1_raw_id_probe_report);
+                                       else
+                                               probe_status = xbox_ref_xgd1_layout_probe_with_handle (
+                                                               disc_get_native_handle (d), disc_get_device (d), options.xgd1_layout_probe_report);
+
+                                       fprintf (stderr, "Issuing STOP UNIT / spin-down after %s probe... ", probe_name);
+                                       stop_ok = disc_stop_unit (d, false);
+                                       fprintf (stderr, "%s\n", stop_ok ? "OK" : "Failed");
+                                       gettimeofday (&(stats -> end_time), NULL);
+                                       fprintf (stderr, "%s probe status: %s\n", probe_name, probe_status == 0 ? "OK" : "FAILED");
+                                       friidump_summary_reset();
+                                       return probe_status == 0;
+#else
+                                       fprintf (stderr, "XGD1 probe modes are available only in the Windows build.\n");
+                                       return false;
+#endif
+                               }
+
                                if (options.hlds_e7_scan) {
                                        out = disc_hlds_e7_scan (d, options.hlds_e7_scan_log, options.hlds_e7_scan_dump_prefix);
                                        fprintf (stderr, "Issuing STOP UNIT / spin-down after HLDS 0xE7 scan... ");
                                if (options.hlds_e7_scan) {
                                        out = disc_hlds_e7_scan (d, options.hlds_e7_scan_log, options.hlds_e7_scan_dump_prefix);
                                        fprintf (stderr, "Issuing STOP UNIT / spin-down after HLDS 0xE7 scan... ");
@@ -1679,6 +1834,7 @@ int main (int argc, char *argv[]) {
 
        /* First of all... */
        drop_euid ();
 
        /* First of all... */
        drop_euid ();
+       friidump_init_executable_dir((argc > 0) ? argv[0] : NULL);
        xbox_ref_log_open_for_target(NULL, 0);
        
        welcome ();
        xbox_ref_log_open_for_target(NULL, 0);
        
        welcome ();
@@ -1758,6 +1914,8 @@ int main (int argc, char *argv[]) {
                my_free (options.raw_out);
                my_free (options.raw_in);
                my_free (options.hlds_profile_report);
                my_free (options.raw_out);
                my_free (options.raw_in);
                my_free (options.hlds_profile_report);
+               my_free (options.xgd1_layout_probe_report);
+               my_free (options.xgd1_raw_id_probe_report);
        }
 
        if (xbox_ref_log_path())
        }
 
        if (xbox_ref_log_path())