usbloadergx/source/usbloader/alternatedol.c

269 lines
6.4 KiB
C
Raw Normal View History

2009-07-31 14:45:14 +02:00
#include <ogcsys.h>
#include <stdio.h>
#include <gccore.h>
#include <string.h>
#include <malloc.h>
#include "apploader.h"
#include "wdvd.h"
#include "fstfile.h"
#include "../patches/dvd_broadway.h"
extern u8 mountMethod;
2009-07-31 14:45:14 +02:00
/** Alternate dolloader made by WiiPower modified by dimok **/
2010-09-24 02:48:03 +02:00
bool Load_Dol(void **buffer, int* dollen, char * filepath)
{
2009-07-31 14:45:14 +02:00
int ret;
FILE* file;
void* dol_buffer;
char fullpath[200];
char gameidbuffer6[7];
2010-09-24 02:48:03 +02:00
memset(gameidbuffer6, 0, 7);
memcpy(gameidbuffer6, (char*) 0x80000000, 6);
snprintf(fullpath, 200, "%s%s.dol", filepath, gameidbuffer6);
2009-07-31 14:45:14 +02:00
2010-09-24 02:48:03 +02:00
file = fopen(fullpath, "rb");
2009-07-31 14:45:14 +02:00
2010-09-24 02:48:03 +02:00
if (file == NULL)
{
2010-09-24 02:48:03 +02:00
fclose(file);
2009-07-31 14:45:14 +02:00
return false;
}
int filesize;
2010-09-24 02:48:03 +02:00
fseek(file, 0, SEEK_END);
filesize = ftell(file);
fseek(file, 0, SEEK_SET);
2010-09-24 02:48:03 +02:00
dol_buffer = malloc(filesize);
if (dol_buffer == NULL)
{
2010-09-24 02:48:03 +02:00
fclose(file);
return false;
2009-07-31 14:45:14 +02:00
}
2010-09-24 02:48:03 +02:00
ret = fread(dol_buffer, 1, filesize, file);
if (ret != filesize)
{
2010-09-24 02:48:03 +02:00
free(dol_buffer);
fclose(file);
return false;
2009-07-31 14:45:14 +02:00
}
2010-09-24 02:48:03 +02:00
fclose(file);
2009-07-31 14:45:14 +02:00
*buffer = dol_buffer;
*dollen = filesize;
return true;
}
2010-09-24 02:48:03 +02:00
bool Remove_001_Protection(void *Address, int Size)
{
2010-09-24 02:48:03 +02:00
u8 SearchPattern[16] = { 0x40, 0x82, 0x00, 0x0C, 0x38, 0x60, 0x00, 0x01, 0x48, 0x00, 0x02, 0x44, 0x38, 0x61, 0x00,
0x18 };
u8 PatchData[16] =
{ 0x40, 0x82, 0x00, 0x04, 0x38, 0x60, 0x00, 0x01, 0x48, 0x00, 0x02, 0x44, 0x38, 0x61, 0x00, 0x18 };
2009-07-31 14:45:14 +02:00
void *Addr = Address;
void *Addr_end = Address + Size;
2009-07-31 14:45:14 +02:00
2010-09-24 02:48:03 +02:00
while (Addr <= Addr_end - sizeof(SearchPattern))
{
2010-09-24 02:48:03 +02:00
if (memcmp(Addr, SearchPattern, sizeof(SearchPattern)) == 0)
{
2010-09-24 02:48:03 +02:00
memcpy(Addr, PatchData, sizeof(PatchData));
2009-07-31 14:45:14 +02:00
return true;
}
Addr += 4;
}
return false;
}
typedef struct _dolheader
{
2009-07-31 14:45:14 +02:00
u32 text_pos[7];
u32 data_pos[11];
u32 text_start[7];
u32 data_start[11];
u32 text_size[7];
u32 data_size[11];
u32 bss_start;
u32 bss_size;
u32 entry_point;
} dolheader;
static dolheader *dolfile;
u32 load_dol_image(void *dolstart, u8 videoSelected, u8 languageChoice, u8 patchcountrystring, u8 vipatch, u8 cheat, u32 returnTo, u8 fix002)
{
2009-07-31 14:45:14 +02:00
u32 i;
2010-09-24 02:48:03 +02:00
if (dolstart)
{
2010-09-24 02:48:03 +02:00
dolfile = (dolheader *) dolstart;
for (i = 0; i < 7; i++)
{
2010-09-24 02:48:03 +02:00
if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100)) continue;
2010-09-24 02:48:03 +02:00
ICInvalidateRange((void *) dolfile->text_start[i], dolfile->text_size[i]);
memmove((void *) dolfile->text_start[i], dolstart + dolfile->text_pos[i], dolfile->text_size[i]);
gamepatches((void *) dolfile->text_start[i], dolfile->text_size[i], videoSelected, languageChoice, patchcountrystring,
vipatch, cheat, returnTo, fix002);
2010-09-24 02:48:03 +02:00
Remove_001_Protection((void *) dolfile->data_start[i], dolfile->data_size[i]);
2009-07-31 14:45:14 +02:00
}
2010-09-24 02:48:03 +02:00
for (i = 0; i < 11; i++)
{
2010-09-24 02:48:03 +02:00
if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100)) continue;
2010-09-24 02:48:03 +02:00
memmove((void *) dolfile->data_start[i], dolstart + dolfile->data_pos[i], dolfile->data_size[i]);
gamepatches((void *) dolfile->data_start[i], dolfile->data_size[i], videoSelected, languageChoice, patchcountrystring,
vipatch, cheat, returnTo, fix002);
2010-09-24 02:48:03 +02:00
Remove_001_Protection((void *) dolfile->data_start[i], dolfile->data_size[i]);
DCFlushRangeNoSync((void *) dolfile->data_start[i], dolfile->data_size[i]);
2009-07-31 14:45:14 +02:00
}
/*
2010-09-24 02:48:03 +02:00
memset ((void *) dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *) dolfile->bss_start, dolfile->bss_size);
*/
2009-07-31 14:45:14 +02:00
return dolfile->entry_point;
}
return 0;
}
static int i;
static int phase;
2010-09-24 02:48:03 +02:00
u32 load_dol_start(void *dolstart)
{
2010-09-24 02:48:03 +02:00
if (dolstart)
{
2010-09-24 02:48:03 +02:00
dolfile = (dolheader *) dolstart;
2009-07-31 14:45:14 +02:00
return dolfile->entry_point;
}
else
{
2009-07-31 14:45:14 +02:00
return 0;
}
2010-09-24 02:48:03 +02:00
memset((void *) dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *) dolfile->bss_start, dolfile->bss_size);
2009-07-31 14:45:14 +02:00
phase = 0;
i = 0;
}
2010-09-24 02:48:03 +02:00
bool load_dol_image_modified(void **offset, u32 *pos, u32 *len)
{
2010-09-24 02:48:03 +02:00
if (phase == 0)
{
2010-09-24 02:48:03 +02:00
if (i == 7)
{
2009-07-31 14:45:14 +02:00
phase = 1;
i = 0;
}
else
{
2010-09-24 02:48:03 +02:00
if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100))
{
2009-07-31 14:45:14 +02:00
*offset = 0;
*pos = 0;
*len = 0;
}
else
{
2010-09-24 02:48:03 +02:00
*offset = (void *) dolfile->text_start[i];
2009-07-31 14:45:14 +02:00
*pos = dolfile->text_pos[i];
*len = dolfile->text_size[i];
}
i++;
return true;
}
}
2010-09-24 02:48:03 +02:00
if (phase == 1)
{
2010-09-24 02:48:03 +02:00
if (i == 11)
{
2009-07-31 14:45:14 +02:00
phase = 2;
return false;
}
2010-09-24 02:48:03 +02:00
if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100))
{
2009-07-31 14:45:14 +02:00
*offset = 0;
*pos = 0;
*len = 0;
}
else
{
2010-09-24 02:48:03 +02:00
*offset = (void *) dolfile->data_start[i];
2009-07-31 14:45:14 +02:00
*pos = dolfile->data_pos[i];
*len = dolfile->data_size[i];
}
i++;
return true;
}
return false;
}
static vu32 dvddone = 0;
2010-09-24 02:48:03 +02:00
void __dvd_readidcb(s32 result)
{
dvddone = result;
}
u32 Load_Dol_from_disc(u32 doloffset, u8 videoSelected, u8 languageChoice, u8 patchcountrystring, u8 vipatch, u8 cheat, u32 returnTo, u8 fix002)
{
2009-07-31 14:45:14 +02:00
int ret;
void *dol_header;
u32 entrypoint;
2010-09-24 02:48:03 +02:00
dol_header = memalign(32, sizeof(dolheader));
if (dol_header == NULL)
{
2009-07-31 14:45:14 +02:00
return -1;
}
2010-09-24 02:48:03 +02:00
if (!mountMethod)
ret = WDVD_Read(dol_header, sizeof(dolheader), (doloffset << 2));
else
{
dvddone = 0;
2010-09-24 02:48:03 +02:00
ret = bwDVD_LowRead(dol_header, sizeof(dolheader), doloffset, __dvd_readidcb);
while (ret >= 0 && dvddone == 0)
;
}
2010-09-24 02:48:03 +02:00
entrypoint = load_dol_start(dol_header);
2009-07-31 14:45:14 +02:00
2010-09-24 02:48:03 +02:00
if (entrypoint == 0)
{
2010-09-24 02:48:03 +02:00
free(dol_header);
2009-07-31 14:45:14 +02:00
return -1;
}
void *offset;
u32 pos;
u32 len;
2010-09-24 02:48:03 +02:00
while (load_dol_image_modified(&offset, &pos, &len))
{
2010-09-24 02:48:03 +02:00
if (len != 0)
{
2010-09-24 02:48:03 +02:00
ret = WDVD_Read(offset, len, (doloffset << 2) + pos);
2009-07-31 14:45:14 +02:00
gamepatches(offset, len, videoSelected, languageChoice, patchcountrystring, vipatch, cheat, returnTo, fix002);
2009-07-31 14:45:14 +02:00
2010-09-24 02:48:03 +02:00
Remove_001_Protection(offset, len);
2010-09-24 02:48:03 +02:00
DCFlushRange(offset, len);
2009-07-31 14:45:14 +02:00
}
}
2010-09-24 02:48:03 +02:00
free(dol_header);
2009-07-31 14:45:14 +02:00
return entrypoint;
2009-07-31 14:45:14 +02:00
}