GPU_Init(NULL);
u32 gpuCmdSize=0x40000;
- u32* gpuCmd=(u32*)gfxAllocLinear(gpuCmdSize*4);
+ u32* gpuCmd=(u32*)linearAlloc(gpuCmdSize*4);
GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize);
- vertArray=(float*)gfxAllocLinear(0x100000);
- texData=(u32*)gfxAllocLinear(0x100000);
+ vertArray=(float*)linearAlloc(0x100000);
+ texData=(u32*)linearAlloc(0x100000);
memcpy(texData, test_png_bin, test_png_bin_size);
memcpy(vertArray, mdlData, sizeof(mdlData));
#include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
+#include <3ds/linear.h>
#include <3ds/os.h>
#include <3ds/gfx.h>
//helper stuff
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
-void* gfxAllocLinear(size_t size);
//global variables
extern u8* gfxTopLeftFramebuffers[2];
--- /dev/null
+#pragma once
+
+// Functions for allocating/deallocating memory from linear heap
+void* linearAlloc(size_t size);
+void* linearRealloc(void* mem, size_t size);
+void linearFree(void* mem);
Handle gspEvent, gspSharedMemHandle;
-u8* gspHeap;
u32* gxCmdBuf;
-extern u32 __gsp_heap_size;
-
-// TODO: this function is not thread-safe and you cannot 'free' this memory.
-void* gfxAllocLinear(size_t size)
-{
- static size_t currentOffset = 0;
- size_t free = __gsp_heap_size - currentOffset;
-
- if(free >= size)
- {
- currentOffset += size;
- return (void*) &gspHeap[currentOffset - size];
- }
-
- return NULL;
-}
-
void gfxSet3D(bool enable)
{
GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &gfxThreadID);
svcMapMemoryBlock(gspSharedMemHandle, (u32)gfxSharedMemory, 0x3, 0x10000000);
- //map GSP heap
- svcControlMemory((u32*)&gspHeap, 0x0, 0x0, __gsp_heap_size, 0x10003, 0x3);
-
// default gspHeap configuration :
// topleft1 0x00000000-0x00046500
// topleft2 0x00046500-0x0008CA00
// topright1 0x000FD200-0x00143700
// topright2 0x00143700-0x00189C00
- gfxTopLeftFramebuffers[0]=gfxAllocLinear(0x46500);
- gfxTopLeftFramebuffers[1]=gfxAllocLinear(0x46500);
- gfxBottomFramebuffers[0]=gfxAllocLinear(0x38400);
- gfxBottomFramebuffers[1]=gfxAllocLinear(0x38400);
- gfxTopRightFramebuffers[0]=gfxAllocLinear(0x46500);
- gfxTopRightFramebuffers[1]=gfxAllocLinear(0x46500);
+ gfxTopLeftFramebuffers[0]=linearAlloc(0x46500);
+ gfxTopLeftFramebuffers[1]=linearAlloc(0x46500);
+ gfxBottomFramebuffers[0]=linearAlloc(0x38400);
+ gfxBottomFramebuffers[1]=linearAlloc(0x38400);
+ gfxTopRightFramebuffers[0]=linearAlloc(0x46500);
+ gfxTopRightFramebuffers[1]=linearAlloc(0x46500);
enable3d=false;
//initialize framebuffer info structures
// Exit event handler
gspExitEventHandler();
- //free GSP heap
- svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, __gsp_heap_size, MEMOP_FREE, 0x0);
+ // Free framebuffers (let's pretend linearFree is actually implemented...)
+ linearFree(gfxTopRightFramebuffers[1]);
+ linearFree(gfxTopRightFramebuffers[0]);
+ linearFree(gfxBottomFramebuffers[1]);
+ linearFree(gfxBottomFramebuffers[0]);
+ linearFree(gfxTopLeftFramebuffers[1]);
+ linearFree(gfxTopLeftFramebuffers[0]);
//unmap GSP shared mem
svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);
int __system_argc;
char** __system_argv;
void (*__system_retAddr)(void);
+u32 __linear_heap;
// Data from _prm structure
extern void* __service_ptr; // used to detect if we're run from a homebrew launcher
-extern u32 __heap_size;
+extern u32 __heap_size, __linear_heap_size;
extern const char* __system_arglist;
// newlib definitions we need
// TODO: APT exit goes here
- // Unmap the heap
+ // Unmap the linear heap
+ svcControlMemory(&__linear_heap, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
+
+ // Unmap the application heap
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
// Jump to the loader if it provided a callback
heapBase = 0x08000000;
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3);
+ // Allocate the linear heap
+ svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3);
+
// Set up newlib heap
fake_heap_start = (char*)heapBase;
fake_heap_end = fake_heap_start + __heap_size;
--- /dev/null
+#include <3ds.h>
+
+extern u32 __linear_heap, __linear_heap_size;
+
+// TODO: this allocator sucks! It is not thread-safe and you cannot 'free' this memory.
+void* linearAlloc(size_t size)
+{
+ static size_t currentOffset = 0;
+ size_t free = __linear_heap_size - currentOffset;
+
+ // Enforce 8-byte alignment
+ size = (size + 7) &~ 7;
+
+ void* mem = NULL;
+ if (free >= size)
+ {
+ mem = (void*)(__linear_heap + currentOffset);
+ currentOffset += size;
+ }
+
+ return mem;
+}
+
+void* linearRealloc(void* mem, size_t size)
+{
+ return NULL; // TODO
+}
+
+void linearFree(void* mem)
+{
+ // TODO
+}
svcClearEvent(gspEvent);
u32 cmdBufHeader;
- __asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
+ __asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
u8 commandIndex=cmdBufHeader&0xFF;
u8 totalCommands=(cmdBufHeader>>8)&0xFF;
memcpy(dst, gxCommand, 0x20);
u32 mcrVal=0x0;
- __asm__ ("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (mcrVal)); //Data Synchronization Barrier Register
+ __asm__ __volatile__ ("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));
+ __asm__ __volatile__ ("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));
+ __asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
totalCommands=((cmdBufHeader&0xFF00)>>8)+1;
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00);
}