add level table JSON format
This commit is contained in:
+98
-148
@@ -2913,224 +2913,204 @@ public:
|
||||
}
|
||||
|
||||
static std::string serialize(const ItemParameterTable& pmt) {
|
||||
set<uint32_t> relocations;
|
||||
RELFileWriter<BE> rel;
|
||||
RootT root;
|
||||
phosg::StringWriter w;
|
||||
|
||||
if constexpr (!std::is_same_v<HeaderT, EmptyHeader>) {
|
||||
w.put<HeaderT>(HeaderT());
|
||||
rel.template put<HeaderT>(HeaderT());
|
||||
}
|
||||
|
||||
auto align = [&w](size_t alignment) -> void {
|
||||
while (w.size() & (alignment - 1)) {
|
||||
w.put_u8(0);
|
||||
}
|
||||
};
|
||||
auto write_ref = [&w, &relocations](const ArrayRefT<BE>& ref) -> void {
|
||||
w.put<ArrayRefT<BE>>(ref);
|
||||
relocations.emplace(w.size() - 4);
|
||||
};
|
||||
|
||||
if constexpr (requires { root.entry_count; }) {
|
||||
root.entry_count = 0x13;
|
||||
}
|
||||
|
||||
align(4);
|
||||
ArrayRefT<BE> shields_ref{pmt.num_armors_or_shields_in_class(2) - HasImplicitPlaceholders, w.size()};
|
||||
rel.align(4);
|
||||
ArrayRefT<BE> shields_ref{pmt.num_armors_or_shields_in_class(2) - HasImplicitPlaceholders, rel.w.size()};
|
||||
for (size_t data1_2 = 0; data1_2 < (shields_ref.count + HasImplicitPlaceholders); data1_2++) {
|
||||
w.put<ArmorOrShieldT>(pmt.get_armor_or_shield(2, data1_2));
|
||||
rel.template put<ArmorOrShieldT>(pmt.get_armor_or_shield(2, data1_2));
|
||||
}
|
||||
if constexpr (requires { root.shield_stat_boost_index_table; }) {
|
||||
root.shield_stat_boost_index_table = w.size();
|
||||
w.write(pmt.get_shield_stat_boost_index_table());
|
||||
root.shield_stat_boost_index_table = rel.write(pmt.get_shield_stat_boost_index_table());
|
||||
}
|
||||
|
||||
align(4);
|
||||
ArrayRefT<BE> armors_ref{pmt.num_armors_or_shields_in_class(1) - HasImplicitPlaceholders, w.size()};
|
||||
rel.align(4);
|
||||
ArrayRefT<BE> armors_ref{pmt.num_armors_or_shields_in_class(1) - HasImplicitPlaceholders, rel.w.size()};
|
||||
for (size_t data1_2 = 0; data1_2 < (armors_ref.count + HasImplicitPlaceholders); data1_2++) {
|
||||
w.put<ArmorOrShieldT>(pmt.get_armor_or_shield(1, data1_2));
|
||||
rel.template put<ArmorOrShieldT>(pmt.get_armor_or_shield(1, data1_2));
|
||||
}
|
||||
if constexpr (requires { root.armor_stat_boost_index_table; }) {
|
||||
root.armor_stat_boost_index_table = w.size();
|
||||
w.write(pmt.get_armor_stat_boost_index_table());
|
||||
root.armor_stat_boost_index_table = rel.write(pmt.get_armor_stat_boost_index_table());
|
||||
}
|
||||
|
||||
align(4);
|
||||
ArrayRefT<BE> units_ref{pmt.num_units() - HasImplicitPlaceholders, w.size()};
|
||||
rel.align(4);
|
||||
ArrayRefT<BE> units_ref{pmt.num_units() - HasImplicitPlaceholders, rel.w.size()};
|
||||
for (size_t data1_2 = 0; data1_2 < (units_ref.count + HasImplicitPlaceholders); data1_2++) {
|
||||
w.put<UnitT>(pmt.get_unit(data1_2));
|
||||
rel.template put<UnitT>(pmt.get_unit(data1_2));
|
||||
}
|
||||
|
||||
align(4);
|
||||
ArrayRefT<BE> mags_ref{pmt.num_mags() - HasImplicitPlaceholders, w.size()};
|
||||
rel.align(4);
|
||||
ArrayRefT<BE> mags_ref{pmt.num_mags() - HasImplicitPlaceholders, rel.w.size()};
|
||||
for (size_t data1_2 = 0; data1_2 < (mags_ref.count + HasImplicitPlaceholders); data1_2++) {
|
||||
w.put<MagT>(pmt.get_mag(data1_2));
|
||||
rel.template put<MagT>(pmt.get_mag(data1_2));
|
||||
}
|
||||
|
||||
align(4);
|
||||
rel.align(4);
|
||||
std::vector<ArrayRefT<BE>> tool_refs;
|
||||
for (size_t data1_1 = 0; data1_1 < pmt.num_tool_classes(); data1_1++) {
|
||||
auto& ref = tool_refs.emplace_back(ArrayRefT<BE>{pmt.num_tools_in_class(data1_1), w.size()});
|
||||
auto& ref = tool_refs.emplace_back(ArrayRefT<BE>{pmt.num_tools_in_class(data1_1), rel.w.size()});
|
||||
for (size_t data1_2 = 0; data1_2 < ref.count; data1_2++) {
|
||||
w.put<ToolT>(pmt.get_tool(data1_1, data1_2));
|
||||
rel.template put<ToolT>(pmt.get_tool(data1_1, data1_2));
|
||||
}
|
||||
}
|
||||
|
||||
align(4);
|
||||
rel.align(4);
|
||||
std::vector<ArrayRefT<BE>> weapon_refs;
|
||||
for (size_t data1_1 = 0; data1_1 < pmt.num_weapon_classes(); data1_1++) {
|
||||
auto& ref = weapon_refs.emplace_back(ArrayRefT<BE>{pmt.num_weapons_in_class(data1_1), w.size()});
|
||||
auto& ref = weapon_refs.emplace_back(ArrayRefT<BE>{pmt.num_weapons_in_class(data1_1), rel.w.size()});
|
||||
for (size_t data1_2 = 0; data1_2 < ref.count; data1_2++) {
|
||||
w.put<WeaponT>(pmt.get_weapon(data1_1, data1_2));
|
||||
rel.template put<WeaponT>(pmt.get_weapon(data1_1, data1_2));
|
||||
}
|
||||
}
|
||||
if constexpr (requires { root.weapon_stat_boost_index_table; }) {
|
||||
root.weapon_stat_boost_index_table = w.size();
|
||||
w.write(pmt.get_weapon_stat_boost_index_table());
|
||||
root.weapon_stat_boost_index_table = rel.write(pmt.get_weapon_stat_boost_index_table());
|
||||
}
|
||||
|
||||
align(4);
|
||||
root.photon_color_table = w.size();
|
||||
rel.align(4);
|
||||
root.photon_color_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_photon_colors(); z++) {
|
||||
w.put<PhotonColorEntryT<BE>>(pmt.get_photon_color(z));
|
||||
rel.template put<PhotonColorEntryT<BE>>(pmt.get_photon_color(z));
|
||||
}
|
||||
|
||||
align(4);
|
||||
root.weapon_range_table = w.size();
|
||||
rel.align(4);
|
||||
root.weapon_range_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_weapon_ranges(); z++) {
|
||||
w.put<WeaponRangeT<BE>>(pmt.get_weapon_range(z));
|
||||
rel.template put<WeaponRangeT<BE>>(pmt.get_weapon_range(z));
|
||||
}
|
||||
|
||||
root.weapon_kind_table = w.size();
|
||||
root.weapon_kind_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_weapon_classes(); z++) {
|
||||
w.put_u8(pmt.get_weapon_kind(z));
|
||||
rel.w.put_u8(pmt.get_weapon_kind(z));
|
||||
}
|
||||
|
||||
if constexpr (requires { root.weapon_integral_sale_divisor_table; }) {
|
||||
root.weapon_integral_sale_divisor_table = w.size();
|
||||
root.weapon_integral_sale_divisor_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_weapon_classes(); z++) {
|
||||
w.put_u8(pmt.get_sale_divisor(0, z));
|
||||
rel.w.put_u8(pmt.get_sale_divisor(0, z));
|
||||
}
|
||||
} else {
|
||||
align(4);
|
||||
root.weapon_sale_divisor_table = w.size();
|
||||
rel.align(4);
|
||||
root.weapon_sale_divisor_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_weapon_sale_divisors(); z++) {
|
||||
w.put<F32T<BE>>(pmt.get_sale_divisor(0, z));
|
||||
rel.template put<F32T<BE>>(pmt.get_sale_divisor(0, z));
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (requires { root.non_weapon_integral_sale_divisor_table; }) {
|
||||
root.non_weapon_integral_sale_divisor_table = w.size();
|
||||
NonWeaponSaleDivisorsDCProtos sds;
|
||||
sds.armor_divisor = pmt.get_sale_divisor(1, 1);
|
||||
sds.shield_divisor = pmt.get_sale_divisor(1, 2);
|
||||
sds.unit_divisor = pmt.get_sale_divisor(1, 3);
|
||||
w.put<NonWeaponSaleDivisorsDCProtos>(sds);
|
||||
root.non_weapon_integral_sale_divisor_table = rel.template put<NonWeaponSaleDivisorsDCProtos>(sds);
|
||||
} else {
|
||||
align(4);
|
||||
root.non_weapon_sale_divisor_table = w.size();
|
||||
rel.align(4);
|
||||
NonWeaponSaleDivisorsT<BE> sds;
|
||||
sds.armor_divisor = pmt.get_sale_divisor(1, 1);
|
||||
sds.shield_divisor = pmt.get_sale_divisor(1, 2);
|
||||
sds.unit_divisor = pmt.get_sale_divisor(1, 3);
|
||||
sds.mag_divisor = pmt.get_sale_divisor(2, 0);
|
||||
w.put<NonWeaponSaleDivisorsT<BE>>(sds);
|
||||
root.non_weapon_sale_divisor_table = rel.template put<NonWeaponSaleDivisorsT<BE>>(sds);
|
||||
}
|
||||
|
||||
MagFeedResultsListOffsetsT<BE> mag_feed_result_offsets;
|
||||
for (size_t table_index = 0; table_index < 8; table_index++) {
|
||||
mag_feed_result_offsets[table_index] = w.size();
|
||||
mag_feed_result_offsets[table_index] = rel.w.size();
|
||||
for (size_t item_id = 0; item_id < 11; item_id++) {
|
||||
w.put<MagFeedResult>(pmt.get_mag_feed_result(table_index, item_id));
|
||||
rel.template put<MagFeedResult>(pmt.get_mag_feed_result(table_index, item_id));
|
||||
}
|
||||
}
|
||||
|
||||
root.star_value_table = w.size();
|
||||
w.write(pmt.get_star_value_table());
|
||||
root.star_value_table = rel.write(pmt.get_star_value_table());
|
||||
|
||||
if constexpr (requires { root.unknown_a1; }) {
|
||||
align(2);
|
||||
root.unknown_a1 = w.size();
|
||||
w.write(pmt.get_unknown_a1());
|
||||
rel.align(2);
|
||||
root.unknown_a1 = rel.write(pmt.get_unknown_a1());
|
||||
}
|
||||
|
||||
align(2);
|
||||
root.special_table = w.size();
|
||||
rel.align(2);
|
||||
root.special_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_specials(); z++) {
|
||||
w.put<SpecialT<BE>>(pmt.get_special(z));
|
||||
rel.template put<SpecialT<BE>>(pmt.get_special(z));
|
||||
}
|
||||
|
||||
align(4);
|
||||
root.weapon_effect_table = w.size();
|
||||
rel.align(4);
|
||||
root.weapon_effect_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_weapon_effects(); z++) {
|
||||
w.put<WeaponEffectT<BE>>(pmt.get_weapon_effect(z));
|
||||
rel.template put<WeaponEffectT<BE>>(pmt.get_weapon_effect(z));
|
||||
}
|
||||
|
||||
align(4);
|
||||
rel.align(4);
|
||||
if constexpr (requires { root.shield_effect_table; }) {
|
||||
root.shield_effect_table = w.size();
|
||||
root.shield_effect_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_shield_effects(); z++) {
|
||||
w.put<ShieldEffectT<BE>>(pmt.get_shield_effect(z));
|
||||
rel.template put<ShieldEffectT<BE>>(pmt.get_shield_effect(z));
|
||||
}
|
||||
}
|
||||
|
||||
align(4);
|
||||
rel.align(4);
|
||||
if constexpr (requires { root.sound_remap_table; }) {
|
||||
std::vector<SoundRemapTableOffsetsT<BE>> remap_refs;
|
||||
const auto& remaps = pmt.get_all_sound_remaps();
|
||||
for (const auto& remap : remaps) {
|
||||
auto& remap_ref = remap_refs.emplace_back();
|
||||
remap_ref.sound_id = remap.sound_id;
|
||||
remap_ref.remaps_for_rt_index_table = w.size();
|
||||
remap_ref.remaps_for_rt_index_table = rel.w.size();
|
||||
for (uint32_t remap_sound_id : remap.by_rt_index) {
|
||||
w.put<U32T<BE>>(remap_sound_id);
|
||||
rel.template put<U32T<BE>>(remap_sound_id);
|
||||
}
|
||||
remap_ref.remaps_for_char_class_table = w.size();
|
||||
remap_ref.remaps_for_char_class_table = rel.w.size();
|
||||
for (uint32_t remap_sound_id : remap.by_char_class) {
|
||||
w.put<U32T<BE>>(remap_sound_id);
|
||||
rel.template put<U32T<BE>>(remap_sound_id);
|
||||
}
|
||||
}
|
||||
ArrayRefT<BE> remap_vec{remaps.size(), w.size()};
|
||||
ArrayRefT<BE> remap_vec{remaps.size(), rel.w.size()};
|
||||
for (const auto& remap_ref : remap_refs) {
|
||||
w.put<SoundRemapTableOffsetsT<BE>>(remap_ref);
|
||||
relocations.emplace(w.size() - 8);
|
||||
relocations.emplace(w.size() - 4);
|
||||
uint32_t offset = rel.template put<SoundRemapTableOffsetsT<BE>>(remap_ref);
|
||||
rel.relocations.emplace(offset + 4);
|
||||
rel.relocations.emplace(offset + 8);
|
||||
}
|
||||
root.sound_remap_table = w.size();
|
||||
write_ref(remap_vec);
|
||||
root.sound_remap_table = rel.write_ref(remap_vec);
|
||||
}
|
||||
|
||||
align(4);
|
||||
root.stat_boost_table = w.size();
|
||||
rel.align(4);
|
||||
root.stat_boost_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_stat_boosts(); z++) {
|
||||
w.put<StatBoostT<BE>>(pmt.get_stat_boost(z));
|
||||
rel.template put<StatBoostT<BE>>(pmt.get_stat_boost(z));
|
||||
}
|
||||
|
||||
if constexpr (requires { root.max_tech_level_table; }) {
|
||||
root.max_tech_level_table = w.size();
|
||||
MaxTechniqueLevels max_tech_levels;
|
||||
for (size_t tech_num = 0; tech_num < 0x13; tech_num++) {
|
||||
for (size_t char_class = 0; char_class < 0x0C; char_class++) {
|
||||
max_tech_levels[tech_num][char_class] = pmt.get_max_tech_level(char_class, tech_num);
|
||||
}
|
||||
}
|
||||
w.put<MaxTechniqueLevels>(max_tech_levels);
|
||||
root.max_tech_level_table = rel.template put<MaxTechniqueLevels>(max_tech_levels);
|
||||
}
|
||||
|
||||
ArrayRefT<BE> combination_table_ref;
|
||||
if constexpr (requires { root.combination_table; }) {
|
||||
combination_table_ref.offset = w.size();
|
||||
combination_table_ref.offset = rel.w.size();
|
||||
combination_table_ref.count = pmt.num_item_combinations();
|
||||
for (size_t z = 0; z < combination_table_ref.count; z++) {
|
||||
w.put<ItemCombination>(pmt.get_item_combination(z));
|
||||
rel.template put<ItemCombination>(pmt.get_item_combination(z));
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (requires { root.tech_boost_table; }) {
|
||||
align(4);
|
||||
root.tech_boost_table = w.size();
|
||||
rel.align(4);
|
||||
root.tech_boost_table = rel.w.size();
|
||||
for (size_t z = 0; z < pmt.num_tech_boosts(); z++) {
|
||||
w.put<TechBoostT<BE>>(pmt.get_tech_boost(z));
|
||||
rel.template put<TechBoostT<BE>>(pmt.get_tech_boost(z));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3138,8 +3118,8 @@ public:
|
||||
if constexpr (requires { root.unwrap_table; }) {
|
||||
for (size_t event = 0; event < pmt.num_events(); event++) {
|
||||
auto [event_items, num_items] = pmt.get_event_items(event);
|
||||
unwrap_table_refs.emplace_back(ArrayRefT<BE>{num_items, w.size()});
|
||||
w.write(event_items, sizeof(EventItem) * num_items);
|
||||
unwrap_table_refs.emplace_back(ArrayRefT<BE>{num_items, rel.w.size()});
|
||||
rel.write(event_items, sizeof(EventItem) * num_items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3147,95 +3127,65 @@ public:
|
||||
if constexpr (requires { root.unsealable_table; }) {
|
||||
const auto& items = pmt.all_unsealable_items();
|
||||
unsealable_table_ref.count = items.size();
|
||||
unsealable_table_ref.offset = w.size();
|
||||
unsealable_table_ref.offset = rel.w.size();
|
||||
for (const auto& item : items) {
|
||||
UnsealableItem encoded;
|
||||
u32_to_item_code(encoded.item, item);
|
||||
w.put<UnsealableItem>(encoded);
|
||||
rel.template put<UnsealableItem>(encoded);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayRefT<BE> ranged_specials_ref;
|
||||
if constexpr (requires { root.ranged_special_table; }) {
|
||||
ranged_specials_ref.count = pmt.num_ranged_specials();
|
||||
ranged_specials_ref.offset = w.size();
|
||||
ranged_specials_ref.offset = rel.w.size();
|
||||
for (size_t z = 0; z < ranged_specials_ref.count; z++) {
|
||||
w.put<RangedSpecial>(pmt.get_ranged_special(z));
|
||||
rel.template put<RangedSpecial>(pmt.get_ranged_special(z));
|
||||
}
|
||||
}
|
||||
|
||||
align(4);
|
||||
root.armor_table = w.size();
|
||||
write_ref(armors_ref);
|
||||
write_ref(shields_ref);
|
||||
root.unit_table = w.size();
|
||||
write_ref(units_ref);
|
||||
root.mag_table = w.size();
|
||||
write_ref(mags_ref);
|
||||
root.tool_table = w.size();
|
||||
rel.align(4);
|
||||
root.armor_table = rel.write_ref(armors_ref);
|
||||
rel.write_ref(shields_ref);
|
||||
root.unit_table = rel.write_ref(units_ref);
|
||||
root.mag_table = rel.write_ref(mags_ref);
|
||||
root.tool_table = rel.w.size();
|
||||
for (const auto& ref : tool_refs) {
|
||||
write_ref(ref);
|
||||
rel.write_ref(ref);
|
||||
}
|
||||
root.weapon_table = w.size();
|
||||
root.weapon_table = rel.w.size();
|
||||
for (const auto& ref : weapon_refs) {
|
||||
write_ref(ref);
|
||||
rel.write_ref(ref);
|
||||
}
|
||||
if constexpr (requires { root.combination_table; }) {
|
||||
root.combination_table = w.size();
|
||||
write_ref(combination_table_ref);
|
||||
root.combination_table = rel.write_ref(combination_table_ref);
|
||||
}
|
||||
if constexpr (requires { root.unwrap_table; }) {
|
||||
ArrayRefT<BE> event_ref{unwrap_table_refs.size(), w.size()};
|
||||
ArrayRefT<BE> event_ref{unwrap_table_refs.size(), rel.w.size()};
|
||||
for (const auto& ref : unwrap_table_refs) {
|
||||
write_ref(ref);
|
||||
rel.write_ref(ref);
|
||||
}
|
||||
root.unwrap_table = w.size();
|
||||
write_ref(event_ref);
|
||||
root.unwrap_table = rel.write_ref(event_ref);
|
||||
}
|
||||
if constexpr (requires { root.unsealable_table; }) {
|
||||
root.unsealable_table = w.size();
|
||||
write_ref(unsealable_table_ref);
|
||||
root.unsealable_table = rel.write_ref(unsealable_table_ref);
|
||||
}
|
||||
if constexpr (requires { root.ranged_special_table; }) {
|
||||
root.ranged_special_table = w.size();
|
||||
write_ref(ranged_specials_ref);
|
||||
root.ranged_special_table = rel.write_ref(ranged_specials_ref);
|
||||
}
|
||||
|
||||
root.mag_feed_table = w.size();
|
||||
w.put<MagFeedResultsListOffsetsT<BE>>(mag_feed_result_offsets);
|
||||
root.mag_feed_table = rel.template put<MagFeedResultsListOffsetsT<BE>>(mag_feed_result_offsets);
|
||||
for (size_t z = 1; z <= 8; z++) {
|
||||
relocations.emplace(w.size() - (z * 4));
|
||||
rel.relocations.emplace(rel.w.size() - (z * 4));
|
||||
}
|
||||
|
||||
RELFileFooterT<BE> footer;
|
||||
footer.root_offset = w.size();
|
||||
w.put<RootT>(root);
|
||||
uint32_t root_offset = rel.template put<RootT>(root);
|
||||
constexpr size_t root_field_count = (sizeof(RootT) / 4) - ((requires { root.entry_count; }) ? 1 : 0);
|
||||
for (size_t z = 1; z <= root_field_count; z++) {
|
||||
relocations.emplace(w.size() - (z * 4));
|
||||
rel.relocations.emplace(rel.w.size() - (z * 4));
|
||||
}
|
||||
|
||||
align(0x20);
|
||||
footer.relocations_offset = w.size();
|
||||
footer.num_relocations = relocations.size();
|
||||
footer.unused1[0] = 1;
|
||||
uint32_t last_offset = 0;
|
||||
for (uint32_t reloc_offset : relocations) {
|
||||
if (reloc_offset & 3) {
|
||||
throw logic_error("Relocation is not 4-byte aligned");
|
||||
}
|
||||
size_t reloc_value = (reloc_offset - last_offset) >> 2;
|
||||
if (reloc_value > 0xFFFF) {
|
||||
throw runtime_error("Relocation offset is too far away from previous");
|
||||
}
|
||||
w.put<U16T<BE>>(reloc_value);
|
||||
last_offset = reloc_offset;
|
||||
}
|
||||
|
||||
align(0x20);
|
||||
w.put<RELFileFooterT<BE>>(footer);
|
||||
|
||||
return std::move(w.str());
|
||||
return rel.finalize(root_offset);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user