2009-05-03 20:53:31 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ogcsys.h>
|
2009-07-30 07:41:12 +02:00
|
|
|
#include <ogc/lwp_watchdog.h>
|
|
|
|
|
2010-05-30 16:18:25 +02:00
|
|
|
#include "patches/gamepatches.h"
|
2010-05-29 17:43:19 +02:00
|
|
|
#include "patches/wip.h"
|
2009-05-03 20:53:31 +02:00
|
|
|
#include "apploader.h"
|
|
|
|
#include "disc.h"
|
2010-05-29 09:38:54 +02:00
|
|
|
#include "video.h"
|
2009-07-30 07:41:12 +02:00
|
|
|
#include "wdvd.h"
|
2010-11-07 13:16:34 +01:00
|
|
|
#include "frag.h"
|
2009-10-21 01:00:19 +02:00
|
|
|
#include "alternatedol.h"
|
2010-11-06 16:30:14 +01:00
|
|
|
#include "memory/memory.h"
|
2009-12-19 15:05:31 +01:00
|
|
|
#include "wbfs.h"
|
2010-10-27 16:45:27 +02:00
|
|
|
#include "../settings/SettingsEnums.h"
|
2010-05-29 09:38:54 +02:00
|
|
|
#include "../gecko.h"
|
2010-02-27 19:18:01 +01:00
|
|
|
|
2011-11-12 19:14:09 +01:00
|
|
|
// Global app entry point
|
|
|
|
extern u32 AppEntrypoint;
|
|
|
|
|
2009-05-03 20:53:31 +02:00
|
|
|
/* Constants */
|
2010-09-19 01:16:05 +02:00
|
|
|
#define PTABLE_OFFSET 0x40000
|
|
|
|
#define WII_MAGIC 0x5D1C9EA3
|
2009-05-03 20:53:31 +02:00
|
|
|
|
|
|
|
/* Disc pointers */
|
2010-09-24 02:48:03 +02:00
|
|
|
static u32 *buffer = (u32 *) 0x93000000;
|
|
|
|
static u8 *diskid = (u8 *) Disc_ID;
|
2011-03-14 22:19:21 +01:00
|
|
|
static GXRModeObj *vmode = NULL;
|
|
|
|
static u32 vmode_reg = 0;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-03-14 22:19:21 +01:00
|
|
|
void Disc_SetLowMem(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Setup low memory */
|
|
|
|
*Sys_Magic = 0x0D15EA5E; // Standard Boot Code
|
|
|
|
*Version = 0x00000001; // Version
|
|
|
|
*Arena_L = 0x00000000; // Arena Low
|
|
|
|
*BI2 = 0x817E5480; // BI2
|
|
|
|
*Bus_Speed = 0x0E7BE2C0; // Console Bus Speed
|
|
|
|
*CPU_Speed = 0x2B73A840; // Console CPU Speed
|
|
|
|
|
|
|
|
/* Setup low memory */
|
|
|
|
*Assembler = 0x38A00040; // Assembler
|
|
|
|
*(u32 *) 0x800000E4 = 0x80431A80;
|
|
|
|
*Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address
|
|
|
|
*Simulated_Mem = 0x01800000; // Simulated Memory Size
|
|
|
|
*(vu32 *) 0xCD00643C = 0x00000000; // 32Mhz on Bus
|
|
|
|
|
|
|
|
int iosVer = IOS_GetVersion();
|
|
|
|
if(iosVer != 222 && iosVer != 223 && iosVer != 224 && iosVer != 225 && IOS_GetRevision() >= 18)
|
|
|
|
*GameID_Address = 0x80000000; // Game ID Address
|
|
|
|
|
|
|
|
/* Copy disc ID */
|
|
|
|
memcpy((void *) Online_Check, (void *) Disc_ID, 4);
|
|
|
|
|
|
|
|
/* Flush cache */
|
|
|
|
DCFlushRange((void *) Disc_ID, 0x3F00);
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2011-03-14 22:19:21 +01:00
|
|
|
void Disc_SelectVMode(u8 videoselected)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
vmode = VIDEO_GetPreferredMode(0);
|
2011-03-14 22:19:21 +01:00
|
|
|
|
|
|
|
/* Get video mode configuration */
|
|
|
|
bool progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable();
|
2011-12-20 22:41:00 +01:00
|
|
|
u32 tvmode = CONF_GetVideo();
|
2011-03-14 22:19:21 +01:00
|
|
|
|
|
|
|
/* Select video mode register */
|
2011-12-20 22:41:00 +01:00
|
|
|
switch (tvmode)
|
2011-03-14 22:19:21 +01:00
|
|
|
{
|
|
|
|
case CONF_VIDEO_PAL:
|
|
|
|
if (CONF_GetEuRGB60() > 0)
|
|
|
|
{
|
|
|
|
vmode_reg = VI_EURGB60;
|
|
|
|
vmode = progressive ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vmode_reg = VI_PAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONF_VIDEO_MPAL:
|
|
|
|
vmode_reg = VI_MPAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONF_VIDEO_NTSC:
|
|
|
|
vmode_reg = VI_NTSC;
|
|
|
|
break;
|
|
|
|
}
|
2009-07-30 07:41:12 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
switch (videoselected)
|
2011-03-14 22:19:21 +01:00
|
|
|
{
|
|
|
|
default:
|
|
|
|
case VIDEO_MODE_DISCDEFAULT: // DEFAULT (DISC/GAME)
|
|
|
|
/* Select video mode */
|
|
|
|
switch (diskid[3])
|
|
|
|
{
|
|
|
|
// PAL
|
|
|
|
case 'D':
|
|
|
|
case 'F':
|
|
|
|
case 'P':
|
|
|
|
case 'X':
|
|
|
|
case 'Y':
|
2011-12-20 22:41:00 +01:00
|
|
|
if (tvmode != CONF_VIDEO_PAL)
|
2011-03-14 22:19:21 +01:00
|
|
|
{
|
|
|
|
vmode_reg = VI_PAL;
|
|
|
|
vmode = progressive ? &TVNtsc480Prog : &TVNtsc480IntDf;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// NTSC
|
|
|
|
case 'E':
|
|
|
|
case 'J':
|
|
|
|
default:
|
2011-12-20 22:41:00 +01:00
|
|
|
if (tvmode != CONF_VIDEO_NTSC)
|
2011-03-14 22:19:21 +01:00
|
|
|
{
|
|
|
|
vmode_reg = VI_NTSC;
|
|
|
|
vmode = progressive ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VIDEO_MODE_PAL50: // PAL50
|
|
|
|
vmode = &TVPal528IntDf;
|
|
|
|
vmode_reg = vmode->viTVMode >> 2;
|
|
|
|
break;
|
|
|
|
case VIDEO_MODE_PAL60: // PAL60
|
|
|
|
vmode = progressive ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf;
|
|
|
|
vmode_reg = progressive ? TVEurgb60Hz480Prog.viTVMode >> 2 : vmode->viTVMode >> 2;
|
|
|
|
break;
|
|
|
|
case VIDEO_MODE_NTSC: // NTSC
|
|
|
|
vmode = progressive ? &TVNtsc480Prog : &TVNtsc480IntDf;
|
|
|
|
vmode_reg = vmode->viTVMode >> 2;
|
|
|
|
break;
|
2011-07-26 00:28:22 +02:00
|
|
|
case VIDEO_MODE_PAL480P:
|
|
|
|
vmode = &TVNtsc480Prog;
|
2011-12-20 22:41:00 +01:00
|
|
|
vmode_reg = TVEurgb60Hz480Prog.viTVMode >> 2;
|
2011-07-26 00:28:22 +02:00
|
|
|
break;
|
|
|
|
case VIDEO_MODE_NTSC480P:
|
|
|
|
vmode = &TVNtsc480Prog;
|
2011-12-20 22:41:00 +01:00
|
|
|
vmode_reg = vmode->viTVMode >> 2;
|
2011-07-26 00:28:22 +02:00
|
|
|
break;
|
2011-03-14 22:19:21 +01:00
|
|
|
case VIDEO_MODE_SYSDEFAULT: // AUTO PATCH TO SYSTEM
|
|
|
|
break;
|
2010-09-30 07:45:21 +02:00
|
|
|
}
|
2011-03-14 22:19:21 +01:00
|
|
|
}
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-03-14 22:19:21 +01:00
|
|
|
void __Disc_SetVMode(void)
|
|
|
|
{
|
|
|
|
/* Set video mode register */
|
|
|
|
*Video_Mode = vmode_reg;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-03-14 22:19:21 +01:00
|
|
|
/* Set video mode */
|
|
|
|
if (vmode != NULL)
|
2011-06-18 09:00:42 +02:00
|
|
|
{
|
2011-03-14 22:19:21 +01:00
|
|
|
VIDEO_Configure(vmode);
|
2011-06-18 09:00:42 +02:00
|
|
|
}
|
2010-02-27 19:18:01 +01:00
|
|
|
|
2011-03-14 22:19:21 +01:00
|
|
|
/* Setup video */
|
2011-06-18 09:00:42 +02:00
|
|
|
VIDEO_SetBlack(TRUE);
|
2011-03-14 22:19:21 +01:00
|
|
|
VIDEO_Flush();
|
|
|
|
VIDEO_WaitVSync();
|
|
|
|
if (vmode->viTVMode & VI_NON_INTERLACE)
|
|
|
|
VIDEO_WaitVSync();
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
void __Disc_SetTime(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Extern */
|
|
|
|
extern void settime(u64);
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Set proper time */
|
|
|
|
settime(secs_to_ticks( time( NULL ) - 946684800 ));
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2011-03-14 22:19:21 +01:00
|
|
|
s32 Disc_FindPartition(u64 *outbuf)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
u64 offset = 0, table_offset = 0;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
u32 cnt, nb_partitions;
|
|
|
|
s32 ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Read partition info */
|
|
|
|
ret = WDVD_UnencryptedRead(buffer, 0x20, PTABLE_OFFSET);
|
|
|
|
if (ret < 0) return ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Get data */
|
|
|
|
nb_partitions = buffer[0];
|
|
|
|
table_offset = buffer[1] << 2;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Read partition table */
|
|
|
|
ret = WDVD_UnencryptedRead(buffer, 0x20, table_offset);
|
|
|
|
if (ret < 0) return ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Find game partition */
|
|
|
|
for (cnt = 0; cnt < nb_partitions; cnt++)
|
|
|
|
{
|
|
|
|
u32 type = buffer[cnt * 2 + 1];
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Game partition */
|
|
|
|
if (!type) offset = buffer[cnt * 2] << 2;
|
|
|
|
}
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* No game partition found */
|
|
|
|
if (!offset) return -1;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Set output buffer */
|
|
|
|
*outbuf = offset;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
return 0;
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
s32 Disc_Init(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Init DVD subsystem */
|
|
|
|
return WDVD_Init();
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
s32 Disc_Open(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
s32 ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Reset drive */
|
|
|
|
ret = WDVD_Reset();
|
|
|
|
if (ret < 0) return ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Read disc ID */
|
|
|
|
return WDVD_ReadDiskId(diskid);
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
s32 Disc_Wait(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
u32 cover = 0;
|
|
|
|
s32 ret;
|
|
|
|
|
|
|
|
/* Wait for disc */
|
|
|
|
while (!(cover & 0x2))
|
|
|
|
{
|
|
|
|
/* Get cover status */
|
|
|
|
ret = WDVD_GetCoverStatus(&cover);
|
|
|
|
if (ret < 0) return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
s32 Disc_SetUSB(const u8 *id)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Set USB mode */
|
|
|
|
return WDVD_SetUSBMode((u8 *) id, -1);
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
s32 Disc_ReadHeader(void *outbuf)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Read disc header */
|
|
|
|
return WDVD_UnencryptedRead(outbuf, sizeof(struct discHdr), 0);
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
s32 Disc_IsWii(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
struct discHdr *header = (struct discHdr *) buffer;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
s32 ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Read disc header */
|
|
|
|
ret = Disc_ReadHeader(header);
|
|
|
|
if (ret < 0) return ret;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Check magic word */
|
|
|
|
if (header->magic != WII_MAGIC) return -1;
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
return 0;
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2011-09-03 11:39:26 +02:00
|
|
|
s32 Disc_JumpToEntrypoint(s32 hooktype, u32 dolparameter)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Set an appropiate video mode */
|
|
|
|
__Disc_SetVMode();
|
2009-05-03 20:53:31 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Set time */
|
|
|
|
__Disc_SetTime();
|
2009-07-30 07:41:12 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Shutdown IOS subsystems */
|
|
|
|
extern void __exception_closeall();
|
|
|
|
u32 level = IRQ_Disable();
|
|
|
|
__IOS_ShutdownSubsystems();
|
|
|
|
__exception_closeall();
|
2010-09-19 01:16:05 +02:00
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
/* Originally from tueidj - taken from NeoGamme (thx) */
|
2011-01-16 14:12:07 +01:00
|
|
|
*(vu32*)0xCC003024 = dolparameter != 0 ? dolparameter : 1;
|
|
|
|
|
2011-12-23 23:04:27 +01:00
|
|
|
if(AppEntrypoint == 0x3400)
|
2011-11-12 19:14:09 +01:00
|
|
|
{
|
2011-12-23 23:04:27 +01:00
|
|
|
if(hooktype)
|
|
|
|
{
|
|
|
|
__asm__(
|
|
|
|
"lis %r3, returnpoint@h\n"
|
|
|
|
"ori %r3, %r3, returnpoint@l\n"
|
|
|
|
"mtlr %r3\n"
|
|
|
|
"lis %r3, 0x8000\n"
|
|
|
|
"ori %r3, %r3, 0x18A8\n"
|
|
|
|
"mtctr %r3\n"
|
|
|
|
"bctr\n"
|
|
|
|
"returnpoint:\n"
|
|
|
|
"bl DCDisable\n"
|
|
|
|
"bl ICDisable\n"
|
|
|
|
"li %r3, 0\n"
|
|
|
|
"mtsrr1 %r3\n"
|
|
|
|
"lis %r4, AppEntrypoint@h\n"
|
|
|
|
"ori %r4,%r4,AppEntrypoint@l\n"
|
|
|
|
"lwz %r4, 0(%r4)\n"
|
|
|
|
"mtsrr0 %r4\n"
|
|
|
|
"rfi\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__asm__(
|
|
|
|
"isync\n"
|
|
|
|
"lis %r3, AppEntrypoint@h\n"
|
|
|
|
"ori %r3, %r3, AppEntrypoint@l\n"
|
|
|
|
"lwz %r3, 0(%r3)\n"
|
|
|
|
"mtsrr0 %r3\n"
|
|
|
|
"mfmsr %r3\n"
|
|
|
|
"li %r4, 0x30\n"
|
|
|
|
"andc %r3, %r3, %r4\n"
|
|
|
|
"mtsrr1 %r3\n"
|
|
|
|
"rfi\n"
|
|
|
|
);
|
|
|
|
}
|
2011-11-12 19:14:09 +01:00
|
|
|
}
|
|
|
|
else if (hooktype)
|
2011-07-26 00:28:22 +02:00
|
|
|
{
|
|
|
|
__asm__(
|
|
|
|
"lis %r3, AppEntrypoint@h\n"
|
|
|
|
"ori %r3, %r3, AppEntrypoint@l\n"
|
|
|
|
"lwz %r3, 0(%r3)\n"
|
|
|
|
"mtlr %r3\n"
|
|
|
|
"lis %r3, 0x8000\n"
|
|
|
|
"ori %r3, %r3, 0x18A8\n"
|
|
|
|
"nop\n"
|
|
|
|
"mtctr %r3\n"
|
|
|
|
"bctr\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__asm__(
|
|
|
|
"lis %r3, AppEntrypoint@h\n"
|
|
|
|
"ori %r3, %r3, AppEntrypoint@l\n"
|
|
|
|
"lwz %r3, 0(%r3)\n"
|
|
|
|
"mtlr %r3\n"
|
|
|
|
"blr\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
IRQ_Restore(level);
|
|
|
|
|
|
|
|
return 0;
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
void PatchCountryStrings(void *Address, int Size)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
u8 SearchPattern[4] = { 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
u8 PatchData[4] = { 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
u8 *Addr = (u8*) Address;
|
|
|
|
|
|
|
|
int wiiregion = CONF_GetRegion();
|
|
|
|
|
|
|
|
switch (wiiregion)
|
|
|
|
{
|
|
|
|
case CONF_REGION_JP:
|
|
|
|
SearchPattern[0] = 0x00;
|
|
|
|
SearchPattern[1] = 0x4A; // J
|
|
|
|
SearchPattern[2] = 0x50; // P
|
|
|
|
break;
|
|
|
|
case CONF_REGION_EU:
|
|
|
|
SearchPattern[0] = 0x02;
|
|
|
|
SearchPattern[1] = 0x45; // E
|
|
|
|
SearchPattern[2] = 0x55; // U
|
|
|
|
break;
|
|
|
|
case CONF_REGION_KR:
|
|
|
|
SearchPattern[0] = 0x04;
|
|
|
|
SearchPattern[1] = 0x4B; // K
|
|
|
|
SearchPattern[2] = 0x52; // R
|
|
|
|
break;
|
|
|
|
case CONF_REGION_CN:
|
|
|
|
SearchPattern[0] = 0x05;
|
|
|
|
SearchPattern[1] = 0x43; // C
|
|
|
|
SearchPattern[2] = 0x4E; // N
|
|
|
|
break;
|
|
|
|
case CONF_REGION_US:
|
|
|
|
default:
|
|
|
|
SearchPattern[0] = 0x01;
|
|
|
|
SearchPattern[1] = 0x55; // U
|
|
|
|
SearchPattern[2] = 0x53; // S
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (diskid[3])
|
|
|
|
{
|
|
|
|
case 'J':
|
|
|
|
PatchData[1] = 0x4A; // J
|
|
|
|
PatchData[2] = 0x50; // P
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'D':
|
|
|
|
case 'F':
|
|
|
|
case 'P':
|
|
|
|
case 'X':
|
|
|
|
case 'Y':
|
|
|
|
PatchData[1] = 0x45; // E
|
|
|
|
PatchData[2] = 0x55; // U
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
default:
|
|
|
|
PatchData[1] = 0x55; // U
|
|
|
|
PatchData[2] = 0x53; // S
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (Size >= 4)
|
|
|
|
{
|
|
|
|
if (Addr[0] == SearchPattern[0] && Addr[1] == SearchPattern[1] && Addr[2] == SearchPattern[2] && Addr[3]
|
|
|
|
== SearchPattern[3])
|
|
|
|
{
|
|
|
|
//*Addr = PatchData[0];
|
|
|
|
Addr += 1;
|
|
|
|
*Addr = PatchData[1];
|
|
|
|
Addr += 1;
|
|
|
|
*Addr = PatchData[2];
|
|
|
|
Addr += 1;
|
|
|
|
//*Addr = PatchData[3];
|
|
|
|
Addr += 1;
|
|
|
|
Size -= 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Addr += 4;
|
|
|
|
Size -= 4;
|
|
|
|
}
|
|
|
|
}
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|