/*---------------------------------------------------------------------------* Project: SystemUpdater File: process_import.c Copyright 2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: $ $Rev$ $Author$ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include "kami_font.h" #include "hw_info.h" #include "TWLHWInfo_api.h" #include "graphics.h" #include "kami_global.h" #include "font.h" #include "sort_title.h" /*---------------------------------------------------------------------------* 型定義 *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* 定数定義 *---------------------------------------------------------------------------*/ #define THREAD_STACK_SIZE (16*1024) #define DIR_NUM 3 #define FULLPATH_LEN ( FS_ENTRY_LONGNAME_MAX+6 ) static const char* sDirectoryNameRegion[] = { "japan", "america", "europe", "australia", "china", "korea" }; static const char* sDirectoryNameConsole[] = { "debugger", // IS_TWL_DEBUGGER "standalone", // IS_TWL_CAPTURE "standalone", // TWL "" // UNKNOWN }; typedef struct { u8 dirNameIndex; char fileName[FS_ENTRY_LONGNAME_MAX]; } ImportFileInfo; /*---------------------------------------------------------------------------* 内部変数定義 *---------------------------------------------------------------------------*/ static u32 sCurrentProgress; static vu8 sNowImport = FALSE; static vu8 sProgress = FALSE; static u8 sStack[THREAD_STACK_SIZE]; /*---------------------------------------------------------------------------* 内部関数宣言 *---------------------------------------------------------------------------*/ static s32 kamiImportTad(const char* path, BOOL erase); static void ProgressThread(void* arg); static void Destructor(void* arg); void ProgressDraw(f32 ratio); BOOL ImportDirectoryTad(char* directory); static u32 CountTadInDir( char (*dir_path)[FULLPATH_LEN], u32 dir_num ); static BOOL MakeList( char (*dir)[FULLPATH_LEN], u32 dir_max, ImportFileInfo *info, TitleSortSet *sortset ); static BOOL ImportTadFromList( char (*dir)[FULLPATH_LEN], ImportFileInfo *info, TitleSortSet *sortset, u32 import_max ); /*---------------------------------------------------------------------------* 処理関数定義 *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* Name: ProcessImport Description: Arguments: なし。 Returns: なし。 *---------------------------------------------------------------------------*/ BOOL ProcessImport( void *(*alloc)(unsigned long), void (*free)(void *) ) { const s32 MAX_RETRY_COUNT = 2; BOOL result = TRUE; char directory[DIR_NUM][FULLPATH_LEN]; s32 i=0; s32 j=0; u32 fileCount = 0; ImportFileInfo *importFileInfoList = NULL; TitleSortSet *titleSortSetList = NULL; void *sortBuf = NULL; OS_WaitVBlankIntr(); NNS_G2dCharCanvasClearArea(&gCanvas, TXT_COLOR_WHITE, 0, 30, 256, 100); OS_WaitVBlankIntr(); NNS_G2dCharCanvasClearArea(&gCanvas2, TXT_COLOR_BLACK, 0, 130, 256, 62); OS_WaitVBlankIntr(); NNS_G2dTextCanvasDrawText(&gTextCanvas, 40, 60, TXT_COLOR_WHITE_BASE, TXT_DRAWTEXT_FLAG_DEFAULT, (const char*)L"Now Import.."); while(!FadeInTick()) { G3X_Reset(); G3_Identity(); G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_DECAL, GX_CULL_NONE, 0, 31, 0); G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W); OS_WaitVBlankIntr(); } STD_TSNPrintf(directory[0], sizeof(directory[0]), "rom:/data/%s/%s/", sDirectoryNameConsole[GetConsole()], sDirectoryNameRegion[gRegion]); STD_TSNPrintf(directory[1], sizeof(directory[1]), "rom:/data/common/%s/", sDirectoryNameRegion[gRegion]); STD_TSNPrintf(directory[2], sizeof(directory[2]), "rom:/data/common/"); // ディレクトリ内の TAD ファイル数をカウントする fileCount = CountTadInDir(directory, DIR_NUM); // ファイル名+ディレクトリインデックス配列、TitleSortInfo 配列を確保 importFileInfoList = alloc( sizeof(ImportFileInfo) * fileCount ); titleSortSetList = alloc( sizeof(TitleSortSet) * fileCount ); // 情報を読み込む result &= MakeList( directory, DIR_NUM, importFileInfoList, titleSortSetList); // TitleSortInfoをソート sortBuf = alloc( MATH_QSortStackSize( fileCount ) ); SortTitle( titleSortSetList, fileCount, sortBuf ); // インポート result &= ImportTadFromList( directory, importFileInfoList, titleSortSetList, fileCount ); // もはや必要ないリストの解放 free( importFileInfoList ); free( titleSortSetList ); while (!FadeOutTick()) { OS_WaitVBlankIntr(); } return result; } /*---------------------------------------------------------------------------* Name: CountTadInDir Description: リストで指定したディレクトリにある TAD の総数を返します。 Arguments: dir_list,dir_max Returns: u32 *---------------------------------------------------------------------------*/ static u32 CountTadInDir( char (*dir_list)[FULLPATH_LEN], u32 dir_max ) { int l; u32 count = 0; for( l=0; lattributes & (FS_ATTRIBUTE_DOS_DIRECTORY | FS_ATTRIBUTE_IS_DIRECTORY)) == 0) { char* pExtension; // 拡張子のチェック pExtension = STD_SearchCharReverse( info->longname, '.'); if (pExtension) { if (!STD_CompareString( pExtension, ".tad") || !STD_CompareString( pExtension, ".TAD") ) { count++; } } } } FS_CloseDirectory( &dir ); } return count; } /*---------------------------------------------------------------------------* Name: MakeList Description: リストで指定したディレクトリから ImportTadFromList を行うのに必要なリストを作成します。 Arguments: dir_list, dir_max, info, sortset Returns: BOOL *---------------------------------------------------------------------------*/ static BOOL MakeList( char (*dir_list)[FULLPATH_LEN], u32 dir_max, ImportFileInfo *info, TitleSortSet *sortset ) { int l; u32 count = 0; BOOL result = TRUE; for( l=0; lattributes & (FS_ATTRIBUTE_DOS_DIRECTORY | FS_ATTRIBUTE_IS_DIRECTORY)) == 0) { char* pExtension; // 拡張子のチェック pExtension = STD_SearchCharReverse( fsinfo->longname, '.'); if (pExtension) { if (!STD_CompareString( pExtension, ".tad") || !STD_CompareString( pExtension, ".TAD") ) { NAMTadInfo tadInfo; char fullPath[FULLPATH_LEN]; // フルパス作成 STD_TSNPrintf(fullPath, sizeof(fullPath), "%s/%s", dirName, fsinfo->longname); // TAD情報取得 // tadファイルの情報取得 if (NAM_ReadTadInfo(&tadInfo, fullPath) != NAM_OK) { // 失敗したらエラーを表示して次のファイルへ、結果はFalse kamiFontPrintfConsole(CONSOLE_RED, "Error NAM_ReadTadInfo()\n"); kamiFontPrintfConsole(CONSOLE_RED, "file : %s\n",fsinfo->longname); result = FALSE; continue; } // ImportFileInfo と TitleSortSet に情報を転載 info[count].dirNameIndex = (u8)l; STD_TSNPrintf(info[count].fileName, FS_ENTRY_LONGNAME_MAX, fsinfo->longname); sortset[count].index = count; sortset[count].titleID = tadInfo.titleInfo.titleId; count++; } } } } } return result; } /*---------------------------------------------------------------------------* Name: ImportTadFromList Description: MakeList で得たリストの情報に従って TAD をインポートします。 Arguments: dir_list, info, sortset, import_max Returns: BOOL *---------------------------------------------------------------------------*/ static BOOL ImportTadFromList( char (*dir_list)[FULLPATH_LEN], ImportFileInfo *info, TitleSortSet *sortset, u32 import_max ) { int l; int j; BOOL result = TRUE; s32 listNo=0; for( l=0; lattributes & (FS_ATTRIBUTE_DOS_DIRECTORY | FS_ATTRIBUTE_IS_DIRECTORY)) == 0) { char* pExtension; // 拡張子のチェック pExtension = STD_SearchCharReverse( info->longname, '.'); if (pExtension) { if (!STD_CompareString( pExtension, ".tad") || !STD_CompareString( pExtension, ".TAD") ) { STD_TSPrintf(string1, "List %d ", ++listNo); STD_ConvertStringSjisToUnicode(string2, NULL, string1, NULL, NULL); NNS_G2dCharCanvasClearArea(&gCanvas, TXT_COLOR_WHITE, 0, 60, 256, 20); NNS_G2dTextCanvasDrawText(&gTextCanvas, 40, 60, TXT_COLOR_WHITE_BASE, TXT_DRAWTEXT_FLAG_DEFAULT, (const char*)L"Now Import.."); NNS_G2dTextCanvasDrawText(&gTextCanvas, 135, 60, TXT_COLOR_WHITE_BASE, TXT_DRAWTEXT_FLAG_DEFAULT, (const char*)string2); STD_TSNPrintf(full_path, sizeof(full_path), "%s/%s", directory, info->longname); // kamiFontPrintfConsole(CONSOLE_GREEN, " %s\n", full_path); // MAX_RETRY_COUNTまでリトライする for (j=0; jpriority - 1); OS_WakeupThreadDirect(&thread); // Import開始 nam_result = NAM_ImportTad( path ); // インポート開始フラグを下げる sNowImport = FALSE; // 進捗スレッドの自力終了を待つ while (sProgress){}; // きちんと表示する G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W); OS_WaitVBlankIntr(); // InstalledSoftBoxCount, FreeSoftBoxCount の値を現在のNANDの状態に合わせて更新します。 (void)NAMUT_UpdateSoftBoxCount(); return nam_result; } /*---------------------------------------------------------------------------* Name: ProgressThread Description: .tad ファイルインポートの進捗を表示するスレッド。 進捗が100%に達すると処理を抜ける。 Arguments: arg - 使用しない。 Returns: None. *---------------------------------------------------------------------------*/ static void ProgressThread(void* /*arg*/) { u32 currentSize; u32 totalSize = 0; u32 totalSizeBk = 0; sProgress = TRUE; while (sNowImport) { NAM_GetProgress(¤tSize, &totalSize); if ((totalSize > 0 && totalSize == currentSize) || totalSizeBk > totalSize) { // 既にインポートが終了 ProgressDraw((f32)1.0); break; } else if (totalSize > 0) { ProgressDraw((f32)currentSize/totalSize); } totalSizeBk = totalSize; // Vブランク待ち G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W); OS_WaitVBlankIntr(); // 3D初期化 G3X_Reset(); G3_Identity(); G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_DECAL, GX_CULL_NONE, 0, 31, 0); } sProgress = FALSE; } /*---------------------------------------------------------------------------* Name: ProgressDraw Description: インポートの進捗を表示します Arguments: Returns: None. *---------------------------------------------------------------------------*/ void ProgressDraw(f32 ratio) { s16 x = (s16)(30 + (226 - 30)*ratio); // グリーンバー DrawQuadWithColors( 30, 86, x, 95, GX_RGB(22, 31, 22), GX_RGB(12, 25, 12)); // グレーバー DrawQuad( 30, 86, 226, 95, GX_RGB(28, 28, 28)); }