From 5c88d06a6203f51e129d645ea49339b31a5d0d1a Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Wed, 20 Mar 2019 03:59:12 +0300 Subject: [PATCH] Improve save loader. --- src/common/buffer.h | 10 - src/common/types.cpp | 7 +- src/common/types.h | 7 +- src/mmo_extractor/mmo_extractor.cpp | 4 +- src/mpj_loader/mpj.cpp | 6 +- src/save_loader/save.cpp | 308 ++++++++++++++++++---------- src/save_loader/save.h | 158 +++++++++----- src/save_loader/save_loader.cpp | 7 +- 8 files changed, 322 insertions(+), 185 deletions(-) diff --git a/src/common/buffer.h b/src/common/buffer.h index 279901b..e8541de 100644 --- a/src/common/buffer.h +++ b/src/common/buffer.h @@ -34,16 +34,6 @@ #define READ_PASCAL_STRING(b, var) var = b.read_pascal_string() -#define READ_N_OBJECTS_WITH_LOAD(b, o) \ - do \ - { \ - uint32_t n; \ - READ(b, n); \ - o.resize(n); \ - for (auto &e : o) \ - e.load(b); \ - } while (0) - #define WRITE(b, var) b.write(&var) std::string version(); diff --git a/src/common/types.cpp b/src/common/types.cpp index d1b142c..7cf27e9 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -59,8 +59,11 @@ void weather::load(const buffer &b) switch (smokeType) { case SmokeType::biexp: - READ(b, unk8); - b.skip(-4); + { + float unk81[10]; + READ(b, unk81); + memcpy(unk8, unk81, sizeof(f32) * 10); + } break; default: READ(b, unk8); diff --git a/src/common/types.h b/src/common/types.h index e7fe8f1..c7e64f0 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -23,6 +23,11 @@ #include "buffer.h" #include "color.h" +using u8 = uint8_t; +using u16 = uint16_t; +using u32 = uint32_t; +using f32 = float; + enum class GameType { Aim1, @@ -207,7 +212,7 @@ struct BuildingGoods void load(const buffer &b) { READ_STRING(b, name); - READ_N_OBJECTS_WITH_LOAD(b, goods); + b.read_vector(goods); } }; diff --git a/src/mmo_extractor/mmo_extractor.cpp b/src/mmo_extractor/mmo_extractor.cpp index 8eef60b..8ef7dde 100644 --- a/src/mmo_extractor/mmo_extractor.cpp +++ b/src/mmo_extractor/mmo_extractor.cpp @@ -79,8 +79,8 @@ struct mmo_storage uint32_t len = 0; READ(b, len); - READ_N_OBJECTS_WITH_LOAD(b, organizations); - READ_N_OBJECTS_WITH_LOAD(b, organizationBases); + b.read_vector(organizations); + b.read_vector(organizationBases); prices.load(b); } diff --git a/src/mpj_loader/mpj.cpp b/src/mpj_loader/mpj.cpp index c274b38..409cab1 100644 --- a/src/mpj_loader/mpj.cpp +++ b/src/mpj_loader/mpj.cpp @@ -158,8 +158,8 @@ void map_music::load(const buffer &b) void organizations::load(const buffer &b) { - READ_N_OBJECTS_WITH_LOAD(b, orgs); - READ_N_OBJECTS_WITH_LOAD(b, organizationBases); + b.read_vector(orgs); + b.read_vector(organizationBases); } void gliders_n_goods::load(const buffer &b) @@ -221,4 +221,4 @@ void mpj::load(const path &fn) filename = fn; buffer b(read_file(filename)); load(b); -} \ No newline at end of file +} diff --git a/src/save_loader/save.cpp b/src/save_loader/save.cpp index 38d2342..f41430e 100644 --- a/src/save_loader/save.cpp +++ b/src/save_loader/save.cpp @@ -136,14 +136,14 @@ void radar_segment::load(const buffer &b) void gamedata_segment::load(const buffer &b) { READ(b, unk00); - READ_N_OBJECTS_WITH_LOAD(b, locs); - READ_N_OBJECTS_WITH_LOAD(b, orgs); + b.read_vector(locs); + b.read_vector(orgs); READ(b, unk0); - READ_N_OBJECTS_WITH_LOAD(b, unk1); + b.read_vector(unk1); READ_STRING(b, base_name); READ(b, unk2); READ_PASCAL_STRING(b, user_name); - READ_N_OBJECTS_WITH_LOAD(b, unk3); + b.read_vector(unk3); READ_STRING(b, icon); READ(b, unk4); } @@ -255,50 +255,18 @@ void mech_segment::ammo_count::load(const buffer &b) READ(b, count); } -void mech_segment::mech::load(const buffer &b) +void mech_segment::mech::glider_desc::load(const buffer &b) { - READ(b, id); - READ_STRING(b, name); - READ_STRING(b, name2); - READ_STRING(b, org); - save_changes.rewrite_mech_org(b, org); - READ_STRING(b, building); - - READ(b, flags); - READ(b, unk11); - READ(b, unk12); - READ(b, unk13); - READ(b, unk14); - - auto f = (uint32_t)flags; - if (!(f == 0x01000101 || f == 0x00000001 || f == 0x00000101 || f == 0x01000001)) - { - READ(b, unk16); - return; - } - - READ(b, unk15); - - if (unk14 == 0) - return; - - READ(b, unk15_1); // size? - - b.read_vector(equipments); - - READ(b, unk40); - READ(b, unk4); - // glider.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x1666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x1666); weapon1.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x2666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x2666); weapon2.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x2666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x2666); reactor1.load(b); reactor2.load(b); engine1.load(b); @@ -339,33 +307,34 @@ void mech_segment::mech::load(const buffer &b) } ureactor1.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x3666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x3666); ureactor2.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x3666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x3666); uengine1.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x4666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x4666); uengine2.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x4666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x4666); uenergy_shield.load(b); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x5666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x5666); uarmor.load(b); g_unk4.load(b); READ(b, glider_mask); - if (isPlayer()) - save_changes.rewrite_upgrade_equ_for_player(b, 0x1666); + //if (isPlayer()) + //save_changes.rewrite_upgrade_equ_for_player(b, 0x1666); b.read_vector(ammos3); + // READ(b, money); - if (name == "PLAYER") - save_changes.rewrite_money(b); + //if (name == "PLAYER") + //save_changes.rewrite_money(b); b.read_vector(items); @@ -383,8 +352,8 @@ void mech_segment::mech::load(const buffer &b) READ(b, g_unk7); /*if (g_unk7 != 0) { - b.skip(-4); - return; + b.skip(-4); + return; }*/ READ(b, g_unk8); READ(b, g_unk9); @@ -392,6 +361,43 @@ void mech_segment::mech::load(const buffer &b) } } +void mech_segment::mech::load(const buffer &b) +{ + READ(b, id); + READ_STRING(b, name); + READ_STRING(b, name2); + READ_STRING(b, org); + //save_changes.rewrite_mech_org(b, org); + READ_STRING(b, building); + + READ(b, flags); + READ(b, unk11); + READ(b, unk12); + READ(b, unk13); + READ(b, unk14); + + auto f = (uint32_t)flags; + if (!(f == 0x01000101 || f == 0x00000001 || f == 0x00000101 || f == 0x01000001)) + { + READ(b, unk16); + return; + } + + READ(b, unk15); + + if (unk14 == 0) + return; + + READ(b, unk15_1); // size? + + b.read_vector(equipments); + + READ(b, unk40); + READ(b, unk4); + + gl.load(b); +} + bool mech_segment::mech::isPlayer() const { return name == "PLAYER"; @@ -413,15 +419,18 @@ void groups_segment::mech::load(const buffer &b) void groups_segment::group::load(const buffer &b) { - READ(b, pos); - READ_STRING(b, org); - READ_STRING(b, base); uint32_t unk0; uint16_t unk1; float unk2[3]; + + READ(b, pos); + READ_STRING(b, org); + READ_STRING(b, base); + READ(b, unk0); READ(b, unk1); READ(b, unk2); + b.read_vector(mechs); } @@ -464,42 +473,8 @@ void builds_segment::load(const buffer &b) void orgs_segment::org::load(const buffer &b) { - struct base - { - struct mech - { - std::string name; - - void load(const buffer &b) - { - READ_STRING(b, name); - } - }; - - std::string name; - float unk2; - bool unk3; - uint32_t unk4[2]; - std::vector mechs; - std::string mname; // mech - - void load(const buffer &b) - { - READ_STRING(b, name); - READ(b, unk2); - READ(b, unk3); - READ(b, unk4); - b.read_vector(mechs); - } - }; - - uint32_t unk0[8]; - std::vector bases; - std::string unk1; - READ(b, unk0); - b.read_vector(bases); - READ_STRING(b, unk1); + base.load(b); } void orgs_segment::load(const buffer &b) @@ -530,16 +505,118 @@ void tradeeqp_segment::load(const buffer &b) b.read_vector(blds); } -void objects_segment::base::load(const buffer &b) +void objects_segment::object::load(const buffer &b) { - READ_STRING(b, name); - READ(b, unk0); + READ_STRING(b, owner); + READ(b, type); READ(b, unk1); + READ(b, unk01); + READ(b, coords); + READ(b, len0); // flags? + + switch (type) + { + case 0x10: // ammo (mines etc.) + { + std::string name; + READ_STRING(b, name); + std::string owner; + READ_STRING(b, owner); + b.skip(0x1E); + } + break; + case 0x15: // mech, money, tov + { + std::string what; + u8 unk0; + u32 unk1[2]; + std::string s1; + u32 unk2; + std::string s2; + f32 unk3; + + READ_STRING(b, what); + if (what == "TT_MONEY") + ; + else if (what == "TT_MECHANOID") + ; + else if (what == "TT_RAW_FRAGMENT") + ; + else if (what == "TT_CONTAINER") + ; + else + std::cerr << "unknown object: " << what << "\n"; + + READ(b, unk0); + READ(b, unk1); + READ_STRING(b, s1); + READ(b, unk2); + READ_STRING(b, s2); + READ(b, unk3); + } + break; + case 0x1a: // mech in base + { + float unk3; + u8 unk4; // also flags? 0x47 for in buildings, 0x4f + + float unk5[2][3]; + u32 flags; + float unk10[2]; + + // flags != 1 + float unk100[3]; + u32 len1; + float unk11[4]; + u32 unk111; + + // flags == 1 + std::string unk12; + + READ(b, unk3); + READ(b, unk4); + READ(b, unk5); + READ(b, flags); + READ(b, unk10); + + if (flags == 1) + { + READ_STRING(b, unk12); + } + else + { + READ(b, unk100); + READ(b, len1); + READ(b, unk11); + READ(b, unk111); + } + + std::vector mechs; + uint32_t n; + READ(b, n); + mechs.resize(n); + for (int i = 0; i < n; i++) + READ_STRING(b, mechs[i]); + + // in production? + if (flags == 1) + { + std::string s; + uint32_t n; + READ(b, n); + while (n--) + READ_STRING(b, s); + } + } + break; + default: + throw SW_RUNTIME_ERROR("unknown object in OBJECTS with type " + std::to_string(type)); + } } void objects_segment::load(const buffer &b) { - b.read_vector(bases); + b.read_vector(objects); } void mms_state_segment::load(const buffer &b) @@ -547,10 +624,20 @@ void mms_state_segment::load(const buffer &b) READ_STRING(b, name); } +void mms_c_config_segment::object::load(const buffer &b) +{ + READ(b, unk0); + gl.load(b); +} + void mms_c_config_segment::load(const buffer &b) { - // todo: insert config read from mech - b.read_vector(objects); + while (!b.eof()) + { + object o; + o.load(b); + objects.push_back(o); + } } void mms_world_data_segment::load(const buffer &b) @@ -570,13 +657,14 @@ void segment_desc::load(const buffer &b) READ(b, magic); if (magic != (uint32_t)-2) throw SW_RUNTIME_ERROR("bad magic for segment: " + name); - uint32_t len; - READ(b, len); // length of segment + 4 (sizeof(int) - internal segment length) + + uint32_t len; // length of segment + 4 (sizeof(int) or internal segment length size) + READ(b, len); uint32_t offset; READ(b, offset); uint32_t unk1; READ(b, unk1); - uint32_t len2; + uint32_t len2; // length of segment READ(b, len2); if (len != len2 + sizeof(len2)) throw SW_RUNTIME_ERROR("bad length for segment: " + name); @@ -606,11 +694,11 @@ void segment_desc::load(const buffer &b) // CASE("GROUPS", groups_segment); CASE("ORGDATA", orgdata_segment); CASE("BUILDS", builds_segment); - //CASE("ORGS", orgs_segment); + CASE("ORGS", orgs_segment); CASE("TRADEEQP", tradeeqp_segment); - // CASE("OBJECTS", objects_segment); + CASE("OBJECTS", objects_segment); CASE("MMS_STATE", mms_state_segment); - // CASE("MMS_C_CONFIG", mms_c_config_segment); // (my) clan config + CASE("MMS_C_CONFIG", mms_c_config_segment); // (my) clan config CASE("MMS_WORLD_DATA", mms_world_data_segment); CASE("MAINMECH", mainmech_segment); DEFAULT @@ -620,7 +708,7 @@ void segment_desc::load(const buffer &b) return; } - seg->load(b); + seg->load(buffer(b, len2)); if (b.index() != end) throw SW_RUNTIME_ERROR("bad segment read: " + name); diff --git a/src/save_loader/save.h b/src/save_loader/save.h index 23e50ff..3e32dc7 100644 --- a/src/save_loader/save.h +++ b/src/save_loader/save.h @@ -392,6 +392,58 @@ struct mech_segment : public segment struct mech { + struct glider_desc + { + // glider + // g_unk = glider unknown + + // mask works only for weapons + moddable_equipment glider; + moddable_equipment weapon1; + moddable_equipment weapon2; + moddable_equipment reactor1; + moddable_equipment reactor2; + moddable_equipment engine1; + moddable_equipment engine2; + moddable_equipment energy_shield; + moddable_equipment armor; + + uint32_t g_unk0; + uint32_t g_unk1 = 0; + uint32_t g_unk2; + + std::vector ammos; + std::vector ammos1; + std::vector ammos2; + + uint32_t g_unk3 = 0; + + // mask works for all except uarmor + moddable_equipment2 ureactor1; + moddable_equipment2 ureactor2; + moddable_equipment2 uengine1; + moddable_equipment2 uengine2; + moddable_equipment2 uenergy_shield; + moddable_equipment2 uarmor; + // + moddable_equipment g_unk4; + ModificatorMask glider_mask; + + std::vector ammos3; + + float money; + + std::vector items; + + uint32_t g_unk6[28][3] = { 0 }; + float g_unk7 = 0; + float g_unk8 = 0; + uint32_t g_unk9 = 0; + uint8_t g_unk10 = 0; + + void load(const buffer &b); + }; + uint8_t id; std::string name; std::string name2; @@ -412,51 +464,7 @@ struct mech_segment : public segment float unk40; uint32_t unk4[7]; - // glider - // g_unk = glider unknown - - // mask works only for weapons - moddable_equipment glider; - moddable_equipment weapon1; - moddable_equipment weapon2; - moddable_equipment reactor1; - moddable_equipment reactor2; - moddable_equipment engine1; - moddable_equipment engine2; - moddable_equipment energy_shield; - moddable_equipment armor; - - uint32_t g_unk0; - uint32_t g_unk1 = 0; - uint32_t g_unk2; - - std::vector ammos; - std::vector ammos1; - std::vector ammos2; - - uint32_t g_unk3 = 0; - - // mask works for all except uarmor - moddable_equipment2 ureactor1; - moddable_equipment2 ureactor2; - moddable_equipment2 uengine1; - moddable_equipment2 uengine2; - moddable_equipment2 uenergy_shield; - moddable_equipment2 uarmor; - moddable_equipment g_unk4; - ModificatorMask glider_mask; - - std::vector ammos3; - - float money; - - std::vector items; - - uint32_t g_unk6[28][3] = { 0 }; - float g_unk7 = 0; - float g_unk8 = 0; - uint32_t g_unk9 = 0; - uint8_t g_unk10 = 0; + glider_desc gl; void load(const buffer &b); @@ -540,11 +548,49 @@ struct builds_segment : public segment void load(const buffer &b); }; -// todo struct orgs_segment : public segment { struct org { + struct base + { + struct mech + { + std::string name; + u32 unk0[2]; + std::string org; + u32 unk1; + f32 unk2; + + void load(const buffer &b) + { + READ_STRING(b, name); + READ(b, unk0); + READ_STRING(b, org); + READ(b, unk1); + READ(b, unk2); + } + }; + + std::string name; + float unk2; + u8 unk3; + uint32_t unk4[2]; + std::vector mechs; + + void load(const buffer &b) + { + READ_STRING(b, name); + READ(b, unk2); + READ(b, unk3); + READ(b, unk4); + b.read_vector(mechs); + } + }; + + uint32_t unk0[9]; + base base; + void load(const buffer &b); }; @@ -582,19 +628,21 @@ struct tradeeqp_segment : public segment void load(const buffer &b); }; -// todo struct objects_segment : public segment { - struct base + struct object { - std::string name; - uint32_t unk0[26]; - uint16_t unk1; + std::string owner; // empty for outdoor and outmech + u32 type; + u8 unk1; + u32 unk01; + vector3f coords; + u32 len0; void load(const buffer &b); }; - std::vector bases; + std::vector objects; void load(const buffer &b); }; @@ -607,12 +655,14 @@ struct mms_state_segment : public segment void load(const buffer &b); }; -// todo struct mms_c_config_segment : public segment { struct object { - void load(const buffer &b) {} + u32 unk0[10]; // maybe attach to glider_desc? + mech_segment::mech::glider_desc gl; + + void load(const buffer &b); }; std::vector objects; diff --git a/src/save_loader/save_loader.cpp b/src/save_loader/save_loader.cpp index 5b8253d..e2719c4 100644 --- a/src/save_loader/save_loader.cpp +++ b/src/save_loader/save_loader.cpp @@ -35,8 +35,9 @@ int main(int argc, char *argv[]) cl::ParseCommandLineOptions(argc, argv); //save_changes.mech_org = "ORG_PLAYER"; - save_changes.money = 999999999.0f; - save_changes.upgrade_equ_for_player = true; + + //save_changes.money = 999999999.0f; + //save_changes.upgrade_equ_for_player = true; auto func = [](auto &p) { @@ -46,7 +47,7 @@ int main(int argc, char *argv[]) save s; s.load(f); - writeFile(p.string(), save_changes.out.buf()); + //writeFile(p.string(), save_changes.out.buf()); }; if (fs::is_regular_file(p))