usbloadergx/source/usbloader/alternatedol.c
dimok321 6022ad060d *Added ThreadedTask instance class for easy one time run operations on another thread
*Added Free Space show option to the settings (can be enabled even on FAT partitions)
*Moved partition free space determination to a ThreadedTask because it takes up to 10 seconds on FAT. This speeds up the build up of the main game menu (on start and on change from other menu) on all partitions.
*Removed double "waiting for slow HDD" screens
*Fixed scrollbar in settings
2010-12-31 13:13:14 +00:00

269 lines
6.4 KiB
C

#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;
/** Alternate dolloader made by WiiPower modified by dimok **/
bool Load_Dol(void **buffer, int* dollen, char * filepath)
{
int ret;
FILE* file;
void* dol_buffer;
char fullpath[200];
char gameidbuffer6[7];
memset(gameidbuffer6, 0, 7);
memcpy(gameidbuffer6, (char*) 0x80000000, 6);
snprintf(fullpath, 200, "%s%s.dol", filepath, gameidbuffer6);
file = fopen(fullpath, "rb");
if (file == NULL)
{
fclose(file);
return false;
}
int filesize;
fseek(file, 0, SEEK_END);
filesize = ftell(file);
fseek(file, 0, SEEK_SET);
dol_buffer = malloc(filesize);
if (dol_buffer == NULL)
{
fclose(file);
return false;
}
ret = fread(dol_buffer, 1, filesize, file);
if (ret != filesize)
{
free(dol_buffer);
fclose(file);
return false;
}
fclose(file);
*buffer = dol_buffer;
*dollen = filesize;
return true;
}
bool Remove_001_Protection(void *Address, int Size)
{
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 };
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;
}
typedef struct _dolheader
{
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)
{
u32 i;
if (dolstart)
{
dolfile = (dolheader *) dolstart;
for (i = 0; i < 7; i++)
{
if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100)) continue;
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);
Remove_001_Protection((void *) dolfile->data_start[i], dolfile->data_size[i]);
}
for (i = 0; i < 11; i++)
{
if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100)) continue;
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);
Remove_001_Protection((void *) dolfile->data_start[i], dolfile->data_size[i]);
DCFlushRangeNoSync((void *) dolfile->data_start[i], dolfile->data_size[i]);
}
/*
memset ((void *) dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *) dolfile->bss_start, dolfile->bss_size);
*/
return dolfile->entry_point;
}
return 0;
}
static int i;
static int phase;
u32 load_dol_start(void *dolstart)
{
if (dolstart)
{
dolfile = (dolheader *) dolstart;
return dolfile->entry_point;
}
else
{
return 0;
}
memset((void *) dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *) dolfile->bss_start, dolfile->bss_size);
phase = 0;
i = 0;
}
bool load_dol_image_modified(void **offset, u32 *pos, u32 *len)
{
if (phase == 0)
{
if (i == 7)
{
phase = 1;
i = 0;
}
else
{
if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100))
{
*offset = 0;
*pos = 0;
*len = 0;
}
else
{
*offset = (void *) dolfile->text_start[i];
*pos = dolfile->text_pos[i];
*len = dolfile->text_size[i];
}
i++;
return true;
}
}
if (phase == 1)
{
if (i == 11)
{
phase = 2;
return false;
}
if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100))
{
*offset = 0;
*pos = 0;
*len = 0;
}
else
{
*offset = (void *) dolfile->data_start[i];
*pos = dolfile->data_pos[i];
*len = dolfile->data_size[i];
}
i++;
return true;
}
return false;
}
static vu32 dvddone = 0;
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)
{
int ret;
void *dol_header;
u32 entrypoint;
dol_header = memalign(32, sizeof(dolheader));
if (dol_header == NULL)
{
return -1;
}
if (!mountMethod)
ret = WDVD_Read(dol_header, sizeof(dolheader), (doloffset << 2));
else
{
dvddone = 0;
ret = bwDVD_LowRead(dol_header, sizeof(dolheader), doloffset, __dvd_readidcb);
while (ret >= 0 && dvddone == 0)
;
}
entrypoint = load_dol_start(dol_header);
if (entrypoint == 0)
{
free(dol_header);
return -1;
}
void *offset;
u32 pos;
u32 len;
while (load_dol_image_modified(&offset, &pos, &len))
{
if (len != 0)
{
ret = WDVD_Read(offset, len, (doloffset << 2) + pos);
gamepatches(offset, len, videoSelected, languageChoice, patchcountrystring, vipatch, cheat, returnTo, fix002);
Remove_001_Protection(offset, len);
DCFlushRange(offset, len);
}
}
free(dol_header);
return entrypoint;
}