Files
korenkonder_ReDIVA/src/KKdLib/f2/enrs.cpp
T

287 lines
8.4 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "enrs.hpp"
enum enrs_value_type {
ENRS_VALUE_INT8 = 0x0,
ENRS_VALUE_INT16 = 0x1,
ENRS_VALUE_INT32 = 0x2,
ENRS_VALUE_INVALID = 0x3,
};
inline static bool enrs_length_get_size_type(uint32_t* length, size_t val);
inline static bool enrs_length_get_size(uint32_t* length, size_t val);
static bool enrs_read_packed_value(stream& s, uint32_t* val);
static bool enrs_write_packed_value(stream& s, uint32_t val);
static bool enrs_read_packed_value_type(stream& s, uint32_t* val, enrs_type* type);
static bool enrs_write_packed_value_type(stream& s, uint32_t val, enrs_type type);
enrs_entry::enrs_entry(): offset(), count(), size(), repeat_count() {
}
enrs_entry::enrs_entry(uint32_t offset, uint32_t count, uint32_t size, uint32_t repeat_count) {
this->offset = offset;
this->count = count;
this->size = size;
this->repeat_count = repeat_count;
}
enrs_entry::~enrs_entry() {
}
void enrs_entry::append(uint32_t skip_bytes, uint32_t repeat_count, enrs_type type) {
sub.push_back({ skip_bytes, repeat_count, type });
}
void enrs_entry::append(enrs_sub_entry&& data) {
sub.push_back(data);
}
enrs::enrs() {
}
enrs::~enrs() {
}
void enrs::apply(void* data) {
if (!data)
return;
uint8_t* d = (uint8_t*)data;
uint8_t* temp;
for (enrs_entry& i : vec) {
d += i.offset;
for (size_t j = 0; j < i.repeat_count; j++) {
temp = d + i.size * j;
for (enrs_sub_entry& k : i.sub) {
temp += k.skip_bytes;
switch (k.type) {
case ENRS_WORD:
for (size_t l = k.repeat_count; l; l--) {
*(uint16_t*)temp = reverse_endianness_uint16_t(*(uint16_t*)temp);
temp += 2;
}
break;
case ENRS_DWORD:
for (size_t l = k.repeat_count; l; l--) {
*(uint32_t*)temp = reverse_endianness_uint32_t(*(uint32_t*)temp);
temp += 4;
}
break;
case ENRS_QWORD:
for (size_t l = k.repeat_count; l; l--) {
*(uint64_t*)temp = reverse_endianness_uint64_t(*(uint64_t*)temp);
temp += 8;
}
break;
}
}
}
}
}
uint32_t enrs::length() {
uint32_t l = 0x10;
uint32_t o = 0;
for (enrs_entry& i : vec) {
uint32_t offset = i.offset;
i.count = (uint32_t)i.sub.size();
if (&i != vec.data() && (&i)[-1].count < 1) {
o += (uint32_t)((size_t)(&i)[-1].size * (&i)[-1].repeat_count);
if (i.count > 0) {
offset += o;
o = 0;
}
}
if (i.count < 1)
continue;
if (enrs_length_get_size(&l, offset)
|| enrs_length_get_size(&l, i.count)
|| enrs_length_get_size(&l, i.size)
|| enrs_length_get_size(&l, i.repeat_count))
goto End;
if (i.repeat_count < 1 || i.count > 0x40000000)
continue;
for (enrs_sub_entry& j : i.sub) {
if (enrs_length_get_size_type(&l, j.skip_bytes)
|| enrs_length_get_size(&l, j.repeat_count))
goto End;
}
}
End:
l = align_val(l, 0x10);
return l;
}
void enrs::read(stream& s) {
vec.clear();
s.read_uint32_t();
size_t l = s.read_uint32_t();
s.read_uint32_t();
s.read_uint32_t();
vec.reserve(l);
for (size_t i = 0; i < l; i++) {
enrs_entry entry;
if (enrs_read_packed_value(s, &entry.offset)
|| enrs_read_packed_value(s, &entry.count)
|| enrs_read_packed_value(s, &entry.size)
|| enrs_read_packed_value(s, &entry.repeat_count))
return;
if (!entry.count || !entry.repeat_count) {
vec.push_back(entry);
continue;
}
entry.sub.reserve(entry.count);
for (size_t j = 0; j < entry.count; j++) {
enrs_sub_entry sub_entry = {};
if (enrs_read_packed_value_type(s, &sub_entry.skip_bytes, &sub_entry.type)
|| enrs_read_packed_value(s, &sub_entry.repeat_count))
return;
entry.sub.push_back(sub_entry);
}
vec.push_back(entry);
}
}
void enrs::write(stream& s) {
uint32_t o = 0;
size_t length = enrs::length();
s.write_uint32_t(0);
s.write_uint32_t((uint32_t)vec.size());
s.write_uint32_t(0);
s.write_uint32_t(0);
for (enrs_entry& i : vec) {
uint32_t offset = i.offset;
i.count = (uint32_t)i.sub.size();
if (&i != vec.data() && (&i)[-1].count < 1) {
o += (uint32_t)((size_t)(&i)[-1].size * (&i)[-1].repeat_count);
if ((&i)->count > 0) {
offset += o;
o = 0;
}
}
if (i.count < 1)
continue;
if (enrs_write_packed_value(s, offset)
|| enrs_write_packed_value(s, i.count)
|| enrs_write_packed_value(s, i.size)
|| enrs_write_packed_value(s, i.repeat_count))
goto End;
if (i.repeat_count < 1)
continue;
for (enrs_sub_entry& j : i.sub)
if (enrs_write_packed_value_type(s, j.skip_bytes, j.type)
|| enrs_write_packed_value(s, j.repeat_count))
goto End;
}
End:
s.align_write(0x10);
}
inline static bool enrs_length_get_size_type(uint32_t* length, size_t val) {
*length += val < 0x10 ? 1 : val < 0x1000 ? 2 : val < 0x10000000 ? 4 : 1;
return val >= 0x10000000;
}
inline static bool enrs_length_get_size(uint32_t* length, size_t val) {
if (!length)
return true;
*length += val < 0x40 ? 1 : val < 0x4000 ? 2 : val < 0x40000000 ? 4 : 1;
return val >= 0x40000000;
}
static bool enrs_read_packed_value(stream& s, uint32_t* val) {
*val = s.read_uint8_t();
enrs_value_type value = (enrs_value_type)((*val >> 6) & 0x3);
*val &= 0x3F;
if (value == ENRS_VALUE_INT32)
*val = (((((*val << 8) | s.read_uint8_t()) << 8) | s.read_uint8_t()) << 8) | s.read_uint8_t();
else if (value == ENRS_VALUE_INT16)
*val = (*val << 8) | s.read_uint8_t();
else if (value == ENRS_VALUE_INVALID) {
*val = 0;
return true;
}
return false;
}
static bool enrs_write_packed_value(stream& s, uint32_t val) {
if (val < 0x40)
s.write_uint8_t((uint8_t)((ENRS_VALUE_INT8 << 6) | (val & 0x3F)));
else if (val < 0x4000) {
s.write_uint8_t((uint8_t)((ENRS_VALUE_INT16 << 6) | ((val >> 8) & 0x3F)));
s.write_uint8_t((uint8_t)val);
}
else if (val < 0x40000000) {
s.write_uint8_t((uint8_t)((ENRS_VALUE_INT32 << 6) | ((val >> 24) & 0x3F)));
s.write_uint8_t((uint8_t)(val >> 16));
s.write_uint8_t((uint8_t)(val >> 8));
s.write_uint8_t((uint8_t)val);
}
else {
s.write_uint8_t(ENRS_VALUE_INVALID << 6);
return true;
}
return false;
}
static bool enrs_read_packed_value_type(stream& s, uint32_t* val, enrs_type* type) {
*val = s.read_uint8_t();
enrs_value_type value = (enrs_value_type)((*val >> 6) & 0x3);
*type = (enrs_type)((*val >> 4) & 0x3);
*val &= 0xF;
if (value == ENRS_VALUE_INT32)
*val = (((((*val << 8) | s.read_uint8_t()) << 8) | s.read_uint8_t()) << 8) | s.read_uint8_t();
else if (value == ENRS_VALUE_INT16)
*val = (*val << 8) | s.read_uint8_t();
else if (value == ENRS_VALUE_INVALID) {
*val = 0;
return true;
}
return false;
}
static bool enrs_write_packed_value_type(stream& s, uint32_t val, enrs_type type) {
uint8_t t = ((uint8_t)type & 0x3) << 4;
if (val < 0x10)
s.write_uint8_t((uint8_t)((ENRS_VALUE_INT8 << 6) | t | (val & 0xF)));
else if (val < 0x1000) {
s.write_uint8_t((uint8_t)((ENRS_VALUE_INT16 << 6) | t | ((val >> 8) & 0xF)));
s.write_uint8_t((uint8_t)val);
}
else if (val < 0x10000000) {
s.write_uint8_t((uint8_t)((ENRS_VALUE_INT32 << 6) | t | ((val >> 24) & 0xF)));
s.write_uint8_t((uint8_t)(val >> 16));
s.write_uint8_t((uint8_t)(val >> 8));
s.write_uint8_t((uint8_t)val);
}
else {
s.write_uint8_t(ENRS_VALUE_INVALID << 6);
return true;
}
return false;
}