techkaczynski.dev / code

summaryrefslogtreecommitdiff
path: root/save.c
diff options
context:
space:
mode:
Diffstat (limited to 'save.c')
-rw-r--r--save.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/save.c b/save.c
index db906a2..23f2c1e 100644
--- a/save.c
+++ b/save.c
@@ -516,6 +516,145 @@ write_model_chunk(FILE *fp) {
}
static bool
+read_material_chunk(FILE *fp, SaveLoadContext *ctx, MaterialProperty prop) {
+ u32 count;
+ if (!read_u32_le(fp, &count)) {
+ return false;
+ }
+
+ for (u32 i = 0; i < count; ++i) {
+ u64 pid;
+ u32 mat_idx, key_len;
+
+ if (!read_u64_le(fp, &pid) ||
+ !read_u32_le(fp, &mat_idx) ||
+ !read_u32_le(fp, &key_len)) {
+ return false;
+ }
+
+ if (!pid || pid >= ctx->next_pid ||
+ mat_idx == UINT32_MAX || !key_len) {
+ return false;
+ }
+
+ Entity *ent = entity_get(entity_id_from_pid(pid));
+ if (!ent || !ent->mdl.has) {
+ return false;
+ }
+
+ ModelCmp *model = &ent->mdl;
+
+ if (mat_idx >= model->mat_cnt) {
+ size_t slots = (size_t)mat_idx + 1;
+ if (slots > SIZE_MAX / sizeof(MaterialOverride)) {
+ return false;
+ }
+
+ MaterialOverride *materials;
+ materials = realloc(model->materials,
+ slots * sizeof(*materials));
+
+ if (!materials) {
+ return false;
+ }
+
+ memset(materials + model->mat_cnt, 0,
+ (slots - model->mat_cnt) *
+ sizeof(*materials));
+
+ model->materials = materials;
+ model->mat_cnt = slots;
+ }
+
+ MaterialOverride *material;
+ material = &model->materials[mat_idx];
+
+ char **field = prop == MAT_PROP_TEXTURE ?
+ &material->tex_key : &material->shader_key;
+
+ if (*field) {
+ return false;
+ }
+
+ char *key = malloc((size_t)key_len + 1);
+ if (!key) {
+ return false;
+ }
+
+ if (fread(key, 1, key_len, fp) != key_len) {
+ free(key);
+ return false;
+ }
+
+ key[key_len] = '\0';
+ *field = key;
+ }
+
+ return true;
+}
+
+static bool
+write_material_chunk(FILE *fp, MaterialProperty prop) {
+ SaveChunk chunk = {0};
+ u32 count = 0;
+ cstr label = prop == MAT_PROP_TEXTURE ? "MTEX" : "MSHD";
+
+ for (u32 i = 0; i < entity_count(); ++i) {
+ Entity *ent = &entity_data()[i];
+
+ if (!ent->pid || !ent->mdl.has) {
+ continue;
+ }
+
+ for (u32 j = 0; j < ent->mdl.mat_cnt; ++j) {
+ const MaterialOverride *material;
+ material = &ent->mdl.materials[j];
+
+ cstr key = prop == MAT_PROP_TEXTURE ?
+ material->tex_key : material->shader_key;
+
+ count += key != NULL;
+ }
+ }
+
+ if (!chunk_begin(fp, label, &chunk) ||
+ !write_u32_le(fp, count)) {
+ return false;
+ }
+
+ for (u32 i = 0; i < entity_count(); ++i) {
+ Entity *ent = &entity_data()[i];
+
+ if (!ent->pid || !ent->mdl.has) {
+ continue;
+ }
+
+ for (u32 j = 0; j < ent->mdl.mat_cnt; ++j) {
+ const MaterialOverride *material;
+ material = &ent->mdl.materials[j];
+
+ cstr key = prop == MAT_PROP_TEXTURE ?
+ material->tex_key : material->shader_key;
+
+ if (!key) {
+ continue;
+ }
+
+ u32 key_len = (u32)strlen(key);
+
+ if (!write_u64_le(fp, ent->pid) ||
+ !write_u32_le(fp, j) ||
+ !write_u32_le(fp, key_len) ||
+ !write_byte_arr(fp, key, key_len)) {
+ return false;
+ }
+ }
+ }
+
+ return chunk_end(fp, &chunk);
+}
+
+static bool
read_physics_shape(FILE *fp, PhysicsShape *shape) {
*shape = (PhysicsShape){0};
@@ -1006,6 +1145,18 @@ save_file_read(cstr path) {
break;
}
success = read_model_chunk(fp, &ctx);
+ } else if (memcmp(label, "MTEX", 4) ==0 ||
+ memcmp(label, "MSHD", 4) == 0) {
+ if (!read_entt) {
+ success = false;
+ break;
+ }
+
+ MaterialProperty prop;
+ prop = memcmp(label, "MTEX", 4) == 0 ?
+ MAT_PROP_TEXTURE : MAT_PROP_SHADER;
+
+ success = read_material_chunk(fp, &ctx, prop);
} else if (memcmp(label, "PHYS", 4) == 0) {
if (!read_entt) {
TraceLog(LOG_ERROR, "PHYS found before ENTT.");
@@ -1059,6 +1210,8 @@ save_file_write(cstr path) {
write_entity_chunk(fp) &&
write_transform_chunk(fp) &&
write_model_chunk(fp) &&
+ write_material_chunk(fp, MAT_PROP_TEXTURE) &&
+ write_material_chunk(fp, MAT_PROP_SHADER) &&
write_physics_chunk(fp);
if (fclose(fp) != 0) {