Skip to content
2 changes: 2 additions & 0 deletions src/audio/miniaudio/ma_audio_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,8 @@ static void maGroupLoad(AudioSystem* audio, int32_t groupIndex) {

DataWinParserOptions options = {0};
options.parseAudo = true;
if (audio->dw->mappedFile)
options.loadType = DATAWINLOADTYPE_MAP_FILE;
DataWin *audioGroup = DataWin_parse(((MaAudioSystem*)audio)->fileSystem->vtable->resolvePath(((MaAudioSystem*)audio)->fileSystem, buf), options);
arrput(audio->audioGroups, audioGroup);
free(buf);
Expand Down
3 changes: 3 additions & 0 deletions src/audio/openal/al_audio_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static char* resolveExternalPath(AlAudioSystem* ma, Sound* sound) {

static void maInit(AudioSystem* audio, DataWin* dataWin, FileSystem* fileSystem) {
AlAudioSystem* ma = (AlAudioSystem*) audio;
ma->base.dw = dataWin;
arrput(ma->base.audioGroups, dataWin);
ma->fileSystem = fileSystem;

Expand Down Expand Up @@ -945,6 +946,8 @@ static void maGroupLoad(AudioSystem* audio, int32_t groupIndex) {

DataWinParserOptions options = {0};
options.parseAudo = true;
if (audio->dw->mappedFile)
options.loadType = DATAWINLOADTYPE_MAP_FILE;
DataWin *audioGroup = DataWin_parse(((AlAudioSystem*)audio)->fileSystem->vtable->resolvePath(((AlAudioSystem*)audio)->fileSystem, buf), options);
arrput(audio->audioGroups, audioGroup);
free(buf);
Expand Down
4 changes: 2 additions & 2 deletions src/desktop/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,8 @@ int main(int argc, char* argv[]) {
bool platformInitialized = false;
int32_t inputFrameCount = 0;

bool fastForwardActive = false;
bool fastForwardTabPrev = false;
while (true) {
fprintf(stderr, "Loading %s...\n", args.dataWinPath);

Expand Down Expand Up @@ -1803,8 +1805,6 @@ int main(int argc, char* argv[]) {

// Limit frame rate to room speed (skip in headless mode for max speed!!)
if (!args.headless && runner->currentRoom->speed > 0) {
static bool fastForwardActive = false;
static bool fastForwardTabPrev = false;
bool fastForwardTabNow = RunnerKeyboard_checkPressed(runner->keyboard, VK_TAB);
if (args.fastForwardSpeed > 0.0 && fastForwardTabNow && !fastForwardTabPrev) {
fastForwardActive = !fastForwardActive;
Expand Down
155 changes: 155 additions & 0 deletions src/gl/gl_renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1590,6 +1590,160 @@ static void glDrawTriangle(Renderer *renderer, float x1, float y1, float x2, flo
}
}

static int vertex_type_components(int type)
{
switch (type) {
case VERTEX_TYPE_FLOAT1:
return 1;
case VERTEX_TYPE_FLOAT2:
return 2;
case VERTEX_TYPE_FLOAT3:
return 3;
case VERTEX_TYPE_FLOAT4:
return 4;
case VERTEX_TYPE_UBYTE4:
return 4;
case VERTEX_TYPE_COLOR:
return 4;
}

return 4;
}

static void glDrawVertexBuffer(MAYBE_UNUSED Renderer* renderer, VertexBuffer* buffer, int32_t primitive, int32_t texture, int32_t offset, int32_t number) {
if (!buffer || !buffer->format)
return;

typedef struct {
GLuint vbo;
} GLVertexBuffer;

GLVertexBuffer *glBuffer = (GLVertexBuffer *)buffer->rendererData;

if (!glBuffer) {
glBuffer = (GLVertexBuffer *)malloc(sizeof(*glBuffer));
glGenBuffers(1, &glBuffer->vbo);
buffer->rendererData = (void *) glBuffer;
}

GLenum mode;

switch (primitive) {
case PRIMITIVE_POINTS:
mode = GL_POINTS;
break;

case PRIMITIVE_LINES:
mode = GL_LINES;
break;

case PRIMITIVE_LINE_STRIP:
mode = GL_LINE_STRIP;
break;

case PRIMITIVE_TRIANGLES:
mode = GL_TRIANGLES;
break;

case PRIMITIVE_TRIANGLE_STRIP:
mode = GL_TRIANGLE_STRIP;
break;

case PRIMITIVE_TRIANGLE_FAN:
mode = GL_TRIANGLE_FAN;
break;

default:
return;
}

glBindBuffer(GL_ARRAY_BUFFER, glBuffer->vbo);
glBufferData(GL_ARRAY_BUFFER, buffer->size, buffer->data, GL_DYNAMIC_DRAW);

for (int i = 0; i < buffer->format->numElements; i++) {
VertexElement *e = &buffer->format->elements[i];

switch (e->usage) {
case VERTEX_USAGE_POSITION:
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
vertex_type_components(e->type),
GL_FLOAT,
GL_FALSE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;

case VERTEX_USAGE_COLOR:
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
4,
GL_UNSIGNED_BYTE,
GL_TRUE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;

case VERTEX_USAGE_NORMAL:
glEnableVertexAttribArray(2);
glVertexAttribPointer(
2,
3,
GL_FLOAT,
GL_FALSE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;

case VERTEX_USAGE_TEXCOORD:
glEnableVertexAttribArray(3);
glVertexAttribPointer(
3,
2,
GL_FLOAT,
GL_FALSE,
buffer->format->stride,
(void*)(intptr_t)e->offset
);
break;
}
}

if (texture != -1) {
glBindTexture(GL_TEXTURE_2D, texture);
}

int vertexCount = buffer->size / buffer->format->stride;
if (offset < 0) offset = 0;
if (offset >= vertexCount) offset = vertexCount - 1;

if (number == -1) {
number = vertexCount - offset;
} else {
if (number < 0) number = 0;
if (offset + number > vertexCount) {
number = vertexCount - offset;
}
}

glDrawArrays(
mode,
offset,
number
);

for (int i = 0; i < buffer->format->numElements; i++) {
glDisableVertexAttribArray(i);
}

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

// ===[ Text Drawing ]===

// Resolved font state shared between glDrawText and glDrawTextColor
Expand Down Expand Up @@ -2691,6 +2845,7 @@ Renderer* GLRenderer_create(void) {
glVtable.drawLine = glDrawLine;
glVtable.drawLineColor = glDrawLineColor;
glVtable.drawTriangle = glDrawTriangle;
glVtable.drawVertexBuffer = glDrawVertexBuffer;
glVtable.drawText = glDrawText;
glVtable.drawTextColor = glDrawTextColor;
glVtable.flush = glRendererFlush;
Expand Down
57 changes: 57 additions & 0 deletions src/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,62 @@ typedef struct {
int32_t dstAlpha;
} BlendFactors;

// Vertex

typedef enum {
PRIMITIVE_POINTS = 0,
PRIMITIVE_LINES = 1,
PRIMITIVE_LINE_STRIP = 2,
PRIMITIVE_TRIANGLES = 3,
PRIMITIVE_TRIANGLE_STRIP = 4,
PRIMITIVE_TRIANGLE_FAN = 5,
} PrimitiveType;

typedef enum {
VERTEX_USAGE_POSITION = 1,
VERTEX_USAGE_COLOR = 2,
VERTEX_USAGE_NORMAL = 3,
VERTEX_USAGE_TEXCOORD = 4,
} VertexUsage;

typedef enum {
VERTEX_TYPE_FLOAT1,
VERTEX_TYPE_FLOAT2,
VERTEX_TYPE_FLOAT3,
VERTEX_TYPE_FLOAT4,
VERTEX_TYPE_UBYTE4,
VERTEX_TYPE_COLOR,
} VertexType;

typedef struct {
VertexUsage usage;
VertexType type;
uint32_t offset;
uint32_t size;
} VertexElement;

typedef struct {
VertexElement elements[16];
int numElements;
uint32_t stride;
} VertexFormat;

typedef struct {
uint8_t *data;
size_t size;
size_t capacity;

VertexFormat *format;
uint32_t vertexSize;

uint8_t currentVertex[256];
uint32_t currentOffset;

bool isFrozen;
bool vertexStarted;
void* rendererData; // Backend-specific data (e.g., OpenGL buffer ID)
} VertexBuffer;

typedef struct {
void (*init)(Renderer* renderer, DataWin* dataWin);
void (*destroy)(Renderer* renderer);
Expand All @@ -100,6 +156,7 @@ typedef struct {
void (*drawLineColor)(Renderer* renderer, float x1, float y1, float x2, float y2, float width, uint32_t color1, uint32_t color2, float alpha);
void (*drawText)(Renderer* renderer, const char* text, float x, float y, float xscale, float yscale, float angleDeg, float lineSeparation);
void (*drawTextColor)(Renderer* renderer, const char* text, float x, float y, float xscale, float yscale, float angleDeg, int32_t c1, int32_t c2, int32_t c3, int32_t c4, float alpha, float lineSeparation);
void (*drawVertexBuffer)(Renderer* renderer, VertexBuffer* buffer, int32_t primitive, int32_t texture, int32_t offset, int32_t count);
void (*flush)(Renderer* renderer);
void (*clearScreen)(Renderer* renderer, uint32_t color, float alpha);
int32_t (*createSpriteFromSurface)(Renderer* renderer, int32_t surfaceID, int32_t x, int32_t y, int32_t w, int32_t h, bool removeback, bool smooth, int32_t xorig, int32_t yorig);
Expand Down
7 changes: 5 additions & 2 deletions src/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ static GMLArray* VM_arraySetWithCoW(VMContext* ctx, RValue* slot, int32_t index,
require(slot != nullptr);
requireMessageFormatted(__FILE__, __LINE__, index >= 0, "Trying to write to an array using a negative index! Index: %d", index);

RValue writeVal = RValue_makeIndependent(val);

void* intendedOwner;
#if IS_WAD17_OR_HIGHER_ENABLED
intendedOwner = IS_WAD17_OR_HIGHER(ctx) ? ctx->currentArrayOwner : (void*) slot;
Expand All @@ -277,7 +279,7 @@ static GMLArray* VM_arraySetWithCoW(VMContext* ctx, RValue* slot, int32_t index,
fresh->owner = intendedOwner;
*slot = RValue_makeArray(fresh);
GMLArray_growTo(fresh, index + 1);
GMLArray_set(fresh, index, val);
RValue_writeIntoSlotStealingOwnershipOrCopying(GMLArray_slot(fresh, index), writeVal);
return fresh;
}

Expand All @@ -299,7 +301,8 @@ static GMLArray* VM_arraySetWithCoW(VMContext* ctx, RValue* slot, int32_t index,
}

// Case 3: Write!
GMLArray_set(arr, index, val);
GMLArray_growTo(arr, index + 1);
RValue_writeIntoSlotStealingOwnershipOrCopying(GMLArray_slot(arr, index), writeVal);
return arr;
}

Expand Down
Loading
Loading