Merge branch 'master' of github.com:smealum/ctrulib

Conflicts:
	libctru/include/ctr/GSP.h
	libctru/source/GSP.c
This commit is contained in:
smea 2014-05-27 20:49:50 +02:00
commit 4beea43184
29 changed files with 1822 additions and 142 deletions

View File

@ -1,7 +1,7 @@
CC = arm-none-eabi-gcc CC = arm-none-eabi-gcc
LINK = arm-none-eabi-ld LINK = arm-none-eabi-ld
OBJCOPY = arm-none-eabi-objcopy OBJCOPY = arm-none-eabi-objcopy
CTRULIB = "../libctru" CTRULIB = ../libctru
CFLAGS += -Wall -std=c99 -march=armv6 -O3 -I"$(CTRULIB)/include" -I$(DEVKITPRO)/libnds/include CFLAGS += -Wall -std=c99 -march=armv6 -O3 -I"$(CTRULIB)/include" -I$(DEVKITPRO)/libnds/include
LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib" LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib"

View File

@ -1,4 +1,4 @@
.section ".text" .section ".init"
.arm .arm
.align 4 .align 4
.global _init .global _init

View File

@ -139,6 +139,14 @@ int main()
swapBuffers(); swapBuffers();
copyBuffer(); copyBuffer();
} }
else if(status == APP_SUSPENDING)
{
aptReturnToMenu();
}
else if(status == APP_SLEEPMODE)
{
aptWaitStatusEvent();
}
svc_sleepThread(16666666); svc_sleepThread(16666666);
} }

View File

@ -2,8 +2,8 @@ CC = arm-none-eabi-gcc
LINK = arm-none-eabi-gcc LINK = arm-none-eabi-gcc
AS = arm-none-eabi-as AS = arm-none-eabi-as
OBJCOPY = arm-none-eabi-objcopy OBJCOPY = arm-none-eabi-objcopy
CTRULIB = "../libctru" CTRULIB = ../libctru
AEMSTROPATH = "../../aemstro" AEMSTROPATH = ../../aemstro
CFLAGS += -Wall -std=c99 -march=armv6 -O3 -I"$(CTRULIB)/include" -I$(DEVKITPRO)/libnds/include CFLAGS += -Wall -std=c99 -march=armv6 -O3 -I"$(CTRULIB)/include" -I$(DEVKITPRO)/libnds/include
# LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(DEVKITARM)/lib/gcc/arm-none-eabi/4.7.1" -L"$(CTRULIB)/lib" # LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(DEVKITARM)/lib/gcc/arm-none-eabi/4.7.1" -L"$(CTRULIB)/lib"
# LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib" # LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib"

View File

@ -1,4 +1,4 @@
.section ".text" .section ".init"
.arm .arm
.align 4 .align 4
.global _init .global _init

View File

@ -11,7 +11,7 @@
#include <ctr/SHDR.h> #include <ctr/SHDR.h>
#include <ctr/svc.h> #include <ctr/svc.h>
#include "costable.h" #include "costable.h"
#include "test_vsh_bin.h" #include "test_shbin.h"
u8* gspHeap; u8* gspHeap;
u32* gxCmdBuf; u32* gxCmdBuf;
@ -101,7 +101,7 @@ int main()
GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize); GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize);
DVLB_s* shader=SHDR_ParseSHBIN((u32*)test_vsh_bin,test_vsh_bin_size); DVLB_s* shader=SHDR_ParseSHBIN((u32*)test_shbin,test_shbin_size);
APP_STATUS status; APP_STATUS status;
while((status=aptGetStatus())!=APP_EXITING) while((status=aptGetStatus())!=APP_EXITING)
@ -128,6 +128,14 @@ int main()
swapBuffers(); swapBuffers();
} }
else if(status == APP_SUSPENDING)
{
aptReturnToMenu();
}
else if(status == APP_SLEEPMODE)
{
aptWaitStatusEvent();
}
svc_sleepThread(16666666); svc_sleepThread(16666666);
} }

2
libctru/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build
lib

8
libctru/include/ctr/AC.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef AC_H
#define AC_H
Result ACU_GetWifiStatus(Handle servhandle, u32 *out);
Result ACU_WaitInternetConnection();
#endif

View File

@ -9,9 +9,13 @@ typedef enum{
}NS_APPID; // cf http://3dbrew.org/wiki/NS#AppIDs }NS_APPID; // cf http://3dbrew.org/wiki/NS#AppIDs
typedef enum{ typedef enum{
APP_NOTINITIALIZED,
APP_RUNNING, APP_RUNNING,
APP_SUSPENDED, APP_SUSPENDED,
APP_EXITING APP_EXITING,
APP_SUSPENDING,
APP_SLEEPMODE,
APP_PREPARE_SLEEPMODE
}APP_STATUS; }APP_STATUS;
extern Handle aptEvents[3]; extern Handle aptEvents[3];
@ -23,10 +27,16 @@ void aptCloseSession();
void aptSetupEventHandler(); void aptSetupEventHandler();
void aptSetStatus(APP_STATUS status); void aptSetStatus(APP_STATUS status);
APP_STATUS aptGetStatus(); APP_STATUS aptGetStatus();
u32 aptGetStatusPower();//This can be used when the status is APP_SUSPEND* to check how the return-to-menu was triggered: 0 = home-button, 1 = power-button.
void aptSetStatusPower(u32 status);
void aptReturnToMenu();//This should be called by the user application when aptGetStatus() returns APP_SUSPENDING, not calling this will result in return-to-menu being disabled with the status left at APP_SUSPENDING. This function will not return until the system returns to the application, or when the status was changed to APP_EXITING.
void aptWaitStatusEvent();
NS_APPID aptGetMenuAppID();
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_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_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_InquireNotification(Handle* handle, u32 appID, u8* signalType); Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType);
@ -34,7 +44,10 @@ Result APT_NotifyToWait(Handle* handle, NS_APPID appID);
Result APT_AppletUtility(Handle* handle, u32* out, u32 a, u32 size1, u8* buf1, u32 size2, u8* buf2); Result APT_AppletUtility(Handle* handle, u32* out, u32 a, u32 size1, u8* buf1, u32 size2, u8* buf2);
Result APT_GlanceParameter(Handle* handle, NS_APPID appID, u32 bufferSize, u32* buffer, u32* actualSize, u8* signalType); Result APT_GlanceParameter(Handle* handle, NS_APPID appID, u32 bufferSize, u32* buffer, u32* actualSize, u8* signalType);
Result APT_ReceiveParameter(Handle* handle, NS_APPID appID, u32 bufferSize, u32* buffer, u32* actualSize, u8* signalType); Result APT_ReceiveParameter(Handle* handle, NS_APPID appID, u32 bufferSize, u32* buffer, u32* actualSize, u8* signalType);
Result APT_SendParameter(Handle* handle, NS_APPID src_appID, NS_APPID dst_appID, u32 bufferSize, u32* buffer, Handle paramhandle, u8 signalType);
Result APT_SendCaptureBufferInfo(Handle* handle, u32 bufferSize, u32* buffer);
Result APT_ReplySleepQuery(Handle* handle, NS_APPID appID, u32 a); Result APT_ReplySleepQuery(Handle* handle, NS_APPID appID, u32 a);
Result APT_ReplySleepNotificationComplete(Handle* handle, NS_APPID appID);
Result APT_PrepareToCloseApplication(Handle* handle, u8 a); Result APT_PrepareToCloseApplication(Handle* handle, u8 a);
Result APT_CloseApplication(Handle* handle, u32 a, u32 b, u32 c); Result APT_CloseApplication(Handle* handle, u32 a, u32 b, u32 c);

View File

@ -0,0 +1,12 @@
#ifndef CFGNOR_H
#define CFGNOR_H
Result CFGNOR_Initialize(u8 value);
Result CFGNOR_Shutdown();
Result CFGNOR_ReadData(u32 offset, u32 *buf, u32 size);
Result CFGNOR_WriteData(u32 offset, u32 *buf, u32 size);
Result CFGNOR_DumpFlash(u32 *buf, u32 size);
Result CFGNOR_WriteFlash(u32 *buf, u32 size);
#endif

View File

@ -0,0 +1,19 @@
#ifndef CSND_H
#define CSND_H
#define CSND_SHAREDMEM_DEFAULT 0x10004000
Result CSND_initialize(u32* sharedMem);
Result CSND_shutdown();
Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1);
void CSND_setchannel_playbackstate(u32 channel, u32 value);
void CSND_sharedmemtype0_cmd0(u32 channel, u32 value);
void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams);
Result CSND_sharedmemtype0_cmdupdatestate(int waitdone);
Result CSND_getchannelstate(u32 entryindex, u32 *out);
Result CSND_getchannelstate_isplaying(u32 entryindex, u8 *status);
#endif

View File

@ -47,6 +47,7 @@ Result FSFILE_Close(Handle handle);
Result FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, u32 *buffer, u32 size); Result FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, u32 *buffer, u32 size);
Result FSFILE_Write(Handle handle, u32 *bytesWritten, u64 offset, u32 *buffer, u32 size, u32 flushFlags); Result FSFILE_Write(Handle handle, u32 *bytesWritten, u64 offset, u32 *buffer, u32 size, u32 flushFlags);
Result FSFILE_GetSize(Handle handle, u64 *size); Result FSFILE_GetSize(Handle handle, u64 *size);
Result FSFILE_SetSize(Handle handle, u64 size);
Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entrycount, u16 *buffer); Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entrycount, u16 *buffer);
Result FSDIR_Close(Handle handle); Result FSDIR_Close(Handle handle);

View File

@ -3,12 +3,40 @@
#define GSP_REBASE_REG(r) ((r)-0x1EB00000) #define GSP_REBASE_REG(r) ((r)-0x1EB00000)
typedef struct
{
u32 active_framebuf;//"0=first, 1=second"
u32 *framebuf0_vaddr;//"Framebuffer virtual address, for the main screen this is the 3D left framebuffer"
u32 *framebuf1_vaddr;//"For the main screen: 3D right framebuffer address"
u32 framebuf_widthbytesize;//"Value for 0x1EF00X90, controls framebuffer width"
u32 format;//"Framebuffer format, this u16 is written to the low u16 for LCD register 0x1EF00X70."
u32 framebuf_dispselect;//"Value for 0x1EF00X78, controls which framebuffer is displayed"
u32 unk;//"?"
} GSP_FramebufferInfo;
typedef struct//See this for GSP_CaptureInfoEntry and GSP_CaptureInfo: http://3dbrew.org/wiki/GSPGPU:ImportDisplayCaptureInfo
{
u32 *framebuf0_vaddr;
u32 *framebuf1_vaddr;
u32 format;
u32 framebuf_widthbytesize;
} GSP_CaptureInfoEntry;
typedef struct
{
GSP_CaptureInfoEntry screencapture[2];
} GSP_CaptureInfo;
Result gspInit(); Result gspInit();
void gspExit(); void gspExit();
Result GSPGPU_AcquireRight(Handle *handle, u8 flags); Result GSPGPU_AcquireRight(Handle *handle, u8 flags);
Result GSPGPU_ReleaseRight(Handle *handle); Result GSPGPU_ReleaseRight(Handle *handle);
Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *captureinfo);
Result GSPGPU_SaveVramSysArea(Handle* handle);
Result GSPGPU_RestoreVramSysArea(Handle* handle);
Result GSPGPU_SetLcdForceBlack(Handle *handle, u8 flags); Result GSPGPU_SetLcdForceBlack(Handle *handle, u8 flags);
Result GSPGPU_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *framebufinfo);
Result GSPGPU_FlushDataCache(Handle *handle, u8* adr, u32 size); Result GSPGPU_FlushDataCache(Handle *handle, u8* adr, u32 size);
Result GSPGPU_InvalidateDataCache(Handle* handle, u8* adr, u32 size); Result GSPGPU_InvalidateDataCache(Handle* handle, u8* adr, u32 size);
Result GSPGPU_WriteHWRegs(Handle *handle, u32 regAddr, u32* data, u8 size); Result GSPGPU_WriteHWRegs(Handle *handle, u32 regAddr, u32* data, u8 size);

15
libctru/include/ctr/IR.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef IR_H
#define IR_H
Result IRU_Initialize(u32 *sharedmem_addr, u32 sharedmem_size);//The permissions for the specified memory is set to RO. This memory must be already mapped.
Result IRU_Shutdown();
Handle IRU_GetServHandle();
Result IRU_SendData(u8 *buf, u32 size, u32 wait);
Result IRU_RecvData(u8 *buf, u32 size, u8 flag, u32 *transfercount, u32 wait);
Result IRU_SetBitRate(u8 value);
Result IRU_GetBitRate(u8 *out);
Result IRU_SetIRLEDState(u32 value);
Result IRU_GetIRLEDRecvState(u32 *out);
#endif

View File

@ -1,7 +1,7 @@
#ifndef SOC_H #ifndef SOC_H
#define SOC_H #define SOC_H
Result SOC_Initialize(u32 *context_addr, u32 context_size); Result SOC_Initialize(u32 *context_addr, u32 context_size);//Example context_size: 0x48000. The specified context buffer can no longer be accessed by the process which called this function, since the userland permissions for this block are set to no-access.
Result SOC_Shutdown(); Result SOC_Shutdown();
int SOC_GetErrno(); int SOC_GetErrno();

View File

@ -24,6 +24,7 @@ typedef enum{
Result svc_createMutex(Handle* mutex, bool initialLocked); Result svc_createMutex(Handle* mutex, bool initialLocked);
Result svc_releaseMutex(Handle handle); Result svc_releaseMutex(Handle handle);
Result svc_createEvent(Handle* event, u8 resettype); Result svc_createEvent(Handle* event, u8 resettype);
Result svc_signalEvent(Handle handle);
Result svc_clearEvent(Handle handle); Result svc_clearEvent(Handle handle);
Result svc_createMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 mypermission, u32 otherpermission); Result svc_createMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 mypermission, u32 otherpermission);
Result svc_mapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission); Result svc_mapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission);
@ -31,8 +32,10 @@ typedef enum{
Result svc_waitSynchronization1(Handle handle, s64 nanoseconds); Result svc_waitSynchronization1(Handle handle, s64 nanoseconds);
Result svc_waitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 nanoseconds); Result svc_waitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 nanoseconds);
Result svc_closeHandle(Handle handle); Result svc_closeHandle(Handle handle);
u64 svc_getSystemTick();
Result svc_getSystemInfo(s64* out, u32 type, s32 param); Result svc_getSystemInfo(s64* out, u32 type, s32 param);
Result svc_connectToPort(volatile Handle* out, const char* portName); Result svc_connectToPort(volatile Handle* out, const char* portName);
Result svc_sendSyncRequest(Handle session); Result svc_sendSyncRequest(Handle session);
Result svc_getProcessId(u32 *out, Handle handle);
#endif #endif

View File

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#define U64_MAX (0xFFFFFFFFFFFFFFFF) #define U64_MAX UINT64_MAX
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
@ -26,8 +26,6 @@
typedef volatile s32 vs32; typedef volatile s32 vs32;
typedef volatile s64 vs64; typedef volatile s64 vs64;
typedef u16 wchar;
typedef u32 Handle; typedef u32 Handle;
typedef s32 Result; typedef s32 Result;
typedef void (*ThreadFunc)(u32); typedef void (*ThreadFunc)(u32);

87
libctru/source/AC.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctr/types.h>
#include <ctr/AC.h>
#include <ctr/svc.h>
#include <ctr/srv.h>
Result ACU_cmd1(Handle servhandle, u32 *ptr)//Unknown what this cmd does at the time of writing. (ptr=0x200-byte outbuf)
{
u32 tmp0, tmp1;
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
tmp0 = cmdbuf[0x100>>2];
tmp1 = cmdbuf[0x104>>2];
cmdbuf[0] = 0x00010000;
cmdbuf[0x100>>2] = 0x00800002;
cmdbuf[0x104>>2] = (u32)ptr;
if((ret = svc_sendSyncRequest(servhandle))!=0)return ret;
cmdbuf[0x100>>2] = tmp0;
cmdbuf[0x104>>2] = tmp1;
return (Result)cmdbuf[1];
}
Result ACU_cmd26(Handle servhandle, u32 *ptr, u8 val)//Unknown what this cmd does at the time of writing. (ptr=0x200-byte inbuf/outbuf)
{
u32 tmp0, tmp1;
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
tmp0 = cmdbuf[0x100>>2];
tmp1 = cmdbuf[0x104>>2];
cmdbuf[0] = 0x00260042;
cmdbuf[1] = (u32)val;
cmdbuf[0x100>>2] = 0x00800002;
cmdbuf[0x104>>2] = (u32)ptr;
cmdbuf[2] = 0x00800002;
cmdbuf[3] = (u32)ptr;
if((ret = svc_sendSyncRequest(servhandle))!=0)return ret;
cmdbuf[0x100>>2] = tmp0;
cmdbuf[0x104>>2] = tmp1;
return (Result)cmdbuf[1];
}
Result ACU_GetWifiStatus(Handle servhandle, u32 *out)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000D0000;
if((ret = svc_sendSyncRequest(servhandle))!=0)return ret;
*out = cmdbuf[2];
return (Result)cmdbuf[1];
}
Result ACU_WaitInternetConnection()
{
Handle servhandle = 0;
Result ret=0;
u32 outval=0;
if((ret = srv_getServiceHandle(NULL, &servhandle, "ac:u"))!=0)return ret;
while(1)
{
ret = ACU_GetWifiStatus(servhandle, &outval);
if(ret==0 && outval==1)break;
}
svc_closeHandle(servhandle);
return ret;
}

View File

@ -19,13 +19,166 @@ Handle aptEventHandlerThread;
u64 aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]; //u64 so that it's 8-byte aligned u64 aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]; //u64 so that it's 8-byte aligned
Handle aptStatusMutex; Handle aptStatusMutex;
u32 aptStatus; Handle aptStatusEvent = 0;
APP_STATUS aptStatus = APP_NOTINITIALIZED;
APP_STATUS aptStatus_beforesleepmode = APP_NOTINITIALIZED;
u32 aptStatusPower = 0;
u32 aptParameters[0x1000/4]; //TEMP u32 aptParameters[0x1000/4]; //TEMP
void aptInitCaptureInfo(u32 *ns_capinfo)
{
u32 tmp=0;
u32 main_pixsz, sub_pixsz;
GSP_CaptureInfo gspcapinfo;
memset(&gspcapinfo, 0, sizeof(GSP_CaptureInfo));
GSPGPU_ImportDisplayCaptureInfo(NULL, &gspcapinfo);
if(gspcapinfo.screencapture[0].framebuf0_vaddr != gspcapinfo.screencapture[1].framebuf0_vaddr)ns_capinfo[1] = 1;
ns_capinfo[4] = gspcapinfo.screencapture[0].format & 0x7;
ns_capinfo[7] = gspcapinfo.screencapture[1].format & 0x7;
if(ns_capinfo[4] < 2)
{
main_pixsz = 3;
}
else
{
main_pixsz = 2;
}
if(ns_capinfo[7] < 2)
{
sub_pixsz = 3;
}
else
{
sub_pixsz = 2;
}
ns_capinfo[2] = sub_pixsz * 0x14000;
ns_capinfo[3] = ns_capinfo[2];
if(ns_capinfo[1])ns_capinfo[3] = main_pixsz * 0x19000 + ns_capinfo[2];
tmp = main_pixsz * 0x19000 + ns_capinfo[3];
ns_capinfo[0] = main_pixsz * 0x7000 + tmp;
}
void aptWaitStatusEvent()
{
svc_waitSynchronization1(aptStatusEvent, U64_MAX);
svc_clearEvent(aptStatusEvent);
}
void aptAppletUtility_Exit_RetToApp()
{
u8 buf1[4], buf2[4];
memset(buf1, 0, 4);
buf1[0]=0x10;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2);
aptCloseSession();
buf1[0]=0x00;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
buf1[0]=0x01;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2);
aptCloseSession();
buf1[0]=0x00;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
}
NS_APPID aptGetMenuAppID()
{
NS_APPID menu_appid;
aptOpenSession();
APT_GetAppletManInfo(NULL, 0xff, NULL, NULL, &menu_appid, NULL);
aptCloseSession();
return menu_appid;
}
void aptReturnToMenu()
{
NS_APPID menu_appid;
u32 tmp0 = 1, tmp1 = 0;
u32 ns_capinfo[0x20>>2];
u32 tmp_params[0x20>>2];
if(aptGetStatusPower()==0)//This is only executed when ret-to-menu was triggered via the home-button, not the power-button.
{
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x6, 0x4, (u8*)&tmp0, 0x1, (u8*)&tmp1);
aptCloseSession();
}
aptOpenSession();
APT_PrepareToJumpToHomeMenu(NULL); //prepare for return to menu
aptCloseSession();
svc_clearEvent(aptStatusEvent);
aptSetStatus(APP_SUSPENDED);
GSPGPU_SaveVramSysArea(NULL);
memset(tmp_params, 0, 0x20);
memset(ns_capinfo, 0, 0x20);
aptInitCaptureInfo(ns_capinfo);
menu_appid = aptGetMenuAppID();
aptOpenSession();
APT_SendParameter(NULL, currentAppId, menu_appid, 0x20, ns_capinfo, 0x0, 0x10);
aptCloseSession();
aptOpenSession();
APT_SendCaptureBufferInfo(NULL, 0x20, ns_capinfo);
aptCloseSession();
GSPGPU_ReleaseRight(NULL); //disable GSP module access
aptOpenSession();
APT_JumpToHomeMenu(NULL, 0x0, 0x0, 0x0); //jump !
aptCloseSession();
aptOpenSession();
APT_NotifyToWait(NULL, currentAppId);
aptCloseSession();
if(aptGetStatusPower()==0)//This is only executed when ret-to-menu was triggered via the home-button, not the power-button.
{
tmp0 = 0;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, (u8*)&tmp0, 0x1, (u8*)&tmp1);
aptCloseSession();
}
aptWaitStatusEvent();
}
void aptEventHandler(u32 arg) void aptEventHandler(u32 arg)
{ {
bool runThread=true; bool runThread=true;
while(runThread) while(runThread)
{ {
s32 syncedID=0x0; s32 syncedID=0x0;
@ -45,17 +198,44 @@ void aptEventHandler(u32 arg)
switch(signalType) switch(signalType)
{ {
case 0x1: //home menu button got pressed case 0x1: //home menu button got pressed
case 0x8: //power button got pressed
if(aptGetStatus()==APP_RUNNING)
{
aptOpenSession(); aptOpenSession();
APT_PrepareToJumpToHomeMenu(NULL); //prepare for return to menu APT_ReplySleepQuery(NULL, currentAppId, 0x0);
aptCloseSession(); aptCloseSession();
aptSetStatus(APP_SUSPENDED); if(signalType==0x1)aptSetStatusPower(0);
if(signalType==0x8)aptSetStatusPower(1);
aptSetStatus(APP_SUSPENDING);//The main thread should call aptReturnToMenu() when the status gets set to this.
}
GSPGPU_ReleaseRight(NULL); //disable GSP module access break;
case 0x3: //preparing to enter sleep-mode
aptStatus_beforesleepmode = aptGetStatus();
aptOpenSession(); aptOpenSession();
APT_JumpToHomeMenu(NULL, 0x0, 0x0, 0x0); //jump ! APT_ReplySleepQuery(NULL, currentAppId, 0x1);
aptCloseSession(); aptCloseSession();
aptSetStatus(APP_PREPARE_SLEEPMODE);
break;
case 0x5: //entering sleep-mode
if(aptGetStatus()==APP_PREPARE_SLEEPMODE)
{
aptOpenSession();
APT_ReplySleepNotificationComplete(NULL, currentAppId);
aptCloseSession();
aptSetStatus(APP_SLEEPMODE);
}
break;
case 0x6: //leaving sleep-mode
if(aptGetStatus()==APP_SLEEPMODE)
{
if(aptStatus_beforesleepmode == APP_RUNNING)GSPGPU_SetLcdForceBlack(NULL, 0);
aptSetStatus(aptStatus_beforesleepmode);
}
break; break;
} }
} }
@ -73,13 +253,11 @@ void aptEventHandler(u32 arg)
break; break;
case 0xB: //just returned from menu case 0xB: //just returned from menu
GSPGPU_AcquireRight(NULL, 0x0); GSPGPU_AcquireRight(NULL, 0x0);
GSPGPU_RestoreVramSysArea(NULL);
aptAppletUtility_Exit_RetToApp();
aptSetStatus(APP_RUNNING); aptSetStatus(APP_RUNNING);
break; break;
case 0xC: //exiting application case 0xC: //exiting application
aptOpenSession();
APT_ReplySleepQuery(NULL, currentAppId, 0x0);
aptCloseSession();
runThread=false; runThread=false;
aptSetStatus(APP_EXITING); //app exit signal aptSetStatus(APP_EXITING); //app exit signal
break; break;
@ -117,31 +295,21 @@ Result aptInit(NS_APPID appID)
if((ret=APT_NotifyToWait(NULL, currentAppId)))return ret; if((ret=APT_NotifyToWait(NULL, currentAppId)))return ret;
aptCloseSession(); aptCloseSession();
svc_createEvent(&aptStatusEvent, 0);
return 0; return 0;
} }
void aptExit() void aptExit()
{ {
u8 buf1[4], buf2[4]; aptAppletUtility_Exit_RetToApp();
buf1[0]=0x02; buf1[1]=0x00; buf1[2]=0x00; buf1[3]=0x00; if(aptGetStatusPower()==1)//This is only executed when application-termination was triggered via the home-menu power-off screen.
{
aptOpenSession(); aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2); APT_ReplySleepQuery(NULL, currentAppId, 0x0);
aptCloseSession(); aptCloseSession();
aptOpenSession(); }
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2);
aptCloseSession();
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
aptOpenSession(); aptOpenSession();
APT_PrepareToCloseApplication(NULL, 0x1); APT_PrepareToCloseApplication(NULL, 0x1);
@ -153,13 +321,14 @@ void aptExit()
svc_closeHandle(aptStatusMutex); svc_closeHandle(aptStatusMutex);
// svc_closeHandle(aptLockHandle); // svc_closeHandle(aptLockHandle);
svc_closeHandle(aptStatusEvent);
} }
void aptSetupEventHandler() void aptSetupEventHandler()
{ {
u8 buf1[4], buf2[4]; u8 buf1[4], buf2[4];
buf1[0]=0x02; buf1[1]=0x00; buf1[2]=0x00; buf1[3]=0x04; /*buf1[0]=0x02; buf1[1]=0x00; buf1[2]=0x00; buf1[3]=0x04;
aptOpenSession(); aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2); APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2);
aptCloseSession(); aptCloseSession();
@ -177,6 +346,22 @@ void aptSetupEventHandler()
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2); APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2);
aptCloseSession(); aptCloseSession();
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();*/
memset(buf1, 0, 4);
buf1[0] = 0x10;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2);
aptCloseSession();
buf1[0] = 0x00;
aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession();
aptOpenSession(); aptOpenSession();
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2); APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
aptCloseSession(); aptCloseSession();
@ -185,6 +370,8 @@ void aptSetupEventHandler()
aptStatus=0; aptStatus=0;
svc_releaseMutex(aptStatusMutex); svc_releaseMutex(aptStatusMutex);
aptSetStatus(APP_RUNNING);
//create thread for stuff handling APT events //create thread for stuff handling APT events
svc_createThread(&aptEventHandlerThread, aptEventHandler, 0x0, (u32*)(&aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]), 0x31, 0xfffffffe); svc_createThread(&aptEventHandlerThread, aptEventHandler, 0x0, (u32*)(&aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]), 0x31, 0xfffffffe);
} }
@ -200,8 +387,35 @@ APP_STATUS aptGetStatus()
void aptSetStatus(APP_STATUS status) void aptSetStatus(APP_STATUS status)
{ {
u32 prevstatus;
svc_waitSynchronization1(aptStatusMutex, U64_MAX); svc_waitSynchronization1(aptStatusMutex, U64_MAX);
prevstatus = status;
aptStatus = status; aptStatus = status;
if(prevstatus!=APP_NOTINITIALIZED)
{
if(status==APP_RUNNING)svc_signalEvent(aptStatusEvent);
if(status==APP_EXITING)svc_signalEvent(aptStatusEvent);
}
svc_releaseMutex(aptStatusMutex);
}
u32 aptGetStatusPower()
{
u32 ret;
svc_waitSynchronization1(aptStatusMutex, U64_MAX);
ret=aptStatusPower;
svc_releaseMutex(aptStatusMutex);
return ret;
}
void aptSetStatusPower(u32 status)
{
svc_waitSynchronization1(aptStatusMutex, U64_MAX);
aptStatusPower = status;
svc_releaseMutex(aptStatusMutex); svc_releaseMutex(aptStatusMutex);
} }
@ -262,6 +476,24 @@ Result APT_Enable(Handle* handle, u32 a)
return cmdbuf[1]; return cmdbuf[1];
} }
Result APT_GetAppletManInfo(Handle* handle, u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu_appid, NS_APPID *active_appid)
{
if(!handle)handle=&aptuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x00050040; //request header code
cmdbuf[1]=inval;
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
if(outval8)*outval8=cmdbuf[2];
if(outval32)*outval32=cmdbuf[3];
if(menu_appid)*menu_appid=cmdbuf[4];
if(active_appid)*active_appid=cmdbuf[5];
return cmdbuf[1];
}
Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType) Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType)
{ {
if(!handle)handle=&aptuHandle; if(!handle)handle=&aptuHandle;
@ -380,6 +612,47 @@ Result APT_ReceiveParameter(Handle* handle, NS_APPID appID, u32 bufferSize, u32*
return cmdbuf[1]; return cmdbuf[1];
} }
Result APT_SendParameter(Handle* handle, NS_APPID src_appID, NS_APPID dst_appID, u32 bufferSize, u32* buffer, Handle paramhandle, u8 signalType)
{
u32* cmdbuf=getThreadCommandBuffer();
if(!handle)handle=&aptuHandle;
cmdbuf[0] = 0x000C0104; //request header code
cmdbuf[1] = src_appID;
cmdbuf[2] = dst_appID;
cmdbuf[3] = signalType;
cmdbuf[4] = bufferSize;
cmdbuf[5]=0x0;
cmdbuf[6] = paramhandle;
cmdbuf[7] = (bufferSize<<14) | 2;
cmdbuf[8] = (u32)buffer;
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result APT_SendCaptureBufferInfo(Handle* handle, u32 bufferSize, u32* buffer)
{
u32* cmdbuf=getThreadCommandBuffer();
if(!handle)handle=&aptuHandle;
cmdbuf[0] = 0x00400042; //request header code
cmdbuf[1] = bufferSize;
cmdbuf[2] = (bufferSize<<14) | 2;
cmdbuf[3] = (u32)buffer;
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result APT_ReplySleepQuery(Handle* handle, NS_APPID appID, u32 a) Result APT_ReplySleepQuery(Handle* handle, NS_APPID appID, u32 a)
{ {
if(!handle)handle=&aptuHandle; if(!handle)handle=&aptuHandle;
@ -395,6 +668,20 @@ Result APT_ReplySleepQuery(Handle* handle, NS_APPID appID, u32 a)
return cmdbuf[1]; return cmdbuf[1];
} }
Result APT_ReplySleepNotificationComplete(Handle* handle, NS_APPID appID)
{
if(!handle)handle=&aptuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x3F0040; //request header code
cmdbuf[1]=appID;
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result APT_PrepareToCloseApplication(Handle* handle, u8 a) Result APT_PrepareToCloseApplication(Handle* handle, u8 a)
{ {
if(!handle)handle=&aptuHandle; if(!handle)handle=&aptuHandle;

113
libctru/source/CFGNOR.c Normal file
View File

@ -0,0 +1,113 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctr/types.h>
#include <ctr/svc.h>
#include <ctr/srv.h>
#include <ctr/CFGNOR.h>
Handle CFGNOR_handle = 0;
Result CFGNOR_Initialize(u8 value)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
ret = srv_getServiceHandle(NULL, &CFGNOR_handle, "cfg:nor");
if(ret!=0)return ret;
cmdbuf[0] = 0x00010040;
cmdbuf[1] = (u32)value;
if((ret = svc_sendSyncRequest(CFGNOR_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result CFGNOR_Shutdown()
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00020000;
if((ret = svc_sendSyncRequest(CFGNOR_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
svc_closeHandle(CFGNOR_handle);
CFGNOR_handle = 0;
return ret;
}
Result CFGNOR_ReadData(u32 offset, u32 *buf, u32 size)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00050082;
cmdbuf[1] = offset;
cmdbuf[2] = size;
cmdbuf[3] = (size<<4) | 12;
cmdbuf[4] = (u32)buf;
if((ret = svc_sendSyncRequest(CFGNOR_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result CFGNOR_WriteData(u32 offset, u32 *buf, u32 size)
{
u32 ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00060082;
cmdbuf[1] = offset;
cmdbuf[2] = size;
cmdbuf[3] = (size<<4) | 10;
cmdbuf[4] = (u32)buf;
if((ret = svc_sendSyncRequest(CFGNOR_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result CFGNOR_DumpFlash(u32 *buf, u32 size)
{
Result ret = 0;
u32 pos=0;
u32 chunksize = 0x100;
for(pos=0; pos<size; pos+=chunksize)
{
if(size-pos < chunksize)chunksize = size-pos;
ret = CFGNOR_ReadData(pos, &buf[pos>>2], chunksize);
if(ret!=0)break;
}
return ret;
}
Result CFGNOR_WriteFlash(u32 *buf, u32 size)
{
Result ret = 0;
u32 pos=0;
u32 chunksize = 0x100;
for(pos=0; pos<size; pos+=chunksize)
{
if(size-pos < chunksize)chunksize = size-pos;
ret = CFGNOR_WriteData(pos, &buf[pos>>2], chunksize);
if(ret!=0)break;
}
return ret;
}

325
libctru/source/CSND.c Normal file
View File

@ -0,0 +1,325 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctr/types.h>
#include <ctr/CSND.h>
#include <ctr/svc.h>
#include <ctr/srv.h>
//See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
Handle CSND_handle = 0;
Handle CSND_mutexhandle = 0;
Handle CSND_sharedmemhandle = 0;
u32 *CSND_sharedmem = NULL;
static u32 CSND_bitmask=0;
static u32 CSND_sharedmem_cmdblocksize = 0x2000;
static u32 CSND_sharedmem_startcmdoff = 0;
static u32 CSND_sharedmem_currentcmdoff = 0;
Result CSND_cmd1(Handle *mutexhandle, Handle *sharedmemhandle, u32 sharedmem_size, u32 off0, u32 off1, u32 off2, u32 off3)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00010140;
cmdbuf[1] = sharedmem_size;
cmdbuf[2] = off0;
cmdbuf[3] = off1;
cmdbuf[4] = off2;
cmdbuf[5] = off3;
if((ret = svc_sendSyncRequest(CSND_handle))!=0)return ret;
*mutexhandle = cmdbuf[3];
*sharedmemhandle = cmdbuf[4];
return (Result)cmdbuf[1];
}
Result CSND_cmd2()
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00020000;
if((ret = svc_sendSyncRequest(CSND_handle))!=0)return ret;
return (Result)cmdbuf[1];
}
Result CSND_cmd5(u32 *bitmask)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00050000;
if((ret = svc_sendSyncRequest(CSND_handle))!=0)return ret;
*bitmask = cmdbuf[2];
return (Result)cmdbuf[1];
}
Result CSND_initialize(u32* sharedMem)
{
Result ret=0;
if(sharedMem==NULL)sharedMem = (u32*)CSND_SHAREDMEM_DEFAULT;
CSND_sharedmem = sharedMem;
ret = srv_getServiceHandle(NULL, &CSND_handle, "csnd:SND");
if(ret!=0)return ret;
ret = CSND_cmd1(&CSND_mutexhandle, &CSND_sharedmemhandle, CSND_sharedmem_cmdblocksize+0x114, CSND_sharedmem_cmdblocksize, CSND_sharedmem_cmdblocksize+8, CSND_sharedmem_cmdblocksize+0xc8, CSND_sharedmem_cmdblocksize+0xd8);
if(ret!=0)return ret;
ret = svc_mapMemoryBlock(CSND_sharedmemhandle, (u32)CSND_sharedmem, 3, 0x10000000);
if(ret!=0)return ret;
memset(CSND_sharedmem, 0, 0x2114);
ret = CSND_cmd5(&CSND_bitmask);
if(ret!=0)return ret;
return 0;
}
Result CSND_shutdown()
{
Result ret;
svc_unmapMemoryBlock(CSND_sharedmemhandle, (u32)CSND_sharedmem);
svc_closeHandle(CSND_sharedmemhandle);
ret = CSND_cmd2();
if(ret!=0)return ret;
return svc_closeHandle(CSND_handle);
}
Result CSND_cmd3(u32 offset)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00030040;
cmdbuf[1] = offset;
if((ret = svc_sendSyncRequest(CSND_handle))!=0)return ret;
return (Result)cmdbuf[1];
}
void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams)
{
u16 *ptr;
u32 prevoff;
s32 outindex=0;
svc_waitSynchronizationN(&outindex, &CSND_mutexhandle, 1, 0, ~0);
if(CSND_sharedmem_startcmdoff != CSND_sharedmem_currentcmdoff)
{
if(CSND_sharedmem_currentcmdoff>=0x20)
{
prevoff = CSND_sharedmem_currentcmdoff-0x20;
}
else
{
prevoff = CSND_sharedmem_cmdblocksize-0x20;
}
ptr = (u16*)&CSND_sharedmem[prevoff>>2];
*ptr = CSND_sharedmem_currentcmdoff;
}
ptr = (u16*)&CSND_sharedmem[CSND_sharedmem_currentcmdoff>>2];
ptr[0] = 0xffff;
ptr[1] = cmdid;
ptr[2] = 0;
ptr[3] = 0;
memcpy(&ptr[8>>1], cmdparams, 0x18);
CSND_sharedmem_currentcmdoff+= 0x20;
if(CSND_sharedmem_currentcmdoff >= CSND_sharedmem_cmdblocksize)CSND_sharedmem_currentcmdoff = 0;
svc_releaseMutex(CSND_mutexhandle);
}
Result CSND_processtype0cmds()
{
Result ret=0;
if(CSND_sharedmem_startcmdoff == CSND_sharedmem_currentcmdoff)return 0;
ret = CSND_cmd3(CSND_sharedmem_startcmdoff);
CSND_sharedmem_startcmdoff = CSND_sharedmem_currentcmdoff;
return ret;
}
u32 CSND_convertsamplerate(u32 samplerate)
{
return (u32)(6.7027964E+07f / ((float)samplerate));
}
void CSND_sharedmemtype0_cmd0(u32 channel, u32 value)
{
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
cmdparams[1] = value;
CSND_writesharedmem_cmdtype0(0x0, (u8*)&cmdparams);
}
void CSND_setchannel_playbackstate(u32 channel, u32 value)
{
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
cmdparams[1] = value;
CSND_writesharedmem_cmdtype0(0x1, (u8*)&cmdparams);
}
void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
{
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
cmdparams[1] = physaddr;
cmdparams[2] = size;
CSND_writesharedmem_cmdtype0(0x3, (u8*)&cmdparams);
}
void CSND_sharedmemtype0_cmd9(u32 channel, u16 value)
{
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
cmdparams[1] = value | (value<<16);
CSND_writesharedmem_cmdtype0(0x9, (u8*)&cmdparams);
}
void CSND_sharedmemtype0_cmd8(u32 channel, u32 samplerate)
{
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
cmdparams[1] = CSND_convertsamplerate(samplerate);
CSND_writesharedmem_cmdtype0(0x8, (u8*)&cmdparams);
}
void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 unk0, u32 unk1, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
{
u32 val;
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
cmdparams[0] = channel & 0x1f;
cmdparams[0] |= (unk0 & 0xf) << 6;
if(!looping)cmdparams[0] |= 2 << 10;
if(looping)cmdparams[0] |= 1 << 10;
cmdparams[0] |= (encoding & 3) << 12;
cmdparams[0] |= (unk1 & 3) << 14;
val = CSND_convertsamplerate(samplerate);
if(val<0x42)val = 0x42;
if(val>0xffff)val = 0xffff;
cmdparams[0] |= val<<16;
cmdparams[3] = physaddr0;
cmdparams[4] = physaddr1;
cmdparams[5] = totalbytesize;
CSND_writesharedmem_cmdtype0(0xe, (u8*)&cmdparams);
}
Result CSND_sharedmemtype0_cmdupdatestate(int waitdone)
{
u8 *ptr;
int ret=0;
u32 cmdparams[0x18>>2];
memset(cmdparams, 0, 0x18);
ptr = (u8*)&CSND_sharedmem[CSND_sharedmem_startcmdoff>>2];
CSND_writesharedmem_cmdtype0(0x300, (u8*)&cmdparams);
ret = CSND_processtype0cmds();
if(ret!=0)return ret;
if(waitdone)
{
while(*ptr == 0);
}
return 0;
}
Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1)
{
u32 physaddr0 = 0;
u32 physaddr1 = 0;
if((u32)vaddr0 >= 0x14000000 && (u32)vaddr0<0x1c000000)physaddr0 = (u32)vaddr0 + 0x0c000000;
if((u32)vaddr1 >= 0x14000000 && (u32)vaddr1<0x1c000000)physaddr1 = (u32)vaddr1 + 0x0c000000;
CSND_sharedmemtype0_cmde(channel, looping, encoding, samplerate, unk0, unk1, physaddr0, physaddr1, totalbytesize);
CSND_sharedmemtype0_cmd8(channel, samplerate);
if(looping)CSND_sharedmemtype0_cmd3(channel, physaddr0, totalbytesize);
CSND_sharedmemtype0_cmd8(channel, samplerate);
CSND_sharedmemtype0_cmd9(channel, 0xffff);
CSND_setchannel_playbackstate(channel, 1);
return CSND_sharedmemtype0_cmdupdatestate(0);
}
Result CSND_getchannelstate(u32 entryindex, u32 *out)
{
Result ret=0;
if((ret = CSND_sharedmemtype0_cmdupdatestate(1))!=0)return ret;
memcpy(out, &CSND_sharedmem[(CSND_sharedmem_cmdblocksize+8 + entryindex*0xc) >> 2], 0xc);
out[2] -= 0x0c000000;
return 0;
}
Result CSND_getchannelstate_isplaying(u32 entryindex, u8 *status)
{
Result ret;
u32 entry[0xc>>2];
ret = CSND_getchannelstate(entryindex, entry);
if(ret!=0)return ret;
*status = entry[0] & 0xff;
return 0;
}

View File

@ -189,6 +189,21 @@ Result FSFILE_GetSize(Handle handle, u64 *size)
return cmdbuf[1]; return cmdbuf[1];
} }
Result FSFILE_SetSize(Handle handle, u64 size)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x08050080;
cmdbuf[1] = (u32)size;
cmdbuf[2] = (u32)(size >> 32);
Result ret = 0;
if ((ret = svc_sendSyncRequest(handle)))return ret;
return cmdbuf[1];
}
Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entrycount, u16 *buffer) Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entrycount, u16 *buffer)
{ {
u32 *cmdbuf=getThreadCommandBuffer(); u32 *cmdbuf=getThreadCommandBuffer();

View File

@ -47,6 +47,52 @@ Result GSPGPU_ReleaseRight(Handle* handle)
return cmdbuf[1]; return cmdbuf[1];
} }
Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *captureinfo)
{
if(!handle)handle=&gspGpuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x00180000; //request header code
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
ret = cmdbuf[1];
if(ret==0)
{
memcpy(captureinfo, &cmdbuf[2], 0x20);
}
return ret;
}
Result GSPGPU_SaveVramSysArea(Handle* handle)
{
if(!handle)handle=&gspGpuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x00190000; //request header code
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result GSPGPU_RestoreVramSysArea(Handle* handle)
{
if(!handle)handle=&gspGpuHandle;
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x001A0000; //request header code
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags) Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags)
{ {
if(!handle)handle=&gspGpuHandle; if(!handle)handle=&gspGpuHandle;
@ -61,6 +107,22 @@ Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags)
return cmdbuf[1]; return cmdbuf[1];
} }
Result GSPGPU_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *framebufinfo)
{
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
if(!handle)handle=&gspGpuHandle;
cmdbuf[0] = 0x00050200;
cmdbuf[1] = screenid;
memcpy(&cmdbuf[2], framebufinfo, sizeof(GSP_FramebufferInfo));
if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1];
}
Result GSPGPU_FlushDataCache(Handle* handle, u8* adr, u32 size) Result GSPGPU_FlushDataCache(Handle* handle, u8* adr, u32 size)
{ {
if(!handle)handle=&gspGpuHandle; if(!handle)handle=&gspGpuHandle;
@ -80,16 +142,17 @@ Result GSPGPU_FlushDataCache(Handle* handle, u8* adr, u32 size)
Result GSPGPU_InvalidateDataCache(Handle* handle, u8* adr, u32 size) Result GSPGPU_InvalidateDataCache(Handle* handle, u8* adr, u32 size)
{ {
Result ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
if(!handle)handle=&gspGpuHandle; if(!handle)handle=&gspGpuHandle;
u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0] = 0x00090082;
cmdbuf[0]=0x90082; //request header code
cmdbuf[1] = (u32)adr; cmdbuf[1] = (u32)adr;
cmdbuf[2] = size; cmdbuf[2] = size;
cmdbuf[3]=0x0; cmdbuf[3] = 0;
cmdbuf[4]=0xffff8001; cmdbuf[4] = 0xFFFF8001;
Result ret=0;
if((ret=svc_sendSyncRequest(*handle)))return ret; if((ret=svc_sendSyncRequest(*handle)))return ret;
return cmdbuf[1]; return cmdbuf[1];

237
libctru/source/IR.c Normal file
View File

@ -0,0 +1,237 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctr/types.h>
#include <ctr/svc.h>
#include <ctr/srv.h>
#include <ctr/IR.h>
static Handle iru_handle=0;
static Handle iru_sharedmem_handle=0;
static u32 *iru_sharedmem = NULL;
static u32 iru_sharedmem_size = 0;
Result irucmd_Initialize()
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00010000;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result irucmd_Shutdown()
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00020000;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result irucmd_StartSendTransfer(u8 *buf, u32 size)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00030042;
cmdbuf[1] = size;
cmdbuf[2] = (size<<4) | 10;
cmdbuf[3] = (u32)buf;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result irucmd_WaitSendTransfer()
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00040000;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result irucmd_StartRecvTransfer(u32 size, u8 flag)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000500C2;
cmdbuf[1] = iru_sharedmem_size;
cmdbuf[2] = size;
cmdbuf[3] = (u8)flag;
cmdbuf[4] = 0;
cmdbuf[5] = iru_sharedmem_handle;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result irucmd_WaitRecvTransfer(u32 *transfercount)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00060000;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
*transfercount = cmdbuf[2];
return ret;
}
Result IRU_SetBitRate(u8 value)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00090040;
cmdbuf[1] = (u32)value;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result IRU_GetBitRate(u8 *out)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000A0000;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
*out = (u8)cmdbuf[2];
return ret;
}
Result IRU_SetIRLEDState(u32 value)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000B0040;
cmdbuf[1] = value;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
return ret;
}
Result IRU_GetIRLEDRecvState(u32 *out)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000C0000;
if((ret = svc_sendSyncRequest(iru_handle))!=0)return ret;
ret = (Result)cmdbuf[1];
*out = cmdbuf[2];
return ret;
}
Result IRU_Initialize(u32 *sharedmem_addr, u32 sharedmem_size)
{
Result ret = 0;
if(iru_handle)return 0;
ret = srv_getServiceHandle(NULL, &iru_handle, "ir:u");
if(ret!=0)return ret;
ret = irucmd_Initialize();
if(ret!=0)return ret;
ret = svc_createMemoryBlock(&iru_sharedmem_handle, (u32)sharedmem_addr, sharedmem_size, 1, 3);
if(ret!=0)return ret;
iru_sharedmem = sharedmem_addr;
iru_sharedmem_size = sharedmem_size;
return ret;
}
Result IRU_Shutdown()
{
Result ret = 0;
if(iru_handle==0)return 0;
ret = irucmd_Shutdown();
if(ret!=0)return ret;
svc_closeHandle(iru_handle);
svc_closeHandle(iru_sharedmem_handle);
iru_handle = 0;
iru_sharedmem_handle = 0;
return 0;
}
Handle IRU_GetServHandle()
{
return iru_handle;
}
Result IRU_SendData(u8 *buf, u32 size, u32 wait)
{
Result ret = 0;
ret = irucmd_StartSendTransfer(buf, size);
if(ret!=0)return ret;
if(wait==0)return 0;
return irucmd_WaitSendTransfer();
}
Result IRU_RecvData(u8 *buf, u32 size, u8 flag, u32 *transfercount, u32 wait)
{
Result ret = 0;
*transfercount = 0;
ret = irucmd_StartRecvTransfer(size, flag);
if(ret!=0)return ret;
if(wait)
{
ret = irucmd_WaitRecvTransfer(transfercount);
if(ret!=0)return ret;
if(buf)memcpy(buf, iru_sharedmem, size);
}
return 0;
}

View File

@ -1,3 +1,4 @@
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -9,9 +10,103 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
static Handle socu_handle = 0; Handle SOCU_handle = 0;
static int soc_errno = 0; static int SOCU_errno = 0;
#define NET_UNKNOWN_ERROR_OFFSET -10000//This is from libogc network_wii.c.
static u8 _net_error_code_map[] = { //This is based on the array from libogc network_wii.c.
0, // 0
E2BIG,
EACCES,
EADDRINUSE,
EADDRNOTAVAIL,
EAFNOSUPPORT, // 5
EAGAIN,
EALREADY,
EBADF,
EBADMSG,
EBUSY, // 10
ECANCELED,
ECHILD,
ECONNABORTED,
ECONNREFUSED,
ECONNRESET, // 15
EDEADLK,
EDESTADDRREQ,
EDOM,
EDQUOT,
EEXIST, // 20
EFAULT,
EFBIG,
EHOSTUNREACH,
EIDRM,
EILSEQ, // 25
EINPROGRESS,
EINTR,
EINVAL,
EIO,
EISCONN, // 30
EISDIR,
ELOOP,
EMFILE,
EMLINK,
EMSGSIZE, // 35
EMULTIHOP,
ENAMETOOLONG,
ENETDOWN,
ENETRESET,
ENETUNREACH, // 40
ENFILE,
ENOBUFS,
ENODATA,
ENODEV,
ENOENT, // 45
ENOEXEC,
ENOLCK,
ENOLINK,
ENOMEM,
ENOMSG, // 50
ENOPROTOOPT,
ENOSPC,
ENOSR,
ENOSTR,
ENOSYS, // 55
ENOTCONN,
ENOTDIR,
ENOTEMPTY,
ENOTSOCK,
ENOTSUP, // 60
ENOTTY,
ENXIO,
EOPNOTSUPP,
EOVERFLOW,
EPERM, // 65
EPIPE,
EPROTO,
EPROTONOSUPPORT,
EPROTOTYPE,
ERANGE, // 70
EROFS,
ESPIPE,
ESRCH,
ESTALE,
ETIME, // 75
ETIMEDOUT,
};
static s32 _net_convert_error(s32 sock_retval)//This is based on the function from libogc network_wii.c.
{
if (sock_retval >= 0) return sock_retval;
if (sock_retval < -sizeof(_net_error_code_map)
|| !_net_error_code_map[-sock_retval])
return NET_UNKNOWN_ERROR_OFFSET + sock_retval;
return -_net_error_code_map[-sock_retval];
}
Result socu_cmd1(Handle memhandle, u32 memsize) Result socu_cmd1(Handle memhandle, u32 memsize)
{ {
@ -24,7 +119,7 @@ Result socu_cmd1(Handle memhandle, u32 memsize)
cmdbuf[4] = 0; cmdbuf[4] = 0;
cmdbuf[5] = memhandle; cmdbuf[5] = memhandle;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
return cmdbuf[1]; return cmdbuf[1];
} }
@ -36,14 +131,14 @@ Result SOC_Shutdown()
cmdbuf[0] = 0x00190000; cmdbuf[0] = 0x00190000;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
svc_closeHandle(socu_handle); svc_closeHandle(SOCU_handle);
return cmdbuf[1]; return cmdbuf[1];
} }
Result SOC_Initialize(u32 *context_addr, u32 context_size)//Example context_size: 0x48000. The specified context buffer can no longer be accessed by the process which called this function, since the userland permissions for this block are set to no-access. Result SOC_Initialize(u32 *context_addr, u32 context_size)
{ {
Result ret=0; Result ret=0;
Handle memhandle = 0; Handle memhandle = 0;
@ -51,14 +146,14 @@ Result SOC_Initialize(u32 *context_addr, u32 context_size)//Example context_size
ret = svc_createMemoryBlock(&memhandle, (u32)context_addr, context_size, 0, 3); ret = svc_createMemoryBlock(&memhandle, (u32)context_addr, context_size, 0, 3);
if(ret!=0)return ret; if(ret!=0)return ret;
if((ret = srv_getServiceHandle(NULL, &socu_handle, "soc:U"))!=0)return ret; if((ret = srv_getServiceHandle(NULL, &SOCU_handle, "soc:U"))!=0)return ret;
return socu_cmd1(memhandle, context_size); return socu_cmd1(memhandle, context_size);
} }
int SOC_GetErrno() int SOC_GetErrno()
{ {
return soc_errno; return SOCU_errno;
} }
int socket(int domain, int type, int protocol) int socket(int domain, int type, int protocol)
@ -72,13 +167,13 @@ int socket(int domain, int type, int protocol)
cmdbuf[3] = protocol; cmdbuf[3] = protocol;
cmdbuf[4] = 0x20; cmdbuf[4] = 0x20;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
soc_errno = ret; SOCU_errno = ret;
if(ret!=0)return -1; if(ret!=0)return -1;
return (int)cmdbuf[2]; return _net_convert_error(cmdbuf[2]);
} }
int closesocket(int sockfd) int closesocket(int sockfd)
@ -90,11 +185,11 @@ int closesocket(int sockfd)
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = 0x20; cmdbuf[2] = 0x20;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret =_net_convert_error(cmdbuf[2]);
soc_errno = ret; SOCU_errno = ret;
if(ret!=0)return -1; if(ret!=0)return -1;
return 0; return 0;
@ -110,11 +205,11 @@ int shutdown(int sockfd, int shutdown_type)
cmdbuf[2] = (u32)shutdown_type; cmdbuf[2] = (u32)shutdown_type;
cmdbuf[3] = 0x20; cmdbuf[3] = 0x20;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
soc_errno = ret; SOCU_errno = ret;
if(ret!=0)return -1; if(ret!=0)return -1;
return 0; return 0;
@ -130,11 +225,11 @@ int listen(int sockfd, int max_connections)
cmdbuf[2] = (u32)max_connections; cmdbuf[2] = (u32)max_connections;
cmdbuf[3] = 0x20; cmdbuf[3] = 0x20;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
soc_errno = ret; SOCU_errno = ret;
if(ret!=0)return -1; if(ret!=0)return -1;
return 0; return 0;
@ -143,12 +238,12 @@ int listen(int sockfd, int max_connections)
int accept(int sockfd, struct sockaddr *addr, int *addrlen) int accept(int sockfd, struct sockaddr *addr, int *addrlen)
{ {
int ret=0; int ret=0;
int tmp_addrlen=0x1c;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8]; u8 tmpaddr[0x1c];
int tmp_addrlen=8;
u32 saved_threadstorage[2]; u32 saved_threadstorage[2];
memset(tmpaddr, 0, 8); memset(tmpaddr, 0, 0x1c);
cmdbuf[0] = 0x00040082; cmdbuf[0] = 0x00040082;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
@ -161,21 +256,20 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen)
cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2;
cmdbuf[0x104>>2] = (u32)tmpaddr; cmdbuf[0x104>>2] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1]; cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)soc_errno = ret; if(ret<0)SOCU_errno = ret;
if(ret>=0 && addr!=NULL) if(ret>=0 && addr!=NULL)
{ {
*addrlen = tmpaddr[0];
memset(addr, 0, sizeof(struct sockaddr));
addr->sa_family = tmpaddr[1]; addr->sa_family = tmpaddr[1];
memcpy(&addr->sa_data, &tmpaddr[2], tmp_addrlen-2); if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
} }
if(ret<0)return -1; if(ret<0)return -1;
@ -185,27 +279,43 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen)
int bind(int sockfd, const struct sockaddr *addr, int addrlen) int bind(int sockfd, const struct sockaddr *addr, int addrlen)
{ {
int ret=0; int ret=0;
int tmp_addrlen=0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8]; u8 tmpaddr[0x1c];
struct sockaddr_in *inaddr = (struct sockaddr_in*)addr;
addrlen = 8; memset(tmpaddr, 0, 0x1c);
tmpaddr[0] = 8;
if(addr->sa_family == AF_INET)
{
tmp_addrlen = 8;
}
else
{
tmp_addrlen = 0x1c;
}
if(addrlen < tmp_addrlen)
{
SOCU_errno = -EINVAL;
return -1;
}
tmpaddr[0] = tmp_addrlen;
tmpaddr[1] = addr->sa_family; tmpaddr[1] = addr->sa_family;
memcpy(&tmpaddr[2], &addr->sa_data, addrlen-2); memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2);
cmdbuf[0] = 0x00050084; cmdbuf[0] = 0x00050084;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)addrlen; cmdbuf[2] = (u32)tmp_addrlen;
cmdbuf[3] = 0x20; cmdbuf[3] = 0x20;
cmdbuf[5] = (((u32)addrlen)<<14) | 2; cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
cmdbuf[6] = (u32)tmpaddr; cmdbuf[6] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
soc_errno = ret; SOCU_errno = ret;
if(ret<0)return -1; if(ret<0)return -1;
return 0; return 0;
@ -214,27 +324,43 @@ int bind(int sockfd, const struct sockaddr *addr, int addrlen)
int connect(int sockfd, const struct sockaddr *addr, int addrlen) int connect(int sockfd, const struct sockaddr *addr, int addrlen)
{ {
int ret=0; int ret=0;
int tmp_addrlen=0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8]; u8 tmpaddr[0x1c];
struct sockaddr_in *inaddr = (struct sockaddr_in*)addr;
addrlen = 8; memset(tmpaddr, 0, 0x1c);
tmpaddr[0] = 8;
if(addr->sa_family == AF_INET)
{
tmp_addrlen = 8;
}
else
{
tmp_addrlen = 0x1c;
}
if(addrlen < tmp_addrlen)
{
SOCU_errno = -EINVAL;
return -1;
}
tmpaddr[0] = tmp_addrlen;
tmpaddr[1] = addr->sa_family; tmpaddr[1] = addr->sa_family;
memcpy(&tmpaddr[2], &addr->sa_data, addrlen-2); memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2);
cmdbuf[0] = 0x00060084; cmdbuf[0] = 0x00060084;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)addrlen; cmdbuf[2] = (u32)addrlen;
cmdbuf[3] = 0x20; cmdbuf[3] = 0x20;
cmdbuf[5] = (((u32)addrlen)<<14) | 2; cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
cmdbuf[6] = (u32)tmpaddr; cmdbuf[6] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
soc_errno = ret; SOCU_errno = ret;
if(ret<0)return -1; if(ret<0)return -1;
return 0; return 0;
@ -244,11 +370,13 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src
{ {
int ret=0; int ret=0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8];
u32 tmp_addrlen=0; u32 tmp_addrlen=0;
u8 tmpaddr[0x1c];
u32 saved_threadstorage[2]; u32 saved_threadstorage[2];
memset(tmpaddr, 0, 8); memset(tmpaddr, 0, 0x1c);
if(src_addr)tmp_addrlen = 0x1c;
cmdbuf[0] = 0x00070104; cmdbuf[0] = 0x00070104;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
@ -265,14 +393,21 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src
cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2;
cmdbuf[0x104>>2] = (u32)tmpaddr; cmdbuf[0x104>>2] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1]; cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)soc_errno = ret; if(ret<0)SOCU_errno = ret;
if(ret>0 && src_addr!=NULL)
{
src_addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
}
if(ret<0)return -1; if(ret<0)return -1;
return ret; return ret;
@ -282,11 +417,13 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src
{ {
int ret=0; int ret=0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8];
u32 tmp_addrlen=0; u32 tmp_addrlen=0;
u8 tmpaddr[0x1c];
u32 saved_threadstorage[4]; u32 saved_threadstorage[4];
memset(tmpaddr, 0, 8); if(src_addr)tmp_addrlen = 0x1c;
memset(tmpaddr, 0, 0x1c);
cmdbuf[0] = 0x00080102; cmdbuf[0] = 0x00080102;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
@ -305,7 +442,7 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src
cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2;
cmdbuf[0x10c>>2] = (u32)tmpaddr; cmdbuf[0x10c>>2] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1]; cmdbuf[0x104>>2] = saved_threadstorage[1];
@ -313,21 +450,50 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src
cmdbuf[0x10c>>2] = saved_threadstorage[3]; cmdbuf[0x10c>>2] = saved_threadstorage[3];
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)soc_errno = ret; if(ret<0)SOCU_errno = ret;
if(ret>0 && src_addr!=NULL)
{
src_addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
}
if(ret<0)return -1; if(ret<0)return -1;
return ret; return ret;
} }
int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, struct sockaddr *dest_addr, int addrlen) int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen)
{ {
int ret=0; int ret=0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8];
u32 tmp_addrlen=0; u32 tmp_addrlen=0;
u8 tmpaddr[0x1c];
memset(tmpaddr, 0, 8); memset(tmpaddr, 0, 0x1c);
if(dest_addr)
{
if(dest_addr->sa_family == AF_INET)
{
tmp_addrlen = 8;
}
else
{
tmp_addrlen = 0x1c;
}
if(addrlen < tmp_addrlen)
{
SOCU_errno = -EINVAL;
return -1;
}
tmpaddr[0] = tmp_addrlen;
tmpaddr[1] = dest_addr->sa_family;
memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
}
cmdbuf[0] = 0x00090106; cmdbuf[0] = 0x00090106;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
@ -340,24 +506,46 @@ int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, struct sockadd
cmdbuf[9] = (((u32)len)<<4) | 10; cmdbuf[9] = (((u32)len)<<4) | 10;
cmdbuf[10] = (u32)buf; cmdbuf[10] = (u32)buf;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)soc_errno = ret; if(ret<0)SOCU_errno = ret;
if(ret<0)return -1; if(ret<0)return -1;
return ret; return ret;
} }
int socuipc_cmda(int sockfd, const void *buf, int len, int flags, struct sockaddr *dest_addr, int addrlen) int socuipc_cmda(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen)
{ {
int ret=0; int ret=0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[8]; u32 tmp_addrlen=0;
int tmp_addrlen=0; u8 tmpaddr[0x1c];
memset(tmpaddr, 0, 8); memset(tmpaddr, 0, 0x1c);
if(dest_addr)
{
if(dest_addr->sa_family == AF_INET)
{
tmp_addrlen = 8;
}
else
{
tmp_addrlen = 0x1c;
}
if(addrlen < tmp_addrlen)
{
SOCU_errno = -EINVAL;
return -1;
}
tmpaddr[0] = tmp_addrlen;
tmpaddr[1] = dest_addr->sa_family;
memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
}
cmdbuf[0] = 0x000A0106; cmdbuf[0] = 0x000A0106;
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
@ -370,25 +558,25 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, struct sockadd
cmdbuf[9] = (tmp_addrlen<<14) | 0x402; cmdbuf[9] = (tmp_addrlen<<14) | 0x402;
cmdbuf[10] = (u32)tmpaddr; cmdbuf[10] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
if(ret==0)ret = (int)cmdbuf[2]; if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)soc_errno = ret; if(ret<0)SOCU_errno = ret;
if(ret<0)return -1; if(ret<0)return -1;
return ret; return ret;
} }
int recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen)//UDP is not supported for these since the input/output sockaddr is not used. int recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen)
{ {
//if(len<0x2000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen); if(len<0x2000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen); return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
} }
int sendto(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen) int sendto(int sockfd, const void *buf, int len, int flags, const struct sockaddr *dest_addr, int addrlen)
{ {
//if(len<0x2000)return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen); if(len<0x2000)return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
return socuipc_cmd9(sockfd, buf, len, flags, (struct sockaddr*)dest_addr, addrlen); return socuipc_cmd9(sockfd, buf, len, flags, (struct sockaddr*)dest_addr, addrlen);
} }
@ -402,3 +590,217 @@ int send(int sockfd, const void *buf, int len, int flags)
return sendto(sockfd, buf, len, flags, NULL, 0); return sendto(sockfd, buf, len, flags, NULL, 0);
} }
int getsockopt(int sockfd, int level, int option_name, void * data, int * data_len)
{
int ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[2];
cmdbuf[0] = 0x00110102;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)level;
cmdbuf[3] = (u32)option_name;
cmdbuf[4] = (u32)*data_len;
cmdbuf[5] = 0x20;
saved_threadstorage[0] = cmdbuf[0x100>>2];
saved_threadstorage[1] = cmdbuf[0x104>>2];
cmdbuf[0x100>>2] = ((*data_len)<<14) | 2;
cmdbuf[0x104>>2] = (u32)data;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1];
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret==0)*data_len = cmdbuf[3];
if(ret<0)return -1;
return ret;
}
int setsockopt(int sockfd, int level, int option_name, const void * data, int data_len)
{
int ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00120104;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)level;
cmdbuf[3] = (u32)option_name;
cmdbuf[4] = (u32)data_len;
cmdbuf[5] = 0x20;
cmdbuf[7] = (data_len<<14) | 0x2402;
cmdbuf[8] = (u32)data;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
return ret;
}
int fcntl(int sockfd, int cmd, ...)
{
int ret=0;
int arg=0;
u32 *cmdbuf = getThreadCommandBuffer();
va_list args;
va_start(args, cmd);
if(cmd!=F_GETFL && cmd!=F_SETFL)
{
SOCU_errno = -EINVAL;
return -1;
}
if(cmd==F_SETFL)
{
arg = va_arg(args, int);
if(arg && arg!=O_NONBLOCK)
{
SOCU_errno = -EINVAL;
return -1;
}
if(arg==O_NONBLOCK)arg = 0x4;
}
cmdbuf[0] = 0x001300C2;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)cmd;
cmdbuf[3] = (u32)arg;
cmdbuf[4] = 0x20;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
return ret;
}
int sockatmark(int sockfd)
{
int ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00150042;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = 0x20;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
return ret;
}
long gethostid()
{
int ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00160000;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
if(ret==0)ret = cmdbuf[2];
return ret;
}
int getsockname(int sockfd, struct sockaddr *addr, int * addr_len)
{
int ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[2];
u8 tmpaddr[0x1c];
cmdbuf[0] = 0x00170082;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = 0x1c;
cmdbuf[3] = 0x20;
saved_threadstorage[0] = cmdbuf[0x100>>2];
saved_threadstorage[1] = cmdbuf[0x104>>2];
cmdbuf[0x100>>2] = (0x1c<<14) | 2;
cmdbuf[0x104>>2] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1];
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret==0)
{
addr->sa_family = tmpaddr[1];
if(*addr_len > tmpaddr[0])*addr_len = tmpaddr[0];
memset(addr, 0, sizeof(struct sockaddr));
memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
}
if(ret<0)return -1;
return ret;
}
int getpeername(int sockfd, struct sockaddr *addr, int * addr_len)
{
int ret=0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[2];
u8 tmpaddr[0x1c];
cmdbuf[0] = 0x00180082;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = 0x1c;
cmdbuf[3] = 0x20;
saved_threadstorage[0] = cmdbuf[0x100>>2];
saved_threadstorage[1] = cmdbuf[0x104>>2];
cmdbuf[0x100>>2] = (0x1c<<14) | 2;
cmdbuf[0x104>>2] = (u32)tmpaddr;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1];
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret==0)
{
addr->sa_family = tmpaddr[1];
if(*addr_len > tmpaddr[0])*addr_len = tmpaddr[0];
memset(addr, 0, sizeof(struct sockaddr));
memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
}
if(ret<0)return -1;
return ret;
}

View File

@ -76,6 +76,12 @@ svc_createEvent:
str r1, [r2] str r1, [r2]
bx lr bx lr
.global svc_signalEvent
.type svc_signalEvent, %function
svc_signalEvent:
svc 0x18
bx lr
.global svc_clearEvent .global svc_clearEvent
.type svc_clearEvent, %function .type svc_clearEvent, %function
svc_clearEvent: svc_clearEvent:
@ -128,6 +134,12 @@ svc_waitSynchronizationN:
ldr r5, [sp], #4 ldr r5, [sp], #4
bx lr bx lr
.global svc_getSystemTick
.type svc_getSystemTick, %function
svc_getSystemTick:
svc 0x28
bx lr
.global svc_getSystemInfo .global svc_getSystemInfo
.type svc_getSystemInfo, %function .type svc_getSystemInfo, %function
svc_getSystemInfo: svc_getSystemInfo:
@ -154,3 +166,12 @@ svc_connectToPort:
svc_sendSyncRequest: svc_sendSyncRequest:
svc 0x32 svc 0x32
bx lr bx lr
.global svc_getProcessId
.type svc_getProcessId, %function
svc_getProcessId:
str r0, [sp,#-0x4]!
svc 0x35
ldr r3, [sp], #4
str r1, [r3]
bx lr

View File

@ -2,7 +2,7 @@ CC = arm-none-eabi-gcc
LINK = arm-none-eabi-ld LINK = arm-none-eabi-ld
AS = arm-none-eabi-as AS = arm-none-eabi-as
OBJCOPY = arm-none-eabi-objcopy OBJCOPY = arm-none-eabi-objcopy
CTRULIB = "../libctru" CTRULIB = ../libctru
CFLAGS += -Wall -std=c99 -march=armv6 -O3 -I"$(CTRULIB)/include" -I$(DEVKITPRO)/libnds/include CFLAGS += -Wall -std=c99 -march=armv6 -O3 -I"$(CTRULIB)/include" -I$(DEVKITPRO)/libnds/include
LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib" LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib"
@ -28,7 +28,10 @@ endef
.PHONY:=all .PHONY:=all
all: $(PROJECTNAME).bin all: dir $(PROJECTNAME).bin
dir:
@mkdir -p build
ctrulib: ctrulib:
cd $(CTRULIB) && make cd $(CTRULIB) && make

View File

@ -1,4 +1,4 @@
.section ".text" .section ".init"
.arm .arm
.align 4 .align 4
.global _init .global _init

View File

@ -137,7 +137,10 @@ int main()
aptSetupEventHandler(); aptSetupEventHandler();
while(!aptGetStatus()) APP_STATUS status;
while((status=aptGetStatus())!=APP_EXITING)
{
if(status==APP_RUNNING)
{ {
u32 PAD=hidSharedMem[7]; u32 PAD=hidSharedMem[7];
renderEffect(); renderEffect();
@ -147,10 +150,19 @@ int main()
GSPGPU_WriteHWRegs(NULL, 0x202A04, &regData, 4); GSPGPU_WriteHWRegs(NULL, 0x202A04, &regData, 4);
svc_sleepThread(1000000000); svc_sleepThread(1000000000);
} }
else if(status == APP_SUSPENDING)
{
aptReturnToMenu();
}
else if(status == APP_SLEEPMODE)
{
aptWaitStatusEvent();
}
}
svc_closeHandle(fsuHandle); svc_closeHandle(fsuHandle);
hidExit(); hidExit();
gspGpuInit(); gspGpuExit();
aptExit(); aptExit();
svc_exitProcess(); svc_exitProcess();
return 0; return 0;