From 9a9834858271784c7c43675fd1e3291f968e7393 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 10 Mar 2026 15:07:50 -0500 Subject: [PATCH] Renders on Dolphin also. --- assets/scene/minesweeper.lua | 2 +- cmake/targets/dolphin.cmake | 1 - src/dusk/display/mesh/mesh.c | 1 + src/dusk/display/spritebatch/spritebatch.h | 3 +- src/duskdolphin/debug/debug.c | 15 +- src/duskdolphin/display/displaydolphin.c | 19 ++- src/duskdolphin/display/mesh/meshdolphin.c | 19 ++- .../display/texture/texturedolphin.c | 129 ++++++++++-------- 8 files changed, 114 insertions(+), 75 deletions(-) diff --git a/assets/scene/minesweeper.lua b/assets/scene/minesweeper.lua index 9e2c7bb..8c75607 100644 --- a/assets/scene/minesweeper.lua +++ b/assets/scene/minesweeper.lua @@ -15,7 +15,7 @@ CELL_STATE_HOVER = 1 CELL_STATE_DOWN = 2 CELL_STATE_DISABLED = 3 -screenSetBackground(colorBlack()) +screenSetBackground(colorCornflowerBlue()) camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) -- tilesetUi = tilesetGetByName("ui") diff --git a/cmake/targets/dolphin.cmake b/cmake/targets/dolphin.cmake index 559465f..e1648c8 100644 --- a/cmake/targets/dolphin.cmake +++ b/cmake/targets/dolphin.cmake @@ -1,6 +1,5 @@ # Target definitions target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC - DUSK_PLATFORM_ENDIAN_BIG DUSK_DOLPHIN DUSK_DISPLAY_WIDTH=640 DUSK_DISPLAY_HEIGHT=480 diff --git a/src/dusk/display/mesh/mesh.c b/src/dusk/display/mesh/mesh.c index 5dd79d8..fc61476 100644 --- a/src/dusk/display/mesh/mesh.c +++ b/src/dusk/display/mesh/mesh.c @@ -8,6 +8,7 @@ #include "mesh.h" #include "util/memory.h" #include "assert/assert.h" +#include "debug/debug.h" errorret_t meshInit( mesh_t *mesh, diff --git a/src/dusk/display/spritebatch/spritebatch.h b/src/dusk/display/spritebatch/spritebatch.h index 7200211..6a87c19 100644 --- a/src/dusk/display/spritebatch/spritebatch.h +++ b/src/dusk/display/spritebatch/spritebatch.h @@ -9,7 +9,7 @@ #include "display/mesh/quad.h" #include "display/texture/texture.h" -#define SPRITEBATCH_SPRITES_MAX 128 +#define SPRITEBATCH_SPRITES_MAX 16 #define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT) @@ -20,7 +20,6 @@ typedef struct { } spritebatch_t; // Have to define these seperately because of alignment in certain platforms. -// (Looking at you Dolphin) extern meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT]; extern spritebatch_t SPRITEBATCH; diff --git a/src/duskdolphin/debug/debug.c b/src/duskdolphin/debug/debug.c index 6f42aae..85b9bd7 100644 --- a/src/duskdolphin/debug/debug.c +++ b/src/duskdolphin/debug/debug.c @@ -12,20 +12,25 @@ static char_t DEBUG_ERROR_BUFFER[16*1024] = {0}; void debugPrint(const char_t *message, ...) { - // append to error buffer size_t start = strlen(DEBUG_ERROR_BUFFER); + va_list args; va_start(args, message); - fprintf(stdout, message, args); - va_end(args); - - va_start(args, message); + + // Print to stdout + va_list copy; + va_copy(copy, args); + vfprintf(stdout, message, copy); + va_end(copy); + + // Append to buffer vsnprintf( DEBUG_ERROR_BUFFER + start, sizeof(DEBUG_ERROR_BUFFER) - start, message, args ); + va_end(args); } diff --git a/src/duskdolphin/display/displaydolphin.c b/src/duskdolphin/display/displaydolphin.c index a794c6f..cd25869 100644 --- a/src/duskdolphin/display/displaydolphin.c +++ b/src/duskdolphin/display/displaydolphin.c @@ -15,9 +15,15 @@ errorret_t displayInitDolphin(void) { DISPLAY.frameBuffer[0] = MEM_K0_TO_K1( SYS_AllocateFramebuffer(DISPLAY.screenMode) ); + if(DISPLAY.frameBuffer[0] == NULL) { + errorThrow("Failed to allocate framebuffer"); + } DISPLAY.frameBuffer[1] = MEM_K0_TO_K1( SYS_AllocateFramebuffer(DISPLAY.screenMode) ); + if(DISPLAY.frameBuffer[1] == NULL) { + errorThrow("Failed to allocate framebuffer"); + } VIDEO_Configure(DISPLAY.screenMode); VIDEO_SetNextFramebuffer(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer]); @@ -28,6 +34,9 @@ errorret_t displayInitDolphin(void) { if(DISPLAY.screenMode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync(); DISPLAY.fifoBuffer = memalign(32, DISPLAY_DOLPHIN_FIFO_SIZE); + if(DISPLAY.fifoBuffer == NULL) { + errorThrow("Failed to allocate FIFO buffer"); + } memoryZero(DISPLAY.fifoBuffer, DISPLAY_DOLPHIN_FIFO_SIZE); GX_Init(DISPLAY.fifoBuffer, DISPLAY_DOLPHIN_FIFO_SIZE); @@ -69,15 +78,16 @@ errorret_t displayInitDolphin(void) { // Setup cull modes GX_SetCullMode(GX_CULL_NONE); GX_SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE); - GX_CopyDisp(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer], GX_TRUE); GX_SetDispCopyGamma(GX_GM_1_0); + GX_SetColorUpdate(GX_TRUE); + // Describe mesh vertex format. GX_ClearVtxDesc(); GX_SetVtxDesc(GX_VA_POS, GX_INDEX16); GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX16); GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); - GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_U8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); errorOk(); @@ -85,14 +95,15 @@ errorret_t displayInitDolphin(void) { errorret_t displayUpdateDolphin(void) { ENGINE.running = SYS_MainLoop(); + errorOk(); } errorret_t displaySwapDolphin(void) { GX_DrawDone(); DISPLAY.whichFrameBuffer ^= 1; - GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); - GX_SetColorUpdate(GX_TRUE); + // GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + // GX_SetColorUpdate(GX_TRUE); GX_CopyDisp(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer], GX_TRUE); VIDEO_SetNextFramebuffer(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer]); VIDEO_Flush(); diff --git a/src/duskdolphin/display/mesh/meshdolphin.c b/src/duskdolphin/display/mesh/meshdolphin.c index 580cd73..cb14f27 100644 --- a/src/duskdolphin/display/mesh/meshdolphin.c +++ b/src/duskdolphin/display/mesh/meshdolphin.c @@ -8,6 +8,7 @@ #include "display/mesh/mesh.h" #include "display/texture/texture.h" #include "assert/assert.h" +#include "debug/debug.h" errorret_t meshInitDolphin( meshdolphin_t *mesh, @@ -38,22 +39,28 @@ errorret_t meshDrawDolphin( vertexOffset + vertexCount <= mesh->vertexCount, "Requested vertex range is invalid" ); + assertTrue(vertexCount <= UINT16_MAX, "Vertex count exceeds GX limit"); + + // Matches vertex format described in displaydolphin.c + assertTrue(sizeof(color_t) == 4, "color_t must be exactly 4 bytes"); + assertTrue(offsetof(meshvertex_t, color) == 0, "color offset wrong"); + assertTrue(offsetof(meshvertex_t, uv) == 4, "uv offset wrong"); + assertTrue(offsetof(meshvertex_t, pos) == 12, "pos offset wrong"); + + textureDolphinUploadTEV(); - // Prepare Vertex descriptor DCFlushRange( (void*)&mesh->vertices[vertexOffset], sizeof(meshvertex_t) * vertexCount ); - const u8 stride = (u8)sizeof(meshvertex_t); + const uint8_t stride = (uint8_t)sizeof(meshvertex_t); GX_SetArray(GX_VA_POS, (void*)&mesh->vertices[vertexOffset].pos[0], stride); - GX_SetArray(GX_VA_CLR0, (void*)&mesh->vertices[vertexOffset].color, stride); + GX_SetArray(GX_VA_CLR0, (void*)&mesh->vertices[vertexOffset].color.r, stride); GX_SetArray(GX_VA_TEX0, (void*)&mesh->vertices[vertexOffset].uv[0], stride); - textureDolphinUploadTEV(); - GX_Begin(mesh->primitiveType, GX_VTXFMT0, (uint16_t)vertexCount); - for(u16 i = 0; i < (u16)vertexCount; ++i) { + for(uint16_t i = 0; i < (uint16_t)vertexCount; ++i) { GX_Position1x16(i); GX_Color1x16(i); GX_TexCoord1x16(i); diff --git a/src/duskdolphin/display/texture/texturedolphin.c b/src/duskdolphin/display/texture/texturedolphin.c index bb86bbe..5b429f7 100644 --- a/src/duskdolphin/display/texture/texturedolphin.c +++ b/src/duskdolphin/display/texture/texturedolphin.c @@ -87,62 +87,6 @@ errorret_t textureInitDolphin( // ); // break; - // case TEXTURE_FORMAT_ALPHA: { - // assertTrue( - // (width % 4) == 0 && (height % 4) == 0, - // "GX_TF_I8 requires w/h multiple of 4 (or pad)" - // ); - - // // 1 byte per pixel (I8), GX expects 4x4 tiled layout - // const size_t alphaSize = (size_t)width * (size_t)height; - - // texture->alpha = (u8*)memalign(32, alphaSize); - // assertNotNull(texture->alpha, "Failed to allocate alpha texture data"); - - // const u32 tilesPerRow = ((u32)width) >> 3; // /8 - - // for (u32 y = 0; y < (u32)height; ++y) { - // const u32 tileY = y >> 2; // /4 - // const u32 inTileY = (y & 3) << 3; // (y%4)*8 - - // for (u32 x = 0; x < (u32)width; ++x) { - // const u32 srcI = y * (u32)width + x; - // const u8 srcA = data.alpha.data[srcI]; // linear input - - // const u32 tileX = x >> 3; // /8 - // const u32 tileIndex = tileY * tilesPerRow + tileX; - - // const u32 tileBase = tileIndex * 32; // 8*4*1 = 32 bytes per tile - // const u32 inTile = inTileY + (x & 7); // (y%4)*8 + (x%8) - - // texture->alpha[tileBase + inTile] = 0xFF - srcA;// Fixes inverted alpha. - // } - // } - - // // Flush CPU cache so GX sees the swizzled I8 texture data - // DCFlushRange(texture->alpha, alphaSize); - - // // Initialize GX texture object with swizzled data - // GX_InitTexObj( - // &texture->texObj, - // texture->alpha, - // width, height, - // GX_TF_I8, - // GX_REPEAT, GX_REPEAT, - // GX_FALSE - // ); - - // GX_InitTexObjLOD( - // &texture->texObj, - // GX_NEAR, GX_NEAR, - // 0.0f, 0.0f, 0.0f, - // GX_FALSE, - // GX_FALSE, - // GX_ANISO_1 - // ); - // break; - // } - // case TEXTURE_FORMAT_PALETTE: { // // Not supported, convert to RGBA using lookup // color_t* formatted = memoryAllocate(width * height * sizeof(color_t)); @@ -176,6 +120,13 @@ errorret_t textureInitDolphin( } errorret_t textureBindDolphin(texturedolphin_t *texture) { + if(texture == NULL) { + GX_SetNumChans(0); + errorOk(); + } + + GX_SetNumChans(1); + GX_LoadTexObj(&texture->texObj, GX_TEXMAP0); errorOk(); } @@ -184,5 +135,71 @@ errorret_t textureDisposeDolphin(texturedolphin_t *texture) { } void textureDolphinUploadTEV(void) { + if(TEXTURE_BOUND == NULL) { + GX_SetNumChans(1); + GX_SetChanCtrl( + GX_COLOR0A0, + GX_DISABLE, + GX_SRC_REG, + GX_SRC_VTX, + GX_LIGHTNULL, + GX_DF_NONE, + GX_AF_NONE + ); + GX_SetChanAmbColor(GX_COLOR0A0, (GXColor){0, 0, 0, 0}); + GX_SetChanMatColor(GX_COLOR0A0, (GXColor){255, 255, 255, 255}); + GX_SetNumTexGens(0); + + GX_SetNumTevStages(1); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + + GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); + GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + + return; + } + + // Add channel for vertex color + GX_SetNumChans(1); + GX_SetChanCtrl( + GX_COLOR0A0,// Store in color channel 0 + GX_DISABLE,// Lighting disabled + GX_SRC_REG,// Ambient color? + GX_SRC_VTX,// Material color? + GX_LIGHTNULL,// Light Mask + GX_DF_NONE,// Diffuse function + GX_AF_NONE// Attenuation function + ); + + // One set of UVs + GX_SetNumTexGens(1); + GX_SetTexCoordGen( + GX_TEXCOORD0, + GX_TG_MTX2x4, + GX_TG_TEX0, + GX_IDENTITY + ); + + // Basically the shader setup + switch(TEXTURE_BOUND->format) { + case TEXTURE_FORMAT_RGBA: + // One TEV stage: vertex color * texture color + GX_SetNumTevStages(1); + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GX_SetTevOrder( + GX_TEVSTAGE0, + GX_TEXCOORD0, + GX_TEXMAP0, + GX_COLOR0A0 + ); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + break; + + default: + assertUnreachable("Unknown texture format in meshDraw"); + break; + } } \ No newline at end of file