*Added PoP Patch to apply automatically. The internal patch is not applied if you have a .wip file for PoP. So the .wip patches override the internal patch.

*Cleanup inside the apploader
This commit is contained in:
dimok321 2010-05-30 14:18:25 +00:00
parent 1e9951f586
commit a5ca9235ca
11 changed files with 558 additions and 478 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>1.0 r934</version>
<release_date>201005300653</release_date>
<version>1.0 r935</version>
<release_date>201005300742</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.

File diff suppressed because one or more lines are too long

View File

@ -1,185 +1,188 @@
#include "mem2.h"
#include "mem2alloc.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) {
return p;
}
return __real_malloc(size);
}
p = __real_malloc(size);
if (p != 0) {
return p;
}
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)
{
memset(p, 0, n * size);
return p;
}
return __real_calloc(n, size);
}
p = __real_calloc(n, size);
if (p != 0) {
return p;
}
p = MEM2_alloc(n * size);
if (p != 0) {
memset(p, 0, 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) {
return p;
}
}
return __real_memalign(a, size);
}
p = __real_memalign(a, size);
if (p != 0 || a > 32 || 32 % a != 0) {
return p;
}
return MEM2_alloc(size);
}
void __wrap_free(void *p)
{
if (((u32)p & 0x10000000) != 0) {
MEM2_free(p);
} else {
__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) {
return n;
}
n = __real_malloc(size);
if (n == 0) {
return 0;
}
if (p != 0)
{
memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size);
MEM2_free(p);
}
return n;
}
// ptr from malloc
n = __real_realloc(p, size);
if (n != 0) {
return n;
}
n = MEM2_alloc(size);
if (n == 0) {
return 0;
}
if (p != 0)
{
memcpy(n, p, __real_malloc_usable_size(p) < size ? __real_malloc_usable_size(p) : size);
__real_free(p);
}
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);
}
}
#include "mem2.h"
#include "mem2alloc.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) {
return p;
}
return __real_malloc(size);
}
p = __real_malloc(size);
if (p != 0) {
return p;
}
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)
{
memset(p, 0, n * size);
return p;
}
return __real_calloc(n, size);
}
p = __real_calloc(n, size);
if (p != 0) {
return p;
}
p = MEM2_alloc(n * size);
if (p != 0) {
memset(p, 0, 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) {
return p;
}
}
return __real_memalign(a, size);
}
p = __real_memalign(a, size);
if (p != 0 || a > 32 || 32 % a != 0) {
return p;
}
return MEM2_alloc(size);
}
void __wrap_free(void *p)
{
if(!p)
return;
if (((u32)p & 0x10000000) != 0) {
MEM2_free(p);
} else {
__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) {
return n;
}
n = __real_malloc(size);
if (n == 0) {
return 0;
}
if (p != 0)
{
memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size);
MEM2_free(p);
}
return n;
}
// ptr from malloc
n = __real_realloc(p, size);
if (n != 0) {
return n;
}
n = MEM2_alloc(size);
if (n == 0) {
return 0;
}
if (p != 0)
{
memcpy(n, p, __real_malloc_usable_size(p) < size ? __real_malloc_usable_size(p) : size);
__real_free(p);
}
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);
}
}

View File

@ -0,0 +1,19 @@
#include <string.h>
#include <gctypes.h>
bool PatchDOL(u8 * Address, int Size, const u8 * SearchPattern, int SearchSize, const u8 * PatchData, int PatchSize)
{
u8 * Addr = Address;
u8 * Addr_end = Address+Size;
while(Addr <= Addr_end-SearchSize)
{
if(memcmp(Addr, SearchPattern, SearchSize)==0)
{
memcpy(Addr, PatchData, PatchSize);
return true;
}
Addr += 4;
}
return false;
}

View File

@ -0,0 +1,8 @@
#ifndef DOLPATCHER_C_
#define DOLPATCHER_C_
#include <gctypes.h>
bool PatchDOL(u8 * Address, int Size, const u8 * SearchPattern, int SearchSize, const u8 * PatchData, int PatchSize);
#endif

View File

@ -0,0 +1,269 @@
#include <gccore.h>
#include <malloc.h>
#include <string.h>
#include "dolpatcher.h"
#include "wip.h"
/** Anti 002 fix for IOS 249 rev > 12 thanks to WiiPower **/
bool Anti_002_fix(u8 * Address, int Size)
{
u8 SearchPattern[12] = { 0x2C, 0x00, 0x00, 0x00, 0x48, 0x00, 0x02, 0x14, 0x3C, 0x60, 0x80, 0x00 };
u8 PatchData[12] = { 0x2C, 0x00, 0x00, 0x00, 0x40, 0x82, 0x02, 0x14, 0x3C, 0x60, 0x80, 0x00 };
return PatchDOL(Address, Size, (const u8 *) &SearchPattern, sizeof(SearchPattern), (const u8 *) &PatchData, sizeof(PatchData));
}
/** Thanks to WiiPower **/
bool NSMBPatch(u8 * 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 };
u8 PatchData[32] = { 0x4E, 0x80, 0x00, 0x20, 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 };
return PatchDOL(Address, Size, (const u8 *) &SearchPattern, sizeof(SearchPattern), (const u8 *) &PatchData, sizeof(PatchData));
}
else if (memcmp("SMN", (char *)0x80000000, 3) == 0)
{
u8 SearchPattern[4] = { 0x7A, 0x6B, 0x6F, 0x6A };
u8 PatchData[32] = { 0x4E, 0x80, 0x00, 0x20, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x34, 0x39, 0x61, 0x00, 0x30, 0x48, 0x12, 0xD9, 0x39, 0x7C, 0x7B, 0x1B, 0x78, 0x7C, 0x9C, 0x23, 0x78, 0x7C, 0xBD, 0x2B, 0x78 };
return PatchDOL(Address, Size, (const u8 *) &SearchPattern, sizeof(SearchPattern), (const u8 *) &PatchData, sizeof(PatchData));
}
return false;
}
bool PoPPatch()
{
if (memcmp("SPX", (char *)0x80000000, 3) == 0 || memcmp("RPW", (char *)0x80000000, 3) == 0)
{
WIP_Code * CodeList = malloc(5*sizeof(WIP_Code));
CodeList[0].offset = 0x007AAC6A; CodeList[0].srcaddress = 0x7A6B6F6A; CodeList[0].dstaddress = 0x6F6A7A6B;
CodeList[1].offset = 0x007AAC75; CodeList[1].srcaddress = 0x7C7A6939; CodeList[1].dstaddress = 0x69397C7A;
CodeList[2].offset = 0x007AAC82; CodeList[2].srcaddress = 0x7376686B; CodeList[2].dstaddress = 0x686B7376;
CodeList[3].offset = 0x007AAC92; CodeList[3].srcaddress = 0x80717570; CodeList[3].dstaddress = 0x75708071;
CodeList[4].offset = 0x007AAC9D; CodeList[4].srcaddress = 0x82806F3F; CodeList[4].dstaddress = 0x6F3F8280;
if(set_wip_list(CodeList, 5) == false)
{
free(CodeList);
CodeList = NULL;
}
}
return false;
}
/** Insert the individual gamepatches above with the patterns and patch data **/
/** Following is only the VideoPatcher **/
#if 0 /** Isn't used right now **/
static GXRModeObj* vmodes[] = {
&TVNtsc240Ds,
&TVNtsc240DsAa,
&TVNtsc240Int,
&TVNtsc240IntAa,
&TVNtsc480IntDf,
&TVNtsc480IntAa,
&TVNtsc480Prog,
&TVMpal480IntDf,
&TVPal264Ds,
&TVPal264DsAa,
&TVPal264Int,
&TVPal264IntAa,
&TVPal524IntAa,
&TVPal528Int,
&TVPal528IntDf,
&TVPal574IntDfScale,
&TVEurgb60Hz240Ds,
&TVEurgb60Hz240DsAa,
&TVEurgb60Hz240Int,
&TVEurgb60Hz240IntAa,
&TVEurgb60Hz480Int,
&TVEurgb60Hz480IntDf,
&TVEurgb60Hz480IntAa,
&TVEurgb60Hz480Prog,
&TVEurgb60Hz480ProgSoft,
&TVEurgb60Hz480ProgAa
};
#endif
static GXRModeObj* PAL2NTSC[]={
&TVMpal480IntDf, &TVNtsc480IntDf,
&TVPal264Ds, &TVNtsc240Ds,
&TVPal264DsAa, &TVNtsc240DsAa,
&TVPal264Int, &TVNtsc240Int,
&TVPal264IntAa, &TVNtsc240IntAa,
&TVPal524IntAa, &TVNtsc480IntAa,
&TVPal528Int, &TVNtsc480IntAa,
&TVPal528IntDf, &TVNtsc480IntDf,
&TVPal574IntDfScale, &TVNtsc480IntDf,
&TVEurgb60Hz240Ds, &TVNtsc240Ds,
&TVEurgb60Hz240DsAa, &TVNtsc240DsAa,
&TVEurgb60Hz240Int, &TVNtsc240Int,
&TVEurgb60Hz240IntAa, &TVNtsc240IntAa,
&TVEurgb60Hz480Int, &TVNtsc480IntAa,
&TVEurgb60Hz480IntDf, &TVNtsc480IntDf,
&TVEurgb60Hz480IntAa, &TVNtsc480IntAa,
&TVEurgb60Hz480Prog, &TVNtsc480Prog,
&TVEurgb60Hz480ProgSoft,&TVNtsc480Prog,
&TVEurgb60Hz480ProgAa, &TVNtsc480Prog,
0,0
};
static GXRModeObj* NTSC2PAL[]={
&TVNtsc240Ds, &TVPal264Ds,
&TVNtsc240DsAa, &TVPal264DsAa,
&TVNtsc240Int, &TVPal264Int,
&TVNtsc240IntAa, &TVPal264IntAa,
&TVNtsc480IntDf, &TVPal528IntDf,
&TVNtsc480IntAa, &TVPal524IntAa,
&TVNtsc480Prog, &TVPal528IntDf,
0,0
};
static GXRModeObj* NTSC2PAL60[]={
&TVNtsc240Ds, &TVEurgb60Hz240Ds,
&TVNtsc240DsAa, &TVEurgb60Hz240DsAa,
&TVNtsc240Int, &TVEurgb60Hz240Int,
&TVNtsc240IntAa, &TVEurgb60Hz240IntAa,
&TVNtsc480IntDf, &TVEurgb60Hz480IntDf,
&TVNtsc480IntAa, &TVEurgb60Hz480IntAa,
&TVNtsc480Prog, &TVEurgb60Hz480Prog,
0,0
};
static bool compare_videomodes(GXRModeObj* mode1, GXRModeObj* mode2)
{
if (mode1->viTVMode != mode2->viTVMode || mode1->fbWidth != mode2->fbWidth || mode1->efbHeight != mode2->efbHeight || mode1->xfbHeight != mode2->xfbHeight ||
mode1->viXOrigin != mode2->viXOrigin || mode1->viYOrigin != mode2->viYOrigin || mode1->viWidth != mode2->viWidth || mode1->viHeight != mode2->viHeight ||
mode1->xfbMode != mode2->xfbMode || mode1->field_rendering != mode2->field_rendering || mode1->aa != mode2->aa || mode1->sample_pattern[0][0] != mode2->sample_pattern[0][0] ||
mode1->sample_pattern[1][0] != mode2->sample_pattern[1][0] || mode1->sample_pattern[2][0] != mode2->sample_pattern[2][0] ||
mode1->sample_pattern[3][0] != mode2->sample_pattern[3][0] || mode1->sample_pattern[4][0] != mode2->sample_pattern[4][0] ||
mode1->sample_pattern[5][0] != mode2->sample_pattern[5][0] || mode1->sample_pattern[6][0] != mode2->sample_pattern[6][0] ||
mode1->sample_pattern[7][0] != mode2->sample_pattern[7][0] || mode1->sample_pattern[8][0] != mode2->sample_pattern[8][0] ||
mode1->sample_pattern[9][0] != mode2->sample_pattern[9][0] || mode1->sample_pattern[10][0] != mode2->sample_pattern[10][0] ||
mode1->sample_pattern[11][0] != mode2->sample_pattern[11][0] || mode1->sample_pattern[0][1] != mode2->sample_pattern[0][1] ||
mode1->sample_pattern[1][1] != mode2->sample_pattern[1][1] || mode1->sample_pattern[2][1] != mode2->sample_pattern[2][1] ||
mode1->sample_pattern[3][1] != mode2->sample_pattern[3][1] || mode1->sample_pattern[4][1] != mode2->sample_pattern[4][1] ||
mode1->sample_pattern[5][1] != mode2->sample_pattern[5][1] || mode1->sample_pattern[6][1] != mode2->sample_pattern[6][1] ||
mode1->sample_pattern[7][1] != mode2->sample_pattern[7][1] || mode1->sample_pattern[8][1] != mode2->sample_pattern[8][1] ||
mode1->sample_pattern[9][1] != mode2->sample_pattern[9][1] || mode1->sample_pattern[10][1] != mode2->sample_pattern[10][1] ||
mode1->sample_pattern[11][1] != mode2->sample_pattern[11][1] || mode1->vfilter[0] != mode2->vfilter[0] ||
mode1->vfilter[1] != mode2->vfilter[1] || mode1->vfilter[2] != mode2->vfilter[2] || mode1->vfilter[3] != mode2->vfilter[3] || mode1->vfilter[4] != mode2->vfilter[4] ||
mode1->vfilter[5] != mode2->vfilter[5] || mode1->vfilter[6] != mode2->vfilter[6] ) {
return false;
} else {
return true;
}
}
static void patch_videomode(GXRModeObj* mode1, GXRModeObj* mode2)
{
mode1->viTVMode = mode2->viTVMode;
mode1->fbWidth = mode2->fbWidth;
mode1->efbHeight = mode2->efbHeight;
mode1->xfbHeight = mode2->xfbHeight;
mode1->viXOrigin = mode2->viXOrigin;
mode1->viYOrigin = mode2->viYOrigin;
mode1->viWidth = mode2->viWidth;
mode1->viHeight = mode2->viHeight;
mode1->xfbMode = mode2->xfbMode;
mode1->field_rendering = mode2->field_rendering;
mode1->aa = mode2->aa;
mode1->sample_pattern[0][0] = mode2->sample_pattern[0][0];
mode1->sample_pattern[1][0] = mode2->sample_pattern[1][0];
mode1->sample_pattern[2][0] = mode2->sample_pattern[2][0];
mode1->sample_pattern[3][0] = mode2->sample_pattern[3][0];
mode1->sample_pattern[4][0] = mode2->sample_pattern[4][0];
mode1->sample_pattern[5][0] = mode2->sample_pattern[5][0];
mode1->sample_pattern[6][0] = mode2->sample_pattern[6][0];
mode1->sample_pattern[7][0] = mode2->sample_pattern[7][0];
mode1->sample_pattern[8][0] = mode2->sample_pattern[8][0];
mode1->sample_pattern[9][0] = mode2->sample_pattern[9][0];
mode1->sample_pattern[10][0] = mode2->sample_pattern[10][0];
mode1->sample_pattern[11][0] = mode2->sample_pattern[11][0];
mode1->sample_pattern[0][1] = mode2->sample_pattern[0][1];
mode1->sample_pattern[1][1] = mode2->sample_pattern[1][1];
mode1->sample_pattern[2][1] = mode2->sample_pattern[2][1];
mode1->sample_pattern[3][1] = mode2->sample_pattern[3][1];
mode1->sample_pattern[4][1] = mode2->sample_pattern[4][1];
mode1->sample_pattern[5][1] = mode2->sample_pattern[5][1];
mode1->sample_pattern[6][1] = mode2->sample_pattern[6][1];
mode1->sample_pattern[7][1] = mode2->sample_pattern[7][1];
mode1->sample_pattern[8][1] = mode2->sample_pattern[8][1];
mode1->sample_pattern[9][1] = mode2->sample_pattern[9][1];
mode1->sample_pattern[10][1] = mode2->sample_pattern[10][1];
mode1->sample_pattern[11][1] = mode2->sample_pattern[11][1];
mode1->vfilter[0] = mode2->vfilter[0];
mode1->vfilter[1] = mode2->vfilter[1];
mode1->vfilter[2] = mode2->vfilter[2];
mode1->vfilter[3] = mode2->vfilter[3];
mode1->vfilter[4] = mode2->vfilter[4];
mode1->vfilter[5] = mode2->vfilter[5];
mode1->vfilter[6] = mode2->vfilter[6];
}
static bool Search_and_patch_Video_Modes(u8 * Address, u32 Size, GXRModeObj* Table[])
{
u8 *Addr = (u8 *)Address;
bool found = 0;
u32 i;
while (Size >= sizeof(GXRModeObj)) {
for (i = 0; Table[i]; i+=2) {
if (compare_videomodes(Table[i], (GXRModeObj*)Addr))
{
found = 1;
patch_videomode((GXRModeObj*)Addr, Table[i+1]);
Addr += (sizeof(GXRModeObj)-4);
Size -= (sizeof(GXRModeObj)-4);
break;
}
}
Addr += 4;
Size -= 4;
}
return found;
}
void VideoModePatcher(u8 * dst, int len, u8 videoSelected)
{
GXRModeObj** table = NULL;
if (videoSelected == 5) // patch
{
switch (CONF_GetVideo()) {
case CONF_VIDEO_PAL:
if (CONF_GetEuRGB60() > 0) {
table = NTSC2PAL60;
} else {
table = NTSC2PAL;
}
break;
case CONF_VIDEO_MPAL:
table = NTSC2PAL;
break;
default:
table = PAL2NTSC;
break;
}
Search_and_patch_Video_Modes(dst, len, table);
}
}

View File

@ -0,0 +1,12 @@
#ifndef GAMEPATCHES_H_
#define GAMEPATCHES_H_
#include <gccore.h>
bool Anti_002_fix(u8 * Address, int Size);
bool NSMBPatch(u8 * Address, int Size);
bool PoPPatch();
bool Search_and_patch_Video_Modes(u8 * Address, u32 Size, GXRModeObj* Table[]);
void VideoModePatcher(u8 * dst, int len, u8 videoSelected);
#endif

View File

@ -5,13 +5,7 @@
#include "gecko.h"
#include "settings/cfg.h"
typedef struct
{
u32 offset;
u32 srcaddress;
u32 dstaddress;
} WIP_Code;
#include "wip.h"
static WIP_Code * CodeList = NULL;
static u32 CodesCount = 0;
@ -58,6 +52,22 @@ void do_wip_code(u8 * dst, u32 len)
Counter++;
}
//! for internal patches only
//! .wip files override internal patches
//! the codelist has to be freed if the set fails
//! if set was successful the codelist will be freed when it's done
bool set_wip_list(WIP_Code * list, int size)
{
if(!CodeList && size > 0)
{
CodeList = list;
CodesCount = size;
return true;
}
return false;
}
void wip_reset_counter()
{
ProcessedLength = 0;
@ -71,6 +81,7 @@ void free_wip()
free(CodeList);
CodeList = NULL;
CodesCount = 0;
Counter = 0;
ProcessedLength = 0;
}
@ -86,6 +97,13 @@ int load_wip_code(u8 *gameid)
if (!fp)
{
memset(GameID, 0, sizeof(GameID));
memcpy(GameID, gameid, 4);
snprintf(filepath, sizeof(filepath), "%s%s.wip", Settings.WipCodepath, GameID);
fp = fopen(filepath, "rb");
}
if (!fp)
{
memset(GameID, 0, sizeof(GameID));
memcpy(GameID, gameid, 3);
snprintf(filepath, sizeof(filepath), "%s%s.wip", Settings.WipCodepath, GameID);
fp = fopen(filepath, "rb");
@ -100,6 +118,8 @@ int load_wip_code(u8 *gameid)
while (fgets(line, sizeof(line), fp))
{
if (line[0] == '#') continue;
if (line[0] == ';') continue;
if (line[0] == ':') continue;
if(strlen(line) < 26) continue;
@ -113,10 +133,8 @@ int load_wip_code(u8 *gameid)
WIP_Code * tmp = realloc(CodeList, (CodesCount+1)*sizeof(WIP_Code));
if(!tmp)
{
if(CodeList)
free(CodeList);
CodeList = NULL;
fclose(fp);
free_wip();
return -1;
}

View File

@ -1,8 +1,18 @@
#ifndef __WIP_H__
#define __WIP_H__
#include <gccore.h>
typedef struct
{
u32 offset;
u32 srcaddress;
u32 dstaddress;
} WIP_Code;
int load_wip_code(u8 *gameid);
void do_wip_code(u8 * dst, u32 len);
bool set_wip_list(WIP_Code * list, int size);
void wip_reset_counter();
void free_wip();

View File

@ -13,6 +13,8 @@
#include "settings/cfg.h"
#include "gecko.h"
#include "patches/wip.h"
#include "patches/dolpatcher.h"
#include "patches/gamepatches.h"
extern bool geckoinit;
@ -31,276 +33,12 @@ static u8 *appldr = (u8 *)0x81200000;
/* Variables */
static u32 buffer[0x20] ATTRIBUTE_ALIGN(32);
struct SSettings Settings;
static void __noprint(const char *fmt, ...) {
}
static void __noprint(const char *fmt, ...) { }
bool compare_videomodes(GXRModeObj* mode1, GXRModeObj* mode2) {
if (mode1->viTVMode != mode2->viTVMode || mode1->fbWidth != mode2->fbWidth || mode1->efbHeight != mode2->efbHeight || mode1->xfbHeight != mode2->xfbHeight ||
mode1->viXOrigin != mode2->viXOrigin || mode1->viYOrigin != mode2->viYOrigin || mode1->viWidth != mode2->viWidth || mode1->viHeight != mode2->viHeight ||
mode1->xfbMode != mode2->xfbMode || mode1->field_rendering != mode2->field_rendering || mode1->aa != mode2->aa || mode1->sample_pattern[0][0] != mode2->sample_pattern[0][0] ||
mode1->sample_pattern[1][0] != mode2->sample_pattern[1][0] || mode1->sample_pattern[2][0] != mode2->sample_pattern[2][0] ||
mode1->sample_pattern[3][0] != mode2->sample_pattern[3][0] || mode1->sample_pattern[4][0] != mode2->sample_pattern[4][0] ||
mode1->sample_pattern[5][0] != mode2->sample_pattern[5][0] || mode1->sample_pattern[6][0] != mode2->sample_pattern[6][0] ||
mode1->sample_pattern[7][0] != mode2->sample_pattern[7][0] || mode1->sample_pattern[8][0] != mode2->sample_pattern[8][0] ||
mode1->sample_pattern[9][0] != mode2->sample_pattern[9][0] || mode1->sample_pattern[10][0] != mode2->sample_pattern[10][0] ||
mode1->sample_pattern[11][0] != mode2->sample_pattern[11][0] || mode1->sample_pattern[0][1] != mode2->sample_pattern[0][1] ||
mode1->sample_pattern[1][1] != mode2->sample_pattern[1][1] || mode1->sample_pattern[2][1] != mode2->sample_pattern[2][1] ||
mode1->sample_pattern[3][1] != mode2->sample_pattern[3][1] || mode1->sample_pattern[4][1] != mode2->sample_pattern[4][1] ||
mode1->sample_pattern[5][1] != mode2->sample_pattern[5][1] || mode1->sample_pattern[6][1] != mode2->sample_pattern[6][1] ||
mode1->sample_pattern[7][1] != mode2->sample_pattern[7][1] || mode1->sample_pattern[8][1] != mode2->sample_pattern[8][1] ||
mode1->sample_pattern[9][1] != mode2->sample_pattern[9][1] || mode1->sample_pattern[10][1] != mode2->sample_pattern[10][1] ||
mode1->sample_pattern[11][1] != mode2->sample_pattern[11][1] || mode1->vfilter[0] != mode2->vfilter[0] ||
mode1->vfilter[1] != mode2->vfilter[1] || mode1->vfilter[2] != mode2->vfilter[2] || mode1->vfilter[3] != mode2->vfilter[3] || mode1->vfilter[4] != mode2->vfilter[4] ||
mode1->vfilter[5] != mode2->vfilter[5] || mode1->vfilter[6] != mode2->vfilter[6] ) {
return false;
} else {
return true;
}
}
void patch_videomode(GXRModeObj* mode1, GXRModeObj* mode2) {
mode1->viTVMode = mode2->viTVMode;
mode1->fbWidth = mode2->fbWidth;
mode1->efbHeight = mode2->efbHeight;
mode1->xfbHeight = mode2->xfbHeight;
mode1->viXOrigin = mode2->viXOrigin;
mode1->viYOrigin = mode2->viYOrigin;
mode1->viWidth = mode2->viWidth;
mode1->viHeight = mode2->viHeight;
mode1->xfbMode = mode2->xfbMode;
mode1->field_rendering = mode2->field_rendering;
mode1->aa = mode2->aa;
mode1->sample_pattern[0][0] = mode2->sample_pattern[0][0];
mode1->sample_pattern[1][0] = mode2->sample_pattern[1][0];
mode1->sample_pattern[2][0] = mode2->sample_pattern[2][0];
mode1->sample_pattern[3][0] = mode2->sample_pattern[3][0];
mode1->sample_pattern[4][0] = mode2->sample_pattern[4][0];
mode1->sample_pattern[5][0] = mode2->sample_pattern[5][0];
mode1->sample_pattern[6][0] = mode2->sample_pattern[6][0];
mode1->sample_pattern[7][0] = mode2->sample_pattern[7][0];
mode1->sample_pattern[8][0] = mode2->sample_pattern[8][0];
mode1->sample_pattern[9][0] = mode2->sample_pattern[9][0];
mode1->sample_pattern[10][0] = mode2->sample_pattern[10][0];
mode1->sample_pattern[11][0] = mode2->sample_pattern[11][0];
mode1->sample_pattern[0][1] = mode2->sample_pattern[0][1];
mode1->sample_pattern[1][1] = mode2->sample_pattern[1][1];
mode1->sample_pattern[2][1] = mode2->sample_pattern[2][1];
mode1->sample_pattern[3][1] = mode2->sample_pattern[3][1];
mode1->sample_pattern[4][1] = mode2->sample_pattern[4][1];
mode1->sample_pattern[5][1] = mode2->sample_pattern[5][1];
mode1->sample_pattern[6][1] = mode2->sample_pattern[6][1];
mode1->sample_pattern[7][1] = mode2->sample_pattern[7][1];
mode1->sample_pattern[8][1] = mode2->sample_pattern[8][1];
mode1->sample_pattern[9][1] = mode2->sample_pattern[9][1];
mode1->sample_pattern[10][1] = mode2->sample_pattern[10][1];
mode1->sample_pattern[11][1] = mode2->sample_pattern[11][1];
mode1->vfilter[0] = mode2->vfilter[0];
mode1->vfilter[1] = mode2->vfilter[1];
mode1->vfilter[2] = mode2->vfilter[2];
mode1->vfilter[3] = mode2->vfilter[3];
mode1->vfilter[4] = mode2->vfilter[4];
mode1->vfilter[5] = mode2->vfilter[5];
mode1->vfilter[6] = mode2->vfilter[6];
}
GXRModeObj* vmodes[] = {
&TVNtsc240Ds,
&TVNtsc240DsAa,
&TVNtsc240Int,
&TVNtsc240IntAa,
&TVNtsc480IntDf,
&TVNtsc480IntAa,
&TVNtsc480Prog,
&TVMpal480IntDf,
&TVPal264Ds,
&TVPal264DsAa,
&TVPal264Int,
&TVPal264IntAa,
&TVPal524IntAa,
&TVPal528Int,
&TVPal528IntDf,
&TVPal574IntDfScale,
&TVEurgb60Hz240Ds,
&TVEurgb60Hz240DsAa,
&TVEurgb60Hz240Int,
&TVEurgb60Hz240IntAa,
&TVEurgb60Hz480Int,
&TVEurgb60Hz480IntDf,
&TVEurgb60Hz480IntAa,
&TVEurgb60Hz480Prog,
&TVEurgb60Hz480ProgSoft,
&TVEurgb60Hz480ProgAa
};
GXRModeObj* PAL2NTSC[]={
&TVMpal480IntDf, &TVNtsc480IntDf,
&TVPal264Ds, &TVNtsc240Ds,
&TVPal264DsAa, &TVNtsc240DsAa,
&TVPal264Int, &TVNtsc240Int,
&TVPal264IntAa, &TVNtsc240IntAa,
&TVPal524IntAa, &TVNtsc480IntAa,
&TVPal528Int, &TVNtsc480IntAa,
&TVPal528IntDf, &TVNtsc480IntDf,
&TVPal574IntDfScale, &TVNtsc480IntDf,
&TVEurgb60Hz240Ds, &TVNtsc240Ds,
&TVEurgb60Hz240DsAa, &TVNtsc240DsAa,
&TVEurgb60Hz240Int, &TVNtsc240Int,
&TVEurgb60Hz240IntAa, &TVNtsc240IntAa,
&TVEurgb60Hz480Int, &TVNtsc480IntAa,
&TVEurgb60Hz480IntDf, &TVNtsc480IntDf,
&TVEurgb60Hz480IntAa, &TVNtsc480IntAa,
&TVEurgb60Hz480Prog, &TVNtsc480Prog,
&TVEurgb60Hz480ProgSoft,&TVNtsc480Prog,
&TVEurgb60Hz480ProgAa, &TVNtsc480Prog,
0,0
};
GXRModeObj* NTSC2PAL[]={
&TVNtsc240Ds, &TVPal264Ds,
&TVNtsc240DsAa, &TVPal264DsAa,
&TVNtsc240Int, &TVPal264Int,
&TVNtsc240IntAa, &TVPal264IntAa,
&TVNtsc480IntDf, &TVPal528IntDf,
&TVNtsc480IntAa, &TVPal524IntAa,
&TVNtsc480Prog, &TVPal528IntDf,
0,0
};
GXRModeObj* NTSC2PAL60[]={
&TVNtsc240Ds, &TVEurgb60Hz240Ds,
&TVNtsc240DsAa, &TVEurgb60Hz240DsAa,
&TVNtsc240Int, &TVEurgb60Hz240Int,
&TVNtsc240IntAa, &TVEurgb60Hz240IntAa,
&TVNtsc480IntDf, &TVEurgb60Hz480IntDf,
&TVNtsc480IntAa, &TVEurgb60Hz480IntAa,
&TVNtsc480Prog, &TVEurgb60Hz480Prog,
0,0
};
bool Search_and_patch_Video_Modes(void *Address, u32 Size, GXRModeObj* Table[]) {
u8 *Addr = (u8 *)Address;
bool found = 0;
u32 i;
while (Size >= sizeof(GXRModeObj)) {
for (i = 0; Table[i]; i+=2) {
if (compare_videomodes(Table[i], (GXRModeObj*)Addr))
{
found = 1;
patch_videomode((GXRModeObj*)Addr, Table[i+1]);
Addr += (sizeof(GXRModeObj)-4);
Size -= (sizeof(GXRModeObj)-4);
break;
}
}
Addr += 4;
Size -= 4;
}
return found;
}
/** Anti 002 fix for IOS 249 rev > 12 thanks to WiiPower **/
void Anti_002_fix(void *Address, int Size) {
u8 SearchPattern[12] = { 0x2C, 0x00, 0x00, 0x00, 0x48, 0x00, 0x02, 0x14, 0x3C, 0x60, 0x80, 0x00 };
u8 PatchData[12] = { 0x2C, 0x00, 0x00, 0x00, 0x40, 0x82, 0x02, 0x14, 0x3C, 0x60, 0x80, 0x00 };
void *Addr = Address;
void *Addr_end = Address+Size;
while (Addr <= Addr_end-sizeof(SearchPattern)) {
if (memcmp(Addr, SearchPattern, sizeof(SearchPattern))==0) {
memcpy(Addr,PatchData,sizeof(PatchData));
}
Addr += 4;
}
}
/** Thanks to WiiPower **/
bool NewSuperMarioBrosPatch(void *Address, int Size)
void gamepatches(void * dst, int len, u8 videoSelected, u8 patchcountrystring, u8 vipatch, u8 cheat)
{
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 };
u8 PatchData[32] = { 0x4E, 0x80, 0x00, 0x20, 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 };
void *Addr = Address;
void *Addr_end = Address+Size;
while(Addr <= Addr_end-sizeof(SearchPattern))
{
if(memcmp(Addr, SearchPattern, sizeof(SearchPattern))==0)
{
memcpy(Addr,PatchData,sizeof(PatchData));
return true;
}
Addr += 4;
}
}
else if (memcmp("SMN", (char *)0x80000000, 3) == 0)
{
u8 SearchPattern[32] = { 0x94, 0x21, 0xFF, 0xD0, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x34, 0x39, 0x61, 0x00, 0x30, 0x48, 0x12, 0xD9, 0x39, 0x7C, 0x7B, 0x1B, 0x78, 0x7C, 0x9C, 0x23, 0x78, 0x7C, 0xBD, 0x2B, 0x78 };
u8 PatchData[32] = { 0x4E, 0x80, 0x00, 0x20, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x34, 0x39, 0x61, 0x00, 0x30, 0x48, 0x12, 0xD9, 0x39, 0x7C, 0x7B, 0x1B, 0x78, 0x7C, 0x9C, 0x23, 0x78, 0x7C, 0xBD, 0x2B, 0x78 };
void *Addr = Address;
void *Addr_end = Address+Size;
while(Addr <= Addr_end-sizeof(SearchPattern))
{
if(memcmp(Addr, SearchPattern, sizeof(SearchPattern))==0)
{
memcpy(Addr,PatchData,sizeof(PatchData));
return true;
}
Addr += 4;
}
}
return false;
}
void gamepatches(void * dst, int len, u8 videoSelected, u8 patchcountrystring, u8 vipatch, u8 cheat) {
GXRModeObj** table = NULL;
if (videoSelected == 5) // patch
{
switch (CONF_GetVideo()) {
case CONF_VIDEO_PAL:
if (CONF_GetEuRGB60() > 0) {
table = NTSC2PAL60;
} else {
table = NTSC2PAL;
}
break;
case CONF_VIDEO_MPAL:
table = NTSC2PAL;
break;
default:
table = PAL2NTSC;
break;
}
Search_and_patch_Video_Modes(dst, len, table);
}
VideoModePatcher(dst, len, videoSelected);
if(cheat)
dogamehooks(dst,len);
@ -315,7 +53,7 @@ void gamepatches(void * dst, int len, u8 videoSelected, u8 patchcountrystring, u
if (patchcountrystring == 1)
PatchCountryStrings(dst, len);
NewSuperMarioBrosPatch(dst, len);
NSMBPatch(dst, len);
do_wip_code((u8 *) dst, len);
@ -331,7 +69,7 @@ s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8
u32 appldr_len;
s32 ret;
gprintf("\nApploader_Run() started");
gprintf("\nApploader_Run() started\n");
//u32 geckoattached = usb_isgeckoalive(EXI_CHANNEL_1);
//if (geckoattached)usb_flush(EXI_CHANNEL_1);
@ -359,13 +97,14 @@ s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8
/* Initialize apploader */
appldr_init(__noprint);
if (error002fix!=0) {
if (error002fix!=0)
{
/* ERROR 002 fix (thanks to WiiPower for sharing this)*/
*(u32 *)0x80003188 = *(u32 *)0x80003140;
// *(u32 *)0x80003140 = *(u32 *)0x80003188;
}
for (;;) {
for (;;)
{
void *dst = NULL;
int len = 0, offset = 0;
@ -384,17 +123,15 @@ s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8
*entry = appldr_final();
/** Load alternate dol if set **/
if (alternatedol == 1) {
// gprintf("\n\talt dol from FAT");
if (alternatedol == 1)
{
wip_reset_counter();
void *dolbuffer;
int dollen;
void *dolbuffer = NULL;
int dollen = 0;
bool dolloaded = Load_Dol(&dolbuffer, &dollen, Settings.dolpath, videoSelected, patchcountrystring, vipatch, cheat);
if (dolloaded)
{
DCFlushRange(dolbuffer, dollen);
/* Set entry point from apploader */
*entry = (entry_point) load_dol_image(dolbuffer);
}

View File

@ -6,6 +6,7 @@
#include <wiiuse/wpad.h>
#include "patches/fst.h"
#include "patches/gamepatches.h"
#include "patches/wip.h"
#include "apploader.h"
#include "disc.h"
@ -284,14 +285,17 @@ s32 Disc_BootPartition(u64 offset, u8 videoselected, u8 cheat, u8 vipatch, u8 pa
if (ret < 0)
return ret;
/* Setup low memory */
__Disc_SetLowMem();
char gameid[8];
memset(gameid, 0, 8);
memcpy(gameid, (char*)Disc_ID, 6);
load_wip_code((u8 *) &gameid);
/* Setup low memory */
__Disc_SetLowMem();
/* If a wip file is loaded for this game this does nothing - Dimok */
PoPPatch();
/* Run apploader */
ret = Apploader_Run(&p_entry, cheat, videoselected, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset);