mirror of
https://gitlab.com/Nanolx/homebrewfilter.git
synced 2024-12-27 10:01:48 +01:00
266 lines
4.3 KiB
C
266 lines
4.3 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ogcsys.h>
|
|
#include <ogc/lwp_watchdog.h>
|
|
|
|
#include "config.h"
|
|
#include "patches.h"
|
|
#include "video.h"
|
|
#include "wpad.h"
|
|
#include "tools.h"
|
|
|
|
/* DOL header structure */
|
|
typedef struct {
|
|
u32 textoff[7];
|
|
u32 dataoff[11];
|
|
|
|
u8 *textmem[7];
|
|
u8 *datamem[11];
|
|
|
|
u32 textsize[7];
|
|
u32 datasize[11];
|
|
|
|
u8 *bssmem;
|
|
u32 bsssize;
|
|
|
|
u32 entry;
|
|
|
|
u32 unused[7];
|
|
} dolheader;
|
|
|
|
/* Entry pointer */
|
|
typedef void (*dolentry)(void);
|
|
|
|
/* Constants */
|
|
#define DOL_INDEX 1
|
|
|
|
|
|
void __Loader_SetLowMem(void)
|
|
{
|
|
/* Setup low memory */
|
|
*(vu32*)0x800000F8 = 0x0E7BE2C0;
|
|
*(vu32*)0x800000FC = 0x2B73A840;
|
|
|
|
/* Flush cache */
|
|
DCFlushRange((void *)(0x800000F8), 0xFF);
|
|
|
|
// Set the clock
|
|
settime(secs_to_ticks(time(NULL) - 946684800));
|
|
|
|
// Remove 002 error
|
|
*(u16 *)0x80003140 = 0x0038;
|
|
*(u16 *)0x80003142 = 0xffff;
|
|
*(u16 *)0x80003188 = 0x0038;
|
|
*(u16 *)0x8000318A = 0xffff;
|
|
|
|
DCFlushRange((void*)0x80003140, 4);
|
|
DCFlushRange((void*)0x80003188, 4);
|
|
}
|
|
|
|
void __Loader_SetVMode(u64 tid)
|
|
{
|
|
GXRModeObj *vmode_ptr = NULL;
|
|
u32 vmode_reg;
|
|
|
|
u32 progressive, tvmode;
|
|
|
|
/* Get video mode configuration */
|
|
progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable();
|
|
tvmode = CONF_GetVideo();
|
|
|
|
/* Select video mode */
|
|
switch(tid & 0xFF) {
|
|
/* PAL */
|
|
case 'P':
|
|
vmode_reg = (CONF_GetEuRGB60() > 0) ? 5 : 1;
|
|
|
|
if (tvmode != CONF_VIDEO_PAL) {
|
|
vmode_reg = 5;
|
|
vmode_ptr = &TVNtsc480IntDf;
|
|
}
|
|
|
|
break;
|
|
|
|
/* NTSC or unknown */
|
|
case 'E':
|
|
case 'J':
|
|
vmode_reg = 0;
|
|
|
|
if (tvmode != CONF_VIDEO_NTSC)
|
|
vmode_ptr = &TVEurgb60Hz480IntDf;
|
|
|
|
break;
|
|
|
|
default:
|
|
vmode_reg = 0;
|
|
}
|
|
|
|
/* Override video mode */
|
|
if (loaderCfg.forcePal50) {
|
|
vmode_reg = 1;
|
|
vmode_ptr = &TVPal528IntDf;
|
|
}
|
|
|
|
if (loaderCfg.forcePal60) {
|
|
vmode_reg = 5;
|
|
vmode_ptr = &TVEurgb60Hz480IntDf;
|
|
}
|
|
|
|
if (loaderCfg.forceNtsc) {
|
|
vmode_reg = 0;
|
|
vmode_ptr = &TVNtsc480IntDf;
|
|
}
|
|
|
|
if (loaderCfg.forceHdtv) {
|
|
vmode_reg = 0;
|
|
vmode_ptr = &TVNtsc480Prog;
|
|
}
|
|
|
|
|
|
/* Set video mode register */
|
|
*(vu32 *)0x800000CC = vmode_reg;
|
|
|
|
/* Set video mode */
|
|
if (vmode_ptr) {
|
|
/* If progressive available, use it */
|
|
if (progressive)
|
|
vmode_ptr = &TVNtsc480Prog;
|
|
|
|
Video_Configure(vmode_ptr);
|
|
Video_Clear(COLOR_BLACK);
|
|
}
|
|
|
|
// Anti-green screen fix
|
|
VIDEO_SetBlack(TRUE);
|
|
VIDEO_Flush();
|
|
VIDEO_WaitVSync();
|
|
}
|
|
|
|
|
|
void __Loader_PatchDol(u8 *buffer, u32 len)
|
|
{
|
|
struct config *cfg = &loaderCfg;
|
|
|
|
/* Video mode patching */
|
|
if (cfg->patchVmode)
|
|
Patch_VideoMode(buffer, len);
|
|
}
|
|
|
|
s32 __Loader_ReadDol(dolentry *p_entry)
|
|
{
|
|
static dolheader dol ATTRIBUTE_ALIGN(32);
|
|
|
|
u32 cnt;
|
|
s32 cfd = -1, ret;
|
|
|
|
/* Open DOL file */
|
|
cfd = ES_OpenContent(DOL_INDEX);
|
|
if (cfd < 0)
|
|
return cfd;
|
|
|
|
/* Read DOL header */
|
|
ret = ES_ReadContent(cfd, (u8 *)&dol, sizeof(dol));
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* Clear BSS */
|
|
memset(dol.bssmem, 0, dol.bsssize);
|
|
|
|
/* Read TEXT section */
|
|
for (cnt = 0; cnt < 7; cnt++) {
|
|
u32 offset = dol.textoff[cnt];
|
|
|
|
if (offset >= sizeof(dol)) {
|
|
u8 *buffer = (u8 *)dol.textmem[cnt];
|
|
u32 len = dol.textsize[cnt];
|
|
|
|
/* Seek */
|
|
ES_SeekContent(cfd, offset, 0);
|
|
|
|
/* Read */
|
|
ret = ES_ReadContent(cfd, buffer, len);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* Patch */
|
|
__Loader_PatchDol(buffer, len);
|
|
}
|
|
}
|
|
|
|
/* Read DATA section */
|
|
for (cnt = 0; cnt < 11; cnt++) {
|
|
u32 offset = dol.dataoff[cnt];
|
|
|
|
if (offset >= sizeof(dol)) {
|
|
u8 *buffer = (u8 *)dol.datamem[cnt];
|
|
u32 len = dol.datasize[cnt];
|
|
|
|
/* Seek */
|
|
ES_SeekContent(cfd, offset, 0);
|
|
|
|
/* Read */
|
|
ret = ES_ReadContent(cfd, buffer, len);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* Patch */
|
|
__Loader_PatchDol(buffer, len);
|
|
}
|
|
}
|
|
|
|
/* Set entry point */
|
|
*p_entry = (dolentry)dol.entry;
|
|
|
|
out:
|
|
/* Close DOL file */
|
|
if (cfd >= 0)
|
|
ES_CloseContent(cfd);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void __Loader_Shutdown(void)
|
|
{
|
|
/* Deinitialize ISFS */
|
|
ISFS_Deinitialize();
|
|
|
|
/* Shutdown IOS subsystems */
|
|
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
|
}
|
|
|
|
|
|
s32 Loader_Execute(void)
|
|
{
|
|
dolentry p_entry = NULL;
|
|
|
|
u64 tid;
|
|
s32 ret;
|
|
|
|
/* Get title ID */
|
|
ret = ES_GetTitleID(&tid);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
/* Load DOL */
|
|
ret = __Loader_ReadDol(&p_entry);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
/* Set low memory */
|
|
__Loader_SetLowMem();
|
|
|
|
/* Set video mode */
|
|
__Loader_SetVMode(tid);
|
|
|
|
/* Shutdown subsystems */
|
|
__Loader_Shutdown();
|
|
|
|
/* Clear screen */
|
|
Video_Clear(COLOR_BLACK);
|
|
|
|
/* Jump to the entry point */
|
|
p_entry();
|
|
|
|
return 0;
|
|
}
|