diff --git a/src/dusk/display/CMakeLists.txt b/src/dusk/display/CMakeLists.txt index 9779d059..5e525bc2 100644 --- a/src/dusk/display/CMakeLists.txt +++ b/src/dusk/display/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC display.c + screen.c ) dusk_run_python( diff --git a/src/dusk/display/screen.c b/src/dusk/display/screen.c new file mode 100644 index 00000000..f1d294ad --- /dev/null +++ b/src/dusk/display/screen.c @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "display/screen.h" + +screen_t SCREEN = { 0 }; diff --git a/src/dusk/display/screen.h b/src/dusk/display/screen.h index 5145920b..370e9d1b 100644 --- a/src/dusk/display/screen.h +++ b/src/dusk/display/screen.h @@ -8,5 +8,9 @@ #pragma once #include "dusk.h" -#define SCREEN_WIDTH ((int32_t)DUSK_DISPLAY_WIDTH) -#define SCREEN_HEIGHT ((int32_t)DUSK_DISPLAY_HEIGHT) +typedef struct { + int32_t width; + int32_t height; +} screen_t; + +extern screen_t SCREEN; diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index 37823352..050a3d91 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_FULL); + sceneSet(SCENE_TYPE_SPINNINGBOX); errorOk(); } diff --git a/src/dusk/scene/CMakeLists.txt b/src/dusk/scene/CMakeLists.txt index a5a20b24..2ba4664e 100644 --- a/src/dusk/scene/CMakeLists.txt +++ b/src/dusk/scene/CMakeLists.txt @@ -13,4 +13,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} add_subdirectory(full) add_subdirectory(overworld) add_subdirectory(rainbownothing) +add_subdirectory(spinningbox) add_subdirectory(white32) \ No newline at end of file diff --git a/src/dusk/scene/full/scenefull.c b/src/dusk/scene/full/scenefull.c index 6841e766..c1e9201a 100644 --- a/src/dusk/scene/full/scenefull.c +++ b/src/dusk/scene/full/scenefull.c @@ -41,53 +41,49 @@ static color_t hueColor(float_t t) { static rtexture_t testTex; -#define ASPECT FIXED((float_t)SCREEN_WIDTH / (float_t)SCREEN_HEIGHT) +#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 +#define TILEMAP_Y (SCREEN.height - 10) +#define TILEMAP_SCROLL_SPEED 20.0f +#define TILEMAP_SCROLL_RANGE 32.0f static rtexture_t tilemapTileset; static rtilemapchunk_t tilemapChunk; static void renderTest2DQuad(void) { - renderSprite(50, 30, 192, 160, 0, testTex, COLOR_WHITE); + renderSprite(25, 15, 96, 80, 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); + renderSprite(170, 15, 80, 80, 12000, testTex, color(100, 100, 220, 255)); + renderSprite(190, 30, 80, 80, 6000, testTex, color(220, 140, 60, 255)); + renderSprite(210, 45, 80, 80, 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, + -45, 0, 0, + (int16_t)(cosf(angle) * 30.0f), 0, (int16_t)(sinf(angle) * 30.0f), + 0, 30, 0, 0, testTex, COLOR_WHITE ); } static void renderTest3DOverlap(void) { renderQuad3D( - 150, 0, -60, - 60, 0, 0, - 0, 60, 0, + 40, 0, -30, + 30, 0, 0, + 0, 30, 0, 0, testTex, color(100, 100, 220, 255) ); renderQuad3D( - 190, 0, 60, - 60, 0, 0, - 0, 60, 0, + 50, 0, 30, + 30, 0, 0, + 0, 30, 0, 0, testTex, COLOR_WHITE ); } @@ -114,16 +110,20 @@ errorret_t sceneFullInit(scenedata_t *data) { 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); + int32_t chunkW = SCREEN.width / TILEMAP_TILE_W + 4; + int32_t chunkH = SCREEN.height / TILEMAP_TILE_H + 1; + uint8_t *chunkIdx = (uint8_t *)memoryAllocate((uint32_t)(chunkW * chunkH)); + assertNotNull(chunkIdx, "Failed to allocate tilemap chunk indices"); + for(int32_t row = 0; row < chunkH; row++) + for(int32_t col = 0; col < chunkW; col++) + chunkIdx[row * chunkW + col] = (uint8_t)((col + row) % 2); tilemapChunk = renderTilemapChunkCreate( - TILEMAP_CHUNK_W, TILEMAP_CHUNK_H, - TILEMAP_TILE_W, TILEMAP_TILE_H, + (uint16_t)chunkW, (uint16_t)chunkH, + TILEMAP_TILE_W, TILEMAP_TILE_H, tilemapTileset, chunkIdx ); + memoryFree(chunkIdx); errorOk(); } @@ -148,7 +148,7 @@ errorret_t sceneFullRender(scenedata_t *data) { renderTest2DZOrder(); renderSetProjection(FOV_Y, ASPECT, FIXED(10), FIXED(10000)); - renderSetView(0, 150, 400, 0, 0, 0); + renderSetView(0, 75, 200, 0, 0, 0); renderTest3DQuad(); renderTest3DOverlap(); diff --git a/src/dusk/scene/scenetype.c b/src/dusk/scene/scenetype.c index eb0e925c..bf48c371 100644 --- a/src/dusk/scene/scenetype.c +++ b/src/dusk/scene/scenetype.c @@ -31,6 +31,13 @@ scenecallbacks_t SCENE_TYPES[SCENE_TYPE_COUNT] = { .dispose = sceneRainbowNothingDispose }, + [SCENE_TYPE_SPINNINGBOX] = { + .init = sceneSpinningBoxInit, + .update = sceneSpinningBoxUpdate, + .render = sceneSpinningBoxRender, + .dispose = sceneSpinningBoxDispose + }, + [SCENE_TYPE_WHITE32] = { .init = sceneWhite32Init, .update = sceneWhite32Update, diff --git a/src/dusk/scene/scenetype.h b/src/dusk/scene/scenetype.h index f2e29cf7..9b7b3a74 100644 --- a/src/dusk/scene/scenetype.h +++ b/src/dusk/scene/scenetype.h @@ -10,12 +10,14 @@ #include "scene/full/scenefull.h" #include "scene/overworld/sceneoverworld.h" #include "scene/rainbownothing/scenerainbownothing.h" +#include "scene/spinningbox/scenespinningbox.h" #include "scene/white32/scenewhite32.h" typedef union scenedata_u { scenefull_t full; sceneoverworld_t overworld; scenerainbownothing_t rainbownothing; + scenespinningbox_t spinningbox; scenewhite32_t white32; } scenedata_t; @@ -33,6 +35,7 @@ typedef enum { SCENE_TYPE_FULL, SCENE_TYPE_OVERWORLD, SCENE_TYPE_RAINBOWNOTHING, + SCENE_TYPE_SPINNINGBOX, SCENE_TYPE_WHITE32, SCENE_TYPE_COUNT } scenetype_t; diff --git a/src/dusk/scene/spinningbox/CMakeLists.txt b/src/dusk/scene/spinningbox/CMakeLists.txt new file mode 100644 index 00000000..426eb16a --- /dev/null +++ b/src/dusk/scene/spinningbox/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 + scenespinningbox.c +) diff --git a/src/dusk/scene/spinningbox/scenespinningbox.c b/src/dusk/scene/spinningbox/scenespinningbox.c new file mode 100644 index 00000000..8b0d795d --- /dev/null +++ b/src/dusk/scene/spinningbox/scenespinningbox.c @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "scene/spinningbox/scenespinningbox.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 + +static const uint8_t BOX_INDICES[3 * 3] = { + 0, 1, 2, + 3, 4, 5, + 6, 7, 8, +}; + +static const color_t BOX_PALETTE[256] = { + [0] = { 255, 0, 0, 255 }, + [1] = { 0, 255, 0, 255 }, + [2] = { 0, 0, 255, 255 }, + [3] = { 255, 255, 0, 255 }, + [4] = { 255, 0, 255, 255 }, + [5] = { 0, 255, 255, 255 }, + [6] = { 255, 165, 0, 255 }, + [7] = { 128, 0, 255, 255 }, + [8] = { 255, 255, 255, 255 }, +}; + +static rtexture_t spinTex; + +#define ASPECT FIXED((float_t)SCREEN.width / (float_t)SCREEN.height) +#define FOV_Y FIXED(1.0472f) + +errorret_t sceneSpinningBoxInit(scenedata_t *data) { + spinTex = renderTextureCreate(3, 3, BOX_INDICES, BOX_PALETTE); + assertTrue(spinTex != RTEXTURE_NONE, "Failed to create spinningbox texture"); + errorOk(); +} + +errorret_t sceneSpinningBoxUpdate(scenedata_t *data) { + color_t *pal = renderTextureGetPalette(spinTex); + int32_t idx = rand() % 9; + pal[idx] = color( + (uint8_t)(rand() % 256), + (uint8_t)(rand() % 256), + (uint8_t)(rand() % 256), + 255 + ); + errorOk(); +} + +errorret_t sceneSpinningBoxRender(scenedata_t *data) { + renderClear(color(16, 16, 24, 255)); + + renderSetProjection(FOV_Y, ASPECT, FIXED(10), FIXED(10000)); + renderSetView(0, 0, 150, 0, 0, 0); + + float_t angle = fixedToFloat(TIME.time); + renderQuad3D( + 0, 0, 0, + (int16_t)(cosf(angle) * 40.0f), 0, (int16_t)(sinf(angle) * 40.0f), + 0, 40, 0, + 0, spinTex, COLOR_WHITE + ); + + errorOk(); +} + +errorret_t sceneSpinningBoxDispose(scenedata_t *data) { + renderTextureDispose(spinTex); + errorOk(); +} diff --git a/src/dusk/scene/spinningbox/scenespinningbox.h b/src/dusk/scene/spinningbox/scenespinningbox.h new file mode 100644 index 00000000..b2659295 --- /dev/null +++ b/src/dusk/scene/spinningbox/scenespinningbox.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; +} scenespinningbox_t; + +errorret_t sceneSpinningBoxInit(scenedata_t *data); +errorret_t sceneSpinningBoxUpdate(scenedata_t *data); +errorret_t sceneSpinningBoxRender(scenedata_t *data); +errorret_t sceneSpinningBoxDispose(scenedata_t *data); diff --git a/src/duskpsp/display/displaypsp.c b/src/duskpsp/display/displaypsp.c index 70fd8c2d..7d2e051e 100644 --- a/src/duskpsp/display/displaypsp.c +++ b/src/duskpsp/display/displaypsp.c @@ -8,6 +8,7 @@ #include "display/displaypsp.h" #include "display/render/renderpsp.h" #include "display/display.h" +#include "display/screen.h" #include "assert/assert.h" #include #include @@ -26,6 +27,8 @@ static uint32_t __attribute__((aligned(64))) displayList[0x10000]; errorret_t displayPSPInit(void) { DISPLAY.whichBuffer = 0; + SCREEN.width = PSP_SCREEN_W; + SCREEN.height = PSP_SCREEN_H; sceGuInit(); sceGuStart(GU_DIRECT, displayList); diff --git a/src/duskpsp/display/render/renderpsp.c b/src/duskpsp/display/render/renderpsp.c index 4fe72055..23667285 100644 --- a/src/duskpsp/display/render/renderpsp.c +++ b/src/duskpsp/display/render/renderpsp.c @@ -251,7 +251,7 @@ static void draw3DQuad(const ropquad3d_t *q) { verts[4] = (GuVert3D){u1,v1, abgr, brx,bry,brz}; verts[5] = (GuVert3D){u1,v0, abgr, trx,try_,trz}; - sceGuDrawArray( + sceGumDrawArray( GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, 0, verts diff --git a/src/dusksdl2/display/displaysdl2.c b/src/dusksdl2/display/displaysdl2.c index d66edc33..62de6d92 100644 --- a/src/dusksdl2/display/displaysdl2.c +++ b/src/dusksdl2/display/displaysdl2.c @@ -6,6 +6,7 @@ */ #include "display/display.h" +#include "display/screen.h" #include "engine/engine.h" #include "display/render/rendergl.h" #include "error/errorgl.h" @@ -57,6 +58,8 @@ errorret_t displaySDL2Flush(ropbuffer_t *buf) { int w, h; SDL_GetWindowSize(DISPLAY.window, &w, &h); + SCREEN.width = (int32_t)w; + SCREEN.height = (int32_t)h; errorChain(renderGLFlush(buf, w, h)); errorOk(); }