From 91924e125995d24a139f77b52f30ea17d6b2eee7 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 19 Jun 2026 21:56:43 -0500 Subject: [PATCH] float -> float_t --- .../asset/loader/display/assettilesetloader.c | 4 +- src/dusk/engine/engine.c | 2 +- src/dusk/scene/CMakeLists.txt | 1 + src/dusk/scene/full/CMakeLists.txt | 9 + src/dusk/scene/full/scenefull.c | 165 ++++++++++++++++++ src/dusk/scene/full/scenefull.h | 18 ++ src/dusk/scene/scenetype.c | 7 + src/dusk/scene/scenetype.h | 3 + .../display/render/renderdolphin.c | 44 ++--- .../display/shader/shaderdolphin.c | 4 +- 10 files changed, 230 insertions(+), 27 deletions(-) create mode 100644 src/dusk/scene/full/CMakeLists.txt create mode 100644 src/dusk/scene/full/scenefull.c create mode 100644 src/dusk/scene/full/scenefull.h diff --git a/src/dusk/asset/loader/display/assettilesetloader.c b/src/dusk/asset/loader/display/assettilesetloader.c index 3e9cba92..07db838b 100644 --- a/src/dusk/asset/loader/display/assettilesetloader.c +++ b/src/dusk/asset/loader/display/assettilesetloader.c @@ -99,8 +99,8 @@ errorret_t assetTilesetLoaderSync(assetloading_t *loading) { assetLoaderErrorThrow(loading, "Row count cannot be 0"); } - out->uv[0] = endianLittleToHostFloat(*(float *)(data + 16)); - out->uv[1] = endianLittleToHostFloat(*(float *)(data + 20)); + out->uv[0] = endianLittleToHostFloat(*(float_t *)(data + 16)); + out->uv[1] = endianLittleToHostFloat(*(float_t *)(data + 20)); if(out->uv[1] < 0.0f || out->uv[1] > 1.0f) { memoryFree(data); diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index daf6045d..37823352 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -35,7 +35,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { errorChain(sceneInit()); consolePrint("Engine initialized"); - sceneSet(SCENE_TYPE_WHITE32); + sceneSet(SCENE_TYPE_FULL); errorOk(); } diff --git a/src/dusk/scene/CMakeLists.txt b/src/dusk/scene/CMakeLists.txt index 30f7198c..a5a20b24 100644 --- a/src/dusk/scene/CMakeLists.txt +++ b/src/dusk/scene/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} ) # Subdirs +add_subdirectory(full) add_subdirectory(overworld) add_subdirectory(rainbownothing) add_subdirectory(white32) \ No newline at end of file diff --git a/src/dusk/scene/full/CMakeLists.txt b/src/dusk/scene/full/CMakeLists.txt new file mode 100644 index 00000000..797c3326 --- /dev/null +++ b/src/dusk/scene/full/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + scenefull.c +) diff --git a/src/dusk/scene/full/scenefull.c b/src/dusk/scene/full/scenefull.c new file mode 100644 index 00000000..6841e766 --- /dev/null +++ b/src/dusk/scene/full/scenefull.c @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "scene/full/scenefull.h" +#include "assert/assert.h" +#include "display/render/render.h" +#include "display/screen.h" +#include "display/color.h" +#include "time/time.h" +#include "util/fixed.h" +#include "util/memory.h" + +static const uint8_t initIndices[3 * 3] = { + 0, 1, 2, + 3, 4, 5, + 6, 7, 8, +}; + +static const color_t initPalette[256] = { + [0] = { 255, 0, 0, 255 }, /* red */ + [1] = { 0, 255, 0, 255 }, /* green */ + [2] = { 0, 0, 255, 255 }, /* blue */ + [3] = { 255, 255, 0, 255 }, /* yellow */ + [4] = { 255, 0, 255, 255 }, /* magenta */ + [5] = { 0, 255, 255, 255 }, /* cyan */ + [6] = { 255, 165, 0, 255 }, /* orange */ + [7] = { 128, 0, 255, 255 }, /* purple */ + [8] = { 255, 255, 255, 255 }, /* white */ +}; + +static color_t hueColor(float_t t) { + uint8_t r = (uint8_t)((cosf(t) * 0.5f + 0.5f) * 255.0f); + uint8_t g = (uint8_t)((cosf(t - 2.094f) * 0.5f + 0.5f) * 255.0f); + uint8_t b = (uint8_t)((cosf(t - 4.189f) * 0.5f + 0.5f) * 255.0f); + return color(r, g, b, 255); +} + +static rtexture_t testTex; + +#define ASPECT FIXED((float_t)SCREEN_WIDTH / (float_t)SCREEN_HEIGHT) +#define FOV_Y FIXED(1.0472f) + +#define TILEMAP_TILE_W 16 +#define TILEMAP_TILE_H 16 +/* Array-size macros use raw DUSK_DISPLAY_* (no cast) so they remain integer + * constant expressions valid for stack array declarations. */ +#define TILEMAP_CHUNK_W (DUSK_DISPLAY_WIDTH / TILEMAP_TILE_W + 4) +#define TILEMAP_CHUNK_H (DUSK_DISPLAY_HEIGHT / TILEMAP_TILE_H + 1) +#define TILEMAP_Y (SCREEN_HEIGHT - 10) +#define TILEMAP_SCROLL_SPEED 40.0f +#define TILEMAP_SCROLL_RANGE 64.0f + +static rtexture_t tilemapTileset; +static rtilemapchunk_t tilemapChunk; + +static void renderTest2DQuad(void) { + renderSprite(50, 30, 192, 160, 0, testTex, COLOR_WHITE); +} + +static void renderTest2DZOrder(void) { + renderSprite(340, 30, 160, 160, 24000, testTex, color(100, 100, 220, 255)); + renderSprite(380, 60, 160, 160, 12000, testTex, color(220, 140, 60, 255)); + renderSprite(420, 90, 160, 160, 0, testTex, COLOR_WHITE); +} + +static void renderTest3DQuad(void) { + float_t angle = fixedToFloat(TIME.time); + renderQuad3D( + -180, 0, 0, + (int16_t)(cosf(angle) * 60.0f), 0, (int16_t)(sinf(angle) * 60.0f), + 0, 60, 0, + 0, testTex, COLOR_WHITE + ); +} + +static void renderTest3DOverlap(void) { + renderQuad3D( + 150, 0, -60, + 60, 0, 0, + 0, 60, 0, + 0, testTex, color(100, 100, 220, 255) + ); + renderQuad3D( + 190, 0, 60, + 60, 0, 0, + 0, 60, 0, + 0, testTex, COLOR_WHITE + ); +} + +static void renderTestTilemap(void) { + float_t t = fixedToFloat(TIME.time); + float_t scrollPx = fmodf(t * TILEMAP_SCROLL_SPEED, TILEMAP_SCROLL_RANGE); + int16_t x = -(int16_t)(int)scrollPx; + renderTilemapChunk(x, TILEMAP_Y, 8000, tilemapChunk); +} + +errorret_t sceneFullInit(scenedata_t *data) { + testTex = renderTextureCreate(3, 3, initIndices, initPalette); + assertTrue(testTex != RTEXTURE_NONE, "Failed to create test texture"); + + uint8_t tsIdx[32 * 16]; + color_t tsPal[256]; + memoryZero(tsPal, sizeof(tsPal)); + for(int y = 0; y < 16; y++) + for(int x = 0; x < 32; x++) + tsIdx[y * 32 + x] = (x < 16) ? 0 : 1; + tsPal[0] = color(210, 180, 100, 255); + tsPal[1] = color( 60, 130, 60, 255); + tilemapTileset = renderTextureCreate(32, 16, tsIdx, tsPal); + assertTrue(tilemapTileset != RTEXTURE_NONE, "Failed to create tilemap tileset"); + + uint8_t chunkIdx[TILEMAP_CHUNK_W * TILEMAP_CHUNK_H]; + for(int row = 0; row < TILEMAP_CHUNK_H; row++) + for(int col = 0; col < TILEMAP_CHUNK_W; col++) + chunkIdx[row * TILEMAP_CHUNK_W + col] = (uint8_t)((col + row) % 2); + tilemapChunk = renderTilemapChunkCreate( + TILEMAP_CHUNK_W, TILEMAP_CHUNK_H, + TILEMAP_TILE_W, TILEMAP_TILE_H, + tilemapTileset, + chunkIdx + ); + + errorOk(); +} + +errorret_t sceneFullUpdate(scenedata_t *data) { + float_t t = fixedToFloat(TIME.time); + + renderTextureGetPalette(testTex)[8] = hueColor(t * 2.0f); + renderTextureGetIndices(testTex)[1 * 3 + 1] = (uint8_t)((uint32_t)t % 9u); + + color_t *tilePal = renderTextureGetPalette(tilemapTileset); + tilePal[0] = hueColor(t * 0.7f); + tilePal[1] = hueColor(t * 0.7f + 3.14159f); + + errorOk(); +} + +errorret_t sceneFullRender(scenedata_t *data) { + renderClear(color(24, 24, 40, 255)); + + renderTest2DQuad(); + renderTest2DZOrder(); + + renderSetProjection(FOV_Y, ASPECT, FIXED(10), FIXED(10000)); + renderSetView(0, 150, 400, 0, 0, 0); + renderTest3DQuad(); + renderTest3DOverlap(); + + renderTestTilemap(); + + errorOk(); +} + +errorret_t sceneFullDispose(scenedata_t *data) { + renderTilemapChunkDispose(tilemapChunk); + renderTextureDispose(tilemapTileset); + renderTextureDispose(testTex); + errorOk(); +} diff --git a/src/dusk/scene/full/scenefull.h b/src/dusk/scene/full/scenefull.h new file mode 100644 index 00000000..4e03e15f --- /dev/null +++ b/src/dusk/scene/full/scenefull.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "scene/scenebase.h" + +typedef struct { + int32_t _unused; +} scenefull_t; + +errorret_t sceneFullInit(scenedata_t *data); +errorret_t sceneFullUpdate(scenedata_t *data); +errorret_t sceneFullRender(scenedata_t *data); +errorret_t sceneFullDispose(scenedata_t *data); diff --git a/src/dusk/scene/scenetype.c b/src/dusk/scene/scenetype.c index 056ba698..eb0e925c 100644 --- a/src/dusk/scene/scenetype.c +++ b/src/dusk/scene/scenetype.c @@ -10,6 +10,13 @@ scenecallbacks_t SCENE_TYPES[SCENE_TYPE_COUNT] = { [SCENE_TYPE_NULL] = { 0 }, + [SCENE_TYPE_FULL] = { + .init = sceneFullInit, + .update = sceneFullUpdate, + .render = sceneFullRender, + .dispose = sceneFullDispose + }, + [SCENE_TYPE_OVERWORLD] = { .init = sceneOverworldInit, .update = sceneOverworldUpdate, diff --git a/src/dusk/scene/scenetype.h b/src/dusk/scene/scenetype.h index d0b352d0..f2e29cf7 100644 --- a/src/dusk/scene/scenetype.h +++ b/src/dusk/scene/scenetype.h @@ -7,11 +7,13 @@ #pragma once #include "scene/scenebase.h" +#include "scene/full/scenefull.h" #include "scene/overworld/sceneoverworld.h" #include "scene/rainbownothing/scenerainbownothing.h" #include "scene/white32/scenewhite32.h" typedef union scenedata_u { + scenefull_t full; sceneoverworld_t overworld; scenerainbownothing_t rainbownothing; scenewhite32_t white32; @@ -28,6 +30,7 @@ typedef struct { typedef enum { SCENE_TYPE_NULL, + SCENE_TYPE_FULL, SCENE_TYPE_OVERWORLD, SCENE_TYPE_RAINBOWNOTHING, SCENE_TYPE_WHITE32, diff --git a/src/duskdolphin/display/render/renderdolphin.c b/src/duskdolphin/display/render/renderdolphin.c index dce71a91..6760d5fd 100644 --- a/src/duskdolphin/display/render/renderdolphin.c +++ b/src/duskdolphin/display/render/renderdolphin.c @@ -262,10 +262,10 @@ static void draw2DSprite(const ropsprite_t *s) { bindTexture(s->texture); setTintChannel(s->tint); - float u0 = (s->uvX / 255.0f); - float v0 = (s->uvY / 255.0f); - float u1 = ((s->uvX + s->uvW) / 255.0f); - float v1 = ((s->uvY + s->uvH) / 255.0f); + float_t u0 = (s->uvX / 255.0f); + float_t v0 = (s->uvY / 255.0f); + float_t u1 = ((s->uvX + s->uvW) / 255.0f); + float_t v1 = ((s->uvY + s->uvH) / 255.0f); int16_t x0 = s->x, y0 = s->y; int16_t x1 = (int16_t)(s->x + s->w), y1 = (int16_t)(s->y + s->h); @@ -285,17 +285,17 @@ static void draw3DQuad(const ropquad3d_t *q) { bindTexture(q->texture); setTintChannel(q->tint); - float u0 = q->uvX/255.0f, v0 = q->uvY/255.0f; - float u1 = (q->uvX+q->uvW)/255.0f, v1 = (q->uvY+q->uvH)/255.0f; + float_t u0 = q->uvX/255.0f, v0 = q->uvY/255.0f; + float_t u1 = (q->uvX+q->uvW)/255.0f, v1 = (q->uvY+q->uvH)/255.0f; - float cx = (float)q->cx, cy = (float)q->cy, cz = (float)q->cz; - float rx = (float)q->rx, ry = (float)q->ry, rz = (float)q->rz; - float ux = (float)q->ux, uy = (float)q->uy, uz = (float)q->uz; + float_t cx = (float_t)q->cx, cy = (float_t)q->cy, cz = (float_t)q->cz; + float_t rx = (float_t)q->rx, ry = (float_t)q->ry, rz = (float_t)q->rz; + float_t ux = (float_t)q->ux, uy = (float_t)q->uy, uz = (float_t)q->uz; - float tlx = cx-rx+ux, tly = cy-ry+uy, tlz = cz-rz+uz; - float trx = cx+rx+ux, try_= cy+ry+uy, trz = cz+rz+uz; - float blx = cx-rx-ux, bly = cy-ry-uy, blz = cz-rz-uz; - float brx = cx+rx-ux, bry = cy+ry-uy, brz = cz+rz-uz; + float_t tlx = cx-rx+ux, tly = cy-ry+uy, tlz = cz-rz+uz; + float_t trx = cx+rx+ux, try_= cy+ry+uy, trz = cz+rz+uz; + float_t blx = cx-rx-ux, bly = cy-ry-uy, blz = cz-rz-uz; + float_t brx = cx+rx-ux, bry = cy+ry-uy, brz = cz+rz-uz; uint8_t r=q->tint.r, g=q->tint.g, b=q->tint.b, a=q->tint.a; GX_Begin(GX_QUADS, GX_VTXFMT0, 4); @@ -363,10 +363,10 @@ rtilemapchunk_t renderDolphinTilemapChunkCreate( int16_t px1 = (int16_t)(px0 + tileW); int16_t py1 = (int16_t)(py0 + tileH); - float u0 = (float)(tileCol * tileW) / (float)texW; - float v0 = (float)(tileRow * tileH) / (float)texH; - float u1 = u0 + (float)tileW / (float)texW; - float v1 = v0 + (float)tileH / (float)texH; + float_t u0 = (float_t)(tileCol * tileW) / (float_t)texW; + float_t v0 = (float_t)(tileRow * tileH) / (float_t)texH; + float_t u1 = u0 + (float_t)tileW / (float_t)texW; + float_t v1 = v0 + (float_t)tileH / (float_t)texH; GX_Position2s16(px0, py0); GX_Color4u8(255,255,255,255); GX_TexCoord2f32(u0,v0); GX_Position2s16(px1, py0); GX_Color4u8(255,255,255,255); GX_TexCoord2f32(u1,v0); @@ -439,13 +439,13 @@ errorret_t renderDolphinFlush(ropbuffer_t *buf) { case ROP_SET_PROJECTION: { const ropprojection_t *p = (const ropprojection_t *)hdr; if(p->fovY > FIXED_ZERO) { - float fovDeg = fixedToFloat(p->fovY) * (180.0f / 3.14159f); - float aspect = fixedToFloat(p->aspect); + float_t fovDeg = fixedToFloat(p->fovY) * (180.0f / 3.14159f); + float_t aspect = fixedToFloat(p->aspect); guPerspective(dolphinProj, fovDeg, aspect, fixedToFloat(p->nearZ), fixedToFloat(p->farZ)); } else { - float aspect = fixedToFloat(p->aspect); + float_t aspect = fixedToFloat(p->aspect); guOrtho(dolphinProj, -1.0f, 1.0f, -aspect, aspect, fixedToFloat(p->nearZ), fixedToFloat(p->farZ)); @@ -454,8 +454,8 @@ errorret_t renderDolphinFlush(ropbuffer_t *buf) { } case ROP_SET_VIEW: { const ropview_t *v = (const ropview_t *)hdr; - guVector eye = {(float)v->eyeX, (float)v->eyeY, (float)v->eyeZ}; - guVector target = {(float)v->tgtX, (float)v->tgtY, (float)v->tgtZ}; + guVector eye = {(float_t)v->eyeX, (float_t)v->eyeY, (float_t)v->eyeZ}; + guVector target = {(float_t)v->tgtX, (float_t)v->tgtY, (float_t)v->tgtZ}; guVector up = {0.0f, 1.0f, 0.0f}; guLookAt(dolphinView, &eye, &up, &target); if(dolphinIs3D) { diff --git a/src/duskdolphin/display/shader/shaderdolphin.c b/src/duskdolphin/display/shader/shaderdolphin.c index cc381b02..52f2d1ef 100644 --- a/src/duskdolphin/display/shader/shaderdolphin.c +++ b/src/duskdolphin/display/shader/shaderdolphin.c @@ -201,8 +201,8 @@ errorret_t shaderUpdateMVPDolphin() { shaderMat4ToMtx44(SHADER_BOUND->proj, SHADER_BOUND->dolphinProj); // Fix projection Z mapping between GLM and GX. - float A = SHADER_BOUND->dolphinProj[2][2]; - float B = SHADER_BOUND->dolphinProj[2][3]; + float_t A = SHADER_BOUND->dolphinProj[2][2]; + float_t B = SHADER_BOUND->dolphinProj[2][3]; SHADER_BOUND->dolphinProj[2][2] = 0.5f * (A + 1.0f); SHADER_BOUND->dolphinProj[2][3] = 0.5f * B;