Add common library with some helpers.

This commit is contained in:
lzwdgc 2015-06-29 18:50:30 +03:00
parent ef6cd29915
commit fb6aa75845
17 changed files with 483 additions and 384 deletions

2
.gitmodules vendored
View file

@ -1,3 +1,3 @@
[submodule "dep/dbmgr"] [submodule "dep/dbmgr"]
path = dep/dbmgr path = dep/dbmgr
url = https://github.com/aimrebirth/DatabaseManager.git url = git@github.com:aimrebirth/DatabaseManager.git

View file

@ -21,6 +21,8 @@ endif(MSVC)
include_directories(dep/dbmgr/include) include_directories(dep/dbmgr/include)
add_subdirectory(dep/dbmgr) add_subdirectory(dep/dbmgr)
set_target_properties(sqlite3 PROPERTIES FOLDER Extern)
set_target_properties(DatabaseManager PROPERTIES FOLDER Extern)
add_custom_target(version ALL add_custom_target(version ALL
COMMAND git rev-list HEAD --count > ${CMAKE_CURRENT_BINARY_DIR}/version.h_ COMMAND git rev-list HEAD --count > ${CMAKE_CURRENT_BINARY_DIR}/version.h_

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

View file

@ -1,12 +1,15 @@
include_directories(common)
file(GLOB unpaker_src "unpaker/*") file(GLOB unpaker_src "unpaker/*")
add_executable(unpaker ${unpaker_src}) add_executable(unpaker ${unpaker_src})
file(GLOB db_extractor_src "db_extractor/*") file(GLOB db_extractor_src "db_extractor/*")
add_executable(db_extractor ${db_extractor_src}) add_executable(db_extractor ${db_extractor_src})
target_link_libraries(db_extractor common)
file(GLOB obj_extractor_src "obj_extractor/*") file(GLOB obj_extractor_src "obj_extractor/*")
add_executable(obj_extractor ${obj_extractor_src}) add_executable(obj_extractor ${obj_extractor_src})
target_link_libraries(obj_extractor DatabaseManager) target_link_libraries(obj_extractor DatabaseManager common)
file(GLOB script2txt_src "script2txt/*") file(GLOB script2txt_src "script2txt/*")
add_executable(script2txt ${script2txt_src}) add_executable(script2txt ${script2txt_src})
@ -16,3 +19,6 @@ add_executable(mmp_extractor ${mmp_extractor_src})
file(GLOB mod_converter_src "mod_converter/*") file(GLOB mod_converter_src "mod_converter/*")
add_executable(mod_converter ${mod_converter_src}) add_executable(mod_converter ${mod_converter_src})
target_link_libraries(mod_converter common)
add_subdirectory(common)

View file

@ -0,0 +1,2 @@
file(GLOB common_src "*.h" "*.cpp")
add_library(common ${common_src})

127
src/common/common.cpp Normal file
View file

@ -0,0 +1,127 @@
/*
* AIM tools
* 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 "common.h"
#include <stdio.h>
const int build_version =
#include <version.h.in>
;
std::string version()
{
using namespace std;
string s;
s = to_string(0) + "." +
to_string(1) + "." +
to_string(0) + "." +
to_string(build_version);
return s;
}
std::vector<uint8_t> readFile(const std::string &fn)
{
FILE *f = fopen(fn.c_str(), "rb");
if (!f)
throw std::runtime_error("Cannot open file " + fn);
fseek(f, 0, SEEK_END);
auto sz = ftell(f);
fseek(f, 0, SEEK_SET);
std::vector<uint8_t> buf(sz);
fread(buf.data(), 1, sz, f);
fclose(f);
return buf;
}
buffer::buffer()
{
}
buffer::buffer(const std::vector<uint8_t> &buf, uint32_t data_offset)
: buf(new std::vector<uint8_t>(buf)), data_offset(data_offset)
{
skip(0);
size = buf.size();
}
buffer::buffer(buffer &rhs, uint32_t size)
: buf(rhs.buf)
{
index = rhs.index;
data_offset = rhs.data_offset;
ptr = rhs.ptr;
this->size = index + size;
rhs.skip(size);
}
buffer::buffer(buffer &rhs, uint32_t size, uint32_t offset)
: buf(rhs.buf)
{
index = offset;
data_offset = offset;
ptr = (uint8_t *)buf->data() + index;
this->size = index + size;
}
uint32_t buffer::read(void *dst, uint32_t size, bool nothrow)
{
if (!buf)
throw std::logic_error("buffer: not initialized");
if (index >= this->size)
{
if (nothrow)
return 0;
throw std::logic_error("buffer: out of range");
}
if (index + size > this->size)
size = this->size - index;
memcpy(dst, buf->data() + index, size);
skip(size);
return size;
}
void buffer::skip(int n)
{
if (!buf)
throw std::logic_error("buffer: not initialized");
index += n;
data_offset += n;
ptr = (uint8_t *)buf->data() + index;
}
bool buffer::check(int index) const
{
return this->index == index;
}
bool buffer::eof() const
{
return check(this->size);
}
uint32_t buffer::getIndex() const
{
return index;
}
uint32_t buffer::getSize() const
{
return this->size;
}

55
src/common/common.h Normal file
View file

@ -0,0 +1,55 @@
/*
* AIM tools
* 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/>.
*/
#pragma once
#include <memory>
#include <stdint.h>
#include <string>
#include <vector>
#define READ(b, var) b.read(&var, sizeof(var))
#define READ_NOTHROW(b, var) b.read(&var, sizeof(var), true)
#define READ_N(b, var, sz) b.read(&var, sz)
std::string version();
std::vector<uint8_t> readFile(const std::string &fn);
class buffer
{
public:
buffer();
buffer(const std::vector<uint8_t> &buf, uint32_t data_offset = 0);
buffer(buffer &rhs, uint32_t size);
buffer(buffer &rhs, uint32_t size, uint32_t offset);
uint32_t read(void *dst, uint32_t size, bool nothrow = false);
void skip(int n);
bool eof() const;
bool check(int index) const;
uint32_t getIndex() const;
uint32_t getSize() const;
private:
std::shared_ptr<const std::vector<uint8_t>> buf;
uint32_t index = 0;
uint8_t *ptr = 0;
uint32_t data_offset = 0;
uint32_t size = 0;
};

View file

@ -18,9 +18,7 @@
#include "db.h" #include "db.h"
#define FREAD(var) fread(&var, 1, sizeof(var), f) #include <common.h>
#define SREAD(var) s.read(&var, sizeof(var))
#define SREAD_N(var, sz) s.read(&var, sz)
string getSqlType(uint32_t ft) string getSqlType(uint32_t ft)
{ {
@ -38,37 +36,37 @@ string getSqlType(uint32_t ft)
return ""; return "";
} }
void table::load(FILE *f) void table::load(buffer &b)
{ {
FREAD(id); READ(b, id);
FREAD(name); READ(b, name);
FREAD(unk1); READ(b, unk1);
FREAD(unk2); READ(b, unk2);
FREAD(unk3); READ(b, unk3);
FREAD(unk4); READ(b, unk4);
} }
void field::load(FILE *f) void field::load(buffer &b)
{ {
FREAD(table_id); READ(b, table_id);
FREAD(id); READ(b, id);
FREAD(name); READ(b, name);
FREAD(unk1); READ(b, unk1);
FREAD(unk2); READ(b, unk2);
FREAD(unk3); READ(b, unk3);
FREAD(type); READ(b, type);
} }
void tab::load(FILE *f) void tab::load(buffer &b)
{ {
FREAD(number_of_tables); READ(b, number_of_tables);
FREAD(number_of_fields); READ(b, number_of_fields);
auto n = number_of_tables; auto n = number_of_tables;
while (n--) while (n--)
{ {
table t; table t;
t.load(f); t.load(b);
tables[t.id] = t; tables[t.id] = t;
} }
@ -76,39 +74,35 @@ void tab::load(FILE *f)
while (n--) while (n--)
{ {
field t; field t;
t.load(f); t.load(b);
fields[t.id] = t; fields[t.id] = t;
} }
} }
void value::load_index(FILE *f) void value::load_index(buffer &b)
{ {
FREAD(table_id); READ(b, table_id);
FREAD(name); READ(b, name);
FREAD(unk1); READ(b, unk1);
FREAD(unk2); READ(b, unk2);
FREAD(unk3); READ(b, unk3);
FREAD(offset); READ(b, offset);
FREAD(data_size); READ(b, data_size);
buf.resize(data_size);
} }
void value::load_data(FILE *f) void value::load_data(buffer &b)
{ {
fseek(f, offset, SEEK_SET); data = buffer(b, data_size, offset);
fread(buf.data(), buf.size(), 1, f);
} }
void value::extract_fields(const tab &tab) void value::extract_fields(const tab &tab)
{ {
s_file s(buf); while (!data.eof())
while (1)
{ {
field_value fv; field_value fv;
if (SREAD(fv.field_id) == 0) if (READ_NOTHROW(data, fv.field_id) == 0)
break; break;
SREAD(fv.size); READ(data, fv.size);
auto i = tab.fields.find(fv.field_id); auto i = tab.fields.find(fv.field_id);
if (i == tab.fields.end()) if (i == tab.fields.end())
continue; continue;
@ -116,17 +110,17 @@ void value::extract_fields(const tab &tab)
{ {
case T_STRING: case T_STRING:
fv.s.resize(fv.size); fv.s.resize(fv.size);
SREAD_N(fv.s[0], fv.s.size()); READ_N(data, fv.s[0], fv.s.size());
break; break;
case T_INTEGER: case T_INTEGER:
SREAD(fv.i); READ(data, fv.i);
if (fv.size > sizeof(fv.i)) if (fv.size > sizeof(fv.i))
s.skip(fv.size - sizeof(fv.i)); data.skip(fv.size - sizeof(fv.i));
break; break;
case T_FLOAT: case T_FLOAT:
SREAD(fv.f); READ(data, fv.f);
if (fv.size > sizeof(fv.i)) if (fv.size > sizeof(fv.i))
s.skip(fv.size - sizeof(fv.i)); data.skip(fv.size - sizeof(fv.i));
break; break;
default: default:
assert(false); assert(false);
@ -135,15 +129,15 @@ void value::extract_fields(const tab &tab)
} }
} }
void db::load(FILE *f) void db::load(buffer &b)
{ {
FREAD(number_of_values); READ(b, number_of_values);
auto n = number_of_values; auto n = number_of_values;
while (n--) while (n--)
{ {
value t; value t;
t.load_index(f); t.load_index(b);
values.push_back(t); values.push_back(t);
} }
} }

View file

@ -24,6 +24,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <common.h>
using namespace std; using namespace std;
enum FieldType enum FieldType
@ -43,7 +45,7 @@ struct table
uint32_t unk3; uint32_t unk3;
uint32_t unk4; uint32_t unk4;
void load(FILE *f); void load(buffer &b);
}; };
struct field struct field
@ -56,7 +58,7 @@ struct field
uint32_t unk3; uint32_t unk3;
uint32_t type; uint32_t type;
void load(FILE *f); void load(buffer &b);
}; };
struct tab struct tab
@ -67,7 +69,7 @@ struct tab
map<uint32_t, table> tables; map<uint32_t, table> tables;
map<uint32_t, field> fields; map<uint32_t, field> fields;
void load(FILE *f); void load(buffer &b);
}; };
struct field_value struct field_value
@ -82,30 +84,6 @@ struct field_value
struct value struct value
{ {
struct s_file
{
uint32_t index = 0;
const vector<char> buf;
s_file(const vector<char> &buf)
: buf(buf)
{}
uint32_t read(void *dst, uint32_t size)
{
if (index >= buf.size())
return 0;
if (index + size > buf.size())
size = buf.size() - index;
memcpy(dst, buf.data() + index, size);
index += size;
return size;
}
void skip(int n)
{
index += n;
}
};
uint32_t table_id; uint32_t table_id;
char name[0x14]; char name[0x14];
uint32_t unk1; uint32_t unk1;
@ -113,17 +91,14 @@ struct value
uint32_t unk3; uint32_t unk3;
uint32_t offset; uint32_t offset;
uint32_t data_size; uint32_t data_size;
buffer data;
//
vector<char> buf;
//
uint32_t number_of_fields; uint32_t number_of_fields;
vector<field_value> fields; vector<field_value> fields;
void extract_fields(const tab &tab); void extract_fields(const tab &tab);
void load_index(FILE *f); void load_index(buffer &b);
void load_data(FILE *f); void load_data(buffer &b);
}; };
struct db struct db
@ -133,5 +108,5 @@ struct db
tab t; tab t;
vector<value> values; vector<value> values;
void load(FILE *f); void load(buffer &b);
}; };

View file

@ -22,42 +22,15 @@
#include <Windows.h> #include <Windows.h>
void open_tab(string path, tab &tab) #include <common.h>
{
path += ".tab";
FILE *f = fopen(path.c_str(), "rb");
if (!f)
return;
tab.load(f);
fclose(f);
}
void open_index(string path, db &index)
{
path += ".ind";
FILE *f = fopen(path.c_str(), "rb");
if (!f)
return;
index.load(f);
fclose(f);
}
void open_data(string path, db &index)
{
path += ".dat";
FILE *f = fopen(path.c_str(), "rb");
if (!f)
return;
for (auto &v : index.values)
v.load_data(f);
fclose(f);
}
void open_db(string path, db &db) void open_db(string path, db &db)
{ {
open_tab(path, db.t); db.t.load(buffer(readFile(path + ".tab")));
open_index(path, db); db.load(buffer(readFile(path + ".ind")));
open_data(path, db); buffer b(readFile(path + ".dat"));
for (auto &v : db.values)
v.load_data(b);
for (auto &v : db.values) for (auto &v : db.values)
v.extract_fields(db.t); v.extract_fields(db.t);
} }
@ -179,6 +152,7 @@ void create_sql(string path, const db &db)
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
try
{ {
if (argc != 2) if (argc != 2)
{ {
@ -190,4 +164,14 @@ int main(int argc, char *argv[])
open_db(path, db); open_db(path, db);
create_sql(path, db); create_sql(path, db);
return 0; return 0;
}
catch (std::exception &e)
{
printf("error: %s\n", e.what());
return 1;
}
catch (...)
{
printf("error: unknown exception\n");
return 1;
} }

View file

@ -21,58 +21,31 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
using namespace std; #include <common.h>
#include "model.h" #include "model.h"
const int build_version = using namespace std;
#include <version.h.in>
;
std::string version()
{
string s;
s = to_string(0) + "." +
to_string(1) + "." +
to_string(0) + "." +
to_string(build_version);
return s;
}
void convert_model(string fn) void convert_model(string fn)
{ {
printf("%s\n", fn.c_str());
buffer b(readFile(fn));
model m; model m;
FILE *f = fopen(fn.c_str(), "rb"); m.load(b);
if (!f)
return;
try
{
m.load(f);
auto p = ftell(f); if (!b.eof())
fseek(f, 0, SEEK_END);
auto end = ftell(f);
fclose(f);
if (p != end)
{
stringstream ss;
ss << hex << p << " != " << hex << end;
throw std::logic_error(ss.str());
}
}
catch (std::exception &e)
{ {
printf("error: %s\n", fn.c_str()); stringstream ss;
printf("%s\n", e.what()); ss << hex << b.getIndex() << " != " << hex << b.getSize();
fclose(f); throw std::logic_error(ss.str());
return;
} }
m.writeObj(fn + ".obj"); m.writeObj(fn + ".obj");
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
try
{ {
#ifdef NDEBUG #ifdef NDEBUG
if (argc != 2) if (argc != 2)
@ -98,4 +71,14 @@ int main(int argc, char *argv[])
convert_model("h:\\Games\\AIM\\data\\res0.pak.dir\\Data\\Models\\MOD_GL_M1_A_ATTACKER_DAMAGED"); convert_model("h:\\Games\\AIM\\data\\res0.pak.dir\\Data\\Models\\MOD_GL_M1_A_ATTACKER_DAMAGED");
#endif #endif
return 0; return 0;
}
catch (std::exception &e)
{
printf("error: %s\n", e.what());
return 1;
}
catch (...)
{
printf("error: unknown exception\n");
return 1;
} }

View file

@ -20,31 +20,28 @@
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <time.h>
#include <common.h>
using namespace std; using namespace std;
std::string version(); std::string version();
#define FREAD(var) fread(&var, 1, sizeof(var), f) void vertex::load(buffer &b, uint32_t flags)
#define SREAD(var) s.read(&var, sizeof(var))
#define SREAD_N(var, sz) s.read(&var, sz)
void vertex::load(s_file &s, uint32_t flags)
{ {
SREAD(vX); READ(b, vX);
SREAD(vZ); READ(b, vZ);
SREAD(vY); READ(b, vY);
if (flags & F_WIND) if (flags & F_WIND)
SREAD(wind); READ(b, wind);
SREAD(nX); READ(b, nX);
SREAD(nZ); READ(b, nZ);
SREAD(nY); READ(b, nY);
SREAD(t1); READ(b, t1);
SREAD(t2); READ(b, t2);
} }
std::string vertex::printVertex() const std::string vertex::printVertex() const
@ -68,50 +65,46 @@ std::string vertex::printTex() const
return s; return s;
} }
void fragment::load(FILE *f) void fragment::load(buffer &b)
{ {
FREAD(type); // header
FREAD(name0); READ(b, type);
FREAD(name1); READ(b, name0);
FREAD(name2); READ(b, name1);
FREAD(name3); READ(b, name2);
FREAD(name4); READ(b, name3);
FREAD(unk0); READ(b, name4);
FREAD(unk1); READ(b, unk0);
FREAD(unk2); READ(b, unk1);
FREAD(unk3); READ(b, unk2);
FREAD(size); READ(b, unk3);
FREAD(unk4); READ(b, size);
data.resize(size); READ(b, unk4);
data_offset = ftell(f);
fread(data.data(), 1, size, f);
}
bool fragment::extract() // data
{ buffer data(b, size);
s_file s(data, data_offset); READ(data, n_segments);
SREAD(n_segments);
segments.resize(n_segments); segments.resize(n_segments);
SREAD(header); READ(data, header);
SREAD(triangles_mult_7); READ(data, triangles_mult_7);
SREAD(unk10); READ(data, unk10);
SREAD(flags); READ(data, flags);
SREAD(n_vertex); READ(data, n_vertex);
vertices.resize(n_vertex); vertices.resize(n_vertex);
SREAD(n_triangles); READ(data, n_triangles);
if (triangles_mult_7) if (triangles_mult_7)
n_triangles *= 7; n_triangles *= 7;
triangles.resize(n_triangles); triangles.resize(n_triangles);
for (auto &v : vertices) for (auto &v : vertices)
v.load(s, flags); v.load(data, flags);
for (auto &t : triangles) for (auto &t : triangles)
SREAD(t); READ(data, t);
// segments
for (auto &seg : segments) for (auto &seg : segments)
{ {
uint32_t type; uint32_t type;
SREAD(type); READ(data, type);
switch (type) switch (type)
{ {
case 1: case 1:
@ -127,94 +120,91 @@ bool fragment::extract()
throw std::logic_error("unknown segment type " + std::to_string(type)); throw std::logic_error("unknown segment type " + std::to_string(type));
} }
seg->type = type; seg->type = type;
seg->extract(s); seg->load(data);
} }
return s.eof(); if (!data.eof())
throw std::logic_error("extraction error: fragment #" + std::string(name0));
} }
void segment1::extract(s_file &s) void segment1::load(buffer &b)
{ {
SREAD(name); READ(b, name);
SREAD(unk0); READ(b, unk0);
triangles.resize(unk0[0][0]); triangles.resize(unk0[0][0]);
unk1.resize(unk0[0][0]); unk1.resize(unk0[0][0]);
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
for (auto &t : triangles) for (auto &t : triangles)
SREAD(t); READ(b, t);
for (auto &unk: unk1) for (auto &unk: unk1)
SREAD(unk); READ(b, unk);
} }
} }
void segment2::extract(s_file &s) void segment2::load(buffer &b)
{ {
SREAD(name); READ(b, name);
SREAD(unk0); READ(b, unk0);
triangles.resize(unk0[0][0]); triangles.resize(unk0[0][0]);
unk1.resize(unk0[0][0]); unk1.resize(unk0[0][0]);
unk1_1.resize(unk0[0][0]); unk1_1.resize(unk0[0][0]);
for (auto &t : triangles) for (auto &t : triangles)
SREAD(t); READ(b, t);
for (auto &unk : unk1) for (auto &unk : unk1)
SREAD(unk); READ(b, unk);
for (auto &unk : unk1_1) for (auto &unk : unk1_1)
SREAD(unk); READ(b, unk);
while (!s.eof()) while (!b.eof())
{ {
repeater r; repeater r;
r.extract(s); r.load(b);
unk2.push_back(r); unk2.push_back(r);
} }
} }
void segment2::repeater::extract(s_file &s) void segment2::repeater::load(buffer &b)
{ {
SREAD(unk2); READ(b, unk2);
triangles2.resize(unk2); triangles2.resize(unk2);
SREAD(unk8); READ(b, unk8);
SREAD(unk3); READ(b, unk3);
for (auto &t : triangles2) for (auto &t : triangles2)
SREAD(t); READ(b, t);
SREAD(unk6); READ(b, unk6);
SREAD(flags); READ(b, flags);
SREAD(n_vertex); READ(b, n_vertex);
vertices.resize(n_vertex); vertices.resize(n_vertex);
SREAD(n_triangles); READ(b, n_triangles);
triangles.resize(n_triangles); triangles.resize(n_triangles);
for (auto &v : vertices) for (auto &v : vertices)
v.load(s, flags); v.load(b, flags);
for (auto &t : triangles) for (auto &t : triangles)
SREAD(t); READ(b, t);
} }
void segment6::extract(s_file &s) void segment6::load(buffer &b)
{ {
SREAD(name); READ(b, name);
SREAD(unk0); READ(b, unk0);
triangles.resize(unk0[0][0]); triangles.resize(unk0[0][0]);
for (int i = 0; i < 1; i++) for (int i = 0; i < 1; i++)
{ {
for (auto &t : triangles) for (auto &t : triangles)
SREAD(t); READ(b, t);
char unk1[0x30]; // some 6 floats char unk1[0x30]; // some 6 floats
for (int i = 0; i < unk0[0][0]; i++) for (int i = 0; i < unk0[0][0]; i++)
SREAD(unk1); READ(b, unk1);
} }
} }
void model::load(FILE *f) void model::load(buffer &b)
{ {
FREAD(n_fragments); READ(b, n_fragments);
FREAD(header); READ(b, header);
fragments.resize(n_fragments); fragments.resize(n_fragments);
for (int i = 0; i < fragments.size(); i++) for (auto &f : fragments)
{ f.load(b);
fragments[i].load(f);
if (!fragments[i].extract())
throw std::logic_error("extraction error: fragment #" + std::to_string(i));
}
} }
void model::writeObj(std::string fn) void model::writeObj(std::string fn)

View file

@ -22,37 +22,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
struct s_file class buffer;
{
uint32_t index = 0;
const std::vector<uint8_t> &buf;
uint8_t *ptr;
uint32_t data_offset;
s_file(const std::vector<uint8_t> &buf, uint32_t data_offset)
: buf(buf), data_offset(data_offset)
{}
uint32_t read(void *dst, uint32_t size)
{
if (index >= buf.size())
throw std::logic_error("s_file: out of range");
if (index + size > buf.size())
size = buf.size() - index;
memcpy(dst, buf.data() + index, size);
skip(size);
return size;
}
void skip(int n)
{
index += n;
data_offset += n;
ptr = (uint8_t *)buf.data() + index;
}
bool eof() const
{
return index == buf.size();
}
};
enum enum
{ {
@ -74,7 +44,7 @@ struct vertex
float t1; float t1;
float t2; float t2;
void load(s_file &s, uint32_t flags); void load(buffer &b, uint32_t flags);
std::string printVertex() const; std::string printVertex() const;
std::string printNormal() const; std::string printNormal() const;
@ -97,7 +67,7 @@ struct segment
{ {
uint32_t type; uint32_t type;
virtual void extract(s_file &s) = 0; virtual void load(buffer &b) = 0;
}; };
struct segment1 : public segment struct segment1 : public segment
@ -107,7 +77,7 @@ struct segment1 : public segment
std::vector<triangle> triangles; std::vector<triangle> triangles;
std::vector<unk_float3x4> unk1; std::vector<unk_float3x4> unk1;
virtual void extract(s_file &s); virtual void load(buffer &b);
}; };
struct segment2 : public segment struct segment2 : public segment
@ -125,7 +95,7 @@ struct segment2 : public segment
std::vector<vertex> vertices; std::vector<vertex> vertices;
std::vector<uint16_t> triangles; std::vector<uint16_t> triangles;
virtual void extract(s_file &s); virtual void load(buffer &b);
}; };
char name[0xC]; char name[0xC];
@ -135,17 +105,17 @@ struct segment2 : public segment
std::vector<unk_float6> unk1_1; std::vector<unk_float6> unk1_1;
std::vector<repeater> unk2; std::vector<repeater> unk2;
virtual void extract(s_file &s); virtual void load(buffer &b);
}; };
struct segment6 : public segment1 struct segment6 : public segment1
{ {
virtual void extract(s_file &s); virtual void load(buffer &b);
}; };
struct fragment struct fragment
{ {
// main header // header
uint32_t type; uint32_t type;
char name0[0x20]; char name0[0x20];
char name1[0x20]; char name1[0x20];
@ -159,10 +129,7 @@ struct fragment
uint32_t size; uint32_t size;
uint32_t unk4[10]; uint32_t unk4[10];
// data buffer // data
std::vector<uint8_t> data;
// main data
uint32_t n_segments; uint32_t n_segments;
char header[0x68]; char header[0x68];
uint32_t triangles_mult_7; uint32_t triangles_mult_7;
@ -176,11 +143,7 @@ struct fragment
// segments // segments
std::vector<segment *> segments; std::vector<segment *> segments;
// internal vars void load(buffer &b);
uint32_t data_offset;
void load(FILE *f);
bool extract();
}; };
struct model struct model
@ -189,6 +152,6 @@ struct model
char header[0x40]; char header[0x40];
std::vector<fragment> fragments; std::vector<fragment> fragments;
void load(FILE *f); void load(buffer &b);
void writeObj(std::string fn); void writeObj(std::string fn);
}; };

View file

@ -29,6 +29,8 @@
#include <Polygon4/Storage.h> #include <Polygon4/Storage.h>
#include <common.h>
using namespace std; using namespace std;
struct storage struct storage
@ -39,27 +41,31 @@ struct storage
MapGoods mg; MapGoods mg;
MapMusic mm; MapMusic mm;
MapSounds ms; MapSounds ms;
void load(buffer &b)
{
objects.load(b);
mgs.load(b);
if (b.eof()) // custom maps
return;
mg.load(b);
mm.load(b);
ms.load(b);
if (!b.eof())
{
stringstream ss;
ss << hex << b.getIndex() << " != " << hex << b.getSize();
throw std::logic_error(ss.str());
}
}
}; };
storage read_mmo(string fn) storage read_mmo(string fn)
{ {
storage s; storage s;
s.name = fn; s.name = fn;
FILE *f = fopen(fn.c_str(), "rb"); s.load(buffer(readFile(fn)));
if (!f)
return s;
s.objects.load(f);
s.mgs.load(f);
if (feof(f))
{
// custom maps?
fclose(f);
return s;
}
s.mg.load(f);
s.mm.load(f);
s.ms.load(f);
fclose(f);
return s; return s;
} }
@ -197,6 +203,7 @@ void write_mmo(string db, const storage &s)
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
try
{ {
if (argc != 3) if (argc != 3)
{ {
@ -206,4 +213,14 @@ int main(int argc, char *argv[])
storage s = read_mmo(argv[2]); storage s = read_mmo(argv[2]);
write_mmo(argv[1], s); write_mmo(argv[1], s);
return 0; return 0;
}
catch (std::exception &e)
{
printf("error: %s\n", e.what());
return 1;
}
catch (...)
{
printf("error: unknown exception\n");
return 1;
} }

View file

@ -18,10 +18,10 @@
#include "objects.h" #include "objects.h"
Segment *Segment::create_segment(FILE *f) Segment *Segment::create_segment(buffer &b)
{ {
SegmentType segment_type; SegmentType segment_type;
FREAD(segment_type); READ(b, segment_type);
Segment *segment = 0; Segment *segment = 0;
switch (segment_type) switch (segment_type)
@ -78,22 +78,22 @@ Segment *Segment::create_segment(FILE *f)
if (segment) if (segment)
{ {
segment->segment_type = segment_type; segment->segment_type = segment_type;
FREAD(segment->segment_len); READ(b, segment->segment_len);
FREAD(segment->n_objects); READ(b, segment->n_objects);
} }
return segment; return segment;
} }
void Objects::load(FILE *f) void Objects::load(buffer &b)
{ {
FREAD(n_segments); READ(b, n_segments);
for (int s = 0; s < n_segments; s++) for (int s = 0; s < n_segments; s++)
{ {
auto seg = Segment::create_segment(f); auto seg = Segment::create_segment(b);
if (!seg) if (!seg)
break; break;
seg->load(f); seg->load(b);
segments.push_back(seg); segments.push_back(seg);
} }
} }

View file

@ -24,8 +24,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#define FREAD(var) fread(&var, 1, sizeof(var), f) #include <common.h>
#define FREAD_N(var, n) fread(&var, 1, n, f)
using namespace std; using namespace std;
@ -71,8 +70,8 @@ struct Segment
uint32_t n_objects; uint32_t n_objects;
virtual ~Segment(){} virtual ~Segment(){}
static Segment *create_segment(FILE *f); static Segment *create_segment(buffer &b);
virtual void load(FILE *f) = 0; virtual void load(buffer &b) = 0;
}; };
template <class T> template <class T>
@ -80,12 +79,12 @@ struct SegmentObjects : public Segment
{ {
vector<T> objects; vector<T> objects;
virtual void load(FILE *f) virtual void load(buffer &b)
{ {
for (int i = 0; i < n_objects; i++) for (int i = 0; i < n_objects; i++)
{ {
T r; T r;
r.load(f); r.load(b);
objects.push_back(r); objects.push_back(r);
} }
} }
@ -104,10 +103,10 @@ struct Common
Vector4 m_rotate_z[3]; Vector4 m_rotate_z[3];
Vector4 position; Vector4 position;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(m_rotate_z); READ(b, m_rotate_z);
FREAD(position); READ(b, position);
} }
}; };
@ -116,12 +115,12 @@ struct MapObject : public Common
char name1[0x20]; char name1[0x20];
char name2[0x20]; char name2[0x20];
void load(FILE *f) void load(buffer &b)
{ {
Common::load(f); Common::load(b);
FREAD(name1); READ(b, name1);
FREAD(name2); READ(b, name2);
} }
}; };
@ -130,14 +129,14 @@ struct MapObjectWithArray : public MapObject
uint32_t len; uint32_t len;
vector<uint32_t> unk7; vector<uint32_t> unk7;
void load(FILE *f) void load(buffer &b)
{ {
MapObject::load(f); MapObject::load(b);
FREAD(len); READ(b, len);
unk7.resize(len); unk7.resize(len);
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
FREAD(unk7[i]); READ(b, unk7[i]);
} }
}; };
@ -146,12 +145,12 @@ struct Sound : public Common
uint32_t unk1[11]; uint32_t unk1[11];
char name1[0x14]; char name1[0x14];
void load(FILE *f) void load(buffer &b)
{ {
Common::load(f); Common::load(b);
FREAD(unk1); READ(b, unk1);
FREAD(name1); READ(b, name1);
} }
}; };
@ -172,7 +171,7 @@ KNOWN_OBJECT(Anomaly);
KNOWN_OBJECT(Boundary); KNOWN_OBJECT(Boundary);
#define UNKNOWN_OBJECT(name) \ #define UNKNOWN_OBJECT(name) \
struct name : public MapObject { void load(FILE *f){ int pos = ftell(f); assert(false); } } struct name : public MapObject { void load(buffer &b){ int pos = b.getIndex(); assert(false); } }
UNKNOWN_OBJECT(Building); UNKNOWN_OBJECT(Building);
UNKNOWN_OBJECT(Goods); UNKNOWN_OBJECT(Goods);
@ -183,5 +182,5 @@ struct Objects
uint32_t n_segments; uint32_t n_segments;
vector<Segment *> segments; vector<Segment *> segments;
void load(FILE *f); void load(buffer &b);
}; };

View file

@ -24,6 +24,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <common.h>
using namespace std; using namespace std;
struct MechGroup struct MechGroup
@ -47,35 +49,35 @@ struct MechGroup
vector<string> configs; vector<string> configs;
char unk100; char unk100;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(unk1); READ(b, unk1);
FREAD(unk2); READ(b, unk2);
FREAD(type1); READ(b, type1);
FREAD(len1); READ(b, len1);
FREAD(name1); READ(b, name1);
if (type1 == 3 || type1 == 4) if (type1 == 3 || type1 == 4)
{ {
FREAD(unk30); READ(b, unk30);
} }
else if (type1 == 2) else if (type1 == 2)
{ {
FREAD(len); READ(b, len);
unk11.resize(len); unk11.resize(len);
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
FREAD(unk11[i]); READ(b, unk11[i]);
} }
else if (type1 == 1 || type1 == 0) else if (type1 == 1 || type1 == 0)
{ {
FREAD(unk20); READ(b, unk20);
FREAD(unk21); READ(b, unk21);
} }
else else
assert(false); assert(false);
configs.resize(len1, string(0x20, 0)); configs.resize(len1, string(0x20, 0));
for (int i = 0; i < len1; i++) for (int i = 0; i < len1; i++)
FREAD_N(configs[i][0], 0x20); READ_N(b, configs[i][0], 0x20);
FREAD(unk100); READ(b, unk100);
} }
}; };
@ -86,15 +88,15 @@ struct MechGroups
vector<MechGroup> mgs; vector<MechGroup> mgs;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(n); READ(b, n);
FREAD(prefix); READ(b, prefix);
for (int s = 0; s < n; s++) for (int s = 0; s < n; s++)
{ {
MechGroup mg; MechGroup mg;
mg.load(f); mg.load(b);
mgs.push_back(mg); mgs.push_back(mg);
} }
} }
@ -107,12 +109,12 @@ struct Good
float price; float price;
float unk2[10]; float unk2[10];
void load(FILE *f) void load(buffer &b)
{ {
FREAD(name); READ(b, name);
FREAD(unk1); READ(b, unk1);
FREAD(price); READ(b, price);
FREAD(unk2); READ(b, unk2);
} }
}; };
@ -123,15 +125,15 @@ struct BuildingGoods
vector<Good> goods; vector<Good> goods;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(name); READ(b, name);
FREAD(n); READ(b, n);
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
Good g; Good g;
g.load(f); g.load(b);
goods.push_back(g); goods.push_back(g);
} }
} }
@ -146,17 +148,17 @@ struct MapGoods
vector<BuildingGoods> bgs; vector<BuildingGoods> bgs;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(unk1); READ(b, unk1);
FREAD(unk2); READ(b, unk2);
FREAD(unk3); READ(b, unk3);
FREAD(n); READ(b, n);
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
BuildingGoods bg; BuildingGoods bg;
bg.load(f); bg.load(b);
bgs.push_back(bg); bgs.push_back(bg);
} }
} }
@ -174,25 +176,25 @@ struct MapMusic
uint32_t n2; uint32_t n2;
vector<string> names2; vector<string> names2;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(unk1); READ(b, unk1);
FREAD(name1); READ(b, name1);
FREAD(name2); READ(b, name2);
FREAD(n1); READ(b, n1);
for (int i = 0; i < n1; i++) for (int i = 0; i < n1; i++)
{ {
char name[0x20]; char name[0x20];
FREAD(name); READ(b, name);
names1.push_back(name); names1.push_back(name);
} }
FREAD(n2); READ(b, n2);
for (int i = 0; i < n2; i++) for (int i = 0; i < n2; i++)
{ {
char name[0x20]; char name[0x20];
FREAD(name); READ(b, name);
names2.push_back(name); names2.push_back(name);
} }
} }
@ -205,12 +207,12 @@ struct MapSound
uint32_t unk2; uint32_t unk2;
float unk3[4]; float unk3[4];
void load(FILE *f) void load(buffer &b)
{ {
FREAD(name); READ(b, name);
FREAD(unk1); READ(b, unk1);
FREAD(unk2); READ(b, unk2);
FREAD(unk3); READ(b, unk3);
} }
}; };
@ -219,13 +221,13 @@ struct MapSounds
uint32_t n; uint32_t n;
vector<MapSound> sounds; vector<MapSound> sounds;
void load(FILE *f) void load(buffer &b)
{ {
FREAD(n); READ(b, n);
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
MapSound s; MapSound s;
s.load(f); s.load(b);
sounds.push_back(s); sounds.push_back(s);
} }
} }