diff --git a/src/libwhb/include/whb/log.h b/src/libwhb/include/whb/log.h new file mode 100644 index 00000000..10871b03 --- /dev/null +++ b/src/libwhb/include/whb/log.h @@ -0,0 +1,29 @@ +#pragma once +#include + +/** + * \defgroup whb_log Logger + * \ingroup whb + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*LogHandlerFn)(const char *msg); + +BOOL +WHBAddLogHandler(LogHandlerFn fn); + +BOOL +WHBLogPrint(const char *str); + +BOOL +WHBLogPrintf(const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/src/libwhb/include/whb/log_udp.h b/src/libwhb/include/whb/log_udp.h new file mode 100644 index 00000000..28ba5d75 --- /dev/null +++ b/src/libwhb/include/whb/log_udp.h @@ -0,0 +1,21 @@ +#pragma once +#include + +/** + * \defgroup whb_log_udp UDP Log Output + * \ingroup whb + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL +WHBLogUdpInit(); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/src/libwhb/src/file.c b/src/libwhb/src/file.c index d120b010..d02926df 100644 --- a/src/libwhb/src/file.c +++ b/src/libwhb/src/file.c @@ -2,6 +2,7 @@ #include #include #include +#include static BOOL sInitialised = FALSE; @@ -49,6 +50,7 @@ WHBOpenFile(const char *path, FSInitCmdBlock(&cmd); result = FSOpenFile(&sClient, &cmd, tmp, mode, &handle, -1); if (result < 0) { + WHBLogPrintf("%s: FSOpenFile error %d", __FUNCTION__, result); return WHB_FILE_FATAL_ERROR; } @@ -64,6 +66,7 @@ WHBGetFileSize(int32_t handle) FSInitCmdBlock(&cmd); result = FSGetStatFile(&sClient, &cmd, (FSFileHandle)handle, &stat, -1); if (result < 0) { + WHBLogPrintf("%s: FSGetStatFile error %d", __FUNCTION__, result); return 0; } @@ -81,6 +84,7 @@ WHBReadFile(int32_t handle, FSInitCmdBlock(&cmd); result = FSReadFile(&sClient, &cmd, buf, size, count, (FSFileHandle)handle, 0, -1); if (result < 0) { + WHBLogPrintf("%s: FSReadFile error %d", __FUNCTION__, result); return 0; } @@ -95,6 +99,7 @@ WHBCloseFile(int32_t handle) FSInitCmdBlock(&cmd); result = FSCloseFile(&sClient, &cmd, (FSFileHandle)handle, -1); if (result != FS_STATUS_OK) { + WHBLogPrintf("%s: FSCloseFile error %d", __FUNCTION__, result); return WHB_FILE_FATAL_ERROR; } @@ -110,6 +115,7 @@ WHBReadWholeFile(const char *path, char *buf = NULL; handle = WHBOpenFile(path, "r"); if (handle == WHB_FILE_FATAL_ERROR) { + WHBLogPrintf("%s: WHBOpenFile failed", __FUNCTION__); return NULL; } @@ -120,6 +126,7 @@ WHBReadWholeFile(const char *path, buf = MEMAllocFromDefaultHeapEx(size, 64); if (!buf) { + WHBLogPrintf("%s: MEMAllocFromDefaultHeapEx(0x%X, 64) failed", __FUNCTION__, size); goto error; } diff --git a/src/libwhb/src/gfx.c b/src/libwhb/src/gfx.c index a6d2bbf5..1cdf9fae 100644 --- a/src/libwhb/src/gfx.c +++ b/src/libwhb/src/gfx.c @@ -15,6 +15,7 @@ #include #include #include +#include #define WHB_GFX_COMMAND_BUFFER_POOL_SIZE (0x400000) @@ -148,12 +149,23 @@ GfxInitDepthBuffer(GX2DepthBuffer *db, static uint32_t GfxProcCallbackAcquired(void *context) { - GfxHeapInitMEM1(); - GfxHeapInitForeground(); + if (!GfxHeapInitMEM1()) { + WHBLogPrintf("%s: GfxHeapInitMEM1 failed", __FUNCTION__); + goto error; + } + + if (!GfxHeapInitForeground()) { + WHBLogPrintf("%s: GfxHeapInitForeground failed", __FUNCTION__); + goto error; + } // Allocate TV scan buffer. sTvScanBuffer = GfxHeapAllocForeground(sTvScanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT); if (!sTvScanBuffer) { + WHBLogPrintf("%s: sTvScanBuffer = GfxHeapAllocForeground(0x%X, 0x%X) failed", + __FUNCTION__, + sTvScanBufferSize, + GX2_SCAN_BUFFER_ALIGNMENT); goto error; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sTvScanBuffer, sTvScanBufferSize); @@ -162,6 +174,10 @@ GfxProcCallbackAcquired(void *context) // Allocate TV colour buffer. sTvColourBuffer.surface.image = GfxHeapAllocMEM1(sTvColourBuffer.surface.imageSize, sTvColourBuffer.surface.alignment); if (!sTvColourBuffer.surface.image) { + WHBLogPrintf("%s: sTvColourBuffer = GfxHeapAllocMEM1(0x%X, 0x%X) failed", + __FUNCTION__, + sTvColourBuffer.surface.imageSize, + sTvColourBuffer.surface.alignment); goto error; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sTvColourBuffer.surface.image, sTvColourBuffer.surface.imageSize); @@ -169,6 +185,10 @@ GfxProcCallbackAcquired(void *context) // Allocate TV depth buffer. sTvDepthBuffer.surface.image = GfxHeapAllocMEM1(sTvDepthBuffer.surface.imageSize, sTvDepthBuffer.surface.alignment); if (!sTvDepthBuffer.surface.image) { + WHBLogPrintf("%s: sTvDepthBuffer = GfxHeapAllocMEM1(0x%X, 0x%X) failed", + __FUNCTION__, + sTvDepthBuffer.surface.imageSize, + sTvDepthBuffer.surface.alignment); goto error; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sTvDepthBuffer.surface.image, sTvDepthBuffer.surface.imageSize); @@ -176,6 +196,10 @@ GfxProcCallbackAcquired(void *context) // Allocate DRC scan buffer. sDrcScanBuffer = GfxHeapAllocForeground(sDrcScanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT); if (!sDrcScanBuffer) { + WHBLogPrintf("%s: sDrcScanBuffer = GfxHeapAllocForeground(0x%X, 0x%X) failed", + __FUNCTION__, + sDrcScanBufferSize, + GX2_SCAN_BUFFER_ALIGNMENT); goto error; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sDrcScanBuffer, sDrcScanBufferSize); @@ -184,6 +208,10 @@ GfxProcCallbackAcquired(void *context) // Allocate DRC colour buffer. sDrcColourBuffer.surface.image = GfxHeapAllocMEM1(sDrcColourBuffer.surface.imageSize, sDrcColourBuffer.surface.alignment); if (!sDrcColourBuffer.surface.image) { + WHBLogPrintf("%s: sDrcColourBuffer = GfxHeapAllocMEM1(0x%X, 0x%X) failed", + __FUNCTION__, + sDrcColourBuffer.surface.imageSize, + sDrcColourBuffer.surface.alignment); goto error; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sDrcColourBuffer.surface.image, sDrcColourBuffer.surface.imageSize); @@ -191,13 +219,17 @@ GfxProcCallbackAcquired(void *context) // Allocate DRC depth buffer. sDrcDepthBuffer.surface.image = GfxHeapAllocMEM1(sDrcDepthBuffer.surface.imageSize, sDrcDepthBuffer.surface.alignment); if (!sDrcDepthBuffer.surface.image) { + WHBLogPrintf("%s: sDrcDepthBuffer = GfxHeapAllocMEM1(0x%X, 0x%X) failed", + __FUNCTION__, + sDrcDepthBuffer.surface.imageSize, + sDrcDepthBuffer.surface.alignment); goto error; } GX2Invalidate(GX2_INVALIDATE_MODE_CPU, sDrcDepthBuffer.surface.image, sDrcDepthBuffer.surface.imageSize); return 0; error: - return 1; + return -1; } static uint32_t @@ -250,6 +282,7 @@ WHBGfxInit() sCommandBufferPool = GfxHeapAllocMEM2(WHB_GFX_COMMAND_BUFFER_POOL_SIZE, GX2_COMMAND_BUFFER_ALIGNMENT); if (!sCommandBufferPool) { + WHBLogPrintf("%s: failed to allocate command buffer pool", __FUNCTION__); goto error; } @@ -299,8 +332,8 @@ WHBGfxInit() GX2CalcDRCSize(sDrcRenderMode, sDrcSurfaceFormat, GX2_BUFFERING_MODE_DOUBLE, &sDrcScanBufferSize, &unk); GfxInitTvColourBuffer(&sDrcColourBuffer, drcWidth, drcHeight, sDrcSurfaceFormat, GX2_AA_MODE1X); GfxInitDepthBuffer(&sDrcDepthBuffer, sDrcColourBuffer.surface.width, sDrcColourBuffer.surface.height, GX2_SURFACE_FORMAT_FLOAT_R32, sDrcColourBuffer.surface.aa); - if (GfxProcCallbackAcquired(NULL) != 0) { + WHBLogPrintf("%s: GfxProcCallbackAcquired failed", __FUNCTION__); goto error; } @@ -311,6 +344,7 @@ WHBGfxInit() // Initialise TV context state. sTvContextState = GfxHeapAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT); if (!sTvContextState) { + WHBLogPrintf("%s: failed to allocate sTvContextState", __FUNCTION__); goto error; } GX2SetupContextStateEx(sTvContextState, TRUE); @@ -324,6 +358,7 @@ WHBGfxInit() // Initialise DRC context state. sDrcContextState = GfxHeapAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT); if (!sDrcContextState) { + WHBLogPrintf("%s: failed to allocate sDrcContextState", __FUNCTION__); goto error; } GX2SetupContextStateEx(sDrcContextState, TRUE); @@ -336,8 +371,6 @@ WHBGfxInit() // Set 60fps VSync GX2SetSwapInterval(1); - GX2SetTVEnable(TRUE); - GX2SetDRCEnable(TRUE); return TRUE; @@ -433,9 +466,11 @@ WHBGfxBeginRender() void WHBGfxFinishRender() { - GX2Flush(); GX2SwapScanBuffers(); GX2Flush(); + GX2DrawDone(); + GX2SetTVEnable(TRUE); + GX2SetDRCEnable(TRUE); } void diff --git a/src/libwhb/src/gfx_heap.c b/src/libwhb/src/gfx_heap.c index 5f735dd4..9b726bb2 100644 --- a/src/libwhb/src/gfx_heap.c +++ b/src/libwhb/src/gfx_heap.c @@ -3,6 +3,7 @@ #include #include #include +#include static void * sGfxHeapMEM1 = NULL; @@ -10,22 +11,35 @@ sGfxHeapMEM1 = NULL; static void * sGfxHeapForeground = NULL; +#define GFX_FRAME_HEAP_TAG (0x123DECAF) + BOOL GfxHeapInitMEM1() { - MEMHeapHandle mem1 = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); - uint32_t size = MEMGetAllocatableSizeForFrmHeapEx(mem1, 4); - if (!size) { + MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); + uint32_t size; + void *base; + + if (!MEMRecordStateForFrmHeap(heap, GFX_FRAME_HEAP_TAG)) { + WHBLogPrintf("%s: MEMRecordStateForFrmHeap failed", __FUNCTION__); return FALSE; } - void *base = MEMAllocFromFrmHeapEx(mem1, size, 4); + size = MEMGetAllocatableSizeForFrmHeapEx(heap, 4); + if (!size) { + WHBLogPrintf("%s: MEMGetAllocatableSizeForFrmHeapEx == 0", __FUNCTION__); + return FALSE; + } + + base = MEMAllocFromFrmHeapEx(heap, size, 4); if (!base) { + WHBLogPrintf("%s: MEMAllocFromFrmHeapEx(heap, 0x%X, 4) failed", __FUNCTION__, size); return FALSE; } sGfxHeapMEM1 = MEMCreateExpHeapEx(base, size, 0); if (!sGfxHeapMEM1) { + WHBLogPrintf("%s: MEMCreateExpHeapEx(0x%08X, 0x%X, 0) failed", __FUNCTION__, base, size); return FALSE; } @@ -35,33 +49,39 @@ GfxHeapInitMEM1() BOOL GfxHeapDestroyMEM1() { - MEMHeapHandle mem1 = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); + MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); if (sGfxHeapMEM1) { MEMDestroyExpHeap(sGfxHeapMEM1); sGfxHeapMEM1 = NULL; } - MEMFreeToFrmHeap(mem1, MEM_FRAME_HEAP_FREE_ALL); + MEMFreeByStateToFrmHeap(heap, GFX_FRAME_HEAP_TAG); return TRUE; } BOOL GfxHeapInitForeground() { - MEMHeapHandle mem1 = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG); - uint32_t size = MEMGetAllocatableSizeForFrmHeapEx(mem1, 4); + MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG); + uint32_t size; + void *base; + + size = MEMGetAllocatableSizeForFrmHeapEx(heap, 4); if (!size) { + WHBLogPrintf("%s: MEMAllocFromFrmHeapEx(heap, 0x%X, 4)", __FUNCTION__, size); return FALSE; } - void *base = MEMAllocFromFrmHeapEx(mem1, size, 4); + base = MEMAllocFromFrmHeapEx(heap, size, 4); if (!base) { + WHBLogPrintf("%s: MEMGetAllocatableSizeForFrmHeapEx == 0", __FUNCTION__); return FALSE; } sGfxHeapForeground = MEMCreateExpHeapEx(base, size, 0); if (!sGfxHeapForeground) { + WHBLogPrintf("%s: MEMCreateExpHeapEx(0x%08X, 0x%X, 0)", __FUNCTION__, base, size); return FALSE; } diff --git a/src/libwhb/src/gfx_shader.c b/src/libwhb/src/gfx_shader.c index 9346ecf2..eb57f7d5 100644 --- a/src/libwhb/src/gfx_shader.c +++ b/src/libwhb/src/gfx_shader.c @@ -6,6 +6,7 @@ #include #include #include +#include GX2PixelShader * WHBGfxLoadGFDPixelShader(uint32_t index, @@ -16,18 +17,28 @@ WHBGfxLoadGFDPixelShader(uint32_t index, void *program = NULL; if (index >= GFDGetPixelShaderCount(file)) { + WHBLogPrintf("%s: index %u >= %u GFDGetPixelShaderCount(file)", + __FUNCTION__, + index, + GFDGetPixelShaderCount(file)); goto error; } headerSize = GFDGetPixelShaderHeaderSize(index, file); - programSize = GFDGetPixelShaderProgramSize(index, file); + if (!headerSize) { + WHBLogPrintf("%s: headerSize == 0", __FUNCTION__); + goto error; + } - if (!headerSize || !programSize) { + programSize = GFDGetPixelShaderProgramSize(index, file); + if (!programSize) { + WHBLogPrintf("%s: programSize == 0", __FUNCTION__); goto error; } shader = (GX2PixelShader *)GfxHeapAllocMEM2(headerSize, 64); if (!shader) { + WHBLogPrintf("%s: GfxHeapAllocMEM2(%u, 64) failed", __FUNCTION__, headerSize); goto error; } @@ -36,11 +47,18 @@ WHBGfxLoadGFDPixelShader(uint32_t index, shader->gx2rBuffer.elemCount = 1; shader->gx2rBuffer.buffer = NULL; if (!GX2RCreateBuffer(&shader->gx2rBuffer)) { + WHBLogPrintf("%s: GX2RCreateBuffer failed with programSize = %u", __FUNCTION__, programSize); goto error; } program = GX2RLockBufferEx(&shader->gx2rBuffer, 0); + if (!program) { + WHBLogPrintf("%s: GX2RLockBufferEx failed", __FUNCTION__); + goto error; + } + if (!GFDGetPixelShader(shader, program, index, file)) { + WHBLogPrintf("%s: GFDGetPixelShader failed", __FUNCTION__); GX2RUnlockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_DISABLE_CPU_INVALIDATE | GX2R_RESOURCE_DISABLE_GPU_INVALIDATE); goto error; } @@ -79,18 +97,28 @@ WHBGfxLoadGFDVertexShader(uint32_t index, void *program = NULL; if (index >= GFDGetVertexShaderCount(file)) { + WHBLogPrintf("%s: index %u >= %u GFDGetVertexShaderCount(file)", + __FUNCTION__, + index, + GFDGetVertexShaderCount(file)); goto error; } headerSize = GFDGetVertexShaderHeaderSize(index, file); - programSize = GFDGetVertexShaderProgramSize(index, file); + if (!headerSize) { + WHBLogPrintf("%s: headerSize == 0", __FUNCTION__); + goto error; + } - if (!headerSize || !programSize) { + programSize = GFDGetVertexShaderProgramSize(index, file); + if (!programSize) { + WHBLogPrintf("%s: programSize == 0", __FUNCTION__); goto error; } shader = (GX2VertexShader *)GfxHeapAllocMEM2(headerSize, 64); if (!shader) { + WHBLogPrintf("%s: GfxHeapAllocMEM2(%u, 64) failed", __FUNCTION__, headerSize); goto error; } @@ -99,11 +127,18 @@ WHBGfxLoadGFDVertexShader(uint32_t index, shader->gx2rBuffer.elemCount = 1; shader->gx2rBuffer.buffer = NULL; if (!GX2RCreateBuffer(&shader->gx2rBuffer)) { + WHBLogPrintf("%s: GX2RCreateBuffer failed with programSize = %u", __FUNCTION__, programSize); goto error; } program = GX2RLockBufferEx(&shader->gx2rBuffer, 0); + if (!program) { + WHBLogPrintf("%s: GX2RLockBufferEx failed", __FUNCTION__); + goto error; + } + if (!GFDGetVertexShader(shader, program, index, file)) { + WHBLogPrintf("%s: GFDGetVertexShader failed", __FUNCTION__); GX2RUnlockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_DISABLE_CPU_INVALIDATE | GX2R_RESOURCE_DISABLE_GPU_INVALIDATE); goto error; } diff --git a/src/libwhb/src/gfx_texture.c b/src/libwhb/src/gfx_texture.c index b71f03ad..6019a91e 100644 --- a/src/libwhb/src/gfx_texture.c +++ b/src/libwhb/src/gfx_texture.c @@ -2,6 +2,7 @@ #include #include #include +#include #include GX2Texture * @@ -13,6 +14,7 @@ WHBGfxLoadGFDTexture(uint32_t index, void *image = NULL; if (index >= GFDGetTextureCount(file)) { + WHBLogPrintf("%s: invalid GFD texture index %u", __FUNCTION__, index); goto error; } @@ -25,6 +27,7 @@ WHBGfxLoadGFDTexture(uint32_t index, texture = (GX2Texture *)GfxHeapAllocMEM2(headerSize, 64); if (!texture) { + WHBLogPrintf("%s: GfxHeapAllocMEM2(0x%X, 64) failed", __FUNCTION__, headerSize); goto error; } diff --git a/src/libwhb/src/log.c b/src/libwhb/src/log.c new file mode 100644 index 00000000..6b52c25f --- /dev/null +++ b/src/libwhb/src/log.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +#define MAX_HANDLERS 16 +#define PRINTF_BUFFER_LENGTH 2048 + +static LogHandlerFn +sHandlers[MAX_HANDLERS] = { 0 }; + +BOOL +WHBAddLogHandler(LogHandlerFn fn) +{ + int i; + + for (i = 0; i < MAX_HANDLERS; ++i) { + if (!sHandlers[i]) { + sHandlers[i] = fn; + return TRUE; + } + } + + return FALSE; +} + +BOOL +WHBLogPrint(const char *str) +{ + int i; + + for (i = 0; i < MAX_HANDLERS; ++i) { + if (sHandlers[i]) { + sHandlers[i](str); + } + } + + return TRUE; +} + +BOOL +WHBLogPrintf(const char *fmt, ...) +{ + char *buf = MEMAllocFromDefaultHeapEx(PRINTF_BUFFER_LENGTH, 4); + va_list va; + BOOL result; + + if (!buf) { + return FALSE; + } + + va_start(va, fmt); + + vsnprintf(buf, PRINTF_BUFFER_LENGTH, fmt, va); + result = WHBLogPrint(buf); + + MEMFreeToDefaultHeap(buf); + va_end(va); + return result; +} diff --git a/src/libwhb/src/log_udp.c b/src/libwhb/src/log_udp.c new file mode 100644 index 00000000..713d4cc2 --- /dev/null +++ b/src/libwhb/src/log_udp.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include + +static int +sSocket = -1; + +static struct sockaddr_in +sSendAddr; + +#define SERVER_PORT 4405 + +static void +udpLogHandler(const char *msg) +{ + sendto(sSocket, + msg, + strlen(msg), + 0, + (struct sockaddr *)&sSendAddr, + sizeof(struct sockaddr_in)); +} + +BOOL +WHBLogUdpInit() +{ + int broadcastEnable = 1; + socket_lib_init(); + + sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sSocket < 0) { + return FALSE; + } + + setsockopt(sSocket, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); + + memset(&sSendAddr, 0, sizeof(struct sockaddr_in)); + sSendAddr.sin_family = AF_INET; + sSendAddr.sin_port = htons(SERVER_PORT); + sSendAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + + WHBAddLogHandler(udpLogHandler); + return TRUE; +}