]> Chaos Git - corbenik/ctrulib.git/commitdiff
initial commit
authorsmea <smealum@gmail.com>
Sat, 18 Jan 2014 22:18:03 +0000 (23:18 +0100)
committersmea <smealum@gmail.com>
Sat, 18 Jan 2014 22:18:03 +0000 (23:18 +0100)
13 files changed:
arm11u/Makefile [new file with mode: 0644]
arm11u/source/crt0.s [new file with mode: 0644]
arm11u/source/main.c [new file with mode: 0644]
libctru/Makefile [new file with mode: 0644]
libctru/include/ctr/APT.h [new file with mode: 0644]
libctru/include/ctr/GSP.h [new file with mode: 0644]
libctru/include/ctr/srv.h [new file with mode: 0644]
libctru/include/ctr/svc.h [new file with mode: 0644]
libctru/include/ctr/types.h [new file with mode: 0644]
libctru/source/APT.c [new file with mode: 0644]
libctru/source/GSP.c [new file with mode: 0644]
libctru/source/srv.c [new file with mode: 0644]
libctru/source/svc.s [new file with mode: 0644]

diff --git a/arm11u/Makefile b/arm11u/Makefile
new file mode 100644 (file)
index 0000000..02d2192
--- /dev/null
@@ -0,0 +1,38 @@
+CC = arm-none-eabi-gcc
+LINK = arm-none-eabi-ld
+OBJCOPY = arm-none-eabi-objcopy
+CTRULIB = "../libctru"
+CFLAGS += -Wall -std=c99 -march=armv6 -O0 -I"$(CTRULIB)/include"
+LDFLAGS += --script=ccd00.ld -L"$(DEVKITARM)/arm-none-eabi/lib" -L"$(CTRULIB)/lib"
+
+CFILES = $(wildcard source/*.c)
+OFILES = $(CFILES:source/%.c=build/%.o)
+DFILES = $(CFILES:source/%.c=build/%.d)
+SFILES = $(wildcard source/*.s)
+OFILES += $(SFILES:source/%.s=build/%.o)
+PROJECTNAME = ${shell basename "$(CURDIR)"}
+
+.PHONY:=all
+
+all: $(PROJECTNAME).bin
+
+$(PROJECTNAME).bin: $(PROJECTNAME).elf
+       $(OBJCOPY) -O binary $< $@
+
+$(PROJECTNAME).elf: $(OFILES)
+       $(LINK) $(LDFLAGS) -o $(PROJECTNAME).elf $(filter-out build/crt0.o, $(OFILES)) -lctru -lc
+
+clean:
+       @rm -f build/*.o build/*.d
+       @rm -f $(PROJECTNAME).elf $(PROJECTNAME).bin
+       @echo "all cleaned up !"
+
+-include $(DFILES)
+
+build/%.o: source/%.c
+       $(CC) $(CFLAGS) -c $< -o $@
+       @$(CC) -MM $< > build/$*.d
+
+build/%.o: source/%.s
+       $(CC) $(CFLAGS) -c $< -o $@
+       @$(CC) -MM $< > build/$*.d
diff --git a/arm11u/source/crt0.s b/arm11u/source/crt0.s
new file mode 100644 (file)
index 0000000..6463bc2
--- /dev/null
@@ -0,0 +1,12 @@
+.section ".text"
+.arm
+.align 4
+.global _init
+.global _start
+
+_start:
+       blx __libc_init_array
+       blx main
+
+_init:
+       bx lr
diff --git a/arm11u/source/main.c b/arm11u/source/main.c
new file mode 100644 (file)
index 0000000..8842b97
--- /dev/null
@@ -0,0 +1,101 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctr/types.h>
+#include <ctr/srv.h>
+#include <ctr/APT.h>
+#include <ctr/GSP.h>
+#include <ctr/svc.h>
+
+int main()
+{
+       Handle srvHandle, aptuHandle;
+       
+       getSrvHandle(&srvHandle);
+       
+       //initialize APT stuff, escape load screen
+       srv_getServiceHandle(srvHandle, &aptuHandle, "APT:U");
+       APT_GetLockHandle(aptuHandle, 0x0, NULL);
+       svc_closeHandle(aptuHandle);
+       svc_sleepThread(0x50000);
+       
+       Handle hmEvent;
+       srv_getServiceHandle(srvHandle, &aptuHandle, "APT:U");
+       APT_Initialize(aptuHandle, 0x300, &hmEvent, NULL);
+       svc_closeHandle(aptuHandle);
+       svc_sleepThread(0x50000);
+       
+       srv_getServiceHandle(srvHandle, &aptuHandle, "APT:U");
+       APT_Enable(aptuHandle, 0x0);
+       svc_closeHandle(aptuHandle);
+       svc_sleepThread(0x50000);
+
+       //do stuff with GPU...
+       Handle gspGpuHandle;
+       srv_getServiceHandle(srvHandle, &gspGpuHandle, "gsp::Gpu");
+
+       GSPGPU_AcquireRight(gspGpuHandle, 0x0);
+       GSPGPU_SetLcdForceBlack(gspGpuHandle, 0x0);
+
+       //set subscreen to blue
+       u32 regData=0x01FF0000;
+       GSPGPU_WriteHWRegs(gspGpuHandle, 0x202A04, (u8*)&regData, 4);
+
+       //grab main left screen framebuffer addresses
+       u8* topLeftFramebuffers[2];
+       GSPGPU_ReadHWRegs(gspGpuHandle, 0x400468, (u8*)&topLeftFramebuffers, 8);
+
+       //convert PA to VA (assuming FB in VRAM)
+       topLeftFramebuffers[0]+=0x7000000;
+       topLeftFramebuffers[1]+=0x7000000;
+
+       //setup our gsp shared mem section
+       u8 threadID;
+       Handle gspEvent, gspSharedMemHandle;
+       svc_createEvent(&gspEvent, 0x0);
+       GSPGPU_RegisterInterruptRelayQueue(gspGpuHandle, gspEvent, 0x1, &gspSharedMemHandle, &threadID);
+       svc_mapMemoryBlock(gspSharedMemHandle, 0x10002000, 0x3, 0x10000000);
+
+       //map GSP heap
+       u8* gspHeap;
+       svc_controlMemory((u32*)&gspHeap, 0x0, 0x0, 0x2000000, 0x10003, 0x3);
+
+       int i;
+       for(i=1;i<0x600000;i++)
+       {
+               gspHeap[i]=0xFF^gspHeap[i-1];
+       }
+
+       //wait until we can write stuff to it
+       svc_waitSynchronization1(gspEvent, 0x55bcb0);
+
+       // //GSP shared mem : 0x2779F000
+       // //write GX command ! (to GSP shared mem, at 0x10002000)
+       u32* gxCmdBuf=(u32*)(0x10002000+0x800+threadID*0x200);
+       u32 gxCommand[0x8];
+
+       //GX RequestDma
+       gxCommand[0]=0x00; //CommandID
+       gxCommand[1]=(u32)gspHeap; //source address
+       // gxCommand[2]=(u32)topLeftFramebuffers[0]; //destination address
+       gxCommand[2]=0x1F000000; //destination address
+       // gxCommand[3]=0x5DC00*2; //size
+       gxCommand[3]=0x600000; //size
+       gxCommand[4]=gxCommand[5]=gxCommand[6]=gxCommand[7]=0x0;
+
+       GSPGPU_submitGxCommand(gxCmdBuf, gxCommand, gspGpuHandle);
+
+       // debug
+       regData=0x010000FF;
+       GSPGPU_WriteHWRegs(gspGpuHandle, 0x202A04, (u8*)&regData, 4);
+
+       svc_waitSynchronization1(hmEvent, 0xffffffffffffffff);
+
+       // debug
+       regData=0x0100FFFF;
+       GSPGPU_WriteHWRegs(gspGpuHandle, 0x202A04, (u8*)&regData, 4);
+
+       while(1);
+
+       return 0;
+}
diff --git a/libctru/Makefile b/libctru/Makefile
new file mode 100644 (file)
index 0000000..92c78e4
--- /dev/null
@@ -0,0 +1,36 @@
+CC = arm-none-eabi-gcc
+AR = arm-none-eabi-ar
+CFLAGS += -Wall -std=c99 -march=armv6 -O0 -I"$(CURDIR)/include/"
+
+CFILES = $(wildcard source/*.c)
+OFILES = $(CFILES:source/%.c=build/%.o)
+DFILES = $(CFILES:source/%.c=build/%.d)
+SFILES = $(wildcard source/*.s)
+OFILES += $(SFILES:source/%.s=build/%.o)
+PROJECTNAME = "libctru"
+
+.PHONY:=all dir
+
+all: dir lib/$(PROJECTNAME).a
+
+dir:
+       mkdir -p build
+       mkdir -p lib
+
+lib/$(PROJECTNAME).a: $(OFILES)
+       $(AR) rvs $@ $^
+
+clean:
+       @rm -f build/*.o build/*.d
+       @rm -f $(PROJECTNAME).a
+       @echo "all cleaned up !"
+
+-include $(DFILES)
+
+build/%.o: source/%.c
+       $(CC) $(CFLAGS) -c $< -o $@
+       @$(CC) -MM $< > build/$*.d
+
+build/%.o: source/%.s
+       $(CC) $(CFLAGS) -c $< -o $@
+       @$(CC) -MM $< > build/$*.d
diff --git a/libctru/include/ctr/APT.h b/libctru/include/ctr/APT.h
new file mode 100644 (file)
index 0000000..c184400
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef APT_H
+#define APT_H
+
+void APT_GetLockHandle(Handle handle, u16 flags, Handle* lockHandle);
+void APT_Initialize(Handle handle, u32 a, Handle* eventHandle1, Handle* eventHandle2);
+Result APT_Enable(Handle handle, u32 a);
+Result APT_PrepareToJumpToHomeMenu(Handle handle);
+Result APT_JumpToHomeMenu(Handle handle, u32 a, u32 b, u32 c);
+
+#endif
diff --git a/libctru/include/ctr/GSP.h b/libctru/include/ctr/GSP.h
new file mode 100644 (file)
index 0000000..b3bae75
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef GSP_H
+#define GSP_H
+
+void GSPGPU_AcquireRight(Handle handle, u8 flags);
+void GSPGPU_SetLcdForceBlack(Handle handle, u8 flags);
+void GSPGPU_WriteHWRegs(Handle handle, u32 regAddr, u8* data, u8 size);
+void GSPGPU_ReadHWRegs(Handle handle, u32 regAddr, u8* data, u8 size);
+void GSPGPU_RegisterInterruptRelayQueue(Handle handle, Handle eventHandle, u32 flags, Handle* outMemHandle, u8* threadID);
+Result GSPGPU_TriggerCmdReqQueue(Handle handle);
+Result GSPGPU_submitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x20], Handle handle);
+
+#endif
diff --git a/libctru/include/ctr/srv.h b/libctru/include/ctr/srv.h
new file mode 100644 (file)
index 0000000..7c3f302
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef SRV_H
+#define SRV_H
+
+
+Result srv_10002(Handle handle);
+void getSrvHandle(Handle* out);
+void srv_getServiceHandle(Handle handle, Handle* out, char* server);
+
+#endif
diff --git a/libctru/include/ctr/svc.h b/libctru/include/ctr/svc.h
new file mode 100644 (file)
index 0000000..a692bef
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef SVC_H
+#define SVC_H
+
+       u32* svc_getData(void);
+       void svc_sleepThread(s64 ns);
+       Result svc_controlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, u32 operation, u32 permissions); //(outaddr is usually the same as the input addr0)
+       Result svc_createEvent(Handle* event, u8 resettype);
+       Result svc_mapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission);
+       Result svc_waitSynchronization1(Handle handle, s64 nanoseconds);
+       Result svc_closeHandle(Handle handle);
+       Result svc_connectToPort(volatile Handle* out, const char* portName);
+       Result svc_sendSyncRequest(Handle session);
+
+#endif
diff --git a/libctru/include/ctr/types.h b/libctru/include/ctr/types.h
new file mode 100644 (file)
index 0000000..5e59346
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef TYPES_H
+#define TYPES_H
+
+       #include <stdint.h>
+
+       typedef unsigned char u8;
+       typedef unsigned short u16;
+       typedef unsigned int u32;
+       typedef unsigned long long u64;
+
+       typedef signed char s8;
+       typedef signed short s16;
+       typedef signed int s32;
+       typedef signed long long s64;
+
+       typedef u32 Handle;
+       typedef u32 Result;
+
+#endif
diff --git a/libctru/source/APT.c b/libctru/source/APT.c
new file mode 100644 (file)
index 0000000..853f1b2
--- /dev/null
@@ -0,0 +1,55 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctr/types.h>
+#include <ctr/APT.h>
+#include <ctr/svc.h>
+
+void APT_GetLockHandle(Handle handle, u16 flags, Handle* lockHandle)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x10040; //request header code
+       svcData[1]=flags;
+       svc_sendSyncRequest(handle); //check return value...
+       if(lockHandle)*lockHandle=svcData[1];
+}
+
+void APT_Initialize(Handle handle, u32 a, Handle* eventHandle1, Handle* eventHandle2)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x20080; //request header code
+       svcData[1]=a;
+       svcData[2]=0x0;
+       svc_sendSyncRequest(handle); //check return value...
+       if(eventHandle1)*eventHandle1=svcData[3]; //return to menu event ?
+       if(eventHandle2)*eventHandle2=svcData[4];
+}
+
+Result APT_Enable(Handle handle, u32 a)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x30040; //request header code
+       svcData[1]=a;
+       svc_sendSyncRequest(handle); //check return value...
+       return svcData[1];
+}
+
+Result APT_PrepareToJumpToHomeMenu(Handle handle)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x2b0000; //request header code
+       svc_sendSyncRequest(handle); //check return value...
+       return svcData[1];
+}
+
+Result APT_JumpToHomeMenu(Handle handle, u32 a, u32 b, u32 c)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x2C0044; //request header code
+       svcData[1]=a;
+       svcData[2]=b;
+       svcData[3]=c;
+       svcData[4]=(b<<14)|2;
+       svc_sendSyncRequest(handle); //check return value...
+       return svcData[1];
+}
diff --git a/libctru/source/GSP.c b/libctru/source/GSP.c
new file mode 100644 (file)
index 0000000..9413f2d
--- /dev/null
@@ -0,0 +1,114 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctr/types.h>
+#include <ctr/GSP.h>
+#include <ctr/svc.h>
+
+
+void GSPGPU_AcquireRight(Handle handle, u8 flags)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x160042; //request header code
+       svcData[1]=flags;
+       svcData[2]=0x0;
+       svcData[3]=0xffff8001;
+       svc_sendSyncRequest(handle); //check return value...
+}
+
+void GSPGPU_SetLcdForceBlack(Handle handle, u8 flags)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0xB0040; //request header code
+       svcData[1]=flags;
+       svc_sendSyncRequest(handle); //check return value...
+}
+
+void GSPGPU_WriteHWRegs(Handle handle, u32 regAddr, u8* data, u8 size)
+{
+       if(size>0x80 || !data)return;
+
+       u32* svcData=svc_getData();
+       svcData[0]=0x10082; //request header code
+       svcData[1]=regAddr;
+       svcData[2]=size;
+       svcData[3]=(size<<14)|2;
+       svcData[4]=(u32)data;
+       svc_sendSyncRequest(handle); //check return value...
+}
+
+void GSPGPU_ReadHWRegs(Handle handle, u32 regAddr, u8* data, u8 size)
+{
+       if(size>0x80 || !data)return;
+
+       u32* svcData=svc_getData();
+       svcData[0]=0x40080; //request header code
+       svcData[1]=regAddr;
+       svcData[2]=size;
+       svcData[0x40]=(size<<14)|2;
+       svcData[0x40+1]=(u32)data;
+       svc_sendSyncRequest(handle); //check return value...
+}
+
+void GSPGPU_RegisterInterruptRelayQueue(Handle handle, Handle eventHandle, u32 flags, Handle* outMemHandle, u8* threadID)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x130042; //request header code
+       svcData[1]=flags;
+       svcData[2]=0x0;
+       svcData[3]=eventHandle;
+       svc_sendSyncRequest(handle); //check return value...
+       if(threadID)*threadID=svcData[2];
+       if(outMemHandle)*outMemHandle=svcData[4];
+}
+
+Result GSPGPU_TriggerCmdReqQueue(Handle handle)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0xC0000; //request header code
+       svc_sendSyncRequest(handle); //check return value...
+       return svcData[0];
+}
+
+//essentially : get commandIndex and totalCommands, calculate offset of new command, copy command and update totalCommands
+//use LDREX/STREX because this data may also be accessed by the GSP module and we don't want to break stuff
+//(mostly, we could overwrite the buffer header with wrong data and make the GSP module reexecute old commands)
+Result GSPGPU_submitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle handle)
+{
+       if(!sharedGspCmdBuf || !gxCommand)return -1;
+
+       u32 cmdBufHeader;
+       __asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
+
+       u8 commandIndex=cmdBufHeader&0xFF;
+       u8 totalCommands=(cmdBufHeader>>8)&0xFF;
+
+       if(totalCommands>15)return -2;
+
+       u8 nextCmd=(commandIndex+totalCommands)%15; //there are 15 command slots
+       u32* dst=&sharedGspCmdBuf[8*(1+nextCmd)];
+       memcpy(dst, gxCommand, 0x20);
+
+       u32 mcrVal=0x0;
+       __asm__ ("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (mcrVal)); //Data Synchronization Barrier Register
+       totalCommands++;
+       cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8);
+
+       while(1)
+       {
+               u32 strexResult;
+               __asm__ ("strex %[result], %[val], [%[adr]]" : [result] "=r" (strexResult) : [adr] "r" (sharedGspCmdBuf), [val] "r" (cmdBufHeader));
+               if(!strexResult)break;
+
+               __asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
+               totalCommands=((cmdBufHeader&0xFF00)>>8)+1;
+               cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)|0xFF00);
+       }
+
+       if(totalCommands==1)
+       {
+               GSPGPU_TriggerCmdReqQueue(handle);
+       }
+
+       return 0;
+}
diff --git a/libctru/source/srv.c b/libctru/source/srv.c
new file mode 100644 (file)
index 0000000..cf4e4a2
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctr/types.h>
+#include <ctr/srv.h>
+#include <ctr/svc.h>
+
+Result srv_10002(Handle handle)
+{
+       u32* svcData=svc_getData();
+       svcData[0]=0x10002; //request header code
+       svcData[1]=0x20;
+       svc_sendSyncRequest(handle); //check return value...
+       return svcData[1];
+}
+
+void getSrvHandle(Handle* out)
+{
+       if(!out)return;
+
+       svc_connectToPort(out, "srv:");
+       srv_10002(*out);
+}
+
+void srv_getServiceHandle(Handle handle, Handle* out, char* server)
+{
+       u8 l=strlen(server);
+       if(!out || !server || l>8)return;
+       u32* svcData=svc_getData();
+       svcData[0]=0x50100; //request header code
+       strcpy((char*)&svcData[1], server);
+       svcData[3]=l;
+       svcData[4]=0x0;
+       svc_sendSyncRequest(handle); //check return value...
+       *out=svcData[3];
+}
diff --git a/libctru/source/svc.s b/libctru/source/svc.s
new file mode 100644 (file)
index 0000000..a7cca5d
--- /dev/null
@@ -0,0 +1,72 @@
+.arm
+
+.align 4
+
+.global svc_getData
+.type svc_getData, %function
+svc_getData:
+       mrc p15, 0, r0, c13, c0, 3
+       add r0, #0x80
+       bx lr
+
+
+.global svc_controlMemory
+.type svc_controlMemory, %function
+svc_controlMemory:
+       stmfd sp!, {r0, r4}
+       ldr R0, [sp, #0x8]
+       ldr r4, [sp, #0x8+0x4]
+       svc 0x01
+       ldr r2, [sp]
+       str r1, [r2]
+       ldr r4, [sp, #4]!
+       add sp, sp, #4
+       bx lr
+
+.global svc_sleepThread
+.type svc_sleepThread, %function
+svc_sleepThread:
+       svc 0x0A
+       bx lr
+
+.global svc_createEvent
+.type svc_createEvent, %function
+svc_createEvent:
+       str r0, [sp,#-4]!
+       svc 0x17
+       ldr r2, [sp], #4
+       str r1, [r2]
+       bx lr
+
+.global svc_mapMemoryBlock
+.type svc_mapMemoryBlock, %function
+svc_mapMemoryBlock:
+       svc 0x1F
+       bx lr
+
+.global svc_closeHandle
+.type svc_closeHandle, %function
+svc_closeHandle:
+       svc 0x23
+       bx lr
+
+.global svc_waitSynchronization1
+.type svc_waitSynchronization1, %function
+svc_waitSynchronization1:
+       svc 0x24
+       bx lr
+
+.global svc_connectToPort
+.type svc_connectToPort, %function
+svc_connectToPort:
+       str r0, [sp,#-0x4]!
+       svc 0x2D
+       ldr r3, [sp], #4
+       str r1, [r3]
+       bx lr
+
+.global svc_sendSyncRequest
+.type svc_sendSyncRequest, %function
+svc_sendSyncRequest:
+       svc 0x32
+       bx lr