-WIP moved code to load channels into external game booter

This commit is contained in:
fix94.1 2012-09-07 20:10:04 +00:00
parent f1767d5082
commit e229aca6a5
15 changed files with 490 additions and 139 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -82,7 +82,7 @@ s32 Apploader_Run(entry_point *entry, u8 vidMode, GXRModeObj *vmode, bool vipatc
free_wip();
if(hooktype != 0 && hookpatched)
ocarina_do_code();
ocarina_do_code(0);
/* Set entry point from apploader */
*entry = appldr_final();

View File

@ -0,0 +1,48 @@
#include <ogcsys.h>
#include <locale.h>
#include <malloc.h>
#include <ogc/isfs.h>
#include <string.h>
#include "fs.h"
#include "utils.h"
static fstats stats ATTRIBUTE_ALIGN(32);
u8 *ISFS_GetFile(u8 *path, u32 *size, s32 length)
{
*size = 0;
s32 fd = ISFS_Open((const char *)path, ISFS_OPEN_READ);
u8 *buf = NULL;
if(fd >= 0)
{
memset(&stats, 0, sizeof(fstats));
if(ISFS_GetFileStats(fd, &stats) >= 0)
{
if(length <= 0)
length = stats.file_length;
if(length > 0)
buf = (u8 *)memalign(32, ALIGN32(length));
if(buf)
{
*size = stats.file_length;
if(ISFS_Read(fd, (char*)buf, length) != length)
{
*size = 0;
free(buf);
}
}
}
ISFS_Close(fd);
}
if(*size > 0)
{
DCFlushRange(buf, *size);
ICInvalidateRange(buf, *size);
}
return buf;
}

View File

@ -0,0 +1,15 @@
#ifndef _FS_H_
#define _FS_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
u8 *ISFS_GetFile(u8 *path, u32 *size, s32 length);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -32,7 +32,7 @@ extern u8 debuggerselect;
void app_gameconfig_set(u32 *gameconfig, u32 tempgameconfsize);
void ocarina_set_codes(void *list, u8 *listend, u8 *cheats, u32 cheatSize);
int ocarina_do_code();
int ocarina_do_code(u64 chantitle);
#ifdef __cplusplus
}

View File

@ -0,0 +1,215 @@
/*******************************************************************************
* lz77.c
*
* Copyright (c) 2009 The Lemon Man
* Copyright (c) 2009 Nicksasa
* Copyright (c) 2009 WiiPower
*
* Distributed under the terms of the GNU General Public License (v2)
* See http://www.gnu.org/licenses/gpl-2.0.txt for more info.
*
* Description:
* -----------
*
******************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include "lz77.h"
#include "utils.h"
u32 packBytes(int a, int b, int c, int d)
{
return (d << 24) | (c << 16) | (b << 8) | (a);
}
s32 __decompressLZ77_11(u8 *in, u32 inputLen, u8 **output, u32 *outputLen)
{
int x, y;
u8 *out = NULL;
u32 compressedPos = 0x4;
u32 decompressedPos = 0x0;
u32 decompressedSize = 0;
decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8;
if (!decompressedSize)
{
decompressedSize = packBytes(in[4], in[5], in[6], in[7]);
compressedPos += 0x4;
}
//printf("Decompressed size : %i\n", decompressedSize);
out = malloc(ALIGN32(decompressedSize));
if (out == NULL)
{
printf("Out of memory\n");
return -1;
}
while (compressedPos < inputLen && decompressedPos < decompressedSize)
{
u8 byteFlag = in[compressedPos];
compressedPos++;
for (x = 7; x >= 0; x--)
{
if ((byteFlag & (1 << x)) > 0)
{
u8 first = in[compressedPos];
u8 second = in[compressedPos + 1];
u32 pos, copyLen;
if (first < 0x20)
{
u8 third = in[compressedPos + 2];
if (first >= 0x10)
{
u32 fourth = in[compressedPos + 3];
pos = (u32)(((third & 0xF) << 8) | fourth) + 1;
copyLen = (u32)((second << 4) | ((first & 0xF) << 12) | (third >> 4)) + 273;
compressedPos += 4;
} else
{
pos = (u32)(((second & 0xF) << 8) | third) + 1;
copyLen = (u32)(((first & 0xF) << 4) | (second >> 4)) + 17;
compressedPos += 3;
}
} else
{
pos = (u32)(((first & 0xF) << 8) | second) + 1;
copyLen = (u32)(first >> 4) + 1;
compressedPos += 2;
}
for (y = 0; y < (int)copyLen; y++)
{
out[decompressedPos + y] = out[decompressedPos - pos + y];
}
decompressedPos += copyLen;
} else
{
out[decompressedPos] = in[compressedPos];
decompressedPos++;
compressedPos++;
}
if (compressedPos >= inputLen || decompressedPos >= decompressedSize)
break;
}
}
*output = out;
*outputLen = decompressedSize;
return 0;
}
s32 __decompressLZ77_10(u8 *in, u8 **output, u32 *outputLen)
{
int x, y;
u8 *out = NULL;
u32 compressedPos = 0;
u32 decompressedSize = 0x4;
u32 decompressedPos = 0;
decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8;
//int compressionType = (packBytes(in[0], in[1], in[2], in[3]) >> 4) & 0xF;
//printf("Decompressed size : %i\n", decompressedSize);
out = malloc(ALIGN32(decompressedSize));
if (out == NULL)
{
printf("Out of memory\n");
return -1;
}
compressedPos += 0x4;
while (decompressedPos < decompressedSize)
{
u8 flag = *(u8*)(in + compressedPos);
compressedPos += 1;
for (x = 0; x < 8; x++)
{
if (flag & 0x80)
{
u8 first = in[compressedPos];
u8 second = in[compressedPos + 1];
u16 pos = (u16)((((first << 8) + second) & 0xFFF) + 1);
u8 copyLen = (u8)(3 + ((first >> 4) & 0xF));
for (y = 0; y < copyLen; y++)
{
out[decompressedPos + y] = out[decompressedPos - pos + (y % pos)];
}
compressedPos += 2;
decompressedPos += copyLen;
} else
{
out[decompressedPos] = in[compressedPos];
compressedPos += 1;
decompressedPos += 1;
}
flag <<= 1;
if (decompressedPos >= decompressedSize)
break;
}
}
*output = out;
*outputLen = decompressedSize;
return 0;
}
int isLZ77compressed(u8 *buffer)
{
if ((buffer[0] == LZ77_0x10_FLAG) || (buffer[0] == LZ77_0x11_FLAG))
{
return 1;
}
return 0;
}
int decompressLZ77content(u8 *buffer, u32 length, u8 **output, u32 *outputLen)
{
int ret;
switch (buffer[0])
{
case LZ77_0x10_FLAG:
//printf("LZ77 variant 0x10 compressed content...unpacking may take a while...\n");
ret = __decompressLZ77_10(buffer, output, outputLen);
break;
case LZ77_0x11_FLAG:
//printf("LZ77 variant 0x11 compressed content...unpacking may take a while...\n");
ret = __decompressLZ77_11(buffer, length, output, outputLen);
break;
default:
//printf("Not compressed ...\n");
ret = -1;
break;
}
return ret;
}

View File

@ -0,0 +1,34 @@
/*******************************************************************************
* lz77.h
*
* Copyright (c) 2009 The Lemon Man
* Copyright (c) 2009 Nicksasa
* Copyright (c) 2009 WiiPower
*
* Distributed under the terms of the GNU General Public License (v2)
* See http://www.gnu.org/licenses/gpl-2.0.txt for more info.
*
* Description:
* -----------
*
******************************************************************************/
#ifndef _LZ77_MODULE
#define _LZ77_MODULE
#define LZ77_0x10_FLAG 0x10
#define LZ77_0x11_FLAG 0x11
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int isLZ77compressed(u8 *buffer);
int decompressLZ77content(u8 *buffer, u32 length, u8 **output, u32 *outputLen);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -26,7 +26,10 @@
#include "patchcode.h"
#include "cios.h"
#include "disc.h"
#include "fs.h"
#include "fst.h"
#include "lz77.h"
#include "utils.h"
#include "videopatch.h"
using namespace std;
@ -51,10 +54,7 @@ typedef struct _the_CFG {
u32 gameconfsize;
u8 BootType;
/* needed for channels */
void *dolchunkoffset[18];
u32 dolchunksize[18];
u32 dolchunkcount;
u32 startPoint;
u64 title;
} the_CFG;
static the_CFG *conf = (the_CFG*)0x90000000;
@ -68,21 +68,146 @@ u32 AppEntrypoint;
extern "C" { extern void __exception_closeall(); }
typedef struct _dolheader
{
u32 section_pos[18];
u32 section_start[18];
u32 section_size[18];
u32 bss_start;
u32 bss_size;
u32 entry_point;
u32 padding[7];
} __attribute__((packed)) dolheader;
void *dolchunkoffset[18];
u32 dolchunksize[18];
u32 dolchunkcount;
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio)
{
for(u32 i = 0; i < conf->dolchunkcount; i++)
for(u32 i = 0; i < dolchunkcount; i++)
{
patchVideoModes(conf->dolchunkoffset[i], conf->dolchunksize[i], vidMode, vmode, patchVidModes);
if(vipatch) vidolpatcher(conf->dolchunkoffset[i], conf->dolchunksize[i]);
if(configbytes[0] != 0xCD) langpatcher(conf->dolchunkoffset[i], conf->dolchunksize[i]);
if(countryString) PatchCountryStrings(conf->dolchunkoffset[i], conf->dolchunksize[i]);
if(aspectRatio != -1) PatchAspectRatio(conf->dolchunkoffset[i], conf->dolchunksize[i], aspectRatio);
patchVideoModes(dolchunkoffset[i], dolchunksize[i], vidMode, vmode, patchVidModes);
if(vipatch) vidolpatcher(dolchunkoffset[i], dolchunksize[i]);
if(configbytes[0] != 0xCD) langpatcher(dolchunkoffset[i], dolchunksize[i]);
if(countryString) PatchCountryStrings(dolchunkoffset[i], dolchunksize[i]);
if(aspectRatio != -1) PatchAspectRatio(dolchunkoffset[i], dolchunksize[i], aspectRatio);
if(hooktype != 0)
dogamehooks(conf->dolchunkoffset[i], conf->dolchunksize[i], true);
dogamehooks(dolchunkoffset[i], dolchunksize[i], true);
}
}
static u8 *GetDol(u32 bootcontent)
{
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
sprintf(filepath, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(conf->title), TITLE_LOWER(conf->title), bootcontent);
u32 contentSize = 0;
u8 *data = ISFS_GetFile((u8 *) &filepath, &contentSize, -1);
if(data != NULL && contentSize != 0)
{
if(isLZ77compressed(data))
{
u8 *decompressed;
u32 size = 0;
if(decompressLZ77content(data, contentSize, &decompressed, &size) < 0)
{
free(data);
return NULL;
}
free(data);
data = decompressed;
}
return data;
}
return NULL;
}
static bool GetAppNameFromTmd(char *app, bool dol, u32 *bootcontent)
{
bool ret = false;
char tmd[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
sprintf(tmd, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(conf->title), TITLE_LOWER(conf->title));
u32 size;
u8 *data = ISFS_GetFile((u8 *) &tmd, &size, -1);
if (data == NULL || size < 0x208)
return ret;
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
u16 i;
for(i = 0; i < tmd_file->num_contents; ++i)
{
if(tmd_file->contents[i].index == (dol ? tmd_file->boot_index : 0))
{
*bootcontent = tmd_file->contents[i].cid;
sprintf(app, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(conf->title), TITLE_LOWER(conf->title), *bootcontent);
ret = true;
break;
}
}
free(data);
return ret;
}
static u32 MoveDol(u8 *buffer)
{
dolchunkcount = 0;
dolheader *dolfile = (dolheader *)buffer;
if(dolfile->bss_start)
{
if(!(dolfile->bss_start & 0x80000000))
dolfile->bss_start |= 0x80000000;
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *)dolfile->bss_start, dolfile->bss_size);
ICInvalidateRange((void *)dolfile->bss_start, dolfile->bss_size);
}
int i;
for(i = 0; i < 18; i++)
{
if(!dolfile->section_size[i])
continue;
if(dolfile->section_pos[i] < sizeof(dolheader))
continue;
if(!(dolfile->section_start[i] & 0x80000000))
dolfile->section_start[i] |= 0x80000000;
dolchunkoffset[dolchunkcount] = (void *)dolfile->section_start[i];
dolchunksize[dolchunkcount] = dolfile->section_size[i];
//gprintf("Moving section %u from offset %08x to %08x-%08x...\n", i, dolfile->section_pos[i], dolchunkoffset[dolchunkcount], (u32)dolchunkoffset[dolchunkcount]+dolchunksize[dolchunkcount]);
memmove(dolchunkoffset[dolchunkcount], buffer + dolfile->section_pos[i], dolchunksize[dolchunkcount]);
DCFlushRange(dolchunkoffset[dolchunkcount], dolchunksize[dolchunkcount]);
ICInvalidateRange(dolchunkoffset[dolchunkcount], dolchunksize[dolchunkcount]);
dolchunkcount++;
}
return dolfile->entry_point;
}
u32 LoadChannel()
{
char app[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
u32 bootcontent;
u32 entry = 0;
if(!GetAppNameFromTmd(app, true, &bootcontent))
return entry;
u8 *data = GetDol(bootcontent);
entry = MoveDol(data);
free(data);
return entry;
}
int main()
{
VIDEO_Init();
@ -118,12 +243,13 @@ int main()
}
else if(conf->BootType == TYPE_CHANNEL)
{
if(hooktype != 0)
ocarina_do_code();
ISFS_Initialize();
AppEntrypoint = LoadChannel();
PatchChannel(conf->vidMode, vmode, conf->vipatch, conf->countryString,
conf->patchVidMode, conf->aspectRatio);
AppEntrypoint = conf->startPoint;
if(hooktype != 0)
ocarina_do_code(conf->title);
ISFS_Deinitialize();
}
/* Set time */

View File

@ -0,0 +1,26 @@
#ifndef _UTILS_H_
#define _UTILS_H_
#include <gctypes.h>
#define KB_SIZE 1024.0
#define MB_SIZE 1048576.0
#define GB_SIZE 1073741824.0
#define MAX_FAT_PATH 1024
#define round_up(x,n) (-(-(x) & -(n)))
#define ALIGN(n, x) (((x) + (n - 1)) & ~(n - 1))
#define ALIGN32(x) (((x) + 31) & ~31)
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
#define TITLE_UPPER(x) ((u32)((x) >> 32))
#define TITLE_LOWER(x) ((u32)(x) & 0xFFFFFFFF)
#define Write8(addr, val) *(u8 *)addr = val; DCFlushRange((void *)addr, sizeof(u8));
#define Write16(addr, val) *(u16 *)addr = val; DCFlushRange((void *)addr, sizeof(u16));
#define Write32(addr, val) *(u32 *)addr = val; DCFlushRange((void *)addr, sizeof(u32));
#endif

View File

@ -15,24 +15,7 @@
#include "unzip/lz77.h"
#include "types.h"
typedef void (*entrypoint) (void);
typedef struct _dolheader
{
u32 section_pos[18];
u32 section_start[18];
u32 section_size[18];
u32 bss_start;
u32 bss_size;
u32 entry_point;
u32 padding[7];
} __attribute__((packed)) dolheader;
void *dolchunkoffset[18];
u32 dolchunksize[18];
u32 dolchunkcount;
s32 BootChannel(u32 entry, u64 chantitle, u32 ios, u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode, int aspectRatio)
s32 BootChannel(u64 chantitle, u32 ios, u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode, int aspectRatio)
{
// IOS Version Check
*Real_IOSVersion = ((ios << 16)) | 0xFFFF;
@ -45,49 +28,10 @@ s32 BootChannel(u32 entry, u64 chantitle, u32 ios, u8 vidMode, bool vipatch, boo
*Disc_ID = TITLE_LOWER(chantitle);
DCFlushRange((void*)Disc_ID, 4);
ExternalBooter_ChannelSetup(dolchunkoffset, dolchunksize, dolchunkcount, entry);
WiiFlow_ExternalBooter(vidMode, vipatch, countryString, patchVidMode, aspectRatio, 0, TYPE_CHANNEL);
return 0;
}
u32 LoadChannel(u8 *buffer)
{
dolchunkcount = 0;
dolheader *dolfile = (dolheader *)buffer;
if(dolfile->bss_start)
{
if(!(dolfile->bss_start & 0x80000000))
dolfile->bss_start |= 0x80000000;
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *)dolfile->bss_start, dolfile->bss_size);
ICInvalidateRange((void *)dolfile->bss_start, dolfile->bss_size);
}
int i;
for(i = 0; i < 18; i++)
{
if(!dolfile->section_size[i])
continue;
if(dolfile->section_pos[i] < sizeof(dolheader))
continue;
if(!(dolfile->section_start[i] & 0x80000000))
dolfile->section_start[i] |= 0x80000000;
dolchunkoffset[dolchunkcount] = (void *)dolfile->section_start[i];
dolchunksize[dolchunkcount] = dolfile->section_size[i];
gprintf("Moving section %u from offset %08x to %08x-%08x...\n", i, dolfile->section_pos[i], dolchunkoffset[dolchunkcount], (u32)dolchunkoffset[dolchunkcount]+dolchunksize[dolchunkcount]);
memmove(dolchunkoffset[dolchunkcount], buffer + dolfile->section_pos[i], dolchunksize[dolchunkcount]);
DCFlushRange(dolchunkoffset[dolchunkcount], dolchunksize[dolchunkcount]);
ICInvalidateRange(dolchunkoffset[dolchunkcount], dolchunksize[dolchunkcount]);
dolchunkcount++;
}
return dolfile->entry_point;
}
bool Identify_GenerateTik(signed_blob **outbuf, u32 *outlen)
{
signed_blob *buffer = (signed_blob *)memalign(32, ALIGN32(STD_SIGNED_TIK_SIZE));
@ -177,34 +121,3 @@ bool Identify(u64 titleid)
return ret < 0 ? false : true;
}
u8 *GetDol(u64 title, u32 bootcontent)
{
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
sprintf(filepath, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), bootcontent);
gprintf("Loading DOL: %s...", filepath);
u32 contentSize = 0;
u8 *data = ISFS_GetFile((u8 *) &filepath, &contentSize, -1);
if (data != NULL && contentSize != 0)
{
gprintf("Done!\n");
if (isLZ77compressed(data))
{
u8 *decompressed;
u32 size = 0;
if (decompressLZ77content(data, contentSize, &decompressed, &size) < 0)
{
gprintf("Decompression failed\n");
free(data);
return NULL;
}
free(data);
data = decompressed;
}
return data;
}
gprintf("Failed!\n");
return NULL;
}

View File

@ -4,7 +4,7 @@
#include <gctypes.h>
#include <gccore.h>
s32 BootChannel(u32 entry, u64 chantitle, u32 ios, u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode, int aspectRatio);
s32 BootChannel(u64 chantitle, u32 ios, u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode, int aspectRatio);
u32 LoadChannel(u8 *buffer);
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio);

View File

@ -67,24 +67,6 @@ Channels::~Channels()
{
}
u32 Channels::Load(u64 title)
{
char app[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
u32 bootcontent;
u32 entry = 0;
if(!GetAppNameFromTmd(title, app, true, &bootcontent))
return entry;
u8 *data = GetDol(title, bootcontent);
Identify(title);
entry = LoadChannel(data);
free(data);
return entry;
}
u8 Channels::GetRequestedIOS(u64 title)
{
u8 IOS = 0;

View File

@ -54,10 +54,7 @@ typedef struct _the_CFG {
u32 gameconfsize;
u8 BootType;
/* needed for channels */
void *dolchunkoffset[18];
u32 dolchunksize[18];
u32 dolchunkcount;
u32 startPoint;
u64 title;
} the_CFG;
the_CFG normalCFG;
@ -98,15 +95,9 @@ void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 pat
BootHomebrew();
}
void ExternalBooter_ChannelSetup(void *dolchunkoffset[18], u32 dolchunksize[18], u32 dolchunkcount, u32 StartPoint)
void ExternalBooter_ChannelSetup(u64 title)
{
for(u8 i = 0; i < 18; i++)
{
normalCFG.dolchunkoffset[i] = dolchunkoffset[i];
normalCFG.dolchunksize[i] = dolchunksize[i];
}
normalCFG.dolchunkcount = dolchunkcount;
normalCFG.startPoint = StartPoint;
normalCFG.title = title;
}
void ShutdownBeforeExit(bool KeepPatches)

View File

@ -30,7 +30,7 @@ extern u32 hooktype;
void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode,
int aspectRatio, u32 returnTo, u8 BootType);
void ExternalBooter_ChannelSetup(void *dolchunkoffset[18], u32 dolchunksize[18], u32 dolchunkcount, u32 StartPoint);
void ExternalBooter_ChannelSetup(u64 title);
void ShutdownBeforeExit(bool KeepPatches = false);
#endif

View File

@ -1134,14 +1134,15 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
}
else
{
entry = channel.Load(gameTitle);
setLanguage(language);
SmartBuf cheatFile;
u32 cheatSize = 0;
if(cheat)
_loadFile(cheatFile, cheatSize, m_cheatDir.c_str(), fmt("%s.gct", id.c_str()));
ocarina_load_code(cheatFile.get(), cheatSize);
BootChannel(entry, gameTitle, gameIOS, videoMode, vipatch, countryPatch, patchVidMode, aspectRatio);
Identify(gameTitle);
ExternalBooter_ChannelSetup(gameTitle);
BootChannel(gameTitle, gameIOS, videoMode, vipatch, countryPatch, patchVidMode, aspectRatio);
}
}