Cheating:
*Due space limitations only the debug version of kenobigc is supported, this means there is a bit less space for cheats. git-svn-id: svn://localhost/Users/andi/Downloads/code/trunk@2 be6c1b03-d731-4111-a574-e37d80d43941
This commit is contained in:
parent
e635dd34dc
commit
7f75f5eb1e
949
Card.c
Normal file
949
Card.c
Normal file
@ -0,0 +1,949 @@
|
||||
#include "Card.h"
|
||||
|
||||
FIL CardStat;
|
||||
|
||||
void CardInit( void )
|
||||
{
|
||||
FILINFO f;
|
||||
u32 i,wrote;
|
||||
CARDStat CStat;
|
||||
|
||||
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( f_chdir((const TCHAR*)0) != FR_OK )
|
||||
{
|
||||
f_mkdir((const TCHAR*)0);
|
||||
f_chdir((const TCHAR*)0);
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
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( memcmp( Filename, CStat.fileName, strlen(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;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
fres = f_open( &savefile, Filename, 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 );
|
||||
|
||||
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 );
|
||||
|
||||
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;
|
||||
}
|
||||
u32 Device = 0;
|
||||
void CARDUpdateRegisters( void )
|
||||
{
|
||||
u32 read;
|
||||
|
||||
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 );
|
||||
|
||||
#ifdef ACTIVITYLED
|
||||
set32( HW_GPIO_OUT, 1<<5 );
|
||||
#endif
|
||||
|
||||
while( read32(CARD_CMD) == 0xdeadbeef );
|
||||
write32( CARD_SCMD, read32(CARD_CMD) );
|
||||
write32( CARD_CMD, 0xdeadbeef );
|
||||
|
||||
if( 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 );
|
||||
|
||||
while( read32(CARD_CONTROL) & 1 )
|
||||
clear32( CARD_CONTROL, 1 );
|
||||
|
||||
while( (read32(CARD_SSTATUS) & 0x10) != 0x10 )
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32(CARD_SRETURN) );
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
|
||||
#endif
|
||||
} 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 {
|
||||
|
||||
#ifdef CARDDEBUG
|
||||
// dbgprintf("\"%s\")", CS.fileName );
|
||||
dbgprintf("MC:CARDGetState( %d, 0x%08x, \"%s\"):0", read32(CARD_SCMD_1), P2C(read32(CARD_SCMD_2)), CS.fileName );
|
||||
#endif
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
// dbgprintf("MC:CARDGetState( %d, 0x%08x, ):%d\n", read32(CARD_SCMD_1), P2C(read32(CARD_SCMD_2)), read32( CARD_SRETURN) );
|
||||
#endif
|
||||
} 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 );
|
||||
}
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":1\n");
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_CONTROL) & 1 )
|
||||
clear32( CARD_CONTROL, 1 );
|
||||
|
||||
while( (read32(CARD_SSTATUS) & 0x10) != 0x10 )
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
|
||||
#endif
|
||||
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%u\n", read32(CARD_SRETURN) );
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%u\n", read32(CARD_SRETURN) );
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
|
||||
#endif
|
||||
} 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 );
|
||||
|
||||
while( read32(CARD_SCONTROL) & 1 )
|
||||
clear32( CARD_SCONTROL, 1 );
|
||||
|
||||
set32( CARD_SSTATUS, 0x10 );
|
||||
#ifdef CARDDEBUG
|
||||
dbgprintf(":%d\n", read32( CARD_SRETURN ) );
|
||||
#endif
|
||||
} break;
|
||||
}
|
||||
#ifdef ACTIVITYLED
|
||||
clear32( HW_GPIO_OUT, 1<<5 );
|
||||
#endif
|
||||
}
|
||||
}
|
114
Card.h
Normal file
114
Card.h
Normal file
@ -0,0 +1,114 @@
|
||||
#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"
|
||||
#ifdef TRIFORCE
|
||||
#include "JVSIOMessage.h"
|
||||
#endif
|
||||
#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
30
CardPatches.c
Normal 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
448
CheatCode.c
Normal 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
|
||||
//};
|
74
Config.c
Normal file
74
Config.c
Normal file
@ -0,0 +1,74 @@
|
||||
#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 && Cfg->Version == CONFIG_VERSION )
|
||||
{
|
||||
memcpy( DMLCfg, Cfg, sizeof( DML_CFG ) );
|
||||
|
||||
} else {
|
||||
|
||||
dbgprintf("No 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->VideoMode = DML_VID_DML_AUTO;
|
||||
DMLCfg->Version = CONFIG_VERSION;
|
||||
DMLCfg->Magicbytes = 0xD1050CF6;
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
u32 ConfigGetVideMode( void )
|
||||
{
|
||||
return DMLCfg->VideoMode;
|
||||
}
|
||||
|
||||
char *ConfigGetGamePath( void )
|
||||
{
|
||||
return DMLCfg->GamePath;
|
||||
}
|
||||
char *ConfigGetCheatPath( void )
|
||||
{
|
||||
return DMLCfg->CheatPath;
|
||||
}
|
97
Config.h
Normal file
97
Config.h
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef _CFG_
|
||||
#define _CFG_
|
||||
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "ipc.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; // 0x00000001
|
||||
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_NODISC = (1<<9),
|
||||
DML_CFG_BOOT_DISC = (1<<10),
|
||||
DML_CFG_BOOT_DOL = (1<<11),
|
||||
};
|
||||
|
||||
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 );
|
||||
u32 ConfigGetVideMode( void );
|
||||
|
||||
char *ConfigGetGamePath( void );
|
||||
char *ConfigGetCheatPath( void );
|
||||
|
||||
#endif
|
398
DVD.c
Normal file
398
DVD.c
Normal file
@ -0,0 +1,398 @@
|
||||
#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];
|
||||
|
||||
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( "Could not find any USB device!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
s32 DVDSelectGame( void )
|
||||
{
|
||||
char *str = (char*)malloca( 256, 32 );
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_GAME_PATH) )
|
||||
{
|
||||
sprintf( str, "%s", ConfigGetGamePath() );
|
||||
|
||||
} else {
|
||||
dbgprintf("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("Failed to open:\"%s\" fres:%d\n", str, fres );
|
||||
free(str);
|
||||
return -2;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
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;
|
||||
|
||||
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
29
DVD.h
Normal 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
10
DVDPatches.c
Normal 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
|
124
Drive.c
Normal file
124
Drive.c
Normal 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
16
Drive.h
Normal 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
|
42
FwritePatches.c
Normal file
42
FwritePatches.c
Normal 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
47
GCPad.h
Normal 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
|
||||
|
89
HW.h
Normal file
89
HW.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef _HW_
|
||||
#define _HW_
|
||||
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "memory.h"
|
||||
#include "ipc.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
53
Makefile
Normal 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
|
874
Patches.c
Normal file
874
Patches.c
Normal file
@ -0,0 +1,874 @@
|
||||
#include "Patches.h"
|
||||
|
||||
#include "CardPatches.c"
|
||||
#include "DVDPatches.c"
|
||||
#include "FwritePatches.c"
|
||||
#include "CheatCode.c"
|
||||
|
||||
extern u32 DOLSize;
|
||||
|
||||
unsigned char OSReportDM[] =
|
||||
{
|
||||
0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x04, 0x90, 0xE1, 0x00, 0x08, 0x3C, 0xE0, 0xC0, 0x00,
|
||||
0x90, 0x67, 0x18, 0x60, 0x90, 0x87, 0x18, 0x64, 0x90, 0xA7, 0x18, 0x68, 0x90, 0xC7, 0x18, 0x6C,
|
||||
0x90, 0xE7, 0x18, 0x70, 0x91, 0x07, 0x18, 0x74, 0x80, 0x07, 0x18, 0x60, 0x7C, 0x00, 0x18, 0x00,
|
||||
0x41, 0x82, 0xFF, 0xF8, 0x80, 0xE1, 0x00, 0x08, 0x80, 0x01, 0x00, 0x04, 0x7C, 0x08, 0x03, 0xA6,
|
||||
0x4E, 0x80, 0x00, 0x20,
|
||||
} ;
|
||||
// Audio streaming replacement functions copied from Swiss r92
|
||||
u32 __dvdLowAudioStatusNULL[17] = {
|
||||
// execute function(1); passed in on r4
|
||||
0x9421FFC0, // stwu sp, -0x0040 (sp)
|
||||
0x7C0802A6, // mflr r0
|
||||
0x90010000, // stw r0, 0 (sp)
|
||||
0x7C8903A6, // mtctr r4
|
||||
0x3C80CC00, // lis r4, 0xCC00
|
||||
0x2E830000, // cmpwi cr5, r3, 0
|
||||
0x4196000C, // beq- cr5, +0xC ?
|
||||
0x38600001, // li r3, 1
|
||||
0x48000008, // b +0x8 ?
|
||||
0x38600000, // li r3, 0
|
||||
0x90646020, // stw r3, 0x6020 (r4)
|
||||
0x38600001, // li r3, 1
|
||||
0x4E800421, // bctrl
|
||||
0x80010000, // lwz r0, 0 (sp)
|
||||
0x7C0803A6, // mtlr r0
|
||||
0x38210040, // addi sp, sp, 64
|
||||
0x4E800020 // blr
|
||||
};
|
||||
|
||||
u32 __dvdLowAudioConfigNULL[10] = {
|
||||
// execute callback(1); passed in on r5 without actually touching the drive!
|
||||
0x9421FFC0, // stwu sp, -0x0040 (sp)
|
||||
0x7C0802A6, // mflr r0
|
||||
0x90010000, // stw r0, 0 (sp)
|
||||
0x7CA903A6, // mtctr r5
|
||||
0x38600001, // li r3, 1
|
||||
0x4E800421, // bctrl
|
||||
0x80010000, // lwz r0, 0 (sp)
|
||||
0x7C0803A6, // mtlr r0
|
||||
0x38210040, // addi sp, sp, 64
|
||||
0x4E800020 // blr
|
||||
};
|
||||
|
||||
u32 __dvdLowReadAudioNULL[] = {
|
||||
// execute callback(1); passed in on r6 without actually touching the drive!
|
||||
0x9421FFC0, // stwu sp, -0x0040 (sp)
|
||||
0x7C0802A6, // mflr r0
|
||||
0x90010000, // stw r0, 0 (sp)
|
||||
0x7CC903A6, // mtctr r6
|
||||
0x38600001, // li r3, 1
|
||||
0x4E800421, // bctr;
|
||||
0x80010000, // lwz r0, 0 (sp)
|
||||
0x7C0803A6, // mtlr r0
|
||||
0x38210040, // addi sp, sp, 64
|
||||
0x4E800020
|
||||
};
|
||||
|
||||
u32 __GXSetVAT_patch[31] = {
|
||||
/*0x8122ce00,*/ 0x39400000, 0x896904f2, 0x7d284b78,
|
||||
0x556007ff, 0x41820050, 0x38e00008, 0x3cc0cc01,
|
||||
0x98e68000, 0x61400070, 0x61440080, 0x61430090,
|
||||
0x98068000, 0x38000000, 0x80a8001c, 0x90a68000,
|
||||
0x98e68000, 0x98868000, 0x8088003c, 0x90868000,
|
||||
0x98e68000, 0x98668000, 0x8068005c, 0x90668000,
|
||||
0x98068000, 0x556bf87f, 0x394a0001, 0x39080004,
|
||||
0x4082ffa0, 0x38000000, 0x980904f2, 0x4e800020
|
||||
};
|
||||
|
||||
|
||||
FuncPattern FPatterns[] =
|
||||
{
|
||||
{ 0xCC, 17, 10, 5, 3, 2, DVDInquiryAsync, sizeof(DVDInquiryAsync), "DVDInquiryAsync", 0, 0 },
|
||||
{ 0xC8, 16, 9, 5, 3, 3, DVDSeekAbsAsyncPrio, sizeof(DVDSeekAbsAsyncPrio), "DVDSeekAbsAsyncPrio", 0, 0 },
|
||||
{ 0xD4, 13, 8, 11, 2, 7, (u8*)NULL, 0xdead0004, "AIResetStreamSampleCount", 0, 0 },
|
||||
|
||||
{ 0x94, 18, 10, 2, 0, 2, (u8*)__dvdLowReadAudioNULL, sizeof(__dvdLowReadAudioNULL), "DVDLowReadAudio", 0, 0 },
|
||||
{ 0x88, 18, 8, 2, 0, 2, (u8*)__dvdLowAudioStatusNULL, sizeof(__dvdLowAudioStatusNULL), "DVDLowAudioStatus", 0, 0 },
|
||||
{ 0x98, 19, 8, 2, 1, 3, (u8*)__dvdLowAudioConfigNULL, sizeof(__dvdLowAudioConfigNULL), "DVDLowAudioConfig", 0, 0 },
|
||||
|
||||
{ 0x308, 40, 18, 10, 23, 17, patch_fwrite_GC, sizeof(patch_fwrite_GC), "__fwrite A", 1, 0 },
|
||||
{ 0x338, 48, 20, 10, 24, 16, patch_fwrite_GC, sizeof(patch_fwrite_GC), "__fwrite B", 1, 0 },
|
||||
{ 0x2D8, 41, 17, 8, 21, 13, patch_fwrite_GC, sizeof(patch_fwrite_GC), "__fwrite C", 1, 0 },
|
||||
|
||||
{ 0x98, 8, 3, 0, 3, 5, (u8*)NULL, 0xdead0001, "__GXSetVAT", 0, 0 },
|
||||
|
||||
{ 0x3A8, 86, 13, 27, 17, 24, (u8*)NULL, 0xdead000B, "PADRead A", 2, 0 },
|
||||
{ 0x2FC, 73, 8, 23, 16, 15, (u8*)NULL, 0xdead000B, "PADRead B", 2, 0 },
|
||||
{ 0x3B0, 87, 13, 27, 17, 25, (u8*)NULL, 0xdead000B, "PADRead C", 2, 0 },
|
||||
{ 0x334, 78, 7, 20, 17, 19, (u8*)NULL, 0xdead000B, "PADRead D", 2, 0 },
|
||||
|
||||
};
|
||||
|
||||
FuncPattern CPatterns[] =
|
||||
{
|
||||
{ 0x14C, 28, 12, 7, 12, 4, CARDFreeBlocks, sizeof(CARDFreeBlocks), "CARDFreeBlocks A", 1, 0 },
|
||||
{ 0x11C, 24, 10, 7, 10, 4, CARDFreeBlocks, sizeof(CARDFreeBlocks), "CARDFreeBlocks B", 1, 0 },
|
||||
{ 0xC0, 22, 5, 2, 5, 10, CARDGetSerialNo, sizeof(CARDGetSerialNo),"CARDGetSerialNo", 0, 0 },
|
||||
{ 0x84, 12, 5, 3, 4, 2, CARDGetEncoding, sizeof(CARDGetEncoding),"CARDGetEncoding", 0, 0 },
|
||||
{ 0x80, 11, 5, 3, 4, 2, CARDGetMemSize, sizeof(CARDGetMemSize), "CARDGetMemSize", 0, 0 },
|
||||
|
||||
{ 0x94, 11, 6, 3, 5, 4, __CARDSync, sizeof(__CARDSync), "__CARDSync", 0, 0 },
|
||||
{ 0x50, 6, 3, 2, 2, 2, CARDCheck, sizeof(CARDCheck), "CARDCheck", 0, 0 },
|
||||
//{ 0x24, 4, 2, 1, 0, 2, CARDCheckAsync, sizeof(CARDCheckAsync), "CARDCheckAsync", 0, 0 },
|
||||
{ 0x58C, 82, 11, 18, 41, 57, CARDCheckEX, sizeof(CARDCheckEX), "CARDCheckExAsync", 0, 0 },
|
||||
{ 0x34, 4, 2, 1, 2, 2, CARDProbe, sizeof(CARDProbe), "CARDProbe", 2, 0 },
|
||||
//{ 0x1C, 2, 2, 1, 0, 2, CARDProbe, sizeof(CARDProbe), "CARDProbe B", 2, 0 }, //This is causing more trouble than a hack...
|
||||
{ 0x178, 20, 6, 6, 20, 4, CARDProbeEX, sizeof(CARDProbeEX), "CARDProbeEx A", 3, 0 },
|
||||
{ 0x198, 22, 6, 5, 19, 4, CARDProbeEX, sizeof(CARDProbeEX), "CARDProbeEx B", 3, 0 },
|
||||
{ 0x160, 17, 6, 5, 18, 4, CARDProbeEX, sizeof(CARDProbeEX), "CARDProbeEx C", 3, 0 },
|
||||
{ 0x19C, 32, 14, 11, 12, 3, CARDMountAsync, sizeof(CARDMountAsync), "CARDMountAsync A", 4, 0 },
|
||||
{ 0x184, 30, 14, 11, 10, 3, CARDMountAsync, sizeof(CARDMountAsync), "CARDMountAsync B", 4, 0 },
|
||||
{ 0xA8, 15, 8, 6, 3, 2, CARDCheck, sizeof(CARDCheck), "CARDUnMount", 0, 0 },
|
||||
|
||||
{ 0x174, 23, 6, 7, 14, 5, CARDOpen, sizeof(CARDOpen), "CARDOpen A", 5, 0 },
|
||||
{ 0x118, 14, 6, 6, 11, 4, CARDOpen, sizeof(CARDOpen), "CARDOpen B", 5, 0 },
|
||||
{ 0x170, 23, 6, 7, 14, 5, CARDOpen, sizeof(CARDOpen), "CARDOpen C", 5, 0 },
|
||||
{ 0x15C, 27, 6, 5, 15, 6, CARDFastOpen, sizeof(CARDFastOpen), "CARDFastOpen A", 11, 0 },
|
||||
{ 0x100, 20, 10, 4, 10, 4, CARDFastOpen, sizeof(CARDFastOpen), "CARDFastOpen B", 11, 0 },
|
||||
{ 0x50, 8, 4, 2, 2, 3, CARDClose, sizeof(CARDClose), "CARDClose", 0, 0 },
|
||||
{ 0x21C, 44, 6, 13, 19, 12, CARDCreate, sizeof(CARDCreate), "CARDCreateAsync A", 6, 0 },
|
||||
{ 0x214, 42, 6, 13, 19, 12, CARDCreate, sizeof(CARDCreate), "CARDCreateAsync B", 6, 0 },
|
||||
{ 0x10C, 25, 6, 9, 9, 5, CARDDelete, sizeof(CARDDelete), "CARDDeleteAsync A", 12, 0 },
|
||||
{ 0x10C, 25, 6, 9, 9, 5, CARDDelete, sizeof(CARDDelete), "CARDDeleteAsync C", 12, 0 },
|
||||
{ 0x128, 24, 7, 9, 12, 5, CARDFastDelete, sizeof(CARDFastDelete), "CARDFastDelete", 0, 0 },
|
||||
{ 0x144, 27, 3, 8, 10, 9, CARDRead, sizeof(CARDRead), "CARDReadAsync A", 7, 0 },
|
||||
{ 0x140, 30, 7, 7, 10, 10, CARDRead, sizeof(CARDRead), "CARDReadAsync B", 7, 0 },
|
||||
{ 0x140, 27, 3, 8, 10, 9, CARDRead, sizeof(CARDRead), "CARDReadAsync C", 7, 0 },
|
||||
{ 0x110, 24, 4, 8, 9, 6, CARDWrite, sizeof(CARDWrite), "CARDWriteAsync A", 8, 0 },
|
||||
{ 0x10C, 23, 4, 8, 9, 6, CARDWrite, sizeof(CARDWrite), "CARDWriteAsync B", 8, 0 },
|
||||
{ 0x1F8, 37, 3, 17, 18, 9, CARDRename, sizeof(CARDRename), "CARDRenameAsync", 0, 0 },
|
||||
{ 0x128, 25, 9, 9, 6, 5, CARDGetStats, sizeof(CARDGetStats), "CARDGetStatus A", 9, 0 },
|
||||
{ 0x110, 25, 9, 8, 6, 5, CARDGetStats, sizeof(CARDGetStats), "CARDGetStatus B", 9, 0 },
|
||||
{ 0x124, 25, 9, 9, 6, 5, CARDGetStats, sizeof(CARDGetStats), "CARDGetStatus C", 9, 0 },
|
||||
{ 0x170, 29, 9, 9, 12, 5, CARDSetStats, sizeof(CARDSetStats), "CARDSetStatusAsync A", 10, 0 },
|
||||
{ 0x16C, 29, 9, 9, 12, 5, CARDSetStats, sizeof(CARDSetStats), "CARDSetStatusAsync B", 10, 0 },
|
||||
};
|
||||
|
||||
u32 CardLowestOff = 0;
|
||||
|
||||
|
||||
void PatchB( u32 dst, u32 src )
|
||||
{
|
||||
u32 newval = (dst - src);
|
||||
newval&= 0x03FFFFFC;
|
||||
newval|= 0x48000000;
|
||||
write32( src, newval );
|
||||
}
|
||||
void PatchBL( u32 dst, u32 src )
|
||||
{
|
||||
u32 newval = (dst - src);
|
||||
newval&= 0x03FFFFFC;
|
||||
newval|= 0x48000001;
|
||||
write32( src, newval );
|
||||
}
|
||||
void MPattern( u8 *Data, u32 Length, FuncPattern *FunctionPattern )
|
||||
{
|
||||
u32 i;
|
||||
|
||||
memset( FunctionPattern, 0, sizeof(FuncPattern) );
|
||||
|
||||
for( i = 0; i < Length; i+=4 )
|
||||
{
|
||||
u32 word = read32( (u32)Data + i );
|
||||
|
||||
if( (word & 0xFC000003) == 0x48000001 )
|
||||
FunctionPattern->FCalls++;
|
||||
|
||||
if( (word & 0xFC000003) == 0x48000000 )
|
||||
FunctionPattern->Branch++;
|
||||
if( (word & 0xFFFF0000) == 0x40800000 )
|
||||
FunctionPattern->Branch++;
|
||||
if( (word & 0xFFFF0000) == 0x41800000 )
|
||||
FunctionPattern->Branch++;
|
||||
if( (word & 0xFFFF0000) == 0x40810000 )
|
||||
FunctionPattern->Branch++;
|
||||
if( (word & 0xFFFF0000) == 0x41820000 )
|
||||
FunctionPattern->Branch++;
|
||||
|
||||
if( (word & 0xFC000000) == 0x80000000 )
|
||||
FunctionPattern->Loads++;
|
||||
if( (word & 0xFF000000) == 0x38000000 )
|
||||
FunctionPattern->Loads++;
|
||||
if( (word & 0xFF000000) == 0x3C000000 )
|
||||
FunctionPattern->Loads++;
|
||||
|
||||
if( (word & 0xFC000000) == 0x90000000 )
|
||||
FunctionPattern->Stores++;
|
||||
if( (word & 0xFC000000) == 0x94000000 )
|
||||
FunctionPattern->Stores++;
|
||||
|
||||
if( (word & 0xFF000000) == 0x7C000000 )
|
||||
FunctionPattern->Moves++;
|
||||
|
||||
if( word == 0x4E800020 )
|
||||
break;
|
||||
}
|
||||
|
||||
FunctionPattern->Length = i;
|
||||
}
|
||||
bool CPattern( FuncPattern *FPatA, FuncPattern *FPatB )
|
||||
{
|
||||
if( memcmp( FPatA, FPatB, sizeof(u32) * 6 ) == 0 )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void DoCardPatches( char *ptr, u32 size, u32 SectionOffset )
|
||||
{
|
||||
u32 i,j,k,offset,fail,FoundCardFuncStart=0;
|
||||
|
||||
dbgprintf("DoCardPatches( 0x%p, %d, 0x%X)\n", ptr, size, SectionOffset );
|
||||
|
||||
for( i=0; i < size; i+=4 )
|
||||
{
|
||||
if( read32( (u32)ptr + i) == 0x7C630214 && read32( (u32)ptr + i + 4) == 0x806300B8 )
|
||||
{
|
||||
dbgprintf("Found [CARDGetXferredBytes] @ 0x%08X\n", (u32)ptr + i - 12 );
|
||||
memcpy( ptr + i - 12, CARDGetXferredBytes, sizeof(CARDGetXferredBytes) );
|
||||
}
|
||||
|
||||
if( read32( (u32)ptr + i ) != 0x7C0802A6 ) // MFLR
|
||||
continue;
|
||||
|
||||
FuncPattern fp;
|
||||
MPattern( (u8*)(ptr+i), size, &fp );
|
||||
|
||||
for( j=0; j < sizeof(CPatterns)/sizeof(FuncPattern); ++j )
|
||||
{
|
||||
if( CPatterns[j].PatchLength == 0 )
|
||||
continue;
|
||||
|
||||
if( CPatterns[j].Found ) // Skip already found patches
|
||||
continue;
|
||||
|
||||
if( CPattern( &fp, &(CPatterns[j]) ) )
|
||||
{
|
||||
if( CPatterns[j].Patch == CARDFreeBlocks )
|
||||
{
|
||||
if( CardLowestOff == 0 )
|
||||
{
|
||||
dbgprintf("CardLowestOff:0x%08X\n", i );
|
||||
CardLowestOff = i;
|
||||
}
|
||||
|
||||
//Check for CARDGetResultCode which is always (when used) above CARDFreeBlocks
|
||||
if( read32( (u32)ptr + i - 0x30 ) == 0x2C030000 )
|
||||
{
|
||||
dbgprintf("Found [CARDGetResultCode] @ 0x%08X\n", (u32)ptr + i - 0x30 + SectionOffset );
|
||||
memcpy( ptr + i - 0x30, CARDGetResultCode, sizeof(CARDGetResultCode) );
|
||||
}
|
||||
|
||||
FoundCardFuncStart = 1;
|
||||
}
|
||||
|
||||
if( FoundCardFuncStart == 0 )
|
||||
continue;
|
||||
|
||||
dbgprintf("Found [%s] @ 0x%08X\n", CPatterns[j].Name, (u32)ptr + i + SectionOffset );
|
||||
CPatterns[j].Found = (u32)ptr + i;
|
||||
|
||||
// If this is a patch group set all others of this group as found aswell
|
||||
if( CPatterns[j].Group )
|
||||
{
|
||||
for( k=0; k < sizeof(CPatterns)/sizeof(FuncPattern); ++k )
|
||||
{
|
||||
if( CPatterns[k].Group == CPatterns[j].Group )
|
||||
{
|
||||
if( !CPatterns[k].Found ) //Don't overwrite the offset!
|
||||
CPatterns[k].Found = -1; // Usually this holds the offset, to determinate it from a REALLY found pattern we set it -1 which still counts a logical TRUE
|
||||
|
||||
//dbgprintf("Setting [%s] to found!\n", CPatterns[k].Name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If by now no CARDProbe is found it won't be so set it to found to prevent CARDProbe B false hits
|
||||
if( CPatterns[j].Patch == CARDRead )
|
||||
{
|
||||
for( k=0; k < sizeof(CPatterns)/sizeof(FuncPattern); ++k )
|
||||
{
|
||||
if( CPatterns[k].Patch == CARDProbe )
|
||||
{
|
||||
if( !CPatterns[k].Found ) //Don't overwrite the offset!
|
||||
CPatterns[k].Found = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( strstr( CPatterns[j].Name, "Async" ) != NULL )
|
||||
{
|
||||
//dbgprintf("Async!\n");
|
||||
|
||||
//Most games only use the normal functions so we patch a branch over to async and clear the CB
|
||||
//Find function call to our function
|
||||
|
||||
offset = (u32)ptr + i;
|
||||
fail = 0;
|
||||
|
||||
while(fail < 3)
|
||||
{
|
||||
//dbgprintf("[%08X] %08X %08X(%08X)\n", offset, read32( offset ) & 0xFC000003,read32( offset ) & 0x03FFFFFC ,(read32( offset ) & 0x03FFFFFC ) + offset);
|
||||
if( (read32( offset ) & 0xFC000003 ) == 0x48000001 )
|
||||
{
|
||||
if( (((read32( offset ) & 0x03FFFFFC ) + offset) & 0x03FFFFFC) == (u32)ptr+i )
|
||||
break;
|
||||
}
|
||||
|
||||
if( read32( offset ) == 0x4E800020 )
|
||||
fail++;
|
||||
|
||||
offset+=4;
|
||||
}
|
||||
|
||||
if( fail < 3 )
|
||||
{
|
||||
dbgprintf("Found function call to [%s] @ 0x%08X\n", CPatterns[j].Name, offset + SectionOffset );
|
||||
|
||||
//Now find function start
|
||||
offset -= 4;
|
||||
while(1)
|
||||
{
|
||||
if( read32( offset ) == 0x7C0802A6 )
|
||||
break;
|
||||
|
||||
offset-=4;
|
||||
}
|
||||
|
||||
dbgprintf("Found function start of [%s(Sync)] @ 0x%08X\n", CPatterns[j].Name, offset + SectionOffset );
|
||||
|
||||
//This patches a li rX, 0 before the Async function call for the Sync call
|
||||
//Since this register of the cb is different per function we do this haxx
|
||||
if( (read32( offset + 0x04 ) & 0x0000F000 ) == 0x00008000 ) // lis
|
||||
{
|
||||
write32( offset, read32( offset + 0x0C ) & 0xFBE00000 );
|
||||
|
||||
//Forge a branch to the async function
|
||||
|
||||
offset += 4;
|
||||
|
||||
u32 newval = ((u32)ptr + i) - offset;
|
||||
newval&= 0x03FFFFFC;
|
||||
newval|= 0x48000000;
|
||||
write32( offset, newval );
|
||||
} else {
|
||||
dbgprintf("Unhandled Async cb case!\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
dbgprintf("No sync function found!\n");
|
||||
}
|
||||
|
||||
memcpy( ptr + i, CPatterns[j].Patch, CPatterns[j].PatchLength );
|
||||
|
||||
} else {
|
||||
memcpy( ptr + i, CPatterns[j].Patch, CPatterns[j].PatchLength );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( j=0; j < sizeof(CPatterns)/sizeof(FuncPattern); ++j )
|
||||
{
|
||||
if( CPatterns[j].Found == 0 )
|
||||
dbgprintf("Pattern %s not found!\n", CPatterns[j].Name );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
void DoPatches( char *ptr, u32 size, u32 SectionOffset )
|
||||
{
|
||||
u32 i=0,j=0,k=0,value;
|
||||
u32 PatchCount = 0;
|
||||
|
||||
dbgprintf("DoPatches( 0x%p, %d, 0x%X)\n", ptr, size, SectionOffset );
|
||||
|
||||
// HACK: PokemonXD and Pokemon Colosseum low memory clear patch
|
||||
if(( (read32(0)>>8) == 0x475858 ) || ( (read32(0)>>8) == 0x474336 ))
|
||||
{
|
||||
// patch out initial memset(0x1800, 0, 0x1800)
|
||||
if( (read32(0) & 0xFF) == 0x4A ) // JAP
|
||||
write32( 0x560C, 0x60000000 );
|
||||
else // EUR/USA
|
||||
write32( 0x5614, 0x60000000 );
|
||||
|
||||
// patch memset to jump to test function
|
||||
write32(0x00005498, 0x4BFFABF0);
|
||||
|
||||
// patch in test < 0x3000 function
|
||||
write32(0x00000088, 0x3D008000);
|
||||
write32(0x0000008C, 0x61083000);
|
||||
write32(0x00000090, 0x7C044000);
|
||||
write32(0x00000094, 0x4180542C);
|
||||
write32(0x00000098, 0x90E40004);
|
||||
write32(0x0000009C, 0x48005400);
|
||||
|
||||
// skips __start init of debugger mem
|
||||
write32(0x00003194, 0x48000028);
|
||||
}
|
||||
|
||||
|
||||
// Reset Found
|
||||
for( k=0; k < sizeof(FPatterns)/sizeof(FuncPattern); ++k )
|
||||
FPatterns[k].Found = 0;
|
||||
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_NMM) )
|
||||
DoCardPatches( ptr, size, SectionOffset );
|
||||
|
||||
//Note: ORing the values prevents an early break out when a single patterns has multiple hits
|
||||
PatchCount=0;
|
||||
|
||||
for( i=0; i < size; i+=4 )
|
||||
{
|
||||
if( (PatchCount & 1) == 0 )
|
||||
{
|
||||
if( read32( (u32)ptr + i ) == 0x3C00A800 ) // Loader
|
||||
{
|
||||
int j=0;
|
||||
while( read32( (u32)ptr + i - j ) != 0x7C0802A6 ) // Seek to start of function
|
||||
j+=4;
|
||||
|
||||
//Check if there is a lis %rX, 0xCC00 in this function
|
||||
//At least Sunshine has one false hit on lis r3,0xA800
|
||||
int k=0;
|
||||
while( 1 )
|
||||
{
|
||||
if( read32( (u32)ptr + i + k - j ) == 0x4E800020 )
|
||||
break;
|
||||
|
||||
if( (read32( (u32)ptr + i + k - j ) & 0xF81FFFFF) == 0x3800CC00 )
|
||||
break;
|
||||
|
||||
k += 4;
|
||||
}
|
||||
|
||||
if( read32( (u32)ptr + i + k - j ) == 0x4E800020 )
|
||||
{
|
||||
//dbgprintf("Patch:No 0xCC00 found around:%08X\n", (u32)ptr+i);
|
||||
continue;
|
||||
}
|
||||
|
||||
k = 0;
|
||||
while(1)
|
||||
{
|
||||
u32 val = read32( (u32)ptr + i + k );
|
||||
|
||||
if( (val & 0xFFFF ) == 0xCC00 )
|
||||
{
|
||||
write32( (u32)ptr + i + k, (val&0xFFFF0000) | 0xC000 );
|
||||
//dbgprintf("Patch:lis 0x%08X\n", (u32)ptr + i + k + SectionOffset );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (val & 0xFC00FF00) == 0x90006000 )
|
||||
{
|
||||
write32( (u32)ptr + i + k, (val&0xFFFF00FF) | 0x2F00 );
|
||||
//dbgprintf("Patch:stw 0x%08X\n", (u32)ptr + i + k + SectionOffset );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( read32( (u32)ptr + i + k ) == 0x4E800020 )
|
||||
break;
|
||||
|
||||
k+=4;
|
||||
}
|
||||
|
||||
write32( (u32)ptr + i, 0x3C00A700 );
|
||||
|
||||
dbgprintf("Patch:Found [DVDLowRead]: 0x%08X\n", (u32)ptr + i + SectionOffset );
|
||||
|
||||
PatchCount |= 1;
|
||||
|
||||
} else if( read32( (u32)ptr + i ) == 0x3C60A800 ) // Games
|
||||
{
|
||||
int j=0;
|
||||
while( read32( (u32)ptr + i - j ) != 0x7C0802A6 ) // Seek to start of function
|
||||
j+=4;
|
||||
|
||||
//Check if there is a lis %rX, 0xCC00 in this function
|
||||
//At least Sunshine has one false hit on lis r3,0xA800
|
||||
int k=0;
|
||||
while( 1 )
|
||||
{
|
||||
if( read32( (u32)ptr + i + k - j ) == 0x4E800020 )
|
||||
break;
|
||||
if( (read32( (u32)ptr + i + k - j ) & 0xF81FFFFF) == 0x3800CC00 )
|
||||
{
|
||||
write32( (u32)ptr + i + k - j, (read32((u32)ptr + i + k - j) & 0xFFFF0000) | 0xC000 );
|
||||
break;
|
||||
}
|
||||
|
||||
k += 4;
|
||||
}
|
||||
|
||||
if( read32( (u32)ptr + i + k - j ) == 0x4E800020 )
|
||||
{
|
||||
//dbgprintf("Patch:No 0xCC00 found around:%08X\n", (u32)ptr+i);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Search addi 0x6000
|
||||
while( 1 )
|
||||
{
|
||||
if( read32( (u32)ptr + i + k - j ) == 0x4E800020 )
|
||||
break;
|
||||
if( (read32( (u32)ptr + i + k - j ) & 0xFFFF) == 0x6000 )
|
||||
{
|
||||
write32( (u32)ptr + i + k - j, (read32((u32)ptr + i + k - j) & 0xFFFF0000) | 0x2F00 );
|
||||
break;
|
||||
}
|
||||
|
||||
k += 4;
|
||||
|
||||
}
|
||||
|
||||
if( read32( (u32)ptr + i + k - j ) == 0x4E800020 )
|
||||
{
|
||||
//dbgprintf("Patch:No 0xCC00 found around:%08X\n", (u32)ptr+i);
|
||||
continue;
|
||||
}
|
||||
|
||||
write32( (u32)ptr + i, 0x3C60A700 );
|
||||
|
||||
dbgprintf("Patch:Found [DVDLowRead]: 0x%08X\n", (u32)ptr + i + SectionOffset );
|
||||
|
||||
PatchCount |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( (PatchCount & 2) == 0 )
|
||||
if( (read32( (u32)ptr + i )&0xFC00FFFF) == 0x5400077A &&
|
||||
(read32( (u32)ptr + i + 4 )&0xFC00FFFF) == 0x28000000 &&
|
||||
read32( (u32)ptr + i + 8 ) == 0x41820008 &&
|
||||
(read32( (u32)ptr + i +12 )&0xFC00FFFF) == 0x64002000
|
||||
)
|
||||
{
|
||||
dbgprintf("Patch:Found [__OSDispatchInterrupt]: 0x%08X 0x%08X\n", (u32)ptr + i + 0 + SectionOffset, (u32)ptr + i + 0x1A8 + SectionOffset );
|
||||
|
||||
write32( (u32)ptr + i + 0, (read32( (u32)ptr + i + 0 ) & 0xFFFF0000) | 0x0463 );
|
||||
write32( (u32)ptr + i + 0x1A8, (read32( (u32)ptr + i + 0x1A8 ) & 0xFFFF0000) | 0x0463 );
|
||||
|
||||
PatchCount |= 2;
|
||||
}
|
||||
|
||||
if( (PatchCount & 4) == 0 )
|
||||
if( read32( (u32)ptr + i ) == 0x5480056A &&
|
||||
read32( (u32)ptr + i + 4 ) == 0x28000000 &&
|
||||
read32( (u32)ptr + i + 8 ) == 0x40820008 &&
|
||||
(read32( (u32)ptr + i +12 )&0xFC00FFFF) == 0x60000004
|
||||
)
|
||||
{
|
||||
dbgprintf("Patch:Found [SetInterruptMask]: 0x%08X\n", (u32)ptr + i + 12 + SectionOffset );
|
||||
|
||||
write32( (u32)ptr + i + 12, (read32( (u32)ptr + i + 12 ) & 0xFFFF0000) | 0x4000 );
|
||||
|
||||
PatchCount |= 4;
|
||||
}
|
||||
|
||||
if( (PatchCount & 8) == 0 )
|
||||
if( (read32( (u32)ptr + i + 0 ) & 0xFFFF) == 0x6000 &&
|
||||
(read32( (u32)ptr + i + 4 ) & 0xFFFF) == 0x002A &&
|
||||
(read32( (u32)ptr + i + 8 ) & 0xFFFF) == 0x0054
|
||||
)
|
||||
{
|
||||
u32 Offset = (u32)ptr + i - 8;
|
||||
|
||||
dbgprintf("Patch:Found [__DVDIntrruptHandler]: 0x%08X\n", Offset + SectionOffset );
|
||||
|
||||
if( (read32(Offset+4) & 0xFFFF) == 0xCC00 ) // Loader
|
||||
{
|
||||
value = *(vu32*)(Offset+4);
|
||||
value&= 0xFFFF0000;
|
||||
value|= 0x0000C000;
|
||||
*(vu32*)(Offset+4) = value;
|
||||
|
||||
} else {
|
||||
|
||||
value = *(vu32*)Offset;
|
||||
value&= 0xFFFF0000;
|
||||
value|= 0x0000C000;
|
||||
*(vu32*)Offset = value;
|
||||
}
|
||||
|
||||
Offset += 8;
|
||||
|
||||
value = *(vu32*)Offset;
|
||||
value&= 0xFFFF0000;
|
||||
value|= 0x00002F30;
|
||||
*(vu32*)Offset = value;
|
||||
|
||||
Offset += 20;
|
||||
|
||||
dbgprintf("Patch:[__DVDInterruptHandler] 0x%08X\n", Offset + SectionOffset );
|
||||
*(vu32*)Offset = 0x3D00CD00; Offset += 4;
|
||||
*(vu32*)Offset = 0x38000034; Offset += 4;
|
||||
*(vu32*)Offset = 0x90080004; Offset +=16;
|
||||
|
||||
dbgprintf("Patch:[__DVDInterruptHandler] 0x%08X\n", Offset + SectionOffset );
|
||||
*(vu32*)Offset = 0x3D00CD00; Offset += 4;
|
||||
*(vu32*)Offset = 0x3C004000; Offset += 4;
|
||||
*(vu32*)Offset = 0x90080030; Offset +=32;
|
||||
|
||||
if( (read32(Offset-8) & 0xFFFF) == 0xCC00 ) // Loader
|
||||
{
|
||||
Offset -= 8;
|
||||
}
|
||||
|
||||
dbgprintf("Patch:[__DVDInterruptHandler] 0x%08X\n", Offset + SectionOffset );
|
||||
|
||||
value = *(vu32*)Offset;
|
||||
value&= 0xFFFF0000;
|
||||
value|= 0x0000C000;
|
||||
*(vu32*)Offset = value;
|
||||
|
||||
Offset += 4;
|
||||
|
||||
value = *(vu32*)Offset;
|
||||
value&= 0xFFFF0000;
|
||||
value|= 0x00002F08;
|
||||
*(vu32*)Offset = value;
|
||||
|
||||
PatchCount |= 8;
|
||||
}
|
||||
|
||||
if( (PatchCount & 32) == 0 )
|
||||
{
|
||||
if( (read32( (u32)ptr + i + 0 ) & 0xFFFF) == 0xCC00 && // Game
|
||||
(read32( (u32)ptr + i + 4 ) & 0xFFFF) == 0x6000 &&
|
||||
(read32( (u32)ptr + i +12 ) & 0xFFFF) == 0x001C
|
||||
)
|
||||
{
|
||||
u32 Offset = (u32)ptr + i;
|
||||
|
||||
dbgprintf("Patch:[cbForStateBusy] 0x%08X\n", Offset + SectionOffset );
|
||||
|
||||
write32( Offset, 0x3C80C000 );
|
||||
write32( Offset+4, 0x38842F30 );
|
||||
|
||||
PatchCount |= 32;
|
||||
|
||||
} else if( (read32( (u32)ptr + i + 0 ) & 0xFFFF) == 0xCC00 && // Loader
|
||||
(read32( (u32)ptr + i + 4 ) & 0xFFFF) == 0x6018 &&
|
||||
(read32( (u32)ptr + i +12 ) & 0xFFFF) == 0x001C
|
||||
)
|
||||
{
|
||||
u32 Offset = (u32)ptr + i;
|
||||
|
||||
dbgprintf("Patch:[cbForStateBusy] 0x%08X\n", Offset + SectionOffset );
|
||||
|
||||
write32( Offset, 0x3C60C000 );
|
||||
write32( Offset+4, 0x80832F48 );
|
||||
|
||||
PatchCount |= 32;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_CHEATS) || ConfigGetConfig( DML_CFG_DEBUGGER ) )
|
||||
{
|
||||
// OSSleepThread(Pattern 1)
|
||||
if( (PatchCount & 16) == 0 )
|
||||
if( read32((u32)ptr + i + 0 ) == 0x3C808000 &&
|
||||
( read32((u32)ptr + i + 4 ) == 0x38000004 || read32((u32)ptr + i + 4 ) == 0x808400E4 ) &&
|
||||
( read32((u32)ptr + i + 8 ) == 0x38000004 || read32((u32)ptr + i + 8 ) == 0x808400E4 )
|
||||
)
|
||||
{
|
||||
int j = 12;
|
||||
|
||||
while( read32((u32)ptr + i + j ) != 0x4E800020 )
|
||||
j+=4;
|
||||
|
||||
dbgprintf("Patch:[Hook:OSSleepThread] at 0x%08X\n", ((u32)ptr + i + j) | 0x80000000 );
|
||||
|
||||
u32 DBGSize;
|
||||
|
||||
//if( ConfigGetConfig( DML_CFG_DEBUGGER ) )
|
||||
//{
|
||||
memcpy( (void*)0x1800, kenobigcDBG, sizeof(kenobigcDBG) );
|
||||
DBGSize = sizeof(kenobigcDBG);
|
||||
//} else {
|
||||
// memcpy( (void*)0x1800, kenobigc, sizeof(kenobigc) );
|
||||
// DBGSize = sizeof(kenobigc);
|
||||
//}
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_DEBUGWAIT) )
|
||||
write32( P2C(read32(0x1808)), 1 );
|
||||
else
|
||||
write32( P2C(read32(0x1808)), 0 );
|
||||
|
||||
u32 newval = 0x18A8 - ((u32)ptr + i + j);
|
||||
newval&= 0x03FFFFFC;
|
||||
newval|= 0x48000000;
|
||||
write32( (u32)ptr + i + j, newval );
|
||||
|
||||
memcpy( (void*)0x1800, (void*)0, 6 );
|
||||
|
||||
char *path = (char*)malloc( 128 );
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_CHEAT_PATH) )
|
||||
{
|
||||
sprintf( path, "%s", ConfigGetCheatPath() );
|
||||
} else {
|
||||
sprintf( path, "/games/%.6s/%.6s.gct", (char*)0x1800, (char*)0x1800 );
|
||||
}
|
||||
|
||||
FIL CodeFD;
|
||||
u32 read;
|
||||
|
||||
if( f_open( &CodeFD, path, FA_OPEN_EXISTING|FA_READ ) == FR_OK )
|
||||
{
|
||||
if( CodeFD.fsize >= 0x2E80 - (0x1800+DBGSize-8) )
|
||||
{
|
||||
dbgprintf("Patch:Cheatfile is too large, it must not be large than %d bytes!\n",
|
||||
0x2E80 - (0x1800+DBGSize-8));
|
||||
} else {
|
||||
if( f_read( &CodeFD, (void*)(0x1800+DBGSize-8), CodeFD.fsize, &read ) == FR_OK )
|
||||
{
|
||||
dbgprintf("Patch:Copied cheat file to memory\n");
|
||||
write32( 0x1804, 1 );
|
||||
} else
|
||||
dbgprintf("Patch:Failed to read cheat file:\"%s\"\n", path );
|
||||
}
|
||||
|
||||
f_close( &CodeFD );
|
||||
|
||||
} else {
|
||||
dbgprintf("Patch:Failed to open/find cheat file:\"%s\"\n", path );
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
PatchCount |= 16;
|
||||
}
|
||||
}
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_CHEATS) )
|
||||
{
|
||||
if( PatchCount == 63 )
|
||||
break;
|
||||
} else {
|
||||
if( PatchCount == 47 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i < size; i+=4 )
|
||||
{
|
||||
if( read32( (u32)ptr + i ) != 0x4E800020 )
|
||||
continue;
|
||||
|
||||
i+=4;
|
||||
|
||||
FuncPattern fp;
|
||||
MPattern( (u8*)(ptr+i), size, &fp );
|
||||
|
||||
for( j=0; j < sizeof(FPatterns)/sizeof(FuncPattern); ++j )
|
||||
{
|
||||
if( FPatterns[j].Found ) //Skip already found patches
|
||||
continue;
|
||||
|
||||
if( CPattern( &fp, &(FPatterns[j]) ) )
|
||||
{
|
||||
u32 FOffset = (u32)ptr + i;
|
||||
|
||||
dbgprintf("Patch:Found [%s]: 0x%08X\n", FPatterns[j].Name, FOffset + SectionOffset );
|
||||
|
||||
switch( FPatterns[j].PatchLength )
|
||||
{
|
||||
case 0xdead0004: // Audiostreaming hack
|
||||
{
|
||||
switch( read32(0) >> 8 )
|
||||
{
|
||||
case 0x474544: // Eternal Darkness
|
||||
break;
|
||||
default:
|
||||
{
|
||||
write32( FOffset + 0xB4, 0x60000000 );
|
||||
write32( FOffset + 0xC0, 0x60000000 );
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case 0xdead0001: // Patch for __GXSetVAT, fixes the dungeon map freeze in Wind Waker
|
||||
{
|
||||
switch( read32(0) >> 8 )
|
||||
{
|
||||
case 0x505A4C: // The Legend of Zelda: Collector's Edition
|
||||
if( !(DOLSize == 3847012 || DOLSize == 3803812) ) // only patch the main.dol of the Zelda:ww game
|
||||
break;
|
||||
case 0x475A4C: // The Legend of Zelda: The Wind Waker
|
||||
{
|
||||
write32(FOffset, (read32(FOffset) & 0xff00ffff) | 0x220000);
|
||||
memcpy((void *)(FOffset + 4), __GXSetVAT_patch, sizeof(__GXSetVAT_patch));
|
||||
|
||||
dbgprintf("Patch:Applied __GXSetVAT patch\n");
|
||||
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case 0xdead000B: // PADRead hook
|
||||
{
|
||||
//Find blr
|
||||
|
||||
j=0;
|
||||
while(1)
|
||||
{
|
||||
if( read32( FOffset + j ) == 0x4E800020 )
|
||||
break;
|
||||
j+=4;
|
||||
}
|
||||
|
||||
dbgprintf("Patch:[PADRead hook] %08X\n", FOffset + j );
|
||||
|
||||
memcpy( (void*)0x2EE0, padipc, sizeof(padipc) );
|
||||
PatchB( 0x2EE0, FOffset + j );
|
||||
write32( 0x12FC, 0 );
|
||||
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
if( ConfigGetConfig( DML_CFG_CHEATS ) )
|
||||
{
|
||||
if( FPatterns[j].Patch == patch_fwrite_GC )
|
||||
break;
|
||||
}
|
||||
|
||||
if( (FPatterns[j].Length >> 16) == 0xdead )
|
||||
{
|
||||
dbgprintf("DIP:Unhandled dead case:%08X\n", FPatterns[j].Length );
|
||||
} else
|
||||
{
|
||||
memcpy( (void*)(FOffset), FPatterns[j].Patch, FPatterns[j].PatchLength );
|
||||
|
||||
if ((FPatterns[j].Patch == (u8 *)__dvdLowAudioStatusNULL) && ((read32(0) >> 8) == 0x47494B))
|
||||
{
|
||||
// Ikaruga resets to the main menu, if the returned status is 0(finished playing the stream), but it works if 1(still playing) is returned
|
||||
write32(FOffset + 36, 0x38600001);
|
||||
dbgprintf("Patch:LowAudioStatus patched for Ikaruga\n");
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
// If this is a patch group set all others of this group as found aswell
|
||||
if( FPatterns[j].Group )
|
||||
{
|
||||
for( k=0; k < sizeof(FPatterns)/sizeof(FuncPattern); ++k )
|
||||
{
|
||||
if( FPatterns[k].Group == FPatterns[j].Group )
|
||||
{
|
||||
if( !FPatterns[k].Found ) // Don't overwrite the offset!
|
||||
FPatterns[k].Found = -1; // Usually this holds the offset, to determinate it from a REALLY found pattern we set it -1 which still counts a logical TRUE
|
||||
|
||||
//dbgprintf("Setting [%s] to found!\n", FPatterns[k].Name );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
Patches.h
Normal file
52
Patches.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef _PATCHES_
|
||||
#define _PATCHES_
|
||||
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "ipc.h"
|
||||
#include "alloc.h"
|
||||
#include "ff.h"
|
||||
#include "vsprintf.h"
|
||||
#include "HW.h"
|
||||
#include "dol.h"
|
||||
|
||||
|
||||
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;
|
||||
|
||||
void PatchGCIPL( 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
205
alloc.c
Normal 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("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("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("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
23
alloc.h
Normal 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
23
asm/CARDCheck.S
Normal 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
43
asm/CARDCheckAsync.S
Normal 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
60
asm/CARDCheckEX.S
Normal 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
47
asm/CARDClose.S
Normal 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
|
88
asm/CARDCreate.S
Normal file
88
asm/CARDCreate.S
Normal file
@ -0,0 +1,88 @@
|
||||
#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, -0x10(%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
|
||||
|
||||
lwz %r0, 0x14(%sp)
|
||||
addi %sp, %sp, 0x10
|
||||
mtlr %r0
|
||||
blr
|
||||
|
80
asm/CARDDelete.S
Normal file
80
asm/CARDDelete.S
Normal 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
69
asm/CARDFastDelete.S
Normal 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
62
asm/CARDFastOpen.S
Normal 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
32
asm/CARDFreeBlocks.S
Normal 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
30
asm/CARDGetEncoding.S
Normal 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
30
asm/CARDGetMemSize.S
Normal 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
19
asm/CARDGetResultCode.S
Normal 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
29
asm/CARDGetSerialNo.S
Normal 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
74
asm/CARDGetStats.S
Normal 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
17
asm/CARDGetXferredBytes.S
Normal 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
26
asm/CARDMount.S
Normal 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
42
asm/CARDMountAsync.S
Normal 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
71
asm/CARDOpen.S
Normal 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
21
asm/CARDProbe.S
Normal 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
41
asm/CARDProbeEX.S
Normal 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
82
asm/CARDRead.S
Normal 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, -0x20(%sp)
|
||||
stw %r31, 0x1C(%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
|
||||
mtctr %r12
|
||||
li %r3, 0
|
||||
li %r4, 0
|
||||
bctrl
|
||||
|
||||
skip_cb:
|
||||
li %r3, 0
|
||||
mr %r4, %r3
|
||||
|
||||
lwz %r0, 0x24(%sp)
|
||||
lwz %r31, 0x1C(%sp)
|
||||
addi %sp, %sp, 0x20
|
||||
mtlr %r0
|
||||
blr
|
87
asm/CARDRename.S
Normal file
87
asm/CARDRename.S
Normal 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
83
asm/CARDSetStats.S
Normal 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
|
80
asm/CARDWrite.S
Normal file
80
asm/CARDWrite.S
Normal file
@ -0,0 +1,80 @@
|
||||
#include <asm.h>
|
||||
|
||||
#
|
||||
# r3 file *
|
||||
# r4 buffer
|
||||
# r5 length
|
||||
# r6 offset
|
||||
# r7 cb
|
||||
|
||||
CardWrite:
|
||||
|
||||
mflr %r0
|
||||
stw %r0, 4(%sp)
|
||||
stwu %sp, -0x10(%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
|
||||
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
|
60
asm/DVDInquiryAsync.S
Normal file
60
asm/DVDInquiryAsync.S
Normal 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
47
asm/DVDSeekAbsAsyncPrio.S
Normal 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
9
asm/__CARDSync.S
Normal file
@ -0,0 +1,9 @@
|
||||
#include <asm.h>
|
||||
|
||||
#
|
||||
# r3 *Async result
|
||||
|
||||
__CARDSync:
|
||||
|
||||
mr %r3, %r4
|
||||
blr
|
4
asm/make.cmd
Normal file
4
asm/make.cmd
Normal file
@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
for /R %%i IN (*.S) DO E:\devkitPro\devkitPPC\bin\powerpc-eabi-as.exe %%i -o %%~ni.elf
|
||||
for /R %%i IN (*.S) DO E:\devkitPro\devkitPPC\bin\powerpc-eabi-strip.exe -s %%~ni.elf -O binary -o %%~ni.bin
|
||||
for /R %%i in (*.bin) DO "C:\Users\crediar\Documents\Visual Studio 2010\Projects\bin2h\Release\bin2h.exe" %%~ni.bin
|
11
asm/padipc.S
Normal file
11
asm/padipc.S
Normal file
@ -0,0 +1,11 @@
|
||||
#include <asm.h>
|
||||
|
||||
|
||||
PADRead:
|
||||
|
||||
lis %r4, 0xCC00
|
||||
lwz %r0, 0x6404(%r4)
|
||||
lwz %r4, 0x6408(%r4)
|
||||
lis %r4, 0xC000
|
||||
stw %r0, 0x12FC(%r4)
|
||||
blr
|
32
bsdtypes.h
Normal file
32
bsdtypes.h
Normal 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
|
||||
|
||||
|
292
dip.c
Normal file
292
dip.c
Normal file
@ -0,0 +1,292 @@
|
||||
#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;
|
||||
|
||||
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 );
|
||||
}
|
||||
u32 DIUpdateRegisters( void )
|
||||
{
|
||||
u32 read,i,j;
|
||||
static u32 PatchState = 0;
|
||||
static u32 DOLReadSize= 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 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 );
|
||||
}
|
||||
|
||||
if( PatchState == 0 )
|
||||
{
|
||||
if( Length == 0x100 )
|
||||
{
|
||||
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 = sizeof(dolhdr);
|
||||
|
||||
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];
|
||||
}
|
||||
DOLMinOff -= 0x80000000;
|
||||
DOLMaxOff -= 0x80000000;
|
||||
|
||||
dbgprintf("DIP:DOLSize:%d DOLMinOff:0x%08X DOLMaxOff:0x%08X\n", DOLSize, DOLMinOff, DOLMaxOff );
|
||||
|
||||
PatchState = 1;
|
||||
}
|
||||
} else if( read32(Buffer) == 0x7F454C46 )
|
||||
{
|
||||
if (getfilenamebyoffset(Offset) != NULL)
|
||||
{
|
||||
dbgprintf("DIP:The Game is loading %s\n", getfilenamebyoffset(Offset));
|
||||
} else
|
||||
{
|
||||
dbgprintf("DIP:The Game is loading some .elf that is not in the fst...\n");
|
||||
}
|
||||
for (i = ((*(u32 *)0x00000038) & ~0x80000000) + 16; i < 0x01800000; i+=12) // Search the fst for the dvd offset of the .elf file
|
||||
{
|
||||
if (*(u32 *)i == Offset)
|
||||
{
|
||||
DOLSize = *(u32 *)(i+4);
|
||||
DOLReadSize = Length;
|
||||
|
||||
if( DOLReadSize == DOLSize ) // The .elf is read completely already
|
||||
{
|
||||
dbgprintf("DIP:The .elf is read completely, file size: %u bytes\n", DOLSize);
|
||||
DoPatches( (char*)(Buffer), Length, 0x80000000 );
|
||||
} else // a part of the .elf is read
|
||||
{
|
||||
PatchState = 2;
|
||||
DOLMinOff=Buffer;
|
||||
DOLMaxOff=Buffer+Length;
|
||||
if (Length <= 4096) // The .elf header is read
|
||||
{
|
||||
ELFNumberOfSections = read16(Buffer+0x2c) -2; // Assume that 2 sections are .bss and .sbss which are not read
|
||||
dbgprintf("DIP:The .elf header is read(%u bytes), .elf file size: %u bytes, number of sections to load: %u\n", Length, DOLSize, ELFNumberOfSections);
|
||||
} else // The .elf is read into a buffer
|
||||
{
|
||||
ELFNumberOfSections = -1; // Make sure that ELFNumberOfSections == 0 does not become true
|
||||
dbgprintf("DIP:The .elf is read into a buffer, read progress: %u/%u bytes\n", Length, DOLSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if ( PatchState != 0 )
|
||||
{
|
||||
DOLReadSize += Length;
|
||||
|
||||
if (PatchState == 2)
|
||||
{
|
||||
ELFNumberOfSections--;
|
||||
|
||||
// DOLMinOff and DOLMaxOff are optimised when loading .dol files
|
||||
if (DOLMinOff > Buffer)
|
||||
DOLMinOff = Buffer;
|
||||
|
||||
if (DOLMaxOff < Buffer+Length)
|
||||
DOLMaxOff = Buffer+Length;
|
||||
|
||||
if (ELFNumberOfSections < 0)
|
||||
{
|
||||
dbgprintf("DIP:.elf read progress: %u/%u bytes\n", DOLReadSize, DOLSize);
|
||||
} else
|
||||
{
|
||||
dbgprintf("DIP:.elf read progress: %u/%u bytes, sections left: %u\n", DOLReadSize, DOLSize, ELFNumberOfSections);
|
||||
}
|
||||
}
|
||||
|
||||
//dbgprintf("DIP:DOLSize:%d DOLReadSize:%d\n", DOLSize, DOLReadSize );
|
||||
if( DOLReadSize >= DOLSize || (PatchState == 2 && ELFNumberOfSections == 0))
|
||||
{
|
||||
DoPatches( (char*)(DOLMinOff), DOLMaxOff-DOLMinOff, 0x80000000 );
|
||||
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) );
|
||||
}
|
||||
|
||||
} 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) );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
138
dip.h
Normal file
138
dip.h
Normal file
@ -0,0 +1,138 @@
|
||||
#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"
|
||||
|
||||
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
|
93
diskio.c
Normal file
93
diskio.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include "diskio.h"
|
||||
#include "string.h"
|
||||
#include "memory.h"
|
||||
|
||||
extern u32 IsInit;
|
||||
|
||||
DSTATUS disk_initialize( BYTE drv )
|
||||
{
|
||||
udelay( 50000 );
|
||||
|
||||
tiny_ehci_init();
|
||||
|
||||
int ret = -ENODEV;
|
||||
|
||||
do {
|
||||
|
||||
udelay( 4000 );
|
||||
ret = ehci_discover();
|
||||
|
||||
} while( ret == -ENODEV );
|
||||
|
||||
dbgprintf("ehci_discover():%d\n", ret );
|
||||
|
||||
s32 r = USBStorage_Init();
|
||||
|
||||
u32 s_size;
|
||||
u32 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
70
diskio.h
Normal 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
16
dol.h
Normal 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
|
85
ehci-mem.c
Normal file
85
ehci-mem.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 = 0x17FF000;
|
||||
// ehci->periodic = ehci_maligned(DEFAULT_I_TDPS * sizeof(__le32),32,4096);
|
||||
|
||||
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++)
|
||||
{
|
||||
// ehci->qtds[i] = ehci_maligned(sizeof(struct ehci_qtd),32,4096);
|
||||
|
||||
ptr -= sizeof(struct ehci_qtd);
|
||||
ehci->qtds[i] = (struct ehci_qtd*)(ptr);
|
||||
}
|
||||
|
||||
ehci->qtd_used = 0;
|
||||
// ehci->asyncqh = ehci_maligned(sizeof(struct ehci_qh),32,4096);
|
||||
|
||||
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;
|
||||
|
||||
// ehci->async = ehci_maligned(sizeof(struct ehci_qh),32,4096);
|
||||
|
||||
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;
|
||||
}
|
811
ehci.c
Normal file
811
ehci.c
Normal file
@ -0,0 +1,811 @@
|
||||
/* 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("\nhandshake timeout!!\n\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);
|
||||
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("\nqtd 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 ( "un successfull 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*)0x1800, rpData, wLength );
|
||||
|
||||
urb.transfer_buffer = (u8*)0x1800;
|
||||
|
||||
ret = ehci_do_urb( dev, &urb );
|
||||
|
||||
memcpy( rpData, (void*)0x1800, 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))
|
||||
{
|
||||
ehci_writel( PORT_OWNER, status_reg);
|
||||
//ehci_dbg ( "port %d had no usb2 device connected at startup %X \n", port,ehci_readl(status_reg));
|
||||
return -ENODEV;// no USB2 device connected
|
||||
}
|
||||
|
||||
ehci_dbg ( "port %d has usb2 device connected! reset it...\n", port);
|
||||
ehci_writel( 0x1803,status_reg);
|
||||
|
||||
while ((ehci_readl(status_reg) & 0x1801) != 0x1801)
|
||||
{
|
||||
ehci_dbg ( "Waiting for port %d to settle...(%04x)\n", port, ehci_readl(status_reg));
|
||||
ehci_writel( 0x1803,status_reg);
|
||||
msleep(500);
|
||||
}
|
||||
|
||||
ehci_writel( 0x1903,status_reg);
|
||||
//ehci_writel( PORT_OWNER|PORT_POWER|PORT_RESET,status_reg);
|
||||
msleep(50);// wait 50ms for the reset sequence
|
||||
ehci_writel( 0x1001,status_reg);
|
||||
retval = handshake( status_reg, PORT_RESET, 0, 2000);
|
||||
|
||||
if (retval != 0)
|
||||
{
|
||||
ehci_dbg ( "port %d reset error %d\n", port, retval);
|
||||
return retval;
|
||||
}
|
||||
ehci_dbg ( "port %d reseted status:%04x...\n", port,ehci_readl(status_reg));
|
||||
msleep(50);
|
||||
// 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("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("unable to set device addr...\n");
|
||||
return retval;
|
||||
}
|
||||
dev->toggles = 0;
|
||||
|
||||
dev->id = port+1;
|
||||
ehci_dbg ( "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 ( "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 ( "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("found %d devices\n",j);
|
||||
*num = j;
|
||||
return 0;
|
||||
}
|
||||
#include "usb.c"
|
||||
#include "usbstorage.c"
|
282
ehci.h
Normal file
282
ehci.h
Normal 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
160
ehci_defs.h
Normal 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
55
ehci_types.h
Normal 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
|
335
ff.h
Normal file
335
ff.h
Normal 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
189
ffconf.h
Normal 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
62
global.h
Normal 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 0x00000001
|
||||
#define DM_VERSION 0x00020000
|
||||
|
||||
#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
180
hollywood.h
Normal 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
37
integer.h
Normal 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
81
iosmodule.ld
Normal 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*)
|
||||
}
|
||||
}
|
67
ipc.h
Normal file
67
ipc.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef __IPC_H__
|
||||
#define __IPC_H__ 1
|
||||
|
||||
struct ioctl_vector {
|
||||
void *data;
|
||||
unsigned int len;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ipcmessage
|
||||
{
|
||||
unsigned int command; // 0
|
||||
unsigned int result; // 4
|
||||
union
|
||||
{
|
||||
unsigned int fd; // 8
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
char *device; // 12
|
||||
unsigned int mode; // 16
|
||||
unsigned int resultfd; // 20
|
||||
} open;
|
||||
|
||||
struct
|
||||
{
|
||||
void *data;
|
||||
unsigned int length;
|
||||
} read, write;
|
||||
|
||||
struct
|
||||
{
|
||||
int offset;
|
||||
int origin;
|
||||
} seek;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int command;
|
||||
|
||||
unsigned int *buffer_in;
|
||||
unsigned int length_in;
|
||||
unsigned int *buffer_io;
|
||||
unsigned int length_io;
|
||||
} ioctl;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int command; // C
|
||||
|
||||
unsigned int argc_in; // 10
|
||||
unsigned int argc_io; // 14
|
||||
struct ioctl_vector *argv; // 18
|
||||
} ioctlv;
|
||||
};
|
||||
} __attribute__((packed)) ipcmessage;
|
||||
|
||||
#define IOS_OPEN 0x01
|
||||
#define IOS_CLOSE 0x02
|
||||
#define IOS_READ 0x03
|
||||
#define IOS_WRITE 0x04
|
||||
#define IOS_SEEK 0x05
|
||||
#define IOS_IOCTL 0x06
|
||||
#define IOS_IOCTLV 0x07
|
||||
|
||||
#endif
|
299
main.c
Normal file
299
main.c
Normal file
@ -0,0 +1,299 @@
|
||||
/*
|
||||
|
||||
DIOS MIOS - Gamecube USB loader for Nintendo Wii
|
||||
|
||||
Copyright (C) 2010-2012 crediar
|
||||
|
||||
*/
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "ipc.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"
|
||||
|
||||
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 )
|
||||
{
|
||||
u32 val;
|
||||
__asm("mov %0,lr": "=r" (val) );
|
||||
|
||||
*(vu32*)0xD800070 |= 1;
|
||||
|
||||
dbgprintf("PrefetchAbort LR:%08x\n", val-8 );
|
||||
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-8,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);
|
||||
}
|
||||
} else if( IRQs & IRQ_RESET )
|
||||
{
|
||||
;
|
||||
} else {
|
||||
|
||||
set32( HW_EXICTRL, 1 );
|
||||
|
||||
udelay(1000);
|
||||
dbgprintf("IRQ:%08X %08X\n", read32(HW_ARMIRQFLAG), read32(HW_GPIO_INTFLAG) );
|
||||
set32( HW_EXICTRL, 0 );
|
||||
}
|
||||
|
||||
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;
|
||||
FIL Log;
|
||||
|
||||
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/diosmioslite\n");
|
||||
|
||||
//dbgprintf("CPU Ver:%d.%d\n", SP[1], SP[0] );
|
||||
|
||||
//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 );
|
||||
|
||||
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 );
|
||||
|
||||
while (1)
|
||||
{
|
||||
ahb_flush_from( AHB_STARLET ); //flush to arm
|
||||
|
||||
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);
|
||||
//}
|
||||
|
||||
DIUpdateRegisters();
|
||||
|
||||
if( ConfigGetConfig(DML_CFG_NMM) )
|
||||
CARDUpdateRegisters();
|
||||
|
||||
ahb_flush_to( AHB_PPC ); //flush to ppc
|
||||
}
|
||||
}
|
251
memory.c
Normal file
251
memory.c
Normal 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;
|
||||
}
|
108
memory.h
Normal file
108
memory.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef __MEMORY_H__
|
||||
#define __MEMORY_H__
|
||||
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "ipc.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
70
memory_asm.S
Normal 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
213
start.s
Normal 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
125
string.c
Normal 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;
|
||||
}
|
23
string.h
Normal file
23
string.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _STRING_H_
|
||||
#define _STRING_H_
|
||||
|
||||
#include "global.h"
|
||||
|
||||
char *strcpy(char *, const char *);
|
||||
char *strncpy(char *, const char *, size_t);
|
||||
int strcmp(const char *, const char *);
|
||||
int strncmp(const char *p, const char *q, size_t n);
|
||||
size_t strlen(const char *);
|
||||
size_t strnlen(const char *, size_t);
|
||||
char *strchr(const char *s, int c);
|
||||
extern void *memset(void *, int, size_t);
|
||||
|
||||
void udelay(u32 d);
|
||||
|
||||
//void *memcpy(void *, const void *, size_t);
|
||||
//void *memcpy(void *, const void *, size_t);
|
||||
//void *memcpy(void *, const void *, size_t);
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
int sprintf( char *astr, const char *fmt, ...);
|
||||
|
||||
#endif
|
92
tiny_ehci_glue.c
Normal file
92
tiny_ehci_glue.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
EHCI glue. A bit hacky for the moment. needs cleaning..
|
||||
|
||||
Copyright (C) 2008 kwiirk.
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "tiny_ehci_glue.h"
|
||||
|
||||
#define static
|
||||
#define inline extern
|
||||
|
||||
int verbose=0;
|
||||
|
||||
void BUG(void)
|
||||
{
|
||||
dbgprintf("bug\n");
|
||||
while(1);
|
||||
}
|
||||
#define BUG_ON(a) if(a)BUG()
|
||||
|
||||
void msleep(int msec)
|
||||
{
|
||||
udelay(2048*msec);
|
||||
}
|
||||
extern u32 __exe_start_virt__;
|
||||
extern u32 __ram_start_virt__;
|
||||
|
||||
extern u32 ios_thread_stack;
|
||||
|
||||
void print_hex_dump_bytes(char *header,int prefix,u8 *buf,int len)
|
||||
{
|
||||
int i;
|
||||
if (len>0x100)len=0x100;
|
||||
dbgprintf("%s %08X\n",header,(u32)buf);
|
||||
for (i=0;i<len;i++){
|
||||
dbgprintf("%02x ",buf[i]);
|
||||
if((i&0xf) == 0xf)
|
||||
dbgprintf("\n");
|
||||
}
|
||||
dbgprintf("\n");
|
||||
}
|
||||
#define DUMP_PREFIX_OFFSET 1
|
||||
#include "ehci.h"
|
||||
#define ehci_readl(a) ((*((volatile u32*)(a))))
|
||||
//#define ehci_writel(e,v,a) do{msleep(40);dbgprintf("writel %08X %08X\n",a,v);*((volatile u32*)(a))=(v);}while(0)
|
||||
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||
|
||||
struct ehci_hcd _ehci;
|
||||
struct ehci_hcd *ehci;
|
||||
|
||||
#include "ehci.c"
|
||||
|
||||
int usb_os_init(void);
|
||||
int tiny_ehci_init(void)
|
||||
{
|
||||
int retval;
|
||||
ehci = &_ehci;
|
||||
|
||||
//memset(ehci,0,sizeof(*ehci));
|
||||
if(usb_os_init()<0)
|
||||
return 0;
|
||||
|
||||
ehci->caps = (void*)0x0D040000;
|
||||
ehci->regs = (void*)(0x0D040000 + HC_LENGTH(ehci_readl(&ehci->caps->hc_capbase)));
|
||||
|
||||
ehci->num_port = 4;
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl( &ehci->caps->hcs_params );
|
||||
|
||||
/* data structure init */
|
||||
retval = ehci_init();
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci_release_ports(); //quickly release none usb2 port
|
||||
|
||||
return 0;
|
||||
}
|
25
tiny_ehci_glue.h
Normal file
25
tiny_ehci_glue.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef _TEGLUE_
|
||||
#define _TEGLUE_
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include "ehci_types.h"
|
||||
#include "utils.h"
|
||||
#include "vsprintf.h"
|
||||
|
||||
int tiny_ehci_init(void);
|
||||
|
||||
#define readl(a) (*((volatile u32*)(a)))
|
||||
#define writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||
#define ehci_dbg(a...) dbgprintf(a)
|
||||
#define printk(a...) dbgprintf(a)
|
||||
#define get_timer() (*(((volatile u32*)0x0D800010)))
|
||||
|
||||
#define cpu_to_le32(a) swab32(a)
|
||||
#define le32_to_cpu(a) swab32(a)
|
||||
#define cpu_to_le16(a) swab16(a)
|
||||
#define le16_to_cpu(a) swab16(a)
|
||||
#define cpu_to_be32(a) (a)
|
||||
#define be32_to_cpu(a) (a)
|
||||
|
||||
#endif
|
233
usb.c
Normal file
233
usb.c
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
This file implements libogc usb API, but with ehci direct call
|
||||
|
||||
most of the file credit goes to libogc devs
|
||||
*/
|
||||
|
||||
#define __usb_control_message(fd, b, c,d, e, f, g, h, i) ehci_control_message(fd,b,c,d,e,f,g)
|
||||
|
||||
static s32 __usb_getdesc(struct ehci_device * fd, u8 *buffer, u8 type, u8 index, u8 size)
|
||||
{
|
||||
//printk("usb_get desc %X %X %p\n",type,index,buffer);
|
||||
return __usb_control_message(fd, USB_ENDPOINT_IN ,USB_REQ_GETDESCRIPTOR, (type << 8) | index, 0, size, buffer, NULL, NULL);
|
||||
}
|
||||
|
||||
s32 USB_GetDescriptors(struct ehci_device * fd, usb_devdesc *udd)
|
||||
{
|
||||
u8 *buffer = NULL;
|
||||
u8 *ptr = NULL;
|
||||
usb_configurationdesc *ucd = NULL;
|
||||
usb_interfacedesc *uid = NULL;
|
||||
usb_endpointdesc *ued = NULL;
|
||||
s32 retval = 0;
|
||||
u32 iConf, iInterface, iEndpoint;
|
||||
|
||||
buffer = USB_Alloc(sizeof(*udd));
|
||||
if(buffer == NULL)
|
||||
{
|
||||
retval = -ENOMEM;
|
||||
goto free_and_error;
|
||||
}
|
||||
|
||||
retval = __usb_getdesc(fd, buffer, USB_DT_DEVICE, 0, USB_DT_DEVICE_SIZE);
|
||||
if(retval < 0)
|
||||
{
|
||||
dbgprintf("__usb_getdesc():%d failed\n", retval );
|
||||
goto free_and_error;
|
||||
}
|
||||
|
||||
memcpy( udd, buffer, USB_DT_DEVICE_SIZE );
|
||||
USB_Free(buffer);
|
||||
|
||||
u32 *_udd = (u32*)udd;
|
||||
|
||||
_udd[1] = ( udd->bLength << 24 ) | ( udd->bDescriptorType << 16 ) | cpu_to_le16(udd->bcdUSB);
|
||||
_udd[2] = ( cpu_to_le16(udd->idVendor) << 16 ) | cpu_to_le16(udd->idProduct);
|
||||
_udd[3] = ( cpu_to_le16(udd->bcdDevice) << 16 ) | (udd->iManufacturer<<8) | udd->iProduct;
|
||||
|
||||
u32 _ptr = (u32)USB_Alloc( udd->bNumConfigurations * sizeof(*udd->configurations) );
|
||||
|
||||
//udd->configurations = USB_Alloc(udd->bNumConfigurations* sizeof(*udd->configurations));
|
||||
if( _ptr == 0)
|
||||
{
|
||||
dbgprintf("USB_Alloc():failed:%u\n", __LINE__ );
|
||||
retval = -ENOMEM;
|
||||
goto free_and_error;
|
||||
}
|
||||
|
||||
_udd[4] = ( udd->iSerialNumber << 24 ) | ( udd->bNumConfigurations << 16 ) | (_ptr>>16);
|
||||
_udd[5] = ((_ptr & 0xFFFF) << 16) | (_udd[5]&0xFFFF);
|
||||
|
||||
memset( udd->configurations, 0, udd->bNumConfigurations * sizeof(*udd->configurations) );
|
||||
|
||||
for( iConf = 0; iConf < udd->bNumConfigurations; iConf++)
|
||||
{
|
||||
buffer = USB_Alloc( USB_DT_CONFIG_SIZE );
|
||||
if(buffer == NULL)
|
||||
{
|
||||
retval = -ENOMEM;
|
||||
goto free_and_error;
|
||||
}
|
||||
|
||||
retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, USB_DT_CONFIG_SIZE);
|
||||
ucd = &udd->configurations[iConf];
|
||||
memcpy( ucd, buffer, USB_DT_CONFIG_SIZE );
|
||||
USB_Free( buffer );
|
||||
|
||||
u32 *_ucd = (u32*)ucd;
|
||||
|
||||
_ucd[0] = ( ucd->bLength << 24 ) | ( ucd->bDescriptorType << 16 ) | cpu_to_le16(ucd->wTotalLength);
|
||||
|
||||
//ucd->wTotalLength = cpu_to_le16(ucd->wTotalLength);
|
||||
|
||||
buffer = USB_Alloc( ucd->wTotalLength);
|
||||
if(buffer == NULL)
|
||||
{
|
||||
retval = -ENOMEM;
|
||||
goto free_and_error;
|
||||
}
|
||||
|
||||
retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, ucd->wTotalLength);
|
||||
if(retval < 0)
|
||||
goto free_and_error;
|
||||
|
||||
ptr = buffer;
|
||||
ptr += ucd->bLength;
|
||||
|
||||
retval = -ENOMEM;
|
||||
//ucd->interfaces = USB_Alloc(ucd->bNumInterfaces* sizeof(*ucd->interfaces));
|
||||
//if(ucd->interfaces == NULL)
|
||||
// goto free_and_error;
|
||||
|
||||
_ptr = (u32)USB_Alloc(ucd->bNumInterfaces* sizeof(*ucd->interfaces));
|
||||
if( _ptr == 0 )
|
||||
goto free_and_error;
|
||||
|
||||
_ucd[2] = ( ucd->bMaxPower << 24 ) | (_ptr>>8);
|
||||
_ucd[3] = ((_ptr & 0xFF) << 24) | (_ucd[3]&0xFFFFFF);
|
||||
|
||||
//dbgprintf("ucd->interfaces:%p\n", ucd->interfaces );
|
||||
memset( ucd->interfaces, 0, ucd->bNumInterfaces * sizeof(*ucd->interfaces) );
|
||||
|
||||
for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++)
|
||||
{
|
||||
uid = &ucd->interfaces[iInterface];
|
||||
memcpy(uid, ptr, USB_DT_INTERFACE_SIZE);
|
||||
ptr += uid->bLength;
|
||||
|
||||
//uid->endpoints = USB_Alloc(uid->bNumEndpoints* sizeof(*uid->endpoints));
|
||||
//if(uid->endpoints == NULL)
|
||||
// goto free_and_error;
|
||||
|
||||
u32 *_uid = (u32*)uid;
|
||||
_ptr = (u32)USB_Alloc(uid->bNumEndpoints* sizeof(*uid->endpoints));
|
||||
|
||||
_uid[2] = (uid->iInterface<<24) | (_ptr >> 8);
|
||||
_uid[3] = (_ptr<<24) | (_uid[3]&0xFFFFFF);
|
||||
|
||||
memset( uid->endpoints, 0, uid->bNumEndpoints * sizeof(*uid->endpoints) );
|
||||
|
||||
for( iEndpoint = 0; iEndpoint < uid->bNumEndpoints; iEndpoint++)
|
||||
{
|
||||
ued = &uid->endpoints[iEndpoint];
|
||||
memcpy( ued, ptr, USB_DT_ENDPOINT_SIZE );
|
||||
ptr += ued->bLength;
|
||||
|
||||
//ued->wMaxPacketSize = cpu_to_le16(ued->wMaxPacketSize);
|
||||
u32 *_ued = (u32*)ued;
|
||||
_ued[1] = (cpu_to_le16(ued->wMaxPacketSize) << 16 ) | (_ued[1] & 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
USB_Free( buffer);
|
||||
buffer = (u8*)NULL;
|
||||
}
|
||||
retval = 0;
|
||||
|
||||
free_and_error:
|
||||
if(buffer != NULL)
|
||||
USB_Free(buffer);
|
||||
if(retval < 0)
|
||||
USB_FreeDescriptors(udd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void USB_FreeDescriptors(usb_devdesc *udd)
|
||||
{
|
||||
int iConf, iInterface;
|
||||
usb_configurationdesc *ucd;
|
||||
usb_interfacedesc *uid;
|
||||
if(udd->configurations != NULL)
|
||||
{
|
||||
for(iConf = 0; iConf < udd->bNumConfigurations; iConf++)
|
||||
{
|
||||
ucd = &udd->configurations[iConf];
|
||||
if(ucd->interfaces != NULL)
|
||||
{
|
||||
for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++)
|
||||
{
|
||||
uid = &ucd->interfaces[iInterface];
|
||||
if(uid->endpoints != NULL)
|
||||
USB_Free(uid->endpoints);
|
||||
}
|
||||
USB_Free(ucd->interfaces);
|
||||
}
|
||||
}
|
||||
USB_Free(udd->configurations);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void USB_SuspendDevice(struct ehci_device *fd)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
void USB_ResumeDevice(struct ehci_device *fd)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
s32 USB_WriteBlkMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData)
|
||||
{
|
||||
return ehci_bulk_message(fd,bEndpoint,wLength,rpData);
|
||||
}
|
||||
|
||||
s32 USB_WriteCtrlMsg(struct ehci_device *fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData)
|
||||
{
|
||||
return __usb_control_message(fd,bmRequestType,bmRequest,wValue,wIndex,wLength,rpData,NULL,NULL);
|
||||
}
|
||||
|
||||
s32 USB_GetConfiguration(struct ehci_device *fd, u8 *configuration)
|
||||
{
|
||||
u8 *_configuration;
|
||||
s32 retval;
|
||||
|
||||
_configuration = USB_Alloc(1);
|
||||
if(_configuration == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
retval = __usb_control_message(fd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_DEVICE), USB_REQ_GETCONFIG, 0, 0, 1, _configuration, NULL, NULL);
|
||||
if(retval >= 0)
|
||||
*configuration = *_configuration;
|
||||
USB_Free( _configuration);
|
||||
|
||||
return retval;
|
||||
}
|
||||
s32 USB_SetConfiguration(struct ehci_device *fd, u8 configuration)
|
||||
{
|
||||
return __usb_control_message(fd, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_DEVICE), USB_REQ_SETCONFIG, configuration, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
s32 USB_SetAlternativeInterface(struct ehci_device *fd, u8 interface, u8 alternateSetting)
|
||||
{
|
||||
if(alternateSetting == 0)
|
||||
return -EINVAL;
|
||||
return __usb_control_message(fd, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_INTERFACE),
|
||||
USB_REQ_SETINTERFACE, alternateSetting, interface, 0, NULL, NULL, NULL);
|
||||
|
||||
}
|
||||
s32 USB_ClearHalt(struct ehci_device *fd, u8 endpoint)
|
||||
{
|
||||
return __usb_control_message(fd, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_ENDPOINT),
|
||||
USB_REQ_CLEARFEATURE, USB_FEATURE_ENDPOINT_HALT, endpoint, 0, NULL, NULL, NULL);
|
||||
}
|
176
usb.h
Normal file
176
usb.h
Normal file
@ -0,0 +1,176 @@
|
||||
#ifndef __USB_H__
|
||||
#define __USB_H__
|
||||
|
||||
|
||||
#define USB_MAXPATH IPC_MAXPATH_LEN
|
||||
|
||||
#define USB_OK 0
|
||||
#define USB_FAILED 1
|
||||
|
||||
/* Descriptor types */
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
|
||||
/* Standard requests */
|
||||
#define USB_REQ_GETSTATUS 0x00
|
||||
#define USB_REQ_CLEARFEATURE 0x01
|
||||
#define USB_REQ_SETFEATURE 0x03
|
||||
#define USB_REQ_SETADDRESS 0x05
|
||||
#define USB_REQ_GETDESCRIPTOR 0x06
|
||||
#define USB_REQ_SETDESCRIPTOR 0x07
|
||||
#define USB_REQ_GETCONFIG 0x08
|
||||
#define USB_REQ_SETCONFIG 0x09
|
||||
#define USB_REQ_GETINTERFACE 0x0a
|
||||
#define USB_REQ_SETINTERFACE 0x0b
|
||||
#define USB_REQ_SYNCFRAME 0x0c
|
||||
|
||||
/* Descriptor sizes per descriptor type */
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
|
||||
/* control message request type bitmask */
|
||||
#define USB_CTRLTYPE_DIR_HOST2DEVICE (0<<7)
|
||||
#define USB_CTRLTYPE_DIR_DEVICE2HOST (1<<7)
|
||||
#define USB_CTRLTYPE_TYPE_STANDARD (0<<5)
|
||||
#define USB_CTRLTYPE_TYPE_CLASS (1<<5)
|
||||
#define USB_CTRLTYPE_TYPE_VENDOR (2<<5)
|
||||
#define USB_CTRLTYPE_TYPE_RESERVED (3<<5)
|
||||
#define USB_CTRLTYPE_REC_DEVICE 0
|
||||
#define USB_CTRLTYPE_REC_INTERFACE 1
|
||||
#define USB_CTRLTYPE_REC_ENDPOINT 2
|
||||
#define USB_CTRLTYPE_REC_OTHER 3
|
||||
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0
|
||||
|
||||
#define USB_ENDPOINT_IN 0x80
|
||||
#define USB_ENDPOINT_OUT 0x00
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
# define ATTRIBUTE_PACKED __attribute__((packed))
|
||||
|
||||
typedef struct _usbctrlrequest {
|
||||
u8 bRequestType;
|
||||
u8 bRequest;
|
||||
u16 wValue;
|
||||
|
||||
u16 wIndex;
|
||||
u16 wLength;
|
||||
} ATTRIBUTE_PACKED usbctrlrequest;
|
||||
|
||||
typedef struct _usbendpointdesc
|
||||
{
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bEndpointAddress;
|
||||
u8 bmAttributes;
|
||||
|
||||
u16 wMaxPacketSize;
|
||||
u8 bInterval;
|
||||
u8 pad;
|
||||
} ATTRIBUTE_PACKED usb_endpointdesc;
|
||||
|
||||
typedef struct _usbinterfacedesc
|
||||
{
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u8 bInterfaceNumber;
|
||||
u8 bAlternateSetting;
|
||||
|
||||
u8 bNumEndpoints;
|
||||
u8 bInterfaceClass;
|
||||
u8 bInterfaceSubClass;
|
||||
u8 bInterfaceProtocol;
|
||||
|
||||
u8 iInterface;
|
||||
struct _usbendpointdesc *endpoints;
|
||||
} ATTRIBUTE_PACKED usb_interfacedesc;
|
||||
|
||||
typedef struct _usbconfdesc
|
||||
{
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u16 wTotalLength;
|
||||
|
||||
u8 bNumInterfaces;
|
||||
u8 bConfigurationValue;
|
||||
u8 iConfiguration;
|
||||
u8 bmAttributes;
|
||||
|
||||
u8 bMaxPower;
|
||||
struct _usbinterfacedesc *interfaces;
|
||||
} ATTRIBUTE_PACKED usb_configurationdesc;
|
||||
|
||||
typedef struct _usbdevdesc
|
||||
{
|
||||
u8 bLength;
|
||||
u8 bDescriptorType;
|
||||
u16 bcdUSB;
|
||||
|
||||
u8 bDeviceClass;
|
||||
u8 bDeviceSubClass;
|
||||
u8 bDeviceProtocol;
|
||||
u8 bMaxPacketSize0;
|
||||
|
||||
u16 idVendor;
|
||||
u16 idProduct;
|
||||
|
||||
u16 bcdDevice;
|
||||
u8 iManufacturer;
|
||||
u8 iProduct;
|
||||
|
||||
u8 iSerialNumber;
|
||||
u8 bNumConfigurations;
|
||||
struct _usbconfdesc *configurations;
|
||||
} ATTRIBUTE_PACKED usb_devdesc;
|
||||
|
||||
struct ehci_device;
|
||||
|
||||
s32 USB_OpenDevice(const char *device,u16 vid,u16 pid,struct ehci_device **fd);
|
||||
s32 USB_CloseDevice(struct ehci_device **fd);
|
||||
|
||||
s32 USB_GetDescriptors(struct ehci_device *fd, usb_devdesc *udd);
|
||||
void USB_FreeDescriptors(usb_devdesc *udd);
|
||||
|
||||
s32 USB_GetDeviceDescription(struct ehci_device *fd,usb_devdesc *devdesc);
|
||||
|
||||
void USB_SuspendDevice(struct ehci_device *fd);
|
||||
void USB_ResumeDevice(struct ehci_device *fd);
|
||||
|
||||
s32 USB_ReadIntrMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
|
||||
|
||||
s32 USB_ReadBlkMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
|
||||
|
||||
s32 USB_ReadCtrlMsg(struct ehci_device *fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData);
|
||||
|
||||
s32 USB_WriteIntrMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
|
||||
|
||||
s32 USB_WriteBlkMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
|
||||
|
||||
s32 USB_WriteCtrlMsg(struct ehci_device *fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData);
|
||||
|
||||
s32 USB_GetConfiguration(struct ehci_device *fd, u8 *configuration);
|
||||
s32 USB_SetConfiguration(struct ehci_device *fd, u8 configuration);
|
||||
s32 USB_SetAlternativeInterface(struct ehci_device *fd, u8 interface, u8 alternateSetting);
|
||||
s32 USB_ClearHalt(struct ehci_device *fd, u8 endpointAddress);
|
||||
s32 USB_GetDeviceList(const char *devpath,void *descr_buffer,u8 num_descr,u8 b0,u8 *cnt_descr);
|
||||
|
||||
/* alloc memory from the USB subsystem */
|
||||
void * USB_Alloc(int size);
|
||||
void USB_Free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif
|
78
usb_os.c
Normal file
78
usb_os.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include <string.h>
|
||||
#include "ehci_types.h"
|
||||
#include "usb.h"
|
||||
#include "ehci.h"
|
||||
#include "alloc.h"
|
||||
|
||||
void *VirtualToPhysical( void *address )
|
||||
{
|
||||
if( ((u32)address & 0xFFFF0000) == 0xFFFF0000 )
|
||||
return (void*)address;
|
||||
|
||||
return (void*)((u32)address & 0x7FFFFFFF);
|
||||
}
|
||||
void sync_after_write( void *a, u32 v )
|
||||
{
|
||||
dc_flushrange( a, v );
|
||||
}
|
||||
void sync_before_read( void *a, u32 v )
|
||||
{
|
||||
dc_invalidaterange( a, v );
|
||||
}
|
||||
|
||||
|
||||
int usb_os_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void *ehci_maligned(int size,int alignement,int crossing)
|
||||
{
|
||||
return (void*)malloca( size, alignement );
|
||||
}
|
||||
dma_addr_t ehci_virt_to_dma(void *a)
|
||||
{
|
||||
return (dma_addr_t)VirtualToPhysical(a);
|
||||
}
|
||||
dma_addr_t ehci_dma_map_to(void *buf,size_t len)
|
||||
{
|
||||
sync_after_write(buf, len);
|
||||
return (dma_addr_t)VirtualToPhysical(buf);
|
||||
}
|
||||
dma_addr_t ehci_dma_map_from(void *buf,size_t len)
|
||||
{
|
||||
sync_after_write(buf, len);
|
||||
return (dma_addr_t)VirtualToPhysical(buf);
|
||||
}
|
||||
dma_addr_t ehci_dma_map_bidir(void *buf,size_t len)
|
||||
{
|
||||
sync_after_write(buf, len);
|
||||
return (dma_addr_t)VirtualToPhysical(buf);
|
||||
}
|
||||
void ehci_dma_unmap_to(dma_addr_t buf,size_t len)
|
||||
{
|
||||
sync_before_read((void*)buf, len);
|
||||
}
|
||||
void ehci_dma_unmap_from(dma_addr_t buf,size_t len)
|
||||
{
|
||||
sync_before_read((void*)buf, len);
|
||||
}
|
||||
void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len)
|
||||
{
|
||||
sync_before_read((void*)buf, len);
|
||||
}
|
||||
void *USB_Alloc(int size)
|
||||
{
|
||||
//u32 val;
|
||||
//__asm("mov %0,lr": "=r" (val) );
|
||||
//dbgprintf("USB_Alloc(%u) LR:%08x\n", size, val );
|
||||
|
||||
//void *ptr = malloc(size);
|
||||
//memset( ptr, 0, size );
|
||||
//return ptr;
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
void USB_Free(void *ptr)
|
||||
{
|
||||
return free(ptr);
|
||||
}
|
745
usbstorage.c
Normal file
745
usbstorage.c
Normal file
@ -0,0 +1,745 @@
|
||||
/*-------------------------------------------------------------
|
||||
|
||||
usbstorage.c -- Bulk-only USB mass storage support
|
||||
|
||||
Copyright (C) 2008
|
||||
Sven Peter (svpe) <svpe@gmx.net>
|
||||
|
||||
quick port to ehci/ios: Kwiirk
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
-------------------------------------------------------------*/
|
||||
|
||||
#define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f)
|
||||
|
||||
#define HEAP_SIZE (32*1024)
|
||||
#define TAG_START 0x1//BADC0DE
|
||||
|
||||
#define CBW_SIZE 31
|
||||
#define CBW_SIGNATURE 0x43425355
|
||||
#define CBW_IN (1 << 7)
|
||||
#define CBW_OUT 0
|
||||
|
||||
#define CSW_SIZE 13
|
||||
#define CSW_SIGNATURE 0x53425355
|
||||
|
||||
#define SCSI_TEST_UNIT_READY 0x00
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_REQUEST_SENSE 0x03
|
||||
#define SCSI_READ_CAPACITY 0x25
|
||||
#define SCSI_READ_10 0x28
|
||||
#define SCSI_WRITE_10 0x2A
|
||||
|
||||
#define SCSI_SENSE_REPLY_SIZE 18
|
||||
#define SCSI_SENSE_NOT_READY 0x02
|
||||
#define SCSI_SENSE_MEDIUM_ERROR 0x03
|
||||
#define SCSI_SENSE_HARDWARE_ERROR 0x04
|
||||
|
||||
#define USB_CLASS_MASS_STORAGE 0x08
|
||||
#define MASS_STORAGE_SCSI_COMMANDS 0x06
|
||||
#define MASS_STORAGE_BULK_ONLY 0x50
|
||||
|
||||
#define USBSTORAGE_GET_MAX_LUN 0xFE
|
||||
#define USBSTORAGE_RESET 0xFF
|
||||
|
||||
#define USB_ENDPOINT_BULK 0x02
|
||||
|
||||
#define USBSTORAGE_CYCLE_RETRIES 3
|
||||
|
||||
#define MAX_TRANSFER_SIZE 4096
|
||||
|
||||
#define DEVLIST_MAXSIZE 8
|
||||
|
||||
static s32 __usbstorage_reset(usbstorage_handle *dev);
|
||||
static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun);
|
||||
|
||||
// ehci driver has its own timeout.
|
||||
static s32 __USB_BlkMsgTimeout(usbstorage_handle *dev, u8 bEndpoint, u16 wLength, void *rpData)
|
||||
{
|
||||
return USB_WriteBlkMsg(dev->usb_fd, bEndpoint, wLength, rpData);
|
||||
}
|
||||
|
||||
static s32 __USB_CtrlMsgTimeout(usbstorage_handle *dev, u8 bmRequestType, u8 bmRequest, u16 wValue, u16 wIndex, u16 wLength, void *rpData)
|
||||
{
|
||||
return USB_WriteCtrlMsg(dev->usb_fd, bmRequestType, bmRequest, wValue, wIndex, wLength, rpData);
|
||||
}
|
||||
static s32 __send_cbw(usbstorage_handle *dev, u8 lun, u32 len, u8 flags, const u8 *cb, u8 cbLen)
|
||||
{
|
||||
s32 retval = USBSTORAGE_OK;
|
||||
|
||||
if(cbLen == 0 || cbLen > 16)
|
||||
return -EINVAL;
|
||||
|
||||
memset(dev->buffer, 0, CBW_SIZE);
|
||||
|
||||
((u32*)dev->buffer)[0]=cpu_to_le32(CBW_SIGNATURE);
|
||||
((u32*)dev->buffer)[1]=cpu_to_le32(dev->tag);
|
||||
((u32*)dev->buffer)[2]=cpu_to_le32(len);
|
||||
dev->buffer[12] = flags;
|
||||
dev->buffer[13] = lun;
|
||||
dev->buffer[14] = (cbLen > 6 ? 0x10 : 6);
|
||||
|
||||
memcpy(dev->buffer + 15, (void*)cb, cbLen);
|
||||
|
||||
retval = __USB_BlkMsgTimeout(dev, dev->ep_out, CBW_SIZE, (void *)dev->buffer);
|
||||
|
||||
if(retval == CBW_SIZE) return USBSTORAGE_OK;
|
||||
else if(retval >= 0) return USBSTORAGE_ESHORTWRITE;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue)
|
||||
{
|
||||
s32 retval = USBSTORAGE_OK;
|
||||
u32 signature, tag, _dataResidue, _status;
|
||||
|
||||
memset(dev->buffer, 0xff, CSW_SIZE);
|
||||
|
||||
retval = __USB_BlkMsgTimeout(dev, dev->ep_in, CSW_SIZE, dev->buffer);
|
||||
//print_hex_dump_bytes("csv resp:",DUMP_PREFIX_OFFSET,dev->buffer,CSW_SIZE);
|
||||
|
||||
if(retval >= 0 && retval != CSW_SIZE) return USBSTORAGE_ESHORTREAD;
|
||||
else if(retval < 0) return retval;
|
||||
|
||||
signature = le32_to_cpu(((u32*)dev->buffer)[0]);
|
||||
tag = le32_to_cpu(((u32*)dev->buffer)[1]);
|
||||
_dataResidue = le32_to_cpu(((u32*)dev->buffer)[2]);
|
||||
_status = dev->buffer[12];
|
||||
|
||||
if(signature != CSW_SIGNATURE) {
|
||||
BUG();
|
||||
return USBSTORAGE_ESIGNATURE;
|
||||
}
|
||||
|
||||
if(dataResidue != NULL)
|
||||
*dataResidue = _dataResidue;
|
||||
if(status != NULL)
|
||||
*status = _status;
|
||||
|
||||
if(tag != dev->tag) return USBSTORAGE_ETAG;
|
||||
dev->tag++;
|
||||
|
||||
return USBSTORAGE_OK;
|
||||
}
|
||||
static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, u8 cbLen, u8 write, u8 *_status, u32 *_dataResidue)
|
||||
{
|
||||
s32 retval = USBSTORAGE_OK;
|
||||
|
||||
u8 status = 0;
|
||||
u32 dataResidue = 0;
|
||||
u32 thisLen;
|
||||
|
||||
s8 retries = USBSTORAGE_CYCLE_RETRIES + 1;
|
||||
|
||||
do
|
||||
{
|
||||
retries--;
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
break;
|
||||
|
||||
if(write)
|
||||
{
|
||||
retval = __send_cbw(dev, lun, len, CBW_OUT, cb, cbLen);
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
break;
|
||||
if(retval < 0)
|
||||
{
|
||||
if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
|
||||
retval = USBSTORAGE_ETIMEDOUT;
|
||||
continue;
|
||||
}
|
||||
while(len > 0)
|
||||
{
|
||||
thisLen=len;
|
||||
retval = __USB_BlkMsgTimeout(dev, dev->ep_out, thisLen, buffer);
|
||||
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
break;
|
||||
|
||||
if(retval < 0)
|
||||
{
|
||||
retval = USBSTORAGE_EDATARESIDUE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(retval != thisLen && len > 0)
|
||||
{
|
||||
retval = USBSTORAGE_EDATARESIDUE;
|
||||
break;
|
||||
}
|
||||
len -= retval;
|
||||
buffer += retval;
|
||||
}
|
||||
|
||||
if(retval < 0)
|
||||
{
|
||||
if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
|
||||
retval = USBSTORAGE_ETIMEDOUT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = __send_cbw(dev, lun, len, CBW_IN, cb, cbLen);
|
||||
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
break;
|
||||
|
||||
if(retval < 0)
|
||||
{
|
||||
if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
|
||||
retval = USBSTORAGE_ETIMEDOUT;
|
||||
continue;
|
||||
}
|
||||
while(len > 0)
|
||||
{
|
||||
thisLen=len;
|
||||
retval = __USB_BlkMsgTimeout(dev, dev->ep_in, thisLen, buffer);
|
||||
//print_hex_dump_bytes("usbs in:",DUMP_PREFIX_OFFSET,dev->buffer,36);
|
||||
if(retval < 0)
|
||||
break;
|
||||
|
||||
len -= retval;
|
||||
buffer += retval;
|
||||
|
||||
if(retval != thisLen)
|
||||
break;
|
||||
}
|
||||
|
||||
if(retval < 0)
|
||||
{
|
||||
if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
|
||||
retval = USBSTORAGE_ETIMEDOUT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
retval = __read_csw(dev, &status, &dataResidue);
|
||||
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
break;
|
||||
|
||||
if(retval < 0)
|
||||
{
|
||||
if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
|
||||
retval = USBSTORAGE_ETIMEDOUT;
|
||||
continue;
|
||||
}
|
||||
|
||||
retval = USBSTORAGE_OK;
|
||||
} while(retval < 0 && retries > 0);
|
||||
|
||||
if(retval < 0 && retval != USBSTORAGE_ETIMEDOUT)
|
||||
{
|
||||
if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
|
||||
retval = USBSTORAGE_ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
||||
if(_status != NULL)
|
||||
*_status = status;
|
||||
if(_dataResidue != NULL)
|
||||
*_dataResidue = dataResidue;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun)
|
||||
{
|
||||
s32 retval;
|
||||
u8 cmd[16];
|
||||
u8 *sense= USB_Alloc(SCSI_SENSE_REPLY_SIZE);
|
||||
u8 status = 0;
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
cmd[0] = SCSI_TEST_UNIT_READY;
|
||||
|
||||
retval = __cycle(dev, lun, NULL, 0, cmd, 1, 1, &status, NULL);
|
||||
if(retval < 0) return retval;
|
||||
|
||||
if(status != 0)
|
||||
{
|
||||
cmd[0] = SCSI_REQUEST_SENSE;
|
||||
cmd[1] = lun << 5;
|
||||
cmd[4] = SCSI_SENSE_REPLY_SIZE;
|
||||
cmd[5] = 0;
|
||||
memset(sense, 0, SCSI_SENSE_REPLY_SIZE);
|
||||
retval = __cycle(dev, lun, sense, SCSI_SENSE_REPLY_SIZE, cmd, 6, 0, NULL, NULL);
|
||||
if(retval < 0) goto error;
|
||||
|
||||
status = sense[2] & 0x0F;
|
||||
if(status == SCSI_SENSE_NOT_READY || status == SCSI_SENSE_MEDIUM_ERROR || status == SCSI_SENSE_HARDWARE_ERROR)
|
||||
retval = USBSTORAGE_ESENSE;
|
||||
}
|
||||
error:
|
||||
USB_Free(sense);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static s32 __usbstorage_reset(usbstorage_handle *dev)
|
||||
{
|
||||
s32 retval;
|
||||
|
||||
if(dev->suspended == 1)
|
||||
{
|
||||
USB_ResumeDevice(dev->usb_fd);
|
||||
dev->suspended = 0;
|
||||
}
|
||||
/*
|
||||
retval = ehci_reset_device(dev->usb_fd);
|
||||
if(retval < 0 && retval != -7004)
|
||||
goto end;
|
||||
*/
|
||||
//debug_printf("usbstorage reset..\n");
|
||||
retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL);
|
||||
|
||||
/* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */
|
||||
if(retval < 0 && retval != -7004)
|
||||
goto end;
|
||||
|
||||
/* gives device enough time to process the reset */
|
||||
msleep(10);
|
||||
|
||||
//debug_printf("cleat halt on bulk ep..\n");
|
||||
retval = USB_ClearHalt(dev->usb_fd, dev->ep_in);
|
||||
if(retval < 0)
|
||||
goto end;
|
||||
retval = USB_ClearHalt(dev->usb_fd, dev->ep_out);
|
||||
|
||||
end:
|
||||
return retval;
|
||||
}
|
||||
|
||||
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd)
|
||||
{
|
||||
s32 retval = -1;
|
||||
u8 conf,*max_lun = NULL;
|
||||
u32 iConf, iInterface, iEp;
|
||||
usb_devdesc udd;
|
||||
usb_configurationdesc *ucd;
|
||||
usb_interfacedesc *uid;
|
||||
usb_endpointdesc *ued;
|
||||
|
||||
max_lun = USB_Alloc(1);
|
||||
if(max_lun==NULL) return -ENOMEM;
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
|
||||
dev->tag = TAG_START;
|
||||
dev->usb_fd = fd;
|
||||
|
||||
retval = USB_GetDescriptors(dev->usb_fd, &udd);
|
||||
if(retval < 0)
|
||||
{
|
||||
dbgprintf("USB_GetDescriptors():%d\n", retval );
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
dbgprintf("udd.bNumConfigurations:%u\n", udd.bNumConfigurations );
|
||||
|
||||
for(iConf = 0; iConf < udd.bNumConfigurations; iConf++)
|
||||
{
|
||||
ucd = &udd.configurations[iConf];
|
||||
for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++)
|
||||
{
|
||||
uid = &ucd->interfaces[iInterface];
|
||||
if(uid->bInterfaceClass == USB_CLASS_MASS_STORAGE &&
|
||||
uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS &&
|
||||
uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY)
|
||||
{
|
||||
if(uid->bNumEndpoints < 2)
|
||||
continue;
|
||||
|
||||
dev->ep_in = dev->ep_out = 0;
|
||||
for(iEp = 0; iEp < uid->bNumEndpoints; iEp++)
|
||||
{
|
||||
ued = &uid->endpoints[iEp];
|
||||
if(ued->bmAttributes != USB_ENDPOINT_BULK)
|
||||
continue;
|
||||
|
||||
if(ued->bEndpointAddress & USB_ENDPOINT_IN)
|
||||
{
|
||||
dev->ep_in = ued->bEndpointAddress;
|
||||
dbgprintf("%08X:%08X\n", dev->ep_in, ued->bEndpointAddress );
|
||||
} else {
|
||||
dev->ep_out = ued->bEndpointAddress;
|
||||
dbgprintf("%08X:%08X\n", dev->ep_out, ued->bEndpointAddress );
|
||||
}
|
||||
}
|
||||
|
||||
if(dev->ep_in != 0 && dev->ep_out != 0)
|
||||
{
|
||||
dev->configuration = ucd->bConfigurationValue;
|
||||
dev->interface = uid->bInterfaceNumber;
|
||||
dev->altInterface = uid->bAlternateSetting;
|
||||
|
||||
dbgprintf("%08X:%08X\n", dev->configuration , ucd->bConfigurationValue );
|
||||
dbgprintf("%08X:%08X\n", dev->interface , uid->bInterfaceNumber );
|
||||
dbgprintf("%08X:%08X\n", dev->altInterface , uid->bAlternateSetting );
|
||||
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_FreeDescriptors(&udd);
|
||||
retval = USBSTORAGE_ENOINTERFACE;
|
||||
goto free_and_return;
|
||||
|
||||
found:
|
||||
USB_FreeDescriptors(&udd);
|
||||
|
||||
retval = USBSTORAGE_EINIT;
|
||||
if(USB_GetConfiguration(dev->usb_fd, &conf) < 0)
|
||||
goto free_and_return;
|
||||
if(conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0)
|
||||
goto free_and_return;
|
||||
if(dev->altInterface != 0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0)
|
||||
goto free_and_return;
|
||||
dev->suspended = 0;
|
||||
|
||||
retval = USBStorage_Reset(dev);
|
||||
if(retval < 0)
|
||||
goto free_and_return;
|
||||
|
||||
retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun);
|
||||
if(retval < 0)
|
||||
dev->max_lun = 1;
|
||||
else
|
||||
dev->max_lun = *max_lun;
|
||||
|
||||
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
goto free_and_return;
|
||||
|
||||
retval = USBSTORAGE_OK;
|
||||
|
||||
if(dev->max_lun == 0)
|
||||
dev->max_lun++;
|
||||
|
||||
/* taken from linux usbstorage module (drivers/usb/storage/transport.c) */
|
||||
/*
|
||||
* Some devices (i.e. Iomega Zip100) need this -- apparently
|
||||
* the bulk pipes get STALLed when the GetMaxLUN request is
|
||||
* processed. This is, in theory, harmless to all other devices
|
||||
* (regardless of if they stall or not).
|
||||
*/
|
||||
USB_ClearHalt(dev->usb_fd, dev->ep_in);
|
||||
USB_ClearHalt(dev->usb_fd, dev->ep_out);
|
||||
|
||||
dev->buffer = /*USB_Alloc(MAX_TRANSFER_SIZE)*/(u8*)0xFFFE4000;
|
||||
|
||||
if(dev->buffer == NULL) retval = -ENOMEM;
|
||||
else retval = USBSTORAGE_OK;
|
||||
|
||||
free_and_return:
|
||||
if(max_lun!=NULL) USB_Free(max_lun);
|
||||
if(retval < 0)
|
||||
{
|
||||
if(dev->buffer != NULL)
|
||||
USB_Free(dev->buffer);
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
return retval;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 USBStorage_Close(usbstorage_handle *dev)
|
||||
{
|
||||
if(dev->buffer != NULL)
|
||||
USB_Free(dev->buffer);
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 USBStorage_Reset(usbstorage_handle *dev)
|
||||
{
|
||||
s32 retval;
|
||||
|
||||
retval = __usbstorage_reset(dev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
s32 USBStorage_GetMaxLUN(usbstorage_handle *dev)
|
||||
{
|
||||
|
||||
return dev->max_lun;
|
||||
}
|
||||
|
||||
s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun)
|
||||
{
|
||||
s32 retval;
|
||||
|
||||
if(lun >= dev->max_lun)
|
||||
return -EINVAL;
|
||||
|
||||
retval = __usbstorage_clearerrors(dev, lun);
|
||||
if(retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = USBStorage_Inquiry(dev, lun);
|
||||
|
||||
retval = USBStorage_ReadCapacity(dev, lun, &dev->sector_size[lun], &dev->n_sector[lun]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
s32 USBStorage_Inquiry(usbstorage_handle *dev, u8 lun)
|
||||
{
|
||||
s32 retval;
|
||||
u8 cmd[] = {SCSI_INQUIRY, lun << 5,0,0,36,0};
|
||||
u8 *response = USB_Alloc(36);
|
||||
|
||||
retval = __cycle(dev, lun, response, 36, cmd, 6, 0, NULL, NULL);
|
||||
//print_hex_dump_bytes("inquiry result:",DUMP_PREFIX_OFFSET,response,36);
|
||||
USB_Free(response);
|
||||
return retval;
|
||||
}
|
||||
s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors)
|
||||
{
|
||||
s32 retval;
|
||||
u8 cmd[] = {SCSI_READ_CAPACITY, lun << 5};
|
||||
u8 *response = USB_Alloc(8);
|
||||
u32 val;
|
||||
retval = __cycle(dev, lun, response, 8, cmd, 2, 0, NULL, NULL);
|
||||
if(retval >= 0)
|
||||
{
|
||||
|
||||
memcpy(&val, response, 4);
|
||||
if(n_sectors != NULL)
|
||||
*n_sectors = be32_to_cpu(val);
|
||||
memcpy(&val, response + 4, 4);
|
||||
if(sector_size != NULL)
|
||||
*sector_size = be32_to_cpu(val);
|
||||
retval = USBSTORAGE_OK;
|
||||
}
|
||||
USB_Free(response);
|
||||
return retval;
|
||||
}
|
||||
|
||||
s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer)
|
||||
{
|
||||
u8 status = 0;
|
||||
s32 retval;
|
||||
u8 cmd[] = {
|
||||
SCSI_READ_10,
|
||||
lun << 5,
|
||||
sector >> 24,
|
||||
sector >> 16,
|
||||
sector >> 8,
|
||||
sector,
|
||||
0,
|
||||
n_sectors >> 8,
|
||||
n_sectors,
|
||||
0
|
||||
};
|
||||
if(lun >= dev->max_lun || dev->sector_size[lun] == 0)
|
||||
return -EINVAL;
|
||||
retval = __cycle(dev, lun, buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 0, &status, NULL);
|
||||
if(retval > 0 && status != 0)
|
||||
retval = USBSTORAGE_ESTATUS;
|
||||
return retval;
|
||||
}
|
||||
|
||||
s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer)
|
||||
{
|
||||
u8 status = 0;
|
||||
s32 retval;
|
||||
u8 cmd[] = {
|
||||
SCSI_WRITE_10,
|
||||
lun << 5,
|
||||
sector >> 24,
|
||||
sector >> 16,
|
||||
sector >> 8,
|
||||
sector,
|
||||
0,
|
||||
n_sectors >> 8,
|
||||
n_sectors,
|
||||
0
|
||||
};
|
||||
if(lun >= dev->max_lun || dev->sector_size[lun] == 0)
|
||||
return -EINVAL;
|
||||
retval = __cycle(dev, lun, (u8 *)buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 1, &status, NULL);
|
||||
if(retval > 0 && status != 0)
|
||||
retval = USBSTORAGE_ESTATUS;
|
||||
return retval;
|
||||
}
|
||||
|
||||
s32 USBStorage_Suspend(usbstorage_handle *dev)
|
||||
{
|
||||
if(dev->suspended == 1)
|
||||
return USBSTORAGE_OK;
|
||||
|
||||
USB_SuspendDevice(dev->usb_fd);
|
||||
dev->suspended = 1;
|
||||
|
||||
return USBSTORAGE_OK;
|
||||
|
||||
}
|
||||
/*
|
||||
The following is for implementing the ioctl interface inpired by the disc_io.h
|
||||
as used by libfat
|
||||
|
||||
This opens the first lun of the first usbstorage device found.
|
||||
*/
|
||||
|
||||
static usbstorage_handle __usbfd;
|
||||
static u8 __lun = 0;
|
||||
static u8 __mounted = 0;
|
||||
static u16 __vid = 0;
|
||||
static u16 __pid = 0;
|
||||
|
||||
void switchbuf(void)
|
||||
{
|
||||
memcpy( (void*)0x080A0000, __usbfd.buffer, CBW_SIZE );
|
||||
__usbfd.buffer = (u8*)0x080A0000;
|
||||
}
|
||||
/* perform 512 time the same read */
|
||||
s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer)
|
||||
{
|
||||
s32 retval;
|
||||
int i;
|
||||
if(__mounted != 1)
|
||||
return false;
|
||||
|
||||
for(i=0;i<512;i++){
|
||||
retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer);
|
||||
sector+=numSectors;
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
{
|
||||
__mounted = 0;
|
||||
USBStorage_Close(&__usbfd);
|
||||
}
|
||||
if(retval < 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
// temp function before libfat is available */
|
||||
s32 USBStorage_Try_Device(struct ehci_device *fd)
|
||||
{
|
||||
int maxLun,j,retval;
|
||||
int ret = USBStorage_Open(&__usbfd, fd);
|
||||
if( ret < 0)
|
||||
{
|
||||
dbgprintf("Could not open USB device:%d\n",ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
maxLun = USBStorage_GetMaxLUN(&__usbfd);
|
||||
if(maxLun == USBSTORAGE_ETIMEDOUT)
|
||||
{
|
||||
dbgprintf("USB device timed out\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for(j = 0; j < maxLun; j++)
|
||||
{
|
||||
retval = USBStorage_MountLUN(&__usbfd, j);
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
{
|
||||
USBStorage_Reset(&__usbfd);
|
||||
USBStorage_Close(&__usbfd);
|
||||
break;
|
||||
}
|
||||
|
||||
if(retval < 0)
|
||||
continue;
|
||||
|
||||
__vid=fd->desc.idVendor;
|
||||
__pid=fd->desc.idProduct;
|
||||
__mounted = 1;
|
||||
__lun = j;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbgprintf("USB device failed to mount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ums_init_done = 0;
|
||||
s32 USBStorage_Init(void)
|
||||
{
|
||||
int i;
|
||||
//debug_printf("usbstorage init %d\n", ums_init_done);
|
||||
if(ums_init_done)
|
||||
return 0;
|
||||
ums_init_done = 1;
|
||||
for(i = 0;i<ehci->num_port; i++){
|
||||
struct ehci_device *dev = &ehci->devices[i];
|
||||
if(dev->id != 0){
|
||||
USBStorage_Try_Device(dev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 USBStorage_Get_Capacity(u32*sector_size)
|
||||
{
|
||||
if(__mounted == 1)
|
||||
{
|
||||
if(sector_size){
|
||||
*sector_size = __usbfd.sector_size[__lun];
|
||||
}
|
||||
return __usbfd.n_sector[__lun];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer)
|
||||
{
|
||||
s32 retval;
|
||||
|
||||
if(__mounted != 1)
|
||||
return false;
|
||||
|
||||
retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer);
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
{
|
||||
__mounted = 0;
|
||||
USBStorage_Close(&__usbfd);
|
||||
}
|
||||
if(retval < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 USBStorage_Write_Sectors(u32 sector, u32 numSectors, const void *buffer)
|
||||
{
|
||||
s32 retval;
|
||||
|
||||
if(__mounted != 1)
|
||||
return false;
|
||||
|
||||
retval = USBStorage_Write(&__usbfd, __lun, sector, numSectors, buffer);
|
||||
if(retval == USBSTORAGE_ETIMEDOUT)
|
||||
{
|
||||
__mounted = 0;
|
||||
USBStorage_Close(&__usbfd);
|
||||
}
|
||||
if(retval < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
74
usbstorage.h
Normal file
74
usbstorage.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef __USBSTORAGE_H__
|
||||
#define __USBSTORAGE_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "ehci.h"
|
||||
|
||||
|
||||
#define USBSTORAGE_OK 0
|
||||
#define USBSTORAGE_ENOINTERFACE -10000
|
||||
#define USBSTORAGE_ESENSE -10001
|
||||
#define USBSTORAGE_ESHORTWRITE -10002
|
||||
#define USBSTORAGE_ESHORTREAD -10003
|
||||
#define USBSTORAGE_ESIGNATURE -10004
|
||||
#define USBSTORAGE_ETAG -10005
|
||||
#define USBSTORAGE_ESTATUS -10006
|
||||
#define USBSTORAGE_EDATARESIDUE -10007
|
||||
#define USBSTORAGE_ETIMEDOUT -ETIMEDOUT
|
||||
#define USBSTORAGE_EINIT -10009
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 configuration;
|
||||
u32 interface;
|
||||
u32 altInterface;
|
||||
|
||||
u8 ep_in;
|
||||
u8 ep_out;
|
||||
|
||||
u8 max_lun;
|
||||
u32 sector_size[16];
|
||||
u32 n_sector[16];
|
||||
|
||||
struct ehci_device * usb_fd;
|
||||
|
||||
//mutex_t lock;
|
||||
//cond_t cond;
|
||||
s32 retval;
|
||||
|
||||
u32 tag;
|
||||
u8 suspended;
|
||||
|
||||
u8 *buffer;
|
||||
} usbstorage_handle;
|
||||
|
||||
s32 USBStorage_Initialize(void);
|
||||
void switchbuf(void);
|
||||
|
||||
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd);
|
||||
s32 USBStorage_Close(usbstorage_handle *dev);
|
||||
s32 USBStorage_Reset(usbstorage_handle *dev);
|
||||
|
||||
s32 USBStorage_GetMaxLUN(usbstorage_handle *dev);
|
||||
s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun);
|
||||
s32 USBStorage_Suspend(usbstorage_handle *dev);
|
||||
|
||||
s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors);
|
||||
s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer);
|
||||
s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer);
|
||||
s32 USBStorage_Inquiry(usbstorage_handle *dev, u8 lun);
|
||||
|
||||
#define DEVICE_TYPE_WII_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B')
|
||||
|
||||
s32 USBStorage_Try_Device(struct ehci_device *fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __USBSTORAGE_H__ */
|
204
utils.h
Normal file
204
utils.h
Normal file
@ -0,0 +1,204 @@
|
||||
#ifndef __UTILS_H__
|
||||
#define __UTILS_H__
|
||||
|
||||
#include "global.h"
|
||||
|
||||
static inline u32 read32(u32 addr)
|
||||
{
|
||||
u32 data;
|
||||
__asm__ volatile ("ldr\t%0, [%1]" : "=l" (data) : "l" (addr));
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline void write32(u32 addr, u32 data)
|
||||
{
|
||||
__asm__ volatile ("str\t%0, [%1]" : : "l" (data), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (set), "l" (clear)
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline u16 read16(u32 addr)
|
||||
{
|
||||
u32 data;
|
||||
__asm__ volatile ("ldrh\t%0, [%1]" : "=l" (data) : "l" (addr));
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline void write16(u32 addr, u16 data)
|
||||
{
|
||||
__asm__ volatile ("strh\t%0, [%1]" : : "l" (data), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (set), "l" (clear)
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline u8 read8(u32 addr)
|
||||
{
|
||||
u32 data;
|
||||
__asm__ volatile ("ldrb\t%0, [%1]" : "=l" (data) : "l" (addr));
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline void write8(u32 addr, u8 data)
|
||||
{
|
||||
__asm__ volatile ("strb\t%0, [%1]" : : "l" (data), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (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]"
|
||||
: "=&l" (data)
|
||||
: "l" (addr), "l" (set), "l" (clear)
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are guaranteed to copy by reading from src and writing to dst in <n>-bit units
|
||||
* If size is not aligned, the remaining bytes are not copied
|
||||
*/
|
||||
extern void memset32(void *dst, u32 value, u32 size);
|
||||
extern void memset16(void *dst, u16 value, u32 size);
|
||||
extern void memset8(void *dst, u8 value, u32 size);
|
||||
|
||||
extern void memcpy(void *dst, void *src, u32 size);
|
||||
|
||||
//void udelay(u32 d);
|
||||
void panic(u8 v);
|
||||
|
||||
static inline u32 get_cpsr(void)
|
||||
{
|
||||
u32 data;
|
||||
__asm__ volatile ( "mrs\t%0, cpsr" : "=r" (data) );
|
||||
return data;
|
||||
}
|
||||
|
||||
#define STACK_ALIGN(type, name, cnt, alignment) \
|
||||
u8 _al__##name[((sizeof(type)*(cnt)) + (alignment) + \
|
||||
(((sizeof(type)*(cnt))%(alignment)) > 0 ? ((alignment) - \
|
||||
((sizeof(type)*(cnt))%(alignment))) : 0))]; \
|
||||
type *name = (type*)(((u32)(_al__##name)) + ((alignment) - (( \
|
||||
(u32)(_al__##name))&((alignment)-1))))
|
||||
|
||||
#define swab32(x) ((u32)( \
|
||||
(((u32)(x) & (u32)0x000000ffUL) << 24) | \
|
||||
(((u32)(x) & (u32)0x0000ff00UL) << 8) | \
|
||||
(((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
|
||||
(((u32)(x) & (u32)0xff000000UL) >> 24)))
|
||||
#define swab16(x) ((u16)( \
|
||||
(((u16)(x) & (u16)0x00ffU) << 8) | \
|
||||
(((u16)(x) & (u16)0xff00U) >> 8)))
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
116
utils_asm.S
Normal file
116
utils_asm.S
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||
random utilities
|
||||
|
||||
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||
|
||||
# This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||
# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
*/
|
||||
|
||||
.arm
|
||||
|
||||
.globl memcpy
|
||||
.globl memset32
|
||||
.globl memset16
|
||||
.globl memset8
|
||||
|
||||
.text
|
||||
|
||||
memcpy:
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
|
||||
stmfd sp!, {r4-r6}
|
||||
orr r3, r0, r1
|
||||
tst r3, #3
|
||||
bne _unaligned
|
||||
cmp r2, #0x0F
|
||||
bls _dwordcopyfast
|
||||
cmp r2, #0x1F
|
||||
bls _fastcopy16
|
||||
stmfd sp!, {r7-r9}
|
||||
|
||||
_fastcopy32:
|
||||
ldmia r1!, {r3-r9,r12}
|
||||
stmia r0!, {r3-r9,r12}
|
||||
sub r2, r2, #0x20
|
||||
cmp r2, #0x1F
|
||||
bls _done
|
||||
b _fastcopy32
|
||||
_done:
|
||||
ldmfd sp!, {r7-r9}
|
||||
|
||||
_fastcopy16:
|
||||
cmp r2, #0xf
|
||||
bls _dwordcopyfast
|
||||
ldmia r1!, {r3-r6}
|
||||
stmia r0!, {r3-r6}
|
||||
sub r2, r2, #0x10
|
||||
b _fastcopy16
|
||||
|
||||
_dwordcopyfast:
|
||||
cmp r2, #3
|
||||
bls _unaligned
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
sub r2, r2, #4
|
||||
b _dwordcopyfast
|
||||
|
||||
_unaligned:
|
||||
cmp r0, #0x1800000
|
||||
bcs _bytecopy
|
||||
mov r12, #0xff
|
||||
_dwordcopy:
|
||||
cmp r2, #0
|
||||
beq _done2
|
||||
mov r6, r0
|
||||
and r3, r6, #3
|
||||
ldr r4, [r6,-r3]!
|
||||
mov r3, r3, lsl #3
|
||||
rsb r3, r3, #0x18
|
||||
bic r5, r4, r12, lsl r3
|
||||
ldrb r4, [r1],#1
|
||||
orr r4, r5, r4, lsl r3
|
||||
str r4, [r6]
|
||||
add r0, r0, #1
|
||||
sub r2, r2, #1
|
||||
b _dwordcopy
|
||||
|
||||
_bytecopy:
|
||||
cmp r2, #0
|
||||
beq _done2
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
sub r2, r2, #1
|
||||
b _bytecopy
|
||||
_done2:
|
||||
ldmfd sp!, {r4-r6}
|
||||
bx lr
|
||||
|
||||
memset32:
|
||||
bics r2, #3
|
||||
bxeq lr
|
||||
1: str r1, [r0] ,#4
|
||||
subs r2, #4
|
||||
bne 1b
|
||||
bx lr
|
||||
|
||||
|
||||
memset16:
|
||||
bics r2, #1
|
||||
bxeq lr
|
||||
1: strh r1, [r0], #2
|
||||
subs r2, #2
|
||||
bne 1b
|
||||
bx lr
|
||||
|
||||
memset8:
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
1: strb r1, [r0], #1
|
||||
subs r2, #1
|
||||
bne 1b
|
||||
bx lr
|
||||
|
||||
|
442
vsprintf.c
Normal file
442
vsprintf.c
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* linux/lib/vsprintf.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
|
||||
/*
|
||||
* Wirzenius wrote this portably, Torvalds fucked it up :-)
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "global.h"
|
||||
#include "string.h"
|
||||
#include "ff.h"
|
||||
#include "memory.h"
|
||||
|
||||
char * strstr ( const char *str1, const char *str2)
|
||||
{
|
||||
char *cp = (char *) str1;
|
||||
char *s1, *s2;
|
||||
|
||||
if ( !*str2 )
|
||||
return((char *)str1);
|
||||
|
||||
while (*cp)
|
||||
{
|
||||
s1 = cp;
|
||||
s2 = (char *) str2;
|
||||
while ( *s1 && *s2 && !(*s1-*s2) )
|
||||
s1++, s2++;
|
||||
|
||||
if (!*s2)
|
||||
return(cp);
|
||||
cp++;
|
||||
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static inline int isdigit(int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
static inline int isxdigit(int c)
|
||||
{
|
||||
return (c >= '0' && c <= '9')
|
||||
|| (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
static inline int islower(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
static inline int toupper(int c)
|
||||
{
|
||||
if (islower(c))
|
||||
c -= 'a'-'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
static int skip_atoi(const char **s)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (isdigit(**s))
|
||||
i = i*10 + *((*s)++) - '0';
|
||||
return i;
|
||||
}
|
||||
|
||||
#define ZEROPAD 1 /* pad with zero */
|
||||
#define SIGN 2 /* unsigned/signed long */
|
||||
#define PLUS 4 /* show plus */
|
||||
#define SPACE 8 /* space if plus */
|
||||
#define LEFT 16 /* left justified */
|
||||
#define SPECIAL 32 /* 0x */
|
||||
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
|
||||
|
||||
#define do_div(n,base) ({ \
|
||||
int __res; \
|
||||
__res = ((unsigned long) n) % (unsigned) base; \
|
||||
n = ((unsigned long) n) / (unsigned) base; \
|
||||
__res; })
|
||||
|
||||
static char * number(char * str, long num, int base, int size, int precision
|
||||
,int type)
|
||||
{
|
||||
char c,sign,tmp[66];
|
||||
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
int i;
|
||||
|
||||
if (type & LARGE)
|
||||
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
if (type & LEFT)
|
||||
type &= ~ZEROPAD;
|
||||
if (base < 2 || base > 36)
|
||||
return 0;
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (type & SIGN) {
|
||||
if (num < 0) {
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
} else if (type & PLUS) {
|
||||
sign = '+';
|
||||
size--;
|
||||
} else if (type & SPACE) {
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
if (type & SPECIAL) {
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
i = 0;
|
||||
if (num == 0)
|
||||
tmp[i++]='0';
|
||||
else while (num != 0)
|
||||
tmp[i++] = digits[do_div(num,base)];
|
||||
if (i > precision)
|
||||
precision = i;
|
||||
size -= precision;
|
||||
if (!(type&(ZEROPAD+LEFT)))
|
||||
while(size-->0)
|
||||
*str++ = ' ';
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
if (type & SPECIAL) {
|
||||
if (base==8)
|
||||
*str++ = '0';
|
||||
else if (base==16) {
|
||||
*str++ = '0';
|
||||
*str++ = digits[33];
|
||||
}
|
||||
}
|
||||
if (!(type & LEFT))
|
||||
while (size-- > 0)
|
||||
*str++ = c;
|
||||
while (i < precision--)
|
||||
*str++ = '0';
|
||||
while (i-- > 0)
|
||||
*str++ = tmp[i];
|
||||
while (size-- > 0)
|
||||
*str++ = ' ';
|
||||
return str;
|
||||
}
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
unsigned long num;
|
||||
int i, base;
|
||||
char * str;
|
||||
const char *s;
|
||||
|
||||
int flags; /* flags to number() */
|
||||
|
||||
int field_width; /* width of output field */
|
||||
int precision; /* min. # of digits for integers; max
|
||||
number of chars for from string */
|
||||
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||
|
||||
for(str=buf ; *fmt ; ++fmt)
|
||||
{
|
||||
if (*fmt != '%') {
|
||||
*str++ = *fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* process flags */
|
||||
flags = 0;
|
||||
repeat:
|
||||
++fmt; /* this also skips first '%' */
|
||||
switch (*fmt) {
|
||||
case '-': flags |= LEFT; goto repeat;
|
||||
case '+': flags |= PLUS; goto repeat;
|
||||
case ' ': flags |= SPACE; goto repeat;
|
||||
case '#': flags |= SPECIAL; goto repeat;
|
||||
case '0': flags |= ZEROPAD; goto repeat;
|
||||
}
|
||||
|
||||
/* get field width */
|
||||
field_width = -1;
|
||||
if (isdigit(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0) {
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the precision */
|
||||
precision = -1;
|
||||
if (*fmt == '.') {
|
||||
++fmt;
|
||||
if (isdigit(*fmt))
|
||||
precision = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
/* get the conversion qualifier */
|
||||
qualifier = -1;
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
|
||||
qualifier = *fmt;
|
||||
++fmt;
|
||||
}
|
||||
|
||||
/* default base */
|
||||
base = 10;
|
||||
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
if (!(flags & LEFT))
|
||||
while (--field_width > 0)
|
||||
*str++ = ' ';
|
||||
*str++ = (unsigned char) va_arg(args, int);
|
||||
while (--field_width > 0)
|
||||
*str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
//if (!s)
|
||||
// s = "<NULL>";
|
||||
|
||||
len = strnlen(s, precision);
|
||||
|
||||
if (!(flags & LEFT))
|
||||
while (len < field_width--)
|
||||
*str++ = ' ';
|
||||
for (i = 0; i < len; ++i)
|
||||
*str++ = *s++;
|
||||
while (len < field_width--)
|
||||
*str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1) {
|
||||
field_width = 2*sizeof(void *);
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
str = number(str,
|
||||
(unsigned long) va_arg(args, void *), 16,
|
||||
field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
|
||||
case 'n':
|
||||
if (qualifier == 'l') {
|
||||
long * ip = va_arg(args, long *);
|
||||
*ip = (str - buf);
|
||||
} else {
|
||||
int * ip = va_arg(args, int *);
|
||||
*ip = (str - buf);
|
||||
}
|
||||
continue;
|
||||
|
||||
case '%':
|
||||
*str++ = '%';
|
||||
continue;
|
||||
|
||||
/* integer number formats - set up the flags and "break" */
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= LARGE;
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
*str++ = '%';
|
||||
if (*fmt)
|
||||
*str++ = *fmt;
|
||||
else
|
||||
--fmt;
|
||||
continue;
|
||||
}
|
||||
if (qualifier == 'l')
|
||||
num = va_arg(args, unsigned long);
|
||||
else if (qualifier == 'h') {
|
||||
num = (unsigned short) va_arg(args, int);
|
||||
if (flags & SIGN)
|
||||
num = (short) num;
|
||||
} else if (flags & SIGN)
|
||||
num = va_arg(args, int);
|
||||
else
|
||||
num = va_arg(args, unsigned int);
|
||||
str = number(str, num, base, field_width, precision, flags);
|
||||
}
|
||||
*str = '\0';
|
||||
return str-buf;
|
||||
}
|
||||
int sprintf( char *astr, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsprintf(astr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#define EXI 0xD806814
|
||||
|
||||
void EXISendByte( char byte )
|
||||
{
|
||||
|
||||
loop:
|
||||
*(vu32*)EXI = 0xD0;
|
||||
*(vu32*)(EXI+0x10) = 0xB0000000 | (byte<<20);
|
||||
*(vu32*)(EXI+0x0C) = 0x19;
|
||||
|
||||
while( *(vu32*)(EXI+0x0C)&1 );
|
||||
|
||||
u32 loop = *(vu32*)(EXI+0x10)&0x4000000;
|
||||
|
||||
*(vu32*)EXI = 0;
|
||||
|
||||
if( !loop )
|
||||
goto loop;
|
||||
|
||||
return;
|
||||
}
|
||||
void GeckoSendBuffer( char *buffer )
|
||||
{
|
||||
int i = 0;
|
||||
while( buffer[i] != '\0' )
|
||||
{
|
||||
EXISendByte( buffer[i] );
|
||||
++i;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
extern FIL Log;
|
||||
|
||||
static char buffer[128] ALIGNED(32);
|
||||
int dbgprintf( const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsprintf(buffer, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
//u32 cokie = read32( 0x0D800070 );
|
||||
//set32(0x0D800070,1);
|
||||
|
||||
if( read32( 0x0D800070 ) & 1 )
|
||||
{
|
||||
GeckoSendBuffer( buffer );
|
||||
}/* else {
|
||||
u32 read;
|
||||
u32 fres = f_open( &Log, "/dm.log", FA_READ|FA_WRITE|FA_OPEN_ALWAYS );
|
||||
if( fres != FR_OK )
|
||||
{
|
||||
write32( 0x0D800070, 1 );
|
||||
dbgprintf("f_open():%d\n", fres );
|
||||
}
|
||||
|
||||
f_lseek( &Log, Log.fsize );
|
||||
f_write( &Log, buffer, strlen(buffer), &read );
|
||||
f_close( &Log );
|
||||
}*/
|
||||
|
||||
//write32( 0x0D800070, cokie );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static char ascii(char s)
|
||||
{
|
||||
if(s < 0x20) return '.';
|
||||
if(s > 0x7E) return '.';
|
||||
return s;
|
||||
}
|
||||
|
||||
void hexdump(void *d, int len)
|
||||
{
|
||||
u8 *data;
|
||||
int i, off;
|
||||
data = (u8*)d;
|
||||
for (off=0; off<len; off += 16) {
|
||||
dbgprintf("%08x ",off);
|
||||
for(i=0; i<16; i++)
|
||||
if((i+off)>=len) dbgprintf(" ");
|
||||
else dbgprintf("%02x ",data[off+i]);
|
||||
|
||||
dbgprintf(" ");
|
||||
for(i=0; i<16; i++)
|
||||
if((i+off)>=len) dbgprintf(" ");
|
||||
else dbgprintf("%c",ascii(data[off+i]));
|
||||
dbgprintf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
//void fatal(const char *fmt, ...)
|
||||
//{
|
||||
// va_list args;
|
||||
// char buffer[1024];
|
||||
// int i;
|
||||
//
|
||||
// va_start(args, fmt);
|
||||
// i = vsprintf(buffer, fmt, args);
|
||||
// va_end(args);
|
||||
// OSReport(buffer);
|
||||
// for (;;);
|
||||
//}
|
||||
//
|
||||
|
||||
|
8
vsprintf.h
Normal file
8
vsprintf.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdarg.h>
|
||||
#include "string.h"
|
||||
|
||||
char * strstr ( const char *str1, const char *str2);
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int _sprintf( char *buf, const char *fmt, ... );
|
||||
int dbgprintf( const char *fmt, ...);
|
||||
void hexdump(void *d, int len);
|
Loading…
Reference in New Issue
Block a user