From 64744ce20d19973b9e27d15aa2259728b4cd5958 Mon Sep 17 00:00:00 2001 From: dimok321 <15055714+dimok789@users.noreply.github.com> Date: Sun, 7 Nov 2010 12:16:34 +0000 Subject: [PATCH] *Fixed booting games from FAT/NTFS (thx r-win) *Fixed Toy Story 3 boot bug *Changed IOS limits. Now allowing all IOSs from 200-255 to support more Waninkoko cIOS slots. You will get a warning if you don't have an IOS installed and try to choose it. --- gui.pnproj | 2 +- source/GameBootProcess.cpp | 14 +- source/bannersound.cpp | 1 - source/prompts/DiscBrowser.cpp | 1 - source/settings/Settings.cpp | 88 ++---- source/sys.cpp | 7 - source/sys.h | 1 - source/system/IosLoader.cpp | 70 +++-- source/system/IosLoader.h | 4 +- source/usbloader/disc.c | 25 +- source/usbloader/frag.c | 460 +++++++++++++++++----------- source/usbloader/frag.h | 103 ++++--- source/usbloader/wbfs/wbfs_base.cpp | 9 - source/usbloader/wbfs/wbfs_base.h | 107 ++++--- source/usbloader/wbfs/wbfs_fat.cpp | 79 +---- source/usbloader/wbfs/wbfs_fat.h | 133 ++++---- source/usbloader/wbfs/wbfs_ntfs.cpp | 44 +-- source/usbloader/wbfs/wbfs_ntfs.h | 39 ++- source/usbloader/wdvd.c | 1 + 19 files changed, 585 insertions(+), 603 deletions(-) diff --git a/gui.pnproj b/gui.pnproj index f57902f0..1cf7bd39 100644 --- a/gui.pnproj +++ b/gui.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/source/GameBootProcess.cpp b/source/GameBootProcess.cpp index 90108eae..92590dbc 100644 --- a/source/GameBootProcess.cpp +++ b/source/GameBootProcess.cpp @@ -1,6 +1,7 @@ #include "menu/menus.h" #include "mload/mload.h" #include "mload/mload_modules.h" +#include "system/IosLoader.h" #include "usbloader/disc.h" #include "usbloader/apploader.h" #include "usbloader/wdvd.h" @@ -137,7 +138,7 @@ int BootGame(const char * gameID) if(iosChoice != IOS_GetVersion()) { - gprintf("Reloading into cIOS: %i\n", iosChoice); + gprintf("Reloading into game cIOS: %i...\n", iosChoice); IosLoader::LoadGameCios(iosChoice); if(MountGamePartition(false) < 0) return -1; @@ -149,10 +150,6 @@ int BootGame(const char * gameID) ret = get_frag_list(header->id); gprintf("%d\n", ret); - gprintf("Setting fragment list..."); - ret = set_frag_list(header->id); - gprintf("%d\n", ret); - ret = Disc_SetUSB(header->id); if (ret < 0) Sys_BackToLoader(); gprintf("\tUSB set to game\n"); @@ -162,9 +159,12 @@ int BootGame(const char * gameID) gprintf("\tUSB not set, loading DVD\n"); } + gprintf("Disc_Open()..."); ret = Disc_Open(); + gprintf("%d\n", ret); - if (ret < 0) Sys_BackToLoader(); + if (ret < 0) + Sys_BackToLoader(); if (dvdheader) delete dvdheader; @@ -172,7 +172,7 @@ int BootGame(const char * gameID) ret = do_bca_code(header->id); gprintf("%d\n", ret); - if (reloadblock == ON && Sys_IsHermes()) + if (reloadblock == ON && IosLoader::IsHermesIOS()) { enable_ES_ioctlv_vector(); if (load_from_fs == PART_FS_WBFS) diff --git a/source/bannersound.cpp b/source/bannersound.cpp index 6186da4f..48d11de2 100644 --- a/source/bannersound.cpp +++ b/source/bannersound.cpp @@ -123,7 +123,6 @@ const u8 *LoadBannerSound(const u8 *discid, u32 *size) { if (!discid) return NULL; - Disc_SetUSB(NULL); wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) discid); if (!disc) { diff --git a/source/prompts/DiscBrowser.cpp b/source/prompts/DiscBrowser.cpp index ba3fbfe0..5176939f 100644 --- a/source/prompts/DiscBrowser.cpp +++ b/source/prompts/DiscBrowser.cpp @@ -44,7 +44,6 @@ int DiscBrowse(struct discHdr * header, char * alternatedname, int alternatednam HaltGui(); - Disc_SetUSB(NULL); wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) header->id); if (!disc) { diff --git a/source/settings/Settings.cpp b/source/settings/Settings.cpp index edb45bd0..baf94455 100644 --- a/source/settings/Settings.cpp +++ b/source/settings/Settings.cpp @@ -64,18 +64,6 @@ static const char *opts_partitions[3] = { trNOOP( "Game partition" ), trNOOP( "A static const char *opts_installdir[INSTALL_TO_MAX] = { trNOOP( "None" ), trNOOP( "GAMEID_Gamename" ), trNOOP( "Gamename [GAMEID]" ) }; -bool IsValidPartition(int fs_type, int cios) -{ - if (cios == 249 || cios == 250) - { - return fs_type == FS_TYPE_WBFS; - } - else - { - return fs_type == FS_TYPE_WBFS || fs_type == FS_TYPE_FAT32 || fs_type == FS_TYPE_NTFS; - } -} - /**************************************************************************** * MenuSettings ***************************************************************************/ @@ -1008,26 +996,22 @@ int MenuSettings() if (firstRun) options2.SetName(Idx, "%s", tr( "Boot/Standard" )); if (ret == Idx && Settings.godmode == 1) { - switch (Settings.cios) + char entered[4]; + snprintf(entered, sizeof(entered), "%i", Settings.cios); + if(OnScreenKeyboard(entered, sizeof(entered), 0)) { - case 222: - Settings.cios = 223; - break; - case 223: - Settings.cios = 224; - break; - case 224: - Settings.cios = 249; - break; - case 249: - Settings.cios = 250; - break; - case 250: - Settings.cios = 222; - break; - default: - Settings.cios = 222; - break; + Settings.cios = atoi(entered); + if(Settings.cios < 200) Settings.cios = 200; + else if(Settings.cios > 255) Settings.cios = 255; + + if(NandTitles.IndexOf(TITLE_ID(1, Settings.cios)) < 0) + { + WindowPrompt(tr("Warning:"), tr("This IOS was not found on the titles list. If you are sure you have it installed than ignore this warning."), tr("OK")); + } + else if(Settings.cios == 254) + { + WindowPrompt(tr("Warning:"), tr("This IOS is the BootMii ios. If you are sure it is not BootMii and you have something else installed there than ignore this warning."), tr("OK")); + } } } if (Settings.godmode == 1) @@ -1041,12 +1025,12 @@ int MenuSettings() if (ret == Idx) { // Select the next valid partition, even if that's the same one + int fs_type = partitions.pinfo[Settings.partition].fs_type; do { - Settings.partition = Settings.partition + 1 == partitions.num ? 0 - : Settings.partition + 1; - } while (!IsValidPartition(partitions.pinfo[Settings.partition].fs_type, - Settings.cios)); + Settings.partition = (Settings.partition + 1) % partitions.num; + fs_type = partitions.pinfo[Settings.partition].fs_type; + } while (!(fs_type == FS_TYPE_WBFS || fs_type == FS_TYPE_FAT32 || fs_type == FS_TYPE_NTFS)); } PartInfo pInfo = partitions.pinfo[Settings.partition]; @@ -2622,26 +2606,22 @@ int MenuGameSettings(struct discHdr * header) if (firstRun) options2.SetName(Idx, "IOS"); if (ret == Idx) { - switch (game_cfg.ios) + char entered[4]; + snprintf(entered, sizeof(entered), "%i", Settings.cios); + if(OnScreenKeyboard(entered, sizeof(entered), 0)) { - case 222: - game_cfg.ios = 223; - break; - case 223: - game_cfg.ios = 224; - break; - case 224: - game_cfg.ios = 249; - break; - case 249: - game_cfg.ios = 250; - break; - case 250: - game_cfg.ios = 222; - break; - default: - game_cfg.ios = 222; - break; + Settings.cios = atoi(entered); + if(Settings.cios < 200) Settings.cios = 200; + else if(Settings.cios > 255) Settings.cios = 255; + + if(NandTitles.IndexOf(TITLE_ID(1, Settings.cios)) < 0) + { + WindowPrompt(tr("Warning:"), tr("This IOS was not found on the titles list. If you are sure you have it installed than ignore this warning."), tr("OK")); + } + else if(Settings.cios == 254) + { + WindowPrompt(tr("Warning:"), tr("This IOS is the BootMii ios. If you are sure it is not BootMii and you have something else installed there than ignore this warning."), tr("OK")); + } } } options2.SetValue(Idx, "IOS %i", game_cfg.ios); diff --git a/source/sys.cpp b/source/sys.cpp index f4ccc5a0..287434fd 100644 --- a/source/sys.cpp +++ b/source/sys.cpp @@ -162,13 +162,6 @@ void Sys_BackToLoader(void) Sys_LoadMenu(); } -bool Sys_IsHermes() -{ - int ios = IOS_GetVersion(); - - return ios == 222 || ios == 223 || ios == 224; -} - void ScreenShot() { time_t rawtime; diff --git a/source/sys.h b/source/sys.h index 54cf531b..3c6beca1 100644 --- a/source/sys.h +++ b/source/sys.h @@ -13,7 +13,6 @@ void Sys_ShutdownToIdel(void); void Sys_ShutdownToStandby(void); void Sys_LoadMenu(void); void Sys_BackToLoader(void); -bool Sys_IsHermes(); void ScreenShot(); #endif diff --git a/source/system/IosLoader.cpp b/source/system/IosLoader.cpp index cdf4dee0..550d248c 100644 --- a/source/system/IosLoader.cpp +++ b/source/system/IosLoader.cpp @@ -17,11 +17,31 @@ #include "mload/modules/ehcmodule_5.h" #include "mload/modules/dip_plugin_249.h" #include "mload/modules/odip_frag.h" +#include "gecko.h" /****************************************************************************** * Public Methods: ******************************************************************************/ +/* + * Check if the ios passed is a Hermes ios. + */ +bool IosLoader::IsHermesIOS(s32 ios) +{ + return (ios == 222 || ios == 223 || ios == 224 || ios == 202); +} + +/* + * Check if the ios passed is a Waninkoko ios. + */ +bool IosLoader::IsWaninkokoIOS(s32 ios) +{ + if(ios < 200 || ios > 255) + return false; + + return !IsHermesIOS(ios); +} + /* * Loads CIOS (If possible the one from the settings file). * @return 0 if a cios has been successfully loaded. Else a value below 0 is returned. @@ -102,34 +122,21 @@ s32 IosLoader::LoadGameCios(s32 ios) */ s32 IosLoader::ReloadIosSafe(s32 ios) { - switch (ios) + if(IsHermesIOS(ios)) { - case 222: - { - s32 ios222rev = NandTitles.VersionOf(0x1000000deULL); - if (ios222rev == 4 || ios222rev == 5 || ios222rev == 65535) break; - return -2; - } - case 223: - { - s32 ios223rev = NandTitles.VersionOf(0x1000000dfULL); - if (ios223rev == 4 || ios223rev == 5 || ios223rev == 65535) break; - return -2; - } - case 249: - { - s32 ios249rev = NandTitles.VersionOf(0x1000000f9ULL); - if (ios249rev < 9 || ios249rev == 65280) return -2; - break; - } - case 250: - { - s32 ios250rev = NandTitles.VersionOf(0x1000000faULL); - if (ios250rev < 9 || ios250rev == 65280) return -2; - break; - } - default: - return -3; + s32 iosRev = NandTitles.VersionOf(TITLE_ID(1, ios)); + if((iosRev < 2 || iosRev > 5) && iosRev != 65535) + return -11; + } + else if(IsWaninkokoIOS(ios)) + { + s32 iosRev = NandTitles.VersionOf(TITLE_ID(1, ios)); + if(iosRev < 9 || iosRev > 30) //let's see if Waninkoko actually gets to 30 + return -22; + } + else + { + return -33; } s32 r = IOS_ReloadIOS(ios); @@ -146,7 +153,7 @@ s32 IosLoader::ReloadIosSafe(s32 ios) void IosLoader::LoadIOSModules(s32 ios, s32 ios_rev) { //! Hermes IOS - if(ios == 222 || ios == 223 || ios == 224) + if(IsHermesIOS(ios)) { const u8 * ech_module = NULL; int ehc_module_size = 0; @@ -160,18 +167,21 @@ void IosLoader::LoadIOSModules(s32 ios, s32 ios_rev) ehc_module_size = ehcmodule_2_size; dip_plugin = dip_plugin_2; dip_plugin_size = dip_plugin_2_size; + gprintf("Loading ehc and dip module v2\n"); break; case 3: ech_module = ehcmodule_3; ehc_module_size = ehcmodule_3_size; dip_plugin = dip_plugin_3; dip_plugin_size = dip_plugin_3_size; + gprintf("Loading ehc and dip module v3\n"); break; default: ech_module = ehcmodule_5; ehc_module_size = ehcmodule_5_size; dip_plugin = odip_frag; dip_plugin_size = odip_frag_size; + gprintf("Loading ehc v5 and opendip module\n"); break; } @@ -180,18 +190,20 @@ void IosLoader::LoadIOSModules(s32 ios, s32 ios_rev) { ehc_cfg += 12; ehc_cfg[0] = 0; // USB Port 0 + gprintf("Patched ehc module to use usb port 0.\n"); } load_modules(ech_module, ehc_module_size, dip_plugin, dip_plugin_size); } //! Waninkoko IOS - else if(ios == 249 || ios == 250) + else if(IsWaninkokoIOS(ios)) { if(ios_rev >= 18) { if(mload_init() < 0) return; + gprintf("Loading dip module for Waninkoko's cios\n"); mload_module((u8 *) dip_plugin_249, dip_plugin_249_size); mload_close(); } diff --git a/source/system/IosLoader.h b/source/system/IosLoader.h index 036aabfa..b00b04ef 100644 --- a/source/system/IosLoader.h +++ b/source/system/IosLoader.h @@ -1,7 +1,7 @@ #ifndef _IOSLOADER_H_ #define _IOSLOADER_H_ -#include +#include class IosLoader { @@ -9,6 +9,8 @@ class IosLoader static s32 LoadAppCios(); static s32 LoadGameCios(s32 ios); static s32 ReloadIosSafe(s32 ios); + static bool IsHermesIOS(s32 ios = IOS_GetVersion()); + static bool IsWaninkokoIOS(s32 ios = IOS_GetVersion()); private: static void LoadIOSModules(s32 ios, s32 ios_rev); }; diff --git a/source/usbloader/disc.c b/source/usbloader/disc.c index e6327486..4e930914 100644 --- a/source/usbloader/disc.c +++ b/source/usbloader/disc.c @@ -12,6 +12,7 @@ #include "disc.h" #include "video.h" #include "wdvd.h" +#include "frag.h" #include "alternatedol.h" #include "memory/memory.h" #include "wbfs.h" @@ -241,15 +242,10 @@ s32 Disc_Wait(void) s32 Disc_SetUSB(const u8 *id) { - u32 part = 0; - if (wbfs_part_fs) - { - part = wbfs_part_lba; - } - else - { - part = wbfs_part_idx ? wbfs_part_idx - 1 : 0; - } + if (wbfs_part_fs) + return set_frag_list((u8 *) id); + + u32 part = wbfs_part_idx ? wbfs_part_idx - 1 : 0; /* Set USB mode */ return WDVD_SetUSBMode((u8 *) id, part); @@ -293,11 +289,10 @@ s32 Disc_JumpToEntrypoint(u8 videoselected, bool enablecheat) gprintf("USB Loader GX is done.\n"); /* Shutdown IOS subsystems */ - // fix for PeppaPig (from WiiFlow) - u8 temp_data[4]; - memcpy(temp_data, (u8 *) 0x800000F4, 4); - SYS_ResetSystem(SYS_SHUTDOWN, 0, 0); - memcpy((u8 *) 0x800000F4, temp_data, 4); + extern void __exception_closeall(); + u32 level = IRQ_Disable(); + __IOS_ShutdownSubsystems(); + __exception_closeall(); if (enablecheat) { @@ -323,6 +318,8 @@ s32 Disc_JumpToEntrypoint(u8 videoselected, bool enablecheat) ); } + IRQ_Restore(level); + return 0; } diff --git a/source/usbloader/frag.c b/source/usbloader/frag.c index 22a5769f..6450dc08 100644 --- a/source/usbloader/frag.c +++ b/source/usbloader/frag.c @@ -1,180 +1,280 @@ -#include -#include -#include -#include -#include - -#include "fatmounter.h" -#include "libs/libntfs/ntfs.h" -#include "libs/libwbfs/libwbfs.h" -#include "wbfs.h" -#include "usbstorage2.h" -#include "frag.h" -#include "utils.h" - -FragList *frag_list = NULL; - -void frag_init(FragList *ff, int maxnum) -{ - memset(ff, 0, sizeof(Fragment) * (maxnum + 1)); - ff->maxnum = maxnum; -} - -int frag_append(FragList *ff, u32 offset, u32 sector, u32 count) -{ - int n; - if (count) - { - n = ff->num - 1; - if (ff->num > 0 && ff->frag[n].offset + ff->frag[n].count == offset && ff->frag[n].sector + ff->frag[n].count - == sector) - { - // merge - ff->frag[n].count += count; - } - else - { - // add - if (ff->num >= ff->maxnum) - { - // too many fragments - return -500; - } - n = ff->num; - ff->frag[n].offset = offset; - ff->frag[n].sector = sector; - ff->frag[n].count = count; - ff->num++; - } - } - ff->size = offset + count; - return 0; -} - -int _frag_append(void *ff, u32 offset, u32 sector, u32 count) -{ - return frag_append(ff, offset, sector, count); -} - -int frag_concat(FragList *ff, FragList *src) -{ - int i, ret; - u32 size = ff->size; - //printf("concat: %d %d <- %d %d\n", ff->num, ff->size, src->num, src->size); - for (i = 0; i < src->num; i++) - { - ret = frag_append(ff, size + src->frag[i].offset, src->frag[i].sector, src->frag[i].count); - if (ret) return ret; - } - ff->size = size + src->size; - //printf("concat: -> %d %d\n", ff->num, ff->size); - return 0; -} - -// in case a sparse block is requested, -// the returned poffset might not be equal to requested offset -// the difference should be filled with 0 -int frag_get(FragList *ff, u32 offset, u32 count, u32 *poffset, u32 *psector, u32 *pcount) -{ - int i; - u32 delta; - //printf("frag_get(%u %u)\n", offset, count); - for (i = 0; i < ff->num; i++) - { - if (ff->frag[i].offset <= offset && ff->frag[i].offset + ff->frag[i].count > offset) - { - delta = offset - ff->frag[i].offset; - *poffset = offset; - *psector = ff->frag[i].sector + delta; - *pcount = ff->frag[i].count - delta; - if (*pcount > count) *pcount = count; - goto out; - } - if (ff->frag[i].offset > offset && ff->frag[i].offset < offset + count) - { - delta = ff->frag[i].offset - offset; - *poffset = ff->frag[i].offset; - *psector = ff->frag[i].sector; - *pcount = ff->frag[i].count; - count -= delta; - if (*pcount > count) *pcount = count; - goto out; - } - } - // not found - if (offset + count > ff->size) - { - // error: out of range! - return -1; - } - // if inside range, then it must be just sparse, zero filled - // return empty block at the end of requested - *poffset = offset + count; - *psector = 0; - *pcount = 0; - out: - //printf("=>(%u %u %u)\n", *poffset, *psector, *pcount); - return 0; -} - -int frag_remap(FragList *ff, FragList *log, FragList *phy) -{ - int i; - int ret; - u32 offset; - u32 sector; - u32 count; - u32 delta; - for (i = 0; i < log->num; i++) - { - delta = 0; - count = 0; - do - { - ret = frag_get(phy, log->frag[i].sector + delta + count, log->frag[i].count - delta - count, &offset, - §or, &count); - if (ret) return ret; // error - delta = offset - log->frag[i].sector; - ret = frag_append(ff, log->frag[i].offset + delta, sector, count); - if (ret) return ret; // error - } while (count + delta < log->frag[i].count); - } - return 0; -} - -int get_frag_list(u8 *id) -{ - return WBFS_GetFragList(id); -} - -int set_frag_list(u8 *id) -{ - if (wbfs_part_fs == PART_FS_WBFS) return 0; - if (frag_list == NULL) - { - if (wbfs_part_fs == PART_FS_FAT) - { - // fall back to old fat method - // printf("FAT: fallback to old method\n"); - return 0; - } - // ntfs has no fallback, return error - return -1; - } - - // (+1 for header which is same size as fragment) - int size = sizeof(Fragment) * (frag_list->num + 1); - int ret = USBStorage_WBFS_SetFragList(frag_list, size); - if (ret) - { - // printf("set_frag: %d\n", ret); - return ret; - } - - // verify id matches - char discid[8]; - memset(discid, 0, sizeof(discid)); - ret = USBStorage_WBFS_Read(0, 6, discid); - return 0; -} - +#include +#include +#include +#include +#include + +#include "libs/libntfs/ntfs.h" +#include "libs/libwbfs/libwbfs.h" + +#include "usbloader/wbfs.h" +#include "usbloader/wdvd.h" +#include "usbloader/usbstorage2.h" +#include "frag.h" +#include "sys.h" +#include "gecko.h" + +#define SAFE_FREE(x) if(x) { free(x); x = NULL; } + +extern sec_t fs_ntfs_sec; + +int _FAT_get_fragments (const char *path, _frag_append_t append_fragment, void *callback_data); + +static FragList *frag_list = NULL; + +void frag_init(FragList *ff, int maxnum) +{ + memset(ff, 0, sizeof(Fragment) * (maxnum+1)); + ff->maxnum = maxnum; +} + +void frag_dump(FragList *ff) +{ + int i; + gprintf("frag list: %d %d 0x%x\n", ff->num, ff->size, ff->size); + for (i=0; inum; i++) { + if (i>10) { + gprintf("...\n"); + break; + } + gprintf(" %d : %8x %8x %8x\n", i, + ff->frag[i].offset, + ff->frag[i].count, + ff->frag[i].sector); + } +} + +int frag_append(FragList *ff, u32 offset, u32 sector, u32 count) +{ + int n; + if (count) { + n = ff->num - 1; + if (ff->num > 0 + && ff->frag[n].offset + ff->frag[n].count == offset + && ff->frag[n].sector + ff->frag[n].count == sector) + { + // merge + ff->frag[n].count += count; + } + else + { + // add + if (ff->num >= ff->maxnum) { + // too many fragments + return -500; + } + n = ff->num; + ff->frag[n].offset = offset; + ff->frag[n].sector = sector; + ff->frag[n].count = count; + ff->num++; + } + } + ff->size = offset + count; + return 0; +} + +int _frag_append(void *ff, u32 offset, u32 sector, u32 count) +{ + return frag_append(ff, offset, sector, count); +} + +int frag_concat(FragList *ff, FragList *src) +{ + int i, ret; + u32 size = ff->size; + //printf("concat: %d %d <- %d %d\n", ff->num, ff->size, src->num, src->size); + for (i=0; inum; i++) { + ret = frag_append(ff, size + src->frag[i].offset, + src->frag[i].sector, src->frag[i].count); + if (ret) return ret; + } + ff->size = size + src->size; + //printf("concat: -> %d %d\n", ff->num, ff->size); + return 0; +} + +// in case a sparse block is requested, +// the returned poffset might not be equal to requested offset +// the difference should be filled with 0 +int frag_get(FragList *ff, u32 offset, u32 count, + u32 *poffset, u32 *psector, u32 *pcount) +{ + int i; + u32 delta; + //printf("frag_get(%u %u)\n", offset, count); + for (i=0; inum; i++) { + if (ff->frag[i].offset <= offset + && ff->frag[i].offset + ff->frag[i].count > offset) + { + delta = offset - ff->frag[i].offset; + *poffset = offset; + *psector = ff->frag[i].sector + delta; + *pcount = ff->frag[i].count - delta; + if (*pcount > count) *pcount = count; + goto out; + } + if (ff->frag[i].offset > offset + && ff->frag[i].offset < offset + count) + { + delta = ff->frag[i].offset - offset; + *poffset = ff->frag[i].offset; + *psector = ff->frag[i].sector; + *pcount = ff->frag[i].count; + count -= delta; + if (*pcount > count) *pcount = count; + goto out; + } + } + // not found + if (offset + count > ff->size) { + // error: out of range! + return -1; + } + // if inside range, then it must be just sparse, zero filled + // return empty block at the end of requested + *poffset = offset + count; + *psector = 0; + *pcount = 0; + out: + //printf("=>(%u %u %u)\n", *poffset, *psector, *pcount); + return 0; +} + +int frag_remap(FragList *ff, FragList *log, FragList *phy) +{ + int i; + int ret; + u32 offset; + u32 sector; + u32 count; + u32 delta; + for (i=0; inum; i++) { + delta = 0; + count = 0; + do { + ret = frag_get(phy, + log->frag[i].sector + delta + count, + log->frag[i].count - delta - count, + &offset, §or, &count); + if (ret) return ret; // error + delta = offset - log->frag[i].sector; + ret = frag_append(ff, log->frag[i].offset + delta, sector, count); + if (ret) return ret; // error + } while (count + delta < log->frag[i].count); + } + return 0; +} + +int get_frag_list_for_file(char *fname, u8 *id) +{ + char fname1[1024]; + struct stat st; + FragList *fs = NULL; + FragList *fa = NULL; + FragList *fw = NULL; + int ret; + int i, j; + int is_wbfs = 0; + int ret_val = -1; + + if (strcasecmp(strrchr(fname,'.'), ".wbfs") == 0) { + is_wbfs = 1; + } + + fs = malloc(sizeof(FragList)); + fa = malloc(sizeof(FragList)); + fw = malloc(sizeof(FragList)); + + frag_init(fa, MAX_FRAG); + + for (i=0; i<10; i++) { + frag_init(fs, MAX_FRAG); + if (i > 0) { + fname[strlen(fname)-1] = '0' + i; + if (stat(fname, &st) == -1) break; + } + strcpy(fname1, fname); + if (wbfs_part_fs == PART_FS_FAT) { + ret = _FAT_get_fragments(fname, &_frag_append, fs); + if (ret) { + // don't return failure, let it fallback to old method + //ret_val = ret; + ret_val = 0; + goto out; + } + } else if (wbfs_part_fs == PART_FS_NTFS) { + ret = _NTFS_get_fragments(fname, &_frag_append, fs); + if (ret) { + ret_val = ret; + goto out; + } + // offset to start of partition + for (j=0; jnum; j++) { + fs->frag[j].sector += fs_ntfs_sec; + } + } + frag_concat(fa, fs); + } + + frag_list = malloc(sizeof(FragList)); + frag_init(frag_list, MAX_FRAG); + if (is_wbfs) { + // if wbfs file format, remap. + wbfs_disc_t *d = WBFS_OpenDisc(id); + if (!d) { ret_val = -4; goto out; } + frag_init(fw, MAX_FRAG); + ret = wbfs_get_fragments(d, &_frag_append, fw); + if (ret) { ret_val = -5; goto out; } + WBFS_CloseDisc(d); + // DEBUG: frag_list->num = MAX_FRAG-10; // stress test + ret = frag_remap(frag_list, fw, fa); + if (ret) { ret_val = -6; goto out; } + } else { + // .iso does not need remap just copy + memcpy(frag_list, fa, sizeof(FragList)); + } + + ret_val = 0; + +out: + if (ret_val) { + // error + SAFE_FREE(frag_list); + } + SAFE_FREE(fs); + SAFE_FREE(fa); + SAFE_FREE(fw); + return ret_val; +} + +int get_frag_list(u8 *id) +{ + return WBFS_GetFragList(id); +} + +int set_frag_list(u8 *id) +{ + if (wbfs_part_fs == PART_FS_WBFS) return 1; + if (frag_list == NULL) { + return -2; + } + + // (+1 for header which is same size as fragment) + int size = sizeof(Fragment) * (frag_list->num + 1); + int ret; + DCFlushRange(frag_list, size); + + gprintf("Calling WDVD_SetFragList, frag list size %d\n", size); + ret = WDVD_SetFragList(wbfsDev, frag_list, size); + if (ret) { + return ret; + } + + // verify id matches + char discid[8]; + memset(discid, 0, sizeof(discid)); + ret = WDVD_UnencryptedRead(discid, 8, 0); + gprintf("Reading ID after setting fraglist: %s (expected: %s)\n", discid, id); + return (strncasecmp((char *) id, discid, 6) != 0) ? -3 : 0; +} diff --git a/source/usbloader/frag.h b/source/usbloader/frag.h index 2286ed93..b28daea1 100644 --- a/source/usbloader/frag.h +++ b/source/usbloader/frag.h @@ -1,50 +1,53 @@ -// worst case wbfs fragmentation scenario: -// 9GB (dual layer) / 2mb (wbfs sector size) = 4608 -#define MAX_FRAG 20000 -// max that ehcmodule_frag will allow at the moment is about: -// 40000/4/3-1 = 21844 - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "libs/libwbfs/libwbfs.h" - - typedef struct - { - u32 offset; // file offset, in sectors unit - u32 sector; - u32 count; - } Fragment; - - typedef struct - { - u32 size; // num sectors - u32 num; // num fragments - u32 maxnum; - Fragment frag[MAX_FRAG]; - } FragList; - - typedef int (*frag_append_t)(void *ff, u32 offset, u32 sector, u32 count); - - int _FAT_get_fragments(const char *path, _frag_append_t append_fragment, void *callback_data); - - void frag_init(FragList *ff, int maxnum); - int frag_append(FragList *ff, u32 offset, u32 sector, u32 count); - int _frag_append(void *ff, u32 offset, u32 sector, u32 count); - int frag_concat(FragList *ff, FragList *src); - - // in case a sparse block is requested, - // the returned poffset might not be equal to requested offset - // the difference should be filled with 0 - int frag_get(FragList *ff, u32 offset, u32 count, u32 *poffset, u32 *psector, u32 *pcount); - - int frag_remap(FragList *ff, FragList *log, FragList *phy); - - int get_frag_list(u8 *id); - int set_frag_list(u8 *id); - -#ifdef __cplusplus -} -#endif + +// worst case wbfs fragmentation scenario: +// 9GB (dual layer) / 2mb (wbfs sector size) = 4608 +#define MAX_FRAG 20000 +// max that ehcmodule_frag will allow at the moment is about: +// 40000/4/3-1 = 21844 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libs/libwbfs/libwbfs.h" + +typedef struct +{ + u32 offset; // file offset, in sectors unit + u32 sector; + u32 count; +} Fragment; + +typedef struct +{ + u32 size; // num sectors + u32 num; // num fragments + u32 maxnum; + Fragment frag[MAX_FRAG]; +} FragList; + +typedef int (*frag_append_t)(void *ff, u32 offset, u32 sector, u32 count); + +int _FAT_get_fragments (const char *path, _frag_append_t append_fragment, void *callback_data); + +void frag_init(FragList *ff, int maxnum); +void frag_dump(FragList *ff); +int frag_append(FragList *ff, u32 offset, u32 sector, u32 count); +int _frag_append(void *ff, u32 offset, u32 sector, u32 count); +int frag_concat(FragList *ff, FragList *src); + +// in case a sparse block is requested, +// the returned poffset might not be equal to requested offset +// the difference should be filled with 0 +int frag_get(FragList *ff, u32 offset, u32 count, + u32 *poffset, u32 *psector, u32 *pcount); + +int frag_remap(FragList *ff, FragList *log, FragList *phy); + +int get_frag_list_for_file(char *fname, u8 *id); +int get_frag_list(u8 *id); +int set_frag_list(u8 *id); + +#ifdef __cplusplus +} +#endif diff --git a/source/usbloader/wbfs/wbfs_base.cpp b/source/usbloader/wbfs/wbfs_base.cpp index ed510726..1cfdc582 100644 --- a/source/usbloader/wbfs/wbfs_base.cpp +++ b/source/usbloader/wbfs/wbfs_base.cpp @@ -137,15 +137,6 @@ bool Wbfs::Mounted() return hdd == NULL; } -int Wbfs::GetFragList(u8 *id) -{ - return 0; -} - -int Wbfs::GetFragList(char *filename, _frag_append_t append_fragment, FragList *) -{ - return 0; -} bool Wbfs::ShowFreeSpace(void) { diff --git a/source/usbloader/wbfs/wbfs_base.h b/source/usbloader/wbfs/wbfs_base.h index 83e481e7..670bfd46 100644 --- a/source/usbloader/wbfs/wbfs_base.h +++ b/source/usbloader/wbfs/wbfs_base.h @@ -1,54 +1,53 @@ -#ifndef _H -#define _H - -#include "libs/libwbfs/libwbfs.h" -#include "usbloader/utils.h" -#include "usbloader/frag.h" - -class Wbfs -{ - public: - Wbfs(u32, u32, u32); - - void GetProgressValue(s32 * d, s32 * m); - static s32 Init(u32); - void Close(); - s32 CheckGame(u8 *); - s32 GameSize(u8 *, f32 *); - wbfs_t *GetHddInfo(void); - bool Mounted(); - virtual int GetFragList(u8 *id); - virtual int GetFragList(char *filename, _frag_append_t append_fragment, FragList *); - virtual bool ShowFreeSpace(void); - - virtual s32 Open() = 0; - virtual wbfs_disc_t* OpenDisc(u8 *discid) = 0; - virtual void CloseDisc(wbfs_disc_t *disc) = 0; - virtual s32 Format(); - virtual s32 GetCount(u32 *) = 0; - virtual s32 GetHeaders(struct discHdr *, u32, u32) = 0; - virtual s32 AddGame(void) = 0; - virtual s32 RemoveGame(u8 *) = 0; - virtual s32 DiskSpace(f32 *, f32 *) = 0; - virtual s32 RenameGame(u8 *, const void *) = 0; - virtual s32 ReIDGame(u8 *discid, const void *newID) = 0; - virtual f32 EstimateGameSize(void) = 0; - - /* - static s32 OpenPart(u32 part_fat, u32 part_idx, u32 part_lba, u32 part_size, char *partition); - static s32 OpenNamed(char *partition); - static s32 OpenLBA(u32 lba, u32 size); - */ - protected: - static u32 nb_sectors; - - /* WBFS HDD */ - wbfs_t *hdd; - - u32 device, lba, size; - private: - - static s32 total, done; -}; - -#endif //_H +#ifndef _H +#define _H + +#include "libs/libwbfs/libwbfs.h" +#include "usbloader/utils.h" +#include "usbloader/frag.h" + +class Wbfs +{ + public: + Wbfs(u32, u32, u32); + + void GetProgressValue(s32 * d, s32 * m); + static s32 Init(u32); + void Close(); + s32 CheckGame(u8 *); + s32 GameSize(u8 *, f32 *); + wbfs_t *GetHddInfo(void); + bool Mounted(); + virtual int GetFragList(u8 *id) { return 0; }; + virtual bool ShowFreeSpace(void); + + virtual s32 Open() = 0; + virtual wbfs_disc_t* OpenDisc(u8 *discid) = 0; + virtual void CloseDisc(wbfs_disc_t *disc) = 0; + virtual s32 Format(); + virtual s32 GetCount(u32 *) = 0; + virtual s32 GetHeaders(struct discHdr *, u32, u32) = 0; + virtual s32 AddGame(void) = 0; + virtual s32 RemoveGame(u8 *) = 0; + virtual s32 DiskSpace(f32 *, f32 *) = 0; + virtual s32 RenameGame(u8 *, const void *) = 0; + virtual s32 ReIDGame(u8 *discid, const void *newID) = 0; + virtual f32 EstimateGameSize(void) = 0; + + /* + static s32 OpenPart(u32 part_fat, u32 part_idx, u32 part_lba, u32 part_size, char *partition); + static s32 OpenNamed(char *partition); + static s32 OpenLBA(u32 lba, u32 size); + */ + protected: + static u32 nb_sectors; + + /* WBFS HDD */ + wbfs_t *hdd; + + u32 device, lba, size; + private: + + static s32 total, done; +}; + +#endif //_H diff --git a/source/usbloader/wbfs/wbfs_fat.cpp b/source/usbloader/wbfs/wbfs_fat.cpp index 4f33d16e..5cd9b391 100644 --- a/source/usbloader/wbfs/wbfs_fat.cpp +++ b/source/usbloader/wbfs/wbfs_fat.cpp @@ -817,86 +817,11 @@ bool Wbfs_Fat::is_gameid(char *id) int Wbfs_Fat::GetFragList(u8 *id) { char fname[1024]; - char fname1[1024]; - struct stat st; - FragList *fs = NULL; - FragList *fa = NULL; - FragList *fw = NULL; - int ret; - int i; - int is_wbfs = 0; - int ret_val = -1; - ret = FindFilename(id, fname, sizeof(fname)); + int ret = FindFilename(id, fname, sizeof(fname)); if (!ret) return -1; - if (strcasecmp(strrchr(fname, '.'), ".wbfs") == 0) - { - is_wbfs = 1; - } - - fs = (FragList *) malloc(sizeof(FragList)); - fa = (FragList *) malloc(sizeof(FragList)); - fw = (FragList *) malloc(sizeof(FragList)); - - frag_init(fa, MAX_FRAG); - - for (i = 0; i < 10; i++) - { - frag_init(fs, MAX_FRAG); - if (i > 0) - { - fname[strlen(fname) - 1] = '0' + i; - if (stat(fname, &st) == -1) break; - } - strcpy(fname1, fname); - if ((ret = GetFragList((char *) &fname, &_frag_append, fs))) - { - ret_val = ret; - goto out; - } - frag_concat(fa, fs); - } - frag_list = (FragList *) malloc(sizeof(FragList)); - frag_init(frag_list, MAX_FRAG); - if (is_wbfs) - { - // if wbfs file format, remap. - //printf("=====\n"); - wbfs_disc_t *d = OpenDisc(id); - if (!d) goto out; - frag_init(fw, MAX_FRAG); - ret = wbfs_get_fragments(d, &_frag_append, fw); - if (ret) goto out; - CloseDisc(d); - // DEBUG: - //frag_list->num = MAX_FRAG-10; // stress test - ret = frag_remap(frag_list, fw, fa); - if (ret) goto out; - } - else - { - // .iso does not need remap just copy - //printf("fa:\n"); - memcpy(frag_list, fa, sizeof(FragList)); - } - - ret_val = 0; - - out: if (ret_val) - { - // error - SAFE_FREE( frag_list ); - } - SAFE_FREE( fs ); - SAFE_FREE( fa ); - SAFE_FREE( fw ); - return ret_val; -} - -int Wbfs_Fat::GetFragList(char *filename, _frag_append_t append_fragment, FragList *fs) -{ - return _FAT_get_fragments(filename, append_fragment, fs); + return get_frag_list_for_file(fname, id); } bool Wbfs_Fat::ShowFreeSpace(void) diff --git a/source/usbloader/wbfs/wbfs_fat.h b/source/usbloader/wbfs/wbfs_fat.h index ebdfcb40..6e2783be 100644 --- a/source/usbloader/wbfs/wbfs_fat.h +++ b/source/usbloader/wbfs/wbfs_fat.h @@ -1,67 +1,66 @@ -#ifndef _WBFS_FAT_H -#define _WBFS_FAT_H - -#include - -#include "usbloader/splits.h" -#include "wbfs_base.h" - -class Wbfs_Fat: public Wbfs -{ - public: - Wbfs_Fat(u32 device, u32 lba, u32 size); - ~Wbfs_Fat(); - - virtual s32 Open(); - wbfs_disc_t* OpenDisc(u8 *); - void CloseDisc(wbfs_disc_t *); - - s32 GetCount(u32 *); - s32 GetHeaders(struct discHdr *, u32, u32); - - s32 AddGame(); - s32 RemoveGame(u8 *); - - s32 DiskSpace(f32 *, f32 *); - - s32 RenameGame(u8 *, const void *); - s32 ReIDGame(u8 *, const void *); - - f32 EstimateGameSize(); - - int GetFragList(u8 *); - virtual int GetFragList(char *, _frag_append_t, FragList *); - virtual bool ShowFreeSpace(void); - - protected: - static char wbfs_fs_drive[16]; - private: - split_info_t split; - - static u32 fat_sector_size; - static char wbfs_fat_dir[16]; - static char invalid_path[]; - static struct discHdr *fat_hdr_list; - static u32 fat_hdr_count; - - wbfs_t* OpenPart(char *fname); - void ClosePart(wbfs_t* part); - wbfs_t* CreatePart(u8 *id, char *path); - int FindFilename(u8 *id, char *fname, int len); - void Filename(u8 *id, char *fname, int len, char *path); - bool CheckLayoutB(char *fname, int len, u8* id, char *fname_title); - s32 GetHeadersCount(); - void GetDir(struct discHdr *header, char *path); - - void mk_title_txt(struct discHdr *header, char *path); - void mk_gameid_title(struct discHdr *header, char *name, int re_space, int layout); - void title_filename(char *title); - bool is_gameid(char *id); - - static int nop_rw_sector(void *_fp, u32 lba, u32 count, void* buf) - { - return 0; - } -}; - -#endif //_WBFS_FAT_H +#ifndef _WBFS_FAT_H +#define _WBFS_FAT_H + +#include + +#include "usbloader/splits.h" +#include "wbfs_base.h" + +class Wbfs_Fat: public Wbfs +{ + public: + Wbfs_Fat(u32 device, u32 lba, u32 size); + ~Wbfs_Fat(); + + virtual s32 Open(); + wbfs_disc_t* OpenDisc(u8 *); + void CloseDisc(wbfs_disc_t *); + + s32 GetCount(u32 *); + s32 GetHeaders(struct discHdr *, u32, u32); + + s32 AddGame(); + s32 RemoveGame(u8 *); + + s32 DiskSpace(f32 *, f32 *); + + s32 RenameGame(u8 *, const void *); + s32 ReIDGame(u8 *, const void *); + + f32 EstimateGameSize(); + + int GetFragList(u8 *); + virtual bool ShowFreeSpace(void); + + protected: + static char wbfs_fs_drive[16]; + private: + split_info_t split; + + static u32 fat_sector_size; + static char wbfs_fat_dir[16]; + static char invalid_path[]; + static struct discHdr *fat_hdr_list; + static u32 fat_hdr_count; + + wbfs_t* OpenPart(char *fname); + void ClosePart(wbfs_t* part); + wbfs_t* CreatePart(u8 *id, char *path); + int FindFilename(u8 *id, char *fname, int len); + void Filename(u8 *id, char *fname, int len, char *path); + bool CheckLayoutB(char *fname, int len, u8* id, char *fname_title); + s32 GetHeadersCount(); + void GetDir(struct discHdr *header, char *path); + + void mk_title_txt(struct discHdr *header, char *path); + void mk_gameid_title(struct discHdr *header, char *name, int re_space, int layout); + void title_filename(char *title); + bool is_gameid(char *id); + + static int nop_rw_sector(void *_fp, u32 lba, u32 count, void* buf) + { + return 0; + } +}; + +#endif //_WBFS_FAT_H diff --git a/source/usbloader/wbfs/wbfs_ntfs.cpp b/source/usbloader/wbfs/wbfs_ntfs.cpp index 49a0b8b1..7ba0beef 100644 --- a/source/usbloader/wbfs/wbfs_ntfs.cpp +++ b/source/usbloader/wbfs/wbfs_ntfs.cpp @@ -1,30 +1,14 @@ -#include "wbfs_ntfs.h" -#include "fatmounter.h" -#include "libs/libntfs/ntfs.h" - -s32 Wbfs_Ntfs::Open() -{ - strcpy(wbfs_fs_drive, "NTFS:"); - return MountNTFS(lba); -} - -int Wbfs_Ntfs::GetFragList(char *filename, _frag_append_t append_fragment, FragList *fs) -{ - int ret = _NTFS_get_fragments(filename, append_fragment, fs); - if (ret) - { - return ret; - } - - // offset to start of partition - for (unsigned int j = 0; j < fs->num; j++) - { - fs->frag[j].sector += fs_ntfs_sec; - } - return ret; -} - -bool Wbfs_Ntfs::ShowFreeSpace(void) -{ - return true; -} +#include "wbfs_ntfs.h" +#include "fatmounter.h" +#include "libs/libntfs/ntfs.h" + +s32 Wbfs_Ntfs::Open() +{ + strcpy(wbfs_fs_drive, "NTFS:"); + return MountNTFS(lba); +} + +bool Wbfs_Ntfs::ShowFreeSpace(void) +{ + return true; +} diff --git a/source/usbloader/wbfs/wbfs_ntfs.h b/source/usbloader/wbfs/wbfs_ntfs.h index fda5f607..2551c7a9 100644 --- a/source/usbloader/wbfs/wbfs_ntfs.h +++ b/source/usbloader/wbfs/wbfs_ntfs.h @@ -1,20 +1,19 @@ -#ifndef _WBFS_NTFS_H -#define _WBFS_NTFS_H - -#include "wbfs_fat.h" - -class Wbfs_Ntfs: public Wbfs_Fat -{ - public: - Wbfs_Ntfs(u32 device, u32 lba, u32 size) : - Wbfs_Fat(device, lba, size) - { - } - - virtual s32 Open(); - - int GetFragList(char *filename, _frag_append_t append_fragment, FragList *fs); - bool ShowFreeSpace(void); -}; - -#endif //_WBFS_NTFS_H +#ifndef _WBFS_NTFS_H +#define _WBFS_NTFS_H + +#include "wbfs_fat.h" + +class Wbfs_Ntfs: public Wbfs_Fat +{ + public: + Wbfs_Ntfs(u32 device, u32 lba, u32 size) : + Wbfs_Fat(device, lba, size) + { + } + + virtual s32 Open(); + + bool ShowFreeSpace(void); +}; + +#endif //_WBFS_NTFS_H diff --git a/source/usbloader/wdvd.c b/source/usbloader/wdvd.c index d4bdec69..32938d7c 100644 --- a/source/usbloader/wdvd.c +++ b/source/usbloader/wdvd.c @@ -79,6 +79,7 @@ s32 WDVD_Reset(void) inbuf[0] = IOCTL_DI_RESET << 24; inbuf[1] = 1; + ret = IOS_Ioctl(di_fd, IOCTL_DI_RESET, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf)); if (ret < 0) return ret;