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
#define RUNFLAG_APTWORKAROUND (BIT(0))
#define RUNFLAG_APTREINIT (BIT(1))
typedef enum{
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_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_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_PrepareToJumpToHomeMenu(Handle* handle);
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_InquireNotification(Handle* handle, u32 appID, u8* signalType);
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_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 bool aptIsCrippled(void)
{
return (__system_runflags & RUNFLAG_APTWORKAROUND) != 0;
}
static bool aptIsReinit(void)
{
return (__system_runflags & RUNFLAG_APTREINIT) != 0;
}
static Result __apt_initservicehandle()
{
Result ret=0;
@ -162,7 +177,7 @@ void aptReturnToMenu()
NS_APPID menu_appid;
u32 tmp0 = 1, tmp1 = 0;
if(__system_runflags&RUNFLAG_APTWORKAROUND)
if(aptIsCrippled())
{
svcClearEvent(aptStatusEvent);
aptSetStatus(APP_EXITING);
@ -177,15 +192,15 @@ void aptReturnToMenu()
aptCloseSession();
}
// Set status to SUSPENDED.
svcClearEvent(aptStatusEvent);
aptSetStatus(APP_SUSPENDED);
// Prepare for return to menu
aptOpenSession();
APT_PrepareToJumpToHomeMenu(NULL);
aptCloseSession();
// Set status to SUSPENDED.
svcClearEvent(aptStatusEvent);
aptSetStatus(APP_SUSPENDED);
// Save Vram
GSPGPU_SaveVramSysArea(NULL);
@ -286,8 +301,9 @@ static void __handle_notification() {
aptOpenSession();
ret = APT_InquireNotification(NULL, currentAppId, &type);
aptCloseSession();
if(ret!=0) return;
if(ret!=0)return;
_aptDebug(1, type);
switch(type)
{
@ -350,6 +366,8 @@ static bool __handle_incoming_parameter() {
APT_ReceiveParameter(NULL, currentAppId, 0x1000, aptParameters, NULL, &type);
aptCloseSession();
_aptDebug(2, type);
switch(type)
{
case 0x1: // Application just started.
@ -366,10 +384,14 @@ static bool __handle_incoming_parameter() {
aptSetStatus(APP_APPLETCLOSED);
return true;
case 0xB: // Just returned from menu.
GSPGPU_AcquireRight(NULL, 0x0);
GSPGPU_RestoreVramSysArea(NULL);
aptAppletUtility_Exit_RetToApp(0);
aptSetStatus(APP_RUNNING);
if (aptStatusMutex)
{
GSPGPU_AcquireRight(NULL, 0x0);
GSPGPU_RestoreVramSysArea(NULL);
aptAppletUtility_Exit_RetToApp(0);
aptSetStatus(APP_RUNNING);
} else
aptAppStarted();
return true;
case 0xC: // Exiting application.
@ -387,9 +409,8 @@ void aptEventHandler(void *arg)
while(runThread)
{
s32 syncedID = 0;
svcWaitSynchronizationN(&syncedID, aptEvents, 2, 0, U64_MAX);
svcWaitSynchronizationN(&syncedID, aptEvents, 3, 0, U64_MAX);
svcClearEvent(aptEvents[syncedID]);
switch(syncedID)
{
// Event 0 means we got a signal from NS (home button, power button etc).
@ -400,7 +421,7 @@ void aptEventHandler(void *arg)
case 0x1:
runThread = __handle_incoming_parameter();
break;
// Event 2 means we should exit the thread (event will be added later).
// Event 2 means we should exit the thread.
case 0x2:
runThread = false;
break;
@ -418,6 +439,8 @@ Result aptInit(void)
if (aptInitialised) return ret;
aptStatusMutex = 0;
// Initialize APT stuff, escape load screen.
ret = __apt_initservicehandle();
if(ret!=0)return ret;
@ -429,7 +452,7 @@ Result aptInit(void)
svcCreateEvent(&aptStatusEvent, 0);
svcCreateEvent(&aptSleepSync, 0);
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))
if(!aptIsCrippled())
{
aptOpenSession();
if((ret=APT_Initialize(NULL, currentAppId, &aptEvents[0], &aptEvents[1])))return ret;
@ -439,6 +462,22 @@ Result aptInit(void)
if((ret=APT_Enable(NULL, 0x0)))return ret;
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();
if((ret=APT_NotifyToWait(NULL, currentAppId)))return ret;
aptCloseSession();
@ -458,7 +497,7 @@ void aptExit()
{
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.
if(aptGetStatusPower() == 1)
@ -468,17 +507,37 @@ void aptExit()
aptCloseSession();
}
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))
if(!aptIsCrippled())
{
aptOpenSession();
APT_PrepareToCloseApplication(NULL, 0x1);
aptCloseSession();
bool isReinit = aptIsReinit();
if (aptGetStatus() == APP_EXITING)
{
aptOpenSession();
APT_PrepareToCloseApplication(NULL, 0x1);
aptCloseSession();
aptOpenSession();
APT_CloseApplication(NULL, 0x0, 0x0, 0x0);
aptCloseSession();
aptOpenSession();
APT_CloseApplication(NULL, 0x0, 0x0, 0x0);
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(aptStatusMutex);
@ -492,7 +551,7 @@ bool aptMainLoop()
{
while(1)
{
//if(__system_runflags&RUNFLAG_APTWORKAROUND)__handle_notification();
//if(aptIsCrippled())__handle_notification();
switch(aptGetStatus())
{
@ -531,7 +590,7 @@ void aptAppStarted()
aptSetStatus(APP_RUNNING);
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))
if(!aptIsCrippled())
{
memset(buf1, 0, 4);
@ -642,6 +701,18 @@ Result APT_Initialize(Handle* handle, NS_APPID appId, Handle* eventHandle1, Hand
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)
{
if(!handle)handle=&aptuHandle;
@ -743,6 +814,35 @@ Result APT_JumpToHomeMenu(Handle* handle, u32 a, u32 b, u32 c)
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)
{
if(!handle)handle=&aptuHandle;