mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-14 17:33:25 +00:00
Initial mmo_extractor2.
This commit is contained in:
parent
8f8a49791a
commit
074c91d7c4
4 changed files with 186 additions and 4 deletions
|
|
@ -86,6 +86,7 @@ struct db2 {
|
|||
tab *tab_{};
|
||||
ind *ind_{};
|
||||
dat *dat_{};
|
||||
int codepage{1251};
|
||||
|
||||
db2() = default;
|
||||
db2(const path &fn) : fn{fn} {
|
||||
|
|
@ -117,14 +118,14 @@ struct db2 {
|
|||
auto fields = tab_->fields();
|
||||
auto values = ind_->values();
|
||||
|
||||
auto calc_fields_size = [](this auto &&f, std::string_view field_name, auto &&n, auto &&v, auto &&...fields) {
|
||||
auto calc_fields_size = [&](this auto &&f, std::string_view field_name, auto &&n, auto &&v, auto &&...fields) {
|
||||
if (field_name == n) {
|
||||
if constexpr (std::same_as<std::decay_t<decltype(v)>, int>) {
|
||||
return sizeof(db2::dat::field_value_base) + sizeof(int);
|
||||
} else if constexpr (std::same_as<std::decay_t<decltype(v)>, float>) {
|
||||
return sizeof(db2::dat::field_value_base) + sizeof(float);
|
||||
} else {
|
||||
auto s = str2str(v, CP_UTF8, 1251);
|
||||
auto s = str2str(v, CP_UTF8, codepage);
|
||||
return sizeof(db2::dat::field_value_base) + s.size() + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -139,7 +140,7 @@ struct db2 {
|
|||
return sizeof(db2::dat::field_value_base) + 1;
|
||||
}
|
||||
};
|
||||
auto write_fields = [](this auto &&f, auto &&p, auto &&field, std::string_view field_name, auto &&n, auto &&v, auto &&...fields) {
|
||||
auto write_fields = [&](this auto &&f, auto &&p, auto &&field, std::string_view field_name, auto &&n, auto &&v, auto &&...fields) {
|
||||
if (field_name == n) {
|
||||
if constexpr (std::same_as<std::decay_t<decltype(v)>, int>) {
|
||||
if (field.type != db2::field_type::integer) {
|
||||
|
|
@ -165,7 +166,7 @@ struct db2 {
|
|||
if (field.type != db2::field_type::string) {
|
||||
throw std::runtime_error{"field type mismatch"};
|
||||
}
|
||||
auto s = str2str(v, CP_UTF8, 1251);
|
||||
auto s = str2str(v, CP_UTF8, codepage);
|
||||
(*(db2::dat::field_value_base *)p).field_id = field.id;
|
||||
(*(db2::dat::field_value_base *)p).size = s.size() + 1;
|
||||
p += sizeof(db2::dat::field_value_base);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ struct stream {
|
|||
memcpy(p, (uint8_t*)&v, sizeof(v));
|
||||
p += sizeof(v);
|
||||
}
|
||||
template <typename T>
|
||||
void read(std::vector<T> &v) {
|
||||
memcpy(v.data(), p, sizeof(T) * v.size());
|
||||
p += sizeof(T) * v.size();
|
||||
}
|
||||
void skip(size_t len) {
|
||||
p += len;
|
||||
}
|
||||
|
|
|
|||
124
src/common/mmo2.h
Normal file
124
src/common/mmo2.h
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#pragma once
|
||||
|
||||
#include "mmap.h"
|
||||
|
||||
struct mmo_storage2 {
|
||||
struct object {
|
||||
uint32_t type;
|
||||
uint32_t size;
|
||||
uint32_t n_objects;
|
||||
};
|
||||
struct mech_group {
|
||||
char name[0x20];
|
||||
char org[0x20];
|
||||
// probably state
|
||||
// alive
|
||||
// dead
|
||||
// in the base
|
||||
// in the other mech cargo
|
||||
uint32_t type;
|
||||
uint32_t n_mechs;
|
||||
char org_ru[0x70];
|
||||
};
|
||||
struct map_good {
|
||||
char name[0x20];
|
||||
char cond[0x40];
|
||||
float buy_price;
|
||||
float sell_price;
|
||||
float unk[8];
|
||||
uint32_t unk1;
|
||||
};
|
||||
|
||||
// our own data
|
||||
struct section {
|
||||
uint32_t offset;
|
||||
};
|
||||
struct {
|
||||
section objects;
|
||||
section mech_groups;
|
||||
section map_goods;
|
||||
section music_and_sounds;
|
||||
} sections;
|
||||
struct map_building {
|
||||
uint32_t offset;
|
||||
std::map<std::string, uint32_t> building_goods;
|
||||
};
|
||||
std::map<std::string, map_building> map_building_goods;
|
||||
|
||||
void load(auto &&fn) {
|
||||
primitives::templates2::mmap_file<uint8_t> f{fn};
|
||||
stream s{f};
|
||||
// objects
|
||||
{
|
||||
sections.objects.offset = s.p - f.p;
|
||||
uint32_t n_segments = s;
|
||||
while (n_segments--) {
|
||||
object o = s;
|
||||
s.skip(o.size);
|
||||
}
|
||||
}
|
||||
// mech_groups
|
||||
{
|
||||
sections.mech_groups.offset = s.p - f.p;
|
||||
uint32_t n_mechs = s;
|
||||
s.skip(0x30);
|
||||
while (n_mechs--) {
|
||||
mech_group o = s;
|
||||
|
||||
switch (o.type) {
|
||||
case 0:
|
||||
case 1: {
|
||||
uint32_t unk0 = s; // road id?
|
||||
float unk1 = s; // height?
|
||||
} break;
|
||||
case 2: {
|
||||
std::vector<uint32_t> t; // current path?
|
||||
uint32_t len = s;
|
||||
t.resize(len);
|
||||
s.read(t);
|
||||
} break;
|
||||
case 3: // 3 = free mechanoids only?
|
||||
case 4: {
|
||||
uint32_t t = s; // other mech id?
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
while (o.n_mechs--) {
|
||||
struct mech {
|
||||
char name[0x20];
|
||||
};
|
||||
mech m = s;
|
||||
}
|
||||
bool hidden = s;
|
||||
}
|
||||
}
|
||||
// map goods
|
||||
{
|
||||
sections.map_goods.offset = s.p - f.p;
|
||||
uint32_t size = s;
|
||||
uint32_t unk2 = s;
|
||||
float unk3 = s;
|
||||
uint32_t n_buildings = s;
|
||||
while (n_buildings--) {
|
||||
struct bld {
|
||||
char name[0x20];
|
||||
};
|
||||
bld b = s;
|
||||
map_building_goods[b.name].offset = s.p - f.p;
|
||||
uint32_t n_goods = s;
|
||||
while (n_goods--) {
|
||||
map_good g = s;
|
||||
map_building_goods[b.name].building_goods[g.name] = s.p - f.p;
|
||||
}
|
||||
}
|
||||
}
|
||||
// music & sounds section
|
||||
{
|
||||
sections.music_and_sounds.offset = s.p - f.p;
|
||||
uint32_t size = s;
|
||||
s.skip(size);
|
||||
}
|
||||
}
|
||||
};
|
||||
52
src/mmo_extractor2/mmo_extractor2.cpp
Normal file
52
src/mmo_extractor2/mmo_extractor2.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* AIM mmo_extractor2 (only for aim1)
|
||||
* Copyright (C) 2024 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 "mmo2.h"
|
||||
#include "objects.h"
|
||||
|
||||
#include <primitives/sw/main.h>
|
||||
#include <primitives/sw/cl.h>
|
||||
|
||||
void read_mmo(const path &fn)
|
||||
{
|
||||
mmo_storage2 s;
|
||||
s.load(fn);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cl::opt<path> p(cl::Positional, cl::desc("<.mmo file or directory with .mmo files>"), cl::value_desc("file or directory"), cl::Required);
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv);
|
||||
|
||||
if (fs::is_regular_file(p))
|
||||
read_mmo(p);
|
||||
else if (fs::is_directory(p))
|
||||
{
|
||||
auto files = enumerate_files_like(p, ".*\\.[Mm][Mm][Oo]", false);
|
||||
for (auto &file : files)
|
||||
{
|
||||
std::cerr << "processing: " << file << "\n";
|
||||
read_mmo(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Bad fs object");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue