TwlToolsRED/build/tools/KENJCleaner/src/main.c
N1363 bc6cd94f64 KENJCleaner追加。
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@521 7061adef-622a-194b-ae81-725974e89856
2010-09-29 09:51:02 +00:00

607 lines
17 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************/
/* main.c */
/* SaveDataCleaner */
/* */
/* Copyright (C) 2003-2006 NINTENDO Co.,Ltd. */
/********************************************************************/
/*
ƒ<>ƒCƒ“
*/
#include <twl.h>
#include <twl/aes.h>
#include <twl/na.h>
#include <twl/na/ARM9/init.h>
#include <twl/sea.h>
#include <twl/nam.h>
#include "myChar.h"
#include "myFunc.h"
// define data-----------------------------------------------------------------
#define MY_DEBUG 0
#define ROUND_UP(value, alignment) \
(((u32)(value) + (alignment-1)) & ~(alignment-1))
#define STREAMING_BUFFER_SIZE (128 * 1024)
#define TITLEID_HI_USER_NAND 0x0003000400000000LL
#define TARGET_INITIALCODE_SPEC_FILE "SaveDataCleaner.spec"
// extern data-----------------------------------------------------------------
// function's prototype--------------------------------------------------------
static void INTR_VBlank( void );
static void InitHeap( void );
BOOL SearchTitle( OSTitleId titleID, BOOL *pIsPrivSave, BOOL *pIsPubSave );
BOOL CleanupSaveDataDrive( const char *pDriveName , OSTitleId titleID );
BOOL CreateFileWithLength( char *path, u32 length );
BOOL DeleteDirectoryRecursively( const char *path );
BOOL FillFileRandom( const char* path );
BOOL DumpFile( const char* pPath );
BOOL ReadTargetFileFromSD( const char *pFilename, char **ppDst, u32 *pFileSize );
// global variables------------------------------------------------------------
u8 targetGameCode[ 5 ] = { 'K', 'E', 'N', 'J', 0x00 };
// static variables------------------------------------------------------------
static u8 sStreamBuffer[ STREAMING_BUFFER_SIZE ] ATTRIBUTE_ALIGN(32);
static FSFATFSArchiveWork sOtherTitleWork ATTRIBUTE_ALIGN(32);
// const data------------------------------------------------------------------
// ============================================================================
// function's description
// ============================================================================
void TwlMain(void)
{
BOOL isFound = FALSE;
BOOL isPrivSave = FALSE;
BOOL isPubSave = FALSE;
BOOL isFailed = FALSE;
BOOL isAutoExe = TRUE;
u16 pad_old = 0;
u16 pad = 0;
u16 trg = 0;
OSTitleId titleID;
(void)OS_EnableIrq();
(void)OS_EnableInterrupts();
OS_Init();
SEA_Init();
FS_Init( 3 );
// AES_Init();
InitHeap();
InitDispMain();
InitDispSub ();
NAM_Init( OS_AllocFromMain, OS_FreeToMain );
// Vƒuƒ‰ƒ“ƒNŠ„è<E2809A>žÝ‰Â----------------------------
(void)OS_SetIrqFunction( OS_IE_V_BLANK, INTR_VBlank );
(void)OS_EnableIrqMask ( OS_IE_V_BLANK );
(void)GX_VBlankIntr( TRUE );
//---- •\ަŠJŽn
GX_DispOn();
GXS_DispOn();
PrintStringS( 1, 0, YELLOW, "SaveData Clearner" );
// SDƒJ<C692>[ƒh<C692>ãÌSPECƒtƒ@ƒCƒ©ç<E2809A>Aƒ^<5E>[ƒQƒbƒgÌGameCodeð“ÇÝ<E2809A>žÝ
#if USE_SDCARD
{
u32 size;
char *pSrc = TARGET_INITIALCODE_SPEC_FILE;
char *pSDFileBuffer;
if( !ReadTargetFileFromSD( pSrc, &pSDFileBuffer, &size ) ) {
PrintStringS( 1, 6, RED, "SD card specfile read failed." );
PrintStringS( 1, 8, WHITE, "Please set" );
PrintStringS( 1, 10, WHITE, " \"%s\"", TARGET_INITIALCODE_SPEC_FILE );
SVC_WaitVBlankIntr();
OS_Terminate();
}
if( !STD_TSScanf( pSDFileBuffer, "%4s", targetGameCode ) ||
STD_StrLen( (const char *)targetGameCode ) != 4 ) {
PrintStringS( 1, 6, RED, "SD card specfile format failed." );
PrintStringS( 1, 8, WHITE, "Please set InitialCode." );
SVC_WaitVBlankIntr();
OS_Terminate();
}
OS_TPrintf( "%s\n", targetGameCode );
OS_Free( pSDFileBuffer );
}
#endif
// targetGameCode ‚©‚ç titleID ð<E2809A>ì<EFBFBD>¬
{
int i;
u8 *pDst = (u8 *)&titleID;
titleID = TITLEID_HI_USER_NAND;
for( i = 0; i < 4; i++ ) {
*pDst++ = targetGameCode[ 3 -i ];
}
}
// ƒZ<C692>[ƒuƒf<C692>[ƒ^ƒT<C692>[ƒ`
isFound = SearchTitle( titleID, &isPrivSave, &isPubSave );
PrintStringS( 1, 6, WHITE, "InitialCode : %s", targetGameCode );
if( isFound ) {
PrintStringS( 1, 8, GREEN, "application found.", targetGameCode );
PrintStringS( 1, 10, WHITE, "Press [A] to Cleanup START." );
PrintStringS( 1, 11, WHITE, "Press [B] to STOP." );
}else {
PrintStringS( 1, 8, YELLOW, "application not found.", targetGameCode );
*(u16 *)0x05000006 = myPalette[ YELLOW ][ 1 ];
}
SVC_WaitVBlankIntr();
// ƒ<>ƒCƒ“ƒ<C692>[ƒv----------------------------
trg = PAD_Read(); // ƒpƒbƒhƒf<C692>[ƒ^“ǂݎæ‚è
while( isFound ){
// ƒpƒbƒhƒf<C692>[ƒ^“ǂݎæ‚è
pad_old = pad;
pad = PAD_Read();
trg = (u16)( pad ^ pad_old );
if( ( trg & ( PAD_BUTTON_A | PAD_BUTTON_B ) ) || isAutoExe ) {
ClearRectangleS( 1, 10, 31, 1 );
ClearRectangleS( 1, 11, 31, 1 );
}
if( ( trg & PAD_BUTTON_A ) || isAutoExe ) {
// ƒZ<C692>[ƒuƒf<C692>[ƒ^ƒNƒŠƒAŽÀ<C5BD>s
// PrivateƒZ<C692>[ƒuƒf<C692>[ƒ^
PrintStringS( 1, 10, WHITE, "Private Save:" );
if( isPrivSave ) {
PrintStringS( 14, 10, YELLOW, "cleanup executing..." );
if( CleanupSaveDataDrive( "otherPrv", titleID ) ) {
PrintStringS( 14, 10, GREEN, "cleanup succeedded. " );
}else {
PrintStringS( 14, 10, RED, "cleanup failed. " );
isFailed = TRUE;
}
}else {
PrintStringS( 14, 10, YELLOW, "not existed." );
}
// PublicƒZ<C692>[ƒuƒf<C692>[ƒ^
PrintStringS( 1, 11, WHITE, "Public Save:" );
if( isPubSave ) {
PrintStringS( 14, 11, YELLOW, "cleanup executing." );
if( CleanupSaveDataDrive( "otherPub", titleID ) ) {
PrintStringS( 14, 11, GREEN, "cleanup succeedded. " );
}else {
PrintStringS( 14, 11, RED, "cleanup failed. " );
isFailed = TRUE;
}
}else {
PrintStringS( 14, 11, YELLOW, "not existed." );
}
PrintStringS( 1, 12, WHITE, "Application :" );
PrintStringS( 14, 12, YELLOW, "cleanup executing." );
if( NAM_DeleteTitle( titleID ) == NAM_OK ) {
PrintStringS( 14, 12, GREEN, "cleanup succeedded. " );
}else {
PrintStringS( 14, 12, RED, "cleanup failed. " );
isFailed = TRUE;
}
if( isFailed ) {
*(u16 *)0x05000006 = myPalette[ RED ][ 1 ];
}else {
*(u16 *)0x05000006 = myPalette[ LIGHTGREEN ][ 1 ];
}
break;
}else if( trg & PAD_BUTTON_B ) {
// ƒZ<C692>[ƒuƒf<C692>[ƒ^ƒNƒŠƒAƒLƒƒƒ“ƒZƒ<C692>B
PrintStringS( 1, 10, YELLOW, "Cancel SaveData cleanup." );
break;
}
SVC_WaitVBlankIntr(); // Vƒuƒ‰ƒ“ƒNŠ„<C5A0>ž<EFBFBD>I—¹Ò¿
}
SVC_WaitVBlankIntr();
OS_Terminate();
}
// Vƒuƒ‰ƒ“ƒNŠ„è<E2809A>žÝ
static void INTR_VBlank(void)
{
//---- BG-VRAMÌ<E2809A>X<EFBFBD>V
DC_FlushRange( bg0BakM, sizeof(bg0BakM) );
MI_CpuCopyFast ( bg0BakM, (void*)( HW_BG_VRAM + BG0_SCREEN_BASE ), sizeof(bg0BakM) );
DC_FlushRange( bg0BakS, sizeof(bg0BakS) );
MI_CpuCopyFast ( bg0BakS, (void*)( HW_DB_BG_VRAM + BG0_SCREEN_BASE ), sizeof(bg0BakS) );
//---- Š„è<E2809A>žÝƒ`ƒFƒbƒNƒtƒ‰ƒO
OS_SetIrqCheckFlag( OS_IE_V_BLANK );
}
// ƒq<C692>[ƒv<C692>‰Šú‰»
static void InitHeap( void )
{
void* tempLo;
OSHeapHandle hh;
// ƒ<>ƒCƒ“ƒ<E2809C>ƒƒŠ<C692>ã̃AƒŠ<C692>[ƒiɃq<C692>[ƒvðÐÆÂ<E2809A>ì<EFBFBD>¬
tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
if (hh < 0) {
// ƒq<C692>[ƒv<C692>ì<EFBFBD>¬Éޏ”sµ½<E2809A>ê<EFBFBD>͈Ù<CB86>í<EFBFBD>I—¹
OS_Panic("ARM9: Fail to create heap...\n");
}
(void)OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
}
/*---------------------------------------------------------------------------*
ŠÖ<C5A0>è`
*---------------------------------------------------------------------------*/
// Žwèƒ^ƒCƒgƒª<E28098>ݷ驊m”Fµ<E2809A>A<E28098>Ý·éÈç<E2809A>AsameMakerFlag ð­<E280B9>§ƒZƒbƒgµ<E2809A>APrivateƒZ<C692>[ƒuƒf<C692>[ƒ^<5E>APublicƒZ<C692>[ƒuƒf<C692>[ƒ^Ì<E28098>Ý—L³ð•Ô·<E2809A>B
BOOL SearchTitle( OSTitleId titleID, BOOL *pIsPrivSave, BOOL *pIsPubSave )
{
int i;
int index, shift;
OSTitleIDList *pList = (OSTitleIDList *)HW_OS_TITLE_ID_LIST;
for ( i = 0; i < pList->num; i++ ) {
if( pList->TitleID[ i ] == titleID ) {
break;
}
}
if( i == pList->num ) {
*pIsPrivSave = FALSE;
*pIsPubSave = FALSE;
return FALSE;
}
index = i >> 3;
shift = i % 8;
pList->sameMakerFlag[ index ] |= 0x01 << shift;
// pList->privateFlag[ index ] |= 0x01 << shift; // ƒ†<C692>[ƒU<C692>[ƒAƒvƒŠÈç<E2809A>AprivateFlagàâèȢ͸<E2809A>B
*pIsPrivSave = ( pList->privateFlag[ index ] & ( 0x01 << shift ) ) ? TRUE : FALSE;
*pIsPubSave = ( pList->publicFlag [ index ] & ( 0x01 << shift ) ) ? TRUE : FALSE;
return TRUE;
}
// Žwè³ê½ƒZ<C692>[ƒuƒf<C692>[ƒ^ƒhƒ‰ƒCƒũZ<C692>[ƒuƒf<C692>[ƒ^<5E>ÁŽ
BOOL CleanupSaveDataDrive( const char *pDriveName , OSTitleId titleID ) // otherPrv, otherPub
{
#define TEMP_FILE "temp.bin"
BOOL result = TRUE;
FSArchiveResource rsc, rsc2;
char path[ FS_ENTRY_LONGNAME_MAX ];
if( pDriveName == NULL ) {
OS_TPrintf( "drive name invalid.\n" );
return FALSE;
}
// PrivateƒZ<C692>[ƒuƒf<C692>[ƒ^‚ðƒ}ƒEƒ“ƒg
if( FSi_MountSpecialArchive( titleID, pDriveName, &sOtherTitleWork) != FS_RESULT_SUCCESS ) {
return FALSE;
}
// PrivateƒZ<C692>[ƒuƒf<C692>[ƒ^ƒhƒ‰ƒCƒu<C692>ãÌSƒf<C692>[ƒ^<5E>í<EFBFBD>œ
STD_TSPrintf( path, "%s:/", pDriveName );
if( !DeleteDirectoryRecursively( path ) ) {
OS_TPrintf( "%s delete recursively failed.\n", path );
result = FALSE;
goto END;
}
// ƒhƒ‰ƒCƒuÌó«—̈æðŽæ“¾
if( !FS_GetArchiveResource( path, &rsc ) ) {
OS_TPrintf( "FS_GetArchiveResource(%s) failed : code = %08x\n", path, FS_GetArchiveResultCode( &rsc ) );
result = FALSE;
goto END;
}
// ó«—̈æª32bitð´¦Ä¢½<E2809A>ê<EFBFBD>̓Gƒ‰<C692>[
if( rsc.availableSize > 0x0000000100000000LL ) {
OS_TPrintf( "%s : availableSize over 32bit.\n", pDriveName );
result = FALSE;
goto END;
}
STD_TSPrintf( path, "%s:/%s", pDriveName, TEMP_FILE );
#if MY_DEBUG
(void)CreateFileWithLength( path, (u32)rsc.availableSize );
(void)DumpFile( path );
(void)FS_DeleteFile( path );
#endif
// ƒhƒ‰ƒCƒuÌó«ƒTƒCƒYMAXÅ<E2809A>ATEMPƒtƒ@ƒCƒ<C692><EFBFBD>¬
if( !CreateFileWithLength( path, (u32)rsc.availableSize ) ) {
OS_TPrintf( "CreateFileWithLength(%s, %08x) failed.\n", path, (u32)rsc.availableSize );
result = FALSE;
goto END;
}
// ƒtƒ@ƒCƒƒ‰ƒ“ƒ_ƒ€ƒtƒBƒ
if( !FillFileRandom( path ) ) {
OS_TPrintf( "FillFileRandom(%s) failed.\n", path );
result = FALSE;
}
// ƒtƒ@ƒCƒ<C692>í<EFBFBD>œ
if( !FS_DeleteFile( path ) ) {
OS_TPrintf( "FS_DeleteFile(%s) failed.\n", path );
result = FALSE;
}
// <20>Ä“xƒhƒ‰ƒCƒuÌó«—̈æðŽæ“¾
if( !FS_GetArchiveResource( path, &rsc2 ) ) {
OS_TPrintf( "FS_GetArchiveResource(%s) failed : code = %08x\n", path, FS_GetArchiveResultCode( &rsc2 ) );
result = FALSE;
}
#if MY_DEBUG
(void)CreateFileWithLength( path, (u32)rsc.availableSize );
(void)DumpFile( path );
(void)FS_DeleteFile( path );
#endif
// ó«ƒTƒCƒYª“¯©ƒ`ƒFƒbƒN
OS_TPrintf( "Before available size : %016llx\n", rsc.availableSize );
OS_TPrintf( "After available size : %016llx\n", rsc2.availableSize );
if( rsc.availableSize != rsc2.availableSize ) {
OS_TPrintf( "available size error.\n" );
result = FALSE;
}
END:
// ƒZ<C692>[ƒuƒf<C692>[ƒ^‚̃}ƒEƒ“ƒg‰ð<E280B0>œ
(void)FSi_MountSpecialArchive(0, NULL, &sOtherTitleWork);
return result;
}
// ŽwèƒpƒXˆÈ‰ºÌƒfƒBƒŒƒNƒgƒŠð<E2809A>ÁŽ
BOOL DeleteDirectoryRecursively( const char *pPath )
{
FSFile dir;
FSDirectoryEntryInfo entryInfo;
BOOL ret = TRUE;
char path[ FS_ENTRY_LONGNAME_MAX ];
FS_InitFile( &dir );
// ˆø<CB86>ÅŽwè³ê½ƒfƒBƒŒƒNƒgƒŠðŠJ­
if ( !FS_OpenDirectory( &dir, pPath, FS_FILEMODE_R ) ) {
OS_TWarning( "Fail! FS_OpenDirectory(%s) in %s\n", pPath, __func__ );
return FALSE;
}
// ƒfƒBƒŒƒNƒgƒŠÌ<E28099>gð“ÇÞ
while ( FS_ReadDirectory( &dir, &entryInfo ) )
{
if ( STD_CompareString( entryInfo.longname, "." ) == 0 ||
STD_CompareString( entryInfo.longname, ".." ) == 0 ) {
continue;
}
STD_CopyLString( path, pPath, FS_ENTRY_LONGNAME_MAX );
STD_ConcatenateLString( path, "/", FS_ENTRY_LONGNAME_MAX );
STD_ConcatenateLString( path, entryInfo.longname, FS_ENTRY_LONGNAME_MAX );
// ƒfƒBƒŒƒNƒgƒŠ
if (entryInfo.attributes & FS_ATTRIBUTE_IS_DIRECTORY) {
if (!FS_DeleteDirectoryAuto(path)) {
ret = FALSE;
OS_TWarning( "Fail! FS_DeleteDirectoryAuto(%s) in %s\n", path, __func__ );
}
}else {
// ƒtƒ@ƒCƒ
if ( !FS_DeleteFileAuto( path ) ) {
ret = FALSE;
OS_TWarning( "Fail! FS_DeleteFileAuto(%s) in %s\n", path, __func__ );
}
}
}
// ƒfƒBƒŒƒNƒgƒŠð•Âé
FS_CloseDirectory( &dir );
return ret;
}
// Žwèƒtƒ@ƒCƒðŽwèƒTƒCƒYÅ<E2809A>ì<EFBFBD>¬
BOOL CreateFileWithLength( char *path, u32 length )
{
FSFile file;
BOOL result = TRUE;
// PrivateƒZ<C692>[ƒuƒf<C692>[ƒ^ƒhƒ‰ƒCƒu<C692>ãÉTEMPƒtƒ@ƒCƒ<C692>ì<EFBFBD>¬
if ( !FS_CreateFile( path, FS_PERMIT_R | FS_PERMIT_RW ) )
{
OS_TPrintf( "FS_CreateFile(%s) failed.\n", path );
return FALSE;
}
// TEMPƒtƒ@ƒCƒƒI<C692>[ƒvƒ“
FS_InitFile(&file);
if ( !FS_OpenFileEx( &file, path, FS_FILEMODE_W ) )
{
OS_TPrintf( "FS_OpenFile(%s) failed.\n", path );
result = FALSE;
goto END;
}
// ƒtƒ@ƒCƒƒTƒCƒYðƒZƒbƒg
if ( FS_SetFileLength( &file, length ) != FS_RESULT_SUCCESS )
{
OS_TPrintf( "FS_SetFileLength(%s) failed.\n", path );
result = FALSE;
}
END:
// ƒtƒ@ƒCƒƒNƒ<4E><C692>[ƒY
(void)FS_CloseFile( &file );
return result;
}
// Žwèƒtƒ@ƒCƒðƒ‰ƒ“ƒ_ƒ€ƒf<C692>[ƒ^ŃtƒBƒ
BOOL FillFileRandom( const char* pPath )
{
u64 seed;
MATHRandContext32 rndctx;
u32 *pBuffer = (u32 *)sStreamBuffer;
s32 result = TRUE;
FSFile f;
// —<><E28094>ÌSEED<45>Ýè
if( AES_Rand( &seed, sizeof(seed) ) != AES_RESULT_SUCCESS ) {
return FALSE;
}
MATH_InitRand32( &rndctx, seed );
// ƒtƒ@ƒCƒƒtƒBƒ
FS_InitFile( &f );
if( !FS_OpenFileEx( &f, pPath, FS_FILEMODE_RWL ) ) {
return FALSE;
}else {
u32 fileSize;
u32 current;
fileSize = FS_GetFileLength(&f);
for( current = 0; current < fileSize; current += STREAMING_BUFFER_SIZE ) {
const u32 nextSize = MATH_MIN( STREAMING_BUFFER_SIZE, fileSize - current);
const u32 nextU32 = MATH_DIVUP( nextSize, sizeof(u32) );
u32 i;
s32 writtenSize;
u32* p = pBuffer;
for( i = 0; i < nextU32; ++i ) {
*p++ = MATH_Rand32( &rndctx, 0 );
}
writtenSize = FS_WriteFile( &f, pBuffer, (s32)nextSize );
if( writtenSize != (s32)nextSize ) {
result = FALSE;
break;
}
}
(void)FS_CloseFile( &f );
}
return result;
}
// Žwèƒtƒ@ƒCƒðƒXƒgƒŠ<C692>[ƒ€ƒoƒbƒtƒ@‚ɓǂݎ̂Ä
BOOL DumpFile( const char* pPath )
{
u32 *pBuffer = (u32 *)sStreamBuffer;
s32 result = TRUE;
FSFile f;
// ƒtƒ@ƒCƒƒtƒBƒ
FS_InitFile( &f );
if( !FS_OpenFileEx( &f, pPath, FS_FILEMODE_R ) ) {
return FALSE;
}else {
u32 fileSize;
u32 current;
fileSize = FS_GetFileLength(&f);
for( current = 0; current < fileSize; current += STREAMING_BUFFER_SIZE ) {
const u32 nextSize = MATH_MIN( STREAMING_BUFFER_SIZE, fileSize - current);
const u32 nextU32 = MATH_DIVUP( nextSize, sizeof(u32) );
s32 readSize;
readSize = FS_ReadFile( &f, pBuffer, (s32)nextSize );
if( readSize != (s32)nextSize ) {
result = FALSE;
break;
}
}
(void)FS_CloseFile( &f );
}
return result;
}
// SDƒJ<C692>[ƒh̃<C692>[ƒgƒfƒBƒŒƒNƒgƒŠ<C692>ãÌŽwèƒtƒ@ƒCƒðƒoƒbƒtƒ@É“ÇÝ<E2809A>žÝ
BOOL ReadTargetFileFromSD( const char *pFilename, char **ppDst, u32 *pFileSize )
{
FSFile dir, file;
BOOL open_is_ok;
BOOL read_is_ok;
u32 allocSize;
BOOL result = TRUE;
char fullPath[FS_ENTRY_LONGNAME_MAX+6];
// ƒoƒbƒtƒ@̃NƒŠƒA
MI_CpuClear8( fullPath, sizeof(fullPath) );
// SDƒJ<C692>[ƒh̃<C692>[ƒgƒfƒBƒŒƒNƒgƒŠðŒŸ<C592>õ
FS_InitFile(&dir);
if ( !FS_OpenDirectory(&dir, "sdmc:/", FS_FILEMODE_R) )
{
OS_TPrintf("Error FS_OpenDirectory(sdmc:/)");
}
else
{
FSDirectoryEntryInfo info[1];
// ƒ<C692>[ƒgƒfƒBƒŒƒNƒgƒŠ<C692>ãŃ^<5E>[ƒQƒbƒgƒtƒ@ƒCƒðT·
while (FS_ReadDirectory(&dir, info))
{
if ((info->attributes & (FS_ATTRIBUTE_DOS_DIRECTORY | FS_ATTRIBUTE_IS_DIRECTORY)) == 0 )
{
if (!STD_CompareNString(info->longname, pFilename, STD_GetStringLength( pFilename ) ) )
{
STD_CopyString( fullPath, "sdmc:/" );
STD_ConcatenateString( fullPath, pFilename );
break;
}
}
}
(void)FS_CloseDirectory(&dir);
}
// ƒtƒ@ƒCƒƒI<C692>[ƒvƒ“
FS_InitFile(&file);
open_is_ok = FS_OpenFile(&file, fullPath);
if (!open_is_ok)
{
OS_TPrintf( "FS_OpenFile(\"%s\") ... ERROR!\n", fullPath);
return FALSE;
}
// ƒtƒ@ƒCƒƒŠ<C692>[ƒh
*pFileSize = FS_GetFileLength(&file) ;
allocSize = ROUND_UP(*pFileSize, 32) ;
*ppDst = OS_Alloc( allocSize );
SDK_NULL_ASSERT(*ppDst);
DC_InvalidateRange(*ppDst, allocSize);
read_is_ok = FS_ReadFile( &file, *ppDst, (s32)*pFileSize );
FS_CloseFile(&file);
if (!read_is_ok)
{
OS_TPrintf( "FS_ReadFile(\"%s\") ... ERROR!\n", fullPath);
OS_Free(*ppDst);
return FALSE;
}
return TRUE;
}