From 9fcca821fe7da2d3bab7d46ff73389308be11484 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 21 Apr 2014 19:12:56 -0400 Subject: [PATCH 01/21] Added code for using the CSND service. --- libctru/include/ctr/CSND.h | 18 ++ libctru/source/CSND.c | 325 +++++++++++++++++++++++++++++++++++++ 2 files changed, 343 insertions(+) create mode 100644 libctru/include/ctr/CSND.h create mode 100644 libctru/source/CSND.c diff --git a/libctru/include/ctr/CSND.h b/libctru/include/ctr/CSND.h new file mode 100644 index 0000000..36d3352 --- /dev/null +++ b/libctru/include/ctr/CSND.h @@ -0,0 +1,18 @@ +#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); +Result CSND_sharedmemtype0_cmdupdatestate(int waitdone); + +Result CSND_getchannelstate(u32 entryindex, u32 *out); +Result CSND_getchannelstate_isplaying(u32 entryindex, u8 *status); + +#endif + diff --git a/libctru/source/CSND.c b/libctru/source/CSND.c new file mode 100644 index 0000000..6ab2a7c --- /dev/null +++ b/libctru/source/CSND.c @@ -0,0 +1,325 @@ +#include +#include +#include +#include + +#include +#include +#include + +//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; +} + From a3be8c58b3d5d89c8dd957146d53777db2cf444c Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 21 Apr 2014 22:58:05 -0400 Subject: [PATCH 02/21] Added code for using the ac:u service. --- libctru/include/ctr/AC.h | 8 ++++ libctru/source/AC.c | 87 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 libctru/include/ctr/AC.h create mode 100644 libctru/source/AC.c diff --git a/libctru/include/ctr/AC.h b/libctru/include/ctr/AC.h new file mode 100644 index 0000000..dd3e78a --- /dev/null +++ b/libctru/include/ctr/AC.h @@ -0,0 +1,8 @@ +#ifndef AC_H +#define AC_H + +Result ACU_GetWifiStatus(Handle servhandle, u32 *out); +Result ACU_WaitInternetConnection(); + +#endif + diff --git a/libctru/source/AC.c b/libctru/source/AC.c new file mode 100644 index 0000000..87242ea --- /dev/null +++ b/libctru/source/AC.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include + +#include +#include +#include + +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; +} + From 06dfc9aaceefd4ed078fd7e6ca3646b8f0570421 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 22 Apr 2014 15:15:46 -0400 Subject: [PATCH 03/21] Added code for using the ir:u service. --- libctru/include/ctr/IR.h | 15 +++ libctru/source/IR.c | 237 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 libctru/include/ctr/IR.h create mode 100644 libctru/source/IR.c diff --git a/libctru/include/ctr/IR.h b/libctru/include/ctr/IR.h new file mode 100644 index 0000000..8c09d66 --- /dev/null +++ b/libctru/include/ctr/IR.h @@ -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 + diff --git a/libctru/source/IR.c b/libctru/source/IR.c new file mode 100644 index 0000000..0600662 --- /dev/null +++ b/libctru/source/IR.c @@ -0,0 +1,237 @@ +#include +#include +#include + +#include +#include +#include + +#include + +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; +} + From c5250ab5676661717ab26158dd4890cc61975f46 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 22 Apr 2014 16:13:18 -0400 Subject: [PATCH 04/21] Added code for the cfg:nor service. --- libctru/include/ctr/CFGNOR.h | 12 ++++ libctru/source/CFGNOR.c | 113 +++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 libctru/include/ctr/CFGNOR.h create mode 100644 libctru/source/CFGNOR.c diff --git a/libctru/include/ctr/CFGNOR.h b/libctru/include/ctr/CFGNOR.h new file mode 100644 index 0000000..b6ca73d --- /dev/null +++ b/libctru/include/ctr/CFGNOR.h @@ -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 + diff --git a/libctru/source/CFGNOR.c b/libctru/source/CFGNOR.c new file mode 100644 index 0000000..c8695d8 --- /dev/null +++ b/libctru/source/CFGNOR.c @@ -0,0 +1,113 @@ +#include +#include +#include + +#include +#include +#include + +#include + +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>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>2], chunksize); + if(ret!=0)break; + } + + return ret; +} + From c69bc04dffe6d1286190a66724bea6bd333c6955 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 22 Apr 2014 20:18:21 -0400 Subject: [PATCH 05/21] Added GSPGPU code for SetBufferSwap and InvalidateDataCache. --- libctru/include/ctr/GSP.h | 13 +++++++++++++ libctru/source/GSP.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/libctru/include/ctr/GSP.h b/libctru/include/ctr/GSP.h index b38bd23..3b16f2e 100644 --- a/libctru/include/ctr/GSP.h +++ b/libctru/include/ctr/GSP.h @@ -3,13 +3,26 @@ #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; + Result gspInit(); void gspExit(); Result GSPGPU_AcquireRight(Handle *handle, u8 flags); Result GSPGPU_ReleaseRight(Handle *handle); 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_InvalidateDataCache(Handle* handle, u8 *adr, u32 size); Result GSPGPU_WriteHWRegs(Handle *handle, u32 regAddr, u32* data, u8 size); Result GSPGPU_WriteHWRegsWithMask(Handle* handle, u32 regAddr, u32* data, u8 datasize, u32* maskdata, u8 masksize); Result GSPGPU_ReadHWRegs(Handle *handle, u32 regAddr, u32* data, u8 size); diff --git a/libctru/source/GSP.c b/libctru/source/GSP.c index c71e107..ea557eb 100644 --- a/libctru/source/GSP.c +++ b/libctru/source/GSP.c @@ -61,6 +61,22 @@ Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags) 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) { if(!handle)handle=&gspGpuHandle; @@ -78,6 +94,24 @@ Result GSPGPU_FlushDataCache(Handle* handle, u8* adr, u32 size) return cmdbuf[1]; } +Result GSPGPU_InvalidateDataCache(Handle* handle, u8 *adr, u32 size) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + if(!handle)handle=&gspGpuHandle; + + cmdbuf[0] = 0x00090082; + cmdbuf[1] = (u32)adr; + cmdbuf[2] = size; + cmdbuf[3] = 0; + cmdbuf[4] = 0xFFFF8001; + + if((ret=svc_sendSyncRequest(*handle)))return ret; + + return cmdbuf[1]; +} + Result GSPGPU_WriteHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size) { if(!handle)handle=&gspGpuHandle; From 4a1619f7c702360869cc382b4ef8f2371d0d3d21 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 27 Apr 2014 21:28:48 -0400 Subject: [PATCH 06/21] Added svc_signalEvent, svc_getSystemTick, and svc_getProcessId. Enabled using SOC cmd8/cmda, and other minor changes. --- libctru/include/ctr/CSND.h | 1 + libctru/include/ctr/SOC.h | 2 +- libctru/include/ctr/svc.h | 3 ++ libctru/source/SOC.c | 72 +++++++++++++++++++------------------- libctru/source/svc.s | 21 +++++++++++ 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/libctru/include/ctr/CSND.h b/libctru/include/ctr/CSND.h index 36d3352..070f19e 100644 --- a/libctru/include/ctr/CSND.h +++ b/libctru/include/ctr/CSND.h @@ -9,6 +9,7 @@ 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); diff --git a/libctru/include/ctr/SOC.h b/libctru/include/ctr/SOC.h index 2bb2e7c..3dc33ef 100644 --- a/libctru/include/ctr/SOC.h +++ b/libctru/include/ctr/SOC.h @@ -1,7 +1,7 @@ #ifndef 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(); int SOC_GetErrno(); diff --git a/libctru/include/ctr/svc.h b/libctru/include/ctr/svc.h index e28cade..d9cae4e 100644 --- a/libctru/include/ctr/svc.h +++ b/libctru/include/ctr/svc.h @@ -24,6 +24,7 @@ typedef enum{ Result svc_createMutex(Handle* mutex, bool initialLocked); Result svc_releaseMutex(Handle handle); Result svc_createEvent(Handle* event, u8 resettype); + Result svc_signalEvent(Handle handle); Result svc_clearEvent(Handle handle); Result svc_createMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 mypermission, 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_waitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 nanoseconds); Result svc_closeHandle(Handle handle); + u64 svc_getSystemTick(); Result svc_getSystemInfo(s64* out, u32 type, s32 param); Result svc_connectToPort(volatile Handle* out, const char* portName); Result svc_sendSyncRequest(Handle session); + Result svc_getProcessId(u32 *out, Handle handle); #endif diff --git a/libctru/source/SOC.c b/libctru/source/SOC.c index 86ddc60..2ebddac 100644 --- a/libctru/source/SOC.c +++ b/libctru/source/SOC.c @@ -10,8 +10,8 @@ #include #include -static Handle socu_handle = 0; -static int soc_errno = 0; +Handle SOCU_handle = 0; +static int SOCU_errno = 0; Result socu_cmd1(Handle memhandle, u32 memsize) { @@ -24,7 +24,7 @@ Result socu_cmd1(Handle memhandle, u32 memsize) cmdbuf[4] = 0; cmdbuf[5] = memhandle; - if((ret = svc_sendSyncRequest(socu_handle))!=0)return ret; + if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; return cmdbuf[1]; } @@ -36,14 +36,14 @@ Result SOC_Shutdown() 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]; } -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; Handle memhandle = 0; @@ -51,14 +51,14 @@ Result SOC_Initialize(u32 *context_addr, u32 context_size)//Example context_size ret = svc_createMemoryBlock(&memhandle, (u32)context_addr, context_size, 0, 3); 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); } int SOC_GetErrno() { - return soc_errno; + return SOCU_errno; } int socket(int domain, int type, int protocol) @@ -72,10 +72,10 @@ int socket(int domain, int type, int protocol) cmdbuf[3] = protocol; 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]; - soc_errno = ret; + SOCU_errno = ret; if(ret!=0)return -1; return (int)cmdbuf[2]; @@ -90,11 +90,11 @@ int closesocket(int sockfd) cmdbuf[1] = (u32)sockfd; 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]; if(ret==0)ret = (int)cmdbuf[2]; - soc_errno = ret; + SOCU_errno = ret; if(ret!=0)return -1; return 0; @@ -110,11 +110,11 @@ int shutdown(int sockfd, int shutdown_type) cmdbuf[2] = (u32)shutdown_type; 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]; if(ret==0)ret = (int)cmdbuf[2]; - soc_errno = ret; + SOCU_errno = ret; if(ret!=0)return -1; return 0; @@ -130,11 +130,11 @@ int listen(int sockfd, int max_connections) cmdbuf[2] = (u32)max_connections; 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]; if(ret==0)ret = (int)cmdbuf[2]; - soc_errno = ret; + SOCU_errno = ret; if(ret!=0)return -1; return 0; @@ -161,14 +161,14 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen) cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; 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[0x104>>2] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; if(ret==0)ret = (int)cmdbuf[2]; - if(ret<0)soc_errno = ret; + if(ret<0)SOCU_errno = ret; if(ret>=0 && addr!=NULL) { @@ -186,8 +186,8 @@ int bind(int sockfd, const struct sockaddr *addr, int addrlen) { int ret=0; u32 *cmdbuf = getThreadCommandBuffer(); + //struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; u8 tmpaddr[8]; - struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; addrlen = 8; tmpaddr[0] = 8; @@ -201,11 +201,11 @@ int bind(int sockfd, const struct sockaddr *addr, int addrlen) cmdbuf[5] = (((u32)addrlen)<<14) | 2; 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]; if(ret==0)ret = (int)cmdbuf[2]; - soc_errno = ret; + SOCU_errno = ret; if(ret<0)return -1; return 0; @@ -215,8 +215,8 @@ int connect(int sockfd, const struct sockaddr *addr, int addrlen) { int ret=0; u32 *cmdbuf = getThreadCommandBuffer(); + //struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; u8 tmpaddr[8]; - struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; addrlen = 8; tmpaddr[0] = 8; @@ -230,11 +230,11 @@ int connect(int sockfd, const struct sockaddr *addr, int addrlen) cmdbuf[5] = (((u32)addrlen)<<14) | 2; 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]; if(ret==0)ret = (int)cmdbuf[2]; - soc_errno = ret; + SOCU_errno = ret; if(ret<0)return -1; return 0; @@ -265,14 +265,14 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; 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[0x104>>2] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; if(ret==0)ret = (int)cmdbuf[2]; - if(ret<0)soc_errno = ret; + if(ret<0)SOCU_errno = ret; if(ret<0)return -1; return ret; @@ -305,7 +305,7 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; 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[0x104>>2] = saved_threadstorage[1]; @@ -314,13 +314,13 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src ret = (int)cmdbuf[1]; if(ret==0)ret = (int)cmdbuf[2]; - if(ret<0)soc_errno = ret; + if(ret<0)SOCU_errno = ret; if(ret<0)return -1; 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; u32 *cmdbuf = getThreadCommandBuffer(); @@ -340,17 +340,17 @@ int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, struct sockadd cmdbuf[9] = (((u32)len)<<4) | 10; 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]; if(ret==0)ret = (int)cmdbuf[2]; - if(ret<0)soc_errno = ret; + if(ret<0)SOCU_errno = ret; if(ret<0)return -1; 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; u32 *cmdbuf = getThreadCommandBuffer(); @@ -370,11 +370,11 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, struct sockadd cmdbuf[9] = (tmp_addrlen<<14) | 0x402; 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]; if(ret==0)ret = (int)cmdbuf[2]; - if(ret<0)soc_errno = ret; + if(ret<0)SOCU_errno = ret; if(ret<0)return -1; return ret; @@ -382,13 +382,13 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, struct sockadd 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. { - //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); } 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); } diff --git a/libctru/source/svc.s b/libctru/source/svc.s index 903ed31..7716f60 100644 --- a/libctru/source/svc.s +++ b/libctru/source/svc.s @@ -76,6 +76,12 @@ svc_createEvent: str r1, [r2] bx lr +.global svc_signalEvent +.type svc_signalEvent, %function +svc_signalEvent: + svc 0x18 + bx lr + .global svc_clearEvent .type svc_clearEvent, %function svc_clearEvent: @@ -128,6 +134,12 @@ svc_waitSynchronizationN: ldr r5, [sp], #4 bx lr +.global svc_getSystemTick +.type svc_getSystemTick, %function +svc_getSystemTick: + svc 0x28 + bx lr + .global svc_getSystemInfo .type svc_getSystemInfo, %function svc_getSystemInfo: @@ -154,3 +166,12 @@ svc_connectToPort: svc_sendSyncRequest: svc 0x32 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 From d3a9f1443e0555832361e15c1e5d2125172e8498 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 30 Apr 2014 18:55:04 -0400 Subject: [PATCH 07/21] rename "test_vsh_bin" to "test_shbin" to fix build of gpu demo --- gpu/source/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gpu/source/main.c b/gpu/source/main.c index b9c51e6..b8bb001 100644 --- a/gpu/source/main.c +++ b/gpu/source/main.c @@ -11,7 +11,7 @@ #include #include #include "costable.h" -#include "test_vsh_bin.h" +#include "test_shbin.h" u8* gspHeap; u32* gxCmdBuf; @@ -101,7 +101,7 @@ int main() 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; while((status=aptGetStatus())!=APP_EXITING) From 7a5d01108af50daca091905244a3aafe2dcdc3cc Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 4 May 2014 21:55:59 -0400 Subject: [PATCH 08/21] Added SOC error conversion, and implemented getsockopt, setsockopt, fcntl, sockatmark, gethostid, getsockname, and getpeername. --- libctru/source/SOC.c | 329 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 318 insertions(+), 11 deletions(-) diff --git a/libctru/source/SOC.c b/libctru/source/SOC.c index 2ebddac..e9f5472 100644 --- a/libctru/source/SOC.c +++ b/libctru/source/SOC.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,10 +10,104 @@ #include #include #include +#include +#include +#include Handle SOCU_handle = 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 ret=0; @@ -78,7 +173,7 @@ int socket(int domain, int type, int protocol) SOCU_errno = ret; if(ret!=0)return -1; - return (int)cmdbuf[2]; + return _net_convert_error(cmdbuf[2]); } int closesocket(int sockfd) @@ -93,7 +188,7 @@ int closesocket(int sockfd) if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret =_net_convert_error(cmdbuf[2]); SOCU_errno = ret; if(ret!=0)return -1; @@ -113,7 +208,7 @@ int shutdown(int sockfd, int shutdown_type) if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); SOCU_errno = ret; if(ret!=0)return -1; @@ -133,7 +228,7 @@ int listen(int sockfd, int max_connections) if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); SOCU_errno = ret; if(ret!=0)return -1; @@ -167,7 +262,7 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen) cmdbuf[0x104>>2] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); if(ret<0)SOCU_errno = ret; if(ret>=0 && addr!=NULL) @@ -204,7 +299,7 @@ int bind(int sockfd, const struct sockaddr *addr, int addrlen) if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); SOCU_errno = ret; if(ret<0)return -1; @@ -233,7 +328,7 @@ int connect(int sockfd, const struct sockaddr *addr, int addrlen) if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); SOCU_errno = ret; if(ret<0)return -1; @@ -271,7 +366,7 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src cmdbuf[0x104>>2] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); if(ret<0)SOCU_errno = ret; if(ret<0)return -1; @@ -313,7 +408,7 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src cmdbuf[0x10c>>2] = saved_threadstorage[3]; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); if(ret<0)SOCU_errno = ret; if(ret<0)return -1; @@ -343,7 +438,7 @@ int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, const struct s if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); if(ret<0)SOCU_errno = ret; if(ret<0)return -1; @@ -373,7 +468,7 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, const struct s if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; ret = (int)cmdbuf[1]; - if(ret==0)ret = (int)cmdbuf[2]; + if(ret==0)ret = _net_convert_error(cmdbuf[2]); if(ret<0)SOCU_errno = ret; if(ret<0)return -1; @@ -402,3 +497,215 @@ int send(int sockfd, const void *buf, int len, int flags) 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]; + 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]; + memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2); + } + + if(ret<0)return -1; + return ret; +} + From e20c97a050b7735a06aab5258072a30ebfeb816f Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Wed, 7 May 2014 17:19:33 +0100 Subject: [PATCH 09/21] remove dodgy wchar type, use UINT64_MAX from stdint.h for U64_MAX --- libctru/include/ctr/types.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libctru/include/ctr/types.h b/libctru/include/ctr/types.h index d61eea8..85cb47c 100644 --- a/libctru/include/ctr/types.h +++ b/libctru/include/ctr/types.h @@ -4,7 +4,7 @@ #include #include - #define U64_MAX (0xFFFFFFFFFFFFFFFF) + #define U64_MAX UINT64_MAX typedef uint8_t u8; typedef uint16_t u16; @@ -26,8 +26,6 @@ typedef volatile s32 vs32; typedef volatile s64 vs64; - typedef u16 wchar; - typedef u32 Handle; typedef s32 Result; typedef void (*ThreadFunc)(u32); From 7560f2f8ef95689e6a55907deac26607e821d7f9 Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Wed, 7 May 2014 18:01:19 +0100 Subject: [PATCH 10/21] ignore generated folders --- libctru/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 libctru/.gitignore diff --git a/libctru/.gitignore b/libctru/.gitignore new file mode 100644 index 0000000..a76bc14 --- /dev/null +++ b/libctru/.gitignore @@ -0,0 +1,2 @@ +build +lib From 271464ffc225cee7bb93222167adb1c14c0a329b Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 10 May 2014 17:22:22 -0400 Subject: [PATCH 11/21] Improved SOC addr handling, and implemented addr handling for the sendto/recvfrom cmds. --- libctru/source/SOC.c | 153 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 124 insertions(+), 29 deletions(-) diff --git a/libctru/source/SOC.c b/libctru/source/SOC.c index e9f5472..2d9865e 100644 --- a/libctru/source/SOC.c +++ b/libctru/source/SOC.c @@ -238,12 +238,12 @@ int listen(int sockfd, int max_connections) int accept(int sockfd, struct sockaddr *addr, int *addrlen) { int ret=0; + int tmp_addrlen=0x1c; u32 *cmdbuf = getThreadCommandBuffer(); - u8 tmpaddr[8]; - int tmp_addrlen=8; + u8 tmpaddr[0x1c]; u32 saved_threadstorage[2]; - memset(tmpaddr, 0, 8); + memset(tmpaddr, 0, 0x1c); cmdbuf[0] = 0x00040082; cmdbuf[1] = (u32)sockfd; @@ -267,10 +267,9 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen) if(ret>=0 && addr!=NULL) { - *addrlen = tmpaddr[0]; - memset(addr, 0, sizeof(struct sockaddr)); 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; @@ -280,20 +279,36 @@ int accept(int sockfd, struct sockaddr *addr, int *addrlen) int bind(int sockfd, const struct sockaddr *addr, int addrlen) { int ret=0; + int tmp_addrlen=0; u32 *cmdbuf = getThreadCommandBuffer(); - //struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; - u8 tmpaddr[8]; + u8 tmpaddr[0x1c]; - addrlen = 8; - tmpaddr[0] = 8; + memset(tmpaddr, 0, 0x1c); + + 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; - memcpy(&tmpaddr[2], &addr->sa_data, addrlen-2); + memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2); cmdbuf[0] = 0x00050084; cmdbuf[1] = (u32)sockfd; - cmdbuf[2] = (u32)addrlen; + cmdbuf[2] = (u32)tmp_addrlen; cmdbuf[3] = 0x20; - cmdbuf[5] = (((u32)addrlen)<<14) | 2; + cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2; cmdbuf[6] = (u32)tmpaddr; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; @@ -309,20 +324,36 @@ int bind(int sockfd, const struct sockaddr *addr, int addrlen) int connect(int sockfd, const struct sockaddr *addr, int addrlen) { int ret=0; + int tmp_addrlen=0; u32 *cmdbuf = getThreadCommandBuffer(); - //struct sockaddr_in *inaddr = (struct sockaddr_in*)addr; - u8 tmpaddr[8]; + u8 tmpaddr[0x1c]; - addrlen = 8; - tmpaddr[0] = 8; + memset(tmpaddr, 0, 0x1c); + + 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; - memcpy(&tmpaddr[2], &addr->sa_data, addrlen-2); + memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2); cmdbuf[0] = 0x00060084; cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)addrlen; cmdbuf[3] = 0x20; - cmdbuf[5] = (((u32)addrlen)<<14) | 2; + cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2; cmdbuf[6] = (u32)tmpaddr; if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret; @@ -339,11 +370,13 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src { int ret=0; u32 *cmdbuf = getThreadCommandBuffer(); - u8 tmpaddr[8]; u32 tmp_addrlen=0; + u8 tmpaddr[0x1c]; u32 saved_threadstorage[2]; - memset(tmpaddr, 0, 8); + memset(tmpaddr, 0, 0x1c); + + if(src_addr)tmp_addrlen = 0x1c; cmdbuf[0] = 0x00070104; cmdbuf[1] = (u32)sockfd; @@ -369,6 +402,13 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src if(ret==0)ret = _net_convert_error(cmdbuf[2]); 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; return ret; } @@ -376,12 +416,14 @@ int socuipc_cmd7(int sockfd, void *buf, int len, int flags, struct sockaddr *src int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src_addr, int *addrlen) { int ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - u8 tmpaddr[8]; + u32 *cmdbuf = getThreadCommandBuffer(); u32 tmp_addrlen=0; + u8 tmpaddr[0x1c]; u32 saved_threadstorage[4]; - memset(tmpaddr, 0, 8); + if(src_addr)tmp_addrlen = 0x1c; + + memset(tmpaddr, 0, 0x1c); cmdbuf[0] = 0x00080102; cmdbuf[1] = (u32)sockfd; @@ -411,6 +453,13 @@ int socuipc_cmd8(int sockfd, void *buf, int len, int flags, struct sockaddr *src if(ret==0)ret = _net_convert_error(cmdbuf[2]); 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; return ret; } @@ -419,10 +468,32 @@ int socuipc_cmd9(int sockfd, const void *buf, int len, int flags, const struct s { int ret=0; u32 *cmdbuf = getThreadCommandBuffer(); - u8 tmpaddr[8]; 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[1] = (u32)sockfd; @@ -449,10 +520,32 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, const struct s { int ret=0; u32 *cmdbuf = getThreadCommandBuffer(); - u8 tmpaddr[8]; - int 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] = 0x000A0106; cmdbuf[1] = (u32)sockfd; @@ -664,6 +757,7 @@ int getsockname(int sockfd, struct sockaddr *addr, int * addr_len) { 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); } @@ -702,6 +796,7 @@ int getpeername(int sockfd, struct sockaddr *addr, int * addr_len) { 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); } From 9714dad3092affbe85c1b09b15ac0f002fc6a910 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 10 May 2014 21:25:26 -0400 Subject: [PATCH 12/21] Removed outdated SOC comment. --- libctru/source/SOC.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/source/SOC.c b/libctru/source/SOC.c index 2d9865e..3cc884f 100644 --- a/libctru/source/SOC.c +++ b/libctru/source/SOC.c @@ -568,7 +568,7 @@ int socuipc_cmda(int sockfd, const void *buf, int len, int flags, const struct s 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); return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen); From 0e1b6ebe434ce196f2e22566bd05ec193b59a8a4 Mon Sep 17 00:00:00 2001 From: ichfly Date: Tue, 20 May 2014 16:14:47 +0200 Subject: [PATCH 13/21] added FSFILE_SetSize --- libctru/source/FS.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libctru/source/FS.c b/libctru/source/FS.c index 53697e8..aa38297 100644 --- a/libctru/source/FS.c +++ b/libctru/source/FS.c @@ -189,6 +189,21 @@ Result FSFILE_GetSize(Handle handle, u64 *size) 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) { u32 *cmdbuf=getThreadCommandBuffer(); From 624775d80e8757390eeb930963444bf290e87b43 Mon Sep 17 00:00:00 2001 From: ichfly Date: Tue, 20 May 2014 17:21:48 +0200 Subject: [PATCH 14/21] added prototype --- libctru/include/ctr/FS.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libctru/include/ctr/FS.h b/libctru/include/ctr/FS.h index cc9f65b..7073fef 100644 --- a/libctru/include/ctr/FS.h +++ b/libctru/include/ctr/FS.h @@ -47,6 +47,7 @@ Result FSFILE_Close(Handle handle); 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_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_Close(Handle handle); From 8c656065a41d7c7ee558a59fc19a1f7817e19050 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 20 May 2014 15:49:03 -0400 Subject: [PATCH 15/21] Implemented more APT and GSPGPU commands. Improved return-to-menu handling, screenshots for the suspended application are now handled as well. Implemented power-button handling, and implemented sleep-mode handling. Updated the example apps for the APT changes, and fixed other issues with the examples. --- arm11u/Makefile | 2 +- arm11u/source/crt0.s | 2 +- arm11u/source/main.c | 8 ++ gpu/Makefile | 4 +- gpu/source/crt0.s | 2 +- gpu/source/main.c | 8 ++ libctru/include/ctr/APT.h | 12 +- libctru/include/ctr/GSP.h | 16 +++ libctru/source/APT.c | 231 ++++++++++++++++++++++++++++++++++++-- libctru/source/GSP.c | 46 ++++++++ sdmc/Makefile | 7 +- sdmc/source/crt0.s | 2 +- sdmc/source/main.c | 30 +++-- 13 files changed, 342 insertions(+), 28 deletions(-) diff --git a/arm11u/Makefile b/arm11u/Makefile index 8f02861..ca643f4 100644 --- a/arm11u/Makefile +++ b/arm11u/Makefile @@ -1,7 +1,7 @@ CC = arm-none-eabi-gcc LINK = arm-none-eabi-ld OBJCOPY = arm-none-eabi-objcopy -CTRULIB = "../libctru" +CTRULIB = ../libctru 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" diff --git a/arm11u/source/crt0.s b/arm11u/source/crt0.s index 6463bc2..557c327 100644 --- a/arm11u/source/crt0.s +++ b/arm11u/source/crt0.s @@ -1,4 +1,4 @@ -.section ".text" +.section ".init" .arm .align 4 .global _init diff --git a/arm11u/source/main.c b/arm11u/source/main.c index 027a117..6cc7f83 100644 --- a/arm11u/source/main.c +++ b/arm11u/source/main.c @@ -139,6 +139,14 @@ int main() swapBuffers(); copyBuffer(); } + else if(status == APP_SUSPENDING) + { + aptReturnToMenu(); + } + else if(status == APP_SLEEPMODE) + { + aptWaitStatusEvent(); + } svc_sleepThread(16666666); } diff --git a/gpu/Makefile b/gpu/Makefile index 6591a65..4840710 100644 --- a/gpu/Makefile +++ b/gpu/Makefile @@ -2,8 +2,8 @@ CC = arm-none-eabi-gcc LINK = arm-none-eabi-gcc AS = arm-none-eabi-as OBJCOPY = arm-none-eabi-objcopy -CTRULIB = "../libctru" -AEMSTROPATH = "../../aemstro" +CTRULIB = ../libctru +AEMSTROPATH = ../../aemstro 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"$(CTRULIB)/lib" diff --git a/gpu/source/crt0.s b/gpu/source/crt0.s index 6463bc2..557c327 100644 --- a/gpu/source/crt0.s +++ b/gpu/source/crt0.s @@ -1,4 +1,4 @@ -.section ".text" +.section ".init" .arm .align 4 .global _init diff --git a/gpu/source/main.c b/gpu/source/main.c index b8bb001..097e09b 100644 --- a/gpu/source/main.c +++ b/gpu/source/main.c @@ -128,6 +128,14 @@ int main() swapBuffers(); } + else if(status == APP_SUSPENDING) + { + aptReturnToMenu(); + } + else if(status == APP_SLEEPMODE) + { + aptWaitStatusEvent(); + } svc_sleepThread(16666666); } diff --git a/libctru/include/ctr/APT.h b/libctru/include/ctr/APT.h index 06a24f9..a5c2e94 100644 --- a/libctru/include/ctr/APT.h +++ b/libctru/include/ctr/APT.h @@ -9,9 +9,12 @@ typedef enum{ }NS_APPID; // cf http://3dbrew.org/wiki/NS#AppIDs typedef enum{ + APT_NOTINITIALIZED, APP_RUNNING, APP_SUSPENDED, - APP_EXITING + APP_EXITING, + APP_SUSPENDING, + APP_SLEEPMODE }APP_STATUS; extern Handle aptEvents[3]; @@ -23,6 +26,10 @@ void aptCloseSession(); void aptSetupEventHandler(); void aptSetStatus(APP_STATUS status); 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(); Result APT_GetLockHandle(Handle* handle, u16 flags, Handle* lockHandle); Result APT_Initialize(Handle* handle, NS_APPID appId, Handle* eventHandle1, Handle* eventHandle2); @@ -34,7 +41,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_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_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_ReplySleepNotificationComplete(Handle* handle, NS_APPID appID); Result APT_PrepareToCloseApplication(Handle* handle, u8 a); Result APT_CloseApplication(Handle* handle, u32 a, u32 b, u32 c); diff --git a/libctru/include/ctr/GSP.h b/libctru/include/ctr/GSP.h index 3b16f2e..57f3cdf 100644 --- a/libctru/include/ctr/GSP.h +++ b/libctru/include/ctr/GSP.h @@ -14,11 +14,27 @@ typedef struct 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(); void gspExit(); Result GSPGPU_AcquireRight(Handle *handle, u8 flags); 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_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *framebufinfo); Result GSPGPU_FlushDataCache(Handle *handle, u8* adr, u32 size); diff --git a/libctru/source/APT.c b/libctru/source/APT.c index 63ece7f..e9ccdfd 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -19,13 +19,117 @@ Handle aptEventHandlerThread; u64 aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]; //u64 so that it's 8-byte aligned Handle aptStatusMutex; -u32 aptStatus; +Handle aptStatusEvent = 0; +u32 aptStatus = APT_NOTINITIALIZED; +u32 aptStatusPower = 0; 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 aptReturnToMenu() +{ + u32 tmp0 = 1, tmp1 = 0; + u32 ns_capinfo[0x20>>2]; + u32 tmp_params[0x20>>2]; + + /*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); + + aptOpenSession(); + APT_SendParameter(NULL, currentAppId, 0x101, 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) { bool runThread=true; + while(runThread) { s32 syncedID=0x0; @@ -45,18 +149,37 @@ void aptEventHandler(u32 arg) switch(signalType) { case 0x1: //home menu button got pressed - aptOpenSession(); - APT_PrepareToJumpToHomeMenu(NULL); //prepare for return to menu - aptCloseSession(); + case 0x8: //power button got pressed + if(aptGetStatus()==APP_RUNNING) + { + aptOpenSession(); + APT_ReplySleepQuery(NULL, currentAppId, 0x0); + aptCloseSession(); - aptSetStatus(APP_SUSPENDED); - - GSPGPU_ReleaseRight(NULL); //disable GSP module access - + 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. + } + + break; + + case 0x3: //preparing to enter sleep-mode aptOpenSession(); - APT_JumpToHomeMenu(NULL, 0x0, 0x0, 0x0); //jump ! + APT_ReplySleepQuery(NULL, currentAppId, 0x1); aptCloseSession(); break; + + case 0x5: //entering sleep-mode + aptOpenSession(); + APT_ReplySleepNotificationComplete(NULL, currentAppId); + aptCloseSession(); + aptSetStatus(APP_SLEEPMODE); + break; + + case 0x6: //leaving sleep-mode + GSPGPU_SetLcdForceBlack(NULL, 0); + aptSetStatus(APP_RUNNING); + break; } } break; @@ -73,6 +196,7 @@ void aptEventHandler(u32 arg) break; case 0xB: //just returned from menu GSPGPU_AcquireRight(NULL, 0x0); + GSPGPU_RestoreVramSysArea(NULL); aptSetStatus(APP_RUNNING); break; case 0xC: //exiting application @@ -116,6 +240,8 @@ Result aptInit(NS_APPID appID) aptOpenSession(); if((ret=APT_NotifyToWait(NULL, currentAppId)))return ret; aptCloseSession(); + + svc_createEvent(&aptStatusEvent, 0); return 0; } @@ -153,6 +279,7 @@ void aptExit() svc_closeHandle(aptStatusMutex); // svc_closeHandle(aptLockHandle); + svc_closeHandle(aptStatusEvent); } void aptSetupEventHandler() @@ -185,6 +312,8 @@ void aptSetupEventHandler() aptStatus=0; svc_releaseMutex(aptStatusMutex); + aptSetStatus(APP_RUNNING); + //create thread for stuff handling APT events svc_createThread(&aptEventHandlerThread, aptEventHandler, 0x0, (u32*)(&aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]), 0x31, 0xfffffffe); } @@ -200,8 +329,35 @@ APP_STATUS aptGetStatus() void aptSetStatus(APP_STATUS status) { + u32 prevstatus; + svc_waitSynchronization1(aptStatusMutex, U64_MAX); - aptStatus=status; + + prevstatus = status; + aptStatus = status; + + if(prevstatus!=APT_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); } @@ -380,6 +536,47 @@ Result APT_ReceiveParameter(Handle* handle, NS_APPID appID, u32 bufferSize, u32* 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) { if(!handle)handle=&aptuHandle; @@ -395,6 +592,20 @@ Result APT_ReplySleepQuery(Handle* handle, NS_APPID appID, u32 a) 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) { if(!handle)handle=&aptuHandle; diff --git a/libctru/source/GSP.c b/libctru/source/GSP.c index ea557eb..a47acdd 100644 --- a/libctru/source/GSP.c +++ b/libctru/source/GSP.c @@ -47,6 +47,52 @@ Result GSPGPU_ReleaseRight(Handle* handle) 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) { if(!handle)handle=&gspGpuHandle; diff --git a/sdmc/Makefile b/sdmc/Makefile index 4196b20..197fe4e 100644 --- a/sdmc/Makefile +++ b/sdmc/Makefile @@ -2,7 +2,7 @@ CC = arm-none-eabi-gcc LINK = arm-none-eabi-ld AS = arm-none-eabi-as OBJCOPY = arm-none-eabi-objcopy -CTRULIB = "../libctru" +CTRULIB = ../libctru 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" @@ -28,7 +28,10 @@ endef .PHONY:=all -all: $(PROJECTNAME).bin +all: dir $(PROJECTNAME).bin + +dir: + @mkdir -p build ctrulib: cd $(CTRULIB) && make diff --git a/sdmc/source/crt0.s b/sdmc/source/crt0.s index 6463bc2..557c327 100644 --- a/sdmc/source/crt0.s +++ b/sdmc/source/crt0.s @@ -1,4 +1,4 @@ -.section ".text" +.section ".init" .arm .align 4 .global _init diff --git a/sdmc/source/main.c b/sdmc/source/main.c index b146328..0fbf9b8 100644 --- a/sdmc/source/main.c +++ b/sdmc/source/main.c @@ -137,20 +137,32 @@ int main() aptSetupEventHandler(); - while(!aptGetStatus()) + APP_STATUS status; + while((status=aptGetStatus())!=APP_EXITING) { - u32 PAD=hidSharedMem[7]; - renderEffect(); - swapBuffers(); - copyBuffer(); - u32 regData=PAD|0x01000000; - GSPGPU_WriteHWRegs(NULL, 0x202A04, ®Data, 4); - svc_sleepThread(1000000000); + if(status==APP_RUNNING) + { + u32 PAD=hidSharedMem[7]; + renderEffect(); + swapBuffers(); + copyBuffer(); + u32 regData=PAD|0x01000000; + GSPGPU_WriteHWRegs(NULL, 0x202A04, ®Data, 4); + svc_sleepThread(1000000000); + } + else if(status == APP_SUSPENDING) + { + aptReturnToMenu(); + } + else if(status == APP_SLEEPMODE) + { + aptWaitStatusEvent(); + } } svc_closeHandle(fsuHandle); hidExit(); - gspGpuInit(); + gspGpuExit(); aptExit(); svc_exitProcess(); return 0; From 07bd9aa357f9a002f17c224e34a8f771944823d3 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 20 May 2014 23:27:50 -0400 Subject: [PATCH 16/21] Fixed issues involving application termination. This fixed the applet launch hang after launching a ctrulib app, and fixed the issue where the power/HOME buttons did not work correctly under the power-off screen. --- libctru/source/APT.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libctru/source/APT.c b/libctru/source/APT.c index e9ccdfd..0aafd34 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -200,10 +200,6 @@ void aptEventHandler(u32 arg) aptSetStatus(APP_RUNNING); break; case 0xC: //exiting application - aptOpenSession(); - APT_ReplySleepQuery(NULL, currentAppId, 0x0); - aptCloseSession(); - runThread=false; aptSetStatus(APP_EXITING); //app exit signal break; @@ -251,23 +247,37 @@ void aptExit() u8 buf1[4], buf2[4]; buf1[0]=0x02; buf1[1]=0x00; buf1[2]=0x00; buf1[3]=0x00; + + 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, 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(); + if(aptGetStatusPower()==1)//This is only executed when application-termination was triggered via the home-menu power-off screen. + { + aptOpenSession(); + APT_ReplySleepQuery(NULL, currentAppId, 0x0); + aptCloseSession(); + } aptOpenSession(); APT_PrepareToCloseApplication(NULL, 0x1); From 54757cfd6089d2e55b654acbb8a4a8255aedecb8 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Wed, 21 May 2014 12:43:58 -0400 Subject: [PATCH 17/21] Fixed issue where the application would no longer receive any NS signals/notifications once the system returns to the application, from home-menu. --- libctru/source/APT.c | 78 ++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/libctru/source/APT.c b/libctru/source/APT.c index 0aafd34..cdc3fd2 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -73,6 +73,37 @@ void aptWaitStatusEvent() 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(); +} + void aptReturnToMenu() { u32 tmp0 = 1, tmp1 = 0; @@ -197,6 +228,7 @@ void aptEventHandler(u32 arg) case 0xB: //just returned from menu GSPGPU_AcquireRight(NULL, 0x0); GSPGPU_RestoreVramSysArea(NULL); + aptAppletUtility_Exit_RetToApp(); aptSetStatus(APP_RUNNING); break; case 0xC: //exiting application @@ -244,33 +276,7 @@ Result aptInit(NS_APPID appID) void aptExit() { - u8 buf1[4], buf2[4]; - - buf1[0]=0x02; buf1[1]=0x00; buf1[2]=0x00; buf1[3]=0x00; - - 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(); + aptAppletUtility_Exit_RetToApp(); if(aptGetStatusPower()==1)//This is only executed when application-termination was triggered via the home-menu power-off screen. { @@ -296,7 +302,7 @@ void aptSetupEventHandler() { 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(); APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2); aptCloseSession(); @@ -314,6 +320,22 @@ void aptSetupEventHandler() APT_AppletUtility(NULL, NULL, 0x7, 0x4, buf1, 0x1, buf2); 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(); APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2); aptCloseSession(); From ce92c8b20db15be0da559ccfbe7fac61a394177f Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 22 May 2014 00:22:56 -0400 Subject: [PATCH 18/21] Implemented APT_GetAppletManInfo. Implemented loading the menu AppID with APT_GetAppletManInfo, instead of using a hard-coded AppID. --- libctru/include/ctr/APT.h | 2 ++ libctru/source/APT.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/libctru/include/ctr/APT.h b/libctru/include/ctr/APT.h index a5c2e94..3d5f5fa 100644 --- a/libctru/include/ctr/APT.h +++ b/libctru/include/ctr/APT.h @@ -30,10 +30,12 @@ u32 aptGetStatusPower();//This can be used when the status is APP_SUSPEND* to ch 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_Initialize(Handle* handle, NS_APPID appId, Handle* eventHandle1, Handle* eventHandle2); Result APT_Enable(Handle* handle, u32 a); +Result APT_GetAppletManInfo(Handle* handle, u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu_appid, NS_APPID *active_appid); Result APT_PrepareToJumpToHomeMenu(Handle* handle); Result APT_JumpToHomeMenu(Handle* handle, u32 a, u32 b, u32 c); Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType); diff --git a/libctru/source/APT.c b/libctru/source/APT.c index cdc3fd2..7e54cea 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -104,8 +104,20 @@ void aptAppletUtility_Exit_RetToApp() 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]; @@ -128,8 +140,10 @@ void aptReturnToMenu() aptInitCaptureInfo(ns_capinfo); + menu_appid = aptGetMenuAppID(); + aptOpenSession(); - APT_SendParameter(NULL, currentAppId, 0x101, 0x20, ns_capinfo, 0x0, 0x10); + APT_SendParameter(NULL, currentAppId, menu_appid, 0x20, ns_capinfo, 0x0, 0x10); aptCloseSession(); aptOpenSession(); @@ -450,6 +464,24 @@ Result APT_Enable(Handle* handle, u32 a) 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) { if(!handle)handle=&aptuHandle; From d99ab4310698c4e6c34927c742fbc139cc64b13e Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 22 May 2014 13:06:50 -0400 Subject: [PATCH 19/21] Enabled APT_AppletUtility code which was needed for aptReturnToMenu. --- libctru/source/APT.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libctru/source/APT.c b/libctru/source/APT.c index 7e54cea..4ae8e1d 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -122,9 +122,12 @@ void aptReturnToMenu() u32 ns_capinfo[0x20>>2]; u32 tmp_params[0x20>>2]; - /*aptOpenSession(); - APT_AppletUtility(NULL, NULL, 0x6, 0x4, (u8*)&tmp0, 0x1, (u8*)&tmp1); - aptCloseSession();*/ + 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 From 4260edd6c9c55e6c692db9fcf35766ffa45838ed Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 22 May 2014 13:56:16 -0400 Subject: [PATCH 20/21] Adjusted sleep-mode code so that the APP_STATUS on leaving sleep-mode, would be set to the status which was set when the prepare sleep-mode signal was triggered(and other minor changes). --- libctru/include/ctr/APT.h | 5 +++-- libctru/source/APT.c | 26 ++++++++++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/libctru/include/ctr/APT.h b/libctru/include/ctr/APT.h index 3d5f5fa..5ce2fd6 100644 --- a/libctru/include/ctr/APT.h +++ b/libctru/include/ctr/APT.h @@ -9,12 +9,13 @@ typedef enum{ }NS_APPID; // cf http://3dbrew.org/wiki/NS#AppIDs typedef enum{ - APT_NOTINITIALIZED, + APP_NOTINITIALIZED, APP_RUNNING, APP_SUSPENDED, APP_EXITING, APP_SUSPENDING, - APP_SLEEPMODE + APP_SLEEPMODE, + APP_PREPARE_SLEEPMODE }APP_STATUS; extern Handle aptEvents[3]; diff --git a/libctru/source/APT.c b/libctru/source/APT.c index 4ae8e1d..4b28fcd 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -20,7 +20,8 @@ u64 aptEventHandlerStack[APT_HANDLER_STACKSIZE/8]; //u64 so that it's 8-byte ali Handle aptStatusMutex; Handle aptStatusEvent = 0; -u32 aptStatus = APT_NOTINITIALIZED; +APP_STATUS aptStatus = APP_NOTINITIALIZED; +APP_STATUS aptStatus_beforesleepmode = APP_NOTINITIALIZED; u32 aptStatusPower = 0; u32 aptParameters[0x1000/4]; //TEMP @@ -212,21 +213,30 @@ void aptEventHandler(u32 arg) break; case 0x3: //preparing to enter sleep-mode + aptStatus_beforesleepmode = aptGetStatus(); + GSPGPU_SetLcdForceBlack(NULL, 1); aptOpenSession(); APT_ReplySleepQuery(NULL, currentAppId, 0x1); aptCloseSession(); + aptSetStatus(APP_PREPARE_SLEEPMODE); break; case 0x5: //entering sleep-mode - aptOpenSession(); - APT_ReplySleepNotificationComplete(NULL, currentAppId); - aptCloseSession(); - aptSetStatus(APP_SLEEPMODE); + if(aptGetStatus()==APP_PREPARE_SLEEPMODE) + { + aptOpenSession(); + APT_ReplySleepNotificationComplete(NULL, currentAppId); + aptCloseSession(); + aptSetStatus(APP_SLEEPMODE); + } break; case 0x6: //leaving sleep-mode - GSPGPU_SetLcdForceBlack(NULL, 0); - aptSetStatus(APP_RUNNING); + if(aptGetStatus()==APP_SLEEPMODE) + { + GSPGPU_SetLcdForceBlack(NULL, 0); + aptSetStatus(aptStatus_beforesleepmode); + } break; } } @@ -385,7 +395,7 @@ void aptSetStatus(APP_STATUS status) prevstatus = status; aptStatus = status; - if(prevstatus!=APT_NOTINITIALIZED) + if(prevstatus!=APP_NOTINITIALIZED) { if(status==APP_RUNNING)svc_signalEvent(aptStatusEvent); if(status==APP_EXITING)svc_signalEvent(aptStatusEvent); From 3e69e498bb0db4bc975201604bc0dc59da560a22 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 22 May 2014 14:21:39 -0400 Subject: [PATCH 21/21] Adjusted sleep-mode code so that on leaving sleep-mode, GSPGPU_SetLcdForceBlack() is only used when the status was APP_RUNNING(also removed GSPGPU_SetLcdForceBlack call for prepare sleep-mode signal). --- libctru/source/APT.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libctru/source/APT.c b/libctru/source/APT.c index 4b28fcd..f58a8de 100644 --- a/libctru/source/APT.c +++ b/libctru/source/APT.c @@ -214,7 +214,6 @@ void aptEventHandler(u32 arg) case 0x3: //preparing to enter sleep-mode aptStatus_beforesleepmode = aptGetStatus(); - GSPGPU_SetLcdForceBlack(NULL, 1); aptOpenSession(); APT_ReplySleepQuery(NULL, currentAppId, 0x1); aptCloseSession(); @@ -234,7 +233,7 @@ void aptEventHandler(u32 arg) case 0x6: //leaving sleep-mode if(aptGetStatus()==APP_SLEEPMODE) { - GSPGPU_SetLcdForceBlack(NULL, 0); + if(aptStatus_beforesleepmode == APP_RUNNING)GSPGPU_SetLcdForceBlack(NULL, 0); aptSetStatus(aptStatus_beforesleepmode); } break;