Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
207 lines (186 sloc) 4.53 KB
// Copyright 2018 FIX94
// This code is licensed to you under the terms of the GNU GPL, version 2;
// see file LICENSE or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include "loader.h"
#define TO_ARAM 0
#define TO_MRAM 1
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef volatile unsigned int vu32;
typedef volatile unsigned short vu16;
typedef struct _cInfo
{
int chan;
int fnum;
int offset;
int length;
u16 block;
} cInfo;
static void sync_cache(void *p, u32 n)
{
u32 start, end;
start = (u32)p & ~31;
end = ((u32)p + n + 31) & ~31;
n = (end - start) >> 5;
while (n--) {
asm("dcbst 0,%0 ; icbi 0,%0" : : "b"(p));
p += 32;
}
asm("sync ; isync");
}
void *_memcpy(void *ptr, const void *src, int size)
{
char* ptr2 = ptr;
const char* src2 = src;
while(size--) *ptr2++ = *src2++;
return ptr;
}
void os_enable_interrupts()
{
asm("mfmsr 3 ; ori 3, 3, 0x8000 ; mtmsr 3");
}
void os_disable_interrupts()
{
asm("mfmsr 3 ; rlwinm 3,3,0,17,15 ; mtmsr 3");
}
void ar_dma(u32 type, u32 mram, u32 aram, u32 len)
{
//interrupts are enabled so play it safe
os_disable_interrupts();
while(*(vu16*)0xCC00500A & 0x200) ;
*(vu16*)0xCC005020 = (mram>>16);
*(vu16*)0xCC005022 = (mram&0xFFFF);
*(vu16*)0xCC005024 = (aram>>16);
*(vu16*)0xCC005026 = (aram&0xFFFF);
*(vu16*)0xCC005028 = (type<<15)|(len>>16);
*(vu16*)0xCC00502A = (len&0xFFFF);
while(*(vu16*)0xCC00500A & 0x200) ;
os_enable_interrupts();
}
#if 0
#define EXI 0xCC006814
void EXISendByte( char byte )
{
loop:
*(vu32*)EXI = 0xD0;
*(vu32*)(EXI+0x10) = 0xB0000000 | (byte<<20);
*(vu32*)(EXI+0x0C) = 0x19;
while( *(vu32*)(EXI+0x0C)&1 );
u32 loop = *(vu32*)(EXI+0x10)&0x4000000;
*(vu32*)EXI = 0;
if( !loop )
goto loop;
return;
}
void pChar(char byte)
{
EXISendByte(byte);EXISendByte('\n');
}
void pHex(u32 h)
{
int i;
for(i = 28; i >= 0; i-=4)
{
u32 cBit = ((h>>i)&0xF);
if(cBit < 10)
EXISendByte('0'+cBit);
else
EXISendByte('A'+(cBit-10));
}
EXISendByte('\n');
}
#else
#define pChar(...)
#define pHex(...)
#endif
void os_stopaudiosystem(void);
void os_disable_scheduler(void);
int card_getres(int chan);
int card_mountasync(int chan, void* workArea, void *cb1, void *cb2);
int card_unmount(int chan);
int card_open(int chan, const char *path, cInfo *inf);
int card_close(cInfo *inf);
int card_readasync(cInfo *inf, void* addr, int length, int offset, void *cb);
void gx_flush(void);
void gx_abortframe(void);
extern volatile u8 gx_done;
static void our_gx_drawdone()
{
*(volatile u8*)0xCC008000 = 0x61;
*(volatile u32*)0xCC008000 = 0x45000002;
gx_flush();
gx_done = 0;
}
void __attribute__ ((noreturn)) _main()
{
pChar('0');
//game audio threads are still running
//so we just disable threading to prevent the
//game from randomly crashing on CARD access
os_disable_scheduler();
//prevent BEEPing
os_stopaudiosystem();
//setdrawdone not available in jap+ version
//so use this workaround way instead
gx_flush();
gx_abortframe();
our_gx_drawdone();
pChar('1');
//enable interrupts for GX and CARD access
os_enable_interrupts();
pChar('2');
//wait for the GX calls we did to finish
while(gx_done == 0) ;
//game id DOLX00 for boot.dol
*(volatile u32*)0x80000000 = 0x444F4C58;
*(volatile u16*)0x80000004 = 0x3030;
sync_cache((void*)0x80000000, 6);
//re-mount the memory card
card_mountasync(0, (void*)0x81200000, (void*)0, (void*)0);
int res;
//we have interrupts enabled so we will
//know when its not busy anymore luckily
while((res = card_getres(0)) == -1) ;
pChar('3');
//open up boot.dol from memory card
cInfo mInf;
unsigned int boot_str[3]; boot_str[0] = 0x626F6F74;
boot_str[1] = 0x2E646F6C; boot_str[2] = 0;
card_open(0, ((char*)&boot_str), &mInf);
pChar('4');
u32 curOffset = 0;
//copy until it returns error
while(card_readasync(&mInf, (void*)0x80001800, 0x200, curOffset, (void*)0) == 0)
{
int res;
//we have interrupts enabled so we will
//know when its not busy anymore luckily
while((res = card_getres(0)) == -1) ;
//this indirectly tells us the file is done
if(res < 0)
break;
sync_cache((void*)0x80001800, 0x200);
ar_dma(TO_ARAM, 0x1800, curOffset, 0x200);
curOffset += 0x200;
}
pChar('5');
//we are done
card_close(&mInf);
card_unmount(0);
pChar('6');
//not needed anymore
os_disable_interrupts();
//copy our loader into mem
_memcpy((void*)0x80001800, loader, loader_size);
sync_cache((void*)0x80001800, loader_size);
pChar('7');
//jump to it
__asm__ volatile(
"lis 3, 0x8000\n"
"ori 3, 3, 0x1800\n"
"mtlr 3\n"
"blr\n"
);
__builtin_unreachable();
}
You can’t perform that action at this time.