mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-15 01:43:25 +00:00
Add mmp extractor.
This commit is contained in:
parent
c13dede2e8
commit
0a67413c4b
6 changed files with 218 additions and 40 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8a5126cd1a2769780bd4e05c18d553f2bcb60f56
|
Subproject commit 8fbdd4aba7438c7d3eace1308476597460d0aeed
|
||||||
|
|
@ -10,3 +10,6 @@ target_link_libraries(obj_extractor DatabaseManager)
|
||||||
|
|
||||||
file(GLOB script2txt_src "script2txt/*")
|
file(GLOB script2txt_src "script2txt/*")
|
||||||
add_executable(script2txt ${script2txt_src})
|
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
57
src/mmp_extractor/mmp.cpp
Normal 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
60
src/mmp_extractor/mmp.h
Normal 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);
|
||||||
|
};
|
||||||
57
src/mmp_extractor/mmp_extractor.cpp
Normal file
57
src/mmp_extractor/mmp_extractor.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,7 @@ using namespace std;
|
||||||
|
|
||||||
struct storage
|
struct storage
|
||||||
{
|
{
|
||||||
|
string name;
|
||||||
Objects objects;
|
Objects objects;
|
||||||
MechGroups mgs;
|
MechGroups mgs;
|
||||||
MapGoods mg;
|
MapGoods mg;
|
||||||
|
|
@ -43,6 +44,7 @@ struct storage
|
||||||
storage read_mmo(string fn)
|
storage read_mmo(string fn)
|
||||||
{
|
{
|
||||||
storage s;
|
storage s;
|
||||||
|
s.name = fn;
|
||||||
FILE *f = fopen(fn.c_str(), "rb");
|
FILE *f = fopen(fn.c_str(), "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return s;
|
return s;
|
||||||
|
|
@ -69,7 +71,30 @@ void write_mmo(string db, const storage &s)
|
||||||
auto storage = initStorage(db);
|
auto storage = initStorage(db);
|
||||||
storage->load();
|
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)
|
for (auto &seg : s.objects.segments)
|
||||||
{
|
{
|
||||||
|
|
@ -78,7 +103,6 @@ void write_mmo(string db, const storage &s)
|
||||||
SegmentObjects<Shell> *segment = (SegmentObjects<Shell> *)seg;
|
SegmentObjects<Shell> *segment = (SegmentObjects<Shell> *)seg;
|
||||||
set<string> objs;
|
set<string> objs;
|
||||||
std::map<string, int> bld_ids;
|
std::map<string, int> bld_ids;
|
||||||
std::map<string, int> coord_ids;
|
|
||||||
for (auto &object : segment->objects)
|
for (auto &object : segment->objects)
|
||||||
objs.insert(object.name1);
|
objs.insert(object.name1);
|
||||||
for (auto &o : objs)
|
for (auto &o : objs)
|
||||||
|
|
@ -101,24 +125,13 @@ void write_mmo(string db, const storage &s)
|
||||||
MapBuilding mb;
|
MapBuilding mb;
|
||||||
mb.text_id = object.name2;
|
mb.text_id = object.name2;
|
||||||
mb.building = storage->buildings[bld_ids[object.name1]];
|
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)
|
mb.map = this_map;
|
||||||
{
|
mb.x = object.position.x * 100.0;
|
||||||
Coordinate c;
|
mb.y = object.position.y * 100.0;
|
||||||
c.x = object.position.x;
|
mb.z = object.position.z * 100.0;
|
||||||
c.y = object.position.y;
|
mb.yaw = atan2(object.m_rotate_z[1].x, object.m_rotate_z[0].x);
|
||||||
c.z = object.position.z;
|
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));
|
||||||
return *p.second.get() == c;
|
mb.roll = atan2(object.m_rotate_z[2].y, object.m_rotate_z[2].z);
|
||||||
});
|
|
||||||
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;
|
|
||||||
auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const decltype(Storage::mapBuildings)::value_type &p)
|
auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const decltype(Storage::mapBuildings)::value_type &p)
|
||||||
{
|
{
|
||||||
return *p.second.get() == mb;
|
return *p.second.get() == mb;
|
||||||
|
|
@ -138,7 +151,6 @@ void write_mmo(string db, const storage &s)
|
||||||
SegmentObjects<Surface> *segment = (SegmentObjects<Surface> *)seg;
|
SegmentObjects<Surface> *segment = (SegmentObjects<Surface> *)seg;
|
||||||
set<string> objs;
|
set<string> objs;
|
||||||
std::map<string, int> bld_ids;
|
std::map<string, int> bld_ids;
|
||||||
std::map<string, int> coord_ids;
|
|
||||||
for (auto &object : segment->objects)
|
for (auto &object : segment->objects)
|
||||||
objs.insert(object.name1);
|
objs.insert(object.name1);
|
||||||
for (auto &o : objs)
|
for (auto &o : objs)
|
||||||
|
|
@ -160,25 +172,14 @@ void write_mmo(string db, const storage &s)
|
||||||
{
|
{
|
||||||
detail::MapObject mb;
|
detail::MapObject mb;
|
||||||
//mb.text_id = object.name2;
|
//mb.text_id = object.name2;
|
||||||
|
mb.map = this_map;
|
||||||
mb.object = storage->objects[bld_ids[object.name1]];
|
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)
|
mb.x = object.position.x * 100.0;
|
||||||
{
|
mb.y = object.position.y * 100.0;
|
||||||
Coordinate c;
|
mb.z = object.position.z * 100.0;
|
||||||
c.x = object.position.x;
|
mb.yaw = atan2(object.m_rotate_z[1].x, object.m_rotate_z[0].x);
|
||||||
c.y = object.position.y;
|
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));
|
||||||
c.z = object.position.z;
|
mb.roll = atan2(object.m_rotate_z[2].y, object.m_rotate_z[2].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;
|
|
||||||
auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const decltype(Storage::mapObjects)::value_type &p)
|
auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const decltype(Storage::mapObjects)::value_type &p)
|
||||||
{
|
{
|
||||||
return *p.second.get() == mb;
|
return *p.second.get() == mb;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue