MEMHeapHandle mem1_heap = NULL;
MEMHeapHandle bucket_heap = NULL;
void *VMEM_alloc(size_t size, uint32_t align)
{
if (align < 4)
align = 4;
size++;
uint8_t area;
uint8_t *ret = (uint8_t *)MEMAllocFromExpHeapEx(mem1_heap, size, align);
if(ret == NULL)
{
// Let's use bucket just like MEM1
ret = (uint8_t *)MEMAllocFromExpHeapEx(bucket_heap, size, align);
if(ret == NULL)
{
// Last hance to get memory: Use slow MEM2
ret = (uint8_t *)MEMAllocFromDefaultHeapEx(size, align);
if(ret == NULL)
return NULL;
area = 2;
}
else
area = 1;
}
else
area = 0;
*ret = area;
return ret + 1;
}
void *VMEM_free(void *ptr)
{
if(ptr == NULL)
return;
switch(--ptr)
{
case 0:
MEMFreeToExpHeap(mem1_heap, ptr);
return;
case 1:
MEMFreeToExpHeap(bucket_heap, ptr);
return;
default:
MEMFreeToDefaultHeap(ptr);
}
}
static inline void release_vmem()
{
if(mem1_heap != NULL)
{
MEMDestroyExpHeap(mem1_heap);
MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3);
mem1_heap = NULL;
}
if(bucket_heap != NULL)
{
MEMDestroyExpHeap(bucket_heap);
MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3);
bucket_heap = NULL;
}
}
GXFifoObj *GX_Init(void *fifo, size_t fifo_size)
{
for(int i = 0; i < 2; i++)
{
MEMHeapHandle heap_handle;
uint32_t allocatable_size;
void *memory;
if((i == 0 && mem1_heap == NULL) || (i == 1 && bucket_heap == NULL))
{
heap_handle = MEMGetBaseHeapHandle(i == 0 ? MEMORY_ARENA_1 : MEMORY_ARENA_FG_BUCKET);
allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(heap_handle, 4);
memory = MEMAllocFromFrmHeapEx(heap_handle, allocatable_size, 4);
if(i == 0)
{
if(mem1_heap == NULL)
return NULL;
mem1_heap = MEMCreateExpHeapEx(memory, allocatable_size, 0);
if(mem1_heap == NULL)
{
MEMFreeToFrmHeap(heap_handle, 3);
return NULL;
}
}
else
{
if(bucket_heap == NULL)
{
release_vmem();
return NULL;
}
bucket_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0);
if(bucket_heap == NULL)
{
MEMFreeToFrmHeap(heap_handle, 3);
release_vmem();
return NULL;
}
}
}
}
GXFifoObj *ret = VMEM_alloc(sizeof(GXFifoObj), 4);
if(ret == NULL)
{
release_vmem();
return NULL;
}
ret->gx2_cmdbuffer = VMEM_alloc(GX2_COMMAND_BUFFER_SIZE, 0x40);
if(ret->gx2_cmdbuffer == NULL)
{
VMEM_free(ret);
release_vmem();
return NULL;
}
ret->fifo = fifo;
ret->fifo_size = fifo_size;
GX_InitFifoBase(ret, fifo, fifo_size);
uint32_t gx2_init_attributes[9] = {;
GX2_INIT_CMD_BUF_BASE,
(uint32_t)ret->gx2_cmdbuffer,
GX2_INIT_CMD_BUF_POOL_SIZE,
GX2_COMMAND_BUFFER_SIZE,
GX2_INIT_ARGC,
(uint32_t)NULL,
GX2_INIT_ARGV,
0,
GX2_INIT_END
};
GX2Init(gx2_init_attributes);
int32_t tvScanMode = GX2_TV_SCAN_MODE_480I;
uint32_t tvWidth = 854;
uint32_t tvHeight = 480;
GX2TVRenderMode tvRenderMode = GX2_TV_RENDER_MODE_WIDE_480P;
uint32_t scanBufferSize;
uint32_t scaleNeeded;
GX2CalcTVSize(tvRenderMode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE, &scanBufferSize, &scaleNeeded);
tvScanBuffer = VMEM_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT); // TODO
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, tvScanBuffer, scanBufferSize);
GX2SetTVBuffer(tvScanBuffer, scanBufferSize, tvRenderMode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE);
GX2CalcDRCSize((GX2DrcRenderMode)drcScanMode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE, &scanBufferSize, &scaleNeeded);
drcScanBuffer = VMEM_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT); // TODO
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, drcScanBuffer, scanBufferSize);
GX2SetDRCBuffer(drcScanBuffer, scanBufferSize, (GX2DrcRenderMode)drcScanMode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE);
GX2AAMode tvAAMode = GX2_AA_MODE1X;
GX2AAMode drcAAMode = GX2_AA_MODE4X;
GX2InitColorBuffer(&tvColorBuffer, GX2_SURFACE_DIM_TEXTURE_2D, tvWidth, tvHeight, 1, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, tvAAMode);
tvColorBuffer.surface.image = VMEM_alloc(tvColorBuffer.surface.imageSize, tvColorBuffer.surface.alignment);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, tvColorBuffer.surface.image, tvColorBuffer.surface.imageSize);
GX2InitDepthBuffer(&tvDepthBuffer, GX2_SURFACE_DIM_TEXTURE_2D, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_FLOAT_R32, (GX2AAMode)tvAAMode);
tvDepthBuffer.surface.image = VMEM_alloc(tvDepthBuffer.surface.imageSize, tvDepthBuffer.surface.alignment);
drcDepthBuffer.surface.image = tvDepthBuffer.surface.image:
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, tvDepthBuffer.surface.image, tvDepthBuffer.surface.imageSize);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, drcDepthBuffer.surface.image, drcDepthBuffer.surface.imageSize);
uint32_t size, align;
GX2CalcDepthBufferHiZInfo(&tvDepthBuffer, &size, &align);
tvDepthBuffer.hiZPtr = VMEM_alloc(size, align);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, tvDepthBuffer.hiZPtr, size);
GX2InitDepthBufferHiZEnable(&tvDepthBuffer, GX2_ENABLE);
GX2InitColorBuffer(&drcColorBuffer, GX2_SURFACE_DIM_TEXTURE_2D, 854, 480, 1, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, (GX2AAMode)drcAAMode);
drcColorBuffer.surface.image = VMEM_alloc(drcColorBuffer.surface.imageSize, drcColorBuffer.surface.alignment);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, drcColorBuffer.surface.image, drcColorBuffer.surface.imageSize);
GX2CalcDepthBufferHiZInfo(&drcDepthBuffer, &size, &align);
drcDepthBuffer.hiZPtr = VMEM_alloc(size, align);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, drcDepthBuffer.hiZPtr, size);
GX2InitDepthBufferHiZEnable(&drcDepthBuffer, GX2_ENABLE);
uint32_t auxSize, auxAlign;
GX2CalcColorBufferAuxInfo(&tvColorBuffer, &auxSize, &auxAlign);
tvColorBuffer.aaBuffer = VMEM_alloc(auxSize, auxAlign);
tvColorBuffer.aaSize = auxSize;
memset(tvColorBuffer.aaBuffer, GX2_AA_BUFFER_CLEAR_VALUE, auxSize);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, tvColorBuffer.aaBuffer, auxSize);
GX2CalcColorBufferAuxInfo(&drcColorBuffer, &auxSize, &auxAlign);
drcColorBuffer.aaBuffer = VMEM_alloc(auxSize, auxAlign);
drcColorBuffer.aaSize = auxSize;
memset(drcColorBuffer.aaBuffer, GX2_AA_BUFFER_CLEAR_VALUE, auxSize);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, drcColorBuffer.aaBuffer, auxSize);
tvContextState = (GX2ContextState*)VMEM_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
GX2SetupContextStateEx(tvContextState, GX2_TRUE);
GX2SetContextState(tvContextState);
GX2SetColorBuffer(&tvColorBuffer, GX2_RENDER_TARGET_0);
GX2SetDepthBuffer(&tvDepthBuffer);
drcContextState = (GX2ContextState*)VMEM_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
GX2SetupContextStateEx(drcContextState, GX2_TRUE);
GX2SetContextState(drcContextState);
GX2SetColorBuffer(&drcColorBuffer, GX2_RENDER_TARGET_0);
GX2SetDepthBuffer(&drcDepthBuffer);
GX2SetViewport(0.0f, 0.0f, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 0.0f, 1.0f);
GX2SetScissor(0, 0, tvColorBuffer.surface.width, tvColorBuffer.surface.height);
projectionMtx = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f);
viewMtx = glm::mat4(1.0f);
viewMtx = glm::translate(viewMtx, glm::vec3(0.0f, 0.0f, -2.5f));
viewMtx = glm::rotate(viewMtx, DegToRad(25.0f), glm::vec3(1.0f, 0.0f, 0.0f));
GX2InitSampler(&aaSampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR);
GX2InitTexture(&tvAaTexture, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, 0, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_SURFACE_DIM_TEXTURE_2D, GX2_TILE_MODE_DEFAULT);
tvAaTexture.surface.image = tvColorBuffer.surface.image;
tvAaTexture.surface.imageSize = tvColorBuffer.surface.imageSize;
tvAaTexture.surface.mipmaps = tvColorBuffer.surface.mipmaps;
return ret;
}
void GX_InitFifoBase(GXFifoObj *fifo, void *base, size_t size)
{
size -= 1;
GX_InitFifoLimits(fifo, size, size >> 1); // TODO
GX_InitFifoPtrs(fifo, base, base);
}
void GX_InitFifoLimits(GXFifoObj *fifo, uint32_t highwater, uint32_t lowwater)
{
fifo->high = highwater;
fifo->low = lowwater;
}
void GX_InitFifoPtrs(XFifoObj *fifo, void *read, void *write)
{
fifo->read = read;
fifo->write = write;
}
void GX_GetFifoPtrs(GXFifoObj *fifo, void **read_out, void **write_out)
{
*read_out = fifo->read;
*write_out = fifo->write;
}