mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-25 20:56:53 +01:00
Lots of changes in this revision:
* Added MEM2 support by Hibern * Better partition support (by oggzee) * Support for subdirectories in FAT32 (by oggzee) * Added support for cios 223 and 250 * Added BCA support (go to Settings->Custom Paths) to change the path of the BCA files (by Hermes) * Fixed issue with hairless mode * Fixed issue with IOS_ReloadIOSsafe (by giantpune) * Added setting to save games in a subdirectory * Fixed slow startup when loading from FAT (WiiTDB required!) * Changed handling of new titles a bit (speed improvement) Known issue: * FAT rename and re-id broken again due to subdirectory support (yes, I'm lazy)
This commit is contained in:
parent
d14bebd159
commit
2543c555a4
@ -2,8 +2,8 @@
|
||||
<app version="1">
|
||||
<name> USB Loader GX</name>
|
||||
<coder>USB Loader GX Team</coder>
|
||||
<version>1.0 r846</version>
|
||||
<release_date>200912030606</release_date>
|
||||
<version>1.0 r847</version>
|
||||
<release_date>200912031841</release_date>
|
||||
<short_description>Loads games from USB-devices</short_description>
|
||||
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
|
||||
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
|
||||
|
5
Makefile
5
Makefile
@ -20,7 +20,7 @@ SOURCES := source source/libwiigui source/images source/fonts source/sounds \
|
||||
source/libwbfs source/unzip source/language source/mload source/patches \
|
||||
source/usbloader source/xml source/network source/settings source/prompts \
|
||||
source/ramdisk source/wad source/banner source/cheats source/homebrewboot \
|
||||
source/themes source/menu source/libfat
|
||||
source/themes source/menu source/libfat source/memory
|
||||
DATA := data
|
||||
INCLUDES := source
|
||||
|
||||
@ -30,8 +30,9 @@ INCLUDES := source
|
||||
|
||||
CFLAGS = -g -O2 -save-temps -Wall $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = -Xassembler -aln=$@.lst $(CFLAGS)
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size
|
||||
-include $(PROJECTDIR)/Make.config
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
|
Binary file not shown.
2
gui.pnps
2
gui.pnps
@ -1 +1 @@
|
||||
<pd><ViewState><e p="gui\source\mload" x="false"></e><e p="gui\source\settings" x="true"></e><e p="gui\source\images" x="false"></e><e p="gui\source\libfat" x="false"></e><e p="gui\source\prompts" x="false"></e><e p="gui\source\banner" x="false"></e><e p="gui\source\cheats" x="false"></e><e p="gui\source\network" x="false"></e><e p="gui\source\unzip" x="false"></e><e p="gui\source\usbloader" x="true"></e><e p="gui\source\xml" x="false"></e><e p="gui\source\fonts" x="false"></e><e p="gui\source\menu" x="false"></e><e p="gui\source\ramdisk" x="false"></e><e p="gui\source\sounds" x="false"></e><e p="gui\source\wad" x="false"></e><e p="gui" x="true"></e><e p="gui\source\homebrewboot" x="false"></e><e p="gui\source\language" x="false"></e><e p="gui\source" x="true"></e><e p="gui\source\libwbfs" x="false"></e><e p="gui\source\libwiigui" x="false"></e><e p="gui\source\patches" x="false"></e><e p="gui\source\themes" x="false"></e></ViewState></pd>
|
||||
<pd><ViewState><e p="gui\source\mload" x="false"></e><e p="gui\source\settings" x="false"></e><e p="gui\source\images" x="false"></e><e p="gui\source\libfat" x="false"></e><e p="gui\source\prompts" x="true"></e><e p="gui\source\banner" x="false"></e><e p="gui\source\cheats" x="false"></e><e p="gui\source\network" x="false"></e><e p="gui\source\fonts" x="false"></e><e p="gui\source\menu" x="false"></e><e p="gui\source\ramdisk" x="false"></e><e p="gui\source\sounds" x="false"></e><e p="gui\source\wad" x="false"></e><e p="gui" x="true"></e><e p="gui\source\homebrewboot" x="false"></e><e p="gui\source\language" x="false"></e><e p="gui\source" x="true"></e><e p="gui\source\libwbfs" x="false"></e><e p="gui\source\libwiigui" x="false"></e><e p="gui\source\patches" x="false"></e><e p="gui\source\themes" x="false"></e><e p="gui\source\memory" x="false"></e><e p="gui\source\unzip" x="false"></e><e p="gui\source\usbloader" x="false"></e><e p="gui\source\xml" x="false"></e></ViewState></pd>
|
@ -13,6 +13,7 @@
|
||||
#include "gui_gamebrowser.h"
|
||||
#include "../settings/cfg.h"
|
||||
#include "../main.h"
|
||||
#include "settings/newtitles.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
@ -341,14 +342,15 @@ void GuiGameBrowser::UpdateListEntries()
|
||||
gameTxtOver[i]->SetPosition(24, 0);
|
||||
|
||||
if (Settings.marknewtitles) {
|
||||
if (gameList[next].isNew) {
|
||||
bool isNew = NewTitles::Instance()->IsNew(gameList[next].id);
|
||||
if (isNew) {
|
||||
gameTxt[i]->SetMaxWidth(maxTextWidth - (newGames->GetWidth() + 1), GuiText::DOTTED);
|
||||
gameTxtOver[i]->SetMaxWidth(maxTextWidth - (newGames->GetWidth() + 1), GuiText::SCROLL);
|
||||
} else {
|
||||
gameTxt[i]->SetMaxWidth(maxTextWidth, GuiText::DOTTED);
|
||||
gameTxtOver[i]->SetMaxWidth(maxTextWidth, GuiText::SCROLL);
|
||||
}
|
||||
newImg[i]->SetVisible(gameList[next].isNew != 0);
|
||||
newImg[i]->SetVisible(isNew);
|
||||
}
|
||||
|
||||
gameIndex[i] = next;
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "wad/title.h"
|
||||
#include "usbloader/partition_usbloader.h"
|
||||
#include "usbloader/usbstorage.h"
|
||||
#include "memory/mem2.h"
|
||||
|
||||
extern bool geckoinit;
|
||||
extern bool textVideoInit;
|
||||
@ -177,7 +178,7 @@ void InitTextVideo () {
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
// InitTextVideo();
|
||||
InitTextVideo();
|
||||
|
||||
//DEBUG_Init(GDBSTUB_DEVICE_USB, 1);
|
||||
//_break();
|
||||
@ -195,8 +196,17 @@ main(int argc, char *argv[]) {
|
||||
gprintf(", %s",argv[i]?argv[i]:"<NULL>");
|
||||
gprintf(")");
|
||||
|
||||
// This part is added, because we need a identify patched ios
|
||||
printf("\n\tReloading into ios 236");
|
||||
if (IOS_ReloadIOSsafe(236) < 0) {
|
||||
printf("\n\tIOS 236 not found, reloading into 36");
|
||||
IOS_ReloadIOSsafe(36);
|
||||
}
|
||||
|
||||
printf("\n\tStarting up");
|
||||
|
||||
MEM2_init(36); // Initialize 36 MB
|
||||
MEM2_takeBigOnes(true);
|
||||
|
||||
s32 ret;
|
||||
bool startupproblem = false;
|
||||
@ -228,15 +238,25 @@ main(int argc, char *argv[]) {
|
||||
{
|
||||
InitTextVideo();
|
||||
printf("\x1b[2J");
|
||||
printf("\n\n\n\tERROR!");
|
||||
printf("\n\tUSB Loader GX needs unstubbed cIOS 222 v4 or 249 v9+");
|
||||
printf("\n\n\tI found \n\t\t222 = %d%s",ios222rev,ios222rev==65535?" (Stubbed by 4.2 update)":"");
|
||||
printf("\n\t\t249 = %d%s",ios249rev,ios249rev==65535?" (Stubbed by 4.2 update)":"");
|
||||
printf("\n\n\tGo figure out how to get some cIOS action going on\n\tin your Wii and come back and see me.");
|
||||
|
||||
sleep(15);
|
||||
printf("\n\n\tBye");
|
||||
exit(0);
|
||||
if ((ios222rev < 0 && ios222rev != WII_EINSTALL) || (ios249rev < 0 && ios249rev != WII_EINSTALL)) {
|
||||
printf("\n\n\n\tWARNING!");
|
||||
printf("\n\tUSB Loader GX needs unstubbed cIOS 222 v4 or 249 v9+");
|
||||
printf("\n\n\tWe cannot determine the versions on your system,\n\tsince you have no patched ios 36 or 236 installed.");
|
||||
printf("\n\tTherefor, if loading of USB Loader GX fails, you\n\tprobably have installed the 4.2 update,");
|
||||
printf("\n\tand you should go figure out how to get some cios action going on\n\tin your Wii.");
|
||||
printf("\n\n\tThis message will show every time.");
|
||||
sleep(5);
|
||||
} else {
|
||||
printf("\n\n\n\tERROR!");
|
||||
printf("\n\tUSB Loader GX needs unstubbed cIOS 222 v4 or 249 v9+");
|
||||
printf("\n\n\tI found \n\t\t222 = %d%s",ios222rev,ios222rev==65535?" (Stubbed by 4.2 update)":"");
|
||||
printf("\n\t\t249 = %d%s",ios249rev,ios249rev==65535?" (Stubbed by 4.2 update)":"");
|
||||
printf("\n\n\tGo figure out how to get some cIOS action going on\n\tin your Wii and come back and see me.");
|
||||
|
||||
sleep(15);
|
||||
printf("\n\n\tBye");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\tReloading ios 249...");
|
||||
@ -248,11 +268,24 @@ main(int argc, char *argv[]) {
|
||||
printf("\n\tIOS 249 failed, reloading ios 222...");
|
||||
ret = IOS_ReloadIOSsafe(222);
|
||||
printf("%d", ret);
|
||||
if(ret < 0) {
|
||||
printf("\n\tERROR: cIOS could not be loaded!\n");
|
||||
sleep(5);
|
||||
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
printf("\n\tIOS 222 failed, reloading ios 250...");
|
||||
ret = IOS_ReloadIOSsafe(250);
|
||||
printf("%d", ret);
|
||||
|
||||
if(ret < 0) {
|
||||
printf("\n\tIOS 250 failed, reloading ios 223...");
|
||||
ret = IOS_ReloadIOSsafe(223);
|
||||
printf("%d", ret);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("\n\tERROR: cIOS could not be loaded!\n");
|
||||
sleep(5);
|
||||
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n\tInitialize sd card");
|
||||
SDCard_Init();
|
||||
printf("\n\tLoad ehc module");
|
||||
@ -327,12 +360,13 @@ main(int argc, char *argv[]) {
|
||||
// gprintf("\n\tbootDevice = %s",bootDevice);
|
||||
|
||||
/* Load Custom IOS */
|
||||
if (Settings.cios == ios222 && IOS_GetVersion() != 222) {
|
||||
printf("\n\tReloading IOS to config setting (222)...");
|
||||
if ((Settings.cios == ios222 && IOS_GetVersion() != 222) ||
|
||||
(Settings.cios == ios223 && IOS_GetVersion() != 223)) {
|
||||
printf("\n\tReloading IOS to config setting (%d)...", ios222 ? 222 : 223);
|
||||
SDCard_deInit();// unmount SD for reloading IOS
|
||||
USBDevice_deInit();// unmount USB for reloading IOS
|
||||
USBStorage_Deinit();
|
||||
ret = IOS_ReloadIOSsafe(222);
|
||||
ret = IOS_ReloadIOSsafe(ios222 ? 222 : 223);
|
||||
printf("%d", ret);
|
||||
SDCard_Init();
|
||||
load_ehc_module();
|
||||
@ -344,12 +378,14 @@ main(int argc, char *argv[]) {
|
||||
SDCard_Init(); // now mount SD:/
|
||||
USBDevice_Init(); // and mount USB:/
|
||||
WBFS_Init(WBFS_DEVICE_USB);
|
||||
} else if (Settings.cios == ios249 && IOS_GetVersion() != 249) {
|
||||
printf("\n\tReloading IOS to config setting (249)...");
|
||||
} else if ((Settings.cios == ios249 && IOS_GetVersion() != 249) ||
|
||||
(Settings.cios == ios250 && IOS_GetVersion() != 250)) {
|
||||
|
||||
printf("\n\tReloading IOS to config setting (%d)...", ios249 ? 249 : 250);
|
||||
SDCard_deInit();// unmount SD for reloading IOS
|
||||
USBDevice_deInit();// unmount USB for reloading IOS
|
||||
USBStorage_Deinit();
|
||||
ret = IOS_ReloadIOSsafe(249);
|
||||
ret = IOS_ReloadIOSsafe(ios249 ? 249 : 250);
|
||||
printf("%d", ret);
|
||||
if (ret < 0) {
|
||||
Settings.cios = ios222;
|
||||
@ -377,9 +413,9 @@ main(int argc, char *argv[]) {
|
||||
|
||||
//if a ID was passed via args copy it and try to boot it after the partition is mounted
|
||||
//its not really a headless mode. more like hairless.
|
||||
if (argc>0&&argv[1])
|
||||
if (argc > 1 && argv[1])
|
||||
{
|
||||
strcpy(headlessID,argv[1]);
|
||||
strncpy(headlessID, argv[1], sizeof(headlessID));
|
||||
}
|
||||
|
||||
//! Init the rest of the System
|
||||
|
213
source/memory/mem2.cpp
Normal file
213
source/memory/mem2.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
|
||||
#include "mem2.h"
|
||||
#include "mem2alloc.h"
|
||||
#include "gecko.h"
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MEM2_PRIORITY_SIZE 0x40
|
||||
|
||||
// Forbid the use of MEM2 through malloc
|
||||
u32 MALLOC_MEM2 = 0;
|
||||
|
||||
static CMEM2Alloc g_mem2gp;
|
||||
|
||||
void MEM2_init(unsigned int mem2Size)
|
||||
{
|
||||
g_mem2gp.init(mem2Size);
|
||||
}
|
||||
|
||||
void MEM2_cleanup(void)
|
||||
{
|
||||
g_mem2gp.cleanup();
|
||||
}
|
||||
|
||||
extern "C" void *MEM2_alloc(unsigned int s)
|
||||
{
|
||||
return g_mem2gp.allocate(s);
|
||||
}
|
||||
|
||||
extern "C" void MEM2_free(void *p)
|
||||
{
|
||||
g_mem2gp.release(p);
|
||||
}
|
||||
|
||||
extern "C" void *MEM2_realloc(void *p, unsigned int s)
|
||||
{
|
||||
return g_mem2gp.reallocate(p, s);
|
||||
}
|
||||
|
||||
extern "C" unsigned int MEM2_usableSize(void *p)
|
||||
{
|
||||
return CMEM2Alloc::usableSize(p);
|
||||
}
|
||||
|
||||
// Give priority to MEM2 for big allocations
|
||||
// Used for saving some space in malloc, which is required for 2 reasons :
|
||||
// - decent speed on small and frequent allocations
|
||||
// - newlib uses its malloc internally (for *printf for example) so it should always have some memory left
|
||||
bool g_bigGoesToMem2 = false;
|
||||
|
||||
void MEM2_takeBigOnes(bool b)
|
||||
{
|
||||
g_bigGoesToMem2 = b;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
extern __typeof(malloc) __real_malloc;
|
||||
extern __typeof(calloc) __real_calloc;
|
||||
extern __typeof(realloc) __real_realloc;
|
||||
extern __typeof(memalign) __real_memalign;
|
||||
extern __typeof(free) __real_free;
|
||||
extern __typeof(malloc_usable_size) __real_malloc_usable_size;
|
||||
|
||||
void *__wrap_malloc(size_t size)
|
||||
{
|
||||
void *p;
|
||||
if (g_bigGoesToMem2 && size > MEM2_PRIORITY_SIZE)
|
||||
{
|
||||
p = MEM2_alloc(size);
|
||||
if (p != 0) {
|
||||
gprintf("Malloc of size %d returns address in MEM2\n", size);
|
||||
return p;
|
||||
}
|
||||
gprintf("Malloc of size %d returns address in MEM1\n", size);
|
||||
return __real_malloc(size);
|
||||
}
|
||||
p = __real_malloc(size);
|
||||
if (p != 0) {
|
||||
gprintf("Malloc of size %d returns address in MEM1\n", size);
|
||||
return p;
|
||||
}
|
||||
gprintf("Malloc of size %d returns address in MEM2\n", size);
|
||||
return MEM2_alloc(size);
|
||||
}
|
||||
|
||||
void *__wrap_calloc(size_t n, size_t size)
|
||||
{
|
||||
void *p;
|
||||
if (g_bigGoesToMem2 && size > MEM2_PRIORITY_SIZE)
|
||||
{
|
||||
p = MEM2_alloc(n * size);
|
||||
if (p != 0)
|
||||
{
|
||||
gprintf("Calloc of amount %d, size %d returns address in MEM2\n", n, size);
|
||||
memset(p, 0, n * size);
|
||||
return p;
|
||||
}
|
||||
gprintf("Calloc of amount %d, size %d returns address in MEM1\n", n, size);
|
||||
return __real_calloc(n, size);
|
||||
}
|
||||
p = __real_calloc(n, size);
|
||||
if (p != 0) {
|
||||
gprintf("Calloc of amount %d, size %d returns address in MEM1\n", n, size);
|
||||
return p;
|
||||
}
|
||||
p = MEM2_alloc(n * size);
|
||||
if (p != 0) {
|
||||
gprintf("Calloc of amount %d, size %d returns address in MEM2\n", n, size);
|
||||
memset(p, 0, n * size);
|
||||
} else {
|
||||
gprintf("Calloc of amount %d, size %d returns NULL\n", n, size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *__wrap_memalign(size_t a, size_t size)
|
||||
{
|
||||
void *p;
|
||||
if (g_bigGoesToMem2 && size > MEM2_PRIORITY_SIZE)
|
||||
{
|
||||
if (a <= 32 && 32 % a == 0)
|
||||
{
|
||||
p = MEM2_alloc(size);
|
||||
if (p != 0) {
|
||||
gprintf("Memalign in blocks of %d, size %d returns address in MEM2\n", a, size);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
gprintf("Memalign in blocks of %d, size %d returns address in MEM1\n", a, size);
|
||||
return __real_memalign(a, size);
|
||||
}
|
||||
p = __real_memalign(a, size);
|
||||
if (p != 0 || a > 32 || 32 % a != 0) {
|
||||
gprintf("Memalign in blocks of %d, size %d returns address in MEM1\n", a, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
p = MEM2_alloc(size);
|
||||
if (p != 0) {
|
||||
gprintf("Memalign in blocks of %d, size %d returns address in MEM2\n", a, size);
|
||||
} else {
|
||||
gprintf("Memalign in blocks of %d, size %d returns NULL\n", a, size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void __wrap_free(void *p)
|
||||
{
|
||||
if (((u32)p & 0x10000000) != 0) {
|
||||
gprintf("Free pointer in address in MEM2\n");
|
||||
MEM2_free(p);
|
||||
} else {
|
||||
gprintf("Free pointer in address in MEM1\n");
|
||||
__real_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void *__wrap_realloc(void *p, size_t size)
|
||||
{
|
||||
void *n;
|
||||
// ptr from mem2
|
||||
if (((u32)p & 0x10000000) != 0 || (p == 0 && g_bigGoesToMem2 && size > MEM2_PRIORITY_SIZE))
|
||||
{
|
||||
n = MEM2_realloc(p, size);
|
||||
if (n != 0) {
|
||||
gprintf("Realloc of size %d returns memory in MEM2\n", size);
|
||||
return n;
|
||||
}
|
||||
n = __real_malloc(size);
|
||||
if (n == 0) {
|
||||
gprintf("Realloc of size %d returns NULL\n", size);
|
||||
return 0;
|
||||
}
|
||||
if (p != 0)
|
||||
{
|
||||
memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size);
|
||||
MEM2_free(p);
|
||||
}
|
||||
gprintf("Realloc of size %d returns memory in MEM1\n", size);
|
||||
return n;
|
||||
}
|
||||
// ptr from malloc
|
||||
n = __real_realloc(p, size);
|
||||
if (n != 0) {
|
||||
gprintf("Realloc of size %d returns memory in MEM1\n", size);
|
||||
return n;
|
||||
}
|
||||
n = MEM2_alloc(size);
|
||||
if (n == 0) {
|
||||
gprintf("Realloc of size %d returns memory in MEM2\n", size);
|
||||
return 0;
|
||||
}
|
||||
if (p != 0)
|
||||
{
|
||||
memcpy(n, p, __real_malloc_usable_size(p) < size ? __real_malloc_usable_size(p) : size);
|
||||
__real_free(p);
|
||||
}
|
||||
gprintf("Realloc of size %d returns memory in MEM2\n", size);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t __wrap_malloc_usable_size(void *p)
|
||||
{
|
||||
if (((u32)p & 0x10000000) != 0)
|
||||
return MEM2_usableSize(p);
|
||||
return __real_malloc_usable_size(p);
|
||||
}
|
||||
|
||||
}
|
26
source/memory/mem2.h
Normal file
26
source/memory/mem2.h
Normal file
@ -0,0 +1,26 @@
|
||||
// 2 MEM2 allocators, one for general purpose, one for covers
|
||||
// Aligned and padded to 32 bytes, as required by many functions
|
||||
|
||||
#ifndef __MEM2_HPP
|
||||
#define __MEM2_HPP
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void *MEM2_alloc(unsigned int s);
|
||||
void *MEM2_realloc(void *p, unsigned int s);
|
||||
void MEM2_free(void *p);
|
||||
unsigned int MEM2_usableSize(void *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
void MEM2_init(unsigned int mem2Size);
|
||||
void MEM2_cleanup(void);
|
||||
void MEM2_takeBigOnes(bool b);
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(__MEM2_HPP)
|
198
source/memory/mem2alloc.cpp
Normal file
198
source/memory/mem2alloc.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
|
||||
#include "mem2alloc.h"
|
||||
|
||||
#include <ogc/system.h>
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
class LockMutex
|
||||
{
|
||||
mutex_t &m_mutex;
|
||||
public:
|
||||
LockMutex(mutex_t &m) : m_mutex(m) { LWP_MutexLock(m_mutex); }
|
||||
~LockMutex(void) { LWP_MutexUnlock(m_mutex); }
|
||||
};
|
||||
|
||||
void CMEM2Alloc::init(unsigned int size)
|
||||
{
|
||||
m_baseAddress = (SBlock *)(((u32)SYS_GetArena2Lo() + 31) & ~31);
|
||||
m_endAddress = (SBlock *)((char *)m_baseAddress + std::min(size * 0x100000, SYS_GetArena2Size() & ~31));
|
||||
if (m_endAddress > (SBlock *)0x93000000) // See loader/disc.c
|
||||
m_endAddress = (SBlock *)0x93000000;
|
||||
SYS_SetArena2Lo(m_endAddress);
|
||||
LWP_MutexInit(&m_mutex, 0);
|
||||
}
|
||||
|
||||
void CMEM2Alloc::init(void *addr, void *end)
|
||||
{
|
||||
m_baseAddress = (SBlock *)(((u32)addr + 31) & ~31);
|
||||
m_endAddress = (SBlock *)((u32)end & ~31);
|
||||
LWP_MutexInit(&m_mutex, 0);
|
||||
}
|
||||
|
||||
void CMEM2Alloc::cleanup(void)
|
||||
{
|
||||
LWP_MutexDestroy(m_mutex);
|
||||
m_mutex = 0;
|
||||
m_first = 0;
|
||||
// // Try to release the range we took through SYS functions
|
||||
// if (SYS_GetArena2Lo() == m_endAdress)
|
||||
// SYS_SetArena2Lo(m_baseAddress);
|
||||
m_baseAddress = 0;
|
||||
m_endAddress = 0;
|
||||
}
|
||||
|
||||
void CMEM2Alloc::clear(void)
|
||||
{
|
||||
m_first = 0;
|
||||
memset(m_baseAddress, 0, (u8 *)m_endAddress - (u8 *)m_endAddress);
|
||||
}
|
||||
|
||||
unsigned int CMEM2Alloc::usableSize(void *p)
|
||||
{
|
||||
return p == 0 ? 0 : ((SBlock *)p - 1)->s * sizeof (SBlock);
|
||||
}
|
||||
|
||||
void *CMEM2Alloc::allocate(unsigned int s)
|
||||
{
|
||||
if (s == 0)
|
||||
s = 1;
|
||||
//
|
||||
LockMutex lock(m_mutex);
|
||||
//
|
||||
s = (s - 1) / sizeof (SBlock) + 1;
|
||||
// First block
|
||||
if (m_first == 0)
|
||||
{
|
||||
if (m_baseAddress + s + 1 >= m_endAddress)
|
||||
return 0;
|
||||
m_first = m_baseAddress;
|
||||
m_first->next = 0;
|
||||
m_first->prev = 0;
|
||||
m_first->s = s;
|
||||
m_first->f = false;
|
||||
return (void *)(m_first + 1);
|
||||
}
|
||||
// Search for a free block
|
||||
SBlock *i;
|
||||
SBlock *j;
|
||||
for (i = m_first; i != 0; i = i->next)
|
||||
{
|
||||
if (i->f && i->s >= s)
|
||||
break;
|
||||
j = i;
|
||||
}
|
||||
// Create a new block
|
||||
if (i == 0)
|
||||
{
|
||||
i = j + j->s + 1;
|
||||
if (i + s + 1 >= m_endAddress)
|
||||
return 0;
|
||||
j->next = i;
|
||||
i->prev = j;
|
||||
i->next = 0;
|
||||
i->s = s;
|
||||
i->f = false;
|
||||
return (void *)(i + 1);
|
||||
}
|
||||
// Reuse a free block
|
||||
i->f = false;
|
||||
// Split it
|
||||
if (i->s > s + 1)
|
||||
{
|
||||
j = i + s + 1;
|
||||
j->f = true;
|
||||
j->s = i->s - s - 1;
|
||||
i->s = s;
|
||||
j->next = i->next;
|
||||
j->prev = i;
|
||||
i->next = j;
|
||||
if (j->next != 0)
|
||||
j->next->prev = j;
|
||||
}
|
||||
return (void *)(i + 1);
|
||||
}
|
||||
|
||||
void CMEM2Alloc::release(void *p)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
LockMutex lock(m_mutex);
|
||||
SBlock *i = (SBlock *)p - 1;
|
||||
i->f = true;
|
||||
// Merge with previous block
|
||||
if (i->prev != 0 && i->prev->f)
|
||||
{
|
||||
i = i->prev;
|
||||
i->s += i->next->s + 1;
|
||||
i->next = i->next->next;
|
||||
if (i->next != 0)
|
||||
i->next->prev = i;
|
||||
}
|
||||
// Merge with next block
|
||||
if (i->next != 0 && i->next->f)
|
||||
{
|
||||
i->s += i->next->s + 1;
|
||||
i->next = i->next->next;
|
||||
if (i->next != 0)
|
||||
i->next->prev = i;
|
||||
}
|
||||
}
|
||||
|
||||
void *CMEM2Alloc::reallocate(void *p, unsigned int s)
|
||||
{
|
||||
SBlock *i;
|
||||
SBlock *j;
|
||||
void *n;
|
||||
|
||||
if (s == 0)
|
||||
s = 1;
|
||||
if (p == 0)
|
||||
return allocate(s);
|
||||
i = (SBlock *)p - 1;
|
||||
s = (s - 1) / sizeof (SBlock) + 1;
|
||||
{
|
||||
LockMutex lock(m_mutex);
|
||||
// Last block
|
||||
if (i->next == 0 && i + s + 1 < m_endAddress)
|
||||
{
|
||||
i->s = s;
|
||||
return p;
|
||||
}
|
||||
// Size <= current size + next block
|
||||
if (i->s < s && i->next->f && i->s + i->next->s + 1 >= s)
|
||||
{
|
||||
// Merge
|
||||
i->s += i->next->s + 1;
|
||||
i->next = i->next->next;
|
||||
if (i->next != 0)
|
||||
i->next->prev = i;
|
||||
}
|
||||
// Size <= current size
|
||||
if (i->s >= s)
|
||||
{
|
||||
// Split
|
||||
if (i->s > s + 1)
|
||||
{
|
||||
j = i + s + 1;
|
||||
j->f = true;
|
||||
j->s = i->s - s - 1;
|
||||
i->s = s;
|
||||
j->next = i->next;
|
||||
j->prev = i;
|
||||
i->next = j;
|
||||
if (j->next != 0)
|
||||
j->next->prev = j;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
// Size > current size
|
||||
n = allocate(s * sizeof (SBlock));
|
||||
if (n == 0)
|
||||
return 0;
|
||||
memcpy(n, p, i->s * sizeof (SBlock));
|
||||
release(p);
|
||||
return n;
|
||||
}
|
41
source/memory/mem2alloc.h
Normal file
41
source/memory/mem2alloc.h
Normal file
@ -0,0 +1,41 @@
|
||||
// MEM2 allocator
|
||||
// Made as a class so i can have 2 sections, one being dedicated to the covers
|
||||
|
||||
#ifndef __MEM2ALLOC_HPP
|
||||
#define __MEM2ALLOC_HPP
|
||||
|
||||
#include <ogc/mutex.h>
|
||||
|
||||
class CMEM2Alloc
|
||||
{
|
||||
public:
|
||||
void *allocate(unsigned int s);
|
||||
void release(void *p);
|
||||
void *reallocate(void *p, unsigned int s);
|
||||
void init(unsigned int size);
|
||||
void init(void *addr, void *end);
|
||||
void cleanup(void);
|
||||
void clear(void);
|
||||
static unsigned int usableSize(void *p);
|
||||
void forceEndAddress(void *newAddr) { m_endAddress = (SBlock *)newAddr; }
|
||||
void *getEndAddress(void) const { return m_endAddress; }
|
||||
void info(void *&address, unsigned int &size) const { address = m_baseAddress; size = (const char *)m_endAddress - (const char *)m_baseAddress; }
|
||||
//
|
||||
CMEM2Alloc(void) : m_baseAddress(0), m_endAddress(0), m_first(0), m_mutex(0) { }
|
||||
private:
|
||||
struct SBlock
|
||||
{
|
||||
unsigned int s;
|
||||
SBlock *next;
|
||||
SBlock *prev;
|
||||
bool f;
|
||||
} __attribute__((aligned(32)));
|
||||
SBlock *m_baseAddress;
|
||||
SBlock *m_endAddress;
|
||||
SBlock *m_first;
|
||||
mutex_t m_mutex;
|
||||
private:
|
||||
CMEM2Alloc(const CMEM2Alloc &);
|
||||
};
|
||||
|
||||
#endif // !defined(__MEM2ALLOC_HPP)
|
@ -30,6 +30,7 @@
|
||||
#include "sys.h"
|
||||
#include "wpad.h"
|
||||
#include "settings/newtitles.h"
|
||||
#include "patches/fst.h"
|
||||
|
||||
/*** Variables that are also used extern ***/
|
||||
GuiWindow * mainWindow = NULL;
|
||||
@ -275,14 +276,14 @@ int MainMenu(int menu) {
|
||||
if (strcmp(headlessID,"")==0)
|
||||
ResumeGui();
|
||||
|
||||
bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, Settings.volume);
|
||||
bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, Settings.volume);
|
||||
bgMusic->SetLoop(1); //loop music
|
||||
// startup music
|
||||
if (strcmp("", Settings.oggload_path) && strcmp("notset", Settings.ogg_path)) {
|
||||
bgMusic->Load(Settings.ogg_path);
|
||||
}
|
||||
bgMusic->Play();
|
||||
|
||||
|
||||
while (currentMenu != MENU_EXIT) {
|
||||
bgMusic->SetVolume(Settings.volume);
|
||||
|
||||
@ -490,13 +491,17 @@ int MainMenu(int menu) {
|
||||
if(dvdheader)
|
||||
delete dvdheader;
|
||||
|
||||
gprintf("Loading BCA data...");
|
||||
ret = do_bca_code(header->id);
|
||||
gprintf("%d\n", ret);
|
||||
|
||||
if (reloadblock == on && Sys_IsHermes()) {
|
||||
patch_cios_data();
|
||||
if (!load_from_fat) {
|
||||
mload_close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u8 errorfixer002 = 0;
|
||||
switch (fix002) {
|
||||
case on:
|
||||
|
@ -16,7 +16,6 @@ extern char headlessID[8];
|
||||
***************************************************************************/
|
||||
int MenuCheck() {
|
||||
gprintf("\nMenuCheck()");
|
||||
//WindowPrompt("test",0,"ok");
|
||||
int menu = MENU_NONE;
|
||||
int i = 0;
|
||||
int choice;
|
||||
@ -59,12 +58,12 @@ int MenuCheck() {
|
||||
extern PartList partitions;
|
||||
// Added for slow HDD
|
||||
for (int runs = 0; runs < 10; runs++) {
|
||||
if (Partition_GetList(&partitions) != 0) {
|
||||
if (Partition_GetList(WBFS_DEVICE_USB, &partitions) != 0) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Settings.partition != -1 && partitions.num > Settings.partition) {
|
||||
if (Settings.partition != -1 && partitions.num > Settings.partition) {
|
||||
PartInfo pinfo = partitions.pinfo[Settings.partition];
|
||||
ret2 = WBFS_OpenPart(pinfo.fs_type == FS_TYPE_FAT32, pinfo.fat_i, partitions.pentry[Settings.partition].sector, partitions.pentry[Settings.partition].size, (char *) &game_partition);
|
||||
|
||||
@ -103,14 +102,14 @@ int MenuCheck() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ret2 >= 0 || load_from_fat) {
|
||||
cfg_save_global();
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
if (ret2 < 0 && !load_from_fat) {
|
||||
choice = WindowPrompt(tr("No WBFS or FAT game partition found"),tr("You need to select or format a partition"), tr("Select"), tr("Format"), tr("Return"));
|
||||
if (choice == 0) {
|
||||
@ -120,7 +119,7 @@ int MenuCheck() {
|
||||
menu = MENU_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret2 = Disc_Init();
|
||||
if (ret2 < 0) {
|
||||
WindowPrompt (tr("Error !"),tr("Could not initialize DIP module!"),tr("OK"));
|
||||
@ -136,6 +135,13 @@ int MenuCheck() {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// open database if needed, load titles if needed
|
||||
OpenXMLDatabase(Settings.titlestxt_path,Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride==1?true:false, true);
|
||||
|
||||
// titles.txt loaded after database to override database titles with custom titles
|
||||
//snprintf(pathname, sizeof(pathname), "%stitles.txt", Settings.titlestxt_path);
|
||||
//cfg_parsefile(pathname, &title_set);
|
||||
|
||||
//Spieleliste laden
|
||||
__Menu_GetEntries(0);
|
||||
|
||||
@ -151,13 +157,6 @@ int MenuCheck() {
|
||||
USBDevice_Init();
|
||||
SDCard_Init();
|
||||
}
|
||||
|
||||
// open database if needed, load titles if needed
|
||||
OpenXMLDatabase(Settings.titlestxt_path,Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride==1?true:false, true);
|
||||
|
||||
// titles.txt loaded after database to override database titles with custom titles
|
||||
//snprintf(pathname, sizeof(pathname), "%stitles.txt", Settings.titlestxt_path);
|
||||
//cfg_parsefile(pathname, &title_set);
|
||||
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "prompts/DiscBrowser.h"
|
||||
#include "settings/Settings.h"
|
||||
#include "wpad.h"
|
||||
#include "sys.h"
|
||||
|
||||
#include "libwiigui/gui_gamebrowser.h"
|
||||
#include "libwiigui/gui_gamegrid.h"
|
||||
@ -574,6 +575,8 @@ int MenuDiscList() {
|
||||
}
|
||||
|
||||
ResumeGui();
|
||||
|
||||
// ShowMemInfo();
|
||||
|
||||
while (menu == MENU_NONE) {
|
||||
|
||||
|
@ -1,117 +1,122 @@
|
||||
#define size_dip_plugin 3080
|
||||
#define size_dip_plugin 3224
|
||||
|
||||
unsigned char dip_plugin[3080] __attribute__((aligned (32)))={
|
||||
unsigned char dip_plugin[3224] __attribute__((aligned (32)))={
|
||||
19, 119, 228, 85, 18, 52, 0, 1, 32, 34, 205, 172, 32, 32, 13, 57, 32, 32, 8, 197, 32, 32, 8, 153, 32, 32, 91, 129, 32,
|
||||
32, 0, 73, 32, 32, 40, 117, 32, 32, 54, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
19, 119, 233, 53, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 71, 120, 234, 0, 2, 7, 70, 192, 71,
|
||||
120, 234, 0, 2, 23, 70, 192, 71, 120, 234, 0, 2, 39, 70, 192, 71, 120, 234, 0, 2, 31, 70, 192, 71, 120, 234, 0, 2, 5,
|
||||
70, 192, 71, 120, 234, 0, 1, 247, 70, 192, 71, 120, 234, 0, 2, 29, 70, 192, 71, 120, 234, 0, 2, 25, 70, 192, 71, 120,
|
||||
234, 0, 2, 33, 181, 0, 75, 7, 176, 137, 147, 0, 70, 104, 35, 0, 33, 0, 34, 0, 147, 1, 147, 2, 240, 0, 252, 85, 176,
|
||||
9, 188, 2, 71, 8, 70, 192, 227, 0, 0, 0, 181, 16, 28, 3, 34, 32, 28, 12, 72, 13, 28, 25, 247, 255, 255, 210, 33, 32,
|
||||
72, 11, 247, 255, 255, 202, 73, 10, 34, 1, 104, 11, 66, 19, 209, 253, 34, 32, 28, 32, 73, 6, 247, 255, 255, 196, 28,
|
||||
32, 33, 32, 247, 255, 255, 188, 75, 4, 104, 24, 188, 16, 188, 2, 71, 8, 70, 192, 13, 0, 96, 0, 13, 0, 96, 28, 13, 0,
|
||||
96, 32, 181, 240, 70, 95, 70, 86, 70, 77, 70, 68, 180, 240, 10, 203, 70, 154, 75, 20, 176, 137, 37, 0, 28, 7, 28, 14,
|
||||
70, 145, 70, 108, 70, 155, 70, 168, 70, 91, 96, 35, 70, 67, 96, 99, 96, 163, 70, 83, 96, 227, 28, 56, 70, 75, 28, 49,
|
||||
97, 35, 247, 255, 255, 162, 70, 104, 28, 57, 28, 50, 240, 0, 252, 6, 53, 1, 40, 0, 209, 8, 176, 9, 188, 60, 70, 144,
|
||||
70, 153, 70, 162, 70, 171, 188, 240, 188, 2, 71, 8, 45, 15, 217, 223, 231, 243, 208, 0, 0, 0, 181, 112, 176, 136, 75,
|
||||
8, 28, 6, 28, 13, 70, 108, 147, 0, 96, 97, 146, 2, 247, 255, 255, 129, 28, 49, 28, 42, 70, 104, 240, 0, 251, 229, 176,
|
||||
8, 188, 112, 188, 2, 71, 8, 168, 0, 0, 0, 181, 240, 70, 95, 70, 86, 70, 77, 70, 68, 180, 240, 176, 143, 144, 4, 145,
|
||||
3, 146, 2, 41, 0, 209, 0, 224, 126, 10, 82, 70, 145, 35, 128, 34, 0, 1, 27, 70, 147, 34, 255, 147, 1, 3, 210, 171, 6,
|
||||
146, 0, 70, 152, 224, 7, 154, 3, 68, 179, 69, 90, 217, 62, 154, 5, 24, 179, 10, 219, 68, 153, 154, 3, 70, 91, 26, 214,
|
||||
70, 74, 2, 83, 154, 2, 66, 154, 216, 87, 35, 0, 147, 5, 36, 0, 159, 4, 34, 128, 68, 95, 28, 56, 28, 49, 1, 18, 240,
|
||||
0, 248, 103, 44, 0, 209, 47, 40, 0, 208, 45, 155, 0, 28, 6, 66, 152, 217, 1, 38, 255, 3, 246, 10, 242, 70, 146, 36,
|
||||
0, 75, 43, 70, 66, 96, 19, 35, 0, 96, 83, 96, 147, 70, 83, 96, 211, 70, 75, 97, 19, 28, 56, 28, 49, 247, 255, 255, 38,
|
||||
70, 64, 28, 57, 28, 50, 240, 0, 251, 138, 52, 1, 28, 5, 40, 0, 208, 192, 44, 15, 217, 230, 45, 0, 208, 188, 176, 15,
|
||||
28, 40, 188, 60, 70, 144, 70, 153, 70, 162, 70, 171, 188, 240, 188, 2, 71, 8, 154, 5, 25, 147, 154, 1, 66, 147, 217,
|
||||
1, 155, 5, 26, 214, 32, 128, 1, 0, 33, 32, 247, 255, 254, 251, 28, 4, 40, 0, 208, 18, 33, 128, 1, 9, 70, 74, 247, 255,
|
||||
255, 59, 28, 5, 40, 0, 208, 15, 28, 32, 247, 255, 254, 217, 231, 216, 26, 211, 0, 155, 28, 28, 147, 5, 30, 99, 65, 156,
|
||||
231, 163, 37, 1, 66, 109, 231, 208, 37, 0, 231, 206, 154, 5, 28, 56, 24, 161, 28, 50, 247, 255, 254, 214, 28, 56, 28,
|
||||
49, 247, 255, 254, 206, 231, 228, 70, 192, 208, 0, 0, 0, 181, 48, 28, 13, 28, 20, 6, 195, 209, 18, 75, 15, 66, 152,
|
||||
217, 19, 33, 0, 75, 14, 24, 194, 75, 14, 66, 154, 216, 1, 75, 13, 26, 25, 66, 161, 211, 5, 28, 8, 66, 169, 216, 10,
|
||||
30, 99, 67, 152, 224, 0, 32, 0, 188, 48, 188, 2, 71, 8, 35, 192, 4, 91, 26, 25, 231, 232, 28, 40, 30, 99, 67, 152, 231,
|
||||
244, 1, 127, 255, 255, 240, 0, 0, 0, 3, 97, 127, 255, 19, 97, 128, 0, 71, 112, 70, 192, 181, 48, 28, 4, 72, 15, 28,
|
||||
13, 104, 131, 104, 193, 176, 129, 24, 91, 24, 154, 105, 3, 43, 0, 209, 15, 104, 67, 43, 0, 209, 7, 28, 32, 28, 41, 247,
|
||||
255, 255, 13, 176, 1, 188, 48, 188, 2, 71, 8, 28, 32, 28, 41, 247, 255, 255, 27, 231, 246, 28, 32, 28, 41, 240, 0, 249,
|
||||
220, 231, 241, 70, 192, 19, 119, 240, 0, 181, 240, 79, 27, 35, 1, 28, 4, 96, 59, 176, 129, 33, 32, 247, 255, 254, 127,
|
||||
104, 227, 43, 8, 208, 8, 28, 32, 240, 0, 250, 214, 35, 0, 96, 59, 176, 1, 188, 240, 188, 2, 71, 8, 105, 163, 37, 197,
|
||||
104, 24, 104, 89, 247, 255, 254, 109, 105, 163, 1, 173, 104, 27, 28, 40, 33, 8, 104, 92, 104, 30, 247, 255, 254, 100,
|
||||
75, 10, 4, 36, 64, 30, 67, 52, 78, 9, 96, 44, 28, 40, 33, 4, 96, 52, 247, 255, 254, 73, 28, 48, 33, 4, 247, 255, 254,
|
||||
69, 35, 0, 96, 59, 32, 0, 231, 217, 70, 192, 19, 119, 240, 40, 0, 0, 255, 255, 0, 0, 49, 136, 181, 16, 73, 20, 28, 4,
|
||||
104, 139, 104, 202, 24, 154, 105, 11, 43, 0, 209, 18, 104, 75, 43, 0, 209, 11, 33, 32, 247, 255, 254, 175, 40, 0, 219,
|
||||
3, 105, 162, 75, 12, 66, 154, 208, 10, 188, 16, 188, 2, 71, 8, 33, 32, 247, 255, 254, 185, 231, 242, 33, 32, 240, 0,
|
||||
249, 123, 231, 238, 75, 6, 34, 1, 112, 26, 120, 91, 43, 0, 209, 238, 247, 255, 254, 10, 231, 235, 70, 192, 19, 119,
|
||||
240, 0, 93, 28, 158, 163, 32, 34, 205, 172, 181, 240, 70, 87, 70, 70, 180, 192, 28, 4, 120, 0, 176, 129, 28, 14, 28,
|
||||
23, 40, 224, 208, 24, 77, 133, 35, 0, 98, 43, 28, 3, 59, 112, 43, 143, 217, 13, 28, 32, 28, 49, 28, 58, 240, 0, 250,
|
||||
108, 28, 4, 176, 1, 28, 32, 188, 12, 70, 144, 70, 154, 188, 240, 188, 2, 71, 8, 74, 123, 0, 155, 88, 211, 70, 159, 77,
|
||||
120, 106, 43, 43, 0, 209, 2, 105, 43, 43, 0, 208, 230, 28, 48, 33, 0, 28, 58, 240, 0, 248, 240, 106, 43, 224, 143, 104,
|
||||
107, 43, 0, 209, 2, 105, 43, 43, 0, 208, 217, 36, 0, 231, 221, 35, 1, 34, 37, 84, 171, 104, 43, 43, 0, 208, 0, 224,
|
||||
173, 28, 32, 28, 58, 240, 0, 250, 62, 28, 4, 34, 0, 35, 37, 84, 234, 44, 0, 209, 204, 224, 46, 104, 235, 104, 169, 70,
|
||||
154, 105, 43, 70, 136, 43, 0, 209, 0, 224, 176, 32, 0, 34, 0, 70, 67, 70, 81, 67, 11, 209, 2, 42, 0, 209, 0, 224, 176,
|
||||
28, 3, 30, 90, 65, 147, 96, 107, 28, 48, 28, 57, 247, 255, 255, 107, 28, 4, 231, 176, 105, 43, 43, 0, 208, 167, 35,
|
||||
2, 224, 85, 104, 97, 104, 162, 40, 208, 209, 0, 224, 144, 28, 48, 247, 255, 254, 250, 28, 4, 40, 0, 209, 160, 35, 37,
|
||||
92, 235, 43, 0, 209, 156, 28, 48, 28, 57, 247, 255, 254, 237, 231, 151, 35, 36, 92, 234, 42, 0, 209, 179, 105, 41, 84,
|
||||
234, 35, 37, 96, 42, 96, 106, 96, 170, 96, 234, 98, 42, 84, 234, 70, 136, 41, 0, 209, 0, 231, 128, 105, 108, 247, 255,
|
||||
253, 142, 70, 64, 28, 41, 28, 34, 56, 1, 49, 24, 240, 0, 248, 249, 28, 4, 231, 122, 104, 107, 43, 0, 208, 93, 75, 60,
|
||||
36, 160, 98, 43, 2, 36, 231, 114, 104, 107, 43, 0, 209, 3, 105, 43, 43, 0, 209, 0, 231, 101, 104, 99, 104, 162, 7, 155,
|
||||
67, 19, 74, 53, 36, 0, 64, 19, 96, 235, 231, 98, 104, 99, 72, 51, 64, 24, 247, 255, 253, 122, 28, 4, 231, 91, 104, 98,
|
||||
35, 36, 84, 234, 36, 0, 231, 86, 105, 43, 96, 51, 28, 48, 28, 57, 247, 255, 253, 67, 36, 0, 231, 78, 104, 99, 97, 43,
|
||||
43, 0, 209, 40, 105, 99, 36, 0, 97, 107, 231, 70, 104, 43, 231, 238, 104, 99, 36, 0, 96, 43, 231, 64, 104, 171, 231,
|
||||
232, 104, 99, 36, 0, 96, 171, 231, 58, 104, 107, 43, 0, 209, 3, 105, 43, 43, 0, 209, 0, 231, 45, 28, 48, 33, 0, 28,
|
||||
58, 240, 0, 248, 55, 28, 48, 28, 57, 247, 255, 253, 29, 36, 0, 231, 40, 104, 97, 104, 162, 28, 48, 247, 255, 254, 122,
|
||||
28, 4, 231, 79, 28, 40, 28, 33, 49, 8, 34, 6, 48, 24, 247, 255, 253, 17, 231, 206, 105, 43, 43, 0, 209, 158, 231, 15,
|
||||
2, 201, 2, 82, 231, 107, 28, 58, 28, 32, 28, 49, 240, 0, 249, 121, 28, 2, 30, 83, 65, 154, 231, 71, 105, 43, 43, 0,
|
||||
208, 0, 231, 74, 96, 106, 36, 0, 231, 2, 70, 192, 19, 119, 240, 0, 19, 119, 233, 144, 0, 5, 49, 0, 255, 255, 128, 0,
|
||||
127, 255, 255, 255, 181, 240, 70, 87, 70, 78, 70, 69, 180, 224, 70, 128, 28, 14, 70, 148, 42, 0, 208, 51, 33, 3, 28,
|
||||
2, 64, 10, 35, 4, 26, 155, 28, 24, 64, 8, 69, 96, 216, 49, 40, 0, 208, 49, 36, 0, 70, 67, 85, 30, 52, 1, 66, 160, 216,
|
||||
250, 69, 132, 208, 32, 70, 99, 26, 27, 8, 159, 70, 153, 0, 187, 70, 154, 43, 0, 208, 17, 4, 51, 6, 50, 2, 49, 67, 26,
|
||||
67, 10, 28, 21, 70, 67, 67, 53, 24, 26, 33, 0, 0, 139, 49, 1, 80, 213, 66, 185, 211, 250, 68, 84, 69, 209, 208, 6, 70,
|
||||
67, 25, 24, 52, 1, 112, 6, 48, 1, 69, 164, 216, 250, 188, 28, 70, 144, 70, 153, 70, 162, 188, 240, 188, 1, 71, 0, 70,
|
||||
96, 231, 203, 36, 0, 231, 211, 70, 192, 181, 112, 76, 17, 28, 6, 104, 32, 176, 130, 28, 13, 98, 2, 97, 6, 100, 1, 97,
|
||||
65, 33, 68, 247, 255, 252, 147, 28, 48, 28, 41, 247, 255, 252, 143, 75, 10, 34, 2, 104, 24, 104, 35, 73, 9, 147, 0,
|
||||
35, 1, 247, 255, 252, 154, 28, 41, 28, 4, 28, 48, 247, 255, 252, 145, 176, 2, 28, 32, 188, 112, 188, 2, 71, 8, 19, 119,
|
||||
240, 44, 19, 119, 240, 48, 87, 70, 83, 2, 181, 240, 176, 133, 28, 4, 28, 15, 146, 3, 40, 2, 216, 75, 77, 47, 104, 43,
|
||||
43, 0, 208, 74, 78, 46, 104, 48, 40, 0, 219, 1, 247, 255, 252, 97, 74, 44, 0, 163, 88, 152, 33, 1, 247, 255, 252, 107,
|
||||
96, 48, 40, 0, 219, 66, 104, 48, 40, 0, 219, 49, 104, 40, 28, 57, 34, 6, 48, 32, 247, 255, 252, 87, 104, 40, 169, 3,
|
||||
34, 4, 48, 64, 247, 255, 252, 81, 104, 42, 36, 4, 28, 19, 51, 32, 96, 19, 104, 42, 35, 6, 96, 83, 104, 42, 33, 68, 28,
|
||||
19, 51, 64, 96, 147, 104, 43, 96, 220, 104, 40, 247, 255, 252, 59, 104, 43, 104, 48, 34, 2, 147, 0, 73, 22, 35, 0, 247,
|
||||
255, 252, 71, 104, 42, 28, 19, 51, 32, 96, 19, 104, 43, 96, 92, 104, 42, 28, 19, 51, 64, 96, 147, 104, 43, 96, 220,
|
||||
176, 5, 188, 240, 188, 2, 71, 8, 32, 1, 66, 64, 231, 248, 75, 11, 78, 8, 96, 43, 35, 1, 66, 91, 96, 51, 231, 179, 44,
|
||||
0, 209, 186, 72, 8, 33, 1, 247, 255, 252, 31, 96, 48, 231, 180, 70, 192, 19, 119, 240, 44, 19, 119, 240, 48, 19, 119,
|
||||
235, 252, 87, 70, 83, 1, 19, 119, 240, 64, 19, 119, 235, 208, 233, 45, 64, 128, 229, 159, 113, 0, 229, 151, 112, 0,
|
||||
235, 0, 0, 45, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159, 112, 236, 229, 151, 112, 0, 235, 0,
|
||||
0, 39, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159, 112, 216, 229, 151, 112, 0, 235, 0, 0, 33, 232,
|
||||
189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159, 112, 196, 229, 151, 112, 0, 235, 0, 0, 27, 232, 189, 64,
|
||||
128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159, 112, 176, 229, 151, 112, 0, 235, 0, 0, 21, 232, 189, 64, 128, 225,
|
||||
47, 255, 30, 233, 45, 64, 128, 229, 159, 112, 156, 229, 151, 112, 0, 235, 0, 0, 15, 232, 189, 64, 128, 225, 47, 255,
|
||||
30, 230, 0, 8, 16, 225, 47, 255, 30, 230, 0, 7, 240, 225, 47, 255, 30, 230, 0, 3, 144, 225, 47, 255, 30, 230, 0, 3,
|
||||
176, 225, 47, 255, 30, 230, 0, 3, 208, 225, 47, 255, 30, 230, 0, 3, 240, 225, 47, 255, 30, 230, 0, 4, 80, 225, 47, 255,
|
||||
30, 225, 47, 255, 23, 239, 0, 0, 204, 225, 47, 255, 30, 180, 124, 181, 0, 247, 255, 253, 30, 188, 2, 188, 124, 71, 8,
|
||||
181, 112, 176, 136, 104, 133, 28, 1, 75, 14, 71, 24, 70, 192, 70, 114, 28, 1, 32, 4, 223, 171, 71, 16, 181, 240, 70,
|
||||
95, 70, 86, 70, 77, 70, 68, 180, 240, 75, 8, 104, 27, 71, 24, 19, 119, 224, 16, 19, 119, 224, 20, 19, 119, 224, 24,
|
||||
19, 119, 224, 28, 19, 119, 224, 32, 19, 119, 224, 36, 32, 16, 0, 213, 19, 119, 224, 12, 70, 192, 70, 192, 19, 119, 228,
|
||||
236, 19, 119, 228, 200, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 190, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
32, 0, 73, 32, 32, 40, 117, 32, 32, 54, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 119, 233,
|
||||
160, 19, 119, 233, 117, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 71, 120, 234, 0, 2, 23, 70, 192,
|
||||
71, 120, 234, 0, 2, 39, 70, 192, 71, 120, 234, 0, 2, 55, 70, 192, 71, 120, 234, 0, 2, 47, 70, 192, 71, 120, 234, 0,
|
||||
2, 21, 70, 192, 71, 120, 234, 0, 2, 7, 70, 192, 71, 120, 234, 0, 2, 45, 70, 192, 71, 120, 234, 0, 2, 41, 70, 192, 71,
|
||||
120, 234, 0, 2, 49, 181, 0, 75, 7, 176, 137, 147, 0, 70, 104, 35, 0, 33, 0, 34, 0, 147, 1, 147, 2, 240, 0, 252, 157,
|
||||
176, 9, 188, 2, 71, 8, 70, 192, 227, 0, 0, 0, 181, 16, 28, 3, 34, 32, 28, 12, 72, 13, 28, 25, 247, 255, 255, 210, 33,
|
||||
32, 72, 11, 247, 255, 255, 202, 73, 10, 34, 1, 104, 11, 66, 19, 209, 253, 34, 32, 28, 32, 73, 6, 247, 255, 255, 196,
|
||||
28, 32, 33, 32, 247, 255, 255, 188, 75, 4, 104, 24, 188, 16, 188, 2, 71, 8, 70, 192, 13, 0, 96, 0, 13, 0, 96, 28, 13,
|
||||
0, 96, 32, 181, 240, 70, 95, 70, 86, 70, 77, 70, 68, 180, 240, 10, 203, 70, 154, 75, 20, 176, 137, 37, 0, 28, 7, 28,
|
||||
14, 70, 145, 70, 108, 70, 155, 70, 168, 70, 91, 96, 35, 70, 67, 96, 99, 96, 163, 70, 83, 96, 227, 28, 56, 70, 75, 28,
|
||||
49, 97, 35, 247, 255, 255, 162, 70, 104, 28, 57, 28, 50, 240, 0, 252, 78, 53, 1, 40, 0, 209, 8, 176, 9, 188, 60, 70,
|
||||
144, 70, 153, 70, 162, 70, 171, 188, 240, 188, 2, 71, 8, 45, 15, 217, 223, 231, 243, 208, 0, 0, 0, 181, 112, 176, 136,
|
||||
75, 8, 28, 6, 28, 13, 70, 108, 147, 0, 96, 97, 146, 2, 247, 255, 255, 129, 28, 49, 28, 42, 70, 104, 240, 0, 252, 45,
|
||||
176, 8, 188, 112, 188, 2, 71, 8, 168, 0, 0, 0, 181, 240, 70, 95, 70, 86, 70, 77, 70, 68, 180, 240, 176, 143, 144, 4,
|
||||
145, 3, 146, 2, 41, 0, 209, 0, 224, 126, 10, 82, 70, 145, 35, 128, 34, 0, 1, 27, 70, 147, 34, 255, 147, 1, 3, 210, 171,
|
||||
6, 146, 0, 70, 152, 224, 7, 154, 3, 68, 179, 69, 90, 217, 62, 154, 5, 24, 179, 10, 219, 68, 153, 154, 3, 70, 91, 26,
|
||||
214, 70, 74, 2, 83, 154, 2, 66, 154, 216, 87, 35, 0, 147, 5, 36, 0, 159, 4, 34, 128, 68, 95, 28, 56, 28, 49, 1, 18,
|
||||
240, 0, 248, 103, 44, 0, 209, 47, 40, 0, 208, 45, 155, 0, 28, 6, 66, 152, 217, 1, 38, 255, 3, 246, 10, 242, 70, 146,
|
||||
36, 0, 75, 43, 70, 66, 96, 19, 35, 0, 96, 83, 96, 147, 70, 83, 96, 211, 70, 75, 97, 19, 28, 56, 28, 49, 247, 255, 255,
|
||||
38, 70, 64, 28, 57, 28, 50, 240, 0, 251, 210, 52, 1, 28, 5, 40, 0, 208, 192, 44, 15, 217, 230, 45, 0, 208, 188, 176,
|
||||
15, 28, 40, 188, 60, 70, 144, 70, 153, 70, 162, 70, 171, 188, 240, 188, 2, 71, 8, 154, 5, 25, 147, 154, 1, 66, 147,
|
||||
217, 1, 155, 5, 26, 214, 32, 128, 1, 0, 33, 32, 247, 255, 254, 251, 28, 4, 40, 0, 208, 18, 33, 128, 1, 9, 70, 74, 247,
|
||||
255, 255, 59, 28, 5, 40, 0, 208, 15, 28, 32, 247, 255, 254, 217, 231, 216, 26, 211, 0, 155, 28, 28, 147, 5, 30, 99,
|
||||
65, 156, 231, 163, 37, 1, 66, 109, 231, 208, 37, 0, 231, 206, 154, 5, 28, 56, 24, 161, 28, 50, 247, 255, 254, 214, 28,
|
||||
56, 28, 49, 247, 255, 254, 206, 231, 228, 70, 192, 208, 0, 0, 0, 181, 48, 28, 13, 28, 20, 6, 195, 209, 18, 75, 15, 66,
|
||||
152, 217, 19, 33, 0, 75, 14, 24, 194, 75, 14, 66, 154, 216, 1, 75, 13, 26, 25, 66, 161, 211, 5, 28, 8, 66, 169, 216,
|
||||
10, 30, 99, 67, 152, 224, 0, 32, 0, 188, 48, 188, 2, 71, 8, 35, 192, 4, 91, 26, 25, 231, 232, 28, 40, 30, 99, 67, 152,
|
||||
231, 244, 1, 127, 255, 255, 240, 0, 0, 0, 3, 97, 127, 255, 19, 97, 128, 0, 71, 112, 70, 192, 181, 48, 28, 4, 72, 15,
|
||||
28, 13, 104, 131, 104, 193, 176, 129, 24, 91, 24, 154, 105, 3, 43, 0, 209, 15, 104, 67, 43, 0, 209, 7, 28, 32, 28, 41,
|
||||
247, 255, 255, 13, 176, 1, 188, 48, 188, 2, 71, 8, 28, 32, 28, 41, 247, 255, 255, 27, 231, 246, 28, 32, 28, 41, 240,
|
||||
0, 249, 246, 231, 241, 70, 192, 19, 119, 240, 0, 181, 240, 79, 27, 35, 1, 28, 4, 96, 59, 176, 129, 33, 32, 247, 255,
|
||||
254, 127, 104, 227, 43, 8, 208, 8, 28, 32, 240, 0, 250, 246, 35, 0, 96, 59, 176, 1, 188, 240, 188, 2, 71, 8, 105, 163,
|
||||
37, 197, 104, 24, 104, 89, 247, 255, 254, 109, 105, 163, 1, 173, 104, 27, 28, 40, 33, 8, 104, 92, 104, 30, 247, 255,
|
||||
254, 100, 75, 10, 4, 36, 64, 30, 67, 52, 78, 9, 96, 44, 28, 40, 33, 4, 96, 52, 247, 255, 254, 73, 28, 48, 33, 4, 247,
|
||||
255, 254, 69, 35, 0, 96, 59, 32, 0, 231, 217, 70, 192, 19, 119, 240, 40, 0, 0, 255, 255, 0, 0, 49, 136, 181, 16, 73,
|
||||
20, 28, 4, 104, 139, 104, 202, 24, 154, 105, 11, 43, 0, 209, 18, 104, 75, 43, 0, 209, 11, 33, 32, 247, 255, 254, 175,
|
||||
40, 0, 219, 3, 105, 162, 75, 12, 66, 154, 208, 10, 188, 16, 188, 2, 71, 8, 33, 32, 247, 255, 254, 185, 231, 242, 33,
|
||||
32, 240, 0, 249, 149, 231, 238, 75, 6, 34, 1, 112, 26, 120, 91, 43, 0, 209, 238, 247, 255, 254, 10, 231, 235, 70, 192,
|
||||
19, 119, 240, 0, 93, 28, 158, 163, 32, 34, 205, 172, 181, 240, 70, 87, 70, 70, 180, 192, 28, 6, 120, 0, 176, 129, 28,
|
||||
15, 70, 144, 40, 224, 208, 24, 77, 145, 35, 0, 98, 43, 28, 3, 59, 112, 43, 143, 217, 13, 28, 48, 28, 57, 70, 66, 240,
|
||||
0, 250, 180, 28, 4, 176, 1, 28, 32, 188, 12, 70, 144, 70, 154, 188, 240, 188, 2, 71, 8, 74, 135, 0, 155, 88, 211, 70,
|
||||
159, 77, 132, 106, 43, 43, 0, 209, 2, 105, 43, 43, 0, 208, 230, 28, 56, 33, 0, 70, 66, 240, 0, 249, 10, 106, 43, 96,
|
||||
59, 28, 56, 70, 65, 247, 255, 253, 212, 36, 0, 231, 223, 104, 107, 43, 0, 209, 2, 105, 43, 43, 0, 208, 211, 36, 0, 231,
|
||||
215, 104, 107, 43, 0, 209, 2, 105, 43, 43, 0, 208, 203, 28, 56, 33, 0, 70, 66, 240, 0, 248, 239, 28, 56, 70, 65, 247,
|
||||
255, 253, 187, 36, 0, 231, 198, 104, 115, 36, 0, 96, 171, 231, 194, 104, 171, 231, 217, 104, 115, 36, 0, 96, 43, 231,
|
||||
188, 104, 43, 231, 211, 104, 115, 97, 43, 43, 0, 208, 6, 28, 40, 28, 49, 48, 24, 49, 8, 34, 6, 247, 255, 253, 166, 105,
|
||||
115, 36, 0, 97, 107, 231, 171, 105, 43, 231, 194, 104, 114, 35, 36, 84, 234, 36, 0, 231, 164, 104, 235, 104, 172, 70,
|
||||
154, 105, 43, 43, 0, 209, 0, 224, 170, 32, 0, 34, 0, 70, 83, 67, 35, 209, 2, 42, 0, 209, 0, 224, 142, 28, 3, 30, 90,
|
||||
65, 147, 96, 107, 28, 56, 70, 65, 247, 255, 255, 70, 28, 4, 231, 139, 35, 1, 34, 37, 84, 171, 104, 43, 43, 0, 209, 0,
|
||||
224, 132, 104, 113, 104, 178, 28, 56, 247, 255, 254, 214, 28, 4, 34, 0, 35, 37, 84, 234, 44, 0, 208, 0, 231, 120, 28,
|
||||
56, 70, 65, 247, 255, 254, 201, 231, 115, 104, 115, 72, 70, 64, 24, 247, 255, 253, 139, 28, 4, 231, 108, 76, 68, 33,
|
||||
64, 28, 32, 247, 255, 253, 106, 34, 0, 28, 33, 224, 3, 50, 1, 42, 64, 209, 0, 231, 90, 92, 163, 43, 0, 208, 248, 34,
|
||||
64, 28, 56, 247, 255, 253, 80, 28, 56, 33, 64, 247, 255, 253, 72, 36, 0, 231, 83, 35, 36, 92, 234, 42, 0, 208, 0, 231,
|
||||
116, 84, 234, 35, 37, 84, 234, 105, 43, 96, 42, 96, 106, 96, 170, 96, 234, 98, 42, 70, 154, 43, 0, 209, 0, 231, 59,
|
||||
105, 108, 247, 255, 253, 73, 70, 80, 28, 41, 28, 34, 56, 1, 49, 24, 240, 0, 248, 206, 28, 4, 231, 53, 104, 113, 104,
|
||||
178, 40, 208, 208, 59, 28, 56, 247, 255, 254, 133, 28, 4, 40, 0, 208, 0, 231, 42, 35, 37, 92, 235, 43, 0, 208, 0, 231,
|
||||
37, 231, 171, 105, 43, 43, 0, 209, 0, 231, 26, 35, 2, 231, 55, 104, 107, 43, 0, 209, 3, 105, 43, 43, 0, 209, 0, 231,
|
||||
17, 104, 115, 104, 178, 7, 155, 67, 19, 74, 24, 36, 0, 64, 19, 96, 235, 231, 14, 104, 107, 43, 0, 208, 17, 75, 21, 36,
|
||||
160, 98, 43, 2, 36, 231, 6, 105, 43, 43, 0, 208, 0, 231, 108, 96, 106, 36, 0, 230, 255, 28, 48, 70, 66, 240, 0, 249,
|
||||
175, 28, 4, 231, 122, 105, 43, 43, 0, 209, 234, 230, 239, 2, 201, 2, 82, 231, 192, 70, 66, 28, 48, 240, 0, 249, 162,
|
||||
28, 2, 30, 83, 65, 154, 231, 78, 70, 192, 19, 119, 240, 0, 19, 119, 234, 32, 127, 255, 255, 255, 19, 119, 233, 160,
|
||||
255, 255, 128, 0, 0, 5, 49, 0, 181, 240, 70, 87, 70, 78, 70, 69, 180, 224, 70, 128, 28, 14, 70, 148, 42, 0, 208, 51,
|
||||
33, 3, 28, 2, 64, 10, 35, 4, 26, 155, 28, 24, 64, 8, 69, 96, 216, 49, 40, 0, 208, 49, 36, 0, 70, 67, 85, 30, 52, 1,
|
||||
66, 160, 216, 250, 69, 132, 208, 32, 70, 99, 26, 27, 8, 159, 70, 153, 0, 187, 70, 154, 43, 0, 208, 17, 4, 51, 6, 50,
|
||||
2, 49, 67, 26, 67, 10, 28, 21, 70, 67, 67, 53, 24, 26, 33, 0, 0, 139, 49, 1, 80, 213, 66, 185, 211, 250, 68, 84, 69,
|
||||
209, 208, 6, 70, 67, 25, 24, 52, 1, 112, 6, 48, 1, 69, 164, 216, 250, 188, 28, 70, 144, 70, 153, 70, 162, 188, 240,
|
||||
188, 1, 71, 0, 70, 96, 231, 203, 36, 0, 231, 211, 70, 192, 181, 112, 76, 17, 28, 6, 104, 32, 176, 130, 28, 13, 98, 2,
|
||||
97, 6, 100, 1, 97, 65, 33, 68, 247, 255, 252, 121, 28, 48, 28, 41, 247, 255, 252, 117, 75, 10, 34, 2, 104, 24, 104,
|
||||
35, 73, 9, 147, 0, 35, 1, 247, 255, 252, 128, 28, 41, 28, 4, 28, 48, 247, 255, 252, 119, 176, 2, 28, 32, 188, 112, 188,
|
||||
2, 71, 8, 19, 119, 240, 44, 19, 119, 240, 48, 87, 70, 83, 2, 181, 240, 176, 133, 28, 4, 28, 15, 146, 3, 40, 2, 216,
|
||||
75, 77, 47, 104, 43, 43, 0, 208, 74, 78, 46, 104, 48, 40, 0, 219, 1, 247, 255, 252, 71, 74, 44, 0, 163, 88, 152, 33,
|
||||
1, 247, 255, 252, 81, 96, 48, 40, 0, 219, 66, 104, 48, 40, 0, 219, 49, 104, 40, 28, 57, 34, 6, 48, 32, 247, 255, 252,
|
||||
61, 104, 40, 169, 3, 34, 4, 48, 64, 247, 255, 252, 55, 104, 42, 36, 4, 28, 19, 51, 32, 96, 19, 104, 42, 35, 6, 96, 83,
|
||||
104, 42, 33, 68, 28, 19, 51, 64, 96, 147, 104, 43, 96, 220, 104, 40, 247, 255, 252, 33, 104, 43, 104, 48, 34, 2, 147,
|
||||
0, 73, 22, 35, 0, 247, 255, 252, 45, 104, 42, 28, 19, 51, 32, 96, 19, 104, 43, 96, 92, 104, 42, 28, 19, 51, 64, 96,
|
||||
147, 104, 43, 96, 220, 176, 5, 188, 240, 188, 2, 71, 8, 32, 1, 66, 64, 231, 248, 75, 11, 78, 8, 96, 43, 35, 1, 66, 91,
|
||||
96, 51, 231, 179, 44, 0, 209, 186, 72, 8, 33, 1, 247, 255, 252, 5, 96, 48, 231, 180, 70, 192, 19, 119, 240, 44, 19,
|
||||
119, 240, 48, 19, 119, 236, 140, 87, 70, 83, 1, 19, 119, 240, 64, 19, 119, 236, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 233, 45, 64, 128, 229, 159, 113, 80, 229, 151, 112, 0, 235, 0, 0, 45, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45,
|
||||
64, 128, 229, 159, 113, 60, 229, 151, 112, 0, 235, 0, 0, 39, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128,
|
||||
229, 159, 113, 40, 229, 151, 112, 0, 235, 0, 0, 33, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159,
|
||||
113, 20, 229, 151, 112, 0, 235, 0, 0, 27, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159, 113, 0, 229,
|
||||
151, 112, 0, 235, 0, 0, 21, 232, 189, 64, 128, 225, 47, 255, 30, 233, 45, 64, 128, 229, 159, 112, 236, 229, 151, 112,
|
||||
0, 235, 0, 0, 15, 232, 189, 64, 128, 225, 47, 255, 30, 230, 0, 8, 16, 225, 47, 255, 30, 230, 0, 7, 240, 225, 47, 255,
|
||||
30, 230, 0, 3, 144, 225, 47, 255, 30, 230, 0, 3, 176, 225, 47, 255, 30, 230, 0, 3, 208, 225, 47, 255, 30, 230, 0, 3,
|
||||
240, 225, 47, 255, 30, 230, 0, 4, 80, 225, 47, 255, 30, 225, 47, 255, 23, 239, 0, 0, 204, 225, 47, 255, 30, 180, 124,
|
||||
181, 0, 247, 255, 252, 254, 188, 2, 188, 124, 71, 8, 181, 112, 176, 136, 104, 133, 28, 1, 75, 34, 71, 24, 70, 192, 70,
|
||||
192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 70, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 114, 28, 1, 32, 4, 223, 171, 71, 16, 181, 240, 70, 95, 70, 86, 70, 77, 70, 68, 180, 240,
|
||||
75, 8, 104, 27, 71, 24, 19, 119, 224, 16, 19, 119, 224, 20, 19, 119, 224, 24, 19, 119, 224, 28, 19, 119, 224, 32, 19,
|
||||
119, 224, 36, 32, 16, 0, 213, 19, 119, 224, 12, 70, 192, 70, 192, 19, 119, 229, 58, 19, 119, 229, 108, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
19, 119, 228, 202, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 229, 34, 19, 119, 228,
|
||||
120, 19, 119, 229, 84, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 229, 44, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 230, 58, 19, 119, 228, 120, 19, 119, 229, 220, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 230, 24, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 229, 142, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 229, 44,
|
||||
19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 184, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 230,
|
||||
102, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 230, 24, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
19, 119, 228, 196, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 229, 44, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 229, 158, 19, 119, 228, 120,
|
||||
19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 158, 19,
|
||||
119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 230, 14, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
230, 24, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 230, 70, 19, 119, 229, 170, 19, 119, 228, 120, 19, 119, 228, 120,
|
||||
19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 158, 19, 119, 228, 120, 19, 119, 228, 120, 19,
|
||||
119, 228, 120, 19, 119, 228, 212, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228,
|
||||
120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 230, 6, 19, 119, 230, 2, 19, 119, 229, 250, 19, 119, 229, 246, 19,
|
||||
119, 229, 230, 19, 119, 229, 214, 19, 119, 229, 204, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 229, 190, 47, 100, 101,
|
||||
118, 47, 117, 115, 98, 47, 101, 104, 99, 0, 0, 0, 0, 47, 100, 101, 118, 47, 117, 115, 98, 50, 0, 0, 0, 47, 100, 101,
|
||||
118, 47, 115, 100, 105, 111, 47, 115, 100, 104, 99, 0, 0, 19, 119, 235, 224, 19, 119, 235, 236, 19, 119, 235, 208
|
||||
120, 19, 119, 228, 246, 19, 119, 228, 254, 19, 119, 229, 2, 19, 119, 229, 10, 19, 119, 229, 14, 19, 119, 229, 44, 19,
|
||||
119, 229, 48, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119,
|
||||
228, 120, 19, 119, 228, 120, 19, 119, 228, 120, 19, 119, 229, 156, 47, 100, 101, 118, 47, 117, 115, 98, 47, 101, 104,
|
||||
99, 0, 0, 0, 0, 47, 100, 101, 118, 47, 117, 115, 98, 50, 0, 0, 0, 47, 100, 101, 118, 47, 115, 100, 105, 111, 47, 115,
|
||||
100, 104, 99, 0, 0, 19, 119, 236, 112, 19, 119, 236, 124, 19, 119, 236, 96
|
||||
};
|
||||
|
@ -1,3 +1,3 @@
|
||||
#define size_dip_plugin 3080
|
||||
#define size_dip_plugin 3224
|
||||
|
||||
extern unsigned char dip_plugin[3080];
|
||||
extern unsigned char dip_plugin[3224];
|
||||
|
@ -612,7 +612,6 @@ return 0;
|
||||
|
||||
|
||||
int patch_cios_data() {
|
||||
|
||||
patch_datas[0]=*((u32 *) (dip_plugin+16*4));
|
||||
mload_set_ES_ioctlv_vector((void *) patch_datas[0]);
|
||||
return 1;
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include "dvd_broadway.h"
|
||||
#include "wpad.h"
|
||||
#include "fatmounter.h"
|
||||
#include "sys.h"
|
||||
#include "mload/mload.h"
|
||||
#include "mload/dip_plugin.h"
|
||||
|
||||
extern struct SSettings Settings;
|
||||
|
||||
@ -95,4 +98,61 @@ u32 do_sd_code(char *filename)
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 do_bca_code(u8 *gameid)
|
||||
{
|
||||
if (IOS_GetVersion() == 222 || IOS_GetVersion() == 223)
|
||||
{
|
||||
FILE *fp;
|
||||
u32 filesize;
|
||||
char filepath[150];
|
||||
memset(filepath, 0, 150);
|
||||
u8 bcaCode[64] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
sprintf(filepath, "%s%6s", Settings.BcaCodepath, gameid);
|
||||
filepath[strlen(Settings.BcaCodepath)+6] = '.';
|
||||
filepath[strlen(Settings.BcaCodepath)+7] = 'b';
|
||||
filepath[strlen(Settings.BcaCodepath)+8] = 'c';
|
||||
filepath[strlen(Settings.BcaCodepath)+9] = 'a';
|
||||
|
||||
fp = fopen(filepath, "rb");
|
||||
if (!fp) {
|
||||
memset(filepath, 0, 150);
|
||||
sprintf(filepath, "%s%3s", Settings.BcaCodepath, gameid + 1);
|
||||
filepath[strlen(Settings.BcaCodepath)+3] = '.';
|
||||
filepath[strlen(Settings.BcaCodepath)+4] = 'b';
|
||||
filepath[strlen(Settings.BcaCodepath)+5] = 'c';
|
||||
filepath[strlen(Settings.BcaCodepath)+6] = 'a';
|
||||
fp = fopen(filepath, "rb");
|
||||
|
||||
if (!fp) {
|
||||
// Set default bcaCode
|
||||
memset(bcaCode, 0, 64);
|
||||
bcaCode[0x33] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
u32 ret = 0;
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
filesize = ftell(fp);
|
||||
|
||||
if (filesize == 64) {
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
ret = fread(bcaCode, 1, 64, fp);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (ret != 64) {
|
||||
// Set default bcaCode
|
||||
memset(bcaCode, 0, 64);
|
||||
bcaCode[0x33] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mload_seek(*((u32 *) (dip_plugin+15*4)), SEEK_SET); // offset 15 (bca_data area)
|
||||
mload_write(bcaCode, 64);
|
||||
mload_close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ extern "C"
|
||||
|
||||
//u32 do_fst(u32 fstlocation);
|
||||
u32 do_sd_code(char *filename);
|
||||
u32 do_bca_code(u8 *gameid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -172,32 +172,6 @@ void dogamehooks(void *addr, u32 len)
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
case 2:
|
||||
if(memcmp(addr_start, kpadhooks, sizeof(kpadhooks))==0){
|
||||
patchhook((u32)addr_start, len);
|
||||
patched = 1;
|
||||
}
|
||||
|
||||
if(memcmp(addr_start, kpadoldhooks, sizeof(kpadoldhooks))==0){
|
||||
patchhook((u32)addr_start, len);
|
||||
patched = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(memcmp(addr_start, joypadhooks, sizeof(joypadhooks))==0){
|
||||
patchhook((u32)addr_start, len);
|
||||
patched = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if(memcmp(addr_start, recoveryhooks, sizeof(recoveryhooks))==0){
|
||||
patchhook3((u32)addr_start, len);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case 2:
|
||||
|
||||
if(memcmp(addr_start, viwiihooks, sizeof(viwiihooks))==0){
|
||||
@ -206,69 +180,6 @@ void dogamehooks(void *addr, u32 len)
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
case 6:
|
||||
// jap region free
|
||||
if(memcmp(addr_start, regionfreehooks, sizeof(regionfreehooks))==0){
|
||||
regionfreejap((u32)addr_start, len);
|
||||
}
|
||||
|
||||
// usa region free
|
||||
if(memcmp(addr_start, regionfreehooks, sizeof(regionfreehooks))==0){
|
||||
regionfreeusa((u32)addr_start, len);
|
||||
}
|
||||
|
||||
// pal region free
|
||||
if(memcmp(addr_start, regionfreehooks, sizeof(regionfreehooks))==0){
|
||||
regionfreepal((u32)addr_start, len);
|
||||
}
|
||||
|
||||
// skip disc update
|
||||
if(memcmp(addr_start, updatecheckhook, sizeof(updatecheckhook))==0){
|
||||
patchupdatecheck((u32)addr_start, len);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 7:
|
||||
if(memcmp(addr_start, healthcheckhook, sizeof(healthcheckhook))==0){
|
||||
removehealthcheck((u32)addr_start, len);
|
||||
}
|
||||
break;
|
||||
|
||||
// no copy flags
|
||||
case 8:
|
||||
// Remove the actual flag so can copy back
|
||||
if(memcmp(addr_start, nocopyflag5, sizeof(nocopyflag5))==0){
|
||||
copyflagcheck5((u32)addr_start, len);
|
||||
}
|
||||
|
||||
|
||||
if(memcmp(addr_start, nocopyflag1, sizeof(nocopyflag1))==0){
|
||||
copyflagcheck1((u32)addr_start, len);
|
||||
}
|
||||
|
||||
if(memcmp(addr_start, nocopyflag2, sizeof(nocopyflag2))==0){
|
||||
copyflagcheck2((u32)addr_start, len);
|
||||
}
|
||||
|
||||
// no VC and GH3 save
|
||||
if(memcmp(addr_start, nocopyflag3, sizeof(nocopyflag2))==0){
|
||||
copyflagcheck3((u32)addr_start, len);
|
||||
}
|
||||
// no VC and GH3 save display remove
|
||||
if(memcmp(addr_start, nocopyflag4, sizeof(nocopyflag4))==0){
|
||||
copyflagcheck4((u32)addr_start, len);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 9:
|
||||
if(memcmp(addr_start, movedvdpatch, sizeof(movedvdpatch))==0){
|
||||
movedvdhooks((u32)addr_start, len);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
// multidol
|
||||
case 3:
|
||||
|
||||
@ -355,5 +266,3 @@ void vidolpatcher(void *addr, u32 len)
|
||||
addr_start += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -181,7 +181,7 @@ void WindowCredits() {
|
||||
starImg.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
starImg.SetPosition(505,350);
|
||||
|
||||
int numEntries = 20;
|
||||
int numEntries = 21;
|
||||
GuiText * txt[numEntries];
|
||||
|
||||
txt[i] = new GuiText(tr("Credits"), 26, (GXColor) {255, 255, 255, 255});
|
||||
@ -216,16 +216,16 @@ void WindowCredits() {
|
||||
i++;
|
||||
y+=26;
|
||||
|
||||
txt[i] = new GuiText(" http://code.google.com/p/usbloader-gui/", 20, (GXColor) {255, 255, 255, 255});
|
||||
txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
||||
txt[i]->SetPosition(50,y);
|
||||
i++; //y+=28;
|
||||
|
||||
txt[i] = new GuiText(tr("Official Site:"), 20, (GXColor) {255, 255, 255, 255});
|
||||
txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
||||
txt[i]->SetPosition(-180,y);
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
txt[i]->SetPosition(10,y);
|
||||
i++;
|
||||
y+=28;
|
||||
|
||||
txt[i] = new GuiText("http://code.google.com/p/usbloader-gui/", 20, (GXColor) {255, 255, 255, 255});
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
txt[i]->SetPosition(160,y);
|
||||
i++;
|
||||
y+=26;
|
||||
|
||||
GuiText::SetPresets(22, (GXColor) {255, 255, 255, 255}, 0, GuiText::WRAP,FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP);
|
||||
|
||||
@ -244,7 +244,7 @@ void WindowCredits() {
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
txt[i]->SetPosition(160,y);
|
||||
i++;
|
||||
y+=34;
|
||||
y+=26;
|
||||
|
||||
char text[100];
|
||||
|
||||
@ -257,7 +257,7 @@ void WindowCredits() {
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
txt[i]->SetPosition(160,y);
|
||||
i++;
|
||||
y+=34;
|
||||
y+=26;
|
||||
|
||||
txt[i] = new GuiText(tr("Big thanks to:"));
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
@ -290,7 +290,7 @@ void WindowCredits() {
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
txt[i]->SetPosition(160,y);
|
||||
i++;
|
||||
y+=22;
|
||||
y+=26;
|
||||
|
||||
txt[i] = new GuiText(tr("Special thanks to:"));
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
@ -326,6 +326,13 @@ void WindowCredits() {
|
||||
i++;
|
||||
y+=22;
|
||||
|
||||
sprintf(text, "Oggzee %s", tr("for FAT support"));
|
||||
txt[i] = new GuiText(text);
|
||||
txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
||||
txt[i]->SetPosition(60,y);
|
||||
i++;
|
||||
y+=22;
|
||||
|
||||
for (i=0; i < numEntries; i++)
|
||||
creditsWindowBox.Append(txt[i]);
|
||||
|
||||
|
@ -46,12 +46,12 @@ static const char *opts_no_yes[settings_off_on_max] = {trNOOP("No"),trNOOP("Yes"
|
||||
static const char *opts_off_on[settings_off_on_max] = {trNOOP("OFF"),trNOOP("ON") };
|
||||
static const char *opts_videomode[settings_language_max][2] = {{"",trNOOP("Disc Default")},{trNOOP("System Default"),""},{trNOOP("AutoPatch"),""},{trNOOP("Force"), " PAL50"},{trNOOP("Force")," PAL60"},{trNOOP("Force")," NTSC"}};
|
||||
static const char *opts_language[settings_language_max] = {trNOOP("Console Default"),trNOOP("Japanese"),trNOOP("English"),trNOOP("German"),trNOOP("French"),trNOOP("Spanish"),trNOOP("Italian"),trNOOP("Dutch"),trNOOP("SChinese"),trNOOP("TChinese"),trNOOP("Korean")};
|
||||
static const char *opts_cios[settings_ios_max] = {"IOS 249","IOS 222", "IOS 223"};
|
||||
static const char *opts_cios[settings_ios_max] = {"IOS 249","IOS 222", "IOS 223", "IOS 250"};
|
||||
static const char *opts_parentalcontrol[5] = {trNOOP("0 (Everyone)"),trNOOP("1 (Child 7+)"),trNOOP("2 (Teen 12+)"),trNOOP("3 (Mature 16+)"),trNOOP("4 (Adults Only 18+)")};
|
||||
static const char *opts_error002[settings_error002_max] = {trNOOP("No"),trNOOP("Yes"),trNOOP("Anti")};
|
||||
|
||||
bool IsValidPartition(int fs_type, int cios) {
|
||||
if (cios == 249) {
|
||||
if (cios == 249 || cios == 250) {
|
||||
return fs_type == FS_TYPE_WBFS;
|
||||
} else {
|
||||
return fs_type == FS_TYPE_WBFS || fs_type == FS_TYPE_FAT32;
|
||||
@ -992,7 +992,7 @@ int MenuSettings()
|
||||
if (++Settings.cios >= settings_cios_max) {
|
||||
Settings.cios = 0;
|
||||
}
|
||||
if (Settings.cios != 0 && ios222rev!=4) {
|
||||
if ((Settings.cios == 1 && ios222rev!=4) || (Settings.cios == 2 && ios223rev != 4)) {
|
||||
WindowPrompt(tr("Hermes CIOS"),tr("USB Loader GX will only run with Hermes CIOS rev 4! Please make sure you have revision 4 installed!"),tr("OK"));
|
||||
}
|
||||
}
|
||||
@ -1022,6 +1022,15 @@ int MenuSettings()
|
||||
pInfo.fs_type == FS_TYPE_FAT32 ? pInfo.fat_i : pInfo.wbfs_i,
|
||||
partition_size);
|
||||
}
|
||||
|
||||
if (ret == ++Idx || firstRun)
|
||||
{
|
||||
if (firstRun) options2.SetName(Idx, "%s", tr("FAT: Use directories"));
|
||||
if (ret == Idx) {
|
||||
Settings.FatInstallToDir = Settings.FatInstallToDir == 0 ? 1 : 0;
|
||||
}
|
||||
options2.SetValue(Idx, "%s", tr(opts_no_yes[Settings.FatInstallToDir]));
|
||||
}
|
||||
|
||||
if(ret == ++Idx || firstRun)
|
||||
{
|
||||
@ -1824,6 +1833,34 @@ int MenuSettings()
|
||||
options2.SetValue(Idx, "%s", Settings.theme_downloadpath);
|
||||
}
|
||||
|
||||
if(ret == ++Idx || firstRun)
|
||||
{
|
||||
if(firstRun) options2.SetName(Idx, "%s", tr("BCA Codes Path"));
|
||||
if(ret == Idx)
|
||||
{
|
||||
w.Remove(&optionBrowser2);
|
||||
w.Remove(&backBtn);
|
||||
char entered[100] = "";
|
||||
strlcpy(entered, Settings.BcaCodepath, sizeof(entered));
|
||||
titleTxt.SetText(tr("BCA Codes Path"));
|
||||
int result = BrowseDevice(entered, sizeof(entered), FB_DEFAULT, noFILES);
|
||||
titleTxt.SetText(tr("Custom Paths"));
|
||||
w.Append(&optionBrowser2);
|
||||
w.Append(&backBtn);
|
||||
if ( result == 1 )
|
||||
{
|
||||
int len = (strlen(entered)-1);
|
||||
if (entered[len] !='/')
|
||||
strncat (entered, "/", 1);
|
||||
strlcpy(Settings.BcaCodepath, entered, sizeof(Settings.BcaCodepath));
|
||||
WindowPrompt(tr("BCA Codes Path changed"),0,tr("OK"));
|
||||
if (!isInserted(bootDevice))
|
||||
WindowPrompt(tr("No SD-Card inserted!"),tr("Insert an SD-Card to save."),tr("OK"));
|
||||
}
|
||||
}
|
||||
options2.SetValue(Idx, "%s", Settings.BcaCodepath);
|
||||
}
|
||||
|
||||
firstRun = false;
|
||||
}
|
||||
}
|
||||
@ -2330,8 +2367,12 @@ int GameSettings(struct discHdr * header)
|
||||
viChoice = Settings.vpatch;
|
||||
if (Settings.cios == ios222)
|
||||
iosChoice = i222;
|
||||
else
|
||||
iosChoice = i249;
|
||||
else if (Settings.cios == 250)
|
||||
iosChoice = i250;
|
||||
else if (Settings.cios == ios223)
|
||||
iosChoice = i223;
|
||||
else
|
||||
iosChoice = 249;
|
||||
parentalcontrolChoice = 0;
|
||||
fix002 = Settings.error002;
|
||||
countrystrings = Settings.patchcountrystrings;
|
||||
@ -2847,6 +2888,10 @@ int GameSettings(struct discHdr * header)
|
||||
reloadblock = off;
|
||||
if (Settings.cios == ios222)
|
||||
iosChoice = i222;
|
||||
else if (Settings.cios == ios250)
|
||||
iosChoice = i250;
|
||||
else if (Settings.cios == ios223)
|
||||
iosChoice = i223;
|
||||
else
|
||||
iosChoice = i249;
|
||||
parentalcontrolChoice = 0;
|
||||
|
@ -201,6 +201,7 @@ void CFG_Default(int widescreen) { // -1 = non forced Mode
|
||||
snprintf(Settings.homebrewapps_path, sizeof(Settings.homebrewapps_path), "%s/apps/", bootDevice);
|
||||
snprintf(Settings.Cheatcodespath, sizeof(Settings.Cheatcodespath), "%s/codes/", bootDevice);
|
||||
snprintf(Settings.TxtCheatcodespath, sizeof(Settings.TxtCheatcodespath), "%s/txtcodes/", bootDevice);
|
||||
snprintf(Settings.BcaCodepath, sizeof(Settings.BcaCodepath), "%s/bca/", bootDevice);
|
||||
snprintf(Settings.dolpath, sizeof(Settings.dolpath), "%s/", bootDevice);
|
||||
sprintf(Settings.ogg_path, "notset");
|
||||
}
|
||||
@ -355,6 +356,7 @@ void Global_Default(void) {
|
||||
Settings.screensaver = 3;
|
||||
Settings.partition = -1;
|
||||
Settings.marknewtitles = 1;
|
||||
Settings.FatInstallToDir = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -532,6 +534,10 @@ void path_set(char *name, char *val) {
|
||||
strlcpy(Settings.ogg_path, val, sizeof(Settings.ogg_path));
|
||||
return;
|
||||
}
|
||||
if (strcmp(name, "BcaCodepath") == 0) {
|
||||
strlcpy(Settings.BcaCodepath, val, sizeof(Settings.BcaCodepath));
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@ -1049,6 +1055,11 @@ void global_cfg_set(char *name, char *val) {
|
||||
Settings.marknewtitles = i;
|
||||
}
|
||||
return;
|
||||
} else if (strcmp(name, "fatInstallToDir") == 0) {
|
||||
int i;
|
||||
if (sscanf(val, "%d", &i) == 1) {
|
||||
Settings.FatInstallToDir = i;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_bool("godmode", &Settings.godmode);
|
||||
@ -1283,6 +1294,7 @@ bool cfg_save_global() { // save global settings
|
||||
fprintf(f, "theme_downloadpath = %s\n ", Settings.theme_downloadpath);
|
||||
fprintf(f, "homebrewapps_path = %s\n ", Settings.homebrewapps_path);
|
||||
fprintf(f, "Cheatcodespath = %s\n ", Settings.Cheatcodespath);
|
||||
fprintf(f, "BcaCodepath = %s\n", Settings.BcaCodepath);
|
||||
fprintf(f, "titlesOverride = %d\n ", Settings.titlesOverride);
|
||||
//fprintf(f, "db_url = %s\n ", Settings.db_url);
|
||||
//fprintf(f, "db_JPtoEN = %d\n ", Settings.db_JPtoEN);
|
||||
@ -1294,6 +1306,7 @@ bool cfg_save_global() { // save global settings
|
||||
fprintf(f, "discart = %d\n ", Settings.discart);
|
||||
fprintf(f, "partition = %d\n", Settings.partition);
|
||||
fprintf(f, "marknewtitles = %d\n", Settings.marknewtitles);
|
||||
fprintf(f, "fatInstallToDir = %d\n", Settings.FatInstallToDir);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
@ -298,12 +298,15 @@ extern "C" {
|
||||
i249=0,
|
||||
i222,
|
||||
i223,
|
||||
i250,
|
||||
settings_ios_max // always the last entry
|
||||
};
|
||||
|
||||
enum {
|
||||
ios249=0,
|
||||
ios222,
|
||||
ios223,
|
||||
ios250,
|
||||
settings_cios_max // always the last entry
|
||||
};
|
||||
|
||||
@ -422,6 +425,8 @@ extern "C" {
|
||||
u8 discart;
|
||||
short gamesound;
|
||||
u8 marknewtitles;
|
||||
char BcaCodepath[100];
|
||||
u8 FatInstallToDir;
|
||||
};
|
||||
extern struct SSettings Settings;
|
||||
|
||||
|
@ -78,6 +78,35 @@ NewTitles::~NewTitles()
|
||||
firstTitle = lastTitle = NULL;
|
||||
}
|
||||
|
||||
void NewTitles::CheckGame(u8 *titleid)
|
||||
{
|
||||
Title *t = firstTitle;
|
||||
while (t != NULL) {
|
||||
// Loop all titles, search for the correct titleid
|
||||
if (strcmp((const char *) titleid, (const char *) t->titleId) == 0) {
|
||||
return; // Game found, which is excellent
|
||||
}
|
||||
t = (Title *) t->next;
|
||||
}
|
||||
|
||||
// Not found, add it
|
||||
t = new Title();
|
||||
strncpy((char *) t->titleId, (char *) titleid, 6);
|
||||
t->timestamp = time(NULL);
|
||||
if (isNewFile) {
|
||||
t->timestamp -= (NEW_SECONDS + 1); // Mark all games as not new if this is a new file
|
||||
}
|
||||
|
||||
if (firstTitle == NULL) {
|
||||
firstTitle = t;
|
||||
lastTitle = t;
|
||||
} else {
|
||||
lastTitle -> next = t;
|
||||
lastTitle = t;
|
||||
}
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
bool NewTitles::IsNew(u8 *titleid)
|
||||
{
|
||||
Title *t = firstTitle;
|
||||
@ -95,23 +124,8 @@ bool NewTitles::IsNew(u8 *titleid)
|
||||
}
|
||||
t = (Title *) t->next;
|
||||
}
|
||||
|
||||
// Not found, add it
|
||||
t = new Title();
|
||||
strncpy((char *) t->titleId, (char *) titleid, 6);
|
||||
t->timestamp = time(NULL);
|
||||
if (isNewFile) {
|
||||
t->timestamp -= (NEW_SECONDS + 1); // Mark all games as not new if this is a new file
|
||||
}
|
||||
|
||||
if (firstTitle == NULL) {
|
||||
firstTitle = t;
|
||||
lastTitle = t;
|
||||
} else {
|
||||
lastTitle -> next = t;
|
||||
lastTitle = t;
|
||||
}
|
||||
isDirty = true;
|
||||
// We should never get here, since all files should be added by now!
|
||||
CheckGame(titleid);
|
||||
|
||||
return !isNewFile; // If this is a new file, return false
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ public:
|
||||
static void DestroyInstance();
|
||||
|
||||
void Save();
|
||||
void CheckGame(u8 *titleid);
|
||||
bool IsNew(u8 *titleid);
|
||||
void Remove(u8 *titleid);
|
||||
private:
|
||||
|
@ -207,11 +207,22 @@ bool Sys_IsHermes() {
|
||||
return IOS_GetVersion() == 222 || IOS_GetVersion() == 223;
|
||||
}
|
||||
|
||||
#include "Prompts/PromptWindows.h"
|
||||
|
||||
void ShowMemInfo() {
|
||||
char buf[255];
|
||||
struct mallinfo mymallinfo = mallinfo();
|
||||
sprintf((char *) &buf,"Total: %d, Used: %d, Can be freed: %d", mymallinfo.arena/1024, mymallinfo.uordblks/1024, mymallinfo.keepcost/1024);
|
||||
WindowPrompt("Mem info", (char *) &buf, "OK");
|
||||
}
|
||||
|
||||
|
||||
#include "wad/title.h"
|
||||
|
||||
s32 ios222rev = -69;
|
||||
s32 ios223rev = -69;
|
||||
s32 ios249rev = -69;
|
||||
s32 ios250rev = -69;
|
||||
|
||||
s32 IOS_ReloadIOSsafe(int ios)
|
||||
{
|
||||
@ -219,20 +230,31 @@ s32 IOS_ReloadIOSsafe(int ios)
|
||||
{
|
||||
if (ios222rev == -69)
|
||||
ios222rev = getIOSrev(0x00000001000000dell);
|
||||
|
||||
|
||||
if (ios222rev != 4)return -2;
|
||||
if (ios222rev >= 0 && ios222rev != 4)return -2;
|
||||
}
|
||||
else if (ios==223)
|
||||
{
|
||||
if (ios223rev == -69)
|
||||
ios223rev = getIOSrev(0x00000001000000dfll);
|
||||
|
||||
if (ios223rev >= 0 && ios223rev != 4)return -2;
|
||||
}
|
||||
else if (ios==249)
|
||||
{
|
||||
if (ios249rev == -69)
|
||||
ios249rev = getIOSrev(0x00000001000000f9ll);
|
||||
|
||||
ios249rev = getIOSrev(0x00000001000000f9ll);
|
||||
|
||||
if (!(ios249rev>=9 && ios249rev<65535))return -2;
|
||||
if (ios249rev >= 0 && !(ios249rev>=9 && ios249rev<65280))return -2;
|
||||
}
|
||||
else if (ios==250)
|
||||
{
|
||||
if (ios250rev == -69)
|
||||
ios250rev = getIOSrev(0x00000001000000fall);
|
||||
|
||||
if (ios250rev >= 0 && !(ios250rev>=9 && ios250rev<65280))return -2;
|
||||
}
|
||||
|
||||
return IOS_ReloadIOS(ios);
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,11 @@ int Sys_IosReload(int IOS);
|
||||
bool Sys_IsHermes();
|
||||
s32 IOS_ReloadIOSsafe(int ios);
|
||||
|
||||
void ShowMemInfo();
|
||||
extern s32 ios222rev;
|
||||
extern s32 ios223rev;
|
||||
extern s32 ios249rev;
|
||||
extern s32 ios250rev;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -256,6 +256,8 @@ void PretendThereIsADiscInTheDrive(void *buffer, u32 len)
|
||||
/** Thanks to WiiPower **/
|
||||
bool NewSuperMarioBrosPatch(void *Address, int Size)
|
||||
{
|
||||
if (IOS_GetVersion() == 222 || IOS_GetVersion() == 223) return false; // Don't use this when using Hermes, it'll use the BCA fix instead...
|
||||
|
||||
if (memcmp("SMNE", (char *)0x80000000, 4) == 0)
|
||||
{
|
||||
u8 SearchPattern[32] = { 0x94, 0x21, 0xFF, 0xD0, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x34, 0x39, 0x61, 0x00, 0x30, 0x48, 0x12, 0xD7, 0x89, 0x7C, 0x7B, 0x1B, 0x78, 0x7C, 0x9C, 0x23, 0x78, 0x7C, 0xBD, 0x2B, 0x78 };
|
||||
@ -387,7 +389,8 @@ s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8
|
||||
|
||||
if (error002fix!=0) {
|
||||
/* ERROR 002 fix (thanks to WiiPower for sharing this)*/
|
||||
*(u32 *)0x80003140 = *(u32 *)0x80003188;
|
||||
*(u32 *)0x80003188 = *(u32 *)0x80003140;
|
||||
// *(u32 *)0x80003140 = *(u32 *)0x80003188;
|
||||
}
|
||||
|
||||
if (cheat || geckoinit) {
|
||||
|
@ -19,8 +19,7 @@ extern "C" {
|
||||
u8 bufsize;
|
||||
|
||||
/* Padding */
|
||||
u8 isNew; // Use space from the padding below
|
||||
u8 unused1[13];
|
||||
u8 unused1[14];
|
||||
|
||||
/* Magic word */
|
||||
u32 magic;
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <vector>
|
||||
#include <wchar.h>
|
||||
|
||||
|
||||
#include "listfiles.h"
|
||||
#define typei 0x00010001
|
||||
|
||||
@ -163,8 +162,8 @@ int __Menu_GetPrevFilter(int t, wchar_t* gameFilter, u32 gameFiltered, wchar_t *
|
||||
{
|
||||
struct discHdr *header = &buffer[i];
|
||||
|
||||
/* Is new? */
|
||||
header->isNew = NewTitles::Instance()->IsNew(header->id);
|
||||
/* Register game */
|
||||
NewTitles::Instance()->CheckGame(header->id);
|
||||
|
||||
/* Filter Favorite */
|
||||
if (Settings.fave && t==0)
|
||||
@ -479,8 +478,8 @@ int __Menu_GetGameList(int t, wchar_t* gameFilter, discHdr ** PgameList, u32 *Pg
|
||||
for (u32 i = 0; i < cnt; i++) {
|
||||
struct discHdr *header = &buffer[i];
|
||||
|
||||
/* Is new? */
|
||||
header->isNew = NewTitles::Instance()->IsNew(header->id);
|
||||
/* Register game */
|
||||
NewTitles::Instance()->CheckGame(header->id);
|
||||
|
||||
/* Filters */
|
||||
if (Settings.fave && t==0) {
|
||||
@ -515,7 +514,7 @@ int __Menu_GetGameList(int t, wchar_t* gameFilter, discHdr ** PgameList, u32 *Pg
|
||||
}
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
|
||||
if (Settings.sort==pcount) {
|
||||
qsort(buffer, cnt, sizeof(struct discHdr), __Menu_EntryCmpCount);
|
||||
} else if (Settings.fave) {
|
||||
@ -547,6 +546,7 @@ int __Menu_GetEntries(int t, const wchar_t* Filter) {
|
||||
|
||||
new_gameFilter = wcsdup_new(Filter ? Filter : (gameFilter ? gameFilter : L"") );
|
||||
if(new_gameFilter == NULL) return -1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (mountMethod==3)
|
||||
@ -562,6 +562,7 @@ int __Menu_GetEntries(int t, const wchar_t* Filter) {
|
||||
break;
|
||||
new_gameFilter[wcslen(new_gameFilter)-1] = 0;
|
||||
}
|
||||
|
||||
/* init GameFilterNextList */
|
||||
if(__Menu_GetGameFilter_NextList(new_gameList, new_gameCnt, &new_gameFilter, &new_gameFilterNextList) < 0)
|
||||
goto error;
|
||||
|
@ -1,57 +1,123 @@
|
||||
// Modified by oggzee
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ogcsys.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "partition_usbloader.h"
|
||||
#include "usbstorage.h"
|
||||
#include "sdhc.h"
|
||||
#include "usbstorage.h"
|
||||
#include "utils.h"
|
||||
#include "libwbfs/libwbfs.h"
|
||||
#include "wbfs.h"
|
||||
#include "libwbfs/libwbfs.h"
|
||||
|
||||
/* 'partition table' structure */
|
||||
typedef struct {
|
||||
/* Zero bytes */
|
||||
u8 padding[446];
|
||||
/* Zero bytes */
|
||||
u8 padding[446];
|
||||
|
||||
/* Partition table entries */
|
||||
partitionEntry entries[MAX_PARTITIONS];
|
||||
/* Partition table entries */
|
||||
partitionEntry entries[MAX_PARTITIONS];
|
||||
} ATTRIBUTE_PACKED partitionTable;
|
||||
|
||||
s32 Partition_GetEntries(partitionEntry *outbuf, u32 *outval) {
|
||||
static partitionTable table ATTRIBUTE_ALIGN(32);
|
||||
|
||||
u32 cnt, sector_size;
|
||||
s32 ret;
|
||||
s32 Partition_GetEntries(u32 device, partitionEntry *outbuf, u32 *outval)
|
||||
{
|
||||
static partitionTable table ATTRIBUTE_ALIGN(32);
|
||||
|
||||
/* Get sector size */
|
||||
ret = USBStorage_GetCapacity(§or_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
u32 cnt, sector_size;
|
||||
s32 ret;
|
||||
|
||||
/* Read partition table */
|
||||
ret = USBStorage_ReadSectors(0, 1, &table);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Read from specified device */
|
||||
switch (device) {
|
||||
case WBFS_DEVICE_USB: {
|
||||
/* Get sector size */
|
||||
ret = USBStorage_GetCapacity(§or_size);
|
||||
if (ret == 0)
|
||||
return -1;
|
||||
|
||||
/* Swap endianess */
|
||||
for (cnt = 0; cnt < 4; cnt++) {
|
||||
partitionEntry *entry = &table.entries[cnt];
|
||||
/* Read partition table */
|
||||
ret = USBStorage_ReadSectors(0, 1, &table);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
entry->sector = swap32(entry->sector);
|
||||
entry->size = swap32(entry->size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set partition entries */
|
||||
memcpy(outbuf, table.entries, sizeof(table.entries));
|
||||
case WBFS_DEVICE_SDHC: {
|
||||
/* SDHC sector size */
|
||||
sector_size = SDHC_SECTOR_SIZE;
|
||||
|
||||
/* Set sector size */
|
||||
*outval = sector_size;
|
||||
/* Read partition table */
|
||||
ret = SDHC_ReadSectors(0, 1, &table);
|
||||
if (!ret)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Swap endianess */
|
||||
for (cnt = 0; cnt < 4; cnt++) {
|
||||
partitionEntry *entry = &table.entries[cnt];
|
||||
|
||||
entry->sector = swap32(entry->sector);
|
||||
entry->size = swap32(entry->size);
|
||||
}
|
||||
|
||||
/* Set partition entries */
|
||||
memcpy(outbuf, table.entries, sizeof(table.entries));
|
||||
|
||||
/* Set sector size */
|
||||
*outval = sector_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Partition_GetEntriesEx(partitionEntry *outbuf, u32 *outval, int *num)
|
||||
bool Device_ReadSectors(u32 device, u32 sector, u32 count, void *buffer)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
/* Read from specified device */
|
||||
switch (device) {
|
||||
case WBFS_DEVICE_USB:
|
||||
ret = USBStorage_ReadSectors(sector, count, buffer);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case WBFS_DEVICE_SDHC:
|
||||
return SDHC_ReadSectors(sector, count, buffer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Device_WriteSectors(u32 device, u32 sector, u32 count, void *buffer)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
/* Read from specified device */
|
||||
switch (device) {
|
||||
case WBFS_DEVICE_USB:
|
||||
ret = USBStorage_WriteSectors(sector, count, buffer);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case WBFS_DEVICE_SDHC:
|
||||
return SDHC_WriteSectors(sector, count, buffer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 Partition_GetEntriesEx(u32 device, partitionEntry *outbuf, u32 *psect_size, int *num)
|
||||
{
|
||||
static partitionTable table ATTRIBUTE_ALIGN(32);
|
||||
partitionEntry *entry;
|
||||
@ -61,34 +127,60 @@ s32 Partition_GetEntriesEx(partitionEntry *outbuf, u32 *outval, int *num)
|
||||
int maxpart = *num;
|
||||
|
||||
// Get sector size
|
||||
ret = USBStorage_GetCapacity(§or_size);
|
||||
if (ret == 0) return -1;
|
||||
switch (device) {
|
||||
case WBFS_DEVICE_USB:
|
||||
ret = USBStorage_GetCapacity(§or_size);
|
||||
if (ret == 0) return -1;
|
||||
break;
|
||||
case WBFS_DEVICE_SDHC:
|
||||
sector_size = SDHC_SECTOR_SIZE;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
/* Set sector size */
|
||||
*psect_size = sector_size;
|
||||
|
||||
u32 ext = 0;
|
||||
u32 next = 0;
|
||||
|
||||
// Read partition table
|
||||
ret = USBStorage_ReadSectors(0, 1, &table);
|
||||
ret = Device_ReadSectors(device, 0, 1, &table);
|
||||
if (!ret) return -1;
|
||||
// Check if it's a RAW WBFS disc, without partition table
|
||||
if (get_fs_type(&table) == FS_TYPE_WBFS) {
|
||||
memset(outbuf, 0, sizeof(table.entries));
|
||||
wbfs_head_t *head = (wbfs_head_t*)&table;
|
||||
outbuf->size = wbfs_ntohl(head->n_hd_sec);
|
||||
*num = 1;
|
||||
return 0;
|
||||
}
|
||||
/* Swap endianess */
|
||||
for (i = 0; i < 4; i++) {
|
||||
entry = &table.entries[i];
|
||||
entry->sector = swap32(entry->sector);
|
||||
entry->size = swap32(entry->size);
|
||||
if (!ext && entry->type == 0x0f) ext = entry->sector;
|
||||
if (!ext && part_is_extended(entry->type)) {
|
||||
ext = entry->sector;
|
||||
}
|
||||
}
|
||||
/* Set partition entries */
|
||||
memcpy(outbuf, table.entries, sizeof(table.entries));
|
||||
/* Set sector size */
|
||||
*outval = sector_size;
|
||||
// num primary
|
||||
*num = 4;
|
||||
|
||||
if (!ext) return 0;
|
||||
|
||||
next = ext;
|
||||
// scan extended partition for logical
|
||||
if (ext) for(i=0; i<maxpart-4; i++) {
|
||||
ret = USBStorage_ReadSectors(next, 1, &table);
|
||||
for(i=0; i<maxpart-4; i++) {
|
||||
ret = Device_ReadSectors(device, next, 1, &table);
|
||||
if (!ret) break;
|
||||
if (i == 0) {
|
||||
// handle the invalid scenario where wbfs is on an EXTENDED
|
||||
// partition instead of on the Logical inside Extended.
|
||||
if (get_fs_type(&table) == FS_TYPE_WBFS) break;
|
||||
}
|
||||
entry = &table.entries[0];
|
||||
entry->sector = swap32(entry->sector);
|
||||
entry->size = swap32(entry->size);
|
||||
@ -106,12 +198,32 @@ s32 Partition_GetEntriesEx(partitionEntry *outbuf, u32 *outval, int *num)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool part_is_extended(int type)
|
||||
{
|
||||
if (type == 0x05) return true;
|
||||
if (type == 0x0f) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool part_is_data(int type)
|
||||
{
|
||||
if (type && !part_is_extended(type)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool part_valid_data(partitionEntry *entry)
|
||||
{
|
||||
if (entry->size && entry->type && entry->sector) {
|
||||
return part_is_data(entry->type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char* part_type_data(int type)
|
||||
{
|
||||
switch (type) {
|
||||
@ -133,8 +245,20 @@ char* part_type_data(int type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_fs_type(char *buf)
|
||||
char *part_type_name(int type)
|
||||
{
|
||||
static char unk[8];
|
||||
if (type == 0) return "UNUSED";
|
||||
if (part_is_extended(type)) return "EXTEND";
|
||||
char *p = part_type_data(type);
|
||||
if (p) return p;
|
||||
sprintf(unk, "UNK-%02x", type);
|
||||
return unk;
|
||||
}
|
||||
|
||||
int get_fs_type(void *buff)
|
||||
{
|
||||
char *buf = buff;
|
||||
// WBFS
|
||||
wbfs_head_t *head = (wbfs_head_t *)buf;
|
||||
if (head->magic == wbfs_htonl(WBFS_MAGIC)) return FS_TYPE_WBFS;
|
||||
@ -154,7 +278,19 @@ bool is_type_fat(int type)
|
||||
return (type == FS_TYPE_FAT16 || type == FS_TYPE_FAT32);
|
||||
}
|
||||
|
||||
s32 Partition_GetList(PartList *plist)
|
||||
|
||||
char *get_fs_name(int i)
|
||||
{
|
||||
switch (i) {
|
||||
case FS_TYPE_FAT16: return "FAT16";
|
||||
case FS_TYPE_FAT32: return "FAT32";
|
||||
case FS_TYPE_NTFS: return "NTFS";
|
||||
case FS_TYPE_WBFS: return "WBFS";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
s32 Partition_GetList(u32 device, PartList *plist)
|
||||
{
|
||||
partitionEntry *entry = NULL;
|
||||
PartInfo *pinfo = NULL;
|
||||
@ -164,10 +300,19 @@ s32 Partition_GetList(PartList *plist)
|
||||
|
||||
// Get partition entries
|
||||
plist->num = MAX_PARTITIONS_EX;
|
||||
ret = Partition_GetEntriesEx(plist->pentry, &plist->sector_size, &plist->num);
|
||||
ret = Partition_GetEntriesEx(device, plist->pentry, &plist->sector_size, &plist->num);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
// check for RAW WBFS disc
|
||||
if (plist->num == 1) {
|
||||
pinfo = &plist->pinfo[0];
|
||||
entry = &plist->pentry[0];
|
||||
plist->wbfs_n = 1;
|
||||
pinfo->wbfs_i = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char buf[plist->sector_size];
|
||||
|
||||
// scan partitions for filesystem type
|
||||
@ -175,10 +320,15 @@ s32 Partition_GetList(PartList *plist)
|
||||
pinfo = &plist->pinfo[i];
|
||||
entry = &plist->pentry[i];
|
||||
if (!entry->size) continue;
|
||||
if (!part_type_data(entry->type)) continue;
|
||||
if (!USBStorage_ReadSectors(entry->sector, 1, buf)) continue;
|
||||
if (!entry->type) continue;
|
||||
if (!entry->sector) continue;
|
||||
// even though wrong, it's possible WBFS is on an extended part.
|
||||
//if (!part_is_data(entry->type)) continue;
|
||||
if (!Device_ReadSectors(device, entry->sector, 1, buf)) continue;
|
||||
pinfo->fs_type = get_fs_type(buf);
|
||||
if (pinfo->fs_type == FS_TYPE_WBFS) {
|
||||
// multiple wbfs on sdhc not supported
|
||||
if (device == WBFS_DEVICE_SDHC && (plist->wbfs_n > 1 || i > 4)) continue;
|
||||
plist->wbfs_n++;
|
||||
pinfo->wbfs_i = plist->wbfs_n;
|
||||
} else if (is_type_fat(pinfo->fs_type)) {
|
||||
@ -188,3 +338,24 @@ s32 Partition_GetList(PartList *plist)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Partition_FixEXT(u32 device, int part)
|
||||
{
|
||||
static partitionTable table ATTRIBUTE_ALIGN(32);
|
||||
int ret;
|
||||
|
||||
if (part < 0 || part > 3) return -1;
|
||||
// Read partition table
|
||||
ret = Device_ReadSectors(device, 0, 1, &table);
|
||||
if (!ret) return -1;
|
||||
if (part_is_extended(table.entries[part].type)) {
|
||||
table.entries[part].type = 0x0b; // FAT32
|
||||
ret = Device_WriteSectors(device, 0, 1, &table);
|
||||
if (!ret) return -1;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,62 +1,74 @@
|
||||
#ifndef _PARTITION_H_
|
||||
#ifndef _PARTITION_H_
|
||||
#define _PARTITION_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 'partition entry' structure */
|
||||
typedef struct {
|
||||
/* Boot indicator */
|
||||
u8 boot;
|
||||
|
||||
/* Starting CHS */
|
||||
u8 start[3];
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Partition type */
|
||||
u8 type;
|
||||
/* 'partition entry' structure */
|
||||
typedef struct {
|
||||
/* Boot indicator */
|
||||
u8 boot;
|
||||
|
||||
/* Ending CHS */
|
||||
u8 end[3];
|
||||
/* Starting CHS */
|
||||
u8 start[3];
|
||||
|
||||
/* Partition sector */
|
||||
u32 sector;
|
||||
/* Partition type */
|
||||
u8 type;
|
||||
|
||||
/* Partition size */
|
||||
u32 size;
|
||||
} ATTRIBUTE_PACKED partitionEntry;
|
||||
/* Ending CHS */
|
||||
u8 end[3];
|
||||
|
||||
/* Constants */
|
||||
#define MAX_PARTITIONS 4
|
||||
#define MAX_PARTITIONS_EX 10
|
||||
/* Partition sector */
|
||||
u32 sector;
|
||||
|
||||
#define FS_TYPE_UNK 0
|
||||
#define FS_TYPE_FAT16 1
|
||||
#define FS_TYPE_FAT32 2
|
||||
#define FS_TYPE_NTFS 3
|
||||
#define FS_TYPE_WBFS 4
|
||||
/* Partition size */
|
||||
u32 size;
|
||||
} ATTRIBUTE_PACKED partitionEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fs_type;
|
||||
int wbfs_i; // seq wbfs part index
|
||||
int fat_i; // seq fat part index
|
||||
} PartInfo;
|
||||
/* Constants */
|
||||
#define MAX_PARTITIONS 4
|
||||
#define MAX_PARTITIONS_EX 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int num;
|
||||
u32 sector_size;
|
||||
partitionEntry pentry[MAX_PARTITIONS_EX];
|
||||
int wbfs_n;
|
||||
int fat_n;
|
||||
PartInfo pinfo[MAX_PARTITIONS_EX];
|
||||
} PartList;
|
||||
#define FS_TYPE_UNK 0
|
||||
#define FS_TYPE_FAT16 1
|
||||
#define FS_TYPE_FAT32 2
|
||||
#define FS_TYPE_NTFS 3
|
||||
#define FS_TYPE_WBFS 4
|
||||
|
||||
/* Prototypes */
|
||||
s32 Partition_GetEntries(partitionEntry *, u32 *);
|
||||
s32 Partition_GetEntriesEx(partitionEntry *, u32 *, int *);
|
||||
s32 Partition_GetList(PartList *plist);
|
||||
typedef struct
|
||||
{
|
||||
int fs_type;
|
||||
int wbfs_i; // seq wbfs part index
|
||||
int fat_i; // seq fat part index
|
||||
} PartInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int num;
|
||||
u32 sector_size;
|
||||
partitionEntry pentry[MAX_PARTITIONS_EX];
|
||||
int wbfs_n;
|
||||
int fat_n;
|
||||
PartInfo pinfo[MAX_PARTITIONS_EX];
|
||||
} PartList;
|
||||
|
||||
/* Prototypes */
|
||||
s32 Partition_GetEntries(u32 device, partitionEntry *outbuf, u32 *outval);
|
||||
s32 Partition_GetEntriesEx(u32 device, partitionEntry *outbuf, u32 *outval, int *num);
|
||||
bool Device_ReadSectors(u32 device, u32 sector, u32 count, void *buffer);
|
||||
bool Device_WriteSectors(u32 device, u32 sector, u32 count, void *buffer);
|
||||
s32 Partition_GetList(u32 device, PartList *plist);
|
||||
int Partition_FixEXT(u32 device, int part);
|
||||
|
||||
bool part_is_extended(int type);
|
||||
bool part_is_data(int type);
|
||||
char* part_type_data(int type);
|
||||
char* part_type_name(int type);
|
||||
bool part_valid_data(partitionEntry *entry);
|
||||
int get_fs_type(void *buf);
|
||||
bool is_type_fat(int type);
|
||||
char* get_fs_name(int i);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ static s32 hid = -1, fd = -1;
|
||||
static u32 sector_size;
|
||||
|
||||
extern void* SYS_AllocArena2MemLo(u32 size,u32 align);
|
||||
static void *mem2_ptr=NULL;
|
||||
//static void *mem2_ptr=NULL;
|
||||
|
||||
inline s32 __USBStorage_isMEM2Buffer(const void *buffer) {
|
||||
u32 high_addr = ((u32)buffer) >> 24;
|
||||
@ -151,7 +151,7 @@ void USBStorage_Deinit(void) {
|
||||
|
||||
s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) {
|
||||
|
||||
void *buf = (void *)buffer;
|
||||
// void *buf = (void *)buffer;
|
||||
u32 len = (sector_size * numSectors);
|
||||
|
||||
s32 ret;
|
||||
@ -159,30 +159,31 @@ s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) {
|
||||
/* Device not opened */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
if(!mem2_ptr) mem2_ptr=SYS_AllocArena2MemLo(2048*256,32);
|
||||
|
||||
// if(!mem2_ptr) mem2_ptr=SYS_AllocArena2MemLo(2048*256,32);
|
||||
/* MEM1 buffer */
|
||||
if (!__USBStorage_isMEM2Buffer(buffer)) {
|
||||
// if (!__USBStorage_isMEM2Buffer(buffer)) {
|
||||
/* Allocate memory */
|
||||
buf = mem2_ptr; //iosAlloc(hid, len);
|
||||
if (!buf)
|
||||
return IPC_ENOMEM;
|
||||
}
|
||||
// buf = mem2_ptr; //iosAlloc(hid, len);
|
||||
// if (!buf)
|
||||
// return IPC_ENOMEM;
|
||||
// }
|
||||
|
||||
/* Read data */
|
||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buf, len);
|
||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buffer, len);
|
||||
|
||||
/* Copy data */
|
||||
if (buf != buffer) {
|
||||
memcpy(buffer, buf, len);
|
||||
// if (buf != buffer) {
|
||||
// memcpy(buffer, buf, len);
|
||||
//iosFree(hid, buf);
|
||||
}
|
||||
// }
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) {
|
||||
|
||||
void *buf = (void *)buffer;
|
||||
// void *buf = (void *)buffer;
|
||||
u32 len = (sector_size * numSectors);
|
||||
|
||||
s32 ret;
|
||||
@ -190,26 +191,26 @@ s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) {
|
||||
/* Device not opened */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
if(!mem2_ptr) mem2_ptr = SYS_AllocArena2MemLo(2048*256,32);
|
||||
// if(!mem2_ptr) mem2_ptr = SYS_AllocArena2MemLo(2048*256,32);
|
||||
|
||||
|
||||
/* MEM1 buffer */
|
||||
if (!__USBStorage_isMEM2Buffer(buffer)) {
|
||||
// if (!__USBStorage_isMEM2Buffer(buffer)) {
|
||||
/* Allocate memory */
|
||||
buf = mem2_ptr; //buf = iosAlloc(hid, len);
|
||||
if (!buf)
|
||||
return IPC_ENOMEM;
|
||||
// buf = mem2_ptr; //buf = iosAlloc(hid, len);
|
||||
// if (!buf)
|
||||
// return IPC_ENOMEM;
|
||||
|
||||
/* Copy data */
|
||||
memcpy(buf, buffer, len);
|
||||
}
|
||||
// memcpy(buf, buffer, len);
|
||||
// }
|
||||
|
||||
/* Write data */
|
||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buf, len);
|
||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buffer, len);
|
||||
|
||||
/* Free memory */
|
||||
if (buf != buffer)
|
||||
iosFree(hid, buf);
|
||||
// if (buf != buffer)
|
||||
// iosFree(hid, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ s32 WBFS_OpenNamed(char *partition)
|
||||
}
|
||||
|
||||
// Get partition entries
|
||||
ret = Partition_GetList(&plist);
|
||||
ret = Partition_GetList(wbfsDev, &plist);
|
||||
if (ret || plist.num == 0) return -1;
|
||||
|
||||
if (part_fat) {
|
||||
|
@ -24,8 +24,11 @@
|
||||
#include "disc.h"
|
||||
#include "settings/cfg.h"
|
||||
|
||||
|
||||
// WBFS FAT by oggzee
|
||||
|
||||
// max fat fname = 256
|
||||
#define MAX_FAT_PATH 1024
|
||||
#define D_S(A) A, sizeof(A)
|
||||
|
||||
char wbfs_fat_drive[16];
|
||||
@ -42,36 +45,38 @@ static u32 fat_sector_size = 512;
|
||||
void WBFS_Spinner(s32 x, s32 max);
|
||||
s32 __WBFS_ReadDVD(void *fp, u32 lba, u32 len, void *iobuf);
|
||||
|
||||
|
||||
s32 _WBFS_FAT_GetHeadersCount(void *outbuf, u32 *count, u32 len)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
char *p;
|
||||
int ret, cnt = 0;
|
||||
char path[100];
|
||||
char path[MAX_FAT_PATH];
|
||||
wbfs_t *part = NULL;
|
||||
u32 size;
|
||||
u8 *ptr;
|
||||
struct discHdr tmpHdr;
|
||||
int hdrsize;
|
||||
struct stat st;
|
||||
u8 id[8];
|
||||
int is_dir;
|
||||
//dbg_time1();
|
||||
|
||||
strcpy(path, wbfs_fat_drive);
|
||||
strcat(path, wbfs_fat_dir);
|
||||
dir = opendir(path);
|
||||
//printf("opendir: %s %p\n", path, dir); Wpad_WaitButtons();
|
||||
if (!dir) {
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
while ((dent = readdir(dir)) != NULL) {
|
||||
//printf("found: %s\n", dent->d_name);
|
||||
if (outbuf && cnt >= *count) break;
|
||||
if ((char)dent->d_name[0] == '.') continue;
|
||||
p = strrchr(dent->d_name, '.');
|
||||
if (!p) continue;
|
||||
if (strcasecmp(p, ".wbfs") != 0) continue;
|
||||
if (strlen(dent->d_name) != 11) continue; // GAMEID.wbfs
|
||||
u8 id[8];
|
||||
if (strlen(dent->d_name) < 8) continue; // "GAMEID_x"
|
||||
|
||||
memcpy(id, dent->d_name, 6);
|
||||
id[6] = 0;
|
||||
|
||||
@ -80,6 +85,26 @@ s32 _WBFS_FAT_GetHeadersCount(void *outbuf, u32 *count, u32 len)
|
||||
strcat(path, "/");
|
||||
strcat(path, dent->d_name);
|
||||
stat(path, &st);
|
||||
|
||||
is_dir = S_ISDIR(st.st_mode);
|
||||
//printf("path: %s %d\n", path, is_dir);
|
||||
if (is_dir) {
|
||||
// usb:/wbfs/GAMEID_TITLE/GAMEID.wbfs
|
||||
if (dent->d_name[6] != '_') continue;
|
||||
strcat(path, "/");
|
||||
strcat(path, (char*)id);
|
||||
strcat(path, ".wbfs");
|
||||
//printf("path2: %s\n", path);
|
||||
if (stat(path, &st) == -1) continue;
|
||||
} else {
|
||||
// usb:/wbfs/GAMEID.wbfs
|
||||
p = strrchr(dent->d_name, '.');
|
||||
if (!p) continue;
|
||||
if (strcasecmp(p, ".wbfs") != 0) continue;
|
||||
if (strlen(dent->d_name) != 11) continue; // GAMEID.wbfs
|
||||
}
|
||||
|
||||
//printf("found: %s %d MB\n", path, (int)(st.st_size/1024/1024));
|
||||
// size must be at least 1MB to be considered a valid wbfs file
|
||||
if (st.st_size < 1024*1024) continue;
|
||||
if (!outbuf) {
|
||||
@ -89,40 +114,43 @@ s32 _WBFS_FAT_GetHeadersCount(void *outbuf, u32 *count, u32 len)
|
||||
}
|
||||
ptr = ((u8 *)outbuf) + (cnt * len);
|
||||
hdrsize = len;
|
||||
|
||||
// if we have titles.txt entry use that
|
||||
char *title = cfg_get_title(id);
|
||||
// if directory, and no titles.txt get title from dir name
|
||||
if (!title && is_dir) {
|
||||
title = &dent->d_name[7];
|
||||
}
|
||||
if (title) {
|
||||
memset(&tmpHdr, 0, sizeof(tmpHdr));
|
||||
memcpy(tmpHdr.id, id, 6);
|
||||
strncpy(tmpHdr.title, title, sizeof(tmpHdr.title));
|
||||
strncpy(tmpHdr.title, title, sizeof(tmpHdr.title)-1);
|
||||
tmpHdr.magic = 0x5D1C9EA3;
|
||||
memcpy(ptr, &tmpHdr, hdrsize);
|
||||
cnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// no title found, read it from wbfs file directly
|
||||
// else read it from wbfs file directly
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (fp != NULL) {
|
||||
fseek(fp, 512, SEEK_SET);
|
||||
fread(&tmpHdr, sizeof(struct discHdr), 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (tmpHdr.magic == 0x5D1C9EA3 && (memcmp(tmpHdr.id, id, 6) == 0)) {
|
||||
if ((tmpHdr.magic == 0x5D1C9EA3) && (memcmp(tmpHdr.id, id, 6) == 0)) {
|
||||
memcpy(ptr, &tmpHdr, hdrsize);
|
||||
cnt++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// no title found, read it from wbfs file
|
||||
// but this is a little bit slower
|
||||
// but this is a little bit slower
|
||||
// open 'partition' file
|
||||
part = WBFS_FAT_OpenPart(id);
|
||||
if (!part) {
|
||||
printf("bad wbfs file: %s\n", dent->d_name);
|
||||
sleep(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get header */
|
||||
ret = wbfs_get_disc_info(part, 0, ptr, hdrsize, &size);
|
||||
if (ret == 0) cnt++;
|
||||
@ -131,7 +159,7 @@ s32 _WBFS_FAT_GetHeadersCount(void *outbuf, u32 *count, u32 len)
|
||||
*count = cnt;
|
||||
closedir(dir);
|
||||
//dbg_time2("\nFAT HDRS");
|
||||
//Wpad_WaitButtons();
|
||||
//Wpad_WaitButtonsCommon();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -175,7 +203,6 @@ s32 WBFS_FAT_DiskSpace(f32 *used, f32 *free)
|
||||
// statvfs is slow, so cache values
|
||||
if (!wbfs_fat_vfs_have || wbfs_fat_vfs_lba != wbfs_part_lba) {
|
||||
ret = statvfs(wbfs_fat_drive, &wbfs_fat_vfs);
|
||||
|
||||
if (ret) return 0;
|
||||
wbfs_fat_vfs_have = 1;
|
||||
wbfs_fat_vfs_lba = wbfs_part_lba;
|
||||
@ -192,32 +219,122 @@ s32 WBFS_FAT_DiskSpace(f32 *used, f32 *free)
|
||||
|
||||
static int nop_read_sector(void *_fp,u32 lba,u32 count,void*buf)
|
||||
{
|
||||
//printf("read %d %d\n", lba, count); //Wpad_WaitButtons();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nop_write_sector(void *_fp,u32 lba,u32 count,void*buf)
|
||||
{
|
||||
//printf("write %d %d\n", lba, count); //Wpad_WaitButtons();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WBFS_FAT_fname(u8 *id, char *fname, int len)
|
||||
void WBFS_FAT_fname(u8 *id, char *fname, int len, char *path)
|
||||
{
|
||||
snprintf(fname, len, "%s%s/%.6s.wbfs", wbfs_fat_drive, wbfs_fat_dir, id);
|
||||
if (path == NULL) {
|
||||
snprintf(fname, len, "%s%s/%.6s.wbfs", wbfs_fat_drive, wbfs_fat_dir, id);
|
||||
} else {
|
||||
snprintf(fname, len, "%s/%.6s.wbfs", path, id);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_gameid_title(struct discHdr *header, char *name, int re_space)
|
||||
{
|
||||
int i, len;
|
||||
|
||||
memcpy(name, header->id, 6);
|
||||
name[6] = 0;
|
||||
strcat(name, "_");
|
||||
strcat(name, get_title(header));
|
||||
|
||||
// replace silly chars with '_'
|
||||
len = strlen(name);
|
||||
for (i = 0; i < len; i++) {
|
||||
if(strchr("\\/:<>|\"", name[i]) || iscntrl(name[i])) {
|
||||
name[i] = '_';
|
||||
}
|
||||
if(re_space && name[i]==' ') {
|
||||
name[i] = '_';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WBFS_FAT_get_dir(struct discHdr *header, char *path)
|
||||
{
|
||||
strcpy(path, wbfs_fat_drive);
|
||||
strcat(path, wbfs_fat_dir);
|
||||
if (Settings.FatInstallToDir) {
|
||||
strcat(path, "/");
|
||||
mk_gameid_title(header, path + strlen(path), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_title_txt(struct discHdr *header, char *path)
|
||||
{
|
||||
char fname[MAX_FAT_PATH];
|
||||
FILE *f;
|
||||
|
||||
strcpy(fname, path);
|
||||
strcat(fname, "/");
|
||||
mk_gameid_title(header, fname+strlen(fname), 1);
|
||||
strcat(fname, ".txt");
|
||||
|
||||
f = fopen(fname, "wb");
|
||||
if (!f) return;
|
||||
fprintf(f, "%.6s = %.64s\n", header->id, get_title(header));
|
||||
fclose(f);
|
||||
printf("Info file: %s\n", fname);
|
||||
}
|
||||
|
||||
|
||||
int WBFS_FAT_find_fname(u8 *id, char *fname, int len)
|
||||
{
|
||||
struct stat st;
|
||||
WBFS_FAT_fname(id, fname, len, NULL);
|
||||
if (stat(fname, &st) == 0) return 1;
|
||||
// direct file not found, check subdirs
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
char path[MAX_FAT_PATH];
|
||||
strcpy(path, wbfs_fat_drive);
|
||||
strcat(path, wbfs_fat_dir);
|
||||
dir = opendir(path);
|
||||
//printf("opendir: %s %p\n", path, dir); Wpad_WaitButtons();
|
||||
if (!dir) {
|
||||
goto err;
|
||||
}
|
||||
while ((dent = readdir(dir)) != NULL) {
|
||||
char *name = (char*)dent->d_name;
|
||||
if (name[0] == '.') continue;
|
||||
if (name[6] != '_') continue;
|
||||
if (strncmp(name, (char*)id, 6) != 0) continue;
|
||||
if (strlen(name) < 8) continue;
|
||||
snprintf(fname, len, "%s/%s/%.6s.wbfs", path, name, id);
|
||||
if (stat(fname, &st) == 0) {
|
||||
closedir(dir);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
// not found
|
||||
err:
|
||||
*fname = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wbfs_t* WBFS_FAT_OpenPart(u8 *id)
|
||||
{
|
||||
char fname[100];
|
||||
char fname[MAX_FAT_PATH];
|
||||
wbfs_t *part = NULL;
|
||||
int ret;
|
||||
|
||||
// wbfs 'partition' file
|
||||
WBFS_FAT_fname(id, fname, sizeof(fname));
|
||||
if ( !WBFS_FAT_find_fname(id, fname, sizeof(fname)) ) return NULL;
|
||||
ret = split_open(&split, fname);
|
||||
if (ret) return NULL;
|
||||
part = wbfs_open_partition(
|
||||
split_read_sector,
|
||||
split_write_sector, //readonly //split_write_sector,
|
||||
nop_write_sector, //readonly //split_write_sector,
|
||||
&split, fat_sector_size, split.total_sec, 0, 0);
|
||||
if (!part) {
|
||||
split_close(&split);
|
||||
@ -225,17 +342,20 @@ wbfs_t* WBFS_FAT_OpenPart(u8 *id)
|
||||
return part;
|
||||
}
|
||||
|
||||
wbfs_t* WBFS_FAT_CreatePart(u8 *id)
|
||||
wbfs_t* WBFS_FAT_CreatePart(u8 *id, char *path)
|
||||
{
|
||||
char fname[100];
|
||||
char fname[MAX_FAT_PATH];
|
||||
wbfs_t *part = NULL;
|
||||
u64 size = (u64)143432*2*0x8000ULL;
|
||||
u32 n_sector = size / 512;
|
||||
int ret;
|
||||
|
||||
//printf("CREATE PART %s %lld %d\n", id, size, n_sector);
|
||||
snprintf(D_S(fname), "%s%s", wbfs_fat_drive, wbfs_fat_dir);
|
||||
mkdir(fname, 0777);
|
||||
WBFS_FAT_fname(id, fname, sizeof(fname));
|
||||
mkdir(fname, 0777); // base usb:/wbfs
|
||||
mkdir(path, 0777); // game subdir
|
||||
WBFS_FAT_fname(id, fname, sizeof(fname), path);
|
||||
printf("Writing to %s\n", fname);
|
||||
ret = split_create(&split, fname, OPT_split_size, size, true);
|
||||
if (ret) return NULL;
|
||||
|
||||
@ -243,6 +363,8 @@ wbfs_t* WBFS_FAT_CreatePart(u8 *id)
|
||||
u32 scnt = 0;
|
||||
int fd = split_get_file(&split, 0, &scnt, 0);
|
||||
if (fd<0) {
|
||||
printf("ERROR creating file\n");
|
||||
sleep(2);
|
||||
split_close(&split);
|
||||
return NULL;
|
||||
}
|
||||
@ -267,42 +389,87 @@ void WBFS_FAT_ClosePart(wbfs_t* part)
|
||||
|
||||
s32 WBFS_FAT_RemoveGame(u8 *discid)
|
||||
{
|
||||
char fname[100];
|
||||
char fname[MAX_FAT_PATH];
|
||||
int loc;
|
||||
// wbfs 'partition' file
|
||||
WBFS_FAT_fname(discid, fname, sizeof(fname));
|
||||
loc = WBFS_FAT_find_fname(discid, fname, sizeof(fname));
|
||||
if ( !loc ) return -1;
|
||||
split_create(&split, fname, 0, 0, true);
|
||||
split_close(&split);
|
||||
if (loc == 1) return 0;
|
||||
|
||||
// game is in subdir
|
||||
// remove optional .txt file
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
char path[MAX_FAT_PATH];
|
||||
strncpy(path, fname, sizeof(path));
|
||||
char *p= strrchr(path, '/');
|
||||
if (p) *p = 0;
|
||||
dir = opendir(path);
|
||||
if (!dir) return 0;
|
||||
while ((dent = readdir(dir)) != NULL) {
|
||||
char *name = (char*)dent->d_name;
|
||||
if (name[0] == '.') continue;
|
||||
if (name[6] != '_') continue;
|
||||
if (strncmp(name, (char*)discid, 6) != 0) continue;
|
||||
p = strrchr(name, '.');
|
||||
if (!p) continue;
|
||||
if (strcasecmp(p, ".txt") != 0) continue;
|
||||
snprintf(fname, sizeof(fname), "%s/%s", path, name);
|
||||
remove(fname);
|
||||
break;
|
||||
}
|
||||
closedir(dir);
|
||||
// remove game subdir
|
||||
//rmdir(path);
|
||||
if (unlink(path) == -1) {
|
||||
}
|
||||
|
||||
// Reset FAT stats
|
||||
wbfs_fat_vfs_have = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
s32 WBFS_FAT_AddGame(void)
|
||||
{
|
||||
static struct discHdr header ATTRIBUTE_ALIGN(32);
|
||||
s32 ret;
|
||||
char path[MAX_FAT_PATH];
|
||||
wbfs_t *part = NULL;
|
||||
|
||||
//write_test(); return -1;
|
||||
s32 ret;
|
||||
|
||||
// read ID from DVD
|
||||
Disc_ReadHeader(&header);
|
||||
// path
|
||||
WBFS_FAT_get_dir(&header, path);
|
||||
// create wbfs 'partition' file
|
||||
part = WBFS_FAT_CreatePart(header.id);
|
||||
part = WBFS_FAT_CreatePart(header.id, path);
|
||||
if (!part) return -1;
|
||||
/* Add game to device */
|
||||
partition_selector_t part_sel = ONLY_GAME_PARTITION;
|
||||
int copy_1_1 = 0;
|
||||
/*
|
||||
switch (CFG.install_partitions) {
|
||||
case CFG_INSTALL_GAME:
|
||||
part_sel = ONLY_GAME_PARTITION;
|
||||
break;
|
||||
case CFG_INSTALL_ALL:
|
||||
part_sel = ALL_PARTITIONS;
|
||||
break;
|
||||
case CFG_INSTALL_1_1:
|
||||
part_sel = ALL_PARTITIONS;
|
||||
copy_1_1 = 1;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
extern wbfs_t *hdd;
|
||||
wbfs_t *old_hdd = hdd;
|
||||
hdd = part; // used by spinner
|
||||
ret = wbfs_add_disc(part, __WBFS_ReadDVD, NULL, WBFS_Spinner, ONLY_GAME_PARTITION, 0);
|
||||
ret = wbfs_add_disc(part, __WBFS_ReadDVD, NULL, WBFS_Spinner, part_sel, copy_1_1);
|
||||
hdd = old_hdd;
|
||||
wbfs_trim(part);
|
||||
WBFS_FAT_ClosePart(part);
|
||||
|
||||
// Reset FAT stats
|
||||
wbfs_fat_vfs_have = 0;
|
||||
if (ret < 0) return ret;
|
||||
mk_title_txt(&header, path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -315,7 +482,7 @@ s32 WBFS_FAT_DVD_Size(u64 *comp_size, u64 *real_size)
|
||||
wbfs_t *part = NULL;
|
||||
u64 size = (u64)143432*2*0x8000ULL;
|
||||
u32 n_sector = size / fat_sector_size;
|
||||
u32 wii_sec_sz;
|
||||
u32 wii_sec_sz;
|
||||
|
||||
// init a temporary dummy part
|
||||
// as a placeholder for wbfs_size_disc
|
||||
@ -326,13 +493,21 @@ s32 WBFS_FAT_DVD_Size(u64 *comp_size, u64 *real_size)
|
||||
wii_sec_sz = part->wii_sec_sz;
|
||||
|
||||
/* Add game to device */
|
||||
ret = wbfs_size_disc(part, __WBFS_ReadDVD, NULL, ONLY_GAME_PARTITION, &comp_sec, &last_sec);
|
||||
partition_selector_t part_sel = ONLY_GAME_PARTITION;
|
||||
/*
|
||||
if (CFG.install_partitions) {
|
||||
part_sel = ALL_PARTITIONS;
|
||||
} else {
|
||||
part_sel = ONLY_GAME_PARTITION;
|
||||
}
|
||||
*/
|
||||
ret = wbfs_size_disc(part, __WBFS_ReadDVD, NULL, part_sel, &comp_sec, &last_sec);
|
||||
wbfs_close(part);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (comp_size != NULL) *comp_size = (u64)wii_sec_sz * comp_sec;
|
||||
if (real_size != NULL) *real_size = (u64)wii_sec_sz * last_sec;
|
||||
*comp_size = (u64)wii_sec_sz * comp_sec;
|
||||
*real_size = (u64)wii_sec_sz * last_sec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -366,8 +541,8 @@ s32 WBFS_FAT_ReIDGame(u8 *discid, const void *newID)
|
||||
char fnamenew[100];
|
||||
s32 cnt = 0x31;
|
||||
|
||||
WBFS_FAT_fname(discid, fname, sizeof(fname));
|
||||
WBFS_FAT_fname((u8*) newID, fnamenew, sizeof(fnamenew));
|
||||
WBFS_FAT_fname(discid, fname, sizeof(fname), NULL);
|
||||
WBFS_FAT_fname((u8*) newID, fnamenew, sizeof(fnamenew), NULL);
|
||||
|
||||
int stringlength = strlen(fname);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define IOCTL_DI_SEEK 0xAB
|
||||
#define IOCTL_DI_STOPLASER 0xD2
|
||||
#define IOCTL_DI_OFFSET 0xD9
|
||||
#define IOCTL_DI_DISC_BCA 0xDA
|
||||
#define IOCTL_DI_STOPMOTOR 0xE3
|
||||
#define IOCTL_DI_SETUSBMODE 0xF4
|
||||
#define IOCTL_DI_DISABLERESET 0xF6
|
||||
@ -336,3 +337,20 @@ s32 WDVD_SetUSBMode(const u8 *id, s32 partition) {
|
||||
|
||||
return (ret == 1) ? 0 : -ret;
|
||||
}
|
||||
|
||||
s32 WDVD_Read_Disc_BCA(void *buf)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
memset(inbuf, 0, sizeof(inbuf));
|
||||
|
||||
/* Disc read */
|
||||
inbuf[0] = IOCTL_DI_DISC_BCA << 24;
|
||||
//inbuf[1] = 64;
|
||||
|
||||
ret = IOS_Ioctl(di_fd, IOCTL_DI_DISC_BCA, inbuf, sizeof(inbuf), buf, 64);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (ret == 1) ? 0 : -ret;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ extern "C" {
|
||||
s32 WDVD_GetCoverStatus(u32 *);
|
||||
s32 WDVD_DisableReset(u8);
|
||||
s32 WDVD_SetUSBMode(const u8 *, s32 partition);
|
||||
s32 WDVD_Read_Disc_BCA(void *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user