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));
}
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>
void read_vector(std::vector<T> &v, int n) const
@ -118,6 +125,8 @@ public:
uint32_t size() const;
const std::vector<uint8_t> &buf() const;
const uint8_t *getPtr() const { return ptr; }
private:
std::shared_ptr<std::vector<uint8_t>> buf_;
mutable uint32_t index_ = 0;

View file

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

View file

@ -23,6 +23,49 @@
#include <objects.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
struct int_variable
@ -321,7 +364,6 @@ struct others_segment : public segment
}
};
// todo
struct mech_segment : public segment
{
struct equipment
@ -352,19 +394,19 @@ struct mech_segment : public segment
}
};
struct unk_equ
struct moddable_equipment2
{
uint8_t id;
std::string name;
uint32_t unk0;
uint32_t unk1;
uint32_t unk0; // health?
ModificatorMask mask;
void load(const buffer &b)
{
READ(b, id);
READ_STRING(b, name);
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
{
unk0 = 0x1,
@ -578,15 +479,58 @@ struct mech_segment : public segment
uint8_t unk14;
uint32_t unk15;
uint32_t unk15_1;
uint32_t unk16;
uint32_t unk16 = 0;
std::vector<equipment> equipments;
uint32_t unk4[8];
glider g;
float unk40;
uint32_t unk4[7];
uint32_t unk5[8];
uint8_t unk6;
// glider
// 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)
{
@ -594,6 +538,7 @@ struct mech_segment : public segment
READ_STRING(b, name);
READ_STRING(b, name2);
READ_STRING(b, org);
save_changes.rewrite_mech_org(b, org);
READ_STRING(b, building);
READ(b, flags);
@ -603,28 +548,134 @@ struct mech_segment : public segment
READ(b, unk14);
auto f = (uint32_t)flags;
if (f == 0x01000101 ||
if (!(f == 0x01000101 ||
f == 0x00000001 ||
f == 0x00000101 ||
f == 0x01000001)
{
READ(b, unk15);
if (unk14 == 0)
return;
READ(b, unk15_1);
b.read_vector(equipments);
READ(b, unk4);
g.load(b);
}
else
f == 0x01000001))
{
READ(b, unk16);
return;
}
READ(b, unk15);
if (unk14 == 0)
return;
READ(b, unk15_1);
b.read_vector(equipments);
READ(b, unk40);
READ(b, unk4);
//
glider.load(b);
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, 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
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
{
vector3 pos;
std::string org;
float unk0[12];
std::string base;
float unk0[4];
uint16_t unk1;
std::vector<mech> mechs;
void load(const buffer &b)
{
READ(b, pos);
READ_STRING(b, org);
READ_STRING(b, base);
READ(b, unk0);
READ(b, unk1);
b.read_vector(mechs);
}
};

View file

@ -21,14 +21,6 @@
#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[])
try
{
@ -37,7 +29,19 @@ try
printf("Usage: %s file.sav\n", argv[0]);
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;
}
catch (std::exception &e)