Files
korenkonder_ReDIVA/src/KKdLib/f2/struct.c
T

252 lines
7.4 KiB
C

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "struct.h"
#include "../io/path.h"
#include "../io/stream.h"
#include "../divafile.h"
vector_old_func(f2_struct)
static void f2_struct_read_data(stream* s, f2_struct* st, f2_header* h);
static void f2_struct_write_inner(stream* s, f2_struct* st, uint32_t depth, bool use_depth, bool shift_x);
static void f2_struct_get_length(f2_struct* s, bool shift_x);
static void f2_struct_write_pof(stream* s, vector_old_size_t* pof, uint32_t depth, bool shift_x);
static void f2_struct_write_enrs(stream* s, vector_old_enrs_entry* enrs, uint32_t depth);
void f2_struct_read(f2_struct* st, const char* path) {
memset(st, 0, sizeof(f2_struct));
stream s;
io_open(&s, path, "rb");
if (&s.io.stream) {
divafile_sdecrypt(&s);
f2_header h;
f2_header_read(&s, &h);
f2_struct_read_data(&s, st, &h);
}
io_free(&s);
}
void f2_struct_read(f2_struct* st, const wchar_t* path) {
memset(st, 0, sizeof(f2_struct));
stream s;
io_open(&s, path, L"rb");
if (&s.io.stream) {
divafile_sdecrypt(&s);
f2_header h;
f2_header_read(&s, &h);
f2_struct_read_data(&s, st, &h);
}
io_free(&s);
}
void f2_struct_read(f2_struct* st, const void* data, size_t length) {
memset(st, 0, sizeof(f2_struct));
stream s;
io_open(&s, data, length);
if (&s.io.data.data) {
divafile_sdecrypt(&s);
f2_header h;
f2_header_read(&s, &h);
f2_struct_read_data(&s, st, &h);
}
io_free(&s);
}
void f2_struct_read(f2_struct* st, stream* s) {
memset(st, 0, sizeof(f2_struct));
if (s->io.stream || s->io.data.data) {
divafile_sdecrypt(s);
f2_header h;
f2_header_read(s, &h);
f2_struct_read_data(s, st, &h);
}
}
void f2_struct_write(f2_struct* st, const char* path, bool use_depth, bool shift_x) {
stream s;
io_open(&s, path, "wb");
if (s.io.stream) {
f2_struct_get_length(st, shift_x);
f2_struct_write_inner(&s, st, 0, use_depth, shift_x);
}
io_free(&s);
}
void f2_struct_write(f2_struct* st, const wchar_t* path, bool use_depth, bool shift_x) {
stream s;
io_open(&s, path, L"wb");
if (s.io.stream) {
f2_struct_get_length(st, shift_x);
f2_struct_write_inner(&s, st, 0, use_depth, shift_x);
}
io_free(&s);
}
void f2_struct_write(f2_struct* st, void** data, size_t* length, bool use_depth, bool shift_x) {
if (!st || !data)
return;
f2_struct_get_length(st, shift_x);
stream s;
io_open(&s, 0, st->header.data_size + 0x40ULL);
f2_struct_write_inner(&s, st, 0, use_depth, shift_x);
io_copy(&s, data, length);
io_free(&s);
}
void f2_struct_write(f2_struct* st, stream* s, bool use_depth, bool shift_x) {
if (s->io.stream || s->type == STREAM_MEMORY) {
f2_struct_get_length(st, shift_x);
f2_struct_write_inner(s, st, 0, use_depth, shift_x);
}
}
void f2_struct_free(f2_struct* st) {
if (st->data)
free(st->data);
st->length = 0;
if (st->pof.begin)
vector_old_size_t_free(&st->pof, 0);
if (st->enrs.begin)
enrs_free(&st->enrs);
if (st->sub_structs.begin)
vector_old_f2_struct_free(&st->sub_structs, f2_struct_free);
memset(st, 0, sizeof(f2_struct));
}
static void f2_struct_get_length(f2_struct* s, bool shift_x) {
bool has_enrs, has_pof, has_sub_structs;
f2_struct* i;
uint32_t l;
vector_old_f2_struct ls;
has_pof = vector_old_length(s->pof) > 0 ? true : false;
has_enrs = vector_old_length(s->enrs) > 0 ? true : false;
has_sub_structs = vector_old_length(s->sub_structs) > 0 ? true : false;
s->header.section_size = s->data ? (uint32_t)s->length : 0;
l = s->header.section_size;
if (has_enrs) {
uint32_t len = enrs_length(&s->enrs);
l += 0x20 + align_val(len, 0x10);
}
if (has_pof) {
uint32_t len = pof_length(&s->pof, shift_x);
l += 0x20 + align_val(len, 0x10);
}
if (has_sub_structs) {
ls = s->sub_structs;
for (i = ls.begin; i != ls.end; i++) {
f2_struct_get_length(i, shift_x);
l += i->header.data_size;
l += i->header.length;
}
s->sub_structs = ls;
}
if (has_enrs || has_pof || has_sub_structs)
l += 0x20;
s->header.data_size = l;
}
static void f2_struct_read_data(stream* s, f2_struct* st, f2_header* h) {
uint32_t l = h->use_section_size ? h->section_size : h->data_size;
uint32_t depth = h->depth;
memset(st, 0, sizeof(f2_struct));
st->header = *h;
if (l) {
st->data = force_malloc(l);
io_read(s, st->data, l);
st->length = l;
}
uint32_t sig;
size_t length = (size_t)h->data_size - l;
size_t position = 0;
while (length > position) {
f2_header_read(s, h);
sig = reverse_endianness_uint32_t(h->signature);
l = h->use_section_size ? h->section_size : h->data_size;
position += (size_t)h->length + l;
if (sig == 'EOFC')
break;
else if (sig == 'ENRS') {
size_t pos = io_get_position(s);
enrs_read(s, &st->enrs);
io_set_position(s, pos + l, SEEK_SET);
}
else if ((sig & 0xF0FFFFFF) == 'POF0') {
size_t pos = io_get_position(s);
pof_read(s, &st->pof, sig == 'POF1');
io_set_position(s, pos + l, SEEK_SET);
}
else {
f2_struct* s_st = vector_old_f2_struct_reserve_back(&st->sub_structs);
f2_struct_read_data(s, s_st, h);
}
}
if (vector_old_length(st->sub_structs) < 1)
vector_old_f2_struct_free(&st->sub_structs, f2_struct_free);
}
static void f2_struct_write_inner(stream* s, f2_struct* st, uint32_t depth, bool use_depth, bool shift_x) {
st->header.depth = use_depth ? depth : 0;
f2_header_write(s, &st->header, st->header.length == 0x40);
if (st->data)
io_write(s, st->data, st->length);
if (st->enrs.begin)
f2_struct_write_enrs(s, &st->enrs, use_depth ? depth + 1 : 0);
if (st->pof.begin)
f2_struct_write_pof(s, &st->pof, use_depth ? depth + 1 : 0, shift_x);
if (st->sub_structs.begin)
for (f2_struct* i = st->sub_structs.begin; i != st->sub_structs.end; i++)
f2_struct_write_inner(s, i, depth + 1, use_depth, shift_x);
if (st->enrs.begin || st->pof.begin || st->sub_structs.begin)
f2_header_write_end_of_container(s, use_depth ? depth + 1 : 0);
if (!depth)
f2_header_write_end_of_container(s, 0);
}
static void f2_struct_write_pof(stream* s, vector_old_size_t* pof, uint32_t depth, bool shift_x) {
size_t len = pof_length(pof, shift_x);
f2_header h;
memset(&h, 0, sizeof(f2_header));
h.signature = shift_x ? reverse_endianness_uint32_t('POF1') : reverse_endianness_uint32_t('POF0');
h.length = 0x20;
h.depth = depth;
h.use_section_size = true;
h.data_size = h.section_size = (uint32_t)align_val(len, 0x10);
f2_header_write(s, &h, false);
pof_write(s, pof, shift_x);
}
static void f2_struct_write_enrs(stream* s, vector_old_enrs_entry* enrs, uint32_t depth) {
size_t len = enrs_length(enrs);
f2_header h;
memset(&h, 0, sizeof(f2_header));
h.signature = reverse_endianness_uint32_t('ENRS');
h.length = 0x20;
h.depth = depth;
h.use_section_size = true;
h.data_size = h.section_size = (uint32_t)align_val(len, 0x10);
f2_header_write(s, &h, false);
enrs_write(s, enrs);
}