Fix aim2 .mmo format reader.

This commit is contained in:
lzwdgc 2015-07-05 18:17:43 +03:00
parent a5989276a7
commit b5ad31087d
5 changed files with 224 additions and 18 deletions

View file

@ -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"
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

View file

@ -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;

View file

@ -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__':

View file

@ -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);
}
}

View file

@ -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);
}
}
};
};
struct OrganizationConfig
{
uint32_t n_configs;
vector<string> 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<Organization> 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<OrganizationBase> 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<Price> 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<Price> prices;
uint32_t n_bases;
vector<BuildingPrice> 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);
}
};