Compare commits

...

22 Commits

Author SHA1 Message Date
incentive e88ed98318 Merge upstream newserv master 2026-05-09 01:02:34 -04:00
Martin Michelsen 211d08710b add default item parameter tables 2026-05-08 18:25:57 -07:00
Martin Michelsen ee40425393 add ItemParameterTable binary serialization; make JSON the default format 2026-05-08 09:23:53 -07:00
Corrine 12f9a045ca Same treatment to AR Codes. 2026-05-07 19:35:21 -07:00
Corrine 8134243fb1 Prevent confusion. 2026-05-07 19:35:21 -07:00
Corrine c869ed27f1 Fixed a mistake with NoRareSelling 2026-05-07 19:35:21 -07:00
Corrine 321ba64016 Finished. 2026-05-07 19:35:21 -07:00
Corrine a8606d26a8 Added MoreSaveSlots.59NJ 2026-05-07 19:35:21 -07:00
Corrine a57cca6c12 Port 59NL server patches to 59NJ (pt. 1) 2026-05-07 19:35:21 -07:00
incentive 86a46df442 Treat proxy A0 lobby exit as intentional
CMake / build (macos-latest) (push) Has been cancelled
CMake / build (ubuntu-latest) (push) Has been cancelled
2026-05-06 02:03:51 -04:00
incentive cdb397f5ea Add GC EP1 and EP2 EXP client patches 2026-05-05 22:34:44 -04:00
incentive 2b73d58033 Add GC Normal Dragon HP client patch 2026-05-05 22:21:33 -04:00
incentive 5abd47ff72 Align BB Normal Dragon HP with V2 2026-05-05 19:39:05 -04:00
incentive 261cb5c76f Log Dragon boss action state 2026-05-05 19:12:20 -04:00
incentive ea1044c271 Merge boss flags when blocking damage rollback 2026-05-05 18:51:10 -04:00
incentive a1c358e13a Preserve boss flags when blocking damage rollback 2026-05-05 18:28:46 -04:00
incentive 1f00bf1d9b Clamp boss damage rollback from 6x0A 2026-05-05 18:12:36 -04:00
incentive 8bc602012e Allow DC V2 Falz death-drop pickup recovery 2026-05-05 16:52:25 -04:00
Martin Michelsen b8e7d81a22 add check for invalid defensive item type 2026-05-04 10:32:08 -07:00
Martin Michelsen d384cf4f11 fix mag evolution table reference 2026-05-04 09:51:57 -07:00
Martin Michelsen 681ce135f8 add JSON encoding for ItemPMT 2026-05-03 22:55:53 -07:00
Martin Michelsen e19c0b8bc9 add 11/2000 mag table 2026-05-02 10:50:55 -07:00
80 changed files with 21237 additions and 508 deletions
-2
View File
@@ -30,8 +30,6 @@
## PSOBB
- Figure out why Pouilly Slime EXP doesn't work
- Make server-specified rare enemies work with maps loaded by the proxy
- Implement serialization for various table types (ItemPMT, ItemPT, etc.)
- Record some BB tests
- Add all necessary Guild Card number rewrites in BB commands on the proxy
+9
View File
@@ -81,12 +81,14 @@ Disable item equip restrictions ("God of equip")
3OJ5 => 041050D4 38000005
3OJT => 0415BF50 38000005
3OP0 => 041052D4 38000005
59NJ => 005C9F35 E9A7000000
59NL => 005C9F31 E9A7000000
All items visible in Pioneer 2
3OE1 => 04102D88 38600000
Mags visible in Pioneer 2
59NJ => 005D8F27 EB04
59NL => 005D8F4B EB04
Disable pause menu background + offset
@@ -94,6 +96,9 @@ Disable pause menu background + offset
0428735C 4800000C
3OE2 => 0424CED8 48000370
042887D8 4800000C
59NJ => 00719C58 9090
00733C57 9090
00733ABE 90E9
59NL => 00719B54 9090
00733BA7 9090
00733A0E 90E9
@@ -637,6 +642,8 @@ Fast tekker (skips wind-up jingle)
0023EF77 jmp +0x0A
4OPU => 0023F14C mov dword [ebp + 0x14C], 1
0023F167 jmp +0x0A
59NJ => 006DA14B mov dword [edi + 0x14C], 1
006DA168 jmp +0x0B
59NL => 006DA113 mov dword [edi + 0x14C], 1
006DA130 jmp +0x0B
@@ -973,6 +980,8 @@ Override Challenge mode random enemy location tables limit
4OEU => 002E742C XXXXXXXX (count as little-endian dword)
4OPD => 002E720C XXXXXXXX (count as little-endian dword)
4OPU => 002E745C XXXXXXXX (count as little-endian dword)
59NJ => 0080FA3F XXXXXXXX (count * 4 as little-endian dword)
0080FA58 XXXXXXXX (count as little-endian dword)
59NL => 0080ECB7 XXXXXXXX (count * 4 as little-endian dword)
0080ECD0 XXXXXXXX (count as little-endian dword)
+1 -1
View File
@@ -486,7 +486,7 @@ void ItemData::encode_for_version(Version to_version, shared_ptr<const ItemParam
if (should_encode_v2_data && (this->data1[1] > 0x26)) {
if (this->data1[1] < 0x89) {
this->data1[5] = this->data1[1];
this->data1[1] = item_parameter_table->get_weapon_class(this->data1[1]);
this->data1[1] = item_parameter_table->get_weapon_kind(this->data1[1]);
if (this->data1[1] == 0x00) {
this->data1[1] = 0x0F;
}
+195 -11
View File
@@ -1,5 +1,7 @@
#include "ItemNameIndex.hh"
#include <algorithm>
#include "StaticGameData.hh"
using namespace std;
@@ -787,9 +789,9 @@ void ItemNameIndex::print_table(FILE* stream) const {
auto pmt = this->item_parameter_table;
phosg::fwrite_fmt(stream, "WEAPONS\n");
phosg::fwrite_fmt(stream, " CODE => ---ID--- TYPE SKIN POINTS FLAG ATPLO ATPHI ATPRQ MSTRQ ATARQ -MST- GND PH SP ATA SB(S1:AMT1,S2:AMT2) PJ 1X 1Y 2X 2Y CR --A1-- A4 A5 TB BF CL ST* USL ---DIVISOR--- NAME\n");
phosg::fwrite_fmt(stream, " CODE => ---ID--- TYPE SKIN POINTS FLAG ATPLO ATPHI ATPRQ MSTRQ ATARQ -MST- GND PH SP ATA SB(S1:AMT1,S2:AMT2) PJ 1X 1Y 2X 2Y CR --A1-- A4 A5 TB(TN:FL:AMOUNT, ... ) BF CL ST* USL ---DIVISOR--- NAME\n");
for (size_t data1_1 = 0; data1_1 < pmt->num_weapon_classes(); data1_1++) {
uint8_t weapon_class = pmt->get_weapon_class(data1_1);
uint8_t weapon_class = pmt->get_weapon_kind(data1_1);
float sale_divisor = pmt->get_sale_divisor(0x00, data1_1);
string divisor_str = std::format("{:g}", sale_divisor);
divisor_str.resize(13, ' ');
@@ -806,8 +808,24 @@ void ItemNameIndex::print_table(FILE* stream) const {
item.data1[2] = data1_2;
string name = this->describe_item(item);
auto& stat_boost = pmt->get_stat_boost(w.stat_boost_entry_index);
phosg::fwrite_fmt(stream, " 00{:02X}{:02X} => {:08X} {:04X} {:04X} {:6} {:04X} {:5} {:5} {:5} {:5} {:5} {:5} {:3} {:02X} {:02X} {:3} {:02X}({:02X}:{:04X},{:02X}:{:04X}) {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}{:02X}{:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:2}* {} {} {}\n",
const auto& stat_boost = pmt->get_stat_boost(w.stat_boost_entry_index);
string tech_boost_str;
if (w.tech_boost_entry_index < pmt->num_tech_boosts()) {
const auto& tech_boost = pmt->get_tech_boost(w.tech_boost_entry_index);
tech_boost_str = std::format("({:02X}:{:02X}:{:g},{:02X}:{:02X}:{:g},{:02X}:{:02X}:{:g})",
tech_boost.tech_num1, tech_boost.flags1, tech_boost.amount1, tech_boost.tech_num2, tech_boost.flags2,
tech_boost.amount2, tech_boost.tech_num3, tech_boost.flags3, tech_boost.amount3);
}
tech_boost_str.resize(40, ' ');
phosg::fwrite_fmt(stream,
// CODE => ID TYPE SKIN PTS FLAG ATP- ATP+ ATPR MSTR ATAR MST GND PH SP ATA
" 00{:02X}{:02X} => {:08X} {:04X} {:04X} {:6} {:04X} {:5} {:5} {:5} {:5} {:5} {:5} {:3} {:02X} {:02X} {:3} "
// SB( S1:AMT1 , S2:AMT2 ) PJ 1X 1Y 2X 2Y CR --------A1-------- A4
"{:02X}({:02X}:{:04X},{:02X}:{:04X}) {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}{:02X}{:02X} {:02X} "
// A5 TB( TN: FL: AMT, TN: FL: AMT, TN: FL: AMT) BF CL ST* US DV NAME\n"
"{:02X} {:02X}{} {:02X} {:02X} {:2}* {} {} {}\n",
data1_1,
data1_2,
w.id,
@@ -841,7 +859,8 @@ void ItemNameIndex::print_table(FILE* stream) const {
w.unknown_a1[2],
w.unknown_a4,
w.unknown_a5,
w.tech_boost,
w.tech_boost_entry_index,
tech_boost_str,
w.behavior_flags,
weapon_class,
stars,
@@ -852,7 +871,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
}
phosg::fwrite_fmt(stream, "ARMORS\n");
phosg::fwrite_fmt(stream, " CODE => ---ID--- TYPE SKIN POINTS -DFP- -EVP- BP BE FLAG LVL EFR ETH EIC EDK ELT DFR EVR SB(S1:AMT1,S2:AMT2) TB FT A4 ST* ---DIVISOR--- NAME\n");
phosg::fwrite_fmt(stream, " CODE => ---ID--- TYPE SKIN POINTS -DFP- -EVP- BP BE FLAG LVL EFR ETH EIC EDK ELT DFR EVR SB(S1:AMT1,S2:AMT2) TB(TN:FL:AMOUNT, ... ) FT A4 ST* ---DIVISOR--- NAME\n");
for (size_t data1_1 = 1; data1_1 < 3; data1_1++) {
float sale_divisor = pmt->get_sale_divisor(0x01, data1_1);
string divisor_str = std::format("{:g}", sale_divisor);
@@ -870,7 +889,17 @@ void ItemNameIndex::print_table(FILE* stream) const {
string name = this->describe_item(item);
auto& stat_boost = pmt->get_stat_boost(a.stat_boost_entry_index);
phosg::fwrite_fmt(stream, " 01{:02X}{:02X} => {:08X} {:04X} {:04X} {:6} {:5} {:5} {:02X} {:02X} {:04X} {:3} {:3} {:3} {:3} {:3} {:3} {:3} {:3} {:02X}({:02X}:{:04X},{:02X}:{:04X}) {:02X} {:02X} {:02X} {:2}* {} {}\n",
string tech_boost_str;
if (a.tech_boost_entry_index < pmt->num_tech_boosts()) {
const auto& tech_boost = pmt->get_tech_boost(a.tech_boost_entry_index);
tech_boost_str = std::format("({:02X}:{:02X}:{:g},{:02X}:{:02X}:{:g},{:02X}:{:02X}:{:g})",
tech_boost.tech_num1, tech_boost.flags1, tech_boost.amount1, tech_boost.tech_num2, tech_boost.flags2,
tech_boost.amount2, tech_boost.tech_num3, tech_boost.flags3, tech_boost.amount3);
}
tech_boost_str.resize(40, ' ');
phosg::fwrite_fmt(stream, " 01{:02X}{:02X} => {:08X} {:04X} {:04X} {:6} {:5} {:5} {:02X} {:02X} {:04X} {:3} {:3} {:3} {:3} {:3} {:3} {:3} {:3} {:02X}({:02X}:{:04X},{:02X}:{:04X}) {:02X}{} {:02X} {:02X} {:2}* {} {}\n",
data1_1,
data1_2,
a.id,
@@ -895,7 +924,8 @@ void ItemNameIndex::print_table(FILE* stream) const {
stat_boost.amount1,
stat_boost.stat2,
stat_boost.amount2,
a.tech_boost,
a.tech_boost_entry_index,
tech_boost_str,
a.flags_type,
a.unknown_a4,
stars,
@@ -1040,7 +1070,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
}
phosg::fwrite_fmt(stream, "SPECIAL DEFINITIONS\n");
phosg::fwrite_fmt(stream, " SPECIAL => TYPE COUNT ST* NAME\n");
phosg::fwrite_fmt(stream, " SP => TYPE COUNT ST* NAME\n");
for (size_t index = 0; index < pmt->num_specials(); index++) {
const auto& sp = pmt->get_special(index);
uint8_t stars = pmt->get_special_stars(index);
@@ -1051,12 +1081,12 @@ void ItemNameIndex::print_table(FILE* stream) const {
} catch (const out_of_range&) {
}
}
phosg::fwrite_fmt(stream, " {:02X} => {:04X} {:5} {:2}* {}\n", index, sp.type, sp.amount, stars, name);
phosg::fwrite_fmt(stream, " {:02X} => {:04X} {:5} {:2}* {}\n", index, sp.type, sp.amount, stars, name);
}
phosg::fwrite_fmt(stream, "ITEM COMBINATIONS\n");
phosg::fwrite_fmt(stream, " ---USE + -EQUIP => RESULT MLV GND LVL CLS\n");
for (const auto& combo_list_it : pmt->get_all_item_combinations()) {
for (const auto& combo_list_it : pmt->item_combinations_index()) {
for (const auto& combo : combo_list_it.second) {
phosg::fwrite_fmt(stream, " {:02X}{:02X}{:02X} + {:02X}{:02X}{:02X} => {:02X}{:02X}{:02X}",
combo.used_item[0], combo.used_item[1], combo.used_item[2],
@@ -1096,4 +1126,158 @@ void ItemNameIndex::print_table(FILE* stream) const {
event_item.item[0], event_item.item[1], event_item.item[2], event_item.probability);
}
}
phosg::fwrite_fmt(stream, "PHOTON COLORS\n");
phosg::fwrite_fmt(stream, " ## => ---A1--- (A2) (A3)\n");
for (size_t z = 0; z < pmt->num_photon_colors(); z++) {
const auto& pc = pmt->get_photon_color(z);
phosg::fwrite_fmt(stream, " {:02X} => {:08X} ({:g}, {:g}, {:g}, {:g}) ({:g}, {:g}, {:g}, {:g})\n",
z, pc.unknown_a1, pc.unknown_a2.x, pc.unknown_a2.y, pc.unknown_a2.z, pc.unknown_a2.t,
pc.unknown_a3.x, pc.unknown_a3.y, pc.unknown_a3.z, pc.unknown_a3.t);
}
phosg::fwrite_fmt(stream, "WEAPON RANGES\n");
phosg::fwrite_fmt(stream, " ## => ---A3--- ---A4--- ---A5--- (A1) (A2)\n");
for (size_t z = 0; z < pmt->num_weapon_ranges(); z++) {
const auto& wr = pmt->get_weapon_range(z);
phosg::fwrite_fmt(stream, " {:02X} => {:08X} {:08X} {:08X} ({:g}) ({:g})\n",
z, wr.unknown_a3, wr.unknown_a4, wr.unknown_a5, wr.unknown_a1, wr.unknown_a2);
}
phosg::fwrite_fmt(stream, "SALE DIVISORS\n");
phosg::fwrite_fmt(stream, " ARMOR = {:g}\n", pmt->get_sale_divisor(1, 1));
phosg::fwrite_fmt(stream, " SHIELD = {:g}\n", pmt->get_sale_divisor(1, 2));
phosg::fwrite_fmt(stream, " UNIT = {:g}\n", pmt->get_sale_divisor(1, 3));
phosg::fwrite_fmt(stream, " MAG = {:g}\n", pmt->get_sale_divisor(2, 0));
auto write_data_string = [&](const std::string& data, size_t addr = 0) -> void {
if (data.empty()) {
phosg::fwrite_fmt(stream, " (no data)\n");
} else {
auto data_str = phosg::format_data(data, addr);
phosg::strip_trailing_whitespace(data_str);
phosg::fwrite_fmt(stream, " {}\n", phosg::str_replace_all(data_str, "\n", "\n "));
}
};
phosg::fwrite_fmt(stream, "STAR VALUES\n");
write_data_string(pmt->get_star_value_table(), pmt->get_star_value_index_range().first);
phosg::fwrite_fmt(stream, "UNKNOWN_A1\n");
write_data_string(pmt->get_unknown_a1());
phosg::fwrite_fmt(stream, "WEAPON EFFECTS\n");
phosg::fwrite_fmt(stream, " ## => -SOUND1- -VALUE1- -SOUND2- -VALUE2- ----------------A5---------------\n");
for (size_t z = 0; z < pmt->num_weapon_effects(); z++) {
const auto& we = pmt->get_weapon_effect(z);
auto a5_str = phosg::format_data_string(we.unknown_a5.data(), we.unknown_a5.size());
phosg::fwrite_fmt(stream, " {:02X} => {:08X} {:08X} {:08X} {:08X} {}\n",
z, we.sound_id1, we.eff_value1, we.sound_id2, we.eff_value2, a5_str);
}
phosg::fwrite_fmt(stream, "WEAPON STAT BOOST INDEX TABLE\n");
write_data_string(pmt->get_weapon_stat_boost_index_table());
phosg::fwrite_fmt(stream, "ARMOR STAT BOOST INDEX TABLE\n");
write_data_string(pmt->get_armor_stat_boost_index_table());
phosg::fwrite_fmt(stream, "SHIELD STAT BOOST INDEX TABLE\n");
write_data_string(pmt->get_shield_stat_boost_index_table());
phosg::fwrite_fmt(stream, "STAT BOOSTS\n");
phosg::fwrite_fmt(stream, " ## => BOOSTS\n");
for (size_t z = 0; z < pmt->num_stat_boosts(); z++) {
const auto& sb = pmt->get_stat_boost(z);
static constexpr std::array<const char*, 0x10> stat_names{
"ATP+", "ATA+", "EVP+", "DFP+", "MST+", "HP+", "LCK+", "ALL+",
"ATP-", "ATA-", "EVP-", "DFP-", "MST-", "HP-", "LCK-", "ALL-"};
string s;
if (sb.stat1 > 0x10) {
s = std::format("[{:02X}:{:04X}]", sb.stat1, sb.amount1);
} else if (sb.stat1 > 0) {
s = std::format("{}{}", stat_names[sb.stat1 - 1], sb.amount1);
}
if (sb.stat2) {
if (!s.empty()) {
s += ", ";
}
if (sb.stat2 > 0x10) {
s += std::format("[{:02X}:{:04X}]", sb.stat2, sb.amount2);
} else if (sb.stat2 > 0) {
s += std::format("{}{}", stat_names[sb.stat2 - 1], sb.amount2);
}
}
if (s.empty()) {
s = "(none)";
}
phosg::fwrite_fmt(stream, " {:02X} => {}\n", z, s);
}
phosg::fwrite_fmt(stream, "SHIELD EFFECTS\n");
phosg::fwrite_fmt(stream, " ## => -SOUND1- ---A1---\n");
for (size_t z = 0; z < pmt->num_shield_effects(); z++) {
const auto& se = pmt->get_shield_effect(z);
phosg::fwrite_fmt(stream, " {:02X} => {:08X} {:08X}\n", z, se.sound_id, se.unknown_a1);
}
phosg::fwrite_fmt(stream, "SOUND REMAPS\n");
phosg::fwrite_fmt(stream, " -SOUND1- => RT:[...] CC:[...]\n");
for (const auto& remap : pmt->get_all_sound_remaps()) {
std::string rt_str;
for (uint32_t rt_sound_id : remap.by_rt_index) {
if (!rt_str.empty()) {
rt_str += ",";
}
rt_str += std::format("{:08X}", rt_sound_id);
}
std::string cc_str;
for (uint32_t cc_sound_id : remap.by_char_class) {
if (!cc_str.empty()) {
cc_str += ",";
}
cc_str += std::format("{:08X}", cc_sound_id);
}
phosg::fwrite_fmt(stream, " {:08X} => RT:[{}] CC:[{}]\n", remap.sound_id, rt_str, cc_str);
}
phosg::fwrite_fmt(stream, "TECH BOOSTS\n");
phosg::fwrite_fmt(stream, " ## => BOOSTS\n");
for (size_t z = 0; z < pmt->num_tech_boosts(); z++) {
const auto& tb = pmt->get_tech_boost(z);
string s;
if (tb.amount1) {
s += std::format("{:02X}:{:02X}:{:g}", tb.tech_num1, tb.flags1, tb.amount1);
}
if (tb.amount2) {
s += std::format("{:02X}:{:02X}:{:g}", tb.tech_num2, tb.flags2, tb.amount2);
}
if (tb.amount3) {
s += std::format("{:02X}:{:02X}:{:g}", tb.tech_num3, tb.flags3, tb.amount3);
}
phosg::fwrite_fmt(stream, " {:02X} => {}\n", z, s);
}
phosg::fwrite_fmt(stream, "UNSEALABLE ITEMS\n");
phosg::fwrite_fmt(stream, " -ITEM- NAME\n");
std::vector<uint32_t> unsealable_items;
for (uint32_t item_code : pmt->all_unsealable_items()) {
unsealable_items.emplace_back(item_code);
}
std::sort(unsealable_items.begin(), unsealable_items.end());
for (uint32_t item_code : unsealable_items) {
ItemData item;
item.data1[0] = item_code >> 16;
item.data1[1] = item_code >> 8;
item.data1[2] = item_code;
string name = this->describe_item(item);
phosg::fwrite_fmt(stream, " {:06X} {}\n", item_code, name);
}
phosg::fwrite_fmt(stream, "RANGED SPECIALS\n");
phosg::fwrite_fmt(stream, " ## => 11 12 WR A1\n");
for (size_t z = 0; z < pmt->num_ranged_specials(); z++) {
const auto& rs = pmt->get_ranged_special(z);
phosg::fwrite_fmt(stream, " {:02X} => {:02X} {:02X} {:02X} {:02X}\n",
z, rs.data1_1, rs.data1_2, rs.weapon_range_index, rs.unknown_a1);
}
}
+2329 -279
View File
File diff suppressed because it is too large Load Diff
+207 -67
View File
@@ -51,6 +51,9 @@ public:
uint16_t type = 0; // "Model" in Soly's ItemPMT editor
uint16_t skin = 0; // "Texture" in Soly's ItemPMT editor
uint32_t team_points = 0;
void parse_base_from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct Weapon : ItemBase {
uint16_t class_flags = 0;
@@ -64,7 +67,8 @@ public:
uint8_t photon = 0;
uint8_t special = 0;
uint8_t ata = 0;
uint8_t stat_boost_entry_index = 0; // TODO: This could be larger (16 or 32 bits)
uint8_t stat_boost_entry_index = 0;
parray<uint8_t, 3> v2_unknown_a9;
uint8_t projectile = 0;
int8_t trail1_x = 0;
int8_t trail1_y = 0;
@@ -74,13 +78,16 @@ public:
parray<uint8_t, 3> unknown_a1 = 0;
uint8_t unknown_a4 = 0;
uint8_t unknown_a5 = 0;
uint8_t tech_boost = 0;
uint8_t tech_boost_entry_index = 0;
// Bits in behavior_flags:
// 01 = disable combos (weapon can only be used once in a row)
// 02 = TODO (sets TItemWeapon flag 40000; used in TItemWeapon_v1E)
// 04 = TODO (sets TItemWeapon flag 80000; used in TItemWeapon_v1E)
// 08 = weapon cannot have attributes (they are ignored if present)
uint8_t behavior_flags = 0;
static Weapon from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct ArmorOrShield : ItemBase {
@@ -98,7 +105,7 @@ public:
uint8_t dfp_range = 0;
uint8_t evp_range = 0;
uint8_t stat_boost_entry_index = 0;
uint8_t tech_boost = 0;
uint8_t tech_boost_entry_index = 0;
// TODO: Figure out what this does. Only a few values appear to do anything:
// Armors:
// 01 sets item->flags |= 1 (used in TItemProArmor_v10)
@@ -108,12 +115,18 @@ public:
// 03 sets item->flags |= 8 (used in TItemProShield_v1A)
uint8_t flags_type = 0;
uint8_t unknown_a4 = 0;
static ArmorOrShield from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct Unit : ItemBase {
uint16_t stat = 0;
uint16_t stat_amount = 0;
int16_t modifier_amount = 0;
static Unit from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct Mag : ItemBase {
@@ -142,6 +155,9 @@ public:
uint8_t on_death_flag = 0;
uint8_t on_boss_flag = 0;
uint16_t class_flags = 0x00FF;
static Mag from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct Tool : ItemBase {
@@ -157,7 +173,10 @@ public:
// 00000020 - usable in boss arenas
// 00000040 - usable in Challenge mode
// 00000080 - is rare (renders as red box; V3+ only)
/* 0C */ uint32_t item_flags = 0;
uint32_t item_flags = 0;
static Tool from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct MagFeedResult {
@@ -168,11 +187,17 @@ public:
int8_t iq = 0;
int8_t synchro = 0;
parray<uint8_t, 2> unused;
static MagFeedResult from_json(const phosg::JSON& json);
phosg::JSON json() const;
} __packed_ws__(MagFeedResult, 8);
struct Special {
uint16_t type = 0xFFFF;
uint16_t amount = 0;
static Special from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct StatBoost {
@@ -201,6 +226,9 @@ public:
uint16_t amount1 = 0;
uint8_t stat2 = 0;
uint16_t amount2 = 0;
static StatBoost from_json(const phosg::JSON& json);
phosg::JSON json() const;
} __attribute__((packed));
// Indexed as [tech_num][char_class]
@@ -215,23 +243,41 @@ public:
uint8_t level = 0;
uint8_t char_class = 0;
parray<uint8_t, 3> unused;
static ItemCombination from_json(const phosg::JSON& json);
phosg::JSON json() const;
} __packed_ws__(ItemCombination, 0x10);
struct TechniqueBoost {
uint8_t tech_num = 0;
// It appears that only one bit in the flags field is used: 01 = enable piercing (for Megid)
uint8_t flags = 0;
float amount = 0.0f;
struct TechBoost {
// It appears that only one bit in the flags fields is used: 01 = enable piercing (for Megid)
uint8_t tech_num1 = 0;
uint8_t flags1 = 0;
float amount1 = 0.0f;
uint8_t tech_num2 = 0;
uint8_t flags2 = 0;
float amount2 = 0.0f;
uint8_t tech_num3 = 0;
uint8_t flags3 = 0;
float amount3 = 0.0f;
static TechBoost from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct EventItem {
parray<uint8_t, 3> item;
uint8_t probability = 0;
static EventItem from_json(const phosg::JSON& json);
phosg::JSON json() const;
} __packed_ws__(EventItem, 4);
struct UnsealableItem {
parray<uint8_t, 3> item;
uint8_t unused = 0;
static UnsealableItem from_json(const phosg::JSON& json);
phosg::JSON json() const;
} __packed_ws__(UnsealableItem, 4);
struct NonWeaponSaleDivisors {
@@ -239,119 +285,213 @@ public:
float shield_divisor = 0.0f;
float unit_divisor = 0.0f;
float mag_divisor = 0.0f;
static NonWeaponSaleDivisors from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct ShieldEffect {
uint32_t sound_id;
uint32_t unknown_a1;
uint32_t sound_id = 0;
uint32_t unknown_a1 = 0;
static ShieldEffect from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct PhotonColorEntry {
uint32_t unknown_a1;
uint32_t unknown_a1 = 0;
VectorXYZTF unknown_a2;
VectorXYZTF unknown_a3;
static PhotonColorEntry from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct UnknownA1 {
uint16_t unknown_a1;
uint16_t unknown_a2;
};
uint16_t unknown_a1 = 0;
uint16_t unknown_a2 = 0;
struct UnknownA5 {
uint32_t target_param; // For players, char_class; for enemies, rt_index; for objects, 0x30
uint32_t unknown_a2;
uint32_t unknown_a3;
static UnknownA1 from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct WeaponEffect {
uint32_t sound_id1;
uint32_t eff_value1;
uint32_t sound_id2;
uint32_t eff_value2;
uint32_t sound_id1 = 0;
uint32_t eff_value1 = 0;
uint32_t sound_id2 = 0;
uint32_t eff_value2 = 0;
parray<uint8_t, 0x10> unknown_a5;
static WeaponEffect from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct WeaponRange {
float unknown_a1;
float unknown_a2;
uint32_t unknown_a3; // Angle
uint32_t unknown_a4; // Angle
uint32_t unknown_a5;
float unknown_a1 = 0;
float unknown_a2 = 0;
uint32_t unknown_a3 = 0; // Angle
uint32_t unknown_a4 = 0; // Angle
uint32_t unknown_a5 = 0;
static WeaponRange from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct RangedSpecial {
uint8_t data1_1;
uint8_t data1_2;
uint8_t weapon_range_index;
uint8_t unknown_a1;
uint8_t data1_1 = 0;
uint8_t data1_2 = 0;
uint8_t weapon_range_index = 0;
uint8_t unknown_a1 = 0;
static RangedSpecial from_json(const phosg::JSON& json);
phosg::JSON json() const;
} __packed_ws__(RangedSpecial, 4);
ItemParameterTable() = delete;
struct SoundRemaps {
uint32_t sound_id = 0;
std::vector<uint32_t> by_rt_index;
std::vector<uint32_t> by_char_class;
static SoundRemaps from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
virtual ~ItemParameterTable() = default;
static std::shared_ptr<ItemParameterTable> create(std::shared_ptr<const std::string> data, Version version);
static std::shared_ptr<ItemParameterTable> from_binary(std::shared_ptr<const std::string> data, Version version);
static std::shared_ptr<ItemParameterTable> from_json(const phosg::JSON& json);
phosg::JSON json() const;
std::string serialize_binary(Version version) const;
std::set<uint32_t> compute_all_valid_primary_identifiers() const;
// weapon_table accessors
virtual size_t num_weapon_classes() const = 0;
virtual size_t num_weapons_in_class(uint8_t data1_1) const = 0;
virtual const Weapon& get_weapon(uint8_t data1_1, uint8_t data1_2) const = 0;
// armor_table accessors
virtual size_t num_armors_or_shields_in_class(uint8_t data1_1) const = 0;
virtual const ArmorOrShield& get_armor_or_shield(uint8_t data1_1, uint8_t data1_2) const = 0;
// unit_table accessors
virtual size_t num_units() const = 0;
virtual const Unit& get_unit(uint8_t data1_2) const = 0;
virtual size_t num_mags() const = 0;
virtual const Mag& get_mag(uint8_t data1_1) const = 0;
// tool_table accessors
virtual size_t num_tool_classes() const = 0;
virtual size_t num_tools_in_class(uint8_t data1_1) const = 0;
virtual const Tool& get_tool(uint8_t data1_1, uint8_t data1_2) const = 0;
virtual std::pair<uint8_t, uint8_t> find_tool_by_id(uint32_t id) const = 0;
std::variant<const Weapon*, const ArmorOrShield*, const Unit*, const Mag*, const Tool*>
definition_for_primary_identifier(uint32_t primary_identifier) const;
// mag_table accessors
virtual size_t num_mags() const = 0;
virtual const Mag& get_mag(uint8_t data1_1) const = 0;
// weapon_kind_table accessors (data1_1 in [0, num_weapon_classes()])
virtual size_t num_weapon_kinds() const = 0;
virtual uint8_t get_weapon_kind(uint8_t data1_1) const = 0;
// photon_color_table accessors
virtual size_t num_photon_colors() const = 0;
virtual const PhotonColorEntry& get_photon_color(size_t index) const = 0;
// weapon_range_table accessors
virtual size_t num_weapon_ranges() const = 0;
virtual const WeaponRange& get_weapon_range(size_t index) const = 0;
// weapon_sale_divisor_table and non_weapon_sale_divisor_table accessors (data1_0 in [0, 1, 2]; data1_1 in [0,
// num_weapon_classes()] for weapons or ignored otherwise)
virtual size_t num_weapon_sale_divisors() const = 0;
virtual float get_sale_divisor(uint8_t data1_0, uint8_t data1_1) const = 0;
virtual const MagFeedResult& get_mag_feed_result(uint8_t table_index, uint8_t which) const = 0;
// mag_feed_table accessors (table_index in [0, 7], item_index in [0, 10])
virtual const MagFeedResult& get_mag_feed_result(uint8_t table_index, uint8_t item_index) const = 0;
// star_value_table accessors
virtual std::pair<uint32_t, uint32_t> get_star_value_index_range() const = 0;
virtual uint32_t get_special_stars_base_index() const = 0;
virtual uint8_t get_item_stars(uint32_t id) const = 0;
virtual uint8_t get_special_stars(uint8_t special) const = 0;
std::string get_star_value_table() const;
// unknown_a1 accessors
virtual std::string get_unknown_a1() const = 0;
// special_table accessors
virtual size_t num_specials() const = 0;
virtual const Special& get_special(uint8_t special) const = 0;
virtual const StatBoost& get_stat_boost(uint8_t entry_index) const = 0;
virtual uint8_t get_max_tech_level(uint8_t char_class, uint8_t tech_num) const = 0;
virtual uint8_t get_weapon_class(uint8_t data1_1) const = 0;
// weapon_effect_table accessors
virtual size_t num_weapon_effects() const = 0;
virtual const WeaponEffect& get_weapon_effect(size_t index) const = 0;
// weapon_stat_boost_index_table accessors
virtual size_t num_weapon_stat_boost_indexes() const = 0;
virtual uint8_t get_weapon_stat_boost_index(size_t index) const = 0;
std::string get_weapon_stat_boost_index_table() const;
// armor_stat_boost_index_table accessors
virtual size_t num_armor_stat_boost_indexes() const = 0;
virtual uint8_t get_armor_stat_boost_index(size_t index) const = 0;
std::string get_armor_stat_boost_index_table() const;
// shield_stat_boost_index_table accessors
virtual size_t num_shield_stat_boost_indexes() const = 0;
virtual uint8_t get_shield_stat_boost_index(size_t index) const = 0;
std::string get_shield_stat_boost_index_table() const;
// stat_boost_table accessors
virtual size_t num_stat_boosts() const = 0;
virtual const StatBoost& get_stat_boost(size_t index) const = 0;
// shield_effect_table accessors
virtual size_t num_shield_effects() const = 0;
virtual const ShieldEffect& get_shield_effect(size_t index) const = 0;
// max_tech_level_table accessors
virtual uint8_t get_max_tech_level(uint8_t char_class, uint8_t tech_num) const = 0;
// combination_table accessors
virtual size_t num_item_combinations() const = 0;
virtual const ItemCombination& get_item_combination(size_t index) const = 0;
const std::map<uint32_t, std::vector<ItemCombination>>& item_combinations_index() const;
const std::vector<ItemCombination>& all_combinations_for_used_item(const ItemData& used_item) const;
const ItemCombination& get_item_combination(const ItemData& used_item, const ItemData& equipped_item) const;
// sound_remap_table accessors
virtual const std::vector<SoundRemaps>& get_all_sound_remaps() const = 0;
// tech_boost_table accessors
virtual size_t num_tech_boosts() const = 0;
virtual const TechBoost& get_tech_boost(size_t index) const = 0;
// unwrap_table accessors
virtual size_t num_events() const = 0;
virtual std::pair<const EventItem*, size_t> get_event_items(uint8_t event_number) const = 0;
// unsealable_table accessors
virtual const std::unordered_set<uint32_t>& all_unsealable_items() const = 0;
bool is_unsealable_item(uint8_t data1_0, uint8_t data1_1, uint8_t data1_2) const;
bool is_unsealable_item(const ItemData& item) const;
// ranged_special_table accessors
virtual size_t num_ranged_specials() const = 0;
virtual const RangedSpecial& get_ranged_special(size_t index) const = 0;
// Composite accessors
std::variant<const Weapon*, const ArmorOrShield*, const Unit*, const Mag*, const Tool*>
definition_for_primary_identifier(uint32_t primary_identifier) const;
uint32_t get_item_id(const ItemData& item) const;
uint32_t get_item_team_points(const ItemData& item) const;
uint8_t get_item_base_stars(const ItemData& item) const;
uint8_t get_item_adjusted_stars(const ItemData& item, bool ignore_unidentified = false) const;
bool is_item_rare(const ItemData& item) const;
virtual bool is_unsealable_item(uint8_t data1_0, uint8_t data1_1, uint8_t data1_2) const = 0;
bool is_unsealable_item(const ItemData& item) const;
const ItemCombination& get_item_combination(const ItemData& used_item, const ItemData& equipped_item) const;
const std::vector<ItemCombination>& get_all_combinations_for_used_item(const ItemData& used_item) const;
virtual const std::map<uint32_t, std::vector<ItemCombination>>& get_all_item_combinations() const = 0;
virtual size_t num_events() const = 0;
virtual std::pair<const EventItem*, size_t> get_event_items(uint8_t event_number) const = 0;
size_t price_for_item(const ItemData& item) const;
protected:
std::shared_ptr<const std::string> data;
phosg::StringReader r;
ItemParameterTable() = default;
mutable std::unordered_map<uint16_t, Weapon> weapons;
mutable std::vector<ArmorOrShield> armors;
mutable std::vector<ArmorOrShield> shields;
mutable std::vector<Unit> units;
mutable std::vector<Mag> mags;
mutable std::unordered_map<uint16_t, Tool> tools;
mutable std::vector<Special> specials;
mutable std::vector<StatBoost> stat_boosts;
// Key is used_item. We can't index on (used_item, equipped_item) because equipped_item may contain wildcards, and
// the matching order matters.
mutable std::map<uint32_t, std::vector<ItemCombination>> item_combination_index;
explicit ItemParameterTable(std::shared_ptr<const std::string> data);
mutable std::optional<std::map<uint32_t, std::vector<ItemCombination>>> item_combination_index;
};
+4 -4
View File
@@ -46,18 +46,18 @@ ItemTranslationTable::ItemTranslationTable(
uint32_t e_id = this->entries[z].id_for_version[v_s];
if (is_canonical(e_id)) {
if (!entry_index.count(e_id)) {
throw logic_error(std::format("(row {} version {}) canonical ID {:X} is missing from the index", z, phosg::name_for_enum(v), e_id));
throw logic_error(std::format("(row {} version {}) canonical ID {:08X} is missing from the index", z, phosg::name_for_enum(v), e_id));
}
try {
item_parameter_table->definition_for_primary_identifier(e_id);
} catch (const out_of_range&) {
throw runtime_error(std::format("(row {} version {}) ID {:X} not defined in item parameter table", z, phosg::name_for_enum(v), e_id));
throw runtime_error(std::format("(row {} version {}) ID {:08X} not defined in item parameter table", z, phosg::name_for_enum(v), e_id));
}
if (!remaining_identifiers.erase(e_id)) {
throw runtime_error(std::format("(row {} version {}) ID {:X} not in item parameter table's primary identifier list", z, phosg::name_for_enum(v), e_id));
throw runtime_error(std::format("(row {} version {}) ID {:08X} not in item parameter table's primary identifier list", z, phosg::name_for_enum(v), e_id));
}
} else if (!entry_index.count(make_canonical(e_id))) {
throw runtime_error(std::format("(row {} version {}) ID {:X} refers to nonexistent canonical ID", z, phosg::name_for_enum(v), e_id));
throw runtime_error(std::format("(row {} version {}) ID {:08X} refers to nonexistent canonical ID", z, phosg::name_for_enum(v), e_id));
}
}
+41
View File
@@ -2387,6 +2387,47 @@ Action a_compare_common_item_set(
cs1->print_diff(stdout, *cs2);
});
Action a_decode_item_parameter_table(
"decode-item-parameter-table", "\
decode-item-parameter-table [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS...]\n\
Converts an ItemPMT file into a JSON item parameter table. A version\n\
option is required. Use --hex to make item codes in the output readable;\n\
however, this option also uses nonstandard JSON syntax - newserv can parse\n\
it, but many other JSON parsers can\'t. Expects compressed input (a .prs\n\
file) by default; use --decompressed if the input is not compressed.\n",
+[](phosg::Arguments& args) {
auto input_data = read_input_data(args);
if (!args.get<bool>("decompressed")) {
input_data = prs_decompress(input_data);
}
auto data = std::make_shared<string>(std::move(input_data));
auto pmt = ItemParameterTable::from_binary(data, get_cli_version(args, Version::BB_V4));
auto json = pmt->json();
uint32_t serialize_options = phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS;
if (args.get<bool>("hex")) {
serialize_options |= phosg::JSON::SerializeOption::HEX_INTEGERS;
}
string json_data = json.serialize(serialize_options);
write_output_data(args, json_data.data(), json_data.size(), nullptr);
});
Action a_encode_item_parameter_table(
"encode-item-parameter-table", "\
encode-item-parameter-table [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS...]\n\
Converts a JSON item parameter table into an ItemPMT file compatible with\n\
the game client. A version option is required. By default the output will\n\
be compressed, as the client expects; use --decompressed to get\n\
uncompressed output.\n",
+[](phosg::Arguments& args) {
auto json = phosg::JSON::parse(read_input_data(args));
auto pmt = ItemParameterTable::from_json(json);
string data = pmt->serialize_binary(get_cli_version(args, Version::BB_V4));
if (!args.get<bool>("decompressed")) {
data = prs_compress_optimal(data);
}
write_output_data(args, data.data(), data.size(), nullptr);
});
Action a_describe_item(
"describe-item", "\
describe-item DATA-OR-DESCRIPTION\n\
+2 -1
View File
@@ -2230,6 +2230,7 @@ static asio::awaitable<HandlerResult> C_V123_A0(shared_ptr<Client> c, Channel::M
// Change Ship from the lobby counter menu. We override the Change Ship action to end the proxy session, but we only
// do so if the player is in a lobby in order to properly handle the download quest case.
if (c->proxy_session->is_in_lobby) {
c->proxy_session->ending_intentionally = true;
c->proxy_session->server_channel->disconnect();
co_return HandlerResult::SUPPRESS;
} else {
@@ -2847,7 +2848,7 @@ asio::awaitable<void> handle_proxy_server_commands(
// If this is the currently-active backend channel, treat the abort as a backend disconnect.
// Normal Change Ship/Change Block reconnects replace ses->server_channel first; the old
// aborted channel will not match here, so those expected aborts stay silent.
if ((c->proxy_session == ses) && (ses->server_channel == channel)) {
if ((c->proxy_session == ses) && (ses->server_channel == channel) && !ses->ending_intentionally) {
error_str = "Server channel\ndisconnected";
}
} else {
+1
View File
@@ -16,6 +16,7 @@
struct ServerState;
struct ProxySession {
bool ending_intentionally = false;
static size_t num_proxy_sessions;
std::shared_ptr<Channel> server_channel;
+79 -12
View File
@@ -2487,10 +2487,25 @@ static asio::awaitable<void> on_pick_up_item_generic(
// TODO: Figure out what the actual max range is; 30 is an overestimate
double dist2 = fi->pos.dist2(c->pos);
if (dist2 > 900.0) {
l->log.warning_f("Player {} requests to pick up {:08X}, but it is too far away (dist2={})",
client_id, item_id, dist2);
l->add_item(floor, fi);
co_return;
const bool allow_dcv2_falz_pickup_distance_recovery =
is_request &&
(c->version() == Version::DC_V2) &&
(l->episode == Episode::EP1) &&
(floor == 0x0E) &&
(fi->from_obj == nullptr) &&
(fi->from_ene == nullptr) &&
fi->visible_to_client(c->lobby_client_id);
if (allow_dcv2_falz_pickup_distance_recovery) {
l->log.warning_f(
"DC V2 Falz floor item pickup distance recovery: Player {} picking up {:08X}; dist2={} item_floor={} player_floor={}",
client_id, item_id, dist2, static_cast<uint64_t>(floor), static_cast<uint64_t>(c->floor));
} else {
l->log.warning_f("Player {} requests to pick up {:08X}, but it is too far away (dist2={})",
client_id, item_id, dist2);
l->add_item(floor, fi);
co_return;
}
}
try {
@@ -3696,21 +3711,61 @@ static asio::awaitable<void> on_update_enemy_state(shared_ptr<Client> c, Subcomm
}
bool should_track_hit = (src_flags & 0x00000200); // "Enemy was hit" flag (see 6x0A comments in CommandFormats.hh)
uint16_t incoming_total_damage = cmd.total_damage.load();
bool is_boss = type_definition_for_enemy(ene_st->super_ene->type).is_boss();
bool blocked_damage_rollback = is_boss && (incoming_total_damage < ene_st->total_damage);
if (should_track_hit) {
ene_st->set_last_hit_by_client_id(c->lobby_client_id);
}
ene_st->game_flags = src_flags;
ene_st->total_damage = cmd.total_damage;
l->log.info_f("E-{:03X} updated to damage={} game_flags={:08X}; last hit {}",
ene_st->e_id, ene_st->total_damage, ene_st->game_flags, should_track_hit ? "claimed" : "not claimed");
if (blocked_damage_rollback) {
uint32_t old_game_flags = ene_st->game_flags;
ene_st->game_flags |= src_flags;
l->log.warning_f("Blocked boss damage rollback and merged flags via 6x0A from C-{} on E-{:03X}: incoming_damage={} current_damage={} incoming_flags={:08X} old_flags={:08X} merged_flags={:08X}",
c->lobby_client_id, ene_st->e_id, incoming_total_damage, ene_st->total_damage, src_flags, old_game_flags, ene_st->game_flags);
} else {
ene_st->game_flags = src_flags;
ene_st->total_damage = incoming_total_damage;
}
// Forward the server-authoritative damage/flags, not stale lower state from the sender.
cmd.total_damage = ene_st->total_damage;
cmd.game_flags = is_big_endian(c->version()) ? phosg::bswap32(ene_st->game_flags) : ene_st->game_flags;
l->log.info_f("E-{:03X} updated to damage={} game_flags={:08X}; last hit {}{}",
ene_st->e_id,
ene_st->total_damage,
ene_st->game_flags,
should_track_hit ? "claimed" : "not claimed",
blocked_damage_rollback ? " (damage rollback blocked)" : "");
if (ene_st->alias_target_ene_st) {
bool alias_is_boss = type_definition_for_enemy(ene_st->alias_target_ene_st->super_ene->type).is_boss();
bool alias_blocked_damage_rollback = alias_is_boss && (incoming_total_damage < ene_st->alias_target_ene_st->total_damage);
if (should_track_hit) {
ene_st->alias_target_ene_st->set_last_hit_by_client_id(c->lobby_client_id);
}
ene_st->alias_target_ene_st->game_flags = src_flags;
ene_st->alias_target_ene_st->total_damage = cmd.total_damage;
l->log.info_f("Alias target E-{:03X} updated to damage={} game_flags={:08X}; last hit {}",
ene_st->alias_target_ene_st->e_id, ene_st->alias_target_ene_st->total_damage, ene_st->alias_target_ene_st->game_flags, should_track_hit ? "claimed" : "not claimed");
if (alias_blocked_damage_rollback) {
uint32_t old_alias_game_flags = ene_st->alias_target_ene_st->game_flags;
ene_st->alias_target_ene_st->game_flags |= src_flags;
l->log.warning_f("Blocked boss damage rollback and merged flags via 6x0A from C-{} on alias target E-{:03X}: incoming_damage={} current_damage={} incoming_flags={:08X} old_flags={:08X} merged_flags={:08X}",
c->lobby_client_id,
ene_st->alias_target_ene_st->e_id,
incoming_total_damage,
ene_st->alias_target_ene_st->total_damage,
src_flags,
old_alias_game_flags,
ene_st->alias_target_ene_st->game_flags);
} else {
ene_st->alias_target_ene_st->game_flags = src_flags;
ene_st->alias_target_ene_st->total_damage = incoming_total_damage;
}
l->log.info_f("Alias target E-{:03X} updated to damage={} game_flags={:08X}; last hit {}{}",
ene_st->alias_target_ene_st->e_id,
ene_st->alias_target_ene_st->total_damage,
ene_st->alias_target_ene_st->game_flags,
should_track_hit ? "claimed" : "not claimed",
alias_blocked_damage_rollback ? " (damage rollback blocked)" : "");
}
// TODO: It'd be nice if this worked on bosses too, but it seems we have to use each boss' specific state-syncing
@@ -3929,6 +3984,18 @@ static asio::awaitable<void> on_dragon_actions_6x12(shared_ptr<Client> c, Subcom
throw runtime_error("DRAGON enemy is an alias");
}
l->log.info_f("Dragon 6x12 from C-{} on E-{:03X}: phase={:04X} unknown_a3={:04X} target_client_id={:08X} pos=({:g}, {:g}) damage={} game_flags={:08X} set_flags={:04X}",
c->lobby_client_id,
ene_st->e_id,
cmd.phase.load(),
cmd.unknown_a3.load(),
cmd.target_client_id.load(),
cmd.x.load(),
cmd.z.load(),
ene_st->total_damage,
ene_st->game_flags,
ene_st->set_flags);
G_DragonBossActions_GC_6x12 sw_cmd = {{cmd.header.subcommand, cmd.header.size, cmd.header.entity_id.load()},
cmd.phase.load(), cmd.unknown_a3.load(), cmd.target_client_id.load(), cmd.x.load(), cmd.z.load()};
bool sender_is_be = is_big_endian(c->version());
+48 -50
View File
@@ -692,6 +692,7 @@ void send_guild_card_chunk_bb(shared_ptr<Client> c, size_t chunk_index) {
}
static bool is_battle_param_stream_file_for_blueballz(const string& filename) {
return (filename == "BattleParamEntry.dat") ||
(filename == "BattleParamEntry_on.dat") ||
@@ -701,31 +702,23 @@ static bool is_battle_param_stream_file_for_blueballz(const string& filename) {
(filename == "BattleParamEntry_ep4_on.dat");
}
static shared_ptr<const string> bb_stream_file_data_for_client(shared_ptr<Client> c, const string& filename) {
static string bb_stream_file_data_for_client(shared_ptr<Client> c) {
auto s = c->require_server_state();
auto raw_data = s->bb_stream_files_cache->get_or_load("system/blueburst/" + filename).file->data;
int64_t effective_blueballz_hp_scale_tier = (c->selected_blueballz_tier >= 0)
? c->selected_blueballz_tier
: s->blueballz_enemy_hp_scale_tier;
if (!is_battle_param_stream_file_for_blueballz(filename) || (effective_blueballz_hp_scale_tier < 0)) {
return raw_data;
if (effective_blueballz_hp_scale_tier < 0) {
return s->bb_stream_file->data;
}
effective_blueballz_hp_scale_tier = std::min<int64_t>(
s->blueballz_max_tier,
effective_blueballz_hp_scale_tier);
string scaled_data = *raw_data;
if (scaled_data.size() < sizeof(BattleParamsIndex::Table)) {
c->log.warning_f("Blueballz enemy HP scaling skipped for {}; file is too small", filename);
return raw_data;
}
string scaled_data = s->bb_stream_file->data;
double mult = 1.0 + (static_cast<double>(effective_blueballz_hp_scale_tier) * 0.25);
auto* table = reinterpret_cast<BattleParamsIndex::Table*>(scaled_data.data());
size_t ultimate_index = static_cast<size_t>(Difficulty::ULTIMATE);
auto scale_u16 = [mult](uint32_t v) -> uint16_t {
@@ -742,28 +735,39 @@ static shared_ptr<const string> bb_stream_file_data_for_client(shared_ptr<Client
return static_cast<uint16_t>(scaled);
};
for (size_t z = 0; z < 0x60; z++) {
auto& stats = table->stats[ultimate_index][z];
stats.char_stats.hp = scale_u16(stats.char_stats.hp);
for (const auto& sf_entry : s->bb_stream_file->entries) {
if (!is_battle_param_stream_file_for_blueballz(sf_entry.filename)) {
continue;
}
if ((sf_entry.offset > scaled_data.size()) ||
(sf_entry.size > (scaled_data.size() - sf_entry.offset))) {
c->log.warning_f("Blueballz enemy HP scaling skipped for {}; invalid stream-file range",
sf_entry.filename);
continue;
}
if (sf_entry.size < sizeof(BattleParamsIndex::Table)) {
c->log.warning_f("Blueballz enemy HP scaling skipped for {}; file is too small",
sf_entry.filename);
continue;
}
auto* table = reinterpret_cast<BattleParamsIndex::Table*>(
scaled_data.data() + sf_entry.offset);
for (size_t z = 0; z < 0x60; z++) {
auto& stats = table->stats[ultimate_index][z];
stats.char_stats.hp = scale_u16(stats.char_stats.hp);
}
c->log.info_f("Blueballz enemy HP scaling: serving {} with tier {} ({:g}x Ultimate HP)",
sf_entry.filename, effective_blueballz_hp_scale_tier, mult);
}
c->log.info_f("Blueballz enemy HP scaling: serving {} with tier {} ({:g}x Ultimate HP)",
filename, effective_blueballz_hp_scale_tier, mult);
return make_shared<string>(std::move(scaled_data));
return scaled_data;
}
static const vector<string> stream_file_entries = {
"ItemMagEdit.prs",
"ItemPMT.prs",
"BattleParamEntry.dat",
"BattleParamEntry_on.dat",
"BattleParamEntry_lab.dat",
"BattleParamEntry_lab_on.dat",
"BattleParamEntry_ep4.dat",
"BattleParamEntry_ep4_on.dat",
"PlyLevelTbl.prs",
};
void send_stream_file_index_bb(shared_ptr<Client> c) {
auto s = c->require_server_state();
@@ -771,15 +775,19 @@ void send_stream_file_index_bb(shared_ptr<Client> c) {
c->log.info_f("PSO Peeps BBZ stream debug: send_stream_file_index_bb called");
vector<S_StreamFileIndexEntry_BB_01EB> entries;
size_t offset = 0;
for (const string& filename : stream_file_entries) {
auto file_data = bb_stream_file_data_for_client(c, filename);
string contents = bb_stream_file_data_for_client(c);
for (const auto& sf_entry : s->bb_stream_file->entries) {
if ((sf_entry.offset > contents.size()) ||
(sf_entry.size > (contents.size() - sf_entry.offset))) {
throw runtime_error("invalid BB stream file entry range");
}
auto& e = entries.emplace_back();
e.size = file_data->size();
e.checksum = crc32(file_data->data(), e.size);
e.offset = offset;
e.filename.encode(filename);
offset += e.size;
e.size = sf_entry.size;
e.checksum = crc32(contents.data() + sf_entry.offset, e.size);
e.offset = sf_entry.offset;
e.filename.encode(sf_entry.filename);
}
send_command_vt(c, 0x01EB, entries.size(), entries);
}
@@ -787,18 +795,7 @@ void send_stream_file_index_bb(shared_ptr<Client> c) {
void send_stream_file_chunk_bb(shared_ptr<Client> c, uint32_t chunk_index) {
auto s = c->require_server_state();
c->log.info_f("PSO Peeps BBZ stream debug: send_stream_file_chunk_bb called for chunk {}", chunk_index);
size_t total_bytes = 0;
for (const auto& name : stream_file_entries) {
total_bytes += bb_stream_file_data_for_client(c, name)->size();
}
string contents;
contents.reserve(total_bytes);
for (const auto& name : stream_file_entries) {
contents += *bb_stream_file_data_for_client(c, name);
}
string contents = bb_stream_file_data_for_client(c);
S_StreamFileChunk_BB_02EB chunk_cmd;
chunk_cmd.chunk_index = chunk_index;
@@ -809,6 +806,7 @@ void send_stream_file_chunk_bb(shared_ptr<Client> c, uint32_t chunk_index) {
size_t bytes = min<size_t>(contents.size() - offset, sizeof(chunk_cmd.data));
chunk_cmd.data.assign_range(reinterpret_cast<const uint8_t*>(contents.data() + offset), bytes, 0);
size_t cmd_size = offsetof(S_StreamFileChunk_BB_02EB, data) + bytes;
cmd_size = (cmd_size + 3) & ~3;
send_command(c, 0x02EB, 0x00000000, &chunk_cmd, cmd_size);
+36 -6
View File
@@ -79,7 +79,6 @@ ServerState::ServerState(const string& config_filename, bool is_replay)
config_filename(config_filename),
is_replay(is_replay),
thread_pool(make_unique<asio::thread_pool>()),
bb_stream_files_cache(new FileContentsCache(3600000000ULL)),
bb_system_cache(new FileContentsCache(3600000000ULL)),
gba_files_cache(new FileContentsCache(3600000000ULL)) {}
@@ -1847,8 +1846,6 @@ vector<shared_ptr<const SuperMap>> ServerState::supermaps_for_variations(
}
void ServerState::clear_file_caches() {
config_log.info_f("Clearing BB stream file cache");
this->bb_stream_files_cache.reset(new FileContentsCache(3600000000ULL));
config_log.info_f("Clearing BB system cache");
this->bb_system_cache.reset(new FileContentsCache(3600000000ULL));
config_log.info_f("Clearing GBA file cache");
@@ -2164,10 +2161,9 @@ void ServerState::load_item_definitions() {
config_log.info_f("Loading item definition tables");
for (size_t v_s = NUM_PATCH_VERSIONS; v_s < NUM_VERSIONS; v_s++) {
Version v = static_cast<Version>(v_s);
string path = std::format("system/item-tables/ItemPMT-{}.prs", file_path_token_for_version(v));
string path = std::format("system/item-tables/item-parameter-table-{}.json", file_path_token_for_version(v));
config_log.debug_f("Loading item definition table {}", path);
auto data = make_shared<string>(prs_decompress(phosg::load_file(path)));
new_item_parameter_tables[v_s] = ItemParameterTable::create(data, v);
new_item_parameter_tables[v_s] = ItemParameterTable::from_json(phosg::JSON::parse(phosg::load_file(path)));
}
auto json = phosg::JSON::parse(phosg::load_file("system/item-tables/translation-table.json"));
@@ -2243,6 +2239,39 @@ void ServerState::load_dol_files() {
this->dol_file_index = make_shared<DOLFileIndex>("system/dol");
}
void ServerState::generate_bb_stream_file() {
config_log.info_f("Generating BB stream file");
auto sf = std::make_shared<BBStreamFile>();
auto add_file = [&](const std::string& filename, std::string&& file_data = "") -> void {
if (file_data.empty()) {
file_data = phosg::load_file("system/blueburst/" + filename);
}
auto& e = sf->entries.emplace_back();
e.size = file_data.size();
e.checksum = phosg::crc32(file_data.data(), file_data.size());
e.offset = sf->data.size();
e.filename = filename;
sf->data += file_data;
config_log.debug_f(
"[BBStreamFile] Added file {} at offset {:08X} ({:08X} bytes) with checksum {:08X}; total size is now {:08X}",
filename, e.offset, e.size, e.checksum, sf->data.size());
};
add_file("BattleParamEntry.dat");
add_file("BattleParamEntry_on.dat");
add_file("BattleParamEntry_lab.dat");
add_file("BattleParamEntry_lab_on.dat");
add_file("BattleParamEntry_ep4.dat");
add_file("BattleParamEntry_ep4_on.dat");
add_file("PlyLevelTbl.prs");
add_file("ItemMagEdit.prs");
auto pmt = this->item_parameter_table(Version::BB_V4);
add_file("ItemPMT.prs", prs_compress_optimal(pmt->serialize_binary(Version::BB_V4)));
this->bb_stream_file = sf;
}
void ServerState::create_default_lobbies() {
if (this->default_lobbies_created) {
return;
@@ -2322,6 +2351,7 @@ void ServerState::load_all(bool enable_thread_pool) {
this->load_config_late();
this->load_teams();
this->load_quest_index();
this->generate_bb_stream_file();
}
void ServerState::disconnect_all_banned_clients() {
+13 -1
View File
@@ -65,6 +65,17 @@ struct CheatFlags {
explicit CheatFlags(const phosg::JSON& json);
};
struct BBStreamFile {
struct Entry {
uint32_t offset;
uint32_t size;
uint32_t checksum; // crc32
std::string filename;
};
std::vector<Entry> entries;
std::string data;
};
struct ServerState : public std::enable_shared_from_this<ServerState> {
enum class RunShellBehavior {
DEFAULT = 0,
@@ -188,7 +199,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
std::unordered_map<uint64_t, std::shared_ptr<const SuperMap>> supermap_for_source_hash_sum;
std::unordered_map<uint32_t, std::shared_ptr<const SuperMap>> supermap_for_free_play_key;
std::shared_ptr<const RoomLayoutIndex> room_layout_index;
std::shared_ptr<FileContentsCache> bb_stream_files_cache;
std::shared_ptr<const BBStreamFile> bb_stream_file;
std::shared_ptr<FileContentsCache> bb_system_cache;
std::shared_ptr<FileContentsCache> gba_files_cache;
std::shared_ptr<const DOLFileIndex> dol_file_index;
@@ -450,6 +461,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
void load_quest_index(bool raise_on_any_failure = false);
void compile_functions(bool raise_on_any_failure = false);
void load_dol_files();
void generate_bb_stream_file();
void load_all(bool enable_thread_pool);
+3
View File
@@ -211,14 +211,17 @@ ShellCommand c_reload(
args.s->load_set_data_tables();
} else if (type == "battle-params") {
args.s->load_battle_params();
args.s->generate_bb_stream_file();
} else if (type == "level-tables") {
args.s->load_level_tables();
args.s->generate_bb_stream_file();
} else if (type == "text-index") {
args.s->load_text_index();
} else if (type == "word-select") {
args.s->load_word_select_table();
} else if (type == "item-definitions") {
args.s->load_item_definitions();
args.s->generate_bb_stream_file();
} else if (type == "item-name-index") {
args.s->load_item_name_indexes();
} else if (type == "drop-tables") {
+3 -3
View File
@@ -478,8 +478,8 @@ Language language_for_name(const string& name) {
}
const vector<string> tech_id_to_name = {
"foie", "gifoie", "rafoie", "barta", "gibarta", "rabarta", "zonde", "gizonde", "razonde", "grants", "deband",
"jellen", "zalure", "shifta", "ryuker", "resta", "anti", "reverser", "megid"};
"Foie", "Gifoie", "Rafoie", "Barta", "Gibarta", "Rabarta", "Zonde", "Gizonde", "Razonde", "Grants", "Deband",
"Jellen", "Zalure", "Shifta", "Ryuker", "Resta", "Anti", "Reverser", "Megid"};
const unordered_map<string, uint8_t> name_to_tech_id = {
{"foie", 0}, {"gifoie", 1}, {"rafoie", 2}, {"barta", 3}, {"gibarta", 4}, {"rabarta", 5}, {"zonde", 6},
@@ -497,7 +497,7 @@ const string& name_for_technique(uint8_t tech) {
uint8_t technique_for_name(const string& name) {
try {
return name_to_tech_id.at(name);
return name_to_tech_id.at(phosg::tolower(name));
} catch (const out_of_range&) {
}
try {
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
../item-tables/ItemPMT-bb-v4.prs
@@ -1,6 +1,8 @@
.meta name="Kill count fix"
.meta description="Fixes client-side\nkill counts when\nmultiple enemies are\nkilled on the same\nframe"
.versions 59NJ 59NL
entry_ptr:
reloc0:
.offsetof start
@@ -9,9 +11,9 @@ start:
.data 0x005E32C8
.data <VERS 0x005E32A4 0x005E32C8>
.deltaof TItemUnitUnsealable_count_kill, TItemUnitUnsealable_count_kill_end
.address 0x005E32C8
.address <VERS 0x005E32A4 0x005E32C8>
TItemUnitUnsealable_count_kill: # [std] (TItemUnitUnsealable* this @ ecx) -> void
mov eax, [ecx + 0xF8]
movsx eax, word [eax + 0x11A] # eax = this->owner_player->num_kills_since_map_load
@@ -29,14 +31,14 @@ TItemUnitUnsealable_count_kill_skip_update:
setae dh
shl edx, 1
or dword [ecx + 0xDC], edx
jmp 0x005E2C34
jmp <VERS 0x005E2C10 0x005E2C34>
TItemUnitUnsealable_count_kill_end:
.data 0x005F3EFC
.data <VERS 0x005F3E94 0x005F3EFC>
.deltaof TItemWeapon_LameDArgent_count_kill, TItemWeapon_LameDArgent_count_kill_end
.address 0x005F3EFC
.address <VERS 0x005F3E94 0x005F3EFC>
TItemWeapon_LameDArgent_count_kill:
mov eax, [ecx + 0xF8]
movsx eax, word [eax + 0x11A]
@@ -59,9 +61,9 @@ TItemWeapon_LameDArgent_count_kill_end:
.data 0x005FCA74
.data <VERS 0x005FC95C 0x005FCA74>
.deltaof TItemWeapon_SealedJSword_count_kill, TItemWeapon_SealedJSword_count_kill_end
.address 0x005FCA74
.address <VERS 0x005FC95C 0x005FCA74>
TItemWeapon_SealedJSword_count_kill:
mov eax, [ecx + 0xF8]
movsx eax, word [eax + 0x11A]
@@ -0,0 +1,624 @@
# This patch changes the number of BB character save slots from 4 to any number
# up to 127.
# This patch is for documentation purposes only; it works when used as a server
# patch via newserv, but is decidedly inconvenient to use via this method. This
# is because it affects logic that runs before any patches can be sent by the
# server, so the player has to connect once to get the patch, then disconnect
# and connect again to use the additional slots.
# As written, this patch changes the slot count from 4 to 12. To use a
# different slot count, first compute the following values:
# slot count = your desired number of player slots (must be >= 4, <= 127)
# total file size = (slot count * 0x2EA4) + 0x14
# bgm_test_songs_unlocked offset = total file size - 0x10
# save_count offset = total file size - 8
# round2_seed offset = total file size - 4
# Then, for each of the above, search for the string to the left of the = sign
# and change the values used in all of the matching lines.
.meta name="More save slots"
.meta description=""
.meta hide_from_patches_menu
entry_ptr:
reloc0:
.offsetof start
# Include a few functions first
write_call_to_code:
.include WriteCallToCode-59NJ
memcpy:
.include CopyData
ret
start:
# Apply all necessary patches
call apply_enable_scroll_patch
call apply_fix_scroll_patch1
call apply_fix_scroll_patch2
call apply_fix_file_index
call apply_preview_window_fix
call apply_static_patches
# Rewrite the existing char file regions to have the appropriate size; this
# must be done after the patches are applied because we call the checksum
# function, which is patched by one of the above calls
call update_existing_char_file_list
jmp update_existing_char_file_list_memcard
apply_enable_scroll_patch:
# This patch enables scrolling behavior within the character list
push -5 # Jump size (negative = jmp instead of call)
push 0x00413B77 # Jump address
call get_code_size_for_enable_scroll
.deltaof enable_scroll_start, enable_scroll_end
get_code_size_for_enable_scroll:
pop eax
push dword [eax]
call enable_scroll_end
enable_scroll_start:
mov eax, dword ptr [edi + 0x28] # cursor = char_select_menu->cursor_obj (TAdSelectCurGC*)
or dword [eax + 0x01F8], 3 # cursor->flags |= 3 # Enable scrolling
mov eax, [0x00A38BD0] # scroll_bar = TAdScrollBarXb_objs[0]
mov ecx, [eax + 0xEC] # ecx = scroll_bar->client_id
imul ecx, ecx, 0x24
# Set up scroll bar graphics (in struct at scroll_bar + 0x1C)
mov dword [eax + ecx + 0x1C], 0x439D0000
mov dword [eax + ecx + 0x20], 0x43360000
mov dword [eax + ecx + 0x24], 0x439D0000
mov dword [eax + ecx + 0x28], 0x4392AB85
mov dword [eax + ecx + 0x2C], 0x40400000
mov dword [eax + ecx + 0x30], 0x425EA3D7
mov dword [eax + ecx + 0x34], 0x00000008
mov dword [eax + ecx + 0x38], 0x00000000
mov dword [eax + ecx + 0x3C], 0x00000000
or dword [eax + 0xF0], 1 # scroll_bar->flags |= 1
mov ecx, [eax + 0xEC]
shl ecx, 4
mov dword [eax + ecx + 0xAC], 0 # scroll_bar->selection_state[client_id].scroll_offset = 0
mov dword [eax + ecx + 0xB0], 0 # scroll_bar->selection_state[client_id].selected_index = 0
mov dword [eax + ecx + 0xB4], 4 # scroll_bar->selection_state[client_id].num_items_in_view = 4
mov dword [eax + ecx + 0xB8], 0x0B # scroll_bar->selection_state[client_id].last_item_index = (slot count - 1)
pop edi
ret
enable_scroll_end:
call write_call_to_code
ret
apply_fix_scroll_patch1:
# This patch fixes character selection cursor object so it will take the
# scroll offset into account
push 6 # Call size
push 0x00413C30 # Call address
call get_code_size_for_fix_scroll_patch1
.deltaof fix_scroll_patch1_start, fix_scroll_patch1_end
get_code_size_for_fix_scroll_patch1:
pop eax
push dword [eax]
call fix_scroll_patch1_end
fix_scroll_patch1_start:
mov edx, [edi + 0x28] # cursor = this->ad_select_cur_obj (TAdSelectCurGC*)
mov ebp, [edx + 0x44] # ebp = cursor->selected_index_within_view
mov eax, [0x00A38BD0] # scroll_bar = TAdScrollBarXb_objs[0]
add ebp, [eax + 0xAC] # ebp += scroll_bar->selection_state[0].scroll_offset
ret
fix_scroll_patch1_end:
call write_call_to_code
ret
apply_fix_scroll_patch2:
# This patch changes the TAdSinglePlyChrSelectGC::selected_index_within_view
# to be the selected character's absolute index (including scroll_offset),
# not the index only within the displayed four characters
push 6 # Call size
push 0x00413CD0 # Call address
call get_code_size_for_fix_scroll_patch2
.deltaof fix_scroll_patch2_start, fix_scroll_patch2_end
get_code_size_for_fix_scroll_patch2:
pop eax
push dword [eax]
call fix_scroll_patch2_end
fix_scroll_patch2_start:
mov eax, [0x00A38BD0] # scroll_bar = TAdScrollBarXb_objs[0]
mov eax, [eax + 0xAC] # eax = scroll_bar->selection_state[0].scroll_offset
mov edx, [edi + 0x28] # cursor = this->ad_select_cur_obj (TAdSelectCurGC*)
add eax, [edx + 0x44] # eax += cursor->selected_index_within_view
ret
fix_scroll_patch2_end:
call write_call_to_code
ret
apply_fix_file_index:
# This patch fixes the character file indexing so it will account for the
# scroll position
push 5 # Call size
push 0x00413CE8 # Call address
call get_code_size_for_selection_index_fix2
.deltaof selection_index_fix2_start, selection_index_fix2_end
get_code_size_for_selection_index_fix2:
pop eax
push dword [eax]
call selection_index_fix2_end
selection_index_fix2_start:
mov eax, [0x00A38BD0]
mov eax, [eax + 0xAC] # eax = TAdScrollBarXb_objs[0]->selection_state[0].scroll_offset
add ebp, eax # arg0 += eax
mov [esp + 4], ebp
mov eax, 0x006C1ABC
jmp eax # set_current_char_slot
selection_index_fix2_end:
call write_call_to_code
ret
apply_preview_window_fix:
# This patch fixes the preview display so it will show the correct section
# ID, level, etc.
push 5 # Call size
push 0x0040216C # Call address
call get_code_size_for_preview_window_fix
.deltaof preview_window_fix_start, preview_window_fix_end
get_code_size_for_preview_window_fix:
pop eax
push dword [eax]
call preview_window_fix_end
preview_window_fix_start:
mov eax, [0x00A38BD0] # scroll_bar = TAdScrollBarXb_objs[0]
mov eax, [eax + 0xAC] # eax = scroll_bar->selection_state[0].scroll_offset
add [esp + 4], eax
mov eax, 0x006C4514 # get_player_preview_info
jmp eax
preview_window_fix_end:
# This patch applies in two places, so push the second set of args now, then
# apply it twice
push 5 # Call size
push 0x00401842 # Call address
push dword [esp + 0x10] # Code size
push dword [esp + 0x10] # Code address
call write_call_to_code
call write_call_to_code
ret
apply_static_patches:
.include WriteCodeBlocksBB
# These patches change various places where the character data size and slot
# count are referenced
.data 0x00475294
.data 0x00000001
.binary 0C # slot count; TDataProtocol::handle_E5
.data 0x0047534B
.data 0x00000001
.binary 0C # slot count; import_player_preview
.data 0x004786D1
.data 0x00000001
.binary 0C # slot count; TDataProtocol::handle_E4
.data 0x00482559
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C17FB
.data 0x00000001
.binary 0C # slot count
.data 0x006C1D07
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C1D3A
.data 0x00000001
.binary 0C # slot count
.data 0x006C1D58
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C1E13
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C226A
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C22A9
.data 0x00000001
.binary 0C # slot count
.data 0x006C22CA
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C22DA
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C2517
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C267F
.data 0x00000004
.data 0x00022FBC # save_count offset
.data 0x006C2689
.data 0x00000004
.data 0x00022FBC # save_count offset
.data 0x006C272B
.data 0x00000004
.data 0x00022FBC # save_count offset
.data 0x006C2741
.data 0x00000004
.data 0x00022FC0 # round2_seed offset
.data 0x006C27CF
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C28A8
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C314F
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C357B
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C35BA
.data 0x00000001
.binary 0C # slot count
.data 0x006C35E6
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C35F3
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C360E
.data 0x00000004
.data 0x00022FBC # save_count offset
.data 0x006C3617
.data 0x00000004
.data 0x00022FBC # save_count offset
.data 0x006C371C
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C3B5A
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C424D
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C4833
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C486A
.data 0x00000001
.binary 0C # slot count
.data 0x006C49A6
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C49DD
.data 0x00000001
.binary 0C # slot count
.data 0x006C4AC5
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C4AFE
.data 0x00000001
.binary 0C # slot count
.data 0x006C4CDE
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C4D15
.data 0x00000001
.binary 0C # slot count
.data 0x006C4DFD
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C4E36
.data 0x00000001
.binary 0C # slot count
.data 0x006C4F9C
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C4FD7
.data 0x00000001
.binary 0C # slot count
.data 0x006C51C5
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5201
.data 0x00000001
.binary 0C # slot count
.data 0x006C5376
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C53B0
.data 0x00000001
.binary 0C # slot count
.data 0x006C5545
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5581
.data 0x00000001
.binary 0C # slot count
.data 0x006C56F6
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5730
.data 0x00000001
.binary 0C # slot count
.data 0x006C58B6
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C58F0
.data 0x00000001
.binary 0C # slot count
.data 0x006C5A85
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5AC1
.data 0x00000001
.binary 0C # slot count
.data 0x006C5BB2
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5BEC
.data 0x00000001
.binary 0C # slot count
.data 0x006C5D72
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5DAC
.data 0x00000001
.binary 0C # slot count
.data 0x006C5F32
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C5F6C
.data 0x00000001
.binary 0C # slot count
.data 0x006C60F2
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C612C
.data 0x00000001
.binary 0C # slot count
.data 0x006C6346
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C6381
.data 0x00000001
.binary 0C # slot count
.data 0x006C6505
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C6541
.data 0x00000001
.binary 0C # slot count
.data 0x006C6632
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C666C
.data 0x00000001
.binary 0C # slot count
.data 0x006C67F2
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C682C
.data 0x00000001
.binary 0C # slot count
.data 0x006C69B2
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C69EC
.data 0x00000001
.binary 0C # slot count
.data 0x006C6B87
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C6BB8
.data 0x00000004
.data 0x0000005D # memcard block count
.data 0x006C6C3A
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C6C74
.data 0x00000001
.binary 0C # slot count
.data 0x006C6E82
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C6EBC
.data 0x00000001
.binary 0C # slot count
.data 0x006C70B9
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C70F3
.data 0x00000001
.binary 0C # slot count
.data 0x006C7A46
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C7D66
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x006C7D7C
.data 0x00000001
.binary 0C # slot count
.data 0x006C7DC0
.data 0x00000004
.data 0x00022FC4 # total file size
.data 0x0077CC72
.data 0x00000004
.data 0x00022FB4 # bgm_test_songs_unlocked offset
# Signature check on all save files (rewritten as loop)
.data 0x006C1C69
.deltaof sig_check_begin, sig_check_end
sig_check_begin:
mov edx, 0xC87ED5B1 # Expected signature value
add eax, 0x04E8 # &char_file_list->chars[0].part2.signature
mov ecx, 0x0C # slot count
again:
cmp dword [eax], 0 # signature == 0 (no char in slot)
je sig_ok
cmp dword [eax], edx # signature == expected value
jne sig_bad
sig_ok:
add eax, 0x2EA4 # Advance to next slot
dec ecx
jnz again
xor eax, eax # All signatures OK (eax = 0)
jmp sig_check_end
sig_bad:
xor eax, eax # Bad signature (eax = 1)
inc eax
jmp sig_check_end
.binary CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
sig_check_end: # 006C1CB2
# Send slot count in E3 command
.data 0x0046EC10 # TDataProtocol::send_E3_for_index
.deltaof send_slot_count_in_E3_begin, send_slot_count_in_E3_end
send_slot_count_in_E3_begin:
# ecx = this (TDataProtocol*)
# [esp + 4] = slot_index
push 0
push dword [esp + 8] # slot_index
push 0x0C # slot count
push 0x00E30010
mov eax, esp
push 0x10
push eax
mov eax, [ecx]
call [eax + 0x20] # this->send_command(&cmd, 0x10) // ret 8
add esp, 8
mov eax, 0x006C1ABC
call eax # set_current_char_slot(slot_index) // ret 0
add esp, 8
ret 4
send_slot_count_in_E3_end:
# Show slot number in each menu item
.data 0x00401D57
.deltaof show_slot_number_begin, show_slot_number_end
show_slot_number_begin:
# Original call (sprintf(line_buf, "LV%d", preview_info->visual.disp.level + 1))
lea edx, [esp + 0x02C4]
mov ebx, [ebx + 8]
inc ebx
push ebx
mov ecx, esi
push edx
mov eax, 0x00402604
call eax
# Find the end of the string
lea eax, [esp + 0x02C4]
show_slot_number_strend_again:
cmp word [eax], 0
je show_slot_number_strend_done
add eax, 2
jmp show_slot_number_strend_again
show_slot_number_strend_done:
# Format the slot number and append it to the string
mov ecx, [0x00A38BD0] # scroll_bar = TAdScrollBarXb_objs[0]
mov ecx, [ecx + 0xAC] # ecx = scroll_bar->selection_state[0].scroll_offset
lea ecx, [ecx + ebp + 1]
push ecx # Slot number (scroll_offset + z)
call get_show_slot_number_suffix_fmt
.binary 20002800230025006400290020000000 # L" (#%d) "
get_show_slot_number_suffix_fmt:
push eax # Destination buffer
mov eax, 0x00835578 # _swprintf
call eax
add esp, 0x0C
jmp show_slot_number_end
.zero 0x96
show_slot_number_end: # 00401E4D
# End static patches
.data 0x00000000
.data 0x00000000
update_existing_char_file_list:
# Replace the existing character list with an appropriately-longer one. This
# part does not need to be done if the patch is applied statically to the
# executable; this is only necessary when used as a server patch because the
# character list is already allocated at the time the patch is applied.
push 0x00022FC4 # total file size
mov eax, 0x00835915 # operator_new
call eax
add esp, 4
mov edx, [0x00A939C4] # edx = old char_file_list
mov [0x00A939C4], eax
mov ecx, [edx + 0xBA94] # Copy bgm_test_songs_unlocked_high to new file
mov [eax + 0x00022FB4], ecx
mov ecx, [edx + 0xBA98] # Copy bgm_test_songs_unlocked_low to new file
mov [eax + 0x00022FB8], ecx
mov ecx, [edx + 0xBA9C] # Copy save_count to new file
mov [eax + 0x00022FBC], ecx
mov ecx, [edx + 0xBAA0] # Copy round2_seed to new file
mov [eax + 0x00022FC0], ecx
add eax, 4
add edx, 4
mov ecx, 0xBA90
call memcpy # Copy the existing 4 characters over
mov eax, [0x00A939C4]
add eax, 0xBA94
mov ecx, 4
clear_next_char:
cmp ecx, 0x0C # slot count
jge clear_next_char_done
lea edx, [eax + 0x2EA4] # edx = ptr to next char (or footer)
clear_next_char_write_again:
mov dword [eax], 0
add eax, 4
cmp eax, edx
jl clear_next_char_write_again
clear_next_char_done:
# Call eh_vector_constructor_iterator(
# &char_file_list.chars[4],
# sizeof(char_file_list.chars[0]),
# countof(char_file_list.chars) - 4,
# PSOCharacterFile::init,
# PSOCharacterFile::destroy)
push 0x006C197C # PSOCharacterFile::destroy
push 0x006C182C # PSOCharacterFile::init
push 0x08 # slot count - 4
push 0x2EA4 # sizeof(PSOCharacterFile)
mov eax, [0x00A939C4]
add eax, 0xBA94
push eax
mov eax, 0x00835E86
call eax
# Fix the file's checksum
mov eax, [0x00A939C4]
mov ecx, 0x006C2738
jmp ecx # PSOBBCharacterFileList::checksum(char_file_list)
update_existing_char_file_list_memcard:
# Allocate a new memory card file area and copy the data there too. It seems
# Sega didn't fully strip out the local saving code from PSOBB; instead, they
# just made it write to a heap-allocated buffer. Since the file is much
# bigger now, we also have to make that heap-allocated buffer larger. We add
# a few "blocks" on the end, since the original code in the game does that
# too, but it's probably not strictly necessary.
# Like the above, this part is not necessary if this patch is statically
# applied to the executable.
mov eax, 0x00022FC4 # total file size
add eax, 0x0000FFFF
and eax, 0xFFFFC000
push eax
mov eax, 0x0084F258
call eax # malloc10(total file size)
add esp, 4
mov [0x00A939AC], eax
mov edx, [0x00A939C4]
mov ecx, 0x00022FC4 # total file size
jmp memcpy
@@ -0,0 +1,103 @@
# This patch causes the client not to generate its own EXP text and instead use
# the EXP values generated by the server when showing the purple text for enemy
# deaths. This makes EXP gained via EXP share visible, as well as makes
# fractional EXP multiplers (in config.json) display properly.
.meta name="Server EXP display"
.meta description=""
.meta hide_from_patches_menu
entry_ptr:
reloc0:
.offsetof start
start:
call install_hook
call apply_static_patches
ret
install_hook:
pop ecx
push 0 # Write address instead of a call/jmp opcode
push 0x00A0DC54
call get_code_size
.deltaof handle_6xBF_start, handle_6xBF_end
get_code_size:
pop eax
push dword [eax]
call handle_6xBF_end
handle_6xBF_start: # [std](G_6xBF* cmd @ [esp + 4]) -> void
mov edx, [esp + 4]
mov ecx, [0x00A9A074] # local_client_id
cmp [edx + 2], cx
jne skip_text
cmp byte [edx + 1], 3
jl skip_text
movzx eax, word [edx + 8] # cmd.from_enemy_id
cmp eax, 0x1000
jl skip_text
cmp eax, 0x1B50
jge skip_text
call get_enemy_entity
test eax, eax
jnz enemy_entity_ok
# Use player entity if enemy entity is already gone
mov eax, 0x0068D618
xchg eax, ecx
call ecx # eax = TObjPlayer::for_client_id(local_client_id); conveniently, this function preserves all regs except eax
enemy_entity_ok:
push 0x0000FFFF # entity_id; ignored by TFontSmallTask if not a player
push dword [edx + 4] # amount = cmd.amount
push 0x00976380 # prefix = L"EXP"
push 0x14
push 0x14
push 0xFFFF00FF # color (ARGB)
add eax, 0x300
push eax # position
mov eax, 0x0078B8E8
call eax # TFontSmallTask___new__(...)
add esp, 0x1C
skip_text:
mov eax, 0x0069292C # Original handle_6xBF
jmp eax # original_handle_6xBF(cmd)
get_enemy_entity:
.include GetEnemyEntity-59NJ
ret
handle_6xBF_end:
push ecx
.include WriteCallToCode-59NJ
apply_static_patches:
.include WriteCodeBlocksBB
.data 0x0078827D
.deltaof disable_kill_enemy_callsite_start, disable_kill_enemy_callsite_end
disable_kill_enemy_callsite_start:
nop
nop
nop
nop
nop
disable_kill_enemy_callsite_end:
.data 0x00777381
.deltaof disable_exp_steal_callsite_start, disable_exp_steal_callsite_end
disable_exp_steal_callsite_start:
add esp, 0x0C # Original function has `ret 0x0C`
nop
nop
disable_exp_steal_callsite_end:
.data 0x00000000
.data 0x00000000
@@ -10,6 +10,8 @@
.meta description=""
.meta hide_from_patches_menu
.versions 59NJ 59NL
entry_ptr:
reloc0:
.offsetof start
@@ -17,7 +19,7 @@ start:
.include WriteCodeBlocksBB
# Patch 1: rewrite item_is_stackable
.data 0x005C502C
.data <VERS 0x005C5020 0x005C502C>
.deltaof item_is_stackable_start, item_is_stackable_end
item_is_stackable_start:
@@ -32,7 +34,7 @@ item_is_stackable_start:
push eax
mov ecx, esp
.binary E8EC130100 # call max_stack_size_for_tool_start
.binary <VERS E8D8130100 E8EC130100> # call max_stack_size_for_tool_start
pop ecx
cmp eax, 1
jg return_1
@@ -48,7 +50,7 @@ return_1:
item_is_stackable_end:
# Patch 2: rewrite max_stack_size_for_tool
.data 0x005D6430
.data <VERS 0x005D6410 0x005D6430>
.deltaof max_stack_size_for_tool_start, max_stack_size_for_tool_end
max_stack_size_for_tool_start:
@@ -0,0 +1,146 @@
# Currently beta quality, map objects that fade like boxes, and Pioneer's
# background billboards and elevators still have regular draw distance.
# TODO: 90% of stuff is included, bring home the last 10%.
.meta name="Draw Distance"
.meta description="Extends the draw\ndistance of many\nobjects"
entry_ptr:
reloc0:
.offsetof start
write_call_func:
.include WriteCallToCode-59NJ
start:
mov eax, 0x41800000 # Environment clip distance mod 16.0f
mov [0x0097D198], eax # This affects mostly static map objects
mov [0x0097D19C], eax
mov [0x00097D1A0], eax
mov ax, 0x9090
mov [0x00689BC7], ax # Players draw distance 10000.0f always
mov eax, 0x41000000 # Use newly acquired skipped branch room
mov [0x00689BD1], eax # to store our float multiplier
call patch_func_1 # Floor items
call patch_func_2 # Whole bunch of stuff, including NPCs
call patch_func_3 # Duplicate function from above, reuse same hook
call patch_func_4 # TODO: Which objects this affects?
call patch_func_5 # TODO: This one too?
call patch_func_6 # TODO: And this one?
ret
# Floor items
patch_func_1:
pop ecx
push 8
push 0x005C525B
call get_code_size1
.deltaof patch_code1, patch_code_end1
get_code_size1:
pop eax
push dword [eax]
call patch_code_end1
patch_code1:
mov edx, [esp + 0x18]
fld st0, dword [0x00689BD1]
fld st0, dword [esp + 0x14]
fmulp st1, st0
ret
patch_code_end1:
push ecx
jmp write_call_func
# Whole bunch of stuff, including NPCs
patch_func_2:
pop ecx
push 9
push 0x007BB21E
call get_code_size2
.deltaof patch_code2, patch_code_end2
get_code_size2:
pop eax
push dword [eax]
call patch_code_end2
patch_code2:
test eax, 0x400
fld st0, dword [0x00689BD1]
fld st0, dword [esp + 0x2C]
fmulp st1, st0
ret
patch_code_end2:
push ecx
jmp write_call_func
# Duplicate function from above, reuse same hook
patch_func_3:
mov eax, dword [0x007BB21F]
add eax, 0x002A1C74
mov dword [0x00518843], eax
mov byte [0x00518842], 0xE8
mov dword [0x00518847], 0x90909090
ret
# TOComputerMachine01
patch_func_4:
pop ecx
push 7
push 0x00616FF4
call get_code_size4
.deltaof patch_code4, patch_code_end4
get_code_size4:
pop eax
push dword [eax]
call patch_code_end4
patch_code4:
lea edx, [edi + 0x38]
fld st0, dword [0x00689BD1]
fld st0, dword [esp + 0x14]
fmulp st1, st0
ret
patch_code_end4:
push ecx
jmp write_call_func
# TObjCamera
patch_func_5:
pop ecx
push 6
push 0x006439A8
call get_code_size5
.deltaof patch_code5, patch_code_end5
get_code_size5:
pop eax
push dword [eax]
call patch_code_end5
patch_code5:
fld st0, dword [0x00689BD1]
fld st0, dword [esp + 0x28]
fmulp st1, st0
fchs st0
ret
patch_code_end5:
push ecx
jmp write_call_func
# TODO: And this one?
patch_func_6:
pop ecx
push 6
push 0x0065B959
call get_code_size6
.deltaof patch_code6, patch_code_end6
get_code_size6:
pop eax
push dword [eax]
call patch_code_end6
patch_code6:
mov ebp, ecx
fld st0, dword [0x00689BD1]
fld st0, dword [esp + 0x30]
fmulp st1, st0
ret
patch_code_end6:
push ecx
jmp write_call_func
@@ -0,0 +1,258 @@
.meta name="DMC"
.meta description="Mitigates effects\nof enemy health\ndesync"
.meta client_flag="0x0000001000000000"
entry_ptr:
reloc0:
.offsetof start
write_call_to_code_multi:
.include WriteCallToCodeMulti-59NJ
write_address_of_code:
.include WriteAddressOfCode-59NJ
start:
# Replace 6x09 with 6xE4 in subcommand handler table
mov dword [0x00A0DC30], 0x000600E4 # subcommand=0xE4, flags=6
push 0x00A0DC34
call +4
.deltaof handle_6xE4_start, handle_6xE4_end
pop eax
push dword [eax]
call handle_6xE4_end
handle_6xE4_start: # (G_6xE4* cmd @ [esp + 4]) -> void
push ebx
push esi
push edi
test byte [0x00AA8DFC], 0x80
jz handle_6xE4_return
mov ebx, [esp + 0x10] # cmd
movzx eax, word [ebx + 2]
cmp eax, 0x1000
jl handle_6xE4_return
cmp eax, 0x1B50
jge handle_6xE4_return
movzx eax, word [ebx + 2]
.include GetEnemyEntity-59NJ # auto* ene = get_enemy_entity(cmd->header.entity_id);
push eax
movzx eax, word [ebx + 2]
and eax, 0x0FFF
imul eax, eax, 0x0C
add eax, [0x00AADE38] # eax = state_for_enemy(cmd->header.entity_id)
cmp dword [ebx + 0x0C], 0
jl handle_6xE4_not_proportional
mov cx, [ebx + 0x0A] # cmd->max_hp
sub cx, [eax + 0x06] # st.total_damage
movzx ecx, cx
xor edx, edx
cmp ecx, edx
cmovl ecx, edx
push ecx
fild st0, dword [esp] # current_hp = static_cast<float>(max<int32_t>(cmd->max_hp - st.total_damage, 0))
fld st0, dword [ebx + 0x0C]
fmulp st1, st0
fistp dword [esp], st0
mov ecx, dword [esp] # adjusted_hit_amount = static_cast<int16_t>(current_hp * cmd->factor)
add esp, 4
xor edx, edx
inc edx
cmp ecx, edx
cmovl ecx, edx
mov [ebx + 0x04], cx # cmd->hit_amount = min<int32_t>(1, adjusted_hit_amount)
handle_6xE4_not_proportional:
movzx edx, word [eax + 0x06] # st.total_damage
movsx esi, word [ebx + 0x04] # cmd->hit_amount
movzx edi, word [ebx + 0x0A] # cmd->max_hp
add edx, esi # st.total_damage + cmd->hit_amount
cmp edx, edi
jl handle_6xE4_damage_less_than_max_hp
mov [eax + 0x06], di # st.total_damage = cmd->max_hp;
mov edx, [eax]
test edx, 0x800
jnz handle_6xE4_return_pop_ene
or edx, 0x800
mov [eax], edx
cmp dword [esp], 0
je handle_6xE4_return_pop_ene
push edx # out_cmd.flags
sub esp, 8
mov word [esp], 0x030A # out_cmd.header.{subcommand,size}
mov si, [ebx + 2]
mov [esp + 2], si # out_cmd.header.entity_id
and si, 0x0FFF
mov [esp + 4], si # out_cmd.entity_index
mov [esp + 6], di # out_cmd.total_damage
mov ecx, esp
mov edx, 0x00801150
call edx # send_and_handle_60(&out_cmd);
add esp, 0x10
jmp handle_6xE4_return
handle_6xE4_damage_less_than_max_hp:
xor edi, edi
cmp edx, edx
cmovl edx, edi
mov [eax + 0x06], dx # st.total_damage = std::max<int16_t>(st.total_damage + cmd->hit_amount, 0);
mov edx, eax # edx = ene_st
mov eax, [esp] # eax = ene
test eax, eax
jz handle_6xE4_return_pop_ene
mov ecx, eax
push edx
mov edx, [ecx]
call [edx + 0x148] # ene->vtable[0x52](ene, &st);
handle_6xE4_return_pop_ene:
add esp, 4
handle_6xE4_return:
pop edi
pop esi
pop ebx
ret
handle_6xE4_end:
call write_address_of_code
# Write TObjectV00b421c0::incr_hp_with_sync
push 5
push 0x00775224 # TObjectV00b421c0::v18_accept_hit (presumably Resta) - this is add_hp, not subtract_hp!
push 5
push 0x00778063 # TObjectV00b421c0::subtract_hp_if_not_in_state_2
push 5
push 0x00777AB2 # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x00777B2B # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x00777BFC # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x00777C75 # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x00776D2D # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x007769C2 # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x0077683C # TObjectV00b421c0::v19_handle_hit_special_effects
push 5
push 0x00776502 # TObjectV00b421c0::v19_handle_hit_special_effects (Devil's/Demon's)
push 5
push 0x00775B57 # TObjectV00b421c0::v18_accept_hit
push 5
push 0x00775A23 # TObjectV00b421c0::v18_accept_hit
push 5
push 0x007757F0 # TObjectV00b421c0::v18_accept_hit
push 5
push 0x00775606 # TObjectV00b421c0::v18_accept_hit
push 5
push 0x007754BC # TObjectV00b421c0::v18_accept_hit
push 5
push 0x00774E3D # TObjectV00b421c0::v18_accept_hit
push 5
push 0x00774CD6 # TObjectV00b421c0::v18_accept_hit
push 5
push 0x00774713 # TObjectV00b421c0::v17
push 18
call +4
.deltaof on_add_or_subtract_hp_start, on_add_or_subtract_hp_end
pop eax
push dword [eax]
call on_add_or_subtract_hp_end
on_add_or_subtract_hp_start: # (TObjectV00b421c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
test byte [0x00AA8DFC], 0x80
jz on_add_or_subtract_hp_skip_send
movzx eax, word [ecx + 0x1C] # ene->entity_id
cmp eax, 0x1000
jl on_add_or_subtract_hp_skip_send
cmp eax, 0x1B50
jge on_add_or_subtract_hp_skip_send
and eax, 0x0FFF
imul eax, eax, 0x0C
add eax, [0x00AADE38] # eax = state_for_enemy(cmd->header.entity_id)
sub esp, 0x10
mov word [esp], 0x04E4
mov dx, [ecx + 0x1C]
mov [esp + 0x02], dx # cmd.entity_id
mov dx, [esp + 0x14]
cmp dword [esp + 0x10], 0x00775229 # Check if callsite is add_hp
jne on_add_or_subtract_hp_skip_negate_amount
neg dx
on_add_or_subtract_hp_skip_negate_amount:
mov [esp + 0x04], dx # cmd.hit_amount
mov dx, [eax + 6]
mov [esp + 0x06], dx # cmd.total_damage_before_hit
mov dx, [ecx + 0x0334]
mov [esp + 0x08], dx # cmd.current_hp
mov dx, [ecx + 0x02BC]
mov [esp + 0x0A], dx # cmd.max_hp
mov dword [esp + 0x0C], 0xBF800000 # cmd.factor
cmp dword [esp + 0x10], 0x00776507 # Check if callsite is Devil's/Demon's
jne on_add_or_subtract_hp_not_proportional
# esp is 0x18 down from where it is in caller's context
mov edx, 100
sub edx, [esp + 0x24] # edx = (100 - special_amount)
push edx
fild st0, dword [esp] # current_hp_factor = static_cast<float>(100 - special_amount)
fmul st0, dword [esp + 0x54] # *= weapon_reduction_factor
mov dword [esp], 0x42C80000 # 100.0f
fdiv st0, dword [esp]
add esp, 4
fstp dword [esp + 0x0C], st0 # cmd.factor = ((100 - special_amount) * weapon_reduction_factor) / 100
on_add_or_subtract_hp_not_proportional:
mov edx, esp
push ecx
push 0x10
push edx
mov ecx, [0x00AA8E04]
mov edx, 0x007D4CBC
call edx # send_60(root_protocol, &cmd, sizeof(cmd));
pop ecx
add esp, 0x10
on_add_or_subtract_hp_skip_send:
mov eax, 0x007781F0 # subtract_hp
mov edx, 0x007781B0 # add_hp
cmp dword [esp], 0x00775229 # Check if callsite is add_hp
cmove eax, edx
jmp eax
on_add_or_subtract_hp_end:
call write_call_to_code_multi
push 5
push 0x0078864B
push 1
call +4
.deltaof on_6x0A_patch_start, on_6x0A_patch_end
pop eax
push dword [eax]
call on_6x0A_patch_end
on_6x0A_patch_start: # (TObjectV00b421c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
test byte [0x00AA8DFC], 0x80
jz on_6x0A_patch_skip_write
mov [esp + 0x0A], cx
on_6x0A_patch_skip_write:
ret
on_6x0A_patch_end:
call write_call_to_code_multi
ret
@@ -1,45 +1,47 @@
.meta name="Enemy HP bars"
.meta description="Shows HP bars in\nenemy info windows"
.versions 59NJ 59NL
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksBB
.data 0x007318DD
.data <VERS 0x0073197D 0x007318DD>
.data 6
.binary 81E2FDFFFFFF
.data 0x00731F2F
.data <VERS 0x00731FCF 0x00731F2F>
.data 1
.binary FA
.data 0x009F2DA4
.data <VERS 0x009F0DA4 0x009F2DA4>
.data 4
.data 0x42480000
.data 0x009F2DAC
.data <VERS 0x009F0DAC 0x009F2DAC>
.data 4
.data 0x41C00000
.data 0x009F2DD4
.data <VERS 0x009F0DD4 0x009F2DD4>
.data 4
.data 0x42480000
.data 0x009F2DDC
.data <VERS 0x009F0DDC 0x009F2DDC>
.data 4
.data 0x41C00000
.data 0x009F2E04
.data <VERS 0x009F0E04 0x009F2E04>
.data 4
.data 0x42480000
.data 0x009F2E0C
.data <VERS 0x009F0E0C 0x009F2E0C>
.data 4
.data 0x41C00000
.data 0x009F2E34
.data <VERS 0x009F0E34 0x009F2E34>
.data 4
.data 0x42480000
.data 0x009F2E3C
.data <VERS 0x009F0E3C 0x009F2E3C>
.data 4
.data 0x41C00000
.data 0x009F2E64
.data <VERS 0x009F0E64 0x009F2E64>
.data 4
.data 0x42200000
.data 0x009F2E80
.data <VERS 0x009F0E80 0x009F2E80>
.data 4
.data 0xFF00FF15
.data 0x00000000
@@ -1,17 +0,0 @@
# This function implements $exit in a game when no quest is loaded.
.meta name="Exit anywhere"
.meta description=""
.meta hide_from_patches_menu
entry_ptr:
reloc0:
.offsetof start
start:
xor eax, eax
mov [0x00A95624], eax # is_in_quest = false
mov [0x00A955E0], eax # dat_source_type = NONE
inc eax
mov [0x00AAE6D4], ax # should_leave_game = true
ret
@@ -0,0 +1,19 @@
# This function implements $exit in a game when no quest is loaded.
.meta name="Exit anywhere"
.meta description=""
.meta hide_from_patches_menu
.versions 59NJ 59NL
entry_ptr:
reloc0:
.offsetof start
start:
xor eax, eax
mov [<VERS 0x00A931A4 0x00A95624>], eax # is_in_quest = false
mov [<VERS 0x00A93160 0x00A955E0>], eax # dat_source_type = NONE
inc eax
mov [<VERS 0x00AAC254 0x00AAE6D4>], ax # should_leave_game = true
ret
@@ -1,19 +1,21 @@
.meta name="Fast tekker"
.meta description="Skips wind-up sound\nat tekker window"
.versions 59NJ 59NL
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksBB
.data 0x006DA113
.data <VERS 0x006DA14B 0x006DA113>
.deltaof patch1_start, patch1_end
patch1_start:
mov dword [edi + 0x14C], 1
patch1_end:
.data 0x006DA130
.data <VERS 0x006DA168 0x006DA130>
.deltaof patch2_start, patch2_end
patch2_start:
nop
@@ -0,0 +1,34 @@
.meta name="MAG alert"
.meta description="Plays a sound when\nyour MAG is hungry"
entry_ptr:
reloc0:
.offsetof start
start:
pop ecx
push 6
push 0x005D91BE
call get_code_size
.deltaof patch_code, patch_code_end
get_code_size:
pop eax
push dword [eax]
call patch_code_end
patch_code: # [eax] (TItemMag* this @ ecx) -> void
mov dword [ecx + 0x01B8], eax
mov eax, [ecx + 0x00F8]
movzx eax, word [eax + 0x001C] # eax = this->owner_player->entity_id
cmp [0x00A9A074], eax
jne patch_code_skip_sound
push 0
push 0
push 0
push 0xAC
mov eax, 0x00815020
call eax
add esp, 0x10
patch_code_skip_sound:
ret
patch_code_end:
push ecx
.include WriteCallToCode-59NJ
@@ -0,0 +1,43 @@
# Original patch by Soly, in Blue Burst Patch Project
# https://github.com/Solybum/Blue-Burst-Patch-Project
.meta name="No rare selling"
.meta description="Stops you from accidentally\nselling rares to vendors"
entry_ptr:
reloc0:
.offsetof start
start:
# This works by setting the item price to zero if it's rare, which causes
# the game to prevent you from selling the item. For armors and weapons, this
# is easy because there are easily-patchable opcodes within branches that
# return a constant price for rare items.
xor eax, eax
mov [0x005D258F], eax # Rare armors
mov [0x005D26D1], eax # Unidentified weapons
mov [0x005D26E6], eax # Rare weapons
# For tools, it's harder to implement this, because the price comes from the
# ItemPMT tools table and there is no branch for rares. Still, we can add a
# branch to a stub to handle tools.
pop ecx
push 5
push 0x005D2508
call get_code_size
.deltaof patch_code, patch_code_end
get_code_size:
pop eax
push dword [eax]
call patch_code_end
patch_code:
# TODO: It'd be nice to have something like WriteJumpToAndFromCode, since
# this hook is supposed to return to a different place than where it was
# called, hence this mov [esp].
mov dword [esp], 0x005D2556
xor edi, edi
test byte [eax + 0x14], 0x80 # flags & 0x80 = is rare
cmovz edi, [eax + 0x10] # Use price from table if not rare
ret
patch_code_end:
push ecx
.include WriteCallToCode-59NJ
@@ -0,0 +1,230 @@
# Original patch by Soly, in Blue Burst Patch Project
# https://github.com/Solybum/Blue-Burst-Patch-Project
.meta name="Palette"
.meta description="Enables the alternate action\npalette for number keys"
entry_ptr:
reloc0:
.offsetof start
write_call_func:
.include WriteCallToCode-59NJ
start:
mov al, 0xEB
mov [0x0068A7A5], al # SecondaryPaletteAttack1
xor al, al
mov [0x006A11B7], al # SecondaryPaletteAttack2
mov [0x006A0CB7], al # SecondaryPaletteAttack3
call patch_func_1 # GetCurrentPalette
call patch_func_2 # CheckHotkey1_1
call patch_func_3 # CheckHotkey1_2
call patch_func_4 # CheckHotkey2_1
call patch_func_5 # CheckHotkey2_2
call patch_func_6 # CheckHotkey3_1
call patch_func_7 # CheckHotkey3_2
jmp write_code_blocks # UnsetHotkey1, UnsetHotkey2, SetHotkey
# GetCurrentPalette
patch_func_1:
pop ecx
push 8
push 0x00748990
call get_code_size1
.deltaof patch_code1, patch_code_end1
get_code_size1:
pop eax
push dword [eax]
call patch_code_end1
patch_code1:
mov edx, [ebp - 0x14]
mov edx, [edx + 0x2C]
movzx edx, byte [edx + 0x62]
test edx, edx
setnz byte [0x00748B1B]
mov edx, edi
and edx, 0xFF
ret
patch_code_end1:
push ecx
jmp write_call_func
# CheckHotkey1_1
patch_func_2:
pop ecx
push 5
push 0x007489DE
call get_code_size2
.deltaof patch_code2, patch_code_end2
get_code_size2:
pop eax
push dword [eax]
call patch_code_end2
patch_code2:
cmp byte [0x00748B1B], 0
jnz +0x06
movzx edx, byte [eax + esi * 4 + 0x04] # main palette
ret
movzx edx, byte [eax + esi * 4 + 0x3C] # alt palette
ret
patch_code_end2:
push ecx
jmp write_call_func
# CheckHotkey1_2
patch_func_3:
pop ecx
push 5
push 0x007489ED
call get_code_size3
.deltaof patch_code3, patch_code_end3
get_code_size3:
pop eax
push dword [eax]
call patch_code_end3
patch_code3:
cmp byte [0x00748B1B], 0
jnz +0x06
movzx ecx, byte [eax + ecx * 2 + 0x05] # main palette
ret
movzx ecx, byte [eax + ecx * 2 + 0x3D] # alt palette
ret
patch_code_end3:
push ecx
jmp write_call_func
# CheckHotkey2_1
patch_func_4:
pop ecx
push 5
push 0x00748A88
call get_code_size4
.deltaof patch_code4, patch_code_end4
get_code_size4:
pop eax
push dword [eax]
call patch_code_end4
patch_code4:
cmp byte [0x00748B1B], 0
jnz +0x06
movzx edx, byte [edx + ebx * 4 + 0x04] # main palette
ret
movzx edx, byte [edx + ebx * 4 + 0x3C] # alt palette
ret
patch_code_end4:
push ecx
jmp write_call_func
# CheckHotkey2_2
patch_func_5:
pop ecx
push 5
push 0x00748A97
call get_code_size5
.deltaof patch_code5, patch_code_end5
get_code_size5:
pop eax
push dword [eax]
call patch_code_end5
patch_code5:
cmp byte [0x00748B1B], 0
jnz +0x06
movzx ecx, byte [edx + eax * 2 + 0x05] # main palette
ret
movzx ecx, byte [edx + eax * 2 + 0x3D] # alt palette
ret
patch_code_end5:
push ecx
jmp write_call_func
# CheckHotkey3_1
patch_func_6:
pop ecx
push 5
push 0x007103D3
call get_code_size6
.deltaof patch_code6, patch_code_end6
get_code_size6:
pop eax
push dword [eax]
call patch_code_end6
patch_code6:
cmp byte [0x00748B1B], 0
jnz +0x06
movzx ecx, byte [eax + edx * 4 + 0x04] # main palette
ret
movzx ecx, byte [eax + edx * 4 + 0x3C] # alt palette
ret
patch_code_end6:
push ecx
jmp write_call_func
# CheckHotkey3_2
patch_func_7:
pop ecx
push 5
push 0x007103DC
call get_code_size7
.deltaof patch_code7, patch_code_end7
get_code_size7:
pop eax
push dword [eax]
call patch_code_end7
patch_code7:
cmp byte [0x00748B1B], 0
jnz +0x06
movzx ecx, byte [eax + edx * 4 + 0x05] # main palette
ret
movzx ecx, byte [eax + edx * 4 + 0x3D] # alt palette
ret
patch_code_end7:
push ecx
jmp write_call_func
write_code_blocks:
.include WriteCodeBlocksBB
.data 0x00748A05
.deltaof code_block1_start, code_block1_end
# UnsetHotkey1
code_block1_start:
push dword [0x00748B1B]
push eax
mov eax, 0x0068CE4C # SetPaletteHotkey
call eax
.binary 909090909090909090
code_block1_end:
.data 0x00748AAB
.deltaof code_block2_start, code_block2_end
# UnsetHotkey2
code_block2_start:
push dword [0x00748B1B]
push eax
mov eax, 0x0068CE4C # SetPaletteHotkey
call eax
.binary 909090909090909090
code_block2_end:
.data 0x00748B0A
.deltaof code_block3_start, code_block3_end
# SetHotkey
code_block3_start:
mov eax, [ebp - 0x24]
mov ecx, [ebp - 0x28]
movzx ebx, word [eax]
movzx edx, word [eax + 0x02]
push edx
push ebx
push esi
.binary 6800000000 # tmpCurrentPalette = 0x00748B1B
push 0
mov eax, 0x0068CE4C # SetPaletteHotkey
call eax
.binary 90909090909090909090909090909090
code_block3_end:
.data 0x00000000
.data 0x00000000
@@ -0,0 +1,20 @@
.meta name="PSO Peeps Dragon HP"
.meta description="Sets Normal Dragon HP\nto 1800 for V2 crossplay"
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
# GC Plus USA / 3OE1
# BattleParamEntry_on.dat loaded Normal Dragon row at 0x811ABA48
# HP field is row + 0x06 = 0x811ABA4E
# 2500 = 09 C4; 1800 = 07 08
.data 0x811ABA4E
.data 2
.binary 0708
.data 0
.data 0
@@ -0,0 +1,834 @@
.meta name="PSO Peeps EP1 10x EXP"
.meta description="Sets EP1 enemy EXP\nto 10x for GC crossplay"
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
# PSO Peeps GC Plus USA / 3OE1
# Source table: BattleParamEntry_on.dat
# Active online battle-param table loaded at 0x811AB7C0
# EXP field offset within each 0x24-byte row is +0x1C
# Generated from clean BattleParamEntry_on.dat; multiplier=10x
.data 0x811AB7DC
.data 4
.binary 0000000a
.data 0x811AB800
.data 4
.binary 0000003c
.data 0x811AB824
.data 4
.binary 00000032
.data 0x811AB848
.data 4
.binary 00000046
.data 0x811AB86C
.data 4
.binary 00000064
.data 0x811AB890
.data 4
.binary 000005dc
.data 0x811AB8B4
.data 4
.binary 000000fa
.data 0x811AB8D8
.data 4
.binary 000000a0
.data 0x811AB8FC
.data 4
.binary 000000a0
.data 0x811AB920
.data 4
.binary 000000aa
.data 0x811AB944
.data 4
.binary 00000122
.data 0x811AB968
.data 4
.binary 00000028
.data 0x811AB98C
.data 4
.binary 00000028
.data 0x811AB9B0
.data 4
.binary 0000015e
.data 0x811AB9D4
.data 4
.binary 0000015e
.data 0x811AB9F8
.data 4
.binary 000022c4
.data 0x811ABA1C
.data 4
.binary 00000064
.data 0x811ABA40
.data 4
.binary 00000064
.data 0x811ABA64
.data 4
.binary 00000fa0
.data 0x811ABA88
.data 4
.binary 00000118
.data 0x811ABB3C
.data 4
.binary 00000028
.data 0x811ABB60
.data 4
.binary 000003e8
.data 0x811ABB84
.data 4
.binary 00000096
.data 0x811ABBA8
.data 4
.binary 0000001e
.data 0x811ABBCC
.data 4
.binary 000000b4
.data 0x811ABBF0
.data 4
.binary 000000dc
.data 0x811ABC14
.data 4
.binary 000000c8
.data 0x811ABC38
.data 4
.binary 0000010e
.data 0x811ABC5C
.data 4
.binary 0000003c
.data 0x811ABD10
.data 4
.binary 000030d4
.data 0x811ABE9C
.data 4
.binary 00000064
.data 0x811ABEC0
.data 4
.binary 0000003c
.data 0x811ABEE4
.data 4
.binary 00000028
.data 0x811ABF08
.data 4
.binary 00000028
.data 0x811ABF2C
.data 4
.binary 000005dc
.data 0x811ABF50
.data 4
.binary 00000032
.data 0x811ABF98
.data 4
.binary 00007530
.data 0x811ABFE0
.data 4
.binary 00000032
.data 0x811AC220
.data 4
.binary 00000082
.data 0x811AC244
.data 4
.binary 000003e8
.data 0x811AC268
.data 4
.binary 00000032
.data 0x811AC28C
.data 4
.binary 0000003c
.data 0x811AC2B0
.data 4
.binary 00000046
.data 0x811AC2D4
.data 4
.binary 000000c8
.data 0x811AC2F8
.data 4
.binary 00000064
.data 0x811AC31C
.data 4
.binary 00000078
.data 0x811AC340
.data 4
.binary 0000008c
.data 0x811AC364
.data 4
.binary 0000012c
.data 0x811AC388
.data 4
.binary 000000dc
.data 0x811AC3AC
.data 4
.binary 000000f0
.data 0x811AC3D0
.data 4
.binary 00000104
.data 0x811AC55C
.data 4
.binary 00000168
.data 0x811AC580
.data 4
.binary 000001ae
.data 0x811AC5A4
.data 4
.binary 000001a4
.data 0x811AC5C8
.data 4
.binary 000001c2
.data 0x811AC5EC
.data 4
.binary 000001ea
.data 0x811AC610
.data 4
.binary 00000a1e
.data 0x811AC634
.data 4
.binary 000002bc
.data 0x811AC658
.data 4
.binary 00000244
.data 0x811AC67C
.data 4
.binary 00000244
.data 0x811AC6A0
.data 4
.binary 00000258
.data 0x811AC6C4
.data 4
.binary 0000030c
.data 0x811AC6E8
.data 4
.binary 00000190
.data 0x811AC70C
.data 4
.binary 00000190
.data 0x811AC730
.data 4
.binary 000003ca
.data 0x811AC754
.data 4
.binary 00000348
.data 0x811AC778
.data 4
.binary 00007d00
.data 0x811AC79C
.data 4
.binary 000000fa
.data 0x811AC7C0
.data 4
.binary 00000028
.data 0x811AC7E4
.data 4
.binary 00005dc0
.data 0x811AC808
.data 4
.binary 000002ee
.data 0x811AC8BC
.data 4
.binary 00000190
.data 0x811AC8E0
.data 4
.binary 00000730
.data 0x811AC904
.data 4
.binary 0000023a
.data 0x811AC928
.data 4
.binary 0000006e
.data 0x811AC94C
.data 4
.binary 00000262
.data 0x811AC970
.data 4
.binary 0000029e
.data 0x811AC994
.data 4
.binary 00000280
.data 0x811AC9B8
.data 4
.binary 00000302
.data 0x811AC9DC
.data 4
.binary 000001ae
.data 0x811ACA90
.data 4
.binary 00009470
.data 0x811ACC1C
.data 4
.binary 000001ea
.data 0x811ACC40
.data 4
.binary 00000104
.data 0x811ACC64
.data 4
.binary 000000e6
.data 0x811ACC88
.data 4
.binary 000000e6
.data 0x811ACCAC
.data 4
.binary 00000a1e
.data 0x811ACCD0
.data 4
.binary 00000032
.data 0x811ACD3C
.data 4
.binary 00013880
.data 0x811ACD60
.data 4
.binary 00000032
.data 0x811ACFA0
.data 4
.binary 00000230
.data 0x811ACFC4
.data 4
.binary 00000730
.data 0x811ACFE8
.data 4
.binary 000001a4
.data 0x811AD00C
.data 4
.binary 000001ae
.data 0x811AD030
.data 4
.binary 000001c2
.data 0x811AD054
.data 4
.binary 00000280
.data 0x811AD078
.data 4
.binary 000001ea
.data 0x811AD09C
.data 4
.binary 00000208
.data 0x811AD0C0
.data 4
.binary 00000226
.data 0x811AD0E4
.data 4
.binary 0000032a
.data 0x811AD108
.data 4
.binary 0000029e
.data 0x811AD12C
.data 4
.binary 000002bc
.data 0x811AD150
.data 4
.binary 000002da
.data 0x811AD2DC
.data 4
.binary 00000334
.data 0x811AD300
.data 4
.binary 00000398
.data 0x811AD324
.data 4
.binary 00000384
.data 0x811AD348
.data 4
.binary 000003ac
.data 0x811AD36C
.data 4
.binary 000003e8
.data 0x811AD390
.data 4
.binary 00000ed8
.data 0x811AD3B4
.data 4
.binary 0000055a
.data 0x811AD3D8
.data 4
.binary 00000460
.data 0x811AD3FC
.data 4
.binary 00000460
.data 0x811AD420
.data 4
.binary 00000474
.data 0x811AD444
.data 4
.binary 000005c8
.data 0x811AD468
.data 4
.binary 00000370
.data 0x811AD48C
.data 4
.binary 00000370
.data 0x811AD4B0
.data 4
.binary 000005dc
.data 0x811AD4D4
.data 4
.binary 000005a0
.data 0x811AD4F8
.data 4
.binary 000153d8
.data 0x811AD51C
.data 4
.binary 0000012c
.data 0x811AD540
.data 4
.binary 00000050
.data 0x811AD564
.data 4
.binary 000137b8
.data 0x811AD588
.data 4
.binary 00000596
.data 0x811AD63C
.data 4
.binary 00000370
.data 0x811AD660
.data 4
.binary 00000af0
.data 0x811AD684
.data 4
.binary 000004b0
.data 0x811AD6A8
.data 4
.binary 000000dc
.data 0x811AD6CC
.data 4
.binary 00000488
.data 0x811AD6F0
.data 4
.binary 000004d8
.data 0x811AD714
.data 4
.binary 000004b0
.data 0x811AD738
.data 4
.binary 00000500
.data 0x811AD75C
.data 4
.binary 00000398
.data 0x811AD810
.data 4
.binary 0001b198
.data 0x811AD99C
.data 4
.binary 000003e8
.data 0x811AD9C0
.data 4
.binary 00000208
.data 0x811AD9E4
.data 4
.binary 000001e0
.data 0x811ADA08
.data 4
.binary 000001e0
.data 0x811ADA2C
.data 4
.binary 00000ed8
.data 0x811ADA50
.data 4
.binary 0000005a
.data 0x811ADABC
.data 4
.binary 00027100
.data 0x811ADAE0
.data 4
.binary 0000005a
.data 0x811ADD20
.data 4
.binary 00000456
.data 0x811ADD44
.data 4
.binary 00000af0
.data 0x811ADD68
.data 4
.binary 00000384
.data 0x811ADD8C
.data 4
.binary 00000398
.data 0x811ADDB0
.data 4
.binary 000003ac
.data 0x811ADDD4
.data 4
.binary 000004e2
.data 0x811ADDF8
.data 4
.binary 000003e8
.data 0x811ADE1C
.data 4
.binary 00000410
.data 0x811ADE40
.data 4
.binary 00000438
.data 0x811ADE64
.data 4
.binary 000005dc
.data 0x811ADE88
.data 4
.binary 000004d8
.data 0x811ADEAC
.data 4
.binary 00000500
.data 0x811ADED0
.data 4
.binary 00000528
.data 0x811AE05C
.data 4
.binary 000005aa
.data 0x811AE080
.data 4
.binary 00000a8c
.data 0x811AE0A4
.data 4
.binary 00000abe
.data 0x811AE0C8
.data 4
.binary 00000af0
.data 0x811AE0EC
.data 4
.binary 00000b86
.data 0x811AE110
.data 4
.binary 00002328
.data 0x811AE134
.data 4
.binary 00000dac
.data 0x811AE158
.data 4
.binary 00000c80
.data 0x811AE17C
.data 4
.binary 00000c80
.data 0x811AE1A0
.data 4
.binary 00000cb2
.data 0x811AE1C4
.data 4
.binary 00000e2e
.data 0x811AE1E8
.data 4
.binary 000003e8
.data 0x811AE20C
.data 4
.binary 000003e8
.data 0x811AE230
.data 4
.binary 00000f0a
.data 0x811AE254
.data 4
.binary 00000e88
.data 0x811AE278
.data 4
.binary 0002de60
.data 0x811AE29C
.data 4
.binary 00000258
.data 0x811AE2C0
.data 4
.binary 000000a0
.data 0x811AE2E4
.data 4
.binary 00026d18
.data 0x811AE308
.data 4
.binary 00000d70
.data 0x811AE3BC
.data 4
.binary 00000a00
.data 0x811AE3E0
.data 4
.binary 00001b58
.data 0x811AE404
.data 4
.binary 00000c80
.data 0x811AE428
.data 4
.binary 0000024e
.data 0x811AE44C
.data 4
.binary 00000c8a
.data 0x811AE470
.data 4
.binary 00000dde
.data 0x811AE494
.data 4
.binary 00000d0c
.data 0x811AE4B8
.data 4
.binary 00000d0c
.data 0x811AE4DC
.data 4
.binary 00000aaa
.data 0x811AE590
.data 4
.binary 000395f8
.data 0x811AE71C
.data 4
.binary 00000b54
.data 0x811AE740
.data 4
.binary 0000079e
.data 0x811AE764
.data 4
.binary 00000708
.data 0x811AE788
.data 4
.binary 00000708
.data 0x811AE7AC
.data 4
.binary 00002260
.data 0x811AE7D0
.data 4
.binary 000000fa
.data 0x811AE83C
.data 4
.binary 0007a120
.data 0x811AE860
.data 4
.binary 000000c8
.data 0x811AEAA0
.data 4
.binary 00000bb8
.data 0x811AEAC4
.data 4
.binary 00001af4
.data 0x811AEAE8
.data 4
.binary 00000a96
.data 0x811AEB0C
.data 4
.binary 00000ac8
.data 0x811AEB30
.data 4
.binary 00000a78
.data 0x811AEB54
.data 4
.binary 00000d02
.data 0x811AEB78
.data 4
.binary 00000b86
.data 0x811AEB9C
.data 4
.binary 00000bd6
.data 0x811AEBC0
.data 4
.binary 00000c6c
.data 0x811AEBE4
.data 4
.binary 00000ea6
.data 0x811AEC08
.data 4
.binary 00000d3e
.data 0x811AEC2C
.data 4
.binary 00000d7a
.data 0x811AEC50
.data 4
.binary 00000de8
.data 0
.data 0
@@ -0,0 +1,834 @@
.meta name="PSO Peeps EP1 5x EXP"
.meta description="Sets EP1 enemy EXP\nto 5x for GC crossplay"
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
# PSO Peeps GC Plus USA / 3OE1
# Source table: BattleParamEntry_on.dat
# Active online battle-param table loaded at 0x811AB7C0
# EXP field offset within each 0x24-byte row is +0x1C
# Generated from clean BattleParamEntry_on.dat; multiplier=5x
.data 0x811AB7DC
.data 4
.binary 00000005
.data 0x811AB800
.data 4
.binary 0000001e
.data 0x811AB824
.data 4
.binary 00000019
.data 0x811AB848
.data 4
.binary 00000023
.data 0x811AB86C
.data 4
.binary 00000032
.data 0x811AB890
.data 4
.binary 000002ee
.data 0x811AB8B4
.data 4
.binary 0000007d
.data 0x811AB8D8
.data 4
.binary 00000050
.data 0x811AB8FC
.data 4
.binary 00000050
.data 0x811AB920
.data 4
.binary 00000055
.data 0x811AB944
.data 4
.binary 00000091
.data 0x811AB968
.data 4
.binary 00000014
.data 0x811AB98C
.data 4
.binary 00000014
.data 0x811AB9B0
.data 4
.binary 000000af
.data 0x811AB9D4
.data 4
.binary 000000af
.data 0x811AB9F8
.data 4
.binary 00001162
.data 0x811ABA1C
.data 4
.binary 00000032
.data 0x811ABA40
.data 4
.binary 00000032
.data 0x811ABA64
.data 4
.binary 000007d0
.data 0x811ABA88
.data 4
.binary 0000008c
.data 0x811ABB3C
.data 4
.binary 00000014
.data 0x811ABB60
.data 4
.binary 000001f4
.data 0x811ABB84
.data 4
.binary 0000004b
.data 0x811ABBA8
.data 4
.binary 0000000f
.data 0x811ABBCC
.data 4
.binary 0000005a
.data 0x811ABBF0
.data 4
.binary 0000006e
.data 0x811ABC14
.data 4
.binary 00000064
.data 0x811ABC38
.data 4
.binary 00000087
.data 0x811ABC5C
.data 4
.binary 0000001e
.data 0x811ABD10
.data 4
.binary 0000186a
.data 0x811ABE9C
.data 4
.binary 00000032
.data 0x811ABEC0
.data 4
.binary 0000001e
.data 0x811ABEE4
.data 4
.binary 00000014
.data 0x811ABF08
.data 4
.binary 00000014
.data 0x811ABF2C
.data 4
.binary 000002ee
.data 0x811ABF50
.data 4
.binary 00000019
.data 0x811ABF98
.data 4
.binary 00003a98
.data 0x811ABFE0
.data 4
.binary 00000019
.data 0x811AC220
.data 4
.binary 00000041
.data 0x811AC244
.data 4
.binary 000001f4
.data 0x811AC268
.data 4
.binary 00000019
.data 0x811AC28C
.data 4
.binary 0000001e
.data 0x811AC2B0
.data 4
.binary 00000023
.data 0x811AC2D4
.data 4
.binary 00000064
.data 0x811AC2F8
.data 4
.binary 00000032
.data 0x811AC31C
.data 4
.binary 0000003c
.data 0x811AC340
.data 4
.binary 00000046
.data 0x811AC364
.data 4
.binary 00000096
.data 0x811AC388
.data 4
.binary 0000006e
.data 0x811AC3AC
.data 4
.binary 00000078
.data 0x811AC3D0
.data 4
.binary 00000082
.data 0x811AC55C
.data 4
.binary 000000b4
.data 0x811AC580
.data 4
.binary 000000d7
.data 0x811AC5A4
.data 4
.binary 000000d2
.data 0x811AC5C8
.data 4
.binary 000000e1
.data 0x811AC5EC
.data 4
.binary 000000f5
.data 0x811AC610
.data 4
.binary 0000050f
.data 0x811AC634
.data 4
.binary 0000015e
.data 0x811AC658
.data 4
.binary 00000122
.data 0x811AC67C
.data 4
.binary 00000122
.data 0x811AC6A0
.data 4
.binary 0000012c
.data 0x811AC6C4
.data 4
.binary 00000186
.data 0x811AC6E8
.data 4
.binary 000000c8
.data 0x811AC70C
.data 4
.binary 000000c8
.data 0x811AC730
.data 4
.binary 000001e5
.data 0x811AC754
.data 4
.binary 000001a4
.data 0x811AC778
.data 4
.binary 00003e80
.data 0x811AC79C
.data 4
.binary 0000007d
.data 0x811AC7C0
.data 4
.binary 00000014
.data 0x811AC7E4
.data 4
.binary 00002ee0
.data 0x811AC808
.data 4
.binary 00000177
.data 0x811AC8BC
.data 4
.binary 000000c8
.data 0x811AC8E0
.data 4
.binary 00000398
.data 0x811AC904
.data 4
.binary 0000011d
.data 0x811AC928
.data 4
.binary 00000037
.data 0x811AC94C
.data 4
.binary 00000131
.data 0x811AC970
.data 4
.binary 0000014f
.data 0x811AC994
.data 4
.binary 00000140
.data 0x811AC9B8
.data 4
.binary 00000181
.data 0x811AC9DC
.data 4
.binary 000000d7
.data 0x811ACA90
.data 4
.binary 00004a38
.data 0x811ACC1C
.data 4
.binary 000000f5
.data 0x811ACC40
.data 4
.binary 00000082
.data 0x811ACC64
.data 4
.binary 00000073
.data 0x811ACC88
.data 4
.binary 00000073
.data 0x811ACCAC
.data 4
.binary 0000050f
.data 0x811ACCD0
.data 4
.binary 00000019
.data 0x811ACD3C
.data 4
.binary 00009c40
.data 0x811ACD60
.data 4
.binary 00000019
.data 0x811ACFA0
.data 4
.binary 00000118
.data 0x811ACFC4
.data 4
.binary 00000398
.data 0x811ACFE8
.data 4
.binary 000000d2
.data 0x811AD00C
.data 4
.binary 000000d7
.data 0x811AD030
.data 4
.binary 000000e1
.data 0x811AD054
.data 4
.binary 00000140
.data 0x811AD078
.data 4
.binary 000000f5
.data 0x811AD09C
.data 4
.binary 00000104
.data 0x811AD0C0
.data 4
.binary 00000113
.data 0x811AD0E4
.data 4
.binary 00000195
.data 0x811AD108
.data 4
.binary 0000014f
.data 0x811AD12C
.data 4
.binary 0000015e
.data 0x811AD150
.data 4
.binary 0000016d
.data 0x811AD2DC
.data 4
.binary 0000019a
.data 0x811AD300
.data 4
.binary 000001cc
.data 0x811AD324
.data 4
.binary 000001c2
.data 0x811AD348
.data 4
.binary 000001d6
.data 0x811AD36C
.data 4
.binary 000001f4
.data 0x811AD390
.data 4
.binary 0000076c
.data 0x811AD3B4
.data 4
.binary 000002ad
.data 0x811AD3D8
.data 4
.binary 00000230
.data 0x811AD3FC
.data 4
.binary 00000230
.data 0x811AD420
.data 4
.binary 0000023a
.data 0x811AD444
.data 4
.binary 000002e4
.data 0x811AD468
.data 4
.binary 000001b8
.data 0x811AD48C
.data 4
.binary 000001b8
.data 0x811AD4B0
.data 4
.binary 000002ee
.data 0x811AD4D4
.data 4
.binary 000002d0
.data 0x811AD4F8
.data 4
.binary 0000a9ec
.data 0x811AD51C
.data 4
.binary 00000096
.data 0x811AD540
.data 4
.binary 00000028
.data 0x811AD564
.data 4
.binary 00009bdc
.data 0x811AD588
.data 4
.binary 000002cb
.data 0x811AD63C
.data 4
.binary 000001b8
.data 0x811AD660
.data 4
.binary 00000578
.data 0x811AD684
.data 4
.binary 00000258
.data 0x811AD6A8
.data 4
.binary 0000006e
.data 0x811AD6CC
.data 4
.binary 00000244
.data 0x811AD6F0
.data 4
.binary 0000026c
.data 0x811AD714
.data 4
.binary 00000258
.data 0x811AD738
.data 4
.binary 00000280
.data 0x811AD75C
.data 4
.binary 000001cc
.data 0x811AD810
.data 4
.binary 0000d8cc
.data 0x811AD99C
.data 4
.binary 000001f4
.data 0x811AD9C0
.data 4
.binary 00000104
.data 0x811AD9E4
.data 4
.binary 000000f0
.data 0x811ADA08
.data 4
.binary 000000f0
.data 0x811ADA2C
.data 4
.binary 0000076c
.data 0x811ADA50
.data 4
.binary 0000002d
.data 0x811ADABC
.data 4
.binary 00013880
.data 0x811ADAE0
.data 4
.binary 0000002d
.data 0x811ADD20
.data 4
.binary 0000022b
.data 0x811ADD44
.data 4
.binary 00000578
.data 0x811ADD68
.data 4
.binary 000001c2
.data 0x811ADD8C
.data 4
.binary 000001cc
.data 0x811ADDB0
.data 4
.binary 000001d6
.data 0x811ADDD4
.data 4
.binary 00000271
.data 0x811ADDF8
.data 4
.binary 000001f4
.data 0x811ADE1C
.data 4
.binary 00000208
.data 0x811ADE40
.data 4
.binary 0000021c
.data 0x811ADE64
.data 4
.binary 000002ee
.data 0x811ADE88
.data 4
.binary 0000026c
.data 0x811ADEAC
.data 4
.binary 00000280
.data 0x811ADED0
.data 4
.binary 00000294
.data 0x811AE05C
.data 4
.binary 000002d5
.data 0x811AE080
.data 4
.binary 00000546
.data 0x811AE0A4
.data 4
.binary 0000055f
.data 0x811AE0C8
.data 4
.binary 00000578
.data 0x811AE0EC
.data 4
.binary 000005c3
.data 0x811AE110
.data 4
.binary 00001194
.data 0x811AE134
.data 4
.binary 000006d6
.data 0x811AE158
.data 4
.binary 00000640
.data 0x811AE17C
.data 4
.binary 00000640
.data 0x811AE1A0
.data 4
.binary 00000659
.data 0x811AE1C4
.data 4
.binary 00000717
.data 0x811AE1E8
.data 4
.binary 000001f4
.data 0x811AE20C
.data 4
.binary 000001f4
.data 0x811AE230
.data 4
.binary 00000785
.data 0x811AE254
.data 4
.binary 00000744
.data 0x811AE278
.data 4
.binary 00016f30
.data 0x811AE29C
.data 4
.binary 0000012c
.data 0x811AE2C0
.data 4
.binary 00000050
.data 0x811AE2E4
.data 4
.binary 0001368c
.data 0x811AE308
.data 4
.binary 000006b8
.data 0x811AE3BC
.data 4
.binary 00000500
.data 0x811AE3E0
.data 4
.binary 00000dac
.data 0x811AE404
.data 4
.binary 00000640
.data 0x811AE428
.data 4
.binary 00000127
.data 0x811AE44C
.data 4
.binary 00000645
.data 0x811AE470
.data 4
.binary 000006ef
.data 0x811AE494
.data 4
.binary 00000686
.data 0x811AE4B8
.data 4
.binary 00000686
.data 0x811AE4DC
.data 4
.binary 00000555
.data 0x811AE590
.data 4
.binary 0001cafc
.data 0x811AE71C
.data 4
.binary 000005aa
.data 0x811AE740
.data 4
.binary 000003cf
.data 0x811AE764
.data 4
.binary 00000384
.data 0x811AE788
.data 4
.binary 00000384
.data 0x811AE7AC
.data 4
.binary 00001130
.data 0x811AE7D0
.data 4
.binary 0000007d
.data 0x811AE83C
.data 4
.binary 0003d090
.data 0x811AE860
.data 4
.binary 00000064
.data 0x811AEAA0
.data 4
.binary 000005dc
.data 0x811AEAC4
.data 4
.binary 00000d7a
.data 0x811AEAE8
.data 4
.binary 0000054b
.data 0x811AEB0C
.data 4
.binary 00000564
.data 0x811AEB30
.data 4
.binary 0000053c
.data 0x811AEB54
.data 4
.binary 00000681
.data 0x811AEB78
.data 4
.binary 000005c3
.data 0x811AEB9C
.data 4
.binary 000005eb
.data 0x811AEBC0
.data 4
.binary 00000636
.data 0x811AEBE4
.data 4
.binary 00000753
.data 0x811AEC08
.data 4
.binary 0000069f
.data 0x811AEC2C
.data 4
.binary 000006bd
.data 0x811AEC50
.data 4
.binary 000006f4
.data 0
.data 0
@@ -0,0 +1,974 @@
.meta name="PSO Peeps EP2 10x EXP"
.meta description="Sets EP2 enemy EXP\nto 10x for GC crossplay"
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
# PSO Peeps GC Plus USA / 3OE1
# Source table: BattleParamEntry_lab_on.dat
# Active online battle-param table loaded at 0x811AB7C0
# EXP field offset within each 0x24-byte row is +0x1C
# Generated from clean BattleParamEntry_lab_on.dat; multiplier=10x
.data 0x811AB7DC
.data 4
.binary 0000000a
.data 0x811AB800
.data 4
.binary 0000003c
.data 0x811AB824
.data 4
.binary 00000064
.data 0x811AB848
.data 4
.binary 00000078
.data 0x811AB86C
.data 4
.binary 00000064
.data 0x811AB890
.data 4
.binary 000005dc
.data 0x811AB8B4
.data 4
.binary 000000be
.data 0x811AB8D8
.data 4
.binary 00000064
.data 0x811AB8FC
.data 4
.binary 000000a0
.data 0x811AB920
.data 4
.binary 000000aa
.data 0x811AB944
.data 4
.binary 000000aa
.data 0x811AB968
.data 4
.binary 00000014
.data 0x811AB98C
.data 4
.binary 00000014
.data 0x811AB9B0
.data 4
.binary 00000190
.data 0x811AB9D4
.data 4
.binary 00000096
.data 0x811AB9F8
.data 4
.binary 000012c0
.data 0x811ABA1C
.data 4
.binary 00000064
.data 0x811ABA40
.data 4
.binary 0000001e
.data 0x811ABA64
.data 4
.binary 0000251c
.data 0x811ABA88
.data 4
.binary 000000d2
.data 0x811ABB3C
.data 4
.binary 00000028
.data 0x811ABB60
.data 4
.binary 00000a00
.data 0x811ABB84
.data 4
.binary 000001fe
.data 0x811ABBA8
.data 4
.binary 00000014
.data 0x811ABBCC
.data 4
.binary 0000006e
.data 0x811ABBF0
.data 4
.binary 000000be
.data 0x811ABC14
.data 4
.binary 00003a98
.data 0x811ABCC8
.data 4
.binary 00000550
.data 0x811ABD10
.data 4
.binary 000001ea
.data 0x811ABD34
.data 4
.binary 000001c2
.data 0x811ABE0C
.data 4
.binary 000080e8
.data 0x811ABE9C
.data 4
.binary 00000122
.data 0x811ABEC0
.data 4
.binary 0000001e
.data 0x811ABEE4
.data 4
.binary 00000046
.data 0x811ABF08
.data 4
.binary 00000050
.data 0x811AC004
.data 4
.binary 000001d6
.data 0x811AC028
.data 4
.binary 00000078
.data 0x811AC04C
.data 4
.binary 00000096
.data 0x811AC070
.data 4
.binary 00000208
.data 0x811AC0DC
.data 4
.binary 0000012c
.data 0x811AC100
.data 4
.binary 00000078
.data 0x811AC124
.data 4
.binary 00000014
.data 0x811AC148
.data 4
.binary 00000140
.data 0x811AC16C
.data 4
.binary 00000190
.data 0x811AC190
.data 4
.binary 000001f4
.data 0x811AC1B4
.data 4
.binary 00000226
.data 0x811AC220
.data 4
.binary 00000064
.data 0x811AC244
.data 4
.binary 000003e8
.data 0x811AC268
.data 4
.binary 0000006e
.data 0x811AC28C
.data 4
.binary 00000082
.data 0x811AC2B0
.data 4
.binary 00000046
.data 0x811AC2D4
.data 4
.binary 00000078
.data 0x811AC2F8
.data 4
.binary 000000b4
.data 0x811AC31C
.data 4
.binary 000000d2
.data 0x811AC340
.data 4
.binary 0000008c
.data 0x811AC364
.data 4
.binary 00000096
.data 0x811AC388
.data 4
.binary 0000003c
.data 0x811AC3AC
.data 4
.binary 00000046
.data 0x811AC3D0
.data 4
.binary 00000050
.data 0x811AC55C
.data 4
.binary 00000172
.data 0x811AC580
.data 4
.binary 000001c2
.data 0x811AC5A4
.data 4
.binary 00000208
.data 0x811AC5C8
.data 4
.binary 00000226
.data 0x811AC5EC
.data 4
.binary 00000208
.data 0x811AC610
.data 4
.binary 00000b0e
.data 0x811AC634
.data 4
.binary 00000294
.data 0x811AC658
.data 4
.binary 00000208
.data 0x811AC67C
.data 4
.binary 00000244
.data 0x811AC6A0
.data 4
.binary 00000258
.data 0x811AC6C4
.data 4
.binary 00000276
.data 0x811AC6E8
.data 4
.binary 0000017c
.data 0x811AC70C
.data 4
.binary 0000017c
.data 0x811AC730
.data 4
.binary 000003f2
.data 0x811AC754
.data 4
.binary 00000258
.data 0x811AC778
.data 4
.binary 00007d00
.data 0x811AC79C
.data 4
.binary 000000fa
.data 0x811AC7C0
.data 4
.binary 00000028
.data 0x811AC7E4
.data 4
.binary 00009858
.data 0x811AC808
.data 4
.binary 00000294
.data 0x811AC8BC
.data 4
.binary 000001a4
.data 0x811AC8E0
.data 4
.binary 00001400
.data 0x811AC904
.data 4
.binary 000004a6
.data 0x811AC928
.data 4
.binary 00000064
.data 0x811AC94C
.data 4
.binary 00000212
.data 0x811AC970
.data 4
.binary 00000294
.data 0x811AC994
.data 4
.binary 0000afc8
.data 0x811ACA48
.data 4
.binary 00000a1e
.data 0x811ACA90
.data 4
.binary 00000488
.data 0x811ACAB4
.data 4
.binary 00000442
.data 0x811ACB8C
.data 4
.binary 00012cc8
.data 0x811ACC1C
.data 4
.binary 0000033e
.data 0x811ACC40
.data 4
.binary 000001d6
.data 0x811ACC64
.data 4
.binary 000001d6
.data 0x811ACC88
.data 4
.binary 000001e0
.data 0x811ACD84
.data 4
.binary 0000046a
.data 0x811ACDA8
.data 4
.binary 00000226
.data 0x811ACDCC
.data 4
.binary 00000258
.data 0x811ACDF0
.data 4
.binary 000004ba
.data 0x811ACE5C
.data 4
.binary 00000352
.data 0x811ACE80
.data 4
.binary 00000226
.data 0x811ACEA4
.data 4
.binary 000001c2
.data 0x811ACEC8
.data 4
.binary 00000370
.data 0x811ACEEC
.data 4
.binary 000003f2
.data 0x811ACF10
.data 4
.binary 0000049c
.data 0x811ACF34
.data 4
.binary 000004ec
.data 0x811ACF7C
.data 4
.binary 00000032
.data 0x811ACFA0
.data 4
.binary 00000208
.data 0x811ACFC4
.data 4
.binary 000007d0
.data 0x811ACFE8
.data 4
.binary 00000212
.data 0x811AD00C
.data 4
.binary 00000230
.data 0x811AD030
.data 4
.binary 000001c2
.data 0x811AD054
.data 4
.binary 00000226
.data 0x811AD078
.data 4
.binary 0000028a
.data 0x811AD09C
.data 4
.binary 000002bc
.data 0x811AD0C0
.data 4
.binary 00000226
.data 0x811AD0E4
.data 4
.binary 00000258
.data 0x811AD108
.data 4
.binary 000001c2
.data 0x811AD12C
.data 4
.binary 000001d6
.data 0x811AD150
.data 4
.binary 000001e0
.data 0x811AD2DC
.data 4
.binary 00000366
.data 0x811AD300
.data 4
.binary 000003ca
.data 0x811AD324
.data 4
.binary 0000041a
.data 0x811AD348
.data 4
.binary 00000442
.data 0x811AD36C
.data 4
.binary 0000041a
.data 0x811AD390
.data 4
.binary 00000f0a
.data 0x811AD3B4
.data 4
.binary 0000047e
.data 0x811AD3D8
.data 4
.binary 0000041a
.data 0x811AD3FC
.data 4
.binary 00000460
.data 0x811AD420
.data 4
.binary 00000474
.data 0x811AD444
.data 4
.binary 000004a6
.data 0x811AD468
.data 4
.binary 0000037a
.data 0x811AD48C
.data 4
.binary 0000037a
.data 0x811AD4B0
.data 4
.binary 00000672
.data 0x811AD4D4
.data 4
.binary 0000047e
.data 0x811AD4F8
.data 4
.binary 000157c0
.data 0x811AD51C
.data 4
.binary 00000258
.data 0x811AD540
.data 4
.binary 00000258
.data 0x811AD564
.data 4
.binary 000186a0
.data 0x811AD588
.data 4
.binary 000004ce
.data 0x811AD63C
.data 4
.binary 000003a2
.data 0x811AD660
.data 4
.binary 00001d88
.data 0x811AD684
.data 4
.binary 0000074e
.data 0x811AD6A8
.data 4
.binary 0000012c
.data 0x811AD6CC
.data 4
.binary 0000042e
.data 0x811AD6F0
.data 4
.binary 000004ce
.data 0x811AD714
.data 4
.binary 0001e848
.data 0x811AD7C8
.data 4
.binary 00000df2
.data 0x811AD810
.data 4
.binary 00000726
.data 0x811AD834
.data 4
.binary 000006d6
.data 0x811AD90C
.data 4
.binary 000249f0
.data 0x811AD99C
.data 4
.binary 00000596
.data 0x811AD9C0
.data 4
.binary 0000038e
.data 0x811AD9E4
.data 4
.binary 000003de
.data 0x811ADA08
.data 4
.binary 000003f2
.data 0x811ADB04
.data 4
.binary 000006fe
.data 0x811ADB28
.data 4
.binary 00000442
.data 0x811ADB4C
.data 4
.binary 0000047e
.data 0x811ADB70
.data 4
.binary 00000762
.data 0x811ADBDC
.data 4
.binary 000005aa
.data 0x811ADC00
.data 4
.binary 00000442
.data 0x811ADC24
.data 4
.binary 000003b6
.data 0x811ADC48
.data 4
.binary 000005d2
.data 0x811ADC6C
.data 4
.binary 00000672
.data 0x811ADC90
.data 4
.binary 0000073a
.data 0x811ADCB4
.data 4
.binary 0000079e
.data 0x811ADCFC
.data 4
.binary 00000032
.data 0x811ADD20
.data 4
.binary 0000041a
.data 0x811ADD44
.data 4
.binary 00000b22
.data 0x811ADD68
.data 4
.binary 0000042e
.data 0x811ADD8C
.data 4
.binary 00000456
.data 0x811ADDB0
.data 4
.binary 000003ac
.data 0x811ADDD4
.data 4
.binary 00000442
.data 0x811ADDF8
.data 4
.binary 000004ba
.data 0x811ADE1C
.data 4
.binary 000004f6
.data 0x811ADE40
.data 4
.binary 00000438
.data 0x811ADE64
.data 4
.binary 0000047e
.data 0x811ADE88
.data 4
.binary 000003ca
.data 0x811ADEAC
.data 4
.binary 000003de
.data 0x811ADED0
.data 4
.binary 000003f2
.data 0x811AE05C
.data 4
.binary 000005dc
.data 0x811AE080
.data 4
.binary 00000bf4
.data 0x811AE0A4
.data 4
.binary 00000ce4
.data 0x811AE0C8
.data 4
.binary 00000d5c
.data 0x811AE0EC
.data 4
.binary 00000ce4
.data 0x811AE110
.data 4
.binary 00002db4
.data 0x811AE134
.data 4
.binary 00000e10
.data 0x811AE158
.data 4
.binary 00000ce4
.data 0x811AE17C
.data 4
.binary 00000be0
.data 0x811AE1A0
.data 4
.binary 00000c08
.data 0x811AE1C4
.data 4
.binary 00000e88
.data 0x811AE1E8
.data 4
.binary 000003e8
.data 0x811AE20C
.data 4
.binary 000003e8
.data 0x811AE230
.data 4
.binary 000013ec
.data 0x811AE254
.data 4
.binary 00000e10
.data 0x811AE278
.data 4
.binary 0002bf20
.data 0x811AE29C
.data 4
.binary 00000258
.data 0x811AE2C0
.data 4
.binary 000000a0
.data 0x811AE2E4
.data 4
.binary 00033450
.data 0x811AE308
.data 4
.binary 00000f00
.data 0x811AE3BC
.data 4
.binary 00000b7c
.data 0x811AE3E0
.data 4
.binary 00002800
.data 0x811AE404
.data 4
.binary 00001680
.data 0x811AE428
.data 4
.binary 000001f4
.data 0x811AE44C
.data 4
.binary 00000d20
.data 0x811AE470
.data 4
.binary 00000f00
.data 0x811AE494
.data 4
.binary 0003c4d8
.data 0x811AE548
.data 4
.binary 00002a6c
.data 0x811AE590
.data 4
.binary 00001608
.data 0x811AE5B4
.data 4
.binary 00001518
.data 0x811AE68C
.data 4
.binary 00073f78
.data 0x811AE71C
.data 4
.binary 00001158
.data 0x811AE740
.data 4
.binary 00000c30
.data 0x811AE764
.data 4
.binary 00000c30
.data 0x811AE788
.data 4
.binary 00000c6c
.data 0x811AE884
.data 4
.binary 00000d98
.data 0x811AE8A8
.data 4
.binary 00000d5c
.data 0x811AE8CC
.data 4
.binary 00000e10
.data 0x811AE8F0
.data 4
.binary 000016bc
.data 0x811AE95C
.data 4
.binary 00001194
.data 0x811AE980
.data 4
.binary 00000d5c
.data 0x811AE9A4
.data 4
.binary 000007d0
.data 0x811AE9C8
.data 4
.binary 0000120c
.data 0x811AE9EC
.data 4
.binary 000013ec
.data 0x811AEA10
.data 4
.binary 00001644
.data 0x811AEA34
.data 4
.binary 00001770
.data 0x811AEA7C
.data 4
.binary 00000032
.data 0x811AEAA0
.data 4
.binary 00000ce4
.data 0x811AEAC4
.data 4
.binary 000021fc
.data 0x811AEAE8
.data 4
.binary 00000d20
.data 0x811AEB0C
.data 4
.binary 00000d98
.data 0x811AEB30
.data 4
.binary 00000a78
.data 0x811AEB54
.data 4
.binary 00000d5c
.data 0x811AEB78
.data 4
.binary 00000ec4
.data 0x811AEB9C
.data 4
.binary 00000f78
.data 0x811AEBC0
.data 4
.binary 00000b90
.data 0x811AEBE4
.data 4
.binary 00000e10
.data 0x811AEC08
.data 4
.binary 00000bf4
.data 0x811AEC2C
.data 4
.binary 00000c30
.data 0x811AEC50
.data 4
.binary 00000c6c
.data 0
.data 0
@@ -0,0 +1,974 @@
.meta name="PSO Peeps EP2 5x EXP"
.meta description="Sets EP2 enemy EXP\nto 5x for GC crossplay"
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
# PSO Peeps GC Plus USA / 3OE1
# Source table: BattleParamEntry_lab_on.dat
# Active online battle-param table loaded at 0x811AB7C0
# EXP field offset within each 0x24-byte row is +0x1C
# Generated from clean BattleParamEntry_lab_on.dat; multiplier=5x
.data 0x811AB7DC
.data 4
.binary 00000005
.data 0x811AB800
.data 4
.binary 0000001e
.data 0x811AB824
.data 4
.binary 00000032
.data 0x811AB848
.data 4
.binary 0000003c
.data 0x811AB86C
.data 4
.binary 00000032
.data 0x811AB890
.data 4
.binary 000002ee
.data 0x811AB8B4
.data 4
.binary 0000005f
.data 0x811AB8D8
.data 4
.binary 00000032
.data 0x811AB8FC
.data 4
.binary 00000050
.data 0x811AB920
.data 4
.binary 00000055
.data 0x811AB944
.data 4
.binary 00000055
.data 0x811AB968
.data 4
.binary 0000000a
.data 0x811AB98C
.data 4
.binary 0000000a
.data 0x811AB9B0
.data 4
.binary 000000c8
.data 0x811AB9D4
.data 4
.binary 0000004b
.data 0x811AB9F8
.data 4
.binary 00000960
.data 0x811ABA1C
.data 4
.binary 00000032
.data 0x811ABA40
.data 4
.binary 0000000f
.data 0x811ABA64
.data 4
.binary 0000128e
.data 0x811ABA88
.data 4
.binary 00000069
.data 0x811ABB3C
.data 4
.binary 00000014
.data 0x811ABB60
.data 4
.binary 00000500
.data 0x811ABB84
.data 4
.binary 000000ff
.data 0x811ABBA8
.data 4
.binary 0000000a
.data 0x811ABBCC
.data 4
.binary 00000037
.data 0x811ABBF0
.data 4
.binary 0000005f
.data 0x811ABC14
.data 4
.binary 00001d4c
.data 0x811ABCC8
.data 4
.binary 000002a8
.data 0x811ABD10
.data 4
.binary 000000f5
.data 0x811ABD34
.data 4
.binary 000000e1
.data 0x811ABE0C
.data 4
.binary 00004074
.data 0x811ABE9C
.data 4
.binary 00000091
.data 0x811ABEC0
.data 4
.binary 0000000f
.data 0x811ABEE4
.data 4
.binary 00000023
.data 0x811ABF08
.data 4
.binary 00000028
.data 0x811AC004
.data 4
.binary 000000eb
.data 0x811AC028
.data 4
.binary 0000003c
.data 0x811AC04C
.data 4
.binary 0000004b
.data 0x811AC070
.data 4
.binary 00000104
.data 0x811AC0DC
.data 4
.binary 00000096
.data 0x811AC100
.data 4
.binary 0000003c
.data 0x811AC124
.data 4
.binary 0000000a
.data 0x811AC148
.data 4
.binary 000000a0
.data 0x811AC16C
.data 4
.binary 000000c8
.data 0x811AC190
.data 4
.binary 000000fa
.data 0x811AC1B4
.data 4
.binary 00000113
.data 0x811AC220
.data 4
.binary 00000032
.data 0x811AC244
.data 4
.binary 000001f4
.data 0x811AC268
.data 4
.binary 00000037
.data 0x811AC28C
.data 4
.binary 00000041
.data 0x811AC2B0
.data 4
.binary 00000023
.data 0x811AC2D4
.data 4
.binary 0000003c
.data 0x811AC2F8
.data 4
.binary 0000005a
.data 0x811AC31C
.data 4
.binary 00000069
.data 0x811AC340
.data 4
.binary 00000046
.data 0x811AC364
.data 4
.binary 0000004b
.data 0x811AC388
.data 4
.binary 0000001e
.data 0x811AC3AC
.data 4
.binary 00000023
.data 0x811AC3D0
.data 4
.binary 00000028
.data 0x811AC55C
.data 4
.binary 000000b9
.data 0x811AC580
.data 4
.binary 000000e1
.data 0x811AC5A4
.data 4
.binary 00000104
.data 0x811AC5C8
.data 4
.binary 00000113
.data 0x811AC5EC
.data 4
.binary 00000104
.data 0x811AC610
.data 4
.binary 00000587
.data 0x811AC634
.data 4
.binary 0000014a
.data 0x811AC658
.data 4
.binary 00000104
.data 0x811AC67C
.data 4
.binary 00000122
.data 0x811AC6A0
.data 4
.binary 0000012c
.data 0x811AC6C4
.data 4
.binary 0000013b
.data 0x811AC6E8
.data 4
.binary 000000be
.data 0x811AC70C
.data 4
.binary 000000be
.data 0x811AC730
.data 4
.binary 000001f9
.data 0x811AC754
.data 4
.binary 0000012c
.data 0x811AC778
.data 4
.binary 00003e80
.data 0x811AC79C
.data 4
.binary 0000007d
.data 0x811AC7C0
.data 4
.binary 00000014
.data 0x811AC7E4
.data 4
.binary 00004c2c
.data 0x811AC808
.data 4
.binary 0000014a
.data 0x811AC8BC
.data 4
.binary 000000d2
.data 0x811AC8E0
.data 4
.binary 00000a00
.data 0x811AC904
.data 4
.binary 00000253
.data 0x811AC928
.data 4
.binary 00000032
.data 0x811AC94C
.data 4
.binary 00000109
.data 0x811AC970
.data 4
.binary 0000014a
.data 0x811AC994
.data 4
.binary 000057e4
.data 0x811ACA48
.data 4
.binary 0000050f
.data 0x811ACA90
.data 4
.binary 00000244
.data 0x811ACAB4
.data 4
.binary 00000221
.data 0x811ACB8C
.data 4
.binary 00009664
.data 0x811ACC1C
.data 4
.binary 0000019f
.data 0x811ACC40
.data 4
.binary 000000eb
.data 0x811ACC64
.data 4
.binary 000000eb
.data 0x811ACC88
.data 4
.binary 000000f0
.data 0x811ACD84
.data 4
.binary 00000235
.data 0x811ACDA8
.data 4
.binary 00000113
.data 0x811ACDCC
.data 4
.binary 0000012c
.data 0x811ACDF0
.data 4
.binary 0000025d
.data 0x811ACE5C
.data 4
.binary 000001a9
.data 0x811ACE80
.data 4
.binary 00000113
.data 0x811ACEA4
.data 4
.binary 000000e1
.data 0x811ACEC8
.data 4
.binary 000001b8
.data 0x811ACEEC
.data 4
.binary 000001f9
.data 0x811ACF10
.data 4
.binary 0000024e
.data 0x811ACF34
.data 4
.binary 00000276
.data 0x811ACF7C
.data 4
.binary 00000019
.data 0x811ACFA0
.data 4
.binary 00000104
.data 0x811ACFC4
.data 4
.binary 000003e8
.data 0x811ACFE8
.data 4
.binary 00000109
.data 0x811AD00C
.data 4
.binary 00000118
.data 0x811AD030
.data 4
.binary 000000e1
.data 0x811AD054
.data 4
.binary 00000113
.data 0x811AD078
.data 4
.binary 00000145
.data 0x811AD09C
.data 4
.binary 0000015e
.data 0x811AD0C0
.data 4
.binary 00000113
.data 0x811AD0E4
.data 4
.binary 0000012c
.data 0x811AD108
.data 4
.binary 000000e1
.data 0x811AD12C
.data 4
.binary 000000eb
.data 0x811AD150
.data 4
.binary 000000f0
.data 0x811AD2DC
.data 4
.binary 000001b3
.data 0x811AD300
.data 4
.binary 000001e5
.data 0x811AD324
.data 4
.binary 0000020d
.data 0x811AD348
.data 4
.binary 00000221
.data 0x811AD36C
.data 4
.binary 0000020d
.data 0x811AD390
.data 4
.binary 00000785
.data 0x811AD3B4
.data 4
.binary 0000023f
.data 0x811AD3D8
.data 4
.binary 0000020d
.data 0x811AD3FC
.data 4
.binary 00000230
.data 0x811AD420
.data 4
.binary 0000023a
.data 0x811AD444
.data 4
.binary 00000253
.data 0x811AD468
.data 4
.binary 000001bd
.data 0x811AD48C
.data 4
.binary 000001bd
.data 0x811AD4B0
.data 4
.binary 00000339
.data 0x811AD4D4
.data 4
.binary 0000023f
.data 0x811AD4F8
.data 4
.binary 0000abe0
.data 0x811AD51C
.data 4
.binary 0000012c
.data 0x811AD540
.data 4
.binary 0000012c
.data 0x811AD564
.data 4
.binary 0000c350
.data 0x811AD588
.data 4
.binary 00000267
.data 0x811AD63C
.data 4
.binary 000001d1
.data 0x811AD660
.data 4
.binary 00000ec4
.data 0x811AD684
.data 4
.binary 000003a7
.data 0x811AD6A8
.data 4
.binary 00000096
.data 0x811AD6CC
.data 4
.binary 00000217
.data 0x811AD6F0
.data 4
.binary 00000267
.data 0x811AD714
.data 4
.binary 0000f424
.data 0x811AD7C8
.data 4
.binary 000006f9
.data 0x811AD810
.data 4
.binary 00000393
.data 0x811AD834
.data 4
.binary 0000036b
.data 0x811AD90C
.data 4
.binary 000124f8
.data 0x811AD99C
.data 4
.binary 000002cb
.data 0x811AD9C0
.data 4
.binary 000001c7
.data 0x811AD9E4
.data 4
.binary 000001ef
.data 0x811ADA08
.data 4
.binary 000001f9
.data 0x811ADB04
.data 4
.binary 0000037f
.data 0x811ADB28
.data 4
.binary 00000221
.data 0x811ADB4C
.data 4
.binary 0000023f
.data 0x811ADB70
.data 4
.binary 000003b1
.data 0x811ADBDC
.data 4
.binary 000002d5
.data 0x811ADC00
.data 4
.binary 00000221
.data 0x811ADC24
.data 4
.binary 000001db
.data 0x811ADC48
.data 4
.binary 000002e9
.data 0x811ADC6C
.data 4
.binary 00000339
.data 0x811ADC90
.data 4
.binary 0000039d
.data 0x811ADCB4
.data 4
.binary 000003cf
.data 0x811ADCFC
.data 4
.binary 00000019
.data 0x811ADD20
.data 4
.binary 0000020d
.data 0x811ADD44
.data 4
.binary 00000591
.data 0x811ADD68
.data 4
.binary 00000217
.data 0x811ADD8C
.data 4
.binary 0000022b
.data 0x811ADDB0
.data 4
.binary 000001d6
.data 0x811ADDD4
.data 4
.binary 00000221
.data 0x811ADDF8
.data 4
.binary 0000025d
.data 0x811ADE1C
.data 4
.binary 0000027b
.data 0x811ADE40
.data 4
.binary 0000021c
.data 0x811ADE64
.data 4
.binary 0000023f
.data 0x811ADE88
.data 4
.binary 000001e5
.data 0x811ADEAC
.data 4
.binary 000001ef
.data 0x811ADED0
.data 4
.binary 000001f9
.data 0x811AE05C
.data 4
.binary 000002ee
.data 0x811AE080
.data 4
.binary 000005fa
.data 0x811AE0A4
.data 4
.binary 00000672
.data 0x811AE0C8
.data 4
.binary 000006ae
.data 0x811AE0EC
.data 4
.binary 00000672
.data 0x811AE110
.data 4
.binary 000016da
.data 0x811AE134
.data 4
.binary 00000708
.data 0x811AE158
.data 4
.binary 00000672
.data 0x811AE17C
.data 4
.binary 000005f0
.data 0x811AE1A0
.data 4
.binary 00000604
.data 0x811AE1C4
.data 4
.binary 00000744
.data 0x811AE1E8
.data 4
.binary 000001f4
.data 0x811AE20C
.data 4
.binary 000001f4
.data 0x811AE230
.data 4
.binary 000009f6
.data 0x811AE254
.data 4
.binary 00000708
.data 0x811AE278
.data 4
.binary 00015f90
.data 0x811AE29C
.data 4
.binary 0000012c
.data 0x811AE2C0
.data 4
.binary 00000050
.data 0x811AE2E4
.data 4
.binary 00019a28
.data 0x811AE308
.data 4
.binary 00000780
.data 0x811AE3BC
.data 4
.binary 000005be
.data 0x811AE3E0
.data 4
.binary 00001400
.data 0x811AE404
.data 4
.binary 00000b40
.data 0x811AE428
.data 4
.binary 000000fa
.data 0x811AE44C
.data 4
.binary 00000690
.data 0x811AE470
.data 4
.binary 00000780
.data 0x811AE494
.data 4
.binary 0001e26c
.data 0x811AE548
.data 4
.binary 00001536
.data 0x811AE590
.data 4
.binary 00000b04
.data 0x811AE5B4
.data 4
.binary 00000a8c
.data 0x811AE68C
.data 4
.binary 00039fbc
.data 0x811AE71C
.data 4
.binary 000008ac
.data 0x811AE740
.data 4
.binary 00000618
.data 0x811AE764
.data 4
.binary 00000618
.data 0x811AE788
.data 4
.binary 00000636
.data 0x811AE884
.data 4
.binary 000006cc
.data 0x811AE8A8
.data 4
.binary 000006ae
.data 0x811AE8CC
.data 4
.binary 00000708
.data 0x811AE8F0
.data 4
.binary 00000b5e
.data 0x811AE95C
.data 4
.binary 000008ca
.data 0x811AE980
.data 4
.binary 000006ae
.data 0x811AE9A4
.data 4
.binary 000003e8
.data 0x811AE9C8
.data 4
.binary 00000906
.data 0x811AE9EC
.data 4
.binary 000009f6
.data 0x811AEA10
.data 4
.binary 00000b22
.data 0x811AEA34
.data 4
.binary 00000bb8
.data 0x811AEA7C
.data 4
.binary 00000019
.data 0x811AEAA0
.data 4
.binary 00000672
.data 0x811AEAC4
.data 4
.binary 000010fe
.data 0x811AEAE8
.data 4
.binary 00000690
.data 0x811AEB0C
.data 4
.binary 000006cc
.data 0x811AEB30
.data 4
.binary 0000053c
.data 0x811AEB54
.data 4
.binary 000006ae
.data 0x811AEB78
.data 4
.binary 00000762
.data 0x811AEB9C
.data 4
.binary 000007bc
.data 0x811AEBC0
.data 4
.binary 000005c8
.data 0x811AEBE4
.data 4
.binary 00000708
.data 0x811AEC08
.data 4
.binary 000005fa
.data 0x811AEC2C
.data 4
.binary 00000618
.data 0x811AEC50
.data 4
.binary 00000636
.data 0
.data 0
@@ -0,0 +1,44 @@
# (uint16_t entity_id @ eax) -> TObjectV00b421c0* @ eax
# Preserves all registers except eax
get_enemy_entity:
push esi
push edi
push edx
push ecx
xor edx, edx
xchg edx, eax
cmp edx, 0x1000
jl done
cmp edx, 0x4000
jge done
mov esi, [0x00AABCE8] # bs_low = next_player_entity_index
mov edi, [0x00AABCE4]
lea edi, [edi + esi - 1] # bs_high = next_player_entity_index + next_enemy_entity_index - 1
bs_again:
cmp esi, edi
jge bs_done
lea ecx, [esi + edi]
shr ecx, 1
mov eax, [ecx * 4 + 0x00AAB2A0] # all_entities[ecx]
cmp [eax + 0x1C], dx
jge bs_not_less
lea esi, [ecx + 1]
jmp bs_again
bs_not_less:
mov edi, ecx
jmp bs_again
bs_done:
mov eax, [esi * 4 + 0x00AAB2A0] # all_entities[bs_low]
test eax, eax
je done
xor ecx, ecx
cmp [eax + 0x1C], dx
cmovne eax, ecx
done:
pop ecx
pop edx
pop edi
pop esi
@@ -0,0 +1,42 @@
# This file defines the following function:
# write_address_of_code(
# const void* patch_code,
# size_t patch_code_size,
# void** ptr_addr);
# This function allocates memory for patch_code, copies patch_code to that
# memory, then writes the address of the allocated code at the specified
# pointer. The allocated memory is never freed.
# This function pops its arguments off the stack before returning.
write_call_to_code:
# [esp + 0x04] = code ptr
# [esp + 0x08] = code size
# [esp + 0x0C] = ptr addr
# Allocate memory for the copied code
mov ecx, [0x00AA8F84]
push dword [esp + 0x08]
mov eax, 0x007A984C
call eax # malloc7
test eax, eax
je done
# Copy the code to the newly-allocated memory
# eax = dest pointer (from malloc7 call above)
mov edx, [esp + 0x04] # edx = source pointer
mov ecx, [esp + 0x08] # ecx = source size
push ebx
memcpy_again:
dec ecx
mov bl, [edx + ecx] # Copy one byte from source to dest
mov [eax + ecx], bl
test ecx, ecx
jne memcpy_again
pop ebx
# Write the address
mov ecx, [esp + 0x0C]
mov [ecx], eax
done:
ret 0x0C
@@ -0,0 +1,76 @@
# This file defines the following function:
# write_call_to_code(
# const void* patch_code,
# size_t patch_code_size,
# void* call_opcode_address,
# ssize_t call_opcode_bytes);
# This function allocates memory for patch_code, copies patch_code to that
# memory, then writes a call or jmp opcode to call_opcode_address that calls
# the code in the allocated memory region. The allocated memory is never freed.
# call_opcode_bytes specifies how many bytes at the callsite should be
# overwritten. This value must be at least 5; the first 5 bytes are overwritten
# with the call/jmp opcode itself; the rest are overwritten with nop opcodes.
# If call_opcode_bytes is positive, a call opcode is written; if it's negative,
# a jmp opcode is written.
# This function pops its arguments off the stack before returning.
write_call_to_code:
# [esp + 0x04] = code ptr
# [esp + 0x08] = code size
# [esp + 0x0C] = jump callsite
# [esp + 0x10] = callsite size (if zero, write the address instead of a call)
# Allocate memory for the copied code
mov ecx, [0x00AA8F84]
push dword [esp + 0x08]
mov eax, 0x007A984C
call eax # malloc7
test eax, eax
je done
# Copy the code to the newly-allocated memory
# eax = dest pointer (from malloc7 call above)
mov edx, [esp + 0x04] # edx = source pointer
mov ecx, [esp + 0x08] # ecx = source size
push ebx
memcpy_again:
dec ecx
mov bl, [edx + ecx] # Copy one byte from source to dest
mov [eax + ecx], bl
test ecx, ecx
jne memcpy_again
pop ebx
mov edx, [esp + 0x0C] # edx = jump callsite
# If the callsite size is zero, just write the address directly
cmp dword [esp + 0x10], 0
jne write_call_or_jmp
mov [edx], eax
jmp done
# Write the call or jmp opcode
write_call_or_jmp:
lea ecx, [eax - 5]
sub ecx, edx # ecx = (dest code addr) - (jump callsite) - 5
cmp dword [esp + 0x10], 0
setl al
or al, 0xE8
mov [edx], al # Write E8 (call), or E9 (jmp) if size was negative
mov [edx + 1], ecx # Write delta
# Write as many nops after the call opcode as necessary
mov ecx, 5
mov eax, [esp + 0x10]
cmp eax, 0
jge write_nop_again
neg eax
write_nop_again:
cmp ecx, eax
jge done
mov byte [edx + ecx], 0x90
inc ecx
jmp write_nop_again
done:
ret 0x10
@@ -0,0 +1,83 @@
# This file defines the following function:
# void [/std] write_call_to_code(
# const void* patch_code @ [esp + 0x04],
# size_t patch_code_size @ [esp + 0x08],
# size_t call_count @ [esp + 0x0C],
# void* call_opcode_address @ [esp + 0x10],
# ssize_t call_opcode_bytes @ [esp + 0x14],
# ...);
# This function allocates memory for patch_code, copies patch_code to that
# memory, then writes a call or jmp opcode to call_opcode_address that calls
# the code in the allocated memory region. The allocated memory is never freed.
# call_opcode_bytes specifies how many bytes at the callsite should be
# overwritten. This value must be at least 5; the first 5 bytes are overwritten
# with the call/jmp opcode itself; the rest are overwritten with nop opcodes.
# This function pops its arguments off the stack before returning (including
# all the varargs).
write_call_to_code:
# [esp + 0x04] = code ptr
# [esp + 0x08] = code size
# [esp + 0x0C] = callsite count
# [esp + 0x10] = callsite address
# [esp + 0x14] = callsite size
# ... (further callsite address/size pairs)
# Allocate memory for the copied code
mov ecx, [0x00AA8F84]
push dword [esp + 0x08]
mov eax, 0x007A984C
call eax # malloc7
test eax, eax
je done
# Copy the code to the newly-allocated memory
# eax = dest pointer (from malloc7 call above)
mov edx, [esp + 0x04] # edx = source pointer
mov ecx, [esp + 0x08] # ecx = source size
push ebx
memcpy_again:
dec ecx
mov bl, [edx + ecx] # Copy one byte from source to dest
mov [eax + ecx], bl
test ecx, ecx
jne memcpy_again
pop ebx
# Write the call opcodes
xchg ebx, [esp + 0x0C] # Save ebx; get callsite count
mov [esp - 0x08], esi
mov [esp - 0x0C], eax
mov esi, 0x10 # Stack offset of first callsite pair
next_callsite:
mov edx, [esp + esi] # edx = jump callsite
lea ecx, [eax - 5]
sub ecx, edx # ecx = (dest code addr) - (jump callsite) - 5
mov byte [edx], 0xE8
mov [edx + 1], ecx # Write E8 (call) followed by delta
# Write as many nops after the call opcode as necessary
mov ecx, 5
mov eax, [esp + esi + 4]
write_nop_again:
cmp ecx, eax
jge this_callsite_done
mov byte [edx + ecx], 0x90
inc ecx
jmp write_nop_again
this_callsite_done:
mov eax, [esp - 0x0C]
add esi, 8
dec ebx
jnz next_callsite
mov ecx, esi
mov ebx, [esp + 0x0C]
mov esi, [esp - 0x08]
done:
mov eax, [esp]
add esp, ecx
jmp eax
+2 -2
View File
@@ -576,14 +576,14 @@
],
// BB bank size. If you change either of these values, you must also add "BankSize" to BBRequiredPatches, and change
// the patch contents in system/client-functions/BlueBurstExclusive/BankSize.59NL.patch.s to reflect the counts here.
// the patch contents in system/client-functions/BlueBurstExclusive/BankSize.5___.patch.s to reflect the counts here.
"BBMaxBankItems": 200,
"BBMaxBankMeseta": 999999,
// Item stack limits. Note that changing these does not affect the client's behavior automatically - this only exists
// to allow the server to understand the behavior of clients that are already patched with different stack limits.
// If you want to use an unpatched BB client but still have custom stack limits, you can use the StackLimits runtime
// patch by editing system/client-functions/BlueBurstExclusive/StackLimits.59NL.patch.s to match the BB stack limits
// patch by editing system/client-functions/BlueBurstExclusive/StackLimits.5___.patch.s to match the BB stack limits
// and adding "StackLimits" to the BBRequiredPatches list.
// It's important that all players in the same game have the same stack limits, both on the client and server! So, if
// you change the BB stack limits, you must either prevent BB from playing with other versions (see
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
ItemPMT-pc-v2.prs
@@ -1 +0,0 @@
ItemPMT-gc-v3.prs
-1
View File
@@ -1 +0,0 @@
ItemPMT-gc-v3.prs
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
ItemPMT-pc-v2.prs
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
item-parameter-table-pc-v2.json
@@ -0,0 +1 @@
item-parameter-table-gc-v3.json
+1
View File
@@ -0,0 +1 @@
item-parameter-table-gc-v3.json
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
item-parameter-table-pc-v2.json
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+25 -23
View File
@@ -1,19 +1,15 @@
[
// This table maps in-game primary identifiers across client versions. The
// high bit of the entries in this table specifies the entry type; if this
// bit is set, the entry is not "canonical"; that is, it's a one-way mapping
// and the client does not actually have that item defined. Each primary
// identifier must have at most one "canonical" listing for each version
// (but may have none). To convert an item from client A to client B:
// 1. Scan the column for A's version in the table to find the cell that
// contains the primary identifier sent by A. (We optimize this with an
// index.)
// This table maps in-game primary identifiers across client versions. The high bit of the entries in this table
// specifies the entry type; if this bit is set, the entry is not "canonical"; that is, it's a one-way mapping and
// the client does not actually have that item defined. Each primary identifier must have at most one "canonical"
// listing for each version (but may have none). To convert an item from client A to client B:
// 1. Scan the column for A's version in the table to find the cell that contains the primary identifier sent by A.
// (We optimize this with an index.)
// 2. Move left or right to the column for B's version.
// 3. Take the value from that cell, clear the high bit if needed, and use
// that as the primary identifier to show to B.
// 3. Take the value from that cell, clear the high bit if needed, and use that as the primary identifier for B.
// This logic is implemented in ItemTranslationTable.cc.
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
[0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "UNUSED"],
[0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000, "Saber"],
[0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, 0x00010100, "Brand"],
@@ -134,7 +130,6 @@
[0x000F0100, 0x000F0100, 0x000F0100, 0x000F0100, 0x000F0100, 0x000F0100, 0x800F0000, 0x000F0100, 0x000F0100, 0x000F0100, 0x000F0100, 0x000F0100, "ANGRY FIST"],
[0x000F0200, 0x000F0200, 0x000F0200, 0x000F0200, 0x000F0200, 0x000F0200, 0x800F0000, 0x000F0200, 0x000F0200, 0x000F0200, 0x000F0200, 0x000F0200, "GOD HAND"],
[0x000F0300, 0x000F0300, 0x000F0300, 0x000F0300, 0x000F0300, 0x000F0300, 0x800F0000, 0x000F0300, 0x000F0300, 0x000F0300, 0x000F0300, 0x000F0300, "SONIC KNUCKLE"],
[0x000F0400, 0x000F0400, 0x000F0400, 0x000F0400, 0x000F0400, 0x000F0400, 0x80020500, 0x80100000, 0x80100000, 0x80100000, 0x80100000, 0x80100000, "OROTIAGITO (v0-v2)"],
[0x800F0300, 0x800F0300, 0x800F0300, 0x800F0300, 0x800F0300, 0x800F0300, 0x800F0000, 0x800F0300, 0x800F0300, 0x800F0300, 0x800F0300, 0x000F0400, "LOGiN"],
[0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000, "OROTIAGITO"],
[0x00100100, 0x00100100, 0x00100100, 0x00100100, 0x00100100, 0x00100100, 0x80100000, 0x00100100, 0x00100100, 0x00100100, 0x00100100, 0x00100100, "AGITO (1975)"],
@@ -439,7 +434,9 @@
[0x80080500, 0x80080500, 0x80080500, 0x80770000, 0x80770000, 0x80770000, 0x80080500, 0x80770000, 0x80770000, 0x80770000, 0x80770000, 0x00EA0000, "TypeME/MECHGUN"],
[0x80090500, 0x80090500, 0x80090500, 0x80780000, 0x80780000, 0x80780000, 0x80090500, 0x80780000, 0x80780000, 0x80780000, 0x80780000, 0x00EB0000, "TypeSH/SHOT"],
[0x800C0400, 0x800C0400, 0x800C0400, 0x807B0000, 0x807B0000, 0x807B0000, 0x800C0400, 0x807B0000, 0x807B0000, 0x807B0000, 0x807B0000, 0x00EC0000, "TypeWA/WAND"],
[0x80010000, 0x80010000, 0x80010000, 0x00890000, 0x00890000, 0x00890000, 0x008D0000, 0x00AA0000, 0x00AA0000, 0x00AA0000, 0x00AA0000, 0x00ED0000, "???? (WEAPON)"],
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
[0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, 0x01010000, "Frame"],
[0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, 0x01010100, "Armor"],
[0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, 0x01010200, "Psy Armor"],
@@ -528,8 +525,9 @@
[0x81012800, 0x81012800, 0x81012800, 0x81013400, 0x81013400, 0x81013400, 0x81010C00, 0x81013400, 0x81013400, 0x81013400, 0x81013400, 0x01015500, "UNION FIELD"],
[0x81012800, 0x81012800, 0x81012800, 0x81013400, 0x81013400, 0x81013400, 0x81010C00, 0x81013400, 0x81013400, 0x81013400, 0x81013400, 0x01015600, "SAMURAI ARMOR"],
[0x81012800, 0x81012800, 0x81012800, 0x81013400, 0x81013400, 0x81013400, 0x81010C00, 0x81013400, 0x81013400, 0x81013400, 0x81013400, 0x01015700, "STEALTH SUIT"],
[0x81012800, 0x81012800, 0x81012800, 0x81013400, 0x81013400, 0x81013400, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01015800, "???? (ARMOR)"],
[0x81012800, 0x81012800, 0x81012800, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01013500, 0x01015800, "???? (ARMOR)"],
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
[0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, 0x01020000, "Barrier"],
[0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, 0x01020100, "Shield"],
[0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, 0x01020200, "Core Shield"],
@@ -695,8 +693,9 @@
[0x81022600, 0x81022600, 0x81022600, 0x81023500, 0x81023500, 0x81023500, 0x81020C00, 0x81028400, 0x81028400, 0x81028400, 0x81028400, 0x0102A200, "GENPEI (unused)"],
[0x81022600, 0x81022600, 0x81022600, 0x81023500, 0x81023500, 0x81023500, 0x81020C00, 0x81028400, 0x81028400, 0x81028400, 0x81028400, 0x0102A300, "GENPEI (unused)"],
[0x81022600, 0x81022600, 0x81022600, 0x81023500, 0x81023500, 0x81023500, 0x81020C00, 0x81028400, 0x81028400, 0x81028400, 0x81028400, 0x0102A400, "GENPEI (unused)"],
[0x81022600, 0x81022600, 0x81022600, 0x81023500, 0x81023500, 0x81023500, 0x81020C00, 0x01028500, 0x01028500, 0x01028500, 0x01028500, 0x0102A500, "???? (SHIELD)"],
[0x81022600, 0x81022600, 0x81022600, 0x01023A00, 0x01023A00, 0x01023A00, 0x81020C00, 0x01028500, 0x01028500, 0x01028500, 0x01028500, 0x0102A500, "???? (SHIELD)"],
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
[0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, 0x01030000, "Knight/Power"],
[0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, 0x01030100, "General/Power"],
[0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, 0x01030200, "Ogre/Power"],
@@ -799,8 +798,9 @@
[0x81033500, 0x81033500, 0x81033500, 0x81033500, 0x81033500, 0x81033500, 0x81033400, 0x81033500, 0x81033500, 0x81033500, 0x81033500, 0x01036100, "HP/Resurrection"],
[0x81033800, 0x81033800, 0x81033800, 0x81033800, 0x81033800, 0x81033800, 0x81033700, 0x81033800, 0x81033800, 0x81033800, 0x81033800, 0x01036200, "TP/Resurrection"],
[0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x81033A00, 0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x01036300, "PB/Increase"],
[0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x81033B00, 0x01034700, 0x01034800, 0x01034800, 0x01034800, 0x01034800, 0x01036400, "???? (UNIT)"],
[0x81033B00, 0x81033B00, 0x81033B00, 0x01034400, 0x01034400, 0x01034400, 0x01034700, 0x01034800, 0x01034800, 0x01034800, 0x01034800, 0x01036400, "???? (UNIT)"],
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
[0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000, "Mag"],
[0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, 0x02010000, "Varuna"],
[0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, "Mitra"],
@@ -841,10 +841,10 @@
[0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, 0x02250000, "Naraka"],
[0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, 0x02260000, "Madhu"],
[0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, 0x02270000, "Churel"],
[0x82000000, 0x82000000, 0x82000000, 0x02280000, 0x02280000, 0x02280000, 0x82000000, 0x02280000, 0x02280000, 0x02280000, 0x02280000, 0x02280000, "ROBOCHAO"],
[0x82000000, 0x82000000, 0x82000000, 0x02290000, 0x02290000, 0x02290000, 0x82000000, 0x02290000, 0x02290000, 0x02290000, 0x02290000, 0x02290000, "OPA-OPA"],
[0x82000000, 0x82000000, 0x82000000, 0x022A0000, 0x022A0000, 0x022A0000, 0x82000000, 0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, "PIAN"],
[0x82000000, 0x82000000, 0x82000000, 0x022B0000, 0x022B0000, 0x022B0000, 0x82000000, 0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, "CHAO"],
[0x02280000, 0x02280000, 0x02280000, 0x02280000, 0x02280000, 0x02280000, 0x82000000, 0x02280000, 0x02280000, 0x02280000, 0x02280000, 0x02280000, "ROBOCHAO"],
[0x02290000, 0x02290000, 0x02290000, 0x02290000, 0x02290000, 0x02290000, 0x82000000, 0x02290000, 0x02290000, 0x02290000, 0x02290000, 0x02290000, "OPA-OPA"],
[0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, 0x82000000, 0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, 0x022A0000, "PIAN"],
[0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, 0x82000000, 0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, 0x022B0000, "CHAO"],
[0x82000000, 0x82000000, 0x82000000, 0x022C0000, 0x022C0000, 0x022C0000, 0x82000000, 0x022C0000, 0x022C0000, 0x022C0000, 0x022C0000, 0x022C0000, "CHU CHU"],
[0x82000000, 0x82000000, 0x82000000, 0x022D0000, 0x022D0000, 0x022D0000, 0x82000000, 0x022D0000, 0x022D0000, 0x022D0000, 0x022D0000, 0x022D0000, "KAPU KAPU"],
[0x82000000, 0x82000000, 0x82000000, 0x022E0000, 0x022E0000, 0x022E0000, 0x82000000, 0x022E0000, 0x022E0000, 0x022E0000, 0x022E0000, 0x022E0000, "ANGEL'S WING"],
@@ -883,8 +883,9 @@
[0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x024F0000, "Cell of MAG 0505 (mag)"],
[0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x02500000, "Cell of MAG 0506 (mag)"],
[0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x02510000, "Cell of MAG 0507 (mag)"],
[0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x82000000, 0x02280000, 0x02420000, 0x02420000, 0x02420000, 0x02420000, 0x02520000, "???? (MAG)"],
[0x82000000, 0x82000000, 0x82000000, 0x02390000, 0x02390000, 0x02390000, 0x02280000, 0x02420000, 0x02420000, 0x02420000, 0x02420000, 0x02520000, "???? (MAG)"],
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
[0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, "Monomate"],
[0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, 0x03000100, "Dimate"],
[0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, 0x03000200, "Trimate"],
@@ -1027,7 +1028,7 @@
[0x830C0100, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830E0000, 0x03100200, 0x03100200, 0x03100200, 0x03100200, 0x03100200, "Photon Crystal"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830E0000, 0x83100000, 0x83100000, 0x83100000, 0x83100000, 0x03100300, "Secret Ticket"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830E0000, 0x83100000, 0x83100000, 0x83100000, 0x83100000, 0x03100400, "Photon Ticket"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030E0700, 0x030E0700, 0x030E0700, 0x830E0000, 0x03120000, 0x03120000, 0x03120000, 0x03120000, 0x03120000, "Weapons Bronze Badge"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030E0700, 0x030E0700, 0x030E0700, 0x03120000, 0x03120000, 0x03120000, 0x03120000, 0x03120000, 0x03120000, "Weapons Bronze Badge"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030E0800, 0x030E0800, 0x030E0800, 0x830E0000, 0x03120100, 0x03120100, 0x03120100, 0x03120100, 0x03120100, "Weapons Silver Badge"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030E0900, 0x030E0900, 0x030E0900, 0x830E0000, 0x03120200, 0x03120200, 0x03120200, 0x03120200, 0x03120200, "Weapons Gold Badge"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030E0A00, 0x030E0A00, 0x030E0A00, 0x830E0000, 0x03120300, 0x03120300, 0x03120300, 0x03120300, 0x03120300, "Weapons Crystal Badge"],
@@ -1090,5 +1091,6 @@
[0x830C0100, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830E0000, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x03190100, "Team Points 1000"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830E0000, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x03190200, "Team Points 5000"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x830E0000, 0x830D0500, 0x830D0500, 0x830D0500, 0x830D0500, 0x03190300, "Team Points 10000"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030F0000, 0x030F0000, 0x030F0000, 0x03120000, 0x83170400, 0x83170400, 0x83170400, 0x83170400, 0x031A0000, "???? (TOOL)"],
[0x830C0100, 0x830D0500, 0x830D0500, 0x030F0000, 0x030F0000, 0x030F0000, 0x03130000, 0x03180000, 0x03180000, 0x03180000, 0x03180000, 0x031A0000, "???? (TOOL)"],
// DC_NTE-- 11/2000--- DC_V1----- DC_V2----- PC_NTE---- PC_V2----- GC_NTE---- GC_V3----- GC_EP3_NTE GC_EP3---- XB_V3----- BB_V4----- NAME
]
+73
View File
@@ -0,0 +1,73 @@
#!/bin/sh
set -e
EXECUTABLE="$1"
if [ -z "$EXECUTABLE" ]; then
EXECUTABLE="./newserv"
fi
DIR=tests/item-parameter-tables
echo "... DC NTE"
$EXECUTABLE decode-item-parameter-table --dc-nte $DIR/dc-nte.expected.bin --decompressed $DIR/dc-nte.json --hex
$EXECUTABLE encode-item-parameter-table --dc-nte $DIR/dc-nte.json $DIR/dc-nte.encoded.bin --decompressed
bindiff $DIR/dc-nte.expected.bin $DIR/dc-nte.encoded.bin
echo "... DC 11/2000"
$EXECUTABLE decode-item-parameter-table --dc-11-2000 $DIR/dc-11-2000.expected.bin --decompressed $DIR/dc-11-2000.json --hex
$EXECUTABLE encode-item-parameter-table --dc-11-2000 $DIR/dc-11-2000.json $DIR/dc-11-2000.encoded.bin --decompressed
bindiff $DIR/dc-11-2000.expected.bin $DIR/dc-11-2000.encoded.bin
echo "... DC V1"
$EXECUTABLE decode-item-parameter-table --dc-v1 $DIR/dc-v1.expected.bin --decompressed $DIR/dc-v1.json --hex
$EXECUTABLE encode-item-parameter-table --dc-v1 $DIR/dc-v1.json $DIR/dc-v1.encoded.bin --decompressed
bindiff $DIR/dc-v1.expected.bin $DIR/dc-v1.encoded.bin
echo "... DC V2"
$EXECUTABLE decode-item-parameter-table --dc-v2 $DIR/dc-v2.expected.bin --decompressed $DIR/dc-v2.json --hex
$EXECUTABLE encode-item-parameter-table --dc-v2 $DIR/dc-v2.json $DIR/dc-v2.encoded.bin --decompressed
bindiff $DIR/dc-v2.expected.bin $DIR/dc-v2.encoded.bin
echo "... PC NTE"
$EXECUTABLE decode-item-parameter-table --pc-nte $DIR/pc-nte.expected.bin --decompressed $DIR/pc-nte.json --hex
$EXECUTABLE encode-item-parameter-table --pc-nte $DIR/pc-nte.json $DIR/pc-nte.encoded.bin --decompressed
bindiff $DIR/pc-nte.expected.bin $DIR/pc-nte.encoded.bin
echo "... PC V2"
$EXECUTABLE decode-item-parameter-table --pc-v2 $DIR/pc-v2.expected.bin --decompressed $DIR/pc-v2.json --hex
$EXECUTABLE encode-item-parameter-table --pc-v2 $DIR/pc-v2.json $DIR/pc-v2.encoded.bin --decompressed
bindiff $DIR/pc-v2.expected.bin $DIR/pc-v2.encoded.bin
echo "... GC NTE"
$EXECUTABLE decode-item-parameter-table --gc-nte $DIR/gc-nte.expected.bin --decompressed $DIR/gc-nte.json --hex
$EXECUTABLE encode-item-parameter-table --gc-nte $DIR/gc-nte.json $DIR/gc-nte.encoded.bin --decompressed
bindiff $DIR/gc-nte.expected.bin $DIR/gc-nte.encoded.bin
echo "... GC V3"
$EXECUTABLE decode-item-parameter-table --gc-v3 $DIR/gc-v3.expected.bin --decompressed $DIR/gc-v3.json --hex
$EXECUTABLE encode-item-parameter-table --gc-v3 $DIR/gc-v3.json $DIR/gc-v3.encoded.bin --decompressed
bindiff $DIR/gc-v3.expected.bin $DIR/gc-v3.encoded.bin
echo "... GC Ep3 NTE"
$EXECUTABLE decode-item-parameter-table --gc-ep3-nte $DIR/gc-ep3-nte.expected.bin --decompressed $DIR/gc-ep3-nte.json --hex
$EXECUTABLE encode-item-parameter-table --gc-ep3-nte $DIR/gc-ep3-nte.json $DIR/gc-ep3-nte.encoded.bin --decompressed
bindiff $DIR/gc-ep3-nte.expected.bin $DIR/gc-ep3-nte.encoded.bin
echo "... GC Ep3"
$EXECUTABLE decode-item-parameter-table --gc-ep3 $DIR/gc-ep3.expected.bin --decompressed $DIR/gc-ep3.json --hex
$EXECUTABLE encode-item-parameter-table --gc-ep3 $DIR/gc-ep3.json $DIR/gc-ep3.encoded.bin --decompressed
bindiff $DIR/gc-ep3.expected.bin $DIR/gc-ep3.encoded.bin
echo "... XB"
$EXECUTABLE decode-item-parameter-table --xb-v3 $DIR/xb-v3.expected.bin --decompressed $DIR/xb-v3.json --hex
$EXECUTABLE encode-item-parameter-table --xb-v3 $DIR/xb-v3.json $DIR/xb-v3.encoded.bin --decompressed
bindiff $DIR/xb-v3.expected.bin $DIR/xb-v3.encoded.bin
echo "... BB"
$EXECUTABLE decode-item-parameter-table --bb-v4 $DIR/bb-v4.expected.bin --decompressed $DIR/bb-v4.json --hex
$EXECUTABLE encode-item-parameter-table --bb-v4 $DIR/bb-v4.json $DIR/bb-v4.encoded.bin --decompressed
bindiff $DIR/bb-v4.expected.bin $DIR/bb-v4.encoded.bin
echo "... clean up"
rm -f tests/item-parameter-tables/*.encoded.bin tests/item-parameter-tables/*.json
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.