Builds on PSP again.

This commit is contained in:
2025-08-15 21:37:44 -05:00
parent d1ab8b0cc8
commit 81ed15b171
15 changed files with 166 additions and 111 deletions

View File

@@ -10,8 +10,8 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
if(NOT DEFINED DUSK_TARGET_SYSTEM) if(NOT DEFINED DUSK_TARGET_SYSTEM)
set(DUSK_TARGET_SYSTEM "linux") # set(DUSK_TARGET_SYSTEM "linux")
# set(DUSK_TARGET_SYSTEM "psp") set(DUSK_TARGET_SYSTEM "psp")
endif() endif()
# Prep cache # Prep cache

View File

@@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
PRIVATE PRIVATE
memory.c memory.c
string.c string.c
math.c
) )

19
src/dusk/util/math.c Normal file
View File

@@ -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;
}

17
src/dusk/util/math.h Normal file
View File

@@ -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);

View File

@@ -17,6 +17,7 @@ target_link_libraries(${DUSK_TARGET_NAME}
PUBLIC PUBLIC
SDL2::SDL2 SDL2::SDL2
OpenGL::GL OpenGL::GL
GL
) )

View File

@@ -9,49 +9,51 @@
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
void frameBufferInit( #if RENDER_USE_FRAMEBUFFER
framebuffer_t *framebuffer, void frameBufferInit(
const uint32_t width, framebuffer_t *framebuffer,
const uint32_t height 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"); assertNotNull(framebuffer, "Framebuffer cannot be NULL");
assertTrue(width > 0 && height > 0, "Width & height must be greater than 0");
memoryZero(framebuffer, sizeof(framebuffer_t)); memoryZero(framebuffer, sizeof(framebuffer_t));
textureInit(&framebuffer->texture, width, height, NULL); textureInit(&framebuffer->texture, width, height, NULL);
// Generate the framebuffer object // Generate the framebuffer object using EXT
glGenFramebuffers(1, &framebuffer->id); glGenFramebuffersEXT(1, &framebuffer->id);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->id); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
// Attach the texture to the framebuffer // Attach the texture to the framebuffer
glFramebufferTexture2D( glFramebufferTexture2DEXT(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, framebuffer->texture.id, 0 GL_TEXTURE_2D, framebuffer->texture.id, 0
); );
// Check if the framebuffer is complete // Check if the framebuffer is complete
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
assertUnreachable("Framebuffer is not complete"); assertUnreachable("Framebuffer is not complete");
}
// Unbind the framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
} }
// Unbind the framebuffer void frameBufferBind(const framebuffer_t *framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, 0); if(framebuffer == NULL) {
} glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return;
}
void frameBufferBind(const framebuffer_t *framebuffer) { // Bind the framebuffer for rendering
if(framebuffer == NULL) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return;
} }
// Bind the framebuffer for rendering void frameBufferDispose(framebuffer_t *framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->id); assertNotNull(framebuffer, "Framebuffer cannot be NULL");
}
void frameBufferDispose(framebuffer_t *framebuffer) { glDeleteFramebuffersEXT(1, &framebuffer->id);
assertNotNull(framebuffer, "Framebuffer cannot be NULL"); textureDispose(&framebuffer->texture);
}
glDeleteFramebuffers(1, &framebuffer->id); #endif
textureDispose(&framebuffer->texture);
}

View File

@@ -8,35 +8,37 @@
#pragma once #pragma once
#include "display/texture/texture.h" #include "display/texture/texture.h"
typedef struct { #if RENDER_USE_FRAMEBUFFER
GLuint id; typedef struct {
texture_t texture; GLuint id;
} framebuffer_t; texture_t texture;
} framebuffer_t;
/** /**
* Initializes a framebuffer. * Initializes a framebuffer using EXT methods.
* *
* @param framebuffer The framebuffer to initialize. * @param framebuffer The framebuffer to initialize.
* @param width The width of the framebuffer. * @param width The width of the framebuffer.
* @param height The height of the framebuffer. * @param height The height of the framebuffer.
* @return An error code indicating success or failure. * @return An error code indicating success or failure.
*/ */
void frameBufferInit( void frameBufferInit(
framebuffer_t *framebuffer, framebuffer_t *framebuffer,
const uint32_t width, const uint32_t width,
const uint32_t height const uint32_t height
); );
/** /**
* Binds the framebuffer for rendering. * Binds the framebuffer for rendering using EXT methods.
* *
* @param framebuffer The framebuffer to bind, or NULL to unbind. * @param framebuffer The framebuffer to bind, or NULL to unbind.
*/ */
void frameBufferBind(const framebuffer_t *framebuffer); void frameBufferBind(const framebuffer_t *framebuffer);
/** /**
* Disposes of the framebuffer. * Disposes of the framebuffer using EXT methods.
* *
* @param framebuffer The framebuffer to dispose of. * @param framebuffer The framebuffer to dispose of.
*/ */
void frameBufferDispose(framebuffer_t *framebuffer); void frameBufferDispose(framebuffer_t *framebuffer);
#endif

View File

@@ -26,8 +26,6 @@ void meshInit(
mesh->primitiveType = primitiveType; mesh->primitiveType = primitiveType;
mesh->vertexCount = vertexCount; mesh->vertexCount = vertexCount;
mesh->vertices = vertices; mesh->vertices = vertices;
consolePrint("Init mesh");
} }
void meshDraw( void meshDraw(
@@ -50,19 +48,19 @@ void meshDraw(
const GLsizei stride = sizeof(meshvertex_t); const GLsizei stride = sizeof(meshvertex_t);
glColorPointer( glColorPointer(
4, MESH_VERTEX_COLOR_SIZE,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
stride, stride,
(const GLvoid*)&mesh->vertices[offset].color[0] (const GLvoid*)&mesh->vertices[offset].color[0]
); );
glTexCoordPointer( glTexCoordPointer(
2, MESH_VERTEX_UV_SIZE,
GL_FLOAT, GL_FLOAT,
stride, stride,
(const GLvoid*)&mesh->vertices[offset].uv[0] (const GLvoid*)&mesh->vertices[offset].uv[0]
); );
glVertexPointer( glVertexPointer(
3, MESH_VERTEX_POS_SIZE,
GL_FLOAT, GL_FLOAT,
stride, stride,
(const GLvoid*)&mesh->vertices[offset].pos[0] (const GLvoid*)&mesh->vertices[offset].pos[0]

View File

@@ -6,10 +6,14 @@
#pragma once #pragma once
#include "dusksdl2.h" #include "dusksdl2.h"
#define MESH_VERTEX_COLOR_SIZE 4
#define MESH_VERTEX_UV_SIZE 2
#define MESH_VERTEX_POS_SIZE 3
typedef struct { typedef struct {
GLubyte color[4]; GLubyte color[MESH_VERTEX_COLOR_SIZE];
GLfloat uv[2]; GLfloat uv[MESH_VERTEX_UV_SIZE];
GLfloat pos[3]; GLfloat pos[MESH_VERTEX_POS_SIZE];
} meshvertex_t; } meshvertex_t;
typedef struct { typedef struct {

View File

@@ -14,8 +14,6 @@
#include "dusksdl2input.h" #include "dusksdl2input.h"
#include "renderscene.h" #include "renderscene.h"
#include "display/spritebatch/spritebatch.h" #include "display/spritebatch/spritebatch.h"
#include "display/texture/texture.h"
#include "display/mesh/mesh.h"
#include "display/camera/camera.h" #include "display/camera/camera.h"
SDL_Window *RENDER_WINDOW; SDL_Window *RENDER_WINDOW;
@@ -62,11 +60,11 @@ errorret_t renderInit(void) {
SDL_GL_SetSwapInterval(1); SDL_GL_SetSwapInterval(1);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);// PSP defaults this on?
glShadeModel(GL_SMOOTH); // Fixes color on PSP?
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 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_COLOR_ARRAY);// To confirm: every frame on PSP?
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
@@ -93,7 +91,8 @@ errorret_t renderDraw(void) {
} }
} }
// Bind the backbuffer // Reset the state
spriteBatchClear();
renderBackBufferBind(); renderBackBufferBind();
// Draw everything // Draw everything
@@ -108,6 +107,7 @@ errorret_t renderDraw(void) {
// Finish rendering, now render back buffer. // Finish rendering, now render back buffer.
renderBackBufferUnbind(); renderBackBufferUnbind();
renderBackBufferDraw(); renderBackBufferDraw();
textureBind(NULL);
SDL_GL_SwapWindow(RENDER_WINDOW); SDL_GL_SwapWindow(RENDER_WINDOW);
errorOk(); errorOk();

View File

@@ -9,6 +9,8 @@
#include "render.h" #include "render.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "display/spritebatch/spritebatch.h" #include "display/spritebatch/spritebatch.h"
#include "util/memory.h"
#include "util/math.h"
texture_t RENDER_TEXT_TEXTURE; texture_t RENDER_TEXT_TEXTURE;
@@ -20,19 +22,19 @@ void renderTextInit(void) {
const int32_t inputFontWidth = cols * FONT_TILE_WIDTH; const int32_t inputFontWidth = cols * FONT_TILE_WIDTH;
const int32_t inputFontHeight = rows * FONT_TILE_HEIGHT; const int32_t inputFontHeight = rows * FONT_TILE_HEIGHT;
// Round up to nearest multiple of 4
int32_t outputFontWidth = inputFontWidth; int32_t outputFontWidth = inputFontWidth;
if(outputFontWidth % 4 != 0) {
outputFontWidth += 4 - (outputFontWidth % 4);
}
// Round up to nearest multiple of 2
int32_t outputFontHeight = inputFontHeight; 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. // Buffer the pixels.
for(int tileIndex = 0; tileIndex < FONT_TILE_COUNT; ++tileIndex) { for(int tileIndex = 0; tileIndex < FONT_TILE_COUNT; ++tileIndex) {
@@ -53,12 +55,8 @@ void renderTextInit(void) {
} }
} }
textureInit( textureInit(&RENDER_TEXT_TEXTURE, outputFontWidth, outputFontHeight, pixels);
&RENDER_TEXT_TEXTURE, memoryFree(pixels);
outputFontWidth,
outputFontHeight,
pixels
);
} }
void renderTextDrawChar( void renderTextDrawChar(

View File

@@ -8,6 +8,7 @@
#include "spritebatch.h" #include "spritebatch.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
#include "console/console.h"
spritebatch_t SPRITEBATCH; spritebatch_t SPRITEBATCH;
@@ -19,7 +20,7 @@ void spriteBatchInit() {
&SPRITEBATCH.mesh, &SPRITEBATCH.mesh,
GL_TRIANGLES, GL_TRIANGLES,
SPRITEBATCH_VERTEX_COUNT, SPRITEBATCH_VERTEX_COUNT,
SPRITEBATCH.vertices &SPRITEBATCH.vertices[0]
); );
} }
@@ -47,7 +48,6 @@ void spriteBatchPush(
SPRITEBATCH.currentTexture = texture; SPRITEBATCH.currentTexture = texture;
} }
// Get the vertex to buffer
quadBuffer( quadBuffer(
&SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT], &SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
minX, minY, maxX, maxY, minX, minY, maxX, maxY,
@@ -66,7 +66,7 @@ void spriteBatchClear() {
void spriteBatchFlush() { void spriteBatchFlush() {
if(SPRITEBATCH.spriteCount == 0) return; if(SPRITEBATCH.spriteCount == 0) return;
textureBind(SPRITEBATCH.currentTexture); textureBind(SPRITEBATCH.currentTexture);
meshDraw(&SPRITEBATCH.mesh, -1, SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT); meshDraw(&SPRITEBATCH.mesh, 0, QUAD_VERTEX_COUNT * SPRITEBATCH.spriteCount);
spriteBatchClear(); spriteBatchClear();
} }

View File

@@ -9,9 +9,10 @@
#include "display/mesh/quad.h" #include "display/mesh/quad.h"
#include "display/texture/texture.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) #define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT)
typedef struct { typedef struct {
mesh_t mesh; mesh_t mesh;
int32_t spriteCount; int32_t spriteCount;

View File

@@ -8,6 +8,7 @@
#include "texture.h" #include "texture.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
#include "util/math.h"
void textureInit( void textureInit(
texture_t *texture, texture_t *texture,
@@ -18,14 +19,14 @@ void textureInit(
assertNotNull(texture, "Texture cannot be NULL"); assertNotNull(texture, "Texture cannot be NULL");
assertTrue(width > 0 && height > 0, "Width and height must be greater than 0"); assertTrue(width > 0 && height > 0, "Width and height must be greater than 0");
#if PSP || 1 #if PSP
assertTrue( assertTrue(
width % 4 == 0, width == mathNextPowTwo(width),
"Width must be multiples of 4 for PSP" "Width must be powers of 2 for PSP"
); );
assertTrue( assertTrue(
height % 2 == 0, height == mathNextPowTwo(height),
"Height must be multiples of 2 for PSP" "Height must be powers of 2 for PSP"
); );
#endif #endif
@@ -45,14 +46,26 @@ void textureInit(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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) { void textureBind(const texture_t *texture) {
if(texture == NULL) { if(texture == NULL) {
glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D);
// glBindTexture(GL_TEXTURE_2D, 0);
return; 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); glBindTexture(GL_TEXTURE_2D, texture->id);
} }

View File

@@ -12,4 +12,3 @@
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glext.h> #include <GL/glext.h>