Fix mmp extractor. Add mpj loader. Some fixes in buffer class.

This commit is contained in:
lzwdgc 2015-10-22 19:34:26 +03:00
parent 78812b5236
commit e1e46a3b75
17 changed files with 1106 additions and 505 deletions

View file

@ -12,6 +12,7 @@ endif()
file(GLOB script2txt_src "script2txt/*") file(GLOB script2txt_src "script2txt/*")
add_executable(script2txt ${script2txt_src}) add_executable(script2txt ${script2txt_src})
if (DATABASE_MANAGER_DIR) if (DATABASE_MANAGER_DIR)
file(GLOB mmm_extractor_src "mmm_extractor/*") file(GLOB mmm_extractor_src "mmm_extractor/*")
add_executable(mmm_extractor ${mmm_extractor_src}) add_executable(mmm_extractor ${mmm_extractor_src})
@ -22,6 +23,7 @@ add_executable(mmo_extractor ${mmo_extractor_src})
target_link_libraries(mmo_extractor DatabaseManager common) target_link_libraries(mmo_extractor DatabaseManager common)
endif() endif()
file(GLOB mmp_extractor_src "mmp_extractor/*") file(GLOB mmp_extractor_src "mmp_extractor/*")
add_executable(mmp_extractor ${mmp_extractor_src}) add_executable(mmp_extractor ${mmp_extractor_src})
target_link_libraries(mmp_extractor common) target_link_libraries(mmp_extractor common)
@ -30,6 +32,10 @@ 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) target_link_libraries(mod_converter common)
file(GLOB mpj_loader_src "mpj_loader/*")
add_executable(mpj_loader ${mpj_loader_src})
target_link_libraries(mpj_loader common)
file(GLOB tm_converter_src "tm_converter/*") file(GLOB tm_converter_src "tm_converter/*")
add_executable(tm_converter ${tm_converter_src}) add_executable(tm_converter ${tm_converter_src})
target_link_libraries(tm_converter common) target_link_libraries(tm_converter common)

View file

@ -78,6 +78,7 @@ buffer::buffer(const std::vector<uint8_t> &buf, uint32_t data_offset)
{ {
skip(0); skip(0);
size_ = buf_->size(); size_ = buf_->size();
end_ = index_ + size_;
} }
buffer::buffer(buffer &rhs, uint32_t size) buffer::buffer(buffer &rhs, uint32_t size)
@ -86,7 +87,8 @@ buffer::buffer(buffer &rhs, uint32_t size)
index_ = rhs.index_; index_ = rhs.index_;
data_offset = rhs.data_offset; data_offset = rhs.data_offset;
ptr = rhs.ptr; ptr = rhs.ptr;
size_ = index_ + size; size_ = size;
end_ = index_ + size_;
rhs.skip(size); rhs.skip(size);
} }
@ -95,62 +97,39 @@ buffer::buffer(buffer &rhs, uint32_t size, uint32_t offset)
{ {
index_ = offset; index_ = offset;
data_offset = offset; data_offset = offset;
size_ = size;
ptr = (uint8_t *)buf_->data() + index_; ptr = (uint8_t *)buf_->data() + index_;
size_ = index_ + size; end_ = index_ + size_;
} }
uint32_t buffer::read(void *dst, uint32_t size, bool nothrow) const uint32_t buffer::_read(void *dst, uint32_t size, uint32_t offset) const
{ {
if (!buf_) if (!buf_)
throw std::logic_error("buffer: not initialized"); throw std::logic_error("buffer: not initialized");
if (index_ >= size_) if (index_ >= end_)
{
if (nothrow)
return 0;
throw std::logic_error("buffer: out of range"); throw std::logic_error("buffer: out of range");
} if (index_ + offset + size > end_)
if (index_ + size > size_) throw std::logic_error("buffer: too much data");
{ memcpy(dst, buf_->data() + index_ + offset, size);
if (!nothrow) skip(size + offset);
throw std::logic_error("buffer: too much data");
size = size_ - index_;
}
memcpy(dst, buf_->data() + index_, size);
skip(size);
return size; return size;
} }
uint32_t buffer::readfrom(void *dst, uint32_t size, uint32_t offset, bool nothrow) const uint32_t buffer::_write(const void *src, uint32_t size)
{
if (!buf_)
throw std::logic_error("buffer: not initialized");
if (offset + size > size_)
{
if (!nothrow)
throw std::logic_error("buffer: too much data");
size = size_ - offset;
}
memcpy(dst, buf_->data() + offset, size);
return size;
}
uint32_t buffer::write(const void *src, uint32_t size, bool nothrow)
{ {
if (!buf_) if (!buf_)
{ {
buf_ = std::make_shared<std::vector<uint8_t>>(size); buf_ = std::make_shared<std::vector<uint8_t>>(size);
size_ = buf_->size(); size_ = buf_->size();
end_ = index_ + size_;
} }
if (index_ > size_) if (index_ > end_)
{
if (nothrow)
return 0;
throw std::logic_error("buffer: out of range"); throw std::logic_error("buffer: out of range");
} if (index_ + size > end_)
if (index_ + size > size_)
{ {
buf_->resize(index_ + size); buf_->resize(index_ + size);
size_ = buf_->size(); size_ = buf_->size();
end_ = index_ + size_;
} }
memcpy((uint8_t *)buf_->data() + index_, src, size); memcpy((uint8_t *)buf_->data() + index_, src, size);
skip(size); skip(size);
@ -186,7 +165,7 @@ bool buffer::check(int index) const
bool buffer::eof() const bool buffer::eof() const
{ {
return check(size_); return index_ == end_;
} }
uint32_t buffer::index() const uint32_t buffer::index() const

View file

@ -23,10 +23,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#define READ(b, var) b.read(&var, sizeof(var)) #define READ(b, var) b.read(&var)
#define READ_NOTHROW(b, var) b.read(&var, sizeof(var), true)
#define READ_N(b, var, sz) b.read(&var, sz) #define READ_N(b, var, sz) b.read(&var, sz)
#define WRITE(b, var) b.write(&var, sizeof(var)) #define WRITE(b, var) b.write(&var)
std::string version(); std::string version();
std::vector<uint8_t> readFile(const std::string &fn); std::vector<uint8_t> readFile(const std::string &fn);
@ -41,13 +40,36 @@ public:
buffer(buffer &rhs, uint32_t size); buffer(buffer &rhs, uint32_t size);
buffer(buffer &rhs, uint32_t size, uint32_t offset); buffer(buffer &rhs, uint32_t size, uint32_t offset);
uint32_t read(void *dst, uint32_t size, bool nothrow = false) const; template <typename T>
uint32_t readfrom(void *dst, uint32_t size, uint32_t offset, bool nothrow = false) const; uint32_t read(T *dst) const
uint32_t write(const void *src, uint32_t size, bool nothrow = false); {
return _read(dst, sizeof(T), 0);
}
template <typename T>
uint32_t read(T *dst, uint32_t size) const
{
return _read(dst, size * sizeof(T), 0);
}
template <typename T>
uint32_t readfrom(T *dst, uint32_t size, uint32_t offset) const
{
return _read(dst, size * sizeof(T), offset);
}
template <typename T> template <typename T>
uint32_t write(const T &src) uint32_t write(const T &src)
{ {
return write(&src, sizeof(src)); return _write(&src, sizeof(T));
}
template <typename T>
uint32_t write(const T *src, uint32_t size)
{
return _write(src, size * sizeof(T));
}
template <typename T>
uint32_t write(const T *src)
{
return _write(src, sizeof(T));
} }
void seek(uint32_t size) const; void seek(uint32_t size) const;
@ -66,4 +88,8 @@ private:
mutable uint8_t *ptr = 0; mutable uint8_t *ptr = 0;
mutable uint32_t data_offset = 0; mutable uint32_t data_offset = 0;
mutable uint32_t size_ = 0; mutable uint32_t size_ = 0;
uint32_t end_;
uint32_t _read(void *dst, uint32_t size, uint32_t offset = 0) const;
uint32_t _write(const void *src, uint32_t size);
}; };

View file

@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once
#include <stdint.h> #include <stdint.h>
typedef uint16_t color_rgb565; typedef uint16_t color_rgb565;

View file

@ -74,22 +74,22 @@ void write_mat_bmp(const std::string &filename, const mat<T> &m)
return; return;
BITMAPFILEHEADER h = { 0 }; BITMAPFILEHEADER h = { 0 };
h.bfType = 0x4D42; h.bfType = 0x4D42;
h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + m.size() * sizeof(T); h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + m.size() * sizeof(T);
h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO); h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BITMAPINFO i = { 0 }; BITMAPINFOHEADER i = { 0 };
i.bmiHeader.biSize = sizeof(i.bmiHeader); i.biSize = sizeof(i);
i.bmiHeader.biWidth = m.getWidth(); i.biWidth = m.getWidth();
i.bmiHeader.biHeight = m.getHeight(); i.biHeight = m.getHeight();
i.bmiHeader.biPlanes = 1; i.biPlanes = 1;
i.bmiHeader.biBitCount = sizeof(T) * 8; i.biBitCount = sizeof(T) * 8;
i.bmiHeader.biCompression = 0; i.biCompression = 0;
i.bmiHeader.biSizeImage = 0; i.biSizeImage = 0;
i.bmiHeader.biXPelsPerMeter = 0; i.biXPelsPerMeter = 0;
i.bmiHeader.biYPelsPerMeter = 0; i.biYPelsPerMeter = 0;
i.bmiHeader.biClrUsed = 0; i.biClrUsed = 0;
i.bmiHeader.biClrImportant = 0; i.biClrImportant = 0;
fwrite(&h, sizeof(BITMAPFILEHEADER), 1, f); fwrite(&h, sizeof(BITMAPFILEHEADER), 1, f);
fwrite(&i, sizeof(BITMAPINFO), 1, f); fwrite(&i, sizeof(BITMAPINFOHEADER), 1, f);
fwrite(&m(0, 0), m.size() * sizeof(T), 1, f); fwrite(&m(0, 0), m.size() * sizeof(T), 1, f);
fclose(f); fclose(f);
} }

View file

@ -20,55 +20,52 @@
Segment *Segment::create_segment(buffer &b) Segment *Segment::create_segment(buffer &b)
{ {
SegmentType segment_type; ObjectType segment_type;
READ(b, segment_type); READ(b, segment_type);
Segment *segment = 0; Segment *segment = 0;
switch (segment_type) switch (segment_type)
{ {
case SegmentType::ROAD: case ObjectType::ROAD:
segment = new SegmentObjects<Road>; segment = new SegmentObjects<Road>;
break; break;
case SegmentType::BUILDING: case ObjectType::BUILDING:
segment = new SegmentObjects<Building>; segment = new SegmentObjects<Building>;
break; break;
case SegmentType::SURFACE: case ObjectType::TREE:
segment = new SegmentObjects<Surface>; segment = new SegmentObjects<Tree>;
break; break;
case SegmentType::STONE: case ObjectType::STONE:
segment = new SegmentObjects<Stone>; segment = new SegmentObjects<Stone>;
break; break;
case SegmentType::HELPER: case ObjectType::HELPER:
segment = new SegmentObjects<Helper>; segment = new SegmentObjects<Helper>;
break; break;
case SegmentType::SHELL: case ObjectType::IMAGE:
segment = new SegmentObjects<Shell>;
break;
case SegmentType::IMAGE:
segment = new SegmentObjects<Image>; segment = new SegmentObjects<Image>;
break; break;
case SegmentType::EXPLOSION: case ObjectType::LAMP:
segment = new SegmentObjects<Explosion>; segment = new SegmentObjects<Lamp>;
break; break;
case SegmentType::SOUND: case ObjectType::SOUND:
segment = new SegmentObjects<Sound>; segment = new SegmentObjects<Sound>;
break; break;
case SegmentType::ANOMALY: case ObjectType::ANOMALY:
segment = new SegmentObjects<Anomaly>; segment = new SegmentObjects<Anomaly>;
break; break;
case SegmentType::TOWER: case ObjectType::TOWER:
segment = new SegmentObjects<Tower>; segment = new SegmentObjects<Tower>;
break; break;
case SegmentType::BOUNDARY: case ObjectType::BOUNDARY:
segment = new SegmentObjects<Boundary>; segment = new SegmentObjects<Boundary>;
break; break;
case SegmentType::GOODS: case ObjectType::SOUND_ZONE:
segment = new SegmentObjects<Goods>;
break;
case SegmentType::SOUND_ZONE:
segment = new SegmentObjects<SoundZone>; segment = new SegmentObjects<SoundZone>;
break; break;
case SegmentType::unk1: case ObjectType::unk0:
segment = new SegmentObjects<unk0>;
break;
case ObjectType::unk1:
segment = new SegmentObjects<unk1>; segment = new SegmentObjects<unk1>;
break; break;
default: default:

View file

@ -24,49 +24,49 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <buffer.h> #include "buffer.h"
#include "types.h"
using namespace std; enum class ObjectType : uint32_t
enum class SegmentType : uint32_t
{ {
TEXTURE = 0x1, TEXTURE = 1,
MODEL, //MODEL,
SURFACE, // stones //SURFACE,
STONE, // trees STONE = 3,
TREE, TREE = 4,
GLIDER, //GLIDER,
HELPER, HELPER = 7,
ROAD, ROAD = 8,
WEAPON, //WEAPON,
CONFIG, //CONFIG,
SHELL, // buildings //SHELL, // buildings
BUILDING = 11,
IMAGE, IMAGE,
EXPLOSION, // road lights LAMP = 13,
EQUIPMENT, //EXPLOSION, // road lights
ORGANIZATION, //EQUIPMENT,
//ORGANIZATION,
BUILDING, //COVERING = 18,
LAMP, SOUND = 19,
COVERING, //GOODS, // anomaly?
SOUND, ANOMALY = 20, // radiation?
GOODS,
ANOMALY, unk0 = 21, // anomaly?
TOWER, TOWER = 22,
BOUNDARY, BOUNDARY = 23,
SOUND_ZONE, SOUND_ZONE = 24,
unk1 = 0x1b, unk1 = 27,
}; };
struct Segment struct Segment
{ {
SegmentType segment_type; ObjectType segment_type;
uint32_t segment_len = 0; uint32_t segment_len = 0;
uint32_t n_objects = 0; uint32_t n_objects = 0;
virtual ~Segment(){} virtual ~Segment(){}
static Segment *create_segment(buffer &b); static Segment *create_segment(buffer &b);
@ -76,7 +76,7 @@ struct Segment
template <class T> template <class T>
struct SegmentObjects : public Segment struct SegmentObjects : public Segment
{ {
vector<T*> objects; std::vector<T*> objects;
virtual void load(buffer &b) virtual void load(buffer &b)
{ {
@ -89,18 +89,10 @@ struct SegmentObjects : public Segment
} }
}; };
struct Vector4
{
float x = 0;
float y = 0;
float z = 0;
float w = 0;
};
struct Common struct Common
{ {
Vector4 m_rotate_z[3]; Vector4 m_rotate_z[3];
Vector4 position; Vector4 position;
void load(buffer &b) void load(buffer &b)
{ {
@ -126,7 +118,7 @@ struct MapObject : public Common
struct MapObjectWithArray : public MapObject struct MapObjectWithArray : public MapObject
{ {
uint32_t len = 0; uint32_t len = 0;
vector<uint32_t> unk0; std::vector<uint32_t> unk0;
void load(buffer &b) void load(buffer &b)
{ {
@ -159,13 +151,12 @@ struct Boundary : public MapObjectWithArray {};
#define KNOWN_OBJECT(name) \ #define KNOWN_OBJECT(name) \
struct name : public MapObject {} struct name : public MapObject {}
KNOWN_OBJECT(Surface);
KNOWN_OBJECT(Helper);
KNOWN_OBJECT(Shell);
KNOWN_OBJECT(Stone); KNOWN_OBJECT(Stone);
KNOWN_OBJECT(Explosion); KNOWN_OBJECT(Helper);
KNOWN_OBJECT(Building);
KNOWN_OBJECT(Tree);
KNOWN_OBJECT(Lamp);
KNOWN_OBJECT(Image); KNOWN_OBJECT(Image);
KNOWN_OBJECT(Goods);
KNOWN_OBJECT(Anomaly); KNOWN_OBJECT(Anomaly);
KNOWN_OBJECT(Tower); KNOWN_OBJECT(Tower);
KNOWN_OBJECT(SoundZone); KNOWN_OBJECT(SoundZone);
@ -173,13 +164,13 @@ KNOWN_OBJECT(SoundZone);
#define UNKNOWN_OBJECT(name) \ #define UNKNOWN_OBJECT(name) \
struct name : public MapObject { void load(buffer &b){ int pos = b.index(); assert(false); } } struct name : public MapObject { void load(buffer &b){ int pos = b.index(); assert(false); } }
UNKNOWN_OBJECT(Building); UNKNOWN_OBJECT(unk0);
UNKNOWN_OBJECT(unk1); UNKNOWN_OBJECT(unk1);
struct Objects struct Objects
{ {
uint32_t n_segments = 0; uint32_t n_segments = 0;
vector<Segment *> segments; std::vector<Segment *> segments;
void load(buffer &b); void load(buffer &b);
}; };

84
src/common/types.cpp Normal file
View file

@ -0,0 +1,84 @@
/*
* 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 "types.h"
GameType gameType = GameType::Aim2;
void weather::load(buffer &b)
{
READ(b, name);
READ(b, unk0);
READ(b, unk1);
READ(b, smoke_1);
READ(b, smoke_3);
READ(b, smokeType);
READ(b, unk2);
READ(b, cloud_layer1);
READ(b, cloud_layer2);
READ(b, cloud_layer1_speed);
READ(b, cloud_layer2_speed);
READ(b, cloud_layer1_direction);
READ(b, cloud_layer2_direction);
READ(b, sun);
READ(b, general_color);
READ(b, sun_color);
READ(b, moon_color);
READ(b, moon);
READ(b, probability);
READ(b, day_night_gradient_name);
READ(b, dawn_dusk_gradient_name);
READ(b, dawn_dusk_color);
READ(b, effects);
READ(b, smoke_2);
READ(b, smoke_4);
READ(b, slider_3);
READ(b, slider_1);
READ(b, unk8);
}
void weather_group::load(buffer &b)
{
READ(b, n_segs);
segments.resize(n_segs);
READ(b, name);
for (auto &s : segments)
s.load(b);
}
void water::load(buffer &b)
{
READ(b, unk0);
READ(b, name1);
READ(b, unk1);
READ(b, unk2);
READ(b, unk3);
READ(b, unk4);
READ(b, name2);
READ(b, unk5);
}
void water_group::load(buffer &b)
{
while (!b.eof())
{
water w;
w.load(b);
segments.push_back(w);
}
}

298
src/common/types.h Normal file
View file

@ -0,0 +1,298 @@
/*
* 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/>.
*/
#pragma once
#include <stdint.h>
#include "buffer.h"
#include "color.h"
enum class GameType
{
Aim1,
Aim2
};
extern GameType gameType;
struct vector3
{
float x = 0;
float y = 0;
float z = 0;
};
struct Vector4
{
float x = 0;
float y = 0;
float z = 0;
float w = 0;
};
enum class WeatherType : uint32_t
{
rain = 0x1,
snow = 0x2,
storm = 0x4,
};
enum class SmokeType : uint32_t
{
none,
exp,
biexp,
linear,
};
struct weather
{
struct atmospheric_effects
{
vector3 wind;
WeatherType weatherType;
float strength;
float duration;
float probability;
};
char name[0x20];
char unk0[0x20];
uint32_t unk1[2];
color smoke_1; //3?
color smoke_3; //1?
SmokeType smokeType;
uint32_t unk2[3];
char cloud_layer1[0x20];
char cloud_layer2[0x20];
float cloud_layer1_speed;
float cloud_layer2_speed;
vector3 cloud_layer1_direction;
vector3 cloud_layer2_direction;
char sun[0x20];
color general_color;
color sun_color;
color moon_color;
char moon[0x20];
float probability;
char day_night_gradient_name[0x20];
char dawn_dusk_gradient_name[0x20];
color dawn_dusk_color;
atmospheric_effects effects;
color smoke_2;
color smoke_4;
uint32_t slider_3;
uint32_t slider_1;
float unk8[11];
void load(buffer &b);
};
struct weather_group
{
uint32_t n_segs;
char name[0xA0];
std::vector<weather> segments;
void load(buffer &b);
};
struct water
{
float unk0[6];
char name1[0x20];
uint32_t unk1;
float unk2;
uint32_t unk3[16];
float unk4;
char name2[0x20];
uint32_t unk5[16];
void load(buffer &b);
};
struct water_group
{
std::vector<water> segments;
void load(buffer &b);
};
struct Good
{
char name[0x20];
char unk1[0x40];
float unk1_2 = 0;
float price = 0;
float unk2[10];
float unk2_1[2];
uint32_t unk2_2[2];
void load(buffer &b)
{
READ(b, name);
if (gameType == GameType::Aim1)
READ(b, unk1);
else
READ(b, unk1_2);
READ(b, price);
if (gameType == GameType::Aim1)
READ(b, unk2);
else
{
READ(b, unk2_1);
READ(b, unk2_2);
}
}
};
struct BuildingGoods
{
char name[0x20];
uint32_t n = 0;
std::vector<Good> goods;
void load(buffer &b)
{
READ(b, name);
READ(b, n);
for (int i = 0; i < n; i++)
{
Good g;
g.load(b);
goods.push_back(g);
}
}
};
struct MapMusic
{
char name1[0x20];
char name2[0x20];
uint32_t n1 = 0;
std::vector<std::string> names1;
uint32_t n2 = 0;
std::vector<std::string> names2;
void load(buffer &b)
{
READ(b, name1);
READ(b, name2);
READ(b, n1);
for (int i = 0; i < n1; i++)
{
char name[0x20];
READ(b, name);
names1.push_back(name);
}
READ(b, n2);
for (int i = 0; i < n2; i++)
{
char name[0x20];
READ(b, name);
names2.push_back(name);
}
}
};
struct OrganizationConfig
{
uint32_t n_configs = 0;
std::vector<std::string> configs;
void load(buffer &b)
{
READ(b, n_configs);
configs.resize(n_configs, std::string(0x20, 0));
for (int i = 0; i < n_configs; i++)
READ_N(b, configs[i][0], 0x20);
}
};
struct Organization
{
uint32_t unk0 = 0;
char name[0x20];
char unk1[0xE0];
OrganizationConfig configs[3];
void load(buffer &b)
{
READ(b, unk0);
READ(b, name);
READ(b, unk1);
for (auto &c : configs)
c.load(b);
}
};
struct Organizations
{
uint32_t len = 0;
uint32_t n = 0;
std::vector<Organization> organizations;
void load(buffer &b)
{
READ(b, len);
READ(b, n);
for (int i = 0; i < n; i++)
{
Organization s;
s.load(b);
organizations.push_back(s);
}
}
};
struct OrganizationBase
{
char base_name[0x20];
char org_name[0x20];
uint32_t unk0 = 0;
void load(buffer &b)
{
READ(b, base_name);
READ(b, org_name);
READ(b, unk0);
}
};
struct OrganizationBases
{
uint32_t n = 0;
std::vector<OrganizationBase> organizationBases;
void load(buffer &b)
{
READ(b, n);
for (int i = 0; i < n; i++)
{
OrganizationBase s;
s.load(b);
organizationBases.push_back(s);
}
}
};

View file

@ -87,8 +87,14 @@ void value::load_fields(const tab &tab, buffer &b)
while (!data.eof()) while (!data.eof())
{ {
field_value fv; field_value fv;
if (READ_NOTHROW(data, fv.field_id) == 0) try
{
READ(data, fv.field_id);
}
catch (std::exception &)
{
break; break;
}
READ(data, 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())

View file

@ -27,19 +27,19 @@
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include <math.h> #include <math.h>
#include "objects.h" #include <objects.h>
#include "other.h" #include "other.h"
#include <Polygon4/Storage.h> #include <Polygon4/Storage.h>
#include <buffer.h> #include <buffer.h>
#include <types.h>
#define RAD2GRAD(x) (x) = (x) / M_PI * 180.0 #define RAD2GRAD(x) (x) = (x) / M_PI * 180.0
using namespace std; using namespace std;
std::string prefix; std::string prefix;
GameType gameType;
struct storage struct storage
{ {
@ -47,6 +47,7 @@ struct storage
Objects objects; Objects objects;
MechGroups mechGroups; MechGroups mechGroups;
MapGoods mapGoods; MapGoods mapGoods;
uint32_t unk0 = 0;
MapMusic mapMusic; MapMusic mapMusic;
MapSounds mapSounds; MapSounds mapSounds;
// aim2 // aim2
@ -61,6 +62,7 @@ struct storage
if (b.eof()) // custom maps if (b.eof()) // custom maps
return; return;
mapGoods.load(b); mapGoods.load(b);
READ(b, unk0);
mapMusic.load(b); mapMusic.load(b);
mapSounds.load(b); mapSounds.load(b);
if (gameType == GameType::Aim2) if (gameType == GameType::Aim2)
@ -129,8 +131,8 @@ void write_mmo(string db, const storage &s)
for (auto &seg : s.objects.segments) for (auto &seg : s.objects.segments)
{ {
if (seg->segment_type == SegmentType::SHELL || if (seg->segment_type == ObjectType::BUILDING ||
seg->segment_type == SegmentType::TOWER) seg->segment_type == ObjectType::TOWER)
{ {
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
set<string> objs; set<string> objs;
@ -178,10 +180,10 @@ void write_mmo(string db, const storage &s)
} }
} }
} }
if (seg->segment_type == SegmentType::SURFACE || if (seg->segment_type == ObjectType::TREE ||
seg->segment_type == SegmentType::STONE || seg->segment_type == ObjectType::STONE ||
seg->segment_type == SegmentType::EXPLOSION || seg->segment_type == ObjectType::LAMP ||
seg->segment_type == SegmentType::BOUNDARY) seg->segment_type == ObjectType::BOUNDARY)
{ {
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
set<string> objs; set<string> objs;

View file

@ -25,16 +25,7 @@
#include <vector> #include <vector>
#include <buffer.h> #include <buffer.h>
#include <types.h>
using namespace std;
enum class GameType
{
Aim1,
Aim2
};
extern GameType gameType;
struct MechGroup struct MechGroup
{ {
@ -48,13 +39,13 @@ struct MechGroup
//} //}
//{2 //{2
uint32_t len = 0; uint32_t len = 0;
vector<uint32_t> unk11; std::vector<uint32_t> unk11;
//} //}
//{1,0 //{1,0
uint32_t unk20 = 0; uint32_t unk20 = 0;
uint32_t unk21 = 0; uint32_t unk21 = 0;
//} //}
vector<string> configs; std::vector<std::string> configs;
char unk100; char unk100;
void load(buffer &b) void load(buffer &b)
@ -82,7 +73,7 @@ struct MechGroup
} }
else else
assert(false); assert(false);
configs.resize(len1, string(0x20, 0)); configs.resize(len1, std::string(0x20, 0));
for (int i = 0; i < len1; i++) for (int i = 0; i < len1; i++)
READ_N(b, configs[i][0], 0x20); READ_N(b, configs[i][0], 0x20);
READ(b, unk100); READ(b, unk100);
@ -95,7 +86,7 @@ struct MechGroups
uint32_t n = 0; uint32_t n = 0;
char prefix[0x30]; char prefix[0x30];
vector<MechGroup> mgs; std::vector<MechGroup> mgs;
void load(buffer &b) void load(buffer &b)
{ {
@ -113,51 +104,6 @@ struct MechGroups
} }
}; };
struct Good
{
char name[0x20];
char unk1[0x40];
uint32_t unk1_2 = 0;
float price = 0;
float unk2[10];
float unk2_2[4];
void load(buffer &b)
{
READ(b, name);
if (gameType == GameType::Aim1)
READ(b, unk1);
else
READ(b, unk1_2);
READ(b, price);
if (gameType == GameType::Aim1)
READ(b, unk2);
else
READ(b, unk2_2);
}
};
struct BuildingGoods
{
char name[0x20];
uint32_t n = 0;
vector<Good> goods;
void load(buffer &b)
{
READ(b, name);
READ(b, n);
for (int i = 0; i < n; i++)
{
Good g;
g.load(b);
goods.push_back(g);
}
}
};
struct MapGoods struct MapGoods
{ {
uint32_t length = 0; uint32_t length = 0;
@ -165,7 +111,7 @@ struct MapGoods
uint32_t unk3 = 0; uint32_t unk3 = 0;
uint32_t n = 0; uint32_t n = 0;
vector<BuildingGoods> bgs; std::vector<BuildingGoods> bgs;
void load(buffer &b) void load(buffer &b)
{ {
@ -186,42 +132,6 @@ struct MapGoods
} }
}; };
struct MapMusic
{
uint32_t unk1 = 0;
char name1[0x20];
char name2[0x20];
uint32_t n1 = 0;
vector<string> names1;
uint32_t n2 = 0;
vector<string> names2;
void load(buffer &b)
{
READ(b, unk1);
READ(b, name1);
READ(b, name2);
READ(b, n1);
for (int i = 0; i < n1; i++)
{
char name[0x20];
READ(b, name);
names1.push_back(name);
}
READ(b, n2);
for (int i = 0; i < n2; i++)
{
char name[0x20];
READ(b, name);
names2.push_back(name);
}
}
};
struct MapSound struct MapSound
{ {
char name[0x20]; char name[0x20];
@ -241,7 +151,7 @@ struct MapSound
struct MapSounds struct MapSounds
{ {
uint32_t n = 0; uint32_t n = 0;
vector<MapSound> sounds; std::vector<MapSound> sounds;
void load(buffer &b) void load(buffer &b)
{ {
@ -255,87 +165,6 @@ struct MapSounds
} }
}; };
struct OrganizationConfig
{
uint32_t n_configs = 0;
vector<string> configs;
void load(buffer &b)
{
READ(b, n_configs);
configs.resize(n_configs, string(0x20, 0));
for (int i = 0; i < n_configs; i++)
READ_N(b, configs[i][0], 0x20);
}
};
struct Organization
{
uint32_t unk0 = 0;
char name[0x20];
char unk1[0xE0];
OrganizationConfig configs[3];
void load(buffer &b)
{
READ(b, unk0);
READ(b, name);
READ(b, unk1);
for (auto &c : configs)
c.load(b);
}
};
struct Organizations
{
uint32_t len = 0;
uint32_t n = 0;
vector<Organization> organizations;
void load(buffer &b)
{
READ(b, len);
READ(b, n);
for (int i = 0; i < n; i++)
{
Organization s;
s.load(b);
organizations.push_back(s);
}
}
};
struct OrganizationBase
{
char base_name[0x20];
char org_name[0x20];
uint32_t unk0 = 0;
void load(buffer &b)
{
READ(b, base_name);
READ(b, org_name);
READ(b, unk0);
}
};
struct OrganizationBases
{
uint32_t n = 0;
vector<OrganizationBase> organizationBases;
void load(buffer &b)
{
READ(b, n);
for (int i = 0; i < n; i++)
{
OrganizationBase s;
s.load(b);
organizationBases.push_back(s);
}
}
};
struct Price struct Price
{ {
char tov_name[0x20]; char tov_name[0x20];
@ -356,7 +185,7 @@ struct BuildingPrice
{ {
char name[0x20]; char name[0x20];
uint32_t n_tov = 0; uint32_t n_tov = 0;
vector<Price> prices; std::vector<Price> prices;
void load(buffer &b) void load(buffer &b)
{ {
@ -374,9 +203,9 @@ struct BuildingPrice
struct BuildingPrices struct BuildingPrices
{ {
uint32_t n_tov = 0; uint32_t n_tov = 0;
vector<Price> prices; std::vector<Price> prices;
uint32_t n_bases = 0; uint32_t n_bases = 0;
vector<BuildingPrice> buildingPrices; std::vector<BuildingPrice> buildingPrices;
void load(buffer &b) void load(buffer &b)
{ {

View file

@ -24,65 +24,12 @@
void water_segment::load(buffer &b) void water_segment::load(buffer &b)
{ {
while (!b.eof()) wg.load(b);
{
water w;
w.load(b);
segments.push_back(w);
}
}
void water::load(buffer &b)
{
READ(b, unk0);
READ(b, name1);
READ(b, unk1);
READ(b, unk2);
READ(b, unk3);
READ(b, unk4);
READ(b, name2);
READ(b, unk5);
} }
void weather_segment::load(buffer &b) void weather_segment::load(buffer &b)
{ {
READ(b, n_segs); wg.load(b);
segments.resize(n_segs);
READ(b, name);
for (auto &s : segments)
s.load(b);
}
void weather::load(buffer &b)
{
READ(b, name);
READ(b, unk0);
READ(b, unk1);
READ(b, smoke_1);
READ(b, smoke_3);
READ(b, smokeType);
READ(b, unk2);
READ(b, cloud_layer1);
READ(b, cloud_layer2);
READ(b, cloud_layer1_speed);
READ(b, cloud_layer2_speed);
READ(b, cloud_layer1_direction);
READ(b, cloud_layer2_direction);
READ(b, sun);
READ(b, general_color);
READ(b, sun_color);
READ(b, moon_color);
READ(b, moon);
READ(b, probability);
READ(b, day_night_gradient_name);
READ(b, dawn_dusk_gradient_name);
READ(b, dawn_dusk_color);
READ(b, effects);
READ(b, smoke_2);
READ(b, smoke_4);
READ(b, slider_3);
READ(b, slider_1);
READ(b, unk8);
} }
header_segment *header::create_segment(buffer &b) header_segment *header::create_segment(buffer &b)
@ -183,8 +130,6 @@ void mmp::loadTextureNames(const std::string &fn)
void mmp::process() void mmp::process()
{ {
int k = segment::len;
for (auto &s : segments) for (auto &s : segments)
{ {
for (auto &i : s.d.Infomap) for (auto &i : s.d.Infomap)
@ -212,43 +157,50 @@ void mmp::process()
} }
alpha_maps[0] = mat<uint32_t>(h.width, h.height); alpha_maps[0] = mat<uint32_t>(h.width, h.height);
for (auto &t : textures_map) for (auto &t : textures_map)
{
alpha_maps[t.second.g] = mat<uint32_t>(h.width, h.height); alpha_maps[t.second.g] = mat<uint32_t>(h.width, h.height);
}
// merge // merge
heightmap = decltype(heightmap)(h.width, h.height); heightmap = decltype(heightmap)(h.width, h.height);
texmap = decltype(texmap)(h.width, h.height); texmap = decltype(texmap)(h.width, h.height);
texmap_colored = decltype(texmap_colored)(h.width, h.height); texmap_colored = decltype(texmap_colored)(h.width, h.height);
colormap = decltype(colormap)(h.width, h.height); colormap = decltype(colormap)(h.width, h.height);
for (int y = 0; y < h.height; y++)
h_min = std::numeric_limits<Height>::max();
h_max = std::numeric_limits<Height>::min();
for (auto &s : segments)
{ {
auto ys = y / k * xsegs; const auto &data = s.d;
auto yc = y % k * k; int y1 = s.desc.Ymin / 10;
for (int x = 0; x < h.width; x++) int y2 = s.desc.Ymax / 10;
if (y2 > h.height)
y2 = h.height;
for (int y = 0; y1 < y2; y1++, y++)
{ {
auto xs = x / k; int x1 = s.desc.Xmin / 10;
auto xc = x % k; int x2 = s.desc.Xmax / 10;
auto y_rev = h.height - y - 1; auto dx = x2 - x1;
const auto &data = segments[ys + xs].d; if (x2 > h.width)
auto height = data.Heightmap[yc + xc]; x2 = h.width;
auto t = data.Infomap[yc + xc].getTexture(); for (int x = 0; x1 < x2; x1++, x++)
auto t_norm = textures_map.find(t);
if (t_norm != textures_map.end())
{ {
texmap(y_rev, x) = t_norm->second; auto p = y * dx + x;
alpha_maps[t_norm->second.g](y_rev, x) = color{ 0,255,0,0 }; auto y_rev = h.height - y1 - 1; // for bmp reversion
} //auto y_rev = y1;
texmap_colored(y_rev, x) = textures_map_colored[t]; auto t = data.Infomap[p].getTexture();
colormap(y_rev, x) = data.Colormap[yc + xc]; auto t_norm = textures_map.find(t);
if (t_norm != textures_map.end())
{
texmap(y_rev, x1) = t_norm->second;
alpha_maps[t_norm->second.g](y_rev, x1) = color{ 0,255,0,0 };
}
if (x == 0 && y == 0) texmap_colored(y_rev, x1) = textures_map_colored[t];
{ colormap(y_rev, x1) = data.Colormap[p];
h_min = height;
h_max = height; auto height = data.Heightmap[p];
}
else
{
h_min = std::min(h_min, height); h_min = std::min(h_min, height);
h_max = std::max(h_max, height); h_max = std::max(h_max, height);
} }
@ -257,18 +209,31 @@ void mmp::process()
alpha_maps.erase(0); alpha_maps.erase(0);
scale16 = 0xffff / (h_max - h_min); scale16 = 0xffff / (h_max - h_min);
const int unreal_koef = 51200;
const int aim_koef = 10;
const double diff = h_max - h_min;
const double scale = aim_koef / (unreal_koef / diff);
for (int y = 0; y < h.height; y++) for (auto &s : segments)
{ {
auto ys = y / k * xsegs; int y1 = s.desc.Ymin / 10;
auto yc = y % k * k; int y2 = s.desc.Ymax / 10;
for (int x = 0; x < h.width; x++) if (y2 > h.height)
y2 = h.height;
for (int y = 0; y1 < y2; y1++, y++)
{ {
auto xs = x / k; int x1 = s.desc.Xmin / 10;
auto xc = x % k; int x2 = s.desc.Xmax / 10;
auto height = segments[ys + xs].d.Heightmap[yc + xc]; auto dx = x2 - x1;
auto val = (height - h_min) * scale16; if (x2 > h.width)
heightmap(y, x) = val; x2 = h.width;
for (int x = 0; x1 < x2; x1++, x++)
{
auto height = s.d.Heightmap[y * dx + x];
auto val = (height - h_min) * scale16 * scale;
auto &old_height = heightmap(y1, x1);
old_height = val;
}
} }
} }
} }

View file

@ -25,28 +25,9 @@
#include <buffer.h> #include <buffer.h>
#include <color.h> #include <color.h>
#include <mat.h> #include <mat.h>
#include <types.h>
enum class WeatherType : uint32_t using Height = float;
{
rain = 0x1,
snow = 0x2,
storm = 0x4,
};
enum class SmokeType : uint32_t
{
none,
exp,
biexp,
linear,
};
struct direction
{
float x;
float y;
float z;
};
enum class HeaderSegmentType : uint32_t enum class HeaderSegmentType : uint32_t
{ {
@ -63,75 +44,16 @@ struct header_segment
virtual void load(buffer &b) = 0; virtual void load(buffer &b) = 0;
}; };
struct water
{
float unk0[6];
char name1[0x20];
uint32_t unk1;
float unk2;
uint32_t unk3[16];
float unk4;
char name2[0x20];
uint32_t unk5[16];
void load(buffer &b);
};
struct water_segment : public header_segment struct water_segment : public header_segment
{ {
std::vector<water> segments; water_group wg;
virtual void load(buffer &b) override; virtual void load(buffer &b) override;
}; };
struct weather
{
struct atmospheric_effects
{
direction wind;
WeatherType weatherType;
float strength;
float duration;
float probability;
};
char name[0x20];
char unk0[0x20];
uint32_t unk1[2];
color smoke_1; //3?
color smoke_3; //1?
SmokeType smokeType;
uint32_t unk2[3];
char cloud_layer1[0x20];
char cloud_layer2[0x20];
float cloud_layer1_speed;
float cloud_layer2_speed;
direction cloud_layer1_direction;
direction cloud_layer2_direction;
char sun[0x20];
color general_color;
color sun_color;
color moon_color;
char moon[0x20];
float probability;
char day_night_gradient_name[0x20];
char dawn_dusk_gradient_name[0x20];
color dawn_dusk_color;
atmospheric_effects effects;
color smoke_2;
color smoke_4;
uint32_t slider_3;
uint32_t slider_1;
float unk8[11];
void load(buffer &b);
};
struct weather_segment : public header_segment struct weather_segment : public header_segment
{ {
uint32_t n_segs; weather_group wg;
char name[0xA0];
std::vector<weather> segments;
virtual void load(buffer &b) override; virtual void load(buffer &b) override;
}; };
@ -188,17 +110,26 @@ struct segment
int16_t x; int16_t x;
int16_t y; int16_t y;
}; };
struct old_data struct mini_lod
{ {
uint16_t Heightmap[1089 * 2]; static const int len = 33;
color Colormap[1089]; static const int size = len * len;
uint32_t unk0[1089];
normal unk1[1089]; // normals? 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; uint32_t MagicNumber;
old_data old; mini_lod mlod;
float Heightmap[size]; Height Heightmap[size];
info Infomap[size]; info Infomap[size];
color Colormap[size]; color Colormap[size];
shadow Shadowmap[size]; shadow Shadowmap[size];
@ -225,9 +156,9 @@ struct mmp
std::map<int, mat<uint32_t>> alpha_maps; std::map<int, mat<uint32_t>> alpha_maps;
std::map<int, color> textures_map_colored; std::map<int, color> textures_map_colored;
std::map<int, std::string> textures_names; std::map<int, std::string> textures_names;
float h_min; Height h_min;
float h_max; Height h_max;
float scale16 = 0; double scale16 = 0;
mat<uint16_t> heightmap; mat<uint16_t> heightmap;
mat<uint32_t> texmap; mat<uint32_t> texmap;
mat<uint32_t> texmap_colored; mat<uint32_t> texmap_colored;

224
src/mpj_loader/mpj.cpp Normal file
View file

@ -0,0 +1,224 @@
/*
* AIM mpj_loader
* 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 "mpj.h"
#include <algorithm>
#include <assert.h>
#include <fstream>
#include <iomanip>
segment *segment::create_segment(buffer &b)
{
SegmentType type;
READ(b, type);
if (type == SegmentType::none)
READ(b, type);
segment *segment = nullptr;
switch (type)
{
case SegmentType::MapData:
segment = new map_data;
break;
case SegmentType::Surface:
segment = new surface;
break;
case SegmentType::Weather:
segment = new weather_data;
break;
case SegmentType::Objects:
segment = new objects_data;
break;
case SegmentType::Water:
segment = new water_data;
break;
case SegmentType::unk7:
segment = new segment7;
break;
case SegmentType::unk9:
segment = new segment9;
break;
case SegmentType::BuildingGoods:
segment = new building_goods;
break;
case SegmentType::MapMusic:
segment = new map_music;
break;
case SegmentType::Organizations:
segment = new organizations;
break;
case SegmentType::Goods:
segment = new gliders_n_goods;
break;
default:
assert(false);
break;
}
if (segment)
{
segment->type = type;
READ(b, segment->unk0);
READ(b, segment->size);
}
return segment;
}
void map_data::load(buffer &b)
{
auto sz = b.size();
assert(sz % 3 == 0);
sz /= 3;
#define READ_SEG(v) \
v.resize(sz / sizeof(decltype(v)::value_type)); \
READ_N(b, v[0], v.size())
READ_SEG(unk1);
READ_SEG(unk2);
READ_SEG(unk3);
#undef READ_SEG
}
void surface::load(buffer &b)
{
while (!b.eof())
{
value v;
READ(b, v);
unk1.push_back(v);
}
}
void weather_data::load(buffer &b)
{
wg.load(b);
}
void objects_data::load(buffer &b)
{
objects.load(b);
}
void segment7::load(buffer &b)
{
auto n = b.size() / sizeof(decltype(data)::value_type);
data.resize(n);
READ_N(b, data[0], n);
}
void water_data::load(buffer &b)
{
wg.load(b);
}
void segment9::load(buffer &b)
{
auto n = b.size() / sizeof(decltype(data)::value_type);
data.resize(n);
READ_N(b, data[0], n);
}
void building_goods::load(buffer &b)
{
READ(b, unk1);
READ(b, n);
bgs.resize(n);
for (auto &bg : bgs)
bg.load(b);
}
void map_music::load(buffer &b)
{
while (!b.eof())
{
MapMusic mm;
mm.load(b);
mms.push_back(mm);
READ(b, unk1); // or read after cycle?
}
}
void organizations::load(buffer &b)
{
READ(b, n);
orgs.resize(n);
for (auto &org : orgs)
org.load(b);
bases.load(b);
}
void gliders_n_goods::load(buffer &b)
{
READ(b, n_good_groups);
READ(b, n_gliders);
gliders.resize(n_gliders);
for (auto &g : gliders)
g.load(b);
READ(b, unk1);
goods.resize(n_good_groups);
for (auto &g : goods)
g.load(b);
}
void header::load(buffer &b)
{
READ(b, magic);
if (memcmp(magic, "MPRJ", 4) != 0)
throw std::runtime_error("This file is not a mechanoid project");
READ(b, unk0);
READ(b, unk1);
READ(b, unk2);
READ(b, unk3);
READ(b, width);
READ(b, height);
READ(b, unk4);
auto seg_size = 64;
auto xsegs = width / seg_size;
if ((width - 1) % 64 != 0)
xsegs++;
auto ysegs = height / seg_size;
if ((width - 1) % 64 != 0)
ysegs++;
while (!b.eof())
{
auto seg = segment::create_segment(b);
if (!seg)
break;
seg->load(buffer(b, seg->size));
segments.push_back(seg);
}
if (!b.eof())
{
throw std::logic_error("End of file was not reached");
}
}
void mpj::load(buffer &b)
{
h.load(b);
}
void mpj::load(const std::string &fn)
{
filename = fn;
buffer b(readFile(filename));
load(b);
}

211
src/mpj_loader/mpj.h Normal file
View file

@ -0,0 +1,211 @@
/*
* AIM mpj_loader
* 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 <map>
#include <set>
#include <stdint.h>
#include <string>
#include <vector>
#include <buffer.h>
#include <objects.h>
#include <types.h>
enum class SegmentType : uint32_t
{
none = 0,
MapData = 1,
Surface = 2,
Weather = 4,
Objects = 6,
unk7 = 7,
Water = 8,
unk9 = 9,
BuildingGoods = 10,
MapMusic = 11,
Organizations = 12,
Goods = 13,
};
struct segment
{
SegmentType type;
uint32_t unk0;
uint32_t size;
virtual ~segment() {}
static segment *create_segment(buffer &b);
virtual void load(buffer &b) = 0;
};
struct map_data : public segment
{
std::vector<float> unk1;
std::vector<uint32_t> unk2;
std::vector<uint32_t> unk3;
virtual void load(buffer &b) override;
};
struct surface : public segment
{
struct value
{
char name[0x20];
uint32_t unk0;
};
std::vector<value> unk1;
virtual void load(buffer &b) override;
};
struct weather_data : public segment
{
weather_group wg;
virtual void load(buffer &b) override;
};
struct objects_data : public segment
{
Objects objects;
virtual void load(buffer &b) override;
};
struct segment7 : public segment
{
std::vector<uint32_t> data;
virtual void load(buffer &b) override;
};
struct water_data : public segment
{
water_group wg;
virtual void load(buffer &b) override;
};
struct segment9 : public segment
{
std::vector<uint32_t> data;
virtual void load(buffer &b) override;
};
struct building_goods : public segment
{
struct bg_internal
{
BuildingGoods bg;
uint32_t unk0;
void load(buffer &b)
{
bg.load(b);
READ(b, unk0);
}
};
uint32_t unk1; // record format? aim2 ?
uint32_t n;
std::vector<bg_internal> bgs;
virtual void load(buffer &b) override;
};
struct map_music : public segment
{
std::vector<MapMusic> mms;
uint32_t unk1;
virtual void load(buffer &b) override;
};
struct organizations : public segment
{
uint32_t n;
std::vector<Organization> orgs;
OrganizationBases bases;
virtual void load(buffer &b) override;
};
struct gliders_n_goods : public segment
{
struct Good
{
char name[0x20];
int unk0[3];
void load(buffer &b)
{
READ(b, name);
READ(b, unk0);
}
};
struct Goods
{
uint32_t n_goods;
std::vector<Good> goods;
void load(buffer &b)
{
READ(b, n_goods);
goods.resize(n_goods);
for (auto &g : goods)
g.load(b);
}
};
uint32_t n_good_groups;
uint32_t n_gliders;
std::vector<Good> gliders;
uint32_t unk1;
std::vector<Goods> goods;
virtual void load(buffer &b) override;
};
struct header
{
char magic[4];
uint32_t unk0;
uint32_t unk1;
uint32_t unk2;
uint32_t unk3;
uint32_t width;
uint32_t height;
char unk4[0x3F4];
std::vector<segment*> segments;
void load(buffer &b);
};
struct mpj
{
header h;
//
std::string filename;
void load(buffer &b);
void load(const std::string &filename);
};

View file

@ -0,0 +1,50 @@
/*
* AIM mpj_loader
* 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 <iostream>
#include <set>
#include <stdint.h>
#include <string>
#include <sstream>
#include "mpj.h"
using namespace std;
int main(int argc, char *argv[])
try
{
if (argc != 2)
{
cout << "Usage:\n" << argv[0] << " file.mpj" << "\n";
return 1;
}
mpj m;
m.load(argv[1]);
return 0;
}
catch (std::exception &e)
{
printf("error: %s\n", e.what());
return 1;
}
catch (...)
{
printf("error: unknown exception\n");
return 1;
}