RGBA textures

This commit is contained in:
2026-02-05 21:57:56 -06:00
parent dd697d5650
commit 1af5f238e4
18 changed files with 370 additions and 154 deletions

View File

@@ -5,8 +5,10 @@ docker run -it -v ./:/workdir myapp:latest /bin/bash -c ' \
cd /workdir && \
rm -rf build2 && \
mkdir -p build2 && \
cmake -S. -Bbuild2 -DDUSK_TARGET_SYSTEM=gamecube -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/GameCube.cmake" && \
# cmake -S. -Bbuild2 -DDUSK_TARGET_SYSTEM=gamecube -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/GameCube.cmake" && \
cmake -S. -Bbuild2 -DDUSK_TARGET_SYSTEM=wii -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/Wii.cmake" && \
cd build2 && \
make VERBOSE=1 \
make VERBOSE=1 && \
cp ./Dusk.dol ./boot.dol
'
# docker run -it -v ./:/workdir myapp:latest /bin/bash

View File

@@ -16,6 +16,21 @@ if PLATFORM == "psp" then
inputBind("lstick_down", INPUT_ACTION_DOWN)
inputBind("lstick_left", INPUT_ACTION_LEFT)
inputBind("lstick_right", INPUT_ACTION_RIGHT)
elseif PLATFORM == "gamecube" then
inputBind("start", INPUT_ACTION_RAGEQUIT)
-- inputBind("dpad_up", INPUT_ACTION_UP)
-- inputBind("dpad_down", INPUT_ACTION_DOWN)
-- inputBind("dpad_left", INPUT_ACTION_LEFT)
-- inputBind("dpad_right", INPUT_ACTION_RIGHT)
-- inputBind("button_b", INPUT_ACTION_CANCEL)
-- inputBind("button_a", INPUT_ACTION_ACCEPT)
-- inputBind("button_start", INPUT_ACTION_RAGEQUIT)
-- inputBind("lstick_up", INPUT_ACTION_UP)
-- inputBind("lstick_down", INPUT_ACTION_DOWN)
-- inputBind("lstick_left", INPUT_ACTION_LEFT)
-- inputBind("lstick_right", INPUT_ACTION_RIGHT)
else
if INPUT_KEYBOARD then
inputBind("w", INPUT_ACTION_UP)

View File

@@ -40,26 +40,6 @@ display_t DISPLAY = { 0 };
}
#endif
meshvertex_t vertices[3] = {
{
.color = COLOR_RED_4B,
.uv = { 0.5f, 1.0f },
.pos = { 0.0f, 15.0f, 0.0f }
},
{
.color = COLOR_GREEN_4B,
.uv = { 0.0f, 0.0f },
.pos = { -15.0f, -15.0f, 0.0f }
},
{
.color = COLOR_BLUE_4B,
.uv = { 1.0f, 0.0f },
.pos = { 15.0f, -15.0f, 0.0f }
}
};
errorret_t displayInit(void) {
#if DISPLAY_SDL2
uint32_t flags = SDL_INIT_VIDEO;
@@ -213,6 +193,36 @@ errorret_t displayUpdate(void) {
);
errorChain(sceneRender());
color_t colors[4 * 4] = {
COLOR_RED_4B, COLOR_GREEN_4B, COLOR_BLUE_4B, COLOR_YELLOW_4B,
COLOR_CYAN_4B, COLOR_MAGENTA_4B, COLOR_WHITE_4B, COLOR_BLACK_4B,
COLOR_ORANGE_4B, COLOR_PURPLE_4B, COLOR_GRAY_4B, COLOR_BROWN_4B,
COLOR_PINK_4B, COLOR_LIME_4B, COLOR_NAVY_4B, COLOR_TEAL_4B
};
texturedata_t data = {
.rgba = { .colors = colors }
};
camera_t camera;
cameraInit(&camera);
texture_t texture;
textureInit(&texture, 4, 4, TEXTURE_FORMAT_RGBA, data);
cameraPushMatrix(&camera);
spriteBatchClear();
spriteBatchPush(
&texture,
-1, -1,
1, 1,
COLOR_WHITE_4B,
0, 0,
1, 1
);
spriteBatchFlush();
cameraPopMatrix();
textureDispose(&texture);
// Render UI
// uiRender();

View File

@@ -72,32 +72,64 @@ void meshDraw(
#elif DOLPHIN
// Prepare Vertex descriptor
DCFlushRange(
(void*)&mesh->vertices[offset],
sizeof(meshvertex_t) * count
);
GX_ClearVtxDesc();// Just clears so may be un-needed?
GX_SetVtxDesc(GX_VA_POS, GX_INDEX16);
// GX_SetVtxDesc(GX_VA_TEX0, 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_TEX0, GX_TEX_ST, GX_F32, 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);
const u8 stride = (u8)sizeof(meshvertex_t);
GX_SetArray(GX_VA_POS, &mesh->vertices[offset].pos[0], stride);
// GX_SetArray(GX_VA_TEX0, &mesh->vertices[offset].uv[0], stride);
GX_SetArray(GX_VA_CLR0, &mesh->vertices[offset].color, stride);
GX_SetArray(GX_VA_TEX0, &mesh->vertices[offset].uv[0], stride);
// GX_SetNumChans(1);// How many color channels are used
// GX_SetNumTexGens(0);// How many texture coordinate generators are used
// GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
// GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_SetNumChans(1);// How many color channels are used
GX_SetNumTexGens(0);// How many texture coordinate generators are used
// Basically the shader setup
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
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
);
GX_SetNumTexGens(1);
GX_SetTexCoordGen(
GX_TEXCOORD0,
GX_TG_MTX2x4,
GX_TG_TEX0,
GX_IDENTITY
);
GX_SetTevOrder(
GX_TEVSTAGE0,
GX_TEXCOORD0,
GX_TEXMAP0,
GX_COLOR0A0
);
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
GX_Begin(mesh->primitiveType, GX_VTXFMT0, (uint16_t)count);
for(u16 i = 0; i < (u16)count; ++i) {
GX_Position1x16(i);
// GX_TexCoord1x16(i);
GX_Color1x16(i);
GX_TexCoord1x16(i);
}
GX_End();
#endif

View File

@@ -22,21 +22,13 @@ typedef enum {
#define MESH_VERTEX_UV_SIZE 2
#define MESH_VERTEX_POS_SIZE 3
#if DOLPHIN
typedef struct ATTRIBUTE_ALIGN(32) {
#else
typedef struct {
#endif
color4b_t color;
typedef struct {
color_t color;
float uv[MESH_VERTEX_UV_SIZE];
float pos[MESH_VERTEX_POS_SIZE];
} meshvertex_t;
#if DOLPHIN
typedef struct ATTRIBUTE_ALIGN(32) {
#else
typedef struct {
#endif
typedef struct {
const meshvertex_t *vertices;
int32_t vertexCount;
meshprimitivetype_t primitiveType;

View File

@@ -10,13 +10,13 @@
mesh_t QUAD_MESH_SIMPLE;
meshvertex_t QUAD_MESH_SIMPLE_VERTICES[QUAD_VERTEX_COUNT] = {
{ COLOR_WHITE_4B, { 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ COLOR_WHITE_4B, { 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } },
{ COLOR_WHITE_4B, { 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f } },
{ COLOR_WHITE_4B, { 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ COLOR_WHITE_4B, { 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f } },
{ COLOR_WHITE_4B, { 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f } }
{ .color = COLOR_WHITE_4B, .uv = { 0.0f, 0.0f }, .pos = { 0.0f, 0.0f, 0.0f } },
{ .color = COLOR_WHITE_4B, .uv = { 1.0f, 0.0f }, .pos = { 1.0f, 0.0f, 0.0f } },
{ .color = COLOR_WHITE_4B, .uv = { 1.0f, 1.0f }, .pos = { 1.0f, 1.0f, 0.0f } },
{ .color = COLOR_WHITE_4B, .uv = { 0.0f, 0.0f }, .pos = { 0.0f, 0.0f, 0.0f } },
{ .color = COLOR_WHITE_4B, .uv = { 1.0f, 1.0f }, .pos = { 1.0f, 1.0f, 0.0f } },
{ .color = COLOR_WHITE_4B, .uv = { 0.0f, 1.0f }, .pos = { 0.0f, 1.0f, 0.0f } }
};
void quadInit() {
@@ -44,38 +44,48 @@ void quadBuffer(
assertNotNull(vertices, "Vertices cannot be NULL");
// First triangle
vertices[0] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ u0, v0 }, // UV
{ minX, minY, z } // Position
};
vertices[1] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ u1, v0 }, // UV
{ maxX, minY, z } // Position
};
vertices[2] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ u1, v1 }, // UV
{ maxX, maxY, z } // Position
};
vertices[0].color = color;
vertices[0].uv[0] = u0;
vertices[0].uv[1] = v1;
vertices[0].pos[0] = minX;
vertices[0].pos[1] = maxY;
vertices[0].pos[2] = z;
vertices[2].color = color;
vertices[2].uv[0] = u0;
vertices[2].uv[1] = v0;
vertices[2].pos[0] = minX;
vertices[2].pos[1] = minY;
vertices[2].pos[2] = z;
vertices[1].color = color;
vertices[1].uv[0] = u1;
vertices[1].uv[1] = v0;
vertices[1].pos[0] = maxX;
vertices[1].pos[1] = minY;
vertices[1].pos[2] = z;
// Second triangle
vertices[3] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ u0, v0 }, // UV
{ minX, minY, z } // Position
};
vertices[4] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ u1, v1 }, // UV
{ maxX, maxY, z } // Position
};
vertices[5] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ u0, v1 }, // UV
{ minX, maxY, z } // Position
};
vertices[3].color = color;
vertices[3].uv[0] = u0;
vertices[3].uv[1] = v1;
vertices[3].pos[0] = minX;
vertices[3].pos[1] = maxY;
vertices[3].pos[2] = z;
vertices[5].color = color;
vertices[5].uv[0] = u1;
vertices[5].uv[1] = v0;
vertices[5].pos[0] = maxX;
vertices[5].pos[1] = minY;
vertices[5].pos[2] = z;
vertices[4].color = color;
vertices[4].uv[0] = u1;
vertices[4].uv[1] = v1;
vertices[4].pos[0] = maxX;
vertices[4].pos[1] = maxY;
vertices[4].pos[2] = z;
}
void quadBuffer3D(
@@ -93,36 +103,46 @@ void quadBuffer3D(
assertNotNull(uvMax, "UV Max vector cannot be NULL");
// First triangle
vertices[0] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ uvMin[0], uvMin[1] }, // UV
{ min[0], min[1], min[2] } // Position
};
vertices[1] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ uvMax[0], uvMin[1] }, // UV
{ max[0], min[1], min[2] } // Position
};
vertices[2] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ uvMax[0], uvMax[1] }, // UV
{ max[0], max[1], min[2] } // Position
};
vertices[0].color = color;
vertices[0].uv[0] = uvMin[0];
vertices[0].uv[1] = uvMin[1];
vertices[0].pos[0] = min[0];
vertices[0].pos[1] = min[1];
vertices[0].pos[2] = min[2];
vertices[1].color = color;
vertices[1].uv[0] = uvMax[0];
vertices[1].uv[1] = uvMin[1];
vertices[1].pos[0] = max[0];
vertices[1].pos[1] = min[1];
vertices[1].pos[2] = min[2];
vertices[2].color = color;
vertices[2].uv[0] = uvMax[0];
vertices[2].uv[1] = uvMax[1];
vertices[2].pos[0] = max[0];
vertices[2].pos[1] = max[1];
vertices[2].pos[2] = min[2];
// Second triangle
vertices[3] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ uvMin[0], uvMin[1] }, // UV
{ min[0], min[1], min[2] } // Position
};
vertices[4] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ uvMax[0], uvMax[1] }, // UV
{ max[0], max[1], min[2] } // Position
};
vertices[5] = (meshvertex_t) {
{ color.r, color.g, color.b, color.a }, // Color
{ uvMin[0], uvMax[1] }, // UV
{ min[0], max[1], min[2] } // Position
};
vertices[3].color = color;
vertices[3].uv[0] = uvMin[0];
vertices[3].uv[1] = uvMin[1];
vertices[3].pos[0] = min[0];
vertices[3].pos[1] = min[1];
vertices[3].pos[2] = min[2];
vertices[4].color = color;
vertices[4].uv[0] = uvMax[0];
vertices[4].uv[1] = uvMax[1];
vertices[4].pos[0] = max[0];
vertices[4].pos[1] = max[1];
vertices[4].pos[2] = min[2];
vertices[5].color = color;
vertices[5].uv[0] = uvMin[0];
vertices[5].uv[1] = uvMax[1];
vertices[5].pos[0] = min[0];
vertices[5].pos[1] = max[1];
vertices[5].pos[2] = min[2];
}

View File

@@ -9,9 +9,12 @@
#include "assert/assert.h"
#include "util/memory.h"
meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT];
spritebatch_t SPRITEBATCH;
void spriteBatchInit() {
memoryZero(&SPRITEBATCH, sizeof(spritebatch_t));
SPRITEBATCH.spriteCount = 0;
SPRITEBATCH.currentTexture = NULL;
@@ -19,7 +22,7 @@ void spriteBatchInit() {
&SPRITEBATCH.mesh,
MESH_PRIMITIVE_TRIANGLES,
SPRITEBATCH_VERTEX_COUNT,
&SPRITEBATCH.vertices[0]
&SPRITEBATCH_VERTICES[0]
);
}
@@ -45,7 +48,7 @@ void spriteBatchPush(
}
quadBuffer(
&SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
&SPRITEBATCH_VERTICES[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
minX, minY, maxX, maxY,
color,
u0, v0, u1, v1
@@ -72,7 +75,7 @@ void spriteBatchPush3D(
}
quadBuffer3D(
&SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
&SPRITEBATCH_VERTICES[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
min, max, color, uv0, uv1
);

View File

@@ -17,9 +17,11 @@ typedef struct {
mesh_t mesh;
int32_t spriteCount;
texture_t *currentTexture;
meshvertex_t vertices[SPRITEBATCH_VERTEX_COUNT];
} 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;
/**

View File

@@ -144,10 +144,78 @@ void textureInit(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
texture->ready = true;
#elif DOLPHIN
assertTrue((width % 4) == 0 && (height % 4) == 0, "RGB5A3 requires w/h multiple of 4 (or pad)");
// Convert to RGB5A3 format
size_t rgbaSize = width * height * sizeof(u16);
texture->rgba = (u16*)memalign(32, rgbaSize);
for(uint32_t y = 0; y < height; ++y) {
for(uint32_t x = 0; x < width; ++x) {
const int src = y * width + x;
const int tileX = x >> 2;
const int tileY = y >> 2;
const int tilesPerRow = width >> 2;
const int tileIndex = tileY * tilesPerRow + tileX;
const int tileBaseWords = tileIndex * 16;
const int inTile = ((y & 3) << 2) + (x & 3);
const int dest = tileBaseWords + inTile;
color4b_t col = data.rgba.colors[src];
u16 outCol;
if(col.a < 255) {
// 0AAA RRRR GGGG BBBB
outCol = (
(0u << 15) |
((u16)(col.a >> 5) << 12) |
((u16)(col.r >> 4) << 8) |
((u16)(col.g >> 4) << 4) |
((u16)(col.b >> 4) << 0)
);
} else {
// 1RRRR RRGG GGGB BBBB
outCol = (
(1u << 15) |
((u16)(col.r >> 3) << 10) |
((u16)(col.g >> 3) << 5) |
((u16)(col.b >> 3) << 0)
);
}
texture->rgba[dest] = outCol;
}
}
DCFlushRange(texture->rgba, rgbaSize);
GX_InitTexObj(
&texture->texObj,
texture->rgba,
width, height,
GX_TF_RGB5A3,
GX_CLAMP, GX_CLAMP,
GX_FALSE
);
DCFlushRange(texture->rgba, rgbaSize);
GX_InvalidateTexAll();
GX_InitTexObjLOD(
&texture->texObj,
GX_NEAR, GX_NEAR,
0.0f, 0.0f, 0.0f,
GX_FALSE,
GX_FALSE,
GX_ANISO_1
);
texture->ready = true;
#endif
}
void textureBind(const texture_t *texture) {
void textureBind(texture_t *texture) {
if(TEXTURE_BOUND == texture) return;
if(texture == NULL) {
@@ -158,10 +226,7 @@ void textureBind(const texture_t *texture) {
return;
}
assertTrue(
texture->id != 0,
"Texture ID must not be 0"
);
assertTrue(texture->ready, "Texture ID must be ready");
assertTrue(
texture->width > 0 && texture->height > 0,
"Texture width and height must be greater than 0"
@@ -171,15 +236,28 @@ void textureBind(const texture_t *texture) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture->id);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#elif DOLPHIN
GX_LoadTexObj(&texture->texObj, GX_TEXMAP0);
#endif
TEXTURE_BOUND = texture;
}
void textureDispose(texture_t *texture) {
assertNotNull(texture, "Texture cannot be NULL");
assertTrue(texture->id != 0, "Texture ID must not be 0");
assertTrue(texture->ready, "Texture ID must be ready");
if(TEXTURE_BOUND == texture) {
textureBind(NULL);
}
#if DISPLAY_SDL2
glDeleteTextures(1, &texture->id);
#elif DOLPHIN
if(texture->rgba) {
free(texture->rgba);
texture->rgba = NULL;
}
#endif
}

View File

@@ -25,9 +25,14 @@ typedef struct {
#if DISPLAY_SDL2
GLuint id;
#elif DOLPHIN
uint8_t id;
GXTexObj texObj;
union {
u16 *rgba;
};
#endif
bool_t ready;
int32_t width;
int32_t height;
} texture_t;
@@ -71,7 +76,7 @@ void textureInit(
*
* @param texture The texture to bind.
*/
void textureBind(const texture_t *texture);
void textureBind(texture_t *texture);
/**
* Disposes a texture.

View File

@@ -32,6 +32,7 @@
#if DOLPHIN
#include <ogcsys.h>
#include <gccore.h>
#include <malloc.h>
#endif
typedef bool bool_t;

View File

@@ -62,6 +62,8 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
" inputBind(\"lstick_down\", INPUT_ACTION_DOWN)\n"
" inputBind(\"lstick_left\", INPUT_ACTION_LEFT)\n"
" inputBind(\"lstick_right\", INPUT_ACTION_RIGHT)\n"
// "elseif PLATFORM == \"gamecube\" then\n"
// " inputBind(\"start\", INPUT_ACTION_RAGEQUIT)\n"
"else\n"
" if INPUT_KEYBOARD then\n"
" inputBind(\"w\", INPUT_ACTION_UP)\n"
@@ -79,8 +81,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
" end \n"
"end\n"
// "localeSet(DUSK_LOCALE_EN_US)\n"
"sceneSet('scene/initial.dsf')\n"
// "sceneSet('scene/initial.dsf')\n"
));
scriptContextDispose(&ctx);

View File

@@ -55,7 +55,17 @@ void inputUpdate(void) {
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
#endif
#elif DOLPHIN
PAD_Read(INPUT.pads);
PAD_ScanPads();
for(uint8_t i = 0; i < INPUT_PAD_COUNT; i++) {
INPUT.padState[i] = PAD_ButtonsDown(i);
INPUT.pads[i][INPUT_GAMEPAD_AXIS_LEFT_X] = INPUT_AXIS_FLOAT(PAD_StickX(i));
INPUT.pads[i][INPUT_GAMEPAD_AXIS_LEFT_Y] = INPUT_AXIS_FLOAT(PAD_StickY(i));
INPUT.pads[i][INPUT_GAMEPAD_AXIS_C_X] = INPUT_AXIS_FLOAT(PAD_SubStickX(i));
INPUT.pads[i][INPUT_GAMEPAD_AXIS_C_Y] = INPUT_AXIS_FLOAT(PAD_SubStickY(i));
INPUT.pads[i][INPUT_GAMEPAD_AXIS_TRIGGER_LEFT] = INPUT_AXIS_FLOAT(PAD_TriggerL(i));
INPUT.pads[i][INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT] = INPUT_AXIS_FLOAT(PAD_TriggerR(i));
}
#endif

View File

@@ -10,6 +10,11 @@
#include "inputaction.h"
#include "event/event.h"
#if DOLPHIN
#define INPUT_PAD_COUNT PAD_CHANMAX
#define INPUT_AXIS_FLOAT(value) ((float_t)(value) / 128.0f)
#endif
#define INPUT_LISTENER_PRESSED_MAX 16
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
@@ -39,7 +44,8 @@ typedef struct {
#endif
#elif DOLPHIN
PADStatus pads[4];
int padState[INPUT_PAD_COUNT];
float_t pads[INPUT_PAD_COUNT][INPUT_GAMEPAD_AXIS_COUNT];
#endif
} input_t;

View File

@@ -173,27 +173,58 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
#endif
#elif DOLPHIN
#if INPUT_GAMEPAD == 1
{ .name = "a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_A } },
{ .name = "b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_B } },
{ .name = "x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_X } },
{ .name = "y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_Y } },
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_START } },
{ .name = "dpad_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_UP } },
{ .name = "dpad_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_DOWN } },
{ .name = "dpad_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_LEFT } },
{ .name = "dpad_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_RIGHT } },
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_L } },
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_R } },
{ .name = "z", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_Z } },
{ .name = "lstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
{ .name = "cstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
{ .name = "cstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
{ .name = "cstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
{ .name = "cstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
#if WII
#if INPUT_GAMEPAD == 1
{ .name = "a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_A } },
{ .name = "b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_B } },
{ .name = "x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_X } },
{ .name = "y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_Y } },
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_START } },
{ .name = "dpad_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_UP } },
{ .name = "dpad_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_DOWN } },
{ .name = "dpad_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_LEFT } },
{ .name = "dpad_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_RIGHT } },
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_L } },
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_R } },
{ .name = "z", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_Z } },
{ .name = "menu", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_MENU } },
{ .name = "lstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
{ .name = "cstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
{ .name = "cstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
{ .name = "cstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
{ .name = "cstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
{ .name = "ltrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_LEFT, .positive = true } } },
{ .name = "rtrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT, .positive = true } } },
#endif
#elif GAMECUBE
#if INPUT_GAMEPAD == 1
{ .name = "a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_A } },
{ .name = "b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_B } },
{ .name = "x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_X } },
{ .name = "y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_Y } },
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_START } },
{ .name = "dpad_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_UP } },
{ .name = "dpad_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_DOWN } },
{ .name = "dpad_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_LEFT } },
{ .name = "dpad_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_RIGHT } },
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_L } },
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_R } },
{ .name = "z", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_Z } },
{ .name = "menu", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_MENU } },
{ .name = "lstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
{ .name = "cstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
{ .name = "cstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
{ .name = "cstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
{ .name = "cstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
{ .name = "ltrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_LEFT, .positive = true } } },
{ .name = "rtrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT, .positive = true } } },
#endif
#endif
#endif
@@ -232,21 +263,28 @@ float_t inputButtonGetValue(const inputbutton_t button) {
if(SDL_GameControllerGetButton(INPUT.controller, button.gpButton)) {
return 1.0f;
}
#elif DOLPHIN
if(INPUT.padState[0] & button.gpButton) return 1.0f;
#endif
return 0.0f;
}
case INPUT_BUTTON_TYPE_GAMEPAD_AXIS: {
float_t value = 0.0f;
#if INPUT_SDL2 == 1
Sint16 axis = SDL_GameControllerGetAxis(INPUT.controller, button.gpAxis.axis);
if(!button.gpAxis.positive) axis = -axis;
float_t value = (float_t)axis / 32767.0f;
// Deadzone
if(value < INPUT.deadzone) return 0.0f;
return value;
value = (float_t)axis / 32767.0f;
#elif DOLPHIN
value = INPUT.pads[0][button.gpAxis.axis];
#endif
if(!button.gpAxis.positive) value = -value;
if(value >= INPUT.deadzone) return value;
return 0.0f;
}
#endif

View File

@@ -36,7 +36,9 @@
INPUT_GAMEPAD_AXIS_C_X,
INPUT_GAMEPAD_AXIS_C_Y,
INPUT_GAMEPAD_AXIS_TRIGGER_LEFT,
INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT
INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT,
INPUT_GAMEPAD_AXIS_COUNT
} inputgamepadaxis_t;
#endif
#endif

View File

@@ -93,9 +93,9 @@ errorret_t sceneSet(const char_t *script) {
"function sceneUpdate()\n"
"end\n"
"function sceneRender()\n"
" mapCamera.position = vec3(4, 4, 4)\n"
" mapCamera.position = vec3(32, 32, 32)\n"
" cameraPushMatrix(mapCamera)\n"
" spriteBatchPush(nil, -1, -1, 1, 1, colorBlue())\n"
" spriteBatchPush(nil, -10, -10, 10, 10, colorBlue())\n"
" spriteBatchFlush()\n"
" cameraPopMatrix()\n"
"end\n"

View File

@@ -27,7 +27,6 @@ void memoryFree(void *ptr) {
MEMORY_POINTERS_IN_USE--;
}
void memoryCopy(void *dest, const void *src, const size_t size) {
assertNotNull(dest, "Cannot copy to NULL memory.");
assertNotNull(src, "Cannot copy from NULL memory.");