From 81ed15b1717cb1c952fd2fc0f131dffc67838f20 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 15 Aug 2025 21:37:44 -0500 Subject: [PATCH] Builds on PSP again. --- CMakeLists.txt | 4 +- src/dusk/util/CMakeLists.txt | 1 + src/dusk/util/math.c | 19 +++++ src/dusk/util/math.h | 17 +++++ src/dusksdl2/CMakeLists.txt | 1 + .../display/framebuffer/framebuffer.c | 74 ++++++++++--------- .../display/framebuffer/framebuffer.h | 60 +++++++-------- src/dusksdl2/display/mesh/mesh.c | 8 +- src/dusksdl2/display/mesh/mesh.h | 10 ++- src/dusksdl2/display/render.c | 14 ++-- src/dusksdl2/display/rendertext.c | 30 ++++---- .../display/spritebatch/spritebatch.c | 6 +- .../display/spritebatch/spritebatch.h | 3 +- src/dusksdl2/display/texture/texture.c | 27 +++++-- src/dusksdl2/dusksdl2.h | 3 +- 15 files changed, 166 insertions(+), 111 deletions(-) create mode 100644 src/dusk/util/math.c create mode 100644 src/dusk/util/math.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 261b240..ef97795 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) if(NOT DEFINED DUSK_TARGET_SYSTEM) - set(DUSK_TARGET_SYSTEM "linux") - # set(DUSK_TARGET_SYSTEM "psp") + # set(DUSK_TARGET_SYSTEM "linux") + set(DUSK_TARGET_SYSTEM "psp") endif() # Prep cache diff --git a/src/dusk/util/CMakeLists.txt b/src/dusk/util/CMakeLists.txt index 915d256..75b1187 100644 --- a/src/dusk/util/CMakeLists.txt +++ b/src/dusk/util/CMakeLists.txt @@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE memory.c string.c + math.c ) \ No newline at end of file diff --git a/src/dusk/util/math.c b/src/dusk/util/math.c new file mode 100644 index 0000000..ac538d1 --- /dev/null +++ b/src/dusk/util/math.c @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "math.h" + +uint32_t mathNextPowTwo(uint32_t value) { + if (value == 0) return 1; // Handle zero case + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + return value + 1; +} \ No newline at end of file diff --git a/src/dusk/util/math.h b/src/dusk/util/math.h new file mode 100644 index 0000000..ac9bc07 --- /dev/null +++ b/src/dusk/util/math.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +/** + * Finds the next power of two greater than or equal to the given value. + * + * @param value The value to find the next power of two for. + * @return The next power of two greater than or equal to the value. + */ +uint32_t mathNextPowTwo(uint32_t value); \ No newline at end of file diff --git a/src/dusksdl2/CMakeLists.txt b/src/dusksdl2/CMakeLists.txt index 10ab0bd..b2b90b2 100644 --- a/src/dusksdl2/CMakeLists.txt +++ b/src/dusksdl2/CMakeLists.txt @@ -17,6 +17,7 @@ target_link_libraries(${DUSK_TARGET_NAME} PUBLIC SDL2::SDL2 OpenGL::GL + GL ) diff --git a/src/dusksdl2/display/framebuffer/framebuffer.c b/src/dusksdl2/display/framebuffer/framebuffer.c index 8198ebd..b99f71b 100644 --- a/src/dusksdl2/display/framebuffer/framebuffer.c +++ b/src/dusksdl2/display/framebuffer/framebuffer.c @@ -9,49 +9,51 @@ #include "assert/assert.h" #include "util/memory.h" -void frameBufferInit( - framebuffer_t *framebuffer, - const uint32_t width, - const uint32_t height -) { - assertNotNull(framebuffer, "Framebuffer cannot be NULL"); - assertTrue(width > 0 && height > 0, "Width & height must be greater than 0"); +#if RENDER_USE_FRAMEBUFFER + void frameBufferInit( + framebuffer_t *framebuffer, + const uint32_t width, + const uint32_t height + ) { + assertNotNull(framebuffer, "Framebuffer cannot be NULL"); + assertTrue(width > 0 && height > 0, "Width & height must be greater than 0"); - memoryZero(framebuffer, sizeof(framebuffer_t)); - textureInit(&framebuffer->texture, width, height, NULL); + memoryZero(framebuffer, sizeof(framebuffer_t)); + textureInit(&framebuffer->texture, width, height, NULL); - // Generate the framebuffer object - glGenFramebuffers(1, &framebuffer->id); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->id); + // Generate the framebuffer object using EXT + glGenFramebuffersEXT(1, &framebuffer->id); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id); - // Attach the texture to the framebuffer - glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, framebuffer->texture.id, 0 - ); + // Attach the texture to the framebuffer + glFramebufferTexture2DEXT( + GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, framebuffer->texture.id, 0 + ); - // Check if the framebuffer is complete - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - assertUnreachable("Framebuffer is not complete"); + // Check if the framebuffer is complete + if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { + assertUnreachable("Framebuffer is not complete"); + } + + // Unbind the framebuffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } - // Unbind the framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} + void frameBufferBind(const framebuffer_t *framebuffer) { + if(framebuffer == NULL) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + return; + } -void frameBufferBind(const framebuffer_t *framebuffer) { - if(framebuffer == NULL) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - return; + // Bind the framebuffer for rendering + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id); } - // Bind the framebuffer for rendering - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->id); -} + void frameBufferDispose(framebuffer_t *framebuffer) { + assertNotNull(framebuffer, "Framebuffer cannot be NULL"); -void frameBufferDispose(framebuffer_t *framebuffer) { - assertNotNull(framebuffer, "Framebuffer cannot be NULL"); - - glDeleteFramebuffers(1, &framebuffer->id); - textureDispose(&framebuffer->texture); -} \ No newline at end of file + glDeleteFramebuffersEXT(1, &framebuffer->id); + textureDispose(&framebuffer->texture); + } +#endif \ No newline at end of file diff --git a/src/dusksdl2/display/framebuffer/framebuffer.h b/src/dusksdl2/display/framebuffer/framebuffer.h index d61c524..5ddfa89 100644 --- a/src/dusksdl2/display/framebuffer/framebuffer.h +++ b/src/dusksdl2/display/framebuffer/framebuffer.h @@ -8,35 +8,37 @@ #pragma once #include "display/texture/texture.h" -typedef struct { - GLuint id; - texture_t texture; -} framebuffer_t; +#if RENDER_USE_FRAMEBUFFER + typedef struct { + GLuint id; + texture_t texture; + } framebuffer_t; -/** - * Initializes a framebuffer. - * - * @param framebuffer The framebuffer to initialize. - * @param width The width of the framebuffer. - * @param height The height of the framebuffer. - * @return An error code indicating success or failure. - */ -void frameBufferInit( - framebuffer_t *framebuffer, - const uint32_t width, - const uint32_t height -); + /** + * Initializes a framebuffer using EXT methods. + * + * @param framebuffer The framebuffer to initialize. + * @param width The width of the framebuffer. + * @param height The height of the framebuffer. + * @return An error code indicating success or failure. + */ + void frameBufferInit( + framebuffer_t *framebuffer, + const uint32_t width, + const uint32_t height + ); -/** - * Binds the framebuffer for rendering. - * - * @param framebuffer The framebuffer to bind, or NULL to unbind. - */ -void frameBufferBind(const framebuffer_t *framebuffer); + /** + * Binds the framebuffer for rendering using EXT methods. + * + * @param framebuffer The framebuffer to bind, or NULL to unbind. + */ + void frameBufferBind(const framebuffer_t *framebuffer); -/** - * Disposes of the framebuffer. - * - * @param framebuffer The framebuffer to dispose of. - */ -void frameBufferDispose(framebuffer_t *framebuffer); \ No newline at end of file + /** + * Disposes of the framebuffer using EXT methods. + * + * @param framebuffer The framebuffer to dispose of. + */ + void frameBufferDispose(framebuffer_t *framebuffer); +#endif \ No newline at end of file diff --git a/src/dusksdl2/display/mesh/mesh.c b/src/dusksdl2/display/mesh/mesh.c index a02bc7c..ca7fd9a 100644 --- a/src/dusksdl2/display/mesh/mesh.c +++ b/src/dusksdl2/display/mesh/mesh.c @@ -26,8 +26,6 @@ void meshInit( mesh->primitiveType = primitiveType; mesh->vertexCount = vertexCount; mesh->vertices = vertices; - - consolePrint("Init mesh"); } void meshDraw( @@ -50,19 +48,19 @@ void meshDraw( const GLsizei stride = sizeof(meshvertex_t); glColorPointer( - 4, + MESH_VERTEX_COLOR_SIZE, GL_UNSIGNED_BYTE, stride, (const GLvoid*)&mesh->vertices[offset].color[0] ); glTexCoordPointer( - 2, + MESH_VERTEX_UV_SIZE, GL_FLOAT, stride, (const GLvoid*)&mesh->vertices[offset].uv[0] ); glVertexPointer( - 3, + MESH_VERTEX_POS_SIZE, GL_FLOAT, stride, (const GLvoid*)&mesh->vertices[offset].pos[0] diff --git a/src/dusksdl2/display/mesh/mesh.h b/src/dusksdl2/display/mesh/mesh.h index 6c8f4ca..b0d00fd 100644 --- a/src/dusksdl2/display/mesh/mesh.h +++ b/src/dusksdl2/display/mesh/mesh.h @@ -6,10 +6,14 @@ #pragma once #include "dusksdl2.h" +#define MESH_VERTEX_COLOR_SIZE 4 +#define MESH_VERTEX_UV_SIZE 2 +#define MESH_VERTEX_POS_SIZE 3 + typedef struct { - GLubyte color[4]; - GLfloat uv[2]; - GLfloat pos[3]; + GLubyte color[MESH_VERTEX_COLOR_SIZE]; + GLfloat uv[MESH_VERTEX_UV_SIZE]; + GLfloat pos[MESH_VERTEX_POS_SIZE]; } meshvertex_t; typedef struct { diff --git a/src/dusksdl2/display/render.c b/src/dusksdl2/display/render.c index efffaf6..f5f8587 100644 --- a/src/dusksdl2/display/render.c +++ b/src/dusksdl2/display/render.c @@ -14,8 +14,6 @@ #include "dusksdl2input.h" #include "renderscene.h" #include "display/spritebatch/spritebatch.h" -#include "display/texture/texture.h" -#include "display/mesh/mesh.h" #include "display/camera/camera.h" SDL_Window *RENDER_WINDOW; @@ -62,11 +60,11 @@ errorret_t renderInit(void) { SDL_GL_SetSwapInterval(1); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING);// PSP defaults this on? + glShadeModel(GL_SMOOTH); // Fixes color on PSP? glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_LIGHTING);// PSP defaults this on? - glEnable(GL_TEXTURE_2D); - glShadeModel(GL_SMOOTH); // Fixes color on PSP? + glEnableClientState(GL_COLOR_ARRAY);// To confirm: every frame on PSP? glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); @@ -75,7 +73,7 @@ errorret_t renderInit(void) { renderTextInit(); renderBackBufferInit(); renderSceneInit(); - + RENDER_RUNNING = true; errorOk(); } @@ -93,7 +91,8 @@ errorret_t renderDraw(void) { } } - // Bind the backbuffer + // Reset the state + spriteBatchClear(); renderBackBufferBind(); // Draw everything @@ -108,6 +107,7 @@ errorret_t renderDraw(void) { // Finish rendering, now render back buffer. renderBackBufferUnbind(); renderBackBufferDraw(); + textureBind(NULL); SDL_GL_SwapWindow(RENDER_WINDOW); errorOk(); diff --git a/src/dusksdl2/display/rendertext.c b/src/dusksdl2/display/rendertext.c index 7c1c632..c3d3152 100644 --- a/src/dusksdl2/display/rendertext.c +++ b/src/dusksdl2/display/rendertext.c @@ -9,6 +9,8 @@ #include "render.h" #include "assert/assert.h" #include "display/spritebatch/spritebatch.h" +#include "util/memory.h" +#include "util/math.h" texture_t RENDER_TEXT_TEXTURE; @@ -20,19 +22,19 @@ void renderTextInit(void) { const int32_t inputFontWidth = cols * FONT_TILE_WIDTH; const int32_t inputFontHeight = rows * FONT_TILE_HEIGHT; - // Round up to nearest multiple of 4 int32_t outputFontWidth = inputFontWidth; - if(outputFontWidth % 4 != 0) { - outputFontWidth += 4 - (outputFontWidth % 4); - } - - // Round up to nearest multiple of 2 int32_t outputFontHeight = inputFontHeight; - if(outputFontHeight % 2 != 0) { - outputFontHeight += 2 - (outputFontHeight % 2); - } - uint8_t pixels[outputFontWidth * outputFontHeight * sizeof(uint8_t) * 4]; + // Round up to nearest power of 2 + #if PSP + outputFontWidth = mathNextPowTwo(inputFontWidth); + outputFontHeight = mathNextPowTwo(inputFontHeight); + #endif + + uint8_t *pixels = (uint8_t *)memoryAllocate( + outputFontWidth * outputFontHeight * + 4 * sizeof(uint8_t) + ); // Buffer the pixels. for(int tileIndex = 0; tileIndex < FONT_TILE_COUNT; ++tileIndex) { @@ -53,12 +55,8 @@ void renderTextInit(void) { } } - textureInit( - &RENDER_TEXT_TEXTURE, - outputFontWidth, - outputFontHeight, - pixels - ); + textureInit(&RENDER_TEXT_TEXTURE, outputFontWidth, outputFontHeight, pixels); + memoryFree(pixels); } void renderTextDrawChar( diff --git a/src/dusksdl2/display/spritebatch/spritebatch.c b/src/dusksdl2/display/spritebatch/spritebatch.c index f6b85ed..8e2bac9 100644 --- a/src/dusksdl2/display/spritebatch/spritebatch.c +++ b/src/dusksdl2/display/spritebatch/spritebatch.c @@ -8,6 +8,7 @@ #include "spritebatch.h" #include "assert/assert.h" #include "util/memory.h" +#include "console/console.h" spritebatch_t SPRITEBATCH; @@ -19,7 +20,7 @@ void spriteBatchInit() { &SPRITEBATCH.mesh, GL_TRIANGLES, SPRITEBATCH_VERTEX_COUNT, - SPRITEBATCH.vertices + &SPRITEBATCH.vertices[0] ); } @@ -47,7 +48,6 @@ void spriteBatchPush( SPRITEBATCH.currentTexture = texture; } - // Get the vertex to buffer quadBuffer( &SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT], minX, minY, maxX, maxY, @@ -66,7 +66,7 @@ void spriteBatchClear() { void spriteBatchFlush() { if(SPRITEBATCH.spriteCount == 0) return; textureBind(SPRITEBATCH.currentTexture); - meshDraw(&SPRITEBATCH.mesh, -1, SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT); + meshDraw(&SPRITEBATCH.mesh, 0, QUAD_VERTEX_COUNT * SPRITEBATCH.spriteCount); spriteBatchClear(); } diff --git a/src/dusksdl2/display/spritebatch/spritebatch.h b/src/dusksdl2/display/spritebatch/spritebatch.h index 9991c9f..83de8d2 100644 --- a/src/dusksdl2/display/spritebatch/spritebatch.h +++ b/src/dusksdl2/display/spritebatch/spritebatch.h @@ -9,9 +9,10 @@ #include "display/mesh/quad.h" #include "display/texture/texture.h" -#define SPRITEBATCH_SPRITES_MAX 512 +#define SPRITEBATCH_SPRITES_MAX 1 #define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT) + typedef struct { mesh_t mesh; int32_t spriteCount; diff --git a/src/dusksdl2/display/texture/texture.c b/src/dusksdl2/display/texture/texture.c index 410e432..f40528f 100644 --- a/src/dusksdl2/display/texture/texture.c +++ b/src/dusksdl2/display/texture/texture.c @@ -8,6 +8,7 @@ #include "texture.h" #include "assert/assert.h" #include "util/memory.h" +#include "util/math.h" void textureInit( texture_t *texture, @@ -18,14 +19,14 @@ void textureInit( assertNotNull(texture, "Texture cannot be NULL"); assertTrue(width > 0 && height > 0, "Width and height must be greater than 0"); - #if PSP || 1 + #if PSP assertTrue( - width % 4 == 0, - "Width must be multiples of 4 for PSP" + width == mathNextPowTwo(width), + "Width must be powers of 2 for PSP" ); assertTrue( - height % 2 == 0, - "Height must be multiples of 2 for PSP" + height == mathNextPowTwo(height), + "Height must be powers of 2 for PSP" ); #endif @@ -44,15 +45,27 @@ void textureInit( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - + + glBindTexture(GL_TEXTURE_2D, 0); } void textureBind(const texture_t *texture) { if(texture == NULL) { - glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + // glBindTexture(GL_TEXTURE_2D, 0); return; } + + assertTrue( + texture->id != 0, + "Texture ID must not be 0" + ); + assertTrue( + texture->width > 0 && texture->height > 0, + "Texture width and height must be greater than 0" + ); + glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture->id); } diff --git a/src/dusksdl2/dusksdl2.h b/src/dusksdl2/dusksdl2.h index 1680cb1..318c111 100644 --- a/src/dusksdl2/dusksdl2.h +++ b/src/dusksdl2/dusksdl2.h @@ -11,5 +11,4 @@ #define GL_GLEXT_PROTOTYPES #include -#include - +#include \ No newline at end of file