]> Chaos Git - corbenik/ctrulib.git/commitdiff
added gfx for simplified framebuffer access
authorsmea <smealum@gmail.com>
Mon, 25 Aug 2014 04:37:49 +0000 (21:37 -0700)
committersmea <smealum@gmail.com>
Mon, 25 Aug 2014 04:37:49 +0000 (21:37 -0700)
libctru/include/3ds/gfx.h [new file with mode: 0644]
libctru/source/gfx.c [new file with mode: 0644]

diff --git a/libctru/include/3ds/gfx.h b/libctru/include/3ds/gfx.h
new file mode 100644 (file)
index 0000000..27f941b
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef GFX_H
+#define GFX_H
+
+#include <3ds/types.h>
+
+typedef enum
+{
+       GFX_TOP = 0,
+       GFX_BOTTOM = 1
+}gfxScreen_t;
+
+typedef enum
+{
+       GFX_LEFT = 0,
+       GFX_RIGHT = 1,
+       // GFX_BOTTOM = 0
+}gfx3dSide_t;
+
+//system stuff
+void gfxInit();
+void gfxExit();
+
+//control stuff
+void gfxSet3D(bool enable);
+void gfxFlushBuffers();
+void gfxSwapBuffers();
+
+//helper stuff
+u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
+
+//global variables
+extern u8* gfxTopLeftFramebuffers[2];
+extern u8* gfxSubFramebuffers[2];
+extern u8* gfxBottomFramebuffers[2];
+
+#endif
diff --git a/libctru/source/gfx.c b/libctru/source/gfx.c
new file mode 100644 (file)
index 0000000..a55b4f4
--- /dev/null
@@ -0,0 +1,145 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <3ds/types.h>
+#include <3ds/GSP.h>
+#include <3ds/GX.h>
+#include <3ds/svc.h>
+#include <3ds/gfx.h>
+
+GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo;
+
+u8* gfxTopLeftFramebuffers[2];
+u8* gfxTopRightFramebuffers[2];
+u8* gfxBottomFramebuffers[2];
+
+u8 currentBuffer;
+bool enable3d;
+
+Handle gspEvent, gspSharedMemHandle;
+
+u8* gspHeap;
+u32* gxCmdBuf;
+
+void gfxSet3D(bool enable)
+{
+       enable3d=enable;
+}
+
+void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id)
+{
+       if(screen==GFX_TOP)
+       {
+               topFramebufferInfo.active_framebuf=id;
+               topFramebufferInfo.framebuf0_vaddr=(u32*)gfxTopLeftFramebuffers[id];
+               if(enable3d)topFramebufferInfo.framebuf1_vaddr=(u32*)gfxTopRightFramebuffers[id];
+               else topFramebufferInfo.framebuf1_vaddr=topFramebufferInfo.framebuf0_vaddr;
+               topFramebufferInfo.framebuf_widthbytesize=240*3;
+               topFramebufferInfo.format=((1)<<8)|((1)<<6)|((enable3d&1)<<5)|GSP_BGR8_OES;
+               topFramebufferInfo.framebuf_dispselect=id;
+               topFramebufferInfo.unk=0x00000000;
+       }else{
+               bottomFramebufferInfo.active_framebuf=id;
+               bottomFramebufferInfo.framebuf0_vaddr=(u32*)gfxBottomFramebuffers[id];
+               bottomFramebufferInfo.framebuf1_vaddr=0x00000000;
+               bottomFramebufferInfo.framebuf_widthbytesize=240*3;
+               bottomFramebufferInfo.format=GSP_BGR8_OES;
+               bottomFramebufferInfo.framebuf_dispselect=id;
+               bottomFramebufferInfo.unk=0x00000000;
+       }
+}
+
+void gfxInit()
+{
+       gspInit();
+
+       GSPGPU_AcquireRight(NULL, 0x0);
+       GSPGPU_SetLcdForceBlack(NULL, 0x0);
+
+       //setup our gsp shared mem section
+       u8 threadID;
+       svcCreateEvent(&gspEvent, 0x0);
+       GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &threadID);
+       svcMapMemoryBlock(gspSharedMemHandle, 0x10002000, 0x3, 0x10000000);
+
+       //map GSP heap
+       svcControlMemory((u32*)&gspHeap, 0x0, 0x0, 0x02000000, 0x10003, 0x3);
+
+       // default gspHeap configuration :
+       //              topleft1  0x00000000-0x00046500
+       //              topleft2  0x00046500-0x0008CA00
+       //              bottom1   0x0008CA00-0x000C4E00
+       //              bottom2   0x000C4E00-0x000FD200
+       //       if 3d enabled :
+       //              topright1 0x000FD200-0x00143700
+       //              topright2 0x00143700-0x00189C00
+
+       gfxTopLeftFramebuffers[0]=(u8*)gspHeap;
+       gfxTopLeftFramebuffers[1]=gfxTopLeftFramebuffers[0]+0x46500;
+       gfxBottomFramebuffers[0]=gfxTopLeftFramebuffers[1]+0x46500;
+       gfxBottomFramebuffers[1]=gfxBottomFramebuffers[0]+0x38400;
+       gfxTopRightFramebuffers[0]=gfxBottomFramebuffers[1]+0x38400;
+       gfxTopRightFramebuffers[1]=gfxTopRightFramebuffers[0]+0x46500;
+       enable3d=false;
+
+       //initialize framebuffer info structures
+       gfxSetFramebufferInfo(GFX_TOP, 0);
+       gfxSetFramebufferInfo(GFX_BOTTOM, 0);
+
+       //wait until we can write stuff to it
+       svcWaitSynchronization(gspEvent, 0x55bcb0);
+
+       //GSP shared mem : 0x2779F000
+       gxCmdBuf=(u32*)(0x10002000+0x800+threadID*0x200);
+
+       currentBuffer=0;
+}
+
+void gfxExit()
+{
+       //free GSP heap
+       svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, 0x02000000, MEMOP_FREE, 0x0);
+
+       //unmap GSP shared mem
+       svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);
+
+       GSPGPU_UnregisterInterruptRelayQueue(NULL);
+
+       svcCloseHandle(gspSharedMemHandle);
+       svcCloseHandle(gspEvent);
+
+       GSPGPU_ReleaseRight(NULL);
+       
+       gspExit();
+}
+
+u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height)
+{
+       if(width)*width=240;
+
+       if(screen==GFX_TOP)
+       {
+               if(height)*height=400;
+               return (side==GFX_LEFT || !enable3d)?(gfxTopLeftFramebuffers[currentBuffer^1]):(gfxTopRightFramebuffers[currentBuffer^1]);
+       }else{
+               if(height)*height=320;
+               return gfxBottomFramebuffers[currentBuffer^1];
+       }
+}
+
+void gfxFlushBuffers()
+{
+       GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 0x46500);
+       if(enable3d)GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), 0x46500);
+       GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), 0x38400);
+}
+
+void gfxSwapBuffers()
+{
+       currentBuffer^=1;
+       gfxSetFramebufferInfo(GFX_TOP, currentBuffer);
+       gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer);
+       GSPGPU_SetBufferSwap(NULL, GFX_TOP, &topFramebufferInfo);
+       GSPGPU_SetBufferSwap(NULL, GFX_BOTTOM, &bottomFramebufferInfo);
+}