Added RUNFLAG_APTREINIT for supporting environments that require APT reinitialization

This commit is contained in:
fincs 2015-05-06 22:01:40 +02:00
parent 004dfff8bd
commit 350cb955b2
2 changed files with 129 additions and 25 deletions

View File

@ -2,6 +2,7 @@
// TODO : find a better place to put this // TODO : find a better place to put this
#define RUNFLAG_APTWORKAROUND (BIT(0)) #define RUNFLAG_APTWORKAROUND (BIT(0))
#define RUNFLAG_APTREINIT (BIT(1))
typedef enum{ typedef enum{
APPID_HOMEMENU = 0x101, // Home Menu APPID_HOMEMENU = 0x101, // Home Menu
@ -55,11 +56,14 @@ bool aptMainLoop(); // Use like this in your main(): while (aptMainLoop()) { you
Result APT_GetLockHandle(Handle* handle, u16 flags, Handle* lockHandle); Result APT_GetLockHandle(Handle* handle, u16 flags, Handle* lockHandle);
Result APT_Initialize(Handle* handle, NS_APPID appId, Handle* eventHandle1, Handle* eventHandle2); Result APT_Initialize(Handle* handle, NS_APPID appId, Handle* eventHandle1, Handle* eventHandle2);
Result APT_Finalize(Handle* handle, NS_APPID appId);
Result APT_HardwareResetAsync(Handle* handle); Result APT_HardwareResetAsync(Handle* handle);
Result APT_Enable(Handle* handle, u32 a); Result APT_Enable(Handle* handle, u32 a);
Result APT_GetAppletManInfo(Handle* handle, u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu_appid, NS_APPID *active_appid); Result APT_GetAppletManInfo(Handle* handle, u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu_appid, NS_APPID *active_appid);
Result APT_PrepareToJumpToHomeMenu(Handle* handle); Result APT_PrepareToJumpToHomeMenu(Handle* handle);
Result APT_JumpToHomeMenu(Handle* handle, u32 a, u32 b, u32 c); Result APT_JumpToHomeMenu(Handle* handle, u32 a, u32 b, u32 c);
Result APT_PrepareToJumpToApplication(Handle* handle, u32 a);
Result APT_JumpToApplication(Handle* handle, u32 a, u32 b, u32 c);
Result APT_IsRegistered(Handle* handle, NS_APPID appID, u8* out); Result APT_IsRegistered(Handle* handle, NS_APPID appID, u8* out);
Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType); Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType);
Result APT_NotifyToWait(Handle* handle, NS_APPID appID); Result APT_NotifyToWait(Handle* handle, NS_APPID appID);

View File

@ -48,8 +48,23 @@ static Handle __apt_launchapplet_inhandle;
static u32 *__apt_launchapplet_parambuf; static u32 *__apt_launchapplet_parambuf;
static u32 __apt_launchapplet_parambufsize; static u32 __apt_launchapplet_parambufsize;
// The following function can be overriden in order to log APT signals and notifications for debugging purposes
__attribute__((weak)) void _aptDebug(int a, int b)
{
}
static void aptAppStarted(void); static void aptAppStarted(void);
static bool aptIsCrippled(void)
{
return (__system_runflags & RUNFLAG_APTWORKAROUND) != 0;
}
static bool aptIsReinit(void)
{
return (__system_runflags & RUNFLAG_APTREINIT) != 0;
}
static Result __apt_initservicehandle() static Result __apt_initservicehandle()
{ {
Result ret=0; Result ret=0;
@ -162,7 +177,7 @@ void aptReturnToMenu()
NS_APPID menu_appid; NS_APPID menu_appid;
u32 tmp0 = 1, tmp1 = 0; u32 tmp0 = 1, tmp1 = 0;
if(__system_runflags&RUNFLAG_APTWORKAROUND) if(aptIsCrippled())
{ {
svcClearEvent(aptStatusEvent); svcClearEvent(aptStatusEvent);
aptSetStatus(APP_EXITING); aptSetStatus(APP_EXITING);
@ -177,15 +192,15 @@ void aptReturnToMenu()
aptCloseSession(); aptCloseSession();
} }
// Set status to SUSPENDED.
svcClearEvent(aptStatusEvent);
aptSetStatus(APP_SUSPENDED);
// Prepare for return to menu // Prepare for return to menu
aptOpenSession(); aptOpenSession();
APT_PrepareToJumpToHomeMenu(NULL); APT_PrepareToJumpToHomeMenu(NULL);
aptCloseSession(); aptCloseSession();
// Set status to SUSPENDED.
svcClearEvent(aptStatusEvent);
aptSetStatus(APP_SUSPENDED);
// Save Vram // Save Vram
GSPGPU_SaveVramSysArea(NULL); GSPGPU_SaveVramSysArea(NULL);
@ -286,8 +301,9 @@ static void __handle_notification() {
aptOpenSession(); aptOpenSession();
ret = APT_InquireNotification(NULL, currentAppId, &type); ret = APT_InquireNotification(NULL, currentAppId, &type);
aptCloseSession(); aptCloseSession();
if(ret!=0) return;
if(ret!=0)return; _aptDebug(1, type);
switch(type) switch(type)
{ {
@ -350,6 +366,8 @@ static bool __handle_incoming_parameter() {
APT_ReceiveParameter(NULL, currentAppId, 0x1000, aptParameters, NULL, &type); APT_ReceiveParameter(NULL, currentAppId, 0x1000, aptParameters, NULL, &type);
aptCloseSession(); aptCloseSession();
_aptDebug(2, type);
switch(type) switch(type)
{ {
case 0x1: // Application just started. case 0x1: // Application just started.
@ -366,10 +384,14 @@ static bool __handle_incoming_parameter() {
aptSetStatus(APP_APPLETCLOSED); aptSetStatus(APP_APPLETCLOSED);
return true; return true;
case 0xB: // Just returned from menu. case 0xB: // Just returned from menu.
GSPGPU_AcquireRight(NULL, 0x0); if (aptStatusMutex)
GSPGPU_RestoreVramSysArea(NULL); {
aptAppletUtility_Exit_RetToApp(0); GSPGPU_AcquireRight(NULL, 0x0);
aptSetStatus(APP_RUNNING); GSPGPU_RestoreVramSysArea(NULL);
aptAppletUtility_Exit_RetToApp(0);
aptSetStatus(APP_RUNNING);
} else
aptAppStarted();
return true; return true;
case 0xC: // Exiting application. case 0xC: // Exiting application.
@ -387,9 +409,8 @@ void aptEventHandler(void *arg)
while(runThread) while(runThread)
{ {
s32 syncedID = 0; s32 syncedID = 0;
svcWaitSynchronizationN(&syncedID, aptEvents, 2, 0, U64_MAX); svcWaitSynchronizationN(&syncedID, aptEvents, 3, 0, U64_MAX);
svcClearEvent(aptEvents[syncedID]); svcClearEvent(aptEvents[syncedID]);
switch(syncedID) switch(syncedID)
{ {
// Event 0 means we got a signal from NS (home button, power button etc). // Event 0 means we got a signal from NS (home button, power button etc).
@ -400,7 +421,7 @@ void aptEventHandler(void *arg)
case 0x1: case 0x1:
runThread = __handle_incoming_parameter(); runThread = __handle_incoming_parameter();
break; break;
// Event 2 means we should exit the thread (event will be added later). // Event 2 means we should exit the thread.
case 0x2: case 0x2:
runThread = false; runThread = false;
break; break;
@ -418,6 +439,8 @@ Result aptInit(void)
if (aptInitialised) return ret; if (aptInitialised) return ret;
aptStatusMutex = 0;
// Initialize APT stuff, escape load screen. // Initialize APT stuff, escape load screen.
ret = __apt_initservicehandle(); ret = __apt_initservicehandle();
if(ret!=0)return ret; if(ret!=0)return ret;
@ -429,7 +452,7 @@ Result aptInit(void)
svcCreateEvent(&aptStatusEvent, 0); svcCreateEvent(&aptStatusEvent, 0);
svcCreateEvent(&aptSleepSync, 0); svcCreateEvent(&aptSleepSync, 0);
if(!(__system_runflags&RUNFLAG_APTWORKAROUND)) if(!aptIsCrippled())
{ {
aptOpenSession(); aptOpenSession();
if((ret=APT_Initialize(NULL, currentAppId, &aptEvents[0], &aptEvents[1])))return ret; if((ret=APT_Initialize(NULL, currentAppId, &aptEvents[0], &aptEvents[1])))return ret;
@ -439,10 +462,26 @@ Result aptInit(void)
if((ret=APT_Enable(NULL, 0x0)))return ret; if((ret=APT_Enable(NULL, 0x0)))return ret;
aptCloseSession(); aptCloseSession();
// create APT close event
svcCreateEvent(&aptEvents[2], 0);
// After a cycle of APT_Finalize+APT_Initialize APT thinks the
// application is suspended, so we need to tell it to unsuspend us.
if (aptIsReinit())
{
aptOpenSession();
APT_PrepareToJumpToApplication(NULL, 0x0);
aptCloseSession();
aptOpenSession();
APT_JumpToApplication(NULL, 0x0, 0x0, 0x0);
aptCloseSession();
}
aptOpenSession(); aptOpenSession();
if((ret=APT_NotifyToWait(NULL, currentAppId)))return ret; if((ret=APT_NotifyToWait(NULL, currentAppId)))return ret;
aptCloseSession(); aptCloseSession();
// create APT event handler thread // create APT event handler thread
svcCreateThread(&aptEventHandlerThread, aptEventHandler, 0x0, svcCreateThread(&aptEventHandlerThread, aptEventHandler, 0x0,
(u32*)(&aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]), 0x31, 0xfffffffe); (u32*)(&aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]), 0x31, 0xfffffffe);
@ -458,7 +497,7 @@ void aptExit()
{ {
if (!aptInitialised) return; if (!aptInitialised) return;
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))aptAppletUtility_Exit_RetToApp(0); if(!aptIsCrippled())aptAppletUtility_Exit_RetToApp(0);
// This is only executed when application-termination was triggered via the home-menu power-off screen. // This is only executed when application-termination was triggered via the home-menu power-off screen.
if(aptGetStatusPower() == 1) if(aptGetStatusPower() == 1)
@ -468,16 +507,36 @@ void aptExit()
aptCloseSession(); aptCloseSession();
} }
if(!(__system_runflags&RUNFLAG_APTWORKAROUND)) if(!aptIsCrippled())
{ {
aptOpenSession(); bool isReinit = aptIsReinit();
APT_PrepareToCloseApplication(NULL, 0x1); if (aptGetStatus() == APP_EXITING)
aptCloseSession(); {
aptOpenSession();
APT_PrepareToCloseApplication(NULL, 0x1);
aptCloseSession();
aptOpenSession(); aptOpenSession();
APT_CloseApplication(NULL, 0x0, 0x0, 0x0); APT_CloseApplication(NULL, 0x0, 0x0, 0x0);
aptCloseSession(); aptCloseSession();
if (isReinit)
{
extern void (*__system_retAddr)(void);
__system_retAddr = NULL;
}
} else if (isReinit)
{
aptOpenSession();
APT_Finalize(NULL, currentAppId);
aptCloseSession();
}
} }
svcSignalEvent(aptEvents[2]);
svcWaitSynchronization(aptEventHandlerThread, U64_MAX);
svcCloseHandle(aptEventHandlerThread);
svcCloseHandle(aptEvents[2]);
svcCloseHandle(aptSleepSync); svcCloseHandle(aptSleepSync);
@ -492,7 +551,7 @@ bool aptMainLoop()
{ {
while(1) while(1)
{ {
//if(__system_runflags&RUNFLAG_APTWORKAROUND)__handle_notification(); //if(aptIsCrippled())__handle_notification();
switch(aptGetStatus()) switch(aptGetStatus())
{ {
@ -531,7 +590,7 @@ void aptAppStarted()
aptSetStatus(APP_RUNNING); aptSetStatus(APP_RUNNING);
if(!(__system_runflags&RUNFLAG_APTWORKAROUND)) if(!aptIsCrippled())
{ {
memset(buf1, 0, 4); memset(buf1, 0, 4);
@ -642,6 +701,18 @@ Result APT_Initialize(Handle* handle, NS_APPID appId, Handle* eventHandle1, Hand
return cmdbuf[1]; return cmdbuf[1];
} }
Result APT_Finalize(Handle* handle, NS_APPID appId)
{
if(!handle)handle=&aptuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x40040; //request header code
cmdbuf[1]=appId;
Result ret=0;
if((ret=svcSendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result APT_HardwareResetAsync(Handle* handle) Result APT_HardwareResetAsync(Handle* handle)
{ {
if(!handle)handle=&aptuHandle; if(!handle)handle=&aptuHandle;
@ -743,6 +814,35 @@ Result APT_JumpToHomeMenu(Handle* handle, u32 a, u32 b, u32 c)
return cmdbuf[1]; return cmdbuf[1];
} }
Result APT_PrepareToJumpToApplication(Handle* handle, u32 a)
{
if(!handle)handle=&aptuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x230040; //request header code
cmdbuf[1]=a;
Result ret=0;
if((ret=svcSendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result APT_JumpToApplication(Handle* handle, u32 a, u32 b, u32 c)
{
if(!handle)handle=&aptuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x240044; //request header code
cmdbuf[1]=a;
cmdbuf[2]=b;
cmdbuf[3]=c;
cmdbuf[4]=(b<<14)|2;
Result ret=0;
if((ret=svcSendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result APT_NotifyToWait(Handle* handle, NS_APPID appID) Result APT_NotifyToWait(Handle* handle, NS_APPID appID)
{ {
if(!handle)handle=&aptuHandle; if(!handle)handle=&aptuHandle;