1 #include "xbox_ref_bridge.h"
5 void xbox_ref_dump_result_init(xbox_ref_dump_result *result)
8 memset(result, 0, sizeof(*result));
12 #define WIN32_LEAN_AND_MEAN
13 #define _WIN32_WINNT 0x0500
17 #include "xbox_ref/utils.h"
18 #include "xbox_ref/unlock.h"
19 #include "xbox_ref/xbox_ref_log.h"
21 #define printf xbox_ref_printf
23 #define XBOX_REF_LOCKED_VIDEO_VIEW_MAX_SECTORS 200000U
25 static BOOL xbox_ref_capacity_is_game_view(uint32_t sectors)
27 return sectors > XBOX_REF_LOCKED_VIDEO_VIEW_MAX_SECTORS;
30 static uint32_t xbox_ref_refresh_ready_capacity(HANDLE hDevice)
32 RefreshVolume(hDevice);
34 EnsureDriveReady(hDevice, 30000);
35 return GetTotalSectors(hDevice);
38 static char xbox_ref_drive_letter_from_device(const char *device)
40 if (!device || !device[0]) return 0;
41 if (device[0] && device[1] == ':') return device[0];
42 if (device[0] == '\\' && device[1] == '\\' && device[2] == '.' && device[3] == '\\' && device[4] && device[5] == ':') return device[4];
46 static int xbox_ref_gdr8050l_dump_core(HANDLE hDevice, const char *device, const char *filename, char mode, BOOL ownsHandle, xbox_ref_dump_result *result)
50 BOOL isDualLayer = FALSE;
51 bool isDualLayerBool = false;
52 char mediaId[33] = {0};
53 char finalFilename[MAX_PATH] = {0};
54 BOOL filenameOverride;
55 uint32_t totalSectors = 0;
56 DWORD dwBytesReturned = 0;
57 BOOL volumeLocked = FALSE;
60 xbox_ref_dump_result_init(result);
62 result->attempted = 1;
66 filenameOverride = (filename && filename[0]);
68 if (mode != '1' && mode != '2') {
69 xbox_ref_log_open_for_target(filename, 0);
70 printf("[XBOX-REF] Fatal: unsupported Xbox reference dump mode '%c'.\n", mode);
76 driveLetter = xbox_ref_drive_letter_from_device(device);
78 xbox_ref_log_open_for_target(filename, 0);
79 printf("[XBOX-REF] Fatal: could not parse drive letter from device '%s'.\n", device ? device : "(null)");
85 xbox_ref_log_open_for_target(filename, driveLetter);
86 printf("[XBOX-REF] Using copied original GDR-8050L dumper flow for drive %c:.\n", driveLetter);
87 printf("[XBOX-REF] Handle mode: %s.\n", ownsHandle ? "opened by xbox_ref wrapper" : "using FriiDump's existing drive HANDLE");
88 printf("[XBOX-REF] Preserving reference timing sleeps: tray 3000ms, ready-settle 1500ms/10000ms fallback, RefreshVolume 1000ms + post-refresh 2000ms.\n");
90 if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL) {
91 printf("[XBOX-REF] Fatal: invalid drive handle for %c:.\n", driveLetter);
96 uint32_t entrySectors;
97 uint32_t verifiedSectors;
98 BOOL preparedAfterHandshake = FALSE;
100 printf("Opening drive %c: for state-aware Xbox handshake...\n", driveLetter);
101 if (!EnsureDriveReady(hDevice, 30000)) {
102 printf("[XBOX-REF] Fatal: drive did not become ready before Xbox state preparation.\n");
106 entrySectors = GetTotalSectors(hDevice);
107 printf("[XBOX-REF] Entry READ CAPACITY: %u sectors.\n", entrySectors);
109 if (xbox_ref_capacity_is_game_view(entrySectors)) {
110 printf("[XBOX-REF] Entry state already exposes the Xbox game view; skipping the redundant initial handshake and tray cycle.\n");
112 printf("[XBOX-REF] Entry state appears locked/video; attempting the full handshake directly without a media transition.\n");
113 UnlockDrive(hDevice);
114 verifiedSectors = xbox_ref_refresh_ready_capacity(hDevice);
115 preparedAfterHandshake = TRUE;
116 printf("[XBOX-REF] Direct-handshake READ CAPACITY: %u sectors.\n", verifiedSectors);
118 if (!xbox_ref_capacity_is_game_view(verifiedSectors)) {
119 printf("[XBOX-REF][WARN] Direct handshake did not expose the Xbox game view; performing one tray-cycle recovery and retry.\n");
120 AutomateTrayCycle(hDevice);
121 printf("[XBOX-REF] Re-applying the full handshake after recovery media change.\n");
122 UnlockDrive(hDevice);
123 verifiedSectors = xbox_ref_refresh_ready_capacity(hDevice);
124 printf("[XBOX-REF] Recovery-handshake READ CAPACITY: %u sectors.\n", verifiedSectors);
126 if (!xbox_ref_capacity_is_game_view(verifiedSectors)) {
127 printf("[XBOX-REF] Fatal: Xbox game view was not established after direct and recovery handshakes.\n");
133 if (!preparedAfterHandshake)
134 xbox_ref_refresh_ready_capacity(hDevice);
137 printf("Setting drive to maximum performance mode...\n");
138 SetDriveSpeedMax(hDevice);
140 if (!DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL)) {
141 printf("[!] Warning: Could not lock volume. Close any open folders pointing to the drive.\n");
142 printf("[XBOX-REF] The reference dumper treats this as fatal before XBE/title probing.\n");
147 printf("Searching for Xbox Game Signature (Raw SCSI Scan)...\n");
148 game = GetXboxGameInfo(hDevice);
149 printf("Game Title Raw: %s\n", game.TitleName);
150 ReadXboxGameDir(hDevice);
152 totalSectors = GetXboxPhysicalSectors(hDevice);
153 isDualLayerBool = false;
154 GetDiscMetadata(hDevice, &totalSectors, &isDualLayerBool, &game);
155 isDualLayer = isDualLayerBool ? TRUE : FALSE;
156 GetMediaID(hDevice, mediaId);
159 if (game.Success && game.TitleName[0]) {
160 strncpy(result->title, game.TitleName, sizeof(result->title) - 1);
161 result->title[sizeof(result->title) - 1] = '\0';
164 strncpy(result->media_id, mediaId, sizeof(result->media_id) - 1);
165 result->media_id[sizeof(result->media_id) - 1] = '\0';
170 char titleCopy[sizeof(game.TitleName)];
171 memset(titleCopy, 0, sizeof(titleCopy));
172 strncpy(titleCopy, game.TitleName, sizeof(titleCopy) - 1);
173 SanitizeFilename(titleCopy);
174 if (filenameOverride) {
175 strncpy(finalFilename, filename, sizeof(finalFilename) - 1);
176 finalFilename[sizeof(finalFilename) - 1] = '\0';
177 printf("[XBOX-REF] Output filename override: %s\n", finalFilename);
179 snprintf(finalFilename, sizeof(finalFilename), "%s[%s].%s",
180 titleCopy[0] ? titleCopy : "XboxDisc",
181 mediaId[0] ? mediaId : "UNKNOWN_ID",
182 (mode == '1') ? "iso" : "xiso");
183 printf("[XBOX-REF] XBE/DMI-derived output filename: %s\n", finalFilename);
184 xbox_ref_log_retarget(finalFilename);
186 DisplayXboxGameInfo(game);
187 printf("\n--- DISC INFORMATION ---\n");
188 printf("Physical Sectors: %u\n", totalSectors);
189 printf("Layers: %d\n", isDualLayer ? 2 : 1);
190 printf("Media ID: %s\n", mediaId);
191 printf("Target File: %s\n", finalFilename);
192 printf("-------------------------------\n\n");
194 if (filenameOverride) {
195 strncpy(finalFilename, filename, sizeof(finalFilename) - 1);
196 finalFilename[sizeof(finalFilename) - 1] = '\0';
197 printf("Error: Could not retrieve Xbox game information; using override filename %s.\n", finalFilename);
199 printf("Error: Could not retrieve Xbox game information and no output filename override was supplied.\n");
200 printf(" Rerun with -i <file> or -X <file> if metadata probing cannot complete.\n");
205 if (result && finalFilename[0]) {
206 strncpy(result->output_path, finalFilename, sizeof(result->output_path) - 1);
207 result->output_path[sizeof(result->output_path) - 1] = '\0';
210 if (totalSectors != (uint32_t)(REDUMP_SECTORS)) {
211 printf("[WARNING] Unlocked drive-reported sectors: %u does not match expected Xbox game-view sectors: %u\n", totalSectors, (uint32_t)(REDUMP_SECTORS));
212 printf("-Homebrew games may have different sizes.\n\n");
215 if (totalSectors == 0) {
216 printf("Error: Could not determine total sectors for dumping.\n");
220 printf("Starting dump with copied DumpXboxGameDisc() mode %c...\n", mode);
221 ok = DumpXboxGameDisc(hDevice, finalFilename, mode, totalSectors, isDualLayerBool, FALSE, result);
225 DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
226 if (ownsHandle && hDevice != INVALID_HANDLE_VALUE && hDevice != NULL) {
227 printf("Issuing STOP UNIT / spin-down after dump attempt... ");
228 if (StopDriveUnit(hDevice)) printf("OK\n"); else printf("FAILED\n");
231 printf("[XBOX-REF] Returning to FriiDump; final STOP UNIT cleanup will use the same handle.\n");
234 printf("[XBOX-REF] Log file complete: %s\n", xbox_ref_log_path() ? xbox_ref_log_path() : "(unavailable)");
235 xbox_ref_log_close();
237 printf("[XBOX-REF] Returning finalized output evidence to FriiDump's shared Redump verifier.\n");
239 printf("[XBOX-REF] No completed output evidence is available for shared Redump verification.\n");
244 int xbox_ref_gdr8050l_dump_with_handle(void *native_handle, const char *device, const char *filename, char mode, xbox_ref_dump_result *result)
246 return xbox_ref_gdr8050l_dump_core((HANDLE)native_handle, device, filename, mode, FALSE, result);
249 int xbox_ref_gdr8050l_dump(const char *device, const char *filename, char mode, xbox_ref_dump_result *result)
254 driveLetter = xbox_ref_drive_letter_from_device(device);
256 xbox_ref_log_open_for_target(filename, 0);
257 printf("[XBOX-REF] Fatal: could not parse drive letter from device '%s'.\n", device ? device : "(null)");
258 xbox_ref_log_close();
262 hDevice = OpenDrive(driveLetter);
263 if (hDevice == INVALID_HANDLE_VALUE) {
264 xbox_ref_log_open_for_target(filename, driveLetter);
265 printf("[XBOX-REF] Fatal: Cannot open drive %c:. Run as Administrator.\n", driveLetter);
266 xbox_ref_log_close();
270 return xbox_ref_gdr8050l_dump_core(hDevice, device, filename, mode, TRUE, result);
273 int xbox_ref_gdr8050l_dump_with_handle(void *native_handle, const char *device, const char *filename, char mode, xbox_ref_dump_result *result)
275 (void)native_handle; (void)device; (void)filename; (void)mode; xbox_ref_dump_result_init(result); return 1;
278 int xbox_ref_gdr8050l_dump(const char *device, const char *filename, char mode, xbox_ref_dump_result *result)
280 (void)device; (void)filename; (void)mode; xbox_ref_dump_result_init(result); return 1;