Refactor DSP<->APT interaction, see details:
- DSP wrapper is now in charge of handling sleep/awake/cancel events - Added DSP hook mechanism (similar to APT hook) - The DSP component now gets automatically unloaded/reloaded as needed - NDSP now uses DSP hook instead of APT hook to manage lifetime - Moved sleep/wakeup component management logic into NDSP - APT now calls into DSP wrapper in order to arbitrate access to the DSP - Launching libapplets no longer relinquishes DSP rights - this means music can now be played in the background during libapplet activity
This commit is contained in:
parent
b559d93eda
commit
b93e7f19bf
@ -13,12 +13,23 @@ typedef enum
|
|||||||
DSP_INTERRUPT_PIPE = 2 ///< Pipe interrupt.
|
DSP_INTERRUPT_PIPE = 2 ///< Pipe interrupt.
|
||||||
} DSP_InterruptType;
|
} DSP_InterruptType;
|
||||||
|
|
||||||
/// DSP pipe directions.
|
/// DSP hook types.
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
DSP_PIPE_INPUT = 0, ///< DSP to ARM
|
DSPHOOK_ONSLEEP = 0, ///< DSP is going to sleep.
|
||||||
DSP_PIPE_OUTPUT = 1 ///< ARM to DSP
|
DSPHOOK_ONWAKEUP = 1, ///< DSP is waking up.
|
||||||
} DSP_PipeDirection;
|
DSPHOOK_ONCANCEL = 2, ///< DSP was sleeping and the app was cancelled.
|
||||||
|
} DSP_HookType;
|
||||||
|
|
||||||
|
/// DSP hook function.
|
||||||
|
typedef void (* dspHookFn)(DSP_HookType hook);
|
||||||
|
|
||||||
|
/// DSP hook cookie.
|
||||||
|
typedef struct tag_dspHookCookie
|
||||||
|
{
|
||||||
|
struct tag_dspHookCookie* next; ///< Next cookie.
|
||||||
|
dspHookFn callback; ///< Hook callback.
|
||||||
|
} dspHookCookie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the dsp service.
|
* @brief Initializes the dsp service.
|
||||||
@ -35,6 +46,22 @@ Result dspInit(void);
|
|||||||
*/
|
*/
|
||||||
void dspExit(void);
|
void dspExit(void);
|
||||||
|
|
||||||
|
/// Returns true if a component is loaded, false otherwise.
|
||||||
|
bool dspIsComponentLoaded(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up a DSP status hook.
|
||||||
|
* @param cookie Hook cookie to use.
|
||||||
|
* @param callback Function to call when DSP's status changes.
|
||||||
|
*/
|
||||||
|
void dspHook(dspHookCookie* cookie, dspHookFn callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a DSP status hook.
|
||||||
|
* @param cookie Hook cookie to remove.
|
||||||
|
*/
|
||||||
|
void dspUnhook(dspHookCookie* cookie);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if a headphone is inserted.
|
* @brief Checks if a headphone is inserted.
|
||||||
* @param is_inserted Pointer to output the insertion status to.
|
* @param is_inserted Pointer to output the insertion status to.
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
u16 ndspFrameId, ndspBufferCurId, ndspBufferId;
|
u16 ndspFrameId, ndspBufferCurId, ndspBufferId;
|
||||||
void* ndspVars[16][2];
|
void* ndspVars[16][2];
|
||||||
|
|
||||||
static bool bComponentLoaded = false, bDspReady = false, bSleeping = false, bActuallySleeping = false, bNeedsSync = false;
|
static bool bDspReady = false, bSleeping = false, bActuallySleeping = false, bNeedsSync = false;
|
||||||
static u32 droppedFrames, frameCount;
|
static u32 droppedFrames, frameCount;
|
||||||
|
|
||||||
static const void* componentBin;
|
static const void* componentBin;
|
||||||
@ -17,7 +17,7 @@ static u32 componentSize;
|
|||||||
static u16 componentProgMask, componentDataMask;
|
static u16 componentProgMask, componentDataMask;
|
||||||
static bool componentFree;
|
static bool componentFree;
|
||||||
|
|
||||||
static aptHookCookie aptCookie;
|
static dspHookCookie ndspHookCookie;
|
||||||
|
|
||||||
static Handle irqEvent, dspSem;
|
static Handle irqEvent, dspSem;
|
||||||
static LightEvent sleepEvent;
|
static LightEvent sleepEvent;
|
||||||
@ -28,12 +28,6 @@ static u8 dspVar5Backup[0x1080];
|
|||||||
static volatile bool ndspThreadRun;
|
static volatile bool ndspThreadRun;
|
||||||
static Thread ndspThread;
|
static Thread ndspThread;
|
||||||
|
|
||||||
static Result ndspLoadComponent(void)
|
|
||||||
{
|
|
||||||
if (!componentBin) return 1;
|
|
||||||
return DSP_LoadComponent(componentBin, componentSize, componentProgMask, componentDataMask, &bComponentLoaded);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ndspWaitForIrq(void)
|
static inline void ndspWaitForIrq(void)
|
||||||
{
|
{
|
||||||
LightLock_Lock(&ndspMutex);
|
LightLock_Lock(&ndspMutex);
|
||||||
@ -209,9 +203,6 @@ static Result ndspInitialize(bool resume)
|
|||||||
{
|
{
|
||||||
Result rc;
|
Result rc;
|
||||||
|
|
||||||
rc = ndspLoadComponent();
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
rc = svcCreateEvent(&irqEvent, RESET_STICKY);
|
rc = svcCreateEvent(&irqEvent, RESET_STICKY);
|
||||||
if (R_FAILED(rc)) goto _fail1;
|
if (R_FAILED(rc)) goto _fail1;
|
||||||
|
|
||||||
@ -266,7 +257,6 @@ _fail3:
|
|||||||
_fail2:
|
_fail2:
|
||||||
svcCloseHandle(irqEvent);
|
svcCloseHandle(irqEvent);
|
||||||
_fail1:
|
_fail1:
|
||||||
DSP_UnloadComponent();
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,20 +282,20 @@ static void ndspFinalize(bool suspend)
|
|||||||
DSP_RegisterInterruptEvents(0, 2, 2);
|
DSP_RegisterInterruptEvents(0, 2, 2);
|
||||||
svcCloseHandle(irqEvent);
|
svcCloseHandle(irqEvent);
|
||||||
svcCloseHandle(dspSem);
|
svcCloseHandle(dspSem);
|
||||||
DSP_UnloadComponent();
|
|
||||||
bComponentLoaded = false;
|
|
||||||
bDspReady = false;
|
bDspReady = false;
|
||||||
LightLock_Unlock(&ndspMutex);
|
LightLock_Unlock(&ndspMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ndspAptHook(APT_HookType hook, void* param)
|
static void ndspHookCallback(DSP_HookType hook)
|
||||||
{
|
{
|
||||||
switch (hook)
|
switch (hook)
|
||||||
{
|
{
|
||||||
case APTHOOK_ONRESTORE:
|
case DSPHOOK_ONWAKEUP:
|
||||||
case APTHOOK_ONWAKEUP:
|
|
||||||
bSleeping = false;
|
bSleeping = false;
|
||||||
ndspInitialize(true);
|
Result res = ndspInitialize(true);
|
||||||
|
if (R_FAILED(res))
|
||||||
|
svcBreak(USERBREAK_PANIC); // Shouldn't happen.
|
||||||
if (bActuallySleeping)
|
if (bActuallySleeping)
|
||||||
{
|
{
|
||||||
bActuallySleeping = false;
|
bActuallySleeping = false;
|
||||||
@ -313,8 +303,7 @@ static void ndspAptHook(APT_HookType hook, void* param)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APTHOOK_ONSUSPEND:
|
case DSPHOOK_ONSLEEP:
|
||||||
case APTHOOK_ONSLEEP:
|
|
||||||
bSleeping = true;
|
bSleeping = true;
|
||||||
ndspFinalize(true);
|
ndspFinalize(true);
|
||||||
break;
|
break;
|
||||||
@ -481,6 +470,9 @@ Result ndspInit(void)
|
|||||||
rc = dspInit();
|
rc = dspInit();
|
||||||
if (R_FAILED(rc)) goto _fail1;
|
if (R_FAILED(rc)) goto _fail1;
|
||||||
|
|
||||||
|
rc = DSP_LoadComponent(componentBin, componentSize, componentProgMask, componentDataMask, NULL);
|
||||||
|
if (R_FAILED(rc)) goto _fail2;
|
||||||
|
|
||||||
rc = ndspInitialize(false);
|
rc = ndspInitialize(false);
|
||||||
if (R_FAILED(rc)) goto _fail2;
|
if (R_FAILED(rc)) goto _fail2;
|
||||||
|
|
||||||
@ -489,7 +481,7 @@ Result ndspInit(void)
|
|||||||
ndspThread = threadCreate(ndspThreadMain, 0x0, NDSP_THREAD_STACK_SIZE, 0x18, -2, true);
|
ndspThread = threadCreate(ndspThreadMain, 0x0, NDSP_THREAD_STACK_SIZE, 0x18, -2, true);
|
||||||
if (!ndspThread) goto _fail3;
|
if (!ndspThread) goto _fail3;
|
||||||
|
|
||||||
aptHook(&aptCookie, ndspAptHook, NULL);
|
dspHook(&ndspHookCookie, ndspHookCallback);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
_fail3:
|
_fail3:
|
||||||
@ -518,7 +510,7 @@ void ndspExit(void)
|
|||||||
LightEvent_Signal(&sleepEvent);
|
LightEvent_Signal(&sleepEvent);
|
||||||
}
|
}
|
||||||
threadJoin(ndspThread, U64_MAX);
|
threadJoin(ndspThread, U64_MAX);
|
||||||
aptUnhook(&aptCookie);
|
dspUnhook(&ndspHookCookie);
|
||||||
if (!bSleeping)
|
if (!bSleeping)
|
||||||
ndspFinalize(false);
|
ndspFinalize(false);
|
||||||
bSleeping = false;
|
bSleeping = false;
|
||||||
|
@ -55,6 +55,7 @@ enum
|
|||||||
FLAG_CANCELLED = BIT(10),
|
FLAG_CANCELLED = BIT(10),
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
FLAG_DSPWAKEUP = BIT(29),
|
||||||
FLAG_CHAINLOAD = BIT(30),
|
FLAG_CHAINLOAD = BIT(30),
|
||||||
FLAG_SPURIOUS = BIT(31),
|
FLAG_SPURIOUS = BIT(31),
|
||||||
};
|
};
|
||||||
@ -87,6 +88,11 @@ __attribute__((weak)) void _aptDebug(int a, int b) { }
|
|||||||
#define _aptDebug(a,b) ((void)0)
|
#define _aptDebug(a,b) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// APT<->DSP interaction functions (stubbed when not using DSP)
|
||||||
|
__attribute__((weak)) bool aptDspSleep(void) { return false; }
|
||||||
|
__attribute__((weak)) void aptDspWakeup(void) { }
|
||||||
|
__attribute__((weak)) void aptDspCancel(void) { }
|
||||||
|
|
||||||
static void aptCallHook(APT_HookType hookType)
|
static void aptCallHook(APT_HookType hookType)
|
||||||
{
|
{
|
||||||
aptHookCookie* c;
|
aptHookCookie* c;
|
||||||
@ -448,16 +454,34 @@ void aptEventHandler(void *arg)
|
|||||||
// - APTCMD_DSP_SLEEP (*NOT* cancelled afterwards)
|
// - APTCMD_DSP_SLEEP (*NOT* cancelled afterwards)
|
||||||
// - APTCMD_DSP_WAKEUP (*NOT* cancelled afterwards)
|
// - APTCMD_DSP_WAKEUP (*NOT* cancelled afterwards)
|
||||||
|
|
||||||
// We will instead only handle spurious APTCMD_WAKEUP_PAUSE parameters
|
// We will handle the following:
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case APTCMD_DSP_SLEEP:
|
||||||
|
// Handle DSP sleep requests
|
||||||
|
aptDspSleep();
|
||||||
|
break;
|
||||||
|
case APTCMD_DSP_WAKEUP:
|
||||||
|
// Handle DSP wakeup requests
|
||||||
|
aptFlags &= ~FLAG_DSPWAKEUP;
|
||||||
|
aptDspWakeup();
|
||||||
|
break;
|
||||||
|
case APTCMD_WAKEUP_PAUSE:
|
||||||
|
// Handle spurious APTCMD_WAKEUP_PAUSE parameters
|
||||||
// (see aptInit for more details on the hax 2.x spurious wakeup problem)
|
// (see aptInit for more details on the hax 2.x spurious wakeup problem)
|
||||||
if (cmd == APTCMD_WAKEUP_PAUSE && (aptFlags & FLAG_SPURIOUS))
|
if (aptFlags & FLAG_SPURIOUS)
|
||||||
{
|
{
|
||||||
APT_CancelParameter(APPID_NONE, envGetAptAppId(), NULL);
|
APT_CancelParameter(APPID_NONE, envGetAptAppId(), NULL);
|
||||||
aptFlags &= ~FLAG_SPURIOUS;
|
aptFlags &= ~FLAG_SPURIOUS;
|
||||||
continue;
|
break;
|
||||||
|
}
|
||||||
|
// Fallthrough otherwise
|
||||||
|
default:
|
||||||
|
// Others not accounted for -> pass it on to aptReceiveParameter
|
||||||
|
LightEvent_Signal(&aptReceiveEvent);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LightEvent_Signal(&aptReceiveEvent);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,6 +529,8 @@ void aptEventHandler(void *arg)
|
|||||||
break;
|
break;
|
||||||
case APTSIGNAL_SLEEP_ENTER:
|
case APTSIGNAL_SLEEP_ENTER:
|
||||||
_aptDebug(10, aptFlags);
|
_aptDebug(10, aptFlags);
|
||||||
|
if (aptDspSleep())
|
||||||
|
aptFlags |= FLAG_DSPWAKEUP;
|
||||||
if (aptIsActive())
|
if (aptIsActive())
|
||||||
aptFlags |= FLAG_SHOULDSLEEP;
|
aptFlags |= FLAG_SHOULDSLEEP;
|
||||||
else
|
else
|
||||||
@ -512,6 +538,11 @@ void aptEventHandler(void *arg)
|
|||||||
APT_ReplySleepNotificationComplete(envGetAptAppId());
|
APT_ReplySleepNotificationComplete(envGetAptAppId());
|
||||||
break;
|
break;
|
||||||
case APTSIGNAL_SLEEP_WAKEUP:
|
case APTSIGNAL_SLEEP_WAKEUP:
|
||||||
|
if (aptFlags & FLAG_DSPWAKEUP)
|
||||||
|
{
|
||||||
|
aptFlags &= ~FLAG_DSPWAKEUP;
|
||||||
|
aptDspWakeup();
|
||||||
|
}
|
||||||
if (!aptIsActive())
|
if (!aptIsActive())
|
||||||
break;
|
break;
|
||||||
if (aptFlags & FLAG_SLEEPING)
|
if (aptFlags & FLAG_SLEEPING)
|
||||||
@ -589,8 +620,16 @@ APT_Command aptWaitForWakeUp(APT_Transition transition)
|
|||||||
aptCallHook(APTHOOK_ONRESTORE);
|
aptCallHook(APTHOOK_ONRESTORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == APTCMD_WAKEUP_CANCEL)
|
if (cmd == APTCMD_WAKEUP_CANCEL || cmd == APTCMD_WAKEUP_CANCELALL)
|
||||||
|
{
|
||||||
|
aptDspCancel();
|
||||||
|
if (cmd == APTCMD_WAKEUP_CANCEL) // for some reason, not for CANCELALL... is this a bug in official sw?
|
||||||
aptFlags |= FLAG_CANCELLED;
|
aptFlags |= FLAG_CANCELLED;
|
||||||
|
} else if (cmd != APTCMD_WAKEUP_LAUNCHAPP)
|
||||||
|
{
|
||||||
|
aptFlags &= ~FLAG_DSPWAKEUP;
|
||||||
|
aptDspWakeup();
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd != APTCMD_WAKEUP_JUMPTOHOME)
|
if (cmd != APTCMD_WAKEUP_JUMPTOHOME)
|
||||||
{
|
{
|
||||||
@ -732,6 +771,7 @@ void aptJumpToHomeMenu(void)
|
|||||||
|
|
||||||
GSPGPU_SaveVramSysArea();
|
GSPGPU_SaveVramSysArea();
|
||||||
aptScreenTransfer(aptGetMenuAppID(), true);
|
aptScreenTransfer(aptGetMenuAppID(), true);
|
||||||
|
aptDspSleep();
|
||||||
GSPGPU_ReleaseRight();
|
GSPGPU_ReleaseRight();
|
||||||
|
|
||||||
APT_JumpToHomeMenu(NULL, 0, 0);
|
APT_JumpToHomeMenu(NULL, 0, 0);
|
||||||
|
@ -9,6 +9,20 @@
|
|||||||
static Handle dspHandle;
|
static Handle dspHandle;
|
||||||
static int dspRefCount;
|
static int dspRefCount;
|
||||||
|
|
||||||
|
static dspHookCookie dspFirstHook;
|
||||||
|
static bool dspComponentLoaded, dspSleeping;
|
||||||
|
|
||||||
|
static const void* dspSavedCompBin;
|
||||||
|
static u32 dspSavedCompSize;
|
||||||
|
static u16 dspSavedCompProgMask, dspSavedCompDataMask;
|
||||||
|
|
||||||
|
static void dspCallHook(DSP_HookType hookType)
|
||||||
|
{
|
||||||
|
dspHookCookie* c;
|
||||||
|
for (c = &dspFirstHook; c && c->callback; c = c->next)
|
||||||
|
c->callback(hookType);
|
||||||
|
}
|
||||||
|
|
||||||
Result dspInit(void)
|
Result dspInit(void)
|
||||||
{
|
{
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
@ -16,18 +30,91 @@ Result dspInit(void)
|
|||||||
if (AtomicPostIncrement(&dspRefCount)) return 0;
|
if (AtomicPostIncrement(&dspRefCount)) return 0;
|
||||||
|
|
||||||
ret = srvGetServiceHandle(&dspHandle, "dsp::DSP");
|
ret = srvGetServiceHandle(&dspHandle, "dsp::DSP");
|
||||||
if (R_SUCCEEDED(ret)) DSP_UnloadComponent();
|
if (R_FAILED(ret))
|
||||||
else AtomicDecrement(&dspRefCount);
|
{
|
||||||
|
AtomicDecrement(&dspRefCount);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force unload component (if exists)
|
||||||
|
dspComponentLoaded = true;
|
||||||
|
DSP_UnloadComponent();
|
||||||
|
|
||||||
|
dspSleeping = false;
|
||||||
|
dspSavedCompBin = NULL;
|
||||||
|
dspSavedCompSize = 0;
|
||||||
|
dspSavedCompProgMask = 0;
|
||||||
|
dspSavedCompDataMask = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void dspExit(void)
|
void dspExit(void)
|
||||||
{
|
{
|
||||||
if (AtomicDecrement(&dspRefCount)) return;
|
if (AtomicDecrement(&dspRefCount)) return;
|
||||||
|
DSP_UnloadComponent();
|
||||||
svcCloseHandle(dspHandle);
|
svcCloseHandle(dspHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dspIsComponentLoaded(void)
|
||||||
|
{
|
||||||
|
return dspComponentLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dspHook(dspHookCookie* cookie, dspHookFn callback)
|
||||||
|
{
|
||||||
|
if (!callback) return;
|
||||||
|
|
||||||
|
dspHookCookie* hook = &dspFirstHook;
|
||||||
|
*cookie = *hook; // Structure copy.
|
||||||
|
hook->next = cookie;
|
||||||
|
hook->callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dspUnhook(dspHookCookie* cookie)
|
||||||
|
{
|
||||||
|
dspHookCookie* hook;
|
||||||
|
for (hook = &dspFirstHook; hook; hook = hook->next)
|
||||||
|
{
|
||||||
|
if (hook->next == cookie)
|
||||||
|
{
|
||||||
|
*hook = *cookie; // Structure copy.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aptDspSleep(void)
|
||||||
|
{
|
||||||
|
if (!dspComponentLoaded || dspSleeping)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dspCallHook(DSPHOOK_ONSLEEP);
|
||||||
|
DSP_UnloadComponent();
|
||||||
|
dspSleeping = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aptDspWakeup(void)
|
||||||
|
{
|
||||||
|
if (!dspSleeping)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Result ret = DSP_LoadComponent(dspSavedCompBin, dspSavedCompSize, dspSavedCompProgMask, dspSavedCompDataMask, NULL);
|
||||||
|
if (R_FAILED(ret))
|
||||||
|
svcBreak(USERBREAK_PANIC); // Shouldn't happen.
|
||||||
|
|
||||||
|
dspCallHook(DSPHOOK_ONWAKEUP);
|
||||||
|
dspSleeping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aptDspCancel(void)
|
||||||
|
{
|
||||||
|
if (!dspSleeping)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dspCallHook(DSPHOOK_ONCANCEL);
|
||||||
|
}
|
||||||
|
|
||||||
Result DSP_GetHeadphoneStatus(bool* is_inserted)
|
Result DSP_GetHeadphoneStatus(bool* is_inserted)
|
||||||
{
|
{
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
@ -96,6 +183,17 @@ Result DSP_GetSemaphoreHandle(Handle* semaphore)
|
|||||||
|
|
||||||
Result DSP_LoadComponent(const void* component, u32 size, u16 prog_mask, u16 data_mask, bool* is_loaded)
|
Result DSP_LoadComponent(const void* component, u32 size, u16 prog_mask, u16 data_mask, bool* is_loaded)
|
||||||
{
|
{
|
||||||
|
if (dspComponentLoaded)
|
||||||
|
{
|
||||||
|
if (is_loaded) *is_loaded = dspComponentLoaded;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dspSavedCompBin = component;
|
||||||
|
dspSavedCompSize = size;
|
||||||
|
dspSavedCompProgMask = prog_mask;
|
||||||
|
dspSavedCompDataMask = data_mask;
|
||||||
|
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
u32* cmdbuf = getThreadCommandBuffer();
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x11,3,2);
|
cmdbuf[0] = IPC_MakeHeader(0x11,3,2);
|
||||||
@ -105,12 +203,18 @@ Result DSP_LoadComponent(const void* component, u32 size, u16 prog_mask, u16 dat
|
|||||||
cmdbuf[4] = IPC_Desc_Buffer(size,IPC_BUFFER_R);
|
cmdbuf[4] = IPC_Desc_Buffer(size,IPC_BUFFER_R);
|
||||||
cmdbuf[5] = (u32) component;
|
cmdbuf[5] = (u32) component;
|
||||||
if (R_FAILED(ret = svcSendSyncRequest(dspHandle))) return ret;
|
if (R_FAILED(ret = svcSendSyncRequest(dspHandle))) return ret;
|
||||||
*is_loaded = cmdbuf[2] & 0xFF;
|
dspComponentLoaded = cmdbuf[2] & 0xFF;
|
||||||
|
if (is_loaded) *is_loaded = dspComponentLoaded;
|
||||||
return cmdbuf[1];
|
return cmdbuf[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DSP_UnloadComponent(void)
|
Result DSP_UnloadComponent(void)
|
||||||
{
|
{
|
||||||
|
if (!dspComponentLoaded)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dspComponentLoaded = false;
|
||||||
|
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
u32* cmdbuf = getThreadCommandBuffer();
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x12,0,0);
|
cmdbuf[0] = IPC_MakeHeader(0x12,0,0);
|
||||||
|
Loading…
Reference in New Issue
Block a user