This commit is contained in:
2026-06-07 21:16:46 -05:00
parent 51388c90d5
commit dc41c0e302
97 changed files with 1107 additions and 481 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+5 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
@@ -173,7 +173,10 @@ void assetUnlock(const char_t *name) {
assetentry_t *entry = ASSET.entries;
do {
if(entry->type != ASSET_LOADER_TYPE_NULL && stringEquals(entry->name, name)) {
if(
entry->type != ASSET_LOADER_TYPE_NULL &&
stringEquals(entry->name, name)
) {
assetEntryUnlock(entry);
return;
}
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+13 -5
View File
@@ -51,7 +51,9 @@ void assetBatchInit(
assertNotNull(batch, "Batch cannot be NULL.");
assertNotNull(descs, "Descs cannot be NULL.");
assertTrue(count > 0, "Count must be greater than 0.");
assertTrue(count <= ASSET_BATCH_COUNT_MAX, "Count exceeds ASSET_BATCH_COUNT_MAX.");
assertTrue(
count <= ASSET_BATCH_COUNT_MAX, "Count exceeds ASSET_BATCH_COUNT_MAX."
);
memoryZero(batch, sizeof(assetbatch_t));
batch->count = count;
@@ -62,7 +64,9 @@ void assetBatchInit(
);
eventInit(
&batch->onEntryLoaded,
batch->onEntryLoadedCallbacks, batch->onEntryLoadedUsers, ASSET_BATCH_EVENT_MAX
batch->onEntryLoadedCallbacks,
batch->onEntryLoadedUsers,
ASSET_BATCH_EVENT_MAX
);
eventInit(
&batch->onError,
@@ -70,12 +74,16 @@ void assetBatchInit(
);
eventInit(
&batch->onEntryError,
batch->onEntryErrorCallbacks, batch->onEntryErrorUsers, ASSET_BATCH_EVENT_MAX
batch->onEntryErrorCallbacks,
batch->onEntryErrorUsers,
ASSET_BATCH_EVENT_MAX
);
for(uint16_t i = 0; i < count; i++) {
batch->inputs[i] = descs[i].input;
batch->entries[i] = assetLock(descs[i].path, descs[i].type, &batch->inputs[i]);
batch->entries[i] = assetLock(
descs[i].path, descs[i].type, &batch->inputs[i]
);
if(batch->entries[i]->state == ASSET_ENTRY_STATE_LOADED) {
/* Already loaded (cached) — count it now, no subscription needed. */
@@ -151,7 +159,7 @@ void assetBatchDispose(assetbatch_t *batch) {
assertNotNull(batch, "Batch cannot be NULL.");
for(uint16_t i = 0; i < batch->count; i++) {
if(batch->entries[i]) {
/* Unsubscribe while we still hold a lock so the entry is guaranteed live. */
// Unsubscribe while we still hold a lock so the entry is live.
eventUnsubscribe(&batch->entries[i]->onLoaded, assetBatchEntryOnLoadedCb);
eventUnsubscribe(&batch->entries[i]->onError, assetBatchEntryOnErrorCb);
assetUnlockEntry(batch->entries[i]);
+3 -3
View File
@@ -26,17 +26,17 @@ typedef struct {
uint16_t loadedCount;
uint16_t errorCount;
/** Fires once when every entry has loaded successfully. params = assetbatch_t * */
/** Fires once when every entry loaded. params = assetbatch_t * */
event_t onLoaded;
eventcallback_t onLoadedCallbacks[ASSET_BATCH_EVENT_MAX];
void *onLoadedUsers[ASSET_BATCH_EVENT_MAX];
/** Fires each time a single entry finishes loading. params = assetentry_t * */
/** Fires each time a single entry loads. params = assetentry_t * */
event_t onEntryLoaded;
eventcallback_t onEntryLoadedCallbacks[ASSET_BATCH_EVENT_MAX];
void *onEntryLoadedUsers[ASSET_BATCH_EVENT_MAX];
/** Fires once when all entries have finished (any with errors). params = assetbatch_t * */
/** Fires when all entries finish (any with errors). params: assetbatch_t * */
event_t onError;
eventcallback_t onErrorCallbacks[ASSET_BATCH_EVENT_MAX];
void *onErrorUsers[ASSET_BATCH_EVENT_MAX];
+4 -1
View File
@@ -125,7 +125,10 @@ errorret_t assetFileReadEntire(
assertNotNull(file, "Asset file cannot be NULL.");
assertNotNull(outBuffer, "outBuffer cannot be NULL.");
assertNotNull(outSize, "outSize cannot be NULL.");
assertTrue(file->size > 0, "Asset file has no size; call assetFileInit first.");
assertTrue(
file->size > 0,
"Asset file has no size; call assetFileInit first."
);
// File should be closed currently.
assertNull(file->zipFile, "Asset file must be closed before reading entire.");
@@ -23,7 +23,9 @@ errorret_t assetMeshLoaderAsync(assetloading_t *loading) {
assetfile_t *file = &loading->loading.mesh.file;
assetmeshinputaxis_t axis = loading->entry->inputData.mesh;
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
assetLoaderErrorChain(loading,
assetFileInit(file, loading->entry->name, NULL, NULL)
);
assetLoaderErrorChain(loading, assetFileOpen(file));
// Skip the 80-byte STL header.
@@ -33,7 +35,9 @@ errorret_t assetMeshLoaderAsync(assetloading_t *loading) {
}
uint32_t triangleCount;
assetLoaderErrorChain(loading, assetFileRead(file, &triangleCount, sizeof(uint32_t)));
assetLoaderErrorChain(loading,
assetFileRead(file, &triangleCount, sizeof(uint32_t))
);
if(file->lastRead != sizeof(uint32_t)) {
assetLoaderErrorThrow(loading, "Failed to read tri count");
}
@@ -75,7 +79,9 @@ errorret_t assetMeshLoaderAsync(assetloading_t *loading) {
verts[i * 3 + j].uv[1] = 0.0f;
for(uint8_t k = 0; k < 3; k++) {
verts[i * 3 + j].pos[k] = endianLittleToHostFloat(triData.positions[j][k]);
verts[i * 3 + j].pos[k] = endianLittleToHostFloat(
triData.positions[j][k]
);
}
switch(axis) {
@@ -103,7 +103,9 @@ errorret_t assetTextureLoaderAsync(assetloading_t *loading) {
// Ensure we loaded correctly.
if(loading->loading.texture.data == NULL) {
const char_t *errorStr = stbi_failure_reason();
assetLoaderErrorThrow(loading, "Failed to load texture from file %s.", errorStr);
assetLoaderErrorThrow(
loading, "Failed to load texture from file %s.", errorStr
);
}
// Fixes a specific bug probably with Dolphin but for now just assuming endian
@@ -23,14 +23,19 @@ errorret_t assetTilesetLoaderAsync(assetloading_t *loading) {
assertNull(loading->loading.tileset.data, "Data already defined?");
assetfile_t *file = &loading->loading.tileset.file;
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
assetLoaderErrorChain(loading,
assetFileInit(file, loading->entry->name, NULL, NULL)
);
uint8_t *data = memoryAllocate(file->size);
assetLoaderErrorChain(loading, assetFileOpen(file));
assetLoaderErrorChain(loading, assetFileRead(file, data, file->size));
assetLoaderErrorChain(loading, assetFileClose(file));
assetLoaderErrorChain(loading, assetFileDispose(file));
assertTrue(file->lastRead == file->size, "Failed to read entire tileset file.");
assertTrue(
file->lastRead == file->size,
"Failed to read entire tileset file."
);
loading->loading.tileset.data = data;
loading->loading.tileset.state = ASSET_TILESET_LOADING_STATE_PARSE;
+3 -1
View File
@@ -22,7 +22,9 @@ errorret_t assetJsonLoaderAsync(assetloading_t *loading) {
assertNull(loading->loading.json.buffer, "Buffer already defined?");
assetfile_t *file = &loading->loading.json.file;
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
assetLoaderErrorChain(loading,
assetFileInit(file, loading->entry->name, NULL, NULL)
);
if(file->size > ASSET_JSON_FILE_SIZE_MAX) {
assetLoaderErrorThrow(loading, "JSON exceeds maximum allowed size");
@@ -24,12 +24,18 @@ errorret_t assetLocaleLoaderAsync(assetloading_t *loading) {
assetlocalefile_t *localeFile = &loading->entry->data.locale;
memoryZero(localeFile, sizeof(assetlocalefile_t));
assetLoaderErrorChain(loading, assetFileInit(&localeFile->file, loading->entry->name, NULL, NULL));
assetLoaderErrorChain(loading, assetFileInit(
&localeFile->file, loading->entry->name, NULL, NULL
));
assetLoaderErrorChain(loading, assetFileOpen(&localeFile->file));
char_t buffer[1024];
assetLoaderErrorChain(loading, assetLocaleGetString(localeFile, "", 0, buffer, sizeof(buffer)));
assetLoaderErrorChain(loading, assetLocaleParseHeader(localeFile, buffer, sizeof(buffer)));
assetLoaderErrorChain(loading, assetLocaleGetString(
localeFile, "", 0, buffer, sizeof(buffer)
));
assetLoaderErrorChain(loading, assetLocaleParseHeader(
localeFile, buffer, sizeof(buffer)
));
loading->loading.locale.state = ASSET_LOCALE_LOADER_STATE_DONE;
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
@@ -189,7 +189,7 @@ errorret_t assetLocaleLineSkipBlanks(
*
* @param reader Line reader positioned at the line containing the opening
* quote (e.g. `msgstr "..."`).
* @param lineBuffer Buffer the reader fills on each @ref assetFileLineReaderNext
* @param lineBuffer Buffer filled on each @ref assetFileLineReaderNext
* call; also used to detect continuation lines.
* @param stringBuffer Destination for the unescaped string content.
* @param stringBufferSize Capacity of `stringBuffer` in bytes.
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2025 Dominic Masters
// Copyright (c) 2026 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
+1 -1
View File
@@ -74,7 +74,7 @@ void planeBuffer(
const float_t u0 = uvMin[0], u1 = uvMax[0];
const float_t v0 = uvMin[1], v1 = uvMax[1];
switch (axis) {
switch(axis) {
case PLANE_AXIS_XY: {
/* Flat in XY at z = min[2]; spans X and Y. */
const float_t z = min[2];
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+3 -1
View File
@@ -119,7 +119,9 @@ errorret_t componentRenderAll(void) {
for(entityid_t eid = 0; eid < ENTITY_COUNT_MAX; eid++) {
if(!(ENTITY_MANAGER.entities[eid].state & ENTITY_STATE_ACTIVE)) continue;
for(componentid_t cid = 0; cid < ENTITY_COMPONENT_COUNT_MAX; cid++) {
component_t *cmp = &ENTITY_MANAGER.components[componentGetIndex(eid, cid)];
component_t *cmp = &ENTITY_MANAGER.components[
componentGetIndex(eid, cid)
];
if(cmp->type == COMPONENT_TYPE_NULL) continue;
if(!COMPONENT_DEFINITIONS[cmp->type].render) continue;
errorChain(COMPONENT_DEFINITIONS[cmp->type].render(eid, cid));
@@ -22,12 +22,12 @@ static void entityPositionEnsureLocal(entityposition_t *pos) {
if(!dirty) return;
if(dirty & ENTITY_POSITION_FLAG_ROTATION_DIRTY) {
// Rotation or scale changed: rebuild columns 0-2 analytically (XYZ euler order).
const float c0 = cosf(pos->rotation[0]), s0 = sinf(pos->rotation[0]);
const float c1 = cosf(pos->rotation[1]), s1 = sinf(pos->rotation[1]);
const float c2 = cosf(pos->rotation[2]), s2 = sinf(pos->rotation[2]);
const float s0s1 = s0 * s1;
const float c0s1 = c0 * s1;
// Rotation or scale changed: rebuild cols 0-2 analytically (XYZ euler).
const float_t c0 = cosf(pos->rotation[0]), s0 = sinf(pos->rotation[0]);
const float_t c1 = cosf(pos->rotation[1]), s1 = sinf(pos->rotation[1]);
const float_t c2 = cosf(pos->rotation[2]), s2 = sinf(pos->rotation[2]);
const float_t s0s1 = s0 * s1;
const float_t c0s1 = c0 * s1;
pos->localTransform[0][0] = c1 * c2 * pos->scale[0];
pos->localTransform[0][1] = (c0 * s2 + s0s1 * c2) * pos->scale[0];
@@ -53,7 +53,9 @@ static void entityPositionEnsureLocal(entityposition_t *pos) {
pos->localTransform[3][3] = 1.0f;
}
pos->flags &= ~(ENTITY_POSITION_FLAG_ROTATION_DIRTY | ENTITY_POSITION_FLAG_POSITION_DIRTY);
pos->flags &= ~(
ENTITY_POSITION_FLAG_ROTATION_DIRTY | ENTITY_POSITION_FLAG_POSITION_DIRTY
);
}
// Recompute worldTransform from the parent chain. Only called when WORLD_DIRTY.
@@ -68,7 +70,9 @@ static void entityPositionEnsureWorld(entityposition_t *pos) {
pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
);
entityPositionEnsureWorld(parent);
glm_mat4_mul(parent->worldTransform, pos->localTransform, pos->worldTransform);
glm_mat4_mul(
parent->worldTransform, pos->localTransform, pos->worldTransform
);
} else if(pos->childCount > 0) {
// Parentless root with children: children need a valid worldTransform to
// multiply against, but world == local, so just copy.
@@ -123,7 +127,8 @@ void entityPositionLookAt(
glm_lookat(eye, target, up, pos->localTransform);
// localTransform is now authoritative; PRS cache is stale.
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_PRS_DIRTY)
& ~(ENTITY_POSITION_FLAG_ROTATION_DIRTY | ENTITY_POSITION_FLAG_POSITION_DIRTY);
& ~(ENTITY_POSITION_FLAG_ROTATION_DIRTY |
ENTITY_POSITION_FLAG_POSITION_DIRTY);
entityPositionMarkDirty(pos);
}
@@ -137,7 +142,8 @@ void entityPositionGetTransform(
);
entityPositionEnsureWorld(pos);
glm_mat4_copy(
pos->parentEntityId == ENTITY_ID_INVALID ? pos->localTransform : pos->worldTransform,
pos->parentEntityId == ENTITY_ID_INVALID
? pos->localTransform : pos->worldTransform,
dest
);
}
@@ -254,20 +260,26 @@ void entityPositionGetWorldRotation(
return;
}
entityPositionEnsureWorld(pos);
const float (*wt)[4] = pos->worldTransform;
const float sx = sqrtf(wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2]);
const float sy = sqrtf(wt[1][0]*wt[1][0] + wt[1][1]*wt[1][1] + wt[1][2]*wt[1][2]);
const float sz = sqrtf(wt[2][0]*wt[2][0] + wt[2][1]*wt[2][1] + wt[2][2]*wt[2][2]);
const float r00 = sx > 0.0f ? wt[0][0]/sx : 0.0f;
const float r10 = sy > 0.0f ? wt[1][0]/sy : 0.0f;
const float r20 = sz > 0.0f ? wt[2][0]/sz : 0.0f;
const float r01 = sx > 0.0f ? wt[0][1]/sx : 0.0f;
const float r11 = sy > 0.0f ? wt[1][1]/sy : 0.0f;
const float r21 = sz > 0.0f ? wt[2][1]/sz : 0.0f;
const float r22 = sz > 0.0f ? wt[2][2]/sz : 0.0f;
const float sinBeta = glm_clamp(r20, -1.0f, 1.0f);
const float_t (*wt)[4] = pos->worldTransform;
const float_t sx = sqrtf(
wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2]
);
const float_t sy = sqrtf(
wt[1][0]*wt[1][0] + wt[1][1]*wt[1][1] + wt[1][2]*wt[1][2]
);
const float_t sz = sqrtf(
wt[2][0]*wt[2][0] + wt[2][1]*wt[2][1] + wt[2][2]*wt[2][2]
);
const float_t r00 = sx > 0.0f ? wt[0][0]/sx : 0.0f;
const float_t r10 = sy > 0.0f ? wt[1][0]/sy : 0.0f;
const float_t r20 = sz > 0.0f ? wt[2][0]/sz : 0.0f;
const float_t r01 = sx > 0.0f ? wt[0][1]/sx : 0.0f;
const float_t r11 = sy > 0.0f ? wt[1][1]/sy : 0.0f;
const float_t r21 = sz > 0.0f ? wt[2][1]/sz : 0.0f;
const float_t r22 = sz > 0.0f ? wt[2][2]/sz : 0.0f;
const float_t sinBeta = glm_clamp(r20, -1.0f, 1.0f);
dest[1] = asinf(sinBeta);
const float cosBeta = cosf(dest[1]);
const float_t cosBeta = cosf(dest[1]);
if(fabsf(cosBeta) > 1e-6f) {
dest[0] = atan2f(-r21, r22);
dest[2] = atan2f(-r10, r00);
@@ -312,29 +324,41 @@ void entityPositionSetWorldRotation(
entityPositionEnsureWorld(parent);
// Build target world rotation matrix (unit scale) from XYZ euler.
const float c0 = cosf(rotation[0]), s0 = sinf(rotation[0]);
const float c1 = cosf(rotation[1]), s1 = sinf(rotation[1]);
const float c2 = cosf(rotation[2]), s2 = sinf(rotation[2]);
const float s0s1 = s0*s1, c0s1 = c0*s1;
const float_t c0 = cosf(rotation[0]), s0 = sinf(rotation[0]);
const float_t c1 = cosf(rotation[1]), s1 = sinf(rotation[1]);
const float_t c2 = cosf(rotation[2]), s2 = sinf(rotation[2]);
const float_t s0s1 = s0*s1, c0s1 = c0*s1;
// Named wr[col_stored][row_stored] matching cglm column-major layout.
const float wr00 = c1*c2, wr01 = c0*s2 + s0s1*c2, wr02 = s0*s2 - c0s1*c2;
const float wr10 = -c1*s2, wr11 = c0*c2 - s0s1*s2, wr12 = s0*c2 + c0s1*s2;
const float wr20 = s1, wr21 = -s0*c1, wr22 = c0*c1;
const float_t wr00 = c1*c2;
const float_t wr01 = c0*s2 + s0s1*c2;
const float_t wr02 = s0*s2 - c0s1*c2;
const float_t wr10 = -c1*s2;
const float_t wr11 = c0*c2 - s0s1*s2;
const float_t wr12 = s0*c2 + c0s1*s2;
const float_t wr20 = s1;
const float_t wr21 = -s0*c1;
const float_t wr22 = c0*c1;
// Normalize parent world columns to extract pure rotation.
const float (*pt)[4] = parent->worldTransform;
const float psx = sqrtf(pt[0][0]*pt[0][0] + pt[0][1]*pt[0][1] + pt[0][2]*pt[0][2]);
const float psy = sqrtf(pt[1][0]*pt[1][0] + pt[1][1]*pt[1][1] + pt[1][2]*pt[1][2]);
const float psz = sqrtf(pt[2][0]*pt[2][0] + pt[2][1]*pt[2][1] + pt[2][2]*pt[2][2]);
const float pr00 = psx > 0.f ? pt[0][0]/psx : 0.f;
const float pr01 = psx > 0.f ? pt[0][1]/psx : 0.f;
const float pr02 = psx > 0.f ? pt[0][2]/psx : 0.f;
const float pr10 = psy > 0.f ? pt[1][0]/psy : 0.f;
const float pr11 = psy > 0.f ? pt[1][1]/psy : 0.f;
const float pr12 = psy > 0.f ? pt[1][2]/psy : 0.f;
const float pr20 = psz > 0.f ? pt[2][0]/psz : 0.f;
const float pr21 = psz > 0.f ? pt[2][1]/psz : 0.f;
const float pr22 = psz > 0.f ? pt[2][2]/psz : 0.f;
const float_t (*pt)[4] = parent->worldTransform;
const float_t psx = sqrtf(
pt[0][0]*pt[0][0] + pt[0][1]*pt[0][1] + pt[0][2]*pt[0][2]
);
const float_t psy = sqrtf(
pt[1][0]*pt[1][0] + pt[1][1]*pt[1][1] + pt[1][2]*pt[1][2]
);
const float_t psz = sqrtf(
pt[2][0]*pt[2][0] + pt[2][1]*pt[2][1] + pt[2][2]*pt[2][2]
);
const float_t pr00 = psx > 0.f ? pt[0][0]/psx : 0.f;
const float_t pr01 = psx > 0.f ? pt[0][1]/psx : 0.f;
const float_t pr02 = psx > 0.f ? pt[0][2]/psx : 0.f;
const float_t pr10 = psy > 0.f ? pt[1][0]/psy : 0.f;
const float_t pr11 = psy > 0.f ? pt[1][1]/psy : 0.f;
const float_t pr12 = psy > 0.f ? pt[1][2]/psy : 0.f;
const float_t pr20 = psz > 0.f ? pt[2][0]/psz : 0.f;
const float_t pr21 = psz > 0.f ? pt[2][1]/psz : 0.f;
const float_t pr22 = psz > 0.f ? pt[2][2]/psz : 0.f;
// local_R = parent_R^T * world_R (R^-1 == R^T for orthogonal matrices).
// Compute only the 7 entries of the local rotation matrix needed for XYZ
@@ -343,23 +367,24 @@ void entityPositionSetWorldRotation(
// r21/r22 = stored[2][1..2] = math[1..2][2]
// r10/r00 = stored[1][0], stored[0][0] = math[0][1], math[0][0]
// gimbal = stored[0][1], stored[1][1] = math[1][0], math[1][1]
const float lr00 = pr00*wr00 + pr01*wr10 + pr02*wr20; // math[0][0]
const float lr10 = pr00*wr01 + pr01*wr11 + pr02*wr21; // math[0][1]
const float lr20 = pr00*wr02 + pr01*wr12 + pr02*wr22; // math[0][2] → sinBeta
const float lr01 = pr10*wr00 + pr11*wr10 + pr12*wr20; // math[1][0]
const float lr11 = pr10*wr01 + pr11*wr11 + pr12*wr21; // math[1][1]
const float lr21 = pr10*wr02 + pr11*wr12 + pr12*wr22; // math[1][2] → r21
const float lr22 = pr20*wr02 + pr21*wr12 + pr22*wr22; // math[2][2] → r22
const float_t lr00 = pr00*wr00 + pr01*wr10 + pr02*wr20; // math[0][0]
const float_t lr10 = pr00*wr01 + pr01*wr11 + pr02*wr21; // math[0][1]
const float_t lr20 = pr00*wr02 + pr01*wr12 + pr02*wr22; // [0][2] → sinBeta
const float_t lr01 = pr10*wr00 + pr11*wr10 + pr12*wr20; // math[1][0]
const float_t lr11 = pr10*wr01 + pr11*wr11 + pr12*wr21; // math[1][1]
const float_t lr21 = pr10*wr02 + pr11*wr12 + pr12*wr22; // [1][2] → r21
const float_t lr22 = pr20*wr02 + pr21*wr12 + pr22*wr22; // [2][2] → r22
const float sinBeta = glm_clamp(lr20, -1.0f, 1.0f);
const float_t sinBeta = glm_clamp(lr20, -1.0f, 1.0f);
pos->rotation[1] = asinf(sinBeta);
const float cosBeta = cosf(pos->rotation[1]);
const float_t cosBeta = cosf(pos->rotation[1]);
if(fabsf(cosBeta) > 1e-6f) {
pos->rotation[0] = atan2f(-lr21, lr22);
pos->rotation[2] = atan2f(-lr10, lr00);
} else {
pos->rotation[2] = 0.0f;
pos->rotation[0] = (sinBeta > 0.0f) ? atan2f(lr01, lr11) : -atan2f(lr01, lr11);
pos->rotation[0] = (sinBeta > 0.0f)
? atan2f(lr01, lr11) : -atan2f(lr01, lr11);
}
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY;
@@ -392,7 +417,7 @@ void entityPositionGetWorldScale(
return;
}
entityPositionEnsureWorld(pos);
const float (*wt)[4] = pos->worldTransform;
const float_t (*wt)[4] = pos->worldTransform;
dest[0] = sqrtf(wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2]);
dest[1] = sqrtf(wt[1][0]*wt[1][0] + wt[1][1]*wt[1][1] + wt[1][2]*wt[1][2]);
dest[2] = sqrtf(wt[2][0]*wt[2][0] + wt[2][1]*wt[2][1] + wt[2][2]*wt[2][2]);
@@ -431,10 +456,16 @@ void entityPositionSetWorldScale(
pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
);
entityPositionEnsureWorld(parent);
const float (*pt)[4] = parent->worldTransform;
const float psx = sqrtf(pt[0][0]*pt[0][0] + pt[0][1]*pt[0][1] + pt[0][2]*pt[0][2]);
const float psy = sqrtf(pt[1][0]*pt[1][0] + pt[1][1]*pt[1][1] + pt[1][2]*pt[1][2]);
const float psz = sqrtf(pt[2][0]*pt[2][0] + pt[2][1]*pt[2][1] + pt[2][2]*pt[2][2]);
const float_t (*pt)[4] = parent->worldTransform;
const float_t psx = sqrtf(
pt[0][0]*pt[0][0] + pt[0][1]*pt[0][1] + pt[0][2]*pt[0][2]
);
const float_t psy = sqrtf(
pt[1][0]*pt[1][0] + pt[1][1]*pt[1][1] + pt[1][2]*pt[1][2]
);
const float_t psz = sqrtf(
pt[2][0]*pt[2][0] + pt[2][1]*pt[2][1] + pt[2][2]*pt[2][2]
);
pos->scale[0] = psx > 0.0f ? scale[0] / psx : scale[0];
pos->scale[1] = psy > 0.0f ? scale[1] / psy : scale[1];
pos->scale[2] = psz > 0.0f ? scale[2] / psz : scale[2];
@@ -501,8 +532,11 @@ entityposition_t *entityPositionGet(
}
void entityPositionRebuild(entityposition_t *pos) {
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY | ENTITY_POSITION_FLAG_POSITION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY;
pos->flags = (
pos->flags |
ENTITY_POSITION_FLAG_ROTATION_DIRTY |
ENTITY_POSITION_FLAG_POSITION_DIRTY
) & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(pos);
}
@@ -514,7 +548,9 @@ void entityPositionDisposeDeep(
// Detach from parent so the parent's child list stays consistent.
if(pos->parentEntityId != ENTITY_ID_INVALID) {
entityPositionSetParent(entityId, componentId, ENTITY_ID_INVALID, COMPONENT_ID_INVALID);
entityPositionSetParent(
entityId, componentId, ENTITY_ID_INVALID, COMPONENT_ID_INVALID
);
}
// Copy the child list before disposing self (entityDispose invalidates pos).
@@ -524,8 +560,10 @@ void entityPositionDisposeDeep(
for(uint8_t i = 0; i < childCount; i++) {
childEntityIds[i] = pos->childEntityIds[i];
childComponentIds[i] = pos->childComponentIds[i];
// Sever the child's parent link so it won't try to modify our disposed data.
entityposition_t *child = entityPositionGet(childEntityIds[i], childComponentIds[i]);
// Sever child's parent link so it won't try to modify our disposed data.
entityposition_t *child = entityPositionGet(
childEntityIds[i], childComponentIds[i]
);
child->parentEntityId = ENTITY_ID_INVALID;
child->parentComponentId = COMPONENT_ID_INVALID;
}
@@ -560,24 +598,24 @@ void entityPositionDecompose(entityposition_t *pos) {
pos->localTransform[2][2] * pos->localTransform[2][2]
);
// Normalize columns to isolate the rotation matrix (9 floats, no mat4 needed).
const float invS0 = pos->scale[0] > 0.0f ? 1.0f / pos->scale[0] : 0.0f;
const float invS1 = pos->scale[1] > 0.0f ? 1.0f / pos->scale[1] : 0.0f;
const float invS2 = pos->scale[2] > 0.0f ? 1.0f / pos->scale[2] : 0.0f;
// Normalize columns to isolate the rotation matrix (no mat4 needed).
const float_t invS0 = pos->scale[0] > 0.0f ? 1.0f / pos->scale[0] : 0.0f;
const float_t invS1 = pos->scale[1] > 0.0f ? 1.0f / pos->scale[1] : 0.0f;
const float_t invS2 = pos->scale[2] > 0.0f ? 1.0f / pos->scale[2] : 0.0f;
const float r00 = pos->localTransform[0][0] * invS0;
const float r01 = pos->localTransform[0][1] * invS0;
const float r02 = pos->localTransform[0][2] * invS0;
const float r10 = pos->localTransform[1][0] * invS1;
const float r11 = pos->localTransform[1][1] * invS1;
const float r20 = pos->localTransform[2][0] * invS2;
const float r21 = pos->localTransform[2][1] * invS2;
const float r22 = pos->localTransform[2][2] * invS2;
const float_t r00 = pos->localTransform[0][0] * invS0;
const float_t r01 = pos->localTransform[0][1] * invS0;
const float_t r02 = pos->localTransform[0][2] * invS0;
const float_t r10 = pos->localTransform[1][0] * invS1;
const float_t r11 = pos->localTransform[1][1] * invS1;
const float_t r20 = pos->localTransform[2][0] * invS2;
const float_t r21 = pos->localTransform[2][1] * invS2;
const float_t r22 = pos->localTransform[2][2] * invS2;
// Extract XYZ euler angles (R = Rx * Ry * Rz, column-major)
const float sinBeta = glm_clamp(r20, -1.0f, 1.0f);
const float_t sinBeta = glm_clamp(r20, -1.0f, 1.0f);
pos->rotation[1] = asinf(sinBeta);
const float cosBeta = cosf(pos->rotation[1]);
const float_t cosBeta = cosf(pos->rotation[1]);
if(fabsf(cosBeta) > 1e-6f) {
pos->rotation[0] = atan2f(-r21, r22);
@@ -32,21 +32,21 @@
/**
* worldTransform is stale. Either the local matrix changed or an ancestor
* moved; the full parent-chain multiply must be rerun before world data is read.
* moved; worldTransform must be recomputed before world data can be read.
*/
#define ENTITY_POSITION_FLAG_WORLD_DIRTY (1 << 3)
typedef struct {
/*
* Hot fields — flag checks and parent/child traversal (markDirty, ensureWorld)
* Hot fields — flag checks, parent/child traversal (markDirty, ensureWorld)
* only touch these. Kept at the front so they share the first cache line.
*/
/** Bitmask of ENTITY_POSITION_FLAG_* values describing which caches are stale. */
/** ENTITY_POSITION_FLAG_* bitmask; describes which caches are stale. */
uint8_t flags;
/** Entity ID of the parent node, or ENTITY_ID_INVALID if none. */
entityid_t parentEntityId;
/** Component ID of the parent position component, or COMPONENT_ID_INVALID if none. */
/** Component ID of the parent position, or COMPONENT_ID_INVALID if none. */
componentid_t parentComponentId;
/** Number of currently registered children. */
uint8_t childCount;
@@ -60,11 +60,11 @@ typedef struct {
* Accessed more often than the matrices but less often than flags.
*/
/** Cached local position (XYZ). May be stale when ENTITY_POSITION_FLAG_PRS_DIRTY is set. */
/** Cached local position (XYZ). Stale when PRS_DIRTY is set. */
vec3 position;
/** Cached local euler rotation (XYZ, radians). May be stale when ENTITY_POSITION_FLAG_PRS_DIRTY is set. */
/** Cached local rotation (XYZ euler, radians). Stale when PRS_DIRTY. */
vec3 rotation;
/** Cached local scale (XYZ). May be stale when ENTITY_POSITION_FLAG_PRS_DIRTY is set. */
/** Cached local scale (XYZ). Stale when PRS_DIRTY is set. */
vec3 scale;
/*
@@ -338,7 +338,7 @@ entityposition_t *entityPositionGet(
* Signals that the PRS cache was modified externally. Sets both
* ENTITY_POSITION_FLAG_ROTATION_DIRTY and ENTITY_POSITION_FLAG_POSITION_DIRTY
* so all of localTransform is rebuilt lazily on the next read, clears
* ENTITY_POSITION_FLAG_PRS_DIRTY, and propagates ENTITY_POSITION_FLAG_WORLD_DIRTY
* ENTITY_POSITION_FLAG_PRS_DIRTY, propagates ENTITY_POSITION_FLAG_WORLD_DIRTY
* to self and all descendants.
*
* @param pos The position component whose PRS was modified.
+4 -2
View File
@@ -20,6 +20,8 @@
X(POSITION, entityposition_t, position, entityPositionInit, NULL, NULL)
X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL, NULL)
X(RENDERABLE, entityrenderable_t, renderable, entityRenderableInit, entityRenderableDispose, NULL)
X(PHYSICS, entityphysics_t, physics, entityPhysicsInit, entityPhysicsDispose, NULL)
X(RENDERABLE, entityrenderable_t, renderable,
entityRenderableInit, entityRenderableDispose, NULL)
X(PHYSICS, entityphysics_t, physics,
entityPhysicsInit, entityPhysicsDispose, NULL)
X(TRIGGER, entitytrigger_t, trigger, entityTriggerInit, NULL, NULL)
+11 -3
View File
@@ -92,7 +92,9 @@ void entityDispose(const entityid_t entityId) {
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
for(uint8_t i = 0; i < ent->disposeCount; i++) {
ent->onDispose[i](entityId, ent->disposeComponentId[i], ent->disposeUser[i]);
ent->onDispose[i](
entityId, ent->disposeComponentId[i], ent->disposeUser[i]
);
}
for(componentid_t i = 0; i < ENTITY_COMPONENT_COUNT_MAX; i++) {
@@ -125,7 +127,10 @@ void entityUpdateAdd(
ent->updateCount++;
}
void entityUpdateRemove(const entityid_t entityId, const entitycallback_t callback) {
void entityUpdateRemove(
const entityid_t entityId,
const entitycallback_t callback
) {
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
for(uint8_t i = 0; i < ent->updateCount; i++) {
if(ent->onUpdate[i] != callback) continue;
@@ -156,7 +161,10 @@ void entityDisposeAdd(
ent->disposeCount++;
}
void entityDisposeRemove(const entityid_t entityId, const entitycallback_t callback) {
void entityDisposeRemove(
const entityid_t entityId,
const entitycallback_t callback
) {
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
for(uint8_t i = 0; i < ent->disposeCount; i++) {
if(ent->onDispose[i] != callback) continue;
+8 -2
View File
@@ -106,7 +106,10 @@ void entityUpdateAdd(
* @param entityId The entity to remove from.
* @param callback The function to remove.
*/
void entityUpdateRemove(const entityid_t entityId, const entitycallback_t callback);
void entityUpdateRemove(
const entityid_t entityId,
const entitycallback_t callback
);
/**
* Registers a dispose callback, invoked at the start of entityDispose before
@@ -128,4 +131,7 @@ void entityDisposeAdd(
* @param entityId The entity to remove from.
* @param callback The function to remove.
*/
void entityDisposeRemove(const entityid_t entityId, const entitycallback_t callback);
void entityDisposeRemove(
const entityid_t entityId,
const entitycallback_t callback
);
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+6 -1
View File
@@ -9,7 +9,12 @@
#include "assert/assert.h"
#include "util/memory.h"
void eventInit(event_t *event, eventcallback_t *callbacks, void **users, size_t size) {
void eventInit(
event_t *event,
eventcallback_t *callbacks,
void **users,
size_t size
) {
assertNotNull(event, "event must not be NULL");
assertNotNull((void *)callbacks, "callbacks must not be NULL");
assertTrue(size > 0, "size must be greater than 0");
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+18 -18
View File
@@ -7,7 +7,7 @@
#include "physicstest.h"
bool physicsTestAabbVsAabb(
bool_t physicsTestAabbVsAabb(
const vec3 ac, const vec3 ah,
const vec3 bc, const vec3 bh,
vec3 outNormal, float_t *outDepth
@@ -36,7 +36,7 @@ bool physicsTestAabbVsAabb(
return true;
}
bool physicsTestSphereVsSphere(
bool_t physicsTestSphereVsSphere(
const vec3 ac, const float_t ar,
const vec3 bc, const float_t br,
vec3 outNormal, float_t *outDepth
@@ -61,7 +61,7 @@ bool physicsTestSphereVsSphere(
return true;
}
bool physicsTestSphereVsAabb(
bool_t physicsTestSphereVsAabb(
const vec3 sc, const float_t sr,
const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth
@@ -76,7 +76,7 @@ bool physicsTestSphereVsAabb(
glm_vec3_sub((float_t *)sc, closest, diff);
float_t dist2 = glm_vec3_norm2(diff);
bool inside = (dist2 < 1e-10f);
bool_t inside = (dist2 < 1e-10f);
if(!inside && dist2 >= sr * sr) return false;
if(!inside) {
@@ -95,8 +95,8 @@ bool physicsTestSphereVsAabb(
const float_t normals[6][3] = {
{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}
};
int mi = 0;
for(int k = 1; k < 6; k++) {
int_t mi = 0;
for(int_t k = 1; k < 6; k++) {
if(faces[k] < faces[mi]) mi = k;
}
*outDepth = sr + faces[mi];
@@ -107,7 +107,7 @@ bool physicsTestSphereVsAabb(
return true;
}
bool physicsTestSphereVsPlane(
bool_t physicsTestSphereVsPlane(
const vec3 sc, const float_t sr,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
@@ -119,7 +119,7 @@ bool physicsTestSphereVsPlane(
return true;
}
bool physicsTestAabbVsPlane(
bool_t physicsTestAabbVsPlane(
const vec3 ac, const vec3 ah,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
@@ -189,7 +189,7 @@ void physicsTestClosestPointsBetweenSegments(
glm_vec3_lerp((float_t *)a2, (float_t *)b2, s, outP2);
}
bool physicsTestCapsuleVsSphere(
bool_t physicsTestCapsuleVsSphere(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 sc, const float_t sr,
vec3 outNormal, float_t *outDepth
@@ -203,7 +203,7 @@ bool physicsTestCapsuleVsSphere(
);
}
bool physicsTestCapsuleVsAabb(
bool_t physicsTestCapsuleVsAabb(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth
@@ -217,7 +217,7 @@ bool physicsTestCapsuleVsAabb(
);
}
bool physicsTestCapsuleVsPlane(
bool_t physicsTestCapsuleVsPlane(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
@@ -233,7 +233,7 @@ bool physicsTestCapsuleVsPlane(
return true;
}
bool physicsTestCapsuleVsCapsule(
bool_t physicsTestCapsuleVsCapsule(
const vec3 c1, const float_t r1, const float_t hh1,
const vec3 c2, const float_t r2, const float_t hh2,
vec3 outNormal, float_t *outDepth
@@ -247,7 +247,7 @@ bool physicsTestCapsuleVsCapsule(
return physicsTestSphereVsSphere(p1, r1, p2, r2, outNormal, outDepth);
}
bool physicsTestDispatch(
bool_t physicsTestDispatch(
const vec3 aPos, const physicsshape_t aShape,
const vec3 bPos, const physicsshape_t bShape,
vec3 outNormal, float_t *outDepth
@@ -258,7 +258,7 @@ bool physicsTestDispatch(
if(tb == PHYSICS_SHAPE_PLANE) {
const float_t *pn = bShape.data.plane.normal;
const float_t pd = bShape.data.plane.distance;
switch (ta) {
switch(ta) {
case PHYSICS_SHAPE_CUBE:
return physicsTestAabbVsPlane(
aPos, aShape.data.cube.halfExtents,
@@ -291,11 +291,11 @@ bool physicsTestDispatch(
return true;
}
switch (ta) {
switch(ta) {
case PHYSICS_SHAPE_CUBE: {
const float_t *ac = aPos;
const float_t *ah = aShape.data.cube.halfExtents;
switch (tb) {
switch(tb) {
case PHYSICS_SHAPE_CUBE:
return physicsTestAabbVsAabb(
ac, ah,
@@ -330,7 +330,7 @@ bool physicsTestDispatch(
case PHYSICS_SHAPE_SPHERE: {
const float_t sr = aShape.data.sphere.radius;
switch (tb) {
switch(tb) {
case PHYSICS_SHAPE_CUBE:
return physicsTestSphereVsAabb(
aPos, sr,
@@ -362,7 +362,7 @@ bool physicsTestDispatch(
case PHYSICS_SHAPE_CAPSULE: {
const float_t cr = aShape.data.capsule.radius;
const float_t chh = aShape.data.capsule.halfHeight;
switch (tb) {
switch(tb) {
case PHYSICS_SHAPE_CUBE:
return physicsTestCapsuleVsAabb(
aPos, cr, chh,
+1 -1
View File
@@ -8,7 +8,7 @@
#pragma once
#include "dusk.h"
/** Format version written into every save file. Increment on breaking change. */
/** Save file format version. Increment on breaking change. */
#define SAVE_FILE_VERSION 1
/** Magic bytes that identify a Dusk save file. */
+18 -6
View File
@@ -98,7 +98,9 @@ errorret_t saveStreamWriteHeaderImpl(
));
uint32_t placeholder = 0;
errorChain(saveStreamWriteBytesRawImpl(stream, &placeholder, sizeof(uint32_t)));
errorChain(saveStreamWriteBytesRawImpl(
stream, &placeholder, sizeof(uint32_t)
));
stream->checksum = cryptCRC32Begin();
errorOk();
}
@@ -146,7 +148,9 @@ errorret_t saveStreamReadUInt8Impl(savestream_t *stream, uint8_t *out) {
errorOk();
}
errorret_t saveStreamWriteUInt8Impl(savestream_t *stream, const uint8_t *input) {
errorret_t saveStreamWriteUInt8Impl(
savestream_t *stream, const uint8_t *input
) {
errorChain(saveStreamWriteBytesImpl(stream, input, sizeof(uint8_t)));
errorOk();
}
@@ -159,7 +163,9 @@ errorret_t saveStreamReadInt16Impl(savestream_t *stream, int16_t *out) {
errorOk();
}
errorret_t saveStreamWriteInt16Impl(savestream_t *stream, const int16_t *input) {
errorret_t saveStreamWriteInt16Impl(
savestream_t *stream, const int16_t *input
) {
uint16_t raw;
memoryCopy(&raw, input, sizeof(int16_t));
raw = endianLittleToHost16(raw);
@@ -190,7 +196,9 @@ errorret_t saveStreamReadInt32Impl(savestream_t *stream, int32_t *out) {
errorOk();
}
errorret_t saveStreamWriteInt32Impl(savestream_t *stream, const int32_t *input) {
errorret_t saveStreamWriteInt32Impl(
savestream_t *stream, const int32_t *input
) {
uint32_t raw;
memoryCopy(&raw, input, sizeof(int32_t));
raw = endianLittleToHost32(raw);
@@ -221,7 +229,9 @@ errorret_t saveStreamReadInt64Impl(savestream_t *stream, int64_t *out) {
errorOk();
}
errorret_t saveStreamWriteInt64Impl(savestream_t *stream, const int64_t *input) {
errorret_t saveStreamWriteInt64Impl(
savestream_t *stream, const int64_t *input
) {
uint64_t raw;
memoryCopy(&raw, input, sizeof(int64_t));
raw = endianLittleToHost64(raw);
@@ -251,7 +261,9 @@ errorret_t saveStreamReadFloatImpl(savestream_t *stream, float_t *out) {
errorOk();
}
errorret_t saveStreamWriteFloatImpl(savestream_t *stream, const float_t *input) {
errorret_t saveStreamWriteFloatImpl(
savestream_t *stream, const float_t *input
) {
float_t raw = endianLittleToHostFloat(*input);
errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(float_t)));
errorOk();
+14 -3
View File
@@ -71,7 +71,12 @@ errorret_t sceneRenderPipeline(const entityid_t cameraId) {
pipeline[i].componentId = components[i];
pipeline[i].effectivePriority = sceneRenderPipelineGetPriority(r);
}
sort(pipeline, (size_t)entCount, sizeof(scenerenderpipelineentry_t), sceneRenderPipelineCompare);
sort(
pipeline,
(size_t)entCount,
sizeof(scenerenderpipelineentry_t),
sceneRenderPipelineCompare
);
componentid_t camPos = entityGetComponent(cameraId, COMPONENT_TYPE_POSITION);
componentid_t camCam = entityGetComponent(cameraId, COMPONENT_TYPE_CAMERA);
@@ -87,7 +92,11 @@ errorret_t sceneRenderPipeline(const entityid_t cameraId) {
}
entityCameraGetProjection(cameraId, camCam, proj);
for(shaderlistshader_t si = SHADER_LIST_SHADER_NULL + 1; si < SHADER_LIST_SHADER_COUNT; si++) {
for(
shaderlistshader_t si = SHADER_LIST_SHADER_NULL + 1;
si < SHADER_LIST_SHADER_COUNT;
si++
) {
shader_t *s = SHADER_LIST_DEFS[si].shader;
assertNotNull(s, "Shader in list cannot be null");
errorChain(shaderBind(s));
@@ -99,7 +108,9 @@ errorret_t sceneRenderPipeline(const entityid_t cameraId) {
entityid_t eid = pipeline[i].entityId;
componentid_t cid = pipeline[i].componentId;
entityrenderable_t *r = componentGetData(eid, cid, COMPONENT_TYPE_RENDERABLE);
entityrenderable_t *r = componentGetData(
eid, cid, COMPONENT_TYPE_RENDERABLE
);
shader_t *s = sceneRenderPipelineGetShader(r);
componentid_t posComp = entityGetComponent(eid, COMPONENT_TYPE_POSITION);
+1 -1
View File
@@ -49,7 +49,7 @@ shader_t *sceneRenderPipelineGetShader(const entityrenderable_t *r);
/**
* Renders all entities with renderable components in priority order.
* Lower effective priority renders first (behind); higher renders last (on top).
* Lower priority renders first (behind); higher renders last (on top).
* When priority is 0 the effective value is derived from the renderable's type
* and flags; otherwise the explicit priority is used directly.
*
@@ -13,7 +13,7 @@
extern scriptproto_t MODULE_CONSOLE_PROTO;
/**
* Console.print(...args) — concatenates all arguments tab-separated and prints
* Console.print(...args) — concatenates all args tab-separated and prints
* to the engine console.
*/
moduleBaseFunction(moduleConsolePrint);
+2 -2
View File
@@ -7,8 +7,8 @@
#include "modulelocale.h"
#include "asset/loader/locale/assetlocaleloader.h"
#include "util/string.h"
#include <math.h>
#include <string.h>
#define MODULE_LOCALE_SUBSTITUTION_MAX 4
#define MODULE_LOCALE_BUFFER_SIZE 512
@@ -86,7 +86,7 @@ moduleBaseFunction(moduleLocaleSetLocale) {
moduleBaseToString(args[0], name, sizeof(name));
const localeinfo_t *locale = NULL;
if(strcmp(name, LOCALE_EN_US.name) == 0) locale = &LOCALE_EN_US;
if(stringEquals(name, LOCALE_EN_US.name)) locale = &LOCALE_EN_US;
if(locale == NULL) {
return moduleBaseThrow("Locale.setLocale: unknown locale name");
+4 -1
View File
@@ -34,7 +34,10 @@ static void scriptExceptionInfo(
jerry_value_t stackKey = jerry_string_sz("stack");
jerry_value_t stackVal = jerry_object_get(errVal, stackKey);
jerry_value_free(stackKey);
if(!jerry_value_is_exception(stackVal) && !jerry_value_is_undefined(stackVal)) {
if(
!jerry_value_is_exception(stackVal) &&
!jerry_value_is_undefined(stackVal)
) {
jerry_value_t stackStr = jerry_value_to_string(stackVal);
jerry_size_t stackLen = jerry_string_to_buffer(
stackStr, JERRY_ENCODING_UTF8, (jerry_char_t *)stackBuf, stackSize - 1
+6 -2
View File
@@ -40,7 +40,9 @@ void scriptProtoInit(
if(name != NULL) {
jerry_value_t global = jerry_current_realm();
jerry_value_t key = jerry_string_sz(name);
jerry_value_t val = proto->constructor ? proto->constructor : proto->prototype;
jerry_value_t val = proto->constructor
? proto->constructor
: proto->prototype;
jerry_object_set(global, key, val);
jerry_value_free(key);
jerry_value_free(global);
@@ -71,7 +73,9 @@ void scriptProtoDefineProp(
}
jerry_value_t key = jerry_string_sz(name);
jerry_value_t result = jerry_object_define_own_prop(proto->prototype, key, &desc);
jerry_value_t result = jerry_object_define_own_prop(
proto->prototype, key, &desc
);
jerry_value_free(result);
jerry_value_free(key);
jerry_value_free(desc.getter);
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+4 -4
View File
@@ -49,7 +49,7 @@ int32_t timeEpochGetDayOfMonth(const dusktimeepoch_t epoch) {
int32_t year = TIME_EPOCH_START_YEAR;
while (1) {
while(1) {
int32_t daysInYear = TIME_EPOCH_DAYS_IN_YEAR(year);
if(days < daysInYear) break;
@@ -77,7 +77,7 @@ int32_t timeEpochGetMonth(const dusktimeepoch_t epoch) {
int32_t year = TIME_EPOCH_START_YEAR;
while (1) {
while(1) {
int32_t daysInYear = TIME_EPOCH_DAYS_IN_YEAR(year);
if(days < daysInYear) break;
@@ -100,7 +100,7 @@ int32_t timeEpochGetYear(const dusktimeepoch_t epoch) {
int64_t days = (int64_t)(epoch.offsetTime / 86400.0);
int32_t year = TIME_EPOCH_START_YEAR;
while (1) {
while(1) {
int32_t daysInYear = TIME_EPOCH_DAYS_IN_YEAR(year);
if(days < daysInYear) return year;
@@ -136,7 +136,7 @@ size_t timeEpochFormat(
char_t tempBuffer[16];
size_t tempBufferIndex = 0;
switch (formatSpecifier) {
switch(formatSpecifier) {
case 'Y':
tempBufferIndex = snprintf(
tempBuffer, sizeof(tempBuffer), "%04d",
+14 -5
View File
@@ -19,7 +19,12 @@ uifullbox_t UI_FULLBOX_OVER;
void uiFullboxInit(uifullbox_t *fullbox) {
assertNotNull(fullbox, "fullbox must not be NULL");
memoryZero(fullbox, sizeof(uifullbox_t));
eventInit(&fullbox->onTransitionEnd, fullbox->onTransitionEndCallbacks, fullbox->onTransitionEndUsers, 4);
eventInit(
&fullbox->onTransitionEnd,
fullbox->onTransitionEndCallbacks,
fullbox->onTransitionEndUsers,
4
);
}
void uiFullboxUpdate(uifullbox_t *fullbox, float_t delta) {
@@ -39,10 +44,14 @@ static color_t uiFullboxGetColor(const uifullbox_t *fullbox) {
}
float_t t = easingApply(fullbox->easing, fullbox->time / fullbox->duration);
return color4b(
(uint8_t)((float_t)fullbox->fromColor.r + ((float_t)fullbox->toColor.r - (float_t)fullbox->fromColor.r) * t),
(uint8_t)((float_t)fullbox->fromColor.g + ((float_t)fullbox->toColor.g - (float_t)fullbox->fromColor.g) * t),
(uint8_t)((float_t)fullbox->fromColor.b + ((float_t)fullbox->toColor.b - (float_t)fullbox->fromColor.b) * t),
(uint8_t)((float_t)fullbox->fromColor.a + ((float_t)fullbox->toColor.a - (float_t)fullbox->fromColor.a) * t)
(uint8_t)((float_t)fullbox->fromColor.r +
((float_t)fullbox->toColor.r - (float_t)fullbox->fromColor.r) * t),
(uint8_t)((float_t)fullbox->fromColor.g +
((float_t)fullbox->toColor.g - (float_t)fullbox->fromColor.g) * t),
(uint8_t)((float_t)fullbox->fromColor.b +
((float_t)fullbox->toColor.b - (float_t)fullbox->fromColor.b) * t),
(uint8_t)((float_t)fullbox->fromColor.a +
((float_t)fullbox->toColor.a - (float_t)fullbox->fromColor.a) * t)
);
}
+16 -4
View File
@@ -19,11 +19,17 @@ uiloading_t UI_LOADING;
void uiLoadingInit(void) {
memoryZero(&UI_LOADING, sizeof(uiloading_t));
eventInit(&UI_LOADING.onTransitionEnd, UI_LOADING.onTransitionEndCallbacks, UI_LOADING.onTransitionEndUsers, 4);
eventInit(
&UI_LOADING.onTransitionEnd,
UI_LOADING.onTransitionEndCallbacks,
UI_LOADING.onTransitionEndUsers,
4
);
}
void uiLoadingUpdate(float_t delta) {
if(UI_LOADING.duration <= 0.0f || UI_LOADING.time >= UI_LOADING.duration) return;
if(UI_LOADING.duration <= 0.0f || UI_LOADING.time >= UI_LOADING.duration)
return;
UI_LOADING.time += delta;
if(UI_LOADING.time >= UI_LOADING.duration) {
UI_LOADING.time = UI_LOADING.duration;
@@ -37,7 +43,8 @@ errorret_t uiLoadingDraw(void) {
alpha = UI_LOADING.toAlpha;
} else {
float_t t = UI_LOADING.time / UI_LOADING.duration;
alpha = UI_LOADING.fromAlpha + (UI_LOADING.toAlpha - UI_LOADING.fromAlpha) * t;
alpha = UI_LOADING.fromAlpha +
(UI_LOADING.toAlpha - UI_LOADING.fromAlpha) * t;
}
if(alpha <= 0.0f) errorOk();
@@ -65,7 +72,12 @@ static void uiLoadingTransition(
UI_LOADING.toAlpha = to;
UI_LOADING.duration = UI_LOADING_FADE_DURATION;
UI_LOADING.time = 0.0f;
eventInit(&UI_LOADING.onTransitionEnd, UI_LOADING.onTransitionEndCallbacks, UI_LOADING.onTransitionEndUsers, 4);
eventInit(
&UI_LOADING.onTransitionEnd,
UI_LOADING.onTransitionEndCallbacks,
UI_LOADING.onTransitionEndUsers,
4
);
if(callback) eventSubscribe(&UI_LOADING.onTransitionEnd, callback, user);
}
+14 -3
View File
@@ -46,8 +46,18 @@ errorret_t uiTextboxInit(void) {
UI_TEXTBOX.frame.tileset.uv[1] = 1.0f / 3.0f;
UI_TEXTBOX.frame.texture = &TEXTURE_WHITE;
eventInit(&UI_TEXTBOX.onPageComplete, UI_TEXTBOX.onPageCompleteCallbacks, UI_TEXTBOX.onPageCompleteUsers, 4);
eventInit(&UI_TEXTBOX.onLastPage, UI_TEXTBOX.onLastPageCallbacks, UI_TEXTBOX.onLastPageUsers, 4);
eventInit(
&UI_TEXTBOX.onPageComplete,
UI_TEXTBOX.onPageCompleteCallbacks,
UI_TEXTBOX.onPageCompleteUsers,
4
);
eventInit(
&UI_TEXTBOX.onLastPage,
UI_TEXTBOX.onLastPageCallbacks,
UI_TEXTBOX.onLastPageUsers,
4
);
errorOk();
}
@@ -239,7 +249,8 @@ errorret_t uiTextboxDraw(void) {
for(int32_t li = pageFirst; li < pageLast && charsLeft > 0; li++) {
uitextboxline_t *line = &UI_TEXTBOX.lines[li];
int32_t visible = line->count < charsLeft ? line->count : charsLeft;
float_t lineY = contentY + (float_t)(li - pageFirst) * (fontH + UI_TEXTBOX_LINE_SPACING);
float_t lineY = contentY +
(float_t)(li - pageFirst) * (fontH + UI_TEXTBOX_LINE_SPACING);
for(int32_t ci = 0; ci < visible; ci++) {
char_t c = UI_TEXTBOX.text[line->start + ci];
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+2 -1
View File
@@ -25,7 +25,8 @@ typedef struct ref_s {
* @param ref The ref to initialize.
* @param data Opaque context pointer accessible to all callbacks.
* @param onLock Called each time the ref is locked. May be NULL.
* @param onUnlock Called each time the ref is unlocked (count still > 0). May be NULL.
* @param onUnlock Called each time the ref is unlocked (count still > 0).
* May be NULL.
* @param onAllUnlocked Called when the count reaches zero. Responsible for
* any cleanup. May be NULL.
*/
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
@@ -47,7 +47,7 @@ void stringTrim(char_t *str) {
// Trim trailing whitespace
char_t *end = start + strlen(start) - 1;
while (end >= start && stringIsWhitespace(*end)) end--;
while(end >= start && stringIsWhitespace(*end)) end--;
// Null-terminate the string
*(end + 1) = '\0';
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+4 -2
View File
@@ -47,10 +47,12 @@ errorret_t assetInitDolphinFAT(void) {
if(foundPath[0] != '\0') break;
} while(*(++dolphinSearchPath) != NULL);
if(foundPath[0] == '\0') errorThrow("Failed to find asset file on FAT filesystem.");
if(foundPath[0] == '\0')
errorThrow("Failed to find asset file on FAT filesystem.");
ASSET.zip = zip_open(foundPath, ZIP_RDONLY, NULL);
if(ASSET.zip == NULL) errorThrow("Failed to open asset file on FAT filesystem.");
if(ASSET.zip == NULL)
errorThrow("Failed to open asset file on FAT filesystem.");
errorOk();
}
+3 -3
View File
@@ -9,11 +9,11 @@
#include "error/error.h"
#include "display/displaystate.h"
#define DISPLAY_DOLPHIN_FIFO_SIZE (256*1024)
#define DISPLAY_DOLPHIN_FIFO_SIZE (256*1024)
typedef struct {
void *frameBuffer[2];// Double-Bufferred
int whichFrameBuffer;
void *frameBuffer[2]; // Double-Bufferred
int_t whichFrameBuffer;
GXRModeObj *screenMode;
void *fifoBuffer;
} displaydolphin_t;
@@ -25,14 +25,14 @@ errorret_t textureInitDolphin(
for(uint32_t y = 0; y < height; ++y) {
for(uint32_t x = 0; x < width; ++x) {
const int src = y * width + x;
const int_t 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 inTile = ((y & 3) << 2) + (x & 3);
const int tileBase = tileIndex * 64;
const int_t tileX = x >> 2;
const int_t tileY = y >> 2;
const int_t tilesPerRow = width >> 2;
const int_t tileIndex = tileY * tilesPerRow + tileX;
const int_t inTile = ((y & 3) << 2) + (x & 3);
const int_t tileBase = tileIndex * 64;
color_t col = data.rgbaColors[src];
+76 -24
View File
@@ -12,32 +12,84 @@
inputbuttondata_t INPUT_BUTTON_DATA[] = {
#ifdef DUSK_INPUT_GAMEPAD
{ .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 = "up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_UP } },
{ .name = "down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_DOWN } },
{ .name = "left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_LEFT } },
{ .name = "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 = "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 = "up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = PAD_BUTTON_UP } },
{ .name = "down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = PAD_BUTTON_DOWN } },
{ .name = "left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = PAD_BUTTON_LEFT } },
{ .name = "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_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
{ .name = "lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
{ .name = "lstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
{ .name = "lstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
{ .name = "lstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
{ .name = "lstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
{ .name = "rstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
{ .name = "rstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
{ .name = "rstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
{ .name = "rstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_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 } } },
{ .name = "rstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
{ .name = "rstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
{ .name = "rstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
{ .name = "rstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
{ .name = "lstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_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
{ .name = NULL }
+1 -1
View File
@@ -114,7 +114,7 @@ void logError(const char_t *message, ...) {
va_end(copy);
va_end(args);
// PAD_Init is idempotent — safe to call even if inputInit already called it,
// PAD_Init is idempotent — safe even if inputInit already called it,
// and handles the case where the error occurred before inputInit ran.
PAD_Init();
while(SYS_MainLoop()) {
+7 -7
View File
@@ -1,9 +1,9 @@
// /**
// * Copyright (c) 2026 Dominic Masters
// *
// * This software is released under the MIT License.
// * https://opensource.org/licenses/MIT
// */
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "network/network.h"
#include "util/memory.h"
@@ -103,7 +103,7 @@ networkinfo_t networkDolphinGetInfo() {
memoryZero(&info, sizeof(networkinfo_t));
info.type = NETWORK_TYPE_IPV4;
int ret = sscanf(
int_t ret = sscanf(
NETWORK.platform.ip,
"%hhu.%hhu.%hhu.%hhu",
&info.ipv4.ip[0],
+22 -12
View File
@@ -9,7 +9,9 @@
#include "util/memory.h"
#include "util/string.h"
static void _saveGetFileName(const uint8_t slot, char_t *out, const size_t max) {
static void _saveGetFileName(
const uint8_t slot, char_t *out, const size_t max
) {
snprintf(out, max, "%s_%u", SAVE_DOLPHIN_GAME_CODE, (uint32_t)slot);
}
@@ -42,7 +44,9 @@ errorret_t saveLoadDolphin(const uint8_t slot, savefile_t *file) {
char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX];
_saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX);
int32_t result = CARD_Open(SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile);
int32_t result = CARD_Open(
SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile
);
if(result == CARD_ERROR_NOFILE) {
file->exists = false;
errorOk();
@@ -54,17 +58,19 @@ errorret_t saveLoadDolphin(const uint8_t slot, savefile_t *file) {
);
}
void *buffer = memalign(32, SAVE_DOLPHIN_SECTOR_SIZE);
void *buffer = memoryAlign(32, SAVE_DOLPHIN_SECTOR_SIZE);
if(!buffer) {
CARD_Close(&SAVE.platform.cardFile);
errorThrow("Failed to allocate memory card read buffer");
}
result = CARD_Read(&SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0);
result = CARD_Read(
&SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0
);
CARD_Close(&SAVE.platform.cardFile);
if(result < 0) {
free(buffer);
memoryFree(buffer);
file->exists = false;
errorThrow("Failed to read memory card data for slot %u (error %d)",
(uint32_t)slot, result
@@ -72,7 +78,7 @@ errorret_t saveLoadDolphin(const uint8_t slot, savefile_t *file) {
}
memoryCopy(file, buffer, sizeof(savefile_t));
free(buffer);
memoryFree(buffer);
file->exists = true;
errorOk();
@@ -82,15 +88,17 @@ errorret_t saveWriteDolphin(const uint8_t slot, const savefile_t *file) {
char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX];
_saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX);
void *buffer = memalign(32, SAVE_DOLPHIN_SECTOR_SIZE);
void *buffer = memoryAlign(32, SAVE_DOLPHIN_SECTOR_SIZE);
if(!buffer) {
errorThrow("Failed to allocate memory card write buffer");
}
memset(buffer, 0, SAVE_DOLPHIN_SECTOR_SIZE);
memoryZero(buffer, SAVE_DOLPHIN_SECTOR_SIZE);
memoryCopy(buffer, file, sizeof(savefile_t));
// Try open existing file first; create if absent.
int32_t result = CARD_Open(SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile);
int32_t result = CARD_Open(
SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile
);
if(result == CARD_ERROR_NOFILE) {
result = CARD_Create(
SAVE_DOLPHIN_CHANNEL,
@@ -101,15 +109,17 @@ errorret_t saveWriteDolphin(const uint8_t slot, const savefile_t *file) {
}
if(result < 0) {
free(buffer);
memoryFree(buffer);
errorThrow("Failed to open/create memory card file for slot %u (error %d)",
(uint32_t)slot, result
);
}
result = CARD_Write(&SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0);
result = CARD_Write(
&SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0
);
CARD_Close(&SAVE.platform.cardFile);
free(buffer);
memoryFree(buffer);
if(result < 0) {
errorThrow("Failed to write memory card data for slot %u (error %d)",
+2 -1
View File
@@ -394,7 +394,8 @@ errorret_t shaderDisposeGL(shadergl_t *shader) {
}
if(
(SHADER_LEGACY.dirty & (SHADER_LEGACY_DIRTY_VIEW | SHADER_LEGACY_DIRTY_MODEL)) != 0
(SHADER_LEGACY.dirty &
(SHADER_LEGACY_DIRTY_VIEW | SHADER_LEGACY_DIRTY_MODEL)) != 0
) {
glMatrixMode(GL_MODELVIEW);
errorChain(errorGLCheck());
+469 -155
View File
@@ -9,176 +9,490 @@
inputbuttondata_t INPUT_BUTTON_DATA[] = {
#ifdef DUSK_INPUT_GAMEPAD
{ .name = "gamepad_a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "gamepad_b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "gamepad_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "gamepad_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "gamepad_start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "gamepad_back", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "gamepad_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "gamepad_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "gamepad_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "gamepad_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "gamepad_l1", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "gamepad_r1", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
{ .name = "gamepad_l3", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSTICK } },
{ .name = "gamepad_r3", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSTICK } },
{ .name = "gamepad_lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "gamepad_lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "gamepad_lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "gamepad_lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "gamepad_rstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = true } } },
{ .name = "gamepad_rstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = false } } },
{ .name = "gamepad_rstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = true } } },
{ .name = "gamepad_rstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = false } } },
{ .name = "gamepad_l2", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT, .positive = true } } },
{ .name = "gamepad_r2", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT, .positive = true } } },
{ .name = "gamepad_a", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "gamepad_b", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "gamepad_x", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "gamepad_y", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "gamepad_start", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "gamepad_back", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "gamepad_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "gamepad_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "gamepad_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "gamepad_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "gamepad_l1", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "gamepad_r1", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
{ .name = "gamepad_l3", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_LEFTSTICK } },
{ .name = "gamepad_r3", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_RIGHTSTICK } },
{ .name = "gamepad_lstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "gamepad_lstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "gamepad_lstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "gamepad_lstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "gamepad_rstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = true } } },
{ .name = "gamepad_rstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = false } } },
{ .name = "gamepad_rstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = true } } },
{ .name = "gamepad_rstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = false } } },
{ .name = "gamepad_l2", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT,
.positive = true } } },
{ .name = "gamepad_r2", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
.positive = true } } },
#endif
#ifdef DUSK_INPUT_POINTER
{ .name = "mouse_x", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_X } },
{ .name = "mouse_y", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_Y } },
{ .name = "mouse_wheel_x", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_WHEEL_X } },
{ .name = "mouse_wheel_y", { .type = INPUT_BUTTON_TYPE_POINTER, .pointerAxis = INPUT_POINTER_AXIS_WHEEL_Y } },
{ .name = "mouse_x", {
.type = INPUT_BUTTON_TYPE_POINTER,
.pointerAxis = INPUT_POINTER_AXIS_X } },
{ .name = "mouse_y", {
.type = INPUT_BUTTON_TYPE_POINTER,
.pointerAxis = INPUT_POINTER_AXIS_Y } },
{ .name = "mouse_wheel_x", {
.type = INPUT_BUTTON_TYPE_POINTER,
.pointerAxis = INPUT_POINTER_AXIS_WHEEL_X } },
{ .name = "mouse_wheel_y", {
.type = INPUT_BUTTON_TYPE_POINTER,
.pointerAxis = INPUT_POINTER_AXIS_WHEEL_Y } },
#endif
#ifdef DUSK_INPUT_KEYBOARD
{ .name = "a", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_A } },
{ .name = "b", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_B } },
{ .name = "c", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_C } },
{ .name = "d", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_D } },
{ .name = "e", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_E } },
{ .name = "f", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F } },
{ .name = "g", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_G } },
{ .name = "h", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_H } },
{ .name = "i", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_I } },
{ .name = "j", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_J } },
{ .name = "k", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_K } },
{ .name = "l", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_L } },
{ .name = "m", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_M } },
{ .name = "n", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_N } },
{ .name = "o", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_O } },
{ .name = "p", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_P } },
{ .name = "q", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_Q } },
{ .name = "r", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_R } },
{ .name = "s", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_S } },
{ .name = "t", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_T } },
{ .name = "u", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_U } },
{ .name = "v", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_V } },
{ .name = "w", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_W } },
{ .name = "x", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_X } },
{ .name = "y", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_Y } },
{ .name = "z", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_Z } },
{ .name = "a", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_A } },
{ .name = "b", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_B } },
{ .name = "c", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_C } },
{ .name = "d", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_D } },
{ .name = "e", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_E } },
{ .name = "f", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F } },
{ .name = "g", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_G } },
{ .name = "h", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_H } },
{ .name = "i", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_I } },
{ .name = "j", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_J } },
{ .name = "k", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_K } },
{ .name = "l", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_L } },
{ .name = "m", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_M } },
{ .name = "n", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_N } },
{ .name = "o", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_O } },
{ .name = "p", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_P } },
{ .name = "q", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_Q } },
{ .name = "r", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_R } },
{ .name = "s", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_S } },
{ .name = "t", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_T } },
{ .name = "u", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_U } },
{ .name = "v", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_V } },
{ .name = "w", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_W } },
{ .name = "x", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_X } },
{ .name = "y", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_Y } },
{ .name = "z", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_Z } },
{ .name = "0", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_0 } },
{ .name = "1", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_1 } },
{ .name = "2", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_2 } },
{ .name = "3", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_3 } },
{ .name = "4", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_4 } },
{ .name = "5", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_5 } },
{ .name = "6", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_6 } },
{ .name = "7", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_7 } },
{ .name = "8", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_8 } },
{ .name = "9", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_9 } },
{ .name = "0", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_0 } },
{ .name = "1", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_1 } },
{ .name = "2", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_2 } },
{ .name = "3", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_3 } },
{ .name = "4", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_4 } },
{ .name = "5", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_5 } },
{ .name = "6", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_6 } },
{ .name = "7", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_7 } },
{ .name = "8", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_8 } },
{ .name = "9", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_9 } },
{ .name = "space", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SPACE } },
{ .name = "shift", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LSHIFT } },
{ .name = "lshift", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LSHIFT } },
{ .name = "rshift", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RSHIFT } },
{ .name = "lctrl", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LCTRL } },
{ .name = "rctrl", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RCTRL } },
{ .name = "ctrl", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LCTRL } },
{ .name = "lalt", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LALT } },
{ .name = "ralt", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RALT } },
{ .name = "tab", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_TAB } },
{ .name = "enter", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RETURN } },
{ .name = "backspace", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_BACKSPACE } },
{ .name = "escape", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_ESCAPE } },
{ .name = "esc", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_ESCAPE } },
{ .name = "up", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_UP } },
{ .name = "down", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_DOWN } },
{ .name = "left", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LEFT } },
{ .name = "right", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RIGHT } },
{ .name = "pageup", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_PAGEUP } },
{ .name = "pagedown", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_PAGEDOWN } },
{ .name = "home", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_HOME } },
{ .name = "end", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_END } },
{ .name = "insert", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_INSERT } },
{ .name = "delete", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_DELETE } },
{ .name = "space", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_SPACE } },
{ .name = "shift", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LSHIFT } },
{ .name = "lshift", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LSHIFT } },
{ .name = "rshift", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RSHIFT } },
{ .name = "lctrl", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LCTRL } },
{ .name = "rctrl", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RCTRL } },
{ .name = "ctrl", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LCTRL } },
{ .name = "lalt", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LALT } },
{ .name = "ralt", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RALT } },
{ .name = "tab", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_TAB } },
{ .name = "enter", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RETURN } },
{ .name = "backspace", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_BACKSPACE } },
{ .name = "escape", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_ESCAPE } },
{ .name = "esc", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_ESCAPE } },
{ .name = "up", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_UP } },
{ .name = "down", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_DOWN } },
{ .name = "left", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LEFT } },
{ .name = "right", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RIGHT } },
{ .name = "pageup", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_PAGEUP } },
{ .name = "pagedown", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_PAGEDOWN } },
{ .name = "home", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_HOME } },
{ .name = "end", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_END } },
{ .name = "insert", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_INSERT } },
{ .name = "delete", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_DELETE } },
{ .name = "f1", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F1 } },
{ .name = "f2", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F2 } },
{ .name = "f3", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F3 } },
{ .name = "f4", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F4 } },
{ .name = "f5", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F5 } },
{ .name = "f6", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F6 } },
{ .name = "f7", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F7 } },
{ .name = "f8", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F8 } },
{ .name = "f9", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F9 } },
{ .name = "f10", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F10 } },
{ .name = "f11", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F11 } },
{ .name = "f12", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F12 } },
{ .name = "f13", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F13 } },
{ .name = "f14", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F14 } },
{ .name = "f15", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F15 } },
{ .name = "f16", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F16 } },
{ .name = "f17", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F17 } },
{ .name = "f18", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F18 } },
{ .name = "f19", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F19 } },
{ .name = "f20", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F20 } },
{ .name = "f21", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F21 } },
{ .name = "f22", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F22 } },
{ .name = "f23", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F23 } },
{ .name = "f24", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F24 } },
{ .name = "f1", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F1 } },
{ .name = "f2", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F2 } },
{ .name = "f3", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F3 } },
{ .name = "f4", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F4 } },
{ .name = "f5", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F5 } },
{ .name = "f6", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F6 } },
{ .name = "f7", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F7 } },
{ .name = "f8", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F8 } },
{ .name = "f9", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F9 } },
{ .name = "f10", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F10 } },
{ .name = "f11", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F11 } },
{ .name = "f12", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F12 } },
{ .name = "f13", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F13 } },
{ .name = "f14", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F14 } },
{ .name = "f15", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F15 } },
{ .name = "f16", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F16 } },
{ .name = "f17", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F17 } },
{ .name = "f18", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F18 } },
{ .name = "f19", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F19 } },
{ .name = "f20", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F20 } },
{ .name = "f21", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F21 } },
{ .name = "f22", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F22 } },
{ .name = "f23", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F23 } },
{ .name = "f24", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_F24 } },
{ .name = "minus", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_MINUS } },
{ .name = "equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_EQUALS } },
{ .name = "leftbracket", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LEFTBRACKET } },
{ .name = "rightbracket", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RIGHTBRACKET } },
{ .name = "backslash", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_BACKSLASH } },
{ .name = "semicolon", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SEMICOLON } },
{ .name = "apostrophe", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_APOSTROPHE } },
{ .name = "grave", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_GRAVE } },
{ .name = "comma", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_COMMA } },
{ .name = "period", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_PERIOD } },
{ .name = "slash", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SLASH } },
{ .name = "minus", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_MINUS } },
{ .name = "equals", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_EQUALS } },
{ .name = "leftbracket", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LEFTBRACKET } },
{ .name = "rightbracket", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RIGHTBRACKET } },
{ .name = "backslash", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_BACKSLASH } },
{ .name = "semicolon", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_SEMICOLON } },
{ .name = "apostrophe", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_APOSTROPHE } },
{ .name = "grave", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_GRAVE } },
{ .name = "comma", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_COMMA } },
{ .name = "period", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_PERIOD } },
{ .name = "slash", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_SLASH } },
{ .name = "caps", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_CAPSLOCK } },
{ .name = "capslock", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_CAPSLOCK } },
{ .name = "numlock", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_NUMLOCKCLEAR } },
{ .name = "scrollock", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SCROLLLOCK } },
{ .name = "caps", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_CAPSLOCK } },
{ .name = "capslock", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_CAPSLOCK } },
{ .name = "numlock", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_NUMLOCKCLEAR } },
{ .name = "scrollock", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_SCROLLLOCK } },
{ .name = "-", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_MINUS } },
{ .name = "=", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_EQUALS } },
{ .name = "[", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LEFTBRACKET } },
{ .name = "]", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_RIGHTBRACKET } },
{ .name = "\\", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_BACKSLASH } },
{ .name = ";", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SEMICOLON } },
{ .name = "'", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_APOSTROPHE } },
{ .name = "`", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_GRAVE } },
{ .name = ",", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_COMMA } },
{ .name = ".", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_PERIOD } },
{ .name = "/", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SLASH } },
{ .name = "-", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_MINUS } },
{ .name = "=", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_EQUALS } },
{ .name = "[", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_LEFTBRACKET } },
{ .name = "]", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_RIGHTBRACKET } },
{ .name = "\\", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_BACKSLASH } },
{ .name = ";", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_SEMICOLON } },
{ .name = "'", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_APOSTROPHE } },
{ .name = "`", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_GRAVE } },
{ .name = ",", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_COMMA } },
{ .name = ".", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_PERIOD } },
{ .name = "/", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_SLASH } },
{ .name = "kp_0", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_0 } },
{ .name = "kp_1", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_1 } },
{ .name = "kp_2", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_2 } },
{ .name = "kp_3", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_3 } },
{ .name = "kp_4", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_4 } },
{ .name = "kp_5", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_5 } },
{ .name = "kp_6", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_6 } },
{ .name = "kp_7", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_7 } },
{ .name = "kp_8", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_8 } },
{ .name = "kp_9", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_9 } },
{ .name = "kp_period", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_PERIOD } },
{ .name = "kp_divide", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_DIVIDE } },
{ .name = "kp_multiply", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_MULTIPLY } },
{ .name = "kp_minus", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_MINUS } },
{ .name = "kp_plus", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_PLUS } },
{ .name = "kp_enter", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_ENTER } },
{ .name = "kp_equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_EQUALS } },
{ .name = "kp_0", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_0 } },
{ .name = "kp_1", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_1 } },
{ .name = "kp_2", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_2 } },
{ .name = "kp_3", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_3 } },
{ .name = "kp_4", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_4 } },
{ .name = "kp_5", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_5 } },
{ .name = "kp_6", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_6 } },
{ .name = "kp_7", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_7 } },
{ .name = "kp_8", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_8 } },
{ .name = "kp_9", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_9 } },
{ .name = "kp_period", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_PERIOD } },
{ .name = "kp_divide", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_DIVIDE } },
{ .name = "kp_multiply", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_MULTIPLY } },
{ .name = "kp_minus", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_MINUS } },
{ .name = "kp_plus", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_PLUS } },
{ .name = "kp_enter", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_ENTER } },
{ .name = "kp_equals", {
.type = INPUT_BUTTON_TYPE_KEYBOARD,
.scancode = SDL_SCANCODE_KP_EQUALS } },
#endif
{ .name = NULL },
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 Dominic Masters
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
+1 -1
View File
@@ -53,7 +53,7 @@ errorret_t networkLinuxDispose() {
networkinfo_t networkLinuxGetInfo() {
networkinfo_t info;
memset(&info, 0, sizeof(networkinfo_t));
memoryZero(&info, sizeof(networkinfo_t));
bool_t found = false;
+54 -18
View File
@@ -11,27 +11,63 @@
// #define INPUT_PSP_GAMEPAD_BUTTON_CANCEL INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM
inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "triangle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "cross", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "circle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "square", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "select", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
{ .name = "triangle", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "cross", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "circle", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "square", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "start", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "select", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "l", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "r", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
// Refer to systempsp.c for some extra info.
{ .name = "accept", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "cancel", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "accept", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "cancel", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "lstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "lstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "lstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "lstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = NULL }
};
+6 -3
View File
@@ -175,11 +175,14 @@ void networkPSPRequestConnection(
// https://github.com/joel16/CMFileManager-PSP/blob/00dab16c64cd48bf6452fc274a3b898d77c39a8d/app/source/net.cpp#L97
// since I follow this implementation closely.
memoryZero(&NETWORK.platform.dialogData, sizeof(NETWORK.platform.dialogData));
memoryZero(&NETWORK.platform.dialogAdhoc, sizeof(NETWORK.platform.dialogAdhoc));
memoryZero(
&NETWORK.platform.dialogAdhoc, sizeof(NETWORK.platform.dialogAdhoc)
);
NETWORK.platform.dialogData.base.size = sizeof(pspUtilityNetconfData);
NETWORK.platform.dialogData.base.language = systemPSPGetLanguage();
NETWORK.platform.dialogData.base.buttonSwap = systemPSPGetCrossButtonSetting();
NETWORK.platform.dialogData.base.buttonSwap =
systemPSPGetCrossButtonSetting();
NETWORK.platform.dialogData.base.graphicsThread = 17;
NETWORK.platform.dialogData.base.accessThread = 19;
NETWORK.platform.dialogData.base.fontThread = 18;
@@ -212,7 +215,7 @@ void networkPSPRequestDisconnection(
}
errorret_t networkPSPTerm() {
int ret;
int_t ret;
ret = sceNetApctlTerm();
if(ret < 0) {
errorThrow("Failed to terminate netctl: 0x%08X", ret);
+4 -4
View File
@@ -48,14 +48,14 @@ systemdialogtype_t systemGetActiveDialogTypePSP() {
return SYSTEM_DIALOG_TYPE_NONE;
}
int systemPSPGetLanguage() {
int ret;
int_t systemPSPGetLanguage() {
int_t ret;
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_LANGUAGE, &ret);
return ret;
}
int systemPSPGetCrossButtonSetting() {
int ret;
int_t systemPSPGetCrossButtonSetting() {
int_t ret;
// See: https://pspdev.github.io/pspsdk/psputility__sysparam_8h.html#ab588fd5a14adc025f065e09325ffe729
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &ret);
return (
+2 -2
View File
@@ -28,7 +28,7 @@ systemdialogtype_t systemGetActiveDialogTypePSP();
*
* @return PSP_SYSTEMPARAM language value.
*/
int systemPSPGetLanguage();
int_t systemPSPGetLanguage();
/**
* Returns the user's setting for the PSP "Cross Button" configuration, which
@@ -37,4 +37,4 @@ int systemPSPGetLanguage();
*
* @return PSP_UTILITY_ACCEPT_CROSS or PSP_UTILITY_ACCEPT_CIRCLE.
*/
int systemPSPGetCrossButtonSetting();
int_t systemPSPGetCrossButtonSetting();
+2 -2
View File
@@ -25,10 +25,10 @@ void inputUpdateSDL2(void) {
#endif
#ifdef DUSK_INPUT_POINTER
int pointerX, pointerY;
int_t pointerX, pointerY;
SDL_GetMouseState(&pointerX, &pointerY);
int windowWidth, windowHeight;
int_t windowWidth, windowHeight;
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
INPUT.platform.mouseX = (float_t)pointerX / (float_t)windowWidth;
+2 -1
View File
@@ -11,7 +11,8 @@
#define GL_COLOR_INDEX8_EXT 0x80E5
#define GL_NO_ERROR 0
#define glDrawArrays(type, first, count) ((void)0)
#define glColorTableEXT(target, internalformat, count, format, type, pixels) ((void)0)
#define glColorTableEXT( \
target, internalformat, count, format, type, pixels) ((void)0)
#define glDepthFunc(func) ((void)0)
#define glBlendFunc(sfactor, dfactor) ((void)0)
#define glGetError() GL_NO_ERROR
+68 -20
View File
@@ -8,28 +8,76 @@
#include "input/input.h"
inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "triangle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "cross", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "circle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "square", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "select", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
{ .name = "triangle", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_Y } },
{ .name = "cross", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_A } },
{ .name = "circle", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_B } },
{ .name = "square", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_X } },
{ .name = "start", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_START } },
{ .name = "select", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_BACK } },
{ .name = "up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
{ .name = "down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
{ .name = "left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
{ .name = "right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
{ .name = "l", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
{ .name = "r", {
.type = INPUT_BUTTON_TYPE_GAMEPAD,
.gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "lstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
{ .name = "lstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
{ .name = "lstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
{ .name = "lstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
{ .name = "rstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = true } } },
{ .name = "rstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = false } } },
{ .name = "rstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = true } } },
{ .name = "rstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = false } } },
{ .name = "rstick_down", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = true } } },
{ .name = "rstick_up", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_RIGHTY, .positive = false } } },
{ .name = "rstick_right", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = true } } },
{ .name = "rstick_left", {
.type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
.gpAxis = {
.axis = SDL_CONTROLLER_AXIS_RIGHTX, .positive = false } } },
{ .name = NULL }
};