From 79e5ed74ebbc482c4e36771fbf891d278e4d4053 Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Sat, 28 Mar 2015 00:48:16 +0300 Subject: [PATCH] Add obj_extractor. --- src/CMakeLists.txt | 5 +- src/obj_extractor/obj_extractor.cpp | 59 +++++++ src/obj_extractor/objects.cpp | 99 ++++++++++++ src/obj_extractor/objects.h | 185 ++++++++++++++++++++++ src/obj_extractor/other.h | 232 ++++++++++++++++++++++++++++ 5 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 src/obj_extractor/obj_extractor.cpp create mode 100644 src/obj_extractor/objects.cpp create mode 100644 src/obj_extractor/objects.h create mode 100644 src/obj_extractor/other.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 490eac9..c908016 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,4 +2,7 @@ file(GLOB unpaker_src "unpaker/*") add_executable(unpaker ${unpaker_src}) file(GLOB db_extractor_src "db_extractor/*") -add_executable(db_extractor ${db_extractor_src}) \ No newline at end of file +add_executable(db_extractor ${db_extractor_src}) + +file(GLOB obj_extractor_src "obj_extractor/*") +add_executable(obj_extractor ${obj_extractor_src}) \ No newline at end of file diff --git a/src/obj_extractor/obj_extractor.cpp b/src/obj_extractor/obj_extractor.cpp new file mode 100644 index 0000000..e0e24d9 --- /dev/null +++ b/src/obj_extractor/obj_extractor.cpp @@ -0,0 +1,59 @@ +/* + * AIM obj_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "objects.h" +#include "other.h" + +void read_mmo(string fn) +{ + FILE *f = fopen(fn.c_str(), "rb"); + if (!f) + return; + Objects objects; + objects.load(f); + MechGroups mgs; + mgs.load(f); + if (feof(f)) + { + // custom maps? + fclose(f); + return; + } + MapGoods mg; + mg.load(f); + MapMusic mm; + mm.load(f); + MapSounds ms; + ms.load(f); + fclose(f); +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + cout << "Usage:\n" << argv[0] << " file.mmo" << "\n"; + return 1; + } + read_mmo(argv[1]); + return 0; +} \ No newline at end of file diff --git a/src/obj_extractor/objects.cpp b/src/obj_extractor/objects.cpp new file mode 100644 index 0000000..64af13f --- /dev/null +++ b/src/obj_extractor/objects.cpp @@ -0,0 +1,99 @@ +/* + * AIM obj_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "objects.h" + +Segment *Segment::create_segment(FILE *f) +{ + SegmentType segment_type; + FREAD(segment_type); + + Segment *segment = 0; + switch (segment_type) + { + case SegmentType::ROAD: + segment = new SegmentObjects; + break; + case SegmentType::BUILDING: + segment = new SegmentObjects; + break; + case SegmentType::SURFACE: + segment = new SegmentObjects; + break; + case SegmentType::STONE: + segment = new SegmentObjects; + break; + case SegmentType::HELPER: + segment = new SegmentObjects; + break; + case SegmentType::SHELL: + segment = new SegmentObjects; + break; + case SegmentType::IMAGE: + segment = new SegmentObjects; + break; + case SegmentType::EXPLOSION: + segment = new SegmentObjects; + break; + case SegmentType::SOUND: + segment = new SegmentObjects; + break; + case SegmentType::MUSIC: + segment = new SegmentObjects; + break; + case SegmentType::ANOMALY: + segment = new SegmentObjects; + break; + case SegmentType::TOWER: + segment = new SegmentObjects; + break; + case SegmentType::BOUNDARY: + segment = new SegmentObjects; + break; + case SegmentType::GOODS: + segment = new SegmentObjects; + break; + case SegmentType::unk1: + segment = new SegmentObjects; + break; + default: + assert(false); + break; + } + if (segment) + { + segment->segment_type = segment_type; + FREAD(segment->segment_len); + FREAD(segment->n_objects); + } + return segment; +} + +void Objects::load(FILE *f) +{ + FREAD(n_segments); + + for (int s = 0; s < n_segments; s++) + { + auto seg = Segment::create_segment(f); + if (!seg) + break; + seg->load(f); + segments.push_back(seg); + } +} diff --git a/src/obj_extractor/objects.h b/src/obj_extractor/objects.h new file mode 100644 index 0000000..1701381 --- /dev/null +++ b/src/obj_extractor/objects.h @@ -0,0 +1,185 @@ +/* + * AIM obj_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include + +#define FREAD(var) fread(&var, 1, sizeof(var), f) +#define FREAD_N(var, n) fread(&var, 1, n, f) + +using namespace std; + +enum class SegmentType : uint32_t +{ + TEXTURE = 0x1, + MODEL, + SURFACE, + STONE, + TREE, + + GLIDER, + HELPER, + ROAD, + WEAPON, + CONFIG, + + SHELL, // (AMMO,BULLET) + IMAGE, + EXPLOSION, + EQUIPMENT, + ORGANIZATION, + + BUILDING, + LAMP, + COVERING, + SOUND, + MUSIC, + + GOODS, + ANOMALY, + TOWER, + BOUNDARY, + SOUND_ZONE, + + unk1 = 0x1b, +}; + +struct Segment +{ + SegmentType segment_type; + uint32_t segment_len; + uint32_t n_objects; + + virtual ~Segment(){} + static Segment *create_segment(FILE *f); + virtual void load(FILE *f) = 0; +}; + +template +struct SegmentObjects : public Segment +{ + vector objects; + + virtual void load(FILE *f) + { + for (int i = 0; i < n_objects; i++) + { + T r; + r.load(f); + objects.push_back(r); + } + } +}; + +struct Common +{ + float unk2[2]; + uint32_t unk3[2]; + float unk4[2]; + uint32_t unk5[2]; + float unk6[8]; + + void load(FILE *f) + { + FREAD(unk2); + FREAD(unk3); + FREAD(unk4); + FREAD(unk5); + FREAD(unk6); + } +}; + +struct MapObject : public Common +{ + char name1[0x20]; + char name2[0x20]; + + void load(FILE *f) + { + Common::load(f); + + FREAD(name1); + FREAD(name2); + } +}; + +struct MapObjectWithArray : public MapObject +{ + uint32_t len; + vector unk7; + + void load(FILE *f) + { + MapObject::load(f); + + FREAD(len); + unk7.resize(len); + for (int i = 0; i < len; i++) + FREAD(unk7[i]); + } +}; + +struct Sound : public Common +{ + uint32_t unk1[11]; + char name1[0x14]; + + void load(FILE *f) + { + Common::load(f); + + FREAD(unk1); + FREAD(name1); + } +}; + +struct Road : public MapObjectWithArray {}; +struct Tower : public MapObjectWithArray {}; + +#define KNOWN_OBJECT(name) \ + struct name : public MapObject {} + +KNOWN_OBJECT(Surface); +KNOWN_OBJECT(Helper); +KNOWN_OBJECT(Shell); +KNOWN_OBJECT(Stone); +KNOWN_OBJECT(Explosion); +KNOWN_OBJECT(Image); +KNOWN_OBJECT(Music); +KNOWN_OBJECT(Anomaly); +KNOWN_OBJECT(Boundary); + +#define UNKNOWN_OBJECT(name) \ + struct name : public MapObject { void load(FILE *f){ int pos = ftell(f); assert(false); } } + +UNKNOWN_OBJECT(Building); +UNKNOWN_OBJECT(Goods); +UNKNOWN_OBJECT(unk1); + +struct Objects +{ + uint32_t n_segments; + vector segments; + + void load(FILE *f); +}; diff --git a/src/obj_extractor/other.h b/src/obj_extractor/other.h new file mode 100644 index 0000000..200f55f --- /dev/null +++ b/src/obj_extractor/other.h @@ -0,0 +1,232 @@ +/* + * AIM obj_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include + +using namespace std; + +struct MechGroup +{ + char unk1[0x20]; + char unk2[0x20]; + uint32_t type1; + uint32_t len1; + char name1[0x70]; + //{3,4 + uint32_t unk30; + //} + //{2 + uint32_t len; + vector unk11; + //} + //{1,0 + uint32_t unk20; + uint32_t unk21; + //} + vector configs; + char unk100; + + void load(FILE *f) + { + FREAD(unk1); + FREAD(unk2); + FREAD(type1); + FREAD(len1); + FREAD(name1); + if (type1 == 3 || type1 == 4) + { + FREAD(unk30); + } + else if (type1 == 2) + { + FREAD(len); + unk11.resize(len); + for (int i = 0; i < len; i++) + FREAD(unk11[i]); + } + else if (type1 == 1 || type1 == 0) + { + FREAD(unk20); + FREAD(unk21); + } + else + assert(false); + configs.resize(len1, string(0x20, 0)); + for (int i = 0; i < len1; i++) + FREAD_N(configs[i][0], 0x20); + FREAD(unk100); + } +}; + +struct MechGroups +{ + uint32_t n; + char prefix[0x30]; + + vector mgs; + + void load(FILE *f) + { + FREAD(n); + FREAD(prefix); + + for (int s = 0; s < n; s++) + { + MechGroup mg; + mg.load(f); + mgs.push_back(mg); + } + } +}; + +struct Good +{ + char name[0x20]; + char unk1[0x40]; + float price; + float unk2[10]; + + void load(FILE *f) + { + FREAD(name); + FREAD(unk1); + FREAD(price); + FREAD(unk2); + } +}; + +struct BuildingGoods +{ + char name[0x20]; + uint32_t n; + + vector goods; + + void load(FILE *f) + { + FREAD(name); + FREAD(n); + + for (int i = 0; i < n; i++) + { + Good g; + g.load(f); + goods.push_back(g); + } + } +}; + +struct MapGoods +{ + uint32_t unk1; + uint32_t unk2; + uint32_t unk3; + uint32_t n; + + vector bgs; + + void load(FILE *f) + { + FREAD(unk1); + FREAD(unk2); + FREAD(unk3); + FREAD(n); + + for (int i = 0; i < n; i++) + { + BuildingGoods bg; + bg.load(f); + bgs.push_back(bg); + } + } +}; + +struct MapMusic +{ + uint32_t unk1; + char name1[0x20]; + char name2[0x20]; + + uint32_t n1; + vector names1; + + uint32_t n2; + vector names2; + + void load(FILE *f) + { + FREAD(unk1); + FREAD(name1); + FREAD(name2); + + FREAD(n1); + for (int i = 0; i < n1; i++) + { + char name[0x20]; + FREAD(name); + names1.push_back(name); + } + + FREAD(n2); + for (int i = 0; i < n2; i++) + { + char name[0x20]; + FREAD(name); + names2.push_back(name); + } + } +}; + +struct MapSound +{ + char name[0x20]; + float unk1[4]; + uint32_t unk2; + float unk3[4]; + + void load(FILE *f) + { + FREAD(name); + FREAD(unk1); + FREAD(unk2); + FREAD(unk3); + } +}; + +struct MapSounds +{ + uint32_t n; + vector sounds; + + void load(FILE *f) + { + FREAD(n); + for (int i = 0; i < n; i++) + { + MapSound s; + s.load(f); + sounds.push_back(s); + } + } +}; \ No newline at end of file