Improve MECH loading. Add ability to rewrite values.

This commit is contained in:
lzwdgc 2016-06-24 17:12:41 +03:00
parent 01ec4f3a44
commit d2fb7d43d9
4 changed files with 272 additions and 183 deletions

View file

@ -77,6 +77,13 @@ public:
{ {
return _write(src, sizeof(T)); return _write(src, sizeof(T));
} }
uint32_t write(const std::string &s)
{
auto sz = s.size() + 1;
_write(s.c_str(), sz);
skip(0x20 - sz);
return 0x20;
}
template <class T, class SizeType = uint32_t> template <class T, class SizeType = uint32_t>
void read_vector(std::vector<T> &v, int n) const void read_vector(std::vector<T> &v, int n) const
@ -118,6 +125,8 @@ public:
uint32_t size() const; uint32_t size() const;
const std::vector<uint8_t> &buf() const; const std::vector<uint8_t> &buf() const;
const uint8_t *getPtr() const { return ptr; }
private: private:
std::shared_ptr<std::vector<uint8_t>> buf_; std::shared_ptr<std::vector<uint8_t>> buf_;
mutable uint32_t index_ = 0; mutable uint32_t index_ = 0;

View file

@ -297,10 +297,10 @@ struct ModificatorMask
enum class ItemType : uint8_t enum class ItemType : uint8_t
{ {
Glider = 1, Glider = 1,
Weapon, Weapon = 2,
Reactor, Reactor = 3,
Engine, Engine = 4,
EnergyShield EnergyShield = 5,
}; };
uint8_t fight : 4; uint8_t fight : 4;

View file

@ -23,6 +23,49 @@
#include <objects.h> #include <objects.h>
#include <types.h> #include <types.h>
// possible save operations
struct changes
{
buffer out;
std::string mech_org;
float money = 0;
bool upgrade_equ_for_player = false;
void rewrite_mech_org(const buffer &b, std::string &org)
{
if (mech_org.empty())
return;
// setpos
out.seek(b.index());
out.skip(-0x20);
out.write(mech_org);
org = mech_org;
}
void rewrite_money(const buffer &b)
{
if (money == 0)
return;
out.seek(b.index());
out.skip(-4);
out.write(money);
}
void rewrite_upgrade_equ_for_player(const buffer &b, uint32_t value)
{
if (!upgrade_equ_for_player)
return;
out.seek(b.index());
out.skip(-4);
out.write(value);
}
} save_changes;
// common structs // common structs
struct int_variable struct int_variable
@ -321,7 +364,6 @@ struct others_segment : public segment
} }
}; };
// todo
struct mech_segment : public segment struct mech_segment : public segment
{ {
struct equipment struct equipment
@ -352,19 +394,19 @@ struct mech_segment : public segment
} }
}; };
struct unk_equ struct moddable_equipment2
{ {
uint8_t id; uint8_t id;
std::string name; std::string name;
uint32_t unk0; uint32_t unk0; // health?
uint32_t unk1; ModificatorMask mask;
void load(const buffer &b) void load(const buffer &b)
{ {
READ(b, id); READ(b, id);
READ_STRING(b, name); READ_STRING(b, name);
READ(b, unk0); READ(b, unk0);
READ(b, unk1); READ(b, mask);
} }
}; };
@ -414,147 +456,6 @@ struct mech_segment : public segment
} }
}; };
struct glider
{
enum class unk_flag : uint32_t
{
unk0 = 0b0'0001,
unk1 = 0b0'0010,
unk2 = 0b0'0100,
unk3 = 0b0'1000,
unk4 = 0b1'0000,
};
moddable_equipment glider_;
moddable_equipment weapon1;
moddable_equipment weapon2;
moddable_equipment reactor1;
moddable_equipment reactor2;
moddable_equipment engine1;
moddable_equipment engine2;
moddable_equipment energy_shield;
moddable_equipment armor;
uint32_t unk0;
uint32_t unk1 = 0;
unk_flag unk2;
std::vector<ammo> ammos;
std::vector<ammo> ammos1;
std::vector<ammo> ammos2;
unk_flag unk3;
unk_equ ureactor1;
unk_equ ureactor2;
unk_equ uengine1;
unk_equ uengine2;
unk_equ uenergy_shield;
unk_equ uarmor;
std::string unk4;
uint32_t unk5[2];
std::vector<ammo_count> ammos3;
float money;
std::vector<hold_item> items;
uint32_t unk6[28][3];
float unk7 = 0;
float unk8;
uint32_t unk9;
uint8_t unk10;
void load(const buffer &b)
{
glider_.load(b);
weapon1.load(b);
weapon2.load(b);
reactor1.load(b);
reactor2.load(b);
engine1.load(b);
engine2.load(b);
energy_shield.load(b);
armor.load(b);
// ?
READ(b, unk0);
if (unk0 == 0)
READ(b, unk1);
READ(b, unk2);
if (unk0 == 0)
b.read_vector(ammos, unk1);
b.read_vector(ammos1, unk0);
if (unk0 != 0 || unk1 != 0)
{
READ(b, unk3);
//if (unk3 != 0 && unk3 != 10)
//if ((uint32_t)unk3 & (uint32_t)unk_flag::unk1)
if (unk0 > 0)
{
//int n = ((uint32_t)unk3 & (uint32_t)unk_flag::unk2) ? 3 : 2;
//uint32_t n = 3;
//if ((uint32_t)unk3 & (uint32_t)unk_flag::unk3)
// n = 2;
uint32_t n;
b.skip(-8);
READ(b, n);
b.skip(4);
b.read_vector(ammos2, n);
std::vector<single_int<>> v;
b.read_vector(v, n);
}
//else if (unk3 == 10)
//else if ((uint32_t)unk3 & (uint32_t)unk_flag::unk3 ||
// (uint32_t)unk3 & (uint32_t)unk_flag::unk2)
//else if (unk1 != 0)
if (unk1 > 0)
{
unk1--;
while (unk1--)
READ(b, unk3);
}
}
ureactor1.load(b);
ureactor2.load(b);
uengine1.load(b);
uengine2.load(b);
uenergy_shield.load(b);
uarmor.load(b);
READ_STRING(b, unk4);
READ(b, unk5);
b.read_vector(ammos3);
READ(b, money);
b.read_vector(items);
READ(b, unk6);
//if (unk0 == 1)
//if ((uint32_t)unk2 == 15)
if ((uint32_t)unk3 == 0)
{
READ(b, unk7);
if (unk7 != 0)
{
b.skip(-4);
return;
}
READ(b, unk8);
READ(b, unk9);
READ(b, unk10);
}
}
};
enum class MechFlags : uint32_t enum class MechFlags : uint32_t
{ {
unk0 = 0x1, unk0 = 0x1,
@ -578,15 +479,58 @@ struct mech_segment : public segment
uint8_t unk14; uint8_t unk14;
uint32_t unk15; uint32_t unk15;
uint32_t unk15_1; uint32_t unk15_1;
uint32_t unk16; uint32_t unk16 = 0;
std::vector<equipment> equipments; std::vector<equipment> equipments;
uint32_t unk4[8]; float unk40;
glider g; uint32_t unk4[7];
uint32_t unk5[8]; // glider
uint8_t unk6; // g_unk = glider unknown
// mask works only for weapons
moddable_equipment glider;
moddable_equipment weapon1;
moddable_equipment weapon2;
moddable_equipment reactor1;
moddable_equipment reactor2;
moddable_equipment engine1;
moddable_equipment engine2;
moddable_equipment energy_shield;
moddable_equipment armor;
uint32_t g_unk0;
uint32_t g_unk1 = 0;
uint32_t g_unk2;
std::vector<ammo> ammos;
std::vector<ammo> ammos1;
std::vector<ammo> ammos2;
uint32_t g_unk3 = 0;
// mask works for all except uarmor
moddable_equipment2 ureactor1;
moddable_equipment2 ureactor2;
moddable_equipment2 uengine1;
moddable_equipment2 uengine2;
moddable_equipment2 uenergy_shield;
moddable_equipment2 uarmor;
moddable_equipment g_unk4;
ModificatorMask glider_mask;
std::vector<ammo_count> ammos3;
float money;
std::vector<hold_item> items;
uint32_t g_unk6[28][3] = { 0 };
float g_unk7 = 0;
float g_unk8 = 0;
uint32_t g_unk9 = 0;
uint8_t g_unk10 = 0;
void load(const buffer &b) void load(const buffer &b)
{ {
@ -594,6 +538,7 @@ struct mech_segment : public segment
READ_STRING(b, name); READ_STRING(b, name);
READ_STRING(b, name2); READ_STRING(b, name2);
READ_STRING(b, org); READ_STRING(b, org);
save_changes.rewrite_mech_org(b, org);
READ_STRING(b, building); READ_STRING(b, building);
READ(b, flags); READ(b, flags);
@ -603,11 +548,15 @@ struct mech_segment : public segment
READ(b, unk14); READ(b, unk14);
auto f = (uint32_t)flags; auto f = (uint32_t)flags;
if (f == 0x01000101 || if (!(f == 0x01000101 ||
f == 0x00000001 || f == 0x00000001 ||
f == 0x00000101 || f == 0x00000101 ||
f == 0x01000001) f == 0x01000001))
{ {
READ(b, unk16);
return;
}
READ(b, unk15); READ(b, unk15);
if (unk14 == 0) if (unk14 == 0)
@ -617,14 +566,116 @@ struct mech_segment : public segment
b.read_vector(equipments); b.read_vector(equipments);
READ(b, unk40);
READ(b, unk4); READ(b, unk4);
g.load(b); //
} glider.load(b);
else if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x1666);
weapon1.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x2666);
weapon2.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x2666);
reactor1.load(b);
reactor2.load(b);
engine1.load(b);
engine2.load(b);
energy_shield.load(b);
armor.load(b);
// ?
READ(b, g_unk0);
if (g_unk0 == 0)
READ(b, g_unk1);
READ(b, g_unk2);
if (g_unk0 == 0)
b.read_vector(ammos, g_unk1);
b.read_vector(ammos1, g_unk0);
if (g_unk0 != 0 || g_unk1 != 0)
{ {
READ(b, unk16); READ(b, g_unk3);
if (g_unk0 > 0)
{
uint32_t n;
b.skip(-8);
READ(b, n);
b.skip(4);
b.read_vector(ammos2, n);
std::vector<single_int<>> v;
b.read_vector(v, n);
} }
if (g_unk1 > 0)
{
g_unk1--;
while (g_unk1--)
READ(b, g_unk3);
}
}
ureactor1.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x3666);
ureactor2.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x3666);
uengine1.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x4666);
uengine2.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x4666);
uenergy_shield.load(b);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x5666);
uarmor.load(b);
g_unk4.load(b);
READ(b, glider_mask);
if (isPlayer())
save_changes.rewrite_upgrade_equ_for_player(b, 0x1666);
b.read_vector(ammos3);
READ(b, money);
if (name == "PLAYER")
save_changes.rewrite_money(b);
b.read_vector(items);
READ(b, g_unk6);
// TODO
//if (g_unk0 == 1)
//if ((uint32_t)g_unk2 == 15)
//if ((uint32_t)g_unk3 == 0)
//if (unk13[0] == 5)
if (g_unk6[26][0] != 0 &&
strcmp((const char *)b.getPtr(), "GROUPS") != 0)
{
READ(b, g_unk7);
/*if (g_unk7 != 0)
{
b.skip(-4);
return;
}*/
READ(b, g_unk8);
READ(b, g_unk9);
READ(b, g_unk10);
}
}
bool isPlayer() const
{
return name == "PLAYER";
} }
}; };
@ -639,17 +690,42 @@ struct mech_segment : public segment
// todo // todo
struct groups_segment : public segment struct groups_segment : public segment
{ {
struct mech
{
std::string name;
uint32_t unk0;
float unk1[4];
uint32_t unk2[2];
float unk3;
void load(const buffer &b)
{
READ_STRING(b, name);
READ(b, unk0);
READ(b, unk1);
READ(b, unk2);
READ(b, unk3);
}
};
struct group struct group
{ {
vector3 pos; vector3 pos;
std::string org; std::string org;
float unk0[12]; std::string base;
float unk0[4];
uint16_t unk1;
std::vector<mech> mechs;
void load(const buffer &b) void load(const buffer &b)
{ {
READ(b, pos); READ(b, pos);
READ_STRING(b, org); READ_STRING(b, org);
READ_STRING(b, base);
READ(b, unk0); READ(b, unk0);
READ(b, unk1);
b.read_vector(mechs);
} }
}; };

View file

@ -21,14 +21,6 @@
#include "save.h" #include "save.h"
save read_save(const std::string &fn)
{
buffer f(readFile(fn));
save s;
s.load(f);
return s;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
try try
{ {
@ -37,7 +29,19 @@ try
printf("Usage: %s file.sav\n", argv[0]); printf("Usage: %s file.sav\n", argv[0]);
return 1; return 1;
} }
auto s = read_save(argv[1]);
//save_changes.mech_org = "ORG_PLAYER";
save_changes.money = 999999999.0f;
save_changes.upgrade_equ_for_player = true;
buffer f(readFile(argv[1]));
save_changes.out = buffer(f.buf());
save s;
s.load(f);
writeFile(argv[1], save_changes.out.buf());
return 0; return 0;
} }
catch (std::exception &e) catch (std::exception &e)