TwlIPL/build/libraries_sysmenu/util/ARM9/src/util_menuAppManager.c
(no author) 9570f1532d アプリリスト取得時にエラーが発生するとアプリを消していた問題の修正を修正
エラーが発生したらフェータルに落としていた処理を、
エラーが起きたアプリがシステムアプリだったらフェータルに落とし、ユーザアプリだったらアプリを削除する。


git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@3006 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2011-04-04 00:35:50 +00:00

1442 lines
44 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.

/*---------------------------------------------------------------------------*
Project: TwlIPL
File: util_menuAppManager.c
Copyright 2007 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$
*---------------------------------------------------------------------------*/
#ifndef TWL_IPL_MENU_APP_MANAGER_FOR_STG
#include <sysmenu/util_menuAppManager.h>
#endif
#include <stddef.h>
#define MEASURE_BANNER_LOAD_TIME 0
void *(*AMNi_Alloc)( u32 size ) = NULL;
void (*AMNi_Free )( void *ptr ) = NULL;
/////////////////////////////////////////////////////////////////////////////////
// private:
static BOOL AMN_isTitleIdValidForLauncher(NAMTitleId id);
static void AMN_initFlags_();
static void AMN_initCardTitleList_();
static void AMN_initNandTitleList_();
static void AMN_lockSubBannerFileBuffer();
static void AMN_unlockSubBannerFileBuffer();
static u32 AMN_getBannerAnimeCRC(const BannerAnime* pAnime);
static BOOL AMN_checkAndReplaceBannerAnime(s32 index);
static void AMNi_updateFreeBoxCount( u8 count );
static vu8 sThreadStarted;
static vu8 sReadCancelFlag; // Æè ¦¸³Ž<C5BD>B
static vu8 sNandTitleListReady;
static vu8 sCardTitleListLength;
static s32 sNandAllTitleListLength; // error if <= 0
static s32 sNandTitleListLengthForLauncher;
static s32 sNandAppRomHeaderArrayLength;
static TitleProperty sAllTitlePropertyArray[cAllTitleArrayMax];
enum {
cEventMask_SubBannerFileBuffer = 0x1
};
static OSEvent sSubBannerFileBufferEvent;
enum {
cThreadPriority_Read = OS_THREAD_LAUNCHER_PRIORITY + 1,
cThreadPriority_Check = OS_THREAD_LAUNCHER_PRIORITY + 2
};
static OSThread sReadThread;
static OSThread sCheckThread;
static u64 sReadThreadStack[1024];
static u64 sCheckThreadStack[2048]; // 16KBytes FSÆNAMðŽg¤ÌÅ<E2809A>­µ½ßÉŽæé
static OSMessage sCheckMsgBuf[1];
static OSMessageQueue sCheckMsgQueue;
static void AMN_procRead();
static void AMN_procReadNandTitleOnly();
static void AMN_procReadNandTitleHeaderOnly();
static void AMN_procCheck();
static char sBootContentPath[FS_ENTRY_LONGNAME_MAX];
static TWLBannerFile* spNandBannerFileArray;
static TWLBannerFile* spEmptyBannerFileBuffer;
// ƒoƒi<C692>[ƒoƒbƒtƒ@<40>AƒTƒuƒoƒi<C692>[ƒoƒbƒtƒ@Í0x20 Bytes alignedɵ½¢<E2809A>B
// ƒ<>ƒƒŠªŒµµ¢ÌŃTƒuƒoƒi<C692>[ƒoƒbƒtƒ@Í1ŒÂÅŽg¢‰ñ·<E2809A>B
static TWLSubBannerFile* spSubBannerFileBuffer;
static AMNBannerCounter sBannerCounterArray[cAllTitleArrayMax];
static AMNFrameAnimeData sFrameAnimeDataArray[cAllTitleArrayMax];
static AMNFrameAnimeData sEmptyAnimeData;
static ROM_Header_Short sRomHeaderBuffer;
static ROM_Header_Short s_AllRomHeaderArray[OS_TITLEIDLIST_MAX];
// see also TwlIPL_RED/build/systemmenu_RED/Launcher/ARM9/src/bannerCounter.h
inline void AMN_BNC_resetCount( AMNBannerCounter *c )
{
c->count = 0;
c->control = 0;
}
inline void AMN_BNC_setBanner( AMNBannerCounter *c, const TWLBannerFile *b)
{
c->banner = b;
}
inline void AMN_BNC_initCounter( AMNBannerCounter *c, const TWLBannerFile *b)
{
AMN_BNC_setBanner( c, b );
AMN_BNC_resetCount( c );
}
inline const TWLBannerFile* AMN_BNC_getBanner( AMNBannerCounter *c )
{
return c->banner;
}
static void AMN_BNC_incrementCount( AMNBannerCounter *c );
static AMNFrameAnimeData AMN_BNC_getFAD( AMNBannerCounter *c );
static AMNFrameAnimeData AMN_BNC_getFADAndIncCount( AMNBannerCounter *c );
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL AMN_isNandTitleListReady() { return sNandTitleListReady; }
s32 AMN_getNandTitleListLengthForLauncher() { return sNandTitleListLengthForLauncher; }
s32 AMN_getCardTitleListLength() { return sCardTitleListLength; }
s32 AMN_getRomHeaderListLength() { return sNandAppRomHeaderArrayLength + cNandTitleIndexStart;}
////////////////////////////////////////////////////////////////////////////////////////////////////
/*!
ƒRƒ“ƒXƒgƒ‰ƒNƒ^<5E>iC++Žžã̈╨<E280A2>j
AMN_Init()‚©‚çŒÄ‚΂ê‚邾‚¯
*/
static void AMN_Manager( )
{
sThreadStarted = FALSE;
spNandBannerFileArray = NULL;
spEmptyBannerFileBuffer = NULL;
spSubBannerFileBuffer = NULL;
// CARDƒAƒvƒŠÍ1ŒÂÜÅ<E2809A>B
SDK_ASSERT( cCardTitleArrayMax == 1 );
// NANDƒAƒvƒŠÍ39ŒÂÜÅ•\ަūé<E2809A>B
SDK_ASSERT( cNandTitleArrayMax == 39 );
#ifndef TWL_IPL_FINAL
// Œ¾ŒêenumÌŠÄŽ<C5BD>B
SDK_ASSERT( BANNER_PRIO_JAPANESE == OS_LANGUAGE_JAPANESE );
SDK_ASSERT( BANNER_PRIO_ENGLISH == OS_LANGUAGE_ENGLISH );
SDK_ASSERT( BANNER_PRIO_FRENCH == OS_LANGUAGE_FRENCH );
SDK_ASSERT( BANNER_PRIO_GERMAN == OS_LANGUAGE_GERMAN );
SDK_ASSERT( BANNER_PRIO_ITALIAN == OS_LANGUAGE_ITALIAN );
SDK_ASSERT( BANNER_PRIO_SPANISH == OS_LANGUAGE_SPANISH );
SDK_ASSERT( BANNER_PRIO_CHINESE == OS_LANGUAGE_CHINESE );
SDK_ASSERT( BANNER_PRIO_KOREAN == OS_LANGUAGE_HANGUL );
#endif
AMN_initFlags_();
}
/*!
N“®<E2809C>B
*/
void AMN_init( void *(*pAlloc)(u32), void (*pFree)(void*) )
{
// Œ³ƒRƒ“ƒXƒgƒ‰ƒNƒ^
AMN_Manager();
// ±ÌŽž“_ÅAMNi_AllocÆAMNi_FreeªNULLÅ é×µ
SDK_ASSERT( AMNi_Alloc == NULL && AMNi_Free == NULL );
AMNi_Alloc = pAlloc;
AMNi_Free = pFree;
spNandBannerFileArray = (TWLBannerFile*)AMNi_Alloc( sizeof(TWLBannerFile) * cNandTitleArrayMax );
SDK_ASSERT( spNandBannerFileArray );
spEmptyBannerFileBuffer = (TWLBannerFile*)AMNi_Alloc( sizeof(TWLBannerFile) );
SDK_ASSERT( spEmptyBannerFileBuffer );
spSubBannerFileBuffer = (TWLSubBannerFile*)AMNi_Alloc( sizeof(TWLSubBannerFile) );
SDK_ASSERT( spSubBannerFileBuffer );
MI_CpuClearFast(spEmptyBannerFileBuffer, sizeof(TWLBannerFile));
sEmptyAnimeData.image = spEmptyBannerFileBuffer->v1.image;
sEmptyAnimeData.pltt = spEmptyBannerFileBuffer->v1.pltt;
sEmptyAnimeData.hflip = FALSE;
sEmptyAnimeData.vflip = FALSE;
MI_CpuClearFast(sAllTitlePropertyArray, sizeof(sAllTitlePropertyArray));
#ifndef TWL_IPL_FINAL
// test
#if 0
if (0) {
BOOL ret;
ret = NAM_CheckTitleLaunchRights(
0x00030004534d504c // "SMPL" - nandAppSample
// 0x00030015344e4141 // "4NAA" - UIG launcher default
);
IPL_PRINT("NAM_CheckTitleLaunchRights()=%d\n", ret);
SDK_ASSERT( FALSE );
}
if (0) {
FSFile file[1];
BOOL ret;
FS_InitFile(file);
ret = FS_OpenFileEx(file, "sdmc:/dummy.bkp", FS_FILEMODE_R);
IPL_PRINT("FS_OpenFileEx()=%d\n", ret);
FS_CloseFile(file);
SDK_ASSERT( FALSE );
}
// test
if (0) {
s32 ret = NAM_ImportBkpSave("sdmc:/dummy.bkp");
IPL_PRINT("NAM_ImportBkpSave()=%d\n", ret);
SDK_ASSERT( FALSE );
}
if (0) {
// Èñ©<E2809A>A[ES] generate cert failed -2012
// ÉÈé<E2809A>B
s32 ret = NAM_ExportBkp(
// 0x0003001534303241, // "402A" - UIG launcher clone
// 0x00030015344e4141, // "4NAA" - UIG launcher default
0x00030004534d504c, // "SMPL" - nandAppSample
"sdmc:/test.bkp");
IPL_PRINT("NAM_ExportBkp()=%d\n", ret);
}
if (0) {
NAMBkpInfo info;
static TWLBannerFile banner;
info.fileSize = 0;
info.hardwareId = 0;
s32 ret = NAM_ReadBkpInfo(&info, &banner, sizeof(banner),
"sdmc:/test.bkp");
IPL_PRINT("NAM_ReadBkpInfo()=%d, fileSize=%d, HWID=%016llx\n",
ret, info.fileSize, (u64)info.hardwareId);
SDK_ASSERT( FALSE );
}
#endif
#endif
//AMN_restart(); // Ž©“®ƒ<C2AE><C692>[ƒhµÄµÜ¤ÌÍ<E2809A>ˆ<C5A0>ü}”²ƒ‰ƒCƒuƒ‰ƒŠÅCARD¾¯“Çݽ¢<E2809A>ê<EFBFBD>âNAND“ÇÝ<E2809A>žÝƒ^ƒCƒ~ƒ“ƒOðxç¹½¢<E2809A>ê<EFBFBD>É•s“s<E2809C>
}
/*!
<20>ÄN“®<E2809C>B
*/
void AMN_restart()
{
// AMNi_Alloc¨æÑAMNi_Free̓Zƒbƒg³êÄ¢é×µ
SDK_ASSERT( AMNi_Alloc != NULL && AMNi_Free != NULL );
AMN_initFlags_();
SDK_ASSERT( !sThreadStarted || OS_IsThreadTerminated(&sReadThread) );
sThreadStarted = TRUE;
OS_InitEvent(&sSubBannerFileBufferEvent);
AMN_unlockSubBannerFileBuffer();
OS_InitMessageQueue(&sCheckMsgQueue, sCheckMsgBuf, sizeof(sCheckMsgBuf) / sizeof(*sCheckMsgBuf));
OS_CreateThread(&sReadThread, AMN_procRead, NULL,
sReadThreadStack + (sizeof(sReadThreadStack) / sizeof(*sReadThreadStack)),
sizeof(sReadThreadStack),
cThreadPriority_Read);
OS_CreateThread(&sCheckThread, AMN_procCheck, NULL,
sCheckThreadStack + (sizeof(sCheckThreadStack) / sizeof(*sCheckThreadStack)),
sizeof(sCheckThreadStack),
cThreadPriority_Check);
// for safety, wakeup sCheckThread first
OS_WakeupThreadDirect(&sCheckThread);
OS_WakeupThreadDirect(&sReadThread);
}
/*!
NANDƒ^ƒCƒgƒ¾¯Žæ“¾µÈªçÌ<E2809A>ÄN“®<E2809C>B
*/
void AMN_restartWithReadNandTitle()
{
// AMNi_Alloc¨æÑAMNi_Free̓Zƒbƒg³êÄ¢é×µ
SDK_ASSERT( AMNi_Alloc != NULL && AMNi_Free != NULL );
AMN_initFlags_();
SDK_ASSERT( !sThreadStarted || OS_IsThreadTerminated(&sReadThread) );
sThreadStarted = TRUE;
OS_InitEvent(&sSubBannerFileBufferEvent);
AMN_unlockSubBannerFileBuffer();
OS_InitMessageQueue(&sCheckMsgQueue, sCheckMsgBuf, sizeof(sCheckMsgBuf) / sizeof(*sCheckMsgBuf));
OS_CreateThread(&sReadThread, AMN_procReadNandTitleOnly, NULL,
sReadThreadStack + (sizeof(sReadThreadStack) / sizeof(*sReadThreadStack)),
sizeof(sReadThreadStack),
cThreadPriority_Read);
OS_CreateThread(&sCheckThread, AMN_procCheck, NULL,
sCheckThreadStack + (sizeof(sCheckThreadStack) / sizeof(*sCheckThreadStack)),
sizeof(sCheckThreadStack),
cThreadPriority_Check);
// for safety, wakeup sCheckThread first
OS_WakeupThreadDirect(&sCheckThread);
OS_WakeupThreadDirect(&sReadThread);
}
/*!
NANDƒ^ƒCƒgƒÌROM_HEADER_SHORT¾¯Žæ“¾µÈªçÌ<E2809A>ÄN“®<E2809C>B
*/
void AMN_restartWithReadNandTitleHeaderShort()
{
// AMNi_Alloc¨æÑAMNi_Free̓Zƒbƒg³êÄ¢é×µ
SDK_ASSERT( AMNi_Alloc != NULL && AMNi_Free != NULL );
AMN_initFlags_();
SDK_ASSERT( !sThreadStarted || OS_IsThreadTerminated(&sReadThread) );
sThreadStarted = TRUE;
OS_CreateThread(&sReadThread, AMN_procReadNandTitleHeaderOnly, NULL,
sReadThreadStack + (sizeof(sReadThreadStack) / sizeof(*sReadThreadStack)),
sizeof(sReadThreadStack),
cThreadPriority_Read);
OS_WakeupThreadDirect(&sReadThread);
}
/*!
<20>I—¹<E28094>B
*/
void AMN_destroy()
{
sReadCancelFlag = TRUE;
while ( sThreadStarted && !OS_IsThreadTerminated(&sReadThread) ) {
OS_Sleep(1);
}
if( AMNi_Free != NULL && spSubBannerFileBuffer)
{
AMNi_Free( spSubBannerFileBuffer );
}
if( AMNi_Free != NULL && spEmptyBannerFileBuffer)
{
AMNi_Free( spEmptyBannerFileBuffer );
}
if( AMNi_Free != NULL && spNandBannerFileArray)
{
AMNi_Free( spNandBannerFileArray );
}
}
static void AMN_initFlags_()
{
sReadCancelFlag = FALSE;
sNandTitleListReady = FALSE;
sNandAllTitleListLength = 0;
sNandTitleListLengthForLauncher = 0;
sCardTitleListLength = 0;
sNandAppRomHeaderArrayLength = 0;
}
static void AMN_initCardTitleList_()
{
}
// Žwè³ê½titleID̃^ƒCƒgƒƒcƒŠ<C692>[ð<E2809A>ÁŽ
#define TITLE_TREE_PATH_LENGTH 12+8+1+8+1
static void AMNi_deleteTitleTree( NAMTitleId titleID )
{
char path[TITLE_TREE_PATH_LENGTH];// "nand:/title/" + "%08x" + "/" + "%08x" + "\0"
STD_TSNPrintf( path, TITLE_TREE_PATH_LENGTH, "nand:/title/%08x/%08x", (u32)( titleID >> 32 ), (u32)titleID );
(void)FS_DeleteDirectoryAuto( path );
OS_TPrintf( "AMNi_deleteTitleTree : delete %s\n", path );
}
static BOOL AMNi_getAndAddNandTitleData( NAMTitleId titleID, BOOL readShowData )
{
TitleProperty* pTitleProp;
// header<65>î•ñ̎擾
#if (MEASURE_BANNER_LOAD_TIME == 1)
OSTick start;
#endif
FSFile file[1];
BOOL bSuccess;
char path[FS_ENTRY_LONGNAME_MAX];
s32 readLen;
u32 offset;
BOOL isBannerExist = FALSE;
s32 rhArrayLen = cNandTitleIndexStart + sNandAppRomHeaderArrayLength;
// ‚à‚¤“ü‚ç‚È‚¢
if (rhArrayLen >= OS_TITLEIDLIST_MAX) {
return FALSE;
}
FS_InitFile(file);
#if (MEASURE_BANNER_LOAD_TIME == 1)
start = OS_GetTick();
#endif
if( (titleID & TITLE_ID_DATA_ONLY_FLAG_MASK) == 0 )
{
// DataOnlyÅÈ¢<E2809A>ê<EFBFBD>
readLen = NAM_GetTitleBootContentPathFast( path, titleID );
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "NAM_GetTitleBootContentPath : %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
#endif
// ƒtƒ@ƒCƒƒpƒXðŽæ“¾
if(readLen != NAM_OK){
// error
SDK_ASSERT( FALSE );
// ƒVƒXƒeƒ€ƒAƒvƒŠÌ<E2809A>ê<EFBFBD>̓tƒF<C692>[ƒ^ƒÉ—ŽÆµ<E2809A>Aƒ†<C692>[ƒU<C692>[ƒAƒvƒŠÌ<E2809A>ê<EFBFBD>Í<E2809A>í<EFBFBD>œ·é
if( titleID & TITLE_ID_APP_TYPE_MASK )
{
// ƒtƒF<C692>[ƒ^ƒƒGƒ‰<C692>[ð<E2809A>Ýè
UTL_SetFatalError( FATAL_ERROR_LOAD_OPENFILE_FAILED );
}
else
{
// ƒAƒvƒŠð<E2809A>í<EFBFBD>œ
AMNi_deleteTitleTree( titleID );
}
return FALSE;
}
#if (MEASURE_BANNER_LOAD_TIME == 1)
start = OS_GetTick();
#endif
// ƒtƒ@ƒCƒƒI<C692>[ƒvƒ“
bSuccess = FS_OpenFileEx(file, path, FS_FILEMODE_R);
if( ! bSuccess )
{
// error
SDK_ASSERT( FALSE );
// ƒVƒXƒeƒ€ƒAƒvƒŠÌ<E2809A>ê<EFBFBD>̓tƒF<C692>[ƒ^ƒÉ—ŽÆµ<E2809A>Aƒ†<C692>[ƒU<C692>[ƒAƒvƒŠÌ<E2809A>ê<EFBFBD>Í<E2809A>í<EFBFBD>œ·é
if( titleID & TITLE_ID_APP_TYPE_MASK )
{
// ƒtƒF<C692>[ƒ^ƒƒGƒ‰<C692>[ð<E2809A>Ýè
UTL_SetFatalError( FATAL_ERROR_LOAD_OPENFILE_FAILED );
}
else
{
// ƒAƒvƒŠð<E2809A>í<EFBFBD>œ
AMNi_deleteTitleTree( titleID );
}
return FALSE;
}
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "OpenFileEX : %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
start = OS_GetTick();
#endif
readLen = FS_ReadFile(file, &s_AllRomHeaderArray[rhArrayLen], sizeof(ROM_Header_Short));
if( readLen != sizeof(ROM_Header_Short) )
{
// error
SDK_ASSERT( FALSE );
FS_CloseFile(file);
// ƒVƒXƒeƒ€ƒAƒvƒŠÌ<E2809A>ê<EFBFBD>̓tƒF<C692>[ƒ^ƒÉ—ŽÆµ<E2809A>Aƒ†<C692>[ƒU<C692>[ƒAƒvƒŠÌ<E2809A>ê<EFBFBD>Í<E2809A>í<EFBFBD>œ·é
if( titleID & TITLE_ID_APP_TYPE_MASK )
{
// ƒtƒF<C692>[ƒ^ƒƒGƒ‰<C692>[ð<E2809A>Ýè
UTL_SetFatalError( FATAL_ERROR_LOAD_READHEADER_FAILED );
}
else
{
// ƒAƒvƒŠð<E2809A>í<EFBFBD>œ
AMNi_deleteTitleTree( titleID );
}
return FALSE;
}
offset = s_AllRomHeaderArray[rhArrayLen].banner_offset;
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "FS_ReadFile header : %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
#endif
}
else
{
// DataOnlyÌ<E2809A>ê<EFBFBD>
int l;
NAMTitleInfo naminfo;
// ±ÌŠÖ<C5A0>Å“¾çêé<E2809A>î•ñͳŒŸ<C592>ØÈÌʼnü´ñ̉”\<5C>«ª éª<E2809A><41><C692>[ƒJ<C692>[ƒR<C692>[ƒhÌÝÌ”»èÈÌÅ<E2809A>A¬“xð—D<E28094>æ·é<E2809A>B(2008.06.20g‰ª)
// <20>iFast¯Ȣƈê‰ñ300ms®ç¢©©é<E2809A>j
NAM_ReadTitleInfoFast( &naminfo, titleID );
MI_CpuClear8(&s_AllRomHeaderArray[rhArrayLen], sizeof(ROM_Header_Short) );
OS_TPrintf( "0x%0.16llx dataonly-title : makercode = ", titleID );
for(l=0;l<MAKER_CODE_MAX;l++)
{
s_AllRomHeaderArray[rhArrayLen].maker_code[l] = ((char *)&naminfo.companyCode)[l];
OS_TPrintf( "0x%0.2x ", s_AllRomHeaderArray[rhArrayLen].maker_code[l] );
}
OS_TPrintf( "\n" );
s_AllRomHeaderArray[rhArrayLen].titleID = titleID;
sNandAppRomHeaderArrayLength++;
return FALSE;
}
if(s_AllRomHeaderArray[rhArrayLen].platform_code & PLATFORM_CODE_FLAG_TWL){
// ROMƒwƒbƒ_̃Š<C692>[ƒWƒ‡ƒ“ƒ`ƒFƒbƒNÆCRCƒ`ƒFƒbƒNð<E2809A>s¢<E2809A>A•s<E280A2>³ÈƒAƒvƒŠÍ³Ž·é<E2809A>B
if( !UTL_CheckAppRegion( s_AllRomHeaderArray[rhArrayLen].card_region_bitmap ) ) {
OS_TPrintf( "Region Check NG : %llx\n", titleID );
FS_CloseFile(file);
return FALSE;
}
}
if( !UTL_CheckAppCRC16( &s_AllRomHeaderArray[rhArrayLen] ) ) {
OS_TPrintf( "CRC16 Check NG : %llx\n", titleID );
FS_CloseFile(file);
return FALSE;
}
sNandAppRomHeaderArrayLength++;
// ‚à‚¤ƒ‰ƒ“ƒ`ƒƒ<C692>[•\ަ—p<E28094>î•ñÍ<E2809A>ªƒI<C692>[ƒo<C692>[µÄé©<E2809A>A•\ަ—p<E28094>î•ñð“ÇÜÈ¢<E2809A>Ýè
if ( ( sNandTitleListLengthForLauncher >= cNandTitleArrayMax ) || !readShowData ) {
FS_CloseFile(file);
return FALSE;
}
// ˆÈ‰º‚Í•\ަ·éƒAƒvƒŠÌÝ<E2809A>iŒ»<C592>ÝƒŠƒXƒgÉ éƒf<C692>[ƒ^<5E>ªNandƒ^ƒCƒgƒ<C692>Ì<E2809A>Ååð´¦Ä¢È¢<E2809A>ê<EFBFBD><EFBFBD>jÌ<E2809A>ˆ<CB86>
// ƒ^ƒCƒgƒƒŠƒXƒgÖÌljÁ
pTitleProp = &sAllTitlePropertyArray[cNandTitleIndexStart + sNandTitleListLengthForLauncher];
pTitleProp->titleID = titleID;
pTitleProp->pBanner = &spNandBannerFileArray[sNandTitleListLengthForLauncher];
pTitleProp->flags.isValid = TRUE;
pTitleProp->flags.bootType = LAUNCHER_BOOTTYPE_NAND;
// ƒoƒi<C692>[‚̎擾
// ƒoƒi<C692>[ª<E28098>Ý·é<E2809A>ê<EFBFBD>Ì݃Š<C692>[ƒh
if( offset ) {
#if (MEASURE_BANNER_LOAD_TIME == 1)
start = OS_GetTick();
#endif
bSuccess = FS_SeekFile(file, (s32)offset, FS_SEEK_SET);
if( bSuccess )
{
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "FS_SeekFile banner: %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
start = OS_GetTick();
#endif
readLen = FS_ReadFile( file, pTitleProp->pBanner, (s32)sizeof(TWLBannerFile) );
if( readLen == (s32)sizeof(TWLBannerFile) )
{
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "FS_ReadFile banner: %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
start = OS_GetTick();
#endif
// ƒoƒi<C692>[ƒ`ƒFƒbƒNƒŠƒNƒGƒXƒg<E28098>M<EFBFBD>B
OS_SendMessage(&sCheckMsgQueue, (OSMessage)(pTitleProp->pBanner), OS_MESSAGE_BLOCK);
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "check banner: %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
#endif
isBannerExist = TRUE;
}
}
}
if( !isBannerExist )
{
// ƒoƒi<C692>[ª<E28098>ݵȢ<E2809A>ê<EFBFBD>̓oƒbƒtƒ@ƒNƒŠƒA
MI_CpuClearFast( pTitleProp->pBanner, sizeof(TWLBannerFile) );
}
#if (MEASURE_BANNER_LOAD_TIME == 1)
start = OS_GetTick();
#endif
FS_CloseFile(file);
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "close file : %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
start = OS_GetTick();
#endif
// ƒTƒuƒoƒi<C692>[ƒtƒ@ƒCƒð“ÇÝ<E2809A>žñÅÝé
if(s_AllRomHeaderArray[rhArrayLen].exFlags.availableSubBannerFile &&
NAM_OK == NAM_GetTitleBannerFilePath( path, titleID ))
{
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "NAM_GetTitleBannerFilePath : %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
start = OS_GetTick();
#endif
if (FS_OpenFileEx(file, path, FS_FILEMODE_R)) {
// ƒTƒuƒoƒi<C692>[ƒoƒbƒtƒ@Šm•Û<E280A2>B
AMN_lockSubBannerFileBuffer();
readLen = FS_ReadFile(file, spSubBannerFileBuffer, sizeof(*spSubBannerFileBuffer));
FS_CloseFile(file);
if (readLen == sizeof(TWLSubBannerFile)) {
// “ÇÝ<E2809A>žÝÉÍ<E2809A>¬Œ÷µ½ÌÅ<E2809A>³“<E2809C>«ƒ`ƒFƒbƒN
// ƒTƒuƒoƒi<C692>[ƒ`ƒFƒbƒNƒŠƒNƒGƒXƒg<E28098>M<EFBFBD>B
OS_SendMessage(&sCheckMsgQueue, (OSMessage)(cNandTitleIndexStart + sNandTitleListLengthForLauncher), OS_MESSAGE_BLOCK);
// ‰ð•úÍCHECKƒXƒŒƒbƒh¤Å<E2809A>s¤<E2809A>B
} else {
OS_TPrintf("subbanner read failed (%d)\n", readLen);
// ‰ð•ú<E280A2>B
AMN_unlockSubBannerFileBuffer();
}
}
#if (MEASURE_BANNER_LOAD_TIME == 1)
OS_TPrintf( "open-read-close-check subbanner : %dus\n", OS_TicksToMicroSeconds( OS_GetTick() - start ) );
#endif
}
sNandTitleListLengthForLauncher++;
return TRUE;
}
/*!
see also SYSM_InitNandTitleList() and SYSM_GetNandTitleList()
ƒCƒ“ƒ|<7C>[ƒg³êÄ¢é·×ÄÌNANDƒAƒvƒŠð—ñµ½ƒŠƒXƒgÌ<E2809A>€”õ
*/
static void AMN_initNandTitleList_()
{
s32 ret;
s32 l;
NAMTitleId* pNandAllTitleIDList = NULL;
u8 count_valid_app_for_launcher = 0;
int finger = 0;
// ƒCƒ“ƒ|<7C>[ƒg³êÄ¢éƒ^ƒCƒgƒÌŽæ“¾
sNandAllTitleListLength = NAM_GetNumTitles();
OS_TPrintf("NAM_GetNumTitles()=%d\n", sNandAllTitleListLength);
// <20>­È­Æàƒ‰ƒ“ƒ`ƒƒ<C692>[Ƴ<E28093>üƒtƒ@<40>[ƒ€ªƒŠƒXƒgƒAƒbƒv³êé͸<E2809A>B
// ¾ª<E2809A>Aˆê‰ž0ÍÊ·<E2809A>B
SDK_ASSERT( sNandAllTitleListLength >= 0 );
if (sNandAllTitleListLength > 0) {
pNandAllTitleIDList = (NAMTitleId*)AMNi_Alloc( sizeof(NAMTitleId) * sNandAllTitleListLength );
SDK_ASSERT( pNandAllTitleIDList );
if (!pNandAllTitleIDList) {
// error
sNandAllTitleListLength = 0;
} else {
ret = NAM_GetTitleList(pNandAllTitleIDList, (u32)sNandAllTitleListLength);
OS_TPrintf("NAM_GetTitleList()=%d\n", ret);
SDK_ASSERT( ret == NAM_OK );
if (ret != NAM_OK) {
// error
sNandAllTitleListLength = 0;
}
}
}
// ܸ<E2809A>Aƒ^ƒCƒgƒð<E2809A>d—vÈ<E2809A>ÉIðƒ\<5C>[ƒg·é<E2809A>B
// HNB*ð<E2809A>擪É<E2809A>AƒVƒXƒeƒ€ƒAƒvƒŠ<C692>Aƒ†<C692>[ƒUƒAƒvƒŠÌ<E2809A><EFBFBD>˜
// ”ñ•\ަƒ^ƒCƒgƒàˆÚ“®µÄµÜÁÄ¢éª<E2809A>A ÜèŠÖŒWÈ¢
for( l = 0; l < sNandAllTitleListLength; l++ )
{
// HNB*
char *code = ((char *)&pNandAllTitleIDList[l]) + 1;
if( 0 == STD_CompareNString( code, "BNH", 3 ) )
{
if( l != finger)
{
NAMTitleId temp = pNandAllTitleIDList[finger];
pNandAllTitleIDList[finger] = pNandAllTitleIDList[l];
pNandAllTitleIDList[l] = temp;
}
finger++;
}
}
for( l = finger; l < sNandAllTitleListLength; l++ )
{
// ƒVƒXƒeƒ€ƒAƒvƒŠ
if( pNandAllTitleIDList[l] & TITLE_ID_APP_TYPE_MASK )
{
if( l != finger)
{
NAMTitleId temp = pNandAllTitleIDList[finger];
pNandAllTitleIDList[finger] = pNandAllTitleIDList[l];
pNandAllTitleIDList[l] = temp;
}
finger++;
}
}
// ƒ<>ƒƒŠÌŠm•ÛÆ‰ð•ú𓯶ŠÖ<C5A0>”“àÅ<E2809A>s¢½¢ÌÅ<E2809A>A
// Žæ“¾‚µ‚½ƒ^ƒCƒgƒªƒ<C2AA><C692>[ƒ“ƒ`Î<E28098>۩Ǥ©ðƒ`ƒFƒbƒN
// ð<E2809A>A±±Å<E2809A>s¤<E2809A>B
// ‚·‚ׂẴ^ƒCƒgƒÌƒwƒbƒ_ð“ÇÝ<E2809A>žÞÌÅ<E2809A>A<EFBFBD>i<EFBFBD>žÝÌ•K—vÍÈ¢
for (l = 0; l < sNandAllTitleListLength; l++) {
if (AMN_isTitleIdValidForLauncher(pNandAllTitleIDList[l])) {
// {Ì<E28098>ÝèÌ<E2809A>ê<EFBFBD><EFBFBD>AƒAƒvƒŠƒ}ƒl<C692>[ƒWƒƒ—pindexÍ”òÑ”òÑÉÈÁ½è<E2809A>AForSetting()ª•Ô·l(ŒÂ<C592>”)‚æ‚è‘å‚«‚­‚È‚é‚Ì‚Å
// getNandTitleListLengthForSetting()Í—pˆÓµÈ¢<E2809A>B
if( AMNi_getAndAddNandTitleData( pNandAllTitleIDList[l], TRUE ) )
{
// FreeboxCount<6E>X<EFBFBD>V̽ß̃JƒEƒ“ƒ^
count_valid_app_for_launcher++;
}
}
}
// FreeboxCount<6E>X<EFBFBD>V
AMNi_updateFreeBoxCount( count_valid_app_for_launcher );
// ƒ<><C692>[ƒ“ƒ`Î<E28098>ÛÅÈ¢ƒ^ƒCƒgƒÌ<E2809A>î•ñ̎擾
for (l = 0; l < sNandAllTitleListLength; l++) {
if (!AMN_isTitleIdValidForLauncher(pNandAllTitleIDList[l])) {
(void)AMNi_getAndAddNandTitleData( pNandAllTitleIDList[l], FALSE );
}
}
if (pNandAllTitleIDList) {
AMNi_Free( pNandAllTitleIDList );
}
}
// ƒCƒ“ƒ|<7C>[ƒg³êÄ¢é·×Ä̃^ƒCƒgƒÌROM_HEADER_SHORTÌÝ“ÇÝ<E2809A>o·
static void AMN_initNandTitleRomHeaderShortList_()
{
s32 ret;
s32 l;
NAMTitleId* pNandAllTitleIDList = NULL;
// ƒCƒ“ƒ|<7C>[ƒg³êÄ¢éƒ^ƒCƒgƒÌŽæ“¾
sNandAllTitleListLength = NAM_GetNumTitles();
OS_TPrintf("NAM_GetNumTitles()=%d\n", sNandAllTitleListLength);
// <20>­È­Æàƒ‰ƒ“ƒ`ƒƒ<C692>[Ƴ<E28093>üƒtƒ@<40>[ƒ€ªƒŠƒXƒgƒAƒbƒv³êé͸<E2809A>B
// ¾ª<E2809A>Aˆê‰ž0ÍÊ·<E2809A>B
SDK_ASSERT( sNandAllTitleListLength >= 0 );
if (sNandAllTitleListLength > 0) {
pNandAllTitleIDList = (NAMTitleId*)AMNi_Alloc( sizeof(NAMTitleId) * sNandAllTitleListLength );
SDK_ASSERT( pNandAllTitleIDList );
if (!pNandAllTitleIDList) {
// error
sNandAllTitleListLength = 0;
} else {
ret = NAM_GetTitleList(pNandAllTitleIDList, (u32)sNandAllTitleListLength);
OS_TPrintf("NAM_GetTitleList()=%d\n", ret);
SDK_ASSERT( ret == NAM_OK );
if (ret != NAM_OK) {
// error
sNandAllTitleListLength = 0;
}
}
}
// ƒ^ƒCƒgƒÌ<E2809A>î•ñ(ƒwƒbƒ_ÌÝ)‚̎擾
for (l = 0; l < sNandAllTitleListLength; l++) {
(void)AMNi_getAndAddNandTitleData( pNandAllTitleIDList[l], FALSE );
}
// ƒoƒi<C692>[•\ަµÈ¢<E2809A>ê<EFBFBD><EFBFBD>AFreeboxCount<6E>X<EFBFBD>VÍ•K—vÈ¢
// <20>i•|‚¢‚͕̂\Ž¦ÆƒJƒEƒ“ƒgª<E2809A>H¢ˆá¤ŽÈÌÅ<E2809A>j
if (pNandAllTitleIDList) {
AMNi_Free( pNandAllTitleIDList );
}
}
// <20>¶ƒf<C692>[ƒ^<5E>iTitlePropertyÌƒŠƒXƒg<C692>AHeaderShortƒŠƒXƒg<C692>jɃAƒNƒZƒXū锲¯“¹ŠÖ<C5A0>
TitleProperty* AMN_getTitlePropertyList( void )
{
return sAllTitlePropertyArray;
}
ROM_Header_Short* AMN_getRomHeaderList( void )
{
return s_AllRomHeaderArray;
}
static void AMN_procRead()
{
MI_CpuClearFast(sAllTitlePropertyArray, sizeof(sAllTitlePropertyArray));
AMN_initCardTitleList_();
AMN_initNandTitleList_();
OS_SendMessage(&sCheckMsgQueue, NULL, OS_MESSAGE_BLOCK);
OS_JoinThread(&sCheckThread);
AMN_stepBannerAnimeAll( TRUE );
// for GX DMA
DC_StoreAll();
if (!sReadCancelFlag) {
sNandTitleListReady = TRUE;
}
}
// Nandƒ^ƒCƒgƒ¾¯Žæ“¾<E2809C>ACard•”•ªÍno care
static void AMN_procReadNandTitleOnly()
{
MI_CpuClearFast(&sAllTitlePropertyArray[cNandTitleIndexStart], sizeof(TitleProperty) * ( cAllTitleArrayMax - cNandTitleIndexStart ) );
AMN_initNandTitleList_();
OS_SendMessage(&sCheckMsgQueue, NULL, OS_MESSAGE_BLOCK);
OS_JoinThread(&sCheckThread);
AMN_stepBannerAnimeAll( TRUE );
// for GX DMA
DC_StoreAll();
if (!sReadCancelFlag) {
sNandTitleListReady = TRUE;
}
}
// Nandƒ^ƒCƒgƒÌROM_Header_Short¾¯Žæ“¾<E2809C>ACard•”•ªÍno care
static void AMN_procReadNandTitleHeaderOnly()
{
AMN_initNandTitleRomHeaderShortList_();
// for GX DMA
DC_StoreAll();
if (!sReadCancelFlag) {
sNandTitleListReady = TRUE;
}
}
static void AMN_procCheck()
{
OSMessage msg;
s32 index;
TWLBannerFile* pBanner;
while (TRUE) {
OS_ReceiveMessage(&sCheckMsgQueue, &msg, OS_MESSAGE_BLOCK);
// IPL_PRINT("procCheck: msg=0x%x\n", msg);
if (!msg) {
break;
}
index = (s32)msg;
// 0̓XƒŒƒbƒh<C692>I—¹ðˆÓ¡·éÌÅindexƵÄÍ•s“K<E2809C>Ø<EFBFBD>B
// ܽ<E2809A>ACARDÈÌŃTƒuƒoƒi<C692>[Í è¦È¢<E2809A>B
SDK_ASSERT( cNandTitleIndexStart > 0 );
if (cNandTitleIndexStart <= index && index < (cNandTitleIndexStart + cNandTitleArrayMax)) {
// ƒTƒuƒoƒi<C692>[
(void)AMN_checkAndReplaceBannerAnime(index);
AMN_unlockSubBannerFileBuffer();
} else {
pBanner = (TWLBannerFile*)msg;
if (!AMN_checkBannerFile(pBanner)) {
// <20>³“<E2809C>«ƒ`ƒFƒbƒNޏ”sÌ<E2809A>ê<EFBFBD>̓oƒbƒtƒ@ƒNƒŠƒA
MI_CpuClearFast(pBanner, sizeof(*pBanner));
OS_TPrintf("check NG! msg=0x%x propAry=0x%x\n", pBanner, sAllTitlePropertyArray);
}
}
}
}
static void AMN_lockSubBannerFileBuffer()
{
OS_WaitEventEx_And(&sSubBannerFileBufferEvent,
cEventMask_SubBannerFileBuffer,
cEventMask_SubBannerFileBuffer);
}
static void AMN_unlockSubBannerFileBuffer()
{
OS_SignalEvent(&sSubBannerFileBufferEvent,
cEventMask_SubBannerFileBuffer);
}
const TitleProperty* AMN_getTitleProperty(s32 index)
{
const TitleProperty* pTitleProp;
if (cAllTitleIndexStart <= index && index < cAllTitleArrayMax) {
pTitleProp = &sAllTitlePropertyArray[index];
if (pTitleProp->flags.isValid) {
return pTitleProp;
}
}
return NULL;
}
const ROM_Header_Short* AMN_getTitleRomHeaderShort(s32 index)
{
const ROM_Header_Short* pRhs;
if (cAllTitleIndexStart <= index && index < cAllTitleArrayMax) {
pRhs = &s_AllRomHeaderArray[index];
return pRhs;
}
return NULL;
}
BOOL AMN_isDSWirelessIcon(s32 index)
{
const ROM_Header_Short* pRhs = AMN_getTitleRomHeaderShort(index);
if (pRhs) {
return pRhs->exFlags.DSWirelessIcon;
}
return FALSE;
}
BOOL AMN_isWiFiConnectionIcon(s32 index)
{
const ROM_Header_Short* pRhs = AMN_getTitleRomHeaderShort(index);
if (pRhs) {
return pRhs->exFlags.WiFiConnectionIcon;
}
return FALSE;
}
BOOL AMN_isAgreeEULAFlag(s32 index)
{
const ROM_Header_Short* pRhs = AMN_getTitleRomHeaderShort(index);
if (pRhs) {
return pRhs->exFlags.agree_EULA;
}
return FALSE;
}
const u8* AMN_getParentalControlRatingInfo(s32 index)
{
const ROM_Header_Short* pRhs = AMN_getTitleRomHeaderShort(index);
if (pRhs) {
return pRhs->parental_control_rating_info;
}
return FALSE;
}
// ƒ^ƒCƒgƒIDª{Ì<E28098>Ýè—pƵÄͳŒøÅ ÁÄà<E2809A>A
// Ήž·éindexð•Եܷ<E2809A>B
s32 AMN_getIndexByTitleId(NAMTitleId titleId)
{
const TitleProperty* pTitleProp;
s32 index;
// ˆê‰ž<E280B0>ATitleID == 0 ̃AƒvƒŠª é©àµêÈ¢<E2809A>HÌÅ<E2809A>A
// NAND©ç—D<E28094>æ“IÉT·<E2809A>B
// CARDÍTITLE_ID_MEDIA_MASKª1ÉÈé͸<E2809A>B
// NAND
index = cNandTitleIndexStart + sNandTitleListLengthForLauncher - 1;
while (index >= cNandTitleIndexStart) {
pTitleProp = AMN_getTitleProperty(index);
if (pTitleProp &&
pTitleProp->titleID == titleId) {
return index;
}
index--;
}
// CARD
index = sCardTitleListLength - 1;
while (index >= cCardTitleIndexStart) {
pTitleProp = AMN_getTitleProperty(index);
if (pTitleProp &&
pTitleProp->titleID == titleId) {
return index;
}
index--;
}
return -1;
}
// indexª{Ì<E28098>Ýè—pƵÄͳŒøÅ ÁÄà<E2809A>A
// ‘Ήž‚·‚éƒ^ƒCƒgƒIDð•Եܷ<E2809A>B
NAMTitleId AMN_getTitleIdByIndex(s32 index)
{
const TitleProperty* pTitleProp = AMN_getTitleProperty(index);
if (pTitleProp) {
return pTitleProp->titleID;
}
return (NAMTitleId)0;
}
void AMN_stepBannerAnimeAll(BOOL restart)
{
s32 index;
for (index = cAllTitleIndexStart; index < cAllTitleArrayMax; index++) {
AMN_stepBannerAnime(index, restart);
}
}
void AMN_stepBannerAnime(s32 index, BOOL restart)
{
const TWLBannerFile* pBanner;
AMNBannerCounter* pBNC;
if (cAllTitleIndexStart <= index && index < cAllTitleArrayMax) {
pBNC = &sBannerCounterArray[index];
if (restart) {
pBanner = sAllTitlePropertyArray[index].pBanner;
if (!pBanner) {
pBanner = spEmptyBannerFileBuffer;
}
AMN_BNC_initCounter(pBNC, pBanner);
} else {
AMN_BNC_incrementCount(pBNC);
}
sFrameAnimeDataArray[index] = AMN_BNC_getFAD(pBNC);
}
}
const u8* AMN_getBannerImage(s32 index)
{
AMNFrameAnimeData ret = AMN_getBannerAnime(index);
return ret.image;
}
const u8* AMN_getBannerPltt(s32 index)
{
AMNFrameAnimeData ret = AMN_getBannerAnime(index);
return ret.pltt;
}
BOOL AMN_getBannerHFlip(s32 index)
{
AMNFrameAnimeData ret = AMN_getBannerAnime(index);
return ret.hflip;
}
BOOL AMN_getBannerVFlip(s32 index)
{
AMNFrameAnimeData ret = AMN_getBannerAnime(index);
return ret.vflip;
}
AMNFrameAnimeData AMN_getBannerAnime(s32 index)
{
if (cAllTitleIndexStart <= index && index < cAllTitleArrayMax) {
return sFrameAnimeDataArray[index];
}
return sEmptyAnimeData;
}
const u16* AMN_getBannerText2(s32 index, OSLanguage language)
{
const TitleProperty* pTitleProp = AMN_getTitleProperty(index);
if (language >= OS_LANGUAGE_CODE_MAX) {
language = OS_LANGUAGE_ENGLISH;
}
if (pTitleProp) {
if (language < BANNER_LANG_NUM_V1) {
return pTitleProp->pBanner->v1.gameName[language];
}
language = (OSLanguage)(language - BANNER_LANG_NUM_V1);
if (language < BANNER_LANG_NUM_V2) {
return pTitleProp->pBanner->v2.gameName[language];
}
language = (OSLanguage)(language - BANNER_LANG_NUM_V2);
return pTitleProp->pBanner->v3.gameName[language];
}
return spEmptyBannerFileBuffer->v1.gameName[language];
}
const u16* AMN_getBannerText(s32 index)
{
OSOwnerInfo info;
// Æè ¦¸<E2809A>B
// <20>³Ž®ÉÍ{Ì<E28098>ÝèÌLCFGƒ‰ƒbƒp<C692>[©çŽæçȢƃ_ƒ<5F><C692>H
OS_GetOwnerInfo(&info);
return AMN_getBannerText2(index, (OSLanguage)info.language);
}
// see also SYSMi_CheckBannerFile()
// ƒoƒi<C692>[ƒf<C692>[ƒ^Ì<E2809A>³Œëƒ`ƒFƒbƒN
BOOL AMN_checkBannerFile(TWLBannerFile* pBanner)
{
typedef struct BannerCheckParam {
u8 *pSrc;
u32 size;
}BannerCheckParam;
int i;
BOOL retval = TRUE;
u16 calc_crc = 0xffff;
u16 *pHeaderCRC = (u16 *)&pBanner->h.crc16_v1;
BannerCheckParam bannerCheckList[ BANNER_VER_NTR_MAX ];
BannerCheckParam *pChk = &bannerCheckList[ 0 ];
// NTRŒÝŠ·•”•ªÍ•W<E280A2>Ń`ƒFƒbƒN
bannerCheckList[ 0 ].pSrc = (u8 *)&( pBanner->v1 );
bannerCheckList[ 0 ].size = sizeof( BannerFileV1 );
bannerCheckList[ 1 ].pSrc = (u8 *)&( pBanner->v2 );
bannerCheckList[ 1 ].size = sizeof( BannerFileV2 );
bannerCheckList[ 2 ].pSrc = (u8 *)&( pBanner->v3 );
bannerCheckList[ 2 ].size = sizeof( BannerFileV3 );
for( i = 0; i < BANNER_VER_NTR_MAX; i++ ) {
if( i < pBanner->h.version ) {
calc_crc = SVC_GetCRC16( calc_crc, pChk->pSrc, pChk->size );
if( calc_crc != *pHeaderCRC++ ) {
retval = FALSE;
break;
}
}else {
MI_CpuClear16( pChk->pSrc, pChk->size );
}
pChk++;
}
// TWLƒoƒi<C692>[Èç<E2809A>Aƒoƒi<C692>[ƒAƒjƒ<6A>•”àƒ`ƒFƒbƒN
if( pBanner->h.platform == BANNER_PLATFORM_TWL ) {
if (pBanner->h.crc16_anime != AMN_getBannerAnimeCRC(&pBanner->anime)) {
retval = FALSE;
}
}
return retval;
}
// ƒAƒjƒ<6A>•”CRCŽZ<C5BD>o<EFBFBD>B
static u32 AMN_getBannerAnimeCRC(const BannerAnime* pAnime)
{
return SVC_GetCRC16(0xffff, pAnime, sizeof(*pAnime));
}
static BOOL AMN_checkAndReplaceBannerAnime(s32 index)
{
BOOL retval = FALSE;
TWLBannerFile* pBanner;
// ”͈͊OÌindexð³Ž<C5BD>B
if (cNandTitleIndexStart <= index && index < (cNandTitleIndexStart + sNandTitleListLengthForLauncher)) {
if (spSubBannerFileBuffer->h.crc16_anime == AMN_getBannerAnimeCRC(&spSubBannerFileBuffer->anime)) {
// <20>¬Œ÷µ½ÌŃRƒs<C692>[‚·‚é
pBanner = &spNandBannerFileArray[index-cNandTitleIndexStart];
// h.crc16_animeµ©ƒ`ƒFƒbƒNµÄ¢È¢ÌÅ<E2809A>A»êÆanime¾¯ƒRƒs<C692>[
pBanner->h.crc16_anime = spSubBannerFileBuffer->h.crc16_anime;
// MI_CpuCopy()Ì•ûªx­ÈÁ½<E2809A>c
pBanner->anime = spSubBannerFileBuffer->anime;
retval = TRUE;
}
}
// IPL_PRINT("checkAndReplaceBannerAnime(%d)=%d\n", index, retval);
return retval;
}
// see also TwlIPL_RED/build/systemmenu_RED/Launcher/ARM9/src/bannerCounter.c
void AMN_BNC_incrementCount( AMNBannerCounter *c )
{
// TWLÌ݃JƒEƒ“ƒgƒCƒ“ƒNƒŠƒ<C5A0>ƒ“ƒg
if( c->banner->h.platform == BANNER_PLATFORM_TWL )
{
if( c->banner->anime.control[0].frameCount == 0 )
{
// ƒAƒjƒ<6A>É<E2809A>I[µ©<E28098>ݵȢ
//OS_TPrintf( "BNC_incrementCount:Only a Terminator!\n" );
return;
}
c->count++;
if( c->count >= c->banner->anime.control[c->control].frameCount )
{
// ƒJƒEƒ“ƒglªƒRƒ“ƒgƒ<67><C692>̃tƒŒ<C692>[ƒ€ƒJƒEƒ“ƒg𴦽ÌÅŽŸÌƒRƒ“ƒgƒ<67><C692>[ƒ‹‚Ö
c->control++;
c->count = 0;
//ƒ<C692>[ƒvyÑâŽ~Ì<E2809A>ˆ<CB86>
if( c->control >= BANNER_ANIME_CONTROL_INFO_NUM )
{
// ƒRƒ“ƒgƒ<67><C692>ªŒÀŠE𴦽ç³<E28093>ðŒ<C3B0>Ń<C692>[ƒv
AMN_BNC_resetCount( c );
}
else if( c->banner->anime.control[c->control].frameCount == 0 )
{
// ƒRƒ“ƒgƒ<67><C692>̃tƒŒ<C692>[ƒ€ƒJƒEƒ“ƒgª0Èç<E2809A>I[“žB
if( c->banner->anime.control[c->control].animeType == 0 )
{
// ƒAƒjƒ<6A>ƒ^ƒCƒv0Èçƒ<C692>[ƒv
AMN_BNC_resetCount( c );
}
else if( c->banner->anime.control[c->control].animeType == 1 )
{
// ƒAƒjƒ<6A>ƒ^ƒCƒv1ÈçâŽ~<7E>iˆêÂÕRƒ“ƒgƒ<67><C692>Éß·<E2809A>j
c->control--;
}
}
}
}
}
AMNFrameAnimeData AMN_BNC_getFAD( AMNBannerCounter *c )
{
AMNFrameAnimeData ret;
if( c->banner->h.platform == BANNER_PLATFORM_NTR )
{
ret.image = c->banner->v1.image;
ret.pltt = c->banner->v1.pltt;
ret.hflip = FALSE;
ret.vflip = FALSE;
}
else
{
if( c->banner->anime.control[0].frameCount == 0 )
{
// ƒAƒjƒ<6A>É<E2809A>I[µ©<E28098>ݵȢ
//OS_TPrintf( "BNC_getFAD:Only a Terminator!\n" );
ret.image = c->banner->v1.image;
ret.pltt = c->banner->v1.pltt;
ret.hflip = FALSE;
ret.vflip = FALSE;
return ret;
}
// ƒRƒ“ƒgƒ<67><C692>ƒf<C692>[ƒ^ð“ÇñÅ<E2809A>AŒ»<C592>Ý̃tƒŒ<C692>[ƒ€ÉŠY“·éƒf<C692>[ƒ^‚ð•Ô‚·
ret.image = c->banner->anime.image[ c->banner->anime.control[c->control].normal.cellNo ];
ret.pltt = c->banner->anime.pltt[ c->banner->anime.control[c->control].normal.plttNo ];
ret.hflip = c->banner->anime.control[c->control].normal.flipType & 0x1;
ret.vflip = (c->banner->anime.control[c->control].normal.flipType & 0x2) >> 1;
}
return ret;
}
AMNFrameAnimeData AMN_BNC_getFADAndIncCount( AMNBannerCounter *c )
{
AMNFrameAnimeData ret = AMN_BNC_getFAD( c );
AMN_BNC_incrementCount( c );
return ret;
}
BOOL AMN_isTitleIdValidForLauncher(NAMTitleId id)
{
// "Not Launch"ÅÈ¢<E2809A>@©Â<E2809A>@"Data Only"ÅÈ¢<E2809A>@Èç—LŒøÈƒ^ƒCƒgƒÆµÄƒŠƒXƒgÉljÁ
return ((id & ( TITLE_ID_NOT_LAUNCH_FLAG_MASK | TITLE_ID_DATA_ONLY_FLAG_MASK )) == 0);
}
BOOL AMN_isIndexValidForSetting(s32 index)
{
const TitleProperty* pTitleProp = AMN_getTitleProperty(index);
if (pTitleProp) {
return NAM_IsUserTitle(pTitleProp->titleID);
}
return FALSE;
}
static void AMNi_updateFreeBoxCount( u8 count )
{
u32 installed;
u8 free;
BOOL changed = FALSE;
u8 *pBuffer;
BOOL retval = TRUE;
installed = LCFG_TSD_GetInstalledSoftBoxCount();
free = LCFG_TSD_GetFreeSoftBoxCount();
if( count > LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX )
{
count = LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX;
}
OS_TPrintf( "AMNi_updateFreeBoxCount : Install:%d, Free:%d, LCFG_Install:%d, LCFG_Free:%d, MAX:%d\n",
count, LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX - count, installed, free, LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX );
if( (u8)installed != count )
{
LCFG_TSD_SetInstalledSoftBoxCount( ( u8 )count );
changed = TRUE;
}
if( LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX - count != free )
{
LCFG_TSD_SetFreeSoftBoxCount( (u8)( LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX - count ) );
changed = TRUE;
}
if(changed)
{
// LCFGƒ‰ƒCƒuƒ‰ƒŠÌ<E2809A>ÓI•Ï<E280A2>ÌlðNANDÉ”½‰f
pBuffer = AMNi_Alloc( LCFG_WRITE_TEMP );
if (!pBuffer) {
OS_TPrintf( "AMNi_updateFreeBoxCount : AMNi_Alloc failed.\n" );
return;
}
retval = LCFG_WriteTWLSettings( (u8 (*)[ LCFG_WRITE_TEMP ] )pBuffer );
AMNi_Free( pBuffer );
if (!retval) {
OS_TPrintf( "AMNi_updateFreeBoxCount : LCFG_WriteTWLSettings failed.\n" );
return;
}
OS_TPrintf( "AMNi_updateFreeBoxCount : FreeBoxCount is updated.\n" );
}else
{
OS_TPrintf( "AMNi_updateFreeBoxCount : FreeBoxCount is not updated.\n" );
}
}
/*--------------------------------------------------------------------------------------------------------
// ƒAƒvƒŠƒP<C692>[ƒVƒ‡ƒ“Éß<E2809A>žÞƒeƒXƒgƒR<C692>[ƒh̃Tƒ“ƒvƒ
// ŽÀŒ±—pɃq<C692>[ƒvðŠg£ƒ<C2A3>ƒCƒ“ƒ<E2809C>ƒƒŠ©çŠm•۵ĢéÌÅ<C385>ˆÓ
// ŽOÉOS_EnableMainExArena<6E>AOS_Init<69>iOS_InitArena<6E>j<EFBFBD>A¨æÑNAM_InitðŒÄñŨ­•K—v è
static OSHeapHandle os_heap_handle;
static void *alloc_tmp(u32 size)
{
return OS_AllocFromHeap( OS_ARENA_MAINEX, os_heap_handle, size);
}
static void free_tmp( void *ptr )
{
OS_FreeToHeap( OS_ARENA_MAINEX, os_heap_handle, ptr );
}
static void test2()
{
s32 length;
s32 idx;
void *nstart;
nstart = OS_InitAlloc( OS_ARENA_MAINEX, OS_GetMainExArenaLo(), OS_GetMainExArenaHi(), 1 );
OS_SetMainExArenaLo( nstart );
os_heap_handle = OS_CreateHeap( OS_ARENA_MAINEX, OS_GetMainExArenaLo(), OS_GetMainExArenaHi() );
AMN_init( alloc_tmp, free_tmp );
// N“®¼Œã<C592>AŽ©“®“IɃoƒi<C692>[ƒf<C692>[ƒ^“ÇÝ<E2809A>žÝð<E2809A>s¢Ü·<E2809A>B
// ƒ<>ƒCƒ“ƒXƒŒƒbƒhÅÍ<E2809A>AÆè ¦¸Š®—¹ÜÅÒ¿Ü·<E2809A>B
while (!AMN_isNandTitleListReady()) {
OS_Sleep(1);
}
// ƒ^ƒCƒgƒˆê——ðOS_PrintfµÜ·<E2809A>B
// cmn::util::U16toSjisÍ<E2809A>ASTDƒ‰ƒCƒuƒ‰ƒŠÌŠÖ<C5A0>ðŒÄÑ<E2809A>oµÄUnicode©çShiftJISÖ•ÏŠ·µÜ·<E2809A>B
length = AMN_getNandTitleListLengthForLauncher();
for (idx = 0; idx < length; idx++) {
s32 i;
char dst[256];
int dstlen = 256;
i = cNandTitleIndexStart + idx;
MI_CpuClearFast(dst,256);
STD_ConvertStringUnicodeToSjis(dst, &dstlen, AMN_getBannerText(i), NULL, NULL);
OS_TPrintf("title idx=%2d, titleId=%016llx exp=%02x forStg=%d bannerText=%s\n",
i, (u64)AMN_getTitleIdByIndex(i),
AMN_getTitleProperty(i)->expansionFlags,
AMN_isIndexValidForSetting(i),
dst);
}
// ƒ^ƒCƒgƒID©çÌtˆø«
{
static const NAMTitleId table[] = {
0x00030015344e4141, // "4NAA" - UIG launcher default
0x0003001534303141, // "401A" - UIG launcher clone
0x0003001534303241, // "402A" - UIG launcher clone
0x00030017484e4141, // "HNAA" - RED launcher default
0x00030015484e4241, // "HNBA" - RED MachineSettings
0x0000000000000001, // nonexistent
0 // stopper
};
u32 i;
i = 0;
while (table[i]) {
OS_TPrintf("index by titleId(%016llx)=%d\n", (u64)table[i], AMN_getIndexByTitleId(table[i]));
i++;
}
}
// ƒoƒi<C692>[ƒCƒ<43><C692>[ƒWƒf<C692>[ƒ^
{
s32 index;
const u8* pImage;
index = 3; //app::Manager::cNandTitleIndexStart;
pImage = AMN_getBannerImage(index);
OS_TPrintf("banner image for index(%02d)=%02x %02x %02x %02x %02x %02x %02x %02x \n",
index,
pImage[0], pImage[1], pImage[2], pImage[3],
pImage[4], pImage[5], pImage[6], pImage[7]);
}
}
--------------------------------------------------------------------------------------------------------*/