Compare commits

...

No commits in common. "wiki" and "master" have entirely different histories.
wiki ... master

114 changed files with 18022 additions and 155 deletions

916
Card.c Normal file
View File

@ -0,0 +1,916 @@
#include "Card.h"
FIL CardStat;
extern u32 FSTMode;
extern FIL GameFile;
void CardInit( void )
{
FILINFO f;
u32 i,wrote;
CARDStat CStat;
char GameID[0x20];
memset32( (void*)CARD_BASE, 0xdeadbeef, 0x20 );
memset32( (void*)CARD_SHADOW, 0, 0x20 );
//Create savefile dirs for the current game
if( f_chdir("/saves") != FR_OK )
{
f_mkdir("/saves");
f_chdir("/saves");
}
if( FSTMode )
{
FSTRead( (char*)GameID, 0x20, 0 );
} else {
f_lseek( &GameFile, 0 );
f_read( &GameFile, (char*)GameID, 0x20, &wrote );
}
if( f_chdir(GameID) != FR_OK )
{
f_mkdir(GameID);
f_chdir(GameID);
}
switch( f_stat( "stats.bin", &f ) )
{
case FR_NO_FILE:
{
if( f_open( &CardStat, "stats.bin", FA_CREATE_ALWAYS | FA_READ | FA_WRITE ) != FR_OK )
{
//dbgprintf("MC:Could not create stats file!\n");
} else {
memset32( &CStat, 0, sizeof( CARDStat ) );
for( i=0; i < CARD_MAX_FILES; ++i )
{
f_write( &CardStat, &CStat, sizeof( CARDStat ), &wrote );
}
f_sync( &CardStat );
}
} break;
case FR_OK:
{
if( f_open( &CardStat, "stats.bin", FA_OPEN_EXISTING | FA_READ | FA_WRITE ) != FR_OK )
{
;//dbgprintf("MC:Could not create stats file!\n");
}
} break;
default:
{
;//dbgprintf("MC:CardInit fuck up\n");
} break;
}
write32( 0x2FA0, 0 );
}
void LFNfy( char *str )
{
u32 len = strlen(str);
u32 i;
for( i=0; i < len; ++i )
{
switch( str[i] )
{
case '\\':
case '/':
case '*':
case '|':
case '?':
case '<':
case '>':
case '\"':
case ':':
str[i] = ' ';
break;
default:
break;
}
}
}
s32 CardFindFreeEntry( void )
{
CARDStat CStat;
u32 i;
u32 read;
for( i=0; i < CARD_MAX_FILES; ++i )
{
f_lseek( &CardStat, sizeof(CARDStat) * i );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
if( CStat.length == 0 )
{
//dbgprintf("CardFindFreeEntry(%d)\n", i );
return i;
}
}
return -1;
}
s32 CardFindEntryByName( char *Filename )
{
CARDStat CStat;
u32 i;
u32 read;
for( i=0; i < CARD_MAX_FILES; ++i )
{
f_lseek( &CardStat, sizeof(CARDStat) * i );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
if( strcmp( Filename, CStat.fileName ) == 0 )
{
//dbgprintf("CardFindEntryByName(%d,%s,%s)\n", i, Filename, CStat.fileName );
return i;
}
}
return -1;
}
s32 CardOpenFile( char *Filename, CARDFileInfo *CFInfo )
{
FIL savefile;
s32 Slot,fres;
Slot = CardFindEntryByName(Filename);
if( Slot < 0 )
{
write32( CARD_SCMD_4, -1 );
write32( CARD_SRETURN, CARD_NO_FILE );
return -4;
}
LFNfy( Filename );
fres = f_open( &savefile, Filename, FA_READ|FA_WRITE|FA_OPEN_EXISTING ) ;
switch( fres )
{
case FR_NO_PATH:
case FR_NO_FILE:
{
;//dbgprintf("MC:Failed to open:\"%s\":%d\n", Filename, fres );
write32( CARD_SCMD_4, -1 );
write32( CARD_SRETURN, CARD_NO_FILE );
} break;
default:
{
EXIControl(1);
;//dbgprintf("MC:Failed to open:\"%s\":%d\n", Filename, fres );
Shutdown();
} break;
case FR_OK:
{
f_close( &savefile );
write32( CARD_SCMD_4, Slot );
write32( CARD_SRETURN, CARD_SUCCESS );
} break;
}
return 0;
}
s32 CardFastOpenFile( u32 FileNo, CARDFileInfo *CFInfo )
{
CARDStat CStat;
FIL savefile;
s32 Slot,fres;
u32 read;
if( FileNo >= CARD_MAX_FILES )
{
write32( CARD_SRETURN, CARD_NO_FILE );
return 0;
}
f_lseek( &CardStat, sizeof(CARDStat) * FileNo );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
if( CStat.length == 0 )
{
write32( CARD_SRETURN, CARD_NO_FILE );
return 0;
}
LFNfy( CStat.fileName );
fres = f_open( &savefile, CStat.fileName, FA_READ|FA_WRITE|FA_OPEN_EXISTING ) ;
switch( fres )
{
case FR_NO_PATH:
case FR_NO_FILE:
{
;//dbgprintf("MC:Failed to open:\"%s\":%d\n", CStat.fileName, fres );
write32( CARD_SRETURN, CARD_NO_FILE );
} break;
default:
{
EXIControl(1);
;//dbgprintf("MC:Failed to open:\"%s\":%d\n", CStat.fileName, fres );
Shutdown();
} break;
case FR_OK:
{
write32( CARD_SCMD_4, savefile.fsize );
f_close( &savefile );
write32( CARD_SRETURN, CARD_SUCCESS );
} break;
}
return 0;
}
void CardDeleteFile( char *Filename )
{
CARDStat CStat;
u32 wrote;
s32 Slot;
Slot = CardFindEntryByName( Filename );
if( Slot < 0 )
{
dbgprintf("MC:\"%s\" doesn't exists\n", Filename );
write32( CARD_SRETURN, CARD_NO_FILE );
return;
}
memset32( &CStat, 0, sizeof(CARDStat) );
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_write( &CardStat, &CStat, sizeof(CARDStat), &wrote );
f_sync( &CardStat );
f_unlink( Filename );
write32( CARD_SRETURN, CARD_SUCCESS );
}
void CardFastDelete( u32 FileNo )
{
CARDStat CStat;
u32 read;
if( FileNo >= CARD_MAX_FILES )
{
write32( CARD_SRETURN, CARD_NO_FILE );
return;
}
f_lseek( &CardStat, sizeof(CARDStat) * FileNo );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
if( f_unlink( CStat.fileName ) == FR_OK )
{
memset32( &CStat, 0, sizeof(CARDStat) );
f_lseek( &CardStat, sizeof(CARDStat) * FileNo );
f_write( &CardStat, &CStat, sizeof(CARDStat), &read );
f_sync( &CardStat );
write32( CARD_SRETURN, CARD_SUCCESS );
} else {
write32( CARD_SRETURN, CARD_NO_FILE );
}
return;
}
void CardRename( char *NameSrc, char *NameDst )
{
CARDStat CStat;
u32 wrote;
s32 Slot;
Slot = CardFindEntryByName( NameDst );
if( Slot != -1 )
{
f_unlink( NameDst );
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_read( &CardStat, &CStat, sizeof(CARDStat), &wrote );
memset32( &CStat, 0, sizeof(CARDStat) );
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_write( &CardStat, &CStat, sizeof(CARDStat), &wrote );
f_sync( &CardStat );
}
Slot = CardFindEntryByName( NameSrc );
if( Slot == -1 )
{
write32( CARD_SRETURN, CARD_NO_FILE );
return;
}
switch( f_rename( NameSrc, NameDst ) )
{
case FR_OK:
{
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_read( &CardStat, &CStat, sizeof(CARDStat), &wrote );
memcpy( CStat.fileName, NameDst, 32 );
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_write( &CardStat, &CStat, sizeof(CARDStat), &wrote );
f_sync( &CardStat );
write32( CARD_SRETURN, CARD_SUCCESS );
} break;
//case FR_EXIST:
//{
// write32( CARD_SRETURN, CARD_FILE_EXISTS );
//} break;
default:
{
write32( CARD_SRETURN, CARD_FATAL_ERROR );
} break;
}
}
void CardCreateFile( char *Filename, u32 Size, CARDFileInfo *CFInfo )
{
CARDStat CStat;
u32 i,fres,read;
s32 Slot;
FIL savefile;
Slot = CardFindEntryByName( Filename );
if( Slot >= 0 )
{
;//dbgprintf("MC:\"%s\" already exists\n", Filename );
write32( CARD_SRETURN, CARD_FILE_EXISTS );
return;
}
Slot = CardFindFreeEntry();
if( Slot < 0 )
return;
char FName[32];
memcpy( FName, Filename, 32 );
LFNfy( FName );
fres = f_open( &savefile, FName, FA_READ|FA_WRITE|FA_CREATE_NEW );
switch( fres )
{
case FR_EXIST:
{
write32( CARD_SCMD_4, 0 );
write32( CARD_SRETURN, CARD_FILE_EXISTS );
} break;
default:
{
EXIControl(1);
;//dbgprintf("MC:Failed to create:\"%s\":%d\n", Filename, fres );
Shutdown();
} break;
case FR_OK:
{
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
memcpy( CStat.fileName, Filename, strlen(Filename) );
CStat.length = Size;
CStat.time = 0x15745a1a;
memcpy( CStat.gameName, (void*)0, 4 );
memcpy( CStat.company, (void*)4, 2 );
CStat.bannerFormat = 0;
CStat.iconAddr = -1;
CStat.iconFormat = 0;
CStat.iconSpeed = 0;
CStat.commentAddr = -1;
CStat.offsetBanner = -1;
CStat.offsetBannerTlut = -1;
for( i=0; i < 8; ++i )
CStat.offsetIcon[i] = -1;
CStat.offsetIconTlut = -1;
CStat.offsetData = 0;
f_lseek( &CardStat, sizeof(CARDStat) * Slot );
f_write( &CardStat, &CStat, sizeof(CARDStat), &read );
f_sync( &CardStat );
CFInfo->chan = 0;
CFInfo->fileNo = Slot;
CFInfo->iBlock = 0;
CFInfo->length = Size;
CFInfo->offset = 0;
char *buf = (char*)malloc(512);
memset32( buf, 0, 512 );
//Create full file
for( i=0; i < Size; i+=512 )
{
f_write( &savefile, buf, 512, &read);
}
f_close( &savefile );
write32( CARD_SCMD_4, Slot );
write32( CARD_SRETURN, CARD_SUCCESS );
} break;
}
}
void CardReadFile( u32 FileNo, u8 *Buffer, u32 Length, u32 Offset )
{
u32 read;
CARDStat CStat;
FIL savefile;
f_lseek( &CardStat, sizeof(CARDStat) * FileNo );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
LFNfy( CStat.fileName );
if( f_open( &savefile, CStat.fileName, FA_OPEN_EXISTING | FA_READ ) == FR_OK )
{
f_lseek( &savefile, Offset );
f_read( &savefile, (void*)Buffer, Length, &read );
f_close( &savefile );
}
}
void CardWriteFile( u32 FileNo, u8 *Buffer, u32 Length, u32 Offset )
{
u32 read;
CARDStat CStat;
FIL savefile;
f_lseek( &CardStat, sizeof(CARDStat) * FileNo );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
LFNfy( CStat.fileName );
switch( f_open( &savefile, CStat.fileName, FA_OPEN_EXISTING | FA_WRITE ) )
{
case FR_OK:
{
#ifdef CARD_DEBUG
if( f_lseek( &savefile, Offset ) != FR_OK )
{
EXIControl(1);
dbgprintf("Failed to seek to %08x\n", Offset );
Shutdown();
} else {
if( f_write( &savefile, (void*)Buffer, Length, &read ) != FR_OK )
{
EXIControl(1);
dbgprintf("Failed to write %d bytes to %p\n", Length, Buffer );
Shutdown();
}
if( read != Length )
{
EXIControl(1);
dbgprintf("Short write; %d of %d bytes written!\n", read, Length );
Shutdown();
}
}
#else
f_lseek( &savefile, Offset );
f_write( &savefile, (void*)Buffer, Length, &read );
#endif
f_close( &savefile );
} break;
default:
{
EXIControl(1);
dbgprintf("Failed to open:\"%s\"\n", CStat.fileName );
Shutdown();
} break;
}
}
void CardUpdateStats( CARDStat *CStat )
{
u32 IconSize,BannerSize,Format,Offset,i,TLut=0;
BannerSize = CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
IconSize = CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
Offset = CStat->iconAddr;
if( CStat->bannerFormat & CARD_STAT_BANNER_C8 )
{
CStat->offsetBanner = Offset;
CStat->offsetBannerTlut = Offset + BannerSize;
Offset += BannerSize + 512;
} else if( CStat->bannerFormat & CARD_STAT_BANNER_RGB5A3 ) {
CStat->offsetBanner = Offset;
CStat->offsetBannerTlut = -1;
Offset += BannerSize * 2;
} else {
CStat->offsetBanner = -1;
CStat->offsetBannerTlut = -1;
}
for( i=0; i < CARD_ICON_MAX; ++i )
{
Format = CStat->iconFormat >> ( i * 2 );
if( Format & CARD_STAT_ICON_C8 )
{
CStat->offsetIcon[i] = Offset;
Offset += IconSize;
TLut = 1;
} else if ( Format & CARD_STAT_ICON_RGB5A3 ) {
CStat->offsetIcon[i] = Offset;
Offset += IconSize * 2;
} else {
CStat->offsetIcon[i] = -1;
}
}
if( TLut )
{
CStat->offsetIconTlut = Offset;
Offset += 512;
} else {
CStat->offsetIconTlut = -1;
}
CStat->offsetData = Offset;
}
void CARDUpdateRegisters( void )
{
u32 read,i;
u32 CARDOK=0;
if( read32(CARD_CONTROL) != 0xdeadbeef )
{
if( read32( CARD_CONTROL ) & (~3) )
{
write32( CARD_CONTROL, 0xdeadbeef );
return;
}
write32( CARD_SCONTROL, read32(CARD_CONTROL) & 3 );
clear32( CARD_SSTATUS, 0x14 );
write32( CARD_CONTROL, 0xdeadbeef );
if( ConfigGetConfig(DML_CFG_ACTIVITY_LED) )
set32( HW_GPIO_OUT, 1<<5 );
while( read32(CARD_CMD) == 0xdeadbeef );
write32( CARD_SCMD, read32(CARD_CMD) );
write32( CARD_CMD, 0xdeadbeef );
while( read32(CARD_CMD_1) == 0xdeadbeef );
write32( CARD_SCMD_1, read32(CARD_CMD_1) );
write32( CARD_CMD_1, 0xdeadbeef );
if( read32(CARD_CMD_2) != 0xdeadbeef )
{
write32( CARD_SCMD_2, read32(CARD_CMD_2) );
write32( CARD_CMD_2, 0xdeadbeef );
}
if( read32(CARD_CMD_3) != 0xdeadbeef )
{
write32( CARD_SCMD_3, read32(CARD_CMD_3) );
write32( CARD_CMD_3, 0xdeadbeef );
}
if( read32(CARD_CMD_4) != 0xdeadbeef )
{
write32( CARD_SCMD_4, read32(CARD_CMD_4) );
write32( CARD_CMD_4, 0xdeadbeef );
}
switch( read32(CARD_SCMD) >> 24 )
{
case 0x00:
{
;//dbgprintf("CARD:Warning unknown command!\n");
} break;
default:
{
//EXIControl(1);
dbgprintf("CARD:Unknown CMD:%08X %08X %08X %08X %08X %08X\n", read32(CARD_SCMD), read32(CARD_SCMD_1), read32(CARD_SCMD_2), read32(CARD_SCMD_3), read32(CARD_SCMD_4), read32(CARD_SCONTROL) );
Shutdown();
} break;
/* CARDOpen( char *FileName ) */
case 0xC0:
{
char FileName[32];
u32 FInfo = P2C(read32(CARD_SCMD_2));
memcpy( FileName, (void*)0x17E0, 32 );
#ifdef CARDDEBUG
dbgprintf("MC:CARDOpen( \"%s\", 0x%08x )", FileName, FInfo );
#endif
CardOpenFile( (char*)FileName, (CARDFileInfo*)FInfo );
CARDOK = 1;
} break;
case 0xC1:
{
u32 FileNo = read32(CARD_SCMD_1);
#ifdef CARDDEBUG
dbgprintf("MC:CARDClose( %d )", FileNo );
#endif
if( FileNo < 0 )
write32( CARD_SRETURN, -128 );
else
write32( CARD_SRETURN, 0 );
CARDOK = 1;
} break;
case 0xC2:
{
char FileName[32];
u32 Size = read32(CARD_SCMD_2);
u32 FInfo = P2C(read32(CARD_SCMD_3));
memcpy( FileName, (void*)0x17E0, 32 );
#ifdef CARDDEBUG
dbgprintf("MC:CARDCreate( \"%s\", 0x%04x, 0x%08x )", FileName, Size, FInfo );
#endif
CardCreateFile( (char*)FileName, Size, (CARDFileInfo*)FInfo );
write32( 0x2FA0, read32(0x2FA0) + CARD_XFER_CREATE );
CARDOK = 1;
} break;
case 0xC3:
{
CARDStat CS;
#ifdef CARDDEBUG
dbgprintf("MC:CARDGetState( %d, 0x%08x, ", read32(CARD_SCMD_1), P2C(read32(CARD_SCMD_2)) );
#endif
if( read32(CARD_SCMD_1) >= CARD_MAX_FILES )
{
EXIControl(1);
dbgprintf("MC: Invalid file slot!:%d\n", read32(CARD_SCMD_1) );
Shutdown();
}
f_lseek( &CardStat, sizeof(CARDStat) * read32(CARD_SCMD_1) );
f_read( &CardStat, &CS, sizeof(CARDStat), &read );
if( CS.length == 0 )
{
#ifdef CARDDEBUG
// dbgprintf(")");
#endif
write32( CARD_SRETURN, CARD_NO_FILE );
} else {
CardUpdateStats( &CS );
memcpy( (void*)0x1780, &CS, sizeof(CARDStat) );
#ifdef CARDDEBUG
CARDStat *CSTAT = (CARDStat*)0x1780;
dbgprintf("\nMC:Card Status:\n");
dbgprintf("\tFilename:%.32s\n", CSTAT->fileName );
dbgprintf("\tGameName:%.4s\n", CSTAT->gameName );
dbgprintf("\tCompany :%.2s\n", CSTAT->company );
dbgprintf("\tLength :%d\n", CSTAT->length );
dbgprintf("\tTime :%d\n\n", CSTAT->time );
dbgprintf("\tBannerFormat:%d\n", CSTAT->bannerFormat );
dbgprintf("\tIconAddress :0x%04X\n", CSTAT->iconAddr );
dbgprintf("\tIconFormat :0x%02X\n", CSTAT->iconFormat );
dbgprintf("\tIconSpeed :0x%02X\n", CSTAT->iconSpeed );
dbgprintf("\tComntAddress:0x%04X\n\n", CSTAT->commentAddr );
dbgprintf("\tOffsetBanner :0x%04X\n", CSTAT->offsetBanner );
dbgprintf("\tOffsetBnrTlt :0x%04X\n", CSTAT->offsetBannerTlut );
for( i=0; i < CARD_ICON_MAX; ++i)
dbgprintf("\tOffsetIcon[%d]:0x%04X\n", i, CSTAT->offsetIcon[i] );
dbgprintf("\tOffsetIconTlt:0x%04X\n", CSTAT->offsetIconTlut );
dbgprintf("\tOffsetData :0x%04X\n", CSTAT->offsetData );
#endif
write32( CARD_SRETURN, CARD_SUCCESS );
}
CARDOK = 1;
} break;
case 0xC4:
{
CARDStat CS;
#ifdef CARDDEBUG
dbgprintf("MC:CARDSetState( %d, 0x%08x )", read32(CARD_SCMD_1), P2C(read32(CARD_SCMD_2)) );
#endif
if( read32(CARD_SCMD_1) >= CARD_MAX_FILES )
{
EXIControl(1);
dbgprintf("\nMC: Invalid file slot!\n");
Shutdown();
}
CARDStat *CStat = (CARDStat *) P2C(read32(CARD_SCMD_2));
f_lseek( &CardStat, sizeof(CARDStat) * read32(CARD_SCMD_1) );
f_read( &CardStat, &CS, sizeof(CARDStat), &read );
if( CS.length == 0 )
{
#ifdef CARDDEBUG
dbgprintf(")");
#endif
write32( CARD_SRETURN, CARD_NO_FILE );
} else {
CS.bannerFormat = CStat->bannerFormat;
CS.iconAddr = CStat->iconAddr;
CS.iconFormat = CStat->iconFormat;
CS.iconSpeed = CStat->iconSpeed;
CS.commentAddr = CStat->commentAddr;
#ifdef CARDDEBUG
dbgprintf("\nMC:Card Status:\n");
dbgprintf("\tFilename:%.32s\n", CS.fileName );
dbgprintf("\tGameName:%.4s\n", CS.gameName );
dbgprintf("\tCompany :%.2s\n", CS.company );
dbgprintf("\tLength :%d\n", CS.length );
dbgprintf("\tTime :%d\n\n", CS.time );
dbgprintf("\tBannerFormat:%d\n", CS.bannerFormat );
dbgprintf("\tIconAddress :0x%04X\n", CS.iconAddr );
dbgprintf("\tIconFormat :0x%02X\n", CS.iconFormat );
dbgprintf("\tIconSpeed :0x%02X\n", CS.iconSpeed );
dbgprintf("\tComntAddress:0x%04X\n\n", CS.commentAddr );
#endif
CardUpdateStats( &CS );
#ifdef CARDDEBUG
dbgprintf("\tOffsetBanner :0x%04X\n", CS.offsetBanner );
dbgprintf("\tOffsetBnrTlt :0x%04X\n", CS.offsetBannerTlut );
for( i=0; i < CARD_ICON_MAX; ++i)
dbgprintf("\tOffsetIcon[%d]:0x%04X\n", i, CS.offsetIcon[i] );
dbgprintf("\tOffsetIconTlt:0x%04X\n", CS.offsetIconTlut );
dbgprintf("\tOffsetData :0x%04X\n", CS.offsetData );
#endif
f_lseek( &CardStat, sizeof(CARDStat) * read32(CARD_SCMD_1) );
f_write( &CardStat, &CS, sizeof(CARDStat), &read );
f_sync( &CardStat );
write32( 0x2FA0, read32(0x2FA0) + CARD_XFER_SETSTATUS );
write32( CARD_SRETURN, CARD_SUCCESS );
}
CARDOK = 1;
} break;
/* CARDFastOpen( u32 FileNO, CARDFileInfo *CFInfo ) */
case 0xC5:
{
u32 FileNo = read32(CARD_SCMD_1);
u32 FInfo = P2C(read32(CARD_SCMD_2));
#ifdef CARDDEBUG
dbgprintf("MC:CARDFastOpen( %d, 0x%08X )", FileNo, FInfo );
#endif
CardFastOpenFile( FileNo, (CARDFileInfo*)FInfo );
CARDOK = 1;
} break;
case 0xC6:
{
char FileName[32];
memcpy( FileName, (void*)0x17E0, 32 );
#ifdef CARDDEBUG
dbgprintf("MC:CARDDelete( \"%s\" )", FileName );
#endif
CardDeleteFile( (char*)FileName );
write32( 0x2FA0, read32(0x2FA0) + CARD_XFER_DELETE );
CARDOK = 1;
} break;
case 0xC8:
{
u32 Buffer = P2C(read32(CARD_SCMD_1));
u32 Length = read32(CARD_SCMD_2);
u32 Offset = read32(CARD_SCMD_3);
u32 FileNo = read32(CARD_SCMD_4);
#ifdef CARDDEBUG
dbgprintf("MC:CARDWrite( %d, 0x%08x, 0x%04x, 0x%04x )", FileNo, Buffer, Offset, Length );
#endif
if( FileNo >= CARD_MAX_FILES )
{
EXIControl(1);
dbgprintf("\nMC: Invalid file slot!:%d\n", FileNo );
Shutdown();
}
CardWriteFile( FileNo, (u8*)Buffer, Length, Offset );
write32( 0x2FA0, read32(0x2FA0) + CARD_XFER_WRITE + Length );
write32( CARD_SRETURN, 0 );
CARDOK = 1;
} break;
case 0xC9:
{
u32 Buffer = P2C(read32(CARD_SCMD_1));
u32 Length = read32(CARD_SCMD_2);
u32 Offset = read32(CARD_SCMD_3);
u32 FileNo = read32(CARD_SCMD_4);
#ifdef CARDDEBUG
dbgprintf("MC:CARDRead( %d, 0x%08x, 0x%04x, 0x%04x )", FileNo, Buffer, Offset, Length );
#endif
if( FileNo >= CARD_MAX_FILES )
{
EXIControl(1);
dbgprintf("\nMC: Invalid file slot!:%d\n", FileNo );
Shutdown();
}
CardReadFile( FileNo, (u8*)Buffer, Length, Offset );
write32( 0x2FA0, read32(0x2FA0) + Length );
write32( CARD_SRETURN, 0 );
CARDOK = 1;
} break;
case 0xCA:
{
u32 FileNo = read32( CARD_SCMD_1 );
#ifdef CARDDEBUG
dbgprintf("MC:CARDFastDelete( %u )", FileNo );
#endif
CardFastDelete( FileNo );
write32( 0x2FA0, read32(0x2FA0) + CARD_XFER_DELETE );
CARDOK = 1;
} break;
case 0xCB:
{
char NameSrc[32];
char NameDst[32];
memcpy( NameSrc, (void*)0x17C0, 32 );
memcpy( NameDst, (void*)0x17E0, 32 );
#ifdef CARDDEBUG
dbgprintf("MC:CARDRename( \"%s\", \"%s\" )", NameSrc, NameDst );
#endif
CardRename( NameSrc, NameDst );
CARDOK = 1;
} break;
}
if(CARDOK)
{
#ifdef CARDDEBUG
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
#endif
while( read32(CARD_SCONTROL) & 1 )
clear32( CARD_SCONTROL, 1 );
set32( CARD_SSTATUS, 0x10 );
}
if( ConfigGetConfig(DML_CFG_ACTIVITY_LED) )
clear32( HW_GPIO_OUT, 1<<5 );
}
}

111
Card.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef _CARD_
#define _CARD_
#include "string.h"
#include "global.h"
#include "alloc.h"
#include "ff.h"
#include "vsprintf.h"
#include "HW.h"
#include "vsprintf.h"
#define CARD_MAX_FILES 128
#define CARD_BASE 0x00002F60
#define CARD_CMD (CARD_BASE+0x00)
#define CARD_CMD_1 (CARD_BASE+0x04)
#define CARD_CMD_2 (CARD_BASE+0x08)
#define CARD_CMD_3 (CARD_BASE+0x0C)
#define CARD_CMD_4 (CARD_BASE+0x10)
#define CARD_RETURN (CARD_BASE+0x14)
#define CARD_CONTROL (CARD_BASE+0x18)
#define CARD_STATUS (CARD_BASE+0x1C)
#define CARD_SHADOW (CARD_BASE + 0x20)
#define CARD_SCMD (CARD_SHADOW+0x00)
#define CARD_SCMD_1 (CARD_SHADOW+0x04)
#define CARD_SCMD_2 (CARD_SHADOW+0x08)
#define CARD_SCMD_3 (CARD_SHADOW+0x0C)
#define CARD_SCMD_4 (CARD_SHADOW+0x10)
#define CARD_SRETURN (CARD_SHADOW+0x14)
#define CARD_SCONTROL (CARD_SHADOW+0x18)
#define CARD_SSTATUS (CARD_SHADOW+0x1C)
// internal API command xfer bytes
#define CARD_XFER_CREATE (2 * 8 * 1024) // CARDCreate[Async]
#define CARD_XFER_DELETE (2 * 8 * 1024) // CARD[Fast]Delete[Async]
#define CARD_XFER_MOUNT (5 * 8 * 1024) // CARDMount[Async]
#define CARD_XFER_FORMAT (5 * 8 * 1024) // CARDFormat[Async]
#define CARD_XFER_RENAME (1 * 8 * 1024) // CARDRename[Async]
#define CARD_XFER_SETSTATUS (1 * 8 * 1024) // CARDSetStatus[Async]
#define CARD_XFER_SETATTRIBUTES (1 * 8 * 1024) // CARDSetAttributes[Async]
#define CARD_XFER_WRITE (1 * 8 * 1024) // CARDWrite[Async]
#define CARD_FILENAME_MAX 32
#define CARD_ICON_MAX 8
#define CARD_ICON_WIDTH 32
#define CARD_ICON_HEIGHT 32
#define CARD_BANNER_WIDTH 96
#define CARD_BANNER_HEIGHT 32
#define CARD_STAT_ICON_NONE 0
#define CARD_STAT_ICON_C8 1
#define CARD_STAT_ICON_RGB5A3 2
#define CARD_STAT_BANNER_NONE 0
#define CARD_STAT_BANNER_C8 1
#define CARD_STAT_BANNER_RGB5A3 2
enum CardStatus
{
CARD_SUCCESS = 0,
CARD_NO_FILE = -4,
CARD_FILE_EXISTS = -7,
CARD_FATAL_ERROR =-128,
};
typedef struct CARDFileInfo
{
/* 0x00 */ s32 chan;
/* 0x04 */ s32 fileNo;
/* 0x08 */ s32 offset;
/* 0x0C */ s32 length;
/* 0x10 */ u16 iBlock;
} CARDFileInfo;
typedef struct CARDStat
{
// read-only (Set by CARDGetStatus)
/* 0x00 */ char fileName[32];
/* 0x20 */ u32 length;
/* 0x24 */ u32 time; // seconds since 01/01/2000 midnight
/* 0x28 */ u8 gameName[4];
/* 0x2C */ u8 company[2];
// read/write (Set by CARDGetStatus/CARDSetStatus)
/* 0x2E */ u8 bannerFormat;
/* 0x30 */ u32 iconAddr; // offset to the banner, bannerTlut, icon, iconTlut data set.
/* 0x34 */ u16 iconFormat;
/* 0x36 */ u16 iconSpeed;
/* 0x38 */ u32 commentAddr; // offset to the pair of 32 byte character strings.
// read-only (Set by CARDGetStatus)
/* 0x3C */ u32 offsetBanner;
/* 0x40 */ u32 offsetBannerTlut;
/* 0x44 */ u32 offsetIcon[8];
/* 0x64 */ u32 offsetIconTlut;
/* 0x68 */ u32 offsetData;
} CARDStat;
void CardInit( void );
void CARDUpdateRegisters( void );
s32 CardFindFreeEntry( void );
s32 CardOpenFile( char *Filename, CARDFileInfo *CFInfo );
void CardCreateFile( char *Filename, u32 Size, CARDFileInfo *CFInfo );
#endif

30
CardPatches.c Normal file
View File

@ -0,0 +1,30 @@
#ifndef __CARDPATCHES__
#define __CARDPATCHES__
#include "asm\__CARDSync.h"
#include "asm\CARDCheck.h"
#include "asm\CARDCheckAsync.h"
#include "asm\CARDCheckEX.h"
#include "asm\CARDClose.h"
#include "asm\CARDCreate.h"
#include "asm\CARDDelete.h"
#include "asm\CARDFastOpen.h"
#include "asm\CARDFreeBlocks.h"
#include "asm\CARDGetEncoding.h"
#include "asm\CARDGetMemSize.h"
#include "asm\CARDGetSerialNo.h"
#include "asm\CARDGetStats.h"
#include "asm\CARDMount.h"
#include "asm\CARDMountAsync.h"
#include "asm\CARDOpen.h"
#include "asm\CARDProbe.h"
#include "asm\CARDProbeEX.h"
#include "asm\CARDRead.h"
#include "asm\CARDSetStats.h"
#include "asm\CARDWrite.h"
#include "asm\CARDGetResultCode.h"
#include "asm\CARDGetXferredBytes.h"
#include "asm\CARDFastDelete.h"
#include "asm\CARDRename.h"
#endif

448
CheatCode.c Normal file
View File

@ -0,0 +1,448 @@
#include "global.h"
unsigned char kenobigcDBG[4288] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x27, 0x74, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x21, 0xff, 0x58, 0x90, 0x01, 0x00, 0x08,
0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0xac, 0x7c, 0x00, 0x00, 0x26, 0x90, 0x01, 0x00, 0x0c,
0x7c, 0x09, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x10, 0x7c, 0x01, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x14,
0xbc, 0x61, 0x00, 0x18, 0x7f, 0x20, 0x00, 0xa6, 0x63, 0x3a, 0x20, 0x00, 0x73, 0x5a, 0xf9, 0xff,
0x7f, 0x40, 0x01, 0x24, 0xd8, 0x41, 0x00, 0x98, 0xd8, 0x61, 0x00, 0xa0, 0x3f, 0xe0, 0x80, 0x00,
0x3e, 0x80, 0xcc, 0x00, 0xa3, 0x94, 0x40, 0x10, 0x63, 0x95, 0x00, 0xff, 0xb2, 0xb4, 0x40, 0x10,
0x48, 0x00, 0x06, 0x55, 0x3a, 0xa0, 0x00, 0x00, 0x3a, 0xc0, 0x00, 0x19, 0x3a, 0xe0, 0x00, 0xd0,
0x3f, 0x00, 0xcc, 0x00, 0x63, 0xf2, 0x27, 0x74, 0x80, 0x01, 0x00, 0xac, 0x90, 0x12, 0x00, 0x04,
0x92, 0xb8, 0x64, 0x3c, 0x48, 0x00, 0x04, 0x2d, 0x41, 0x82, 0x05, 0xa4, 0x2c, 0x1d, 0x00, 0x04,
0x40, 0x80, 0x00, 0x10, 0x2c, 0x1d, 0x00, 0x01, 0x41, 0x80, 0x05, 0x94, 0x48, 0x00, 0x03, 0x4c,
0x41, 0x82, 0x04, 0xf0, 0x2c, 0x1d, 0x00, 0x06, 0x41, 0x82, 0x00, 0x8c, 0x2c, 0x1d, 0x00, 0x07,
0x41, 0x82, 0x03, 0x30, 0x2c, 0x1d, 0x00, 0x08, 0x41, 0x82, 0x05, 0x80, 0x2c, 0x1d, 0x00, 0x09,
0x41, 0x82, 0x00, 0xa0, 0x2c, 0x1d, 0x00, 0x10, 0x41, 0x82, 0x00, 0x98, 0x2c, 0x1d, 0x00, 0x2f,
0x41, 0x82, 0x00, 0x70, 0x2c, 0x1d, 0x00, 0x30, 0x41, 0x82, 0x00, 0x78, 0x2c, 0x1d, 0x00, 0x38,
0x41, 0x82, 0x05, 0x28, 0x2c, 0x1d, 0x00, 0x40, 0x41, 0x82, 0x03, 0x40, 0x2c, 0x1d, 0x00, 0x41,
0x41, 0x82, 0x03, 0x58, 0x2c, 0x1d, 0x00, 0x44, 0x41, 0x82, 0x00, 0x68, 0x2c, 0x1d, 0x00, 0x50,
0x41, 0x82, 0x00, 0x20, 0x2c, 0x1d, 0x00, 0x60, 0x41, 0x82, 0x00, 0x24, 0x2c, 0x1d, 0x00, 0x89,
0x41, 0x82, 0x00, 0x50, 0x2c, 0x1d, 0x00, 0x99, 0x41, 0x82, 0x05, 0x0c, 0x48, 0x00, 0x05, 0x10,
0x80, 0x72, 0x00, 0x00, 0x48, 0x00, 0x04, 0x29, 0x48, 0x00, 0x05, 0x04, 0x48, 0x00, 0x05, 0x89,
0x48, 0x00, 0x04, 0xfc, 0x38, 0x80, 0x00, 0x01, 0x90, 0x92, 0x00, 0x00, 0x48, 0x00, 0x04, 0xf0,
0x48, 0x00, 0x04, 0x09, 0x3a, 0x00, 0x00, 0xa0, 0x63, 0xec, 0x27, 0x98, 0x48, 0x00, 0x03, 0x14,
0x38, 0x60, 0x01, 0x20, 0x63, 0xec, 0x27, 0x98, 0x48, 0x00, 0x03, 0xc9, 0x48, 0x00, 0x04, 0xd0,
0x2f, 0x1d, 0x00, 0x10, 0x2e, 0x9d, 0x00, 0x44, 0x63, 0xe4, 0x1a, 0xb4, 0x3c, 0x60, 0x80, 0x00,
0x60, 0x63, 0x03, 0x00, 0x48, 0x00, 0x05, 0x09, 0x38, 0x63, 0x0a, 0x00, 0x48, 0x00, 0x05, 0x01,
0x38, 0x63, 0x06, 0x00, 0x48, 0x00, 0x04, 0xf9, 0x63, 0xec, 0x27, 0x88, 0x92, 0xac, 0x00, 0x00,
0x92, 0xac, 0x00, 0x04, 0x92, 0xac, 0x00, 0x08, 0x63, 0xe4, 0x27, 0x98, 0x81, 0x24, 0x00, 0x18,
0x80, 0x72, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x02, 0x40, 0x82, 0x00, 0x0c, 0x41, 0x96, 0x00, 0x0c,
0x48, 0x00, 0x00, 0x20, 0x38, 0x60, 0x00, 0x00, 0x90, 0x6c, 0x00, 0x0c, 0x40, 0x82, 0x00, 0x14,
0x40, 0x96, 0x00, 0x10, 0x61, 0x29, 0x04, 0x00, 0x91, 0x24, 0x00, 0x18, 0x48, 0x00, 0x02, 0x14,
0x55, 0x29, 0x05, 0xa8, 0x91, 0x24, 0x00, 0x18, 0x41, 0x96, 0x04, 0x54, 0x41, 0x9a, 0x00, 0x08,
0x39, 0x8c, 0x00, 0x04, 0x38, 0x60, 0x00, 0x04, 0x48, 0x00, 0x03, 0x09, 0x40, 0x99, 0x00, 0x10,
0x39, 0x8c, 0x00, 0x04, 0x38, 0x60, 0x00, 0x04, 0x48, 0x00, 0x02, 0xf9, 0x63, 0xe4, 0x27, 0x88,
0x80, 0x64, 0x00, 0x00, 0x80, 0x84, 0x00, 0x04, 0x7c, 0x72, 0xfb, 0xa6, 0x7c, 0x95, 0xfb, 0xa6,
0x48, 0x00, 0x04, 0x1c, 0x7c, 0x32, 0x43, 0xa6, 0x7c, 0x3a, 0x02, 0xa6, 0x7c, 0x73, 0x43, 0xa6,
0x7c, 0x7b, 0x02, 0xa6, 0x54, 0x63, 0x05, 0xa8, 0x90, 0x60, 0x27, 0xb0, 0x54, 0x63, 0x06, 0x1e,
0x60, 0x63, 0x20, 0x00, 0x7c, 0x7b, 0x03, 0xa6, 0x3c, 0x60, 0x80, 0x00, 0x60, 0x63, 0x1a, 0xe8,
0x7c, 0x7a, 0x03, 0xa6, 0x4c, 0x00, 0x00, 0x64, 0x3c, 0x60, 0x80, 0x00, 0x60, 0x63, 0x27, 0x98,
0x90, 0x23, 0x00, 0x14, 0x7c, 0x61, 0x1b, 0x78, 0x7c, 0x73, 0x42, 0xa6, 0xbc, 0x41, 0x00, 0x24,
0x7c, 0x24, 0x0b, 0x78, 0x7c, 0x32, 0x42, 0xa6, 0x90, 0x04, 0x00, 0x1c, 0x90, 0x24, 0x00, 0x20,
0x7c, 0x68, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x9c, 0x7c, 0x60, 0x00, 0x26, 0x90, 0x64, 0x00, 0x00,
0x7c, 0x61, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x04, 0x7c, 0x69, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x08,
0x7c, 0x72, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x0c, 0x7c, 0x73, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x10,
0x39, 0x20, 0x00, 0x00, 0x7d, 0x32, 0xfb, 0xa6, 0x7d, 0x35, 0xfb, 0xa6, 0x3c, 0xa0, 0x80, 0x00,
0x60, 0xa5, 0x1b, 0x70, 0x3f, 0xe0, 0xd0, 0x04, 0x63, 0xff, 0x00, 0xa0, 0x93, 0xe5, 0x00, 0x00,
0x7c, 0x00, 0x28, 0x6c, 0x7c, 0x00, 0x04, 0xac, 0x7c, 0x00, 0x2f, 0xac, 0x4c, 0x00, 0x01, 0x2c,
0xd0, 0x04, 0x00, 0xa0, 0x3b, 0xff, 0x00, 0x04, 0x3f, 0xff, 0x00, 0x20, 0x57, 0xf0, 0x01, 0x4b,
0x41, 0x82, 0xff, 0xdc, 0x3f, 0xe0, 0x80, 0x00, 0x63, 0xe5, 0x27, 0x88, 0x82, 0x05, 0x00, 0x00,
0x82, 0x25, 0x00, 0x04, 0x82, 0x65, 0x00, 0x0c, 0x2c, 0x13, 0x00, 0x00, 0x41, 0x82, 0x00, 0x74,
0x2c, 0x13, 0x00, 0x02, 0x40, 0x82, 0x00, 0x18, 0x81, 0x24, 0x00, 0x14, 0x39, 0x33, 0x00, 0x03,
0x91, 0x25, 0x00, 0x00, 0x91, 0x25, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x6c, 0x7c, 0x10, 0x98, 0x00,
0x41, 0x82, 0x00, 0x38, 0x7c, 0x11, 0x98, 0x00, 0x41, 0x82, 0x00, 0x30, 0x7d, 0x30, 0x8a, 0x14,
0x91, 0x25, 0x00, 0x0c, 0x82, 0x05, 0x00, 0x08, 0x2c, 0x10, 0x00, 0x00, 0x41, 0x82, 0x00, 0x48,
0x80, 0x64, 0x00, 0x10, 0x7c, 0x10, 0x18, 0x00, 0x40, 0x82, 0x00, 0x10, 0x3a, 0x00, 0x00, 0x00,
0x92, 0x05, 0x00, 0x08, 0x48, 0x00, 0x00, 0x30, 0x3a, 0x20, 0x00, 0x00, 0x92, 0x25, 0x00, 0x0c,
0x81, 0x24, 0x00, 0x18, 0x61, 0x29, 0x04, 0x00, 0x91, 0x24, 0x00, 0x18, 0x48, 0x00, 0x00, 0x30,
0x7e, 0x12, 0xfb, 0xa6, 0x7e, 0x35, 0xfb, 0xa6, 0x39, 0x20, 0x00, 0x01, 0x91, 0x25, 0x00, 0x0c,
0x48, 0x00, 0x00, 0x1c, 0x38, 0xa0, 0x00, 0x02, 0x63, 0xe4, 0x27, 0x74, 0x90, 0xa4, 0x00, 0x00,
0x38, 0x60, 0x00, 0x11, 0x48, 0x00, 0x01, 0xb9, 0x4b, 0xff, 0xfc, 0x71, 0x7c, 0x20, 0x00, 0xa6,
0x54, 0x21, 0x07, 0xfa, 0x54, 0x21, 0x04, 0x5e, 0x7c, 0x20, 0x01, 0x24, 0x63, 0xe1, 0x27, 0x98,
0x80, 0x61, 0x00, 0x00, 0x7c, 0x6f, 0xf1, 0x20, 0x80, 0x61, 0x00, 0x14, 0x7c, 0x7a, 0x03, 0xa6,
0x80, 0x61, 0x00, 0x18, 0x7c, 0x7b, 0x03, 0xa6, 0x80, 0x61, 0x00, 0x9c, 0x7c, 0x68, 0x03, 0xa6,
0xb8, 0x41, 0x00, 0x24, 0x80, 0x01, 0x00, 0x1c, 0x80, 0x21, 0x00, 0x20, 0x4c, 0x00, 0x00, 0x64,
0x92, 0xb2, 0x00, 0x00, 0x48, 0x00, 0x02, 0x54, 0x2e, 0x9d, 0x00, 0x02, 0x38, 0x60, 0x00, 0x08,
0x63, 0xec, 0x27, 0x7c, 0x48, 0x00, 0x00, 0xfd, 0x80, 0xac, 0x00, 0x00, 0x80, 0x6c, 0x00, 0x04,
0x98, 0x65, 0x00, 0x00, 0x41, 0x94, 0x00, 0x10, 0xb0, 0x65, 0x00, 0x00, 0x41, 0x96, 0x00, 0x08,
0x90, 0x65, 0x00, 0x00, 0x7c, 0x00, 0x28, 0xac, 0x7c, 0x00, 0x04, 0xac, 0x7c, 0x00, 0x2f, 0xac,
0x4c, 0x00, 0x01, 0x2c, 0x48, 0x00, 0x02, 0x08, 0x48, 0x00, 0x01, 0x21, 0x38, 0x60, 0x00, 0x04,
0x63, 0xec, 0x27, 0x7c, 0x48, 0x00, 0x00, 0xbd, 0x82, 0x0c, 0x00, 0x00, 0x3d, 0x80, 0x80, 0x00,
0x61, 0x8c, 0x28, 0xb8, 0x48, 0x00, 0x00, 0x1c, 0x48, 0x00, 0x01, 0x01, 0x38, 0x60, 0x00, 0x08,
0x63, 0xec, 0x27, 0x7c, 0x48, 0x00, 0x00, 0x9d, 0x82, 0x0c, 0x00, 0x04, 0x81, 0x8c, 0x00, 0x00,
0x63, 0xfb, 0x27, 0x84, 0x3a, 0x20, 0x0f, 0x80, 0x48, 0x00, 0x02, 0x39, 0x41, 0x82, 0x00, 0x20,
0x7e, 0x23, 0x8b, 0x78, 0x48, 0x00, 0x00, 0x7d, 0x48, 0x00, 0x00, 0xd1, 0x41, 0x82, 0xff, 0xfc,
0x7d, 0x8c, 0x72, 0x14, 0x35, 0x6b, 0xff, 0xff, 0x41, 0x81, 0xff, 0xe8, 0x80, 0x7b, 0x00, 0x00,
0x2c, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x08, 0x48, 0x00, 0x00, 0x59, 0x7c, 0x00, 0x60, 0xac,
0x7c, 0x00, 0x04, 0xac, 0x7c, 0x00, 0x67, 0xac, 0x4c, 0x00, 0x01, 0x2c, 0x48, 0x00, 0x01, 0x80,
0x7f, 0xc8, 0x02, 0xa6, 0x3c, 0x60, 0xa0, 0x00, 0x48, 0x00, 0x00, 0x15, 0x76, 0x03, 0x08, 0x00,
0x56, 0x1d, 0x86, 0x3e, 0x7f, 0xc8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x92, 0xf8, 0x68, 0x14,
0x90, 0x78, 0x68, 0x24, 0x92, 0xd8, 0x68, 0x20, 0x80, 0xb8, 0x68, 0x20, 0x70, 0xa5, 0x00, 0x01,
0x40, 0x82, 0xff, 0xf8, 0x82, 0x18, 0x68, 0x24, 0x90, 0xb8, 0x68, 0x14, 0x4e, 0x80, 0x00, 0x20,
0x7d, 0x48, 0x02, 0xa6, 0x7c, 0x69, 0x03, 0xa6, 0x39, 0xc0, 0x00, 0x00, 0x48, 0x00, 0x00, 0x79,
0x48, 0x00, 0x00, 0x75, 0x4b, 0xff, 0xff, 0xad, 0x41, 0x82, 0xff, 0xf4, 0x7f, 0xae, 0x61, 0xae,
0x39, 0xce, 0x00, 0x01, 0x42, 0x00, 0xff, 0xe8, 0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20,
0x7d, 0x48, 0x02, 0xa6, 0x7c, 0x69, 0x03, 0xa6, 0x39, 0xc0, 0x00, 0x00, 0x7c, 0x6c, 0x70, 0xae,
0x48, 0x00, 0x00, 0x1d, 0x41, 0x82, 0xff, 0xf8, 0x39, 0xce, 0x00, 0x01, 0x42, 0x00, 0xff, 0xf0,
0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x38, 0x60, 0x00, 0xaa, 0x7f, 0xc8, 0x02, 0xa6,
0x54, 0x63, 0xa0, 0x16, 0x64, 0x63, 0xb0, 0x00, 0x3a, 0xc0, 0x00, 0x19, 0x3a, 0xe0, 0x00, 0xd0,
0x3f, 0x00, 0xcc, 0x00, 0x4b, 0xff, 0xff, 0x69, 0x56, 0x03, 0x37, 0xff, 0x7f, 0xc8, 0x03, 0xa6,
0x4e, 0x80, 0x00, 0x20, 0x7f, 0xc8, 0x02, 0xa6, 0x3c, 0x60, 0xd0, 0x00, 0x4b, 0xff, 0xff, 0x51,
0x56, 0x03, 0x37, 0xff, 0x41, 0x82, 0xff, 0xf4, 0x7f, 0xc8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20,
0x4b, 0xff, 0xff, 0xb9, 0x38, 0x60, 0x00, 0x08, 0x63, 0xec, 0x27, 0x7c, 0x4b, 0xff, 0xff, 0x55,
0x80, 0xac, 0x00, 0x04, 0x81, 0x8c, 0x00, 0x00, 0x63, 0xfb, 0x27, 0x84, 0x62, 0xb1, 0xf8, 0x00,
0x7e, 0x0c, 0x28, 0x50, 0x48, 0x00, 0x00, 0xed, 0x41, 0x81, 0x00, 0x10, 0x82, 0x3b, 0x00, 0x00,
0x2c, 0x11, 0x00, 0x00, 0x41, 0x82, 0x00, 0x68, 0x7e, 0x23, 0x8b, 0x78, 0x4b, 0xff, 0xff, 0x55,
0x4b, 0xff, 0xff, 0xa5, 0x4b, 0xff, 0xff, 0xa1, 0x4b, 0xff, 0xfe, 0xd9, 0x41, 0x82, 0xff, 0xf4,
0x2c, 0x1d, 0x00, 0xcc, 0x41, 0x82, 0x00, 0x48, 0x2c, 0x1d, 0x00, 0xbb, 0x41, 0x82, 0xff, 0xdc,
0x2c, 0x1d, 0x00, 0xaa, 0x40, 0x82, 0xff, 0xdc, 0x7d, 0x8c, 0x72, 0x14, 0x35, 0x6b, 0xff, 0xff,
0x41, 0x80, 0x00, 0x2c, 0x4b, 0xff, 0xff, 0xb4, 0x7e, 0xb5, 0xfb, 0xa6, 0x7e, 0xb2, 0xfb, 0xa6,
0x63, 0xe4, 0x27, 0x98, 0x81, 0x24, 0x00, 0x18, 0x55, 0x29, 0x05, 0xa8, 0x91, 0x24, 0x00, 0x18,
0x48, 0x00, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x80, 0x4b, 0xff, 0xff, 0x25, 0x80, 0x92, 0x00, 0x00,
0x2c, 0x04, 0x00, 0x00, 0x40, 0x82, 0xfa, 0x50, 0xb3, 0x94, 0x40, 0x10, 0xc8, 0x41, 0x00, 0x98,
0xc8, 0x61, 0x00, 0xa0, 0x7f, 0x20, 0x00, 0xa6, 0x80, 0x01, 0x00, 0xac, 0x7c, 0x08, 0x03, 0xa6,
0x80, 0x01, 0x00, 0x0c, 0x7c, 0x0f, 0xf1, 0x20, 0x80, 0x01, 0x00, 0x10, 0x7c, 0x09, 0x03, 0xa6,
0x80, 0x01, 0x00, 0x14, 0x7c, 0x01, 0x03, 0xa6, 0xb8, 0x61, 0x00, 0x18, 0x80, 0x01, 0x00, 0x08,
0x38, 0x21, 0x00, 0xa8, 0x4c, 0x00, 0x01, 0x2c, 0x4e, 0x80, 0x00, 0x20, 0x7e, 0x23, 0x20, 0x50,
0x3c, 0xa0, 0x48, 0x00, 0x52, 0x25, 0x01, 0xba, 0x90, 0xa3, 0x00, 0x00, 0x7c, 0x00, 0x18, 0xac,
0x7c, 0x00, 0x04, 0xac, 0x7c, 0x00, 0x1f, 0xac, 0x4c, 0x00, 0x01, 0x2c, 0x4e, 0x80, 0x00, 0x20,
0x7d, 0x70, 0x8b, 0xd7, 0x7d, 0x4b, 0x89, 0xd6, 0x7d, 0x4a, 0x80, 0x50, 0x91, 0x5b, 0x00, 0x00,
0x4e, 0x80, 0x00, 0x20, 0x7f, 0xa8, 0x02, 0xa6, 0x3d, 0xe0, 0x80, 0x00, 0x61, 0xef, 0x28, 0xb8,
0x63, 0xe7, 0x18, 0x08, 0x3c, 0xc0, 0x80, 0x00, 0x7c, 0xd0, 0x33, 0x78, 0x39, 0x00, 0x00, 0x00,
0x3c, 0x60, 0x00, 0xd0, 0x60, 0x63, 0xc0, 0xde, 0x80, 0x8f, 0x00, 0x00, 0x7c, 0x03, 0x20, 0x00,
0x40, 0x82, 0x00, 0x18, 0x80, 0x8f, 0x00, 0x04, 0x7c, 0x03, 0x20, 0x00, 0x40, 0x82, 0x00, 0x0c,
0x39, 0xef, 0x00, 0x08, 0x48, 0x00, 0x00, 0x0c, 0x7f, 0xa8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20,
0x80, 0x6f, 0x00, 0x00, 0x80, 0x8f, 0x00, 0x04, 0x39, 0xef, 0x00, 0x08, 0x71, 0x09, 0x00, 0x01,
0x2f, 0x89, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00, 0x54, 0x6a, 0x1f, 0x7e, 0x54, 0x65, 0x3f, 0x7e,
0x74, 0x6b, 0x10, 0x00, 0x54, 0x63, 0x01, 0xfe, 0x40, 0x82, 0x00, 0x0c, 0x54, 0xcc, 0x00, 0x0c,
0x48, 0x00, 0x00, 0x08, 0x7e, 0x0c, 0x83, 0x78, 0x2e, 0x05, 0x00, 0x00, 0x2c, 0x0a, 0x00, 0x01,
0x41, 0xa0, 0x00, 0x2c, 0x41, 0xa2, 0x00, 0xe4, 0x2c, 0x0a, 0x00, 0x03, 0x41, 0xa0, 0x01, 0xac,
0x41, 0x82, 0x02, 0x50, 0x2c, 0x0a, 0x00, 0x05, 0x41, 0x80, 0x02, 0xd4, 0x41, 0xa2, 0x04, 0xe0,
0x2c, 0x0a, 0x00, 0x07, 0x41, 0xa0, 0x05, 0x0c, 0x48, 0x00, 0x05, 0xf0, 0x7d, 0x8c, 0x1a, 0x14,
0x2c, 0x05, 0x00, 0x03, 0x41, 0x82, 0x00, 0x48, 0x41, 0x81, 0x00, 0x60, 0x40, 0xbe, 0xff, 0x84,
0x2e, 0x05, 0x00, 0x01, 0x41, 0x91, 0x00, 0x2c, 0x54, 0x8a, 0x84, 0x3e, 0x41, 0x92, 0x00, 0x10,
0x7c, 0x89, 0x61, 0xae, 0x39, 0x29, 0x00, 0x01, 0x48, 0x00, 0x00, 0x0c, 0x7c, 0x89, 0x63, 0x2e,
0x39, 0x29, 0x00, 0x02, 0x35, 0x4a, 0xff, 0xff, 0x40, 0xa0, 0xff, 0xe4, 0x4b, 0xff, 0xff, 0x54,
0x55, 0x8c, 0x00, 0x3a, 0x90, 0x8c, 0x00, 0x00, 0x4b, 0xff, 0xff, 0x48, 0x7c, 0x89, 0x23, 0x78,
0x40, 0x9e, 0x04, 0xc8, 0x35, 0x29, 0xff, 0xff, 0x41, 0x80, 0x04, 0xc0, 0x7c, 0xa9, 0x78, 0xae,
0x7c, 0xa9, 0x61, 0xae, 0x4b, 0xff, 0xff, 0xf0, 0x39, 0xef, 0x00, 0x08, 0x40, 0xbe, 0xff, 0x24,
0x80, 0xaf, 0xff, 0xf8, 0x81, 0x6f, 0xff, 0xfc, 0x54, 0xb1, 0x04, 0x3e, 0x54, 0xaa, 0x85, 0x3e,
0x54, 0xa5, 0x27, 0x3e, 0x2e, 0x85, 0x00, 0x01, 0x41, 0x96, 0x00, 0x10, 0x41, 0xb5, 0x00, 0x14,
0x7c, 0x89, 0x61, 0xae, 0x48, 0x00, 0x00, 0x10, 0x7c, 0x89, 0x63, 0x2e, 0x48, 0x00, 0x00, 0x08,
0x7c, 0x89, 0x61, 0x2e, 0x7c, 0x84, 0x5a, 0x14, 0x7d, 0x29, 0x8a, 0x14, 0x35, 0x4a, 0xff, 0xff,
0x40, 0x80, 0xff, 0xd4, 0x4b, 0xff, 0xfe, 0xdc, 0x54, 0x69, 0x07, 0xff, 0x41, 0x82, 0x00, 0x10,
0x55, 0x08, 0xf8, 0x7e, 0x71, 0x09, 0x00, 0x01, 0x2f, 0x89, 0x00, 0x00, 0x2e, 0x85, 0x00, 0x04,
0x2d, 0x8a, 0x00, 0x05, 0x51, 0x08, 0x08, 0x3c, 0x40, 0x9e, 0x00, 0x78, 0x41, 0x8d, 0x04, 0xb8,
0x7d, 0x8c, 0x1a, 0x14, 0x41, 0x8c, 0x00, 0x0c, 0x41, 0x94, 0x00, 0x30, 0x48, 0x00, 0x00, 0x1c,
0x40, 0x94, 0x00, 0x10, 0x55, 0x8c, 0x00, 0x3a, 0x81, 0x6c, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1c,
0x55, 0x8c, 0x00, 0x3c, 0xa1, 0x6c, 0x00, 0x00, 0x7c, 0x89, 0x20, 0xf8, 0x55, 0x29, 0x84, 0x3e,
0x7d, 0x6b, 0x48, 0x38, 0x54, 0x84, 0x04, 0x3e, 0x7f, 0x0b, 0x20, 0x40, 0x70, 0xa9, 0x00, 0x03,
0x41, 0x82, 0x00, 0x18, 0x2c, 0x09, 0x00, 0x02, 0x41, 0x82, 0x00, 0x18, 0x41, 0x81, 0x00, 0x1c,
0x40, 0x9a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x18, 0x41, 0x9a, 0x00, 0x18, 0x48, 0x00, 0x00, 0x10,
0x41, 0x99, 0x00, 0x10, 0x48, 0x00, 0x00, 0x08, 0x41, 0x98, 0x00, 0x08, 0x61, 0x08, 0x00, 0x01,
0x40, 0x8e, 0xfe, 0x40, 0x41, 0x94, 0xfe, 0x3c, 0x81, 0x6f, 0xff, 0xf8, 0x40, 0x9e, 0x00, 0x20,
0x70, 0x6c, 0x00, 0x08, 0x41, 0x82, 0x00, 0x0c, 0x71, 0x0c, 0x00, 0x01, 0x41, 0x82, 0x00, 0x10,
0x39, 0x8b, 0x00, 0x10, 0x51, 0x8b, 0x03, 0x36, 0x48, 0x00, 0x00, 0x08, 0x55, 0x6b, 0x07, 0x16,
0x91, 0x6f, 0xff, 0xf8, 0x4b, 0xff, 0xfe, 0x0c, 0x40, 0xbe, 0xfe, 0x08, 0x54, 0x69, 0x16, 0xba,
0x54, 0x6e, 0x87, 0xfe, 0x2d, 0x8e, 0x00, 0x00, 0x2e, 0x05, 0x00, 0x04, 0x70, 0xae, 0x00, 0x03,
0x2e, 0x8e, 0x00, 0x02, 0x41, 0x94, 0x00, 0x14, 0x41, 0x96, 0x00, 0x50, 0x7c, 0x64, 0x07, 0x34,
0x7c, 0x84, 0x7a, 0x14, 0x48, 0x00, 0x00, 0x68, 0x54, 0x65, 0xa7, 0xff, 0x41, 0x82, 0x00, 0x0c,
0x7d, 0x27, 0x48, 0x2e, 0x7c, 0x84, 0x4a, 0x14, 0x41, 0x8e, 0x00, 0x08, 0x7c, 0x8c, 0x22, 0x14,
0x2e, 0x8e, 0x00, 0x01, 0x41, 0x96, 0x00, 0x08, 0x80, 0x84, 0x00, 0x00, 0x54, 0x63, 0x67, 0xff,
0x41, 0x82, 0x00, 0x3c, 0x40, 0x90, 0x00, 0x0c, 0x7c, 0x84, 0x32, 0x14, 0x48, 0x00, 0x00, 0x30,
0x7c, 0x84, 0x82, 0x14, 0x48, 0x00, 0x00, 0x28, 0x54, 0x65, 0xa7, 0xff, 0x41, 0x82, 0x00, 0x0c,
0x7d, 0x27, 0x48, 0x2e, 0x7c, 0x84, 0x4a, 0x14, 0x40, 0x90, 0x00, 0x0c, 0x7c, 0xcc, 0x21, 0x2e,
0x4b, 0xff, 0xfd, 0x80, 0x7e, 0x0c, 0x21, 0x2e, 0x4b, 0xff, 0xfd, 0x78, 0x40, 0x90, 0x00, 0x0c,
0x7c, 0x86, 0x23, 0x78, 0x4b, 0xff, 0xfd, 0x6c, 0x7c, 0x90, 0x23, 0x78, 0x4b, 0xff, 0xfd, 0x64,
0x54, 0x89, 0x1e, 0x78, 0x39, 0x29, 0x00, 0x40, 0x2c, 0x05, 0x00, 0x02, 0x41, 0x80, 0x00, 0x48,
0x54, 0x6b, 0x50, 0x03, 0x41, 0x82, 0x00, 0x14, 0x41, 0x81, 0x00, 0x08, 0x48, 0x00, 0x00, 0x10,
0x41, 0xbe, 0xfd, 0x40, 0x48, 0x00, 0x00, 0x08, 0x40, 0xbe, 0xfd, 0x38, 0x2c, 0x05, 0x00, 0x03,
0x41, 0x81, 0x00, 0x10, 0x41, 0xa2, 0x00, 0x10, 0x7d, 0xe7, 0x48, 0x2e, 0x4b, 0xff, 0xfd, 0x24,
0x7d, 0xe7, 0x49, 0x2e, 0x7c, 0x64, 0x07, 0x34, 0x54, 0x84, 0x1a, 0x78, 0x7d, 0xef, 0x22, 0x14,
0x4b, 0xff, 0xfd, 0x10, 0x40, 0xbe, 0xfd, 0x0c, 0x7c, 0xa7, 0x4a, 0x14, 0x40, 0x92, 0x00, 0x14,
0x54, 0x64, 0x04, 0x3e, 0x91, 0xe5, 0x00, 0x00, 0x90, 0x85, 0x00, 0x04, 0x4b, 0xff, 0xfc, 0xf4,
0x81, 0x25, 0x00, 0x04, 0x2c, 0x09, 0x00, 0x00, 0x41, 0xa2, 0xfc, 0xe8, 0x39, 0x29, 0xff, 0xff,
0x91, 0x25, 0x00, 0x04, 0x81, 0xe5, 0x00, 0x00, 0x4b, 0xff, 0xfc, 0xd8, 0x40, 0xbe, 0xfc, 0xd4,
0x54, 0x6b, 0x16, 0xba, 0x7f, 0x47, 0x5a, 0x14, 0x81, 0x3a, 0x00, 0x00, 0x54, 0x6e, 0x67, 0xbe,
0x41, 0x92, 0x00, 0x84, 0x2e, 0x05, 0x00, 0x05, 0x40, 0x90, 0x01, 0x74, 0x2e, 0x05, 0x00, 0x03,
0x40, 0x90, 0x00, 0x90, 0x2e, 0x05, 0x00, 0x01, 0x54, 0x65, 0x87, 0xff, 0x41, 0x82, 0x00, 0x08,
0x7c, 0x8c, 0x22, 0x14, 0x2f, 0x0e, 0x00, 0x01, 0x40, 0x92, 0x00, 0x24, 0x41, 0xb9, 0x00, 0x18,
0x41, 0x9a, 0x00, 0x0c, 0x88, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xf8, 0xa0, 0x84, 0x00, 0x00,
0x48, 0x00, 0x00, 0xf0, 0x80, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xe8, 0x54, 0x73, 0xe5, 0x3e,
0x41, 0xb9, 0x00, 0x20, 0x41, 0x9a, 0x00, 0x10, 0x99, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x01,
0x48, 0x00, 0x00, 0x18, 0xb1, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x02, 0x48, 0x00, 0x00, 0x0c,
0x91, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x04, 0x36, 0x73, 0xff, 0xff, 0x40, 0x80, 0xff, 0xd4,
0x4b, 0xff, 0xfc, 0x40, 0x54, 0x65, 0x87, 0xff, 0x41, 0x82, 0x00, 0x08, 0x7c, 0x84, 0x62, 0x14,
0x71, 0xc5, 0x00, 0x01, 0x41, 0x82, 0x00, 0x9c, 0x7c, 0x84, 0x4a, 0x14, 0x48, 0x00, 0x00, 0x94,
0x54, 0x6a, 0x87, 0xbe, 0x54, 0x8e, 0x16, 0xba, 0x7e, 0x67, 0x72, 0x14, 0x40, 0x92, 0x00, 0x08,
0x3a, 0x6f, 0xff, 0xfc, 0x80, 0x9a, 0x00, 0x00, 0x81, 0x33, 0x00, 0x00, 0x71, 0x4b, 0x00, 0x01,
0x41, 0x82, 0x00, 0x08, 0x7c, 0x9a, 0x23, 0x78, 0x71, 0x4b, 0x00, 0x02, 0x41, 0x82, 0x00, 0x10,
0x7d, 0x33, 0x4b, 0x78, 0x40, 0xb2, 0x00, 0x08, 0x7e, 0x6c, 0x9a, 0x14, 0x54, 0x65, 0x67, 0x3f,
0x2c, 0x05, 0x00, 0x09, 0x40, 0x80, 0x00, 0x54, 0x48, 0x00, 0x00, 0x79, 0x7c, 0x89, 0x22, 0x14,
0x48, 0x00, 0x00, 0x40, 0x7c, 0x89, 0x21, 0xd6, 0x48, 0x00, 0x00, 0x38, 0x7d, 0x24, 0x23, 0x78,
0x48, 0x00, 0x00, 0x30, 0x7d, 0x24, 0x20, 0x38, 0x48, 0x00, 0x00, 0x28, 0x7d, 0x24, 0x22, 0x78,
0x48, 0x00, 0x00, 0x20, 0x7d, 0x24, 0x20, 0x30, 0x48, 0x00, 0x00, 0x18, 0x7d, 0x24, 0x24, 0x30,
0x48, 0x00, 0x00, 0x10, 0x5d, 0x24, 0x20, 0x3e, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x24, 0x26, 0x30,
0x90, 0x9a, 0x00, 0x00, 0x4b, 0xff, 0xfb, 0x8c, 0x2c, 0x05, 0x00, 0x0a, 0x41, 0x81, 0xfb, 0x84,
0xc0, 0x5a, 0x00, 0x00, 0xc0, 0x73, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0c, 0xec, 0x43, 0x10, 0x2a,
0x48, 0x00, 0x00, 0x08, 0xec, 0x43, 0x00, 0xb2, 0xd0, 0x5a, 0x00, 0x00, 0x4b, 0xff, 0xfb, 0x64,
0x7d, 0x48, 0x02, 0xa6, 0x54, 0xa5, 0x1e, 0x78, 0x7d, 0x4a, 0x2a, 0x14, 0x80, 0x9a, 0x00, 0x00,
0x81, 0x33, 0x00, 0x00, 0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x40, 0xbe, 0xfb, 0x44,
0x54, 0x69, 0xc0, 0x3e, 0x7d, 0x8e, 0x63, 0x78, 0x48, 0x00, 0x00, 0x35, 0x41, 0x92, 0x00, 0x0c,
0x7e, 0x31, 0x22, 0x14, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x29, 0x22, 0x14, 0x54, 0x64, 0xc4, 0x3f,
0x38, 0xa0, 0x00, 0x00, 0x41, 0x82, 0xfb, 0x1c, 0x7d, 0x45, 0x88, 0xae, 0x7d, 0x45, 0x49, 0xae,
0x38, 0xa5, 0x00, 0x01, 0x7c, 0x05, 0x20, 0x00, 0x4b, 0xff, 0xff, 0xec, 0x2e, 0x8a, 0x00, 0x04,
0x55, 0x31, 0x36, 0xba, 0x2c, 0x11, 0x00, 0x3c, 0x7e, 0x27, 0x88, 0x2e, 0x40, 0x82, 0x00, 0x08,
0x7d, 0xd1, 0x73, 0x78, 0x41, 0x96, 0x00, 0x08, 0xa2, 0x31, 0x00, 0x00, 0x55, 0x29, 0x56, 0xba,
0x2c, 0x09, 0x00, 0x3c, 0x7d, 0x27, 0x48, 0x2e, 0x40, 0x82, 0x00, 0x08, 0x7d, 0xc9, 0x73, 0x78,
0x41, 0x96, 0x00, 0x08, 0xa1, 0x29, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, 0x2c, 0x05, 0x00, 0x04,
0x40, 0x80, 0x00, 0x28, 0x7c, 0x89, 0x23, 0x78, 0x7d, 0xc3, 0x62, 0x14, 0x55, 0xce, 0x00, 0x3c,
0x4b, 0xff, 0xff, 0xad, 0x7c, 0x84, 0x20, 0xf8, 0x54, 0x84, 0x04, 0x3e, 0x7d, 0x2b, 0x20, 0x38,
0x7e, 0x24, 0x20, 0x38, 0x4b, 0xff, 0xfb, 0xc4, 0x54, 0x6b, 0xe4, 0x3e, 0x4b, 0xff, 0xfb, 0xbc,
0x7c, 0x9a, 0x23, 0x78, 0x54, 0x84, 0x18, 0x38, 0x40, 0x92, 0x00, 0x20, 0x40, 0x9e, 0x00, 0x0c,
0x7d, 0xe8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x7d, 0xe4, 0x7a, 0x14, 0x39, 0xef, 0x00, 0x07,
0x55, 0xef, 0x00, 0x38, 0x4b, 0xff, 0xfa, 0x6c, 0x2e, 0x05, 0x00, 0x03, 0x41, 0x91, 0x00, 0x5c,
0x3c, 0xa0, 0x48, 0x00, 0x7d, 0x83, 0x62, 0x14, 0x55, 0x8c, 0x00, 0x3a, 0x40, 0x92, 0x00, 0x20,
0x40, 0xbe, 0xfa, 0x50, 0x57, 0x44, 0x00, 0x3a, 0x7c, 0x8c, 0x20, 0x50, 0x50, 0x85, 0x01, 0xba,
0x50, 0x65, 0x07, 0xfe, 0x90, 0xac, 0x00, 0x00, 0x4b, 0xff, 0xfa, 0x38, 0x40, 0xbe, 0xff, 0xbc,
0x7d, 0x2c, 0x78, 0x50, 0x51, 0x25, 0x01, 0xba, 0x90, 0xac, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x04,
0x7d, 0x6f, 0x22, 0x14, 0x39, 0x6b, 0xff, 0xfc, 0x7d, 0x2b, 0x60, 0x50, 0x51, 0x25, 0x01, 0xba,
0x90, 0xab, 0x00, 0x00, 0x4b, 0xff, 0xff, 0x94, 0x2e, 0x05, 0x00, 0x06, 0x41, 0x92, 0x00, 0x28,
0x4b, 0xff, 0xfb, 0x28, 0x55, 0x8c, 0x84, 0x3e, 0x57, 0x44, 0x84, 0x3e, 0x57, 0x5a, 0x04, 0x3e,
0x7c, 0x0c, 0x20, 0x00, 0x41, 0x80, 0xfb, 0xa8, 0x7c, 0x0c, 0xd0, 0x00, 0x40, 0x80, 0xfb, 0xa0,
0x4b, 0xff, 0xf9, 0xe0, 0x57, 0x45, 0xff, 0xfe, 0x68, 0xa5, 0x00, 0x01, 0x71, 0x03, 0x00, 0x01,
0x7c, 0x05, 0x18, 0x00, 0x41, 0x82, 0x00, 0x1c, 0x51, 0x1a, 0x0f, 0xbc, 0x6b, 0x5a, 0x00, 0x02,
0x57, 0x45, 0xff, 0xff, 0x41, 0x82, 0x00, 0x08, 0x6b, 0x5a, 0x00, 0x01, 0x93, 0x4f, 0xff, 0xfc,
0x53, 0x48, 0x07, 0xfe, 0x4b, 0xff, 0xf9, 0xac, 0x2c, 0x0b, 0x00, 0x00, 0x41, 0x82, 0x01, 0x38,
0x2c, 0x05, 0x00, 0x01, 0x41, 0x82, 0x00, 0x18, 0x2c, 0x05, 0x00, 0x02, 0x41, 0x82, 0x00, 0x14,
0x2c, 0x05, 0x00, 0x03, 0x41, 0x82, 0x00, 0x70, 0x4b, 0xff, 0xf9, 0x80, 0x54, 0xcc, 0x00, 0x0c,
0x54, 0x97, 0x46, 0x3e, 0x54, 0x98, 0xc4, 0x3e, 0x54, 0x84, 0x06, 0x3e, 0x40, 0x9e, 0x00, 0xfc,
0x56, 0xf9, 0x06, 0x31, 0x7d, 0x9a, 0x63, 0x78, 0x7f, 0x43, 0xd2, 0x14, 0x57, 0x5a, 0x00, 0x3a,
0x41, 0x82, 0x00, 0x18, 0x7e, 0xf7, 0x07, 0x74, 0x7e, 0xf7, 0x00, 0xd0, 0x1f, 0x37, 0x00, 0x02,
0x3b, 0x39, 0x00, 0x04, 0x7f, 0x59, 0xd0, 0x50, 0x2c, 0x17, 0x00, 0x00, 0x41, 0x82, 0x00, 0x1c,
0x3b, 0x20, 0x00, 0x00, 0x7e, 0xe9, 0x03, 0xa6, 0xa3, 0x7a, 0x00, 0x04, 0x7f, 0x79, 0xca, 0x78,
0x3b, 0x5a, 0x00, 0x02, 0x42, 0x00, 0xff, 0xf4, 0x7c, 0x18, 0xc8, 0x00, 0x40, 0x82, 0x00, 0xac,
0x4b, 0xff, 0xfe, 0x90, 0x51, 0x08, 0x08, 0x3c, 0x40, 0x9e, 0x00, 0x9c, 0x54, 0x77, 0xb0, 0x03,
0x41, 0x81, 0x00, 0x88, 0x41, 0x80, 0x00, 0x8c, 0x54, 0x7e, 0x06, 0x3e, 0x1f, 0xde, 0x00, 0x02,
0x54, 0x97, 0x00, 0x1e, 0x6e, 0xf8, 0x80, 0x00, 0x2c, 0x18, 0x00, 0x00, 0x40, 0x82, 0x00, 0x08,
0x62, 0xf7, 0x30, 0x00, 0x54, 0x98, 0x80, 0x1e, 0x1f, 0x3e, 0x00, 0x04, 0x7f, 0x19, 0xc0, 0x50,
0x3b, 0x20, 0x00, 0x00, 0x1f, 0x59, 0x00, 0x04, 0x7f, 0x6f, 0xd0, 0x2e, 0x7f, 0x57, 0xd0, 0x2e,
0x3b, 0x39, 0x00, 0x01, 0x7c, 0x17, 0xc0, 0x40, 0x41, 0x81, 0x00, 0x34, 0x7c, 0x19, 0xf0, 0x00,
0x41, 0x81, 0x00, 0x14, 0x7c, 0x1a, 0xd8, 0x00, 0x41, 0x82, 0xff, 0xdc, 0x3a, 0xf7, 0x00, 0x04,
0x4b, 0xff, 0xff, 0xd0, 0x80, 0x6f, 0xff, 0xf8, 0x60, 0x63, 0x03, 0x00, 0x90, 0x6f, 0xff, 0xf8,
0x92, 0xef, 0xff, 0xfc, 0x7e, 0xf0, 0xbb, 0x78, 0x48, 0x00, 0x00, 0x1c, 0x80, 0x6f, 0xff, 0xf8,
0x60, 0x63, 0x01, 0x00, 0x90, 0x6f, 0xff, 0xf8, 0x61, 0x08, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08,
0x7c, 0x90, 0x23, 0x78, 0x54, 0x64, 0x06, 0x3e, 0x1c, 0x84, 0x00, 0x08, 0x7d, 0xe4, 0x7a, 0x14,
0x4b, 0xff, 0xf8, 0x70, 0x40, 0x92, 0x00, 0x0c, 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14,
0x54, 0x69, 0x06, 0xff, 0x54, 0x65, 0x67, 0xfe, 0x7d, 0x08, 0x4c, 0x30, 0x55, 0x17, 0xff, 0xff,
0x40, 0x82, 0x00, 0x08, 0x7d, 0x08, 0x2a, 0x78, 0x54, 0x85, 0x00, 0x1f, 0x41, 0x82, 0x00, 0x08,
0x7c, 0xa6, 0x2b, 0x78, 0x54, 0x85, 0x80, 0x1f, 0x41, 0x82, 0x00, 0x08, 0x7c, 0xb0, 0x2b, 0x78,
0x4b, 0xff, 0xf8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//unsigned char kenobigc[2736] =
//{
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x60, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x21, 0xff, 0x58, 0x90, 0x01, 0x00, 0x08,
// 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0xac, 0x7c, 0x00, 0x00, 0x26, 0x90, 0x01, 0x00, 0x0c,
// 0x7c, 0x09, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x10, 0x7c, 0x01, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x14,
// 0xbc, 0x61, 0x00, 0x18, 0x7f, 0x20, 0x00, 0xa6, 0x63, 0x3a, 0x20, 0x00, 0x73, 0x5a, 0xf9, 0xff,
// 0x7f, 0x40, 0x01, 0x24, 0xd8, 0x41, 0x00, 0x98, 0xd8, 0x61, 0x00, 0xa0, 0x3f, 0xe0, 0x80, 0x00,
// 0x3e, 0x80, 0xcc, 0x00, 0xa3, 0x94, 0x40, 0x10, 0x63, 0x95, 0x00, 0xff, 0xb2, 0xb4, 0x40, 0x10,
// 0x7f, 0xa8, 0x02, 0xa6, 0x3d, 0xe0, 0x80, 0x00, 0x61, 0xef, 0x22, 0xa8, 0x63, 0xe7, 0x18, 0x08,
// 0x3c, 0xc0, 0x80, 0x00, 0x7c, 0xd0, 0x33, 0x78, 0x39, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x00, 0xd0,
// 0x60, 0x63, 0xc0, 0xde, 0x80, 0x8f, 0x00, 0x00, 0x7c, 0x03, 0x20, 0x00, 0x40, 0x82, 0x00, 0x18,
// 0x80, 0x8f, 0x00, 0x04, 0x7c, 0x03, 0x20, 0x00, 0x40, 0x82, 0x00, 0x0c, 0x39, 0xef, 0x00, 0x08,
// 0x48, 0x00, 0x00, 0x4c, 0x7f, 0xa8, 0x03, 0xa6, 0xb3, 0x94, 0x40, 0x10, 0xc8, 0x41, 0x00, 0x98,
// 0xc8, 0x61, 0x00, 0xa0, 0x7f, 0x20, 0x00, 0xa6, 0x80, 0x01, 0x00, 0xac, 0x7c, 0x08, 0x03, 0xa6,
// 0x80, 0x01, 0x00, 0x0c, 0x7c, 0x0f, 0xf1, 0x20, 0x80, 0x01, 0x00, 0x10, 0x7c, 0x09, 0x03, 0xa6,
// 0x80, 0x01, 0x00, 0x14, 0x7c, 0x01, 0x03, 0xa6, 0xb8, 0x61, 0x00, 0x18, 0x80, 0x01, 0x00, 0x08,
// 0x38, 0x21, 0x00, 0xa8, 0x4c, 0x00, 0x01, 0x2c, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x6f, 0x00, 0x00,
// 0x80, 0x8f, 0x00, 0x04, 0x39, 0xef, 0x00, 0x08, 0x71, 0x09, 0x00, 0x01, 0x2f, 0x89, 0x00, 0x00,
// 0x39, 0x20, 0x00, 0x00, 0x54, 0x6a, 0x1f, 0x7e, 0x54, 0x65, 0x3f, 0x7e, 0x74, 0x6b, 0x10, 0x00,
// 0x54, 0x63, 0x01, 0xfe, 0x40, 0x82, 0x00, 0x0c, 0x54, 0xcc, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x08,
// 0x7e, 0x0c, 0x83, 0x78, 0x2e, 0x05, 0x00, 0x00, 0x2c, 0x0a, 0x00, 0x01, 0x41, 0xa0, 0x00, 0x2c,
// 0x41, 0xa2, 0x00, 0xe4, 0x2c, 0x0a, 0x00, 0x03, 0x41, 0xa0, 0x01, 0xac, 0x41, 0x82, 0x02, 0x50,
// 0x2c, 0x0a, 0x00, 0x05, 0x41, 0x80, 0x02, 0xd4, 0x41, 0xa2, 0x04, 0xe0, 0x2c, 0x0a, 0x00, 0x07,
// 0x41, 0xa0, 0x05, 0x0c, 0x48, 0x00, 0x05, 0xf0, 0x7d, 0x8c, 0x1a, 0x14, 0x2c, 0x05, 0x00, 0x03,
// 0x41, 0x82, 0x00, 0x48, 0x41, 0x81, 0x00, 0x60, 0x40, 0xbe, 0xff, 0x84, 0x2e, 0x05, 0x00, 0x01,
// 0x41, 0x91, 0x00, 0x2c, 0x54, 0x8a, 0x84, 0x3e, 0x41, 0x92, 0x00, 0x10, 0x7c, 0x89, 0x61, 0xae,
// 0x39, 0x29, 0x00, 0x01, 0x48, 0x00, 0x00, 0x0c, 0x7c, 0x89, 0x63, 0x2e, 0x39, 0x29, 0x00, 0x02,
// 0x35, 0x4a, 0xff, 0xff, 0x40, 0xa0, 0xff, 0xe4, 0x4b, 0xff, 0xff, 0x54, 0x55, 0x8c, 0x00, 0x3a,
// 0x90, 0x8c, 0x00, 0x00, 0x4b, 0xff, 0xff, 0x48, 0x7c, 0x89, 0x23, 0x78, 0x40, 0x9e, 0x04, 0xc8,
// 0x35, 0x29, 0xff, 0xff, 0x41, 0x80, 0x04, 0xc0, 0x7c, 0xa9, 0x78, 0xae, 0x7c, 0xa9, 0x61, 0xae,
// 0x4b, 0xff, 0xff, 0xf0, 0x39, 0xef, 0x00, 0x08, 0x40, 0xbe, 0xff, 0x24, 0x80, 0xaf, 0xff, 0xf8,
// 0x81, 0x6f, 0xff, 0xfc, 0x54, 0xb1, 0x04, 0x3e, 0x54, 0xaa, 0x85, 0x3e, 0x54, 0xa5, 0x27, 0x3e,
// 0x2e, 0x85, 0x00, 0x01, 0x41, 0x96, 0x00, 0x10, 0x41, 0xb5, 0x00, 0x14, 0x7c, 0x89, 0x61, 0xae,
// 0x48, 0x00, 0x00, 0x10, 0x7c, 0x89, 0x63, 0x2e, 0x48, 0x00, 0x00, 0x08, 0x7c, 0x89, 0x61, 0x2e,
// 0x7c, 0x84, 0x5a, 0x14, 0x7d, 0x29, 0x8a, 0x14, 0x35, 0x4a, 0xff, 0xff, 0x40, 0x80, 0xff, 0xd4,
// 0x4b, 0xff, 0xfe, 0xdc, 0x54, 0x69, 0x07, 0xff, 0x41, 0x82, 0x00, 0x10, 0x55, 0x08, 0xf8, 0x7e,
// 0x71, 0x09, 0x00, 0x01, 0x2f, 0x89, 0x00, 0x00, 0x2e, 0x85, 0x00, 0x04, 0x2d, 0x8a, 0x00, 0x05,
// 0x51, 0x08, 0x08, 0x3c, 0x40, 0x9e, 0x00, 0x78, 0x41, 0x8d, 0x04, 0xb8, 0x7d, 0x8c, 0x1a, 0x14,
// 0x41, 0x8c, 0x00, 0x0c, 0x41, 0x94, 0x00, 0x30, 0x48, 0x00, 0x00, 0x1c, 0x40, 0x94, 0x00, 0x10,
// 0x55, 0x8c, 0x00, 0x3a, 0x81, 0x6c, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1c, 0x55, 0x8c, 0x00, 0x3c,
// 0xa1, 0x6c, 0x00, 0x00, 0x7c, 0x89, 0x20, 0xf8, 0x55, 0x29, 0x84, 0x3e, 0x7d, 0x6b, 0x48, 0x38,
// 0x54, 0x84, 0x04, 0x3e, 0x7f, 0x0b, 0x20, 0x40, 0x70, 0xa9, 0x00, 0x03, 0x41, 0x82, 0x00, 0x18,
// 0x2c, 0x09, 0x00, 0x02, 0x41, 0x82, 0x00, 0x18, 0x41, 0x81, 0x00, 0x1c, 0x40, 0x9a, 0x00, 0x20,
// 0x48, 0x00, 0x00, 0x18, 0x41, 0x9a, 0x00, 0x18, 0x48, 0x00, 0x00, 0x10, 0x41, 0x99, 0x00, 0x10,
// 0x48, 0x00, 0x00, 0x08, 0x41, 0x98, 0x00, 0x08, 0x61, 0x08, 0x00, 0x01, 0x40, 0x8e, 0xfe, 0x40,
// 0x41, 0x94, 0xfe, 0x3c, 0x81, 0x6f, 0xff, 0xf8, 0x40, 0x9e, 0x00, 0x20, 0x70, 0x6c, 0x00, 0x08,
// 0x41, 0x82, 0x00, 0x0c, 0x71, 0x0c, 0x00, 0x01, 0x41, 0x82, 0x00, 0x10, 0x39, 0x8b, 0x00, 0x10,
// 0x51, 0x8b, 0x03, 0x36, 0x48, 0x00, 0x00, 0x08, 0x55, 0x6b, 0x07, 0x16, 0x91, 0x6f, 0xff, 0xf8,
// 0x4b, 0xff, 0xfe, 0x0c, 0x40, 0xbe, 0xfe, 0x08, 0x54, 0x69, 0x16, 0xba, 0x54, 0x6e, 0x87, 0xfe,
// 0x2d, 0x8e, 0x00, 0x00, 0x2e, 0x05, 0x00, 0x04, 0x70, 0xae, 0x00, 0x03, 0x2e, 0x8e, 0x00, 0x02,
// 0x41, 0x94, 0x00, 0x14, 0x41, 0x96, 0x00, 0x50, 0x7c, 0x64, 0x07, 0x34, 0x7c, 0x84, 0x7a, 0x14,
// 0x48, 0x00, 0x00, 0x68, 0x54, 0x65, 0xa7, 0xff, 0x41, 0x82, 0x00, 0x0c, 0x7d, 0x27, 0x48, 0x2e,
// 0x7c, 0x84, 0x4a, 0x14, 0x41, 0x8e, 0x00, 0x08, 0x7c, 0x8c, 0x22, 0x14, 0x2e, 0x8e, 0x00, 0x01,
// 0x41, 0x96, 0x00, 0x08, 0x80, 0x84, 0x00, 0x00, 0x54, 0x63, 0x67, 0xff, 0x41, 0x82, 0x00, 0x3c,
// 0x40, 0x90, 0x00, 0x0c, 0x7c, 0x84, 0x32, 0x14, 0x48, 0x00, 0x00, 0x30, 0x7c, 0x84, 0x82, 0x14,
// 0x48, 0x00, 0x00, 0x28, 0x54, 0x65, 0xa7, 0xff, 0x41, 0x82, 0x00, 0x0c, 0x7d, 0x27, 0x48, 0x2e,
// 0x7c, 0x84, 0x4a, 0x14, 0x40, 0x90, 0x00, 0x0c, 0x7c, 0xcc, 0x21, 0x2e, 0x4b, 0xff, 0xfd, 0x80,
// 0x7e, 0x0c, 0x21, 0x2e, 0x4b, 0xff, 0xfd, 0x78, 0x40, 0x90, 0x00, 0x0c, 0x7c, 0x86, 0x23, 0x78,
// 0x4b, 0xff, 0xfd, 0x6c, 0x7c, 0x90, 0x23, 0x78, 0x4b, 0xff, 0xfd, 0x64, 0x54, 0x89, 0x1e, 0x78,
// 0x39, 0x29, 0x00, 0x40, 0x2c, 0x05, 0x00, 0x02, 0x41, 0x80, 0x00, 0x48, 0x54, 0x6b, 0x50, 0x03,
// 0x41, 0x82, 0x00, 0x14, 0x41, 0x81, 0x00, 0x08, 0x48, 0x00, 0x00, 0x10, 0x41, 0xbe, 0xfd, 0x40,
// 0x48, 0x00, 0x00, 0x08, 0x40, 0xbe, 0xfd, 0x38, 0x2c, 0x05, 0x00, 0x03, 0x41, 0x81, 0x00, 0x10,
// 0x41, 0xa2, 0x00, 0x10, 0x7d, 0xe7, 0x48, 0x2e, 0x4b, 0xff, 0xfd, 0x24, 0x7d, 0xe7, 0x49, 0x2e,
// 0x7c, 0x64, 0x07, 0x34, 0x54, 0x84, 0x1a, 0x78, 0x7d, 0xef, 0x22, 0x14, 0x4b, 0xff, 0xfd, 0x10,
// 0x40, 0xbe, 0xfd, 0x0c, 0x7c, 0xa7, 0x4a, 0x14, 0x40, 0x92, 0x00, 0x14, 0x54, 0x64, 0x04, 0x3e,
// 0x91, 0xe5, 0x00, 0x00, 0x90, 0x85, 0x00, 0x04, 0x4b, 0xff, 0xfc, 0xf4, 0x81, 0x25, 0x00, 0x04,
// 0x2c, 0x09, 0x00, 0x00, 0x41, 0xa2, 0xfc, 0xe8, 0x39, 0x29, 0xff, 0xff, 0x91, 0x25, 0x00, 0x04,
// 0x81, 0xe5, 0x00, 0x00, 0x4b, 0xff, 0xfc, 0xd8, 0x40, 0xbe, 0xfc, 0xd4, 0x54, 0x6b, 0x16, 0xba,
// 0x7f, 0x47, 0x5a, 0x14, 0x81, 0x3a, 0x00, 0x00, 0x54, 0x6e, 0x67, 0xbe, 0x41, 0x92, 0x00, 0x84,
// 0x2e, 0x05, 0x00, 0x05, 0x40, 0x90, 0x01, 0x74, 0x2e, 0x05, 0x00, 0x03, 0x40, 0x90, 0x00, 0x90,
// 0x2e, 0x05, 0x00, 0x01, 0x54, 0x65, 0x87, 0xff, 0x41, 0x82, 0x00, 0x08, 0x7c, 0x8c, 0x22, 0x14,
// 0x2f, 0x0e, 0x00, 0x01, 0x40, 0x92, 0x00, 0x24, 0x41, 0xb9, 0x00, 0x18, 0x41, 0x9a, 0x00, 0x0c,
// 0x88, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xf8, 0xa0, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xf0,
// 0x80, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xe8, 0x54, 0x73, 0xe5, 0x3e, 0x41, 0xb9, 0x00, 0x20,
// 0x41, 0x9a, 0x00, 0x10, 0x99, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x01, 0x48, 0x00, 0x00, 0x18,
// 0xb1, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x02, 0x48, 0x00, 0x00, 0x0c, 0x91, 0x24, 0x00, 0x00,
// 0x38, 0x84, 0x00, 0x04, 0x36, 0x73, 0xff, 0xff, 0x40, 0x80, 0xff, 0xd4, 0x4b, 0xff, 0xfc, 0x40,
// 0x54, 0x65, 0x87, 0xff, 0x41, 0x82, 0x00, 0x08, 0x7c, 0x84, 0x62, 0x14, 0x71, 0xc5, 0x00, 0x01,
// 0x41, 0x82, 0x00, 0x9c, 0x7c, 0x84, 0x4a, 0x14, 0x48, 0x00, 0x00, 0x94, 0x54, 0x6a, 0x87, 0xbe,
// 0x54, 0x8e, 0x16, 0xba, 0x7e, 0x67, 0x72, 0x14, 0x40, 0x92, 0x00, 0x08, 0x3a, 0x6f, 0xff, 0xfc,
// 0x80, 0x9a, 0x00, 0x00, 0x81, 0x33, 0x00, 0x00, 0x71, 0x4b, 0x00, 0x01, 0x41, 0x82, 0x00, 0x08,
// 0x7c, 0x9a, 0x23, 0x78, 0x71, 0x4b, 0x00, 0x02, 0x41, 0x82, 0x00, 0x10, 0x7d, 0x33, 0x4b, 0x78,
// 0x40, 0xb2, 0x00, 0x08, 0x7e, 0x6c, 0x9a, 0x14, 0x54, 0x65, 0x67, 0x3f, 0x2c, 0x05, 0x00, 0x09,
// 0x40, 0x80, 0x00, 0x54, 0x48, 0x00, 0x00, 0x79, 0x7c, 0x89, 0x22, 0x14, 0x48, 0x00, 0x00, 0x40,
// 0x7c, 0x89, 0x21, 0xd6, 0x48, 0x00, 0x00, 0x38, 0x7d, 0x24, 0x23, 0x78, 0x48, 0x00, 0x00, 0x30,
// 0x7d, 0x24, 0x20, 0x38, 0x48, 0x00, 0x00, 0x28, 0x7d, 0x24, 0x22, 0x78, 0x48, 0x00, 0x00, 0x20,
// 0x7d, 0x24, 0x20, 0x30, 0x48, 0x00, 0x00, 0x18, 0x7d, 0x24, 0x24, 0x30, 0x48, 0x00, 0x00, 0x10,
// 0x5d, 0x24, 0x20, 0x3e, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x24, 0x26, 0x30, 0x90, 0x9a, 0x00, 0x00,
// 0x4b, 0xff, 0xfb, 0x8c, 0x2c, 0x05, 0x00, 0x0a, 0x41, 0x81, 0xfb, 0x84, 0xc0, 0x5a, 0x00, 0x00,
// 0xc0, 0x73, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0c, 0xec, 0x43, 0x10, 0x2a, 0x48, 0x00, 0x00, 0x08,
// 0xec, 0x43, 0x00, 0xb2, 0xd0, 0x5a, 0x00, 0x00, 0x4b, 0xff, 0xfb, 0x64, 0x7d, 0x48, 0x02, 0xa6,
// 0x54, 0xa5, 0x1e, 0x78, 0x7d, 0x4a, 0x2a, 0x14, 0x80, 0x9a, 0x00, 0x00, 0x81, 0x33, 0x00, 0x00,
// 0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x40, 0xbe, 0xfb, 0x44, 0x54, 0x69, 0xc0, 0x3e,
// 0x7d, 0x8e, 0x63, 0x78, 0x48, 0x00, 0x00, 0x35, 0x41, 0x92, 0x00, 0x0c, 0x7e, 0x31, 0x22, 0x14,
// 0x48, 0x00, 0x00, 0x08, 0x7d, 0x29, 0x22, 0x14, 0x54, 0x64, 0xc4, 0x3f, 0x38, 0xa0, 0x00, 0x00,
// 0x41, 0x82, 0xfb, 0x1c, 0x7d, 0x45, 0x88, 0xae, 0x7d, 0x45, 0x49, 0xae, 0x38, 0xa5, 0x00, 0x01,
// 0x7c, 0x05, 0x20, 0x00, 0x4b, 0xff, 0xff, 0xec, 0x2e, 0x8a, 0x00, 0x04, 0x55, 0x31, 0x36, 0xba,
// 0x2c, 0x11, 0x00, 0x3c, 0x7e, 0x27, 0x88, 0x2e, 0x40, 0x82, 0x00, 0x08, 0x7d, 0xd1, 0x73, 0x78,
// 0x41, 0x96, 0x00, 0x08, 0xa2, 0x31, 0x00, 0x00, 0x55, 0x29, 0x56, 0xba, 0x2c, 0x09, 0x00, 0x3c,
// 0x7d, 0x27, 0x48, 0x2e, 0x40, 0x82, 0x00, 0x08, 0x7d, 0xc9, 0x73, 0x78, 0x41, 0x96, 0x00, 0x08,
// 0xa1, 0x29, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, 0x2c, 0x05, 0x00, 0x04, 0x40, 0x80, 0x00, 0x28,
// 0x7c, 0x89, 0x23, 0x78, 0x7d, 0xc3, 0x62, 0x14, 0x55, 0xce, 0x00, 0x3c, 0x4b, 0xff, 0xff, 0xad,
// 0x7c, 0x84, 0x20, 0xf8, 0x54, 0x84, 0x04, 0x3e, 0x7d, 0x2b, 0x20, 0x38, 0x7e, 0x24, 0x20, 0x38,
// 0x4b, 0xff, 0xfb, 0xc4, 0x54, 0x6b, 0xe4, 0x3e, 0x4b, 0xff, 0xfb, 0xbc, 0x7c, 0x9a, 0x23, 0x78,
// 0x54, 0x84, 0x18, 0x38, 0x40, 0x92, 0x00, 0x20, 0x40, 0x9e, 0x00, 0x0c, 0x7d, 0xe8, 0x03, 0xa6,
// 0x4e, 0x80, 0x00, 0x21, 0x7d, 0xe4, 0x7a, 0x14, 0x39, 0xef, 0x00, 0x07, 0x55, 0xef, 0x00, 0x38,
// 0x4b, 0xff, 0xfa, 0x6c, 0x2e, 0x05, 0x00, 0x03, 0x41, 0x91, 0x00, 0x5c, 0x3c, 0xa0, 0x48, 0x00,
// 0x7d, 0x83, 0x62, 0x14, 0x55, 0x8c, 0x00, 0x3a, 0x40, 0x92, 0x00, 0x20, 0x40, 0xbe, 0xfa, 0x50,
// 0x57, 0x44, 0x00, 0x3a, 0x7c, 0x8c, 0x20, 0x50, 0x50, 0x85, 0x01, 0xba, 0x50, 0x65, 0x07, 0xfe,
// 0x90, 0xac, 0x00, 0x00, 0x4b, 0xff, 0xfa, 0x38, 0x40, 0xbe, 0xff, 0xbc, 0x7d, 0x2c, 0x78, 0x50,
// 0x51, 0x25, 0x01, 0xba, 0x90, 0xac, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x04, 0x7d, 0x6f, 0x22, 0x14,
// 0x39, 0x6b, 0xff, 0xfc, 0x7d, 0x2b, 0x60, 0x50, 0x51, 0x25, 0x01, 0xba, 0x90, 0xab, 0x00, 0x00,
// 0x4b, 0xff, 0xff, 0x94, 0x2e, 0x05, 0x00, 0x06, 0x41, 0x92, 0x00, 0x28, 0x4b, 0xff, 0xfb, 0x28,
// 0x55, 0x8c, 0x84, 0x3e, 0x57, 0x44, 0x84, 0x3e, 0x57, 0x5a, 0x04, 0x3e, 0x7c, 0x0c, 0x20, 0x00,
// 0x41, 0x80, 0xfb, 0xa8, 0x7c, 0x0c, 0xd0, 0x00, 0x40, 0x80, 0xfb, 0xa0, 0x4b, 0xff, 0xf9, 0xe0,
// 0x57, 0x45, 0xff, 0xfe, 0x68, 0xa5, 0x00, 0x01, 0x71, 0x03, 0x00, 0x01, 0x7c, 0x05, 0x18, 0x00,
// 0x41, 0x82, 0x00, 0x1c, 0x51, 0x1a, 0x0f, 0xbc, 0x6b, 0x5a, 0x00, 0x02, 0x57, 0x45, 0xff, 0xff,
// 0x41, 0x82, 0x00, 0x08, 0x6b, 0x5a, 0x00, 0x01, 0x93, 0x4f, 0xff, 0xfc, 0x53, 0x48, 0x07, 0xfe,
// 0x4b, 0xff, 0xf9, 0xac, 0x2c, 0x0b, 0x00, 0x00, 0x41, 0x82, 0x01, 0x38, 0x2c, 0x05, 0x00, 0x01,
// 0x41, 0x82, 0x00, 0x18, 0x2c, 0x05, 0x00, 0x02, 0x41, 0x82, 0x00, 0x14, 0x2c, 0x05, 0x00, 0x03,
// 0x41, 0x82, 0x00, 0x70, 0x4b, 0xff, 0xf9, 0x40, 0x54, 0xcc, 0x00, 0x0c, 0x54, 0x97, 0x46, 0x3e,
// 0x54, 0x98, 0xc4, 0x3e, 0x54, 0x84, 0x06, 0x3e, 0x40, 0x9e, 0x00, 0xfc, 0x56, 0xf9, 0x06, 0x31,
// 0x7d, 0x9a, 0x63, 0x78, 0x7f, 0x43, 0xd2, 0x14, 0x57, 0x5a, 0x00, 0x3a, 0x41, 0x82, 0x00, 0x18,
// 0x7e, 0xf7, 0x07, 0x74, 0x7e, 0xf7, 0x00, 0xd0, 0x1f, 0x37, 0x00, 0x02, 0x3b, 0x39, 0x00, 0x04,
// 0x7f, 0x59, 0xd0, 0x50, 0x2c, 0x17, 0x00, 0x00, 0x41, 0x82, 0x00, 0x1c, 0x3b, 0x20, 0x00, 0x00,
// 0x7e, 0xe9, 0x03, 0xa6, 0xa3, 0x7a, 0x00, 0x04, 0x7f, 0x79, 0xca, 0x78, 0x3b, 0x5a, 0x00, 0x02,
// 0x42, 0x00, 0xff, 0xf4, 0x7c, 0x18, 0xc8, 0x00, 0x40, 0x82, 0x00, 0xac, 0x4b, 0xff, 0xfe, 0x90,
// 0x51, 0x08, 0x08, 0x3c, 0x40, 0x9e, 0x00, 0x9c, 0x54, 0x77, 0xb0, 0x03, 0x41, 0x81, 0x00, 0x88,
// 0x41, 0x80, 0x00, 0x8c, 0x54, 0x7e, 0x06, 0x3e, 0x1f, 0xde, 0x00, 0x02, 0x54, 0x97, 0x00, 0x1e,
// 0x6e, 0xf8, 0x80, 0x00, 0x2c, 0x18, 0x00, 0x00, 0x40, 0x82, 0x00, 0x08, 0x62, 0xf7, 0x30, 0x00,
// 0x54, 0x98, 0x80, 0x1e, 0x1f, 0x3e, 0x00, 0x04, 0x7f, 0x19, 0xc0, 0x50, 0x3b, 0x20, 0x00, 0x00,
// 0x1f, 0x59, 0x00, 0x04, 0x7f, 0x6f, 0xd0, 0x2e, 0x7f, 0x57, 0xd0, 0x2e, 0x3b, 0x39, 0x00, 0x01,
// 0x7c, 0x17, 0xc0, 0x40, 0x41, 0x81, 0x00, 0x34, 0x7c, 0x19, 0xf0, 0x00, 0x41, 0x81, 0x00, 0x14,
// 0x7c, 0x1a, 0xd8, 0x00, 0x41, 0x82, 0xff, 0xdc, 0x3a, 0xf7, 0x00, 0x04, 0x4b, 0xff, 0xff, 0xd0,
// 0x80, 0x6f, 0xff, 0xf8, 0x60, 0x63, 0x03, 0x00, 0x90, 0x6f, 0xff, 0xf8, 0x92, 0xef, 0xff, 0xfc,
// 0x7e, 0xf0, 0xbb, 0x78, 0x48, 0x00, 0x00, 0x1c, 0x80, 0x6f, 0xff, 0xf8, 0x60, 0x63, 0x01, 0x00,
// 0x90, 0x6f, 0xff, 0xf8, 0x61, 0x08, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, 0x7c, 0x90, 0x23, 0x78,
// 0x54, 0x64, 0x06, 0x3e, 0x1c, 0x84, 0x00, 0x08, 0x7d, 0xe4, 0x7a, 0x14, 0x4b, 0xff, 0xf8, 0x70,
// 0x40, 0x92, 0x00, 0x0c, 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, 0x54, 0x69, 0x06, 0xff,
// 0x54, 0x65, 0x67, 0xfe, 0x7d, 0x08, 0x4c, 0x30, 0x55, 0x17, 0xff, 0xff, 0x40, 0x82, 0x00, 0x08,
// 0x7d, 0x08, 0x2a, 0x78, 0x54, 0x85, 0x00, 0x1f, 0x41, 0x82, 0x00, 0x08, 0x7c, 0xa6, 0x2b, 0x78,
// 0x54, 0x85, 0x80, 0x1f, 0x41, 0x82, 0x00, 0x08, 0x7c, 0xb0, 0x2b, 0x78, 0x4b, 0xff, 0xf8, 0x30,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
//};

82
Config.c Normal file
View File

@ -0,0 +1,82 @@
#include "Config.h"
DML_CFG *DMLCfg;
void ConfigInit( DML_CFG *Cfg )
{
DMLCfg = (DML_CFG*)0xFFFE4200;
memset32( DMLCfg, 0, sizeof(DML_CFG) );
//If a loader supplied any options we use them otherwise use the code defines
if( Cfg->Magicbytes == 0xD1050CF6 )
{
memcpy( DMLCfg, Cfg, sizeof( DML_CFG ) );
} else {
dbgprintf("No valid config found in RAM\n");
dbgprintf("Version:%08X\n", DMLCfg->Version );
dbgprintf("Config :%08X\n", DMLCfg->Config );
DMLCfg->Config = 0;
#ifdef CHEATHOOK
DMLCfg->Config |= DML_CFG_CHEATS;
#endif
#ifdef DEBUGGER
DMLCfg->Config |= DML_CFG_DEBUGGER;
#endif
#ifdef DEBUGGERWAIT
DMLCfg->Config |= DML_CFG_DEBUGWAIT;
#endif
#ifdef CARDMODE
DMLCfg->Config |= DML_CFG_NMM;
#endif
#ifdef CARDDEBUG
DMLCfg->Config |= DML_CFG_NMM_DEBUG;
#endif
#ifdef ACTIVITYLED
DMLCfg->Config |= DML_CFG_ACTIVITY_LED;
#endif
#ifdef PADHOOK
DMLCfg->Config |= DML_CFG_PADHOOK;
#endif
DMLCfg->Magicbytes = 0xD1050CF6;
DMLCfg->Version = CONFIG_VERSION;
DMLCfg->VideoMode = DML_VID_DML_AUTO;
}
//Check if a memcard is inserted in Slot A
if( (read32(0xD806800) & 0x1000) == 0x1000 )
{
DMLCfg->Config &= ~DML_CFG_NMM; // disable NMM
}
dbgprintf("Config:%08X\n", DMLCfg->Config );
}
inline u32 ConfigGetConfig( u32 Config )
{
return !!(DMLCfg->Config & Config);
}
inline void ConfigSetConfig( u32 Config )
{
DMLCfg->Config |= Config;
}
inline void ConfigClearConfig( u32 Config )
{
DMLCfg->Config &= ~Config;
}
u32 ConfigGetVideMode( void )
{
return DMLCfg->VideoMode;
}
char *ConfigGetGamePath( void )
{
return DMLCfg->GamePath;
}
char *ConfigGetCheatPath( void )
{
return DMLCfg->CheatPath;
}

100
Config.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef _CFG_
#define _CFG_
#include "string.h"
#include "global.h"
#include "alloc.h"
#include "vsprintf.h"
#include "HW.h"
#define EXI_BASE 0x0D806800
typedef struct GC_SRAM
{
/* 0x00 */ u16 CheckSum1;
/* 0x02 */ u16 CheckSum2;
/* 0x04 */ u32 ead0;
/* 0x08 */ u32 ead1;
/* 0x0C */ u32 CounterBias;
/* 0x10 */ u8 DisplayOffsetH;
/* 0x11 */ u8 BootMode; // Bit 6 PAL60 flag
/* 0x12 */ u8 Language;
/* 0x13 */ u8 Flags;
/*
bit desc 0 1
0 -\_ Video mode
1 -/
2 Sound mode Mono Stereo
3 always 1
4 always 0
5 always 1
6 ?
7 Prog mode off on
*/
/* 0x14 */ u8 FlashID[2*12];
/* 0x2C */ u32 WirelessKBID;
/* 0x30 */ u16 WirlessPADID[4];
/* 0x38 */ u8 LastDVDError;
/* 0x39 */ u8 Reserved;
/* 0x3A */ u16 FlashIDChecksum[2];
/* 0x3C */ u16 Unused;
} GC_SRAM;
typedef struct DML_CFG
{
u32 Magicbytes; // 0xD1050CF6
u32 Version; // 0x00000002
u32 VideoMode;
u32 Config;
char GamePath[255];
char CheatPath[255];
} DML_CFG;
enum dmlconfig
{
DML_CFG_CHEATS = (1<<0),
DML_CFG_DEBUGGER = (1<<1),
DML_CFG_DEBUGWAIT = (1<<2),
DML_CFG_NMM = (1<<3),
DML_CFG_NMM_DEBUG = (1<<4),
DML_CFG_GAME_PATH = (1<<5),
DML_CFG_CHEAT_PATH = (1<<6),
DML_CFG_ACTIVITY_LED= (1<<7),
DML_CFG_PADHOOK = (1<<8),
DML_CFG_FORCE_WIDE = (1<<9),
DML_CFG_BOOT_DISC = (1<<10),
DML_CFG_BOOT_DISC2 = (1<<11),
DML_CFG_NODISC = (1<<12),
DML_CFG_SCREENSHOT = (1<<13),
};
enum dmlvideomode
{
DML_VID_DML_AUTO = (0<<16),
DML_VID_FORCE = (1<<16),
DML_VID_NONE = (2<<16),
DML_VID_FORCE_PAL50 = (1<<0),
DML_VID_FORCE_PAL60 = (1<<1),
DML_VID_FORCE_NTSC = (1<<2),
DML_VID_FORCE_PROG = (1<<3),
};
enum VideoModes
{
GCVideoModeNone = 0,
GCVideoModePAL60 = 1,
GCVideoModeNTSC = 2,
GCVideoModePROG = 3,
};
void ConfigInit( DML_CFG *Cfg );
u32 ConfigGetConfig( u32 Config );
void ConfigSetConfig( u32 Config );
void ConfigClearConfig( u32 Config );
u32 ConfigGetVideMode( void );
char *ConfigGetGamePath( void );
char *ConfigGetCheatPath( void );
#endif

443
DVD.c Normal file
View File

@ -0,0 +1,443 @@
#include "DVD.h"
DVDConfig *DICfg = (DVDConfig *)NULL;
u32 read;
static char GamePath[256];
extern FIL GameFile;
extern u32 FSTMode;
extern u32 DOLMaxOff;
extern u32 DOLOffset;
u8 HardDriveConnected;
FATFS fatfs;
static u8 *FSTable ALIGNED(32);
u32 ApploaderSize = 0;
u32 dolOffset = 0;
u32 FSTableSize = 0;
u32 FSTableOffset = 0;
u32 FCEntry=0;
FileCache FC[FILECACHE_MAX];
u32 FCState[FILECACHE_MAX];
DWORD LTable[0x1D0];
static void DVDCreateLinkMap( FIL *File )
{
GameFile.cltbl = LTable;
GameFile.cltbl[0] = sizeof(LTable);
s32 fres = f_lseek( &GameFile, CREATE_LINKMAP );
if( fres == FR_NOT_ENOUGH_CORE )
{
GameFile.cltbl = NULL;
}
}
void DVDInit( void )
{
int i=0;
s32 fres = FR_DISK_ERR;
int MountFail=0;
HardDriveConnected = 0;
while(!HardDriveConnected)
{
while(1)
{
fres = f_mount(0, &fatfs );
dbgprintf( "DIP:f_mount():%d\n", fres );
if( fres == FR_OK )
break;
else
MountFail++;
if( MountFail == 10 )
{
dbgprintf( "DIP:too much fail! looping now!\n");
while(1);
}
udelay(500000);
}
//try to open a file, it doesn't have to exist, just testing if FS works
FIL f;
fres = f_open( &f, "/randmb.in", FA_READ|FA_OPEN_EXISTING );
switch(fres)
{
case FR_OK:
f_close( &f );
case FR_NO_PATH:
case FR_NO_FILE:
{
HardDriveConnected = 1;
fres = FR_OK;
} break;
default:
case FR_DISK_ERR:
{
dbgprintf( "DIP:Disk error\n", fres );
while(1);
} break;
}
}
if( fres != FR_OK )
{
dbgprintf( "DIP:Could not find any USB device!");
}
return;
}
s32 DVDSelectGame( void )
{
char *str = (char*)malloca( 256, 32 );
u32 i=0;
if( ConfigGetConfig(DML_CFG_GAME_PATH) )
{
sprintf( str, "%s", ConfigGetGamePath() );
} else {
dbgprintf("DIP:No game path was supplied!\n");
free(str);
return -1;
}
s32 fres = f_open( &GameFile, str, FA_READ );
if( fres != FR_OK )
{
sprintf( GamePath, "%s", str );
//Try to switch to FST mode
if( !FSTInit() )
{
dbgprintf("DIP:Failed to open:\"%s\" fres:%d\n", str, fres );
free(str);
return -2;
}
} else {
f_close( &GameFile );
dbgprintf("DIP:Current Gamepath:\"%s\"\n", str );
//search the string backwards for '/'
for( i=strlen(str); i > 0; --i )
if( str[i] == '/' )
break;
i++;
if( ConfigGetConfig(DML_CFG_BOOT_DISC2) )
{
sprintf( str+i, "disc2.iso" );
} else {
sprintf( str+i, "game.iso" );
}
dbgprintf("DIP:New Gamepath:\"%s\"\n", str );
fres = f_open( &GameFile, str, FA_READ );
if( fres != FR_OK )
{
dbgprintf("DIP:Failed to open:\"%s\" fres:%d\n", str, fres );
free(str);
return -3;
}
DVDCreateLinkMap(&GameFile);
f_lseek( &GameFile, 0 );
f_read( &GameFile, (void*)0, 0x20, &read );
f_lseek( &GameFile, 0 );
f_read( &GameFile, str, 0x400, &read );
dbgprintf("DIP:Loading game %.6s: %s\n", str, (char *)(str+0x20));
f_lseek( &GameFile, 0x420 );
f_read( &GameFile, str, 0x40, &read );
}
free( str );
return DI_SUCCESS;
}
u32 FSTInit( void )
{
char Path[256];
FIL fd;
u32 read;
sprintf( Path, "%ssys/boot.bin", GamePath );
if( f_open( &fd, Path, FA_READ ) != FR_OK )
{
dbgprintf( "DIP:[%s] Failed to open!\n", Path );
return 0;
} else {
u8 *rbuf = (u8*)malloc( 0x100 );
f_lseek( &fd, 0 );
f_read( &fd, rbuf, 0x100, &read );
dbgprintf("DIP:Loading game %.6s: %s\n", rbuf, (char *)(rbuf+0x20));
//Read DOL/FST offset/sizes for later usage
f_lseek( &fd, 0x0420 );
f_read( &fd, rbuf, 0x20, &read );
dolOffset = *(u32*)(rbuf);
FSTableOffset = *(u32*)(rbuf+4);
FSTableSize = *(u32*)(rbuf+8);
free( rbuf );
dbgprintf( "DIP:FSTableOffset:%08X\n", FSTableOffset );
dbgprintf( "DIP:FSTableSize: %08X\n", FSTableSize );
dbgprintf( "DIP:DolOffset: %08X\n", dolOffset );
FSTMode = 1;
f_close( &fd );
}
//Init cache
u32 count = 0;
for( count=0; count < FILECACHE_MAX; ++count )
{
FCState[count] = 0xdeadbeef;
}
return 1;
}
void Asciify( char *str )
{
int i=0;
for( i=0; i < strlen(str); i++ )
if( str[i] < 0x20 || str[i] > 0x7F )
str[i] = '_';
}
void FSTRead( char *Buffer, u32 Length, u32 Offset )
{
char Path[256];
FIL fd;
u32 read;
int i,j;
if( Offset >= FSTableOffset+FSTableSize ) {
//Get FSTTable offset from low memory, must be set by apploader
if( FSTable == NULL )
{
FSTable = (u8*)((*(vu32*)0x38) & 0x7FFFFFFF);
//dbgprintf("DIP:FSTOffset: %08X\n", (u32)FSTable );
}
//try cache first!
for( i=0; i < FILECACHE_MAX; ++i )
{
if( FCState[i] == 0xdeadbeef )
continue;
if( Offset >= FC[i].Offset )
{
u64 nOffset = Offset - FC[i].Offset;
if( nOffset < FC[i].Size )
{
//dbgprintf("DIP:[Cache:%02d][%08X:%05X]\n", i, (u32)(nOffset>>2), Length );
f_lseek( &(FC[i].File), nOffset );
f_read( &(FC[i].File), Buffer, ((Length)+31)&(~31), &read );
return;
}
}
}
//The fun part!
u32 Entries = *(u32*)(FSTable+0x08);
char *NameOff = (char*)(FSTable + Entries * 0x0C);
FEntry *fe = (FEntry*)(FSTable);
u32 Entry[16];
u32 LEntry[16];
u32 level=0;
for( i=1; i < Entries; ++i )
{
if( level )
{
while( LEntry[level-1] == i )
{
//printf("[%03X]leaving :\"%s\" Level:%d\n", i, buffer + NameOff + swap24( fe[Entry[level-1]].NameOffset ), level );
level--;
}
}
if( fe[i].Type )
{
//Skip empty folders
if( fe[i].NextOffset == i+1 )
continue;
//printf("[%03X]Entering:\"%s\" Level:%d leave:%04X\n", i, buffer + NameOff + swap24( fe[i].NameOffset ), level, swap32( fe[i].NextOffset ) );
Entry[level] = i;
LEntry[level++] = fe[i].NextOffset;
if( level > 15 ) // something is wrong!
break;
} else {
if( Offset >= fe[i].FileOffset )
{
u32 nOffset = (Offset - fe[i].FileOffset);
if( nOffset < fe[i].FileLength )
{
// dbgprintf("DIP:Offset:%08X FOffset:%08X Dif:%08X Flen:%08X nOffset:%08X\n", Offset, fe[i].FileOffset, Offset-fe[i].FileOffset, fe[i].FileLength, nOffset );
//Do not remove!
memset( Path, 0, 256 );
sprintf( Path, "%sroot/", GamePath );
for( j=0; j<level; ++j )
{
if( j )
Path[strlen(Path)] = '/';
memcpy( Path+strlen(Path), NameOff + fe[Entry[j]].NameOffset, strlen(NameOff + fe[Entry[j]].NameOffset ) );
}
if( level )
Path[strlen(Path)] = '/';
memcpy( Path+strlen(Path), NameOff + fe[i].NameOffset, strlen(NameOff + fe[i].NameOffset) );
if( FCEntry >= FILECACHE_MAX )
FCEntry = 0;
if( FCState[FCEntry] != 0xdeadbeef )
{
f_close( &(FC[FCEntry].File) );
FCState[FCEntry] = 0xdeadbeef;
}
Asciify( Path );
f_open( &(FC[FCEntry].File), Path, FA_READ );
FC[FCEntry].Size = fe[i].FileLength;
FC[FCEntry].Offset = fe[i].FileOffset;
FCState[FCEntry] = 0x23;
DVDCreateLinkMap(&(FC[FCEntry].File));
f_lseek( &(FC[FCEntry].File), nOffset );
f_read( &(FC[FCEntry].File), Buffer, Length, &read );
FCEntry++;
}
}
}
}
} else if ( Offset >= FSTableOffset ) {
Offset -= FSTableOffset;
sprintf( Path, "%ssys/fst.bin", GamePath );
if( f_open( &fd, Path, FA_READ ) != FR_OK )
{
dbgprintf( "DIP:[%s] Failed to open!\n", Path );
return;
} else {
//dbgprintf( "DIP:[fst.bin] Offset:%08X Size:%08X\n", Offset, Length );
f_lseek( &fd, Offset );
f_read( &fd, Buffer, Length, &read );
f_close( &fd );
if( FSTable == NULL )
{
FSTable = (u8*)Buffer;
}
return;
}
} else if ( Offset >= dolOffset ) {
Offset -= dolOffset;
sprintf( Path, "%ssys/main.dol", GamePath );
if( f_open( &fd, Path, FA_READ ) != FR_OK )
{
dbgprintf( "DIP:[%s] Failed to open!\n", Path );
return;
} else {
//dbgprintf( "DIP:[main.dol] Offset:%08X Size:%08X\n", Offset, Length );
f_lseek( &fd, Offset );
f_read( &fd, Buffer, Length, &read );
f_close( &fd );
return;
}
} else if ( Offset >= 0x2440 ) {
Offset -= 0x2440;
sprintf( Path, "%ssys/apploader.img", GamePath );
if( f_open( &fd, Path, FA_READ ) != FR_OK )
{
dbgprintf( "DIP:[%s] Failed to open!\n", Path );
return;
} else {
//dbgprintf( "DIP:[apploader.img] Offset:%08X Size:%08X\n", Offset, Length );
f_lseek( &fd, Offset );
f_read( &fd, Buffer, Length, &read );
f_close( &fd );
return;
}
} else if ( Offset >= 0x440 ) {
Offset -= 0x440;
sprintf( Path, "%ssys/bi2.bin", GamePath );
if( f_open( &fd, Path, FA_READ ) != FR_OK )
{
dbgprintf( "DIP:[%s] Failed to open!\n", Path );
return;
} else {
//dbgprintf( "DIP:[bi2.bin] Offset:%08X Size:%08X\n", Offset, Length );
f_lseek( &fd, Offset );
f_read( &fd, Buffer, Length, &read );
f_close( &fd );
return;
}
} else {
sprintf( Path, "%ssys/boot.bin", GamePath );
if( f_open( &fd, Path, FA_READ ) != FR_OK )
{
dbgprintf( "DIP:[%s] Failed to open!\n", Path );
return;
} else {
//dbgprintf( "DIP:[boot.bin] Offset:%08X Size:%08X\n", Offset, Length );
f_lseek( &fd, Offset );
f_read( &fd, Buffer, Length, &read );
f_close( &fd );
return;
}
}
}

29
DVD.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef _DVD_
#define _DVD_
#include "global.h"
#include "HW.h"
#include "Config.h"
#include "ff.h"
#include "dol.h"
#include "Drive.h"
typedef struct
{
u32 SlotID;
u32 Region;
u32 Gamecount;
u32 Config;
u8 GameInfo[][0x80];
} DVDConfig;
void DVDInit( void );
void DVDReadConfig( void );
s32 DVDSelectGame( void );
void DVDUpdateFSTRAM( void );
void DiscBackup( u32 FrameBuffer );
u32 FSTInit( void );
void FSTRead( char *Buffer, u32 Length, u32 Offset );
#endif

10
DVDPatches.c Normal file
View File

@ -0,0 +1,10 @@
#ifndef __DVDPATCHES__
#define __DVDPATCHES__
#include "global.h"
#include "asm\DVDInquiryAsync.h"
#include "asm\DVDSeekAbsAsyncPrio.h"
#include "asm\padipc.h"
#endif

View File

@ -1,2 +0,0 @@
#labels Featured
<wiki:gadget url="http://crediar.no-ip.com/down.xml" width="100%" height="400" up_projectName="diosmioslite"/>

124
Drive.c Normal file
View File

@ -0,0 +1,124 @@
#include "Drive.h"
void DVDLowReset( void )
{
clear32( HW_RESETS, (1<<10) | (1<<17) );
set32( HW_RESETS, (1<<10) | (1<<17) );
}
u32 DVDLowGetError( void )
{
write32( 0x0D806000, 0x2E );
write32( 0x0D806008, 0xE0000000 );
write32( 0x0D806020, 0 );
write32( 0x0D80601c, 1 );
while( read32(0x0D80601c) & 1 );
set32( 0x0D806000, (1<<4) );
return read32( 0x0D806020 );
}
u32 DVDLowSeek( void )
{
write32( 0x0D806000, 0x2E );
write32( 0x0D806008, 0xAB000000 );
write32( 0x0D806020, 0 );
write32( 0x0D80601c, 1 );
while( read32(0x0D80601c) & 1 );
set32( 0x0D806000, (1<<4) );
return read32( 0x0D806020 );
}
u32 DVDLowStopMotor( void )
{
write32( 0x0D806000, 0x2E );
write32( 0x0D806008, 0xE3000000 );
write32( 0x0D806020, 0 );
write32( 0x0D80601c, 1 );
while( read32(0x0D80601c) & 1 );
set32( 0x0D806000, (1<<4) );
return read32( 0x0D806020 );
}
u32 LowReadDiscID( void *data )
{
write32( 0x0D806008, 0xA8000040 );
write32( 0x0D80600C, 0 );
write32( 0x0D806010, 0x20 );
write32( 0x0D806018, 0x20 );
write32( 0x0D806014, (u32)data );
write32( 0x0D806000, 0x3A );
write32( 0x0D80601C, 3 );
while (1)
{
if( read32( 0x0D806000 ) & (1<<2) )
{
set32( 0x0D806000, (1<<2) );
return 1;
}
if( read32( 0x0D806000 ) & (1<<4) )
{
set32( 0x0D806000, (1<<4) );
return 0;
}
}
return 0;
}
u32 LowRead( void *data, u32 Offset, u32 Length )
{
write32( 0x0D806008, 0xA8000000 );
write32( 0x0D80600C, Offset>>2 );
write32( 0x0D806010, Length );
write32( 0x0D806018, Length );
write32( 0x0D806014, (u32)data );
write32( 0x0D806000, 0x3A );
write32( 0x0D80601C, 3 );
while (1)
{
if( read32( 0x0D806000 ) & (1<<2) )
{
set32( 0x0D806000, (1<<2) );
return 1;
}
if( read32( 0x0D806000 ) & (1<<4) )
{
set32( 0x0D806000, (1<<4) );
return 0;
}
}
return 0;
}
u32 DVDEnableAudioStreaming( u32 Enable )
{
write32( 0x0D806004, read32( 0x0D806004 ) );
write32( 0x0D806008, 0xE4000000 | (Enable<<16) | 0x0A );
write32( 0x0D80601C, 1 );
while( read32(0x0D80601C) & 1 );
while(1)
{
if( read32( 0x0D806000 ) & 4 )
return DI_ERROR;
if(!read32(0x0D806018))
return DI_SUCCESS;
}
return DI_FATAL;
}

16
Drive.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _DRIVE_
#define _DRIVE_
#include "global.h"
#include "HW.h"
#include "memory.h"
void DVDLowReset( void );
u32 DVDEnableAudioStreaming( u32 Enable );
u32 DVDLowGetError( void );
u32 DVDLowStopMotor( void );
u32 LowReadDiscID( void *data );
u32 LowRead( void *data, u32 Offset, u32 Length );
u32 DVDLowSeek( void );
#endif

View File

@ -1,80 +0,0 @@
#labels Phase-Support,Featured
#Mashup of frequently asked questions
<wiki:toc max_depth="2"/>
[http://det1re.de/a/sneek/sneek_div.png]
= I just get a black screen (no DIOS MIOS splash screen) =
Chances are high that your USB2IDE device isn't supported.
* Assure that your HDD is formatted with FAT32, no other FS is supported.
* Only cluster sizes 32KB or less are supported.
* Only 2TB drives or less are supported.
* The FAT32 partition MUST be the first primaly partition on the HDD, otherwise it will not work.
* If all the above are ok try another USB2IDE device or wait for an update.
[http://det1re.de/a/sneek/sneek_div.png]
= I just get a black screen AFTER the DIOS MIOS splash screen =
Before anything check the [https://code.google.com/p/diosmios/wiki/GameIssues game issues] wiki page.
If your game isn't listed you should try the following:
* Verify that your dump is ok, just google for the md5 hash.
* Try to install the game with DiscEX (without -c)
* Assure that the game isn't just waiting for the debugger
* Try to use a game version that matches your region
* Verify your loader settings and turn off things like NMM/Force-Prog, NMM/Force-Prog can cause black screens
[http://det1re.de/a/sneek/sneek_div.png]
= It takes long for the DIOS MIOS splash screen to show up =
DIOS MIOS looks for an USB device on port 0 first and has code in place which waits for a device to become ready, only after (10seconds) it tries port 1.
* Simply connect your device to port 0 instead.
[http://det1re.de/a/sneek/sneek_div.png]
= I get a green screen after the DIOS MIOS splash screen =
This usually can have three reasons:
* You have the debugger with waiting enabled
* The game just crashed (should get a crash dump via USBGecko if `__`fwrite patch was applied)
* The game tried to switch from one video mode to another, usually happens when loading USA games on EUR systems or vice versa.
[http://det1re.de/a/sneek/sneek_div.png]
= I get "Fatal error app_main:dst not in MEM1!" =
GCLoader got incorrect data when reading from the ISO
* Verify that your HDD is using 32KB cluster size or less, this error can happen with 64KB cluster size.
* Verify that your dump is ok, just google for the md5 hash.
* Try to install the game again (delete the old folder before)
[http://det1re.de/a/sneek/sneek_div.png]
= I get "Fatal error apploader size is zero!" =
This means DM was unable to mount the selected ISO for whatever reason.
* Verify that your dump is ok, just google for the md5 hash.
* Try to install the game again (delete the old folder before)
* Your loader is using an incorrect config version
* You installed DIOS MIOS and are trying to load a game from SD card
* You installed DIOS MIOS Lite and are trying to load a game from an USB device
[http://det1re.de/a/sneek/sneek_div.png]
= I get "Fatal error entrypoint is not within MEM1!" =
This means the apploader could not load the main.dol
* Verify that your dump is ok, just google for the md5 hash.
* If you used GCReEX or DiscEX -c try DiscEX without -c to install the game as some games might break if you modify them
* Try to install the game again (delete the old folder before)
[http://det1re.de/a/sneek/sneek_div.png]
= My system shuts down when using NMM while loading/saving =
* In short NMM isn't supported for that game.
* This means a fatal error occurred in the NMM code and it could no longer assure stable program execution.
[http://det1re.de/a/sneek/sneek_div.png]
= NoDisc patch doesn't work =
* It seems many loaders havn't caught up yet since NoDisc is no longer controlled via the config but instead just but either having a disc in the drive or not.
[http://det1re.de/a/sneek/sneek_div.png]
= Will NTFS ever be supported? =
* No, it would also take way more space than there is available. Just so you know libNTFS for Wii/GC is about 500KB, total memory DM can use is 96KB and almost everything is already used up.
[http://det1re.de/a/sneek/sneek_div.png]
= Will the Wiimote/Classic Controller ever be supported? =
* No, this would require a complete SDIO/BlueTooth/Wiimote lib, which would also take up way more space than available. (BT+Wiimote lib in libOGC are ~600KB).
[http://det1re.de/a/sneek/sneek_div.png]
= Will WBFS ever be supported? =
HAHA nice joke.

42
FwritePatches.c Normal file
View File

@ -0,0 +1,42 @@
unsigned char VIFlush[8] =
{
0x7C, 0x80, 0x03, 0x78,
0x7C, 0xA3, 0x1B, 0x78,
} ;
//unsigned char __fwrite[] =
//{
// 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0x88, 0x40, 0x86, 0x00, 0x24,
//} ;
//
//unsigned char __fwriteGC[] =
//{
// 0x94, 0x21, 0xFF, 0xD0, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x34, 0xBF, 0x21, 0x00, 0x14,
// 0x7C, 0x99, 0x23, 0x78, 0x7C, 0xDA, 0x33, 0x78, 0x7C, 0x7B, 0x1B, 0x78, 0x7C, 0xBC, 0x2B, 0x78,
// 0x38, 0x80, 0x00, 0x00, 0x7F, 0x43, 0xD3, 0x78,
//} ;
//unsigned char __fwriteGCB[] =
//{
// 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0xB8, 0xBF, 0x21, 0x00, 0x2C,
// 0x3B, 0x44, 0x00, 0x00, 0x3B, 0x66, 0x00, 0x00, 0x3B, 0x83, 0x00, 0x00, 0x3B, 0x25, 0x00, 0x00,
// 0x38, 0x7B, 0x00, 0x00, 0x38, 0x80, 0x00, 0x00,
//} ;
//unsigned char __fwriteGCC[32] =
//{
// 0x94, 0x21, 0xFF, 0xB0, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x54, 0xBE, 0x81, 0x00, 0x20,
// 0x7C, 0x97, 0x23, 0x78, 0x7C, 0xDF, 0x33, 0x78, 0x38, 0x80, 0x00, 0x00, 0x90, 0x61, 0x00, 0x08,
//} ;
unsigned char patch_fwrite_GC[144] =
{
0x7C, 0x85, 0x21, 0xD7, 0x40, 0x81, 0x00, 0x84, 0x3C, 0xE0, 0xCC, 0x00, 0x3D, 0x40, 0xCC, 0x00,
0x3D, 0x60, 0xCC, 0x00, 0x60, 0xE7, 0x68, 0x14, 0x61, 0x4A, 0x68, 0x24, 0x61, 0x6B, 0x68, 0x20,
0x38, 0xC0, 0x00, 0x00, 0x7C, 0x06, 0x18, 0xAE, 0x54, 0x00, 0xA0, 0x16, 0x64, 0x08, 0xB0, 0x00,
0x38, 0x00, 0x00, 0xD0, 0x90, 0x07, 0x00, 0x00, 0x7C, 0x00, 0x06, 0xAC, 0x91, 0x0A, 0x00, 0x00,
0x7C, 0x00, 0x06, 0xAC, 0x38, 0x00, 0x00, 0x19, 0x90, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x06, 0xAC,
0x80, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x04, 0xAC, 0x70, 0x09, 0x00, 0x01, 0x40, 0x82, 0xFF, 0xF4,
0x80, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0xAC, 0x39, 0x20, 0x00, 0x00, 0x91, 0x27, 0x00, 0x00,
0x7C, 0x00, 0x06, 0xAC, 0x74, 0x09, 0x04, 0x00, 0x41, 0x82, 0xFF, 0xB8, 0x38, 0xC6, 0x00, 0x01,
0x7F, 0x86, 0x20, 0x00, 0x40, 0x9E, 0xFF, 0xA0, 0x7C, 0xA3, 0x2B, 0x78, 0x4E, 0x80, 0x00, 0x20,
};

47
GCPad.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef __GCPAD__
#define __GCPAD__
typedef struct
{
union
{
struct
{
bool ErrorStatus :1;
bool ErrorLatch :1;
u32 Reserved :1;
bool Start :1;
bool Y :1;
bool X :1;
bool B :1;
bool A :1;
u32 AlwaysSet :1;
bool R :1;
bool L :1;
bool Z :1;
bool Up :1;
bool Down :1;
bool Right :1;
bool Left :1;
s16 StickX :8;
s16 StickY :8;
};
u32 Buttons;
};
union
{
struct
{
s16 CStickX;
s16 CStickY;
s16 LShoulder;
s16 RShoulder;
};
u32 Sticks;
};
} GCPadStatus;
#endif

View File

@ -1,73 +0,0 @@
#summary This page has a list of games that have issues or require fixing to work on DIOS MIOS
#labels Featured
= Games that don't work due certain protections=
|| Name || Reason ||
|| PSO 3 || Seems to selfcheck itself and stuff (check) ||
= Games that break when modifying the ISO using DiscEX -c =
|| Name || Reason ||
|| Kirby's Air Ride || Unknown ||
|| Phantasy Star Online Episode I & II || hack requires unchanged FST ||
= Games that break when modifying the ISO using GCReEx -x =
|| Name || Reason ||
|| The Legend of Zelda Collector's Edition || Unknown ||
|| The Legend of Zelda OoT/Master Quest || Unknown ||
|| AUS Multi Game Demo Disc 3 || Unknown ||
|| Metroid Prime 2: Echoes Bonus Disc || Unknown ||
|| Star Wars Rebel Strike Preview Disc || Unknown ||
|| Nintendo GameCube Preview Disc: May 2003 || Unknown ||
|| Sonic Gems Collection || Unknown ||
|| Enter the Matrix || Unknown ||
|| Mario Party 4 || Unknown ||
Probably all games that use TGCs.
= Games that have issue due using audio streaming =
|| Name || Effect ||
|| 1080 Avalanche || No music during gameplay ||
|| IKARUGA || No music during gameplay ||
|| XGRA - Extreme G Racing Association || No music during gameplay ||
|| Eternal Darkness || No music during gameplay ||
|| Mario Soccer || No music during gameplay ||
|| Mario Superstar Baseb || No music during gameplay ||
|| Star Fox Adventures || No voices and music, subtitles are late ||
|| Super Monkey Ball || No music during gameplay ||
|| WAVE RACE BLUE STORM || No music during gameplay ||
|| Bomberman Generation || No music during gameplay ||
|| Bloody Roar: Primal Fury || No music during gameplay ||
|| MX Superfly || No music during gameplay ||
|| Resident Evil 4 Preview Disc || No music during gameplay ||
|| Shikigami no Shiro II || No music during gameplay ||
|| Naruto: Clash of Ninja || No music/dialog during gameplay ||
|| Naruto: Clash of Ninja 2 || No music/dialog during gameplay ||
|| Star Wars: The Clone Wars || No music during gameplay ||
|| Tak and the Power of Juju || No music during gameplay ||
|| Tony Hawk's Pro Skater 3 || No music during gameplay ||
|| Tony Hawk's Pro Skater 4 || No music during gameplay ||
|| Tube Slider || No music during gameplay ||
|| Legend of Zelda: Ocarina of Time / Master Quest || No music during game selection ||
|| Lotus Challenge || No music during gameplay ||
|| Lost Kingdoms || No music during gameplay ||
|| Alien Hominid || No music during gameplay ||
|| Crazy Taxi || No music during gameplay ||
|| Crash Bandicoot The Wrath of Cortex || No music during gameplay ||
|| Cel Damage || No music during gameplay ||
|| Star Wars: Jedi Knight II: Jedi Outcast || No music during gameplay ||
= Games that have issue due MIOS patching not being applied =
==*[http://crediar.no-ip.com/gc/ Official DIOS MIOS (Lite) Compatibility List]*==

1045
HW.c Normal file

File diff suppressed because it is too large Load Diff

88
HW.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef _HW_
#define _HW_
#include "string.h"
#include "global.h"
#include "memory.h"
#include "alloc.h"
#include "dip.h"
#include "GCPad.h"
#define P2C(x) ((x)&0x7FFFFFFF)
#define HW_BASE 0x0d800000
#define HW_MEMIRR (HW_BASE+0x60)
#define HW_AHBPROT (HW_BASE+0x64)
#define HW_DDRCTRL_ADDR (HW_BASE+0x74)
#define HW_DDRCTRL_VAL (HW_BASE+0x76)
#define HW_GPIO_ENABLE (HW_BASE+0xDC)
#define HW_GPIO_OUT (HW_BASE+0xE0)
#define HW_GPIO_DIR (HW_BASE+0xE4)
#define HW_GPIO_IN (HW_BASE+0xE8)
#define HW_GPIO_INTLVL (HW_BASE+0xEC)
#define HW_GPIO_INTFLAG (HW_BASE+0xF0)
#define HW_GPIO_INTMASK (HW_BASE+0xF4)
#define HW_GPIO_INMIR (HW_BASE+0xF8)
#define HW_GPIO_OWNER (HW_BASE+0xFC)
#define HW_ACRPLLSYS (HW_BASE+0x1B0)
#define HW_ACRPLLSYSEXT (HW_BASE+0x1B4)
#define DIFLAGS_PPCBOOT (1<<20)
#define IRQ_TIMER (1<<0)
#define IRQ_NAND (1<<1)
#define IRQ_AES (1<<2)
#define IRQ_SHA1 (1<<3)
#define IRQ_EHCI (1<<4)
#define IRQ_OHCI0 (1<<5)
#define IRQ_OHCI1 (1<<6)
#define IRQ_SDHC (1<<7)
#define IRQ_WIFI (1<<8)
#define IRQ_GPIO1B (1<<10)
#define IRQ_GPIO1 (1<<11)
#define IRQ_RESET (1<<17)
#define IRQ_PPCIPC (1<<30)
#define IRQ_IPC (1<<31)
#define GPIO_POWER (1<<1)
#define GPIO_EJECT (1<<9)
extern void DRAMCTRLWrite( u32 Register, u32 Value );
extern u32 DRAMCTRLRead( u32 Register );
void EHCIInit( void );
void EXIControl( u32 value );
void MIOSHWInit( u32 A, u32 B );
void MIOSInit( void );
void MEMInitLow( void );
void BootPPC( void );
void UNKInit( u32 A, u32 B );
void DRAMInit( u32 A, u32 B );
void ChangeClock( void );
void PPCReset( void );
void HWResetDisable( void );
void HWResetEnable( void );
void HW_184( void );
void HW_184_2( void );
void GetRevision( u32 *Version, u32 *Revision );
void HWMAgic( u32 R0, u32 R1, u32 R2, u32 R3 );
u32 DRAMRead( u32 ValueA );
void DRAMWrite( u32 ValueA, u32 ValueB );
u32 RegRead( u32 Register );
void RegWrite( u32 Register, u32 Value );
void HWRegWriteBatch( u32 A, u32 B, u32 C, u32 D, u32 delay );
void Shutdown( void );
#endif

53
Makefile Normal file
View File

@ -0,0 +1,53 @@
PREFIX = $(DEVKITARM)/bin/arm-eabi-
CC = $(PREFIX)gcc
AS = $(PREFIX)as
LD = $(PREFIX)gcc
SSTRIP = $(DEVKITARM)/bin/arm-eabi-strip
CFLAGS = -mbig-endian -fomit-frame-pointer -O2 -Wall -I. -mcpu=arm926ej-s -mthumb
CFLAGS += -fno-builtin-memcpy -fno-builtin-memset -fno-builtin-toupper -fno-builtin-memcmp -fno-builtin-malloc -fno-builtin-free
ASFLAGS = -mbig-endian -mcpu=arm926ej-s
LDFLAGS = -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,iosmodule.ld,-Map,iosmodule.map -n
LIBS = -lgcc
TARGET = iosmodule.elf
OBJECTS = start.o utils_asm.o HW.o Card.o memory.o memory_asm.o Config.o common.o ff.o diskio.o alloc.o Drive.o DVD.o dip.o Patches.o main.o vsprintf.o string.o tiny_ehci_glue.o usb_os.o
.PHONY: FORCE
all: $(TARGET)
$(TARGET) : iosmodule.ld $(OBJECTS)
@echo "LD $@"
@$(LD) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@
@echo $(SSTRIP) -s $@
%.o : %.s
@echo "AS $@"
@$(CC) $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c -x assembler-with-cpp -o $@ $<
%.o : %.S
@echo "AS $@"
@$(CC) $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c -x assembler-with-cpp -o $@ $<
%.o : %.c
@echo "CC $@"
@$(CC) $(CFLAGS) -c -o $@ $<
%.d: %.c
@echo "DEP $@"
@set -e; $(CC) -M $(CFLAGS) $< \
| sed 's?\($*\)\.o[ :]*?\1.o $@ : ?g' > $@; \
[ -s $@ ] || rm -f $@
%.d: %.S
@echo "DEP $@"
@touch $@
-include $(OBJECTS:.o=.d)
clean:
-rm -f *.elf *.o *.bin *.d *.map

1187
Patches.c Normal file

File diff suppressed because it is too large Load Diff

84
Patches.h Normal file
View File

@ -0,0 +1,84 @@
#ifndef _PATCHES_
#define _PATCHES_
#include "string.h"
#include "global.h"
#include "alloc.h"
#include "ff.h"
#include "vsprintf.h"
#include "HW.h"
#include "dol.h"
#include "Config.h"
#define MAX_FB 3
typedef struct PatchInfo
{
u8 *Signature;
u8 *Mask;
u32 Length;
u32 FunctionLength;
u8 *Patch;
u32 PatchLength;
char *Name;
} PatchInfo;
typedef struct FuncPattern
{
u32 Length;
u32 Loads;
u32 Stores;
u32 FCalls;
u32 Branch;
u32 Moves;
u8 *Patch;
u32 PatchLength;
char *Name;
u32 Group;
u32 Found;
} FuncPattern;
typedef struct PatchCache
{
u32 Offset;
u32 PatchID;
} PatchCache;
typedef struct _gx_rmodeobj {
u32 viTVMode;
u16 fbWidth;
u16 efbHeight;
u16 xfbHeight;
u16 viXOrigin;
u16 viYOrigin;
u16 viWidth;
u16 viHeight;
u32 xfbMode;
u8 field_rendering;
u8 aa;
u8 sample_pattern[12][2];
u8 vfilter[7];
} GXRModeObj;
#define VI_NTSC 0
#define VI_PAL 1
#define VI_MPAL 2
#define VI_DEBUG 3
#define VI_DEBUG_PAL 4
#define VI_EUR60 5
#define GXPal528IntDf 0
#define GXEurgb60Hz480IntDf 1
#define GXMpal480IntDf 2
#define GXNtsc480IntDf 3
#define GXNtsc480Int 4
void SMenuAddFramebuffer( void );
void ScreenShot( void );
void DoPatches( char *ptr, u32 size, u32 SectionOffset );
void DoCardPatches( char *ptr, u32 size, u32 SectionOffset );
void DoPatchesLoader( char *ptr, u32 size );
#endif

205
alloc.c Normal file
View File

@ -0,0 +1,205 @@
#include "alloc.h"
#include "vsprintf.h"
u8 *RAM;//[_AHEAP_SIZE_TOTAL];
HeapInfoEntry *HeapInfoEntries=(HeapInfoEntry *)NULL;
extern u32 DRAMRead( u32 a );
extern void DRAMWrite( u32 a, u32 b );
void HeapInit( u8 *Offset )
{
//RAM = (u8*)0xFFFE4000;
//RAM = (u8*)0x13600000;
//RAM = (u8*)0x00600000;
RAM = Offset;
HeapInfoEntries = (HeapInfoEntry*)(RAM+_AHEAP_SIZE);
memset32( HeapInfoEntries, 0, _AHEAP_INFO_SIZE );
while( HeapInfoEntries[0].Offset != 0 )
{
EXIControl(1);
dbgprintf("Alloc:Failed to clear memory!:%08X", HeapInfoEntries[0].Offset );
Shutdown();
}
// dbgprintf("Cleared 0x%04X bytes Space for %d allocs\n", _AHEAP_INFO_SIZE, _AHEAP_INFO_SIZE / 8 );
}
void *malloc( u32 _size )
{
if( _size == 0 )
return NULL;
if( _size > _AHEAP_SIZE )
return NULL;
//align size to 32, easy cheat toallow all allocs to be aligned easily
u32 size = (_size+0x1F) & (~0x1F);
//find a free entry to be used
u32 entry = 0xdeadbeef;
u32 i;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
{
entry = i;
break;
}
}
if( entry == 0xdeadbeef )
{
EXIControl(1);
dbgprintf("Alloc: run out of entries!\n");
while(1);
}
//dbgprintf("Alloc:Using entry:%d to alloc %u(%u) bytes...\n", entry, size, _size );
//Now we search a used entry
u32 used_entry = 0xdeadbeef;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
continue;
used_entry = i;
break;
}
if( used_entry == 0xdeadbeef )
{
//dbgprintf("There are no other entries used atm\n");
HeapInfoEntries[entry].Offset = RAM;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc1: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
}
find_space:
;
//dbgprintf("[%02d]Offset:%08X Size:%08X\n", used_entry, HeapInfoEntries[used_entry].Offset, HeapInfoEntries[used_entry].Size );
//now we search for the next closest and the previous closest entry
u32 next = 0xdeadbeef;
u32 prev = 0xdeadbeef;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
continue;
if( used_entry == i )
continue;
if( next == 0xdeadbeef )
{
if( HeapInfoEntries[i].Offset > HeapInfoEntries[used_entry].Offset )
next = i;
} else {
if( HeapInfoEntries[i].Offset < HeapInfoEntries[next].Offset && HeapInfoEntries[i].Offset > HeapInfoEntries[used_entry].Offset )
next = i;
}
if( prev == 0xdeadbeef )
{
if( HeapInfoEntries[i].Offset < HeapInfoEntries[used_entry].Offset )
prev = i;
} else {
if( HeapInfoEntries[i].Offset > HeapInfoEntries[prev].Offset && HeapInfoEntries[i].Offset < HeapInfoEntries[used_entry].Offset )
prev = i;
}
}
if( next == 0xdeadbeef )
{
//dbgprintf("This is the last entry\n");
//check if there is engough space left for our alloc
if( (u32)(HeapInfoEntries[used_entry].Offset-RAM) + HeapInfoEntries[used_entry].Size + size <= _AHEAP_SIZE )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[used_entry].Offset + HeapInfoEntries[used_entry].Size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc2: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
}
;//dbgprintf("2Not enough space left only had:%d\n", HEAP_SIZE - ((u32)(HeapInfoEntries[used_entry].Offset-RAM) + HeapInfoEntries[used_entry].Size) );
} else if( (u32)(HeapInfoEntries[used_entry].Offset) + HeapInfoEntries[used_entry].Size + size < (u32)(HeapInfoEntries[next].Offset) )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[used_entry].Offset + HeapInfoEntries[used_entry].Size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc4: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
} else {
;//dbgprintf("4Not enough space left only had:%d %d:%d\n", (u32)( HeapInfoEntries[next].Offset - HeapInfoEntries[used_entry].Offset ) - HeapInfoEntries[used_entry].Size, next, used_entry );
}
if( prev == 0xdeadbeef )
{
//dbgprintf("This is the first entry\n");
if( (u32)(HeapInfoEntries[used_entry].Offset-RAM) >= size )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[used_entry].Offset - size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc3: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
}
;//dbgprintf("3Not enough space left only had:%d\n", (u32)(HeapInfoEntries[used_entry].Offset-RAM) );
} else if( (u32)(HeapInfoEntries[prev].Offset) + HeapInfoEntries[prev].Size + size < (u32)(HeapInfoEntries[used_entry].Offset) )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[prev].Offset + HeapInfoEntries[prev].Size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc5: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
} else {
;//dbgprintf("5Not enough space left only had:%d\n", (u32)(HeapInfoEntries[used_entry].Offset-HeapInfoEntries[prev].Offset) - HeapInfoEntries[prev].Size );
}
//if we land here we have to go to the next entry
u32 temp = used_entry + 1;
used_entry = 0xdeadbeef;
for( i=temp; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
continue;
used_entry = i;
break;
}
if( used_entry != 0xdeadbeef )
goto find_space;
dbgprintf("Alloc:failed to alloc %d bytes\n", size );
return NULL;
}
void *malloca( u32 size, u32 align )
{
return malloc( size );
}
void free( void *ptr )
{
if( ptr == NULL )
return;
u32 i;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == ptr )
{
//dbgprintf("free: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[i].Offset, HeapInfoEntries[i].Size, i );
HeapInfoEntries[i].Offset = NULL;
HeapInfoEntries[i].Size = 0;
ptr = NULL;
return;
}
}
}

23
alloc.h Normal file
View File

@ -0,0 +1,23 @@
#include "utils.h"
#include "memory.h"
#include "HW.h"
#ifndef _ALLOC_
#define _ALLOC_
#define _AHEAP_SIZE_TOTAL 0x3000
#define _AHEAP_INFO_SIZE 0x0100
#define _AHEAP_SIZE _AHEAP_SIZE_TOTAL-_AHEAP_INFO_SIZE
typedef struct
{
u8 *Offset;
u32 Size;
} HeapInfoEntry;
void HeapInit( u8 *Offset );
void *malloc( u32 size );
void *malloca( u32 size, u32 align );
void free( void *ptr );
#endif

23
asm/CARDCheck.S Normal file
View File

@ -0,0 +1,23 @@
#include <asm.h>
#
# r3 Channel
CARDCheck:
mflr %r0
cmpwi %r3, 0
beq CARDPresent
li %r3, -3
b end
CARDPresent:
li %r3, 0
end:
lis %r4, 0xC000
stw %r3, 0x2F94(%r4)
mtlr %r0
blr

43
asm/CARDCheckAsync.S Normal file
View File

@ -0,0 +1,43 @@
#include <asm.h>
#
# r3 Channel
# r4 cb( chan, res )
CARDCheck:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
cmpwi %r3, 0
beq CARDPresent
cmpwi %r4, 0
beq NoCardNoCB
mtctr %r4
li %r4, -3
bctrl
NoCardNoCB:
li %r3, -3
b end
CARDPresent:
cmpwi %r4, 0
beq CardNoCB
mtctr %r4
li %r4, 0
bctrl
CardNoCB:
li %r3, 0
end:
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

60
asm/CARDCheckEX.S Normal file
View File

@ -0,0 +1,60 @@
#include <asm.h>
#
# r3 Channel
# r4 *xfer bytes used to repair the FS
# r5 cb
CARDCheckEx:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
cmpwi %r3, 0
beq CARDPresent
cmpwi %r4, 0
beq NoCardZeroPtr
li %r6, 0
stw %r6, 0(%r4)
NoCardZeroPtr:
cmpwi %r5, 0
beq NoCardNoCB
mtctr %r5
li %r4, -3
bctrl
NoCardNoCB:
li %r3, -3
b end
CARDPresent:
cmpwi %r4, 0
beq CardZeroPtr
li %r6, 0
stw %r6, 0(%r4)
CardZeroPtr:
cmpwi %r5, 0
beq CardNoCB
mtctr %r5
li %r4, 0
bctrl
CardNoCB:
li %r3, 0
end:
lis %r4, 0xC000
stw %r3, 0x2F94(%r4)
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

47
asm/CARDClose.S Normal file
View File

@ -0,0 +1,47 @@
#include <asm.h>
#
# r3 FileInfo
CARDClose:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#send cmd to DM
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
lis %r7, 0xC000
lis %r0, 0xC100
stw %r0, 0x2F60(%r7)
lwz %r0, 0x04(%r3)
stw %r0, 0x2F64(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
lwz %r3, 0x2F94(%r7)
mr %r4, %r3
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

90
asm/CARDCreate.S Normal file
View File

@ -0,0 +1,90 @@
#include <asm.h>
#
# r3 chan
# r4 fileName
# r5 size
# r6 fileInfo
# r7 cb
CARDCreate:
cmpwi %r3, 0
beq DoCode
li %r3, -3
li %r4, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x28(%sp)
stmw %r27, 0x14(%sp)
#send cmd to DM
mr %r12, %r7
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
lis %r7, 0xC000
lis %r0, 0xC200
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
stw %r6, 0x2F6C(%r7)
#cache workaround for the filename
li %r5, 8
mtctr %r5
lis %r5, 0xC000
invalidloop:
lwz %r0, 0(%r4)
stw %r0, 0x17E0(%r5)
addi %r4, %r4, 4
addi %r5, %r5, 4
bdnz invalidloop
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
lwz %r0, 0x2F90(%r7)
stw %r0, 0x04(%r6)
cmpwi %r12, 0
beq skip_cb
mtlr %r12
li %r3, 0
li %r4, 0
blrl
skip_cb:
lis %r7, 0xC000
lwz %r3, 0x2F94(%r7)
mr %r4, %r3
lmw %r27, 0x14(%sp)
lwz %r0, 0x2C(%sp)
addi %sp, %sp, 0x28
mtlr %r0
blr

80
asm/CARDDelete.S Normal file
View File

@ -0,0 +1,80 @@
#include <asm.h>
#
# r3 chan
# r4 fileName
# r5 cb
CARDDelete:
cmpwi %r3, 0
beq DoCode
li %r3, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#send cmd to DM
mr %r12, %r5
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
lis %r7, 0xC000
lis %r0, 0xC600
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
#cache workaround for the filename
li %r5, 8
mtctr %r5
lis %r5, 0xC000
invalidloop:
lwz %r0, 0(%r4)
stw %r0, 0x17E0(%r5)
addi %r4, %r4, 4
addi %r5, %r5, 4
bdnz invalidloop
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
cmpwi %r12, 0
beq skip_cb
mtlr %r12
lwz %r3, 0x2F94(%r7)
li %r4, 0
blrl
skip_cb:
lis %r7, 0xC000
lwz %r3, 0x2F94(%r7)
mr %r4, %r3
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

69
asm/CARDFastDelete.S Normal file
View File

@ -0,0 +1,69 @@
#include <asm.h>
#
# r3 chan
# r4 FileNo
# r5 cb
CARDFastDelete:
cmpwi %r3, 0
beq DoCode
li %r3, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#send cmd to DM
mr %r12, %r5
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
lis %r7, 0xC000
lis %r0, 0xCA00
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
cmpwi %r12, 0
beq skip_cb
mtlr %r12
lwz %r3, 0x2F94(%r7)
li %r4, 0
blrl
skip_cb:
lis %r7, 0xC000
lwz %r3, 0x2F94(%r7)
mr %r4, %r3
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

62
asm/CARDFastOpen.S Normal file
View File

@ -0,0 +1,62 @@
#include <asm.h>
#
# r3 chan
# r4 FileNo
# r5 FileInfo
CARDFastOpen:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
cmpwi %r3, 0
bne NoCard
#send cmd to DM
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
lis %r7, 0xC000
lis %r0, 0xC500
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
lwz %r3, 0x2F90(%r7)
stw %r3, 0x10(%r5)
stw %r4, 0x04(%r5)
lwz %r3, 0x2F94(%r7)
b end
NoCard:
li %r3, -3
end:
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

32
asm/CARDFreeBlocks.S Normal file
View File

@ -0,0 +1,32 @@
#include <asm.h>
#
# r3 chan
# r4 byteNotUsed
# r5 filesNotUsed
CARDFreeBlocks:
mflr %r0
cmpwi %r3, 0
beq CARDPresent
li %r3, -3
b end
CARDPresent:
lis %r3, 0x7F
addi %r3, %r3, 0x6000
stw %r3, 0(%r4)
li %r3, 16
stw %r3, 0(%r5)
li %r3, 0
end:
mtlr %r0
blr

30
asm/CARDGetEncoding.S Normal file
View File

@ -0,0 +1,30 @@
#include <asm.h>
#
# r3 Channel
# r4 endcoding(u16)
CARDGetEncoding:
cmpwi %r3, 0
beq DoCode
li %r3, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#0 is USA/EUR, 1 is JAP
li %r0, 0
sth %r0, 0(%r4)
end:
li %r3, 0
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

30
asm/CARDGetMemSize.S Normal file
View File

@ -0,0 +1,30 @@
#include <asm.h>
#
# r3 Channel
# r4 size(u16)
CARDGetMemSize:
cmpwi %r3, 0
beq DoCode
li %r3, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#possible sizes 4,8,16,32,64,128
li %r0, 8
sth %r0, 0(%r4)
end:
li %r3, 0
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

19
asm/CARDGetResultCode.S Normal file
View File

@ -0,0 +1,19 @@
#include <asm.h>
#
# r3 Channel
CARDGetResultCode:
cmpwi %r3, 0
beq CARDPresent
li %r3, -3
b end
CARDPresent:
lis %r3, 0xC000
lwz %r3, 0x2F94(%r3)
end:
blr

29
asm/CARDGetSerialNo.S Normal file
View File

@ -0,0 +1,29 @@
#include <asm.h>
#
# r3 Channel
# r4 serialNo
CARDGetSerialNo:
cmpwi %r3, 0
beq DoCode
li %r3, -3
blr
DoCode:
mflr %r0
lis %r3, 0xc7bd
subi %r3, %r3, 0x26C
stw %r3, 0x00(%r4)
lis %r3, 0xf47f
subi %r3, %r3, 0x3924
stw %r3, 0x04(%r4)
li %r3, 0
mtlr %r0
blr

74
asm/CARDGetStats.S Normal file
View File

@ -0,0 +1,74 @@
#include <asm.h>
#
# r3 chan
# r4 FileNo
# r5 Stat
# r6 cb
CARDGetStats:
cmpwi %r3, 0
beq DoCode
li %r3, 0
li %r4, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#send cmd to DM
mr %r12, %r6
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
lis %r7, 0xC000
lis %r0, 0xC300
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
#cache workaround
li %r6, 27
mtctr %r6
lis %r6, 0xC000
addi %r6, %r6, 0x1780
invalidloop:
lwz %r0, 0(%r6)
stw %r0, 0(%r5)
addi %r5, %r5, 4
addi %r6, %r6, 4
bdnz invalidloop
lwz %r3, 0x2F94(%r7)
mr %r4, %r3
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

17
asm/CARDGetXferredBytes.S Normal file
View File

@ -0,0 +1,17 @@
#include <asm.h>
#
# r3 Channel
CARDGetEncoding:
cmpwi %r3, 0
beq DoCode
blr
DoCode:
lis %r3, 0xC000
lwz %r3, 0x2FA0(%r3)
blr

26
asm/CARDMount.S Normal file
View File

@ -0,0 +1,26 @@
#include <asm.h>
#
# r3 Channel
# r4 workarea
# r5 detachCallback
CARDMount:
mflr %r0
stw %r0, 4(%sp)
cmpwi %r3, 0
beq CARDPresent
li %r3, -3
b end
CARDPresent:
li %r3, 0
end:
lwz %r0, 4(%sp)
mtlr %r0
blr

42
asm/CARDMountAsync.S Normal file
View File

@ -0,0 +1,42 @@
#include <asm.h>
#
# r3 Channel
# r4 workarea
# r5 detachCallback
# r6 attachCallback
CARDMountAsync:
cmpwi %r3, 0
beq DoCode
li %r3, -3
lis %r7, 0xC000
stw %r3, 0x2F94(%r7)
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
li %r3, 0
li %r4, 0
cmpwi %r6, 0
beq end
mtctr %r6
bctrl
end:
li %r3, 0
li %r4, 0
lis %r7, 0xC000
stw %r3, 0x2F94(%r7)
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

71
asm/CARDOpen.S Normal file
View File

@ -0,0 +1,71 @@
#include <asm.h>
#
# r3 chan
# r4 FileName
# r5 FileInfo
CARDOpen:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
cmpwi %r3, 0
bne NoCard
#send cmd to DM
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
lis %r7, 0xC000
#cmd is the same as the offset, one opcode saved!
stw %r7, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
#cache workaround for the filename
li %r3, 8
mtctr %r3
lis %r3, 0xC000
invalidloop:
lwz %r0, 0(%r4)
stw %r0, 0x17E0(%r3)
addi %r4, %r4, 4
addi %r3, %r3, 4
bdnz invalidloop
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
lwz %r0, 0x2F90(%r7)
stw %r0, 0x04(%r5)
lwz %r3, 0x2F94(%r7)
b end
NoCard:
li %r3, -3
end:
mr %r4, %r3
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

21
asm/CARDProbe.S Normal file
View File

@ -0,0 +1,21 @@
#include <asm.h>
#
# r3 Channel
CARDProbe:
mflr %r0
cmpwi %r3, 0
beq CARDPresent
li %r3, 0
b end
CARDPresent:
li %r3, 1
end:
mtlr %r0
blr

41
asm/CARDProbeEX.S Normal file
View File

@ -0,0 +1,41 @@
#include <asm.h>
#
# r3 Channel
# r4 MemSize (can be zero ptr)
# r5 SecSize (can be zero ptr)
CARDProbeEX:
mflr %r0
cmpwi %r3, 0
beq CARDPresent
li %r3, -3
b end
CARDPresent:
cmpwi %r4, 0
beq ZeroMemPtr
li %r3, 8
stw %r3, 0(%r4)
ZeroMemPtr:
cmpwi %r5, 0
beq ZeroSecPtr
li %r3, 0x2000
stw %r3, 0(%r5)
ZeroSecPtr:
li %r3, 0
end:
mtlr %r0
blr

82
asm/CARDRead.S Normal file
View File

@ -0,0 +1,82 @@
#include <asm.h>
#
# r3 file *
# r4 buffer
# r5 length
# r6 offset
# r7 cb
CardRead:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x28(%sp)
stmw %r27, 0x14(%sp)
#Update fileinfo
stw %r5, 0x0C(%r3)
stw %r6, 0x08(%r3)
#send cmd to DM
mr %r12, %r7
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
srwi %r7, %r5, 5
mtctr %r7
mr %r7, %r4
invalidloop:
dcbi %r0, %r7
addi %r7, %r7, 0x20
bdnz invalidloop
lis %r7, 0xC000
lis %r0, 0xC900
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
stw %r6, 0x2F6C(%r7)
lwz %r0, 0x04(%r3)
stw %r0, 0x2F70(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
cmpwi %r12, 0
beq skip_cb
mtlr %r12
li %r3, 0
li %r4, 0
blrl
skip_cb:
li %r3, 0
mr %r4, %r3
lmw %r27, 0x14(%sp)
lwz %r0, 0x2C(%sp)
addi %sp, %sp, 0x28
mtlr %r0
blr

87
asm/CARDRename.S Normal file
View File

@ -0,0 +1,87 @@
#include <asm.h>
#
# r3 chan
# r4 old
# r5 new
# r6 cb
CARDRename:
mflr %r8
cmpwi %r3, 0
bne NoCard
#send cmd to DM
mr %r12, %r6
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
addi %r7, %r7, 0x20
dcbi %r0, %r7
#cache workaround for the filename
li %r3, 8
mtctr %r3
lis %r3, 0xC000
invalidloopA:
lwz %r0, 0(%r4)
stw %r0, 0x17C0(%r3)
addi %r4, %r4, 4
addi %r3, %r3, 4
bdnz invalidloopA
#cache workaround for the filename
li %r3, 8
mtctr %r3
lis %r3, 0xC000
invalidloopB:
lwz %r0, 0(%r5)
stw %r0, 0x17E0(%r3)
addi %r5, %r5, 4
addi %r3, %r3, 4
bdnz invalidloopB
lis %r7, 0xC000
lis %r0, 0xCB00
stw %r0, 0x2F60(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
cmpwi %r12, 0
beq skip_cb
mtlr %r12
li %r3, 0
lwz %r4, 0x2F94(%r7)
blrl
skip_cb:
lwz %r3, 0x2F94(%r7)
b end
NoCard:
li %r3, -3
end:
mr %r4, %r3
mtlr %r8
blr

83
asm/CARDSetStats.S Normal file
View File

@ -0,0 +1,83 @@
#include <asm.h>
#
# r3 chan
# r4 fileNo
# r5 stat
# r6 cb
CARDSetStat:
cmpwi %r3, 0
beq DoCode
li %r3, 0
li %r4, -3
blr
DoCode:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x10(%sp)
#send cmd to DM
mr %r12, %r6
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbst %r0, %r7
#stat
mr %r7, %r5
#0x00
dcbst %r0, %r7
addi %r7, %r7, 0x20
#0x20
dcbst %r0, %r7
addi %r7, %r7, 0x20
#0x40
dcbst %r0, %r7
addi %r7, %r7, 0x20
#0x60
dcbst %r0, %r7
sc
lis %r7, 0xC000
lis %r0, 0xC400
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
cmpwi %r12, 0
beq skip_cb
mtctr %r12
li %r3, 0
li %r4, 0
bctrl
skip_cb:
li %r3, 0
mr %r4, %r3
lwz %r0, 0x14(%sp)
addi %sp, %sp, 0x10
mtlr %r0
blr

82
asm/CARDWrite.S Normal file
View File

@ -0,0 +1,82 @@
#include <asm.h>
#
# r3 file *
# r4 buffer
# r5 length
# r6 offset
# r7 cb
CardWrite:
mflr %r0
stw %r0, 4(%sp)
stwu %sp, -0x28(%sp)
stmw %r27, 0x14(%sp)
#Update fileinfo
stw %r5, 0x0C(%r3)
stw %r6, 0x08(%r3)
#send cmd to DM
mr %r12, %r7
li %r0, 0
lis %r7, 0xC000
addi %r7, %r7, 0x2F60
#IPC area
dcbi %r0, %r7
srwi %r7, %r5, 5
mtctr %r7
mr %r7, %r4
invalidloop:
dcbst %r0, %r7
addi %r7, %r7, 0x20
bdnz invalidloop
sc
lis %r7, 0xC000
lis %r0, 0xC800
stw %r0, 0x2F60(%r7)
stw %r4, 0x2F64(%r7)
stw %r5, 0x2F68(%r7)
stw %r6, 0x2F6C(%r7)
lwz %r0, 0x04(%r3)
stw %r0, 0x2F70(%r7)
li %r0, 3
stw %r0, 0x2F78(%r7)
ready_loop:
lwz %r0, 0x2F78(%r7)
cmpwi %r0, 3
beq ready_loop
wait_loop:
lwz %r0, 0x2F9C(%r7)
andi. %r0, %r0, 0x14
cmpwi %r0, 0
beq wait_loop
cmpwi %r12, 0
beq skip_cb
mtlr %r12
li %r3, 0
li %r4, 0
blrl
skip_cb:
li %r3, 0
mr %r4, %r3
lmw %r27, 0x14(%sp)
lwz %r0, 0x2C(%sp)
addi %sp, %sp, 0x28
mtlr %r0
blr

60
asm/DVDInquiryAsync.S Normal file
View File

@ -0,0 +1,60 @@
#include <asm.h>
# issue read command
#
# r3 dvdstruct
# r4 dst
# r5 cb
DVDInquiryAsync:
stwu %sp, -0x10(%sp)
mflr %r0
stw %r0, 8(%sp)
#update dvdstruct
li %r0, 0
stw %r0, 0x00(%r3)
stw %r0, 0x04(%r3)
stw %r0, 0x0C(%r3)
#offset
stw %r0, 0x10(%r3)
li %r0, 2
stw %r0, 0x08(%r3)
li %r0, 0x20
#TransferSize
stw %r0, 0x1C(%r3)
stw %r0, 0x20(%r3)
#size
stw %r0, 0x14(%r3)
#ptr
stw %r4, 0x18(%r3)
#cb
stw %r5, 0x28(%r3)
#Inquiry reply
li %r0, 0
dcbi %r0, %r4
li %r0, 0x0000
sth %r0, 0x02(%r4)
cmpwi %r5, 0
beq skip_cb
mtctr %r5
mr %r4, %r3
li %r3, 0x20
bctrl
skip_cb:
li %r3, 1
lwz %r0, 8(%sp)
mtlr %r0
addi %sp, %sp, 0x10
blr

47
asm/DVDSeekAbsAsyncPrio.S Normal file
View File

@ -0,0 +1,47 @@
#include <asm.h>
# issue read command
#
# r3 dvdstruct
# r4 off
# r5 cb
# r6 prio
DVDSeekAbsAsyncPrio:
stwu %sp, -0x10(%sp)
mflr %r0
stw %r0, 8(%sp)
#update dvdstruct
li %r0, 0
stw %r0, 0x00(%r3)
stw %r0, 0x04(%r3)
stw %r0, 0x1C(%r3)
li %r0, 2
stw %r0, 0x08(%r3)
li %r0, 0
stw %r0, 0x0C(%r3)
#off
stw %r4, 0x10(%r3)
#cb
stw %r5, 0x28(%r3)
cmpwi %r5, 0
beq skip_cb
mtctr %r5
mr %r4, %r3
li %r3, 0
bctrl
skip_cb:
li %r3, 1
lwz %r0, 8(%sp)
mtlr %r0
addi %sp, %sp, 0x10
blr

9
asm/__CARDSync.S Normal file
View File

@ -0,0 +1,9 @@
#include <asm.h>
#
# r3 *Async result
__CARDSync:
mr %r3, %r4
blr

4
asm/make.cmd Normal file
View File

@ -0,0 +1,4 @@
@echo off
for /R %%i IN (*.S) DO %devkitpro:~1,1%:\%devkitpro:~3%\devkitPPC\bin\powerpc-eabi-as.exe %%i -o %%~ni.elf
for /R %%i IN (*.S) DO %devkitpro:~1,1%:\%devkitpro:~3%\devkitPPC\bin\powerpc-eabi-strip.exe -s %%~ni.elf -O binary -o %%~ni.bin
for /R %%i in (*.bin) DO "..\tools\bin2h\bin2h.exe" %%~ni.bin

18
asm/padipc.S Normal file
View File

@ -0,0 +1,18 @@
#include <asm.h>
PADRead:
lis %r4, 0xCC00
lwz %r5, 0x6428(%r4)
lwz %r0, 0x642C(%r4)
lwz %r0, 0x6404(%r4)
lwz %r4, 0x6408(%r4)
lis %r4, 0xC000
stw %r0, 0x12FC(%r4)
stw %r5, 0x12F8(%r4)
blr

32
bsdtypes.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef __BSDTYPES_H__
#define __BSDTYPES_H__
#include "global.h"
#include "errno.h"
typedef u32 u_int;
//typedef u32 u_int32_t;
typedef u16 u_int16_t;
typedef u8 u_int8_t;
typedef u8 u_char;
typedef u32 bus_space_tag_t;
typedef u32 bus_space_handle_t;
struct device {
char dv_xname[255];
void *dummy;
};
#define MIN(a, b) (((a)>(b))?(b):(a))
#define wakeup(...)
#define bzero(mem, size) memset8(mem, 0, size)
#define ISSET(var, mask) (((var) & (mask)) ? 1 : 0)
#define SET(var, mask) ((var) |= (mask))
#endif

2
common.c Normal file
View File

@ -0,0 +1,2 @@
#include "string.h"
#include "global.h"

378
dip.c Normal file
View File

@ -0,0 +1,378 @@
#include "dip.h"
u32 StreamBufferSize= 54*1024;
u32 Streaming = 0;
u32 StreamOffset = 0;
u32 StreamDiscOffset= 0;
s32 StreamSize = 0;
u32 StreamRAMOffset = 0;
u32 StreamTimer = 0;
u32 StreamStopEnd = 0;
u32 GameRun = 0;
u32 DOLMinOff = 0;
u32 DOLMaxOff = 0;
u32 DOLSize = 0;
u32 DOLOffset = 0;
s32 ELFNumberOfSections = 0;
u32 FSTMode = 0;
u32 DiscChangeIRQ = 0;
extern DML_CFG *DMLCfg;
FIL GameFile;
u32 read;
u32 DiscRead=0;
char *getfilenamebyoffset(u32 offset)
{
u32 fst_offset = read32(0x38) & ~0x80000000;
u32 i;
for (i = fst_offset + 12; i < 0x01800000; i+=12)
{
if (read8(i) == 0 && offset >= read32(i + 4) && offset < read32(i + 4) + read32(i + 8))
{
return (char *)(fst_offset + read32(fst_offset+8)*12 + (read32(i) & 0x00ffffff));
}
}
return (char*)NULL;
}
void DIInit( void )
{
memset32( (void*)DI_BASE, 0xdeadbeef, 0x30 );
memset32( (void*)(DI_SHADOW), 0, 0x30 );
write32( DI_SCONFIG, 0xFF );
write32( DI_SCOVER, 0 );
write32( HW_TIMER, 0 );
}
u32 DIUpdateRegisters( void )
{
u32 read,i,j;
static u32 PatchState = 0;
static u32 DOLReadSize = 0;
static u32 PSOHack = 0;
if( read32(DI_CONTROL) != 0xdeadbeef )
{
write32( DI_SCONTROL, read32(DI_CONTROL) & 3 );
clear32( DI_SSTATUS, 0x14 );
write32( DI_CONTROL, 0xdeadbeef );
if( read32(DI_SCONTROL) & 1 )
{
if( ConfigGetConfig(DML_CFG_ACTIVITY_LED) )
set32( HW_GPIO_OUT, 1<<5 );
if( read32(DI_CMD_0) != 0xdeadbeef )
{
write32( DI_SCMD_0, read32(DI_CMD_0) );
write32( DI_CMD_0, 0xdeadbeef );
}
if( read32(DI_CMD_1) != 0xdeadbeef )
{
write32( DI_SCMD_1, read32(DI_CMD_1) );
write32( DI_CMD_1, 0xdeadbeef );
}
if( read32(DI_CMD_2) != 0xdeadbeef )
{
write32( DI_SCMD_2, read32(DI_CMD_2) );
write32( DI_CMD_2, 0xdeadbeef );
}
if( read32(DI_DMA_ADR) != 0xdeadbeef )
{
write32( DI_SDMA_ADR, read32(DI_DMA_ADR) );
write32( DI_DMA_ADR, 0xdeadbeef );
}
if( read32(DI_DMA_LEN) != 0xdeadbeef )
{
write32( DI_SDMA_LEN, read32(DI_DMA_LEN) );
write32( DI_DMA_LEN, 0xdeadbeef );
}
if( read32(DI_IMM) != 0xdeadbeef )
{
write32( DI_SIMM, read32(DI_IMM) );
write32( DI_IMM, 0xdeadbeef );
}
switch( read32(DI_SCMD_0) >> 24 )
{
case 0xE3:
{
dbgprintf("DIP:DVDLowStopMotor()\n");
u32 CDiscNumber = (read32(4) << 16 ) >> 24;
dbgprintf("DIP:Current disc number:%u\n", CDiscNumber + 1 );
if( CDiscNumber )
{
ConfigClearConfig(DML_CFG_BOOT_DISC2);
} else {
ConfigSetConfig(DML_CFG_BOOT_DISC2);
}
f_close( &GameFile );
dbgprintf("DVDSelectGame():%d\n", DVDSelectGame() );
DiscChangeIRQ = 1;
while( read32(DI_SCONTROL) & 1 )
clear32( DI_SCONTROL, 1 );
set32( DI_SSTATUS, 0x3A );
write32( 0x0d80000C, (1<<0) | (1<<4) );
write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) );
write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) );
set32( 0x0d80000C, (1<<2) );
write32( HW_TIMER, 0 );
} break;
case 0xA7:
case 0xA9:
//dbgprintf("DIP:Async!\n");
case 0xA8:
{
u32 Buffer = P2C(read32(DI_SDMA_ADR));
u32 Length = read32(DI_SCMD_2);
u32 Offset = read32(DI_SCMD_1) << 2;
// dbgprintf("DIP:DVDRead%02X( 0x%08x, 0x%08x, 0x%08x )\n", read32(DI_SCMD_0) >> 24, Offset, Length, Buffer|0x80000000 );
// udelay(250);
if( FSTMode )
{
FSTRead( (char*)Buffer, Length, Offset );
} else {
if( GameFile.fptr != Offset )
if( f_lseek( &GameFile, Offset ) != FR_OK )
{
EXIControl(1);
dbgprintf("DIP:Failed to seek to 0x%08x\n", Offset );
while(1);
}
if( f_read( &GameFile, (char*)Buffer, Length, &read ) != FR_OK )
{
EXIControl(1);
dbgprintf("DIP:Failed to read from 0x%08x to 0x%08X\n", Offset, Buffer );
while(1);
}
}
//if( ((read+31)&(~31)) != Length )
//{
// dbgprintf("DIP:DVDLowRead Offset:%08X Size:%08d Dst:%08X\n", Offset, Length, Buffer );
// dbgprintf("DIP:Failed to read %d bytes, only got %d\n", Length, read );
// break;
//}
if( (u32)Buffer == 0x01300000 )
{
DoPatches( (char*)(0x01300000), Length, 0x80000000 );
}
// PSO 1&2
if( (read32(0) >> 8) == 0x47504F )
{
switch( Offset )
{
case 0x56B8E7E0: // AppSwitcher [EUR]
case 0x56C49600: // [USA] v1.1
case 0x56C4C980: // [USA] v1.0
{
DMLCfg->Config &= ~(DML_CFG_CHEATS|DML_CFG_PADHOOK|DML_CFG_DEBUGGER|DML_CFG_DEBUGWAIT);
DoPatches( (char*)Buffer, Length, 0x80000000 );
} break;
case 0x5668FE20: // psov3.dol [EUR]
case 0x56750660: // [USA] v1.1
case 0x56753EC0: // [USA] v1.0
{
PSOHack = 1;
} break;
}
}
if( PatchState == 0 )
{
if( Length == 0x100 || PSOHack )
{
if( read32( (u32)Buffer ) == 0x100 )
{
//quickly calc the size
DOLSize = sizeof(dolhdr);
dolhdr *dol = (dolhdr*)Buffer;
for( i=0; i < 7; ++i )
DOLSize += dol->sizeText[i];
for( i=0; i < 11; ++i )
DOLSize += dol->sizeData[i];
DOLReadSize = Length;
DOLMinOff=0x81800000;
DOLMaxOff=0;
for( i=0; i < 7; ++i )
{
if( dol->addressText[i] == 0 )
continue;
if( DOLMinOff > dol->addressText[i])
DOLMinOff = dol->addressText[i];
if( DOLMaxOff < dol->addressText[i] + dol->sizeText[i] )
DOLMaxOff = dol->addressText[i] + dol->sizeText[i];
}
for( i=0; i < 11; ++i )
{
if( dol->addressData[i] == 0 )
continue;
if( DOLMinOff > dol->addressData[i])
DOLMinOff = dol->addressData[i];
if( DOLMaxOff < dol->addressData[i] + dol->sizeData[i] )
DOLMaxOff = dol->addressData[i] + dol->sizeData[i];
}
DOLMinOff -= 0x80000000;
DOLMaxOff -= 0x80000000;
if( PSOHack )
{
DOLMinOff = Buffer;
DOLMaxOff = Buffer + DOLSize;
}
dbgprintf("DIP:DOLSize:%d DOLMinOff:0x%08X DOLMaxOff:0x%08X\n", DOLSize, DOLMinOff, DOLMaxOff );
PatchState = 1;
}
PSOHack = 0;
} else if( read32(Buffer) == 0x7F454C46 )
{
dbgprintf("DIP:Game is loading an ELF 0x%08x\n", Offset );
DOLOffset = Offset;
DOLSize = 0;
if( Length > 0x1000 )
{
DOLReadSize = Length;
DoPatches( (char*)(Buffer), Length, 0x80000000 );
} else
DOLReadSize = 0;
Elf32_Ehdr *ehdr = (Elf32_Ehdr*)Buffer;
dbgprintf("DIP:ELF Programheader Entries:%u\n", ehdr->e_phnum );
for( i=0; i < ehdr->e_phnum; ++i )
{
Elf32_Phdr phdr;
if( FSTMode )
{
FSTRead( (char*)&phdr, sizeof(Elf32_Phdr), DOLOffset + ehdr->e_phoff + i * sizeof(Elf32_Phdr) );
} else {
f_lseek( &GameFile, DOLOffset + ehdr->e_phoff + i * sizeof(Elf32_Phdr) );
f_read( &GameFile, &phdr, sizeof(Elf32_Phdr), &read );
}
DOLSize += (phdr.p_filesz+31) & (~31); // align by 32byte
}
dbgprintf("DIP:ELF size:%u\n", DOLSize );
PatchState = 2;
}
} else if ( PatchState == 1 )
{
DOLReadSize += Length;
//dbgprintf("DIP:DOL ize:%d DOL read:%d\n", DOLSize, DOLReadSize );
if( DOLReadSize >= DOLSize )
{
DoPatches( (char*)(DOLMinOff), DOLMaxOff-DOLMinOff, 0x80000000 );
PatchState = 0;
}
} else if ( PatchState == 2 )
{
DoPatches( (char*)(Buffer), Length, 0x80000000 );
if( Buffer > DOLMaxOff )
DOLMaxOff = Buffer;
DOLReadSize += Length;
//dbgprintf("DIP:ELF size:%d ELF read:%d\n", DOLSize, DOLReadSize );
if( DOLReadSize >= DOLSize )
{
PatchState = 0;
}
}
write32( DI_SDMA_LEN, 0 );
while( read32(DI_SCONTROL) & 1 )
clear32( DI_SCONTROL, 1 );
set32( DI_SSTATUS, 0x3A );
if( (read32(DI_SCMD_0) >> 24) == 0xA7 )
{
write32( 0x0d80000C, (1<<0) | (1<<4) );
write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) );
write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) );
set32( 0x0d80000C, (1<<2) );
}
write32( HW_TIMER, 0 );
} break;
default:
{
EXIControl(1);
dbgprintf("DIP:Unknown CMD:%08X %08X %08X %08X %08X %08X\n", read32(DI_SCMD_0), read32(DI_SCMD_1), read32(DI_SCMD_2), read32(DI_SIMM), read32(DI_SDMA_ADR), read32(DI_SDMA_LEN) );
while(1);
} break;
}
if( ConfigGetConfig(DML_CFG_ACTIVITY_LED) )
clear32( HW_GPIO_OUT, 1<<5 );
return 1;
} else {
;//dbgprintf("DIP:DI_CONTROL:%08X:%08X\n", read32(DI_CONTROL), read32(DI_CONTROL) );
}
}
if( (u64)read32(HW_TIMER) >= 25 * 243000000LL / 128 )
{
USBStorage_Read_Sectors( (read32(HW_TIMER) << 3) & 0x000FFFFF, 1, (void*)0x1000 );
write32( HW_TIMER, 0 );
}
return 0;
}

140
dip.h Normal file
View File

@ -0,0 +1,140 @@
#ifndef _DIP_
#define _DIP_
#include "global.h"
#include "string.h"
#include "alloc.h"
#include "ff.h"
#include "vsprintf.h"
#include "HW.h"
#include "dol.h"
#include "Patches.h"
#include "vsprintf.h"
#include "Config.h"
#include "DVD.h"
#include "elf.h"
#include "usbstorage.h"
enum opcodes
{
DVD_IDENTIFY = 0x12,
DVD_READ_DISCID = 0x70,
DVD_LOW_READ = 0x71,
DVD_WAITFORCOVERCLOSE = 0x79,
DVD_READ_PHYSICAL = 0x80,
DVD_READ_COPYRIGHT = 0x81,
DVD_READ_DISCKEY = 0x82,
DVD_GETCOVER = 0x88,
DVD_RESET = 0x8A,
DVD_OPEN_PARTITION = 0x8B,
DVD_CLOSE_PARTITION = 0x8C,
DVD_READ_UNENCRYPTED = 0x8D,
DVD_REPORTKEY = 0xA4,
DVD_LOW_SEEK = 0xAB,
DVD_READ = 0xD0,
DVD_READ_CONFIG = 0xD1,
DVD_READ_BCA = 0xDA,
DVD_GET_ERROR = 0xE0,
DVD_SET_MOTOR = 0xE3,
DVD_SELECT_GAME = 0x23,
DVD_GET_GAMECOUNT = 0x24,
DVD_EJECT_DISC = 0x27,
DVD_INSERT_DISC = 0x28,
DVD_READ_GAMEINFO = 0x30,
};
enum GameRegion
{
JAP=0,
USA,
EUR,
KOR,
ASN,
LTN,
};
#define DI_BASE 0x00002F00
#define DI_STATUS (DI_BASE+0x00)
#define DI_COVER (DI_BASE+0x04)
#define DI_CMD_0 (DI_BASE+0x08)
#define DI_CMD_1 (DI_BASE+0x0C)
#define DI_CMD_2 (DI_BASE+0x10)
#define DI_DMA_ADR (DI_BASE+0x14)
#define DI_DMA_LEN (DI_BASE+0x18)
#define DI_CONTROL (DI_BASE+0x1C)
#define DI_IMM (DI_BASE+0x20)
#define DI_CONFIG (DI_BASE+0x24)
#define DI_SHADOW (DI_BASE + 0x30)
#define DI_SSTATUS (DI_SHADOW+0x00)
#define DI_SCOVER (DI_SHADOW+0x04)
#define DI_SCMD_0 (DI_SHADOW+0x08)
#define DI_SCMD_1 (DI_SHADOW+0x0C)
#define DI_SCMD_2 (DI_SHADOW+0x10)
#define DI_SDMA_ADR (DI_SHADOW+0x14)
#define DI_SDMA_LEN (DI_SHADOW+0x18)
#define DI_SCONTROL (DI_SHADOW+0x1C)
#define DI_SIMM (DI_SHADOW+0x20)
#define DI_SCONFIG (DI_SHADOW+0x24)
typedef struct
{
union
{
struct
{
u32 Type :8;
u32 NameOffset :24;
};
u32 TypeName;
};
union
{
struct // File Entry
{
u32 FileOffset;
u32 FileLength;
};
struct // Dir Entry
{
u32 ParentOffset;
u32 NextOffset;
};
u32 entry[2];
};
} FEntry;
typedef struct
{
u32 Offset;
u32 Size;
FIL File;
} FileCache;
#define FILECACHE_MAX 1
typedef struct
{
u8 *data;
u32 len;
} vector;
typedef struct
{
u32 TMDSize;
u32 TMDOffset;
u32 CertChainSize;
u32 CertChainOffset;
u32 H3TableOffset;
u32 DataOffset;
u32 DataSize;
} PartitionInfo;
void DIInit( void );
u32 DIUpdateRegisters( void );
#endif

102
diskio.c Normal file
View File

@ -0,0 +1,102 @@
#include "diskio.h"
#include "string.h"
#include "memory.h"
extern u32 IsInit;
DSTATUS disk_initialize( BYTE drv )
{
s32 r, s_cnt;
u32 s_size;
while( 1 )
{
udelay( 50000 );
tiny_ehci_init();
int ret = -ENODEV;
do {
udelay( 4000 );
ret = ehci_discover();
} while( ret == -ENODEV );
dbgprintf("ehci_discover():%d\n", ret );
r = USBStorage_Init();
if( r == 0 )
break;
}
s_cnt = USBStorage_Get_Capacity( &s_size );
dbgprintf( "DIP: Drive size: %dMB SectorSize:%d\n", s_cnt / 1024 * s_size / 1024, s_size);
return r;
}
DSTATUS disk_status( BYTE drv )
{
(void)drv;
return 0;
}
DRESULT disk_read( BYTE drv, BYTE *buff, DWORD sector, BYTE count )
{
u8 *buffer = (u8*)buff;
//dbgprintf("disk_read( %d, %d, %p, %p)\n", sector, count, buff, buffer );
if( (u32)buff & 0xF0000000 )
{
buffer = (u8*)0x1000;
u32 i=0;
u32 Blocks = 3;
while(1)
{
if( (count-i) < Blocks )
Blocks = (count-i);
USBStorage_Read_Sectors( sector + i, Blocks, buffer );
memcpy( buff + i * 512, buffer, Blocks * 512 );
i+=Blocks;
if( i >= count )
break;
}
} else {
USBStorage_Read_Sectors( sector, count, buffer );
dc_flushrange( buffer, count*512 );
ahb_flush_from( AHB_SDHC );
}
return RES_OK;
}
// Write Sector(s)
DRESULT disk_write( BYTE drv, const BYTE *buff, DWORD sector, BYTE count )
{
u8 *buffer = (u8*)buff;
if( (u32)buff & 0xF0000000 )
{
buffer = (u8*)0x1000;
u32 i;
for( i=0; i < count; ++i )
{
memcpy( buffer, (void*)buff + i * 512, 512 );
USBStorage_Write_Sectors( sector + i, 1, buffer );
}
} else {
ahb_flush_to( AHB_SDHC );
USBStorage_Write_Sectors( sector, count, buffer );
}
return RES_OK;
}

70
diskio.h Normal file
View File

@ -0,0 +1,70 @@
/*-----------------------------------------------------------------------
/ Low level disk interface modlue include file R0.07 (C)ChaN, 2009
/-----------------------------------------------------------------------
/ FatFs module is an open source project to implement FAT file system to small
/ embedded systems. It is opened for education, research and development under
/ license policy of following trems.
/
/ Copyright (C) 2009, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is no warranty.
/ * You can use, modify and/or redistribute it for personal, non-profit or
/ commercial use without any restriction under your responsibility.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/
// original source: http://elm-chan.org/fsw/ff/00index_e.html
#ifndef _DISKIO
#define _READONLY 0 /* 1: Read-only mode */
#define _USE_IOCTL 1
#include "integer.h"
#include "string.h"
#include "ehci.h"
#include "alloc.h"
#include "tiny_ehci_glue.h"
#include "dip.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
#if _READONLY == 0
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
#endif
#if _USE_IOCTL == 1
DRESULT disk_ioctl (BYTE, BYTE, void*);
#endif
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
#if _USE_IOCTL == 1
/* Command code for disk_ioctl() */
#define CTRL_SYNC 0 /* Mandatory for write functions */
#endif
#define _DISKIO
#endif

16
dol.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _DOL_
#define _DOL_
typedef struct {
unsigned int offsetText[7];
unsigned int offsetData[11];
unsigned int addressText[7];
unsigned int addressData[11];
unsigned int sizeText[7];
unsigned int sizeData[11];
unsigned int addressBSS;
unsigned int sizeBSS;
unsigned int entrypoint;
} dolhdr;
#endif

78
ehci-mem.c Normal file
View File

@ -0,0 +1,78 @@
/*
* Original Copyright (c) 2001 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* this file is part of ehci.c */
static inline void ehci_qtd_init(struct ehci_qtd *qtd
)
{
dma_addr_t dma = ehci_virt_to_dma(qtd);
memset (qtd, 0, sizeof *qtd);
qtd->qtd_dma = dma;
qtd->hw_token = (QTD_STS_HALT);
qtd->hw_next = EHCI_LIST_END();
qtd->hw_alt_next = EHCI_LIST_END();
}
static inline struct ehci_qtd * ehci_qtd_alloc(void)
{
struct ehci_qtd *qtd ;
//debug_printf("ehci_qtd used=%x\n",ehci->qtd_used);
BUG_ON(ehci->qtd_used>=EHCI_MAX_QTD);
qtd = ehci->qtds[ehci->qtd_used++];
ehci_qtd_init(qtd);
return qtd;
}
int ehci_mem_init (void)
{
int i;
u32 ptr = 0x1800000 - DEFAULT_I_TDPS * sizeof(__le32);
ehci->periodic = (u32*)ptr;
ehci->periodic_dma = ehci_virt_to_dma(ehci->periodic);
for (i = 0; i < DEFAULT_I_TDPS; i++)
ehci->periodic[i] = EHCI_LIST_END();
ehci_writel( ehci->periodic_dma, &ehci->regs->frame_list );
for(i=0;i<EHCI_MAX_QTD;i++)
{
ptr -= sizeof(struct ehci_qtd);
ehci->qtds[i] = (struct ehci_qtd*)(ptr);
}
ehci->qtd_used = 0;
ptr -= sizeof(struct ehci_qh);
ehci->asyncqh = (struct ehci_qh*)ptr;
ehci->asyncqh->ehci = ehci;
ehci->asyncqh->qh_dma = ehci_virt_to_dma(ehci->asyncqh);
ehci->asyncqh->qtd_head = NULL;
ptr -= sizeof(struct ehci_qh);
ehci->async = (struct ehci_qh*)ptr;
ehci->async->ehci = ehci;
ehci->async->qh_dma = ehci_virt_to_dma(ehci->async);
ehci->async->qtd_head = NULL;
return 0;
}

832
ehci.c Normal file
View File

@ -0,0 +1,832 @@
/* simplest usb-ehci driver which features:
control and bulk transfers only
only one transfer pending
driver is synchronous (waiting for the end of the transfer)
endianess independant
no uncached memory allocation needed
this driver is originally based on the GPL linux ehci-hcd driver
* Original Copyright (c) 2001 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* magic numbers that can affect system performance */
u32 IsInit = 0;
#undef DEBUG
#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
#define EHCI_TUNE_RL_TT 0
#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
#define EHCI_TUNE_MULT_TT 1
#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */
extern int verbose;
static void
dbg_qtd (const char *label, struct ehci_qtd *qtd)
{
//ehci_dbg( "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
// hc32_to_cpup( &qtd->hw_next),
// hc32_to_cpup( &qtd->hw_alt_next),
// hc32_to_cpup( &qtd->hw_token),
// hc32_to_cpup( &qtd->hw_buf [0]));
//if (qtd->hw_buf [1])
// ehci_dbg( " p1=%08x p2=%08x p3=%08x p4=%08x\n",
// hc32_to_cpup( &qtd->hw_buf[1]),
// hc32_to_cpup( &qtd->hw_buf[2]),
// hc32_to_cpup( &qtd->hw_buf[3]),
// hc32_to_cpup( &qtd->hw_buf[4]));
}
static void
dbg_qh (const char *label, struct ehci_qh *qh)
{
//ehci_dbg ( "%s qh %p n%08x info %x %x qtd %x\n", label,
// qh,
// hc32_to_cpu(qh->hw_next),
// hc32_to_cpu(qh->hw_info1),
// hc32_to_cpu(qh->hw_info2),
// hc32_to_cpu(qh->hw_current));
//dbg_qtd ("overlay", (struct ehci_qtd *) &qh->hw_qtd_next);
}
static void
dbg_command (void)
{
#ifdef DEBUG
u32 command=ehci_readl( &ehci->regs->command);
u32 async=ehci_readl( &ehci->regs->async_next);
ehci_dbg ("async_next: %08x\n",async);
ehci_dbg (
"command %06x %s=%d ithresh=%d%s%s%s%s %s %s\n",
command,
(command & CMD_PARK) ? "park" : "(park)",
CMD_PARK_CNT (command),
(command >> 16) & 0x3f,
(command & CMD_LRESET) ? " LReset" : "",
(command & CMD_IAAD) ? " IAAD" : "",
(command & CMD_ASE) ? " Async" : "",
(command & CMD_PSE) ? " Periodic" : "",
(command & CMD_RESET) ? " Reset" : "",
(command & CMD_RUN) ? "RUN" : "HALT"
);
#endif
}
static void
dbg_status (void)
{
#ifdef DEBUG
u32 status=ehci_readl( &ehci->regs->status);
ehci_dbg (
"status %04x%s%s%s%s%s%s%s%s%s%s\n",
status,
(status & STS_ASS) ? " Async" : "",
(status & STS_PSS) ? " Periodic" : "",
(status & STS_RECL) ? " Recl" : "",
(status & STS_HALT) ? " Halt" : "",
(status & STS_IAA) ? " IAA" : "",
(status & STS_FATAL) ? " FATAL" : "",
(status & STS_FLR) ? " FLR" : "",
(status & STS_PCD) ? " PCD" : "",
(status & STS_ERR) ? " ERR" : "",
(status & STS_INT) ? " INT" : ""
);
#endif
}
void debug_qtds(void)
{
//struct ehci_qh *qh = ehci->async;
//struct ehci_qtd *qtd;
//dbg_qh ("qh",qh);
//dbg_command ();
//dbg_status ();
//for(qtd = qh->qtd_head; qtd; qtd = qtd->next)
//{
// ehci_dma_unmap_bidir(qtd->qtd_dma,sizeof(struct ehci_qtd));
// dbg_qtd("qtd",qtd);
// ehci_dma_map_bidir(qtd,sizeof(struct ehci_qtd));
//}
}
void dump_qh(struct ehci_qh *qh)
{
//struct ehci_qtd *qtd;
//dbg_command ();
//dbg_status ();
//ehci_dma_unmap_bidir(qh->qh_dma,sizeof(struct ehci_qh));
//dbg_qh("qh",qh);
//print_hex_dump_bytes("qh:",DUMP_PREFIX_OFFSET,(void*)qh,12*4);
//for(qtd = qh->qtd_head; qtd; qtd = qtd->next){
// u32 *buf;
// ehci_dma_unmap_bidir(qtd->qtd_dma,sizeof(struct ehci_qtd));
// dbg_qtd("qtd",qtd);
// print_hex_dump_bytes("qtd:",DUMP_PREFIX_OFFSET,(void*)qtd,8*4);
// buf = (u32*)hc32_to_cpu(qtd->hw_buf[0]);
// if(buf)
// print_hex_dump_bytes("qtd buf:",DUMP_PREFIX_OFFSET,(void*)(buf),8*4);
//}
}
/*-------------------------------------------------------------------------*/
/*
* handshake - spin reading hc until handshake completes or fails
* @ptr: address of hc register to be read
* @mask: bits to look at in result of read
* @done: value of those bits when handshake succeeds
* @usec: timeout in microseconds
*
* Returns negative errno, or zero on success
*
* Success happens when the "mask" bits have the specified value (hardware
* handshake done). There are two failure modes: "usec" have passed (major
* hardware flakeout), or the register reads as all-ones (hardware removed).
*
* That last failure should_only happen in cases like physical cardbus eject
* before driver shutdown. But it also seems to be caused by bugs in cardbus
* bridge shutdown: shutting down the bridge before the devices using it.
*/
static int handshake (void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result;
do {
result = ehci_readl( ptr);
if (result == ~(u32)0) /* card removed */
return -ENODEV;
result &= mask;
if (result == done)
return 0;
udelay(1);
usec--;
} while (usec > 0);
ehci_dbg("EHCI:handshake timeout!!\n");
dump_qh(ehci->async);
dump_qh(ehci->asyncqh);
//BUG();
return -ETIMEDOUT;
}
#include "ehci-mem.c"
/* one-time init, only for memory state */
static int ehci_init(void)
{
int retval;
if( (retval = ehci_mem_init()) < 0 )
return retval;
/*
* dedicate a qh for the async ring head, since we couldn't unlink
* a 'real' qh without stopping the async schedule [4.8]. use it
* as the 'reclamation list head' too.
* its dummy is used in hw_alt_next of many tds, to prevent the qh
* from automatically advancing to the next td after short reads.
*/
ehci->async->hw_next = QH_NEXT( ehci->async->qh_dma);
ehci->async->hw_info1 = cpu_to_hc32( QH_HEAD);
ehci->async->hw_token = cpu_to_hc32( QTD_STS_HALT);
ehci->async->hw_qtd_next = EHCI_LIST_END();
ehci->async->hw_alt_next = EHCI_LIST_END();//QTD_NEXT( ehci->async->dummy->qtd_dma);
if( ehci->ctrl_buffer != NULL )
USB_Free( ehci->ctrl_buffer );
ehci->ctrl_buffer = USB_Alloc(sizeof(usbctrlrequest));
ehci->command = 0;
ehci_writel( 0x00800002, &ehci->regs->command);
ehci_writel( ehci->periodic_dma, &ehci->regs->frame_list);
ehci_writel( ehci->async->qh_dma, &ehci->regs->async_next);
ehci_writel( 0x00010009, &ehci->regs->command);
ehci_writel( 1, &ehci->regs->configured_flag);
ehci_writel( 0x00010029, &ehci->regs->command);
return 0;
}
/* fill a qtd, returning how much of the buffer we were able to queue up */
static int qtd_fill( struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token, int maxpacket)
{
int i, count;
u64 addr = buf;
//ehci_dbg("fill qtd with dma %X len %X\n",buf,len);
/* one buffer entry per 4K ... first might be short or unaligned */
qtd->hw_buf[0] = cpu_to_hc32( (u32)addr);
qtd->hw_buf_hi[0] = 0;
count = 0x1000 - (buf & 0x0fff); /* rest of that page */
if (likely (len < count)) /* ... iff needed */
count = len;
else {
buf += 0x1000;
buf &= ~0x0fff;
/* per-qtd limit: from 16K to 20K (best alignment) */
for (i = 1; count < len && i < 5; i++) {
addr = buf;
qtd->hw_buf[i] = cpu_to_hc32( (u32)addr);
qtd->hw_buf_hi[i] = cpu_to_hc32(
(u32)(addr >> 32));
buf += 0x1000;
if ((count + 0x1000) < len)
count += 0x1000;
else
count = len;
}
/* short packets may only terminate transfers */
if (count != len)
count -= (count % maxpacket);
}
qtd->hw_token = cpu_to_hc32( (count << 16) | token);
qtd->length = count;
return count;
}
// high bandwidth multiplier, as encoded in highspeed endpoint descriptors
#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
// ... and packet size, for any kind of endpoint descriptor
#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
/*
* reverse of qh_urb_transaction: free a list of TDs.
* also count the actual transfer length.
*
*/
static void qh_end_transfer (void)
{
struct ehci_qtd *qtd;
struct ehci_qh *qh = ehci->asyncqh;
u32 token;
int error = 0;
for(qtd = qh->qtd_head; qtd; qtd = qtd->next)
{
token = hc32_to_cpu( qtd->hw_token);
if (likely (QTD_PID (token) != 2))
qtd->urb->actual_length += qtd->length - QTD_LENGTH (token);
if (!(qtd->length ==0 && ((token & 0xff)==QTD_STS_HALT)) && (token & QTD_STS_HALT))
{
ehci_dbg("EHCI:qtd error!:");
if (token & QTD_STS_BABBLE)
{
/* FIXME "must" disable babbling device's port too */
ehci_dbg(" BABBLE");
}
if (token & QTD_STS_MMF)
{
/* fs/ls interrupt xfer missed the complete-split */
ehci_dbg(" missed micro frame");
}
if (token & QTD_STS_DBE)
{
ehci_dbg(" databuffer error");
}
if (token & QTD_STS_XACT)
{
ehci_dbg(" wrong ack");
}
if (QTD_CERR (token)==0)
ehci_dbg(" toomany errors");
ehci_dbg("\n");
error = -1;
}
}
if(error)
{
dump_qh(ehci->asyncqh);
qtd->urb->actual_length = error;
}
ehci->qtd_used = 0;
}
/*
* create a list of filled qtds for this URB; won't link into qh.
*/
struct ehci_qtd *qh_urb_transaction (
struct ehci_urb *urb
) {
struct ehci_qtd *qtd, *qtd_prev;
struct ehci_qtd *head;
dma_addr_t buf;
int len, maxpacket;
int is_input;
u32 token;
/*
* URBs map to sequences of QTDs: one logical transaction
*/
head = qtd = ehci_qtd_alloc ();
qtd->urb = urb;
urb->actual_length = 0;
token = QTD_STS_ACTIVE;
token |= (EHCI_TUNE_CERR << 10);
/* for split transactions, SplitXState initialized to zero */
len = urb->transfer_buffer_length;
is_input = urb->input;
if (urb->ep==0) {/* is control */
/* SETUP pid */
qtd_fill( qtd, urb->setup_dma, sizeof (usbctrlrequest), token | (2 /* "setup" */ << 8), 8);
/* ... and always at least one more pid */
token ^= QTD_TOGGLE;
qtd_prev = qtd;
qtd = ehci_qtd_alloc ();
qtd->urb = urb;
qtd_prev->hw_next = QTD_NEXT( qtd->qtd_dma);
qtd_prev->next = qtd;
/* for zero length DATA stages, STATUS is always IN */
if (len == 0)
token |= (1 /* "in" */ << 8);
}
/*
* data transfer stage: buffer setup
*/
buf = urb->transfer_dma;
if (is_input)
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
maxpacket = max_packet(urb->maxpacket);
/*
* buffer gets wrapped in one or more qtds;
* last one may be "short" (including zero len)
* and may serve as a control status ack
*/
for (;;) {
int this_qtd_len;
this_qtd_len = qtd_fill( qtd, buf, len, token, maxpacket);
len -= this_qtd_len;
buf += this_qtd_len;
/*
* short reads advance to a "magic" dummy instead of the next
* qtd ... that forces the queue to stop, for manual cleanup.
* (this will usually be overridden later.)
*/
if (is_input)
qtd->hw_alt_next = ehci->asyncqh->hw_alt_next;
/* qh makes control packets use qtd toggle; maybe switch it */
if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
token ^= QTD_TOGGLE;
if (likely (len <= 0))
break;
qtd_prev = qtd;
qtd = ehci_qtd_alloc ();
qtd->urb = urb;
qtd_prev->hw_next = QTD_NEXT( qtd->qtd_dma);
qtd_prev->next = qtd;
}
qtd->hw_alt_next = EHCI_LIST_END();
/*
* control requests may need a terminating data "status" ack;
* bulk ones may need a terminating short packet (zero length).
*/
if (likely (urb->transfer_buffer_length != 0)) {
int one_more = 0;
if (urb->ep==0) {
one_more = 1;
token ^= 0x0100; /* "in" <--> "out" */
token |= QTD_TOGGLE; /* force DATA1 */
} else if(!(urb->transfer_buffer_length % maxpacket)) {
//one_more = 1;
}
if (one_more) {
qtd_prev = qtd;
qtd = ehci_qtd_alloc ();
qtd->urb = urb;
qtd_prev->hw_next = QTD_NEXT( qtd->qtd_dma);
qtd_prev->next = qtd;
/* never any data in such packets */
qtd_fill( qtd, 0, 0, token, 0);
}
}
/* by default, enable interrupt on urb completion */
qtd->hw_token |= cpu_to_hc32( QTD_IOC);
return head;
}
int ehci_do_urb ( struct ehci_device *dev, struct ehci_urb *urb)
{
struct ehci_qh *qh;
struct ehci_qtd *qtd;
u32 info1 = 0, info2 = 0;
int is_input;
int maxp = 0;
int retval;
//ehci_dbg ("do urb %X %X ep %X\n",urb->setup_buffer,urb->transfer_buffer,urb->ep);
if(urb->ep==0) //control message
urb->setup_dma = ehci_dma_map_to(urb->setup_buffer,sizeof (usbctrlrequest));
if( urb->transfer_buffer_length )
{
if(urb->input)
urb->transfer_dma = ehci_dma_map_to( urb->transfer_buffer, urb->transfer_buffer_length );
else
urb->transfer_dma = ehci_dma_map_from( urb->transfer_buffer, urb->transfer_buffer_length );
}
qh = ehci->asyncqh;
memset(qh,0,12*4);
qtd = qh_urb_transaction( urb );
qh->qtd_head = qtd;
info1 |= ((urb->ep)&0xf)<<8;
info1 |= dev->id;
is_input = urb->input;
maxp = urb->maxpacket;
info1 |= (2 << 12); /* EPS "high" */
if(urb->ep==0)// control
{
info1 |= (EHCI_TUNE_RL_HS << 28);
info1 |= 64 << 16; /* usb2 fixed maxpacket */
info1 |= 1 << 14; /* toggle from qtd */
info2 |= (EHCI_TUNE_MULT_HS << 30);
} else {//bulk
info1 |= (EHCI_TUNE_RL_HS << 28);
/* The USB spec says that high speed bulk endpoints
* always use 512 byte maxpacket. But some device
* vendors decided to ignore that, and MSFT is happy
* to help them do so. So now people expect to use
* such nonconformant devices with Linux too; sigh.
*/
info1 |= max_packet(maxp) << 16;
info2 |= (EHCI_TUNE_MULT_HS << 30);
}
//ehci_dbg("HW info: %08X\n",info1);
qh->hw_info1 = cpu_to_hc32( info1);
qh->hw_info2 = cpu_to_hc32( info2);
qh->hw_next = QH_NEXT( qh->qh_dma );
qh->hw_qtd_next = QTD_NEXT( qtd->qtd_dma );
qh->hw_alt_next = EHCI_LIST_END();
if( urb->ep != 0 )
{
if( get_toggle( dev, urb->ep ) )
qh->hw_token |= cpu_to_hc32(QTD_TOGGLE);
else
qh->hw_token &= ~cpu_to_hc32(QTD_TOGGLE);
//ehci_dbg("toggle for ep %x: %d %x\n", urb->ep, get_toggle(dev,urb->ep), qh->hw_token );
}
qh->hw_token &= cpu_to_hc32( QTD_TOGGLE | QTD_STS_PING);
qh->hw_next = QH_NEXT(ehci->async->qh_dma);
ehci_dma_map_bidir(qh,sizeof(struct ehci_qh));
for(qtd = qh->qtd_head; qtd; qtd = qtd->next)
ehci_dma_map_bidir(qtd,sizeof(struct ehci_qtd));
// start (link qh)
ehci->async->hw_next = QH_NEXT(qh->qh_dma);
ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh));
retval = handshake(&ehci->regs->status,STS_INT,STS_INT,1000*1000);
//print_hex_dump_bytes ("qh mem",0,(void*)qh,17*4);
//retval = poll_transfer_end(1000*1000);
ehci_dma_unmap_bidir(ehci->async->qh_dma,sizeof(struct ehci_qh));
ehci_dma_unmap_bidir(qh->qh_dma,sizeof(struct ehci_qh));
for(qtd = qh->qtd_head; qtd; qtd = qtd->next)
ehci_dma_unmap_bidir(qtd->qtd_dma,sizeof(struct ehci_qtd));
// stop (unlink qh)
ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh));
ehci_dma_unmap_bidir(ehci->async->qh_dma,sizeof(struct ehci_qh));
// ack
ehci_writel( STS_RECL|STS_IAA|STS_INT, &ehci->regs->status);
if(urb->ep!=0)
{
set_toggle(dev,urb->ep,(qh->hw_token & cpu_to_hc32(QTD_TOGGLE))?1:0);
//ehci_dbg("toggle for ep %x: %d %d %x %X\n",urb->ep,get_toggle(dev,urb->ep),(qh->hw_token & cpu_to_hc32(QTD_TOGGLE)),qh->hw_token,dev->toggles);
}
if( retval >= 0 )
// wait hc really stopped
retval = handshake(&ehci->regs->async_next,~0,ehci->async->qh_dma,1*1000);
//release memory, and actualise urb->actual_length
qh_end_transfer();
if(urb->transfer_buffer_length)
{
if(urb->input)
ehci_dma_unmap_to(urb->transfer_dma,urb->transfer_buffer_length);
else
ehci_dma_unmap_from(urb->transfer_dma,urb->transfer_buffer_length);
}
if( urb->ep == 0 ) //control message
ehci_dma_unmap_to(urb->setup_dma,sizeof (usbctrlrequest));
if(retval==0)
{
return urb->actual_length;
}
ehci_dbg ( "EHCI:unsuccessfull urb %d!!\n", retval);
return retval;
}
s32 ehci_control_message(struct ehci_device *dev,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *buf)
{
struct ehci_urb urb;
int ret;
usbctrlrequest *req = (void*)0x17C0;
if( verbose )
ehci_dbg("control msg: rt%02X r%02X v%04X i%04X s%04x %p\n", bmRequestType, bmRequest, wValue, wIndex, wLength, buf );
u32 *_req = (u32*)req;
_req[0] = (bmRequestType<<24) | (bmRequest<<16) | swab16(wValue);
_req[1] = (swab16(wIndex) << 16) | swab16(wLength);
urb.setup_buffer = req;
urb.ep = 0;
urb.input = (bmRequestType&USB_CTRLTYPE_DIR_DEVICE2HOST)!=0;
urb.maxpacket = 64;
urb.transfer_buffer_length = wLength;
if( urb.transfer_buffer_length )
{
if( ((u32)buf >> 28 ) == 0xF )
{
urb.transfer_buffer = USB_Alloc( wLength );
//dbgprintf("memcpy(%p,%p,%u)\n", urb.transfer_buffer, buf, wLength );
memcpy( urb.transfer_buffer, buf, wLength );
ret = ehci_do_urb( dev, &urb );
memcpy( buf, urb.transfer_buffer, wLength );
USB_Free( urb.transfer_buffer );
} else {
urb.transfer_buffer = buf;
ret = ehci_do_urb( dev, &urb );
}
//hexdump( buf, wLength > 0x20 ? 0x20 : wLength );
} else {
urb.transfer_buffer = NULL;
ret = ehci_do_urb( dev, &urb );
}
return ret;
}
s32 ehci_bulk_message(struct ehci_device *dev,u8 bEndpoint,u16 wLength,void *rpData)
{
struct ehci_urb urb;
s32 ret;
urb.setup_buffer = NULL;
urb.ep = bEndpoint;
urb.input = (bEndpoint&0x80)!=0;
urb.maxpacket = 512;
urb.transfer_buffer_length = wLength;
urb.transfer_buffer = rpData;
if (verbose)
ehci_dbg ( "bulk msg: ep:%02X size:%02X addr:%04X\n", bEndpoint, wLength, urb.transfer_buffer );
// hexdump( urb.transfer_buffer, urb.transfer_buffer_length );
if( ((u32)rpData >> 28) == 0xF )
{
memcpy( (void*)0xFE0, rpData, wLength );
urb.transfer_buffer = (u8*)0xFE0;
ret = ehci_do_urb( dev, &urb );
memcpy( rpData, (void*)0xFE0, wLength );
} else {
ret = ehci_do_urb( dev, &urb );
}
// hexdump( urb.transfer_buffer, urb.transfer_buffer_length );
if (verbose)
ehci_dbg ( "==>%d\n", ret);
return ret;
}
int ehci_reset_port(int port)
{
u32 __iomem *status_reg = &ehci->regs->port_status[port];
struct ehci_device *dev = &ehci->devices[port];
u32 status = ehci_readl(status_reg);
int retval = 0;
dev->id = 0;
if( (PORT_OWNER&status) || !(PORT_CONNECT&status) )
{
int retries = 10;
while( !(PORT_CONNECT&status) && retries > 0 )
{
msleep(1000); // sleep 1 second
status = ehci_readl(status_reg);
ehci_dbg ( "EHCI:port %d status at retry %d %X \n", port,retries,status);
retries--;
}
if( retries <= 0 )
{
ehci_writel( PORT_OWNER, status_reg );
ehci_dbg ( "EHCI:port %d had no usb2 device connected at startup %X \n", port,ehci_readl(status_reg) );
return -ENODEV;// no USB2 device connected
}
}
ehci_dbg ( "EHCI:port %d has usb2 device connected! reset it...\n", port);
if( PORT_USB11(ehci_readl(status_reg)) )
{
ehci_dbg("EHCI:Device is USB1.1\n");
}
status = ehci_readl(status_reg);
status|= PORT_RESET;
ehci_writel( status, status_reg );
msleep(50); // wait 50ms for the reset sequence
status = ehci_readl(status_reg);
status ^= PORT_RESET;
ehci_writel( status, status_reg );
retval = handshake( status_reg, PORT_RESET, 0, 2000 );
if(retval != 0)
{
ehci_dbg ( "EHCI:port %d reset error %d\n", port, retval);
return retval;
}
ehci_dbg ( "EHCI:port %d reseted status:%04x...\n", port,ehci_readl(status_reg));
msleep(100);
// now the device has the default device id
retval = ehci_control_message( dev, USB_CTRLTYPE_DIR_DEVICE2HOST, USB_REQ_GETDESCRIPTOR, USB_DT_DEVICE<<8, 0, sizeof(dev->desc), &dev->desc );
if (retval < 0)
{
ehci_dbg("EHCI:unable to get device desc...\n");
return retval;
}
retval = ehci_control_message( dev, USB_CTRLTYPE_DIR_HOST2DEVICE, USB_REQ_SETADDRESS,port+1,0,0,0);
if (retval < 0)
{
ehci_dbg("EHCI:unable to set device addr...\n");
return retval;
}
dev->toggles = 0;
dev->id = port+1;
ehci_dbg ( "EHCI:device %d: %X %X...\n", dev->id,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct));
return retval;
}
int ehci_reset_device(struct ehci_device *dev)
{
return ehci_reset_port(dev->port);
}
#include "usbstorage.h"
int ehci_discover(void)
{
int i;
int ret = 0 ;
// precondition: the ehci should be halted
for(i = 0;i<ehci->num_port; i++)
{
struct ehci_device *dev = &ehci->devices[i];
dev->port = i;
ret = ehci_reset_port(i);
if( ret != -ENODEV )
break;
}
return ret;
}
/* wii: quickly release non ehci or not connected ports,
as we can't kick OHCI drivers laters if we discover a device for them.
*/
int ehci_release_ports(void)
{
int i;
u32 __iomem *status_reg = &ehci->regs->port_status[2];
while(ehci_readl(&ehci->regs->port_status[2]) == 0x1000);// wait port 2 to init
msleep(1);// wait another msec..
for(i = 0;i<ehci->num_port; i++){
status_reg = &ehci->regs->port_status[i];
u32 status = ehci_readl(status_reg);
if (i==2 || !(PORT_CONNECT&status) || PORT_USB11(status))
ehci_writel( PORT_OWNER,status_reg); // release port.
}
return 0;
}
int ehci_open_device(int vid,int pid,int fd)
{
int i;
for(i=0;i<ehci->num_port;i++)
{
ehci_dbg("try device: %d\n",i);
if(ehci->devices[i].fd == 0 &&
le16_to_cpu(ehci->devices[i].desc.idVendor) == vid &&
le16_to_cpu(ehci->devices[i].desc.idProduct) == pid)
{
ehci_dbg("found device: %x %x\n",vid,pid);
ehci->devices[i].fd = fd;
return fd;
}
}
return -6;
}
int ehci_close_device(struct ehci_device *dev)
{
if (dev)
dev->fd = 0;
return 0;
}
void * ehci_fd_to_dev(int fd)
{
int i;
for(i=0;i<ehci->num_port;i++)
{
struct ehci_device *dev = &ehci->devices[i];
ehci_dbg ( "EHCI:device %d:fd:%d %X %X...\n", dev->id,dev->fd,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct));
if(dev->fd == fd){
return dev;
}
}
ehci_dbg("unkown fd! %d\n",fd);
return 0;
}
#define g_ehci #error
int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf)
{
int i,j = 0;
for(i=0;i<ehci->num_port && j<maxdev ;i++)
{
struct ehci_device *dev = &ehci->devices[i];
if(dev->id != 0){
ehci_dbg ( "EHCI:device %d: %X %X...\n", dev->id,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct));
buf[j*4] = 0;
buf[j*4+1] = 0;
buf[j*4+2] = le16_to_cpu(dev->desc.idVendor);
buf[j*4+3] = le16_to_cpu(dev->desc.idProduct);
j++;
}
}
ehci_dbg("EHCI:found %d devices\n",j);
*num = j;
return 0;
}
#include "usb.c"
#include "usbstorage.c"

282
ehci.h Normal file
View File

@ -0,0 +1,282 @@
/*
* Copyright (c) 2009 Kwiirk
* Original Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ehci_types.h"
#ifndef __LINUX_EHCI_HCD_H
#define __LINUX_EHCI_HCD_H
/* definitions used for the EHCI driver */
/*
* __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
* __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on
* the host controller implementation.
*
* To facilitate the strongest possible byte-order checking from "sparse"
* and so on, we use __leXX unless that's not practical.
*/
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
typedef __u32 __bitwise __hc32;
typedef __u16 __bitwise __hc16;
#else
#define __hc32 __le32
#define __hc16 __le16
#endif
#define EHCI_MAX_ROOT_PORTS 4 /* see HCS_N_PORTS */
#define EHCI_MAX_QTD 8
#include "usb.h"
struct ehci_device{
usb_devdesc desc;
int id;
int port;
int fd;
u32 toggles;
};
#define ep_bit(ep) (((ep)&0xf)+(((ep)>>7)?16:0))
#define get_toggle(dev,ep) (((dev)->toggles>>ep_bit(ep))&1)
#define set_toggle(dev,ep,v) (dev)->toggles = ((dev)->toggles &(~(1<<ep_bit(ep)))) | ((v)<<ep_bit(ep))
struct ehci_urb{
void* setup_buffer;
dma_addr_t setup_dma;
void* transfer_buffer;
dma_addr_t transfer_dma;
u32 transfer_buffer_length;
u32 actual_length;
u8 ep;
u8 input;
u32 maxpacket;
};
struct ehci_hcd { /* one per controller */
/* glue to PCI and HCD framework */
void __iomem *_regs;
struct ehci_caps __iomem *caps;
struct ehci_regs __iomem *regs;
struct ehci_dbg_port __iomem *debug;
void *device;
__u32 hcs_params; /* cached register copy */
/* async schedule support */
struct ehci_qh *async; // the head never gets a qtd inside.
struct ehci_qh *asyncqh;
struct ehci_qtd *qtds[EHCI_MAX_QTD];
int qtd_used;
unsigned long next_statechange;
u32 command;
/* HW need periodic table initialised even if we dont use it @todo:is it really true? */
#define DEFAULT_I_TDPS 1024 /* some HCs can do less */
__hc32 *periodic; /* hw periodic table */
dma_addr_t periodic_dma;
u8 num_port;
struct ehci_device devices[EHCI_MAX_ROOT_PORTS]; /* the attached device list per port */
void *ctrl_buffer; /* pre allocated buffer for control messages */
};
/*-------------------------------------------------------------------------*/
#include "ehci_defs.h"
/*-------------------------------------------------------------------------*/
#define QTD_NEXT( dma) cpu_to_hc32( (u32)dma)
/*
* EHCI Specification 0.95 Section 3.5
* QTD: describe data transfer components (buffer, direction, ...)
* See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
*
* These are associated only with "QH" (Queue Head) structures,
* used with control, bulk, and interrupt transfers.
*/
struct ehci_qtd {
/* first part defined by EHCI spec */
__hc32 hw_next; /* see EHCI 3.5.1 */
__hc32 hw_alt_next; /* see EHCI 3.5.2 */
__hc32 hw_token; /* see EHCI 3.5.3 */
#define QTD_TOGGLE (1 << 31) /* data toggle */
#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
#define QTD_IOC (1 << 15) /* interrupt on complete */
#define QTD_CERR(tok) (((tok)>>10) & 0x3)
#define QTD_PID(tok) (((tok)>>8) & 0x3)
#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */
#define QTD_STS_HALT (1 << 6) /* halted on error */
#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */
#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */
#define QTD_STS_XACT (1 << 3) /* device gave illegal response */
#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */
#define QTD_STS_STS (1 << 1) /* split transaction state */
#define QTD_STS_PING (1 << 0) /* issue PING? */
#define ACTIVE_BIT(ehci) cpu_to_hc32( QTD_STS_ACTIVE)
#define HALT_BIT(ehci) cpu_to_hc32( QTD_STS_HALT)
#define STATUS_BIT(ehci) cpu_to_hc32( QTD_STS_STS)
__hc32 hw_buf [5]; /* see EHCI 3.5.4 */
__hc32 hw_buf_hi [5]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t qtd_dma; /* qtd address */
struct ehci_qtd *next; /* sw qtd list */
struct ehci_urb *urb; /* qtd's urb */
size_t length; /* length of buffer */
} __attribute__ ((aligned (32)));
/* mask NakCnt+T in qh->hw_alt_next */
#define QTD_MASK(ehci) cpu_to_hc32 ( ~0x1f)
#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
/*-------------------------------------------------------------------------*/
/* type tag from {qh,itd,sitd,fstn}->hw_next */
#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_hc32( 3 << 1))
/*
* Now the following defines are not converted using the
* __constant_cpu_to_le32() macro anymore, since we have to support
* "dynamic" switching between be and le support, so that the driver
* can be used on one system with SoC EHCI controller using big-endian
* descriptors as well as a normal little-endian PCI EHCI controller.
*/
/* values for that type tag */
#define Q_TYPE_ITD (0 << 1)
#define Q_TYPE_QH (1 << 1)
#define Q_TYPE_SITD (2 << 1)
#define Q_TYPE_FSTN (3 << 1)
/* next async queue entry, or pointer to interrupt/periodic QH */
#define QH_NEXT(dma) (cpu_to_hc32( (((u32)dma)&~0x01f)|Q_TYPE_QH))
/* for periodic/async schedules and qtd lists, mark end of list */
#define EHCI_LIST_END() cpu_to_hc32( 1) /* "null pointer" to hw */
/*
* Entries in periodic shadow table are pointers to one of four kinds
* of data structure. That's dictated by the hardware; a type tag is
* encoded in the low bits of the hardware's periodic schedule. Use
* Q_NEXT_TYPE to get the tag.
*
* For entries in the async schedule, the type tag always says "qh".
*/
union ehci_shadow {
struct ehci_qh *qh; /* Q_TYPE_QH */
struct ehci_itd *itd; /* Q_TYPE_ITD */
struct ehci_sitd *sitd; /* Q_TYPE_SITD */
struct ehci_fstn *fstn; /* Q_TYPE_FSTN */
__hc32 *hw_next; /* (all types) */
void *ptr;
};
/*-------------------------------------------------------------------------*/
/*
* EHCI Specification 0.95 Section 3.6
* QH: describes control/bulk/interrupt endpoints
* See Fig 3-7 "Queue Head Structure Layout".
*
* These appear in both the async and (for interrupt) periodic schedules.
*/
struct ehci_qh {
/* first part defined by EHCI spec */
__hc32 hw_next; /* see EHCI 3.6.1 */
__hc32 hw_info1; /* see EHCI 3.6.2 */
#define QH_HEAD 0x00008000
__hc32 hw_info2; /* see EHCI 3.6.2 */
#define QH_SMASK 0x000000ff
#define QH_CMASK 0x0000ff00
#define QH_HUBADDR 0x007f0000
#define QH_HUBPORT 0x3f800000
#define QH_MULT 0xc0000000
__hc32 hw_current; /* qtd list - see EHCI 3.6.4 */
/* qtd overlay (hardware parts of a struct ehci_qtd) */
__hc32 hw_qtd_next;
__hc32 hw_alt_next;
__hc32 hw_token;
__hc32 hw_buf [5];
__hc32 hw_buf_hi [5];
/* the rest is HCD-private */
dma_addr_t qh_dma; /* address of qh */
struct ehci_qtd *qtd_head; /* sw qtd list */
struct ehci_hcd *ehci;
#define NO_FRAME ((unsigned short)~0) /* pick new start */
} __attribute__ ((aligned (32)));
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/* cpu to ehci */
#define cpu_to_hc32(b) cpu_to_le32(b)
#define hc32_to_cpu(b) le32_to_cpu(b)
#define hc32_to_cpup(b) le32_to_cpu(*(b))
/*-------------------------------------------------------------------------*/
/* os specific functions */
void*ehci_maligned(int size,int alignement,int crossing);
dma_addr_t ehci_virt_to_dma(void *);
dma_addr_t ehci_dma_map_to(void *buf,size_t len);
dma_addr_t ehci_dma_map_from(void *buf,size_t len);
dma_addr_t ehci_dma_map_bidir(void *buf,size_t len);
void ehci_dma_unmap_to(dma_addr_t buf,size_t len);
void ehci_dma_unmap_from(dma_addr_t buf,size_t len);
void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len);
/* extern API */
s32 ehci_control_message(struct ehci_device *dev,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *buf);
s32 ehci_bulk_message(struct ehci_device *dev,u8 bEndpoint,u16 wLength,void *rpData);
int ehci_discover(void);
int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf);
extern struct ehci_hcd *ehci; /* @todo put ehci as a static global and remove ehci from APIs.. */
extern int ehci_open_device(int vid,int pid,int fd);
extern int ehci_close_device(struct ehci_device *dev);
extern void * ehci_fd_to_dev(int fd);
extern int ehci_release_ports(void);
/* UMS API */
s32 USBStorage_Init(void);
s32 USBStorage_Get_Capacity(u32*sector_size);
s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer);
s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer);
s32 USBStorage_Write_Sectors(u32 sector, u32 numSectors, const void *buffer);
#ifndef DEBUG
#define STUB_DEBUG_FILES
#endif /* DEBUG */
/*-------------------------------------------------------------------------*/
#endif /* __LINUX_EHCI_HCD_H */

160
ehci_defs.h Normal file
View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __LINUX_USB_EHCI_DEF_H
#define __LINUX_USB_EHCI_DEF_H
/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
/* Section 2.2 Host Controller Capability Registers */
struct ehci_caps {
/* these fields are specified as 8 and 16 bit registers,
* but some hosts can't perform 8 or 16 bit PCI accesses.
*/
u32 hc_capbase;
#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */
#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */
u32 hcs_params; /* HCSPARAMS - offset 0x4 */
#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */
#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */
#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */
#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */
#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */
#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */
#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */
u32 hcc_params; /* HCCPARAMS - offset 0x8 */
#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */
#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */
#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */
#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */
#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/
#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */
u8 portroute [8]; /* nibbles for routing - offset 0xC */
} __attribute__ ((packed));
/* Section 2.3 Host Controller Operational Registers */
struct ehci_regs {
/* USBCMD: offset 0x00 */
u32 command;
/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
#define CMD_PARK (1<<11) /* enable "park" on async qh */
#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */
#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */
#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */
#define CMD_ASE (1<<5) /* async schedule enable */
#define CMD_PSE (1<<4) /* periodic schedule enable */
/* 3:2 is periodic frame list size */
#define CMD_RESET (1<<1) /* reset HC not bus */
#define CMD_RUN (1<<0) /* start/stop HC */
/* USBSTS: offset 0x04 */
u32 status;
#define STS_ASS (1<<15) /* Async Schedule Status */
#define STS_PSS (1<<14) /* Periodic Schedule Status */
#define STS_RECL (1<<13) /* Reclamation */
#define STS_HALT (1<<12) /* Not running (any reason) */
/* some bits reserved */
/* these STS_* flags are also intr_enable bits (USBINTR) */
#define STS_IAA (1<<5) /* Interrupted on async advance */
#define STS_FATAL (1<<4) /* such as some PCI access errors */
#define STS_FLR (1<<3) /* frame list rolled over */
#define STS_PCD (1<<2) /* port change detect */
#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
#define STS_INT (1<<0) /* "normal" completion (short, ...) */
/* USBINTR: offset 0x08 */
u32 intr_enable;
/* FRINDEX: offset 0x0C */
u32 frame_index; /* current microframe number */
/* CTRLDSSEGMENT: offset 0x10 */
u32 segment; /* address bits 63:32 if needed */
/* PERIODICLISTBASE: offset 0x14 */
u32 frame_list; /* points to periodic list */
/* ASYNCLISTADDR: offset 0x18 */
u32 async_next; /* address of next async queue head */
u32 reserved [9];
/* CONFIGFLAG: offset 0x40 */
u32 configured_flag;
#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
/* PORTSC: offset 0x44 */
u32 port_status [0]; /* up to N_PORTS */
/* 31:23 reserved */
#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */
#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */
#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */
/* 19:16 for port testing */
#define PORT_LED_OFF (0<<14)
#define PORT_LED_AMBER (1<<14)
#define PORT_LED_GREEN (2<<14)
#define PORT_LED_MASK (3<<14)
#define PORT_OWNER (1<<13) /* true: companion hc owns this port */
#define PORT_POWER (1<<12) /* true: has power (see PPC) */
#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */
/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
/* 9 reserved */
#define PORT_RESET (1<<8) /* reset port */
#define PORT_SUSPEND (1<<7) /* suspend port */
#define PORT_RESUME (1<<6) /* resume it */
#define PORT_OCC (1<<5) /* over current change */
#define PORT_OC (1<<4) /* over current active */
#define PORT_PEC (1<<3) /* port enable change */
#define PORT_PE (1<<2) /* port enable */
#define PORT_CSC (1<<1) /* connect status change */
#define PORT_CONNECT (1<<0) /* device connected */
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
} __attribute__ ((packed));
#define USBMODE 0x68 /* USB Device mode */
#define USBMODE_SDIS (1<<3) /* Stream disable */
#define USBMODE_BE (1<<2) /* BE/LE endianness select */
#define USBMODE_CM_HC (3<<0) /* host controller mode */
#define USBMODE_CM_IDLE (0<<0) /* idle state */
/* Appendix C, Debug port ... intended for use with special "debug devices"
* that can help if there's no serial console. (nonstandard enumeration.)
*/
struct ehci_dbg_port {
u32 control;
#define DBGP_OWNER (1<<30)
#define DBGP_ENABLED (1<<28)
#define DBGP_DONE (1<<16)
#define DBGP_INUSE (1<<10)
#define DBGP_ERRCODE(x) (((x)>>7)&0x07)
# define DBGP_ERR_BAD 1
# define DBGP_ERR_SIGNAL 2
#define DBGP_ERROR (1<<6)
#define DBGP_GO (1<<5)
#define DBGP_OUT (1<<4)
#define DBGP_LEN(x) (((x)>>0)&0x0f)
u32 pids;
#define DBGP_PID_GET(x) (((x)>>16)&0xff)
#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok))
u32 data03;
u32 data47;
u32 address;
#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep))
} __attribute__ ((packed));
#endif /* __LINUX_USB_EHCI_DEF_H */

55
ehci_types.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef __EHCI_TYPES_H__
#define __EHCI_TYPES_H__
#include "global.h"
/* linux kernel types needed by our code */
#define __iomem
typedef unsigned long uint32_t;
#if 0
typedef unsigned long u32;
typedef signed long s32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef char s8;
typedef unsigned long long u64;
#endif
#define __u32 u32
#define __le32 u32
#define dma_addr_t u32
#define __GNUG__
typedef u32 spinlock_t;
typedef enum
{
GFP_KERNEL=1
}gfp_t;
struct timer_list
{
int time;
};
enum{
ENODEV =1,
ETIMEDOUT,
EINVAL,
ENOMEM,
};
#define jiffies 0
#define likely(x) (x)
#define unlikely(x) (x)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif

74
elf.h Normal file
View File

@ -0,0 +1,74 @@
/*
preloader 0.30 - A tool which allows to change the default boot up sequence on the Wii console
Copyright (C) 2008-2009 crediar
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
unsigned short e_type;
unsigned short e_machine;
unsigned int e_version;
unsigned int e_entry;
unsigned int e_phoff;
unsigned int e_shoff;
unsigned int e_flags;
unsigned short e_ehsize;
unsigned short e_phentsize;
unsigned short e_phnum;
unsigned short e_shentsize;
unsigned short e_shnum;
unsigned short e_shstrndx;
} __attribute__((packed)) Elf32_Ehdr;
typedef struct {
unsigned int sh_name;
unsigned int sh_type;
unsigned int sh_flags;
unsigned int sh_addr;
unsigned int sh_offset;
unsigned int sh_size;
unsigned int sh_link;
unsigned int sh_info;
unsigned int sh_addralign;
unsigned int sh_entsize;
} __attribute__((packed)) Elf32_Shdr;
typedef struct {
unsigned int p_type;
unsigned int p_offset;
unsigned int p_vaddr;
unsigned int p_paddr;
unsigned int p_filesz;
unsigned int p_memsz;
unsigned int p_flags;
unsigned int p_align;
} __attribute__((packed)) Elf32_Phdr;
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_PAD 7
#define EI_NIDENT 16 //size of ident

7
elfloader/.deps/string.d Normal file
View File

@ -0,0 +1,7 @@
string.o: string.c ../string.c ../string.h ../global.h
../string.c:
../string.h:
../global.h:

18
elfloader/.deps/stub.d Normal file
View File

@ -0,0 +1,18 @@
stub.o: stub.c types.h utils.h start.h hollywood.h string.h ../string.h \
../global.h elf.h
types.h:
utils.h:
start.h:
hollywood.h:
string.h:
../string.h:
../global.h:
elf.h:

9
elfloader/.deps/utils.d Normal file
View File

@ -0,0 +1,9 @@
utils.o: utils.c types.h utils.h hollywood.h start.h
types.h:
utils.h:
hollywood.h:
start.h:

23
elfloader/Makefile Normal file
View File

@ -0,0 +1,23 @@
include starlet.mk
CFLAGS += -fpic -fno-builtin-memcpy
LDSCRIPT = stub.ld
LIBS = -lgcc
TARGET = elfloader.elf
TARGET_BIN = elfloader.bin
OBJS = start.o stub.o string.o utils.o
include common.mk
all: $(TARGET_BIN)
$(TARGET_BIN): $(TARGET)
@echo " OBJCPY $@"
@$(OBJCOPY) -O binary $< $@
clean: myclean
myclean:
-rm -f $(TARGET_BIN)

60
elfloader/common.mk Normal file
View File

@ -0,0 +1,60 @@
AR = $(PREFIX)ar
AS = $(PREFIX)as
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
LD = $(PREFIX)ld
OBJCOPY = $(PREFIX)objcopy
RANLIB = $(PREFIX)ranlib
STRIP = $(PREFIX)strip
BIN2S = $(DEVKITPPC)/bin/bin2s
ifeq ($(NOMAPFILE),)
LDFLAGS += -Wl,-Map,$(TARGET).map
endif
ifneq ($(LDSCRIPT),)
LDFLAGS += -Wl,-T$(LDSCRIPT)
endif
DEPDIR = .deps
all: $(TARGET)
$(TARGET): $(OBJS)
@echo " LINK $@"
@$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
ifneq ($(LDSCRIPT),)
$(TARGET): $(LDSCRIPT)
endif
%.o: %.c
@echo " COMPILE $<"
@mkdir -p $(DEPDIR)
@$(CC) $(CFLAGS) $(DEFINES) -Wp,-MMD,$(DEPDIR)/$(*F).d,-MQ,"$@",-MP -c $< -o $@
%.o: %.s
@echo " ASSEMBLE $<"
@$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@
%.o: %.S
@echo " ASSEMBLE $<"
@$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@
clean:
rm -rf $(DEPDIR)
rm -f $(TARGET) $(TARGET).map $(OBJS)
define bin2o
@echo " BIN2S $(notdir $<)"
@$(BIN2S) -a 32 $< | $(AS) -o $(@)
@echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(<F) | tr . _)`.h
@echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(<F) | tr . _)`.h
@echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(<F) | tr . _)`.h
endef
-include $(DEPDIR)/*
.PHONY: clean

66
elfloader/elf.h Normal file
View File

@ -0,0 +1,66 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: ELF structures
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ELF_H__
#define __ELF_H__
#include "types.h"
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
u16 e_type;
u16 e_machine;
u32 e_version;
void *e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shtrndx;
} Elf32_Ehdr;
typedef struct {
u32 p_type;
u32 p_offset;
void *p_vaddr;
void *p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
} Elf32_Phdr;
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#endif

168
elfloader/elfloader.elf.map Normal file
View File

@ -0,0 +1,168 @@
Archive member included because of file (symbol)
e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_udivsi3.o)
utils.o (__aeabi_uidiv)
e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_dvmd_tls.o)
e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_udivsi3.o) (__aeabi_idiv0)
Discarded input sections
.text 0x00000000 0x0 start.o
.data 0x00000000 0x0 start.o
.bss 0x00000000 0x0 start.o
.text 0x00000000 0x0 stub.o
.data 0x00000000 0x0 stub.o
.bss 0x00000000 0x0 stub.o
.text 0x00000000 0x0 string.o
.data 0x00000000 0x0 string.o
.bss 0x00000000 0x0 string.o
.text.strnlen 0x00000000 0x2c string.o
.text.strlen 0x00000000 0x20 string.o
.text.strncpy 0x00000000 0x4c string.o
.text.strcpy 0x00000000 0x18 string.o
.text.strcmp 0x00000000 0x28 string.o
.text.strncmp 0x00000000 0x48 string.o
.text.memset 0x00000000 0x1c string.o
.text.strchr 0x00000000 0x28 string.o
.text 0x00000000 0x0 utils.o
.data 0x00000000 0x0 utils.o
.bss 0x00000000 0x0 utils.o
.data 0x00000000 0x0 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_udivsi3.o)
.bss 0x00000000 0x0 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_udivsi3.o)
.data 0x00000000 0x0 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_dvmd_tls.o)
.bss 0x00000000 0x0 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_dvmd_tls.o)
Memory Configuration
Name Origin Length Attributes
*default* 0x00000000 0xffffffff
Linker script and memory map
0x00000000 __base_addr = 0x0
0x00000000 . = __base_addr
.header 0x00000000 0x10
0x00000000 __header = .
0x00000000 0x4 LONG 0x10 __code_start
0x00000004 0x4 LONG 0x4b0 __loader_size
0x00000008 0x4 LONG 0x0
0x0000000c 0x4 LONG 0x0
0x00000010 . = ALIGN (0x10)
0x00000010 __code_start = .
.init 0x00000010 0xc8
*(.init)
.init 0x00000010 0xc8 start.o
0x00000010 _start
0x000000bc debug_output
0x000000d8 . = ALIGN (0x4)
.got 0x000000d8 0x0
0x000000d8 __got_start = .
*(.got.*)
*(.got)
0x000000d8 . = ALIGN (0x4)
0x000000d8 __got_end = .
.text 0x000000d8 0x2d4
*(.text.*)
.text.disable_boot0
0x000000d8 0x1c stub.o
.text.mem_setswap
0x000000f4 0x1c stub.o
.text.loadelf 0x00000110 0x90 stub.o
0x00000110 loadelf
.text._main 0x000001a0 0x44 stub.o
0x000001a0 _main
.text.memcmp 0x000001e4 0x48 string.o
0x000001e4 memcmp
.text.udelay 0x0000022c 0x38 utils.o
0x0000022c udelay
.text.panic 0x00000264 0x30 utils.o
0x00000264 panic
*(.gnu.warning)
*(.gnu.linkonce.t*)
*(.glue_7)
.glue_7 0x00000000 0x0 linker stubs
*(.glue_7t)
.glue_7t 0x00000000 0x0 linker stubs
0x00000294 . = ALIGN (0x4)
.text 0x00000294 0x114 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_udivsi3.o)
0x00000294 __aeabi_uidiv
0x00000294 __udivsi3
0x00000388 __aeabi_uidivmod
.text 0x000003a8 0x4 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_dvmd_tls.o)
0x000003a8 __aeabi_idiv0
0x000003a8 __aeabi_ldiv0
0x000003ac __text_end = .
.vfp11_veneer 0x000003ac 0x0
.vfp11_veneer 0x00000000 0x0 linker stubs
.v4_bx 0x000003ac 0x0
.v4_bx 0x00000000 0x0 linker stubs
.rodata 0x000003ac 0x8
*(.rodata)
*all.rodata*(*)
*(.roda)
*(.rodata.*)
.rodata.str1.1
0x000003ac 0x8 stub.o
*(.gnu.linkonce.r*)
0x000003b4 . = ALIGN (0x4)
.data 0x000003b4 0x0
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
0x000003b4 . = ALIGN (0x4)
.bss 0x000003b4 0xc
0x000003b4 __bss_start = .
*(.dynbss)
*(.gnu.linkonce.b*)
*(.bss*)
*(.sbss*)
*(COMMON)
0x000003c0 . = ALIGN (0x20)
*fill* 0x000003b4 0xc 00
0x000003c0 __bss_end = .
0x000003c0 __stack_end = __bss_end
0x000004c0 __stack_addr = (__bss_end + 0x100)
0x000004c0 __end = __stack_addr
0x000004b0 __loader_size = (__end - __code_start)
[0x000003c0] PROVIDE (__stack_end, __stack_end)
[0x000004c0] PROVIDE (__stack_addr, __stack_addr)
[0x000000d8] PROVIDE (__got_start, __got_start)
[0x000000d8] PROVIDE (__got_end, __got_end)
[0x000003b4] PROVIDE (__bss_start, __bss_start)
[0x000003c0] PROVIDE (__bss_end, __bss_end)
LOAD start.o
LOAD stub.o
LOAD string.o
LOAD utils.o
LOAD e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a
OUTPUT(elfloader.elf elf32-bigarm)
.ARM.attributes
0x00000000 0x30
.ARM.attributes
0x00000000 0x24 start.o
.ARM.attributes
0x00000024 0x34 stub.o
.ARM.attributes
0x00000058 0x34 string.o
.ARM.attributes
0x0000008c 0x34 utils.o
.ARM.attributes
0x000000c0 0x1a e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_udivsi3.o)
.ARM.attributes
0x000000da 0x18 e:/devkitpro/devkitarm/bin/../lib/gcc/arm-eabi/4.6.1/be\libgcc.a(_dvmd_tls.o)
.comment 0x00000000 0x22
.comment 0x00000000 0x22 stub.o
0x23 (size before relaxing)
.comment 0x00000000 0x23 string.o
.comment 0x00000000 0x23 utils.o

31
elfloader/hollywood.h Normal file
View File

@ -0,0 +1,31 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: Hollywood register definitions
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __HOLLYWOOD_H__
#define __HOLLYWOOD_H__
#define HW_REG_BASE 0xd800000
#define HW_TIMER (HW_REG_BASE + 0x010)
#define HW_MEMMIRR (HW_REG_BASE + 0x060)
#define HW_BOOT0 (HW_REG_BASE + 0x18c)
#endif

12
elfloader/starlet.mk Normal file
View File

@ -0,0 +1,12 @@
ifeq ($(strip $(DEVKITARM)),)
$(error "Set DEVKITARM in your environment.")
endif
PREFIX = $(DEVKITARM)/bin/arm-eabi-
CFLAGS = -mbig-endian -mcpu=arm926ej-s
CFLAGS += -fomit-frame-pointer -ffunction-sections
CFLAGS += -Wall -Wextra -Os -pipe
ASFLAGS =
LDFLAGS = -mbig-endian -n -nostartfiles -nodefaultlibs -Wl,-gc-sections

113
elfloader/start.S Normal file
View File

@ -0,0 +1,113 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: system startup
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
.arm
.extern _main
.extern __got_start
.extern __got_end
.extern __bss_start
.extern __bss_end
.extern __stack_addr
.extern delay
.globl _start
.globl debug_output
.section .init
_start:
@ Get real address of _start
sub r4, pc, #8
@ Subtract offset to get the address that we were loaded at
ldr r0, =_start
sub r4, r4, r0
@ Output 0x42 to the debug port
mov r0, #0x42
bl debug_output
@ Set up a stack
ldr sp, =__stack_addr
add sp, r4
@ Output 0x43 to the debug port
mov r0, #0x43
bl debug_output
@ relocate the GOT entries
ldr r1, =__got_start
add r1, r4
ldr r2, =__got_end
add r2, r4
got_loop:
@ check for the end
cmp r1, r2
beq done_got
@ read the GOT entry
ldr r3, [r1]
@ add our base address
add r3, r4
str r3, [r1]
@ move on
add r1, r1, #4
b got_loop
done_got:
@ clear BSS
ldr r1, =__bss_start
add r1, r4
ldr r2, =__bss_end
add r2, r4
mov r3, #0
bss_loop:
@ check for the end
cmp r1, r2
beq done_bss
@ clear the word and move on
str r3, [r1]
add r1, r1, #4
b bss_loop
done_bss:
mov r0, #0x44
bl debug_output
@ take the plunge
mov r0, r4
bl _main
@ _main returned! Go to whatever address it returned...
mov r1, r0
mov r0, r4
mov pc, r1
.pool
debug_output:
@ load address of port
mov r3, #0xd800000
@ load old value
ldr r2, [r3, #0xe0]
@ clear debug byte
bic r2, r2, #0xFF0000
@ insert new value
and r0, r0, #0xFF
orr r2, r2, r0, LSL #16
@ store back
str r2, [r3, #0xe0]
mov pc, lr

30
elfloader/start.h Normal file
View File

@ -0,0 +1,30 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: system startup
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __START_H__
#define __START_H__
#include "types.h"
void debug_output(u8 byte);
#endif

BIN
elfloader/start.o Normal file

Binary file not shown.

1
elfloader/string.c Normal file
View File

@ -0,0 +1 @@
#include "../string.c"

1
elfloader/string.h Normal file
View File

@ -0,0 +1 @@
#include "../string.h"

BIN
elfloader/string.o Normal file

Binary file not shown.

86
elfloader/stub.c Normal file
View File

@ -0,0 +1,86 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
#include "utils.h"
#include "start.h"
#include "hollywood.h"
#include "string.h"
#include "elf.h"
typedef struct {
u32 hdrsize;
u32 loadersize;
u32 elfsize;
u32 argument;
} ioshdr;
void *loadelf(const u8 *elf) {
if(memcmp("\x7F" "ELF\x01\x02\x01",elf,7)) {
panic(0xE3);
}
Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf;
if(ehdr->e_phoff == 0) {
panic(0xE4);
}
int count = ehdr->e_phnum;
Elf32_Phdr *phdr = (Elf32_Phdr*)(elf + ehdr->e_phoff);
while(count--)
{
if(phdr->p_type == PT_LOAD) {
const void *src = elf + phdr->p_offset;
memcpy(phdr->p_paddr, src, phdr->p_filesz);
}
phdr++;
}
return ehdr->e_entry;
}
static inline void disable_boot0()
{
set32(HW_BOOT0, 0x1000);
}
static inline void mem_setswap()
{
set32(HW_MEMMIRR, 0x20);
}
void *_main(void *base)
{
ioshdr *hdr = (ioshdr*)base;
u8 *elf;
void *entry;
elf = (u8*) base;
elf += hdr->hdrsize + hdr->loadersize;
debug_output(0xF1);
mem_setswap(1);
disable_boot0(1);
entry = loadelf(elf);
debug_output(0xC1);
return entry;
}

117
elfloader/stub.ld Normal file
View File

@ -0,0 +1,117 @@
/*
elfloader - a Free Software replacement for the Nintendo/BroadOn IOS.
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
OUTPUT_FORMAT("elf32-bigarm")
OUTPUT_ARCH(arm)
EXTERN(_start)
ENTRY(_start)
__base_addr = 0;
SECTIONS
{
. = __base_addr;
.header :
{
__header = .;
/* Entry point (offset) */
LONG(__code_start);
/* Loader size */
LONG(__loader_size);
/* ELF size */
LONG(0);
/* Boot argument? */
LONG(0);
. = ALIGN(16);
}
__code_start = .;
.init :
{
*(.init)
. = ALIGN(4);
}
.got :
{
__got_start = .;
*(.got.*)
*(.got)
. = ALIGN(4);
__got_end = . ;
}
.text :
{
*(.text.*)
*(.gnu.warning)
*(.gnu.linkonce.t*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
}
__text_end = . ;
.rodata :
{
*(.rodata)
*all.rodata*(*)
*(.roda)
*(.rodata.*)
*(.gnu.linkonce.r*)
. = ALIGN(4);
}
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
. = ALIGN(4);
}
.bss :
{
__bss_start = . ;
*(.dynbss)
*(.gnu.linkonce.b*)
*(.bss*)
*(.sbss*)
*(COMMON)
. = ALIGN(32);
__bss_end = . ;
}
}
__stack_end = (__bss_end);
__stack_addr = (__bss_end + 0x100);
__end = __stack_addr ;
__loader_size = __end - __code_start;
PROVIDE (__stack_end = __stack_end);
PROVIDE (__stack_addr = __stack_addr);
PROVIDE (__got_start = __got_start);
PROVIDE (__got_end = __got_end);
PROVIDE (__bss_start = __bss_start);
PROVIDE (__bss_end = __bss_end);

BIN
elfloader/stub.o Normal file

Binary file not shown.

50
elfloader/types.h Normal file
View File

@ -0,0 +1,50 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: types
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __TYPES_H__
#define __TYPES_H__
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16;
typedef volatile unsigned int vu32;
typedef volatile unsigned long long vu64;
typedef volatile signed char vs8;
typedef volatile signed short vs16;
typedef volatile signed int vs32;
typedef volatile signed long long vs64;
typedef s32 size_t;
#define NULL ((void *)0)
#endif

45
elfloader/utils.c Normal file
View File

@ -0,0 +1,45 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: random utilities
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
#include "utils.h"
#include "hollywood.h"
#include "start.h"
void udelay(u32 d)
{
// should be good to max .2% error
u32 ticks = d * 19 / 10;
write32(HW_TIMER, 0);
while(read32(HW_TIMER) < ticks);
}
void panic(u8 v)
{
while(1) {
debug_output(v);
udelay(500000);
debug_output(0);
udelay(500000);
}
}

188
elfloader/utils.h Normal file
View File

@ -0,0 +1,188 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
ELF loader: random utilities
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __UTILS_H__
#define __UTILS_H__
static inline u32 read32(u32 addr)
{
u32 data;
__asm__ volatile ("ldr\t%0, [%1]" : "=r" (data) : "r" (addr));
return data;
}
static inline void write32(u32 addr, u32 data)
{
__asm__ volatile ("str\t%0, [%1]" : : "r" (data), "r" (addr));
}
static inline u32 set32(u32 addr, u32 set)
{
u32 data;
__asm__ volatile (
"ldr\t%0, [%1]\n"
"\torr\t%0, %2\n"
"\tstr\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (set)
);
return data;
}
static inline u32 clear32(u32 addr, u32 clear)
{
u32 data;
__asm__ volatile (
"ldr\t%0, [%1]\n"
"\tbic\t%0, %2\n"
"\tstr\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (clear)
);
return data;
}
static inline u32 mask32(u32 addr, u32 clear, u32 set)
{
u32 data;
__asm__ volatile (
"ldr\t%0, [%1]\n"
"\tbic\t%0, %3\n"
"\torr\t%0, %2\n"
"\tstr\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (set), "r" (clear)
);
return data;
}
static inline u16 read16(u32 addr)
{
u32 data;
__asm__ volatile ("ldrh\t%0, [%1]" : "=r" (data) : "r" (addr));
return data;
}
static inline void write16(u32 addr, u16 data)
{
__asm__ volatile ("strh\t%0, [%1]" : : "r" (data), "r" (addr));
}
static inline u16 set16(u32 addr, u16 set)
{
u16 data;
__asm__ volatile (
"ldrh\t%0, [%1]\n"
"\torr\t%0, %2\n"
"\tstrh\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (set)
);
return data;
}
static inline u16 clear16(u32 addr, u16 clear)
{
u16 data;
__asm__ volatile (
"ldrh\t%0, [%1]\n"
"\tbic\t%0, %2\n"
"\tstrh\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (clear)
);
return data;
}
static inline u16 mask16(u32 addr, u16 clear, u16 set)
{
u16 data;
__asm__ volatile (
"ldrh\t%0, [%1]\n"
"\tbic\t%0, %3\n"
"\torr\t%0, %2\n"
"\tstrh\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (set), "r" (clear)
);
return data;
}
static inline u8 read8(u32 addr)
{
u32 data;
__asm__ volatile ("ldrb\t%0, [%1]" : "=r" (data) : "r" (addr));
return data;
}
static inline void write8(u32 addr, u8 data)
{
__asm__ volatile ("strb\t%0, [%1]" : : "r" (data), "r" (addr));
}
static inline u8 set8(u32 addr, u8 set)
{
u8 data;
__asm__ volatile (
"ldrb\t%0, [%1]\n"
"\torr\t%0, %2\n"
"\tstrb\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (set)
);
return data;
}
static inline u8 clear8(u32 addr, u8 clear)
{
u8 data;
__asm__ volatile (
"ldrb\t%0, [%1]\n"
"\tbic\t%0, %2\n"
"\tstrb\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (clear)
);
return data;
}
static inline u8 mask8(u32 addr, u8 clear, u8 set)
{
u8 data;
__asm__ volatile (
"ldrb\t%0, [%1]\n"
"\tbic\t%0, %3\n"
"\torr\t%0, %2\n"
"\tstrb\t%0, [%1]"
: "=&r" (data)
: "r" (addr), "r" (set), "r" (clear)
);
return data;
}
void udelay(u32 d);
void panic(u8 v);
#endif

BIN
elfloader/utils.o Normal file

Binary file not shown.

4048
ff.c Normal file

File diff suppressed because it is too large Load Diff

335
ff.h Normal file
View File

@ -0,0 +1,335 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.08b (C)ChaN, 2011
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following trems.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 8237 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct {
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
} PARTITION;
extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */
#else /* Single partition configuration */
#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */
#define LD2PT(vol) 0 /* Always mounts the 1st partition */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode string */
#if !_USE_LFN
#error _LFN_UNICODE must be 0 in non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
BYTE n_fats; /* Number of FAT copies (1,2) */
BYTE wflag; /* win[] dirty flag (1:must be written back) */
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
WORD ssize; /* Bytes per sector (512,1024,2048,4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
DWORD fsi_sector; /* fsinfo sector (FAT32) */
#endif
#if _FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
DWORD fsize; /* Sectors per FAT */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
} FATFS;
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0 when fsize==0) */
DWORD clust; /* Current cluster */
DWORD dsect; /* Current data sector */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_SHARE
UINT lockid; /* File lock ID (index of file semaphore table) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File data read/write buffer */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;
/* File status structure (FILINFO) */
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN
TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */
FR_EXIST, /* (8) Acces denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*); /* Truncate file */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
FRESULT f_chdrive (BYTE); /* Change current drive */
FRESULT f_chdir (const TCHAR*); /* Change current directory */
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
int f_putc (TCHAR, FIL*); /* Put a character to the file */
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
#ifndef EOF
#define EOF (-1)
#endif
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT); /* Allocate memory block */
void ff_memfree (void*); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
int ff_req_grant (_SYNC_t); /* Lock sync object */
void ff_rel_grant (_SYNC_t); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#define FA__ERROR 0x80
#if !_FS_READONLY
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek function */
#define CREATE_LINKMAP 0xFFFFFFFF
/*--------------------------------*/
/* Multi-byte word access macros */
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else /* Use byte-by-byte access to the FAT structure */
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

189
ffconf.h Normal file
View File

@ -0,0 +1,189 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
/ the configuration options.
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 8237 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function and Buffer Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
/ object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 0 /* 0 to 3 */
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
/ are removed.
/ 2: f_opendir and f_readdir are removed in addition to 1.
/ 3: f_lseek is removed in addition to 2. */
#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/----------------------------------------------------------------------------*/
#define _CODE_PAGE 437
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
/ 949 - Korean (DBCS, OEM, Windows)
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
/ 1250 - Central Europe (Windows)
/ 1251 - Cyrillic (Windows)
/ 1252 - Latin 1 (Windows)
/ 1253 - Greek (Windows)
/ 1254 - Turkish (Windows)
/ 1255 - Hebrew (Windows)
/ 1256 - Arabic (Windows)
/ 1257 - Baltic (Windows)
/ 1258 - Vietnam (OEM, Windows)
/ 437 - U.S. (OEM)
/ 720 - Arabic (OEM)
/ 737 - Greek (OEM)
/ 775 - Baltic (OEM)
/ 850 - Multilingual Latin 1 (OEM)
/ 858 - Multilingual Latin 1 + Euro (OEM)
/ 852 - Latin 2 (OEM)
/ 855 - Cyrillic (OEM)
/ 866 - Russian (OEM)
/ 857 - Turkish (OEM)
/ 862 - Hebrew (OEM)
/ 874 - Thai (OEM, Windows)
/ 1 - ASCII only (Valid for non LFN cfg.)
*/
#define _USE_LFN 1 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
/ to the project. When enable to use heap, memory control functions
/ ff_memalloc() and ff_memfree() must be added to the project. */
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
/* To switch the character code set on FatFs API to Unicode,
/ enable LFN feature and set _LFN_UNICODE to 1. */
#define _FS_RPATH 1 /* 0 to 2 */
/* The _FS_RPATH option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
/ 2: f_getcwd() is available in addition to 1.
/
/ Note that output of the f_readdir fnction is affected by this option. */
/*---------------------------------------------------------------------------/
/ Physical Drive Configurations
/----------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
/* Maximum sector size to be handled.
/ Always set 512 for memory card and hard disk but a larger value may be
/ required for on-board flash memory, floppy disk and optical disk.
/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size
/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */
/* When set to 0, each volume is bound to the same physical drive number and
/ it can mount only first primaly partition. When it is set to 1, each volume
/ is tied to the partitions listed in VolToPart[]. */
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
/ should be added to the disk_ioctl functio. */
/*---------------------------------------------------------------------------/
/ System Configurations
/----------------------------------------------------------------------------*/
#define _WORD_ACCESS 0 /* 0 or 1 */
/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
/ option defines which access method is used to the word data on the FAT volume.
/
/ 0: Byte-by-byte access.
/ 1: Word access. Do not choose this unless following condition is met.
/
/ When the byte order on the memory is big-endian or address miss-aligned word
/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
/ If it is not the case, the value can also be set to 1 to improve the
/ performance and code size. */
/* A header file that defines sync object types on the O/S, such as
/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module.
/
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
/ 1: Enable reentrancy. Also user provided synchronization handlers,
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
/ function must be added to the project. */
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */

62
global.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef __GLOBAL_H__
#define __GLOBAL_H__
#define UINT_MAX ((unsigned int)0xffffffff)
#define CARD_DEBUG 1
#define CHEATHOOK 1
//#define DEBUGGER 1
//#define DEBUGGERWAIT 1
//#define ACTIVITYLED 1
//#define CARDMODE 1
//#define CARDDEBUG 1
#define REALNAND 1
#define PADHOOK 1
#define CONFIG_VERSION 0x00000002
#define DM_VERSION 0x0002000B
#define DI_SUCCESS 1
#define DI_ERROR 2
#define DI_FATAL 64
//#define DEBUG 0
#define false 0
#define true 1
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef int bool;
typedef unsigned int sec_t;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16;
typedef volatile unsigned int vu32;
typedef volatile unsigned long long vu64;
typedef volatile signed char vs8;
typedef volatile signed short vs16;
typedef volatile signed int vs32;
typedef volatile signed long long vs64;
typedef s32 size_t;
typedef u32 u_int32_t;
typedef s32(*ipccallback)(s32 result,void *usrdata);
#define NULL ((void *)0)
#define ALIGNED(x) __attribute__((aligned(x)))
#endif

180
hollywood.h Normal file
View File

@ -0,0 +1,180 @@
#ifndef __HOLLYWOOD_H__
#define __HOLLYWOOD_H__
/* Hollywood Registers */
#define HW_PPC_REG_BASE 0xd000000
#define HW_REG_BASE 0xd800000
#define IPC_CTRL_Y1 0x01
#define IPC_CTRL_X2 0x02
#define IPC_CTRL_X1 0x04
#define IPC_CTRL_Y2 0x08
#define IPC_CTRL_IX1 0x10
#define IPC_CTRL_IX2 0x20
// Our definitions for this IPC interface
#define IPC_CTRL_OUT IPC_CTRL_Y1
#define IPC_CTRL_IN IPC_CTRL_X1
#define IPC_CTRL_IRQ_IN IPC_CTRL_IX1
// reset both flags (X* for ARM and Y* for PPC)
#define IPC_CTRL_RESET 0x06
// The PPC can only see the first three IPC registers
#define HW_IPC_PPCMSG (HW_REG_BASE + 0x000)
#define HW_IPC_PPCCTRL (HW_REG_BASE + 0x004)
#define HW_IPC_ARMMSG (HW_REG_BASE + 0x008)
#define HW_IPC_ARMCTRL (HW_REG_BASE + 0x00c)
#define HW_TIMER (HW_REG_BASE + 0x010)
#define HW_ALARM (HW_REG_BASE + 0x014)
#define HW_PPCIRQFLAG (HW_REG_BASE + 0x030)
#define HW_PPCIRQMASK (HW_REG_BASE + 0x034)
#define HW_ARMIRQFLAG (HW_REG_BASE + 0x038)
#define HW_ARMIRQMASK (HW_REG_BASE + 0x03c)
#define HW_MEMMIRR (HW_REG_BASE + 0x060)
// something to do with PPCBOOT
// and legacy DI it seems ?!?
#define HW_EXICTRL (HW_REG_BASE + 0x070)
#define EXICTRL_ENABLE_EXI 1
// PPC side of GPIO1 (Starlet can access this too)
// Output state
#define HW_GPIO1BOUT (HW_REG_BASE + 0x0c0)
// Direction (1=output)
#define HW_GPIO1BDIR (HW_REG_BASE + 0x0c4)
// Input state
#define HW_GPIO1BIN (HW_REG_BASE + 0x0c8)
// Interrupt level
#define HW_GPIO1BINTLVL (HW_REG_BASE + 0x0cc)
// Interrupt flags (write 1 to clear)
#define HW_GPIO1BINTFLAG (HW_REG_BASE + 0x0d0)
// Interrupt propagation enable
// Do these interrupts go anywhere???
#define HW_GPIO1BINTENABLE (HW_REG_BASE + 0x0d4)
//??? seems to be a mirror of inputs at some point... power-up state?
#define HW_GPIO1BINMIR (HW_REG_BASE + 0x0d8)
// 0xFFFFFF by default, if cleared disables respective outputs. Top bits non-settable.
#define HW_GPIO1ENABLE (HW_REG_BASE + 0x0dc)
#define HW_GPIO1_SLOT 0x000020
#define HW_GPIO1_DEBUG 0xFF0000
#define HW_GPIO1_DEBUG_SH 16
// Starlet side of GPIO1
// Output state
#define HW_GPIO1OUT (HW_REG_BASE + 0x0e0)
// Direction (1=output)
#define HW_GPIO1DIR (HW_REG_BASE + 0x0e4)
// Input state
#define HW_GPIO1IN (HW_REG_BASE + 0x0e8)
// Interrupt level
#define HW_GPIO1INTLVL (HW_REG_BASE + 0x0ec)
// Interrupt flags (write 1 to clear)
#define HW_GPIO1INTFLAG (HW_REG_BASE + 0x0f0)
// Interrupt propagation enable (interrupts go to main interrupt 0x800)
#define HW_GPIO1INTENABLE (HW_REG_BASE + 0x0f4)
//??? seems to be a mirror of inputs at some point... power-up state?
#define HW_GPIO1INMIR (HW_REG_BASE + 0x0f8)
// Owner of each GPIO bit. If 1, GPIO1B registers assume control. If 0, GPIO1 registers assume control.
#define HW_GPIO1OWNER (HW_REG_BASE + 0x0fc)
// ????
#define HW_DIFLAGS (HW_REG_BASE + 0x180)
#define DIFLAGS_BOOT_CODE 0x100000
// maybe a GPIO???
#define HW_CLOCKS (HW_REG_BASE + 0x190)
#define HW_RESETS (HW_REG_BASE + 0x194)
#define HW_GPIO2OUT (HW_REG_BASE + 0x1c8)
#define HW_GPIO2DIR (HW_REG_BASE + 0x1cc)
#define HW_GPIO2IN (HW_REG_BASE + 0x1d0)
#define HW_OTPCMD (HW_REG_BASE + 0x1ec)
#define HW_OTPDATA (HW_REG_BASE + 0x1f0)
#define HW_VERSION (HW_REG_BASE + 0x214)
/* NAND Registers */
#define NAND_REG_BASE 0xd010000
#define NAND_CMD (NAND_REG_BASE + 0x000)
#define NAND_STATUS NAND_CMD
#define NAND_CONF (NAND_REG_BASE + 0x004)
#define NAND_ADDR0 (NAND_REG_BASE + 0x008)
#define NAND_ADDR1 (NAND_REG_BASE + 0x00c)
#define NAND_DATA (NAND_REG_BASE + 0x010)
#define NAND_ECC (NAND_REG_BASE + 0x014)
#define NAND_UNK1 (NAND_REG_BASE + 0x018)
#define NAND_UNK2 (NAND_REG_BASE + 0x01c)
/* AES Registers */
#define AES_REG_BASE 0xd020000
#define AES_CMD (AES_REG_BASE + 0x000)
#define AES_SRC (AES_REG_BASE + 0x004)
#define AES_DEST (AES_REG_BASE + 0x008)
#define AES_KEY (AES_REG_BASE + 0x00c)
#define AES_IV (AES_REG_BASE + 0x010)
/* SHA-1 Registers */
#define SHA_REG_BASE 0xd030000
#define SHA_CMD (SHA_REG_BASE + 0x000)
#define SHA_SRC (SHA_REG_BASE + 0x004)
#define SHA_H0 (SHA_REG_BASE + 0x008)
#define SHA_H1 (SHA_REG_BASE + 0x00c)
#define SHA_H2 (SHA_REG_BASE + 0x010)
#define SHA_H3 (SHA_REG_BASE + 0x014)
#define SHA_H4 (SHA_REG_BASE + 0x018)
/* SD Host Controller Registers */
#define SDHC_REG_BASE 0xd070000
/* EXI Registers */
#define EXI_REG_BASE 0xd806800
#define EXI0_REG_BASE (EXI_REG_BASE+0x000)
#define EXI1_REG_BASE (EXI_REG_BASE+0x014)
#define EXI2_REG_BASE (EXI_REG_BASE+0x028)
#define EXI0_CSR (EXI0_REG_BASE+0x000)
#define EXI0_MAR (EXI0_REG_BASE+0x004)
#define EXI0_LENGTH (EXI0_REG_BASE+0x008)
#define EXI0_CR (EXI0_REG_BASE+0x00c)
#define EXI0_DATA (EXI0_REG_BASE+0x010)
#define EXI1_CSR (EXI1_REG_BASE+0x000)
#define EXI1_MAR (EXI1_REG_BASE+0x004)
#define EXI1_LENGTH (EXI1_REG_BASE+0x008)
#define EXI1_CR (EXI1_REG_BASE+0x00c)
#define EXI1_DATA (EXI1_REG_BASE+0x010)
#define EXI2_CSR (EXI2_REG_BASE+0x000)
#define EXI2_MAR (EXI2_REG_BASE+0x004)
#define EXI2_LENGTH (EXI2_REG_BASE+0x008)
#define EXI2_CR (EXI2_REG_BASE+0x00c)
#define EXI2_DATA (EXI2_REG_BASE+0x010)
#define EXI_BOOT_BASE (EXI_REG_BASE+0x040)
/* MEMORY CONTROLLER Registers */
#define MEM_REG_BASE 0xd8b4000
#define MEM_PROT (MEM_REG_BASE+0x20a)
#define MEM_PROT_START (MEM_REG_BASE+0x20c)
#define MEM_PROT_END (MEM_REG_BASE+0x20e)
#define MEM_FLUSHREQ (MEM_REG_BASE+0x228)
#define MEM_FLUSHACK (MEM_REG_BASE+0x22a)
#endif

37
integer.h Normal file
View File

@ -0,0 +1,37 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _INTEGER
#define _INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
#else /* Embedded platform */
/* These types must be 16-bit, 32-bit or larger integer */
typedef int INT;
typedef unsigned int UINT;
/* These types must be 8-bit integer */
typedef char CHAR;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
/* These types must be 16-bit integer */
typedef short SHORT;
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types must be 32-bit integer */
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long DWORD;
#endif
#endif

81
iosmodule.ld Normal file
View File

@ -0,0 +1,81 @@
OUTPUT_FORMAT("elf32-bigarm")
OUTPUT_ARCH(arm)
ENTRY(_start)
__stack_size = 0x4000;
MEMORY
{
sram : ORIGIN = 0xFFFF0000, LENGTH = 0x10000
stack : ORIGIN = 0xFFFE0000, LENGTH = 0x4000
}
PHDRS
{
sram PT_LOAD AT ( 0xFFFF0000 ) ;
stack PT_LOAD AT ( 0xFFFE0000 ) ;
}
SECTIONS
{
.init :
{
*(.init)
. = ALIGN(4);
} >sram :sram
.text :
{
*(.text*)
*(.text.*)
*(.gnu.warning)
*(.gnu.linkonce.t*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
} >sram :sram
.rodata :
{
*(.rodata)
*all.rodata*(*)
*(.roda)
*(.rodata.*)
*(.gnu.linkonce.r*)
. = ALIGN(4);
} >sram :sram
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
. = ALIGN(4);
} >sram :sram
.bss :
{
__bss_start = . ;
*(.dynbss)
*(.gnu.linkonce.b*)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = . ;
} >sram :sram
.stack :
{
__stack_end = .;
. = . +__stack_size;
. = ALIGN(4);
__stack_addr = .;
} >stack :stack
/DISCARD/ :
{
*(.ARM.exidx*)
*(.ARM.extab*)
}
}

325
main.c Normal file
View File

@ -0,0 +1,325 @@
/*
DIOS MIOS - Gamecube USB loader for Nintendo Wii
Copyright (C) 2010-2012 crediar
*/
#include "string.h"
#include "global.h"
#include "alloc.h"
#include "ff.h"
#include "diskio.h"
#include "dol.h"
#include "GCPad.h"
#include "HW.h"
#include "Patches.h"
#include "Config.h"
#include "Card.h"
#include "DVD.h"
#include "Drive.h"
#include "dip.h"
#include "Patches.h"
extern u32 DiscChangeIRQ;
char __aeabi_unwind_cpp_pr0[0];
void Syscall( u32 a, u32 b, u32 c, u32 d )
{
//dbgprintf("Syscall,%d,%d,%d,%d\n", a, b, c, d);
return;
}
void SWI( u32 a, u32 b )
{
//dbgprintf("SWI:%X,%X\n", a, b );
return;
}
void PrefetchAbort( void )
{
EXIControl(1);
dbgprintf("PrefetchAbort\n");
while(1);
return;
}
void DataAbort( u32 a, u32 b, u32 c, u32 d, u32 e, u32 f, u32 g, u32 h )
{
u32 val;
__asm("mov %0,lr": "=r" (val) );
*(vu32*)0xD800070 |= 1;
dbgprintf("DataAbort: LR:%08x, %x, %x, %x, %x, %x, %x, %x\n",val,b,c,d,e,f,g,h);
Shutdown();
}
void IRQHandler( void )
{
u32 IRQs = read32(HW_ARMIRQFLAG) /*& read32(HW_ARMIRQMASK)*/;
if( IRQs & IRQ_GPIO1 ) // Starlet GPIO IRQ
{
if( read32(HW_GPIO_INTFLAG) & (1) )
{
set32( HW_EXICTRL, 1 );
int i;
for( i = 0; i < 0x20; i+=4 )
dbgprintf("0x%08X:0x%08X\t0x%08X\n", i, read32( CARD_BASE + i ), read32( CARD_SHADOW + i ) );
dbgprintf("\n");
for( i = 0; i < 0x30; i+=4 )
dbgprintf("0x%08X:0x%08X\t0x%08X\n", i, read32( 0x00002F00 + i ), read32( 0x00002F30 + i ) );
dbgprintf("\n");
for( i = 0; i < 0x30; i+=4 )
dbgprintf("0x%08X:0x%08X\t0x%08X\n", 0x0D806000 + i, read32( 0x0D806000 + i ), read32( 0x0D006000 + i ) );
dbgprintf("DVD:Error:%08X\n", DVDLowGetError() );
udelay(10000);
set32( HW_GPIO_ENABLE, GPIO_POWER );
set32( HW_GPIO_OUT, GPIO_POWER );
while(1);
}
}
//Clear IRQ Flags
write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) );
write32( HW_GPIO_INTFLAG, read32(HW_GPIO_INTFLAG) );
return;
}
void FIQHandler( void )
{
//dbgprintf("FIQHandler\n");
return;
}
void DebugPoke( u8 Value )
{
clear32( 0xD8000E0, 0xFF0000 );
set32( 0xD8000E0, Value<<16 );
}
void SysReset( void )
{
write32( HW_RESETS, (read32( HW_RESETS ) | 0x20 ) & (~1) );
}
void SysShutdown( void )
{
set32( HW_GPIO_ENABLE, GPIO_POWER );
set32( HW_GPIO_OUT, GPIO_POWER );
while(1);
}
u32 fail;
int main( int argc, char *argv[] )
{
udelay(800);
#ifndef REALNAND
PPCReset();
clear32( HW_RESETS, 0x48000 );
clear32( 0xD800184, 0x438E );
ChangeClock();
DRAMInit(1,0);
set32( HW_RESETS, 0x48000 );
set32( 0xD800184, 0x438E );
UNKInit( 1, 1 );
#endif
set32( 0xD800038, IRQ_RESET|IRQ_GPIO1 );
set32( 0xD80003C, IRQ_RESET|IRQ_GPIO1 );
udelay(200);
u32 SP[2];
GetRevision( SP+1, SP );
if( SP[1] == 0 )
{
write32( HW_MEMIRR, 0x67 );
} else {
write32( HW_MEMIRR, 0x27 );
}
MIOSInit();
#ifdef DEBUG
dbgprintf("DIOS-MIOS [DEBUG] v%d.%d\n", DM_VERSION>>16, DM_VERSION & 0xFFFF );
#else
#ifdef REALNAND
dbgprintf("DIOS-MIOS v%d.%db\n", DM_VERSION>>16, DM_VERSION & 0xFFFF );
#else
dbgprintf("DIOS-MIOS v%d.%da\n", DM_VERSION>>16, DM_VERSION & 0xFFFF );
#endif
#endif
dbgprintf("Built: " __DATE__ " " __TIME__ "\n");
dbgprintf("This software is licensed under GPLv3, for more details visit:\nhttp://code.google.com/p/diosmios\n");
//dbgprintf("MEMInitLow()...\n");
MEMInitLow();
// EHCI
*(vu32*)0x0D0400A4 = 0x00004026;
*(vu32*)0x0D0400B0 = 0x0002422E;
*(vu32*)0x0D0400B4 = 0x03802E14;
// DDR control
*(vu16*)0x0D8B4034 = 0x0000;
*(vu16*)0x0D8B403C = 0x0000;
*(vu16*)0x0D8B4034 = 0x0000;
*(vu16*)0x0D8B403C = 0x0000;
*(vu16*)0x0D8B4040 = 0x0000;
*(vu16*)0x0D8B4044 = 0x0000;
*(vu16*)0x0D8B4048 = 0x0000;
*(vu16*)0x0D8B404C = 0x0000;
*(vu16*)0x0D8B4050 = 0x0000;
*(vu16*)0x0D8B4054 = 0x13EB;
*(vu16*)0x0D8B4058 = 0x09B5;
*(vu16*)0x0D8B4060 = 0x0000;
*(vu16*)0x0D8B4064 = 0x0000;
*(vu16*)0x0D8B420C = 0x3620;
*(vu16*)0x0D8B4220 = 0xF000;
udelay(8000);
HeapInit( (u8*)0x13600000 );
set32( HW_EXICTRL, 1 );
DVDInit();
ConfigInit( (DML_CFG*)0x01200000 );
ConfigSetConfig( DML_CFG_BOOT_DISC2 );
if( !ConfigGetConfig(DML_CFG_BOOT_DISC) )
{
if( DVDSelectGame() == DI_SUCCESS )
{
if( ConfigGetConfig(DML_CFG_NMM) )
CardInit();
} else {
dbgprintf("Loading disc\n");
((DML_CFG*)0x01200000)->Version = CONFIG_VERSION;
((DML_CFG*)0x01200000)->Magicbytes = 0xD1050CF6;
((DML_CFG*)0x01200000)->VideoMode = DML_VID_DML_AUTO;
((DML_CFG*)0x01200000)->Config = DML_CFG_BOOT_DISC;
}
}
DIInit();
//Switch mem2 to ARAM
DRAMCTRLWrite( 0x49, 0x0E );
udelay(2);
DRAMCTRLWrite( 0x49, 0x0F );
udelay(2);
HeapInit( (u8*)0xFFFE5000 );
write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) );
write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) );
set32( HW_PPCIRQMASK, (1<<31) );
set32( HW_IPC_PPCCTRL, 0x30 );
write32( 0x0D806008, 0 );
EXIControl(0);
write32( 0x1860, 0xdeadbeef ); // Clear OSReport area
write32( 0x30F8, 0 ); // Tell PPC side to start
ahb_flush_to( AHB_PPC );
u32 PADLock = 0;
while (1)
{
ahb_flush_from( AHB_STARLET ); //flush to arm
if( (((read32(0x12F8) >> 16) & 0x30) == 0x30 ) )
{
if( !PADLock )
{
ScreenShot();
PADLock = 1;
}
} else {
PADLock = 0;
}
if( DiscChangeIRQ )
if( read32(HW_TIMER) * 128 / 243000000 > 2 )
{
// dbgprintf("DIP:IRQ mon!\n");
//DVDGetDriveStatus
//write32( 0x01576D4, 0x38600000 );
while( read32(DI_SCONTROL) & 1 )
clear32( DI_SCONTROL, 1 );
set32( DI_SSTATUS, 0x3A );
write32( 0x0d80000C, (1<<0) | (1<<4) );
write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) );
write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) );
set32( 0x0d80000C, (1<<2) );
DiscChangeIRQ = 0;
}
if( (((read32(0x12FC) >> 16) & 0x1030) == 0x1030 ) )
{
SysReset();
}
if( (((read32(0x12FC) >> 16) & 0x234) == 0x234 ) )
{
SysShutdown();
}
//Baten Kaitos save hax
if( read32(0) == 0x474B4245 )
{
if( read32( 0x0073E640 ) == 0xFFFFFFFF )
{
write32( 0x0073E640, 0 );
}
}
//if( read32(0x1860) != 0xdeadbeef )
//{
// if( read32(0x1860) != 0 )
// {
// dbgprintf( (char*)(P2C(read32(0x1860))),
// (char*)(P2C(read32(0x1864))),
// (char*)(P2C(read32(0x1868))),
// (char*)(P2C(read32(0x186C))),
// (char*)(P2C(read32(0x1870))),
// (char*)(P2C(read32(0x1864)))
// );
// }
// write32(0x1860, 0xdeadbeef);
//}
SMenuAddFramebuffer();
DIUpdateRegisters();
if( ConfigGetConfig(DML_CFG_NMM) )
CARDUpdateRegisters();
ahb_flush_to( AHB_PPC ); //flush to ppc
}
}

251
memory.c Normal file
View File

@ -0,0 +1,251 @@
#include "memory.h"
void _dc_inval_entries(void *start, int count);
void _dc_flush_entries(const void *start, int count);
void _dc_flush(void);
void _ic_inval(void);
void _drain_write_buffer(void);
u32 irq_kill(void);
void irq_restore(u32 cookie);
#define LINESIZE 0x20
#define CACHESIZE 0x4000
#define CR_MMU (1 << 0)
#define CR_DCACHE (1 << 2)
#define CR_ICACHE (1 << 12)
// TODO: move to hollywood.h once we figure out WTF
#define HW_100 (HW_REG_BASE + 0x100)
#define HW_104 (HW_REG_BASE + 0x104)
#define HW_108 (HW_REG_BASE + 0x108)
#define HW_10c (HW_REG_BASE + 0x10c)
#define HW_110 (HW_REG_BASE + 0x110)
#define HW_114 (HW_REG_BASE + 0x114)
#define HW_118 (HW_REG_BASE + 0x118)
#define HW_11c (HW_REG_BASE + 0x11c)
#define HW_120 (HW_REG_BASE + 0x120)
#define HW_124 (HW_REG_BASE + 0x124)
#define HW_130 (HW_REG_BASE + 0x130)
#define HW_134 (HW_REG_BASE + 0x134)
#define HW_138 (HW_REG_BASE + 0x138)
#define HW_188 (HW_REG_BASE + 0x188)
#define HW_18C (HW_REG_BASE + 0x18c)
// what is this thing doing anyway?
// and why only on reads?
u32 _mc_read32(u32 addr)
{
u32 data;
u32 tmp130 = 0;
// this seems to be a bug workaround
if(!(read32(HW_VERSION) & 0xF0))
{
tmp130 = read32(HW_130);
write32(HW_130, tmp130 | 0x400);
// Dummy reads?
read32(HW_138);
read32(HW_138);
read32(HW_138);
read32(HW_138);
}
data = read32(addr);
read32(HW_VERSION); //???
if(!(read32(HW_VERSION) & 0xF0))
write32(HW_130, tmp130);
return data;
}
// this is ripped from IOS, because no one can figure out just WTF this thing is doing
void _ahb_flush_to(enum AHBDEV dev) {
u32 mask = 10;
switch(dev) {
case AHB_STARLET: mask = 0x8000; break;
case AHB_PPC: mask = 0x4000; break;
//case 2: mask = 0x0001; break;
case AHB_NAND: mask = 0x0002; break;
case AHB_AES: mask = 0x0004; break;
case AHB_SHA1: mask = 0x0008; break;
case AHB_EHCI: mask = 0x0010; break;
//case 7: mask = 0x0020; break;
//case 8: mask = 0x0040; break;
case AHB_SDHC: mask = 0x0080; break;
//case 10: mask = 0x0100; break;
//case 11: mask = 0x1000; break;
//case 12: mask = 0x0000; break;
default:
dbgprintf("ahb_invalidate(%d): Invalid device\n", dev);
return;
}
//NOTE: 0xd8b000x, not 0xd8b400x!
u32 val = _mc_read32(0xd8b0008);
if(!(val & mask)) {
switch(dev) {
// 2 to 10 in IOS, add more
case AHB_NAND:
case AHB_AES:
case AHB_SHA1:
case AHB_EHCI:
case AHB_SDHC:
while((read32(HW_18C) & 0xF) == 9)
set32(HW_188, 0x10000);
clear32(HW_188, 0x10000);
set32(HW_188, 0x2000000);
mask32(HW_124, 0x7c0, 0x280);
set32(HW_134, 0x400);
while((read32(HW_18C) & 0xF) != 9);
set32(HW_100, 0x400);
set32(HW_104, 0x400);
set32(HW_108, 0x400);
set32(HW_10c, 0x400);
set32(HW_110, 0x400);
set32(HW_114, 0x400);
set32(HW_118, 0x400);
set32(HW_11c, 0x400);
set32(HW_120, 0x400);
write32(0xd8b0008, _mc_read32(0xd8b0008) & (~mask));
write32(0xd8b0008, _mc_read32(0xd8b0008) | mask);
clear32(HW_134, 0x400);
clear32(HW_100, 0x400);
clear32(HW_104, 0x400);
clear32(HW_108, 0x400);
clear32(HW_10c, 0x400);
clear32(HW_110, 0x400);
clear32(HW_114, 0x400);
clear32(HW_118, 0x400);
clear32(HW_11c, 0x400);
clear32(HW_120, 0x400);
clear32(HW_188, 0x2000000);
mask32(HW_124, 0x7c0, 0xc0);
//0, 1, 11 in IOS, add more
case AHB_STARLET:
case AHB_PPC:
write32(0xd8b0008, val & (~mask));
// wtfux
write32(0xd8b0008, val | mask);
write32(0xd8b0008, val | mask);
write32(0xd8b0008, val | mask);
}
}
}
// invalidate device and then starlet
void ahb_flush_to(enum AHBDEV type)
{
u32 cookie = irq_kill();
_ahb_flush_to(type);
if(type != AHB_STARLET)
_ahb_flush_to(AHB_STARLET);
irq_restore(cookie);
}
// flush device and also invalidate memory
void ahb_flush_from(enum AHBDEV dev)
{
u32 cookie = irq_kill();
u16 req = 0;
u16 ack;
int i;
switch(dev)
{
case AHB_STARLET:
case AHB_PPC:
req = 1;
break;
case AHB_AES:
case AHB_SHA1:
req = 2;
break;
case AHB_NAND:
case AHB_SDHC:
req = 8;
break;
case AHB_EHCI:
req = 4;
break;
default:
dbgprintf("ahb_flush(%d): Invalid device\n", dev);
goto done;
}
write16(MEM_FLUSHREQ, req);
for(i=0;i<1000000;i++) {
ack = read16(MEM_FLUSHACK);
_ahb_flush_to(AHB_STARLET);
if(ack == req)
break;
}
write16(MEM_FLUSHREQ, 0);
if(i>=1000000) {
dbgprintf("ahb_flush(%d): Flush (0x%x) did not ack!\n", dev, req);
}
done:
irq_restore(cookie);
}
void dc_flushrange(const void *start, u32 size)
{
u32 cookie = irq_kill();
if(size > 0x4000) {
_dc_flush();
} else {
void *end = ALIGN_FORWARD(((u8*)start) + size, LINESIZE);
start = ALIGN_BACKWARD(start, LINESIZE);
_dc_flush_entries(start, (end - start) / LINESIZE);
}
_drain_write_buffer();
ahb_flush_from(AHB_PPC);
irq_restore(cookie);
}
void dc_invalidaterange(void *start, u32 size)
{
u32 cookie = irq_kill();
void *end = ALIGN_FORWARD(((u8*)start) + size, LINESIZE);
start = ALIGN_BACKWARD(start, LINESIZE);
_dc_inval_entries(start, (end - start) / LINESIZE);
ahb_flush_to(AHB_STARLET);
irq_restore(cookie);
}
void dc_flushall(void)
{
u32 cookie = irq_kill();
_dc_flush();
_drain_write_buffer();
ahb_flush_from(AHB_PPC);
irq_restore(cookie);
}
void ic_invalidateall(void)
{
u32 cookie = irq_kill();
_ic_inval();
ahb_flush_to(AHB_STARLET);
irq_restore(cookie);
}
u32 dma_addr(void *p)
{
u32 addr = (u32)p;
switch(addr>>20) {
case 0xfff:
case 0x0d4:
case 0x0dc:
if(read32(HW_MEMMIRR) & 0x20) {
addr ^= 0x10000;
}
addr &= 0x0001FFFF;
addr |= 0x0d400000;
break;
}
dbgprintf("DMA to %p: address %08x\n", p, addr);
return addr;
}

107
memory.h Normal file
View File

@ -0,0 +1,107 @@
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include "string.h"
#include "global.h"
#include "utils.h"
#include "hollywood.h"
#include "vsprintf.h"
#define ALIGN_FORWARD(x,align) \
((typeof(x))((((u32)(x)) + (align) - 1) & (~(align-1))))
#define ALIGN_BACKWARD(x,align) \
((typeof(x))(((u32)(x)) & (~(align-1))))
enum AHBDEV {
AHB_STARLET = 0, //or MEM2 or some controller or bus or ??
AHB_PPC = 1, //ppc or something else???
AHB_NAND = 3,
AHB_AES = 4,
AHB_SHA1 = 5,
AHB_EHCI = 6,
AHB_SDHC = 9,
};
void dc_flushrange(const void *start, u32 size);
void dc_invalidaterange(void *start, u32 size);
void dc_flushall(void);
void ic_invalidateall(void);
void ahb_flush_from(enum AHBDEV dev);
void ahb_flush_to(enum AHBDEV dev);
u32 dma_addr(void *p);
static inline u32 get_cr(void)
{
u32 data;
__asm__ volatile ( "mrc\tp15, 0, %0, c1, c0, 0" : "=r" (data) );
return data;
}
static inline u32 get_ttbr(void)
{
u32 data;
__asm__ volatile ( "mrc\tp15, 0, %0, c2, c0, 0" : "=r" (data) );
return data;
}
static inline u32 get_dacr(void)
{
u32 data;
__asm__ volatile ( "mrc\tp15, 0, %0, c3, c0, 0" : "=r" (data) );
return data;
}
static inline void set_cr(u32 data)
{
__asm__ volatile ( "mcr\tp15, 0, %0, c1, c0, 0" :: "r" (data) );
}
static inline void set_ttbr(u32 data)
{
__asm__ volatile ( "mcr\tp15, 0, %0, c2, c0, 0" :: "r" (data) );
}
static inline void set_dacr(u32 data)
{
__asm__ volatile ( "mcr\tp15, 0, %0, c3, c0, 0" :: "r" (data) );
}
static inline u32 get_dfsr(void)
{
u32 data;
__asm__ volatile ( "mrc\tp15, 0, %0, c5, c0, 0" : "=r" (data) );
return data;
}
static inline u32 get_ifsr(void)
{
u32 data;
__asm__ volatile ( "mrc\tp15, 0, %0, c5, c0, 1" : "=r" (data) );
return data;
}
static inline u32 get_far(void)
{
u32 data;
__asm__ volatile ( "mrc\tp15, 0, %0, c6, c0, 0" : "=r" (data) );
return data;
}
void _ahb_flush_to(enum AHBDEV dev);
static inline void dc_inval_block_fast(void *block)
{
__asm__ volatile ( "mcr\tp15, 0, %0, c7, c6, 1" :: "r" (block) );
_ahb_flush_to(AHB_STARLET); //TODO: check if really needed and if not, remove
}
static inline void dc_flush_block_fast(void *block)
{
__asm__ volatile ( "mcr\tp15, 0, %0, c7, c10, 1" :: "r" (block) );
__asm__ volatile ( "mcr\tp15, 0, %0, c7, c10, 4" :: "r" (0) );
ahb_flush_from(AHB_PPC); //TODO: check if really needed and if not, remove
}
#endif

70
memory_asm.S Normal file
View File

@ -0,0 +1,70 @@
#define CPSR_IRQDIS 0x80
#define CPSR_FIQDIS 0x40
.arm
.globl _dc_inval_entries
.globl _dc_flush_entries
.globl _dc_flush
.globl _dc_inval
.globl _ic_inval
.globl _drain_write_buffer
.globl _tlb_inval
.globl irq_kill
.globl irq_restore
.text
irq_kill:
mrs r1, cpsr
and r0, r1, #(CPSR_IRQDIS|CPSR_FIQDIS)
orr r1, r1, #(CPSR_IRQDIS|CPSR_FIQDIS)
msr cpsr_c, r1
bx lr
irq_restore:
mrs r1, cpsr
bic r1, r1, #(CPSR_IRQDIS|CPSR_FIQDIS)
orr r1, r1, r0
msr cpsr_c, r1
bx lr
_dc_inval_entries:
mcr p15, 0, r0, c7, c6, 1
add r0, #0x20
subs r1, #1
bne _dc_inval_entries
bx lr
_dc_flush_entries:
mcr p15, 0, r0, c7, c10, 1
add r0, #0x20
subs r1, #1
bne _dc_flush_entries
bx lr
_dc_flush:
mrc p15, 0, pc, c7, c10, 3
bne _dc_flush
bx lr
_dc_inval:
mov r0, #0
mcr p15, 0, r0, c7, c6, 0
bx lr
_ic_inval:
mov r0, #0
mcr p15, 0, r0, c7, c5, 0
bx lr
_drain_write_buffer:
mov r0, #0
mcr p15, 0, r0, c7, c10, 4
bx lr
_tlb_inval:
mov r0, #0
mcr p15, 0, r0, c8, c7
bx lr

213
start.s Normal file
View File

@ -0,0 +1,213 @@
.global _start
.global start
.global udelay
.global RegWrite
.global RegRead
.global DRAMWrite
.global DRAMRead
.global DRAMCTRLRead
.global DRAMCTRLWrite
.extern main
.extern Syscall
.extern SWI
.extern PrefetchAbort
.extern DataAbort
.extern IRQHandler
.extern FIQHandler
.arm
.section ".init"
_start:
ldr pc, =start
ldr pc, =Syscall
ldr pc, =SWI
ldr pc, =PrefetchAbort
ldr pc, =DataAbort
ldr pc, =0
ldr pc, =IRQHandler
movs pc, lr
start:
mov r0, #0
ldr r1, =0xd80003c
str r0, [r1]
mov r0, #0
mcr p15, 0, r0,c7,c5
mcr p15, 0, r0,c7,c6
mrc p15, 0, r0,c1,c0
bic r0, r0, #4
bic r0, r0, #0x1000
mcr p15, 0, r0,c1,c0
ldr r0,=__bss_start
ldr r1,=__bss_end
mov r2,#0
mov r3,#4
clearbss:
cmp r0, r1
bcs clearbss_end
str r2, [r0], r3
b clearbss
clearbss_end:
msr CPSR_c, #211
ldr sp, =0xFFFF7E60
msr CPSR_c, #210
ldr sp, =0xFFFF7E60
msr CPSR_c, #209
ldr sp, =0xFFFF7E60
msr CPSR_c, #215
ldr sp, =0xFFFF7E60
msr CPSR_c, #219
ldr sp, =0xFFFF7E60
msr CPSR_c, #31
ldr sp, =0xFFFE4000
#enable IRQs
mrs r1, cpsr
bic r1, r1, #0xC0
msr cpsr_c, r1
mov lr, pc
ldr pc, =main
RegWrite:
ldr r3,=0xd8b4000
lsl r0, r0, #1
add r0, r0, r3
strh r1, [r0]
bx lr
RegRead:
ldr r3,=0xd8b4000
lsl r0, r0, #1
add r0, r0, r3
ldrh r0, [r0]
lsl r0, r0, #0x10
lsr r0, r0, #0x10
bx lr
DRAMWrite:
push {r4,lr}
add r3, r0, #0
add r4, r1, #0
mov r0, #0x3a
add r1, r3, #0
bl RegWrite
mov r0, #0x3a
bl RegRead
mov r0, #0x3b
add r1, r4, #0
bl RegWrite
pop {r4}
pop {r0}
bx r0
DRAMRead:
push {lr}
add r1, r0, #0
mov r0, #0x3a
bl RegWrite
mov r0, #0x3a
bl RegRead
mov r0, #0x3b
bl RegRead
pop {r1}
bx r1
DRAMCTRLWrite:
push {r4,r5,lr}
ldr r4, =0x163
add r3, r0, #0
add r5, r1, #0
add r0, r4, #0
add r1, r3, #0
bl DRAMWrite
add r0, r4, #0
bl DRAMRead
mov r0, #0xb1
add r1, r5, #0
lsl r0, r0, #1
bl DRAMWrite
pop {r4,r5}
pop {r0}
bx r0
DRAMCTRLRead:
push {r4,lr}
ldr r4, =0x163
add r1, r0, #0
add r0, r4, #0
bl DRAMWrite
add r0, r4, #0
bl DRAMRead
ldr r0, =0x162
bl DRAMRead
pop {r4}
pop {r1}
bx r1
udelay:
push {lr}
lsr r3, r0, #2
add r3, r3, r0
lsr r2, r0, #6
add r0, r3, r2
cmp r0, #1
bhi loc_ffff20e8
mov r0, #2
loc_ffff20e8:
ldr r1, =0xd800010
ldr r3, [r1]
add r2, r3, r0
cmp r2, r3
bls loc_ffff211c
loc_ffff20f2:
ldr r3, [r1]
cmp r3, r2
bcc loc_ffff20f2
loc_ffff20f8:
pop {r0}
bx r0
loc_ffff211c:
add r3, r1, #0
loc_ffff211e:
ldr r0, [r3]
cmp r0, #0
blt loc_ffff211e
cmp r0, r2
bcc loc_ffff211e
b loc_ffff20f8
.end

125
string.c Normal file
View File

@ -0,0 +1,125 @@
/*
* linux/lib/string.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#include "string.h"
size_t strnlen(const char *s, size_t count)
{
const char *sc;
for (sc = s; count-- && *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
size_t strlen(const char *s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
char *strncpy(char *dst, const char *src, size_t n)
{
char *ret = dst;
while (n && (*dst++ = *src++))
n--;
while (n--)
*dst++ = 0;
return ret;
}
char *strcpy(char *dst, const char *src)
{
char *ret = dst;
while ((*dst++ = *src++))
;
return ret;
}
int strcmp(const char *p, const char *q)
{
for (;;) {
unsigned char a, b;
a = *p++;
b = *q++;
if (a == 0 || a != b)
return a - b;
}
}
int strncmp(const char *p, const char *q, size_t n)
{
while (n-- != 0) {
unsigned char a, b;
a = *p++;
b = *q++;
if (a == 0 || a != b)
return a - b;
}
return 0;
}
void *memset(void *dst, int x, size_t n)
{
unsigned char *p;
for (p = dst; n; n--)
*p++ = x;
return dst;
}
//
//void udelay(u32 d)
//{
// // should be good to max .2% error
// u32 ticks = d * 19 / 10;
//
// if(ticks < 2)
// ticks = 2;
//
// u32 now = *(vu32*)0x0D800010;
//
// u32 then = now + ticks;
//
// if(then < now) {
// while(*(vu32*)0x0D800010 >= now);
// now = *(vu32*)0x0D800010;
// }
//
// while(now < then) {
// now = *(vu32*)0x0D800010;
// }
//}
int memcmp(const void *s1, const void *s2, size_t n)
{
unsigned char *us1 = (unsigned char *) s1;
unsigned char *us2 = (unsigned char *) s2;
while (n-- != 0) {
if (*us1 != *us2)
return (*us1 < *us2) ? -1 : +1;
us1++;
us2++;
}
return 0;
}
char *strchr(const char *s, int c)
{
do {
if(*s == c)
return (char *)s;
} while(*s++ != 0);
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More