Add mmp extractor.

This commit is contained in:
lzwdgc 2015-06-01 01:30:35 +03:00
parent c13dede2e8
commit 0a67413c4b
6 changed files with 218 additions and 40 deletions

@ -1 +1 @@
Subproject commit 8a5126cd1a2769780bd4e05c18d553f2bcb60f56
Subproject commit 8fbdd4aba7438c7d3eace1308476597460d0aeed

View file

@ -10,3 +10,6 @@ target_link_libraries(obj_extractor DatabaseManager)
file(GLOB script2txt_src "script2txt/*")
add_executable(script2txt ${script2txt_src})
file(GLOB mmp_extractor_src "mmp_extractor/*")
add_executable(mmp_extractor ${mmp_extractor_src})

57
src/mmp_extractor/mmp.cpp Normal file
View file

@ -0,0 +1,57 @@
/*
* AIM mmp_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 <http://www.gnu.org/licenses/>.
*/
#include "mmp.h"
#define FREAD(var) fread(&var, 1, sizeof(var), f)
#define FREAD_N(var, n) fread(&var, 1, n, f)
size_t file_size(FILE *f)
{
auto old = ftell(f);
fseek(f, 0, SEEK_END);
auto sz = ftell(f);
fseek(f, old, SEEK_SET);
return sz;
}
void mmp::load(FILE *f)
{
FREAD(unk1);
FREAD(unk2);
FREAD(width);
FREAD(height);
FREAD(unk3);
FREAD(unk4);
FREAD(unk5);
FREAD(unk6);
FREAD(unk7);
FREAD(unk8);
int n_seg = width / 64 * height / 64;
int sz = n_seg * sizeof(segment);
int fsz = file_size(f);
int off = fsz - sz;
fseek(f, off, SEEK_SET);
segments = vector<segment>(n_seg);
for (int i = 0; i < n_seg; i++)
FREAD(segments[i]);
assert(ftell(f) == fsz);
}

60
src/mmp_extractor/mmp.h Normal file
View file

@ -0,0 +1,60 @@
/*
* AIM mmp_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 <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <iostream>
#include <map>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
struct mmp
{
struct segment
{
uint32_t MagicNumber;
uint32_t MiniLayer1[1089];
uint32_t MiniLayer2[1089];
uint32_t MiniLayer3[1089];
uint32_t MiniLayer4[1089];
float Heightmap[4225];
uint32_t Infomap[4225];
uint32_t Colormap[4225];
uint32_t Shadowmap[4225];
uint32_t Normalmap[4225];
};
uint32_t unk1;
char unk2[0x80];
uint32_t width;
uint32_t height;
uint32_t unk3;
char unk4[0xA0];
uint32_t unk5[7];
char unk6[0xA0];
char unk7[0x1AC];
char unk8[0x1AC];
uint32_t offset; // the beginning of segments
vector<segment> segments;
void load(FILE *f);
};

View file

@ -0,0 +1,57 @@
/*
* AIM mmp_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 <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <stdio.h>
#include <stdint.h>
#include <string>
#include "mmp.h"
using namespace std;
mmp read_mmp(string fn)
{
mmp m;
FILE *f = fopen(fn.c_str(), "rb");
if (!f)
return m;
m.load(f);
fclose(f);
return m;
}
int main(int argc, char *argv[])
{
#ifdef NDEBUG
if (argc != 2)
{
cout << "Usage:\n" << argv[0] << " file.mmp" << "\n";
return 1;
}
read_mmp(argv[1]);
#else
auto arena = read_mmp("h:\\Games\\Ìåõàíîèäû\\data\\maps.pak.dir\\arena.mmp");
auto loc1 = read_mmp("h:\\Games\\Ìåõàíîèäû\\data\\maps.pak.dir\\location1.mmp");
#endif
return 0;
}

View file

@ -33,6 +33,7 @@ using namespace std;
struct storage
{
string name;
Objects objects;
MechGroups mgs;
MapGoods mg;
@ -43,6 +44,7 @@ struct storage
storage read_mmo(string fn)
{
storage s;
s.name = fn;
FILE *f = fopen(fn.c_str(), "rb");
if (!f)
return s;
@ -69,7 +71,30 @@ void write_mmo(string db, const storage &s)
auto storage = initStorage(db);
storage->load();
int map_id = 1;
auto p1 = s.name.rfind('\\');
if (p1 == -1)
p1 = 0;
auto p2 = s.name.rfind('/');
if (p2 == -1)
p2 = 0;
int p = max(p1, p2);
string map_name = s.name.substr(p + 1);
map_name = map_name.substr(0, map_name.find('.'));
int map_id = 0;
for (auto &m : storage->maps)
{
if (m.second->text_id == map_name)
{
map_id = m.first;
break;
}
}
if (map_id == 0)
return;
auto this_map = storage->maps[map_id];
for (auto &seg : s.objects.segments)
{
@ -78,7 +103,6 @@ void write_mmo(string db, const storage &s)
SegmentObjects<Shell> *segment = (SegmentObjects<Shell> *)seg;
set<string> objs;
std::map<string, int> bld_ids;
std::map<string, int> coord_ids;
for (auto &object : segment->objects)
objs.insert(object.name1);
for (auto &o : objs)
@ -101,24 +125,13 @@ void write_mmo(string db, const storage &s)
MapBuilding mb;
mb.text_id = object.name2;
mb.building = storage->buildings[bld_ids[object.name1]];
auto iter = find_if(storage->coordinates.begin(), storage->coordinates.end(), [&](const decltype(Storage::coordinates)::value_type &p)
{
Coordinate c;
c.x = object.position.x;
c.y = object.position.y;
c.z = object.position.z;
return *p.second.get() == c;
});
if (iter == storage->coordinates.end())
{
auto c = storage->addCoordinate();
c->x = object.position.x;
c->y = object.position.y;
c->z = object.position.z;
mb.coordinate = c;
}
else
mb.coordinate = iter->second;
mb.map = this_map;
mb.x = object.position.x * 100.0;
mb.y = object.position.y * 100.0;
mb.z = object.position.z * 100.0;
mb.yaw = atan2(object.m_rotate_z[1].x, object.m_rotate_z[0].x);
mb.pitch = atan2(-object.m_rotate_z[2].x, sqrt(object.m_rotate_z[2].y * object.m_rotate_z[2].y + object.m_rotate_z[2].z * object.m_rotate_z[2].z));
mb.roll = atan2(object.m_rotate_z[2].y, object.m_rotate_z[2].z);
auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const decltype(Storage::mapBuildings)::value_type &p)
{
return *p.second.get() == mb;
@ -138,7 +151,6 @@ void write_mmo(string db, const storage &s)
SegmentObjects<Surface> *segment = (SegmentObjects<Surface> *)seg;
set<string> objs;
std::map<string, int> bld_ids;
std::map<string, int> coord_ids;
for (auto &object : segment->objects)
objs.insert(object.name1);
for (auto &o : objs)
@ -160,25 +172,14 @@ void write_mmo(string db, const storage &s)
{
detail::MapObject mb;
//mb.text_id = object.name2;
mb.map = this_map;
mb.object = storage->objects[bld_ids[object.name1]];
auto iter = find_if(storage->coordinates.begin(), storage->coordinates.end(), [&](const decltype(Storage::coordinates)::value_type &p)
{
Coordinate c;
c.x = object.position.x;
c.y = object.position.y;
c.z = object.position.z;
return *p.second.get() == c;
});
if (iter == storage->coordinates.end())
{
auto c = storage->addCoordinate();
c->x = object.position.x;
c->y = object.position.y;
c->z = object.position.z;
mb.coordinate = c;
}
else
mb.coordinate = iter->second;
mb.x = object.position.x * 100.0;
mb.y = object.position.y * 100.0;
mb.z = object.position.z * 100.0;
mb.yaw = atan2(object.m_rotate_z[1].x, object.m_rotate_z[0].x);
mb.pitch = atan2(-object.m_rotate_z[2].x, sqrt(object.m_rotate_z[2].y * object.m_rotate_z[2].y + object.m_rotate_z[2].z * object.m_rotate_z[2].z));
mb.roll = atan2(object.m_rotate_z[2].y, object.m_rotate_z[2].z);
auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const decltype(Storage::mapObjects)::value_type &p)
{
return *p.second.get() == mb;