From b5ad31087d0e2d735268672c29eed67db751b8c2 Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Sun, 5 Jul 2015 18:17:43 +0300 Subject: [PATCH] Fix aim2 .mmo format reader. --- src/obj_extractor/obj_extractor.bat | 3 +- src/obj_extractor/obj_extractor.cpp | 25 +++- src/obj_extractor/obj_extractor.py | 14 +- src/obj_extractor/objects.cpp | 2 +- src/obj_extractor/other.h | 198 ++++++++++++++++++++++++++-- 5 files changed, 224 insertions(+), 18 deletions(-) diff --git a/src/obj_extractor/obj_extractor.bat b/src/obj_extractor/obj_extractor.bat index 5d95771..6f54f48 100644 --- a/src/obj_extractor/obj_extractor.bat +++ b/src/obj_extractor/obj_extractor.bat @@ -1 +1,2 @@ -python obj_extractor.py --db "h:\Games\Epic Games\Projects\Polygon4\Mods\db.sqlite" --dir "h:\Games\AIM\data\maps.pak.dir" \ No newline at end of file +python obj_extractor.py --db "h:\Games\Epic Games\Projects\Polygon4\Mods\db.sqlite" --dir "h:\Games\AIM\data\maps.pak.dir" --prefix m1 +python obj_extractor.py --db "h:\Games\Epic Games\Projects\Polygon4\Mods\db.sqlite" --dir "h:\Games\Steam\steamapps\common\AIM2\Data\mmo.pak\DATA\LOCS" --prefix m2 \ No newline at end of file diff --git a/src/obj_extractor/obj_extractor.cpp b/src/obj_extractor/obj_extractor.cpp index 1817e8c..c8587f8 100644 --- a/src/obj_extractor/obj_extractor.cpp +++ b/src/obj_extractor/obj_extractor.cpp @@ -33,6 +33,9 @@ using namespace std; +std::string prefix; +GameType gameType; + struct storage { string name; @@ -41,6 +44,10 @@ struct storage MapGoods mg; MapMusic mm; MapSounds ms; + // aim2 + Organizations orgs; + OrganizationBases orgsBases; + Prices prices; void load(buffer &b) { @@ -51,6 +58,12 @@ struct storage mg.load(b); mm.load(b); ms.load(b); + if (gameType == GameType::Aim2) + { + orgs.load(b); + orgsBases.load(b); + prices.load(b); + } if (!b.eof()) { @@ -87,6 +100,9 @@ void write_mmo(string db, const storage &s) int p = max(p1, p2); string map_name = s.name.substr(p + 1); map_name = map_name.substr(0, map_name.find('.')); + if (!prefix.empty()) + map_name = prefix + "." + map_name; + transform(map_name.begin(), map_name.end(), map_name.begin(), ::tolower); int map_id = 0; for (auto &m : storage->maps) @@ -209,11 +225,18 @@ void write_mmo(string db, const storage &s) int main(int argc, char *argv[]) try { - if (argc != 3) + if (argc != 4) { cout << "Usage:\n" << argv[0] << " db.sqlite file.mmo" << "\n"; return 1; } + prefix = argv[3]; + if (prefix == "m1") + gameType = GameType::Aim1; + else if (prefix == "m2") + gameType = GameType::Aim2; + else + throw std::runtime_error("unknown prefix (game type)"); storage s = read_mmo(argv[2]); write_mmo(argv[1], s); return 0; diff --git a/src/obj_extractor/obj_extractor.py b/src/obj_extractor/obj_extractor.py index 301b751..ff5444c 100644 --- a/src/obj_extractor/obj_extractor.py +++ b/src/obj_extractor/obj_extractor.py @@ -9,17 +9,21 @@ def main(): parser = argparse.ArgumentParser(description='Batch models converter') parser.add_argument('--dir', dest='dir', help='path to directory with maps') parser.add_argument('--db', dest='db', help='path to db') + parser.add_argument('--prefix', dest='prefix', help='prefix') pargs = parser.parse_args() - if pargs.dir: - run(pargs.dir, pargs.db) + if not pargs.prefix: + pargs.prefix = '' -def run(dir, db): + if pargs.dir: + run(pargs.dir, pargs.db, pargs.prefix) + +def run(dir, db, prefix): for file in sorted(os.listdir(dir)): - if os.path.isdir(file) or os.path.splitext(file)[1] != ".mmo": + if os.path.isdir(file) or os.path.splitext(file)[1].lower() != ".mmo": continue print('loading: ' + file) - p = subprocess.Popen(['obj_extractor.exe', db, dir + '/' + file]) + p = subprocess.Popen(['obj_extractor.exe', db, dir + '/' + file, prefix]) p.communicate() if __name__ == '__main__': diff --git a/src/obj_extractor/objects.cpp b/src/obj_extractor/objects.cpp index b49d853..7a07e77 100644 --- a/src/obj_extractor/objects.cpp +++ b/src/obj_extractor/objects.cpp @@ -93,7 +93,7 @@ void Objects::load(buffer &b) auto seg = Segment::create_segment(b); if (!seg) break; - seg->load(b); + seg->load(buffer(b, seg->segment_len)); segments.push_back(seg); } } diff --git a/src/obj_extractor/other.h b/src/obj_extractor/other.h index a21aae5..17c1cd2 100644 --- a/src/obj_extractor/other.h +++ b/src/obj_extractor/other.h @@ -28,10 +28,18 @@ using namespace std; +enum class GameType +{ + Aim1, + Aim2 +}; + +extern GameType gameType; + struct MechGroup { - char unk1[0x20]; - char unk2[0x20]; + char name[0x20]; + char org[0x20]; uint32_t type1; uint32_t len1; char name1[0x70]; @@ -51,8 +59,8 @@ struct MechGroup void load(buffer &b) { - READ(b, unk1); - READ(b, unk2); + READ(b, name); + READ(b, org); READ(b, type1); READ(b, len1); READ(b, name1); @@ -83,6 +91,7 @@ struct MechGroup struct MechGroups { + uint32_t length; uint32_t n; char prefix[0x30]; @@ -90,6 +99,8 @@ struct MechGroups void load(buffer &b) { + if (gameType == GameType::Aim2) + READ(b, length); READ(b, n); READ(b, prefix); @@ -106,15 +117,23 @@ struct Good { char name[0x20]; char unk1[0x40]; + uint32_t unk1_2; float price; float unk2[10]; + float unk2_2[4]; void load(buffer &b) { READ(b, name); - READ(b, unk1); + if (gameType == GameType::Aim1) + READ(b, unk1); + else + READ(b, unk1_2); READ(b, price); - READ(b, unk2); + if (gameType == GameType::Aim1) + READ(b, unk2); + else + READ(b, unk2_2); } }; @@ -141,7 +160,7 @@ struct BuildingGoods struct MapGoods { - uint32_t unk1; + uint32_t length; uint32_t unk2; uint32_t unk3; uint32_t n; @@ -150,9 +169,10 @@ struct MapGoods void load(buffer &b) { - READ(b, unk1); + READ(b, length); READ(b, unk2); - READ(b, unk3); + if (gameType != GameType::Aim2) + READ(b, unk3); READ(b, n); for (int i = 0; i < n; i++) @@ -160,6 +180,8 @@ struct MapGoods BuildingGoods bg; bg.load(b); bgs.push_back(bg); + if (gameType == GameType::Aim2) + READ(b, unk2); } } }; @@ -231,4 +253,160 @@ struct MapSounds sounds.push_back(s); } } -}; \ No newline at end of file +}; + +struct OrganizationConfig +{ + uint32_t n_configs; + vector configs; + + void load(buffer &b) + { + READ(b, n_configs); + configs.resize(n_configs, string(0x20, 0)); + for (int i = 0; i < n_configs; i++) + READ_N(b, configs[i][0], 0x20); + } +}; + +struct Organization +{ + uint32_t unk0; + char name[0x20]; + char unk1[0xE0]; + OrganizationConfig configs[3]; + + void load(buffer &b) + { + READ(b, unk0); + READ(b, name); + READ(b, unk1); + for (auto &c : configs) + c.load(b); + } +}; + +struct Organizations +{ + uint32_t len; + uint32_t n; + vector organizations; + + void load(buffer &b) + { + READ(b, len); + READ(b, n); + for (int i = 0; i < n; i++) + { + Organization s; + s.load(b); + organizations.push_back(s); + } + } +}; + +struct OrganizationBase +{ + char base_name[0x20]; + char org_name[0x20]; + uint32_t unk0; + + void load(buffer &b) + { + READ(b, base_name); + READ(b, org_name); + READ(b, unk0); + } +}; + +struct OrganizationBases +{ + uint32_t n; + vector organizationBases; + + void load(buffer &b) + { + READ(b, n); + for (int i = 0; i < n; i++) + { + OrganizationBase s; + s.load(b); + organizationBases.push_back(s); + } + } +}; + +struct Price +{ + char tov_name[0x20]; + uint32_t unk0; + uint32_t unk1; + float unk2[3]; + + void load(buffer &b) + { + READ(b, tov_name); + READ(b, unk0); + READ(b, unk1); + READ(b, unk2); + } +}; + +struct BuildingPrice +{ + char name[0x20]; + uint32_t n_tov; + vector prices; + + void load(buffer &b) + { + READ(b, name); + READ(b, n_tov); + for (int i = 0; i < n_tov; i++) + { + Price s; + s.load(b); + prices.push_back(s); + } + } +}; + +struct BuildingPrices +{ + uint32_t n_tov; + vector prices; + uint32_t n_bases; + vector buildingPrices; + + void load(buffer &b) + { + READ(b, n_tov); + for (int i = 0; i < n_tov; i++) + { + Price s; + s.load(b); + prices.push_back(s); + } + READ(b, n_bases); + for (int i = 0; i < n_bases; i++) + { + BuildingPrice s; + s.load(b); + buildingPrices.push_back(s); + } + } +}; + +struct Prices +{ + uint32_t len; + uint32_t unk0; + BuildingPrices buildingPrices; + + void load(buffer &b) + { + READ(b, len); + READ(b, unk0); + buildingPrices.load(b); + } +};