Skip to content

Commit

Permalink
xbox: Check ISO is supported before launching
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryzee119 committed Nov 16, 2023
1 parent d16d196 commit 198256d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 28 deletions.
32 changes: 31 additions & 1 deletion src/dash_launcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,37 @@ bool dash_launcher_is_iso(const char *file_path, char *title, char *title_id)

bool dash_launcher_is_launchable(const char *file_path)
{
return dash_launcher_is_xbe(file_path, NULL, NULL) || dash_launcher_is_iso(file_path, NULL, NULL);
if (dash_launcher_is_xbe(file_path, NULL, NULL))
{
return true;
}
#ifdef NXDK
if (dash_launcher_is_iso(file_path, NULL, NULL))
{
uint32_t supported_isos = platform_iso_supported();
const char *ext = file_path + strlen(file_path) - 4;
if (strcasecmp(ext, ".cci") == 0 && (supported_isos & PLATFORM_XBOX_CCI_SUPPORTED) == 0)
{
//Tried to launch CCI on unsupported BIOS
lv_label_set_text(lv_label_create(container_open()), "ERROR: Tried to launch CCI on unsupported BIOS");
return false;
}
else if (strcasecmp(ext, ".cso") == 0 && (supported_isos & PLATFORM_XBOX_CSO_SUPPORTED) == 0)
{
//Tried to launch CSO on unsupported BIOS
lv_label_set_text(lv_label_create(container_open()), "ERROR: Tried to launch CSO on unsupported BIOS");
return false;
}
else if (strcasecmp(ext, ".iso") == 0 && (supported_isos & PLATFORM_XBOX_ISO_SUPPORTED) == 0)
{
//Tried to launch ISO on unsupported BIOS
lv_label_set_text(lv_label_create(container_open()), "ERROR: Tried to launch ISO on unsupported BIOS");
return false;
}
return true;
}
#endif
return false;
}

void dash_launcher_go(const char *selected_path)
Expand Down
11 changes: 7 additions & 4 deletions src/dash_scroller.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,14 @@ static void item_selection_callback(lv_event_t *event)
lv_snprintf(cmd, sizeof(cmd), SQL_TITLE_GET_LAUNCH_PATH, t->db_id);
db_command_with_callback(cmd, get_launch_path_callback, NULL);

platform_get_iso8601_time(time_str);
lv_snprintf(cmd, sizeof(cmd), SQL_TITLE_SET_LAST_LAUNCH_DATETIME, time_str, t->db_id);
db_command_with_callback(cmd, NULL, NULL);
if (dash_launcher_is_launchable(dash_launch_path))
{
platform_get_iso8601_time(time_str);
lv_snprintf(cmd, sizeof(cmd), SQL_TITLE_SET_LAST_LAUNCH_DATETIME, time_str, t->db_id);
db_command_with_callback(cmd, NULL, NULL);

lv_set_quit(LV_QUIT_OTHER);
lv_set_quit(LV_QUIT_OTHER);
}
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ void platform_flush_cache(void);
*/
void platform_get_iso8601_time(char time_str[20]);



#define PLATFORM_XBOX_ISO_SUPPORTED 0x01
#define PLATFORM_XBOX_CSO_SUPPORTED 0x02
#define PLATFORM_XBOX_CCI_SUPPORTED 0x04
/*
* Xbox Specific. Check if mounting/launching ISOs is supported by the current BIOS
This is a bit flag,
0x1 = ISO is supported
0x2 = CSO is supported
0x4 = CCI is supported
*/
uint32_t platform_iso_supported();

#ifdef __cplusplus
}
#endif
Expand Down
77 changes: 54 additions & 23 deletions src/platform/xbox/xbox_launch.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ int XboxGetFullLaunchPath(const char *input, char *output)
output[endOfPrefix++] = '\\';
}

strcpy(&output[endOfPrefix], pathStart);
// If we have a path, put it back
if (pathStart)
{
strcpy(&output[endOfPrefix], pathStart);
}

// Replace any remaining forward slashes with backslashes
char *slash = strchr(output, '/');
Expand Down Expand Up @@ -174,12 +178,6 @@ typedef struct _ATTACH_SLICE_DATA_CERBIOS {
ANSI_STRING mount_point;
} attach_slice_data_cerbios_t;

void xbox_mount_iso(const char *path)
{
char *xbox_path = lv_mem_alloc(MAX_PATH);
XboxGetFullLaunchPath(path, xbox_path);
}

static int sort_slices(const void* a, const void* b) {
ANSI_STRING* strA = (ANSI_STRING*)a;
ANSI_STRING* strB = (ANSI_STRING*)b;
Expand All @@ -188,6 +186,44 @@ static int sort_slices(const void* a, const void* b) {
return strncmp(strA->Buffer, strB->Buffer, LV_MIN(strA->Length, strB->Length));
}

uint32_t platform_iso_supported()
{
uint32_t support_flags = 0;

OBJECT_ATTRIBUTES obj_attr;
IO_STATUS_BLOCK io_status;
HANDLE handle;
NTSTATUS status;
ANSI_STRING cerb_dev;
ANSI_STRING other_dev;
RtlInitAnsiString(&other_dev, "\\Device\\CdRom1");
RtlInitAnsiString(&cerb_dev, "\\Device\\Virtual0\\Image0");

// Check if CCI is supported
InitializeObjectAttributes(&obj_attr, &cerb_dev, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile(&handle, GENERIC_READ | SYNCHRONIZE, &obj_attr, &io_status, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(status))
{
support_flags |= PLATFORM_XBOX_CCI_SUPPORTED;
}
NtClose(handle);

// Check if CSO is supported
// How?

// Check if ISO is supported
InitializeObjectAttributes(&obj_attr, &other_dev, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile(&handle, GENERIC_READ | SYNCHRONIZE, &obj_attr, &io_status, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(status))
{
support_flags |= PLATFORM_XBOX_ISO_SUPPORTED;
support_flags |= PLATFORM_XBOX_CSO_SUPPORTED; //Assume CISO is too for now
}
NtClose(handle);

return support_flags;
}

void platform_launch_iso(const char *path)
{
uint8_t num_slices = 0;
Expand All @@ -207,12 +243,12 @@ void platform_launch_iso(const char *path)
strcpy(end_path, "\\*");

// Find all ISO, CCI files and set num_slices
const char *matching_ext = &path[strlen(path) - 4];
ANSI_STRING slice_files[MAX_IMAGE_SLICES];
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFileA(sym_path, &findData);
if (hFind != INVALID_HANDLE_VALUE)
{
const char *matching_ext = &path[strlen(path) - 4];
int end = strlen(xbox_path);
do
{
Expand All @@ -230,25 +266,27 @@ void platform_launch_iso(const char *path)
}
}
} while (FindNextFileA(hFind, &findData) != 0);
FindClose(hFind);
}
lv_mem_free(xbox_path);
lv_mem_free(sym_path);


if (num_slices == 0)
{
lv_mem_free(xbox_path);
lv_mem_free(sym_path);
return;
}

// Should be sorted numerically - assumes split isos are atleast numbered sequentially
qsort(slice_files, num_slices, sizeof(ANSI_STRING), sort_slices);

// CerBios has special handling of CCI/ISO images
if (XboxKrnlVersion.Build >= 8008)
// CerBios has special handling of CCI images
bool is_cci = strcasecmp(".cci", matching_ext) == 0;
if (XboxKrnlVersion.Build >= 8008 && is_cci)
{
slices_cerbios = lv_mem_alloc(sizeof(attach_slice_data_cerbios_t));
lv_memset(slices_cerbios, 0, sizeof(attach_slice_data_cerbios_t));

bool is_cci = strcmp((char *)(path + strlen(path) - 3), "cci") == 0;
slices_cerbios->DeviceType = (is_cci) ? 0x64 : 0x44; // Means CCI or normal ISO
slices_cerbios->num_slices = num_slices;
RtlInitAnsiString(&slices_cerbios->mount_point, "\\Device\\CdRom0");
Expand All @@ -274,12 +312,10 @@ void platform_launch_iso(const char *path)
if (!NT_SUCCESS(status))
{
DbgPrint("ERROR: Could not open %s\n", dev_name.Buffer);
goto iso_cleanup;
NtClose(handle);
return;
}

nxUnmountDrive('D');

if (XboxKrnlVersion.Build >= 8008)
if (XboxKrnlVersion.Build >= 8008 && is_cci)
{
NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io_status, VIRTUAL_DETACH_CERBIOS, NULL, 0, NULL, 0);
NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io_status, VIRTUAL_ATTACH_CERBIOS, slices_cerbios, sizeof(attach_slice_data_cerbios_t), NULL, 0);
Expand All @@ -292,9 +328,4 @@ void platform_launch_iso(const char *path)

// If the user did a quick reboot, or somehow got back to us make sure we can use the volume again
IoDismountVolumeByName(&dev_name);

iso_cleanup:
lv_mem_free(xbox_path);
lv_mem_free(sym_path);
NtClose(handle);
}

0 comments on commit 198256d

Please sign in to comment.