1
0
Fork 0
2022-untitled-game/code/src/game/data.c

371 lines
8.7 KiB
C

enum {WALL_COUNT = 64};
enum {TILE_COUNT = 32};
typedef struct data {
struct {
transform_t* coins;
transform_t* eyeballs;
transform_t* pedestals;
int coin_count;
int eyeball_count;
int pedestal_count;
} items;
struct {
transform_t hundreds;
transform_t tens;
transform_t ones;
transform_t coin;
aabb_t collider;
} score;
size_t wall_count;
aabb_t walls[WALL_COUNT];
uint32_t tiles[TILE_COUNT];
} data_t;
mesh_t
mesh_load(SDL_RWops* ops)
{
struct vertex {
vec3 position;
vec3 normal;
vec2 texcoord;
};
uint16_t material_idx;
{
SDL_RWread(ops, &material_idx, sizeof(material_idx), 1);
}
GLuint ebo;
uint16_t index_count;
{
SDL_RWread(ops, &index_count, sizeof(index_count), 1);
uint16_t* indices = scratch_mem_alloc(index_count, sizeof(*indices));
SDL_RWread(ops, indices, sizeof(*indices), index_count);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
index_count * sizeof(*indices),
indices,
GL_STATIC_DRAW);
}
GLuint vbo;
{
uint16_t vertex_count;
SDL_RWread(ops, &vertex_count, sizeof(vertex_count), 1);
struct vertex* vertices = scratch_mem_alloc(vertex_count, sizeof(*vertices));
SDL_RWread(ops, vertices, sizeof(*vertices), vertex_count);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
vertex_count * sizeof(*vertices),
vertices,
GL_STATIC_DRAW);
}
GLuint vao;
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void*)offsetof(struct vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void*)offsetof(struct vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void*)offsetof(struct vertex, texcoord));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
mesh_t result = {
.vao = vao,
.vbo = vbo,
.ebo = ebo,
.index_count = index_count,
.material = material_idx};
return result;
}
material_t
material_load(SDL_RWops* ops)
{
GLuint texture;
{
uint16_t width;
SDL_RWread(ops, &width, sizeof(width), 1);
uint16_t height;
SDL_RWread(ops, &height, sizeof(height), 1);
uint8_t channel_count;
SDL_RWread(ops, &channel_count, sizeof(channel_count), 1);
uint8_t* data = scratch_mem_alloc(width * height * channel_count, sizeof(*data));
SDL_RWread(ops, data, sizeof(*data), width * height * channel_count);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
material_t result = {
.texture = texture};
return result;
}
wav_t
wav_load(SDL_RWops* ops)
{
uint32_t length;
SDL_RWread(ops, &length, sizeof(length), 1);
uint32_t sample_rate;
SDL_RWread(ops, &sample_rate, sizeof(sample_rate), 1);
uint8_t channel_count;
SDL_RWread(ops, &channel_count, sizeof(channel_count), 1);
float volume;
SDL_RWread(ops, &volume, sizeof(volume), 1);
bool is_looping;
SDL_RWread(ops, &is_looping, sizeof(is_looping), 1);
size_t size = length * channel_count;
float* wav_data = engine_mem_alloc(size, sizeof(*wav_data));
SDL_RWread(ops, wav_data, sizeof(*wav_data), size);
int byte_count = length * channel_count * sizeof(*wav_data);
wav_t result = {
.data = wav_data,
.byte_count = byte_count,
.sample_rate = sample_rate,
.volume = volume};
return result;
}
data_t
data_load(const char* path)
{
SDL_RWops* ops = SDL_RWFromFile(path, "rb");
if (ops == NULL)
{
LOG_ERROR("Error opening file %s: %s", path, SDL_GetError());
exit(EXIT_FAILURE);
}
{
char magic[4];
SDL_RWread(ops, magic, sizeof(magic), 1);
if (magic[0] != 'A' || magic[1] != 'J' || magic[2] != 'M' || magic[3] != '\0') {
LOG_ERROR("%s has an invalid format", path);
exit(EXIT_FAILURE);
}
}
data_t result = {0};
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d meshes", count);
for (int i = 0; i < count; i++)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of mesh is too long: %s", name);
mesh_t mesh = mesh_load(ops);
strncpy(mesh.name, name, name_length);
insert_mesh(mesh);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d materials", count);
for (int i = 0; i < count; i++)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of material is too long: %s", name);
material_t material = material_load(ops);
strncpy(material.name, name, name_length);
insert_material(material);
}
}
// Coins
{
transform_t* data = NULL;
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d coins", count);
data = game_mem_alloc(count, sizeof(*data));
SDL_RWread(ops, data, sizeof(*data), count);
result.items.coins = data;
result.items.coin_count = count;
}
// Eyeballs
{
transform_t* data = NULL;
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d eyeballs", count);
data = game_mem_alloc(count, sizeof(*data));
SDL_RWread(ops, data, sizeof(*data), count);
result.items.eyeballs = data;
result.items.eyeball_count = count;
}
// Pedestals
{
transform_t* data = NULL;
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d pedestals", count);
data = game_mem_alloc(count, sizeof(*data));
SDL_RWread(ops, data, sizeof(*data), count);
result.items.pedestals = data;
result.items.pedestal_count = count;
}
// Score
{
transform_t hundreds;
transform_t tens;
transform_t ones;
transform_t coin;
aabb_t collider;
SDL_RWread(ops, &hundreds, sizeof(hundreds), 1);
SDL_RWread(ops, &tens, sizeof(tens), 1);
SDL_RWread(ops, &ones, sizeof(ones), 1);
SDL_RWread(ops, &coin, sizeof(coin), 1);
SDL_RWread(ops, &collider, sizeof(collider), 1);
result.score.hundreds = hundreds;
result.score.tens = tens;
result.score.ones = ones;
result.score.coin = coin;
result.score.collider = collider;
}
{
aabb_t* walls = NULL;
uint16_t wall_count;
SDL_RWread(ops, &wall_count, sizeof(wall_count), 1);
LOG_ASSERT(wall_count <= WALL_COUNT, "Too many walls");
LOG_DEBUG("Load %d walls", wall_count);
walls = scratch_mem_alloc(wall_count, sizeof(*walls));
SDL_RWread(ops, walls, sizeof(*walls), wall_count);
memcpy(&result.walls, walls, sizeof(*walls) * wall_count);
result.wall_count = wall_count;
}
{
uint32_t* tiles;
uint8_t tile_count;
SDL_RWread(ops, &tile_count, sizeof(tile_count), 1);
LOG_ASSERT(tile_count == TILE_COUNT, "Incorrect number of tiles");
LOG_DEBUG("Load %d tiles", tile_count);
tiles = scratch_mem_alloc(tile_count, sizeof(*tiles));
SDL_RWread(ops, tiles, sizeof(*tiles), TILE_COUNT);
memcpy(&result.tiles, tiles, sizeof(*tiles) * tile_count);
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d songs", count);
for (int i = 0; i < count; i++)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of music is too long: %s", name);
wav_t music = wav_load(ops);
strncpy(music.name, name, name_length);
insert_music(music);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d SFX", count);
for (int i = 0; i < count; i++)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of SFX is too long: %s", name);
wav_t sfx = wav_load(ops);
strncpy(sfx.name, name, name_length);
insert_sfx(sfx);
}
}
int ret = SDL_RWclose(ops);
if (ret != 0) {
LOG_ERROR("Error closing file %s: %s", path, SDL_GetError());
}
return result;
}