From dd1eba3cae2548708fcab0614405667e47cd3e49 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Fri, 22 Nov 2024 01:28:42 +0300 Subject: [PATCH] Refectored `f2_header` and `f2_struct` --- src/CRE/Glitter/file_reader.cpp | 50 +++--- src/CRE/Glitter/file_writer.cpp | 101 +++++------- src/KKdLib/a3da.cpp | 5 +- src/KKdLib/aet.cpp | 10 +- src/KKdLib/database/aet.cpp | 18 +-- src/KKdLib/database/bone.cpp | 19 ++- src/KKdLib/database/object.cpp | 18 +-- src/KKdLib/database/sprite.cpp | 18 +-- src/KKdLib/database/stage.cpp | 12 +- src/KKdLib/database/texture.cpp | 18 +-- src/KKdLib/dsc.cpp | 7 +- src/KKdLib/f2/header.cpp | 215 ++++++++++++++++++++++++-- src/KKdLib/f2/header.hpp | 177 +++++++++++++++++++-- src/KKdLib/f2/struct.cpp | 91 +++++------ src/KKdLib/hash.cpp | 2 +- src/KKdLib/hash.hpp | 4 +- src/KKdLib/mot.cpp | 11 +- src/KKdLib/obj.cpp | 46 +++--- src/KKdLib/post_process_table/dof.cpp | 19 ++- src/KKdLib/pv_exp.cpp | 10 +- src/KKdLib/pvpp.cpp | 2 +- src/KKdLib/pvsr.cpp | 2 +- src/KKdLib/spr.cpp | 12 +- src/KKdLib/txp.cpp | 8 +- src/ReDIVA/main.cpp | 114 ++++++++------ 25 files changed, 626 insertions(+), 363 deletions(-) diff --git a/src/CRE/Glitter/file_reader.cpp b/src/CRE/Glitter/file_reader.cpp index 9f91739a..121c4789 100644 --- a/src/CRE/Glitter/file_reader.cpp +++ b/src/CRE/Glitter/file_reader.cpp @@ -264,7 +264,7 @@ namespace Glitter { } void FileReader::ParseAnimation(f2_struct* st, Animation* anim) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('ANIM')) return; @@ -273,7 +273,7 @@ namespace Glitter { } void FileReader::ParseCurve(f2_struct* st, Animation* anim) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('CURV')) return; @@ -286,7 +286,7 @@ namespace Glitter { uint32_t keys_count; if (type == Glitter::X) { if (st->header.version == 1) { - if (st->header.use_big_endian) { + if (st->header.attrib.get_big_endian()) { c->type = (CurveType)load_reverse_endianness_uint32_t((void*)d); c->repeat = load_reverse_endianness_uint32_t((void*)(d + 4)) != 0; c->flags = (CurveFlag)load_reverse_endianness_uint32_t((void*)(d + 8)); @@ -306,7 +306,7 @@ namespace Glitter { } } else { - if (st->header.use_big_endian) { + if (st->header.attrib.get_big_endian()) { c->type = (CurveType)load_reverse_endianness_uint32_t((void*)d); c->repeat = load_reverse_endianness_uint32_t((void*)(d + 4)) != 0; c->flags = (CurveFlag)load_reverse_endianness_uint32_t((void*)(d + 8)); @@ -327,7 +327,7 @@ namespace Glitter { } } else { - if (st->header.use_big_endian) { + if (st->header.attrib.get_big_endian()) { c->type = (CurveType)load_reverse_endianness_uint32_t((void*)d); c->repeat = load_reverse_endianness_uint32_t((void*)(d + 4)) != 0; c->flags = (CurveFlag)load_reverse_endianness_uint32_t((void*)(d + 8)); @@ -357,16 +357,16 @@ namespace Glitter { } for (f2_struct& i : st->sub_structs) - if (i.header.data_size && i.header.signature == reverse_endianness_uint32_t('KEYS')) { + if (i.header.get_raw_data_size() && i.header.signature == reverse_endianness_uint32_t('KEYS')) { UnpackCurve(i.data.data(), anim, c, - keys_count, i.header.version, i.header.use_big_endian); + keys_count, i.header.version, i.header.attrib.get_big_endian()); break; } anim->curves.push_back(c); } bool FileReader::ParseDivaEffect(GPM, f2_struct* st) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('DVEF')) return false; @@ -416,7 +416,7 @@ namespace Glitter { } bool FileReader::ParseDivaList(f2_struct* st, EffectGroup* eff_group) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('LIST')) return false; @@ -427,7 +427,7 @@ namespace Glitter { } bool FileReader::ParseDivaResource(GPM, f2_struct* st, EffectGroup* eff_group) { - if (!st || !st->header.data_size) + if (!st || !st->header.get_raw_data_size()) return false; for (f2_struct& i : st->sub_structs) @@ -437,13 +437,13 @@ namespace Glitter { } bool FileReader::ParseEffect(f2_struct* st, EffectGroup* eff_group) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('EFCT')) return false; Effect* eff = new Effect(type); if (!UnpackEffect(st->data.data(), eff, - st->header.version, st->header.use_big_endian)) { + st->header.version, st->header.attrib.get_big_endian())) { delete eff; return false; } @@ -457,12 +457,12 @@ namespace Glitter { } bool FileReader::ParseEffectGroup(f2_struct* st, std::vector* vec, EffectGroup* eff_group) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('DVEF')) return false; for (f2_struct& i : st->sub_structs) { - if (!i.header.data_size) + if (!i.header.get_raw_data_size()) continue; if (i.header.signature == reverse_endianness_uint32_t('EFCT')) { @@ -477,12 +477,12 @@ namespace Glitter { } bool FileReader::ParseEmitter(f2_struct* st, Effect* eff, EffectGroup* eff_group) { - if (!st || !st->header.data_size || st->header.signature != reverse_endianness_uint32_t('EMIT')) + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('EMIT')) return false; Emitter* emit = new Emitter(type); if (!UnpackEmitter(st->data.data(), emit, - st->header.version, st->header.use_big_endian)) { + st->header.version, st->header.attrib.get_big_endian())) { delete emit; return false; } @@ -496,12 +496,12 @@ namespace Glitter { } bool FileReader::ParseParticle(f2_struct* st, Emitter* emit, Effect* eff, EffectGroup* eff_group) { - if (!st || !st->header.data_size || st->header.signature != reverse_endianness_uint32_t('PTCL')) + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('PTCL')) return false; Particle* ptcl = new Particle(type); if (!UnpackParticle(st->data.data(), ptcl, - st->header.version, eff, st->header.use_big_endian, eff_group)) { + st->header.version, eff, st->header.attrib.get_big_endian(), eff_group)) { delete ptcl; return false; } @@ -958,13 +958,13 @@ namespace Glitter { } bool FileReader::UnpackDivaList(f2_struct* st, EffectGroup* eff_group) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('GEFF')) return false; size_t d = (size_t)st->data.data(); uint32_t length; - if (st->header.use_big_endian) + if (st->header.attrib.get_big_endian()) length = load_reverse_endianness_uint32_t((void*)d); else length = *(uint32_t*)d; @@ -993,11 +993,11 @@ namespace Glitter { } bool FileReader::UnpackDivaResource(GPM, f2_struct* st, EffectGroup* eff_group) { - if (!st || !st->header.data_size + if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('TXPC')) return false; - eff_group->resources_tex.unpack_file(st->data.data(), st->header.use_big_endian); + eff_group->resources_tex.unpack_file(st->data.data(), st->header.attrib.get_big_endian()); if (!eff_group->resources_count) return false; @@ -1051,7 +1051,7 @@ namespace Glitter { bool FileReader::UnpackDivaResourceHashes(f2_struct* st, EffectGroup* eff_group) { if (eff_group->resources_count && eff_group->resource_hashes.size() > 0) return true; - else if (!st || !st->header.data_size + else if (!st || !st->header.get_raw_data_size() || st->header.signature != reverse_endianness_uint32_t('DVRS')) return false; @@ -1060,7 +1060,7 @@ namespace Glitter { return false; uint32_t count; - if (st->header.use_big_endian) + if (st->header.attrib.get_big_endian()) count = load_reverse_endianness_uint32_t((void*)d); else count = *(int32_t*)d; @@ -1073,7 +1073,7 @@ namespace Glitter { if (!resource_hashes) return false; - if (st->header.use_big_endian) + if (st->header.attrib.get_big_endian()) for (size_t i = count; i; i--, resource_hashes++, d += sizeof(uint64_t)) *resource_hashes = load_reverse_endianness_uint64_t((void*)d); else diff --git a/src/CRE/Glitter/file_writer.cpp b/src/CRE/Glitter/file_writer.cpp index bb2be50f..89362b10 100644 --- a/src/CRE/Glitter/file_writer.cpp +++ b/src/CRE/Glitter/file_writer.cpp @@ -86,10 +86,7 @@ namespace Glitter { void FileWriter::PackCurve(f2_struct* st, Curve* c, bool big_endian) { if (!c->keys.size()) { - st->header.signature = reverse_endianness_uint32_t('KEYS'); - st->header.length = 0x20; - st->header.use_big_endian = false; - st->header.use_section_size = true; + new (&st->header) f2_header('KEYS'); st->header.version = c->keys_version; return; } @@ -449,10 +446,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('KEYS'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('KEYS'); + st->header.attrib.set_big_endian(big_endian); st->header.version = c->keys_version; } @@ -491,10 +486,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('GEFF'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('GEFF'); + st->header.attrib.set_big_endian(big_endian); return true; } @@ -507,10 +500,7 @@ namespace Glitter { eff_group->resources_tex.pack_file(st->data, false); - st->header.signature = reverse_endianness_uint32_t('TXPC'); - st->header.length = 0x20; - st->header.use_big_endian = false; - st->header.use_section_size = true; + new (&st->header) f2_header('TXPC'); return true; } @@ -554,10 +544,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('DVRS'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('DVRS'); + st->header.attrib.set_big_endian(big_endian); return true; } @@ -956,10 +944,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('EFCT'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('EFCT'); + st->header.attrib.set_big_endian(big_endian); st->header.version = eff->version; return true; } @@ -1302,10 +1288,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('EMIT'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('EMIT'); + st->header.attrib.set_big_endian(big_endian); st->header.version = emit->version; return true; } @@ -1817,10 +1801,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('PTCL'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('PTCL'); + st->header.attrib.set_big_endian(big_endian); st->header.version = ptcl->version; return true; } @@ -1882,10 +1864,8 @@ namespace Glitter { if (st->sub_structs.size() < 1) return false; - st->header.signature = reverse_endianness_uint32_t('ANIM'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('ANIM'); + st->header.attrib.set_big_endian(big_endian); return true; } @@ -1924,7 +1904,7 @@ namespace Glitter { st->data.resize(l); d = (size_t)st->data.data(); - if (st->header.use_big_endian) { + if (big_endian) { store_reverse_endianness_uint32_t((void*)d, c->type); store_reverse_endianness_uint32_t((void*)(d + 4), c->repeat ? 1 : 0); store_reverse_endianness_uint32_t((void*)(d + 8), c->flags); @@ -1954,7 +1934,7 @@ namespace Glitter { st->data.resize(l); d = (size_t)st->data.data(); - if (st->header.use_big_endian) { + if (big_endian) { store_reverse_endianness_uint32_t((void*)d, c->type); store_reverse_endianness_uint32_t((void*)(d + 4), c->repeat ? 1 : 0); store_reverse_endianness_uint32_t((void*)(d + 8), c->flags); @@ -2026,10 +2006,8 @@ namespace Glitter { st->enrs = e; - st->header.signature = reverse_endianness_uint32_t('CURV'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('CURV'); + st->header.attrib.set_big_endian(big_endian); st->header.version = c->version; f2_struct s; @@ -2044,10 +2022,7 @@ namespace Glitter { bool FileWriter::UnparseDivaEffect(EffectGroup* eff_group, f2_struct* st, bool big_endian) { UnparseEffectGroup(eff_group, st, big_endian); - st->header.signature = reverse_endianness_uint32_t('DVEF'); - st->header.length = 0x20; - st->header.use_big_endian = false; - st->header.use_section_size = true; + new (&st->header) f2_header('DVEF'); st->header.version = eff_group->version; return true; } @@ -2059,10 +2034,8 @@ namespace Glitter { st->sub_structs.push_back(s); - st->header.signature = reverse_endianness_uint32_t('LIST'); - st->header.length = 0x20; - st->header.use_big_endian = big_endian; - st->header.use_section_size = true; + new (&st->header) f2_header('LIST'); + st->header.attrib.set_big_endian(big_endian); return true; } @@ -2073,10 +2046,7 @@ namespace Glitter { st->sub_structs.push_back(s); - st->header.signature = reverse_endianness_uint32_t('DVRS'); - st->header.length = 0x20; - st->header.use_big_endian = false; - st->header.use_section_size = true; + new (&st->header) f2_header('DVRS'); st->header.version = 1; return true; } @@ -2177,6 +2147,17 @@ namespace Glitter { memcpy(temp, file, file_len); temp[file_len] = 0; + { + f2_struct drs_st; + if (fr.UnparseDivaResource(eff_group, &drs_st)) { + memcpy(&temp[file_len], ".drs", 4); + temp[file_len + 4] = 0; + farc_file* ff_drs = f.add_file(temp); + drs_st.write(&ff_drs->data, &ff_drs->size); + ff_drs->compressed = compress; + ff_drs->encrypted = encrypt; + } + } { f2_struct dve_st; @@ -2194,18 +2175,6 @@ namespace Glitter { } } - { - f2_struct drs_st; - if (fr.UnparseDivaResource(eff_group, &drs_st)) { - memcpy(&temp[file_len], ".drs", 4); - temp[file_len + 4] = 0; - farc_file* ff_drs = f.add_file(temp); - drs_st.write(&ff_drs->data, &ff_drs->size); - ff_drs->compressed = compress; - ff_drs->encrypted = encrypt; - } - } - if (fr.type == Glitter::FT || save_lst) { f2_struct lst_st; if (fr.UnparseDivaList(eff_group, &lst_st, big_endian)) { diff --git a/src/KKdLib/a3da.cpp b/src/KKdLib/a3da.cpp index 245bf284..0cc29744 100644 --- a/src/KKdLib/a3da.cpp +++ b/src/KKdLib/a3da.cpp @@ -547,10 +547,7 @@ static void a3da_write_inner(a3da* a, stream& s) { s_a3da.copy(st.data); s_a3da.close(); - st.header.signature = reverse_endianness_uint32_t('A3DA'); - st.header.length = 0x40; - st.header.use_big_endian = false; - st.header.use_section_size = true; + new (&st.header) f2_header('A3DA'); st.header.inner_signature = a->format == A3DA_FORMAT_XHD ? 0x00131010 : 0x01131010; st.write(s, true, a->format == A3DA_FORMAT_X || a->format == A3DA_FORMAT_XHD); diff --git a/src/KKdLib/aet.cpp b/src/KKdLib/aet.cpp index 19dd1b1f..c44f185d 100644 --- a/src/KKdLib/aet.cpp +++ b/src/KKdLib/aet.cpp @@ -904,8 +904,8 @@ static void aet_set_modern_read_inner(aet_set* as, prj::shared_ptris_x); } diff --git a/src/KKdLib/database/bone.cpp b/src/KKdLib/database/bone.cpp index 9ba2cf6f..64c12934 100644 --- a/src/KKdLib/database/bone.cpp +++ b/src/KKdLib/database/bone.cpp @@ -82,8 +82,8 @@ void bone_database::read(const char* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('BONE')) { memory_stream s_bone; s_bone.open(st.data); - s_bone.big_endian = st.header.use_big_endian; - bone_database_modern_read_inner(this, s_bone, st.header.length); + s_bone.big_endian = st.header.attrib.get_big_endian(); + bone_database_modern_read_inner(this, s_bone, st.header.get_length()); } } free_def(path_bon); @@ -118,8 +118,8 @@ void bone_database::read(const wchar_t* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('BONE')) { memory_stream s_bone; s_bone.open(st.data); - s_bone.big_endian = st.header.use_big_endian; - bone_database_modern_read_inner(this, s_bone, st.header.length); + s_bone.big_endian = st.header.attrib.get_big_endian(); + bone_database_modern_read_inner(this, s_bone, st.header.get_length()); } } free_def(path_bon); @@ -141,8 +141,8 @@ void bone_database::read(const void* data, size_t size, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('BONE')) { memory_stream s_bone; s_bone.open(st.data); - s_bone.big_endian = st.header.use_big_endian; - bone_database_modern_read_inner(this, s_bone, st.header.length); + s_bone.big_endian = st.header.attrib.get_big_endian(); + bone_database_modern_read_inner(this, s_bone, st.header.get_length()); } } } @@ -1418,10 +1418,9 @@ static void bone_database_modern_write_inner(bone_database* bone_data, stream& s st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('BONE'); - st.header.length = is_x ? 0x20 : 0x40; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('BONE'); + st.header.set_length(is_x ? F2_HEADER_DEFAULT_LENGTH : F2_HEADER_EXTENDED_LENGTH); + st.header.attrib.set_big_endian(big_endian); st.write(s, true, is_x); } diff --git a/src/KKdLib/database/object.cpp b/src/KKdLib/database/object.cpp index 4c04efac..d3892f6e 100644 --- a/src/KKdLib/database/object.cpp +++ b/src/KKdLib/database/object.cpp @@ -89,8 +89,8 @@ void object_database_file::read(const char* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('MOSI')) { memory_stream s_mosi; s_mosi.open(st.data); - s_mosi.big_endian = st.header.use_big_endian; - object_database_file_modern_read_inner(this, s_mosi, st.header.length); + s_mosi.big_endian = st.header.attrib.get_big_endian(); + object_database_file_modern_read_inner(this, s_mosi, st.header.get_length()); } } free_def(path_osi); @@ -125,8 +125,8 @@ void object_database_file::read(const wchar_t* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('MOSI')) { memory_stream s_mosi; s_mosi.open(st.data); - s_mosi.big_endian = st.header.use_big_endian; - object_database_file_modern_read_inner(this, s_mosi, st.header.length); + s_mosi.big_endian = st.header.attrib.get_big_endian(); + object_database_file_modern_read_inner(this, s_mosi, st.header.get_length()); } } free_def(path_osi); @@ -148,8 +148,8 @@ void object_database_file::read(const void* data, size_t size, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('MOSI')) { memory_stream s_mosi; s_mosi.open(st.data); - s_mosi.big_endian = st.header.use_big_endian; - object_database_file_modern_read_inner(this, s_mosi, st.header.length); + s_mosi.big_endian = st.header.attrib.get_big_endian(); + object_database_file_modern_read_inner(this, s_mosi, st.header.get_length()); } } } @@ -933,10 +933,8 @@ static void object_database_file_modern_write_inner(object_database_file* obj_db st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('MOSI'); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('MOSI'); + st.header.attrib.set_big_endian(big_endian); st.write(s, true, is_x); } diff --git a/src/KKdLib/database/sprite.cpp b/src/KKdLib/database/sprite.cpp index d5993ef6..b70ca178 100644 --- a/src/KKdLib/database/sprite.cpp +++ b/src/KKdLib/database/sprite.cpp @@ -93,8 +93,8 @@ void sprite_database_file::read(const char* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('SPDB')) { memory_stream s_spdb; s_spdb.open(st.data); - s_spdb.big_endian = st.header.use_big_endian; - sprite_database_file_modern_read_inner(this, s_spdb, st.header.length); + s_spdb.big_endian = st.header.attrib.get_big_endian(); + sprite_database_file_modern_read_inner(this, s_spdb, st.header.get_length()); } } free_def(path_spi); @@ -129,8 +129,8 @@ void sprite_database_file::read(const wchar_t* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('SPDB')) { memory_stream s_spdb; s_spdb.open(st.data); - s_spdb.big_endian = st.header.use_big_endian; - sprite_database_file_modern_read_inner(this, s_spdb, st.header.length); + s_spdb.big_endian = st.header.attrib.get_big_endian(); + sprite_database_file_modern_read_inner(this, s_spdb, st.header.get_length()); } } free_def(path_spi); @@ -152,8 +152,8 @@ void sprite_database_file::read(const void* data, size_t size, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('SPDB')) { memory_stream s_spdb; s_spdb.open(st.data); - s_spdb.big_endian = st.header.use_big_endian; - sprite_database_file_modern_read_inner(this, s_spdb, st.header.length); + s_spdb.big_endian = st.header.attrib.get_big_endian(); + sprite_database_file_modern_read_inner(this, s_spdb, st.header.get_length()); } } } @@ -931,10 +931,8 @@ static void sprite_database_file_modern_write_inner(sprite_database_file* spr_db st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('SPDB'); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('SPDB'); + st.header.attrib.set_big_endian(big_endian); st.write(s, true, spr_db->is_x); } diff --git a/src/KKdLib/database/stage.cpp b/src/KKdLib/database/stage.cpp index f4f18a9d..2bf9e0ad 100644 --- a/src/KKdLib/database/stage.cpp +++ b/src/KKdLib/database/stage.cpp @@ -118,8 +118,8 @@ void stage_database_file::read(const char* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('STGC')) { memory_stream s_stgc; s_stgc.open(st.data); - s_stgc.big_endian = st.header.use_big_endian; - stage_database_file_modern_read_inner(this, s_stgc, st.header.length); + s_stgc.big_endian = st.header.attrib.get_big_endian(); + stage_database_file_modern_read_inner(this, s_stgc, st.header.get_length()); } } free_def(path_stg); @@ -154,8 +154,8 @@ void stage_database_file::read(const wchar_t* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('STGC')) { memory_stream s_stgc; s_stgc.open(st.data); - s_stgc.big_endian = st.header.use_big_endian; - stage_database_file_modern_read_inner(this, s_stgc, st.header.length); + s_stgc.big_endian = st.header.attrib.get_big_endian(); + stage_database_file_modern_read_inner(this, s_stgc, st.header.get_length()); } } free_def(path_stg); @@ -177,8 +177,8 @@ void stage_database_file::read(const void* data, size_t size, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('STGC')) { memory_stream s_stgc; s_stgc.open(st.data); - s_stgc.big_endian = st.header.use_big_endian; - stage_database_file_modern_read_inner(this, s_stgc, st.header.length); + s_stgc.big_endian = st.header.attrib.get_big_endian(); + stage_database_file_modern_read_inner(this, s_stgc, st.header.get_length()); } } } diff --git a/src/KKdLib/database/texture.cpp b/src/KKdLib/database/texture.cpp index cda40666..041af085 100644 --- a/src/KKdLib/database/texture.cpp +++ b/src/KKdLib/database/texture.cpp @@ -73,8 +73,8 @@ void texture_database_file::read(const char* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('MTXI')) { memory_stream s_mtxi; s_mtxi.open(st.data); - s_mtxi.big_endian = st.header.use_big_endian; - texture_database_file_modern_read_inner(this, s_mtxi, st.header.length); + s_mtxi.big_endian = st.header.attrib.get_big_endian(); + texture_database_file_modern_read_inner(this, s_mtxi, st.header.get_length()); } } free_def(path_txi); @@ -109,8 +109,8 @@ void texture_database_file::read(const wchar_t* path, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('MTXI')) { memory_stream s_mtxi; s_mtxi.open(st.data); - s_mtxi.big_endian = st.header.use_big_endian; - texture_database_file_modern_read_inner(this, s_mtxi, st.header.length); + s_mtxi.big_endian = st.header.attrib.get_big_endian(); + texture_database_file_modern_read_inner(this, s_mtxi, st.header.get_length()); } } free_def(path_txi); @@ -132,8 +132,8 @@ void texture_database_file::read(const void* data, size_t size, bool modern) { if (st.header.signature == reverse_endianness_uint32_t('MTXI')) { memory_stream s_mtxi; s_mtxi.open(st.data); - s_mtxi.big_endian = st.header.use_big_endian; - texture_database_file_modern_read_inner(this, s_mtxi, st.header.length); + s_mtxi.big_endian = st.header.attrib.get_big_endian(); + texture_database_file_modern_read_inner(this, s_mtxi, st.header.get_length()); } } } @@ -488,10 +488,8 @@ static void texture_database_file_modern_write_inner(texture_database_file* tex_ st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('MTXI'); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('MTXI'); + st.header.attrib.set_big_endian(big_endian); st.write(s, true, tex_db->is_x); } diff --git a/src/KKdLib/dsc.cpp b/src/KKdLib/dsc.cpp index 9db4b3b4..e7fa0018 100644 --- a/src/KKdLib/dsc.cpp +++ b/src/KKdLib/dsc.cpp @@ -3042,7 +3042,7 @@ bool dsc::parse(const void* data, size_t size, dsc_type type) { case DSC_VRFL: st.read(data, size); data_dsc = (int32_t*)st.data.data(); - if (st.header.use_big_endian) + if (st.header.attrib.get_big_endian()) for (size_t i = size / 4; i; i--, data_dsc++) *data_dsc = load_reverse_endianness_uint32_t(data_dsc); @@ -3248,9 +3248,8 @@ void dsc::unparse(void** data, size_t* size) { st.enrs = e; - st.header.signature = reverse_endianness_uint32_t('PVSC'); - st.header.length = 0x40; - st.header.use_section_size = true; + new (&st.header) f2_header('PVSC'); + st.header.set_length(F2_HEADER_EXTENDED_LENGTH); st.header.inner_signature = 0x13120420; st.write(data, size, true, false); } diff --git a/src/KKdLib/f2/header.cpp b/src/KKdLib/f2/header.cpp index 36462c50..e0a70e22 100644 --- a/src/KKdLib/f2/header.cpp +++ b/src/KKdLib/f2/header.cpp @@ -5,33 +5,214 @@ #include "header.hpp" -void f2_header_read(stream& s, f2_header* h) { - memset(h, 0, sizeof(f2_header)); +static uint8_t calc_crc8(uint8_t* data, uint32_t size, uint8_t seed = 0xFF); +static uint16_t calc_crc16_ccitt(uint8_t* data, uint32_t size, uint16_t seed = 0xFFFF); + +f2_header::f2_header() : signature(), data_size(), length(), attrib(), depth(), crc8(), crc16(), +section_size(), version(), custom(), murmurhash(), unknown1(), inner_signature(), unknown2() { + signature = ' '; + set_length(F2_HEADER_DEFAULT_LENGTH); + attrib.set_type(0x01); +} + +f2_header::f2_header(uint32_t signature, uint32_t size, uint32_t depth, bool align) : f2_header() { + this->signature = reverse_endianness_uint32_t(signature); + set_length(F2_HEADER_DEFAULT_LENGTH); + set_section_size(size, align); + set_data_size(size, align); + + attrib.m.unk0 = 0x00; + attrib.set_align(align); + attrib.set_big_endian(false); + this->depth = (uint8_t)depth; + version &= 0xFFF0FFFF; +} + +void f2_header::apply_xor() { + if (attrib.get_xor_data() > 0x01) + return; + + if (attrib.get_xor_data()) { + remove_xor(); + apply_xor(); + return; + } + + uint8_t* data = get_section_data(); + uint8_t* data_end = data + get_section_size(); + + uint8_t* iv_begin = (uint8_t*)this; + uint8_t* iv = iv_begin; + + uint8_t xor_val = 0xA5; + while (iv != iv_begin + 0x08) + xor_val ^= *iv++; + + if (!xor_val || xor_val == 0xFF) + xor_val = 0x01; + + while (data != data_end) { + xor_val ^= *data; + *data++ = xor_val; + } + + attrib.set_xor_data(0x02); +} + +void f2_header::calc_crc() { + attrib.set_crc(true); + + uint8_t crc8 = calc_crc8((uint8_t*)§ion_size, 0x0C, calc_crc8((uint8_t*)this, 0x11)); + if (attrib.get_type()) + this->crc8 = crc8; + else + abort(); + + uint16_t crc16 = calc_crc16(); + if (attrib.get_type()) + this->crc16 = crc16; + else + abort(); +} + +uint16_t f2_header::calc_crc16() const { + uint16_t hash = calc_crc16_ccitt((uint8_t*)this + F2_HEADER_DEFAULT_LENGTH, + get_length() - F2_HEADER_DEFAULT_LENGTH); + return calc_crc16_ccitt(get_section_data(), get_section_size(), hash); +} + +void f2_header::read(stream& s) { + *this = {}; if (s.check_null()) return; - s.read(h, 0x20); - if (h->length == 0x40) - s.read((uint8_t*)h + 0x20, 0x20); + s.read(this, F2_HEADER_DEFAULT_LENGTH); + if (get_length() > F2_HEADER_DEFAULT_LENGTH) + s.read((uint8_t*)this + F2_HEADER_DEFAULT_LENGTH, + min_def(get_length(), F2_HEADER_EXTENDED_LENGTH) - F2_HEADER_DEFAULT_LENGTH); } -void f2_header_write(stream& s, f2_header* h, bool extended) { +void f2_header::remove_xor() { + if (attrib.get_xor_data() > 0x01) { + if (attrib.get_xor_data() != 0x03) { + uint8_t* data = get_section_data(); + uint8_t* data_end = data + get_section_size(); + + uint8_t* iv_begin = (uint8_t*)this; + uint8_t* iv = iv_begin; + + uint8_t xor_val = 0xA5; + + while (iv != iv_begin + 0x08) + xor_val ^= *iv++; + + if (!xor_val || xor_val == 0xFF) + xor_val = 0x01; + + while (data != data_end) { + uint8_t temp = *data; + *data++ ^= xor_val; + xor_val = temp; + } + + attrib.set_xor_data(0x00); + } + } + else { + if (attrib.get_xor_data() != 0x00) { + uint8_t* data = get_section_data(); + uint8_t* data_end = data + min_def(0x200U, get_section_size()); + + uint8_t* iv_begin = (uint8_t*)this; + uint8_t* iv = iv_begin; + + uint8_t xor_val = 0xA5; + + while (iv != iv_begin + 0x08) + xor_val ^= *iv++; + + if (!xor_val || xor_val == 0xFF) + xor_val = 0x01; + + while (data != data_end) { + uint8_t temp = *data; + *data++ ^= xor_val; + xor_val = temp; + } + + attrib.set_xor_data(0x00); + } + } +} + +bool f2_header::validate_crc(int32_t not_ignore_crc) { + if (!not_ignore_crc && !attrib.get_crc()) + return true; + + uint8_t crc8; + if (attrib.get_type()) + crc8 = this->crc8; + else { + abort(); + crc8 = 0xDE; + } + + if (crc8 == calc_crc8((uint8_t*)&this->section_size, 0x0C, calc_crc8((uint8_t*)this, 0x11))) { + uint16_t crc16; + if (attrib.get_type()) + crc16 = this->crc16; + else { + abort(); + crc16 = 0xDEAD; + } + + if (crc16 == calc_crc16()) + return true; + } + return false; +} + +void f2_header::write(stream& s) { if (s.check_null()) return; - h->length = extended ? 0x40 : 0x20; - s.write(h, h->length); + s.write(this, get_length()); } -void f2_header_write_end_of_container(stream& s, uint32_t depth) { - if (s.check_null()) - return; +// CRC8 Polynomial 0x8D +// 0x813495E0 in PCSB01007 +static uint8_t calc_crc8(uint8_t* data, uint32_t size, uint8_t seed) { + static const uint8_t crc8_table_small[] = { + 0x00, 0x8D, 0x97, 0x1A, 0xA3, 0x2E, 0x34, 0xB9, + 0xCB, 0x46, 0x5C, 0xD1, 0x68, 0xE5, 0xFF, 0x72, + }; - f2_header h = {}; - h.signature = reverse_endianness_uint32_t('EOFC'); - h.length = 0x20; - h.depth = depth; - h.use_section_size = true; - f2_header_write(s, &h, false); + uint8_t crc = seed; + uint8_t* data_end = data + size; + while (data != data_end) { + crc ^= *data++; + crc = crc8_table_small[crc >> 0x04] ^ (crc << 0x04); + crc = crc8_table_small[crc >> 0x04] ^ (crc << 0x04); + } + return crc; } + +// CRC16-CCITT +// 0x81349476 in PCSB01007 +static uint16_t calc_crc16_ccitt(uint8_t* data, uint32_t size, uint16_t seed) { + static const uint16_t crc16_ccitt_table_small[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + }; + + uint16_t crc = seed; + uint8_t* data_end = data + size; + while (data != data_end) { + crc ^= (uint16_t)*data++ << 0x08; + crc = crc16_ccitt_table_small[crc >> 0x0C] ^ (crc << 0x04); + crc = crc16_ccitt_table_small[crc >> 0x0C] ^ (crc << 0x04); + } + return crc; +} + diff --git a/src/KKdLib/f2/header.hpp b/src/KKdLib/f2/header.hpp index 56744998..9f90de7d 100644 --- a/src/KKdLib/f2/header.hpp +++ b/src/KKdLib/f2/header.hpp @@ -8,32 +8,179 @@ #include "../default.hpp" #include "../io/stream.hpp" +#define F2_HEADER_BASE_ALIGNMENT (0x10U) +#define F2_HEADER_DEFAULT_LENGTH (0x20U) +#define F2_HEADER_EXTENDED_LENGTH (0x40U) + +struct f2_header_attrib_member { +friend struct f2_header; +friend union f2_header_attrib; +private: + uint32_t unk0 : 3; + uint32_t align : 1; + uint32_t unk1 : 5; + uint32_t aes : 1; + uint32_t gzip : 1; + uint32_t unk2 : 6; + uint32_t xor_data : 2; + uint32_t crc : 1; + uint32_t unk3 : 7; + uint32_t big_endian : 1; + uint32_t type : 4; +}; + +union f2_header_attrib { + f2_header_attrib_member m; + uint32_t w; + + inline bool get_aes() const { + return !!m.aes; + } + + inline bool get_align() const { + return !!m.align; + } + + inline bool get_big_endian() const { + return !!m.big_endian; + } + + inline bool get_crc() const { + return !!m.crc; + } + + inline bool get_gzip() const { + return !!m.gzip; + } + + inline uint32_t get_type() const { + return m.type; + } + + inline uint32_t get_xor_data() const { + return m.xor_data; + } + + inline void set_aes(bool value) { + m.aes = value ? 0x01 : 0x00; + } + + inline void set_align(bool value) { + m.align = value ? 0x01 : 0x00; + } + + inline void set_big_endian(bool value) { + m.big_endian = value ? 0x01 : 0x00; + } + + inline void set_crc(bool value) { + m.crc = value ? 0x01 : 0x00; + } + + inline void set_gzip(bool value) { + m.gzip = value ? 0x01 : 0x00; + } + + inline void set_type(uint32_t value) { + m.type = value; + } + + inline void set_xor_data(uint32_t value) { + m.xor_data = value; + } +}; + struct f2_header { union { char signature_char[0x04]; // 0x00 uint32_t signature; // 0x00 }; +private: uint32_t data_size; // 0x04 uint32_t length; // 0x08 - union { // 0x0C - struct { - uint32_t flags0 : 27; - uint32_t use_big_endian : 1; - uint32_t use_section_size : 1; - uint32_t flags1 : 3; - }; - uint32_t flags; - }; - uint32_t depth; // 0x10 +public: + f2_header_attrib attrib; // 0x0C + uint8_t depth; // 0x10 + uint8_t crc8; // 0x11 + uint16_t crc16; // 0x12 +private: uint32_t section_size; // 0x14 +public: uint32_t version; // 0x18 - uint32_t unknown0; // 0x1C + uint32_t custom; // 0x1C uint32_t murmurhash; // 0x20 uint32_t unknown1[3]; // 0x24 uint32_t inner_signature; // 0x30 uint32_t unknown2[3]; // 0x34 -}; -extern void f2_header_read(stream& s, f2_header* h); -extern void f2_header_write(stream& s, f2_header* h, bool extended); -extern void f2_header_write_end_of_container(stream& s, uint32_t depth); \ No newline at end of file + f2_header(); + f2_header(uint32_t signature, uint32_t size = 0, uint32_t depth = 0, bool align = false); + + void apply_xor(); + void calc_crc(); + uint16_t calc_crc16() const; + void read(stream& s); + void remove_xor(); + bool validate_crc(int32_t not_ignore_crc = 0); + void write(stream& s); + + inline uint32_t get_data_size() const { + if (attrib.get_type() < 0x02) + return data_size; + else + return F2_HEADER_BASE_ALIGNMENT * data_size; + } + + inline uint32_t get_length() const { + if (attrib.get_type() < 0x02) + return length; + else + return F2_HEADER_BASE_ALIGNMENT * length; + } + + inline uint32_t get_raw_data_size() const { + return data_size; + } + + inline uint8_t* get_section_data() const { + if (get_section_size()) + return (uint8_t*)this + get_length(); + return 0; + } + + inline uint32_t get_section_size() const { + if (!attrib.get_type()) + return data_size; + else if (attrib.get_type() == 0x01) + return section_size; + else + return F2_HEADER_BASE_ALIGNMENT * section_size; + } + + inline void set_data_size(uint32_t value, bool align = false) { + if (attrib.get_type() < 0x02) + data_size = value; + else if (!(value & 0x0F) || !align) + data_size = value / F2_HEADER_BASE_ALIGNMENT; + else + abort(); + } + + inline void set_length(uint32_t value) { + if (attrib.get_type() < 0x02) + length = value; + else + length = value / F2_HEADER_BASE_ALIGNMENT; + } + + inline void set_section_size(uint32_t value, bool align = false) { + if (attrib.get_type()) { + if (attrib.get_type() < 0x02) + section_size = value; + else if (!(section_size & 0x0F) || !align) + section_size = value / F2_HEADER_BASE_ALIGNMENT; + else + abort(); + } + } +}; diff --git a/src/KKdLib/f2/struct.cpp b/src/KKdLib/f2/struct.cpp index b28191f3..f564785b 100644 --- a/src/KKdLib/f2/struct.cpp +++ b/src/KKdLib/f2/struct.cpp @@ -15,7 +15,7 @@ static void f2_struct_get_length(f2_struct* s, bool shift_x); static void f2_struct_write_pof(stream& s, pof* pof, uint32_t depth, bool shift_x); static void f2_struct_write_enrs(stream& s, enrs* enrs, uint32_t depth); -f2_struct::f2_struct() : header() { +f2_struct::f2_struct() { } @@ -34,7 +34,7 @@ void f2_struct::read(const char* path) { divafile::decrypt(s, ms); f2_header h; - f2_header_read(ms, &h); + h.read(ms); f2_struct_read_data(ms, this, &h); } } @@ -50,7 +50,7 @@ void f2_struct::read(const wchar_t* path) { divafile::decrypt(s, ms); f2_header h; - f2_header_read(ms, &h); + h.read(ms); f2_struct_read_data(ms, this, &h); } } @@ -66,7 +66,7 @@ void f2_struct::read(const void* data, size_t size) { divafile::decrypt(s, ms); f2_header h; - f2_header_read(ms, &h); + h.read(ms); f2_struct_read_data(ms, this, &h); } } @@ -79,7 +79,7 @@ void f2_struct::read(stream& s) { divafile::decrypt(s, ms); f2_header h; - f2_header_read(ms, &h); + h.read(ms); f2_struct_read_data(ms, this, &h); } @@ -113,7 +113,7 @@ void f2_struct::write(void** data, size_t* size, bool use_depth, bool shift_x) { f2_struct_get_length(this, shift_x); memory_stream s; - s.open(0, header.data_size + 0x40ULL); + s.open(0, header.get_data_size() + (size_t)F2_HEADER_EXTENDED_LENGTH); f2_struct_write_inner(s, this, 0, use_depth, shift_x); s.copy(data, size); @@ -125,43 +125,41 @@ void f2_struct::write(stream& s, bool use_depth, bool shift_x) { f2_struct_get_length(this, shift_x); f2_struct_write_inner(s, this, 0, use_depth, shift_x); - } static void f2_struct_get_length(f2_struct* s, bool shift_x) { - bool has_pof = s->pof.vec.size() > 0 ? true : false; - bool has_enrs = s->enrs.vec.size() > 0 ? true : false; - bool has_sub_structs = s->sub_structs.size() > 0 ? true : false; + bool has_pof = !!s->pof.vec.size(); + bool has_enrs = !!s->enrs.vec.size(); + bool has_sub_structs = !!s->sub_structs.size(); - s->header.section_size = (uint32_t)s->data.size(); + if (!s->header.attrib.get_type() && (has_pof || has_enrs || has_sub_structs)) + s->header.attrib.set_type(0x01); - uint32_t l = s->header.section_size; - if (has_enrs) { - uint32_t len = s->enrs.length(); - l += 0x20 + align_val(len, 0x10); - } + s->header.set_section_size((uint32_t)s->data.size()); + + uint32_t l = s->header.get_section_size(); + if (has_enrs) + l += F2_HEADER_DEFAULT_LENGTH + align_val(s->enrs.length(), 0x10); if (has_pof) { s->pof.shift_x = shift_x; - uint32_t len = s->pof.length(); - l += 0x20 + align_val(len, 0x10); + l += F2_HEADER_DEFAULT_LENGTH + align_val(s->pof.length(), 0x10); } if (has_sub_structs) { for (f2_struct& i : s->sub_structs) { f2_struct_get_length(&i, shift_x); - l += i.header.data_size; - l += i.header.length; + l += i.header.get_data_size(); + l += i.header.get_length(); } - l += 0x20; + l += F2_HEADER_DEFAULT_LENGTH; } - s->header.data_size = l; + s->header.set_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; + uint32_t l = h->get_section_size(); st->header = *h; if (l) { st->data.resize(l); @@ -169,13 +167,13 @@ static void f2_struct_read_data(stream& s, f2_struct* st, f2_header* h) { } uint32_t sig; - size_t length = (size_t)h->data_size - l; + size_t length = (size_t)h->get_data_size() - l; size_t position = 0; while (length > position) { - f2_header_read(s, h); + h->read(s); sig = reverse_endianness_uint32_t(h->signature); - l = h->use_section_size ? h->section_size : h->data_size; - position += (size_t)h->length + l; + l = h->get_section_size(); + position += (size_t)h->get_length() + l; if (sig == 'EOFC') break; else if (sig == 'ENRS') { @@ -197,12 +195,12 @@ 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) { - bool has_pof = st->pof.vec.size() > 0 ? true : false; - bool has_enrs = st->enrs.vec.size() > 0 ? true : false; - bool has_sub_structs = st->sub_structs.size() > 0 ? true : false; + bool has_pof = !!st->pof.vec.size(); + bool has_enrs = !!st->enrs.vec.size(); + bool has_sub_structs = !!st->sub_structs.size(); - st->header.depth = use_depth ? depth : 0; - f2_header_write(s, &st->header, st->header.length == 0x40); + st->header.depth = use_depth ? (uint8_t)depth : 0; + st->header.write(s); if (st->data.size()) s.write(st->data.data(), st->data.size()); if (has_enrs) @@ -212,33 +210,22 @@ static void f2_struct_write_inner(stream& s, f2_struct* st, uint32_t depth, bool if (has_sub_structs) { for (f2_struct& i : st->sub_structs) f2_struct_write_inner(s, &i, depth + 1, use_depth, shift_x); - f2_header_write_end_of_container(s, use_depth ? depth + 1 : 0); + + f2_header('EOFC', 0, use_depth ? depth + 1 : 0).write(s); + } + + if (!depth) { + f2_header('EOFC', 0).write(s); } - if (!depth) - f2_header_write_end_of_container(s, 0); } static void f2_struct_write_pof(stream& s, pof* pof, uint32_t depth, bool shift_x) { pof->shift_x = shift_x; - size_t len = pof->length(); - f2_header h = {}; - 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); + f2_header(shift_x ? 'POF1' : 'POF0', (uint32_t)align_val(pof->length(), 0x10), depth).write(s); pof->write(s); } static void f2_struct_write_enrs(stream& s, enrs* enrs, uint32_t depth) { - size_t len = enrs->length(); - f2_header h = {}; - 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); + f2_header('ENRS', (uint32_t)align_val(enrs->length(), 0x10), depth).write(s); enrs->write(s); } diff --git a/src/KKdLib/hash.cpp b/src/KKdLib/hash.cpp index bc1c43fb..283c4b78 100644 --- a/src/KKdLib/hash.cpp +++ b/src/KKdLib/hash.cpp @@ -52,7 +52,7 @@ const uint32_t hash_murmurhash_empty = 0x0CAD3078; // "NULL" string const uint32_t hash_murmurhash_null = 0x5A009B23; // Empty string -const uint32_t hash_crc16_ccitt_empty = 0xFFFF; +const uint16_t hash_crc16_ccitt_empty = 0xFFFF; // FNV 1a 64-bit Modified // 0x1403B04D0 in SBZV_7.10 diff --git a/src/KKdLib/hash.hpp b/src/KKdLib/hash.hpp index f340125a..b6021524 100644 --- a/src/KKdLib/hash.hpp +++ b/src/KKdLib/hash.hpp @@ -15,7 +15,7 @@ extern const uint32_t hash_murmurhash_empty; // "NULL" string extern const uint32_t hash_murmurhash_null; // Empty string -extern const uint32_t hash_crc16_ccitt_empty; +extern const uint16_t hash_crc16_ccitt_empty; extern uint64_t hash_fnv1a64m(const void* data, size_t size, bool make_upper = false); extern uint32_t hash_murmurhash(const void* data, size_t size, @@ -60,7 +60,7 @@ inline uint16_t hash_utf8_crc16_ccitt(const char* data, bool make_upper = false) inline uint16_t hash_utf16_crc16_ccitt(const wchar_t* data, bool make_upper = false) { char* temp = utf16_to_utf8(data); - uint32_t hash = hash_crc16_ccitt(temp, utf8_length(temp), make_upper); + uint16_t hash = hash_crc16_ccitt(temp, utf8_length(temp), make_upper); free_def(temp); return hash; } diff --git a/src/KKdLib/mot.cpp b/src/KKdLib/mot.cpp index 4045b3bc..640a89fd 100644 --- a/src/KKdLib/mot.cpp +++ b/src/KKdLib/mot.cpp @@ -580,8 +580,8 @@ static void mot_modern_read_inner(mot_set* ms, prj::shared_ptrdata); - s_oskn.big_endian = oskn->header.use_big_endian; + s_oskn.big_endian = oskn->header.attrib.get_big_endian(); s_oskn_ptr = &s_oskn; } if (oidx) { s_oidx.open(oidx->data); - s_oidx.big_endian = oidx->header.use_big_endian; + s_oidx.big_endian = oidx->header.attrib.get_big_endian(); s_oidx_ptr = &s_oidx; } if (ovtx) { s_ovtx.open(ovtx->data); - s_ovtx.big_endian = ovtx->header.use_big_endian; + s_ovtx.big_endian = ovtx->header.attrib.get_big_endian(); s_ovtx_ptr = &s_ovtx; } obj* obj = set->obj_data[omdl_index]; memory_stream s_omdl; s_omdl.open(i.data); - s_omdl.big_endian = i.header.use_big_endian; + s_omdl.big_endian = i.header.attrib.get_big_endian(); obj_modern_read_model(obj, alloc, - s_omdl, 0, i.header.length, is_x, s_oidx_ptr, s_ovtx_ptr); + s_omdl, 0, i.header.get_length(), is_x, s_oidx_ptr, s_ovtx_ptr); s_omdl.close(); if (s_oskn_ptr) obj->skin = obj_modern_read_skin(alloc, - *s_oskn_ptr, 0, oskn->header.length, is_x); + *s_oskn_ptr, 0, oskn->header.get_length(), is_x); omdl_index++; } @@ -4284,10 +4284,8 @@ static void obj_set_modern_write_inner(obj_set* set, stream& s) { s_oskn.copy(oskn->data); s_oskn.close(); - oskn->header.signature = reverse_endianness_uint32_t('OSKN'); - oskn->header.length = 0x20; - oskn->header.use_big_endian = big_endian; - oskn->header.use_section_size = true; + new (&oskn->header) f2_header('OSKN'); + oskn->header.attrib.set_big_endian(big_endian); } obj_modern_write_model(obj, s_omdl, 0, is_x, omdl); @@ -4296,10 +4294,8 @@ static void obj_set_modern_write_inner(obj_set* set, stream& s) { s_omdl.copy(omdl->data); s_omdl.close(); - omdl->header.signature = reverse_endianness_uint32_t('OMDL'); - omdl->header.length = 0x20; - omdl->header.use_big_endian = big_endian; - omdl->header.use_section_size = true; + new (&omdl->header) f2_header('OMDL'); + omdl->header.attrib.set_big_endian(big_endian); } s_mosd.align_write(0x10); @@ -4309,10 +4305,8 @@ static void obj_set_modern_write_inner(obj_set* set, stream& s) { st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('MOSD'); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('MOSD'); + st.header.attrib.set_big_endian(big_endian); st.write(s, true, set->is_x); } @@ -4943,19 +4937,15 @@ static void obj_modern_write_model(obj* obj, stream& s, s_oidx.copy(oidx->data); s_oidx.close(); - oidx->header.signature = reverse_endianness_uint32_t('OIDX'); - oidx->header.length = 0x20; - oidx->header.use_big_endian = big_endian; - oidx->header.use_section_size = true; + new (&oidx->header) f2_header('OIDX'); + oidx->header.attrib.set_big_endian(big_endian); s_ovtx.align_write(0x10); s_ovtx.copy(ovtx->data); s_ovtx.close(); - ovtx->header.signature = reverse_endianness_uint32_t('OVTX'); - ovtx->header.length = 0x20; - ovtx->header.use_big_endian = big_endian; - ovtx->header.use_section_size = true; + new (&ovtx->header) f2_header('OVTX'); + ovtx->header.attrib.set_big_endian(big_endian); } static void obj_modern_read_model_mesh(obj_mesh* mesh, diff --git a/src/KKdLib/post_process_table/dof.cpp b/src/KKdLib/post_process_table/dof.cpp index 12aef3e2..e4180373 100644 --- a/src/KKdLib/post_process_table/dof.cpp +++ b/src/KKdLib/post_process_table/dof.cpp @@ -33,8 +33,8 @@ void dof::read(const char* path) { if (st.header.signature == reverse_endianness_uint32_t('DOFT')) { memory_stream s_doft; s_doft.open(st.data); - s_doft.big_endian = st.header.use_big_endian; - dof_read_inner(this, s_doft, st.header.length); + s_doft.big_endian = st.header.attrib.get_big_endian(); + dof_read_inner(this, s_doft, st.header.get_length()); } } free_def(path_dft); @@ -51,8 +51,8 @@ void dof::read(const wchar_t* path) { if (st.header.signature == reverse_endianness_uint32_t('DOFT')) { memory_stream s_doft; s_doft.open(st.data); - s_doft.big_endian = st.header.use_big_endian; - dof_read_inner(this, s_doft, st.header.length); + s_doft.big_endian = st.header.attrib.get_big_endian(); + dof_read_inner(this, s_doft, st.header.get_length()); } } free_def(path_dex); @@ -67,8 +67,8 @@ void dof::read(const void* data, size_t size) { if (st.header.signature == reverse_endianness_uint32_t('DOFT')) { memory_stream s_doft; s_doft.open(st.data); - s_doft.big_endian = st.header.use_big_endian; - dof_read_inner(this, s_doft, st.header.length); + s_doft.big_endian = st.header.attrib.get_big_endian(); + dof_read_inner(this, s_doft, st.header.get_length()); } } @@ -253,10 +253,9 @@ static void dof_write_inner(dof* d, stream& s) { st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('DOFT'); - st.header.length = 0x40; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('DOFT'); + st.header.set_length(F2_HEADER_EXTENDED_LENGTH); + st.header.attrib.set_big_endian(big_endian); st.header.murmurhash = murmurhash; st.header.inner_signature = 0x03; diff --git a/src/KKdLib/pv_exp.cpp b/src/KKdLib/pv_exp.cpp index 8308e921..ccfcde97 100644 --- a/src/KKdLib/pv_exp.cpp +++ b/src/KKdLib/pv_exp.cpp @@ -115,8 +115,8 @@ void pv_exp::unpack_file(prj::shared_ptr alloc, const void if (st.header.signature == reverse_endianness_uint32_t('EXPC')) { memory_stream s_expc; s_expc.open(st.data); - s_expc.big_endian = st.header.use_big_endian; - pv_exp_modern_read_inner(this, alloc, s_expc, st.header.length); + s_expc.big_endian = st.header.attrib.get_big_endian(); + pv_exp_modern_read_inner(this, alloc, s_expc, st.header.get_length()); } } } @@ -530,10 +530,8 @@ static void pv_exp_modern_write_inner(pv_exp* exp, stream& s) { s_expc.copy(st.data); s_expc.close(); - st.header.signature = reverse_endianness_uint32_t('EXPC'); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('EXPC'); + st.header.attrib.set_big_endian(big_endian); st.write(s, true, exp->is_x); } diff --git a/src/KKdLib/pvpp.cpp b/src/KKdLib/pvpp.cpp index dced7ab6..ce5919e4 100644 --- a/src/KKdLib/pvpp.cpp +++ b/src/KKdLib/pvpp.cpp @@ -324,7 +324,7 @@ static void pvpp_read_inner(pvpp* pp, stream& s) { return; } - bool big_endian = st.header.use_big_endian; + bool big_endian = st.header.attrib.get_big_endian(); memory_stream s_pvpp; s_pvpp.open(st.data); diff --git a/src/KKdLib/pvsr.cpp b/src/KKdLib/pvsr.cpp index 45cce6f1..bc0d5c15 100644 --- a/src/KKdLib/pvsr.cpp +++ b/src/KKdLib/pvsr.cpp @@ -205,7 +205,7 @@ static void pvsr_read_inner(pvsr* sr, stream& s) { return; } - bool big_endian = st.header.use_big_endian; + bool big_endian = st.header.attrib.get_big_endian(); memory_stream s_pvsr; s_pvsr.open(st.data); diff --git a/src/KKdLib/spr.cpp b/src/KKdLib/spr.cpp index 2aa98421..16a86c97 100644 --- a/src/KKdLib/spr.cpp +++ b/src/KKdLib/spr.cpp @@ -272,8 +272,8 @@ static void spr_set_modern_read_inner(spr_set* ss, if (st.header.signature != reverse_endianness_uint32_t('SPRC') || !st.data.size()) return; - uint32_t header_length = st.header.length; - bool big_endian = st.header.use_big_endian; + uint32_t header_length = st.header.get_length(); + bool big_endian = st.header.attrib.get_big_endian(); bool is_x = st.pof.shift_x; memory_stream s_sprc; @@ -342,7 +342,7 @@ static void spr_set_modern_read_inner(spr_set* ss, } s_sprc.close(); - texofs = st.header.data_size + 0x20; + texofs = st.header.get_data_size() + F2_HEADER_DEFAULT_LENGTH; ss->txp = new txp_set; ss->txp->unpack_file_modern((const void*)((size_t)data + texofs), size - texofs, 'TXPC'); @@ -376,10 +376,8 @@ static void spr_set_modern_write_inner(spr_set* ss, void** data, size_t* size) { st.enrs = e; st.pof = pof; - st.header.signature = reverse_endianness_uint32_t('SPRC'); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header('SPRC'); + st.header.attrib.set_big_endian(big_endian); st.write(data, size, true, is_x); } diff --git a/src/KKdLib/txp.cpp b/src/KKdLib/txp.cpp index 62154ce3..88fe7e50 100644 --- a/src/KKdLib/txp.cpp +++ b/src/KKdLib/txp.cpp @@ -259,10 +259,8 @@ bool txp_set::pack_file_modern(void** data, size_t* size, bool big_endian, uint3 produce_enrs(&st.enrs); - st.header.signature = reverse_endianness_uint32_t(signature); - st.header.length = 0x20; - st.header.use_big_endian = big_endian; - st.header.use_section_size = true; + new (&st.header) f2_header(signature); + st.header.attrib.set_big_endian(big_endian); st.write(data, size, true, false); return true; } @@ -424,7 +422,7 @@ bool txp_set::unpack_file_modern(const void* data, size_t size, uint32_t signatu f2_struct st; st.read(data, size); if (st.header.signature == reverse_endianness_uint32_t(signature)) - ret = unpack_file(st.data.data(), st.header.use_big_endian); + ret = unpack_file(st.data.data(), st.header.attrib.get_big_endian()); return ret; } diff --git a/src/ReDIVA/main.cpp b/src/ReDIVA/main.cpp index 5f148563..bc569d32 100644 --- a/src/ReDIVA/main.cpp +++ b/src/ReDIVA/main.cpp @@ -771,15 +771,14 @@ void compile_all_shaders(bool debug) { } } -/* -void decrypt_x_save_data() { - uint8_t key[] = { +/*bool decrypt_x_save_data() { + static const uint8_t savedata_key[] = { 0xA4, 0xB7, 0x31, 0xD0, 0x33, 0xFB, 0x4A, 0x63, 0x9D, 0xD2, 0x46, 0xA5, 0x05, 0xCD, 0x4B, 0xE5, 0xF2, 0x10, 0xEE, 0x05, 0xC3, 0x56, 0x45, 0x3A, 0xAF, 0x22, 0x5C, 0x88, 0xA0, 0x9F, 0xB6, 0x8A, }; aes256_ctx aes; - aes256_init_ctx(&aes, key); + aes256_init_ctx(&aes, savedata_key); file_stream ifs; ifs.open("SECURE.BIN", "rb"); @@ -790,60 +789,73 @@ void decrypt_x_save_data() { ifs.read(data.data(), data.size()); ifs.close(); - struct savedata_header { - uint32_t signature; - uint32_t data_size; - uint32_t length; - uint32_t flags; - uint8_t unk10; - uint8_t crc8; - uint16_t crc16; - uint32_t section_size; - uint32_t unk18; - uint32_t unk1C; - uint8_t data[]; - }; + f2_header* head = (f2_header*)data.data(); - savedata_header* head = (savedata_header*)data.data(); - - uint8_t* a1 = data.data(); - uint8_t* v5 = a1 + head->length; - uint8_t* v8 = a1; - uint8_t* v9 = v5 + head->section_size; - - uint8_t v10 = 0xA5; - while (v8 != a1 + 8) - v10 ^= *v8++; - - if (!v10 || v10 == 0xFF) - v10 = 1; - - while (v5 != v9) { - uint8_t v12 = *v5; - *v5 ^= v10; - v10 = v12; - v5++; - } - - aes256_ecb_decrypt_buffer(&aes, data.data() + head->length, data.size() - head->length); - - file_stream ofs; - ofs.open("SECURE.BIN_DEC", "wb"); - ofs.write(data.data(), data.size()); - ofs.close(); + bool reset_flags = head->attrib.get_gzip() || head->attrib.get_xor_data(); void* dst = 0; - size_t dst_len = head->unk1C; - deflate::decompress(data.data() + head->length, data.size() - head->length, - &dst, &dst_len, deflate::MODE_GZIP); + size_t dst_len = 0; - file_stream ufs; - ufs.open("SECURE.BIN_DEC_DEFLATE", "wb"); - ufs.write(dst, dst_len); - ufs.close(); + if (head->attrib.get_crc()) { + if (!head->validate_crc()) + return false; + + if (reset_flags) { + head->attrib.set_crc(false); + head->crc8 = 0x00; + head->crc16 = 0x00; + } + } + + if (head->attrib.get_xor_data()) + head->remove_xor(); + + if (head->attrib.get_aes()) { + uint8_t* section_data = head->get_section_data(); + uint32_t section_size = head->get_section_size(); + if (section_data && section_size == align_val(section_size, 0x20)) { + aes256_ecb_decrypt_buffer(&aes, section_data, section_size); + head->attrib.set_aes(false); + } + } + + if (head->attrib.get_gzip()) { + uint8_t* section_data = head->get_section_data(); + uint32_t section_size = head->get_section_size(); + if (!head->custom || !section_data || !section_size) + return false; + + dst = 0; + dst_len = head->custom; + if (deflate::decompress(section_data, section_size, &dst, &dst_len, deflate::MODE_GZIP) < 0 + || !dst_len || dst_len < head->custom) { + if (dst) + free(dst); + return false; + } + + if (reset_flags) + head->attrib.set_gzip(false); + } + else { + dst = malloc(head->custom); + if (dst) { + dst_len = head->custom; + memset(dst, 0, head->custom); + memcpy(dst, head->get_section_data(), min_def(head->custom, head->get_section_size())); + } + } + + if (dst && dst_len) { + file_stream ofs; + ofs.open("SECURE.BIN_DEC", "wb"); + ofs.write(dst, dst_len); + ofs.close(); + } if (dst) free(dst); + return true; }*/ /*void process_edit_dsc(const char* path, const char* file,