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