From e1e46a3b75b4f174a8f3f79a076181e5221d2868 Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Thu, 22 Oct 2015 19:34:26 +0300 Subject: [PATCH] Fix mmp extractor. Add mpj loader. Some fixes in buffer class. --- src/CMakeLists.txt | 6 + src/common/buffer.cpp | 55 ++-- src/common/buffer.h | 40 ++- src/common/color.h | 2 + src/common/mat.h | 30 +-- src/{mmo_extractor => common}/objects.cpp | 41 ++- src/{mmo_extractor => common}/objects.h | 91 +++---- src/common/types.cpp | 84 ++++++ src/common/types.h | 298 ++++++++++++++++++++++ src/db_extractor/db.cpp | 8 +- src/mmo_extractor/mmo_extractor.cpp | 18 +- src/mmo_extractor/other.h | 191 +------------- src/mmp_extractor/mmp.cpp | 147 ++++------- src/mmp_extractor/mmp.h | 115 ++------- src/mpj_loader/mpj.cpp | 224 ++++++++++++++++ src/mpj_loader/mpj.h | 211 +++++++++++++++ src/mpj_loader/mpj_loader.cpp | 50 ++++ 17 files changed, 1106 insertions(+), 505 deletions(-) rename src/{mmo_extractor => common}/objects.cpp (75%) rename src/{mmo_extractor => common}/objects.h (71%) create mode 100644 src/common/types.cpp create mode 100644 src/common/types.h create mode 100644 src/mpj_loader/mpj.cpp create mode 100644 src/mpj_loader/mpj.h create mode 100644 src/mpj_loader/mpj_loader.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 89c8bcc..2b6732e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ endif() file(GLOB script2txt_src "script2txt/*") add_executable(script2txt ${script2txt_src}) + if (DATABASE_MANAGER_DIR) file(GLOB mmm_extractor_src "mmm_extractor/*") 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) endif() + file(GLOB mmp_extractor_src "mmp_extractor/*") add_executable(mmp_extractor ${mmp_extractor_src}) target_link_libraries(mmp_extractor common) @@ -30,6 +32,10 @@ file(GLOB mod_converter_src "mod_converter/*") add_executable(mod_converter ${mod_converter_src}) 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/*") add_executable(tm_converter ${tm_converter_src}) target_link_libraries(tm_converter common) diff --git a/src/common/buffer.cpp b/src/common/buffer.cpp index 05aeefc..a154f42 100644 --- a/src/common/buffer.cpp +++ b/src/common/buffer.cpp @@ -78,6 +78,7 @@ buffer::buffer(const std::vector &buf, uint32_t data_offset) { skip(0); size_ = buf_->size(); + end_ = index_ + size_; } buffer::buffer(buffer &rhs, uint32_t size) @@ -86,7 +87,8 @@ buffer::buffer(buffer &rhs, uint32_t size) index_ = rhs.index_; data_offset = rhs.data_offset; ptr = rhs.ptr; - size_ = index_ + size; + size_ = size; + end_ = index_ + size_; rhs.skip(size); } @@ -95,62 +97,39 @@ buffer::buffer(buffer &rhs, uint32_t size, uint32_t offset) { index_ = offset; data_offset = offset; + size_ = size; 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_) throw std::logic_error("buffer: not initialized"); - if (index_ >= size_) - { - if (nothrow) - return 0; + if (index_ >= end_) throw std::logic_error("buffer: out of range"); - } - if (index_ + size > size_) - { - if (!nothrow) - throw std::logic_error("buffer: too much data"); - size = size_ - index_; - } - memcpy(dst, buf_->data() + index_, size); - skip(size); + if (index_ + offset + size > end_) + throw std::logic_error("buffer: too much data"); + memcpy(dst, buf_->data() + index_ + offset, size); + skip(size + offset); return size; } -uint32_t buffer::readfrom(void *dst, uint32_t size, uint32_t offset, bool nothrow) const -{ - 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) +uint32_t buffer::_write(const void *src, uint32_t size) { if (!buf_) { buf_ = std::make_shared>(size); size_ = buf_->size(); + end_ = index_ + size_; } - if (index_ > size_) - { - if (nothrow) - return 0; + if (index_ > end_) throw std::logic_error("buffer: out of range"); - } - if (index_ + size > size_) + if (index_ + size > end_) { buf_->resize(index_ + size); size_ = buf_->size(); + end_ = index_ + size_; } memcpy((uint8_t *)buf_->data() + index_, src, size); skip(size); @@ -186,7 +165,7 @@ bool buffer::check(int index) const bool buffer::eof() const { - return check(size_); + return index_ == end_; } uint32_t buffer::index() const diff --git a/src/common/buffer.h b/src/common/buffer.h index 811cfa5..1efb9f9 100644 --- a/src/common/buffer.h +++ b/src/common/buffer.h @@ -23,10 +23,9 @@ #include #include -#define READ(b, var) b.read(&var, sizeof(var)) -#define READ_NOTHROW(b, var) b.read(&var, sizeof(var), true) +#define READ(b, var) b.read(&var) #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::vector readFile(const std::string &fn); @@ -41,13 +40,36 @@ public: 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) const; - uint32_t readfrom(void *dst, uint32_t size, uint32_t offset, bool nothrow = false) const; - uint32_t write(const void *src, uint32_t size, bool nothrow = false); + template + uint32_t read(T *dst) const + { + return _read(dst, sizeof(T), 0); + } + template + uint32_t read(T *dst, uint32_t size) const + { + return _read(dst, size * sizeof(T), 0); + } + template + uint32_t readfrom(T *dst, uint32_t size, uint32_t offset) const + { + return _read(dst, size * sizeof(T), offset); + } + template uint32_t write(const T &src) { - return write(&src, sizeof(src)); + return _write(&src, sizeof(T)); + } + template + uint32_t write(const T *src, uint32_t size) + { + return _write(src, size * sizeof(T)); + } + template + uint32_t write(const T *src) + { + return _write(src, sizeof(T)); } void seek(uint32_t size) const; @@ -66,4 +88,8 @@ private: mutable uint8_t *ptr = 0; mutable uint32_t data_offset = 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); }; diff --git a/src/common/color.h b/src/common/color.h index d73d2e7..357577d 100644 --- a/src/common/color.h +++ b/src/common/color.h @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#pragma once + #include typedef uint16_t color_rgb565; diff --git a/src/common/mat.h b/src/common/mat.h index a555056..30af547 100644 --- a/src/common/mat.h +++ b/src/common/mat.h @@ -74,22 +74,22 @@ void write_mat_bmp(const std::string &filename, const mat &m) return; BITMAPFILEHEADER h = { 0 }; h.bfType = 0x4D42; - h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + m.size() * sizeof(T); - h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO); - BITMAPINFO i = { 0 }; - i.bmiHeader.biSize = sizeof(i.bmiHeader); - i.bmiHeader.biWidth = m.getWidth(); - i.bmiHeader.biHeight = m.getHeight(); - i.bmiHeader.biPlanes = 1; - i.bmiHeader.biBitCount = sizeof(T) * 8; - i.bmiHeader.biCompression = 0; - i.bmiHeader.biSizeImage = 0; - i.bmiHeader.biXPelsPerMeter = 0; - i.bmiHeader.biYPelsPerMeter = 0; - i.bmiHeader.biClrUsed = 0; - i.bmiHeader.biClrImportant = 0; + h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + m.size() * sizeof(T); + h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + BITMAPINFOHEADER i = { 0 }; + i.biSize = sizeof(i); + i.biWidth = m.getWidth(); + i.biHeight = m.getHeight(); + i.biPlanes = 1; + i.biBitCount = sizeof(T) * 8; + i.biCompression = 0; + i.biSizeImage = 0; + i.biXPelsPerMeter = 0; + i.biYPelsPerMeter = 0; + i.biClrUsed = 0; + i.biClrImportant = 0; 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); fclose(f); } diff --git a/src/mmo_extractor/objects.cpp b/src/common/objects.cpp similarity index 75% rename from src/mmo_extractor/objects.cpp rename to src/common/objects.cpp index a1d6efd..c6d2df7 100644 --- a/src/mmo_extractor/objects.cpp +++ b/src/common/objects.cpp @@ -20,55 +20,52 @@ Segment *Segment::create_segment(buffer &b) { - SegmentType segment_type; + ObjectType segment_type; READ(b, segment_type); Segment *segment = 0; switch (segment_type) { - case SegmentType::ROAD: + case ObjectType::ROAD: segment = new SegmentObjects; break; - case SegmentType::BUILDING: + case ObjectType::BUILDING: segment = new SegmentObjects; break; - case SegmentType::SURFACE: - segment = new SegmentObjects; + case ObjectType::TREE: + segment = new SegmentObjects; break; - case SegmentType::STONE: + case ObjectType::STONE: segment = new SegmentObjects; break; - case SegmentType::HELPER: + case ObjectType::HELPER: segment = new SegmentObjects; break; - case SegmentType::SHELL: - segment = new SegmentObjects; - break; - case SegmentType::IMAGE: + case ObjectType::IMAGE: segment = new SegmentObjects; break; - case SegmentType::EXPLOSION: - segment = new SegmentObjects; + case ObjectType::LAMP: + segment = new SegmentObjects; break; - case SegmentType::SOUND: + case ObjectType::SOUND: segment = new SegmentObjects; break; - case SegmentType::ANOMALY: + case ObjectType::ANOMALY: segment = new SegmentObjects; break; - case SegmentType::TOWER: + case ObjectType::TOWER: segment = new SegmentObjects; break; - case SegmentType::BOUNDARY: + case ObjectType::BOUNDARY: segment = new SegmentObjects; break; - case SegmentType::GOODS: - segment = new SegmentObjects; - break; - case SegmentType::SOUND_ZONE: + case ObjectType::SOUND_ZONE: segment = new SegmentObjects; break; - case SegmentType::unk1: + case ObjectType::unk0: + segment = new SegmentObjects; + break; + case ObjectType::unk1: segment = new SegmentObjects; break; default: diff --git a/src/mmo_extractor/objects.h b/src/common/objects.h similarity index 71% rename from src/mmo_extractor/objects.h rename to src/common/objects.h index 91b00e6..41449a7 100644 --- a/src/mmo_extractor/objects.h +++ b/src/common/objects.h @@ -24,49 +24,49 @@ #include #include -#include +#include "buffer.h" +#include "types.h" -using namespace std; - -enum class SegmentType : uint32_t +enum class ObjectType : uint32_t { - TEXTURE = 0x1, - MODEL, - SURFACE, // stones - STONE, // trees - TREE, + TEXTURE = 1, + //MODEL, + //SURFACE, + STONE = 3, + TREE = 4, - GLIDER, - HELPER, - ROAD, - WEAPON, - CONFIG, + //GLIDER, + HELPER = 7, + ROAD = 8, + //WEAPON, + //CONFIG, - SHELL, // buildings + //SHELL, // buildings + BUILDING = 11, IMAGE, - EXPLOSION, // road lights - EQUIPMENT, - ORGANIZATION, + LAMP = 13, + //EXPLOSION, // road lights + //EQUIPMENT, + //ORGANIZATION, - BUILDING, - LAMP, - COVERING, - SOUND, - GOODS, + //COVERING = 18, + SOUND = 19, + //GOODS, // anomaly? + ANOMALY = 20, // radiation? - ANOMALY, - TOWER, - BOUNDARY, - SOUND_ZONE, + unk0 = 21, // anomaly? + TOWER = 22, + BOUNDARY = 23, + SOUND_ZONE = 24, - unk1 = 0x1b, + unk1 = 27, }; struct Segment { - SegmentType segment_type; - uint32_t segment_len = 0; - uint32_t n_objects = 0; + ObjectType segment_type; + uint32_t segment_len = 0; + uint32_t n_objects = 0; virtual ~Segment(){} static Segment *create_segment(buffer &b); @@ -76,7 +76,7 @@ struct Segment template struct SegmentObjects : public Segment { - vector objects; + std::vector objects; 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 { - Vector4 m_rotate_z[3]; - Vector4 position; + Vector4 m_rotate_z[3]; + Vector4 position; void load(buffer &b) { @@ -126,7 +118,7 @@ struct MapObject : public Common struct MapObjectWithArray : public MapObject { uint32_t len = 0; - vector unk0; + std::vector unk0; void load(buffer &b) { @@ -159,13 +151,12 @@ struct Boundary : public MapObjectWithArray {}; #define KNOWN_OBJECT(name) \ struct name : public MapObject {} -KNOWN_OBJECT(Surface); -KNOWN_OBJECT(Helper); -KNOWN_OBJECT(Shell); KNOWN_OBJECT(Stone); -KNOWN_OBJECT(Explosion); +KNOWN_OBJECT(Helper); +KNOWN_OBJECT(Building); +KNOWN_OBJECT(Tree); +KNOWN_OBJECT(Lamp); KNOWN_OBJECT(Image); -KNOWN_OBJECT(Goods); KNOWN_OBJECT(Anomaly); KNOWN_OBJECT(Tower); KNOWN_OBJECT(SoundZone); @@ -173,13 +164,13 @@ KNOWN_OBJECT(SoundZone); #define UNKNOWN_OBJECT(name) \ struct name : public MapObject { void load(buffer &b){ int pos = b.index(); assert(false); } } -UNKNOWN_OBJECT(Building); +UNKNOWN_OBJECT(unk0); UNKNOWN_OBJECT(unk1); struct Objects { uint32_t n_segments = 0; - vector segments; + std::vector segments; void load(buffer &b); }; diff --git a/src/common/types.cpp b/src/common/types.cpp new file mode 100644 index 0000000..ea8559b --- /dev/null +++ b/src/common/types.cpp @@ -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 . +*/ + +#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); + } +} diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..d4a5ac8 --- /dev/null +++ b/src/common/types.h @@ -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 . +*/ + +#pragma once + +#include + +#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 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 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 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 names1; + + uint32_t n2 = 0; + std::vector 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 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 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 organizationBases; + + void load(buffer &b) + { + READ(b, n); + for (int i = 0; i < n; i++) + { + OrganizationBase s; + s.load(b); + organizationBases.push_back(s); + } + } +}; diff --git a/src/db_extractor/db.cpp b/src/db_extractor/db.cpp index 640d4ba..806e104 100644 --- a/src/db_extractor/db.cpp +++ b/src/db_extractor/db.cpp @@ -87,8 +87,14 @@ void value::load_fields(const tab &tab, buffer &b) while (!data.eof()) { field_value fv; - if (READ_NOTHROW(data, fv.field_id) == 0) + try + { + READ(data, fv.field_id); + } + catch (std::exception &) + { break; + } READ(data, fv.size); auto i = tab.fields.find(fv.field_id); if (i == tab.fields.end()) diff --git a/src/mmo_extractor/mmo_extractor.cpp b/src/mmo_extractor/mmo_extractor.cpp index c720adb..d4c9836 100644 --- a/src/mmo_extractor/mmo_extractor.cpp +++ b/src/mmo_extractor/mmo_extractor.cpp @@ -27,19 +27,19 @@ #define _USE_MATH_DEFINES #include -#include "objects.h" +#include #include "other.h" #include #include +#include #define RAD2GRAD(x) (x) = (x) / M_PI * 180.0 using namespace std; std::string prefix; -GameType gameType; struct storage { @@ -47,6 +47,7 @@ struct storage Objects objects; MechGroups mechGroups; MapGoods mapGoods; + uint32_t unk0 = 0; MapMusic mapMusic; MapSounds mapSounds; // aim2 @@ -61,6 +62,7 @@ struct storage if (b.eof()) // custom maps return; mapGoods.load(b); + READ(b, unk0); mapMusic.load(b); mapSounds.load(b); if (gameType == GameType::Aim2) @@ -129,8 +131,8 @@ void write_mmo(string db, const storage &s) for (auto &seg : s.objects.segments) { - if (seg->segment_type == SegmentType::SHELL || - seg->segment_type == SegmentType::TOWER) + if (seg->segment_type == ObjectType::BUILDING || + seg->segment_type == ObjectType::TOWER) { SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; set objs; @@ -178,10 +180,10 @@ void write_mmo(string db, const storage &s) } } } - if (seg->segment_type == SegmentType::SURFACE || - seg->segment_type == SegmentType::STONE || - seg->segment_type == SegmentType::EXPLOSION || - seg->segment_type == SegmentType::BOUNDARY) + if (seg->segment_type == ObjectType::TREE || + seg->segment_type == ObjectType::STONE || + seg->segment_type == ObjectType::LAMP || + seg->segment_type == ObjectType::BOUNDARY) { SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; set objs; diff --git a/src/mmo_extractor/other.h b/src/mmo_extractor/other.h index 8ecd85f..25e9af4 100644 --- a/src/mmo_extractor/other.h +++ b/src/mmo_extractor/other.h @@ -25,16 +25,7 @@ #include #include - -using namespace std; - -enum class GameType -{ - Aim1, - Aim2 -}; - -extern GameType gameType; +#include struct MechGroup { @@ -48,13 +39,13 @@ struct MechGroup //} //{2 uint32_t len = 0; - vector unk11; + std::vector unk11; //} //{1,0 uint32_t unk20 = 0; uint32_t unk21 = 0; //} - vector configs; + std::vector configs; char unk100; void load(buffer &b) @@ -82,7 +73,7 @@ struct MechGroup } else assert(false); - configs.resize(len1, string(0x20, 0)); + configs.resize(len1, std::string(0x20, 0)); for (int i = 0; i < len1; i++) READ_N(b, configs[i][0], 0x20); READ(b, unk100); @@ -95,7 +86,7 @@ struct MechGroups uint32_t n = 0; char prefix[0x30]; - vector mgs; + std::vector mgs; 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 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 { uint32_t length = 0; @@ -165,7 +111,7 @@ struct MapGoods uint32_t unk3 = 0; uint32_t n = 0; - vector bgs; + std::vector bgs; 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 names1; - - uint32_t n2 = 0; - vector 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 { char name[0x20]; @@ -241,7 +151,7 @@ struct MapSound struct MapSounds { uint32_t n = 0; - vector sounds; + std::vector sounds; void load(buffer &b) { @@ -255,87 +165,6 @@ struct MapSounds } }; -struct OrganizationConfig -{ - uint32_t n_configs = 0; - vector 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 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 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 { char tov_name[0x20]; @@ -356,7 +185,7 @@ struct BuildingPrice { char name[0x20]; uint32_t n_tov = 0; - vector prices; + std::vector prices; void load(buffer &b) { @@ -374,9 +203,9 @@ struct BuildingPrice struct BuildingPrices { uint32_t n_tov = 0; - vector prices; + std::vector prices; uint32_t n_bases = 0; - vector buildingPrices; + std::vector buildingPrices; void load(buffer &b) { diff --git a/src/mmp_extractor/mmp.cpp b/src/mmp_extractor/mmp.cpp index 696b6ca..d3d7a37 100644 --- a/src/mmp_extractor/mmp.cpp +++ b/src/mmp_extractor/mmp.cpp @@ -24,65 +24,12 @@ void water_segment::load(buffer &b) { - while (!b.eof()) - { - 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); + wg.load(b); } void weather_segment::load(buffer &b) { - READ(b, n_segs); - 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); + wg.load(b); } header_segment *header::create_segment(buffer &b) @@ -183,8 +130,6 @@ void mmp::loadTextureNames(const std::string &fn) void mmp::process() { - int k = segment::len; - for (auto &s : segments) { for (auto &i : s.d.Infomap) @@ -212,43 +157,50 @@ void mmp::process() } alpha_maps[0] = mat(h.width, h.height); for (auto &t : textures_map) + { alpha_maps[t.second.g] = mat(h.width, h.height); + } // merge heightmap = decltype(heightmap)(h.width, h.height); texmap = decltype(texmap)(h.width, h.height); texmap_colored = decltype(texmap_colored)(h.width, h.height); colormap = decltype(colormap)(h.width, h.height); - for (int y = 0; y < h.height; y++) + + h_min = std::numeric_limits::max(); + h_max = std::numeric_limits::min(); + for (auto &s : segments) { - auto ys = y / k * xsegs; - auto yc = y % k * k; - for (int x = 0; x < h.width; x++) + const auto &data = s.d; + int y1 = s.desc.Ymin / 10; + 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; - auto xc = x % k; - auto y_rev = h.height - y - 1; - const auto &data = segments[ys + xs].d; - auto height = data.Heightmap[yc + xc]; - auto t = data.Infomap[yc + xc].getTexture(); - - auto t_norm = textures_map.find(t); - if (t_norm != textures_map.end()) + int x1 = s.desc.Xmin / 10; + int x2 = s.desc.Xmax / 10; + auto dx = x2 - x1; + if (x2 > h.width) + x2 = h.width; + for (int x = 0; x1 < x2; x1++, x++) { - texmap(y_rev, x) = t_norm->second; - alpha_maps[t_norm->second.g](y_rev, x) = color{ 0,255,0,0 }; - } + auto p = y * dx + x; + auto y_rev = h.height - y1 - 1; // for bmp reversion + //auto y_rev = y1; - texmap_colored(y_rev, x) = textures_map_colored[t]; - colormap(y_rev, x) = data.Colormap[yc + xc]; + auto t = data.Infomap[p].getTexture(); + 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) - { - h_min = height; - h_max = height; - } - else - { + texmap_colored(y_rev, x1) = textures_map_colored[t]; + colormap(y_rev, x1) = data.Colormap[p]; + + auto height = data.Heightmap[p]; h_min = std::min(h_min, height); h_max = std::max(h_max, height); } @@ -257,18 +209,31 @@ void mmp::process() alpha_maps.erase(0); 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; - auto yc = y % k * k; - for (int x = 0; x < h.width; x++) + int y1 = s.desc.Ymin / 10; + 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; - auto xc = x % k; - auto height = segments[ys + xs].d.Heightmap[yc + xc]; - auto val = (height - h_min) * scale16; - heightmap(y, x) = val; + int x1 = s.desc.Xmin / 10; + int x2 = s.desc.Xmax / 10; + auto dx = x2 - x1; + if (x2 > h.width) + 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; + } } } } diff --git a/src/mmp_extractor/mmp.h b/src/mmp_extractor/mmp.h index 8ea1ac6..25b404e 100644 --- a/src/mmp_extractor/mmp.h +++ b/src/mmp_extractor/mmp.h @@ -25,28 +25,9 @@ #include #include #include +#include -enum class WeatherType : uint32_t -{ - rain = 0x1, - snow = 0x2, - storm = 0x4, -}; - -enum class SmokeType : uint32_t -{ - none, - exp, - biexp, - linear, -}; - -struct direction -{ - float x; - float y; - float z; -}; +using Height = float; enum class HeaderSegmentType : uint32_t { @@ -63,75 +44,16 @@ struct header_segment 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 { - std::vector segments; + water_group wg; 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 { - uint32_t n_segs; - char name[0xA0]; - std::vector segments; + weather_group wg; virtual void load(buffer &b) override; }; @@ -188,17 +110,26 @@ struct segment int16_t x; int16_t y; }; - struct old_data + struct mini_lod { - uint16_t Heightmap[1089 * 2]; - color Colormap[1089]; - uint32_t unk0[1089]; - normal unk1[1089]; // normals? + 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; - old_data old; - float Heightmap[size]; + mini_lod mlod; + Height Heightmap[size]; info Infomap[size]; color Colormap[size]; shadow Shadowmap[size]; @@ -225,9 +156,9 @@ struct mmp std::map> alpha_maps; std::map textures_map_colored; std::map textures_names; - float h_min; - float h_max; - float scale16 = 0; + Height h_min; + Height h_max; + double scale16 = 0; mat heightmap; mat texmap; mat texmap_colored; diff --git a/src/mpj_loader/mpj.cpp b/src/mpj_loader/mpj.cpp new file mode 100644 index 0000000..cc7a90c --- /dev/null +++ b/src/mpj_loader/mpj.cpp @@ -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 . + */ + +#include "mpj.h" + +#include +#include +#include +#include + +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); +} \ No newline at end of file diff --git a/src/mpj_loader/mpj.h b/src/mpj_loader/mpj.h new file mode 100644 index 0000000..98c2492 --- /dev/null +++ b/src/mpj_loader/mpj.h @@ -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 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +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 unk1; + std::vector unk2; + std::vector unk3; + + virtual void load(buffer &b) override; +}; + +struct surface : public segment +{ + struct value + { + char name[0x20]; + uint32_t unk0; + }; + std::vector 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 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 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 bgs; + + virtual void load(buffer &b) override; +}; + +struct map_music : public segment +{ + std::vector mms; + uint32_t unk1; + + virtual void load(buffer &b) override; +}; + +struct organizations : public segment +{ + uint32_t n; + std::vector 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 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 gliders; + uint32_t unk1; + std::vector 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 segments; + + void load(buffer &b); +}; + +struct mpj +{ + header h; + + // + std::string filename; + + void load(buffer &b); + void load(const std::string &filename); +}; diff --git a/src/mpj_loader/mpj_loader.cpp b/src/mpj_loader/mpj_loader.cpp new file mode 100644 index 0000000..b3ac1a9 --- /dev/null +++ b/src/mpj_loader/mpj_loader.cpp @@ -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 . + */ + +#include +#include +#include +#include +#include + +#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; +}