Update mmo, mmp.

This commit is contained in:
lzwdgc 2018-01-27 03:40:30 +03:00
parent 539c5dde83
commit aad50f9160
11 changed files with 202 additions and 108 deletions

View file

@ -5,3 +5,4 @@ local_settings:
- pvt.egorpugin.primitives.filesystem: master
- pvt.egorpugin.primitives.executor: master
- pvt.cppan.demo.unicode.icu.i18n: "*"
- pvt.cppan.demo.taywee.args: "*"

View file

@ -35,6 +35,7 @@ add_executable(mmo_extractor ${mmo_extractor_src})
target_link_libraries(mmo_extractor
common
pvt.lzwdgc.polygon4.data_manager.data_manager
pvt.cppan.demo.taywee.args
)
file(GLOB mmp_extractor_src "mmp_extractor/*")

View file

@ -65,8 +65,8 @@ Segment *Segment::create_segment(const buffer &b)
case ObjectType::unk0:
segment = new SegmentObjects<unk0>;
break;
case ObjectType::unk1:
segment = new SegmentObjects<unk1>;
case ObjectType::TANK:
segment = new SegmentObjects<Tank>;
break;
default:
assert(false);

View file

@ -59,7 +59,7 @@ enum class ObjectType : uint32_t
BOUNDARY = 23,
SOUND_ZONE = 24,
unk1 = 27,
TANK = 27,
};
struct Segment
@ -160,12 +160,12 @@ KNOWN_OBJECT(Image);
KNOWN_OBJECT(Anomaly);
KNOWN_OBJECT(Tower);
KNOWN_OBJECT(SoundZone);
KNOWN_OBJECT(Tank);
#define UNKNOWN_OBJECT(name) \
struct name : public MapObject { void load(const buffer &b){ int pos = b.index(); assert(false); } }
UNKNOWN_OBJECT(unk0);
UNKNOWN_OBJECT(unk1);
struct Objects
{

View file

@ -33,6 +33,7 @@
#include <Polygon4/DataManager/Storage.h>
#include <Polygon4/DataManager/Types.h>
#include <primitives/filesystem.h>
#include <args.hxx>
#include <buffer.h>
#include <types.h>
@ -52,7 +53,6 @@ struct mmo_storage
Objects objects;
MechGroups mechGroups;
MapGoods mapGoods;
uint32_t unk0 = 0;
MapMusic mapMusic;
MapSounds mapSounds;
// aim2
@ -60,6 +60,8 @@ struct mmo_storage
OrganizationBases orgsBases;
Prices prices;
uint32_t unk0 = 0;
void load(const buffer &b)
{
objects.load(b);
@ -268,39 +270,62 @@ void write_mmo(Storage *storage, const mmo_storage &s)
int main(int argc, char *argv[])
try
{
if (argc != 4)
{
std::cout << "Usage:\n" << argv[0] << " db.sqlite {file.mmo,mmo_dir} prefix" << "\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)");
args::ArgumentParser parser("mmo extractor");
args::HelpFlag help(parser, "help", "Display this help menu", { 'h', "help" });
args::Flag m2(parser, "m2", "m2 .mmo file", { "m2" });
args::Flag print_mechanoids(parser, "print_mechanoids", "Print mechanoids", { "print_mechanoids" });
args::ValueFlag<std::string> db_path(parser, "db_path", "Database file", {'d', "db"});
args::Positional<std::string> file_path(parser, "file or directory", ".mmo file or directory with .mmo files");
parser.Prog(argv[0]);
auto storage = initStorage(argv[1]);
storage->load();
parser.ParseCLI(argc, argv);
path p = argv[2];
if (fs::is_regular_file(p))
write_mmo(storage.get(), read_mmo(p));
else if (fs::is_directory(p))
const path p = file_path.Get();
gameType = m2 ? GameType::Aim2 : GameType::Aim1;
/*{
std::cerr << parser;
}*/
auto action = [&p](auto f)
{
auto files = enumerate_files_like(p, ".*\\.mmo", false);
for (auto &f : files)
if (fs::is_regular_file(p))
f(p, read_mmo(p));
else if (fs::is_directory(p))
{
std::cout << "processing: " << f << "\n";
write_mmo(storage.get(), read_mmo(f));
auto files = enumerate_files_like(p, ".*\\.[Mm][Mm][Oo]", false);
for (auto &file : files)
{
std::cerr << "processing: " << file << "\n";
f(file, read_mmo(file));
}
}
else
throw std::runtime_error("Bad fs object");
};
if (print_mechanoids)
{
action([](const path &file, const mmo_storage &m)
{
for (auto &mg : m.mechGroups.mechGroups)
{
std::cout << mg.name;
std::cout << " " << mg.org;
std::cout << " " << mg.mechanoids.size();
std::cout << " " << file.filename().stem().string();
std::cout << "\n";
}
});
}
else
throw std::runtime_error("Bad fs object");
if (inserted_all)
storage->save();
{
auto storage = initStorage(db_path.Get());
storage->load();
action([&storage](const path &, const auto &m) {write_mmo(storage.get(), m); });
if (inserted_all)
storage->save();
}
return 0;
}

View file

@ -27,63 +27,86 @@
#include <buffer.h>
#include <types.h>
#include <variant>
struct MechGroup
{
std::string name;
std::string org;
uint32_t type1 = 0;
uint32_t len1 = 0;
char name1[0x70];
//{3,4
uint32_t unk30 = 0;
//}
//{2
uint32_t len = 0;
std::vector<uint32_t> unk11;
//}
//{1,0
uint32_t unk20 = 0;
uint32_t unk21 = 0;
//}
std::vector<std::string> configs;
char unk100;
std::vector<std::string> mechanoids;
// used only in m1.loc1 and for sinigr
// probably an old field
std::string org_ru;
struct unk_type01
{
uint32_t unk0 = 0;
float unk1 = 0;
};
std::variant<unk_type01, std::vector<uint32_t>, uint32_t> type_data;
bool hidden;
void load(const buffer &b)
{
READ_STRING(b, name);
READ_STRING(b, org);
READ(b, type1);
READ(b, len1);
READ(b, name1);
if (type1 == 3 || type1 == 4)
uint32_t type = 0;
READ(b, type);
uint32_t number_of_mechanoids = 0;
READ(b, number_of_mechanoids);
READ_STRING_N(b, org_ru, 0x70);
switch (type)
{
READ(b, unk30);
case 0:
case 1:
{
unk_type01 t;
READ(b, t.unk0);
READ(b, t.unk1);
type_data = t;
}
else if (type1 == 2)
break;
case 2:
{
std::vector<uint32_t> t;
uint32_t len = 0;
READ(b, len);
unk11.resize(len);
t.resize(len);
for (int i = 0; i < len; i++)
READ(b, unk11[i]);
READ(b, t[i]);
type_data = t;
}
else if (type1 == 1 || type1 == 0)
break;
case 3: // 3 = free mechanoids only?
case 4:
{
READ(b, unk20);
READ(b, unk21);
uint32_t t;
READ(b, t);
type_data = t;
}
else
break;
default:
assert(false);
configs.resize(len1, std::string(0x20, 0));
for (int i = 0; i < len1; i++)
READ_N(b, configs[i][0], 0x20);
READ(b, unk100);
}
for (int i = 0; i < number_of_mechanoids; i++)
{
std::string t;
READ_STRING_N(b, t, 0x20);
mechanoids.push_back(t);
}
READ(b, hidden);
}
};
struct MechGroups
{
char prefix[0x30];
std::vector<MechGroup> mechGroups;
char unk0[0x30]; // prefix?
void load(const buffer &b)
{
@ -94,7 +117,7 @@ struct MechGroups
}
uint32_t n = 0;
READ(b, n);
READ(b, prefix);
READ(b, unk0);
for (int s = 0; s < n; s++)
{

View file

@ -84,10 +84,14 @@ void header::load(const buffer &b)
void segment::load(const buffer &b)
{
uint32_t offset;
READ(b, offset);
READ(b, desc);
buffer b2(b);
b2.seek(desc.offset);
b2.seek(offset);
READ(b2, d);
b2.seek(offset);
READ(b2, d2);
}
void mmp::load(const buffer &b)
@ -107,7 +111,7 @@ void mmp::load(const buffer &b)
// check whether all segments were read
if (segments.size())
{
auto len = segments[0].desc.offset + segments.size() * sizeof(segment::data);
auto len = b.index() + segments.size() * sizeof(segment::data);
if (len != b.size())
throw std::logic_error("Some segments were not read");
}
@ -167,6 +171,7 @@ void mmp::process()
// merge
heightmap = decltype(heightmap)(h.width, h.length);
//heightmap_segmented = decltype(heightmap)(segment::len, h.length);
texmap = decltype(texmap)(h.width, h.length);
texmap_colored = decltype(texmap_colored)(h.width, h.length);
colormap = decltype(colormap)(h.width, h.length);
@ -213,11 +218,12 @@ void mmp::process()
alpha_maps.erase(0);
scale16 = 0xffff / (h_max - h_min);
const int unreal_koef = 51200;
const int unreal_koef = 51300;
const int aim_koef = 10;
const double diff = h_max - h_min;
scale = aim_koef / (unreal_koef / diff);
scale = aim_koef * diff / unreal_koef;
// make heightmap
for (auto &s : segments)
{
int y1 = s.desc.min.y / 10;
@ -281,7 +287,7 @@ void mmp::writeTexturesList()
void mmp::writeHeightMap()
{
auto fn = filename + ".heightmap16.raw";
auto fn = filename + ".heightmap16.r16";
FILE *f = fopen(fn.c_str(), "wb");
if (f == nullptr)
return;
@ -289,6 +295,16 @@ void mmp::writeHeightMap()
fclose(f);
}
void mmp::writeHeightMapSegmented()
{
/*auto fn = filename + ".heightmap.r16s";
FILE *f = fopen(fn.c_str(), "wb");
if (f == nullptr)
return;
fwrite(&heightmap_segmented(0, 0), heightmap_segmented.size() * sizeof(decltype(heightmap_segmented)::type), 1, f);
fclose(f);*/
}
void mmp::writeTextureMap()
{
auto fn = filename + ".texmap.bmp";

View file

@ -81,49 +81,52 @@ struct segment
static const int len = 65;
static const int size = len * len;
static const int mini_len = 33;
static const int mini_size = mini_len * mini_len;
struct description
{
uint32_t offset;
vector3 min;
vector3 max;
float unk0[5];
uint32_t unk1[7];
};
struct info
{
uint16_t render_flags;
uint16_t texture_index;
uint16_t getTexture() const { return texture_index & 0x0fff; } // first 4 bits are unk (flags?)
};
struct shadow
{
uint8_t unk[4];
};
struct normal
{
int16_t x;
int16_t y;
};
struct flagged_heightmap
{
uint16_t height;
uint16_t flag;
};
struct mini_lod
{
flagged_heightmap Heightmap[mini_size];
color Colormap[mini_size];
uint32_t unk0[mini_size]; // shadowmap?
normal unk1[mini_size]; // normals?
};
struct data
{
struct info
{
uint16_t render_flags;
uint16_t texture_index;
uint16_t getTexture() const { return texture_index & 0x0fff; } // first 4 bits are unk (flags?)
};
struct shadow
{
uint8_t unk[4];
};
struct normal
{
int16_t x;
int16_t y;
};
struct mini_lod
{
static const int len = 33;
static const int size = len * len;
struct flagged_heightmap
{
uint16_t height;
uint16_t flag;
};
flagged_heightmap Heightmap[size];
color Colormap[size];
uint32_t unk0[size]; // shadowmap?
normal unk1[size]; // normals?
};
uint32_t MagicNumber;
mini_lod mlod;
Height Heightmap[size];
@ -133,8 +136,28 @@ struct segment
normal Normalmap[size];
};
struct mini_lod2
{
flagged_heightmap Heightmap[mini_len][mini_len];
color Colormap[mini_len][mini_len];
uint32_t unk0[mini_len][mini_len]; // shadowmap?
normal unk1[mini_len][mini_len]; // normals?
};
struct data2
{
uint32_t MagicNumber;
mini_lod2 mlod;
Height Heightmap[len][len];
info Infomap[len][len];
color Colormap[len][len];
shadow Shadowmap[len][len];
normal Normalmap[len][len];
};
description desc;
data d;
data2 d2;
void load(const buffer &b);
};
@ -158,6 +181,7 @@ struct mmp
double scale16 = 0;
double scale = 0;
mat<uint16_t> heightmap;
//mat<uint16_t> heightmap_segmented;
mat<uint32_t> texmap;
mat<uint32_t> texmap_colored;
mat<uint32_t> colormap;
@ -171,6 +195,7 @@ struct mmp
void writeFileInfo();
void writeTexturesList();
void writeHeightMap();
void writeHeightMapSegmented();
void writeTextureMap();
void writeTextureAlphaMaps();
void writeTextureMapColored();

View file

@ -45,12 +45,13 @@ try
m.load(p.string());
m.process();
m.writeFileInfo();
m.writeTexturesList();
//m.writeTexturesList();
m.writeHeightMap();
m.writeTextureMap();
//m.writeHeightMapSegmented();
/*m.writeTextureMap();
m.writeTextureAlphaMaps();
m.writeTextureMapColored();
m.writeColorMap();
m.writeColorMap();*/
};
path p = argv[1];

View file

@ -256,6 +256,8 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager,
int fx_id = 0;
for (auto &b : model.blocks)
{
// b.h.name == "SHAPE" - collision object
//
if (b.isEngineFx())
{

View file

@ -306,4 +306,4 @@ int decode_f4(char *input, int size, char *output, int segment_offset)
goto LABEL_9;
}
return result;
}
}