mirror of
https://github.com/rvtr/TwlIPL.git
synced 2025-10-31 06:01:12 -04:00
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@448 b08762b0-b915-fc4b-9d8c-17b2551a87ff
511 lines
16 KiB
C
511 lines
16 KiB
C
/*---------------------------------------------------------------------------*
|
||
Project: TwlIPL
|
||
File: ExecPreLoadedApp.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:: 2007-10-31#$
|
||
$Rev: 91 $
|
||
$Author: yosiokat $
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
#include <twl.h>
|
||
#include <sysmenu.h>
|
||
#include "misc.h"
|
||
#include "ExecPreLoadedApp.h"
|
||
|
||
// define data------------------------------------------
|
||
#define RETURN_BUTTON_TOP_X 2
|
||
#define RETURN_BUTTON_TOP_Y 21
|
||
#define RETURN_BUTTON_BOTTOM_X ( RETURN_BUTTON_TOP_X + 8 )
|
||
#define RETURN_BUTTON_BOTTOM_Y ( RETURN_BUTTON_TOP_Y + 2 )
|
||
|
||
#define MLEP_MENU_ELEMENT_NUM 7 // メニューの項目数
|
||
|
||
#define PARAM_LENGTH 10
|
||
|
||
// extern data------------------------------------------
|
||
|
||
// function's prototype declaration---------------------
|
||
|
||
static void MenuScene( void );
|
||
|
||
// global variable -------------------------------------
|
||
extern RTCDrawProperty g_rtcDraw;
|
||
|
||
// static variable -------------------------------------
|
||
static u16 s_csr = 0;
|
||
static void(*s_pNowProcess)(void);
|
||
|
||
// const data -----------------------------------------
|
||
static const u16 *s_pStrMenu[ MLEP_MENU_ELEMENT_NUM ] =
|
||
{
|
||
L"再配置チェッカ0(再配置無し)",
|
||
L"再配置チェッカ1(エラー)",
|
||
L"再配置チェッカ2(正順コピー1)",
|
||
L"再配置チェッカ3(正順コピー2)",
|
||
L"再配置チェッカ4(エラー)",
|
||
L"再配置チェッカ5(WRAMへ配置)",
|
||
L"ランチャーに戻る",
|
||
};
|
||
|
||
static MenuPos s_menuPos[] = {
|
||
{ TRUE, 4 * 8, 8 * 8 },
|
||
{ TRUE, 4 * 8, 10 * 8 },
|
||
{ TRUE, 4 * 8, 12 * 8 },
|
||
{ TRUE, 4 * 8, 14 * 8 },
|
||
{ TRUE, 4 * 8, 16 * 8 },
|
||
{ TRUE, 4 * 8, 18 * 8 },
|
||
{ TRUE, 4 * 8, 20 * 8 },
|
||
};
|
||
|
||
static const MenuParam s_menuParam = {
|
||
MLEP_MENU_ELEMENT_NUM,
|
||
TXT_COLOR_BLACK,
|
||
TXT_COLOR_GREEN,
|
||
TXT_COLOR_RED,
|
||
&s_menuPos[ 0 ],
|
||
(const u16 **)&s_pStrMenu,
|
||
};
|
||
|
||
//======================================================
|
||
// テストプログラム
|
||
//======================================================
|
||
|
||
typedef struct RomSegmentRange {
|
||
u32 start;
|
||
u32 end;
|
||
}RomSegmentRange;
|
||
|
||
//#define EPLA_TWL_HEADER_LOAD_MMEM (SYSM_TWL_ARM9_LTD_LOAD_MMEM_END - 0x4000)
|
||
//#define EPLA_TWL_HEADER_LOAD_MMEM_END SYSM_TWL_ARM9_LTD_LOAD_MMEM_END
|
||
#define EPLA_TWL_HEADER_LOAD_MMEM (0x27e0000 - 0x4000)
|
||
#define EPLA_TWL_HEADER_LOAD_MMEM_END 0x27e0000
|
||
#define EPLA_TWL_ARM7_LTD_LOAD_MMEM (EPLA_TWL_HEADER_LOAD_MMEM - 0x108000)
|
||
#define EPLA_TWL_ARM7_LTD_LOAD_MMEM_END EPLA_TWL_HEADER_LOAD_MMEM
|
||
#define EPLA_TWL_ARM9_LTD_LOAD_MMEM_END EPLA_TWL_ARM7_LTD_LOAD_MMEM
|
||
|
||
#define EPLA_TWL_ARM9_LTD_LOAD_MMEM (SYSM_TWL_ARM9_LTD_LOAD_MMEM + 0x1800)
|
||
|
||
static RomSegmentRange romSegmentRange[RELOCATE_INFO_NUM] = {
|
||
{ SYSM_TWL_ARM9_LOAD_MMEM, SYSM_TWL_ARM9_LOAD_MMEM_END },
|
||
{ SYSM_TWL_ARM7_LOAD_MMEM, SYSM_TWL_ARM7_LOAD_MMEM_END },
|
||
{ EPLA_TWL_ARM9_LTD_LOAD_MMEM, EPLA_TWL_ARM9_LTD_LOAD_MMEM_END },
|
||
{ EPLA_TWL_ARM7_LTD_LOAD_MMEM, EPLA_TWL_ARM7_LTD_LOAD_MMEM_END },
|
||
};
|
||
|
||
static RomSegmentRange romSegmentRangeNitro[RELOCATE_INFO_NUM] = {
|
||
{ SYSM_NTR_ARM9_LOAD_MMEM, SYSM_NTR_ARM9_LOAD_MMEM_END },
|
||
{ SYSM_NTR_ARM7_LOAD_MMEM, SYSM_NTR_ARM7_LOAD_MMEM_END },
|
||
{ EPLA_TWL_ARM9_LTD_LOAD_MMEM, EPLA_TWL_ARM9_LTD_LOAD_MMEM_END },
|
||
{ EPLA_TWL_ARM7_LTD_LOAD_MMEM, EPLA_TWL_ARM7_LTD_LOAD_MMEM_END },
|
||
};
|
||
|
||
static u32 load_region_check_list[RELOCATE_INFO_NUM][(RELOCATE_INFO_NUM+1) * 2 - 1] =
|
||
{
|
||
{SYSM_NTR_ARM7_LOAD_MMEM, SYSM_NTR_ARM7_LOAD_MMEM_END,
|
||
EPLA_TWL_ARM9_LTD_LOAD_MMEM, EPLA_TWL_ARM9_LTD_LOAD_MMEM_END,
|
||
EPLA_TWL_ARM7_LTD_LOAD_MMEM, EPLA_TWL_ARM7_LTD_LOAD_MMEM_END,
|
||
EPLA_TWL_HEADER_LOAD_MMEM, EPLA_TWL_HEADER_LOAD_MMEM_END,
|
||
NULL },
|
||
{SYSM_NTR_ARM9_LOAD_MMEM, SYSM_NTR_ARM9_LOAD_MMEM_END,
|
||
EPLA_TWL_ARM9_LTD_LOAD_MMEM, EPLA_TWL_ARM9_LTD_LOAD_MMEM_END,
|
||
EPLA_TWL_ARM7_LTD_LOAD_MMEM, EPLA_TWL_ARM7_LTD_LOAD_MMEM_END,
|
||
EPLA_TWL_HEADER_LOAD_MMEM, EPLA_TWL_HEADER_LOAD_MMEM_END,
|
||
NULL },
|
||
{SYSM_NTR_ARM9_LOAD_MMEM, SYSM_NTR_ARM9_LOAD_MMEM_END,
|
||
SYSM_NTR_ARM7_LOAD_MMEM, SYSM_NTR_ARM7_LOAD_MMEM_END,
|
||
EPLA_TWL_ARM7_LTD_LOAD_MMEM, EPLA_TWL_ARM7_LTD_LOAD_MMEM_END,
|
||
EPLA_TWL_HEADER_LOAD_MMEM, EPLA_TWL_HEADER_LOAD_MMEM_END,
|
||
NULL },
|
||
{SYSM_NTR_ARM9_LOAD_MMEM, SYSM_NTR_ARM9_LOAD_MMEM_END,
|
||
SYSM_NTR_ARM7_LOAD_MMEM, SYSM_NTR_ARM7_LOAD_MMEM_END,
|
||
EPLA_TWL_ARM9_LTD_LOAD_MMEM, EPLA_TWL_ARM9_LTD_LOAD_MMEM_END,
|
||
EPLA_TWL_HEADER_LOAD_MMEM, EPLA_TWL_HEADER_LOAD_MMEM_END,
|
||
NULL },
|
||
};
|
||
|
||
// ============================================================================
|
||
//
|
||
// アプリ起動
|
||
//
|
||
// ============================================================================
|
||
|
||
// ROMのロード先領域をチェックし、再配置の必要があればロード先アドレスを変更し、再配置情報を*infoにセットする。
|
||
// ロード先領域が被ってはいけない領域のリストcheck_destは{開始, 終了, 開始2, 終了2, ……, NULL}の形式。
|
||
// 再配置の有り無しに関わらずロード可能ならばTRUE、ロード不可能ならばFALSEを返す
|
||
// 再配置が必要ない場合、再配置情報のsrc,dest,lengthにはそれぞれNULLが代入される。
|
||
static BOOL EPLAi_CheckLoadRegionAndSetRelocateInfoEx
|
||
( u32 *dest, u32 length, RomSegmentRange default_region, u32 *check_dest, Relocate_Info *info )
|
||
{
|
||
// 再配置情報が残っている可能性大なのでクリアしておく
|
||
MI_CpuClearFast( info, sizeof(Relocate_Info) );
|
||
|
||
if( default_region.end - default_region.start < length ) return FALSE;// サイズオーバー
|
||
if( !( default_region.start <= *dest && *dest + length <= default_region.end ) )
|
||
{
|
||
// 再配置の必要あり
|
||
while( *check_dest != NULL )
|
||
{
|
||
if( check_dest[0] < *dest + length && *dest < check_dest[1] ) return FALSE;// チェック領域に被ったらNG
|
||
check_dest += 2;
|
||
}
|
||
|
||
// ここまで来ていれば再配置可能
|
||
// 後方コピーフラグOFF
|
||
info->rev = FALSE;
|
||
if( default_region.start < *dest + length && *dest + length <= default_region.end )
|
||
{
|
||
// デフォルト配置領域の先頭部に、再配置先の後部が被っている
|
||
// ポストクリア情報
|
||
info->post_clear_addr = *dest + length;
|
||
info->post_clear_length = default_region.end - (*dest + length);
|
||
}
|
||
else if( default_region.start <= *dest && *dest < default_region.end )
|
||
{
|
||
// デフォルト配置領域の後部に、再配置先の先頭部が被っている
|
||
// ポストクリア情報
|
||
info->post_clear_addr = default_region.start;
|
||
info->post_clear_length = *dest - default_region.start;
|
||
if( *dest < default_region.start + length )
|
||
{
|
||
// 更に、デフォルト配置領域にロードしたデータの最後尾と再配置先の先頭部が被っている
|
||
// 後方コピーフラグON
|
||
info->rev = TRUE;
|
||
}
|
||
}else
|
||
{
|
||
// まったく被っていない
|
||
// ポストクリア情報
|
||
info->post_clear_addr = default_region.start;
|
||
info->post_clear_length = default_region.end - default_region.start;
|
||
}
|
||
info->src = default_region.start;
|
||
info->dest = *dest;
|
||
info->length = length;
|
||
*dest = default_region.start;
|
||
}else
|
||
{
|
||
// 再配置の必要なし
|
||
info->src = NULL;
|
||
info->dest = NULL;
|
||
info->length = NULL;
|
||
info->post_clear_addr = NULL;
|
||
info->post_clear_length = NULL;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// EPLAi_CheckLoadRegionAndSetRelocateInfoExのラッパー関数
|
||
static BOOL EPLAi_CheckLoadRegionAndSetRelocateInfo( RomSegmentName seg, u32 *dest, u32 length, Relocate_Info *info, BOOL isTwlApp)
|
||
{
|
||
RomSegmentRange *rsr;
|
||
if( isTwlApp )
|
||
{
|
||
rsr = romSegmentRange;
|
||
}else
|
||
{
|
||
//NTR専用
|
||
rsr = romSegmentRangeNitro;
|
||
}
|
||
return EPLAi_CheckLoadRegionAndSetRelocateInfoEx(dest, length, rsr[seg], load_region_check_list[seg], info);
|
||
}
|
||
|
||
|
||
static void DrawMenuScene( void )
|
||
{
|
||
PutStringUTF16( 1 * 8, 0 * 8, TXT_COLOR_BLUE, (const u16 *)L"ExecPreLoadedApp");
|
||
// メニュー項目
|
||
DrawMenu( s_csr, &s_menuParam );
|
||
}
|
||
|
||
static void MenuInit( void )
|
||
{
|
||
GX_DispOff();
|
||
GXS_DispOff();
|
||
NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE );
|
||
|
||
PutStringUTF16( 1 * 8, 0 * 8, TXT_COLOR_BLUE, (const u16 *)L"ExecPreLoadedApp");
|
||
GetAndDrawRTCData( &g_rtcDraw, TRUE );
|
||
|
||
SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 );
|
||
|
||
GXS_SetVisiblePlane( GX_PLANEMASK_BG0 );
|
||
|
||
s_pNowProcess = MenuScene;
|
||
|
||
DrawMenuScene();
|
||
|
||
GX_DispOn();
|
||
GXS_DispOn();
|
||
}
|
||
|
||
// 指定ファイルリード
|
||
static s32 ReadFile(FSFile* pf, void* buffer, s32 size)
|
||
{
|
||
u8* p = (u8*)buffer;
|
||
s32 remain = size;
|
||
|
||
while( remain > 0 )
|
||
{
|
||
const s32 len = MATH_IMin(1024, remain);
|
||
const s32 readLen = FS_ReadFile(pf, p, len);
|
||
|
||
if( readLen < 0 )
|
||
{
|
||
return readLen;
|
||
}
|
||
if( readLen != len )
|
||
{
|
||
return size - remain + readLen;
|
||
}
|
||
|
||
remain -= readLen;
|
||
p += readLen;
|
||
}
|
||
|
||
return size;
|
||
}
|
||
|
||
#define EPLAi_GetLauncherParamAddr() ( (LauncherParam *)HW_PARAM_LAUNCH_PARAM )
|
||
|
||
static BOOL LoadTitle( NAMTitleId bootTitleID )
|
||
{
|
||
enum
|
||
{
|
||
region_header = 0,
|
||
region_arm9_ntr,
|
||
region_arm7_ntr,
|
||
region_arm9_twl,
|
||
region_arm7_twl,
|
||
region_max
|
||
};
|
||
// メインメモリのクリア
|
||
// DSダウンロードプレイの時は、ROMヘッダを退避する
|
||
// アプリロード
|
||
// アプリ認証
|
||
|
||
|
||
// ロード
|
||
char path[256];
|
||
FSFile file[1];
|
||
BOOL bSuccess;
|
||
BOOL isTwlApp = TRUE;
|
||
NAM_GetTitleBootContentPath(path, bootTitleID);
|
||
|
||
bSuccess = FS_OpenFileEx(file, path, FS_FILEMODE_R);
|
||
|
||
if( ! bSuccess )
|
||
{
|
||
OS_TPrintf("RebootSystem failed: cant open file\n");
|
||
return FALSE;
|
||
}
|
||
|
||
{
|
||
int i;
|
||
u32 source[region_max];
|
||
u32 length[region_max];
|
||
u32 destaddr[region_max];
|
||
static u8 header[HW_TWL_ROM_HEADER_BUF_SIZE] ATTRIBUTE_ALIGN(32);
|
||
s32 readLen;
|
||
|
||
// まずROMヘッダを読み込む
|
||
// (本来ならここでSRLの正当性判定)
|
||
bSuccess = FS_SeekFile(file, 0x00000000, FS_SEEK_SET);
|
||
|
||
if( ! bSuccess )
|
||
{
|
||
OS_TPrintf("RebootSystem failed: cant seek file(0)\n");
|
||
FS_CloseFile(file);
|
||
return FALSE;
|
||
}
|
||
|
||
readLen = ReadFile(file, header, (s32)sizeof(header));
|
||
|
||
if( readLen != (s32)sizeof(header) )
|
||
{
|
||
OS_TPrintf("RebootSystem failed: cant read file(%p, %d, %d, %d)\n", header, 0, sizeof(header), readLen);
|
||
FS_CloseFile(file);
|
||
return FALSE;
|
||
}
|
||
|
||
if( header[0x15C] != 0x56 || header[0x15D] != 0xCF )
|
||
{
|
||
int i, j;
|
||
for( i = 0; i < 0x20; ++i )
|
||
{
|
||
for( j = 0; j < 0x10; ++j )
|
||
{
|
||
OS_TPrintf("%02X ", header[i * 0x10 + j]);
|
||
}
|
||
OS_TPrintf("\n");
|
||
}
|
||
OS_TPrintf("RebootSystem failed: logo CRC error\n");
|
||
FS_CloseFile(file);
|
||
return FALSE;
|
||
}
|
||
|
||
if( header[0x12] && 0x03 == 0 )
|
||
{
|
||
//NTR専用ROM
|
||
isTwlApp = FALSE;
|
||
}
|
||
|
||
// 各領域を読み込む
|
||
source [region_header ] = 0x00000000;
|
||
length [region_header ] = HW_TWL_ROM_HEADER_BUF_SIZE;
|
||
destaddr[region_header ] = HW_TWL_ROM_HEADER_BUF;
|
||
|
||
source [region_arm9_ntr] = *(const u32*)&header[0x020];
|
||
length [region_arm9_ntr] = *(const u32*)&header[0x02C];
|
||
destaddr[region_arm9_ntr] = *(const u32*)&header[0x028];
|
||
|
||
source [region_arm7_ntr] = *(const u32*)&header[0x030];
|
||
length [region_arm7_ntr] = *(const u32*)&header[0x03C];
|
||
destaddr[region_arm7_ntr] = *(const u32*)&header[0x038];
|
||
|
||
if( isTwlApp )
|
||
{
|
||
source [region_arm9_twl] = *(const u32*)&header[0x1C0];
|
||
length [region_arm9_twl] = *(const u32*)&header[0x1CC];
|
||
destaddr[region_arm9_twl] = *(const u32*)&header[0x1C8];
|
||
|
||
source [region_arm7_twl] = *(const u32*)&header[0x1D0];
|
||
length [region_arm7_twl] = *(const u32*)&header[0x1DC];
|
||
destaddr[region_arm7_twl] = *(const u32*)&header[0x1D8];
|
||
}
|
||
|
||
// 領域読み込み先のチェック及び再配置情報データの作成
|
||
for( i=0; i<RELOCATE_INFO_NUM; i++ )
|
||
{
|
||
if ( !isTwlApp && i >= ARM9_LTD_STATIC ) continue;// nitroでは読み込まない領域
|
||
// 再配置情報のランチャーパラメタへの受け渡し処理。暫定的な実装。SDKに機能として組み込んでしまうか検討中。
|
||
if ( !EPLAi_CheckLoadRegionAndSetRelocateInfo( (RomSegmentName)i, &(destaddr[i+region_arm9_ntr]), length[i+region_arm9_ntr],
|
||
&EPLAi_GetLauncherParamAddr()->body.v1.relocInfo[i], isTwlApp ) )
|
||
{
|
||
OS_TPrintf("RebootSystem failed: ROM Load Region error\n");
|
||
FS_CloseFile(file);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
for (i = region_header; i < region_max; ++i)
|
||
{
|
||
u32 len = length[i];
|
||
|
||
if ( !isTwlApp && i >= region_arm9_twl ) continue;// nitroでは読み込まない領域
|
||
|
||
bSuccess = FS_SeekFile(file, (s32)source[i], FS_SEEK_SET);
|
||
|
||
if( ! bSuccess )
|
||
{
|
||
OS_TPrintf("RebootSystem failed: cant seek file(%d)\n", source[i]);
|
||
FS_CloseFile(file);
|
||
return FALSE;
|
||
}
|
||
|
||
readLen = ReadFile(file, (void *)destaddr[i], (s32)len);
|
||
|
||
if( readLen != (s32)len )
|
||
{
|
||
OS_TPrintf("RebootSystem failed: cant read file(%d, %d)\n", source[i], len);
|
||
FS_CloseFile(file);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
(void)FS_CloseFile(file);
|
||
}
|
||
|
||
// ROMヘッダバッファをコピー
|
||
MI_CpuCopy32( (void *)HW_TWL_ROM_HEADER_BUF, (void *)EPLA_TWL_HEADER_LOAD_MMEM, EPLA_TWL_HEADER_LOAD_MMEM_END - EPLA_TWL_HEADER_LOAD_MMEM );
|
||
|
||
SYSMi_GetWork()->isLoadSucceeded = TRUE;
|
||
return TRUE;
|
||
}
|
||
|
||
static void MenuScene(void)
|
||
{
|
||
BOOL tp_select = FALSE;
|
||
LauncherBootFlags tempflag = {TRUE, 0, TRUE, FALSE, TRUE, FALSE, 0};
|
||
|
||
ReadTP();
|
||
|
||
//--------------------------------------
|
||
// キー入力処理
|
||
//--------------------------------------
|
||
if( pad.trg & PAD_KEY_DOWN ){ // カーソルの移動
|
||
if( ++s_csr == MLEP_MENU_ELEMENT_NUM ) {
|
||
s_csr=0;
|
||
}
|
||
}
|
||
if( pad.trg & PAD_KEY_UP ){
|
||
if( --s_csr & 0x80 ) {
|
||
s_csr=MLEP_MENU_ELEMENT_NUM - 1;
|
||
}
|
||
}
|
||
tp_select = SelectMenuByTP( &s_csr, &s_menuParam );
|
||
|
||
DrawMenuScene();
|
||
|
||
if( ( pad.trg & PAD_BUTTON_A ) || ( tp_select ) ) { // メニュー項目への分岐
|
||
if( s_menuPos[ s_csr ].enable ) {
|
||
switch( s_csr ) {
|
||
case 0:
|
||
//アプリ起動
|
||
if(LoadTitle(0x0003000452434b30))
|
||
OS_SetLauncherParamAndResetHardware( 0, 0x0003000452434b30, &tempflag ); // RCK0
|
||
break;
|
||
case 1:
|
||
//アプリ起動
|
||
if(LoadTitle(0x0003000452434b31))
|
||
OS_SetLauncherParamAndResetHardware( 0, 0x0003000452434b31, &tempflag ); // RCK1
|
||
break;
|
||
case 2:
|
||
//アプリ起動
|
||
if(LoadTitle(0x0003000452434b32))
|
||
OS_SetLauncherParamAndResetHardware( 0, 0x0003000452434b32, &tempflag ); // RCK2
|
||
break;
|
||
case 3:
|
||
//アプリ起動
|
||
if(LoadTitle(0x0003000452434b33))
|
||
OS_SetLauncherParamAndResetHardware( 0, 0x0003000452434b33, &tempflag ); // RCK3
|
||
break;
|
||
case 4:
|
||
//アプリ起動
|
||
if(LoadTitle(0x0003000452434b34))
|
||
OS_SetLauncherParamAndResetHardware( 0, 0x0003000452434b34, &tempflag ); // RCK4
|
||
break;
|
||
case 5:
|
||
//アプリ起動
|
||
if(LoadTitle(0x0003000452434b35))
|
||
OS_SetLauncherParamAndResetHardware( 0, 0x0003000452434b35, &tempflag ); // RCK5
|
||
break;
|
||
case 6:
|
||
OS_SetLauncherParamAndResetHardware( 0, NULL, &tempflag );
|
||
//再起動
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 初期化
|
||
void ExecPreLoadedAppInit( void )
|
||
{
|
||
ChangeUserColor( TSD_GetUserColor() );
|
||
MenuInit();
|
||
}
|
||
|
||
// メインループ
|
||
void ExecPreLoadedAppMain(void)
|
||
{
|
||
s_pNowProcess();
|
||
}
|