diff --git a/libctru/include/3ds/services/apt.h b/libctru/include/3ds/services/apt.h index 04de77a..74fda48 100644 --- a/libctru/include/3ds/services/apt.h +++ b/libctru/include/3ds/services/apt.h @@ -97,6 +97,7 @@ Result APT_Finalize(NS_APPID appId); Result APT_HardwareResetAsync(void); Result APT_Enable(u32 a); Result APT_GetAppletManInfo(u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu_appid, NS_APPID *active_appid); +Result APT_GetAppletInfo(NS_APPID appID, u64* pProgramID, u8* pMediaType, u8* pRegistered, u8* pLoadState, u32* pAttributes); Result APT_GetAppletProgramInfo(u32 id, u32 flags, u16 *titleversion); Result APT_PrepareToJumpToHomeMenu(void); Result APT_JumpToHomeMenu(u32 a, u32 b, u32 c); diff --git a/libctru/include/3ds/services/cfgu.h b/libctru/include/3ds/services/cfgu.h index aaafd26..e3ca2ef 100644 --- a/libctru/include/3ds/services/cfgu.h +++ b/libctru/include/3ds/services/cfgu.h @@ -1,5 +1,32 @@ #pragma once +typedef enum +{ + CFG_REGION_JPN = 0, + CFG_REGION_USA = 1, + CFG_REGION_EUR = 2, + CFG_REGION_AUS = 3, + CFG_REGION_CHN = 4, + CFG_REGION_KOR = 5, + CFG_REGION_TWN = 6, +} CFG_Region; + +typedef enum +{ + CFG_LANGUAGE_JP = 0, + CFG_LANGUAGE_EN = 1, + CFG_LANGUAGE_FR = 2, + CFG_LANGUAGE_DE = 3, + CFG_LANGUAGE_IT = 4, + CFG_LANGUAGE_ES = 5, + CFG_LANGUAGE_ZH = 6, + CFG_LANGUAGE_KO = 7, + CFG_LANGUAGE_NL = 8, + CFG_LANGUAGE_PT = 9, + CFG_LANGUAGE_RU = 10, + CFG_LANGUAGE_TW = 11, +} CFG_Langage; + Result initCfgu(void); Result exitCfgu(void); diff --git a/libctru/include/3ds/svc.h b/libctru/include/3ds/svc.h index defb25b..747a7e2 100644 --- a/libctru/include/3ds/svc.h +++ b/libctru/include/3ds/svc.h @@ -76,13 +76,16 @@ typedef struct { } PageInfo; typedef enum { - ARBITER_FREE = 0, - ARBITER_ACQUIRE = 1, - ARBITER_KERNEL2 = 2, - ARBITER_ACQUIRE_TIMEOUT = 3, - ARBITER_KERNEL4 = 4, + ARBITRATION_SIGNAL = 0, ///< Signal #value threads for wake-up. + ARBITRATION_WAIT_IF_LESS_THAN = 1, ///< If the memory at the address is strictly lower than #value, then wait for signal. + ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN = 2, ///< If the memory at the address is strictly lower than #value, then decrement it and wait for signal. + ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT = 3, ///< If the memory at the address is strictly lower than #value, then wait for signal or timeout. + ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN_TIMEOUT = 4, ///< If the memory at the address is strictly lower than #value, then decrement it and wait for signal or timeout. } ArbitrationType; +/// Special value to signal all the threads +#define ARBITRATION_SIGNAL_ALL (-1) + ///@} ///@name Multithreading @@ -302,8 +305,6 @@ Result svcGetDmaState(void* dmaState, Handle dma); Result svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr); Result svcQueryProcessMemory(MemInfo* info, PageInfo* out, Handle process, u32 addr); -Result svcCreateAddressArbiter(Handle *arbiter); -Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds); Result svcInvalidateProcessDataCache(Handle process, void* addr, u32 size); Result svcFlushProcessDataCache(Handle process, void const* addr, u32 size); @@ -436,6 +437,31 @@ Result svcClearEvent(Handle handle); Result svcWaitSynchronization(Handle handle, s64 nanoseconds); Result svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds); +/** + * @brief Creates an address arbiter + * @sa svcArbitrateAddress + */ +Result svcCreateAddressArbiter(Handle *arbiter); + +/** + * @brief Arbitrate an address, can be used for synchronization + * @param arbiter Handle of the arbiter + * @param addr A pointer to a s32 value. + * @param type Type of action to be performed by the arbiter + * @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison. + * + * This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr. + * + * @code + * s32 val=0; + * // Does *nothing* since val >= 0 + * svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN,0,0); + * // Thread will wait for a signal or wake up after 10000000 nanoseconds because val < 1. + * svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT,1,10000000ULL); + * @endcode + */ +Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds); + Result svcSendSyncRequest(Handle session); Result svcAcceptSession(Handle* session, Handle port); Result svcReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget); diff --git a/libctru/source/services/apt.c b/libctru/source/services/apt.c index e828211..e5260f8 100644 --- a/libctru/source/services/apt.c +++ b/libctru/source/services/apt.c @@ -792,6 +792,24 @@ Result APT_GetAppletManInfo(u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu return cmdbuf[1]; } +Result APT_GetAppletInfo(NS_APPID appID, u64* pProgramID, u8* pMediaType, u8* pRegistered, u8* pLoadState, u32* pAttributes) +{ + u32* cmdbuf=getThreadCommandBuffer(); + cmdbuf[0]=0x00060040; //request header code + cmdbuf[1]=appID; + + Result ret=0; + if((ret=svcSendSyncRequest(aptuHandle)))return ret; + + if(pProgramID)*pProgramID=(u64)cmdbuf[2]|((u64)cmdbuf[3]<<32); + if(pMediaType)*pMediaType=cmdbuf[4]; + if(pRegistered)*pRegistered=cmdbuf[5]; + if(pLoadState)*pLoadState=cmdbuf[6]; + if(pAttributes)*pAttributes=cmdbuf[7]; + + return cmdbuf[1]; +} + Result APT_GetAppletProgramInfo(u32 id, u32 flags, u16 *titleversion) { u32* cmdbuf=getThreadCommandBuffer();