X-Git-Url: https://git.jtryba.com/browse/friidump.git/blobdiff_plain/d44030dfa440b1967ec7dcd3ccfe46fb69934486..7564cb0e17b2d09c012ac9f2a6e62b4363fd563f:/libfriidump/xbox_ref/utils.c?ds=sidebyside diff --git a/libfriidump/xbox_ref/utils.c b/libfriidump/xbox_ref/utils.c index 2e24078..c63b03b 100644 --- a/libfriidump/xbox_ref/utils.c +++ b/libfriidump/xbox_ref/utils.c @@ -3,6 +3,7 @@ #include "xbe_cert.h" #include "unlock.h" #include "xbox_ref_log.h" +#include "../xbox_ref_bridge.h" #include #include @@ -1980,7 +1981,7 @@ static void JsonWriteValidationWarnings(FILE *f, const XboxDvdSidecarCapture *ca if (!payloadFilesPresent) WRITE_WARNING("payload_files_not_fully_present"); if (redumpStyleZeroFilledPadding) - WRITE_WARNING("redump_style_padding_zero_filled_pending_hardware_capture"); + WRITE_WARNING("redump_style_padding_zero_filled_unresolved_content"); #undef WRITE_WARNING @@ -2475,6 +2476,9 @@ static BOOL WriteXboxDvdMediaProfileFile(const char *isoFilename, fprintf(json, " \"pregame_padding_start_lba\": %u,\n", redumpStyle ? XGD1_VIDEO_L0_SECTORS : 0U); fprintf(json, " \"pregame_padding_sector_count\": %u,\n", redumpStyle ? (XGD1_GAME_OUTPUT_START_LBA - XGD1_VIDEO_L0_SECTORS) : 0U); fprintf(json, " \"game_output_start_lba\": %u,\n", gameOutputLba); + fprintf(json, " \"game_leadin_unlocked_source_start_lba\": %u,\n", redumpStyle ? 0U : gameSourceLba); + fprintf(json, " \"game_leadin_source_sector_count\": %u,\n", redumpStyle ? XGD1_XISO_LEADIN_SECTORS : 0U); + fprintf(json, " \"game_leadin_source\": "); JsonWriteEscapedString(json, redumpStyle ? "drive_read10" : "not_applicable"); fprintf(json, ",\n"); fprintf(json, " \"game_unlocked_source_start_lba\": %u,\n", gameSourceLba); fprintf(json, " \"game_unlocked_source_sector_count\": %u,\n", redumpStyle ? XGD1_GAME_SOURCE_SECTORS : gameSectors); fprintf(json, " \"game_xiso_leadin_sector_count\": %u,\n", redumpStyle ? XGD1_XISO_LEADIN_SECTORS : 0U); @@ -2493,10 +2497,12 @@ static BOOL WriteXboxDvdMediaProfileFile(const char *isoFilename, fprintf(json, " \"reconstruction\": {\n"); fprintf(json, " \"is_reconstructed_layout\": %s,\n", redumpStyle ? "true" : "false"); - fprintf(json, " \"filler_policy\": "); JsonWriteEscapedString(json, redumpStyle ? "zero_fill_until_drive_can_read_filler" : "not_applicable"); fprintf(json, ",\n"); + fprintf(json, " \"filler_policy\": "); JsonWriteEscapedString(json, redumpStyle ? "pregame_and_postgame_zero_fill_content_placeholder" : "not_applicable"); fprintf(json, ",\n"); + fprintf(json, " \"filler_geometry_verified\": %s,\n", redumpStyle ? "true" : "false"); fprintf(json, " \"filler_verified_from_disc\": false,\n"); fprintf(json, " \"filler_byte_value\": %s,\n", redumpStyle ? "0" : "null"); - fprintf(json, " \"pending_hardware_capture\": %s,\n", redumpStyle ? "true" : "false"); + fprintf(json, " \"pending_hardware_capture\": false,\n"); + fprintf(json, " \"unresolved_filler_content\": %s,\n", redumpStyle ? "true" : "false"); fprintf(json, " \"filler_ranges\": [\n"); if (redumpStyle) { @@ -2514,7 +2520,7 @@ static BOOL WriteXboxDvdMediaProfileFile(const char *isoFilename, fprintf(json, " }\n"); } fprintf(json, " ],\n"); - fprintf(json, " \"note\": \"Padding/filler ranges are intentionally zero-filled placeholders until a drive/workflow capable of reading those regions is available.\"\n"); + fprintf(json, " \"note\": \"Pregame and postgame physical locations are verified by cache-aligned raw sector IDs, but their inaccessible contents remain zero-filled placeholders. The 32-sector game lead-in is drive-captured from unlocked LBA 0..31.\"\n"); fprintf(json, " },\n"); fprintf(json, " \"dvd_structures\": {\n"); @@ -2627,6 +2633,9 @@ static BOOL WriteXboxDvdSidecarFiles(const char *isoFilename, fprintf(json, " \"pregame_padding_start_lba\": %u,\n", redumpStyle ? XGD1_VIDEO_L0_SECTORS : 0U); fprintf(json, " \"pregame_padding_sector_count\": %u,\n", redumpStyle ? (XGD1_GAME_OUTPUT_START_LBA - XGD1_VIDEO_L0_SECTORS) : 0U); fprintf(json, " \"game_output_start_lba\": %u,\n", gameOutputLba); + fprintf(json, " \"game_leadin_unlocked_source_start_lba\": %u,\n", redumpStyle ? 0U : gameSourceLba); + fprintf(json, " \"game_leadin_source_sector_count\": %u,\n", redumpStyle ? XGD1_XISO_LEADIN_SECTORS : 0U); + fprintf(json, " \"game_leadin_source\": "); JsonWriteEscapedString(json, redumpStyle ? "drive_read10" : "not_applicable"); fprintf(json, ",\n"); fprintf(json, " \"game_unlocked_source_start_lba\": %u,\n", gameSourceLba); fprintf(json, " \"game_unlocked_source_sector_count\": %u,\n", redumpStyle ? XGD1_GAME_SOURCE_SECTORS : gameSectors); fprintf(json, " \"game_xiso_leadin_sector_count\": %u,\n", redumpStyle ? XGD1_XISO_LEADIN_SECTORS : 0U); @@ -2695,7 +2704,10 @@ static BOOL WriteXboxDvdSidecarFiles(const char *isoFilename, fprintf(json, " ],\n"); fprintf(json, " \"auth\": {\n"); - fprintf(json, " \"requires_media_transition\": true,\n"); + fprintf(json, " \"requires_media_transition\": false,\n"); + fprintf(json, " \"unlock_requires_media_transition\": false,\n"); + fprintf(json, " \"locked_video_view_restore_requires_media_transition\": true,\n"); + fprintf(json, " \"state_detection\": \"READ CAPACITY (10) visible-sector count\",\n"); fprintf(json, " \"mode_page\": \"0x3E\",\n"); fprintf(json, " \"challenge_table_source\": \"read_dvd_structure_xbox_control_block\",\n"); fprintf(json, " \"challenge_table_response_offset\": 774,\n"); @@ -2734,7 +2746,7 @@ static BOOL WriteXboxDvdSidecarFiles(const char *isoFilename, return ok; } -void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uint32_t totalDiscSectors, bool isDualLayer, bool EjectOnSuccess) +BOOL DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uint32_t totalDiscSectors, bool isDualLayer, bool EjectOnSuccess, xbox_ref_dump_result *result) { HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; @@ -2760,6 +2772,15 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin memset(&sidecarCapture, 0, sizeof(sidecarCapture)); + if (result) { + result->attempted = 1; + result->mode = xisoFormat; + if (filename && filename[0]) { + strncpy(result->output_path, filename, sizeof(result->output_path) - 1); + result->output_path[sizeof(result->output_path) - 1] = '\0'; + } + } + if (totalDiscSectors == 0) totalDiscSectors = GetTotalSectors(hDevice); if (totalDiscSectors == 0) @@ -2768,11 +2789,11 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin rawTargetSectors = NormalizeRawIsoTargetSectors(totalDiscSectors, isDualLayer); if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - return; + return FALSE; if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { CryptReleaseContext(hProv, 0); - return; + return FALSE; } EnsureDriveReady(hDevice, 30000); @@ -2788,6 +2809,8 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin outputLabel = "RAW ISO"; expectedOutputBytes = (unsigned long long)rawTargetSectors * 2048ULL; + if (result) + result->output_sectors = rawTargetSectors; if (rawTargetSectors != totalDiscSectors) { @@ -2926,20 +2949,28 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin printf("[WARN] XDFS was detected at unlocked source LBA %u, not the expected XISO header LBA 32.\n", detectedXdfsLba); } - // Build the Redump-style XISO/game region using the same proven - // convention as option 2: the first 32 sectors are synthetic XISO - // lead-in/padding, and the real XDFS volume begins at source LBA 32. - // Do not read unlocked source LBA 0..31 here; on the 8050L path those - // LBAs are not the XDFS header sectors we want in the rebuilt image. + // FriiDump 0.5.3.13 cache-aligned raw-ID validation proved that + // unlocked source LBA 0..31 is the physical 32-sector game-region + // lead-in and that XDVDFS begins at source LBA 32. Preserve the + // drive-captured lead-in instead of synthesizing zero sectors. gameSourceLba = XGD1_GAME_SOURCE_START_LBA; gameSectors = REDUMP_SECTORS; rawVideoSectors = XGD1_GAME_OUTPUT_START_LBA; rawGameSourceLba = gameSourceLba; rawGameSectors = gameSectors; - printf("[RAW] Writing %u-sector XISO lead-in/padding at output LBA %u.\n", - XGD1_XISO_LEADIN_SECTORS, XGD1_GAME_OUTPUT_START_LBA); - if (!WriteZeroSectorsOutput(outFile, hHash, XGD1_XISO_LEADIN_SECTORS, XGD1_GAME_OUTPUT_START_LBA, "GAME-XISO-LEADIN")) + printf("[RAW] Capturing %u-sector game lead-in from unlocked source LBA 0..%u at output LBA %u.\n", + XGD1_XISO_LEADIN_SECTORS, + XGD1_XISO_LEADIN_SECTORS - 1, + XGD1_GAME_OUTPUT_START_LBA); + if (!DumpSectorRangeWithRetry(hDevice, + outFile, + hHash, + 0, + XGD1_XISO_LEADIN_SECTORS, + XGD1_GAME_OUTPUT_START_LBA, + "GAME-XISO-LEADIN", + TRUE)) { VirtualFree(videoL1Buffer, 0, MEM_RELEASE); goto cleanup; @@ -3061,6 +3092,8 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin outputLabel = "XISO"; expectedOutputBytes = ((unsigned long long)sectorsToRead + 32ULL) * 2048ULL; + if (result) + result->output_sectors = sectorsToRead + 32U; printf("[SUCCESS] Final XISO target: %u sectors plus 32-sector lead-in (%llu bytes).\n", sectorsToRead, @@ -3150,6 +3183,19 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin printf("\n[WARN] Could not calculate CRC32/MD5/SHA-1/SHA-256 from finalized output file.\n"); } + if (result) { + result->output_size = GetFileSizeBytes64(filename); + strncpy(result->crc32, crc32String, sizeof(result->crc32) - 1); + result->crc32[sizeof(result->crc32) - 1] = '\0'; + strncpy(result->md5, md5String, sizeof(result->md5) - 1); + result->md5[sizeof(result->md5) - 1] = '\0'; + strncpy(result->sha1, sha1String, sizeof(result->sha1) - 1); + result->sha1[sizeof(result->sha1) - 1] = '\0'; + strncpy(result->sha256, fileSha256String, sizeof(result->sha256) - 1); + result->sha256[sizeof(result->sha256) - 1] = '\0'; + result->hashes_complete = result->crc32[0] && result->md5[0] && result->sha1[0] && result->sha256[0]; + } + if (xisoFormat == '1') { printf("Final RAW ISO Sector Count: %u\n", rawTargetSectors); @@ -3192,8 +3238,9 @@ void DumpXboxGameDisc(HANDLE hDevice, const char *filename, char xisoFormat, uin FormatElapsedTime(GetTickCount() - operationStartTick, operationTimeStr); printf("\nOperation Complete! Total elapsed: %s\n", operationTimeStr); - StopDriveUnit(hDevice); - + /* The caller owns final drive cleanup. Embedded FriiDump runs issue one + * STOP UNIT after Redump verification; standalone bridge runs stop the + * drive in xbox_ref_gdr8050l_dump_core() before closing the handle. */ if (EjectOnSuccess) ControlTray(hDevice, TRUE); @@ -3204,4 +3251,11 @@ cleanup: CryptDestroyHash(hHash); if (hProv) CryptReleaseContext(hProv, 0); + if (result) { + result->dump_success = dumpOk ? 1 : 0; + result->elapsed_seconds = (double)(GetTickCount() - operationStartTick) / 1000.0; + if (dumpOk && result->output_size == 0) + result->output_size = GetFileSizeBytes64(filename); + } + return dumpOk; }