X-Git-Url: https://git.jtryba.com/browse/friidump.git/blobdiff_plain/6e43cd3fd4f7324a177331a01d653b4c19c4bca7..7564cb0e17b2d09c012ac9f2a6e62b4363fd563f:/src/friidump.c?ds=inline diff --git a/src/friidump.c b/src/friidump.c index e30b553..292f658 100644 --- a/src/friidump.c +++ b/src/friidump.c @@ -28,6 +28,7 @@ #include "dumper.h" #include "unscrambler.h" #include "xbox_ref/xbox_ref_log.h" +#include "xbox_ref_bridge.h" #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 char g_executable_dir[1024]; 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_VERSION "0.5.3.10" +#define PACKAGE_VERSION "0.5.3.15" #ifdef WIN32 @@ -245,6 +247,10 @@ struct { 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; @@ -267,6 +273,8 @@ static char friidump_drive_letter_from_device(const char *device) { 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; @@ -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: @@ -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) - ? "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) { @@ -699,8 +760,11 @@ static void friidump_verify_redump_values(disc_type type_id, 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); @@ -901,9 +965,13 @@ void help (void) { " --scan-dump-prefix Optional raw 0xE7 window dump prefix for --hlds-e7-scan\n" " --hlds-profile-report Write selected HLDS profile/evidence JSON\n" " --redump-dat-dir Directory containing canonical Redump DAT files\n" - " (default: redump_dat)\n" + " (default: executable-relative redump_dat, then current directory)\n" " --redump-report Write atomic Redump evidence JSON\n" " --no-redump-verify Disable automatic post-dump DAT verification\n" + " --xgd1-layout-probe Read-only locked/unlocked XGD1 boundary probe;\n" + " writes atomic JSON and does not create an ISO\n" + " --xgd1-raw-id-probe 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" @@ -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}, + {"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'}, @@ -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.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 @@ -1165,6 +1239,16 @@ bool optparse (int argc, char **argv) { 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: @@ -1179,6 +1263,9 @@ bool optparse (int argc, char **argv) { 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) { @@ -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"); + } 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; @@ -1212,7 +1306,7 @@ int dologic (disc *d, progstats *stats) { 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; @@ -1327,6 +1421,67 @@ int dologic (disc *d, progstats *stats) { 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... "); @@ -1679,6 +1834,7 @@ int main (int argc, char *argv[]) { /* First of all... */ drop_euid (); + friidump_init_executable_dir((argc > 0) ? argv[0] : NULL); 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.xgd1_layout_probe_report); + my_free (options.xgd1_raw_id_probe_report); } if (xbox_ref_log_path())