use phosg namespace

This commit is contained in:
Martin Michelsen
2024-07-28 11:54:41 -07:00
parent 5523388ad4
commit 1bfbf09891
116 changed files with 2969 additions and 3088 deletions
+8 -10
View File
@@ -23,7 +23,7 @@ AFSArchive::AFSArchive(shared_ptr<const string> data)
le_uint32_t size;
} __packed_ws__(FileEntry, 8);
StringReader r(*this->data);
phosg::StringReader r(*this->data);
const auto& header = r.get<FileHeader>();
if (header.magic != 0x41465300) { // 'AFS\0'
throw runtime_error("file is not an AFS archive");
@@ -52,29 +52,27 @@ string AFSArchive::get_copy(size_t index) const {
return string(reinterpret_cast<const char*>(ret.first), ret.second);
}
StringReader AFSArchive::get_reader(size_t index) const {
phosg::StringReader AFSArchive::get_reader(size_t index) const {
auto ret = this->get(index);
return StringReader(ret.first, ret.second);
return phosg::StringReader(ret.first, ret.second);
}
string AFSArchive::generate(const vector<string>& files, bool big_endian) {
return big_endian ? AFSArchive::generate_t<true>(files) : AFSArchive::generate_t<false>(files);
}
template <bool IsBigEndian>
template <bool BE>
string AFSArchive::generate_t(const vector<string>& files) {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
StringWriter w;
phosg::StringWriter w;
w.put_u32b(0x41465300); // 'AFS\0'
w.put<U32T>(files.size());
w.put<U32T<BE>>(files.size());
// It seems entries are aligned to 0x800-byte boundaries, and the file's
// header is always 0x80000 (!) bytes, most of which is unused
uint32_t data_offset = 0x80000;
for (const auto& file : files) {
w.put<U32T>(data_offset);
w.put<U32T>(file.size());
w.put<U32T<BE>>(data_offset);
w.put<U32T<BE>>(file.size());
data_offset = (data_offset + file.size() + 0x7FF) & (~0x7FF);
}
+4 -2
View File
@@ -8,6 +8,8 @@
#include <string>
#include <unordered_map>
#include "Types.hh"
class AFSArchive {
public:
AFSArchive(std::shared_ptr<const std::string> data);
@@ -23,12 +25,12 @@ public:
std::pair<const void*, size_t> get(size_t index) const;
std::string get_copy(size_t index) const;
StringReader get_reader(size_t index) const;
phosg::StringReader get_reader(size_t index) const;
static std::string generate(const std::vector<std::string>& files, bool big_endian);
private:
template <bool IsBigEndian>
template <bool BE>
static std::string generate_t(const std::vector<std::string>& files);
std::shared_ptr<const std::string> data;
+48 -48
View File
@@ -11,7 +11,7 @@
using namespace std;
shared_ptr<DCNTELicense> DCNTELicense::from_json(const JSON& json) {
shared_ptr<DCNTELicense> DCNTELicense::from_json(const phosg::JSON& json) {
auto ret = make_shared<DCNTELicense>();
ret->serial_number = json.get_string("SerialNumber");
ret->access_key = json.get_string("AccessKey");
@@ -30,14 +30,14 @@ shared_ptr<DCNTELicense> DCNTELicense::from_json(const JSON& json) {
return ret;
}
JSON DCNTELicense::json() const {
return JSON::dict({
phosg::JSON DCNTELicense::json() const {
return phosg::JSON::dict({
{"SerialNumber", this->serial_number},
{"AccessKey", this->access_key},
});
}
shared_ptr<V1V2License> V1V2License::from_json(const JSON& json) {
shared_ptr<V1V2License> V1V2License::from_json(const phosg::JSON& json) {
auto ret = make_shared<V1V2License>();
ret->serial_number = json.get_int("SerialNumber");
ret->access_key = json.get_string("AccessKey");
@@ -50,14 +50,14 @@ shared_ptr<V1V2License> V1V2License::from_json(const JSON& json) {
return ret;
}
JSON V1V2License::json() const {
return JSON::dict({
phosg::JSON V1V2License::json() const {
return phosg::JSON::dict({
{"SerialNumber", this->serial_number},
{"AccessKey", this->access_key},
});
}
shared_ptr<GCLicense> GCLicense::from_json(const JSON& json) {
shared_ptr<GCLicense> GCLicense::from_json(const phosg::JSON& json) {
auto ret = make_shared<GCLicense>();
ret->serial_number = json.get_int("SerialNumber");
ret->access_key = json.get_string("AccessKey");
@@ -74,15 +74,15 @@ shared_ptr<GCLicense> GCLicense::from_json(const JSON& json) {
return ret;
}
JSON GCLicense::json() const {
return JSON::dict({
phosg::JSON GCLicense::json() const {
return phosg::JSON::dict({
{"SerialNumber", this->serial_number},
{"AccessKey", this->access_key},
{"Password", this->password},
});
}
shared_ptr<XBLicense> XBLicense::from_json(const JSON& json) {
shared_ptr<XBLicense> XBLicense::from_json(const phosg::JSON& json) {
auto ret = make_shared<XBLicense>();
ret->gamertag = json.get_string("GamerTag");
ret->user_id = json.get_int("UserID");
@@ -99,15 +99,15 @@ shared_ptr<XBLicense> XBLicense::from_json(const JSON& json) {
return ret;
}
JSON XBLicense::json() const {
return JSON::dict({
phosg::JSON XBLicense::json() const {
return phosg::JSON::dict({
{"GamerTag", this->gamertag},
{"UserID", this->user_id},
{"AccountID", this->account_id},
});
}
shared_ptr<BBLicense> BBLicense::from_json(const JSON& json) {
shared_ptr<BBLicense> BBLicense::from_json(const phosg::JSON& json) {
auto ret = make_shared<BBLicense>();
ret->username = json.get_string("UserName");
ret->password = json.get_string("Password");
@@ -126,14 +126,14 @@ shared_ptr<BBLicense> BBLicense::from_json(const JSON& json) {
return ret;
}
JSON BBLicense::json() const {
return JSON::dict({
phosg::JSON BBLicense::json() const {
return phosg::JSON::dict({
{"UserName", this->username},
{"Password", this->password},
});
}
Account::Account(const JSON& json)
Account::Account(const phosg::JSON& json)
: account_id(0),
flags(0),
ban_end_time(0),
@@ -237,38 +237,38 @@ Account::Account(const JSON& json)
}
}
JSON Account::json() const {
JSON dc_nte_json = JSON::list();
phosg::JSON Account::json() const {
phosg::JSON dc_nte_json = phosg::JSON::list();
for (const auto& it : this->dc_nte_licenses) {
dc_nte_json.emplace_back(it.second->json());
}
JSON dc_json = JSON::list();
phosg::JSON dc_json = phosg::JSON::list();
for (const auto& it : this->dc_licenses) {
dc_json.emplace_back(it.second->json());
}
JSON pc_json = JSON::list();
phosg::JSON pc_json = phosg::JSON::list();
for (const auto& it : this->pc_licenses) {
pc_json.emplace_back(it.second->json());
}
JSON gc_json = JSON::list();
phosg::JSON gc_json = phosg::JSON::list();
for (const auto& it : this->gc_licenses) {
gc_json.emplace_back(it.second->json());
}
JSON xb_json = JSON::list();
phosg::JSON xb_json = phosg::JSON::list();
for (const auto& it : this->xb_licenses) {
xb_json.emplace_back(it.second->json());
}
JSON bb_json = JSON::list();
phosg::JSON bb_json = phosg::JSON::list();
for (const auto& it : this->bb_licenses) {
bb_json.emplace_back(it.second->json());
}
JSON auto_patches_json = JSON::list();
phosg::JSON auto_patches_json = phosg::JSON::list();
for (const auto& it : this->auto_patches_enabled) {
auto_patches_json.emplace_back(it);
}
return JSON::dict({
return phosg::JSON::dict({
{"FormatVersion", 1},
{"AccountID", this->account_id},
{"DCNTELicenses", std::move(dc_nte_json)},
@@ -333,14 +333,14 @@ void Account::print(FILE* stream) const {
}
if (flags_str.empty()) {
flags_str = "none";
} else if (ends_with(flags_str, ",")) {
} else if (phosg::ends_with(flags_str, ",")) {
flags_str.pop_back();
}
fprintf(stream, " Flags: %08" PRIX32 " (%s)\n", this->flags, flags_str.c_str());
}
if (this->ban_end_time) {
string time_str = format_time(this->ban_end_time);
string time_str = phosg::format_time(this->ban_end_time);
fprintf(stream, " Banned until: %" PRIu64 " (%s)\n", this->ban_end_time, time_str.c_str());
}
if (this->ep3_current_meseta || this->ep3_total_meseta_earned) {
@@ -388,14 +388,14 @@ void Account::print(FILE* stream) const {
void Account::save() const {
if (!this->is_temporary) {
auto json = this->json();
string json_data = json.serialize(JSON::SerializeOption::FORMAT | JSON::SerializeOption::HEX_INTEGERS);
string filename = string_printf("system/licenses/%010" PRIu32 ".json", this->account_id);
save_file(filename, json_data);
string json_data = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::HEX_INTEGERS);
string filename = phosg::string_printf("system/licenses/%010" PRIu32 ".json", this->account_id);
phosg::save_file(filename, json_data);
}
}
void Account::delete_file() const {
string filename = string_printf("system/licenses/%010" PRIu32 ".json", this->account_id);
string filename = phosg::string_printf("system/licenses/%010" PRIu32 ".json", this->account_id);
remove(filename.c_str());
}
@@ -420,7 +420,7 @@ shared_ptr<Login> AccountIndex::from_dc_nte_credentials_locked(const string& ser
if (login->dc_nte_license->access_key != access_key) {
throw incorrect_access_key();
}
if (login->account->ban_end_time && (login->account->ban_end_time >= now())) {
if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) {
throw invalid_argument("user is banned");
}
return login;
@@ -448,7 +448,7 @@ shared_ptr<Login> AccountIndex::from_dc_nte_credentials(
auto login = make_shared<Login>();
login->account_was_created = true;
login->account = make_shared<Account>();
login->account->account_id = fnv1a32(serial_number) & 0x7FFFFFFF;
login->account->account_id = phosg::fnv1a32(serial_number) & 0x7FFFFFFF;
auto lic = make_shared<DCNTELicense>();
lic->serial_number = serial_number;
lic->access_key = access_key;
@@ -470,7 +470,7 @@ shared_ptr<Login> AccountIndex::from_dc_credentials_locked(
if (!is_shared && (login->dc_license->access_key != access_key)) {
throw incorrect_access_key();
}
if (login->account->ban_end_time && (login->account->ban_end_time >= now())) {
if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) {
throw invalid_argument("user is banned");
}
if (is_shared) {
@@ -519,7 +519,7 @@ shared_ptr<Login> AccountIndex::from_pc_nte_credentials(uint32_t guild_card_numb
throw missing_account();
}
if (guild_card_number == 0xFFFFFFFF) {
guild_card_number = random_object<uint32_t>() & 0x7FFFFFFF;
guild_card_number = phosg::random_object<uint32_t>() & 0x7FFFFFFF;
}
auto login = make_shared<Login>();
login->account_was_created = true;
@@ -543,7 +543,7 @@ shared_ptr<Login> AccountIndex::from_pc_credentials_locked(
if (!is_shared && (login->pc_license->access_key != access_key)) {
throw incorrect_access_key();
}
if (login->account->ban_end_time && (login->account->ban_end_time >= now())) {
if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) {
throw invalid_argument("user is banned");
}
if (is_shared) {
@@ -599,7 +599,7 @@ shared_ptr<Login> AccountIndex::from_gc_credentials_locked(
if (password && (login->gc_license->password != *password)) {
throw incorrect_password();
}
if (login->account->ban_end_time && (login->account->ban_end_time >= now())) {
if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) {
throw invalid_argument("user is banned");
}
if (is_shared) {
@@ -652,7 +652,7 @@ shared_ptr<Login> AccountIndex::from_xb_credentials_locked(const string& gamerta
(login->xb_license->account_id && (login->xb_license->account_id != account_id))) {
throw incorrect_access_key();
}
if (login->account->ban_end_time && (login->account->ban_end_time >= now())) {
if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) {
throw invalid_argument("user is banned");
}
return login;
@@ -680,7 +680,7 @@ shared_ptr<Login> AccountIndex::from_xb_credentials(
auto login = make_shared<Login>();
login->account_was_created = true;
login->account = make_shared<Account>();
login->account->account_id = fnv1a32(gamertag) & 0x7FFFFFFF;
login->account->account_id = phosg::fnv1a32(gamertag) & 0x7FFFFFFF;
auto lic = make_shared<XBLicense>();
lic->gamertag = gamertag;
lic->user_id = user_id;
@@ -701,7 +701,7 @@ shared_ptr<Login> AccountIndex::from_bb_credentials_locked(const string& usernam
if (password && (login->bb_license->password != *password)) {
throw incorrect_password();
}
if (login->account->ban_end_time && (login->account->ban_end_time >= now())) {
if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) {
throw invalid_argument("user is banned");
}
return login;
@@ -728,7 +728,7 @@ shared_ptr<Login> AccountIndex::from_bb_credentials(const string& username, cons
auto login = make_shared<Login>();
login->account_was_created = true;
login->account = make_shared<Account>();
login->account->account_id = fnv1a32(username) & 0x7FFFFFFF;
login->account->account_id = phosg::fnv1a32(username) & 0x7FFFFFFF;
auto lic = make_shared<BBLicense>();
lic->username = username;
lic->password = *password;
@@ -976,24 +976,24 @@ shared_ptr<Account> AccountIndex::create_temporary_account_for_shared_account(
shared_ptr<const Account> src_a, const string& variation_data) const {
auto ret = make_shared<Account>(*src_a);
ret->is_temporary = true;
ret->account_id = fnv1a32(&src_a->account_id, sizeof(src_a->account_id));
ret->account_id = fnv1a32(variation_data, ret->account_id);
ret->account_id = phosg::fnv1a32(&src_a->account_id, sizeof(src_a->account_id));
ret->account_id = phosg::fnv1a32(variation_data, ret->account_id);
return ret;
}
AccountIndex::AccountIndex(bool force_all_temporary)
: force_all_temporary(force_all_temporary) {
if (!this->force_all_temporary) {
if (!isdir("system/licenses")) {
if (!phosg::isdir("system/licenses")) {
mkdir("system/licenses", 0755);
} else {
for (const auto& item : list_directory("system/licenses")) {
if (ends_with(item, ".json")) {
for (const auto& item : phosg::list_directory("system/licenses")) {
if (phosg::ends_with(item, ".json")) {
try {
JSON json = JSON::parse(load_file("system/licenses/" + item));
phosg::JSON json = phosg::JSON::parse(phosg::load_file("system/licenses/" + item));
this->add(make_shared<Account>(json));
} catch (const exception& e) {
log_error("Failed to index account %s", item.c_str());
phosg::log_error("Failed to index account %s", item.c_str());
throw;
}
}
+12 -12
View File
@@ -16,16 +16,16 @@ struct DCNTELicense {
std::string serial_number;
std::string access_key;
static std::shared_ptr<DCNTELicense> from_json(const JSON& json);
JSON json() const;
static std::shared_ptr<DCNTELicense> from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct V1V2License {
uint32_t serial_number = 0;
std::string access_key;
static std::shared_ptr<V1V2License> from_json(const JSON& json);
JSON json() const;
static std::shared_ptr<V1V2License> from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct GCLicense {
@@ -33,8 +33,8 @@ struct GCLicense {
std::string access_key;
std::string password;
static std::shared_ptr<GCLicense> from_json(const JSON& json);
JSON json() const;
static std::shared_ptr<GCLicense> from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct XBLicense {
@@ -42,16 +42,16 @@ struct XBLicense {
uint64_t user_id = 0;
uint64_t account_id = 0;
static std::shared_ptr<XBLicense> from_json(const JSON& json);
JSON json() const;
static std::shared_ptr<XBLicense> from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct BBLicense {
std::string username;
std::string password;
static std::shared_ptr<BBLicense> from_json(const JSON& json);
JSON json() const;
static std::shared_ptr<BBLicense> from_json(const phosg::JSON& json);
phosg::JSON json() const;
};
struct Account {
@@ -101,10 +101,10 @@ struct Account {
std::unordered_map<std::string, std::shared_ptr<BBLicense>> bb_licenses;
Account() = default;
explicit Account(const JSON& json);
explicit Account(const phosg::JSON& json);
virtual ~Account() = default;
JSON json() const;
phosg::JSON json() const;
virtual void save() const;
virtual void delete_file() const;
+13 -13
View File
@@ -108,11 +108,11 @@ public:
: log("[addr-trans] "),
directory(directory),
enable_ppc(false) {
while (ends_with(this->directory, "/")) {
while (phosg::ends_with(this->directory, "/")) {
this->directory.pop_back();
}
for (const auto& filename : list_directory(this->directory)) {
if (ends_with(filename, ".dol")) {
for (const auto& filename : phosg::list_directory(this->directory)) {
if (phosg::ends_with(filename, ".dol")) {
string name = filename.substr(0, filename.size() - 4);
string path = directory + "/" + filename;
ResourceDASM::DOLFile dol(path.c_str());
@@ -121,7 +121,7 @@ public:
this->mems.emplace(name, mem);
this->enable_ppc = true;
this->log.info("Loaded %s", name.c_str());
} else if (ends_with(filename, ".xbe")) {
} else if (phosg::ends_with(filename, ".xbe")) {
string name = filename.substr(0, filename.size() - 4);
string path = directory + "/" + filename;
ResourceDASM::XBEFile xbe(path.c_str());
@@ -129,10 +129,10 @@ public:
xbe.load_into(mem);
this->mems.emplace(name, mem);
this->log.info("Loaded %s", name.c_str());
} else if (ends_with(filename, ".bin")) {
} else if (phosg::ends_with(filename, ".bin")) {
string name = filename.substr(0, filename.size() - 4);
string path = directory + "/" + filename;
string data = load_file(path);
string data = phosg::load_file(path);
auto mem = make_shared<ResourceDASM::MemoryContext>();
mem->allocate_at(0x8C010000, data.size());
mem->memcpy(0x8C010000, data.data(), data.size());
@@ -160,7 +160,7 @@ public:
uint32_t r2 = 0;
uint32_t r13 = 0;
for (const auto& block : it.second->allocated_blocks()) {
StringReader r = it.second->reader(block.first, block.second);
phosg::StringReader r = it.second->reader(block.first, block.second);
while (!r.eof() && r.where()) {
uint32_t opcode = r.get_u32b();
if ((opcode & 0xFFFF0000) == 0x3DA00000) {
@@ -243,13 +243,13 @@ public:
size_t num_matches = 0;
size_t last_match_address = 0;
size_t match_length = match_bytes_before + match_bytes_after + 4;
StringReader src_r = this->src_mem->reader(src_section.first + src_offset - match_bytes_before, match_length);
phosg::StringReader src_r = this->src_mem->reader(src_section.first + src_offset - match_bytes_before, match_length);
for (const auto& dest_section : dest_mem->allocated_blocks()) {
for (size_t dest_match_offset = 0;
dest_match_offset + match_length < dest_section.second;
dest_match_offset += (is_ppc ? 4 : 1)) {
src_r.go(0);
StringReader dest_r = dest_mem->reader(dest_section.first + dest_match_offset, match_length);
phosg::StringReader dest_r = dest_mem->reader(dest_section.first + dest_match_offset, match_length);
size_t z;
if (is_ppc) {
for (z = 0; z < match_length; z += 4) {
@@ -429,11 +429,11 @@ public:
}
void handle_command(const string& command) {
auto tokens = split(command, ' ');
auto tokens = phosg::split(command, ' ');
if (tokens.empty()) {
throw runtime_error("no command given");
}
strip_trailing_whitespace(tokens[tokens.size() - 1]);
phosg::strip_trailing_whitespace(tokens[tokens.size() - 1]);
if (tokens[0] == "use") {
this->set_source_file(tokens.at(1));
@@ -457,7 +457,7 @@ public:
}
fflush(stdout);
string command = fgets(stdin);
string command = phosg::fgets(stdin);
try {
this->handle_command(command);
} catch (const exception& e) {
@@ -468,7 +468,7 @@ public:
}
private:
PrefixedLogger log;
phosg::PrefixedLogger log;
string directory;
unordered_map<string, shared_ptr<const ResourceDASM::MemoryContext>> mems;
string src_filename;
+14 -17
View File
@@ -5,15 +5,14 @@
#include <stdexcept>
#include "Text.hh"
#include "Types.hh"
using namespace std;
template <bool IsBigEndian>
template <bool BE>
struct BMLHeaderT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
parray<uint8_t, 0x04> unknown_a1;
U32T num_entries;
U32T<BE> num_entries;
parray<uint8_t, 0x38> unknown_a2;
} __packed__;
@@ -22,16 +21,14 @@ using BMLHeaderBE = BMLHeaderT<true>;
check_struct_size(BMLHeader, 0x40);
check_struct_size(BMLHeaderBE, 0x40);
template <bool IsBigEndian>
template <bool BE>
struct BMLHeaderEntryT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
pstring<TextEncoding::ASCII, 0x20> filename;
U32T compressed_size;
U32T<BE> compressed_size;
parray<uint8_t, 0x04> unknown_a1;
U32T decompressed_size;
U32T compressed_gvm_size;
U32T decompressed_gvm_size;
U32T<BE> decompressed_size;
U32T<BE> compressed_gvm_size;
U32T<BE> decompressed_gvm_size;
parray<uint8_t, 0x0C> unknown_a2;
} __packed__;
@@ -40,15 +37,15 @@ using BMLHeaderEntryBE = BMLHeaderEntryT<true>;
check_struct_size(BMLHeaderEntry, 0x40);
check_struct_size(BMLHeaderEntryBE, 0x40);
template <bool IsBigEndian>
template <bool BE>
void BMLArchive::load_t() {
StringReader r(*this->data);
phosg::StringReader r(*this->data);
const auto& header = r.get<BMLHeaderT<IsBigEndian>>();
const auto& header = r.get<BMLHeaderT<BE>>();
size_t offset = 0x800;
while (this->entries.size() < header.num_entries) {
const auto& entry = r.get<BMLHeaderEntryT<IsBigEndian>>();
const auto& entry = r.get<BMLHeaderEntryT<BE>>();
if (offset + entry.compressed_size > this->data->size()) {
throw runtime_error("BML data entry extends beyond end of data");
@@ -106,10 +103,10 @@ string BMLArchive::get_copy(const string& name) const {
}
}
StringReader BMLArchive::get_reader(const string& name) const {
phosg::StringReader BMLArchive::get_reader(const string& name) const {
try {
const auto& entry = this->entries.at(name);
return StringReader(this->data->data() + entry.offset, entry.size);
return phosg::StringReader(this->data->data() + entry.offset, entry.size);
} catch (const out_of_range&) {
throw out_of_range("BML does not contain file: " + name);
}
+2 -2
View File
@@ -24,10 +24,10 @@ public:
std::pair<const void*, size_t> get(const std::string& name) const;
std::pair<const void*, size_t> get_gvm(const std::string& name) const;
std::string get_copy(const std::string& name) const;
StringReader get_reader(const std::string& name) const;
phosg::StringReader get_reader(const std::string& name) const;
private:
template <bool IsBigEndian>
template <bool BE>
void load_t();
std::shared_ptr<const std::string> data;
+1 -1
View File
@@ -54,7 +54,7 @@ BattleParamsIndex::BattleParamsIndex(
for (uint8_t episode = 0; episode < 3; episode++) {
auto& file = this->files[is_solo][episode];
if (file.data->size() < sizeof(Table)) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"battle params table size is incorrect (expected %zX bytes, have %zX bytes; is_solo=%hhu, episode=%hhu)",
sizeof(Table), file.data->size(), is_solo, episode));
}
+7 -8
View File
@@ -38,7 +38,7 @@ CatSession::CatSession(
const struct sockaddr_storage& remote,
Version version,
shared_ptr<const PSOBBEncryption::KeyFile> bb_key_file)
: log(string_printf("[CatSession:%s] ", name_for_enum(version)), proxy_server_log.min_level),
: log(phosg::string_printf("[CatSession:%s] ", phosg::name_for_enum(version)), proxy_server_log.min_level),
base(base),
read_event(event_new(this->base.get(), 0, EV_READ | EV_PERSIST, CatSession::dispatch_read_stdin, this), event_free),
channel(version, 1, CatSession::dispatch_on_channel_input, CatSession::dispatch_on_channel_error, this, "CatSession"),
@@ -48,19 +48,19 @@ CatSession::CatSession(
throw runtime_error("remote is not AF_INET");
}
string netloc_str = render_sockaddr_storage(remote);
string netloc_str = phosg::render_sockaddr_storage(remote);
this->log.info("Connecting to %s", netloc_str.c_str());
struct bufferevent* bev = bufferevent_socket_new(
this->base.get(), -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
if (!bev) {
throw runtime_error(string_printf("failed to open socket (%d)", EVUTIL_SOCKET_ERROR()));
throw runtime_error(phosg::string_printf("failed to open socket (%d)", EVUTIL_SOCKET_ERROR()));
}
this->channel.set_bufferevent(bev, 0);
if (bufferevent_socket_connect(this->channel.bev.get(),
reinterpret_cast<const sockaddr*>(&remote), sizeof(struct sockaddr_in)) != 0) {
throw runtime_error(string_printf("failed to connect (%d)", EVUTIL_SOCKET_ERROR()));
throw runtime_error(phosg::string_printf("failed to connect (%d)", EVUTIL_SOCKET_ERROR()));
}
event_add(this->read_event.get(), nullptr);
@@ -68,7 +68,7 @@ CatSession::CatSession(
}
void CatSession::execute_command(const std::string& command) {
string full_cmd = parse_data_string(command, nullptr, ParseDataFlags::ALLOW_FILES);
string full_cmd = phosg::parse_data_string(command, nullptr, phosg::ParseDataFlags::ALLOW_FILES);
send_command_with_header(this->channel, full_cmd.data(), full_cmd.size());
}
@@ -109,9 +109,8 @@ void CatSession::on_channel_input(
// TODO: Use the iovec form of print_data here instead of
// prepend_command_header (which copies the string)
string full_cmd = prepend_command_header(
this->channel.version, this->channel.crypt_in.get(), command, flag, data);
print_data(stdout, full_cmd, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
string full_cmd = prepend_command_header(this->channel.version, this->channel.crypt_in.get(), command, flag, data);
phosg::print_data(stdout, full_cmd, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
}
void CatSession::dispatch_on_channel_error(Channel& ch, short events) {
+2 -2
View File
@@ -29,10 +29,10 @@ public:
virtual ~CatSession() = default;
protected:
PrefixedLogger log;
phosg::PrefixedLogger log;
std::shared_ptr<struct event_base> base;
std::unique_ptr<struct event, void (*)(struct event*)> read_event;
Poll poll;
phosg::Poll poll;
Channel channel;
std::shared_ptr<const PSOBBEncryption::KeyFile> bb_key_file;
+19 -19
View File
@@ -29,8 +29,8 @@ Channel::Channel(
on_error_t on_error,
void* context_obj,
const string& name,
TerminalFormat terminal_send_color,
TerminalFormat terminal_recv_color)
phosg::TerminalFormat terminal_send_color,
phosg::TerminalFormat terminal_recv_color)
: bev(nullptr, flush_and_free_bufferevent),
virtual_network_id(0),
version(version),
@@ -52,8 +52,8 @@ Channel::Channel(
on_error_t on_error,
void* context_obj,
const string& name,
TerminalFormat terminal_send_color,
TerminalFormat terminal_recv_color)
phosg::TerminalFormat terminal_send_color,
phosg::TerminalFormat terminal_recv_color)
: bev(nullptr, flush_and_free_bufferevent),
version(version),
language(language),
@@ -98,7 +98,7 @@ void Channel::set_bufferevent(struct bufferevent* bev, uint64_t virtual_network_
memset(&this->local_addr, 0, sizeof(this->local_addr));
memset(&this->remote_addr, 0, sizeof(this->remote_addr));
} else {
get_socket_addresses(fd, &this->local_addr, &this->remote_addr);
phosg::get_socket_addresses(fd, &this->local_addr, &this->remote_addr);
}
bufferevent_setcb(this->bev.get(), &Channel::dispatch_on_input, nullptr, &Channel::dispatch_on_error, this);
@@ -206,9 +206,9 @@ Channel::Message Channel::recv() {
}
command_data.resize(command_logical_size - header_size);
if (command_data_log.should_log(LogLevel::INFO) && (this->terminal_recv_color != TerminalFormat::END)) {
if (use_terminal_colors && this->terminal_recv_color != TerminalFormat::NORMAL) {
print_color_escape(stderr, this->terminal_recv_color, TerminalFormat::BOLD, TerminalFormat::END);
if (command_data_log.should_log(phosg::LogLevel::INFO) && (this->terminal_recv_color != phosg::TerminalFormat::END)) {
if (use_terminal_colors && this->terminal_recv_color != phosg::TerminalFormat::NORMAL) {
print_color_escape(stderr, this->terminal_recv_color, phosg::TerminalFormat::BOLD, phosg::TerminalFormat::END);
}
if (version == Version::BB_V4) {
@@ -221,7 +221,7 @@ Channel::Message Channel::recv() {
command_data_log.info(
"Received from %s (version=%s command=%02hX flag=%02" PRIX32 ")",
this->name.c_str(),
name_for_enum(this->version),
phosg::name_for_enum(this->version),
header.command(this->version),
header.flag(this->version));
}
@@ -229,10 +229,10 @@ Channel::Message Channel::recv() {
vector<struct iovec> iovs;
iovs.emplace_back(iovec{.iov_base = header_data.data(), .iov_len = header_data.size()});
iovs.emplace_back(iovec{.iov_base = command_data.data(), .iov_len = command_data.size()});
print_data(stderr, iovs, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stderr, iovs, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
if (use_terminal_colors && this->terminal_recv_color != TerminalFormat::NORMAL) {
print_color_escape(stderr, TerminalFormat::NORMAL, TerminalFormat::END);
if (use_terminal_colors && this->terminal_recv_color != phosg::TerminalFormat::NORMAL) {
phosg::print_color_escape(stderr, phosg::TerminalFormat::NORMAL, phosg::TerminalFormat::END);
}
}
@@ -342,20 +342,20 @@ void Channel::send(uint16_t cmd, uint32_t flag, const std::vector<std::pair<cons
}
send_data.resize(send_data_size, '\0');
if (!silent && (command_data_log.should_log(LogLevel::INFO)) && (this->terminal_send_color != TerminalFormat::END)) {
if (use_terminal_colors && this->terminal_send_color != TerminalFormat::NORMAL) {
print_color_escape(stderr, TerminalFormat::FG_YELLOW, TerminalFormat::BOLD, TerminalFormat::END);
if (!silent && (command_data_log.should_log(phosg::LogLevel::INFO)) && (this->terminal_send_color != phosg::TerminalFormat::END)) {
if (use_terminal_colors && this->terminal_send_color != phosg::TerminalFormat::NORMAL) {
print_color_escape(stderr, phosg::TerminalFormat::FG_YELLOW, phosg::TerminalFormat::BOLD, phosg::TerminalFormat::END);
}
if (version == Version::BB_V4) {
command_data_log.info("Sending to %s (version=BB command=%04hX flag=%08" PRIX32 ")",
this->name.c_str(), cmd, flag);
} else {
command_data_log.info("Sending to %s (version=%s command=%02hX flag=%02" PRIX32 ")",
this->name.c_str(), name_for_enum(version), cmd, flag);
this->name.c_str(), phosg::name_for_enum(version), cmd, flag);
}
print_data(stderr, send_data.data(), logical_size, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
if (use_terminal_colors && this->terminal_send_color != TerminalFormat::NORMAL) {
print_color_escape(stderr, TerminalFormat::NORMAL, TerminalFormat::END);
phosg::print_data(stderr, send_data.data(), logical_size, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
if (use_terminal_colors && this->terminal_send_color != phosg::TerminalFormat::NORMAL) {
print_color_escape(stderr, phosg::TerminalFormat::NORMAL, phosg::TerminalFormat::END);
}
}
+6 -6
View File
@@ -21,8 +21,8 @@ struct Channel {
std::shared_ptr<PSOEncryption> crypt_out;
std::string name;
TerminalFormat terminal_send_color;
TerminalFormat terminal_recv_color;
phosg::TerminalFormat terminal_send_color;
phosg::TerminalFormat terminal_recv_color;
struct Message {
uint16_t command;
@@ -45,8 +45,8 @@ struct Channel {
on_error_t on_error,
void* context_obj,
const std::string& name,
TerminalFormat terminal_send_color = TerminalFormat::END,
TerminalFormat terminal_recv_color = TerminalFormat::END);
phosg::TerminalFormat terminal_send_color = phosg::TerminalFormat::END,
phosg::TerminalFormat terminal_recv_color = phosg::TerminalFormat::END);
// Creates a connected channel
Channel(
struct bufferevent* bev,
@@ -57,8 +57,8 @@ struct Channel {
on_error_t on_error,
void* context_obj,
const std::string& name = "",
TerminalFormat terminal_send_color = TerminalFormat::END,
TerminalFormat terminal_recv_color = TerminalFormat::END);
phosg::TerminalFormat terminal_send_color = phosg::TerminalFormat::END,
phosg::TerminalFormat terminal_recv_color = phosg::TerminalFormat::END);
Channel(const Channel& other) = delete;
Channel(Channel&& other) = delete;
Channel& operator=(const Channel& other) = delete;
+48 -48
View File
@@ -103,7 +103,7 @@ static void check_is_leader(shared_ptr<Lobby> l, shared_ptr<Client> c) {
static void server_command_server_info(shared_ptr<Client> c, const std::string&) {
auto s = c->require_server_state();
string uptime_str = format_duration(now() - s->creation_time);
string uptime_str = phosg::format_duration(phosg::now() - s->creation_time);
send_text_message_printf(c,
"Uptime: $C6%s$C7\nLobbies: $C6%zu$C7\nClients: $C6%zu$C7(g) $C6%zu$C7(p)",
uptime_str.c_str(),
@@ -123,11 +123,11 @@ static void server_command_lobby_info(shared_ptr<Client> c, const std::string&)
if (l->is_game()) {
if (!l->is_ep3()) {
if (l->max_level == 0xFFFFFFFF) {
lines.emplace_back(string_printf("$C6%08X$C7 L$C6%d+$C7", l->lobby_id, l->min_level + 1));
lines.emplace_back(phosg::string_printf("$C6%08X$C7 L$C6%d+$C7", l->lobby_id, l->min_level + 1));
} else {
lines.emplace_back(string_printf("$C6%08X$C7 L$C6%d-%d$C7", l->lobby_id, l->min_level + 1, l->max_level + 1));
lines.emplace_back(phosg::string_printf("$C6%08X$C7 L$C6%d-%d$C7", l->lobby_id, l->min_level + 1, l->max_level + 1));
}
lines.emplace_back(string_printf("$C7Section ID: $C6%s$C7", name_for_section_id(l->effective_section_id())));
lines.emplace_back(phosg::string_printf("$C7Section ID: $C6%s$C7", name_for_section_id(l->effective_section_id())));
switch (l->drop_mode) {
case Lobby::DropMode::DISABLED:
@@ -153,45 +153,45 @@ static void server_command_lobby_info(shared_ptr<Client> c, const std::string&)
}
} else {
lines.emplace_back(string_printf("$C7State seed: $C6%08X$C7", l->random_seed));
lines.emplace_back(phosg::string_printf("$C7State seed: $C6%08X$C7", l->random_seed));
}
} else {
lines.emplace_back(string_printf("$C7Lobby ID: $C6%08X$C7", l->lobby_id));
lines.emplace_back(phosg::string_printf("$C7Lobby ID: $C6%08X$C7", l->lobby_id));
}
string slots_str = "Slots: ";
for (size_t z = 0; z < l->clients.size(); z++) {
if (!l->clients[z]) {
slots_str += string_printf("$C0%zX$C7", z);
slots_str += phosg::string_printf("$C0%zX$C7", z);
} else {
bool is_self = l->clients[z] == c;
bool is_leader = z == l->leader_id;
if (is_self && is_leader) {
slots_str += string_printf("$C6%zX$C7", z);
slots_str += phosg::string_printf("$C6%zX$C7", z);
} else if (is_self) {
slots_str += string_printf("$C2%zX$C7", z);
slots_str += phosg::string_printf("$C2%zX$C7", z);
} else if (is_leader) {
slots_str += string_printf("$C4%zX$C7", z);
slots_str += phosg::string_printf("$C4%zX$C7", z);
} else {
slots_str += string_printf("%zX", z);
slots_str += phosg::string_printf("%zX", z);
}
}
}
lines.emplace_back(std::move(slots_str));
}
send_text_message(c, join(lines, "\n"));
send_text_message(c, phosg::join(lines, "\n"));
}
static void server_command_ping(shared_ptr<Client> c, const std::string&) {
c->ping_start_time = now();
c->ping_start_time = phosg::now();
send_command(c, 0x1D, 0x00);
}
static void proxy_command_ping(shared_ptr<ProxyServer::LinkedSession> ses, const std::string&) {
ses->client_ping_start_time = now();
ses->server_ping_start_time = now();
ses->client_ping_start_time = phosg::now();
ses->server_ping_start_time = ses->client_ping_start_time;
C_GuildCardSearch_40 cmd = {0x00010000, ses->remote_guild_card_number, ses->remote_guild_card_number};
ses->client_channel.send(0x1D, 0x00);
@@ -204,7 +204,7 @@ static void proxy_command_lobby_info(shared_ptr<ProxyServer::LinkedSession> ses,
// don't show it. (The user can see it in the pause menu, unlike in masked-GC
// sessions like GC.)
if (ses->remote_guild_card_number >= 0) {
msg = string_printf("$C7GC: $C6%" PRId64 "$C7\n", ses->remote_guild_card_number);
msg = phosg::string_printf("$C7GC: $C6%" PRId64 "$C7\n", ses->remote_guild_card_number);
}
msg += "Slots: ";
@@ -212,15 +212,15 @@ static void proxy_command_lobby_info(shared_ptr<ProxyServer::LinkedSession> ses,
bool is_self = z == ses->lobby_client_id;
bool is_leader = z == ses->leader_client_id;
if (ses->lobby_players[z].guild_card_number == 0) {
msg += string_printf("$C0%zX$C7", z);
msg += phosg::string_printf("$C0%zX$C7", z);
} else if (is_self && is_leader) {
msg += string_printf("$C6%zX$C7", z);
msg += phosg::string_printf("$C6%zX$C7", z);
} else if (is_self) {
msg += string_printf("$C2%zX$C7", z);
msg += phosg::string_printf("$C2%zX$C7", z);
} else if (is_leader) {
msg += string_printf("$C4%zX$C7", z);
msg += phosg::string_printf("$C4%zX$C7", z);
} else {
msg += string_printf("%zX", z);
msg += phosg::string_printf("%zX", z);
}
}
@@ -233,7 +233,7 @@ static void proxy_command_lobby_info(shared_ptr<ProxyServer::LinkedSession> ses,
}
if (!cheats_tokens.empty()) {
msg += "\n$C7Cheats: $C6";
msg += join(cheats_tokens, ",");
msg += phosg::join(cheats_tokens, ",");
}
vector<const char*> behaviors_tokens;
@@ -251,7 +251,7 @@ static void proxy_command_lobby_info(shared_ptr<ProxyServer::LinkedSession> ses,
}
if (!behaviors_tokens.empty()) {
msg += "\n$C7Flags: $C6";
msg += join(behaviors_tokens, ",");
msg += phosg::join(behaviors_tokens, ",");
}
if (ses->config.override_section_id != 0xFF) {
@@ -353,7 +353,7 @@ static void server_command_swset_swclear(shared_ptr<Client> c, const std::string
return;
}
auto tokens = split(args, ' ');
auto tokens = phosg::split(args, ' ');
uint8_t floor, flag_num;
if (tokens.size() == 1) {
floor = c->floor;
@@ -391,7 +391,7 @@ static void proxy_command_swset_swclear(shared_ptr<ProxyServer::LinkedSession> s
return;
}
auto tokens = split(args, ' ');
auto tokens = phosg::split(args, ' ');
uint8_t floor, flag_num;
if (tokens.size() == 1) {
floor = ses->floor;
@@ -589,7 +589,7 @@ static void server_command_qgwrite(shared_ptr<Client> c, const std::string& args
return;
}
auto tokens = split(args, ' ');
auto tokens = phosg::split(args, ' ');
if (tokens.size() != 2) {
send_text_message(c, "$C6Incorrect number\nof arguments");
return;
@@ -616,7 +616,7 @@ static void server_command_qsync_qsyncall(shared_ptr<Client> c, const std::strin
return;
}
auto tokens = split(args, ' ');
auto tokens = phosg::split(args, ' ');
if (tokens.size() != 2) {
send_text_message(c, "$C6Incorrect number of\narguments");
return;
@@ -655,7 +655,7 @@ static void proxy_command_qsync_qsyncall(shared_ptr<ProxyServer::LinkedSession>
return;
}
auto tokens = split(args, ' ');
auto tokens = phosg::split(args, ' ');
if (tokens.size() != 2) {
send_text_message(ses->client_channel, "$C6Incorrect number of\narguments");
return;
@@ -896,26 +896,26 @@ static void proxy_command_get_player_card(shared_ptr<ProxyServer::LinkedSession>
static void server_command_send_client(shared_ptr<Client> c, const std::string& args) {
check_debug_enabled(c);
string data = parse_data_string(args);
string data = phosg::parse_data_string(args);
data.resize((data.size() + 3) & (~3));
c->channel.send(data);
}
static void server_command_send_server(shared_ptr<Client> c, const std::string& args) {
check_debug_enabled(c);
string data = parse_data_string(args);
string data = phosg::parse_data_string(args);
data.resize((data.size() + 3) & (~3));
on_command_with_header(c, data);
}
static void proxy_command_send_client(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args) {
string data = parse_data_string(args);
string data = phosg::parse_data_string(args);
data.resize((data.size() + 3) & (~3));
ses->client_channel.send(data);
}
static void proxy_command_send_server(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args) {
string data = parse_data_string(args);
string data = phosg::parse_data_string(args);
data.resize((data.size() + 3) & (~3));
ses->server_channel.send(data);
}
@@ -1044,7 +1044,7 @@ static string file_path_for_recording(const std::string& args, uint32_t account_
throw runtime_error("invalid recording name");
}
}
return string_printf("system/ep3/battle-records/%010" PRIu32 "_%s.mzrd", account_id, args.c_str());
return phosg::string_printf("system/ep3/battle-records/%010" PRIu32 "_%s.mzrd", account_id, args.c_str());
}
static void server_command_saverec(shared_ptr<Client> c, const std::string& args) {
@@ -1054,7 +1054,7 @@ static void server_command_saverec(shared_ptr<Client> c, const std::string& args
}
string file_path = file_path_for_recording(args, c->login->account->account_id);
string data = c->ep3_prev_battle_record->serialize();
save_file(file_path, data);
phosg::save_file(file_path, data);
send_text_message(c, "$C7Recording saved");
c->ep3_prev_battle_record.reset();
}
@@ -1080,8 +1080,8 @@ static void server_command_playrec(shared_ptr<Client> c, const std::string& args
string data;
try {
data = load_file(file_path);
} catch (const cannot_open_file&) {
data = phosg::load_file(file_path);
} catch (const phosg::cannot_open_file&) {
send_text_message(c, "$C4The recording does\nnot exist");
return;
}
@@ -1307,8 +1307,8 @@ static void server_command_edit(shared_ptr<Client> c, const std::string& args) {
bool cheats_allowed = ((s->cheat_mode_behavior != ServerState::BehaviorSwitch::OFF) ||
c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE));
string encoded_args = tolower(args);
vector<string> tokens = split(encoded_args, ' ');
string encoded_args = phosg::tolower(args);
vector<string> tokens = phosg::split(encoded_args, ' ');
try {
auto p = c->character();
@@ -1360,7 +1360,7 @@ static void server_command_edit(shared_ptr<Client> c, const std::string& args) {
p->disp.visual.section_id = secid;
}
} else if (tokens.at(0) == "name") {
vector<string> orig_tokens = split(args, ' ');
vector<string> orig_tokens = phosg::split(args, ' ');
p->disp.name.encode(orig_tokens.at(1), p->inventory.language);
} else if (tokens.at(0) == "npc") {
if (tokens.at(1) == "none") {
@@ -1457,7 +1457,7 @@ static void server_command_bbchar_savechar(shared_ptr<Client> c, const std::stri
auto pending_export = make_unique<Client::PendingCharacterExport>();
if (is_bb_conversion) {
vector<string> tokens = split(args, ' ');
vector<string> tokens = phosg::split(args, ' ');
if (tokens.size() != 3) {
send_text_message(c, "$C6Incorrect argument count");
return;
@@ -1632,7 +1632,7 @@ static string name_for_client(shared_ptr<Client> c) {
}
if (c->login) {
return string_printf("SN:%" PRIu32, c->login->account->account_id);
return phosg::string_printf("SN:%" PRIu32, c->login->account->account_id);
}
return "Player";
@@ -1727,7 +1727,7 @@ static void server_command_ban(shared_ptr<Client> c, const std::string& args) {
usecs *= 60 * 60 * 24 * 365;
}
target->login->account->ban_end_time = now() + usecs;
target->login->account->ban_end_time = phosg::now() + usecs;
target->login->account->save();
send_message_box(target, "$C6You have been banned.");
target->should_disconnect = true;
@@ -2135,7 +2135,7 @@ static void proxy_command_item(shared_ptr<ProxyServer::LinkedSession> ses, const
bool set_drop = (!args.empty() && (args[0] == '!'));
ItemData item = s->parse_item_description(ses->version(), (set_drop ? args.substr(1) : args));
item.id = random_object<uint32_t>() | 0x80000000;
item.id = phosg::random_object<uint32_t>() | 0x80000000;
if (set_drop) {
ses->next_drop_item = item;
@@ -2224,7 +2224,7 @@ static void server_command_ep3_set_dice_range(shared_ptr<Client> c, const std::s
}
auto parse_dice_range = +[](const string& spec) -> uint8_t {
auto tokens = split(spec, '-');
auto tokens = phosg::split(spec, '-');
if (tokens.size() == 1) {
uint8_t v = stoull(spec);
return (v << 4) | (v & 0x0F);
@@ -2238,8 +2238,8 @@ static void server_command_ep3_set_dice_range(shared_ptr<Client> c, const std::s
uint8_t def_dice_range = 0;
uint8_t atk_dice_range_2v1 = 0;
uint8_t def_dice_range_2v1 = 0;
for (const auto& spec : split(args, ' ')) {
auto tokens = split(spec, ':');
for (const auto& spec : phosg::split(args, ' ')) {
auto tokens = phosg::split(spec, ':');
if (tokens.size() != 2) {
send_text_message(c, "$C6Invalid dice spec\nformat");
return;
@@ -2305,7 +2305,7 @@ static void server_command_ep3_replace_assist_card(shared_ptr<Client> c, const s
size_t client_id;
string card_name;
if (isdigit(args[0])) {
auto tokens = split(args, ' ', 1);
auto tokens = phosg::split(args, ' ', 1);
client_id = stoul(tokens.at(0), nullptr, 0) - 1;
card_name = tokens.at(1);
} else {
@@ -2408,7 +2408,7 @@ static void server_command_get_ep3_battle_stat(shared_ptr<Client> c, const std::
const char* rank_name = ps->stats.name_for_rank(rank);
send_text_message_printf(c, "$C7Score: %g\nRank: %hhu (%s)", score, rank, rank_name);
} else if (args == "duration") {
string s = format_duration(now() - l->ep3_server->battle_start_usecs);
string s = phosg::format_duration(phosg::now() - l->ep3_server->battle_start_usecs);
send_text_message_printf(c, "$C7Duration: %s", s.c_str());
} else if (args == "fcs-destroyed") {
send_text_message_printf(c, "$C7Team FCs destroyed:\n%" PRIu32, l->ep3_server->team_num_ally_fcs_destroyed[team_id]);
+7 -9
View File
@@ -7,18 +7,16 @@
#include <vector>
#include "Text.hh"
#include "Types.hh"
class Client;
template <bool IsBigEndian>
template <bool BE>
struct ChoiceSearchConfigT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
U32T disabled = 1; // 0 = enabled, 1 = disabled. Unused in command C3
U32T<BE> disabled = 1; // 0 = enabled, 1 = disabled. Unused in command C3
struct Entry {
U16T parent_choice_id = 0;
U16T choice_id = 0;
U16T<BE> parent_choice_id = 0;
U16T<BE> choice_id = 0;
} __packed_ws__(Entry, 4);
parray<Entry, 5> entries;
@@ -31,8 +29,8 @@ struct ChoiceSearchConfigT {
return -1;
}
operator ChoiceSearchConfigT<!IsBigEndian>() const {
ChoiceSearchConfigT<!IsBigEndian> ret;
operator ChoiceSearchConfigT<!BE>() const {
ChoiceSearchConfigT<!BE> ret;
ret.disabled = this->disabled.load();
for (size_t z = 0; z < this->entries.size(); z++) {
auto& ret_e = ret.entries[z];
+53 -53
View File
@@ -144,7 +144,7 @@ void Client::Config::set_flags_for_version(Version version, int64_t sub_version)
this->set_flag(Flag::CAN_RECEIVE_ENABLE_B2_QUEST);
break;
default:
throw runtime_error(string_printf("unknown sub_version %" PRIX64, sub_version));
throw runtime_error(phosg::string_printf("unknown sub_version %" PRIX64, sub_version));
}
}
@@ -188,8 +188,8 @@ Client::Client(
ServerBehavior server_behavior)
: server(server),
id(next_id++),
log(string_printf("[C-%" PRIX64 "] ", this->id), client_log.min_level),
channel(bev, virtual_network_id, version, 1, nullptr, nullptr, this, "", TerminalFormat::FG_YELLOW, TerminalFormat::FG_GREEN),
log(phosg::string_printf("[C-%" PRIX64 "] ", this->id), client_log.min_level),
channel(bev, virtual_network_id, version, 1, nullptr, nullptr, this, "", phosg::TerminalFormat::FG_YELLOW, phosg::TerminalFormat::FG_GREEN),
server_behavior(server_behavior),
should_disconnect(false),
should_send_to_lobby_server(false),
@@ -248,8 +248,8 @@ Client::Client(
// more annoying than helpful at this point.
if ((s->hide_download_commands) &&
((this->channel.version == Version::PC_PATCH) || (this->channel.version == Version::BB_PATCH))) {
this->channel.terminal_recv_color = TerminalFormat::END;
this->channel.terminal_send_color = TerminalFormat::END;
this->channel.terminal_recv_color = phosg::TerminalFormat::END;
this->channel.terminal_send_color = phosg::TerminalFormat::END;
}
this->log.info("Created");
@@ -276,24 +276,24 @@ void Client::update_channel_name() {
auto player = this->character(false, false);
if (player) {
string name_str = player->disp.name.decode(this->language());
this->channel.name = string_printf("C-%" PRIX64 " (%s) @ %s", this->id, name_str.c_str(), ip_str.c_str());
this->channel.name = phosg::string_printf("C-%" PRIX64 " (%s) @ %s", this->id, name_str.c_str(), ip_str.c_str());
} else {
this->channel.name = string_printf("C-%" PRIX64 " @ %s", this->id, ip_str.c_str());
this->channel.name = phosg::string_printf("C-%" PRIX64 " @ %s", this->id, ip_str.c_str());
}
}
void Client::reschedule_save_game_data_event() {
if (this->version() == Version::BB_V4) {
struct timeval tv = usecs_to_timeval(60000000); // 1 minute
struct timeval tv = phosg::usecs_to_timeval(60000000); // 1 minute
event_add(this->save_game_data_event.get(), &tv);
}
}
void Client::reschedule_ping_and_timeout_events() {
auto s = this->require_server_state();
struct timeval ping_tv = usecs_to_timeval(s->client_ping_interval_usecs);
struct timeval ping_tv = phosg::usecs_to_timeval(s->client_ping_interval_usecs);
event_add(this->send_ping_event.get(), &ping_tv);
struct timeval idle_tv = usecs_to_timeval(s->client_idle_timeout_usecs);
struct timeval idle_tv = phosg::usecs_to_timeval(s->client_idle_timeout_usecs);
event_add(this->idle_timeout_event.get(), &idle_tv);
}
@@ -393,7 +393,7 @@ bool Client::evaluate_quest_availability_expression(
.v1_present = v1_present,
};
int64_t ret = expr->evaluate(env);
if (this->log.should_log(LogLevel::INFO)) {
if (this->log.should_log(phosg::LogLevel::INFO)) {
string expr_str = expr->str();
this->log.info("Evaluated integral expression %s => %s", expr_str.c_str(), ret ? "TRUE" : "FALSE");
}
@@ -451,7 +451,7 @@ void Client::send_ping() {
if (!is_patch(this->version())) {
this->log.info("Sending ping command");
// The game doesn't use this timestamp; we only use it for debugging purposes
be_uint64_t timestamp = now();
be_uint64_t timestamp = phosg::now();
try {
this->channel.send(0x1D, 0x00, &timestamp, sizeof(be_uint64_t));
} catch (const exception& e) {
@@ -643,7 +643,7 @@ string Client::system_filename() const {
if (!this->login || !this->login->bb_license) {
throw logic_error("client is not logged in");
}
return string_printf("system/players/system_%s.psosys", this->login->bb_license->username.c_str());
return phosg::string_printf("system/players/system_%s.psosys", this->login->bb_license->username.c_str());
}
string Client::character_filename(const std::string& bb_username, int8_t index) {
@@ -653,11 +653,11 @@ string Client::character_filename(const std::string& bb_username, int8_t index)
if (index < 0) {
throw logic_error("character index is not set");
}
return string_printf("system/players/player_%s_%hhd.psochar", bb_username.c_str(), index);
return phosg::string_printf("system/players/player_%s_%hhd.psochar", bb_username.c_str(), index);
}
string Client::backup_character_filename(uint32_t account_id, size_t index, bool is_ep3) {
return string_printf("system/players/backup_player_%" PRIu32 "_%zu.%s",
return phosg::string_printf("system/players/backup_player_%" PRIu32 "_%zu.%s",
account_id, index, is_ep3 ? "pso3char" : "psochar");
}
@@ -678,7 +678,7 @@ string Client::guild_card_filename() const {
if (!this->login || !this->login->bb_license) {
throw logic_error("client is not logged in");
}
return string_printf("system/players/guild_cards_%s.psocard", this->login->bb_license->username.c_str());
return phosg::string_printf("system/players/guild_cards_%s.psocard", this->login->bb_license->username.c_str());
}
string Client::shared_bank_filename() const {
@@ -688,7 +688,7 @@ string Client::shared_bank_filename() const {
if (!this->login || !this->login->bb_license) {
throw logic_error("client is not logged in");
}
return string_printf("system/players/shared_bank_%s.psobank", this->login->bb_license->username.c_str());
return phosg::string_printf("system/players/shared_bank_%s.psobank", this->login->bb_license->username.c_str());
}
string Client::legacy_account_filename() const {
@@ -698,7 +698,7 @@ string Client::legacy_account_filename() const {
if (!this->login || !this->login->bb_license) {
throw logic_error("client is not logged in");
}
return string_printf("system/players/account_%s.nsa", this->login->bb_license->username.c_str());
return phosg::string_printf("system/players/account_%s.nsa", this->login->bb_license->username.c_str());
}
string Client::legacy_player_filename() const {
@@ -711,7 +711,7 @@ string Client::legacy_player_filename() const {
if (this->bb_character_index < 0) {
throw logic_error("character index is not set");
}
return string_printf(
return phosg::string_printf(
"system/players/player_%s_%hhd.nsc",
this->login->bb_license->username.c_str(),
static_cast<int8_t>(this->bb_character_index + 1));
@@ -747,8 +747,8 @@ void Client::load_all_files() {
this->system_data = files_manager->get_system(sys_filename);
if (this->system_data) {
player_data_log.info("Using loaded system file %s", sys_filename.c_str());
} else if (isfile(sys_filename)) {
this->system_data = make_shared<PSOBBBaseSystemFile>(load_object_file<PSOBBBaseSystemFile>(sys_filename, true));
} else if (phosg::isfile(sys_filename)) {
this->system_data = make_shared<PSOBBBaseSystemFile>(phosg::load_object_file<PSOBBBaseSystemFile>(sys_filename, true));
files_manager->set_system(sys_filename, this->system_data);
player_data_log.info("Loaded system data from %s", sys_filename.c_str());
} else {
@@ -760,9 +760,9 @@ void Client::load_all_files() {
this->character_data = files_manager->get_character(char_filename);
if (this->character_data) {
player_data_log.info("Using loaded character file %s", char_filename.c_str());
} else if (isfile(char_filename)) {
auto f = fopen_unique(char_filename, "rb");
auto header = freadx<PSOCommandHeaderBB>(f.get());
} else if (phosg::isfile(char_filename)) {
auto f = phosg::fopen_unique(char_filename, "rb");
auto header = phosg::freadx<PSOCommandHeaderBB>(f.get());
if (header.size != 0x399C) {
throw runtime_error("incorrect size in character file header");
}
@@ -773,14 +773,14 @@ void Client::load_all_files() {
throw runtime_error("incorrect flag in character file header");
}
static_assert(sizeof(PSOBBCharacterFile) + sizeof(PSOBBFullSystemFile) == 0x3994, ".psochar size is incorrect");
this->character_data = make_shared<PSOBBCharacterFile>(freadx<PSOBBCharacterFile>(f.get()));
this->character_data = make_shared<PSOBBCharacterFile>(phosg::freadx<PSOBBCharacterFile>(f.get()));
files_manager->set_character(char_filename, this->character_data);
player_data_log.info("Loaded character data from %s", char_filename.c_str());
// If there was no .psosys file, load the system file from the .psochar
// file instead
if (!this->system_data) {
this->system_data = make_shared<PSOBBBaseSystemFile>(freadx<PSOBBBaseSystemFile>(f.get()));
this->system_data = make_shared<PSOBBBaseSystemFile>(phosg::freadx<PSOBBBaseSystemFile>(f.get()));
files_manager->set_system(sys_filename, this->system_data);
player_data_log.info("Loaded system data from %s", char_filename.c_str());
}
@@ -797,8 +797,8 @@ void Client::load_all_files() {
this->guild_card_data = files_manager->get_guild_card(card_filename);
if (this->guild_card_data) {
player_data_log.info("Using loaded Guild Card file %s", card_filename.c_str());
} else if (isfile(card_filename)) {
this->guild_card_data = make_shared<PSOBBGuildCardFile>(load_object_file<PSOBBGuildCardFile>(card_filename));
} else if (phosg::isfile(card_filename)) {
this->guild_card_data = make_shared<PSOBBGuildCardFile>(phosg::load_object_file<PSOBBGuildCardFile>(card_filename));
files_manager->set_guild_card(card_filename, this->guild_card_data);
player_data_log.info("Loaded Guild Card data from %s", card_filename.c_str());
} else {
@@ -809,8 +809,8 @@ void Client::load_all_files() {
if (!this->system_data || (!this->character_data && (this->bb_character_index >= 0)) || !this->guild_card_data) {
string nsa_filename = this->legacy_account_filename();
shared_ptr<LegacySavedAccountDataBB> nsa_data;
if (isfile(nsa_filename)) {
nsa_data = make_shared<LegacySavedAccountDataBB>(load_object_file<LegacySavedAccountDataBB>(nsa_filename));
if (phosg::isfile(nsa_filename)) {
nsa_data = make_shared<LegacySavedAccountDataBB>(phosg::load_object_file<LegacySavedAccountDataBB>(nsa_filename));
if (!nsa_data->signature.eq(LegacySavedAccountDataBB::SIGNATURE)) {
throw runtime_error("account data header is incorrect");
}
@@ -839,7 +839,7 @@ void Client::load_all_files() {
if (!this->character_data && (this->bb_character_index >= 0)) {
string nsc_filename = this->legacy_player_filename();
auto nsc_data = load_object_file<LegacySavedPlayerDataBB>(nsc_filename);
auto nsc_data = phosg::load_object_file<LegacySavedPlayerDataBB>(nsc_filename);
if (nsc_data.signature == LegacySavedPlayerDataBB::SIGNATURE_V0) {
nsc_data.signature = LegacySavedPlayerDataBB::SIGNATURE_V0;
nsc_data.unused.clear();
@@ -895,7 +895,7 @@ void Client::load_all_files() {
this->character_data->disp.name.clear_after_bytes(0x18);
this->login->account->auto_reply_message = this->character_data->auto_reply.decode();
this->login->account->save();
this->last_play_time_update = now();
this->last_play_time_update = phosg::now();
}
}
@@ -920,7 +920,7 @@ void Client::save_all() {
}
if (this->external_bank) {
string filename = this->shared_bank_filename();
save_object_file<PlayerBank200>(filename, *this->external_bank);
phosg::save_object_file<PlayerBank200>(filename, *this->external_bank);
player_data_log.info("Saved shared bank file %s", filename.c_str());
}
if (this->external_bank_character) {
@@ -936,7 +936,7 @@ void Client::save_system_file() const {
throw logic_error("no system file loaded");
}
string filename = this->system_filename();
save_object_file(filename, *this->system_data);
phosg::save_object_file(filename, *this->system_data);
player_data_log.info("Saved system file %s", filename.c_str());
}
@@ -944,11 +944,11 @@ void Client::save_character_file(
const string& filename,
shared_ptr<const PSOBBBaseSystemFile> system,
shared_ptr<const PSOBBCharacterFile> character) {
auto f = fopen_unique(filename, "wb");
auto f = phosg::fopen_unique(filename, "wb");
PSOCommandHeaderBB header = {sizeof(PSOCommandHeaderBB) + sizeof(PSOBBCharacterFile) + sizeof(PSOBBBaseSystemFile) + sizeof(PSOBBTeamMembership), 0x00E7, 0x00000000};
fwritex(f.get(), header);
fwritex(f.get(), *character);
fwritex(f.get(), *system);
phosg::fwritex(f.get(), header);
phosg::fwritex(f.get(), *character);
phosg::fwritex(f.get(), *system);
// TODO: Technically, we should write the actual team membership struct to the
// file here, but that would cause Client to depend on Account, which
// it currently does not. This data doesn't matter at all for correctness
@@ -960,14 +960,14 @@ void Client::save_character_file(
// of teams with a different set of team IDs anyway, so the membership struct
// here would be useless either way.
static const PSOBBTeamMembership empty_membership;
fwritex(f.get(), empty_membership);
phosg::fwritex(f.get(), empty_membership);
player_data_log.info("Saved character file %s", filename.c_str());
}
void Client::save_ep3_character_file(
const string& filename,
const PSOGCEp3CharacterFile::Character& character) {
save_file(filename, &character, sizeof(character));
phosg::save_file(filename, &character, sizeof(character));
player_data_log.info("Saved Episode 3 character file %s", filename.c_str());
}
@@ -981,7 +981,7 @@ void Client::save_character_file() {
if (this->should_update_play_time) {
// This is slightly inaccurate, since fractions of a second are truncated
// off each time we save. I'm lazy, so insert shrug emoji here.
uint64_t t = now();
uint64_t t = phosg::now();
uint64_t seconds = (t - this->last_play_time_update) / 1000000;
this->character_data->play_time_seconds += seconds;
player_data_log.info("Added %" PRIu64 " seconds to play time", seconds);
@@ -996,14 +996,14 @@ void Client::save_guild_card_file() const {
throw logic_error("no Guild Card file loaded");
}
string filename = this->guild_card_filename();
save_object_file(filename, *this->guild_card_data);
phosg::save_object_file(filename, *this->guild_card_data);
player_data_log.info("Saved Guild Card file %s", filename.c_str());
}
void Client::load_backup_character(uint32_t account_id, size_t index) {
string filename = this->backup_character_filename(account_id, index, false);
auto f = fopen_unique(filename, "rb");
auto header = freadx<PSOCommandHeaderBB>(f.get());
auto f = phosg::fopen_unique(filename, "rb");
auto header = phosg::freadx<PSOCommandHeaderBB>(f.get());
if (header.size != 0x399C) {
throw runtime_error("incorrect size in character file header");
}
@@ -1013,14 +1013,14 @@ void Client::load_backup_character(uint32_t account_id, size_t index) {
if (header.flag != 0x00000000) {
throw runtime_error("incorrect flag in character file header");
}
this->character_data = make_shared<PSOBBCharacterFile>(freadx<PSOBBCharacterFile>(f.get()));
this->character_data = make_shared<PSOBBCharacterFile>(phosg::freadx<PSOBBCharacterFile>(f.get()));
this->update_character_data_after_load(this->character_data);
this->v1_v2_last_reported_disp.reset();
}
shared_ptr<PSOGCEp3CharacterFile::Character> Client::load_ep3_backup_character(uint32_t account_id, size_t index) {
string filename = this->backup_character_filename(account_id, index, true);
auto ch = make_shared<PSOGCEp3CharacterFile::Character>(load_object_file<PSOGCEp3CharacterFile::Character>(filename));
auto ch = make_shared<PSOGCEp3CharacterFile::Character>(phosg::load_object_file<PSOGCEp3CharacterFile::Character>(filename));
this->character_data = PSOBBCharacterFile::create_from_ep3(*ch);
this->ep3_config = make_shared<Episode3::PlayerConfig>(ch->ep3_config);
this->update_character_data_after_load(this->character_data);
@@ -1052,7 +1052,7 @@ std::shared_ptr<PSOBBCharacterFile> Client::current_bank_character() {
void Client::use_default_bank() {
if (this->external_bank) {
string filename = this->shared_bank_filename();
save_object_file<PlayerBank200>(filename, *this->external_bank);
phosg::save_object_file<PlayerBank200>(filename, *this->external_bank);
this->external_bank.reset();
player_data_log.info("Detached shared bank %s", filename.c_str());
}
@@ -1073,8 +1073,8 @@ bool Client::use_shared_bank() {
if (this->external_bank) {
player_data_log.info("Using loaded shared bank %s", filename.c_str());
return true;
} else if (isfile(filename)) {
this->external_bank = make_shared<PlayerBank200>(load_object_file<PlayerBank200>(filename));
} else if (phosg::isfile(filename)) {
this->external_bank = make_shared<PlayerBank200>(phosg::load_object_file<PlayerBank200>(filename));
files_manager->set_bank(filename, this->external_bank);
player_data_log.info("Loaded shared bank %s", filename.c_str());
return true;
@@ -1096,9 +1096,9 @@ void Client::use_character_bank(int8_t index) {
if (this->external_bank_character) {
this->external_bank_character_index = index;
player_data_log.info("Using loaded character file %s for external bank", filename.c_str());
} else if (isfile(filename)) {
auto f = fopen_unique(filename, "rb");
auto header = freadx<PSOCommandHeaderBB>(f.get());
} else if (phosg::isfile(filename)) {
auto f = phosg::fopen_unique(filename, "rb");
auto header = phosg::freadx<PSOCommandHeaderBB>(f.get());
if (header.size != 0x399C) {
throw runtime_error("incorrect size in character file header");
}
@@ -1108,7 +1108,7 @@ void Client::use_character_bank(int8_t index) {
if (header.flag != 0x00000000) {
throw runtime_error("incorrect flag in character file header");
}
this->external_bank_character = make_shared<PSOBBCharacterFile>(freadx<PSOBBCharacterFile>(f.get()));
this->external_bank_character = make_shared<PSOBBCharacterFile>(phosg::freadx<PSOBBCharacterFile>(f.get()));
this->update_character_data_after_load(this->external_bank_character);
this->external_bank_character_index = index;
files_manager->set_character(filename, this->external_bank_character);
+3 -3
View File
@@ -147,7 +147,7 @@ public:
template <size_t Bytes>
void parse_from(const parray<uint8_t, Bytes>& data) {
StringReader r(data.data(), data.size());
phosg::StringReader r(data.data(), data.size());
if (r.get_u32l() != CLIENT_CONFIG_MAGIC) {
throw std::invalid_argument("config signature is incorrect");
}
@@ -163,7 +163,7 @@ public:
template <size_t Bytes>
void serialize_into(parray<uint8_t, Bytes>& data) const {
StringWriter w;
phosg::StringWriter w;
w.put_u32l(CLIENT_CONFIG_MAGIC);
w.put_u32l(this->specific_version);
w.put_u64l(this->enabled_flags & static_cast<uint64_t>(Flag::CLIENT_SIDE_MASK));
@@ -184,7 +184,7 @@ public:
std::weak_ptr<Server> server;
uint64_t id;
PrefixedLogger log;
phosg::PrefixedLogger log;
std::shared_ptr<Login> login;
+21 -27
View File
@@ -2228,10 +2228,9 @@ struct S_ExecuteCode_B2 {
// The code immediately follows, ending with an S_ExecuteCode_Footer_B2
} __packed_ws__(S_ExecuteCode_B2, 0x0C);
template <bool IsBigEndian>
template <bool BE>
struct S_ExecuteCode_FooterT_B2 {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
static constexpr bool IsBE = BE; // Needed by generate_client_command_t
// Relocations is a list of words (le_uint16_t on DC/PC/XB/BB, be_uint16_t on
// GC) containing the number of doublewords (uint32_t) to skip for each
@@ -2251,14 +2250,14 @@ struct S_ExecuteCode_FooterT_B2 {
// relocations_offset points there, so those 12 bytes may also be omitted from
// the command entirely (without changing code_size - so code_size would
// technically extend beyond the end of the B2 command).
U32T relocations_offset = 0; // Relative to code base (after checksum_size)
U32T num_relocations = 0;
parray<U32T, 2> unused1;
U32T<BE> relocations_offset = 0; // Relative to code base (after checksum_size)
U32T<BE> num_relocations = 0;
parray<U32T<BE>, 2> unused1;
// entrypoint_offset is doubly indirect - it points to a pointer to a 32-bit
// value that itself is the actual entrypoint. This is presumably done so the
// entrypoint can be optionally relocated.
U32T entrypoint_addr_offset = 0; // Relative to code base (after checksum_size).
parray<U32T, 3> unused2;
U32T<BE> entrypoint_addr_offset = 0; // Relative to code base (after checksum_size).
parray<U32T<BE>, 3> unused2;
} __packed__;
using S_ExecuteCode_Footer_GC_B2 = S_ExecuteCode_FooterT_B2<true>;
using S_ExecuteCode_Footer_DC_PC_XB_BB_B2 = S_ExecuteCode_FooterT_B2<false>;
@@ -3951,7 +3950,7 @@ struct G_Unknown_6x09 {
// 6x0A: Update enemy state
template <bool IsBigEndian>
template <bool BE>
struct G_UpdateEnemyStateT_6x0A {
G_EnemyIDHeader header;
le_uint16_t enemy_index = 0; // [0, 0xB50)
@@ -3959,7 +3958,7 @@ struct G_UpdateEnemyStateT_6x0A {
// Flags:
// 00000400 - should play hit animation
// 00000800 - is dead
typename std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t> flags = 0;
typename std::conditional_t<BE, be_uint32_t, le_uint32_t> flags = 0;
} __packed__;
using G_UpdateEnemyState_GC_6x0A = G_UpdateEnemyStateT_6x0A<true>;
using G_UpdateEnemyState_DC_PC_XB_BB_6x0A = G_UpdateEnemyStateT_6x0A<false>;
@@ -4005,15 +4004,14 @@ struct G_Unknown_6x10_6x11_6x12_6x14 {
// 6x12: Dragon boss actions (not valid on Episode 3)
template <bool IsBigEndian>
template <bool BE>
struct G_DragonBossActionsT_6x12 {
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
G_EnemyIDHeader header;
le_uint16_t unknown_a2 = 0;
le_uint16_t unknown_a3 = 0;
le_uint32_t unknown_a4 = 0;
F32T x = 0.0f;
F32T z = 0.0f;
F32T<BE> x = 0.0f;
F32T<BE> z = 0.0f;
} __packed__;
using G_DragonBossActions_DC_PC_XB_BB_6x12 = G_DragonBossActionsT_6x12<false>;
using G_DragonBossActions_GC_6x12 = G_DragonBossActionsT_6x12<true>;
@@ -5043,12 +5041,11 @@ struct G_ExitQuest_6x73 {
// There is a bug in PSO GC with regard to this command: the client does not
// byteswap the header, which means the client_id field is big-endian.
template <bool IsBigEndian>
template <bool BE>
struct G_WordSelectT_6x74 {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
uint8_t subcommand = 0;
uint8_t size = 0;
U16T client_id = 0;
U16T<BE> client_id = 0;
WordSelectMessage message;
} __packed__;
using G_WordSelect_6x74 = G_WordSelectT_6x74<false>;
@@ -5170,14 +5167,12 @@ struct G_SetBattleModeData_6x7D {
// 6x7F: Battle scores and places (not valid on Episode 3)
template <bool IsBigEndian>
template <bool BE>
struct G_BattleScoresT_6x7F {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
struct Entry {
U16T client_id = 0;
U16T place = 0;
U32T score = 0;
U16T<BE> client_id = 0;
U16T<BE> place = 0;
U32T<BE> score = 0;
} __packed_ws__(Entry, 8);
G_UnusedHeader header;
parray<Entry, 4> entries;
@@ -5513,15 +5508,14 @@ struct G_ModifyTradeProposal_6xA6 {
// 6xA8: Gol Dragon boss actions (not valid on pre-V3 or Episode 3)
template <bool IsBigEndian>
template <bool BE>
struct G_GolDragonBossActionsT_6xA8 {
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
G_EnemyIDHeader header;
le_uint16_t unknown_a2 = 0;
le_uint16_t unknown_a3 = 0;
le_uint32_t unknown_a4 = 0;
F32T x = 0.0f;
F32T z = 0.0f;
F32T<BE> x = 0.0f;
F32T<BE> z = 0.0f;
uint8_t unknown_a5 = 0;
parray<uint8_t, 3> unused;
} __packed__;
+43 -45
View File
@@ -4,12 +4,13 @@
#include "EnemyType.hh"
#include "GSLArchive.hh"
#include "StaticGameData.hh"
#include "Types.hh"
using namespace std;
template <typename IntT, size_t Count>
JSON to_json(const parray<IntT, Count>& v) {
auto ret = JSON::list();
phosg::JSON to_json(const parray<IntT, Count>& v) {
auto ret = phosg::JSON::list();
for (size_t z = 0; z < Count; z++) {
ret.emplace_back(v[z]);
}
@@ -17,7 +18,7 @@ JSON to_json(const parray<IntT, Count>& v) {
}
template <typename IntT, size_t Count>
void from_json_into(const JSON& json, parray<IntT, Count>& ret) {
void from_json_into(const phosg::JSON& json, parray<IntT, Count>& ret) {
if (json.size() != Count) {
throw runtime_error("incorrect array length");
}
@@ -27,8 +28,8 @@ void from_json_into(const JSON& json, parray<IntT, Count>& ret) {
}
template <typename IntT, size_t Count>
JSON to_json(const parray<CommonItemSet::Table::Range<IntT>, Count>& v) {
auto ret = JSON::list();
phosg::JSON to_json(const parray<CommonItemSet::Table::Range<IntT>, Count>& v) {
auto ret = phosg::JSON::list();
for (size_t z = 0; z < Count; z++) {
ret.emplace_back(to_json(v[z]));
}
@@ -36,7 +37,7 @@ JSON to_json(const parray<CommonItemSet::Table::Range<IntT>, Count>& v) {
}
template <typename IntT, size_t Count>
void from_json_into(const JSON& json, parray<CommonItemSet::Table::Range<IntT>, Count>& ret) {
void from_json_into(const phosg::JSON& json, parray<CommonItemSet::Table::Range<IntT>, Count>& ret) {
if (json.size() != Count) {
throw runtime_error("incorrect array length");
}
@@ -46,16 +47,16 @@ void from_json_into(const JSON& json, parray<CommonItemSet::Table::Range<IntT>,
}
template <typename IntT>
JSON to_json(const CommonItemSet::Table::Range<IntT>& v) {
phosg::JSON to_json(const CommonItemSet::Table::Range<IntT>& v) {
if (v.min == v.max) {
return JSON(v.min);
return phosg::JSON(v.min);
} else {
return JSON::list({v.min, v.max});
return phosg::JSON::list({v.min, v.max});
}
}
template <typename IntT>
void from_json_into(const JSON& json, CommonItemSet::Table::Range<IntT>& ret) {
void from_json_into(const phosg::JSON& json, CommonItemSet::Table::Range<IntT>& ret) {
if (json.is_int()) {
IntT v = json.as_int();
ret.min = v;
@@ -71,8 +72,8 @@ void from_json_into(const JSON& json, CommonItemSet::Table::Range<IntT>& ret) {
}
template <typename IntT, size_t Count1, size_t Count2>
JSON to_json(const parray<parray<IntT, Count2>, Count1>& v) {
auto ret = JSON::list();
phosg::JSON to_json(const parray<parray<IntT, Count2>, Count1>& v) {
auto ret = phosg::JSON::list();
for (size_t z = 0; z < Count1; z++) {
ret.emplace_back(to_json(v[z]));
}
@@ -80,7 +81,7 @@ JSON to_json(const parray<parray<IntT, Count2>, Count1>& v) {
}
template <typename IntT, size_t Count1, size_t Count2>
void from_json_into(const JSON& json, parray<parray<IntT, Count2>, Count1>& ret) {
void from_json_into(const phosg::JSON& json, parray<parray<IntT, Count2>, Count1>& ret) {
if (json.size() != Count1) {
throw runtime_error("incorrect array length");
}
@@ -90,7 +91,7 @@ void from_json_into(const JSON& json, parray<parray<IntT, Count2>, Count1>& ret)
}
template <typename IntT, size_t Count1, size_t Count2>
void from_json_into(const JSON& json, parray<parray<CommonItemSet::Table::Range<IntT>, Count2>, Count1>& ret) {
void from_json_into(const phosg::JSON& json, parray<parray<CommonItemSet::Table::Range<IntT>, Count2>, Count1>& ret) {
if (json.size() != Count1) {
throw runtime_error("incorrect array length");
}
@@ -99,7 +100,7 @@ void from_json_into(const JSON& json, parray<parray<CommonItemSet::Table::Range<
}
}
CommonItemSet::Table::Table(const JSON& json, Episode episode)
CommonItemSet::Table::Table(const phosg::JSON& json, Episode episode)
: episode(episode) {
from_json_into(json.at("BaseWeaponTypeProbTable"), this->base_weapon_type_prob_table);
from_json_into(json.at("SubtypeBaseTable"), this->subtype_base_table);
@@ -128,7 +129,7 @@ CommonItemSet::Table::Table(const JSON& json, Episode episode)
static const array<Episode, 3> episodes = {Episode::EP1, Episode::EP2, Episode::EP4};
for (Episode episode : episodes) {
for (auto type : enemy_types_for_rare_table_index(episode, z)) {
string name = string_printf("%s:%s", abbreviation_for_episode(episode), name_for_enum(type));
string name = phosg::string_printf("%s:%s", abbreviation_for_episode(episode), phosg::name_for_enum(type));
from_json_into(*enemy_meseta_ranges_json.at(name), this->enemy_meseta_ranges[z]);
this->enemy_type_drop_probs[z] = enemy_type_drop_probs_json.at(name)->as_int();
this->enemy_item_classes[z] = enemy_item_classes_json.at(name)->as_int();
@@ -170,7 +171,7 @@ void CommonItemSet::Table::print(FILE* stream) const {
if (!enemies_str.empty()) {
enemies_str += ", ";
}
enemies_str += name_for_enum(enemy_type);
enemies_str += phosg::name_for_enum(enemy_type);
}
if (drop_probs[z]) {
fprintf(stream, " %02zX %5hu %5hu %3hhu%% %02hX:%s %s\n",
@@ -335,22 +336,22 @@ void CommonItemSet::Table::print(FILE* stream) const {
}
}
JSON CommonItemSet::Table::json() const {
JSON enemy_meseta_ranges_json = JSON::dict();
JSON enemy_type_drop_probs_json = JSON::dict();
JSON enemy_item_classes_json = JSON::dict();
phosg::JSON CommonItemSet::Table::json() const {
phosg::JSON enemy_meseta_ranges_json = phosg::JSON::dict();
phosg::JSON enemy_type_drop_probs_json = phosg::JSON::dict();
phosg::JSON enemy_item_classes_json = phosg::JSON::dict();
for (size_t z = 0; z < 0x64; z++) {
static const array<Episode, 3> episodes = {Episode::EP1, Episode::EP2, Episode::EP4};
for (Episode episode : episodes) {
for (auto type : enemy_types_for_rare_table_index(episode, z)) {
string name = string_printf("%s:%s", abbreviation_for_episode(episode), name_for_enum(type));
string name = phosg::string_printf("%s:%s", abbreviation_for_episode(episode), phosg::name_for_enum(type));
enemy_meseta_ranges_json.emplace(name, to_json(this->enemy_meseta_ranges[z]));
enemy_type_drop_probs_json.emplace(name, this->enemy_type_drop_probs[z]);
enemy_item_classes_json.emplace(name, this->enemy_item_classes[z]);
}
}
}
return JSON::dict({
return phosg::JSON::dict({
{"BaseWeaponTypeProbTable", to_json(this->base_weapon_type_prob_table)},
{"SubtypeBaseTable", to_json(this->subtype_base_table)},
{"SubtypeAreaLengthTable", to_json(this->subtype_area_length_table)},
@@ -376,16 +377,16 @@ JSON CommonItemSet::Table::json() const {
});
}
JSON CommonItemSet::json() const {
auto modes_dict = JSON::dict();
phosg::JSON CommonItemSet::json() const {
auto modes_dict = phosg::JSON::dict();
static const array<GameMode, 4> modes = {GameMode::NORMAL, GameMode::BATTLE, GameMode::CHALLENGE, GameMode::SOLO};
for (const auto& mode : modes) {
auto episodes_dict = JSON::dict();
auto episodes_dict = phosg::JSON::dict();
static const array<Episode, 3> episodes = {Episode::EP1, Episode::EP2, Episode::EP4};
for (const auto& episode : episodes) {
auto difficulty_dict = JSON::dict();
auto difficulty_dict = phosg::JSON::dict();
for (uint8_t difficulty = 0; difficulty < 4; difficulty++) {
auto section_id_dict = JSON::dict();
auto section_id_dict = phosg::JSON::dict();
for (uint8_t section_id = 0; section_id < 10; section_id++) {
try {
auto table = this->get_table(episode, mode, difficulty, section_id);
@@ -423,7 +424,7 @@ void CommonItemSet::print(FILE* stream) const {
}
}
CommonItemSet::Table::Table(const StringReader& r, bool is_big_endian, bool is_v3, Episode episode)
CommonItemSet::Table::Table(const phosg::StringReader& r, bool is_big_endian, bool is_v3, Episode episode)
: episode(episode) {
if (is_big_endian) {
this->parse_itempt_t<true>(r, is_v3);
@@ -432,12 +433,9 @@ CommonItemSet::Table::Table(const StringReader& r, bool is_big_endian, bool is_v
}
}
template <bool IsBigEndian>
void CommonItemSet::Table::parse_itempt_t(const StringReader& r, bool is_v3) {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
const auto& offsets = r.pget<OffsetsT<IsBigEndian>>(r.pget<U32T>(r.size() - 0x10));
template <bool BE>
void CommonItemSet::Table::parse_itempt_t(const phosg::StringReader& r, bool is_v3) {
const auto& offsets = r.pget<OffsetsT<BE>>(r.pget<U32T<BE>>(r.size() - 0x10));
this->base_weapon_type_prob_table = r.pget<parray<uint8_t, 0x0C>>(offsets.base_weapon_type_prob_table_offset);
this->subtype_base_table = r.pget<parray<int8_t, 0x0C>>(offsets.subtype_base_table_offset);
@@ -445,14 +443,14 @@ void CommonItemSet::Table::parse_itempt_t(const StringReader& r, bool is_v3) {
this->grind_prob_table = r.pget<parray<parray<uint8_t, 4>, 9>>(offsets.grind_prob_table_offset);
this->armor_shield_type_index_prob_table = r.pget<parray<uint8_t, 0x05>>(offsets.armor_shield_type_index_prob_table_offset);
this->armor_slot_count_prob_table = r.pget<parray<uint8_t, 0x05>>(offsets.armor_slot_count_prob_table_offset);
const auto& data = r.pget<parray<Range<U16T>, 0x64>>(offsets.enemy_meseta_ranges_offset);
const auto& data = r.pget<parray<Range<U16T<BE>>, 0x64>>(offsets.enemy_meseta_ranges_offset);
for (size_t z = 0; z < data.size(); z++) {
this->enemy_meseta_ranges[z] = Range<uint16_t>{data[z].min, data[z].max};
}
this->enemy_type_drop_probs = r.pget<parray<uint8_t, 0x64>>(offsets.enemy_type_drop_probs_offset);
this->enemy_item_classes = r.pget<parray<uint8_t, 0x64>>(offsets.enemy_item_classes_offset);
{
const auto& data = r.pget<parray<Range<U16T>, 0x0A>>(offsets.box_meseta_ranges_offset);
const auto& data = r.pget<parray<Range<U16T<BE>>, 0x0A>>(offsets.box_meseta_ranges_offset);
for (size_t z = 0; z < data.size(); z++) {
this->box_meseta_ranges[z] = Range<uint16_t>{data[z].min, data[z].max};
}
@@ -466,7 +464,7 @@ void CommonItemSet::Table::parse_itempt_t(const StringReader& r, bool is_v3) {
}
}
} else { // V3
const auto& data = r.pget<parray<parray<U16T, 6>, 0x17>>(offsets.bonus_value_prob_table_offset);
const auto& data = r.pget<parray<parray<U16T<BE>, 6>, 0x17>>(offsets.bonus_value_prob_table_offset);
for (size_t z = 0; z < data.size(); z++) {
for (size_t x = 0; x < data[z].size(); x++) {
this->bonus_value_prob_table[z][x] = data[z][x];
@@ -478,7 +476,7 @@ void CommonItemSet::Table::parse_itempt_t(const StringReader& r, bool is_v3) {
this->special_mult = r.pget<parray<uint8_t, 0x0A>>(offsets.special_mult_offset);
this->special_percent = r.pget<parray<uint8_t, 0x0A>>(offsets.special_percent_offset);
{
const auto& data = r.pget<parray<parray<U16T, 0x0A>, 0x1C>>(offsets.tool_class_prob_table_offset);
const auto& data = r.pget<parray<parray<U16T<BE>, 0x0A>, 0x1C>>(offsets.tool_class_prob_table_offset);
for (size_t z = 0; z < data.size(); z++) {
for (size_t x = 0; x < data[z].size(); x++) {
this->tool_class_prob_table[z][x] = data[z][x];
@@ -505,7 +503,7 @@ shared_ptr<const CommonItemSet::Table> CommonItemSet::get_table(
try {
return this->tables.at(this->key_for_table(episode, mode, difficulty, secid));
} catch (const out_of_range&) {
throw runtime_error(string_printf("common item table not available for episode=%s, mode=%s, difficulty=%hu, secid=%hu",
throw runtime_error(phosg::string_printf("common item table not available for episode=%s, mode=%s, difficulty=%hu, secid=%hu",
name_for_episode(episode), name_for_mode(mode), difficulty, secid));
}
}
@@ -518,7 +516,7 @@ AFSV2CommonItemSet::AFSV2CommonItemSet(
for (size_t difficulty = 0; difficulty < 4; difficulty++) {
for (size_t section_id = 0; section_id < 10; section_id++) {
auto entry = pt_afs.get(difficulty * 10 + section_id);
StringReader r(entry.first, entry.second);
phosg::StringReader r(entry.first, entry.second);
auto table = make_shared<Table>(r, false, false, Episode::EP1);
this->tables.emplace(this->key_for_table(Episode::EP1, GameMode::NORMAL, difficulty, section_id), table);
this->tables.emplace(this->key_for_table(Episode::EP1, GameMode::BATTLE, difficulty, section_id), table);
@@ -556,7 +554,7 @@ GSLV3V4CommonItemSet::GSLV3V4CommonItemSet(std::shared_ptr<const std::string> gs
default:
throw runtime_error("invalid episode");
}
return string_printf(
return phosg::string_printf(
"ItemPT%s%s%c%1hhu.rel",
is_challenge ? "c" : "",
episode_token,
@@ -568,7 +566,7 @@ GSLV3V4CommonItemSet::GSLV3V4CommonItemSet(std::shared_ptr<const std::string> gs
for (Episode episode : episodes) {
for (size_t difficulty = 0; difficulty < 4; difficulty++) {
for (size_t section_id = 0; section_id < 10; section_id++) {
StringReader r;
phosg::StringReader r;
try {
r = gsl.get_reader(filename_for_table(episode, difficulty, section_id, false));
} catch (const exception&) {
@@ -602,7 +600,7 @@ GSLV3V4CommonItemSet::GSLV3V4CommonItemSet(std::shared_ptr<const std::string> gs
}
}
JSONCommonItemSet::JSONCommonItemSet(const JSON& json) {
JSONCommonItemSet::JSONCommonItemSet(const phosg::JSON& json) {
for (const auto& mode_it : json.as_dict()) {
static const unordered_map<string, GameMode> mode_keys(
{{"Normal", GameMode::NORMAL}, {"Battle", GameMode::BATTLE}, {"Challenge", GameMode::CHALLENGE}, {"Solo", GameMode::SOLO}});
@@ -791,7 +789,7 @@ const ProbabilityTable<uint8_t, 100>& TekkerAdjustmentSet::get_bonus_delta_prob_
}
int8_t TekkerAdjustmentSet::get_luck(uint32_t start_offset, uint8_t delta_index) const {
StringReader sub_r = r.sub(start_offset);
phosg::StringReader sub_r = r.sub(start_offset);
while (!sub_r.eof()) {
const auto& entry = sub_r.get<LuckTableEntry>();
if (entry.delta_index == 0xFF) {
+31 -33
View File
@@ -8,14 +8,15 @@
#include "PSOEncryption.hh"
#include "StaticGameData.hh"
#include "Text.hh"
#include "Types.hh"
class CommonItemSet {
public:
class Table {
public:
Table() = delete;
Table(const JSON& json, Episode episode);
Table(const StringReader& r, bool big_endian, bool is_v3, Episode episode);
Table(const phosg::JSON& json, Episode episode);
Table(const phosg::StringReader& r, bool big_endian, bool is_v3, Episode episode);
template <typename IntT>
struct Range {
@@ -47,18 +48,15 @@ public:
parray<uint8_t, 0x0A> unit_max_stars_table;
parray<parray<uint8_t, 10>, 7> box_item_class_prob_table;
JSON json() const;
phosg::JSON json() const;
void print(FILE* stream) const;
private:
template <bool IsBigEndian>
void parse_itempt_t(const StringReader& r, bool is_v3);
template <bool BE>
void parse_itempt_t(const phosg::StringReader& r, bool is_v3);
template <bool IsBigEndian>
template <bool BE>
struct OffsetsT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
// This data structure uses index probability tables in multiple places. An
// index probability table is a table where each entry holds the probability
// that that entry's index is used. For example, if the armor slot count
@@ -80,7 +78,7 @@ public:
// The indexes in this table correspond to the non-rare weapon types 01
// through 0C (Saber through Wand).
// V2/V3: -> parray<uint8_t, 0x0C>
/* 00 */ U32T base_weapon_type_prob_table_offset;
/* 00 */ U32T<BE> base_weapon_type_prob_table_offset;
// This table specifies the base subtype for each weapon type. Negative
// values here mean that the weapon cannot be found in the first N areas (so
@@ -90,7 +88,7 @@ public:
// of weapon that actually appears depends on this value and a value from
// the following table.
// V2/V3: -> parray<int8_t, 0x0C>
/* 04 */ U32T subtype_base_table_offset;
/* 04 */ U32T<BE> subtype_base_table_offset;
// This table specifies how many areas each weapon subtype appears in. For
// example, if Sword (subtype 02, which is index 1 in this table and the
@@ -99,7 +97,7 @@ public:
// through Mine 1), and Gigush (the next sword subtype) can be found in Mine
// 1 through Ruins 3.
// V2/V3: -> parray<uint8_t, 0x0C>
/* 08 */ U32T subtype_area_length_table_offset;
/* 08 */ U32T<BE> subtype_area_length_table_offset;
// This index probability table specifies how likely each possible grind
// value is. The table is indexed as [grind][subtype_area_index], where the
@@ -114,28 +112,28 @@ public:
// ...
// C1 C2 C3 M1 // (Episode 1 area values from the example for reference)
// V2/V3: -> parray<parray<uint8_t, 4>, 9>
/* 0C */ U32T grind_prob_table_offset;
/* 0C */ U32T<BE> grind_prob_table_offset;
// TODO: Figure out exactly how this table is used. Anchor: 80106D34
// V2/V3: -> parray<uint8_t, 0x05>
/* 10 */ U32T armor_shield_type_index_prob_table_offset;
/* 10 */ U32T<BE> armor_shield_type_index_prob_table_offset;
// This index probability table specifies how common each possible slot
// count is for armor drops.
// V2/V3: -> parray<uint8_t, 0x05>
/* 14 */ U32T armor_slot_count_prob_table_offset;
/* 14 */ U32T<BE> armor_slot_count_prob_table_offset;
// This array (indexed by enemy_type) specifies the range of meseta values
// that each enemy can drop.
// V2/V3: -> parray<Range<U16T>, 0x64>
/* 18 */ U32T enemy_meseta_ranges_offset;
/* 18 */ U32T<BE> enemy_meseta_ranges_offset;
// Each byte in this table (indexed by enemy_type) represents the percent
// chance that the enemy drops anything at all. (This check is done before
// the rare drop check, so the chance of getting a rare item from an enemy
// is essentially this probability multiplied by the rare drop rate.)
// V2/V3: -> parray<uint8_t, 0x64>
/* 1C */ U32T enemy_type_drop_probs_offset;
/* 1C */ U32T<BE> enemy_type_drop_probs_offset;
// Each byte in this table (indexed by enemy_type) represents the class of
// item that the enemy can drop. The values are:
@@ -147,12 +145,12 @@ public:
// 05 = meseta
// Anything else = no item
// V2/V3: -> parray<uint8_t, 0x64>
/* 20 */ U32T enemy_item_classes_offset;
/* 20 */ U32T<BE> enemy_item_classes_offset;
// This table (indexed by area - 1) specifies the ranges of meseta values
// that can drop from boxes.
// V2/V3: -> parray<Range<U16T>, 0x0A>
/* 24 */ U32T box_meseta_ranges_offset;
/* 24 */ U32T<BE> box_meseta_ranges_offset;
// This array specifies the chance that a rare weapon will have each
// possible bonus value. This is indexed as [(bonus_value - 10 / 5)][spec],
@@ -162,7 +160,7 @@ public:
// for rare items, spec is always 5.
// V2: -> parray<parray<uint8_t, 5>, 0x17>
// V3: -> parray<parray<U16T, 6>, 0x17>
/* 28 */ U32T bonus_value_prob_table_offset;
/* 28 */ U32T<BE> bonus_value_prob_table_offset;
// This array specifies the value of spec to be used in the above lookup for
// non-rare items. This is NOT an index probability table; this is a direct
@@ -178,7 +176,7 @@ public:
// bonus; in all other areas except Ruins 3, they can have at most two
// bonuses, and in Ruins 3, they can have up to three bonuses.
// V2/V3: // -> parray<parray<uint8_t, 10>, 3>
/* 2C */ U32T nonrare_bonus_prob_spec_offset;
/* 2C */ U32T<BE> nonrare_bonus_prob_spec_offset;
// This array specifies the chance that a weapon will have each bonus type.
// The table is indexed as [bonus_type][area - 1] for non-rare items; for
@@ -193,37 +191,37 @@ public:
// [00 00 00 00 00 01 01 01 01 01] // Chance of getting Hit bonus
// F1 F2 C1 C2 C3 M1 M2 R1 R2 R3 // (Episode 1 areas, for reference)
// V2/V3: -> parray<parray<uint8_t, 10>, 6>
/* 30 */ U32T bonus_type_prob_table_offset;
/* 30 */ U32T<BE> bonus_type_prob_table_offset;
// This array (indexed by area - 1) specifies a multiplier of used in
// special ability determination. It seems this uses the star values from
// ItemPMT, but not yet clear exactly in what way.
// TODO: Figure out exactly what this does. Anchor: 80106FEC
// V2/V3: -> parray<uint8_t, 0x0A>
/* 34 */ U32T special_mult_offset;
/* 34 */ U32T<BE> special_mult_offset;
// This array (indexed by area - 1) specifies the probability that any
// non-rare weapon will have a special ability.
// V2/V3: -> parray<uint8_t, 0x0A>
/* 38 */ U32T special_percent_offset;
/* 38 */ U32T<BE> special_percent_offset;
// This index probability table is indexed by [tool_class][area - 1]. The
// tool class refers to an entry in ItemPMT, which links it to the actual
// item code.
// V2/V3: -> parray<parray<U16T, 0x0A>, 0x1C>
/* 3C */ U32T tool_class_prob_table_offset;
/* 3C */ U32T<BE> tool_class_prob_table_offset;
// This index probability table determines how likely each technique is to
// appear. The table is indexed as [technique_num][area - 1].
// V2/V3: -> parray<parray<uint8_t, 0x0A>, 0x13>
/* 40 */ U32T technique_index_prob_table_offset;
/* 40 */ U32T<BE> technique_index_prob_table_offset;
// This table specifies the ranges for technique disk levels. The table is
// indexed as [technique_num][area - 1]. If either min or max in the range
// is 0xFF, or if max < min, technique disks are not dropped for that
// technique and area pair.
// V2/V3: -> parray<parray<Range<uint8_t>, 0x0A>, 0x13>
/* 44 */ U32T technique_level_ranges_offset;
/* 44 */ U32T<BE> technique_level_ranges_offset;
/* 48 */ uint8_t armor_or_shield_type_bias;
/* 49 */ parray<uint8_t, 3> unused1;
@@ -234,7 +232,7 @@ public:
// game uniformly chooses a random number of stars in the acceptable
// range, then uniformly chooses a random unit with that many stars.
// V2/V3: -> parray<uint8_t, 0x0A>
/* 4C */ U32T unit_max_stars_offset;
/* 4C */ U32T<BE> unit_max_stars_offset;
// This index probability table determines which type of items drop from
// boxes. The table is indexed as [item_class][area - 1], with item_class
@@ -253,7 +251,7 @@ public:
// [16 16 11 11 11 11 11 0F 0C 0B] // Chances per area of an empty box
// F1 F2 C1 C2 C3 M1 M2 R1 R2 R3 // (Episode 1 areas, for reference)
// V2/V3: -> parray<parray<uint8_t, 10>, 7>
/* 50 */ U32T box_item_class_prob_table_offset;
/* 50 */ U32T<BE> box_item_class_prob_table_offset;
// There are several unused fields here.
} __packed__;
@@ -264,7 +262,7 @@ public:
};
std::shared_ptr<const Table> get_table(Episode episode, GameMode mode, uint8_t difficulty, uint8_t secid) const;
JSON json() const;
phosg::JSON json() const;
void print(FILE* stream) const;
protected:
@@ -287,7 +285,7 @@ public:
class JSONCommonItemSet : public CommonItemSet {
public:
explicit JSONCommonItemSet(const JSON& json);
explicit JSONCommonItemSet(const phosg::JSON& json);
};
// Note: There are clearly better ways of doing this, but this implementation
@@ -348,7 +346,7 @@ public:
protected:
std::shared_ptr<const std::string> data;
StringReader r;
phosg::StringReader r;
struct TableSpec {
be_uint32_t offset;
@@ -463,7 +461,7 @@ private:
int8_t get_luck(uint32_t start_offset, uint8_t delta_index) const;
std::shared_ptr<const std::string> data;
StringReader r;
phosg::StringReader r;
struct DeltaProbabilityEntry {
uint8_t delta_index;
+12 -12
View File
@@ -14,7 +14,7 @@
using namespace std;
template <>
const char* name_for_enum<CompressPhase>(CompressPhase v) {
const char* phosg::name_for_enum<CompressPhase>(CompressPhase v) {
switch (v) {
case CompressPhase::INDEX:
return "INDEX";
@@ -118,7 +118,7 @@ struct WindowIndex {
};
struct LZSSInterleavedWriter {
StringWriter w;
phosg::StringWriter w;
size_t buf_offset;
uint8_t next_control_bit;
uint8_t buf[0x19];
@@ -166,7 +166,7 @@ struct LZSSInterleavedWriter {
class ControlStreamReader {
public:
ControlStreamReader(StringReader& r)
ControlStreamReader(phosg::StringReader& r)
: r(r),
bits(0x0000) {}
@@ -188,7 +188,7 @@ public:
}
private:
StringReader& r;
phosg::StringReader& r;
uint16_t bits;
};
@@ -493,7 +493,7 @@ void PRSCompressor::add(const void* data, size_t size) {
throw logic_error("compressor is closed");
}
StringReader r(data, size);
phosg::StringReader r(data, size);
while (!r.eof()) {
this->add_byte(r.get_u8());
}
@@ -874,8 +874,8 @@ PRSDecompressResult prs_decompress_with_meta(
// is encountered partway through an opcode, we throw instead, because it's
// likely the input has been truncated or is malformed in some way.
StringWriter w;
StringReader r(data, size);
phosg::StringWriter w;
phosg::StringReader r(data, size);
ControlStreamReader cr(r);
while (!r.eof()) {
@@ -959,7 +959,7 @@ string prs_decompress(const string& data, size_t max_output_size, bool allow_unt
size_t prs_decompress_size(const void* data, size_t size, size_t max_output_size, bool allow_unterminated) {
size_t ret = 0;
StringReader r(data, size);
phosg::StringReader r(data, size);
ControlStreamReader cr(r);
while (!r.eof()) {
@@ -1011,7 +1011,7 @@ size_t prs_decompress_size(const string& data, size_t max_output_size, bool allo
void prs_disassemble(FILE* stream, const void* data, size_t size) {
size_t output_bytes = 0;
StringReader r(data, size);
phosg::StringReader r(data, size);
ControlStreamReader cr(r);
while (!r.eof()) {
@@ -1249,8 +1249,8 @@ string bc0_decompress(const string& data) {
}
string bc0_decompress(const void* data, size_t size) {
StringReader r(data, size);
StringWriter w;
phosg::StringReader r(data, size);
phosg::StringWriter w;
// Unlike PRS, BC0 uses a memo which "rolls over" every 0x1000 bytes. The
// boundaries of these "memo pages" are offset by -0x12 bytes for some reason,
@@ -1322,7 +1322,7 @@ void bc0_disassemble(FILE* stream, const string& data) {
}
void bc0_disassemble(FILE* stream, const void* data, size_t size) {
StringReader r(data, size);
phosg::StringReader r(data, size);
uint16_t control_stream_bits = 0x0000;
size_t output_bytes = 0;
+2 -2
View File
@@ -18,7 +18,7 @@ enum class CompressPhase {
};
template <>
const char* name_for_enum<CompressPhase>(CompressPhase v);
const char* phosg::name_for_enum<CompressPhase>(CompressPhase v);
typedef std::function<void(CompressPhase phase, size_t input_progress, size_t input_size, size_t output_size)> ProgressCallback;
@@ -146,7 +146,7 @@ private:
WrappedLog<0x101> forward_log;
IndexedLog<0x2000> reverse_log;
StringWriter output;
phosg::StringWriter output;
};
// These functions use PRSCompressor to compress a buffer of data. This is
+20 -20
View File
@@ -1174,7 +1174,7 @@ static uint64_t decode_dc_serial_number_str(const string& s) {
if (new_ch == '\0') {
return INVALID_PRODUCT;
}
serial_number = (serial_number << 4) | value_for_hex_char(new_ch);
serial_number = (serial_number << 4) | phosg::value_for_hex_char(new_ch);
}
return serial_number;
}
@@ -1291,12 +1291,12 @@ string generate_dc_serial_number(uint8_t domain, uint8_t subdomain) {
throw runtime_error("invalid domain");
}
size_t det1 = (subdomain == 0xFF) ? random_object<uint32_t>() : subdomain;
size_t det1 = (subdomain == 0xFF) ? phosg::random_object<uint32_t>() : subdomain;
size_t index1 = offset1 + (det1 % (limit1 - offset1));
size_t index2 = random_object<uint32_t>() % (sizeof(primes2) / sizeof(primes2[0]));
size_t index3 = random_object<uint32_t>() % (sizeof(primes3) / sizeof(primes3[0]));
size_t index2 = phosg::random_object<uint32_t>() % (sizeof(primes2) / sizeof(primes2[0]));
size_t index3 = phosg::random_object<uint32_t>() % (sizeof(primes3) / sizeof(primes3[0]));
uint32_t value = primes1[index1] * primes2[index2] * primes3[index3];
string s = string_printf("%08X", value);
string s = phosg::string_printf("%08X", value);
string ret;
for (char ch : s) {
@@ -1355,7 +1355,7 @@ unordered_map<uint32_t, string> generate_all_dc_serial_numbers(uint8_t domain, u
}
void dc_serial_number_speed_test(uint64_t seed) {
uint32_t effective_seed = (seed & 0xFFFFFFFF00000000) ? random_object<uint32_t>() : seed;
uint32_t effective_seed = (seed & 0xFFFFFFFF00000000) ? phosg::random_object<uint32_t>() : seed;
fprintf(stderr, "Product speed test with seed=%08" PRIX32 "\n", effective_seed);
PSOV2Encryption crypt(effective_seed);
uint64_t time_slow = 0;
@@ -1363,15 +1363,15 @@ void dc_serial_number_speed_test(uint64_t seed) {
size_t num_disagreements = 0;
static constexpr size_t count = 0x1000;
for (size_t z = 0; z < count; z++) {
string s = string_printf("%08X", crypt.next());
string s = phosg::string_printf("%08X", crypt.next());
uint64_t start = now();
uint64_t start = phosg::now();
bool is_valid_fast = dc_serial_number_is_valid_fast(s, 1, 0xFF);
time_fast += now() - start;
time_fast += phosg::now() - start;
start = now();
start = phosg::now();
bool is_valid_slow = dc_serial_number_is_valid_slow(s, 1, 0xFF);
time_slow += now() - start;
time_slow += phosg::now() - start;
if (((z & 0xF) == 0) || is_valid_slow || is_valid_fast) {
fprintf(stderr, "... %02zX: %s => %s %s%s\n", z, s.c_str(), is_valid_slow ? "SLOW" : "----", is_valid_fast ? "FAST" : "----", is_valid_slow != is_valid_fast ? " !!!" : "");
@@ -1391,13 +1391,13 @@ string decrypt_dp_address_jpn(
const string& executable,
const string& values,
const string& indexes) {
StringReader values_r(values);
StringReader indexes_r(indexes);
phosg::StringReader values_r(values);
phosg::StringReader indexes_r(indexes);
size_t fixup_values_offset = values_r.pget_u32l(0x3FFC) - 0x8C004000;
size_t fixup_steps_offset = indexes_r.pget_u32l(0x3BFC) - 0x8C008400;
StringReader fixup_values_r = values_r.sub(fixup_values_offset);
StringReader fixup_steps_r = indexes_r.sub(fixup_steps_offset);
phosg::StringReader fixup_values_r = values_r.sub(fixup_values_offset);
phosg::StringReader fixup_steps_r = indexes_r.sub(fixup_steps_offset);
auto decrypted = decrypt_pr2_data<false>(executable);
size_t fixup_offset = 0;
@@ -1417,9 +1417,9 @@ EncryptedDCv2Executables encrypt_dp_address_jpn(const string& executable, const
EncryptedDCv2Executables ret;
string compressed = prs_compress(executable);
ret.executable = encrypt_pr2_data<false>(compressed, executable.size(), random_object<uint32_t>() & 0x7FFFFF7F);
ret.executable = encrypt_pr2_data<false>(compressed, executable.size(), phosg::random_object<uint32_t>() & 0x7FFFFF7F);
StringReader indexes_r(indexes);
phosg::StringReader indexes_r(indexes);
size_t fixup_steps_offset = indexes_r.pget_u32l(0x3BFC) - 0x8C008400;
ret.indexes = indexes;
ret.indexes.at(fixup_steps_offset) = 0;
@@ -1431,7 +1431,7 @@ std::string crypt_dp_address_jpn_simple(const std::string& data, int64_t mask_ke
throw runtime_error("size is not a multiple of 4");
}
StringReader r(data);
phosg::StringReader r(data);
if (mask_key < 0) {
unordered_map<uint32_t, size_t> key_freq;
while (!r.eof()) {
@@ -1447,11 +1447,11 @@ std::string crypt_dp_address_jpn_simple(const std::string& data, int64_t mask_ke
if (mask_key < 0) {
throw runtime_error("cannot determine mask key");
}
log_info("Determined %08" PRIX64 " to be the most likely mask key", mask_key);
phosg::log_info("Determined %08" PRIX64 " to be the most likely mask key", mask_key);
r.go(0);
}
StringWriter w;
phosg::StringWriter w;
while (!r.eof()) {
w.put_u32l(r.get_u32l() ^ mask_key);
}
+5 -5
View File
@@ -34,15 +34,15 @@ DNSServer::~DNSServer() {
}
void DNSServer::listen(const std::string& socket_path) {
this->add_socket(::listen(socket_path, 0, 0));
this->add_socket(phosg::listen(socket_path, 0, 0));
}
void DNSServer::listen(const std::string& addr, int port) {
this->add_socket(::listen(addr, port, 0));
this->add_socket(phosg::listen(addr, port, 0));
}
void DNSServer::listen(int port) {
this->add_socket(::listen("", port, 0));
this->add_socket(phosg::listen("", port, 0));
}
void DNSServer::add_socket(int fd) {
@@ -66,7 +66,7 @@ string DNSServer::response_for_query(const void* vdata, size_t size, uint32_t re
const char* data = reinterpret_cast<const char*>(vdata);
size_t name_len = strlen(&data[12]) + 1;
be_uint32_t be_resolved_address = resolved_address;
phosg::be_uint32_t be_resolved_address = resolved_address;
string response;
response.append(data, 2);
@@ -104,7 +104,7 @@ void DNSServer::on_receive_message(int fd, short) {
} else if (bytes < 0x0C) {
dns_server_log.warning("input query too small");
print_data(stderr, input.data(), bytes);
phosg::print_data(stderr, input.data(), bytes);
} else if (!this->banned_ipv4_ranges->check(remote)) {
input.resize(bytes);
+6 -6
View File
@@ -10,7 +10,7 @@
using namespace std;
template <>
const char* name_for_enum<EnemyType>(EnemyType type) {
const char* phosg::name_for_enum<EnemyType>(EnemyType type) {
switch (type) {
case EnemyType::UNKNOWN:
return "UNKNOWN";
@@ -274,7 +274,7 @@ const char* name_for_enum<EnemyType>(EnemyType type) {
}
template <>
EnemyType enum_for_name<EnemyType>(const char* name) {
EnemyType phosg::enum_for_name<EnemyType>(const char* name) {
static const unordered_map<string, EnemyType> names({
{"UNKNOWN", EnemyType::UNKNOWN},
{"NONE", EnemyType::NONE},
@@ -672,7 +672,7 @@ uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type)
case EnemyType::SO_DIMENIAN:
return 0x55;
default:
throw runtime_error(string_printf("%s does not have battle parameters in Episode 1", name_for_enum(enemy_type)));
throw runtime_error(phosg::string_printf("%s does not have battle parameters in Episode 1", phosg::name_for_enum(enemy_type)));
}
break;
case Episode::EP2:
@@ -787,7 +787,7 @@ uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type)
case EnemyType::SO_DIMENIAN:
return 0x55;
default:
throw runtime_error(string_printf("%s does not have battle parameters in Episode 2", name_for_enum(enemy_type)));
throw runtime_error(phosg::string_printf("%s does not have battle parameters in Episode 2", phosg::name_for_enum(enemy_type)));
}
break;
case Episode::EP4:
@@ -847,7 +847,7 @@ uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type)
case EnemyType::KONDRIEU:
return 0x2A;
default:
throw runtime_error(string_printf("%s does not have battle parameters in Episode 4", name_for_enum(enemy_type)));
throw runtime_error(phosg::string_printf("%s does not have battle parameters in Episode 4", phosg::name_for_enum(enemy_type)));
}
break;
default:
@@ -1072,7 +1072,7 @@ uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type) {
case EnemyType::ZU_ALT:
return 0x4A;
default:
throw runtime_error(string_printf("%s does not have a rare table entry", name_for_enum(enemy_type)));
throw runtime_error(phosg::string_printf("%s does not have a rare table entry", phosg::name_for_enum(enemy_type)));
}
}
+3 -2
View File
@@ -5,6 +5,7 @@
#include <phosg/Tools.hh>
#include "StaticGameData.hh"
#include "Types.hh"
enum class EnemyType {
UNKNOWN = -1,
@@ -138,9 +139,9 @@ enum class EnemyType {
};
template <>
const char* name_for_enum<EnemyType>(EnemyType type);
const char* phosg::name_for_enum<EnemyType>(EnemyType type);
template <>
EnemyType enum_for_name<EnemyType>(const char* name);
EnemyType phosg::enum_for_name<EnemyType>(const char* name);
bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type);
uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type);
+25 -26
View File
@@ -12,10 +12,10 @@ namespace Episode3 {
void BattleRecord::PlayerEntry::print(FILE* stream) const {
// TODO: Format this nicely somehow. Maybe factor out the functions in
// QuestScript that format some of these structures
print_data(stream, this, sizeof(*this), 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stream, this, sizeof(*this), 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
}
BattleRecord::Event::Event(StringReader& r) {
BattleRecord::Event::Event(phosg::StringReader& r) {
this->type = r.get<Event::Type>();
this->timestamp = r.get_u64l();
switch (this->type) {
@@ -46,7 +46,7 @@ BattleRecord::Event::Event(StringReader& r) {
}
}
void BattleRecord::Event::serialize(StringWriter& w) const {
void BattleRecord::Event::serialize(phosg::StringWriter& w) const {
w.put(this->type);
w.put_u64l(this->timestamp);
switch (this->type) {
@@ -81,7 +81,7 @@ void BattleRecord::Event::serialize(StringWriter& w) const {
}
void BattleRecord::Event::print(FILE* stream) const {
string time_str = format_time(this->timestamp);
string time_str = phosg::format_time(this->timestamp);
fprintf(stream, "Event @%016" PRIX64 " (%s) ", this->timestamp, time_str.c_str());
switch (this->type) {
case Type::PLAYER_JOIN:
@@ -103,23 +103,23 @@ void BattleRecord::Event::print(FILE* stream) const {
break;
case Type::BATTLE_COMMAND:
fprintf(stream, "BATTLE_COMMAND\n");
print_data(stream, this->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
break;
case Type::GAME_COMMAND:
fprintf(stream, "GAME_COMMAND\n");
print_data(stream, this->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
break;
case Type::EP3_GAME_COMMAND:
fprintf(stream, "EP3_GAME_COMMAND\n");
print_data(stream, this->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
break;
case Type::CHAT_MESSAGE:
fprintf(stream, "CHAT_MESSAGE %08" PRIX32 "\n", this->guild_card_number);
print_data(stream, this->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
break;
case Type::SERVER_DATA_COMMAND:
fprintf(stream, "SERVER_DATA_COMMAND\n");
print_data(stream, this->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
break;
default:
throw runtime_error("unknown event type in battle record");
@@ -137,7 +137,7 @@ BattleRecord::BattleRecord(const string& data)
behavior_flags(0),
battle_start_timestamp(0),
battle_end_timestamp(0) {
StringReader r(data);
phosg::StringReader r(data);
uint64_t signature = r.get_u64l();
bool has_random_stream;
@@ -161,7 +161,7 @@ BattleRecord::BattleRecord(const string& data)
}
string BattleRecord::serialize() const {
StringWriter w;
phosg::StringWriter w;
w.put_u64l(this->SIGNATURE_V2);
w.put_u64l(this->battle_start_timestamp);
w.put_u64l(this->battle_end_timestamp);
@@ -202,7 +202,7 @@ void BattleRecord::add_player(
}
Event& ev = this->events.emplace_back();
ev.type = Event::Type::PLAYER_JOIN;
ev.timestamp = now();
ev.timestamp = phosg::now();
auto& player = ev.players.emplace_back();
player.lobby_data = lobby_data;
player.inventory = inventory;
@@ -216,7 +216,7 @@ void BattleRecord::delete_player(uint8_t client_id) {
}
Event& ev = this->events.emplace_back();
ev.type = Event::Type::PLAYER_LEAVE;
ev.timestamp = now();
ev.timestamp = phosg::now();
ev.leaving_client_id = client_id;
}
@@ -226,7 +226,7 @@ void BattleRecord::add_command(Event::Type type, const void* data, size_t size)
}
Event& ev = this->events.emplace_back();
ev.type = type;
ev.timestamp = now();
ev.timestamp = phosg::now();
ev.data.assign(reinterpret_cast<const char*>(data), size);
}
@@ -236,7 +236,7 @@ void BattleRecord::add_command(Event::Type type, string&& data) {
}
Event& ev = this->events.emplace_back();
ev.type = type;
ev.timestamp = now();
ev.timestamp = phosg::now();
ev.data = std::move(data);
}
@@ -247,7 +247,7 @@ void BattleRecord::add_chat_message(
}
Event& ev = this->events.emplace_back();
ev.type = Event::Type::CHAT_MESSAGE;
ev.timestamp = now();
ev.timestamp = phosg::now();
ev.guild_card_number = guild_card_number;
ev.data = std::move(data);
}
@@ -287,7 +287,7 @@ void BattleRecord::set_battle_start_timestamp() {
if (this->battle_start_timestamp != 0) {
throw logic_error("battle start timestamp is already set");
}
this->battle_start_timestamp = now();
this->battle_start_timestamp = phosg::now();
// First, find the correct map definition subcommand to keep, and execute
// player join/leave events to get the present players
@@ -357,12 +357,12 @@ void BattleRecord::set_battle_start_timestamp() {
}
void BattleRecord::set_battle_end_timestamp() {
this->battle_end_timestamp = now();
this->battle_end_timestamp = phosg::now();
}
void BattleRecord::print(FILE* stream) const {
string start_str = format_time(this->battle_start_timestamp);
string end_str = format_time(this->battle_end_timestamp);
string start_str = phosg::format_time(this->battle_start_timestamp);
string end_str = phosg::format_time(this->battle_end_timestamp);
fprintf(stream, "BattleRecord %s behavior_flags=%08" PRIX32 " start=%016" PRIX64 " (%s) end=%016" PRIX64 " (%s); %zu events\n",
this->is_writable ? "writable" : "read-only",
this->behavior_flags,
@@ -394,13 +394,12 @@ void BattleRecordPlayer::set_lobby(shared_ptr<Lobby> l) {
void BattleRecordPlayer::start() {
if (this->play_start_timestamp == 0) {
this->play_start_timestamp = now();
this->play_start_timestamp = phosg::now();
this->schedule_events();
}
}
void BattleRecordPlayer::dispatch_schedule_events(
evutil_socket_t, short, void* ctx) {
void BattleRecordPlayer::dispatch_schedule_events(evutil_socket_t, short, void* ctx) {
reinterpret_cast<BattleRecordPlayer*>(ctx)->schedule_events();
}
@@ -413,7 +412,7 @@ void BattleRecordPlayer::schedule_events() {
}
for (;;) {
uint64_t relative_ts = now() - this->play_start_timestamp + this->record->battle_start_timestamp;
uint64_t relative_ts = phosg::now() - this->play_start_timestamp + this->record->battle_start_timestamp;
if (this->event_it == this->record->events.end()) {
if (relative_ts >= this->record->battle_end_timestamp) {
@@ -426,7 +425,7 @@ void BattleRecordPlayer::schedule_events() {
} else {
// There are no more events to play, but the battle has not officially
// ended yet - reschedule the event for the end time
auto tv = usecs_to_timeval(this->record->battle_end_timestamp - relative_ts);
auto tv = phosg::usecs_to_timeval(this->record->battle_end_timestamp - relative_ts);
event_add(this->next_command_ev.get(), &tv);
}
break;
@@ -467,7 +466,7 @@ void BattleRecordPlayer::schedule_events() {
} else {
// The next event should not occur yet, so reschedule for the time when
// it should occur
auto tv = usecs_to_timeval(this->event_it->timestamp - relative_ts);
auto tv = phosg::usecs_to_timeval(this->event_it->timestamp - relative_ts);
event_add(this->next_command_ev.get(), &tv);
break;
}
+3 -3
View File
@@ -53,8 +53,8 @@ public:
std::string data;
Event() = default;
explicit Event(StringReader& r);
void serialize(StringWriter& w) const;
explicit Event(phosg::StringReader& r);
void serialize(phosg::StringWriter& w) const;
void print(FILE* stream) const;
};
@@ -126,7 +126,7 @@ private:
std::shared_ptr<struct event_base> base;
std::weak_ptr<Lobby> lobby;
std::shared_ptr<struct event> next_command_ev;
StringReader random_r;
phosg::StringReader random_r;
};
} // namespace Episode3
+9 -9
View File
@@ -123,7 +123,7 @@ ssize_t Card::apply_abnormal_condition(
int8_t dice_roll_value,
int8_t random_percent) {
auto s = this->server();
auto log = s->log_stack(string_printf("apply_abnormal_condition(%02hhX, @%04X, @%04X, %hd, %hhd, %hhd): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
auto log = s->log_stack(phosg::string_printf("apply_abnormal_condition(%02hhX, @%04X, @%04X, %hd, %hhd, %hhd): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
bool is_nte = s->options.is_nte();
ssize_t existing_cond_index;
@@ -298,7 +298,7 @@ void Card::commit_attack(
size_t strike_number,
int16_t* out_effective_damage) {
auto s = this->server();
auto log = s->log_stack(string_printf("commit_attack(@%04hX #%04hX, @%04hX #%04hX => %hd (str%zu)): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id(), damage, strike_number));
auto log = s->log_stack(phosg::string_printf("commit_attack(@%04hX #%04hX, @%04hX #%04hX => %hd (str%zu)): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id(), damage, strike_number));
bool is_nte = s->options.is_nte();
int16_t effective_damage = damage;
@@ -507,7 +507,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
}
auto s = this->server();
auto log = s->log_stack(string_printf("execute_attack(@%04X #%04X, @%04X #%04X): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id()));
auto log = s->log_stack(phosg::string_printf("execute_attack(@%04X #%04X, @%04X #%04X): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id()));
bool is_nte = s->options.is_nte();
this->card_flags &= 0xFFFFFFF3;
@@ -905,7 +905,7 @@ void Card::clear_action_chain_and_metadata_and_most_flags() {
void Card::compute_action_chain_results(bool apply_action_conditions, bool ignore_this_card_ap_tp) {
auto s = this->server();
auto log = s->log_stack(string_printf("compute_action_chain_results(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
auto log = s->log_stack(phosg::string_printf("compute_action_chain_results(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
bool is_nte = s->options.is_nte();
this->action_chain.compute_attack_medium(s);
@@ -914,7 +914,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
this->action_chain.chain.tp_effect_bonus = 0;
log.debug("(initial) medium=%s, strike_count=%hhu, ap_effect_bonus=%hhd, tp_effect_bonus=%hhd",
name_for_enum(this->action_chain.chain.attack_medium),
phosg::name_for_enum(this->action_chain.chain.attack_medium),
this->action_chain.chain.strike_count,
this->action_chain.chain.ap_effect_bonus,
this->action_chain.chain.tp_effect_bonus);
@@ -1220,7 +1220,7 @@ void Card::move_phase_before() {
void Card::unknown_80236374(shared_ptr<Card> other_card, const ActionState* as) {
auto s = this->server();
auto log = s->log_stack(string_printf("unknown_80236374(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id()));
auto log = s->log_stack(phosg::string_printf("unknown_80236374(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id()));
auto check_card = [&](shared_ptr<Card> card) -> void {
if (card) {
@@ -1361,8 +1361,8 @@ bool Card::is_guard_item() const {
bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as) {
auto s = this->server();
auto log = s->log_stack(other_card
? string_printf("unknown_80236554(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id())
: string_printf("unknown_80236554(@%04hX #%04hX, null): ", this->get_card_ref(), this->get_card_id()));
? phosg::string_printf("unknown_80236554(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id())
: phosg::string_printf("unknown_80236554(@%04hX #%04hX, null): ", this->get_card_ref(), this->get_card_id()));
if (as) {
string as_str = as->str(s);
log.debug("as = %s", as_str.c_str());
@@ -1439,7 +1439,7 @@ void Card::apply_attack_result() {
auto ps = this->player_state();
bool is_nte = s->options.is_nte();
auto log = s->log_stack(string_printf("apply_attack_result(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
auto log = s->log_stack(phosg::string_printf("apply_attack_result(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
if (!this->action_chain.can_apply_attack()) {
return;
}
+20 -21
View File
@@ -21,7 +21,7 @@ static string refs_str_for_cards_vector(const vector<shared_ptr<T>>& cards) {
if (!ret.empty()) {
ret += ", ";
}
ret += string_printf("@%04hX", ref_for_card(card));
ret += phosg::string_printf("@%04hX", ref_for_card(card));
}
return ret;
}
@@ -453,7 +453,7 @@ bool CardSpecial::apply_stat_deltas_to_all_cards_from_all_conditions_with_card_r
bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condition& cond, shared_ptr<Card> card) {
auto s = this->server();
auto log = s->log_stack(string_printf("apply_stat_deltas_to_card_from_condition_and_clear_cond(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
auto log = s->log_stack(phosg::string_printf("apply_stat_deltas_to_card_from_condition_and_clear_cond(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
bool is_nte = s->options.is_nte();
string cond_str = cond.str(s);
@@ -585,7 +585,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
break;
trial_unimplemented:
default:
log.debug("%s: no adjustments for condition type", name_for_enum(cond_type));
log.debug("%s: no adjustments for condition type", phosg::name_for_enum(cond_type));
break;
}
@@ -1189,7 +1189,7 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
StatSwapType CardSpecial::compute_stat_swap_type(shared_ptr<const Card> card) const {
auto s = this->server();
auto log = s->log_stack(string_printf("compute_stat_swap_type(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
auto log = s->log_stack(phosg::string_printf("compute_stat_swap_type(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
if (!card) {
log.debug("card is missing");
return StatSwapType::NONE;
@@ -1199,7 +1199,7 @@ StatSwapType CardSpecial::compute_stat_swap_type(shared_ptr<const Card> card) co
for (size_t cond_index = 0; cond_index < 9; cond_index++) {
auto& cond = card->action_chain.conditions[cond_index];
if (cond.type != ConditionType::NONE) {
auto cond_log = log.sub(string_printf("(%zu) ", cond_index));
auto cond_log = log.sub(phosg::string_printf("(%zu) ", cond_index));
string cond_str = cond.str(s);
cond_log.debug("%s", cond_str.c_str());
if (!this->card_ref_has_ability_trap(cond)) {
@@ -1675,7 +1675,7 @@ int32_t CardSpecial::evaluate_effect_expr(
const char* expr,
DiceRoll& dice_roll) const {
auto log = this->server()->log_stack("evaluate_effect_expr: ");
if (log.min_level == LogLevel::DEBUG) {
if (log.min_level == phosg::LogLevel::DEBUG) {
log.debug("ast, expr=\"%s\", dice_roll=(client_id=%02hhX, a2=%02hhX, value=%02hhX, value_used_in_expr=%s, a5=%04hX)", expr, dice_roll.client_id, dice_roll.unknown_a2, dice_roll.value, dice_roll.value_used_in_expr ? "true" : "false", dice_roll.unknown_a5);
ast.print(stderr);
}
@@ -1769,10 +1769,10 @@ bool CardSpecial::execute_effect(
uint32_t unknown_p7,
uint16_t attacker_card_ref) {
auto s = this->server();
auto log = s->log_stack(string_printf("execute_effect(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
auto log = s->log_stack(phosg::string_printf("execute_effect(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
{
string cond_str = cond.str(s);
log.debug("cond=%s, card=@%04hX, expr_value=%hd, unknown_p5=%hd, cond_type=%s, unknown_p7=%" PRIu32 ", attacker_card_ref=@%04hX", cond_str.c_str(), ref_for_card(card), expr_value, unknown_p5, name_for_enum(cond_type), unknown_p7, attacker_card_ref);
log.debug("cond=%s, card=@%04hX, expr_value=%hd, unknown_p5=%hd, cond_type=%s, unknown_p7=%" PRIu32 ", attacker_card_ref=@%04hX", cond_str.c_str(), ref_for_card(card), expr_value, unknown_p5, phosg::name_for_enum(cond_type), unknown_p7, attacker_card_ref);
}
bool is_nte = s->options.is_nte();
@@ -2804,7 +2804,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
int16_t p_target_type,
bool apply_usability_filters) const {
auto s = this->server();
auto log = s->log_stack(string_printf("get_targeted_cards_for_condition(@%04hX, %hhu, @%04hX): ", card_ref, def_effect_index, setter_card_ref));
auto log = s->log_stack(phosg::string_printf("get_targeted_cards_for_condition(@%04hX, %hhu, @%04hX): ", card_ref, def_effect_index, setter_card_ref));
log.debug("card_ref=@%04hX, def_effect_index=%02hhX, setter_card_ref=@%04hX, as, p_target_type=%hd, apply_usability_filters=%s", card_ref, def_effect_index, setter_card_ref, p_target_type, apply_usability_filters ? "true" : "false");
vector<shared_ptr<const Card>> ret;
@@ -2836,7 +2836,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
AttackMedium attack_medium = card2
? card2->action_chain.chain.attack_medium
: AttackMedium::UNKNOWN;
log.debug("attack_medium=%s", name_for_enum(attack_medium));
log.debug("attack_medium=%s", phosg::name_for_enum(attack_medium));
auto add_card_refs = [&](const vector<uint16_t>& result_card_refs) -> void {
for (uint16_t result_card_ref : result_card_refs) {
@@ -3944,13 +3944,13 @@ void CardSpecial::evaluate_and_apply_effects(
bool apply_defense_condition_to_all_cards,
uint16_t apply_defense_condition_to_card_ref) {
auto s = this->server();
auto log = s->log_stack(string_printf("evaluate_and_apply_effects(%s, @%04hX, @%04hX): ", name_for_enum(when), set_card_ref, sc_card_ref));
auto log = s->log_stack(phosg::string_printf("evaluate_and_apply_effects(%s, @%04hX, @%04hX): ", phosg::name_for_enum(when), set_card_ref, sc_card_ref));
bool is_nte = s->options.is_nte();
{
string as_str = as.str(s);
log.debug("when=%s, set_card_ref=@%04hX, as=%s, sc_card_ref=@%04hX, apply_defense_condition_to_all_cards=%s, apply_defense_condition_to_card_ref=@%04hX",
name_for_enum(when), set_card_ref, as_str.c_str(), sc_card_ref, apply_defense_condition_to_all_cards ? "true" : "false", apply_defense_condition_to_card_ref);
phosg::name_for_enum(when), set_card_ref, as_str.c_str(), sc_card_ref, apply_defense_condition_to_all_cards ? "true" : "false", apply_defense_condition_to_card_ref);
}
if (!is_nte) {
@@ -4010,12 +4010,12 @@ void CardSpecial::evaluate_and_apply_effects(
log.debug("inputs: dice_roll=%02hhX, random_percent=%hhu, unknown_v1=%s", dice_roll.value, random_percent, unknown_v1 ? "true" : "false");
for (size_t def_effect_index = 0; (def_effect_index < 3) && !unknown_v1 && (ce->def.effects[def_effect_index].type != ConditionType::NONE); def_effect_index++) {
auto effect_log = log.sub(string_printf("(effect:%zu) ", def_effect_index));
auto effect_log = log.sub(phosg::string_printf("(effect:%zu) ", def_effect_index));
const auto& card_effect = ce->def.effects[def_effect_index];
string card_effect_str = card_effect.str();
effect_log.debug("effect: %s", card_effect_str.c_str());
if (card_effect.when != when) {
effect_log.debug("does not apply (effect.when=%s, when=%s)", name_for_enum(card_effect.when), name_for_enum(when));
effect_log.debug("does not apply (effect.when=%s, when=%s)", phosg::name_for_enum(card_effect.when), phosg::name_for_enum(when));
continue;
}
@@ -4067,7 +4067,7 @@ void CardSpecial::evaluate_and_apply_effects(
}
for (size_t z = 0; z < targeted_cards.size(); z++) {
auto target_log = effect_log.sub(string_printf("(target:@%04hX) ", targeted_cards[z]->get_card_ref()));
auto target_log = effect_log.sub(phosg::string_printf("(target:@%04hX) ", targeted_cards[z]->get_card_ref()));
dice_roll.value_used_in_expr = false;
string arg2_str = card_effect.arg2.decode();
target_log.debug("arg2_str = %s", arg2_str.c_str());
@@ -4075,8 +4075,7 @@ void CardSpecial::evaluate_and_apply_effects(
this->evaluate_effect_arg2_condition(
as, targeted_cards[z], arg2_str.c_str(), dice_roll, set_card_ref, sc_card_ref, random_percent, when)) {
target_log.debug("arg2 condition passed");
auto env_stats = this->compute_attack_env_stats(
as, targeted_cards[z], dice_roll, set_card_ref, sc_card_ref);
auto env_stats = this->compute_attack_env_stats(as, targeted_cards[z], dice_roll, set_card_ref, sc_card_ref);
string expr_str = card_effect.expr.decode();
int16_t value = this->evaluate_effect_expr(env_stats, expr_str.c_str(), dice_roll);
target_log.debug("expr = %s, value = %hd", expr_str.c_str(), value);
@@ -4767,7 +4766,7 @@ void CardSpecial::dice_phase_before_for_card(shared_ptr<Card> card) {
template <EffectWhen When1, EffectWhen When2>
void CardSpecial::apply_effects_on_phase_change_t(shared_ptr<Card> unknown_p2, const ActionState* existing_as) {
auto s = this->server();
auto log = s->log_stack(string_printf("apply_effects_on_phase_change_t<%s, %s>(@%04hX #%04hX): ", name_for_enum(When1), name_for_enum(When2), unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
auto log = s->log_stack(phosg::string_printf("apply_effects_on_phase_change_t<%s, %s>(@%04hX #%04hX): ", phosg::name_for_enum(When1), phosg::name_for_enum(When2), unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
bool is_nte = s->options.is_nte();
ActionState as;
@@ -4818,7 +4817,7 @@ void CardSpecial::unknown_8024945C(shared_ptr<Card> unknown_p2, const ActionStat
}
void CardSpecial::unknown_8024966C(shared_ptr<Card> unknown_p2, const ActionState* existing_as) {
auto log = this->server()->log_stack(string_printf("unknown_8024966C(@%04hX #%04hX): ", unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
auto log = this->server()->log_stack(phosg::string_printf("unknown_8024966C(@%04hX #%04hX): ", unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
ActionState as;
if (!existing_as) {
@@ -4969,8 +4968,8 @@ template <
EffectWhen WhenTargetsAndActionCards>
void CardSpecial::apply_effects_before_or_after_attack(shared_ptr<Card> unknown_p2) {
auto s = this->server();
auto log = s->log_stack(string_printf("apply_effects_before_or_after_attack<%s, %s, %s, %s>(@%04hX #%04hX): ",
name_for_enum(WhenAllCards), name_for_enum(WhenAttackerAndActionCards), name_for_enum(WhenAttackerOrHunterSCCard), name_for_enum(WhenTargetsAndActionCards), unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
auto log = s->log_stack(phosg::string_printf("apply_effects_before_or_after_attack<%s, %s, %s, %s>(@%04hX #%04hX): ",
phosg::name_for_enum(WhenAllCards), phosg::name_for_enum(WhenAttackerAndActionCards), phosg::name_for_enum(WhenAttackerOrHunterSCCard), phosg::name_for_enum(WhenTargetsAndActionCards), unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
ActionState as = this->create_attack_state_from_card_action_chain(unknown_p2);
File diff suppressed because it is too large Load Diff
+30 -29
View File
@@ -16,6 +16,7 @@
#include "../PlayerSubordinates.hh"
#include "../Text.hh"
#include "../TextIndex.hh"
#include "../Types.hh"
namespace Episode3 {
@@ -506,7 +507,7 @@ struct CardDefinition {
void decode_code();
std::string str() const;
JSON json() const;
phosg::JSON json() const;
} __packed_ws__(Stat, 4);
struct Effect {
@@ -543,7 +544,7 @@ struct CardDefinition {
bool is_empty() const;
static std::string str_for_arg(const std::string& arg);
std::string str(const char* separator = ", ", const TextSet* text_archive = nullptr) const;
JSON json() const;
phosg::JSON json() const;
} __packed_ws__(Effect, 0x20);
/* 0000 */ be_uint32_t card_id;
@@ -810,7 +811,7 @@ struct CardDefinition {
void decode_range();
std::string str(bool single_line = true, const TextSet* text_archive = nullptr) const;
JSON json() const;
phosg::JSON json() const;
} __packed_ws__(CardDefinition, 0x128);
struct CardDefinitionsFooter {
@@ -1029,8 +1030,8 @@ struct Rules {
// likely be more work than it's worth.
Rules() = default;
explicit Rules(const JSON& json);
JSON json() const;
explicit Rules(const phosg::JSON& json);
phosg::JSON json() const;
bool operator==(const Rules& other) const = default;
bool operator!=(const Rules& other) const = default;
void clear();
@@ -1225,7 +1226,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
/* 48 */
std::string str() const;
JSON json() const;
phosg::JSON json() const;
} __packed_ws__(CameraSpec, 0x48);
// This array specifies the camera zone maps. A camera zone map is a subset of
@@ -1283,7 +1284,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
/* 00 */ pstring<TextEncoding::MARKED, 0x18> deck_name;
/* 18 */ parray<be_uint16_t, 0x20> card_ids; // Last one appears to always be FFFF
/* 58 */
JSON json(uint8_t language) const;
phosg::JSON json(uint8_t language) const;
} __packed_ws__(NPCDeck, 0x58);
/* 1FE8 */ parray<NPCDeck, 3> npc_decks; // Unused if name[0] == 0
@@ -1299,7 +1300,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
// TODO: Figure out exactly how these are used and document here.
/* 0018 */ parray<be_uint16_t, 0x7E> params;
/* 0114 */
JSON json(uint8_t language) const;
phosg::JSON json(uint8_t language) const;
} __packed_ws__(AIParams, 0x114);
/* 20F0 */ parray<AIParams, 3> npc_ai_params; // Unused if name[0] == 0
@@ -1352,7 +1353,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
// strings, excluding any that are empty or begin with the character '^'.
/* 0004 */ parray<pstring<TextEncoding::MARKED, 0x40>, 4> strings;
/* 0104 */
JSON json(uint8_t language) const;
phosg::JSON json(uint8_t language) const;
} __packed_ws__(DialogueSet, 0x104);
// There are up to 0x10 of these per valid NPC, but only the first 13 of them
@@ -1435,7 +1436,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
bool operator==(const EntryState& other) const = default;
bool operator!=(const EntryState& other) const = default;
JSON json() const;
phosg::JSON json() const;
} __packed_ws__(EntryState, 2);
/* 5A10 */ parray<EntryState, 4> entry_states;
/* 5A18 */
@@ -1451,7 +1452,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
void assert_semantically_equivalent(const MapDefinition& other) const;
std::string str(const CardIndex* card_index, uint8_t language) const;
JSON json(uint8_t language) const;
phosg::JSON json(uint8_t language) const;
} __packed_ws__(MapDefinition, 0x5A18);
struct MapDefinitionTrial {
@@ -1534,7 +1535,7 @@ public:
std::shared_ptr<const CardEntry> definition_for_name_normalized(const std::string& name) const;
std::set<uint32_t> all_ids() const;
uint64_t definitions_mtime() const;
JSON definitions_json() const;
phosg::JSON definitions_json() const;
private:
static std::string normalize_card_name(const std::string& name);
@@ -1615,37 +1616,37 @@ private:
// TODO: Figure out how to declare these inside the Episode3 namespace.
template <>
Episode3::HPType enum_for_name<Episode3::HPType>(const char* name);
Episode3::HPType phosg::enum_for_name<Episode3::HPType>(const char* name);
template <>
const char* name_for_enum<Episode3::HPType>(Episode3::HPType hp_type);
const char* phosg::name_for_enum<Episode3::HPType>(Episode3::HPType hp_type);
template <>
Episode3::DiceExchangeMode enum_for_name<Episode3::DiceExchangeMode>(const char* name);
Episode3::DiceExchangeMode phosg::enum_for_name<Episode3::DiceExchangeMode>(const char* name);
template <>
const char* name_for_enum<Episode3::DiceExchangeMode>(Episode3::DiceExchangeMode dice_exchange_mode);
const char* phosg::name_for_enum<Episode3::DiceExchangeMode>(Episode3::DiceExchangeMode dice_exchange_mode);
template <>
Episode3::AllowedCards enum_for_name<Episode3::AllowedCards>(const char* name);
Episode3::AllowedCards phosg::enum_for_name<Episode3::AllowedCards>(const char* name);
template <>
const char* name_for_enum<Episode3::AllowedCards>(Episode3::AllowedCards allowed_cards);
const char* phosg::name_for_enum<Episode3::AllowedCards>(Episode3::AllowedCards allowed_cards);
template <>
const char* name_for_enum<Episode3::BattlePhase>(Episode3::BattlePhase phase);
const char* phosg::name_for_enum<Episode3::BattlePhase>(Episode3::BattlePhase phase);
template <>
const char* name_for_enum<Episode3::SetupPhase>(Episode3::SetupPhase phase);
const char* phosg::name_for_enum<Episode3::SetupPhase>(Episode3::SetupPhase phase);
template <>
const char* name_for_enum<Episode3::RegistrationPhase>(Episode3::RegistrationPhase phase);
const char* phosg::name_for_enum<Episode3::RegistrationPhase>(Episode3::RegistrationPhase phase);
template <>
const char* name_for_enum<Episode3::ActionSubphase>(Episode3::ActionSubphase phase);
const char* phosg::name_for_enum<Episode3::ActionSubphase>(Episode3::ActionSubphase phase);
template <>
const char* name_for_enum<Episode3::AttackMedium>(Episode3::AttackMedium medium);
const char* phosg::name_for_enum<Episode3::AttackMedium>(Episode3::AttackMedium medium);
template <>
const char* name_for_enum<Episode3::CriterionCode>(Episode3::CriterionCode code);
const char* phosg::name_for_enum<Episode3::CriterionCode>(Episode3::CriterionCode code);
template <>
const char* name_for_enum<Episode3::CardType>(Episode3::CardType type);
const char* phosg::name_for_enum<Episode3::CardType>(Episode3::CardType type);
template <>
const char* name_for_enum<Episode3::CardClass>(Episode3::CardClass cc);
const char* phosg::name_for_enum<Episode3::CardClass>(Episode3::CardClass cc);
template <>
const char* name_for_enum<Episode3::ConditionType>(Episode3::ConditionType cond_type);
const char* phosg::name_for_enum<Episode3::ConditionType>(Episode3::ConditionType cond_type);
template <>
const char* name_for_enum<Episode3::EffectWhen>(Episode3::EffectWhen when);
const char* phosg::name_for_enum<Episode3::EffectWhen>(Episode3::EffectWhen when);
template <>
const char* name_for_enum<Episode3::Direction>(Episode3::Direction d);
const char* phosg::name_for_enum<Episode3::Direction>(Episode3::Direction d);
+4 -4
View File
@@ -1780,7 +1780,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
auto card = s->card_for_set_card_ref(pa.attacker_card_ref);
if (card) {
card->loc.direction = pa.facing_direction;
log.debug("set facing direction to %s", name_for_enum(card->loc.direction));
log.debug("set facing direction to %s", phosg::name_for_enum(card->loc.direction));
G_AddToSetCardlog_Ep3_6xB4x4A cmd;
cmd.card_refs.clear(0xFFFF);
@@ -1789,7 +1789,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
cmd.entry_count = 0;
size_t z = 0;
do {
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
log.debug("on action card ref %s", ref_str.c_str());
}
@@ -1826,7 +1826,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
for (size_t z = 0; (z < 4 * 9) && (pa.target_card_refs[z] != 0xFFFF); z++) {
auto target_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
if (target_card) {
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
string ref_str = s->debug_str_for_card_ref(pa.target_card_refs[z]);
log.debug("on target card ref %s", ref_str.c_str());
}
@@ -1856,7 +1856,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
this->subtract_or_check_atk_or_def_points_for_action(pa, 1);
}
for (size_t z = 0; (z < pa.action_card_refs.size()) && (pa.action_card_refs[z] != 0xFFFF); z++) {
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
log.debug("discarding %s from hand", ref_str.c_str());
}
+15 -15
View File
@@ -64,11 +64,11 @@ void Condition::clear_FF() {
std::string Condition::str(shared_ptr<const Server> s) const {
auto card_ref_str = s->debug_str_for_card_ref(this->card_ref);
auto giver_ref_str = s->debug_str_for_card_ref(this->condition_giver_card_ref);
return string_printf(
return phosg::string_printf(
"Condition[type=%s, turns=%hhu, a_arg=%hhd, dice=%hhu, flags=%02hhX, "
"def_eff_index=%hhu, ref=%s, value=%hd, giver_ref=%s "
"percent=%hhu value8=%hd order=%hu a8=%hu]",
name_for_enum(this->type),
phosg::name_for_enum(this->type),
this->remaining_turns,
this->a_arg_value,
this->dice_roll_value,
@@ -103,7 +103,7 @@ void EffectResult::clear() {
std::string EffectResult::str(shared_ptr<const Server> s) const {
string attacker_ref_str = s->debug_str_for_card_ref(this->attacker_card_ref);
string target_ref_str = s->debug_str_for_card_ref(this->target_card_ref);
return string_printf(
return phosg::string_printf(
"EffectResult[att_ref=%s, target_ref=%s, value=%hhd, "
"cur_hp=%hhd, ap=%hhd, tp=%hhd, flags=%02hhX, op=%hhd, "
"cond_index=%hhu, dice=%hhu]",
@@ -139,7 +139,7 @@ bool CardShortStatus::operator!=(const CardShortStatus& other) const {
std::string CardShortStatus::str(shared_ptr<const Server> s) const {
string loc_s = this->loc.str();
string ref_str = s->debug_str_for_card_ref(this->card_ref);
return string_printf(
return phosg::string_printf(
"CardShortStatus[ref=%s, cur_hp=%hd, flags=%08" PRIX32 ", loc=%s, "
"u1=%04hX, max_hp=%hhd, u2=%hhu]",
ref_str.c_str(),
@@ -193,13 +193,13 @@ std::string ActionState::str(shared_ptr<const Server> s) const {
string original_attacker_ref_s = s->debug_str_for_card_ref(this->original_attacker_card_ref);
string target_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
string action_refs_s = s->debug_str_for_card_refs(this->action_card_refs);
return string_printf(
return phosg::string_printf(
"ActionState[client=%hu, u=%hhu, facing=%s, attacker_ref=%s, "
"def_ref=%s, target_refs=%s, action_refs=%s, "
"orig_attacker_ref=%s]",
this->client_id.load(),
this->unused,
name_for_enum(this->facing_direction),
phosg::name_for_enum(this->facing_direction),
attacker_ref_s.c_str(),
defense_ref_s.c_str(),
target_refs_s.c_str(),
@@ -243,7 +243,7 @@ std::string ActionChain::str(shared_ptr<const Server> s) const {
string unknown_card_ref_a3_s = s->debug_str_for_card_ref(this->unknown_card_ref_a3);
string attack_action_card_refs_s = s->debug_str_for_card_refs(this->attack_action_card_refs);
string target_card_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
return string_printf(
return phosg::string_printf(
"ActionChain[eff_ap=%hhd, eff_tp=%hhd, ap_bonus=%hhd, damage=%hhd, "
"acting_ref=%s, unknown_ref_a3=%s, attack_action_refs=%s, "
"attack_action_ref_count=%hhu, medium=%s, target_ref_count=%hhu, "
@@ -258,9 +258,9 @@ std::string ActionChain::str(shared_ptr<const Server> s) const {
unknown_card_ref_a3_s.c_str(),
attack_action_card_refs_s.c_str(),
this->attack_action_card_ref_count,
name_for_enum(this->attack_medium),
phosg::name_for_enum(this->attack_medium),
this->target_card_ref_count,
name_for_enum(this->action_subphase),
phosg::name_for_enum(this->action_subphase),
this->strike_count,
this->damage_multiplier,
this->attack_number,
@@ -341,7 +341,7 @@ std::string ActionChainWithConds::str(shared_ptr<const Server> s) const {
if (ret.back() != '[') {
ret += ", ";
}
ret += string_printf("%zu:", z);
ret += phosg::string_printf("%zu:", z);
ret += this->conditions[z].str(s);
}
}
@@ -580,7 +580,7 @@ std::string ActionMetadata::str(shared_ptr<const Server> s) const {
string target_card_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
string defense_card_refs_s = s->debug_str_for_card_refs(this->defense_card_refs);
string original_attacker_card_refs_s = s->debug_str_for_card_refs(this->original_attacker_card_refs);
return string_printf(
return phosg::string_printf(
"ActionMetadata[ref=%s, target_ref_count=%hhu, def_ref_count=%hhu, "
"subphase=%s, def_power=%hhd, def_bonus=%hhd, "
"att_bonus=%hhd, flags=%08" PRIX32 ", target_refs=%s, "
@@ -588,7 +588,7 @@ std::string ActionMetadata::str(shared_ptr<const Server> s) const {
card_ref_s.c_str(),
this->target_card_ref_count,
this->defense_card_ref_count,
name_for_enum(this->action_subphase),
phosg::name_for_enum(this->action_subphase),
this->defense_power,
this->defense_bonus,
this->attack_bonus,
@@ -683,7 +683,7 @@ std::string HandAndEquipState::str(shared_ptr<const Server> s) const {
string set_card_refs_s = s->debug_str_for_card_refs(this->set_card_refs);
string hand_card_refs2_s = s->debug_str_for_card_refs(this->hand_card_refs2);
string set_card_refs2_s = s->debug_str_for_card_refs(this->set_card_refs2);
return string_printf(
return phosg::string_printf(
"HandAndEquipState[dice=[%hhu, %hhu], atk=%hhu, def=%hhu, atk2=%hhu, "
"a1=%hhu, total_set_cost=%hhu, is_cpu=%hhu, assist_flags=%08" PRIX32 ", "
"hand_refs=%s, assist_ref=%s, set_refs=%s, sc_ref=%s, hand_refs2=%s, "
@@ -858,7 +858,7 @@ static bool is_card_within_range(
const parray<uint8_t, 9 * 9>& range,
const Location& anchor_loc,
const CardShortStatus& ss,
PrefixedLogger* log) {
phosg::PrefixedLogger* log) {
if (ss.card_ref == 0xFFFF) {
if (log) {
log->debug("is_card_within_range: (false) ss.card_ref missing");
@@ -899,7 +899,7 @@ vector<uint16_t> get_card_refs_within_range(
const parray<uint8_t, 9 * 9>& range,
const Location& loc,
const parray<CardShortStatus, 0x10>& short_statuses,
PrefixedLogger* log) {
phosg::PrefixedLogger* log) {
vector<uint16_t> ret;
if (is_card_within_range(range, loc, short_statuses[0], log)) {
if (log) {
+1 -1
View File
@@ -329,6 +329,6 @@ std::vector<uint16_t> get_card_refs_within_range(
const parray<uint8_t, 9 * 9>& range,
const Location& loc,
const parray<CardShortStatus, 0x10>& short_statuses,
PrefixedLogger* log = nullptr);
phosg::PrefixedLogger* log = nullptr);
} // namespace Episode3
+5 -5
View File
@@ -15,8 +15,8 @@ void compute_effective_range(
uint16_t card_id,
const Location& loc,
shared_ptr<const MapAndRulesState> map_and_rules,
PrefixedLogger* log) {
if (log && log->should_log(LogLevel::DEBUG)) {
phosg::PrefixedLogger* log) {
if (log && log->should_log(phosg::LogLevel::DEBUG)) {
string loc_str = loc.str();
log->debug("compute_effective_range: card_id=#%04hX, loc=%s", card_id, loc_str.c_str());
log->debug("compute_effective_range: map_and_rules->map:");
@@ -941,7 +941,7 @@ bool RulerServer::check_usability_or_condition_apply(
AttackMedium attack_medium) const {
auto s = this->server();
bool is_nte = s->options.is_nte();
auto log = s->log_stack(string_printf("check_usability_or_condition_apply(%02hhX, #%04hX, %02hhX, #%04hX, #%04hX, %02hhX, %s, %s): ", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", name_for_enum(attack_medium)));
auto log = s->log_stack(phosg::string_printf("check_usability_or_condition_apply(%02hhX, #%04hX, %02hhX, #%04hX, #%04hX, %02hhX, %s, %s): ", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", phosg::name_for_enum(attack_medium)));
if (static_cast<uint8_t>(attack_medium) & 0x80) {
attack_medium = AttackMedium::UNKNOWN;
@@ -969,7 +969,7 @@ bool RulerServer::check_usability_or_condition_apply(
}
criterion_code = ce1->def.effects[def_effect_index].apply_criterion;
}
log.debug("criterion_code=%s", name_for_enum(criterion_code));
log.debug("criterion_code=%s", phosg::name_for_enum(criterion_code));
// For item usability checks, prevent criteria that depend on player
// positioning/team setup
@@ -2059,7 +2059,7 @@ shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_id(uint3
uint32_t RulerServer::get_card_id_with_effective_range(
uint16_t card_ref, uint16_t card_id_override, TargetMode* out_target_mode) const {
auto log = this->server()->log_stack(string_printf("get_card_id_with_effective_range(@%04hX, #%04hX): ", card_ref, card_id_override));
auto log = this->server()->log_stack(phosg::string_printf("get_card_id_with_effective_range(@%04hX, #%04hX): ", card_ref, card_id_override));
uint16_t card_id = (card_id_override == 0xFFFF)
? this->card_id_for_card_ref(card_ref)
+1 -1
View File
@@ -19,7 +19,7 @@ void compute_effective_range(
uint16_t card_id,
const Location& loc,
std::shared_ptr<const MapAndRulesState> map_and_rules,
PrefixedLogger* log = nullptr);
phosg::PrefixedLogger* log = nullptr);
bool card_linkage_is_valid(
std::shared_ptr<const CardIndex::CardEntry> right_def,
+24 -24
View File
@@ -82,7 +82,7 @@ Server::Server(shared_ptr<Lobby> lobby, Options&& options)
Server::~Server() noexcept(false) {
if (this->logger_stack.size() != 1) {
throw logic_error(string_printf("incorrect logger stack size: expected 1, received %zu", this->logger_stack.size()));
throw logic_error(phosg::string_printf("incorrect logger stack size: expected 1, received %zu", this->logger_stack.size()));
}
delete this->logger_stack.back();
}
@@ -125,7 +125,7 @@ Server::StackLogger::StackLogger(const Server* s, const std::string& prefix)
s->logger_stack.push_back(this);
}
Server::StackLogger::StackLogger(const Server* s, const std::string& prefix, LogLevel min_level)
Server::StackLogger::StackLogger(const Server* s, const std::string& prefix, phosg::LogLevel min_level)
: PrefixedLogger(prefix, min_level),
server(s) {
s->logger_stack.push_back(this);
@@ -172,9 +172,9 @@ std::string Server::debug_str_for_card_ref(uint16_t card_ref) const {
auto ce = this->definition_for_card_ref(card_ref);
if (ce) {
string name = ce->def.en_name.decode();
return string_printf("@%04hX (#%04" PRIX32 " %s)", card_ref, ce->def.card_id.load(), name.c_str());
return phosg::string_printf("@%04hX (#%04" PRIX32 " %s)", card_ref, ce->def.card_id.load(), name.c_str());
} else {
return string_printf("@%04hX (missing)", card_ref);
return phosg::string_printf("@%04hX (missing)", card_ref);
}
}
@@ -185,9 +185,9 @@ std::string Server::debug_str_for_card_id(uint16_t card_id) const {
auto ce = this->definition_for_card_id(card_id);
if (ce) {
string name = ce->def.en_name.decode();
return string_printf("#%04hX (%s)", card_id, name.c_str());
return phosg::string_printf("#%04hX (%s)", card_id, name.c_str());
} else {
return string_printf("#%04hX (missing)", card_id);
return phosg::string_printf("#%04hX (missing)", card_id);
}
}
@@ -240,7 +240,7 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
!(this->options.behavior_flags & BehaviorFlag::DISABLE_MASKING) &&
(size >= 8)) {
masked_data.assign(reinterpret_cast<const char*>(data), size);
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t mask_key = (phosg::random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(masked_data.data(), masked_data.size(), mask_key);
data = masked_data.data();
size = masked_data.size();
@@ -260,7 +260,7 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
} else if ((this->options.behavior_flags & BehaviorFlag::LOG_COMMANDS_IF_LOBBY_MISSING) &&
this->log().info("Generated command")) {
print_data(stderr, data, size, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::DISABLE_COLOR | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stderr, data, size, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
}
}
@@ -272,9 +272,9 @@ void Server::send_6xB4x46() const {
// debugging easier.
G_ServerVersionStrings_Ep3_6xB4x46 cmd;
cmd.version_signature.encode(this->options.is_nte() ? VERSION_SIGNATURE_NTE : VERSION_SIGNATURE, 1);
cmd.date_str1.encode(format_time(this->options.card_index->definitions_mtime() * 1000000), 1);
string build_date = format_time(BUILD_TIMESTAMP);
cmd.date_str2.encode(string_printf("newserv %s compiled at %s", GIT_REVISION_HASH, build_date.c_str()), 1);
cmd.date_str1.encode(phosg::format_time(this->options.card_index->definitions_mtime() * 1000000), 1);
string build_date = phosg::format_time(BUILD_TIMESTAMP);
cmd.date_str2.encode(phosg::string_printf("newserv %s compiled at %s", GIT_REVISION_HASH, build_date.c_str()), 1);
this->send(cmd);
}
@@ -283,7 +283,7 @@ string Server::prepare_6xB6x41_map_definition(shared_ptr<const MapIndex::Map> ma
const auto& compressed = vm->compressed(is_nte);
StringWriter w;
phosg::StringWriter w;
uint32_t subcommand_size = (compressed.size() + sizeof(G_MapData_Ep3_6xB6x41) + 3) & (~3);
w.put<G_MapData_Ep3_6xB6x41>({{{{0xB6, 0, 0}, subcommand_size}, 0x41, {}}, vm->map->map_number.load(), compressed.size(), 0});
w.write(compressed);
@@ -347,7 +347,7 @@ __attribute__((format(printf, 2, 3))) void Server::send_debug_message_printf(con
if (l && (this->options.behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
va_list va;
va_start(va, fmt);
std::string buf = string_vprintf(fmt, va);
std::string buf = phosg::string_vprintf(fmt, va);
va_end(va);
send_text_message(l, buf);
}
@@ -358,7 +358,7 @@ __attribute__((format(printf, 2, 3))) void Server::send_info_message_printf(cons
if (l) {
va_list va;
va_start(va, fmt);
std::string buf = string_vprintf(fmt, va);
std::string buf = phosg::string_vprintf(fmt, va);
va_end(va);
send_text_message(l, buf);
}
@@ -862,7 +862,7 @@ void Server::draw_phase_after() {
// facilities used are different.
uint64_t limit_5mins = this->map_and_rules->rules.overall_time_limit;
uint64_t end_usecs = this->battle_start_usecs + (limit_5mins * 300 * 1000 * 1000);
if (now() >= end_usecs) {
if (phosg::now() >= end_usecs) {
this->overall_time_expired = true;
}
}
@@ -972,7 +972,7 @@ void Server::end_action_phase() {
bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
auto log = this->log_stack("enqueue_attack_or_defense: ");
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
string s = pa->str(this->shared_from_this());
log.debug("input: %s", s.c_str());
}
@@ -1022,7 +1022,7 @@ bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
size_t attack_index = this->num_pending_attacks++;
this->pending_attacks[attack_index] = *pa;
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
string pa_str = this->pending_attacks[attack_index].str(this->shared_from_this());
log.debug("set pending attack %zu: %s", attack_index, pa_str.c_str());
}
@@ -1711,7 +1711,7 @@ void Server::setup_and_start_battle() {
cmd.start_battle = 1;
this->send(cmd);
}
this->battle_start_usecs = now();
this->battle_start_usecs = phosg::now();
this->send_6xB4x46();
@@ -1831,8 +1831,8 @@ void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& dat
auto header = check_size_t<G_CardBattleCommandHeader>(data, 0xFFFF);
size_t expected_size = header.size * 4;
if (expected_size < data.size()) {
print_data(stderr, data);
throw runtime_error(string_printf("command is incomplete: expected %zX bytes, received %zX bytes", expected_size, data.size()));
phosg::print_data(stderr, data);
throw runtime_error(phosg::string_printf("command is incomplete: expected %zX bytes, received %zX bytes", expected_size, data.size()));
}
if (header.subcommand != 0xB3) {
throw runtime_error("server data command is not 6xB3");
@@ -2259,7 +2259,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
}
}
if (verify_error) {
throw runtime_error(string_printf("invalid deck: -0x%" PRIX32, verify_error));
throw runtime_error(phosg::string_printf("invalid deck: -0x%" PRIX32, verify_error));
}
if (!this->options.is_nte() && !(this->options.behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
this->ruler_server->replace_D1_D2_rank_cards_with_Attack(entry.card_ids);
@@ -2579,7 +2579,7 @@ void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const st
uint8_t language = sender_c ? sender_c->language() : 1;
const auto& list_data = this->options.map_index->get_compressed_list(num_players, language);
StringWriter w;
phosg::StringWriter w;
uint32_t subcommand_size = (list_data.size() + sizeof(G_MapList_Ep3_6xB6x40) + 3) & (~3);
w.put<G_MapList_Ep3_6xB6x40>(G_MapList_Ep3_6xB6x40{{{{0xB6, 0, 0}, subcommand_size}, 0x40, {}}, list_data.size(), 0});
w.write(list_data);
@@ -2828,7 +2828,7 @@ void Server::unknown_8023EEF4() {
auto card = this->attack_cards[this->unknown_a14];
if (this->get_current_team_turn() == card->get_team_id()) {
ActionState as = this->pending_attacks_with_cards[this->unknown_a14];
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
log.debug("card @%04hX #%04hX can attack", card->get_card_ref(), card->get_card_id());
string as_str = as.str(this->shared_from_this());
log.debug("as: %s", as_str.c_str());
@@ -2838,7 +2838,7 @@ void Server::unknown_8023EEF4() {
} else {
this->replace_targets_due_to_destruction_or_conditions(&as);
}
if (log.should_log(LogLevel::DEBUG)) {
if (log.should_log(phosg::LogLevel::DEBUG)) {
string as_str = as.str(this->shared_from_this());
log.debug("as after target replacement: %s", as_str.c_str());
}
+4 -4
View File
@@ -72,7 +72,7 @@ public:
std::shared_ptr<const CardIndex> card_index;
std::shared_ptr<const MapIndex> map_index;
uint32_t behavior_flags;
std::shared_ptr<StringReader> opt_rand_stream;
std::shared_ptr<phosg::StringReader> opt_rand_stream;
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt;
std::shared_ptr<const Tournament> tournament;
std::array<std::vector<uint16_t>, 5> trap_card_ids;
@@ -85,10 +85,10 @@ public:
~Server() noexcept(false);
void init();
class StackLogger : public PrefixedLogger {
class StackLogger : public phosg::PrefixedLogger {
public:
StackLogger(const Server* s, const std::string& prefix);
StackLogger(const Server* s, const std::string& prefix, LogLevel min_level);
StackLogger(const Server* s, const std::string& prefix, phosg::LogLevel min_level);
StackLogger(const StackLogger&) = delete;
StackLogger(StackLogger&&);
StackLogger& operator=(const StackLogger&) = delete;
@@ -109,7 +109,7 @@ public:
for (size_t z = 0; z < count; z++) {
if (refs[z] != 0xFFFF) {
std::string ref_str = this->debug_str_for_card_ref(refs[z]);
ret += string_printf("%zu:%s ", z, ref_str.c_str());
ret += phosg::string_printf("%zu:%s ", z, ref_str.c_str());
}
}
if (ret.size() > 1) {
+26 -26
View File
@@ -49,16 +49,16 @@ string Tournament::Team::str() const {
num_com_players += player.is_com();
}
string ret = string_printf("[Team/%zu %s %zuH/%zuC/%zuP name=%s pass=%s rounds=%zu",
string ret = phosg::string_printf("[Team/%zu %s %zuH/%zuC/%zuP name=%s pass=%s rounds=%zu",
this->index, this->is_active ? "active" : "inactive",
num_human_players, num_com_players, this->max_players, this->name.c_str(),
this->password.c_str(), this->num_rounds_cleared);
for (const auto& player : this->players) {
if (player.is_human()) {
if (player.player_name.empty()) {
ret += string_printf(" %08" PRIX32, player.account_id);
ret += phosg::string_printf(" %08" PRIX32, player.account_id);
} else {
ret += string_printf(" %08" PRIX32 " (%s)", player.account_id, player.player_name.c_str());
ret += phosg::string_printf(" %08" PRIX32 " (%s)", player.account_id, player.player_name.c_str());
}
}
}
@@ -206,7 +206,7 @@ Tournament::Match::Match(
string Tournament::Match::str() const {
string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
return string_printf("[Match round=%zu winner=%s]", this->round_num, winner_str.c_str());
return phosg::string_printf("[Match round=%zu winner=%s]", this->round_num, winner_str.c_str());
}
bool Tournament::Match::resolve_if_skippable() {
@@ -230,7 +230,7 @@ bool Tournament::Match::resolve_if_skippable() {
// entirely and just make one team advance arbitrarily (note that this also
// handles the case where both preceding winner teams are empty)
if (!winner_a->has_any_human_players() && !winner_b->has_any_human_players()) {
this->set_winner_team((random_object<uint8_t>() & 1) ? winner_b : winner_a);
this->set_winner_team((phosg::random_object<uint8_t>() & 1) ? winner_b : winner_a);
return true;
}
@@ -318,7 +318,7 @@ Tournament::Tournament(
const Rules& rules,
size_t num_teams,
uint8_t flags)
: log(string_printf("[Tournament:%s] ", name.c_str())),
: log(phosg::string_printf("[Tournament:%s] ", name.c_str())),
map_index(map_index),
com_deck_index(com_deck_index),
name(name),
@@ -342,8 +342,8 @@ Tournament::Tournament(
Tournament::Tournament(
shared_ptr<const MapIndex> map_index,
shared_ptr<const COMDeckIndex> com_deck_index,
const JSON& json)
: log(string_printf("[Tournament:%s] ", json.get_string("name").c_str())),
const phosg::JSON& json)
: log(phosg::string_printf("[Tournament:%s] ", json.get_string("name").c_str())),
map_index(map_index),
com_deck_index(com_deck_index),
source_json(json),
@@ -504,14 +504,14 @@ void Tournament::create_bracket_matches() {
this->final_match = current_round_matches.at(0);
}
JSON Tournament::json() const {
auto teams_list = JSON::list();
phosg::JSON Tournament::json() const {
auto teams_list = phosg::JSON::list();
for (auto team : this->teams) {
auto players_list = JSON::list();
auto players_list = phosg::JSON::list();
for (const auto& player : team->players) {
if (player.is_human()) {
if (!player.player_name.empty()) {
players_list.emplace_back(JSON::list({player.account_id, player.player_name}));
players_list.emplace_back(phosg::JSON::list({player.account_id, player.player_name}));
} else {
players_list.emplace_back(player.account_id);
}
@@ -519,7 +519,7 @@ JSON Tournament::json() const {
players_list.emplace_back(player.com_deck->deck_name);
}
}
teams_list.emplace_back(JSON::dict({
teams_list.emplace_back(phosg::JSON::dict({
{"max_players", team->max_players},
{"player_specs", std::move(players_list)},
{"name", team->name},
@@ -527,7 +527,7 @@ JSON Tournament::json() const {
{"num_rounds_cleared", team->num_rounds_cleared},
}));
}
return JSON::dict({
return phosg::JSON::dict({
{"name", this->name},
{"map_number", this->map->map_number},
{"rules", this->rules.json()},
@@ -649,7 +649,7 @@ void Tournament::start() {
if (this->flags & Flag::SHUFFLE_ENTRIES) {
// Shuffle all the tournament entries
for (size_t z = this->teams.size(); z > 0; z--) {
size_t index = random_object<uint32_t>() % z;
size_t index = phosg::random_object<uint32_t>() % z;
if (index != z - 1) {
this->teams[z - 1].swap(this->teams[index]);
}
@@ -665,7 +665,7 @@ void Tournament::start() {
auto m = this->zero_round_matches[z];
auto t = m->winner_team;
if (t->name.empty()) {
t->name = has_com_teams ? string_printf("COM:%zu", z) : "(no entrant)";
t->name = has_com_teams ? phosg::string_printf("COM:%zu", z) : "(no entrant)";
}
for (const auto& player : t->players) {
if (player.is_com()) {
@@ -791,16 +791,16 @@ TournamentIndex::TournamentIndex(
return;
}
JSON json;
phosg::JSON json;
try {
json = JSON::parse(load_file(this->state_filename));
} catch (const cannot_open_file&) {
json = JSON::list();
json = phosg::JSON::parse(phosg::load_file(this->state_filename));
} catch (const phosg::cannot_open_file&) {
json = phosg::JSON::list();
}
if (json.is_list()) {
if (json.size() > 0x20) {
throw runtime_error("tournament JSON list length is incorrect");
throw runtime_error("tournament phosg::JSON list length is incorrect");
}
for (size_t z = 0; z < min<size_t>(json.size(), 0x20); z++) {
if (!json.at(z).is_null()) {
@@ -815,13 +815,13 @@ TournamentIndex::TournamentIndex(
}
} else if (json.is_dict()) {
if (json.size() > 0x20) {
throw runtime_error("tournament JSON dict length is incorrect");
throw runtime_error("tournament phosg::JSON dict length is incorrect");
}
for (const auto& it : json.as_dict()) {
auto tourn = make_shared<Tournament>(this->map_index, this->com_deck_index, *it.second);
tourn->init();
if (!this->name_to_tournament.emplace(tourn->get_name(), tourn).second) {
// This is logic_error instead of runtime_error because JSON dicts are
// This is logic_error instead of runtime_error because phosg::JSON dicts are
// supposed to already have unique keys
throw logic_error("multiple tournaments have the same name: " + tourn->get_name());
}
@@ -829,7 +829,7 @@ TournamentIndex::TournamentIndex(
this->menu_item_id_to_tournament.emplace_back(tourn);
}
} else {
throw runtime_error("tournament state root JSON is not a list or dict");
throw runtime_error("tournament state root phosg::JSON is not a list or dict");
}
}
@@ -838,11 +838,11 @@ void TournamentIndex::save() const {
return;
}
auto json = JSON::dict();
auto json = phosg::JSON::dict();
for (const auto& it : this->name_to_tournament) {
json.emplace(it.second->get_name(), it.second->json());
}
save_file(this->state_filename, json.serialize(JSON::SerializeOption::FORMAT | JSON::SerializeOption::HEX_INTEGERS | JSON::SerializeOption::ESCAPE_CONTROLS_ONLY));
phosg::save_file(this->state_filename, json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::HEX_INTEGERS | phosg::JSON::SerializeOption::ESCAPE_CONTROLS_ONLY));
}
shared_ptr<Tournament> TournamentIndex::create_tournament(
+5 -5
View File
@@ -49,7 +49,7 @@ public:
bool is_com() const;
bool is_human() const;
JSON json() const;
phosg::JSON json() const;
};
struct Team : public std::enable_shared_from_this<Team> {
@@ -115,11 +115,11 @@ public:
Tournament(
std::shared_ptr<const MapIndex> map_index,
std::shared_ptr<const COMDeckIndex> com_deck_index,
const JSON& json);
const phosg::JSON& json);
~Tournament() = default;
void init();
JSON json() const;
phosg::JSON json() const;
inline const std::string& get_name() const {
return this->name;
@@ -165,11 +165,11 @@ public:
private:
void create_bracket_matches();
PrefixedLogger log;
phosg::PrefixedLogger log;
std::shared_ptr<const MapIndex> map_index;
std::shared_ptr<const COMDeckIndex> com_deck_index;
JSON source_json;
phosg::JSON source_json;
std::string name;
std::shared_ptr<const MapIndex::Map> map;
Rules rules;
+3 -3
View File
@@ -20,7 +20,7 @@ FileContentsCache::File::File(
shared_ptr<const FileContentsCache::File> FileContentsCache::replace(
const string& name, string&& data, uint64_t t) {
if (t == 0) {
t = now();
t = phosg::now();
}
auto new_file = make_shared<File>(name, std::move(data), t);
auto emplace_ret = this->name_to_file.emplace(name, new_file);
@@ -37,7 +37,7 @@ shared_ptr<const FileContentsCache::File> FileContentsCache::replace(
}
FileContentsCache::GetResult FileContentsCache::get_or_load(const std::string& name) {
return this->get(name, load_file);
return this->get(name, phosg::load_file);
}
FileContentsCache::GetResult FileContentsCache::get_or_load(const char* name) {
@@ -59,7 +59,7 @@ shared_ptr<const FileContentsCache::File> FileContentsCache::get_or_throw(
FileContentsCache::GetResult FileContentsCache::get(const std::string& name,
std::function<std::string(const std::string&)> generate) {
uint64_t t = now();
uint64_t t = phosg::now();
try {
auto& entry = this->name_to_file.at(name);
if (this->ttl_usecs && (t - entry->load_time < this->ttl_usecs)) {
+1 -1
View File
@@ -78,7 +78,7 @@ public:
}
template <typename T, typename NameT>
GetObjResult<T> get_obj(NameT name, std::function<T(const std::string&)> generate) {
uint64_t t = now();
uint64_t t = phosg::now();
try {
auto& f = this->name_to_file.at(name);
if (f->data->size() != sizeof(T)) {
+49 -49
View File
@@ -59,7 +59,7 @@ string CompiledFunctionCode::generate_client_command_t(
footer.entrypoint_addr_offset = this->entrypoint_offset_offset;
footer.unused2.clear(0);
StringWriter w;
phosg::StringWriter w;
if (!label_writes.empty()) {
string modified_code = this->code;
for (const auto& it : label_writes) {
@@ -91,7 +91,7 @@ string CompiledFunctionCode::generate_client_command_t(
footer.relocations_offset = override_relocations_offset;
} else {
for (uint16_t delta : this->relocation_deltas) {
w.put<typename FooterT::U16T>(delta);
w.put<U16T<FooterT::IsBE>>(delta);
}
if (this->relocation_deltas.size() & 1) {
w.put_u16(0);
@@ -161,24 +161,24 @@ shared_ptr<CompiledFunctionCode> compile_function_code(
}
// Look in the function directory first, then the system directory
string asm_filename = string_printf("%s/%s.%s.inc.s", function_directory.c_str(), name.c_str(), arch_name_token);
if (!isfile(asm_filename)) {
asm_filename = string_printf("%s/%s.%s.inc.s", system_directory.c_str(), name.c_str(), arch_name_token);
string asm_filename = phosg::string_printf("%s/%s.%s.inc.s", function_directory.c_str(), name.c_str(), arch_name_token);
if (!phosg::isfile(asm_filename)) {
asm_filename = phosg::string_printf("%s/%s.%s.inc.s", system_directory.c_str(), name.c_str(), arch_name_token);
}
if (isfile(asm_filename)) {
if (phosg::isfile(asm_filename)) {
if (!get_include_stack.emplace(name).second) {
throw runtime_error("mutual recursion between includes: " + name);
}
ResourceDASM::EmulatorBase::AssembleResult ret;
switch (arch) {
case CompiledFunctionCode::Architecture::POWERPC:
ret = ResourceDASM::PPC32Emulator::assemble(load_file(asm_filename), get_include);
ret = ResourceDASM::PPC32Emulator::assemble(phosg::load_file(asm_filename), get_include);
break;
case CompiledFunctionCode::Architecture::X86:
ret = ResourceDASM::X86Emulator::assemble(load_file(asm_filename), get_include);
ret = ResourceDASM::X86Emulator::assemble(phosg::load_file(asm_filename), get_include);
break;
case CompiledFunctionCode::Architecture::SH4:
ret = ResourceDASM::SH4Emulator::assemble(load_file(asm_filename), get_include);
ret = ResourceDASM::SH4Emulator::assemble(phosg::load_file(asm_filename), get_include);
break;
default:
throw runtime_error("unknown architecture");
@@ -188,12 +188,12 @@ shared_ptr<CompiledFunctionCode> compile_function_code(
}
string bin_filename = function_directory + "/" + name + ".inc.bin";
if (isfile(bin_filename)) {
return load_file(bin_filename);
if (phosg::isfile(bin_filename)) {
return phosg::load_file(bin_filename);
}
bin_filename = system_directory + "/" + name + ".inc.bin";
if (isfile(bin_filename)) {
return load_file(bin_filename);
if (phosg::isfile(bin_filename)) {
return phosg::load_file(bin_filename);
}
throw runtime_error("data not found for include: " + name + " (from " + asm_filename + " or " + bin_filename + ")");
};
@@ -229,7 +229,7 @@ shared_ptr<CompiledFunctionCode> compile_function_code(
set<uint32_t> reloc_indexes;
for (const auto& it : ret->label_offsets) {
if (starts_with(it.first, "reloc")) {
if (phosg::starts_with(it.first, "reloc")) {
reloc_indexes.emplace(it.second / 4);
}
}
@@ -260,28 +260,28 @@ FunctionCodeIndex::FunctionCodeIndex(const string& directory) {
return;
}
string system_dir_path = ends_with(directory, "/") ? (directory + "System") : (directory + "/System");
string system_dir_path = phosg::ends_with(directory, "/") ? (directory + "System") : (directory + "/System");
uint32_t next_menu_item_id = 1;
for (const auto& subdir_name : list_directory_sorted(directory)) {
string subdir_path = ends_with(directory, "/") ? (directory + subdir_name) : (directory + "/" + subdir_name);
if (!isdir(subdir_path)) {
for (const auto& subdir_name : phosg::list_directory_sorted(directory)) {
string subdir_path = phosg::ends_with(directory, "/") ? (directory + subdir_name) : (directory + "/" + subdir_name);
if (!phosg::isdir(subdir_path)) {
function_compiler_log.warning("Skipping %s (not a directory)", subdir_name.c_str());
continue;
}
for (const auto& filename : list_directory_sorted(subdir_path)) {
for (const auto& filename : phosg::list_directory_sorted(subdir_path)) {
try {
if (!ends_with(filename, ".s")) {
if (!phosg::ends_with(filename, ".s")) {
continue;
}
string name = filename.substr(0, filename.size() - 2);
if (ends_with(name, ".inc")) {
if (phosg::ends_with(name, ".inc")) {
continue;
}
bool is_patch = ends_with(name, ".patch");
bool is_patch = phosg::ends_with(name, ".patch");
if (is_patch) {
name.resize(name.size() - 6);
}
@@ -290,15 +290,15 @@ FunctionCodeIndex::FunctionCodeIndex(const string& directory) {
CompiledFunctionCode::Architecture arch = CompiledFunctionCode::Architecture::UNKNOWN;
uint32_t specific_version = 0;
string short_name = name;
if (ends_with(name, ".ppc")) {
if (phosg::ends_with(name, ".ppc")) {
arch = CompiledFunctionCode::Architecture::POWERPC;
name.resize(name.size() - 4);
short_name = name;
} else if (ends_with(name, ".x86")) {
} else if (phosg::ends_with(name, ".x86")) {
arch = CompiledFunctionCode::Architecture::X86;
name.resize(name.size() - 4);
short_name = name;
} else if (ends_with(name, ".sh4")) {
} else if (phosg::ends_with(name, ".sh4")) {
arch = CompiledFunctionCode::Architecture::SH4;
name.resize(name.size() - 4);
short_name = name;
@@ -321,11 +321,11 @@ FunctionCodeIndex::FunctionCodeIndex(const string& directory) {
}
string path = subdir_path + "/" + filename;
string text = load_file(path);
string text = phosg::load_file(path);
auto code = compile_function_code(arch, subdir_path, system_dir_path, name, text);
if (code->index != 0) {
if (!this->index_to_function.emplace(code->index, code).second) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"duplicate function index: %08" PRIX32, code->index));
}
}
@@ -338,11 +338,11 @@ FunctionCodeIndex::FunctionCodeIndex(const string& directory) {
this->menu_item_id_and_specific_version_to_patch_function.emplace(
static_cast<uint64_t>(code->menu_item_id) << 32 | specific_version, code);
this->name_and_specific_version_to_patch_function.emplace(
string_printf("%s-%08" PRIX32, short_name.c_str(), specific_version), code);
phosg::string_printf("%s-%08" PRIX32, short_name.c_str(), specific_version), code);
}
string index_prefix = code->index ? string_printf("%02X => ", code->index) : "";
string patch_prefix = is_patch ? string_printf("[%08" PRIX32 "/%08" PRIX32 "] ", code->menu_item_id, code->specific_version) : "";
string index_prefix = code->index ? phosg::string_printf("%02X => ", code->index) : "";
string patch_prefix = is_patch ? phosg::string_printf("[%08" PRIX32 "/%08" PRIX32 "] ", code->menu_item_id, code->specific_version) : "";
function_compiler_log.info("Compiled function %s%s%s (%s)",
index_prefix.c_str(), patch_prefix.c_str(), name.c_str(), name_for_architecture(code->arch));
@@ -354,13 +354,13 @@ FunctionCodeIndex::FunctionCodeIndex(const string& directory) {
}
shared_ptr<const Menu> FunctionCodeIndex::patch_menu(uint32_t specific_version) const {
auto suffix = string_printf("-%08" PRIX32, specific_version);
auto suffix = phosg::string_printf("-%08" PRIX32, specific_version);
auto ret = make_shared<Menu>(MenuID::PATCHES, "Patches");
ret->items.emplace_back(PatchesMenuItemID::GO_BACK, "Go back", "Return to the\nmain menu", 0);
for (const auto& it : this->name_and_specific_version_to_patch_function) {
const auto& fn = it.second;
if (fn->hide_from_patches_menu || !ends_with(it.first, suffix)) {
if (fn->hide_from_patches_menu || !phosg::ends_with(it.first, suffix)) {
continue;
}
ret->items.emplace_back(
@@ -374,13 +374,13 @@ shared_ptr<const Menu> FunctionCodeIndex::patch_menu(uint32_t specific_version)
shared_ptr<const Menu> FunctionCodeIndex::patch_switches_menu(
uint32_t specific_version, const std::unordered_set<std::string>& auto_patches_enabled) const {
auto suffix = string_printf("-%08" PRIX32, specific_version);
auto suffix = phosg::string_printf("-%08" PRIX32, specific_version);
auto ret = make_shared<Menu>(MenuID::PATCH_SWITCHES, "Patch switches");
ret->items.emplace_back(PatchesMenuItemID::GO_BACK, "Go back", "Return to the\nmain menu", 0);
for (const auto& it : this->name_and_specific_version_to_patch_function) {
const auto& fn = it.second;
if (fn->hide_from_patches_menu || !ends_with(it.first, suffix)) {
if (fn->hide_from_patches_menu || !phosg::ends_with(it.first, suffix)) {
continue;
}
string name;
@@ -404,7 +404,7 @@ bool FunctionCodeIndex::patch_menu_empty(uint32_t specific_version) const {
std::shared_ptr<const CompiledFunctionCode> FunctionCodeIndex::get_patch(
const std::string& name, uint32_t specific_version) const {
return this->name_and_specific_version_to_patch_function.at(
string_printf("%s-%08" PRIX32, name.c_str(), specific_version));
phosg::string_printf("%s-%08" PRIX32, name.c_str(), specific_version));
}
DOLFileIndex::DOLFileIndex(const string& directory) {
@@ -412,7 +412,7 @@ DOLFileIndex::DOLFileIndex(const string& directory) {
function_compiler_log.info("Function compiler is not available");
return;
}
if (!isdir(directory)) {
if (!phosg::isdir(directory)) {
function_compiler_log.info("DOL file directory is missing");
return;
}
@@ -422,9 +422,9 @@ DOLFileIndex::DOLFileIndex(const string& directory) {
menu->items.emplace_back(ProgramsMenuItemID::GO_BACK, "Go back", "Return to the\nmain menu", 0);
uint32_t next_menu_item_id = 0;
for (const auto& filename : list_directory_sorted(directory)) {
bool is_dol = ends_with(filename, ".dol");
bool is_compressed_dol = ends_with(filename, ".dol.prs");
for (const auto& filename : phosg::list_directory_sorted(directory)) {
bool is_dol = phosg::ends_with(filename, ".dol");
bool is_compressed_dol = phosg::ends_with(filename, ".dol.prs");
if (!is_dol && !is_compressed_dol) {
continue;
}
@@ -436,13 +436,13 @@ DOLFileIndex::DOLFileIndex(const string& directory) {
dol->name = name;
string path = directory + "/" + filename;
string file_data = load_file(path);
string file_data = phosg::load_file(path);
string description;
if (is_compressed_dol) {
size_t decompressed_size = prs_decompress_size(file_data);
StringWriter w;
phosg::StringWriter w;
w.put_u32b(file_data.size());
w.put_u32b(decompressed_size);
w.write(file_data);
@@ -451,15 +451,15 @@ DOLFileIndex::DOLFileIndex(const string& directory) {
}
dol->data = std::move(w.str());
string compressed_size_str = format_size(file_data.size());
string decompressed_size_str = format_size(decompressed_size);
string compressed_size_str = phosg::format_size(file_data.size());
string decompressed_size_str = phosg::format_size(decompressed_size);
function_compiler_log.info("Loaded compressed DOL file %s (%s -> %s)",
dol->name.c_str(), compressed_size_str.c_str(), decompressed_size_str.c_str());
description = string_printf("$C6%s$C7\n%s\n%s (orig)",
description = phosg::string_printf("$C6%s$C7\n%s\n%s (orig)",
dol->name.c_str(), compressed_size_str.c_str(), decompressed_size_str.c_str());
} else {
StringWriter w;
phosg::StringWriter w;
w.put_u32b(0);
w.put_u32b(file_data.size());
w.write(file_data);
@@ -468,9 +468,9 @@ DOLFileIndex::DOLFileIndex(const string& directory) {
}
dol->data = std::move(w.str());
string size_str = format_size(dol->data.size());
string size_str = phosg::format_size(dol->data.size());
function_compiler_log.info("Loaded DOL file %s (%s)", filename.c_str(), size_str.c_str());
description = string_printf("$C6%s$C7\n%s", dol->name.c_str(), size_str.c_str());
description = phosg::string_printf("$C6%s$C7\n%s", dol->name.c_str(), size_str.c_str());
}
this->name_to_file.emplace(dol->name, dol);
@@ -503,7 +503,7 @@ uint32_t specific_version_for_gc_header_checksum(uint32_t header_checksum) {
data.region_code = *region_code;
for (uint8_t version_code = 0; version_code < 8; version_code++) {
data.version_code = version_code;
uint32_t checksum = crc32(&data, sizeof(data));
uint32_t checksum = phosg::crc32(&data, sizeof(data));
uint32_t specific_version = 0x33000030 | (*game_code2 << 16) | (*region_code << 8) | version_code;
if (!checksum_to_specific_version.emplace(checksum, specific_version).second) {
throw logic_error("multiple specific_versions have same header checksum");
@@ -515,7 +515,7 @@ uint32_t specific_version_for_gc_header_checksum(uint32_t header_checksum) {
data.region_code = 'J';
data.system_code = 'D';
data.version_code = 0;
uint32_t checksum = crc32(&data, sizeof(data));
uint32_t checksum = phosg::crc32(&data, sizeof(data));
uint32_t specific_version = 0x33004A54 | (*game_code2 << 16);
if (!checksum_to_specific_version.emplace(checksum, specific_version).second) {
throw logic_error("multiple specific_versions have same header checksum");
+13 -14
View File
@@ -5,16 +5,15 @@
#include <stdexcept>
#include "Text.hh"
#include "Types.hh"
using namespace std;
template <bool IsBigEndian>
template <bool BE>
struct GSLHeaderEntryT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
pstring<TextEncoding::ASCII, 0x20> filename;
U32T offset; // In pages, so actual offset is this * 0x800
U32T size;
U32T<BE> offset; // In pages, so actual offset is this * 0x800
U32T<BE> size;
uint64_t unused;
} __packed__;
@@ -23,12 +22,12 @@ using GSLHeaderEntryBE = GSLHeaderEntryT<true>;
check_struct_size(GSLHeaderEntry, 0x30);
check_struct_size(GSLHeaderEntryBE, 0x30);
template <bool IsBigEndian>
template <bool BE>
void GSLArchive::load_t() {
StringReader r(*this->data);
phosg::StringReader r(*this->data);
uint64_t min_data_offset = 0xFFFFFFFFFFFFFFFF;
while (r.where() < min_data_offset) {
const auto& entry = r.get<GSLHeaderEntryT<IsBigEndian>>();
const auto& entry = r.get<GSLHeaderEntryT<BE>>();
if (entry.filename.empty()) {
break;
}
@@ -71,10 +70,10 @@ string GSLArchive::get_copy(const string& name) const {
}
}
StringReader GSLArchive::get_reader(const string& name) const {
phosg::StringReader GSLArchive::get_reader(const string& name) const {
try {
const auto& entry = this->entries.at(name);
return StringReader(this->data->data() + entry.offset, entry.size);
return phosg::StringReader(this->data->data() + entry.offset, entry.size);
} catch (const out_of_range&) {
throw out_of_range("GSL does not contain file: " + name);
}
@@ -84,16 +83,16 @@ string GSLArchive::generate(const unordered_map<string, string>& files, bool big
return big_endian ? GSLArchive::generate_t<true>(files) : GSLArchive::generate_t<false>(files);
}
template <bool IsBigEndian>
template <bool BE>
string GSLArchive::generate_t(const unordered_map<string, string>& files) {
StringWriter w;
phosg::StringWriter w;
// Make sure there's enough space for a blank header entry before any file's
// data pages begin
uint32_t data_start_offset = ((sizeof(GSLHeaderEntryT<IsBigEndian>) * (files.size() + 1)) + 0x7FF) & (~0x7FF);
uint32_t data_start_offset = ((sizeof(GSLHeaderEntryT<BE>) * (files.size() + 1)) + 0x7FF) & (~0x7FF);
uint32_t data_offset = data_start_offset;
for (const auto& file : files) {
GSLHeaderEntryT<IsBigEndian> entry;
GSLHeaderEntryT<BE> entry;
entry.filename.encode(file.first);
entry.offset = data_offset >> 11;
entry.size = file.second.size();
+3 -3
View File
@@ -21,14 +21,14 @@ public:
std::pair<const void*, size_t> get(const std::string& name) const;
std::string get_copy(const std::string& name) const;
StringReader get_reader(const std::string& name) const;
phosg::StringReader get_reader(const std::string& name) const;
static std::string generate(const std::unordered_map<std::string, std::string>& files, bool big_endian);
private:
template <bool IsBigEndian>
template <bool BE>
void load_t();
template <bool IsBigEndian>
template <bool BE>
static std::string generate_t(const std::unordered_map<std::string, std::string>& files);
std::shared_ptr<const std::string> data;
+2 -2
View File
@@ -34,7 +34,7 @@ struct GVRHeader {
be_uint16_t height;
} __packed_ws__(GVRHeader, 0x10);
string encode_gvm(const Image& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index) {
string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index) {
int8_t dimensions_field = -2;
{
size_t h = img.get_height();
@@ -66,7 +66,7 @@ string encode_gvm(const Image& img, GVRDataFormat data_format, const std::string
throw invalid_argument("cannot encode pixel format");
}
StringWriter w;
phosg::StringWriter w;
w.put<GVMFileHeader>({.signature = 0x47564D48, .header_size = 0x48, .flags = 0x000F, .num_files = 1});
GVMFileEntry file_entry;
file_entry.file_num = 0;
+1 -1
View File
@@ -19,7 +19,7 @@ enum class GVRDataFormat : uint8_t {
DXT1 = 0x0E,
};
std::string encode_gvm(const Image& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index);
std::string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index);
constexpr uint16_t encode_rgb565(uint8_t r, uint8_t g, uint8_t b) {
return ((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001F);
+153 -153
View File
@@ -110,7 +110,7 @@ unordered_multimap<string, string> HTTPServer::parse_url_params(const string& qu
if (query.empty()) {
return params;
}
for (auto it : split(query, '&')) {
for (auto it : phosg::split(query, '&')) {
size_t first_equals = it.find('=');
if (first_equals != string::npos) {
string value(it, first_equals + 1);
@@ -119,8 +119,8 @@ unordered_multimap<string, string> HTTPServer::parse_url_params(const string& qu
for (; read_offset < value.size(); write_offset++) {
if ((value[read_offset] == '%') && (read_offset < value.size() - 2)) {
value[write_offset] =
static_cast<char>(value_for_hex_char(value[read_offset + 1]) << 4) |
static_cast<char>(value_for_hex_char(value[read_offset + 2]));
static_cast<char>(phosg::value_for_hex_char(value[read_offset + 1]) << 4) |
static_cast<char>(phosg::value_for_hex_char(value[read_offset + 2]));
read_offset += 3;
} else if (value[write_offset] == '+') {
value[write_offset] = ' ';
@@ -171,7 +171,7 @@ HTTPServer::HTTPServer(shared_ptr<ServerState> state)
}
void HTTPServer::listen(const string& socket_path) {
int fd = ::listen(socket_path, 0, SOMAXCONN);
int fd = phosg::listen(socket_path, 0, SOMAXCONN);
server_log.info("Listening on Unix socket %s on fd %d (HTTP)", socket_path.c_str(), fd);
this->add_socket(fd);
}
@@ -180,8 +180,8 @@ void HTTPServer::listen(const string& addr, int port) {
if (port == 0) {
this->listen(addr);
} else {
int fd = ::listen(addr, port, SOMAXCONN);
string netloc_str = render_netloc(addr, port);
int fd = phosg::listen(addr, port, SOMAXCONN);
string netloc_str = phosg::render_netloc(addr, port);
server_log.info("Listening on TCP interface %s on fd %d (HTTP)", netloc_str.c_str(), fd);
this->add_socket(fd);
}
@@ -207,7 +207,7 @@ HTTPServer::WebsocketClient::WebsocketClient(struct evhttp_connection* conn)
: conn(conn),
bev(evhttp_connection_get_bufferevent(this->conn)),
pending_opcode(0xFF),
last_communication_time(now()) {}
last_communication_time(phosg::now()) {}
HTTPServer::WebsocketClient::~WebsocketClient() {
evhttp_connection_free(this->conn);
@@ -241,7 +241,7 @@ shared_ptr<HTTPServer::WebsocketClient> HTTPServer::enable_websockets(struct evh
// we're about to free the original
string sec_websocket_key = sec_websocket_key_header;
string sec_websocket_accept_data = sec_websocket_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
string sec_websocket_accept = base64_encode(sha1(sec_websocket_accept_data));
string sec_websocket_accept = phosg::base64_encode(phosg::sha1(sec_websocket_accept_data));
// Hijack the bufferevent since it's no longer handling HTTP at all
struct evhttp_connection* conn = evhttp_request_get_connection(req);
@@ -290,13 +290,13 @@ void HTTPServer::on_websocket_read(struct bufferevent* bev) {
if (bytes_read < 10) {
break; // Full 64-bit header not yet available
}
payload_size = bswap64(*reinterpret_cast<const uint64_t*>(&header_data[2]));
payload_size = phosg::bswap64(*reinterpret_cast<const uint64_t*>(&header_data[2]));
header_size = 10;
} else if (payload_size == 0x7E) {
if (bytes_read < 4) {
break; // Full 16-bit size header not yet available
}
payload_size = bswap16(*reinterpret_cast<const uint16_t*>(&header_data[2]));
payload_size = phosg::bswap16(*reinterpret_cast<const uint16_t*>(&header_data[2]));
header_size = 4;
}
if (evbuffer_get_length(in_buf) < header_size + payload_size) {
@@ -312,7 +312,7 @@ void HTTPServer::on_websocket_read(struct bufferevent* bev) {
}
shared_ptr<WebsocketClient> c = this->bev_to_websocket_client.at(bev);
c->last_communication_time = now();
c->last_communication_time = phosg::now();
// Read and unmask message data
string payload(payload_size, '\0');
@@ -392,11 +392,11 @@ void HTTPServer::send_websocket_message(struct bufferevent* bev,
if (message.size() > 65535) {
header.push_back(0x7F);
header.resize(10);
*reinterpret_cast<uint64_t*>(const_cast<char*>(header.data() + 2)) = bswap64(message.size());
*reinterpret_cast<uint64_t*>(const_cast<char*>(header.data() + 2)) = phosg::bswap64(message.size());
} else if (message.size() > 0x7D) {
header.push_back(0x7E);
header.resize(4);
*reinterpret_cast<uint16_t*>(const_cast<char*>(header.data() + 2)) = bswap16(message.size());
*reinterpret_cast<uint16_t*>(const_cast<char*>(header.data() + 2)) = phosg::bswap16(message.size());
} else {
header.push_back(message.size());
}
@@ -418,7 +418,7 @@ void HTTPServer::handle_websocket_disconnect(shared_ptr<WebsocketClient> c) {
this->rare_drop_subscribers.erase(c);
}
void HTTPServer::send_rare_drop_notification(shared_ptr<const JSON> message) {
void HTTPServer::send_rare_drop_notification(shared_ptr<const phosg::JSON> message) {
forward_to_event_thread(this->base, [this, message]() -> void {
if (this->rare_drop_subscribers.empty()) {
return;
@@ -434,26 +434,26 @@ void HTTPServer::dispatch_handle_request(struct evhttp_request* req, void* ctx)
reinterpret_cast<HTTPServer*>(ctx)->handle_request(req);
}
JSON HTTPServer::generate_quest_json_st(shared_ptr<const Quest> q) {
phosg::JSON HTTPServer::generate_quest_json_st(shared_ptr<const Quest> q) {
if (!q) {
return nullptr;
}
auto battle_rules_json = q->battle_rules ? q->battle_rules->json() : nullptr;
auto challenge_template_index_json = (q->challenge_template_index >= 0)
? q->challenge_template_index
: JSON(nullptr);
return JSON::dict({
: phosg::JSON(nullptr);
return phosg::JSON::dict({
{"Number", q->quest_number},
{"Episode", name_for_episode(q->episode)},
{"Joinable", q->joinable},
{"LockStatusRegister", (q->lock_status_register >= 0) ? q->lock_status_register : JSON(nullptr)},
{"LockStatusRegister", (q->lock_status_register >= 0) ? q->lock_status_register : phosg::JSON(nullptr)},
{"Name", q->name},
{"BattleRules", std::move(battle_rules_json)},
{"ChallengeTemplateIndex", std::move(challenge_template_index_json)},
});
}
JSON HTTPServer::generate_client_config_json_st(const Client::Config& config) {
phosg::JSON HTTPServer::generate_client_config_json_st(const Client::Config& config) {
const char* drop_notifications_mode = "unknown";
switch (config.get_drop_notification_mode()) {
case Client::ItemDropNotificationMode::NOTHING:
@@ -470,7 +470,7 @@ JSON HTTPServer::generate_client_config_json_st(const Client::Config& config) {
break;
}
auto ret = JSON::dict({
auto ret = phosg::JSON::dict({
{"SpecificVersion", config.specific_version},
{"SwitchAssistEnabled", (config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED) ? true : false)},
{"InfiniteHPEnabled", (config.check_flag(Client::Flag::INFINITE_HP_ENABLED) ? true : false)},
@@ -486,46 +486,46 @@ JSON HTTPServer::generate_client_config_json_st(const Client::Config& config) {
{"ProxyBlockFunctionCalls", (config.check_flag(Client::Flag::PROXY_BLOCK_FUNCTION_CALLS) ? true : false)},
{"ProxyEp3UnmaskWhispers", (config.check_flag(Client::Flag::PROXY_EP3_UNMASK_WHISPERS) ? true : false)},
});
ret.emplace("OverrideRandomSeed", config.check_flag(Client::Flag::USE_OVERRIDE_RANDOM_SEED) ? config.override_random_seed : JSON(nullptr));
ret.emplace("OverrideSectionID", (config.override_section_id != 0xFF) ? config.override_section_id : JSON(nullptr));
ret.emplace("OverrideLobbyEvent", (config.override_lobby_event != 0xFF) ? config.override_lobby_event : JSON(nullptr));
ret.emplace("OverrideLobbyNumber", (config.override_lobby_number != 0x80) ? config.override_lobby_number : JSON(nullptr));
ret.emplace("OverrideRandomSeed", config.check_flag(Client::Flag::USE_OVERRIDE_RANDOM_SEED) ? config.override_random_seed : phosg::JSON(nullptr));
ret.emplace("OverrideSectionID", (config.override_section_id != 0xFF) ? config.override_section_id : phosg::JSON(nullptr));
ret.emplace("OverrideLobbyEvent", (config.override_lobby_event != 0xFF) ? config.override_lobby_event : phosg::JSON(nullptr));
ret.emplace("OverrideLobbyNumber", (config.override_lobby_number != 0x80) ? config.override_lobby_number : phosg::JSON(nullptr));
return ret;
}
JSON HTTPServer::generate_account_json_st(shared_ptr<const Account> a) {
auto dc_nte_licenses_json = JSON::list();
phosg::JSON HTTPServer::generate_account_json_st(shared_ptr<const Account> a) {
auto dc_nte_licenses_json = phosg::JSON::list();
for (const auto& it : a->dc_nte_licenses) {
dc_nte_licenses_json.emplace_back(it.first);
}
auto dc_licenses_json = JSON::list();
auto dc_licenses_json = phosg::JSON::list();
for (const auto& it : a->dc_licenses) {
dc_licenses_json.emplace_back(it.first);
}
auto pc_licenses_json = JSON::list();
auto pc_licenses_json = phosg::JSON::list();
for (const auto& it : a->pc_licenses) {
pc_licenses_json.emplace_back(it.first);
}
auto gc_licenses_json = JSON::list();
auto gc_licenses_json = phosg::JSON::list();
for (const auto& it : a->gc_licenses) {
gc_licenses_json.emplace_back(it.first);
}
auto xb_licenses_json = JSON::list();
auto xb_licenses_json = phosg::JSON::list();
for (const auto& it : a->xb_licenses) {
xb_licenses_json.emplace_back(it.first);
}
auto bb_licenses_json = JSON::list();
auto bb_licenses_json = phosg::JSON::list();
for (const auto& it : a->bb_licenses) {
bb_licenses_json.emplace_back(it.first);
}
auto auto_patches_json = JSON::list();
auto auto_patches_json = phosg::JSON::list();
for (const auto& it : a->auto_patches_enabled) {
auto_patches_json.emplace_back(it);
}
return JSON::dict({
return phosg::JSON::dict({
{"AccountID", a->account_id},
{"Flags", a->flags},
{"BanEndTime", a->ban_end_time ? a->ban_end_time : JSON(nullptr)},
{"BanEndTime", a->ban_end_time ? a->ban_end_time : phosg::JSON(nullptr)},
{"Ep3CurrentMeseta", a->ep3_current_meseta},
{"Ep3TotalMesetaEarned", a->ep3_total_meseta_earned},
{"BBTeamID", a->bb_team_id},
@@ -542,11 +542,11 @@ JSON HTTPServer::generate_account_json_st(shared_ptr<const Account> a) {
});
};
JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared_ptr<const ItemNameIndex> item_name_index) {
auto ret = JSON::dict({
phosg::JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared_ptr<const ItemNameIndex> item_name_index) {
auto ret = phosg::JSON::dict({
{"ID", c->id},
{"RemoteAddress", render_sockaddr_storage(c->channel.remote_addr)},
{"Version", name_for_enum(c->version())},
{"RemoteAddress", phosg::render_sockaddr_storage(c->channel.remote_addr)},
{"Version", phosg::name_for_enum(c->version())},
{"SubVersion", c->sub_version},
{"Config", HTTPServer::generate_client_config_json_st(c->config)},
{"Language", name_for_language_code(c->language())},
@@ -555,7 +555,7 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
{"LocationFloor", c->floor},
{"CanChat", c->can_chat},
});
ret.emplace("Account", c->login ? HTTPServer::generate_account_json_st(c->login->account) : JSON(nullptr));
ret.emplace("Account", c->login ? HTTPServer::generate_account_json_st(c->login->account) : phosg::JSON(nullptr));
auto l = c->lobby.lock();
if (l) {
ret.emplace("LobbyID", l->lobby_id);
@@ -580,10 +580,10 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
ret.emplace("NumLuckMaterialsUsed", p->get_material_usage(PSOBBCharacterFile::MaterialType::LUCK));
}
}
JSON items_json = JSON::list();
phosg::JSON items_json = phosg::JSON::list();
for (size_t z = 0; z < p->inventory.num_items; z++) {
const auto& item = p->inventory.items[z];
auto item_dict = JSON::dict({
auto item_dict = phosg::JSON::dict({
{"Flags", item.flags.load()},
{"Data", item.data.hex()},
{"ItemID", item.data.id.load()},
@@ -602,17 +602,17 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
ret.emplace("LCK", p->disp.stats.char_stats.lck.load());
ret.emplace("EXP", p->disp.stats.experience.load());
ret.emplace("Meseta", p->disp.stats.meseta.load());
auto tech_levels_json = JSON::dict();
auto tech_levels_json = phosg::JSON::dict();
for (size_t z = 0; z < 0x13; z++) {
auto level = p->get_technique_level(z);
tech_levels_json.emplace(name_for_technique(z), (level != 0xFF) ? level : JSON(nullptr));
tech_levels_json.emplace(name_for_technique(z), (level != 0xFF) ? level : phosg::JSON(nullptr));
}
ret.emplace("TechniqueLevels", std::move(tech_levels_json));
}
ret.emplace("Height", p->disp.stats.height.load());
ret.emplace("Level", p->disp.stats.level.load());
ret.emplace("NameColor", p->disp.visual.name_color.load());
ret.emplace("ExtraModel", (p->disp.visual.validation_flags & 2) ? p->disp.visual.extra_model : JSON(nullptr));
ret.emplace("ExtraModel", (p->disp.visual.validation_flags & 2) ? p->disp.visual.extra_model : phosg::JSON(nullptr));
ret.emplace("SectionID", name_for_section_id(p->disp.visual.section_id));
ret.emplace("CharClass", name_for_char_class(p->disp.visual.section_id));
ret.emplace("Costume", p->disp.visual.costume.load());
@@ -631,7 +631,7 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
ret.emplace("AutoReply", p->auto_reply.decode(c->language()));
ret.emplace("InfoBoard", p->info_board.decode(c->language()));
auto battle_place_counts = JSON::list({
auto battle_place_counts = phosg::JSON::list({
p->battle_records.place_counts[0].load(),
p->battle_records.place_counts[1].load(),
p->battle_records.place_counts[2].load(),
@@ -641,8 +641,8 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
ret.emplace("BattleDisconnectCount", p->battle_records.disconnect_count.load());
if (!is_ep3(c->version())) {
auto json_for_challenge_times = []<size_t Count>(const parray<ChallengeTime, Count>& times) -> JSON {
auto times_json = JSON::list();
auto json_for_challenge_times = []<size_t Count>(const parray<ChallengeTime, Count>& times) -> phosg::JSON {
auto times_json = phosg::JSON::list();
for (size_t z = 0; z < times.size(); z++) {
times_json.emplace_back(times[z].decode());
}
@@ -662,7 +662,7 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
uint8_t day = (p->challenge_records.grave_time >> 16) & 0xFF;
uint8_t hour = (p->challenge_records.grave_time >> 8) & 0xFF;
uint8_t minute = p->challenge_records.grave_time & 0xFF;
ret.emplace("ChallengeGraveTime", string_printf("%04hu-%02hhu-%02hhu %02hhu:%02hhu:00", year, month, day, hour, minute));
ret.emplace("ChallengeGraveTime", phosg::string_printf("%04hu-%02hhu-%02hhu %02hhu:%02hhu:00", year, month, day, hour, minute));
}
string grave_enemy_types;
if (p->challenge_records.grave_defeated_by_enemy_rt_index) {
@@ -670,7 +670,7 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
if (!grave_enemy_types.empty()) {
grave_enemy_types += "/";
}
grave_enemy_types += name_for_enum(type);
grave_enemy_types += phosg::name_for_enum(type);
}
}
ret.emplace("ChallengeGraveDefeatedByEnemy", std::move(grave_enemy_types));
@@ -691,7 +691,7 @@ JSON HTTPServer::generate_game_client_json_st(shared_ptr<const Client> c, shared
return ret;
}
JSON HTTPServer::generate_proxy_client_json_st(shared_ptr<const ProxyServer::LinkedSession> ses) {
phosg::JSON HTTPServer::generate_proxy_client_json_st(shared_ptr<const ProxyServer::LinkedSession> ses) {
struct LobbyPlayer {
uint32_t guild_card_number = 0;
uint64_t xb_user_id = 0;
@@ -702,35 +702,35 @@ JSON HTTPServer::generate_proxy_client_json_st(shared_ptr<const ProxyServer::Lin
};
std::vector<LobbyPlayer> lobby_players;
auto lobby_players_json = JSON::list();
auto lobby_players_json = phosg::JSON::list();
for (size_t z = 0; z < ses->lobby_players.size(); z++) {
const auto& p = ses->lobby_players[z];
if (p.guild_card_number) {
lobby_players_json.emplace_back(JSON::dict({
lobby_players_json.emplace_back(phosg::JSON::dict({
{"GuildCardNumber", p.guild_card_number},
{"Name", p.name},
{"Language", name_for_language_code(p.language)},
{"SectionID", name_for_section_id(p.section_id)},
{"CharClass", name_for_char_class(p.char_class)},
}));
lobby_players_json.back().emplace("XBUserID", p.xb_user_id ? p.xb_user_id : JSON(nullptr));
lobby_players_json.back().emplace("XBUserID", p.xb_user_id ? p.xb_user_id : phosg::JSON(nullptr));
} else {
lobby_players_json.emplace_back(nullptr);
}
}
auto ret = JSON::dict({
auto ret = phosg::JSON::dict({
{"ID", ses->id},
{"RemoteClientAddress", render_sockaddr_storage(ses->client_channel.remote_addr)},
{"RemoteServerAddress", render_sockaddr_storage(ses->server_channel.remote_addr)},
{"RemoteClientAddress", phosg::render_sockaddr_storage(ses->client_channel.remote_addr)},
{"RemoteServerAddress", phosg::render_sockaddr_storage(ses->server_channel.remote_addr)},
{"LocalPort", ses->local_port},
{"NextDestination", render_sockaddr_storage(ses->next_destination)},
{"Version", name_for_enum(ses->version())},
{"NextDestination", phosg::render_sockaddr_storage(ses->next_destination)},
{"Version", phosg::name_for_enum(ses->version())},
{"SubVersion", ses->sub_version},
{"Name", ses->character_name},
{"DCHardwareID", ses->hardware_id},
{"RemoteGuildCardNumber", ses->remote_guild_card_number},
{"RemoteClientConfigData", format_data_string(&ses->remote_client_config_data[0], ses->remote_client_config_data.size())},
{"RemoteClientConfigData", phosg::format_data_string(&ses->remote_client_config_data[0], ses->remote_client_config_data.size())},
{"Config", HTTPServer::generate_client_config_json_st(ses->config)},
{"Language", name_for_language_code(ses->language())},
{"LobbyClientID", ses->lobby_client_id},
@@ -759,19 +759,19 @@ JSON HTTPServer::generate_proxy_client_json_st(shared_ptr<const ProxyServer::Lin
ret.emplace("DropMode", "proxy");
break;
}
ret.emplace("Account", ses->login ? HTTPServer::generate_account_json_st(ses->login->account) : JSON(nullptr));
ret.emplace("Account", ses->login ? HTTPServer::generate_account_json_st(ses->login->account) : phosg::JSON(nullptr));
return ret;
}
JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<const ItemNameIndex> item_name_index) {
phosg::JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<const ItemNameIndex> item_name_index) {
std::array<std::shared_ptr<Client>, 12> clients;
auto client_ids_json = JSON::list();
auto client_ids_json = phosg::JSON::list();
for (size_t z = 0; z < l->max_clients; z++) {
client_ids_json.emplace_back(l->clients[z] ? l->clients[z]->id : JSON(nullptr));
client_ids_json.emplace_back(l->clients[z] ? l->clients[z]->id : phosg::JSON(nullptr));
}
auto ret = JSON::dict({
auto ret = phosg::JSON::dict({
{"ID", l->lobby_id},
{"AllowedVersions", l->allowed_versions},
{"Event", l->event},
@@ -796,7 +796,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
ret.emplace("QuestSelectionInProgress", l->check_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS));
ret.emplace("QuestInProgress", l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS));
ret.emplace("JoinableQuestInProgress", l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS));
auto variations_json = JSON::list();
auto variations_json = phosg::JSON::list();
for (size_t z = 0; z < l->variations.size(); z++) {
variations_json.emplace_back(l->variations[z].load());
}
@@ -839,11 +839,11 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
}
}
auto floor_items_json = JSON::list();
auto floor_items_json = phosg::JSON::list();
for (size_t floor = 0; floor < l->floor_item_managers.size(); floor++) {
for (const auto& it : l->floor_item_managers[floor].items) {
const auto& item = it.second;
auto item_dict = JSON::dict({
auto item_dict = phosg::JSON::dict({
{"LocationFloor", floor},
{"LocationX", item->x},
{"LocationZ", item->z},
@@ -868,7 +868,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
auto ep3s = l->ep3_server;
if (ep3s) {
auto players_json = JSON::list();
auto players_json = phosg::JSON::list();
for (size_t z = 0; z < 4; z++) {
if (!ep3s->name_entries[z].present) {
players_json.emplace_back(nullptr);
@@ -876,9 +876,9 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
auto lc = l->clients[z];
auto deck_entry = ep3s->deck_entries[z];
JSON deck_json = nullptr;
phosg::JSON deck_json = nullptr;
if (deck_entry) {
auto cards_json = JSON::list();
auto cards_json = phosg::JSON::list();
for (size_t w = 0; w < deck_entry->card_ids.size(); w++) {
try {
const auto& ce = ep3s->options.card_index->definition_for_id(deck_entry->card_ids[w]);
@@ -897,7 +897,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
cards_json.emplace_back(deck_entry->card_ids[w].load());
}
}
deck_json = JSON::dict({
deck_json = phosg::JSON::dict({
{"Name", deck_entry->name.decode(lc ? lc->language() : 1)},
{"TeamID", deck_entry->team_id.load()},
{"Cards", std::move(cards_json)},
@@ -906,7 +906,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
});
}
auto player_json = JSON::dict({
auto player_json = phosg::JSON::dict({
{"PlayerName", ep3s->name_entries[z].name.decode(lc ? lc->language() : 1)},
{"ClientID", ep3s->name_entries[z].client_id},
{"IsCOM", !!ep3s->name_entries[z].is_cpu_player},
@@ -915,13 +915,13 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
players_json.emplace_back(std::move(player_json));
}
}
auto battle_state_json = JSON::dict({
auto battle_state_json = phosg::JSON::dict({
{"BehaviorFlags", ep3s->options.behavior_flags},
{"RandomSeed", ep3s->options.opt_rand_crypt ? ep3s->options.opt_rand_crypt->seed() : JSON(nullptr)},
{"RandomOffset", ep3s->options.opt_rand_crypt ? ep3s->options.opt_rand_crypt->absolute_offset() : JSON(nullptr)},
{"RandomSeed", ep3s->options.opt_rand_crypt ? ep3s->options.opt_rand_crypt->seed() : phosg::JSON(nullptr)},
{"RandomOffset", ep3s->options.opt_rand_crypt ? ep3s->options.opt_rand_crypt->absolute_offset() : phosg::JSON(nullptr)},
{"Tournament", ep3s->options.tournament ? ep3s->options.tournament->json() : nullptr},
{"MapNumber", ep3s->last_chosen_map ? ep3s->last_chosen_map->map_number : JSON(nullptr)},
{"EnvironmentNumber", ep3s->map_and_rules ? ep3s->map_and_rules->environment_number : JSON(nullptr)},
{"MapNumber", ep3s->last_chosen_map ? ep3s->last_chosen_map->map_number : phosg::JSON(nullptr)},
{"EnvironmentNumber", ep3s->map_and_rules ? ep3s->map_and_rules->environment_number : phosg::JSON(nullptr)},
{"Rules", ep3s->map_and_rules ? ep3s->map_and_rules->rules.json() : nullptr},
{"Players", std::move(players_json)},
{"IsBattleFinished", ep3s->battle_finished},
@@ -929,13 +929,13 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
{"RoundNumber", ep3s->round_num},
{"FirstTeamTurn", ep3s->first_team_turn},
{"CurrentTeamTurn", ep3s->current_team_turn1},
{"BattlePhase", name_for_enum(ep3s->battle_phase)},
{"BattlePhase", phosg::name_for_enum(ep3s->battle_phase)},
{"SetupPhase", ep3s->setup_phase},
{"RegistrationPhase", ep3s->registration_phase},
{"ActionSubphase", ep3s->action_subphase},
{"BattleStartTimeUsecs", ep3s->battle_start_usecs},
{"TeamEXP", JSON::list({ep3s->team_exp[0], ep3s->team_exp[1]})},
{"TeamDiceBonus", JSON::list({ep3s->team_dice_bonus[0], ep3s->team_dice_bonus[1]})},
{"TeamEXP", phosg::JSON::list({ep3s->team_exp[0], ep3s->team_exp[1]})},
{"TeamDiceBonus", phosg::JSON::list({ep3s->team_dice_bonus[0], ep3s->team_dice_bonus[1]})},
});
// std::shared_ptr<StateFlags> state_flags;
// std::array<std::shared_ptr<PlayerState>, 4> player_states;
@@ -947,7 +947,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
if (watched_lobby) {
ret.emplace("WatchedLobbyID", watched_lobby->lobby_id);
}
auto watcher_lobby_ids_json = JSON::list();
auto watcher_lobby_ids_json = phosg::JSON::list();
for (const auto& watcher_lobby : l->watcher_lobbies) {
watcher_lobby_ids_json.emplace_back(watcher_lobby->lobby_id);
}
@@ -964,9 +964,9 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr<const Lobby> l, shared_ptr<co
return ret;
}
JSON HTTPServer::generate_game_server_clients_json() const {
return call_on_event_thread<JSON>(this->state->base, [&]() {
auto res = JSON::list();
phosg::JSON HTTPServer::generate_game_server_clients_json() const {
return call_on_event_thread<phosg::JSON>(this->state->base, [&]() {
auto res = phosg::JSON::list();
for (const auto& it : this->state->channel_to_client) {
res.emplace_back(this->generate_game_client_json_st(it.second, this->state->item_name_index_opt(it.second->version())));
}
@@ -974,9 +974,9 @@ JSON HTTPServer::generate_game_server_clients_json() const {
});
}
JSON HTTPServer::generate_proxy_server_clients_json() const {
return call_on_event_thread<JSON>(this->state->base, [&]() {
JSON res = JSON::list();
phosg::JSON HTTPServer::generate_proxy_server_clients_json() const {
return call_on_event_thread<phosg::JSON>(this->state->base, [&]() {
phosg::JSON res = phosg::JSON::list();
if (this->state->proxy_server) {
for (const auto& it : this->state->proxy_server->all_sessions()) {
res.emplace_back(this->generate_proxy_client_json_st(it.second));
@@ -986,8 +986,8 @@ JSON HTTPServer::generate_proxy_server_clients_json() const {
});
}
JSON HTTPServer::generate_server_info_json() const {
return call_on_event_thread<JSON>(this->state->base, [&]() {
phosg::JSON HTTPServer::generate_server_info_json() const {
return call_on_event_thread<phosg::JSON>(this->state->base, [&]() {
size_t game_count = 0;
size_t lobby_count = 0;
for (const auto& it : this->state->id_to_lobby) {
@@ -997,12 +997,12 @@ JSON HTTPServer::generate_server_info_json() const {
lobby_count++;
}
}
uint64_t uptime_usecs = now() - this->state->creation_time;
return JSON::dict({
uint64_t uptime_usecs = phosg::now() - this->state->creation_time;
return phosg::JSON::dict({
{"StartTimeUsecs", this->state->creation_time},
{"StartTime", format_time(this->state->creation_time)},
{"StartTime", phosg::format_time(this->state->creation_time)},
{"UptimeUsecs", uptime_usecs},
{"Uptime", format_duration(uptime_usecs)},
{"Uptime", phosg::format_duration(uptime_usecs)},
{"LobbyCount", lobby_count},
{"GameCount", game_count},
{"ClientCount", this->state->channel_to_client.size()},
@@ -1012,9 +1012,9 @@ JSON HTTPServer::generate_server_info_json() const {
});
}
JSON HTTPServer::generate_lobbies_json() const {
return call_on_event_thread<JSON>(this->state->base, [&]() {
JSON res = JSON::list();
phosg::JSON HTTPServer::generate_lobbies_json() const {
return call_on_event_thread<phosg::JSON>(this->state->base, [&]() {
phosg::JSON res = phosg::JSON::list();
for (const auto& it : this->state->id_to_lobby) {
res.emplace_back(this->generate_lobby_json_st(it.second, this->state->item_name_index_opt(it.second->base_version)));
}
@@ -1022,46 +1022,46 @@ JSON HTTPServer::generate_lobbies_json() const {
});
}
JSON HTTPServer::generate_summary_json() const {
auto ret = call_on_event_thread<JSON>(this->state->base, [&]() {
auto clients_json = JSON::list();
phosg::JSON HTTPServer::generate_summary_json() const {
auto ret = call_on_event_thread<phosg::JSON>(this->state->base, [&]() {
auto clients_json = phosg::JSON::list();
for (const auto& it : this->state->channel_to_client) {
auto c = it.second;
auto p = c->character(false, false);
auto l = c->lobby.lock();
clients_json.emplace_back(JSON::dict({
clients_json.emplace_back(phosg::JSON::dict({
{"ID", c->id},
{"AccountID", c->login ? c->login->account->account_id : JSON(nullptr)},
{"Name", p ? p->disp.name.decode(it.second->language()) : JSON(nullptr)},
{"Version", name_for_enum(it.second->version())},
{"AccountID", c->login ? c->login->account->account_id : phosg::JSON(nullptr)},
{"Name", p ? p->disp.name.decode(it.second->language()) : phosg::JSON(nullptr)},
{"Version", phosg::name_for_enum(it.second->version())},
{"Language", name_for_language_code(it.second->language())},
{"Level", p ? p->disp.stats.level + 1 : JSON(nullptr)},
{"Class", p ? name_for_char_class(p->disp.visual.char_class) : JSON(nullptr)},
{"SectionID", p ? name_for_section_id(p->disp.visual.section_id) : JSON(nullptr)},
{"LobbyID", l ? l->lobby_id : JSON(nullptr)},
{"Level", p ? p->disp.stats.level + 1 : phosg::JSON(nullptr)},
{"Class", p ? name_for_char_class(p->disp.visual.char_class) : phosg::JSON(nullptr)},
{"SectionID", p ? name_for_section_id(p->disp.visual.section_id) : phosg::JSON(nullptr)},
{"LobbyID", l ? l->lobby_id : phosg::JSON(nullptr)},
}));
}
auto proxy_clients_json = JSON::list();
auto proxy_clients_json = phosg::JSON::list();
if (this->state->proxy_server) {
for (const auto& it : this->state->proxy_server->all_sessions()) {
proxy_clients_json.emplace_back(JSON::dict({
{"AccountID", it.second->login ? it.second->login->account->account_id : JSON(nullptr)},
proxy_clients_json.emplace_back(phosg::JSON::dict({
{"AccountID", it.second->login ? it.second->login->account->account_id : phosg::JSON(nullptr)},
{"Name", it.second->character_name},
{"Version", name_for_enum(it.second->version())},
{"Version", phosg::name_for_enum(it.second->version())},
{"Language", name_for_language_code(it.second->language())},
}));
}
}
auto games_json = JSON::list();
auto games_json = phosg::JSON::list();
for (const auto& it : this->state->id_to_lobby) {
auto l = it.second;
if (l->is_game()) {
auto game_json = JSON::dict({
auto game_json = phosg::JSON::dict({
{"ID", l->lobby_id},
{"Name", l->name},
{"BaseVersion", name_for_enum(l->base_version)},
{"BaseVersion", phosg::name_for_enum(l->base_version)},
{"Players", l->count_clients()},
{"CheatsEnabled", l->check_flag(Lobby::Flag::CHEATS_ENABLED)},
{"Episode", name_for_episode(l->episode)},
@@ -1071,7 +1071,7 @@ JSON HTTPServer::generate_summary_json() const {
auto ep3s = l->ep3_server;
game_json.emplace("BattleInProgress", l->check_flag(Lobby::Flag::BATTLE_IN_PROGRESS));
game_json.emplace("IsSpectatorTeam", l->check_flag(Lobby::Flag::IS_SPECTATOR_TEAM));
game_json.emplace("MapNumber", (ep3s && ep3s->last_chosen_map) ? ep3s->last_chosen_map->map_number : JSON(nullptr));
game_json.emplace("MapNumber", (ep3s && ep3s->last_chosen_map) ? ep3s->last_chosen_map->map_number : phosg::JSON(nullptr));
game_json.emplace("Rules", (ep3s && ep3s->map_and_rules) ? ep3s->map_and_rules->rules.json() : nullptr);
} else {
game_json.emplace("QuestSelectionInProgress", l->check_flag(Lobby::Flag::QUEST_SELECTION_IN_PROGRESS));
@@ -1086,7 +1086,7 @@ JSON HTTPServer::generate_summary_json() const {
}
}
return JSON::dict({
return phosg::JSON::dict({
{"Clients", std::move(clients_json)},
{"ProxyClients", std::move(proxy_clients_json)},
{"Games", std::move(games_json)},
@@ -1096,8 +1096,8 @@ JSON HTTPServer::generate_summary_json() const {
return ret;
}
JSON HTTPServer::generate_all_json() const {
return JSON::dict({
phosg::JSON HTTPServer::generate_all_json() const {
return phosg::JSON::dict({
{"Clients", this->generate_game_server_clients_json()},
{"ProxyClients", this->generate_proxy_server_clients_json()},
{"Lobbies", this->generate_lobbies_json()},
@@ -1105,43 +1105,43 @@ JSON HTTPServer::generate_all_json() const {
});
}
JSON HTTPServer::generate_ep3_cards_json(bool trial) const {
phosg::JSON HTTPServer::generate_ep3_cards_json(bool trial) const {
auto index = call_on_event_thread<shared_ptr<const Episode3::CardIndex>>(this->state->base, [&]() {
return trial ? this->state->ep3_card_index_trial : this->state->ep3_card_index;
});
return index->definitions_json();
}
JSON HTTPServer::generate_common_tables_json() const {
phosg::JSON HTTPServer::generate_common_tables_json() const {
auto [set_v2, set_v3_v4] = call_on_event_thread<pair<shared_ptr<const CommonItemSet>, shared_ptr<const CommonItemSet>>>(this->state->base, [&]() {
return make_pair(this->state->common_item_set_v2, this->state->common_item_set_v3_v4);
});
return JSON::dict({{"v1_v2", set_v2->json()}, {"v3_v4", set_v3_v4->json()}});
return phosg::JSON::dict({{"v1_v2", set_v2->json()}, {"v3_v4", set_v3_v4->json()}});
}
JSON HTTPServer::generate_rare_tables_json() const {
phosg::JSON HTTPServer::generate_rare_tables_json() const {
auto sets = call_on_event_thread<unordered_map<string, shared_ptr<const RareItemSet>>>(this->state->base, [&]() {
return this->state->rare_item_sets;
});
JSON ret = JSON::list();
phosg::JSON ret = phosg::JSON::list();
for (const auto& it : sets) {
ret.emplace_back(it.first);
}
return ret;
}
JSON HTTPServer::generate_rare_table_json(const std::string& table_name) const {
phosg::JSON HTTPServer::generate_rare_table_json(const std::string& table_name) const {
try {
auto colls = call_on_event_thread<pair<shared_ptr<const RareItemSet>, shared_ptr<const ItemNameIndex>>>(this->state->base, [&]() {
const auto& table = this->state->rare_item_sets.at(table_name);
shared_ptr<const ItemNameIndex> name_index;
if (ends_with(table_name, "-v1")) {
if (phosg::ends_with(table_name, "-v1")) {
name_index = this->state->item_name_index_opt(Version::DC_V1);
} else if (ends_with(table_name, "-v2")) {
} else if (phosg::ends_with(table_name, "-v2")) {
name_index = this->state->item_name_index_opt(Version::PC_V2);
} else if (ends_with(table_name, "-v3")) {
} else if (phosg::ends_with(table_name, "-v3")) {
name_index = this->state->item_name_index_opt(Version::GC_V3);
} else if (ends_with(table_name, "-v4")) {
} else if (phosg::ends_with(table_name, "-v4")) {
name_index = this->state->item_name_index_opt(Version::BB_V4);
}
return make_pair(table, name_index);
@@ -1153,9 +1153,9 @@ JSON HTTPServer::generate_rare_table_json(const std::string& table_name) const {
}
void HTTPServer::handle_request(struct evhttp_request* req) {
shared_ptr<const JSON> ret;
shared_ptr<const phosg::JSON> ret;
uint32_t serialize_options = 0;
uint64_t start_time = now();
uint64_t start_time = phosg::now();
string uri = evhttp_request_get_uri(req);
try {
@@ -1168,14 +1168,14 @@ void HTTPServer::handle_request(struct evhttp_request* req) {
static const string default_format_option = "false";
if (this->get_url_param(query, "format", &default_format_option) == "true") {
serialize_options |= JSON::SerializeOption::FORMAT | JSON::SerializeOption::SORT_DICT_KEYS;
serialize_options |= phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS;
}
if (this->get_url_param(query, "hex", &default_format_option) == "true") {
serialize_options |= JSON::SerializeOption::HEX_INTEGERS;
serialize_options |= phosg::JSON::SerializeOption::HEX_INTEGERS;
}
if (uri == "/") {
auto endpoints_json = JSON::list({
auto endpoints_json = phosg::JSON::list({
"/y/data/ep3-cards",
"/y/data/ep3-cards-trial",
"/y/data/common-tables",
@@ -1190,7 +1190,7 @@ void HTTPServer::handle_request(struct evhttp_request* req) {
"/y/summary",
"/y/all",
});
ret = make_shared<JSON>(JSON::dict({{"endpoints", std::move(endpoints_json)}}));
ret = make_shared<phosg::JSON>(phosg::JSON::dict({{"endpoints", std::move(endpoints_json)}}));
} else if (uri == "/y/rare-drops/stream") {
auto c = this->enable_websockets(req);
@@ -1198,35 +1198,35 @@ void HTTPServer::handle_request(struct evhttp_request* req) {
throw http_error(400, "this path requires a websocket connection");
} else {
this->rare_drop_subscribers.emplace(c);
auto version_message = JSON::dict({{"ServerType", "newserv"}});
auto version_message = phosg::JSON::dict({{"ServerType", "newserv"}});
this->send_websocket_message(c, version_message.serialize());
return;
}
} else if (uri == "/y/data/ep3-cards") {
ret = make_shared<JSON>(this->generate_ep3_cards_json(false));
ret = make_shared<phosg::JSON>(this->generate_ep3_cards_json(false));
} else if (uri == "/y/data/ep3-cards-trial") {
ret = make_shared<JSON>(this->generate_ep3_cards_json(true));
ret = make_shared<phosg::JSON>(this->generate_ep3_cards_json(true));
} else if (uri == "/y/data/common-tables") {
ret = make_shared<JSON>(this->generate_common_tables_json());
ret = make_shared<phosg::JSON>(this->generate_common_tables_json());
} else if (uri == "/y/data/rare-tables") {
ret = make_shared<JSON>(this->generate_rare_tables_json());
ret = make_shared<phosg::JSON>(this->generate_rare_tables_json());
} else if (!strncmp(uri.c_str(), "/y/data/rare-tables/", 20)) {
ret = make_shared<JSON>(this->generate_rare_table_json(uri.substr(20)));
ret = make_shared<phosg::JSON>(this->generate_rare_table_json(uri.substr(20)));
} else if (uri == "/y/data/config") {
ret = call_on_event_thread<shared_ptr<const JSON>>(this->state->base, [this]() { return this->state->config_json; });
ret = call_on_event_thread<shared_ptr<const phosg::JSON>>(this->state->base, [this]() { return this->state->config_json; });
} else if (uri == "/y/clients") {
ret = make_shared<JSON>(this->generate_game_server_clients_json());
ret = make_shared<phosg::JSON>(this->generate_game_server_clients_json());
} else if (uri == "/y/proxy-clients") {
ret = make_shared<JSON>(this->generate_proxy_server_clients_json());
ret = make_shared<phosg::JSON>(this->generate_proxy_server_clients_json());
} else if (uri == "/y/lobbies") {
ret = make_shared<JSON>(this->generate_lobbies_json());
ret = make_shared<phosg::JSON>(this->generate_lobbies_json());
} else if (uri == "/y/server") {
ret = make_shared<JSON>(this->generate_server_info_json());
ret = make_shared<phosg::JSON>(this->generate_server_info_json());
} else if (uri == "/y/summary") {
ret = make_shared<JSON>(this->generate_summary_json());
ret = make_shared<phosg::JSON>(this->generate_summary_json());
} else if (uri == "/y/all") {
ret = make_shared<JSON>(this->generate_all_json());
ret = make_shared<phosg::JSON>(this->generate_all_json());
} else {
throw http_error(404, "unknown action");
@@ -1246,20 +1246,20 @@ void HTTPServer::handle_request(struct evhttp_request* req) {
return;
}
uint64_t handler_end = now();
uint64_t handler_end = phosg::now();
unique_ptr<struct evbuffer, void (*)(struct evbuffer*)> out_buffer(evbuffer_new(), evbuffer_free);
string* serialized = new string(ret->serialize(JSON::SerializeOption::ESCAPE_CONTROLS_ONLY | serialize_options));
string* serialized = new string(ret->serialize(phosg::JSON::SerializeOption::ESCAPE_CONTROLS_ONLY | serialize_options));
size_t size = serialized->size();
uint64_t serialize_end = now();
uint64_t serialize_end = phosg::now();
auto cleanup = +[](const void*, size_t, void* s) -> void {
delete reinterpret_cast<string*>(s);
};
evbuffer_add_reference(out_buffer.get(), serialized->data(), serialized->size(), cleanup, serialized);
this->send_response(req, 200, "application/json", out_buffer.get());
string handler_time = format_duration(handler_end - start_time);
string serialize_time = format_duration(serialize_end - handler_end);
string size_str = format_size(size);
string handler_time = phosg::format_duration(handler_end - start_time);
string serialize_time = phosg::format_duration(serialize_end - handler_end);
string size_str = phosg::format_size(size);
server_log.info("[HTTPServer] %s in [handler: %s, serialize: %s, size: %s]",
uri.c_str(), handler_time.c_str(), serialize_time.c_str(), size_str.c_str());
}
+17 -17
View File
@@ -28,7 +28,7 @@ public:
void schedule_stop();
void wait_for_stop();
void send_rare_drop_notification(std::shared_ptr<const JSON> message);
void send_rare_drop_notification(std::shared_ptr<const phosg::JSON> message);
protected:
class http_error : public std::runtime_error {
@@ -94,21 +94,21 @@ protected:
const std::string& key,
const std::string* _default = nullptr);
static JSON generate_quest_json_st(std::shared_ptr<const Quest> q);
static JSON generate_client_config_json_st(const Client::Config& config);
static JSON generate_account_json_st(std::shared_ptr<const Account> a);
static JSON generate_game_client_json_st(std::shared_ptr<const Client> c, std::shared_ptr<const ItemNameIndex> item_name_index);
static JSON generate_proxy_client_json_st(std::shared_ptr<const ProxyServer::LinkedSession> ses);
static JSON generate_lobby_json_st(std::shared_ptr<const Lobby> l, std::shared_ptr<const ItemNameIndex> item_name_index);
JSON generate_game_server_clients_json() const;
JSON generate_proxy_server_clients_json() const;
JSON generate_server_info_json() const;
JSON generate_lobbies_json() const;
JSON generate_summary_json() const;
JSON generate_all_json() const;
static phosg::JSON generate_quest_json_st(std::shared_ptr<const Quest> q);
static phosg::JSON generate_client_config_json_st(const Client::Config& config);
static phosg::JSON generate_account_json_st(std::shared_ptr<const Account> a);
static phosg::JSON generate_game_client_json_st(std::shared_ptr<const Client> c, std::shared_ptr<const ItemNameIndex> item_name_index);
static phosg::JSON generate_proxy_client_json_st(std::shared_ptr<const ProxyServer::LinkedSession> ses);
static phosg::JSON generate_lobby_json_st(std::shared_ptr<const Lobby> l, std::shared_ptr<const ItemNameIndex> item_name_index);
phosg::JSON generate_game_server_clients_json() const;
phosg::JSON generate_proxy_server_clients_json() const;
phosg::JSON generate_server_info_json() const;
phosg::JSON generate_lobbies_json() const;
phosg::JSON generate_summary_json() const;
phosg::JSON generate_all_json() const;
JSON generate_ep3_cards_json(bool trial) const;
JSON generate_common_tables_json() const;
JSON generate_rare_tables_json() const;
JSON generate_rare_table_json(const std::string& table_name) const;
phosg::JSON generate_ep3_cards_json(bool trial) const;
phosg::JSON generate_common_tables_json() const;
phosg::JSON generate_rare_tables_json() const;
phosg::JSON generate_rare_table_json(const std::string& table_name) const;
};
+10 -10
View File
@@ -23,7 +23,7 @@ FrameInfo::FrameInfo(LinkType link_type, const void* header_start, size_t size)
this->total_size = size;
this->payload_size = size;
StringReader r(header_start, size);
phosg::StringReader r(header_start, size);
// Parse link-layer header
Protocol proto = Protocol::NONE;
@@ -126,35 +126,35 @@ string FrameInfo::header_str() const {
string ret;
if (this->ether) {
ret = string_printf(
ret = phosg::string_printf(
"ETHER:%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX->%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX",
this->ether->src_mac[0], this->ether->src_mac[1], this->ether->src_mac[2],
this->ether->src_mac[3], this->ether->src_mac[4], this->ether->src_mac[5],
this->ether->dest_mac[0], this->ether->dest_mac[1], this->ether->dest_mac[2],
this->ether->dest_mac[3], this->ether->dest_mac[4], this->ether->dest_mac[5]);
} else if (this->hdlc) {
ret = string_printf("HDLC:%02hhX/%02hhX", this->hdlc->address, this->hdlc->control);
ret = phosg::string_printf("HDLC:%02hhX/%02hhX", this->hdlc->address, this->hdlc->control);
} else {
return "<invalid-frame-info>";
}
if (this->arp) {
ret += string_printf(
ret += phosg::string_printf(
",ARP,hw_type=%04hX,proto_type=%04hX,hw_addr_len=%02hhX,proto_addr_len=%02hhX,op=%04hX",
this->arp->hardware_type.load(), this->arp->protocol_type.load(), this->arp->hwaddr_len, this->arp->paddr_len, this->arp->operation.load());
} else if (this->ipv4) {
ret += string_printf(
ret += phosg::string_printf(
",IPv4,size=%04hX,src=%08" PRIX32 ",dest=%08" PRIX32,
this->ipv4->size.load(), this->ipv4->src_addr.load(), this->ipv4->dest_addr.load());
if (this->udp) {
ret += string_printf(
ret += phosg::string_printf(
",UDP,src_port=%04hX,dest_port=%04hX,size=%04hX",
this->udp->src_port.load(), this->udp->dest_port.load(), this->udp->size.load());
} else if (this->tcp) {
ret += string_printf(
ret += phosg::string_printf(
",TCP,src_port=%04hX,dest_port=%04hX,seq=%08" PRIX32 ",ack=%08" PRIX32 ",flags=%04hX(",
this->tcp->src_port.load(), this->tcp->dest_port.load(), this->tcp->seq_num.load(), this->tcp->ack_num.load(), this->tcp->flags.load());
if (this->tcp->flags & TCPHeader::Flag::FIN) {
@@ -175,14 +175,14 @@ string FrameInfo::header_str() const {
ret += ')';
} else {
ret += string_printf(",proto=%02hhX", this->ipv4->protocol);
ret += phosg::string_printf(",proto=%02hhX", this->ipv4->protocol);
}
} else {
if (this->ether) {
ret += string_printf(",proto=%04hX", this->ether->protocol.load());
ret += phosg::string_printf(",proto=%04hX", this->ether->protocol.load());
} else if (this->hdlc) {
ret += string_printf(",proto=%04hX", this->hdlc->protocol.load());
ret += phosg::string_printf(",proto=%04hX", this->hdlc->protocol.load());
}
}
+2 -2
View File
@@ -161,8 +161,8 @@ struct FrameInfo {
std::string header_str() const;
inline StringReader read_payload() const {
return StringReader(this->payload, this->payload_size);
inline phosg::StringReader read_payload() const {
return phosg::StringReader(this->payload, this->payload_size);
}
void truncate(size_t new_total_size);
+50 -51
View File
@@ -22,7 +22,7 @@ using namespace std;
static const size_t DEFAULT_RESEND_PUSH_USECS = 200000; // 200ms
static string unescape_hdlc_frame(const void* data, size_t size) {
StringReader r(data, size);
phosg::StringReader r(data, size);
if (r.get_u8(data) != 0x7E) {
throw runtime_error("HDLC frame does not begin with 7E");
}
@@ -53,7 +53,7 @@ static string escape_hdlc_frame(const void* data, size_t size, uint32_t escape_c
throw runtime_error("HDLC frame too small for start and end sentinels");
}
StringReader r(data, size);
phosg::StringReader r(data, size);
if (r.pget_u8(size - 1) != 0x7E) {
throw runtime_error("HDLC frame does not end with 7E");
}
@@ -104,9 +104,9 @@ string IPStackSimulator::str_for_ipv4_netloc(uint32_t addr, uint16_t port) {
be_uint32_t be_addr = addr;
char addr_str[INET_ADDRSTRLEN];
if (!inet_ntop(AF_INET, &be_addr, addr_str, INET_ADDRSTRLEN)) {
return string_printf("<UNKNOWN>:%hu", port);
return phosg::string_printf("<UNKNOWN>:%hu", port);
} else {
return string_printf("%s:%hu", addr_str, port);
return phosg::string_printf("%s:%hu", addr_str, port);
}
}
@@ -115,7 +115,7 @@ string IPStackSimulator::str_for_tcp_connection(shared_ptr<const IPClient> c, co
string server_netloc_str = str_for_ipv4_netloc(conn.server_addr, conn.server_port);
string client_netloc_str = str_for_ipv4_netloc(c->ipv4_addr, conn.client_port);
int fd = bufferevent_getfd(c->bev.get());
return string_printf("%d+%016" PRIX64 " (%s -> %s)",
return phosg::string_printf("%d+%016" PRIX64 " (%s -> %s)",
fd, key, client_netloc_str.c_str(), server_netloc_str.c_str());
}
@@ -137,7 +137,7 @@ IPStackSimulator::~IPStackSimulator() {
}
void IPStackSimulator::listen(const string& name, const string& socket_path, Protocol proto) {
int fd = ::listen(socket_path, 0, SOMAXCONN);
int fd = phosg::listen(socket_path, 0, SOMAXCONN);
ip_stack_simulator_log.info("Listening on Unix socket %s on fd %d as %s", socket_path.c_str(), fd, name.c_str());
this->add_socket(name, fd, proto);
}
@@ -146,8 +146,8 @@ void IPStackSimulator::listen(const string& name, const string& addr, int port,
if (port == 0) {
this->listen(name, addr, proto);
} else {
int fd = ::listen(addr, port, SOMAXCONN);
string netloc_str = render_netloc(addr, port);
int fd = phosg::listen(addr, port, SOMAXCONN);
string netloc_str = phosg::render_netloc(addr, port);
ip_stack_simulator_log.info("Listening on TCP interface %s on fd %d as %s", netloc_str.c_str(), fd, name.c_str());
this->add_socket(name, fd, proto);
}
@@ -195,7 +195,7 @@ IPStackSimulator::IPClient::IPClient(
ipv4_addr(0),
idle_timeout_event(event_new(sim->base.get(), -1, EV_TIMEOUT, &IPStackSimulator::IPClient::dispatch_on_idle_timeout, this), event_free) {
uint64_t idle_timeout_usecs = sim->state->client_idle_timeout_usecs;
struct timeval tv = usecs_to_timeval(idle_timeout_usecs);
struct timeval tv = phosg::usecs_to_timeval(idle_timeout_usecs);
event_add(this->idle_timeout_event.get(), &tv);
}
@@ -247,7 +247,7 @@ void IPStackSimulator::dispatch_on_listen_accept(
void IPStackSimulator::on_listen_accept(struct evconnlistener* listener, evutil_socket_t fd, struct sockaddr*, int) {
struct sockaddr_storage remote_addr;
get_socket_addresses(fd, nullptr, &remote_addr);
phosg::get_socket_addresses(fd, nullptr, &remote_addr);
if (this->state->banned_ipv4_ranges->check(remote_addr)) {
close(fd);
return;
@@ -304,7 +304,7 @@ void IPStackSimulator::IPClient::on_client_input(struct bufferevent* bev) {
}
uint64_t idle_timeout_usecs = sim ? sim->state->client_idle_timeout_usecs : 60000000;
struct timeval tv = usecs_to_timeval(idle_timeout_usecs);
struct timeval tv = phosg::usecs_to_timeval(idle_timeout_usecs);
event_add(this->idle_timeout_event.get(), &tv);
switch (this->protocol) {
@@ -325,7 +325,7 @@ void IPStackSimulator::IPClient::on_client_input(struct bufferevent* bev) {
sim->on_client_frame(this->shared_from_this(), frame);
} catch (const exception& e) {
if (ip_stack_simulator_log.warning("Failed to process frame: %s", e.what())) {
print_data(stderr, frame);
phosg::print_data(stderr, frame);
}
}
}
@@ -360,7 +360,7 @@ void IPStackSimulator::IPClient::on_client_input(struct bufferevent* bev) {
sim->on_client_frame(this->shared_from_this(), frame);
} catch (const exception& e) {
if (ip_stack_simulator_log.warning("Failed to process frame: %s", e.what())) {
print_data(stderr, frame);
phosg::print_data(stderr, frame);
}
}
}
@@ -416,7 +416,7 @@ void IPStackSimulator::send_layer3_frame(shared_ptr<IPClient> c, FrameInfo::Prot
evbuffer_add(out_buf, &ether, sizeof(ether));
evbuffer_add(out_buf, data, size);
if (this->pcap_text_log_file) {
StringWriter w;
phosg::StringWriter w;
w.write(&ether, sizeof(ether));
w.write(data, size);
this->log_frame(w.str());
@@ -451,7 +451,7 @@ void IPStackSimulator::send_layer3_frame(shared_ptr<IPClient> c, FrameInfo::Prot
throw logic_error("unknown layer 3 protocol");
}
StringWriter w;
phosg::StringWriter w;
w.put(hdlc);
w.write(data, size);
w.put_u16l(FrameInfo::computed_hdlc_checksum(w.str().data() + 1, w.size() - 1));
@@ -459,7 +459,7 @@ void IPStackSimulator::send_layer3_frame(shared_ptr<IPClient> c, FrameInfo::Prot
string escaped = escape_hdlc_frame(w.str(), c->hdlc_escape_control_character_flags);
if (ip_stack_simulator_log.debug("Sending HDLC frame to virtual network (escaped to %zX bytes)", escaped.size())) {
print_data(stderr, w.str());
phosg::print_data(stderr, w.str());
}
if (c->protocol == Protocol::HDLC_TAPSERVER) {
@@ -490,12 +490,12 @@ void IPStackSimulator::on_client_frame(shared_ptr<IPClient> c, const string& fra
effective_data = &hdlc_unescaped_data;
}
if (ip_stack_simulator_log.debug("Virtual network sent frame")) {
print_data(stderr, *effective_data);
phosg::print_data(stderr, *effective_data);
}
this->log_frame(*effective_data);
FrameInfo fi(link_type, *effective_data);
if (ip_stack_simulator_log.should_log(LogLevel::DEBUG)) {
if (ip_stack_simulator_log.should_log(phosg::LogLevel::DEBUG)) {
string fi_header = fi.header_str();
ip_stack_simulator_log.debug("Frame header: %s", fi_header.c_str());
}
@@ -510,7 +510,7 @@ void IPStackSimulator::on_client_frame(shared_ptr<IPClient> c, const string& fra
uint16_t expected_checksum = fi.computed_hdlc_checksum();
uint16_t stored_checksum = fi.stored_hdlc_checksum();
if (expected_checksum != stored_checksum) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"HDLC checksum is incorrect (%04hX expected, %04hX received)",
expected_checksum, stored_checksum));
}
@@ -533,7 +533,7 @@ void IPStackSimulator::on_client_frame(shared_ptr<IPClient> c, const string& fra
} else if (fi.ipv4) {
uint16_t expected_ipv4_checksum = fi.computed_ipv4_header_checksum();
if (fi.ipv4->checksum != expected_ipv4_checksum) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"IPv4 header checksum is incorrect (%04hX expected, %04hX received)",
expected_ipv4_checksum, fi.ipv4->checksum.load()));
}
@@ -545,7 +545,7 @@ void IPStackSimulator::on_client_frame(shared_ptr<IPClient> c, const string& fra
if (fi.udp) {
uint16_t expected_udp_checksum = fi.computed_udp4_checksum();
if (fi.udp->checksum != expected_udp_checksum) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"UDP checksum is incorrect (%04hX expected, %04hX received)",
expected_udp_checksum, fi.udp->checksum.load()));
}
@@ -554,7 +554,7 @@ void IPStackSimulator::on_client_frame(shared_ptr<IPClient> c, const string& fra
} else if (fi.tcp) {
uint16_t expected_tcp_checksum = fi.computed_tcp4_checksum();
if (fi.tcp->checksum != expected_tcp_checksum) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"TCP checksum is incorrect (%04hX expected, %04hX received)",
expected_tcp_checksum, fi.tcp->checksum.load()));
}
@@ -576,7 +576,7 @@ void IPStackSimulator::on_client_lcp_frame(shared_ptr<IPClient> c, const FrameIn
while (!opts_r.eof()) {
uint8_t opt = opts_r.get_u8();
string opt_data = opts_r.read(opts_r.get_u8() - 2);
StringReader opt_data_r(opt_data);
phosg::StringReader opt_data_r(opt_data);
switch (opt) {
case 0x01: // Maximum receive unit
// TODO: Currently we ignore this, but we probably should use it.
@@ -593,7 +593,7 @@ void IPStackSimulator::on_client_lcp_frame(shared_ptr<IPClient> c, const FrameIn
case 0x04: // Quality protocol
case 0x07: // Protocol field compression
case 0x08: // Address and control field compression
throw runtime_error(string_printf("unimplemented LCP option %02hhX (%zu bytes)", opt, opt_data.size()));
throw runtime_error(phosg::string_printf("unimplemented LCP option %02hhX (%zu bytes)", opt, opt_data.size()));
default:
throw runtime_error("unknown LCP option");
}
@@ -602,7 +602,7 @@ void IPStackSimulator::on_client_lcp_frame(shared_ptr<IPClient> c, const FrameIn
// lazy to do this right now. In our situation, it should suffice to
// simply always send a Configure-Request to the client with a magic
// number not equal to the one we received.
StringWriter opts_w;
phosg::StringWriter opts_w;
opts_w.put_u8(0x01); // Maximum receive unit
opts_w.put_u8(0x04);
opts_w.put_u16b(1500);
@@ -615,7 +615,7 @@ void IPStackSimulator::on_client_lcp_frame(shared_ptr<IPClient> c, const FrameIn
opts_w.put_u8(0x05); // Magic number (bitwise inverse of the remote end's)
opts_w.put_u8(0x06);
opts_w.put_u32b(~c->hdlc_remote_magic_number);
StringWriter request_w;
phosg::StringWriter request_w;
request_w.put<LCPHeader>(LCPHeader{
.command = 0x01, // Configure-Request
.request_id = fi.lcp->request_id,
@@ -624,7 +624,7 @@ void IPStackSimulator::on_client_lcp_frame(shared_ptr<IPClient> c, const FrameIn
request_w.write(opts_w.str());
this->send_layer3_frame(c, FrameInfo::Protocol::LCP, request_w.str());
StringWriter ack_w;
phosg::StringWriter ack_w;
ack_w.put<LCPHeader>(LCPHeader{
.command = 0x02, // Configure-Ack
.request_id = fi.lcp->request_id,
@@ -679,7 +679,7 @@ void IPStackSimulator::on_client_pap_frame(shared_ptr<IPClient> c, const FrameIn
ip_stack_simulator_log.info("Client logged in with username \"%s\" and password", username.c_str());
static const string login_message = "newserv PPP simulator";
StringWriter w;
phosg::StringWriter w;
w.put<PAPHeader>(PAPHeader{
.command = 0x02, // Authenticate-Ack
.request_id = fi.pap->request_id,
@@ -698,11 +698,11 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
uint32_t remote_ip = 0;
uint32_t remote_primary_dns = 0;
uint32_t remote_secondary_dns = 0;
StringWriter rejected_opts_w;
phosg::StringWriter rejected_opts_w;
while (!opts_r.eof()) {
uint8_t opt = opts_r.get_u8();
string opt_data = opts_r.read(opts_r.get_u8() - 2);
StringReader opt_data_r(opt_data);
phosg::StringReader opt_data_r(opt_data);
switch (opt) {
case 0x01: // IP addresses (deprecated as of 1992; we don't support it at all)
throw runtime_error("IPCP client sent IP-Addresses option");
@@ -723,7 +723,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
case 0x82: // Primary NBNS server address
case 0x84: // Secondary NBNS server address
case 0x04: // Mobile IP address
throw runtime_error(string_printf("unimplemented IPCP option %02hhX (%zu bytes)", opt, opt_data.size()));
throw runtime_error(phosg::string_printf("unimplemented IPCP option %02hhX (%zu bytes)", opt, opt_data.size()));
default:
throw runtime_error("unknown IPCP option");
}
@@ -731,7 +731,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
if (!rejected_opts_w.str().empty()) {
// Send a Configure-Reject if the client specified IP header compression
StringWriter reject_w;
phosg::StringWriter reject_w;
reject_w.put<IPCPHeader>(IPCPHeader{
.command = 0x04, // Configure-Reject
.request_id = fi.ipcp->request_id,
@@ -745,7 +745,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
(remote_secondary_dns != 0x24242424)) {
// Send a Configure-Nak if the client's request doesn't exactly match
// what we want them to use.
StringWriter opts_w;
phosg::StringWriter opts_w;
opts_w.put_u8(0x03); // IP address
opts_w.put_u8(0x06);
opts_w.put_u32b(0x1E1E1E1E);
@@ -756,7 +756,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
opts_w.put_u8(0x06);
opts_w.put_u32b(0x24242424);
StringWriter nak_w;
phosg::StringWriter nak_w;
nak_w.put<IPCPHeader>(IPCPHeader{
.command = 0x03, // Configure-Nak
.request_id = fi.ipcp->request_id,
@@ -770,7 +770,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
// As with LCP, we technically should implement the state machine, but I
// continue to be lazy.
StringWriter opts_w;
phosg::StringWriter opts_w;
opts_w.put_u8(0x03); // IP address
opts_w.put_u8(0x06);
opts_w.put_u32b(0x39393939);
@@ -781,7 +781,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
opts_w.put_u8(0x06);
opts_w.put_u32b(0x24242424);
StringWriter request_w;
phosg::StringWriter request_w;
request_w.put<IPCPHeader>(IPCPHeader{
.command = 0x01, // Configure-Request
.request_id = fi.ipcp->request_id,
@@ -790,7 +790,7 @@ void IPStackSimulator::on_client_ipcp_frame(shared_ptr<IPClient> c, const FrameI
request_w.write(opts_w.str());
this->send_layer3_frame(c, FrameInfo::Protocol::IPCP, request_w.str());
StringWriter ack_w;
phosg::StringWriter ack_w;
ack_w.put<IPCPHeader>(IPCPHeader{
.command = 0x02, // Configure-Ack
.request_id = fi.ipcp->request_id,
@@ -841,7 +841,7 @@ void IPStackSimulator::on_client_arp_frame(
reinterpret_cast<const uint8_t*>(fi.payload) + 6);
}
StringWriter w;
phosg::StringWriter w;
w.put<ARPHeader>(ARPHeader{
.hardware_type = fi.arp->hardware_type,
.protocol_type = fi.arp->protocol_type,
@@ -942,7 +942,7 @@ void IPStackSimulator::on_client_udp_frame(shared_ptr<IPClient> c, const FrameIn
throw runtime_error("client sent unknown DHCP command option");
}
StringWriter w;
phosg::StringWriter w;
DHCPHeader r_dhcp;
r_dhcp.opcode = 2; // Response
r_dhcp.hardware_type = 1; // Ethernet
@@ -1027,13 +1027,13 @@ void IPStackSimulator::on_client_udp_frame(shared_ptr<IPClient> c, const FrameIn
r_udp.checksum = FrameInfo::computed_udp4_checksum(
r_ipv4, r_udp, r_data.data(), r_data.size());
if (ip_stack_simulator_log.should_log(LogLevel::DEBUG)) {
if (ip_stack_simulator_log.should_log(phosg::LogLevel::DEBUG)) {
string remote_str = this->str_for_ipv4_netloc(fi.ipv4->src_addr, fi.udp->src_port);
ip_stack_simulator_log.debug("Sending UDP response to %s", remote_str.c_str());
print_data(stderr, r_data);
phosg::print_data(stderr, r_data);
}
StringWriter w;
phosg::StringWriter w;
w.put(r_ipv4);
w.put(r_udp);
w.write(r_data);
@@ -1079,7 +1079,7 @@ void IPStackSimulator::on_client_tcp_frame(
throw runtime_error("TCP SYN contains extra flags");
}
StringReader options_r(fi.tcp + 1, fi.tcp_options_size);
phosg::StringReader options_r(fi.tcp + 1, fi.tcp_options_size);
size_t max_frame_size = 1400;
while (!options_r.eof()) {
uint8_t option = options_r.get_u8();
@@ -1135,7 +1135,7 @@ void IPStackSimulator::on_client_tcp_frame(
conn.server_port = fi.tcp->dest_port;
conn.client_port = fi.tcp->src_port;
conn.next_client_seq = fi.tcp->seq_num + 1;
conn.acked_server_seq = random_object<uint32_t>();
conn.acked_server_seq = phosg::random_object<uint32_t>();
conn.resend_push_usecs = DEFAULT_RESEND_PUSH_USECS;
conn.next_push_max_frame_size = max_frame_size;
conn.awaiting_first_ack = true;
@@ -1240,7 +1240,7 @@ void IPStackSimulator::on_client_tcp_frame(
// server immediately.
} else if (fi.payload_size != 0) {
string conn_str = ip_stack_simulator_log.should_log(LogLevel::WARNING)
string conn_str = ip_stack_simulator_log.should_log(phosg::LogLevel::WARNING)
? this->str_for_tcp_connection(c, *conn)
: "";
@@ -1285,7 +1285,7 @@ void IPStackSimulator::on_client_tcp_frame(
conn_str.c_str());
}
if (was_logged) {
print_data(stderr, payload, payload_size);
phosg::print_data(stderr, payload, payload_size);
}
// Send the new data to the server
@@ -1388,7 +1388,7 @@ void IPStackSimulator::send_pending_push_frame(
conn.acked_server_seq, bytes_to_send, pending_bytes);
this->send_tcp_frame(c, conn, TCPHeader::Flag::PSH, conn.pending_data.get(), bytes_to_send);
struct timeval resend_push_timeout = usecs_to_timeval(conn.resend_push_usecs);
struct timeval resend_push_timeout = phosg::usecs_to_timeval(conn.resend_push_usecs);
event_add(conn.resend_push_event.get(), &resend_push_timeout);
// If the client isn't responding to our PSHes, back off exponentially up to
@@ -1441,7 +1441,7 @@ void IPStackSimulator::send_tcp_frame(
const void* linear_data = src_bytes ? evbuffer_pullup(src_buf, src_bytes) : nullptr;
tcp.checksum = FrameInfo::computed_tcp4_checksum(ipv4, tcp, linear_data, src_bytes);
StringWriter w;
phosg::StringWriter w;
w.put(ipv4);
w.put(tcp);
if (src_bytes) {
@@ -1488,7 +1488,7 @@ void IPStackSimulator::on_server_input(shared_ptr<IPClient> c, IPClient::TCPConn
auto sim = c->sim.lock();
uint64_t idle_timeout_usecs = sim ? sim->state->client_idle_timeout_usecs : 60000000;
struct timeval tv = usecs_to_timeval(idle_timeout_usecs);
struct timeval tv = phosg::usecs_to_timeval(idle_timeout_usecs);
event_add(c->idle_timeout_event.get(), &tv);
evbuffer_add_buffer(conn.pending_data.get(), buf);
@@ -1534,8 +1534,7 @@ void IPStackSimulator::on_server_error(
void IPStackSimulator::log_frame(const string& data) const {
if (this->pcap_text_log_file) {
print_data(this->pcap_text_log_file, data, 0, nullptr,
PrintDataFlags::SKIP_SEPARATOR);
phosg::print_data(this->pcap_text_log_file, data, 0, nullptr, phosg::PrintDataFlags::SKIP_SEPARATOR);
fputc('\n', this->pcap_text_log_file);
fflush(this->pcap_text_log_file);
}
+6 -6
View File
@@ -4,10 +4,10 @@
using namespace std;
IPV4RangeSet::IPV4RangeSet(const JSON& json) {
IPV4RangeSet::IPV4RangeSet(const phosg::JSON& json) {
for (const auto& it : json.as_list()) {
// String should be of the form a.b.c.d or a.b.c.d/e
auto tokens = split(it->as_string(), '/');
auto tokens = phosg::split(it->as_string(), '/');
size_t mask_bits;
if (tokens.size() == 1) {
@@ -21,7 +21,7 @@ IPV4RangeSet::IPV4RangeSet(const JSON& json) {
throw runtime_error("invalid IPv4 address range");
}
auto addr_tokens = split(tokens[0], '.');
auto addr_tokens = phosg::split(tokens[0], '.');
if (addr_tokens.size() != 4) {
throw runtime_error("invalid IPv4 address");
}
@@ -40,12 +40,12 @@ IPV4RangeSet::IPV4RangeSet(const JSON& json) {
}
}
JSON IPV4RangeSet::json() const {
auto ret = JSON::list();
phosg::JSON IPV4RangeSet::json() const {
auto ret = phosg::JSON::list();
for (const auto& it : this->ranges) {
uint32_t addr = it.first;
uint8_t mask_bits = it.second;
ret.emplace_back(string_printf("%hhu.%hhu.%hhu.%hhu/%hhu",
ret.emplace_back(phosg::string_printf("%hhu.%hhu.%hhu.%hhu/%hhu",
static_cast<uint8_t>((addr >> 24) & 0xFF),
static_cast<uint8_t>((addr >> 16) & 0xFF),
static_cast<uint8_t>((addr >> 8) & 0xFF),
+2 -2
View File
@@ -6,9 +6,9 @@
class IPV4RangeSet {
public:
IPV4RangeSet() = default;
explicit IPV4RangeSet(const JSON& json);
explicit IPV4RangeSet(const phosg::JSON& json);
JSON json() const;
phosg::JSON json() const;
bool check(uint32_t addr) const;
bool check(const struct sockaddr_storage& ss) const;
+3 -3
View File
@@ -184,7 +184,7 @@ int64_t IntegralExpression::FlagLookupNode::evaluate(const Env& env) const {
}
string IntegralExpression::FlagLookupNode::str() const {
return string_printf("F_%04hX", this->flag_index);
return phosg::string_printf("F_%04hX", this->flag_index);
}
IntegralExpression::ChallengeCompletionLookupNode::ChallengeCompletionLookupNode(
@@ -214,7 +214,7 @@ int64_t IntegralExpression::ChallengeCompletionLookupNode::evaluate(const Env& e
}
string IntegralExpression::ChallengeCompletionLookupNode::str() const {
return string_printf("CC_%s_%hhu", abbreviation_for_episode(this->episode), static_cast<uint8_t>(this->stage_index + 1));
return phosg::string_printf("CC_%s_%hhu", abbreviation_for_episode(this->episode), static_cast<uint8_t>(this->stage_index + 1));
}
IntegralExpression::TeamRewardLookupNode::TeamRewardLookupNode(const string& reward_name)
@@ -296,7 +296,7 @@ int64_t IntegralExpression::ConstantNode::evaluate(const Env&) const {
}
string IntegralExpression::ConstantNode::str() const {
return string_printf("%" PRId64, this->value);
return phosg::string_printf("%" PRId64, this->value);
}
unique_ptr<const IntegralExpression::Node> IntegralExpression::parse_expr(string_view text) {
+7 -7
View File
@@ -36,7 +36,7 @@ ItemCreator::ItemCreator(
uint8_t section_id,
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt,
shared_ptr<const BattleRules> restrictions)
: log(string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ", name_for_enum(stack_limits->version), abbreviation_for_episode(episode), abbreviation_for_mode(mode), abbreviation_for_difficulty(difficulty), section_id), lobby_log.min_level),
: log(phosg::string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ", phosg::name_for_enum(stack_limits->version), abbreviation_for_episode(episode), abbreviation_for_mode(mode), abbreviation_for_difficulty(difficulty), section_id), lobby_log.min_level),
logic_version(stack_limits->version),
stack_limits(stack_limits),
episode(episode),
@@ -63,8 +63,8 @@ void ItemCreator::set_random_crypt(shared_ptr<PSOLFGEncryption> new_random_crypt
void ItemCreator::set_section_id(uint8_t new_section_id) {
if (this->section_id != new_section_id) {
this->section_id = new_section_id;
this->log.prefix = string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ",
name_for_enum(stack_limits->version),
this->log.prefix = phosg::string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ",
phosg::name_for_enum(stack_limits->version),
abbreviation_for_episode(episode),
abbreviation_for_mode(mode),
abbreviation_for_difficulty(difficulty),
@@ -298,13 +298,13 @@ ItemData ItemCreator::check_rare_specs_and_create_rare_box_item(uint8_t area_nor
for (const auto& spec : rare_specs) {
item = this->check_rate_and_create_rare_item(spec, area_norm);
if (!item.empty()) {
if (this->log.should_log(LogLevel::INFO)) {
if (this->log.should_log(phosg::LogLevel::INFO)) {
auto hex = spec.data.hex();
this->log.info("Box spec %08" PRIX32 " produced item %s", spec.probability, hex.c_str());
}
break;
}
if (this->log.should_log(LogLevel::INFO)) {
if (this->log.should_log(phosg::LogLevel::INFO)) {
auto hex = spec.data.hex();
this->log.info("Box spec %08" PRIX32 " did not produce item %s", spec.probability, hex.c_str());
}
@@ -359,13 +359,13 @@ ItemData ItemCreator::check_rare_spec_and_create_rare_enemy_item(uint32_t enemy_
for (const auto& spec : rare_specs) {
item = this->check_rate_and_create_rare_item(spec, area_norm);
if (!item.empty()) {
if (this->log.should_log(LogLevel::INFO)) {
if (this->log.should_log(phosg::LogLevel::INFO)) {
auto hex = spec.data.hex();
this->log.info("Enemy spec %08" PRIX32 " produced item %s", spec.probability, hex.c_str());
}
break;
}
if (this->log.should_log(LogLevel::INFO)) {
if (this->log.should_log(phosg::LogLevel::INFO)) {
auto hex = spec.data.hex();
this->log.info("Enemy spec %08" PRIX32 " did not produce item %s", spec.probability, hex.c_str());
}
+1 -1
View File
@@ -58,7 +58,7 @@ public:
void set_section_id(uint8_t new_section_id);
private:
PrefixedLogger log;
phosg::PrefixedLogger log;
Version logic_version;
std::shared_ptr<const ItemData::StackLimits> stack_limits;
Episode episode;
+7 -7
View File
@@ -21,7 +21,7 @@ ItemData::StackLimits::StackLimits(
max_tool_stack_sizes_by_data1_1(max_tool_stack_sizes_by_data1_1),
max_meseta_stack_size(max_meseta_stack_size) {}
ItemData::StackLimits::StackLimits(Version version, const JSON& json)
ItemData::StackLimits::StackLimits(Version version, const phosg::JSON& json)
: version(version) {
this->max_tool_stack_sizes_by_data1_1.clear();
for (const auto& limit_json : json.at("ToolLimits").as_list()) {
@@ -53,8 +53,8 @@ ItemData::ItemData(const ItemData& other) {
ItemData::ItemData(uint64_t first, uint64_t second) {
*reinterpret_cast<be_uint64_t*>(&this->data1[0]) = first;
this->data1d[2] = bswap32((second >> 32) & 0xFFFFFFFF);
this->data2d = bswap32(second & 0xFFFFFFFF);
this->data1d[2] = phosg::bswap32((second >> 32) & 0xFFFFFFFF);
this->data2d = phosg::bswap32(second & 0xFFFFFFFF);
}
ItemData& ItemData::operator=(const ItemData& other) {
@@ -400,7 +400,7 @@ void ItemData::decode_for_version(Version from_version) {
// data2d field, since internally it's actually a uint32_t. We treat it
// as individual bytes instead, so we correct for the client's
// byteswapping here.
this->data2d = bswap32(this->data2d);
this->data2d = phosg::bswap32(this->data2d);
}
break;
@@ -482,7 +482,7 @@ void ItemData::encode_for_version(Version to_version, shared_ptr<const ItemParam
this->data2w[1] = this->data2[0] | ((this->data2[2] << 15) & 0x8000);
this->data2w[0] = this->data2[1];
} else if (is_big_endian(to_version)) {
this->data2d = bswap32(this->data2d);
this->data2d = phosg::bswap32(this->data2d);
}
break;
@@ -743,12 +743,12 @@ ItemData ItemData::from_primary_identifier(const StackLimits& limits, uint32_t p
}
string ItemData::hex() const {
return string_printf("%08" PRIX32 " %08" PRIX32 " %08" PRIX32 " (%08" PRIX32 ") %08" PRIX32,
return phosg::string_printf("%08" PRIX32 " %08" PRIX32 " %08" PRIX32 " (%08" PRIX32 ") %08" PRIX32,
this->data1db[0].load(), this->data1db[1].load(), this->data1db[2].load(), this->id.load(), this->data2db.load());
}
string ItemData::short_hex() const {
auto ret = string_printf("%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "%08" PRIX32,
auto ret = phosg::string_printf("%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "%08" PRIX32,
this->data1db[0].load(), this->data1db[1].load(), this->data1db[2].load(), this->data2db.load());
size_t offset = ret.find_last_not_of('0');
if (offset != string::npos) {
+1 -1
View File
@@ -62,7 +62,7 @@ struct ItemData {
uint32_t max_meseta_stack_size;
StackLimits(Version version, const std::vector<uint8_t>& max_tool_stack_sizes_by_data1_1, uint32_t max_meseta_stack_size);
StackLimits(Version version, const JSON& json);
StackLimits(Version version, const phosg::JSON& json);
StackLimits(const StackLimits& other) = default;
StackLimits(StackLimits&& other) = default;
StackLimits& operator=(const StackLimits& other) = default;
+68 -68
View File
@@ -24,7 +24,7 @@ ItemNameIndex::ItemNameIndex(
meta->primary_identifier = primary_identifier;
meta->name = *name;
this->primary_identifier_index.emplace(meta->primary_identifier, meta);
this->name_index.emplace(tolower(meta->name), meta);
this->name_index.emplace(phosg::tolower(meta->name), meta);
}
}
}
@@ -99,7 +99,7 @@ const array<const char*, 0x11> name_for_s_rank_special = {
std::string ItemNameIndex::describe_item(const ItemData& item, bool include_color_escapes) const {
if (item.data1[0] == 0x04) {
return string_printf("%s%" PRIu32 " Meseta", include_color_escapes ? "$C7" : "", item.data2d.load());
return phosg::string_printf("%s%" PRIu32 " Meseta", include_color_escapes ? "$C7" : "", item.data2d.load());
}
vector<string> ret_tokens;
@@ -120,7 +120,7 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
try {
ret_tokens.emplace_back(name_for_weapon_special.at(special_id));
} catch (const out_of_range&) {
ret_tokens.emplace_back(string_printf("!SP:%02hhX", special_id));
ret_tokens.emplace_back(phosg::string_printf("!SP:%02hhX", special_id));
}
}
}
@@ -128,7 +128,7 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
try {
ret_tokens.emplace_back(name_for_s_rank_special.at(item.data1[2]));
} catch (const out_of_range&) {
ret_tokens.emplace_back(string_printf("!SSP:%02hhX", item.data1[2]));
ret_tokens.emplace_back(phosg::string_printf("!SSP:%02hhX", item.data1[2]));
}
}
@@ -149,34 +149,34 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
technique_name = tech_id_to_name.at(item.data1[4]);
technique_name[0] = toupper(technique_name[0]);
} catch (const out_of_range&) {
technique_name = string_printf("!TD:%02hhX", item.data1[4]);
technique_name = phosg::string_printf("!TD:%02hhX", item.data1[4]);
}
// Hide the level for Reverser and Ryuker, unless the level isn't 1
if ((item.data1[2] == 0) && ((item.data1[4] == 0x0E) || (item.data1[4] == 0x11))) {
ret_tokens.emplace_back(string_printf("Disk:%s", technique_name.c_str()));
ret_tokens.emplace_back(phosg::string_printf("Disk:%s", technique_name.c_str()));
} else {
ret_tokens.emplace_back(string_printf("Disk:%s Lv.%d", technique_name.c_str(), item.data1[2] + 1));
ret_tokens.emplace_back(phosg::string_printf("Disk:%s Lv.%d", technique_name.c_str(), item.data1[2] + 1));
}
} else {
try {
auto meta = this->primary_identifier_index.at(primary_identifier);
ret_tokens.emplace_back(meta->name);
} catch (const out_of_range&) {
ret_tokens.emplace_back(string_printf("!ID:%08" PRIX32, primary_identifier));
ret_tokens.emplace_back(phosg::string_printf("!ID:%08" PRIX32, primary_identifier));
}
}
// For weapons, add the grind and bonuses, or S-rank name if applicable
if (item.data1[0] == 0x00) {
if (item.data1[3] > 0) {
ret_tokens.emplace_back(string_printf("+%hhu", item.data1[3]));
ret_tokens.emplace_back(phosg::string_printf("+%hhu", item.data1[3]));
}
if (item.is_s_rank_weapon()) {
// S-rank (has name instead of percent bonuses)
uint16_t be_data1w3 = bswap16(item.data1w[3]);
uint16_t be_data1w4 = bswap16(item.data1w[4]);
uint16_t be_data1w5 = bswap16(item.data1w[5]);
uint16_t be_data1w3 = phosg::bswap16(item.data1w[3]);
uint16_t be_data1w4 = phosg::bswap16(item.data1w[4]);
uint16_t be_data1w5 = phosg::bswap16(item.data1w[5]);
uint8_t char_indexes[8] = {
static_cast<uint8_t>((be_data1w3 >> 5) & 0x1F),
static_cast<uint8_t>(be_data1w3 & 0x1F),
@@ -210,9 +210,9 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
}
if (which & 0x80) {
uint16_t kill_count = ((which << 8) & 0x7F00) | (value & 0xFF);
ret_tokens.emplace_back(string_printf("K:%hu", kill_count));
ret_tokens.emplace_back(phosg::string_printf("K:%hu", kill_count));
} else if (which > 5) {
ret_tokens.emplace_back(string_printf("!PC:%02hhX%02hhX", which, value));
ret_tokens.emplace_back(phosg::string_printf("!PC:%02hhX%02hhX", which, value));
} else {
bonuses[which - 1] = value;
}
@@ -222,11 +222,11 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
bool should_highlight_hit = include_color_escapes && (bonuses[4] > 0);
const char* color_prefix = include_color_escapes ? "$C7" : "";
if (should_include_hit) {
ret_tokens.emplace_back(string_printf("%s%hhd/%hhd/%hhd/%hhd/%s%hhd",
ret_tokens.emplace_back(phosg::string_printf("%s%hhd/%hhd/%hhd/%hhd/%s%hhd",
color_prefix, bonuses[0], bonuses[1], bonuses[2], bonuses[3],
(should_highlight_hit ? "$C6" : ""), bonuses[4]));
} else {
ret_tokens.emplace_back(string_printf("%s%hhd/%hhd/%hhd/%hhd",
ret_tokens.emplace_back(phosg::string_printf("%s%hhd/%hhd/%hhd/%hhd",
color_prefix, bonuses[0], bonuses[1], bonuses[2], bonuses[3]));
}
}
@@ -245,7 +245,7 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
} else if (modifier <= -3) {
ret_tokens.back().append("--");
} else if (modifier != 0) {
ret_tokens.emplace_back(string_printf("!MD:%04hX", modifier));
ret_tokens.emplace_back(phosg::string_printf("!MD:%04hX", modifier));
}
} else { // Armor/shields
@@ -253,22 +253,22 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
if (item.data1[5] == 1) {
ret_tokens.emplace_back("(1 slot)");
} else {
ret_tokens.emplace_back(string_printf("(%hhu slots)", item.data1[5]));
ret_tokens.emplace_back(phosg::string_printf("(%hhu slots)", item.data1[5]));
}
}
if (item.data1w[3] != 0) {
ret_tokens.emplace_back(string_printf("+%hdDEF",
ret_tokens.emplace_back(phosg::string_printf("+%hdDEF",
static_cast<int16_t>(item.data1w[3].load())));
}
if (item.data1w[4] != 0) {
ret_tokens.emplace_back(string_printf("+%hdEVP",
ret_tokens.emplace_back(phosg::string_printf("+%hdEVP",
static_cast<int16_t>(item.data1w[4].load())));
}
}
// For mags, add tons of info
} else if (item.data1[0] == 0x02) {
ret_tokens.emplace_back(string_printf("LV%hhu", item.data1[2]));
ret_tokens.emplace_back(phosg::string_printf("LV%hhu", item.data1[2]));
uint16_t def = item.data1w[2];
uint16_t pow = item.data1w[3];
@@ -278,16 +278,16 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
uint16_t level = stat / 100;
uint8_t partial = stat % 100;
if (partial == 0) {
return string_printf("%hu", level);
return phosg::string_printf("%hu", level);
} else if (partial % 10 == 0) {
return string_printf("%hu.%hhu", level, static_cast<uint8_t>(partial / 10));
return phosg::string_printf("%hu.%hhu", level, static_cast<uint8_t>(partial / 10));
} else {
return string_printf("%hu.%02hhu", level, partial);
return phosg::string_printf("%hu.%02hhu", level, partial);
}
};
ret_tokens.emplace_back(format_stat(def) + "/" + format_stat(pow) + "/" + format_stat(dex) + "/" + format_stat(mind));
ret_tokens.emplace_back(string_printf("%hhu%%", item.data2[0]));
ret_tokens.emplace_back(string_printf("%hhuIQ", item.data2[1]));
ret_tokens.emplace_back(phosg::string_printf("%hhu%%", item.data2[0]));
ret_tokens.emplace_back(phosg::string_printf("%hhuIQ", item.data2[1]));
uint8_t flags = item.data2[2];
if (flags & 7) {
@@ -322,19 +322,19 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
}
try {
ret_tokens.emplace_back(string_printf("(%s)", name_for_mag_color.at(item.data2[3])));
ret_tokens.emplace_back(phosg::string_printf("(%s)", name_for_mag_color.at(item.data2[3])));
} catch (const out_of_range&) {
ret_tokens.emplace_back(string_printf("(!CL:%02hhX)", item.data2[3]));
ret_tokens.emplace_back(phosg::string_printf("(!CL:%02hhX)", item.data2[3]));
}
// For tools, add the amount (if applicable)
} else if (item.data1[0] == 0x03) {
if (item.max_stack_size(*this->limits) > 1) {
ret_tokens.emplace_back(string_printf("x%hhu", item.data1[5]));
ret_tokens.emplace_back(phosg::string_printf("x%hhu", item.data1[5]));
}
}
string ret = join(ret_tokens, " ");
string ret = phosg::join(ret_tokens, " ");
if (include_color_escapes) {
if (is_unidentified) {
return "$C3" + ret;
@@ -361,13 +361,13 @@ ItemData ItemNameIndex::parse_item_description(const std::string& desc) const {
ret = this->parse_item_description_phase(desc, true);
} catch (const exception& e2) {
try {
ret = ItemData::from_data(parse_data_string(desc));
ret = ItemData::from_data(phosg::parse_data_string(desc));
} catch (const exception& ed) {
if (strcmp(e1.what(), e2.what())) {
throw runtime_error(string_printf("cannot parse item description \"%s\" (as text 1: %s) (as text 2: %s) (as data: %s)",
throw runtime_error(phosg::string_printf("cannot parse item description \"%s\" (as text 1: %s) (as text 2: %s) (as data: %s)",
desc.c_str(), e1.what(), e2.what(), ed.what()));
} else {
throw runtime_error(string_printf("cannot parse item description \"%s\" (as text: %s) (as data: %s)",
throw runtime_error(phosg::string_printf("cannot parse item description \"%s\" (as text: %s) (as data: %s)",
desc.c_str(), e1.what(), ed.what()));
}
}
@@ -383,15 +383,15 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
ret.id = 0xFFFFFFFF;
ret.data2d = 0;
string desc = tolower(description);
if (ends_with(desc, " meseta")) {
string desc = phosg::tolower(description);
if (phosg::ends_with(desc, " meseta")) {
ret.data1[0] = 0x04;
ret.data2d = stol(desc, nullptr, 10);
return ret;
}
if (starts_with(desc, "disk:")) {
auto tokens = split(desc, ' ');
if (phosg::starts_with(desc, "disk:")) {
auto tokens = phosg::split(desc, ' ');
tokens[0] = tokens[0].substr(5); // Trim off "disk:"
if ((tokens[0] == "reverser") || (tokens[0] == "ryuker")) {
uint8_t tech = technique_for_name(tokens[0]);
@@ -403,7 +403,7 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
if (tokens.size() != 2) {
throw runtime_error("invalid tech disk format");
}
if (!starts_with(tokens[1], "lv.")) {
if (!phosg::starts_with(tokens[1], "lv.")) {
throw runtime_error("invalid tech disk level");
}
uint8_t tech = technique_for_name(tokens[0]);
@@ -416,11 +416,11 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
return ret;
}
bool is_wrapped = starts_with(desc, "wrapped ");
bool is_wrapped = phosg::starts_with(desc, "wrapped ");
if (is_wrapped) {
desc = desc.substr(8);
}
bool is_unidentified = starts_with(desc, "?");
bool is_unidentified = phosg::starts_with(desc, "?");
if (is_unidentified) {
size_t z;
for (z = 1; z < desc.size(); z++) {
@@ -438,9 +438,9 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
if (!name_for_weapon_special[z]) {
continue;
}
string prefix = tolower(name_for_weapon_special[z]);
string prefix = phosg::tolower(name_for_weapon_special[z]);
prefix += ' ';
if (starts_with(desc, prefix)) {
if (phosg::starts_with(desc, prefix)) {
weapon_special = z;
desc = desc.substr(prefix.size());
break;
@@ -454,7 +454,7 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
// then we'll see Sange & Yasha first, which we should skip.
size_t lookback = 0;
while (lookback < 4) {
if (name_it != this->name_index.end() && desc.starts_with(name_it->first)) {
if (name_it != this->name_index.end() && phosg::starts_with(desc, name_it->first)) {
break;
} else if (name_it == this->name_index.begin()) {
throw runtime_error("no such item");
@@ -468,7 +468,7 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
}
desc = desc.substr(name_it->first.size());
if (starts_with(desc, " ")) {
if (phosg::starts_with(desc, " ")) {
desc = desc.substr(1);
}
@@ -483,12 +483,12 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
// Weapons: add special, grind and percentages (or name, if S-rank)
ret.data1[4] = weapon_special | (is_wrapped ? 0x40 : 0x00) | (is_unidentified ? 0x80 : 0x00);
auto tokens = split(desc, ' ');
auto tokens = phosg::split(desc, ' ');
for (auto& token : tokens) {
if (token.empty()) {
continue;
}
if (starts_with(token, "+")) {
if (phosg::starts_with(token, "+")) {
token = token.substr(1);
ret.data1[3] = stoul(token, nullptr, 10);
@@ -502,17 +502,17 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
char ch = toupper(token[z]);
const char* pos = strchr(s_rank_name_characters, ch);
if (!pos) {
throw runtime_error(string_printf("s-rank name contains invalid character %02hhX (%c)", ch, ch));
throw runtime_error(phosg::string_printf("s-rank name contains invalid character %02hhX (%c)", ch, ch));
}
char_indexes[z] = (pos - s_rank_name_characters);
}
ret.data1w[3] = bswap16(0x8000 | (char_indexes[1] & 0x1F) | ((char_indexes[0] & 0x1F) << 5));
ret.data1w[4] = bswap16(0x8000 | (char_indexes[4] & 0x1F) | ((char_indexes[3] & 0x1F) << 5) | ((char_indexes[2] & 0x1F) << 10));
ret.data1w[5] = bswap16(0x8000 | (char_indexes[7] & 0x1F) | ((char_indexes[6] & 0x1F) << 5) | ((char_indexes[5] & 0x1F) << 10));
ret.data1w[3] = phosg::bswap16(0x8000 | (char_indexes[1] & 0x1F) | ((char_indexes[0] & 0x1F) << 5));
ret.data1w[4] = phosg::bswap16(0x8000 | (char_indexes[4] & 0x1F) | ((char_indexes[3] & 0x1F) << 5) | ((char_indexes[2] & 0x1F) << 10));
ret.data1w[5] = phosg::bswap16(0x8000 | (char_indexes[7] & 0x1F) | ((char_indexes[6] & 0x1F) << 5) | ((char_indexes[5] & 0x1F) << 10));
} else {
auto p_tokens = split(token, '/');
auto p_tokens = phosg::split(token, '/');
if (p_tokens.size() > 5) {
throw runtime_error("invalid bonuses token");
}
@@ -544,15 +544,15 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
ret.data1w[3] = modifiers.at(desc);
} else { // Armor/shield
for (const auto& token : split(desc, ' ')) {
for (const auto& token : phosg::split(desc, ' ')) {
if (token.empty()) {
continue;
} else if (!starts_with(token, "+")) {
} else if (!phosg::starts_with(token, "+")) {
throw runtime_error("invalid armor/shield modifier");
}
if (ends_with(token, "def")) {
if (phosg::ends_with(token, "def")) {
ret.data1w[3] = static_cast<uint16_t>(stol(token.substr(1, token.size() - 4), nullptr, 10));
} else if (ends_with(token, "evp")) {
} else if (phosg::ends_with(token, "evp")) {
ret.data1w[4] = static_cast<uint16_t>(stol(token.substr(1, token.size() - 4), nullptr, 10));
} else {
ret.data1[5] = stoul(token.substr(1), nullptr, 10);
@@ -565,11 +565,11 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
}
} else if (ret.data1[0] == 0x02) {
for (const auto& token : split(desc, ' ')) {
for (const auto& token : phosg::split(desc, ' ')) {
if (token.empty()) {
continue;
} else if (starts_with(token, "pb:")) { // Photon blasts
auto pb_tokens = split(token.substr(3), ',');
} else if (phosg::starts_with(token, "pb:")) { // Photon blasts
auto pb_tokens = phosg::split(token.substr(3), ',');
if (pb_tokens.size() > 3) {
throw runtime_error("too many photon blasts specified");
}
@@ -586,17 +586,17 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
for (const auto& pb_token : pb_tokens) {
ret.add_mag_photon_blast(name_to_pb_num.at(pb_token));
}
} else if (ends_with(token, "%")) { // Synchro
} else if (phosg::ends_with(token, "%")) { // Synchro
ret.data2[0] = stoul(token.substr(0, token.size() - 1), nullptr, 10);
} else if (ends_with(token, "iq")) { // IQ
} else if (phosg::ends_with(token, "iq")) { // IQ
ret.data2[1] = stoul(token.substr(0, token.size() - 2), nullptr, 10);
} else if (!token.empty() && isdigit(token[0])) { // Stats
auto s_tokens = split(token, '/');
auto s_tokens = phosg::split(token, '/');
if (s_tokens.size() != 4) {
throw runtime_error("incorrect stat count");
}
for (size_t z = 0; z < 4; z++) {
auto n_tokens = split(s_tokens[z], '.');
auto n_tokens = phosg::split(s_tokens[z], '.');
if (n_tokens.size() == 0 || n_tokens.size() > 2) {
throw logic_error("incorrect stats argument format");
} else if ((n_tokens.size() == 1) || (n_tokens[1].size() == 0)) {
@@ -620,7 +620,7 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript
}
} else if (ret.data1[0] == 0x03) {
if (ret.max_stack_size(*this->limits) > 1) {
if (starts_with(desc, "x")) {
if (phosg::starts_with(desc, "x")) {
ret.data1[5] = stoul(desc.substr(1), nullptr, 10);
} else {
ret.data1[5] = 1;
@@ -650,7 +650,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
for (size_t data1_1 = 0; data1_1 < pmt->num_weapon_classes; data1_1++) {
uint8_t v1_replacement = pmt->get_weapon_v1_replacement(data1_1);
float sale_divisor = pmt->get_sale_divisor(0x00, data1_1);
string divisor_str = string_printf("%g", sale_divisor);
string divisor_str = phosg::string_printf("%g", sale_divisor);
divisor_str.resize(13, ' ');
size_t data1_2_limit = pmt->num_weapons_in_class(data1_1);
@@ -708,7 +708,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
fprintf(stream, "ARMOR => ---ID--- TYPE SKIN POINTS -DFP- -EVP- BP BE FLAG LVL EFR ETH EIC EDK ELT DFR EVR SB TB -A2- 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 = string_printf("%g", sale_divisor);
string divisor_str = phosg::string_printf("%g", sale_divisor);
divisor_str.resize(13, ' ');
size_t data1_2_limit = pmt->num_armors_or_shields_in_class(data1_1);
@@ -754,7 +754,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
fprintf(stream, "UNIT => ---ID--- TYPE SKIN POINTS STAT COUNT ST-MOD ST* ---DIVISOR--- NAME\n");
{
float sale_divisor = pmt->get_sale_divisor(0x01, 0x03);
string divisor_str = string_printf("%g", sale_divisor);
string divisor_str = phosg::string_printf("%g", sale_divisor);
divisor_str.resize(13, ' ');
size_t data1_2_limit = pmt->num_units();
@@ -791,7 +791,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
uint8_t stars = pmt->get_item_stars(m.base.id);
float sale_divisor = pmt->get_sale_divisor(0x02, data1_1);
string divisor_str = string_printf("%g", sale_divisor);
string divisor_str = phosg::string_printf("%g", sale_divisor);
divisor_str.resize(13, ' ');
ItemData item;
@@ -827,7 +827,7 @@ void ItemNameIndex::print_table(FILE* stream) const {
fprintf(stream, "TOOL => ---ID--- TYPE SKIN POINTS COUNT TECH -COST- ITEMFLAG ST* ---DIVISOR--- NAME\n");
for (size_t data1_1 = 0; data1_1 < pmt->num_tool_classes; data1_1++) {
float sale_divisor = pmt->get_sale_divisor(0x03, data1_1);
string divisor_str = string_printf("%g", sale_divisor);
string divisor_str = phosg::string_printf("%g", sale_divisor);
divisor_str.resize(13, ' ');
size_t data1_2_limit = pmt->num_tools_in_class(data1_1);
+29 -31
View File
@@ -206,8 +206,8 @@ ItemParameterTable::WeaponV4 ItemParameterTable::WeaponGCNTE::to_v4() const {
return ret;
}
template <bool IsBigEndian>
ItemParameterTable::WeaponV4 ItemParameterTable::WeaponV3T<IsBigEndian>::to_v4() const {
template <bool BE>
ItemParameterTable::WeaponV4 ItemParameterTable::WeaponV3T<BE>::to_v4() const {
WeaponV4 ret;
ret.base.id = this->base.id.load();
ret.base.type = this->base.type.load();
@@ -281,8 +281,8 @@ ItemParameterTable::ArmorOrShieldV4 ItemParameterTable::ArmorOrShieldV1V2::to_v4
return ret;
}
template <bool IsBigEndian>
ItemParameterTable::ArmorOrShieldV4 ItemParameterTable::ArmorOrShieldV3T<IsBigEndian>::to_v4() const {
template <bool BE>
ItemParameterTable::ArmorOrShieldV4 ItemParameterTable::ArmorOrShieldV3T<BE>::to_v4() const {
ArmorOrShieldV4 ret;
ret.base.id = this->base.id.load();
ret.base.type = this->base.type.load();
@@ -323,8 +323,8 @@ ItemParameterTable::UnitV4 ItemParameterTable::UnitV1V2::to_v4() const {
return ret;
}
template <bool IsBigEndian>
ItemParameterTable::UnitV4 ItemParameterTable::UnitV3T<IsBigEndian>::to_v4() const {
template <bool BE>
ItemParameterTable::UnitV4 ItemParameterTable::UnitV3T<BE>::to_v4() const {
UnitV4 ret;
ret.base.id = this->base.id.load();
ret.base.type = this->base.type.load();
@@ -370,8 +370,8 @@ ItemParameterTable::MagV4 ItemParameterTable::MagV2::to_v4() const {
return ret;
}
template <bool IsBigEndian>
ItemParameterTable::MagV4 ItemParameterTable::MagV3T<IsBigEndian>::to_v4() const {
template <bool BE>
ItemParameterTable::MagV4 ItemParameterTable::MagV3T<BE>::to_v4() const {
MagV4 ret;
ret.base.id = this->base.id.load();
ret.base.type = this->base.type.load();
@@ -401,8 +401,8 @@ ItemParameterTable::ToolV4 ItemParameterTable::ToolV1V2::to_v4() const {
return ret;
}
template <bool IsBigEndian>
ItemParameterTable::ToolV4 ItemParameterTable::ToolV3T<IsBigEndian>::to_v4() const {
template <bool BE>
ItemParameterTable::ToolV4 ItemParameterTable::ToolV3T<BE>::to_v4() const {
ToolV4 ret;
ret.base.id = this->base.id.load();
ret.base.type = this->base.type.load();
@@ -414,15 +414,15 @@ ItemParameterTable::ToolV4 ItemParameterTable::ToolV3T<IsBigEndian>::to_v4() con
return ret;
}
template <bool IsBigEndian>
size_t indirect_lookup_2d_count(const StringReader& r, size_t root_offset, size_t co_index) {
using ArrayRefT = typename std::conditional_t<IsBigEndian, ItemParameterTable::ArrayRefBE, ItemParameterTable::ArrayRef>;
template <bool BE>
size_t indirect_lookup_2d_count(const phosg::StringReader& r, size_t root_offset, size_t co_index) {
using ArrayRefT = typename std::conditional_t<BE, ItemParameterTable::ArrayRefBE, ItemParameterTable::ArrayRef>;
return r.pget<ArrayRefT>(root_offset + sizeof(ArrayRefT) * co_index).count;
}
template <typename T, bool IsBigEndian>
const T& indirect_lookup_2d(const StringReader& r, size_t root_offset, size_t co_index, size_t item_index) {
using ArrayRefT = typename std::conditional_t<IsBigEndian, ItemParameterTable::ArrayRefBE, ItemParameterTable::ArrayRef>;
template <typename T, bool BE>
const T& indirect_lookup_2d(const phosg::StringReader& r, size_t root_offset, size_t co_index, size_t item_index) {
using ArrayRefT = typename std::conditional_t<BE, ItemParameterTable::ArrayRefBE, ItemParameterTable::ArrayRef>;
const auto& co = r.pget<ArrayRefT>(root_offset + sizeof(ArrayRefT) * co_index);
if (item_index >= co.count) {
@@ -706,10 +706,10 @@ const ItemParameterTable::ToolV4& ItemParameterTable::get_tool(uint8_t data1_1,
}
}
template <typename ToolDefT, bool IsBigEndian>
template <typename ToolDefT, bool BE>
pair<uint8_t, uint8_t> ItemParameterTable::find_tool_by_id_t(uint32_t tool_table_offset, uint32_t item_id) const {
const auto* cos = &this->r.pget<ArrayRefT<IsBigEndian>>(
tool_table_offset, this->num_tool_classes * sizeof(ArrayRefT<IsBigEndian>));
const auto* cos = &this->r.pget<ArrayRefT<BE>>(
tool_table_offset, this->num_tool_classes * sizeof(ArrayRefT<BE>));
for (size_t z = 0; z < this->num_tool_classes; z++) {
const auto& co = cos[z];
const auto* defs = &this->r.pget<ToolDefT>(co.offset, sizeof(ToolDefT) * co.count);
@@ -719,7 +719,7 @@ pair<uint8_t, uint8_t> ItemParameterTable::find_tool_by_id_t(uint32_t tool_table
}
}
}
throw out_of_range(string_printf("invalid tool class %08" PRIX32, item_id));
throw out_of_range(phosg::string_printf("invalid tool class %08" PRIX32, item_id));
}
pair<uint8_t, uint8_t> ItemParameterTable::find_tool_by_id(uint32_t item_id) const {
@@ -740,19 +740,17 @@ pair<uint8_t, uint8_t> ItemParameterTable::find_tool_by_id(uint32_t item_id) con
}
}
template <bool IsBigEndian, typename OffsetsT>
template <bool BE, typename OffsetsT>
float ItemParameterTable::get_sale_divisor_t(const OffsetsT* offsets, uint8_t data1_0, uint8_t data1_1) const {
using FloatT = typename std::conditional<IsBigEndian, be_float, le_float>::type;
switch (data1_0) {
case 0:
if (data1_1 >= this->num_weapon_classes) {
return 0.0f;
}
return this->r.pget<FloatT>(offsets->weapon_sale_divisor_table + data1_1 * sizeof(FloatT));
return this->r.pget<F32T<BE>>(offsets->weapon_sale_divisor_table + data1_1 * sizeof(F32T<BE>));
case 1: {
const auto& divisors = this->r.pget<NonWeaponSaleDivisorsT<IsBigEndian>>(offsets->sale_divisor_table);
const auto& divisors = this->r.pget<NonWeaponSaleDivisorsT<BE>>(offsets->sale_divisor_table);
switch (data1_1) {
case 1:
return divisors.armor_divisor;
@@ -765,7 +763,7 @@ float ItemParameterTable::get_sale_divisor_t(const OffsetsT* offsets, uint8_t da
}
case 2: {
const auto& divisors = this->r.pget<NonWeaponSaleDivisorsT<IsBigEndian>>(offsets->sale_divisor_table);
const auto& divisors = this->r.pget<NonWeaponSaleDivisorsT<BE>>(offsets->sale_divisor_table);
return divisors.mag_divisor;
}
@@ -1136,9 +1134,9 @@ const std::map<uint32_t, std::vector<ItemParameterTable::ItemCombination>>& Item
return this->item_combination_index;
}
template <bool IsBigEndian>
template <bool BE>
size_t ItemParameterTable::num_events_t(uint32_t base_offset) const {
return this->r.pget<ArrayRefT<IsBigEndian>>(base_offset).count;
return this->r.pget<ArrayRefT<BE>>(base_offset).count;
}
size_t ItemParameterTable::num_events() const {
@@ -1155,14 +1153,14 @@ size_t ItemParameterTable::num_events() const {
}
}
template <bool IsBigEndian>
template <bool BE>
std::pair<const ItemParameterTable::EventItem*, size_t> ItemParameterTable::get_event_items_t(
uint32_t base_offset, uint8_t event_number) const {
const auto& co = this->r.pget<ArrayRefT<IsBigEndian>>(base_offset);
const auto& co = this->r.pget<ArrayRefT<BE>>(base_offset);
if (event_number >= co.count) {
throw out_of_range("invalid event number");
}
const auto& event_co = this->r.pget<ArrayRefT<IsBigEndian>>(co.offset + sizeof(ArrayRefT<IsBigEndian>) * event_number);
const auto& event_co = this->r.pget<ArrayRefT<BE>>(co.offset + sizeof(ArrayRefT<BE>) * event_number);
const auto* defs = &this->r.pget<EventItem>(event_co.offset, event_co.count * sizeof(EventItem));
return make_pair(defs, event_co.count);
}
+101 -122
View File
@@ -11,6 +11,7 @@
#include "ItemData.hh"
#include "Text.hh"
#include "Types.hh"
class ItemParameterTable {
public:
@@ -18,11 +19,10 @@ public:
// functions instead of manually branching on various offset table pointers
// being null or not in each public function. Rewrite this and make it better.
template <bool IsBigEndian>
template <bool BE>
struct ArrayRefT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 00 */ U32T count;
/* 04 */ U32T offset;
/* 00 */ U32T<BE> count;
/* 04 */ U32T<BE> offset;
/* 08 */
} __packed__;
@@ -31,25 +31,22 @@ public:
check_struct_size(ArrayRef, 8);
check_struct_size(ArrayRefBE, 8);
template <bool IsBigEndian>
template <bool BE>
struct ItemBaseV2T {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
// id specifies several things; notably, it doubles as the index of the
// item's name in the text archive (e.g. TextEnglish) collection 0.
/* 00 */ U32T id = 0xFFFFFFFF;
/* 00 */ U32T<BE> id = 0xFFFFFFFF;
/* 04 */
} __packed__;
template <bool IsBigEndian>
struct ItemBaseV3T : ItemBaseV2T<IsBigEndian> {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* 04 */ U16T type = 0;
/* 06 */ U16T skin = 0;
template <bool BE>
struct ItemBaseV3T : ItemBaseV2T<BE> {
/* 04 */ U16T<BE> type = 0;
/* 06 */ U16T<BE> skin = 0;
/* 08 */
} __packed__;
template <bool IsBigEndian>
struct ItemBaseV4T : ItemBaseV3T<IsBigEndian> {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 08 */ U32T team_points = 0;
template <bool BE>
struct ItemBaseV4T : ItemBaseV3T<BE> {
/* 08 */ U32T<BE> team_points = 0;
/* 0C */
} __packed__;
@@ -118,17 +115,16 @@ public:
WeaponV4 to_v4() const;
} __packed_ws__(WeaponGCNTE, 0x24);
template <bool IsBigEndian>
template <bool BE>
struct WeaponV3T {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* 00 */ ItemBaseV3T<IsBigEndian> base;
/* 08 */ U16T class_flags = 0;
/* 0A */ U16T atp_min = 0;
/* 0C */ U16T atp_max = 0;
/* 0E */ U16T atp_required = 0;
/* 10 */ U16T mst_required = 0;
/* 12 */ U16T ata_required = 0;
/* 14 */ U16T mst = 0;
/* 00 */ ItemBaseV3T<BE> base;
/* 08 */ U16T<BE> class_flags = 0;
/* 0A */ U16T<BE> atp_min = 0;
/* 0C */ U16T<BE> atp_max = 0;
/* 0E */ U16T<BE> atp_required = 0;
/* 10 */ U16T<BE> mst_required = 0;
/* 12 */ U16T<BE> ata_required = 0;
/* 14 */ U16T<BE> mst = 0;
/* 16 */ uint8_t max_grind = 0;
/* 17 */ uint8_t photon = 0;
/* 18 */ uint8_t special = 0;
@@ -187,16 +183,15 @@ public:
/* 2C */
} __packed_ws__(WeaponV4, 0x2C);
template <typename BaseT, bool IsBigEndian>
template <typename BaseT, bool BE>
struct ArmorOrShieldT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* V1/V2 offsets */
/* 00 */ BaseT base;
/* 04 */ U16T dfp = 0;
/* 06 */ U16T evp = 0;
/* 04 */ U16T<BE> dfp = 0;
/* 06 */ U16T<BE> evp = 0;
/* 08 */ uint8_t block_particle = 0;
/* 09 */ uint8_t block_effect = 0;
/* 0A */ U16T class_flags = 0x00FF;
/* 0A */ U16T<BE> class_flags = 0x00FF;
/* 0C */ uint8_t required_level = 0;
/* 0D */ uint8_t efr = 0;
/* 0E */ uint8_t eth = 0;
@@ -208,12 +203,11 @@ public:
/* 14 */
} __packed__;
template <typename BaseT, bool IsBigEndian>
struct ArmorOrShieldFinalT : ArmorOrShieldT<BaseT, IsBigEndian> {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
template <typename BaseT, bool BE>
struct ArmorOrShieldFinalT : ArmorOrShieldT<BaseT, BE> {
/* 14 */ uint8_t stat_boost = 0;
/* 15 */ uint8_t tech_boost = 0;
/* 16 */ U16T unknown_a2 = 0;
/* 16 */ U16T<BE> unknown_a2 = 0;
/* 18 */
} __packed__;
using ArmorOrShieldV4 = ArmorOrShieldFinalT<ItemBaseV4T<false>, false>;
@@ -225,8 +219,8 @@ public:
struct ArmorOrShieldV1V2 : ArmorOrShieldFinalT<ItemBaseV2T<false>, false> {
ArmorOrShieldV4 to_v4() const;
} __packed_ws__(ArmorOrShieldV1V2, 0x18);
template <bool IsBigEndian>
struct ArmorOrShieldV3T : ArmorOrShieldFinalT<ItemBaseV3T<IsBigEndian>, IsBigEndian> {
template <bool BE>
struct ArmorOrShieldV3T : ArmorOrShieldFinalT<ItemBaseV3T<BE>, BE> {
ArmorOrShieldV4 to_v4() const;
} __packed__;
using ArmorOrShieldV3 = ArmorOrShieldV3T<false>;
@@ -234,21 +228,18 @@ public:
check_struct_size(ArmorOrShieldV3, 0x1C);
check_struct_size(ArmorOrShieldV3BE, 0x1C);
template <typename BaseT, bool IsBigEndian>
template <typename BaseT, bool BE>
struct UnitT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using S16T = typename std::conditional<IsBigEndian, be_int16_t, le_int16_t>::type;
/* V1/V2 offsets */
/* 00 */ BaseT base;
/* 04 */ U16T stat = 0;
/* 06 */ U16T stat_amount = 0;
/* 04 */ U16T<BE> stat = 0;
/* 06 */ U16T<BE> stat_amount = 0;
/* 08 */
} __packed__;
template <typename BaseT, bool IsBigEndian>
struct UnitFinalT : UnitT<BaseT, IsBigEndian> {
using S16T = typename std::conditional<IsBigEndian, be_int16_t, le_int16_t>::type;
/* 08 */ S16T modifier_amount = 0;
template <typename BaseT, bool BE>
struct UnitFinalT : UnitT<BaseT, BE> {
/* 08 */ S16T<BE> modifier_amount = 0;
/* 0A */ parray<uint8_t, 2> unused;
/* 0C */
} __packed__;
@@ -260,8 +251,8 @@ public:
struct UnitV1V2 : UnitFinalT<ItemBaseV2T<false>, false> {
UnitV4 to_v4() const;
} __packed_ws__(UnitV1V2, 0x0C);
template <bool IsBigEndian>
struct UnitV3T : UnitFinalT<ItemBaseV3T<IsBigEndian>, IsBigEndian> {
template <bool BE>
struct UnitV3T : UnitFinalT<ItemBaseV3T<BE>, BE> {
UnitV4 to_v4() const;
} __packed__;
using UnitV3 = UnitV3T<false>;
@@ -269,12 +260,11 @@ public:
check_struct_size(UnitV3, 0x10);
check_struct_size(UnitV3BE, 0x10);
template <typename BaseT, bool IsBigEndian>
template <typename BaseT, bool BE>
struct MagT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* V1/V2 offsets */
/* 00 */ BaseT base;
/* 04 */ U16T feed_table = 0;
/* 04 */ U16T<BE> feed_table = 0;
/* 06 */ uint8_t photon_blast = 0;
/* 07 */ uint8_t activation = 0;
/* 08 */ uint8_t on_pb_full = 0;
@@ -317,10 +307,9 @@ public:
MagV4 to_v4() const;
} __packed_ws__(MagV2, 0x14);
template <bool IsBigEndian>
struct MagV3T : MagT<ItemBaseV3T<IsBigEndian>, IsBigEndian> {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* 10 */ U16T class_flags = 0x00FF;
template <bool BE>
struct MagV3T : MagT<ItemBaseV3T<BE>, BE> {
/* 10 */ U16T<BE> class_flags = 0x00FF;
/* 12 */ parray<uint8_t, 2> unused;
/* 14 */
@@ -331,16 +320,13 @@ public:
check_struct_size(MagV3, 0x18);
check_struct_size(MagV3BE, 0x18);
template <typename BaseT, bool IsBigEndian>
template <typename BaseT, bool BE>
struct ToolT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using S32T = typename std::conditional<IsBigEndian, be_int32_t, le_int32_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* V1/V2 offsets */
/* 00 */ BaseT base;
/* 04 */ U16T amount = 0;
/* 06 */ U16T tech = 0;
/* 08 */ S32T cost = 0;
/* 04 */ U16T<BE> amount = 0;
/* 06 */ U16T<BE> tech = 0;
/* 08 */ S32T<BE> cost = 0;
// Bits in item_flags:
// 00000001 - ever usable by player ("Use" appears in inventory menu)
// 00000002 - unknown
@@ -350,7 +336,7 @@ public:
// 00000020 - usable in boss arenas
// 00000040 - usable in Challenge mode
// 00000080 - is rare (renders as red box; V3+)
/* 0C */ U32T item_flags = 0;
/* 0C */ U32T<BE> item_flags = 0;
/* 10 */
} __packed__;
@@ -359,8 +345,8 @@ public:
struct ToolV1V2 : ToolT<ItemBaseV2T<false>, false> {
ToolV4 to_v4() const;
} __packed_ws__(ToolV1V2, 0x10);
template <bool IsBigEndian>
struct ToolV3T : ToolT<ItemBaseV3T<IsBigEndian>, IsBigEndian> {
template <bool BE>
struct ToolV3T : ToolT<ItemBaseV3T<BE>, BE> {
ToolV4 to_v4() const;
} __packed__;
using ToolV3 = ToolV3T<false>;
@@ -380,34 +366,31 @@ public:
using MagFeedResultsList = parray<MagFeedResult, 11>;
template <bool IsBigEndian>
template <bool BE>
struct MagFeedResultsListOffsetsT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
parray<U32T, 8> offsets; // Offsets of MagFeedResultsList objects
parray<U32T<BE>, 8> offsets; // Offsets of MagFeedResultsList objects
} __packed__;
using MagFeedResultsListOffsets = MagFeedResultsListOffsetsT<false>;
using MagFeedResultsListOffsetsBE = MagFeedResultsListOffsetsT<true>;
check_struct_size(MagFeedResultsListOffsets, 0x20);
check_struct_size(MagFeedResultsListOffsetsBE, 0x20);
template <bool IsBigEndian>
template <bool BE>
struct SpecialT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
U16T type = 0xFFFF;
U16T amount = 0;
U16T<BE> type = 0xFFFF;
U16T<BE> amount = 0;
} __packed__;
using Special = SpecialT<false>;
using SpecialBE = SpecialT<true>;
check_struct_size(Special, 4);
check_struct_size(SpecialBE, 4);
template <bool IsBigEndian>
template <bool BE>
struct StatBoostT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
uint8_t stat1 = 0;
uint8_t stat2 = 0;
U16T amount1 = 0;
U16T amount2 = 0;
U16T<BE> amount1 = 0;
U16T<BE> amount2 = 0;
} __packed__;
using StatBoost = StatBoostT<false>;
using StatBoostBE = StatBoostT<true>;
@@ -428,16 +411,14 @@ public:
parray<uint8_t, 3> unused;
} __packed_ws__(ItemCombination, 0x10);
template <bool IsBigEndian>
template <bool BE>
struct TechniqueBoostT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
using FloatT = typename std::conditional<IsBigEndian, be_float, le_float>::type;
U32T tech1 = 0;
FloatT boost1 = 0.0f;
U32T tech2 = 0;
FloatT boost2 = 0.0f;
U32T tech3 = 0;
FloatT boost3 = 0.0f;
U32T<BE> tech1 = 0;
F32T<BE> boost1 = 0.0f;
U32T<BE> tech2 = 0;
F32T<BE> boost2 = 0.0f;
U32T<BE> tech3 = 0;
F32T<BE> boost3 = 0.0f;
} __packed__;
using TechniqueBoost = TechniqueBoostT<false>;
using TechniqueBoostBE = TechniqueBoostT<true>;
@@ -454,13 +435,12 @@ public:
uint8_t unused = 0;
} __packed_ws__(UnsealableItem, 4);
template <bool IsBigEndian>
template <bool BE>
struct NonWeaponSaleDivisorsT {
using FloatT = typename std::conditional<IsBigEndian, be_float, le_float>::type;
FloatT armor_divisor = 0.0f;
FloatT shield_divisor = 0.0f;
FloatT unit_divisor = 0.0f;
FloatT mag_divisor = 0.0f;
F32T<BE> armor_divisor = 0.0f;
F32T<BE> shield_divisor = 0.0f;
F32T<BE> unit_divisor = 0.0f;
F32T<BE> mag_divisor = 0.0f;
} __packed__;
using NonWeaponSaleDivisors = NonWeaponSaleDivisorsT<false>;
using NonWeaponSaleDivisorsBE = NonWeaponSaleDivisorsT<true>;
@@ -587,33 +567,32 @@ private:
/* 4C / 6B1C */ be_uint32_t tech_boost_table; // -> [TechniqueBoost] (always 0x2C of them? from counts struct?)
} __packed_ws__(TableOffsetsGCNTE, 0x50);
template <bool IsBigEndian>
template <bool BE>
struct TableOffsetsV3V4T {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* ## / GC / BB */
/* 00 / F078 / 14884 */ U32T weapon_table; // -> [{count, offset -> [WeaponV3/WeaponV4]}](0xED)
/* 04 / EF90 / 1478C */ U32T armor_table; // -> [{count, offset -> [ArmorOrShieldV3/ArmorOrShieldV4]}](2; armors and shields)
/* 08 / EFA0 / 1479C */ U32T unit_table; // -> {count, offset -> [UnitV3/UnitV4]} (last if out of range)
/* 0C / EFB0 / 147AC */ U32T tool_table; // -> [{count, offset -> [ToolV3/ToolV4]}](0x1A) (last if out of range)
/* 10 / EFA8 / 147A4 */ U32T mag_table; // -> {count, offset -> [MagV3/MagV4]}
/* 14 / B88C / 0F4B8 */ U32T v1_replacement_table; // -> [uint8_t](0xED)
/* 18 / A7FC / 0DE7C */ U32T photon_color_table; // -> [0x24-byte structs](0x20)
/* 1C / AACC / 0E194 */ U32T weapon_range_table; // -> ???
/* 20 / B938 / 0F5A8 */ U32T weapon_sale_divisor_table; // -> [float](0xED)
/* 24 / BBCC / 0F83C */ U32T sale_divisor_table; // -> NonWeaponSaleDivisors
/* 28 / F608 / 1502C */ U32T mag_feed_table; // -> MagFeedResultsTable
/* 2C / BE9C / 0FB0C */ U32T star_value_table; // -> [uint8_t](0x330) (indexed by .id from weapon, armor, etc.)
/* 30 / C100 / 0FE3C */ U32T special_data_table; // -> [Special]
/* 34 / C1A4 / 0FEE0 */ U32T weapon_effect_table; // -> [16-byte structs]
/* 38 / DE50 / 1275C */ U32T stat_boost_table; // -> [StatBoost]
/* 3C / D6E4 / 11C80 */ U32T shield_effect_table; // -> [8-byte structs]
/* 40 / DF88 / 12894 */ U32T max_tech_level_table; // -> MaxTechniqueLevels
/* 44 / F5D0 / 14FF4 */ U32T combination_table; // -> {count, offset -> [ItemCombination]}
/* 48 / DE48 / 12754 */ U32T unknown_a1;
/* 4C / EB8C / 14278 */ U32T tech_boost_table; // -> [TechniqueBoost] (always 0x2C of them? from counts struct?)
/* 50 / F5F0 / 15014 */ U32T unwrap_table; // -> {count, offset -> [{count, offset -> [EventItem]}]}
/* 54 / F5F8 / 1501C */ U32T unsealable_table; // -> {count, offset -> [UnsealableItem]}
/* 58 / F600 / 15024 */ U32T ranged_special_table; // -> {count, offset -> [4-byte structs]}
/* 00 / F078 / 14884 */ U32T<BE> weapon_table; // -> [{count, offset -> [WeaponV3/WeaponV4]}](0xED)
/* 04 / EF90 / 1478C */ U32T<BE> armor_table; // -> [{count, offset -> [ArmorOrShieldV3/ArmorOrShieldV4]}](2; armors and shields)
/* 08 / EFA0 / 1479C */ U32T<BE> unit_table; // -> {count, offset -> [UnitV3/UnitV4]} (last if out of range)
/* 0C / EFB0 / 147AC */ U32T<BE> tool_table; // -> [{count, offset -> [ToolV3/ToolV4]}](0x1A) (last if out of range)
/* 10 / EFA8 / 147A4 */ U32T<BE> mag_table; // -> {count, offset -> [MagV3/MagV4]}
/* 14 / B88C / 0F4B8 */ U32T<BE> v1_replacement_table; // -> [uint8_t](0xED)
/* 18 / A7FC / 0DE7C */ U32T<BE> photon_color_table; // -> [0x24-byte structs](0x20)
/* 1C / AACC / 0E194 */ U32T<BE> weapon_range_table; // -> ???
/* 20 / B938 / 0F5A8 */ U32T<BE> weapon_sale_divisor_table; // -> [float](0xED)
/* 24 / BBCC / 0F83C */ U32T<BE> sale_divisor_table; // -> NonWeaponSaleDivisors
/* 28 / F608 / 1502C */ U32T<BE> mag_feed_table; // -> MagFeedResultsTable
/* 2C / BE9C / 0FB0C */ U32T<BE> star_value_table; // -> [uint8_t](0x330) (indexed by .id from weapon, armor, etc.)
/* 30 / C100 / 0FE3C */ U32T<BE> special_data_table; // -> [Special]
/* 34 / C1A4 / 0FEE0 */ U32T<BE> weapon_effect_table; // -> [16-byte structs]
/* 38 / DE50 / 1275C */ U32T<BE> stat_boost_table; // -> [StatBoost]
/* 3C / D6E4 / 11C80 */ U32T<BE> shield_effect_table; // -> [8-byte structs]
/* 40 / DF88 / 12894 */ U32T<BE> max_tech_level_table; // -> MaxTechniqueLevels
/* 44 / F5D0 / 14FF4 */ U32T<BE> combination_table; // -> {count, offset -> [ItemCombination]}
/* 48 / DE48 / 12754 */ U32T<BE> unknown_a1;
/* 4C / EB8C / 14278 */ U32T<BE> tech_boost_table; // -> [TechniqueBoost] (always 0x2C of them? from counts struct?)
/* 50 / F5F0 / 15014 */ U32T<BE> unwrap_table; // -> {count, offset -> [{count, offset -> [EventItem]}]}
/* 54 / F5F8 / 1501C */ U32T<BE> unsealable_table; // -> {count, offset -> [UnsealableItem]}
/* 58 / F600 / 15024 */ U32T<BE> ranged_special_table; // -> {count, offset -> [4-byte structs]}
} __packed__;
using TableOffsetsV3V4 = TableOffsetsV3V4T<false>;
using TableOffsetsV3V4BE = TableOffsetsV3V4T<true>;
@@ -622,7 +601,7 @@ private:
Version version;
std::shared_ptr<const std::string> data;
StringReader r;
phosg::StringReader r;
const TableOffsetsDCProtos* offsets_dc_protos;
const TableOffsetsV1V2* offsets_v1_v2;
const TableOffsetsGCNTE* offsets_gc_nte;
@@ -644,13 +623,13 @@ private:
// equipped_item may contain wildcards, and the matching order matters.
mutable std::map<uint32_t, std::vector<ItemCombination>> item_combination_index;
template <typename ToolDefT, bool IsBigEndian>
template <typename ToolDefT, bool BE>
std::pair<uint8_t, uint8_t> find_tool_by_id_t(uint32_t tool_table_offset, uint32_t id) const;
template <bool IsBigEndian, typename OffsetsT>
template <bool BE, typename OffsetsT>
float get_sale_divisor_t(const OffsetsT* offsets, uint8_t data1_0, uint8_t data1_1) const;
template <bool IsBigEndian>
template <bool BE>
size_t num_events_t(uint32_t base_offset) const;
template <bool IsBigEndian>
template <bool BE>
std::pair<const ItemParameterTable::EventItem*, size_t> get_event_items_t(uint32_t base_offset, uint8_t event_number) const;
};
@@ -677,6 +656,6 @@ public:
private:
std::shared_ptr<const std::string> data;
StringReader r;
phosg::StringReader r;
const TableOffsets* offsets;
};
+9 -9
View File
@@ -54,13 +54,13 @@ LevelTableV2::LevelTableV2(const string& data, bool compressed) {
le_uint32_t unknown_a12; // -> u32[3] -> (0x14-byte struct)[0x0F]
} __packed_ws__(Offsets, 0x40);
StringReader r;
phosg::StringReader r;
string decompressed_data;
if (compressed) {
decompressed_data = prs_decompress(data);
r = StringReader(decompressed_data);
r = phosg::StringReader(decompressed_data);
} else {
r = StringReader(data);
r = phosg::StringReader(data);
}
const auto& offsets = r.pget<Offsets>(r.pget_u32l(r.size() - 0x10));
@@ -94,7 +94,7 @@ const LevelStatsDelta& LevelTableV2::stats_delta_for_level(uint8_t char_class, u
}
LevelTableV3BE::LevelTableV3BE(const string& data, bool encrypted) {
StringReader r;
phosg::StringReader r;
string decompressed_data;
if (encrypted) {
auto decrypted = decrypt_pr2_data<true>(data);
@@ -102,9 +102,9 @@ LevelTableV3BE::LevelTableV3BE(const string& data, bool encrypted) {
if (decompressed_data.size() != decrypted.decompressed_size) {
throw runtime_error("decompressed data size does not match expected size");
}
r = StringReader(decompressed_data);
r = phosg::StringReader(decompressed_data);
} else {
r = StringReader(data);
r = phosg::StringReader(data);
}
// The GC format is very simple (but everything is big-endian):
@@ -160,13 +160,13 @@ LevelTableV4::LevelTableV4(const string& data, bool compressed) {
le_uint32_t level_deltas; // -> u32[12] -> LevelStatsDelta[200]
} __packed_ws__(Offsets, 8);
StringReader r;
phosg::StringReader r;
string decompressed_data;
if (compressed) {
decompressed_data = prs_decompress(data);
r = StringReader(decompressed_data);
r = phosg::StringReader(decompressed_data);
} else {
r = StringReader(data);
r = phosg::StringReader(data);
}
const auto& offsets = r.pget<Offsets>(r.pget_u32l(r.size() - 0x10));
+22 -30
View File
@@ -11,21 +11,19 @@
class LevelTable;
template <bool IsBigEndian>
template <bool BE>
struct CharacterStatsT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* 00 */ U16T atp = 0;
/* 02 */ U16T mst = 0;
/* 04 */ U16T evp = 0;
/* 06 */ U16T hp = 0;
/* 08 */ U16T dfp = 0;
/* 0A */ U16T ata = 0;
/* 0C */ U16T lck = 0;
/* 00 */ U16T<BE> atp = 0;
/* 02 */ U16T<BE> mst = 0;
/* 04 */ U16T<BE> evp = 0;
/* 06 */ U16T<BE> hp = 0;
/* 08 */ U16T<BE> dfp = 0;
/* 0A */ U16T<BE> ata = 0;
/* 0C */ U16T<BE> lck = 0;
/* 0E */
operator CharacterStatsT<!IsBigEndian>() const {
CharacterStatsT<!IsBigEndian> ret;
operator CharacterStatsT<!BE>() const {
CharacterStatsT<!BE> ret;
ret.atp = this->atp.load();
ret.mst = this->mst.load();
ret.evp = this->evp.load();
@@ -41,23 +39,19 @@ using CharacterStatsBE = CharacterStatsT<true>;
check_struct_size(CharacterStats, 0x0E);
check_struct_size(CharacterStatsBE, 0x0E);
template <bool IsBigEndian>
template <bool BE>
struct PlayerStatsT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
/* 00 */ CharacterStatsT<IsBigEndian> char_stats;
/* 0E */ U16T esp = 0;
/* 10 */ F32T height = 0.0;
/* 14 */ F32T unknown_a3 = 0.0;
/* 18 */ U32T level = 0;
/* 1C */ U32T experience = 0;
/* 20 */ U32T meseta = 0;
/* 00 */ CharacterStatsT<BE> char_stats;
/* 0E */ U16T<BE> esp = 0;
/* 10 */ F32T<BE> height = 0.0;
/* 14 */ F32T<BE> unknown_a3 = 0.0;
/* 18 */ U32T<BE> level = 0;
/* 1C */ U32T<BE> experience = 0;
/* 20 */ U32T<BE> meseta = 0;
/* 24 */
operator PlayerStatsT<!IsBigEndian>() const {
PlayerStatsT<!IsBigEndian> ret;
operator PlayerStatsT<!BE>() const {
PlayerStatsT<!BE> ret;
ret.char_stats = this->char_stats;
ret.esp = this->esp.load();
ret.height = this->height.load();
@@ -73,10 +67,8 @@ using PlayerStatsBE = PlayerStatsT<true>;
check_struct_size(PlayerStats, 0x24);
check_struct_size(PlayerStatsBE, 0x24);
template <bool IsBigEndian>
template <bool BE>
struct LevelStatsDeltaT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 00 */ uint8_t atp;
/* 01 */ uint8_t mst;
/* 02 */ uint8_t evp;
@@ -85,7 +77,7 @@ struct LevelStatsDeltaT {
/* 05 */ uint8_t ata;
/* 06 */ uint8_t lck;
/* 07 */ uint8_t tp;
/* 08 */ U32T experience;
/* 08 */ U32T<BE> experience;
/* 0C */
void apply(CharacterStats& ps) const {
+9 -9
View File
@@ -16,7 +16,7 @@ bool Lobby::FloorItem::visible_to_client(uint8_t client_id) const {
}
Lobby::FloorItemManager::FloorItemManager(uint32_t lobby_id, uint8_t floor)
: log(string_printf("[Lobby:%08" PRIX32 ":FloorItems:%02hhX] ", lobby_id, floor), lobby_log.min_level),
: log(phosg::string_printf("[Lobby:%08" PRIX32 ":FloorItems:%02hhX] ", lobby_id, floor), lobby_log.min_level),
next_drop_number(0) {}
bool Lobby::FloorItemManager::exists(uint32_t item_id) const {
@@ -137,7 +137,7 @@ uint32_t Lobby::FloorItemManager::reassign_all_item_ids(uint32_t next_item_id) {
Lobby::Lobby(shared_ptr<ServerState> s, uint32_t id, bool is_game)
: server_state(s),
log(string_printf("[%s:%" PRIX32 "] ", is_game ? "Game" : "Lobby", id), lobby_log.min_level),
log(phosg::string_printf("[%s:%" PRIX32 "] ", is_game ? "Game" : "Lobby", id), lobby_log.min_level),
lobby_id(id),
min_level(0),
max_level(0xFFFFFFFF),
@@ -151,7 +151,7 @@ Lobby::Lobby(shared_ptr<ServerState> s, uint32_t id, bool is_game)
base_exp_multiplier(1),
exp_share_multiplier(0.5),
challenge_exp_multiplier(1.0f),
random_seed(random_object<uint32_t>()),
random_seed(phosg::random_object<uint32_t>()),
drop_mode(DropMode::CLIENT),
event(0),
block(0),
@@ -325,7 +325,7 @@ shared_ptr<Map> Lobby::load_maps(
uint32_t random_seed,
shared_ptr<PSOLFGEncryption> opt_rand_crypt,
const parray<le_uint32_t, 0x20>& variations,
const PrefixedLogger* log) {
const phosg::PrefixedLogger* log) {
auto enemy_filenames = sdt->map_filenames_for_variations(variations, episode, mode, SetDataTable::FilenameType::ENEMIES);
auto object_filenames = sdt->map_filenames_for_variations(variations, episode, mode, SetDataTable::FilenameType::OBJECTS);
auto event_filenames = sdt->map_filenames_for_variations(variations, episode, mode, SetDataTable::FilenameType::EVENTS);
@@ -360,7 +360,7 @@ shared_ptr<Map> Lobby::load_maps(
shared_ptr<const Map::RareEnemyRates> rare_rates,
uint32_t rare_seed,
shared_ptr<PSOLFGEncryption> opt_rand_crypt,
const PrefixedLogger* log) {
const phosg::PrefixedLogger* log) {
auto map = make_shared<Map>(version, lobby_id, rare_seed, opt_rand_crypt);
// Don't load free-roam maps in Challenge mode, since players can't go to
@@ -682,7 +682,7 @@ void Lobby::add_client(shared_ptr<Client> c, ssize_t required_client_id) {
void Lobby::remove_client(shared_ptr<Client> c) {
if (this->clients.at(c->lobby_client_id) != c) {
auto other_c = this->clients[c->lobby_client_id].get();
throw logic_error(string_printf(
throw logic_error(phosg::string_printf(
"client\'s lobby client id (%hhu) does not match client list (%u)",
c->lobby_client_id,
static_cast<uint8_t>(other_c ? other_c->lobby_client_id : 0xFF)));
@@ -743,7 +743,7 @@ void Lobby::remove_client(shared_ptr<Client> c) {
(this->idle_timeout_usecs > 0)) {
// If the lobby is persistent but has an idle timeout, make it expire after
// the specified time
auto tv = usecs_to_timeval(this->idle_timeout_usecs);
auto tv = phosg::usecs_to_timeval(this->idle_timeout_usecs);
event_add(this->idle_timeout_event.get(), &tv);
this->log.info("Idle timeout scheduled");
}
@@ -1031,7 +1031,7 @@ bool Lobby::compare_shared(const shared_ptr<const Lobby>& a, const shared_ptr<co
}
template <>
Lobby::DropMode enum_for_name<Lobby::DropMode>(const char* name) {
Lobby::DropMode phosg::enum_for_name<Lobby::DropMode>(const char* name) {
if (!strcmp(name, "DISABLED")) {
return Lobby::DropMode::DISABLED;
} else if (!strcmp(name, "CLIENT")) {
@@ -1048,7 +1048,7 @@ Lobby::DropMode enum_for_name<Lobby::DropMode>(const char* name) {
}
template <>
const char* name_for_enum<Lobby::DropMode>(Lobby::DropMode value) {
const char* phosg::name_for_enum<Lobby::DropMode>(Lobby::DropMode value) {
switch (value) {
case Lobby::DropMode::DISABLED:
return "DISABLED";
+6 -6
View File
@@ -40,7 +40,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
bool visible_to_client(uint8_t client_id) const;
};
struct FloorItemManager {
PrefixedLogger log;
phosg::PrefixedLogger log;
uint64_t next_drop_number;
// It's important that this is a map and not an unordered_map. See the
// comment in send_game_item_state for more details.
@@ -92,7 +92,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
};
std::weak_ptr<ServerState> server_state;
PrefixedLogger log;
phosg::PrefixedLogger log;
uint32_t lobby_id;
@@ -231,7 +231,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
uint32_t random_seed,
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt,
const parray<le_uint32_t, 0x20>& variations,
const PrefixedLogger* log = nullptr);
const phosg::PrefixedLogger* log = nullptr);
static std::shared_ptr<Map> load_maps(
const std::vector<std::string>& enemy_filenames,
const std::vector<std::string>& object_filenames,
@@ -246,7 +246,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
std::shared_ptr<const Map::RareEnemyRates> rare_rates,
uint32_t random_seed,
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt,
const PrefixedLogger* log = nullptr);
const phosg::PrefixedLogger* log = nullptr);
void load_maps();
void create_ep3_server();
@@ -316,6 +316,6 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
};
template <>
Lobby::DropMode enum_for_name<Lobby::DropMode>(const char* name);
Lobby::DropMode phosg::enum_for_name<Lobby::DropMode>(const char* name);
template <>
const char* name_for_enum<Lobby::DropMode>(Lobby::DropMode value);
const char* phosg::name_for_enum<Lobby::DropMode>(Lobby::DropMode value);
+19 -19
View File
@@ -4,32 +4,32 @@
using namespace std;
PrefixedLogger ax_messages_log("[$ax message] ", LogLevel::USE_DEFAULT);
PrefixedLogger channel_exceptions_log("[Channel] ", LogLevel::USE_DEFAULT);
PrefixedLogger client_log("", LogLevel::USE_DEFAULT);
PrefixedLogger command_data_log("[Commands] ", LogLevel::USE_DEFAULT);
PrefixedLogger config_log("[Config] ", LogLevel::USE_DEFAULT);
PrefixedLogger dns_server_log("[DNSServer] ", LogLevel::USE_DEFAULT);
PrefixedLogger function_compiler_log("[FunctionCompiler] ", LogLevel::USE_DEFAULT);
PrefixedLogger ip_stack_simulator_log("[IPStackSimulator] ", LogLevel::USE_DEFAULT);
PrefixedLogger lobby_log("", LogLevel::USE_DEFAULT);
PrefixedLogger patch_index_log("[PatchFileIndex] ", LogLevel::USE_DEFAULT);
PrefixedLogger player_data_log("", LogLevel::USE_DEFAULT);
PrefixedLogger proxy_server_log("[ProxyServer] ", LogLevel::USE_DEFAULT);
PrefixedLogger replay_log("[ReplaySession] ", LogLevel::USE_DEFAULT);
PrefixedLogger server_log("[Server] ", LogLevel::USE_DEFAULT);
PrefixedLogger static_game_data_log("[StaticGameData] ", LogLevel::USE_DEFAULT);
phosg::PrefixedLogger ax_messages_log("[$ax message] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger channel_exceptions_log("[Channel] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger client_log("", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger command_data_log("[Commands] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger config_log("[Config] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger dns_server_log("[DNSServer] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger function_compiler_log("[FunctionCompiler] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger ip_stack_simulator_log("[IPStackSimulator] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger lobby_log("", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger patch_index_log("[PatchFileIndex] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger player_data_log("", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger proxy_server_log("[ProxyServer] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger replay_log("[ReplaySession] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger server_log("[Server] ", phosg::LogLevel::USE_DEFAULT);
phosg::PrefixedLogger static_game_data_log("[StaticGameData] ", phosg::LogLevel::USE_DEFAULT);
static void set_log_level_from_json(
PrefixedLogger& log, const JSON& d, const char* json_key) {
phosg::PrefixedLogger& log, const phosg::JSON& d, const char* json_key) {
try {
string name = toupper(d.at(json_key).as_string());
log.min_level = enum_for_name<LogLevel>(name.c_str());
string name = phosg::toupper(d.at(json_key).as_string());
log.min_level = phosg::enum_for_name<phosg::LogLevel>(name.c_str());
} catch (const out_of_range&) {
}
}
void set_log_levels_from_json(const JSON& json) {
void set_log_levels_from_json(const phosg::JSON& json) {
set_log_level_from_json(ax_messages_log, json, "AXMessages");
set_log_level_from_json(channel_exceptions_log, json, "ChannelExceptions");
set_log_level_from_json(client_log, json, "Clients");
+16 -16
View File
@@ -3,20 +3,20 @@
#include <phosg/JSON.hh>
#include <phosg/Strings.hh>
extern PrefixedLogger ax_messages_log;
extern PrefixedLogger channel_exceptions_log;
extern PrefixedLogger client_log;
extern PrefixedLogger command_data_log;
extern PrefixedLogger config_log;
extern PrefixedLogger dns_server_log;
extern PrefixedLogger function_compiler_log;
extern PrefixedLogger ip_stack_simulator_log;
extern PrefixedLogger lobby_log;
extern PrefixedLogger patch_index_log;
extern PrefixedLogger player_data_log;
extern PrefixedLogger proxy_server_log;
extern PrefixedLogger replay_log;
extern PrefixedLogger server_log;
extern PrefixedLogger static_game_data_log;
extern phosg::PrefixedLogger ax_messages_log;
extern phosg::PrefixedLogger channel_exceptions_log;
extern phosg::PrefixedLogger client_log;
extern phosg::PrefixedLogger command_data_log;
extern phosg::PrefixedLogger config_log;
extern phosg::PrefixedLogger dns_server_log;
extern phosg::PrefixedLogger function_compiler_log;
extern phosg::PrefixedLogger ip_stack_simulator_log;
extern phosg::PrefixedLogger lobby_log;
extern phosg::PrefixedLogger patch_index_log;
extern phosg::PrefixedLogger player_data_log;
extern phosg::PrefixedLogger proxy_server_log;
extern phosg::PrefixedLogger replay_log;
extern phosg::PrefixedLogger server_log;
extern phosg::PrefixedLogger static_game_data_log;
void set_log_levels_from_json(const JSON& json);
void set_log_levels_from_json(const phosg::JSON& json);
+269 -269
View File
File diff suppressed because it is too large Load Diff
+72 -74
View File
@@ -583,7 +583,7 @@ Map::RareEnemyRates::RareEnemyRates(uint32_t enemy_rate, uint32_t boss_rate)
dorphon_eclair(enemy_rate),
kondrieu(boss_rate) {}
Map::RareEnemyRates::RareEnemyRates(const JSON& json)
Map::RareEnemyRates::RareEnemyRates(const phosg::JSON& json)
: hildeblue(json.get_int("Hildeblue")),
rappy(json.get_int("Rappy")),
nar_lily(json.get_int("NarLily")),
@@ -593,8 +593,8 @@ Map::RareEnemyRates::RareEnemyRates(const JSON& json)
dorphon_eclair(json.get_int("DorphonEclair")),
kondrieu(json.get_int("Kondrieu")) {}
JSON Map::RareEnemyRates::json() const {
return JSON::dict({
phosg::JSON Map::RareEnemyRates::json() const {
return phosg::JSON::dict({
{"Hildeblue", this->hildeblue},
{"Rappy", this->rappy},
{"NarLily", this->nar_lily},
@@ -608,7 +608,7 @@ JSON Map::RareEnemyRates::json() const {
string Map::ObjectEntry::str() const {
string name_str = Map::name_for_object_type(this->base_type);
return string_printf("[ObjectEntry type=%04hX \"%s\" flags=%04hX index=%04hX a2=%04hX entity_id=%04hX group=%04hX section=%04hX a3=%04hX x=%g y=%g z=%g x_angle=%08" PRIX32 " y_angle=%08" PRIX32 " z_angle=%08" PRIX32 " params=[%g %g %g %08" PRIX32 " %08" PRIX32 " %08" PRIX32 "] unused=%08" PRIX32 "]",
return phosg::string_printf("[ObjectEntry type=%04hX \"%s\" flags=%04hX index=%04hX a2=%04hX entity_id=%04hX group=%04hX section=%04hX a3=%04hX x=%g y=%g z=%g x_angle=%08" PRIX32 " y_angle=%08" PRIX32 " z_angle=%08" PRIX32 " params=[%g %g %g %08" PRIX32 " %08" PRIX32 " %08" PRIX32 "] unused=%08" PRIX32 "]",
this->base_type.load(),
name_str.c_str(),
this->flags.load(),
@@ -634,7 +634,7 @@ string Map::ObjectEntry::str() const {
}
string Map::EnemyEntry::str() const {
return string_printf("[EnemyEntry type=%04hX flags=%04hX index=%04hX num_children=%04hX floor=%04hX entity_id=%04hX section=%04hX wave_number=%04hX wave_number2=%04hX a1=%04hX x=%g y=%g z=%g x_angle=%08" PRIX32 " y_angle=%08" PRIX32 " z_angle=%08" PRIX32 " params=[%g %g %g %g %g %04hX %04hX] unused=%08" PRIX32 "]",
return phosg::string_printf("[EnemyEntry type=%04hX flags=%04hX index=%04hX num_children=%04hX floor=%04hX entity_id=%04hX section=%04hX wave_number=%04hX wave_number2=%04hX a1=%04hX x=%g y=%g z=%g x_angle=%08" PRIX32 " y_angle=%08" PRIX32 " z_angle=%08" PRIX32 " params=[%g %g %g %g %g %04hX %04hX] unused=%08" PRIX32 "]",
this->base_type.load(),
this->flags.load(),
this->index.load(),
@@ -681,10 +681,10 @@ Map::Enemy::Enemy(
server_flags(0) {}
string Map::Enemy::str() const {
return string_printf("[Map::Enemy E-%hX source %zX %s%s floor=%02hhX section=%04hX wave_number=%04hX server_flags=%02hhX]",
return phosg::string_printf("[Map::Enemy E-%hX source %zX %s%s floor=%02hhX section=%04hX wave_number=%04hX server_flags=%02hhX]",
this->enemy_id,
this->source_index,
name_for_enum(this->type),
phosg::name_for_enum(this->type),
enemy_type_is_rare(this->type) ? " RARE" : "",
this->floor,
this->section,
@@ -693,7 +693,7 @@ string Map::Enemy::str() const {
}
string Map::Event::str() const {
return string_printf("[Map::Event W-%02hhX-%" PRIX32 " flags=%04hX floor=%02hhX action_stream_offset=%" PRIX32 "]",
return phosg::string_printf("[Map::Event W-%02hhX-%" PRIX32 " flags=%04hX floor=%02hhX action_stream_offset=%" PRIX32 "]",
this->floor,
this->event_id,
this->flags,
@@ -702,7 +702,7 @@ string Map::Event::str() const {
}
string Map::Object::str() const {
return string_printf("[Map::Object source %zX %04hX(%s) @%04hX p1=%g p456=[%08" PRIX32 " %08" PRIX32 " %08" PRIX32 "] floor=%02hhX item_drop_checked=%s]",
return phosg::string_printf("[Map::Object source %zX %04hX(%s) @%04hX p1=%g p456=[%08" PRIX32 " %08" PRIX32 " %08" PRIX32 "] floor=%02hhX item_drop_checked=%s]",
this->source_index,
this->base_type,
Map::name_for_object_type(this->base_type),
@@ -716,7 +716,7 @@ string Map::Object::str() const {
}
Map::Map(Version version, uint32_t lobby_id, uint32_t rare_seed, std::shared_ptr<PSOLFGEncryption> opt_rand_crypt)
: log(string_printf("[Lobby:%08" PRIX32 ":map] ", lobby_id), lobby_log.min_level),
: log(phosg::string_printf("[Lobby:%08" PRIX32 ":map] ", lobby_id), lobby_log.min_level),
version(version),
rare_seed(rare_seed),
opt_rand_crypt(opt_rand_crypt) {}
@@ -1254,7 +1254,7 @@ void Map::add_enemies_from_map_data(
throw runtime_error("data size is not a multiple of entry size");
}
StringReader r(data, size);
phosg::StringReader r(data, size);
for (size_t y = 0; y < entry_count; y++) {
this->add_enemy(episode, difficulty, event, floor, y, r.get<EnemyEntry>(), rare_rates);
}
@@ -1284,12 +1284,12 @@ uint32_t Map::DATParserRandomState::next_location_index() {
}
void Map::DATParserRandomState::generate_shuffled_location_table(
const Map::RandomEnemyLocationsHeader& header, StringReader r, uint16_t section) {
const Map::RandomEnemyLocationsHeader& header, phosg::StringReader r, uint16_t section) {
if (header.num_sections == 0) {
throw runtime_error("no locations defined");
}
StringReader sections_r = r.sub(header.section_table_offset, header.num_sections * sizeof(Map::RandomEnemyLocationSection));
phosg::StringReader sections_r = r.sub(header.section_table_offset, header.num_sections * sizeof(Map::RandomEnemyLocationSection));
size_t bs_min = 0;
size_t bs_max = header.num_sections - 1;
@@ -1330,9 +1330,9 @@ void Map::add_random_enemies_from_map_data(
uint8_t difficulty,
uint8_t event,
uint8_t floor,
StringReader wave_events_segment_r,
StringReader locations_segment_r,
StringReader definitions_segment_r,
phosg::StringReader wave_events_segment_r,
phosg::StringReader locations_segment_r,
phosg::StringReader definitions_segment_r,
std::shared_ptr<DATParserRandomState> random_state,
std::shared_ptr<const RareEnemyRates> rare_rates) {
@@ -1362,7 +1362,7 @@ void Map::add_random_enemies_from_map_data(
definitions_header.weight_entry_count * sizeof(RandomEnemyWeight));
for (size_t wave_entry_index = 0; wave_entry_index < wave_events_header.entry_count; wave_entry_index++) {
auto entry_log = this->log.sub(string_printf("(Entry %zu/%" PRIu32 ") ", wave_entry_index, wave_events_header.entry_count.load()));
auto entry_log = this->log.sub(phosg::string_printf("(Entry %zu/%" PRIu32 ") ", wave_entry_index, wave_events_header.entry_count.load()));
const auto& entry = wave_events_segment_r.get<Event2Entry>();
size_t remaining_waves = random_state->rand_int_biased(1, entry.max_waves);
@@ -1372,7 +1372,7 @@ void Map::add_random_enemies_from_map_data(
uint32_t wave_number = entry.wave_number;
while (remaining_waves) {
remaining_waves--;
auto wave_log = entry_log.sub(string_printf("(Wave %zu) ", remaining_waves));
auto wave_log = entry_log.sub(phosg::string_printf("(Wave %zu) ", remaining_waves));
size_t remaining_enemies = random_state->rand_int_biased(entry.min_enemies, entry.max_enemies);
// Trace: at 0080E208 EDI is enemy count
@@ -1382,7 +1382,7 @@ void Map::add_random_enemies_from_map_data(
while (remaining_enemies) {
remaining_enemies--;
auto enemy_log = wave_log.sub(string_printf("(Enemy %zu) ", remaining_enemies));
auto enemy_log = wave_log.sub(phosg::string_printf("(Enemy %zu) ", remaining_enemies));
// TODO: Factor this sum out of the loops
weights_r.go(0);
@@ -1506,7 +1506,7 @@ vector<const Map::Event*> Map::get_events(uint8_t floor, uint32_t event_id) cons
}
void Map::add_events_from_map_data(uint8_t floor, const void* data, size_t size) {
StringReader r(data, size);
phosg::StringReader r(data, size);
const auto& header = r.get<EventsSectionHeader>();
if (header.format != 0) {
throw runtime_error("events section format is not zero");
@@ -1525,7 +1525,7 @@ void Map::add_events_from_map_data(uint8_t floor, const void* data, size_t size)
vector<Map::DATSectionsForFloor> Map::collect_quest_map_data_sections(const void* data, size_t size) {
vector<DATSectionsForFloor> ret;
StringReader r(data, size);
phosg::StringReader r(data, size);
while (!r.eof()) {
size_t header_offset = r.where();
const auto& header = r.get<SectionHeader>();
@@ -1534,7 +1534,7 @@ vector<Map::DATSectionsForFloor> Map::collect_quest_map_data_sections(const void
break;
}
if (header.section_size < sizeof(header)) {
throw runtime_error(string_printf("quest layout has invalid section header at offset 0x%zX", r.where() - sizeof(header)));
throw runtime_error(phosg::string_printf("quest layout has invalid section header at offset 0x%zX", r.where() - sizeof(header)));
}
if (header.floor > 0x100) {
@@ -1593,7 +1593,7 @@ void Map::add_entities_from_quest_data(
std::shared_ptr<const RareEnemyRates> rare_rates) {
auto all_floor_sections = this->collect_quest_map_data_sections(data, size);
StringReader r(data, size);
phosg::StringReader r(data, size);
shared_ptr<DATParserRandomState> random_state;
for (size_t floor = 0; floor < all_floor_sections.size(); floor++) {
const auto& floor_sections = all_floor_sections[floor];
@@ -1713,7 +1713,7 @@ std::vector<Map::Event*> Map::get_events(uint8_t floor) {
template <typename EntryT>
static string disassemble_vector_file_t(const void* data, size_t size, size_t* entry_number, char type_ch) {
deque<string> ret;
StringReader r(data, size);
phosg::StringReader r(data, size);
size_t local_entry_number = 0;
if (!entry_number) {
@@ -1722,14 +1722,14 @@ static string disassemble_vector_file_t(const void* data, size_t size, size_t* e
while (r.remaining() >= sizeof(EntryT)) {
string o_str = r.get<EntryT>().str();
ret.emplace_back(string_printf("/* %c-%zX */ %s", type_ch, (*entry_number)++, o_str.c_str()));
ret.emplace_back(phosg::string_printf("/* %c-%zX */ %s", type_ch, (*entry_number)++, o_str.c_str()));
}
if (r.remaining()) {
ret.emplace_back("// Warning: section size is not a multiple of entry size");
size_t size = r.remaining();
ret.emplace_back(format_data(r.getv(size), size));
ret.emplace_back(phosg::format_data(r.getv(size), size));
}
return join(ret, "\n");
return phosg::join(ret, "\n");
}
string Map::disassemble_objects_data(const void* data, size_t size, size_t* object_number) {
@@ -1742,18 +1742,18 @@ string Map::disassemble_enemies_data(const void* data, size_t size, size_t* enem
string Map::disassemble_wave_events_data(const void* data, size_t size, uint8_t floor) {
deque<string> ret;
StringReader r(data, size);
phosg::StringReader r(data, size);
const auto& evt_header = r.get<EventsSectionHeader>();
if (evt_header.format == 0x65767432) { // 'evt2'
ret.emplace_back(".evt2_format"); // TODO
size_t size = r.remaining();
ret.emplace_back(format_data(r.getv(size), size));
ret.emplace_back(phosg::format_data(r.getv(size), size));
} else {
auto action_stream_r = r.sub(evt_header.action_stream_offset);
for (size_t z = 0; z < evt_header.entry_count; z++) {
const auto& entry = r.get<Event1Entry>();
ret.emplace_back(string_printf("/* W-%02hhX-%" PRIX32 " */ [Event1Entry flags=%04hX type=%04hX section=%04hX wave_number=%04hX delay=%" PRIu32 "]",
ret.emplace_back(phosg::string_printf("/* W-%02hhX-%" PRIX32 " */ [Event1Entry flags=%04hX type=%04hX section=%04hX wave_number=%04hX delay=%" PRIu32 "]",
floor,
entry.event_id.load(),
entry.flags.load(),
@@ -1767,103 +1767,103 @@ string Map::disassemble_wave_events_data(const void* data, size_t size, uint8_t
uint8_t opcode = ev_actions_r.get_u8();
switch (opcode) {
case 0x00:
ret.emplace_back(string_printf(" 00 nop"));
ret.emplace_back(phosg::string_printf(" 00 nop"));
break;
case 0x01:
ret.emplace_back(string_printf(" 01 stop"));
ret.emplace_back(phosg::string_printf(" 01 stop"));
should_continue = false;
break;
case 0x08: {
uint16_t section = ev_actions_r.get_u16l();
uint16_t group = ev_actions_r.get_u16l();
ret.emplace_back(string_printf(" 08 %04hX %04hX construct_objects section=%04hX group=%04hX",
ret.emplace_back(phosg::string_printf(" 08 %04hX %04hX construct_objects section=%04hX group=%04hX",
section, group, section, group));
break;
}
case 0x09: {
uint16_t section = ev_actions_r.get_u16l();
uint16_t wave_number = ev_actions_r.get_u16l();
ret.emplace_back(string_printf(" 09 %04hX %04hX construct_enemies section=%04hX wave_number=%04hX",
ret.emplace_back(phosg::string_printf(" 09 %04hX %04hX construct_enemies section=%04hX wave_number=%04hX",
section, wave_number, section, wave_number));
break;
}
case 0x0A: {
uint16_t id = ev_actions_r.get_u16l();
ret.emplace_back(string_printf(" 0A %04hX enable_switch_flag id=%04hX", id, id));
ret.emplace_back(phosg::string_printf(" 0A %04hX enable_switch_flag id=%04hX", id, id));
break;
}
case 0x0B: {
uint16_t id = ev_actions_r.get_u16l();
ret.emplace_back(string_printf(" 0B %04hX disable_switch_flag id=%04hX", id, id));
ret.emplace_back(phosg::string_printf(" 0B %04hX disable_switch_flag id=%04hX", id, id));
break;
}
case 0x0C: {
uint32_t event_id = ev_actions_r.get_u32l();
ret.emplace_back(string_printf(" 0C %08" PRIX32 " trigger_event event_id=%08" PRIX32, event_id, event_id));
ret.emplace_back(phosg::string_printf(" 0C %08" PRIX32 " trigger_event event_id=%08" PRIX32, event_id, event_id));
break;
}
case 0x0D: {
uint16_t section = ev_actions_r.get_u16l();
uint16_t wave_number = ev_actions_r.get_u16l();
ret.emplace_back(string_printf(" 0D %04hX %04hX construct_enemies_stop section=%04hX wave_number=%04hX",
ret.emplace_back(phosg::string_printf(" 0D %04hX %04hX construct_enemies_stop section=%04hX wave_number=%04hX",
section, wave_number, section, wave_number));
break;
}
default:
ret.emplace_back(string_printf(" %02hhX .invalid", opcode));
ret.emplace_back(phosg::string_printf(" %02hhX .invalid", opcode));
}
}
}
}
return join(ret, "\n");
return phosg::join(ret, "\n");
}
string Map::disassemble_quest_data(const void* data, size_t size) {
auto all_floor_sections = Map::collect_quest_map_data_sections(data, size);
deque<string> ret;
StringReader r(data, size);
phosg::StringReader r(data, size);
size_t object_number = 0;
size_t enemy_number = 0;
for (size_t floor = 0; floor < all_floor_sections.size(); floor++) {
const auto& floor_sections = all_floor_sections[floor];
if (floor_sections.objects != 0xFFFFFFFF) {
ret.emplace_back(string_printf(".objects %zu", floor));
ret.emplace_back(phosg::string_printf(".objects %zu", floor));
const auto& header = r.pget<SectionHeader>(floor_sections.objects);
size_t offset = floor_sections.objects + sizeof(SectionHeader);
ret.emplace_back(Map::disassemble_objects_data(r.pgetv(offset, header.data_size), header.data_size, &object_number));
}
if (floor_sections.enemies != 0xFFFFFFFF) {
ret.emplace_back(string_printf(".enemies %zu", floor));
ret.emplace_back(phosg::string_printf(".enemies %zu", floor));
const auto& header = r.pget<SectionHeader>(floor_sections.enemies);
size_t offset = floor_sections.enemies + sizeof(SectionHeader);
ret.emplace_back(Map::disassemble_enemies_data(r.pgetv(offset, header.data_size), header.data_size, &enemy_number));
}
if (floor_sections.wave_events != 0xFFFFFFFF) {
ret.emplace_back(string_printf(".wave_events %zu", floor));
ret.emplace_back(phosg::string_printf(".wave_events %zu", floor));
const auto& header = r.pget<SectionHeader>(floor_sections.wave_events);
size_t offset = floor_sections.wave_events + sizeof(SectionHeader);
ret.emplace_back(Map::disassemble_wave_events_data(r.pgetv(offset, header.data_size), header.data_size, floor));
}
if (floor_sections.random_enemy_locations != 0xFFFFFFFF) {
ret.emplace_back(string_printf(".random_enemy_locations %zu", floor));
ret.emplace_back(phosg::string_printf(".random_enemy_locations %zu", floor));
const auto& header = r.pget<SectionHeader>(floor_sections.random_enemy_locations);
size_t offset = floor_sections.random_enemy_locations + sizeof(SectionHeader);
auto sub_r = r.sub(offset, header.data_size);
ret.emplace_back(format_data(sub_r.getv(sub_r.remaining()), header.data_size, offset));
ret.emplace_back(phosg::format_data(sub_r.getv(sub_r.remaining()), header.data_size, offset));
}
if (floor_sections.random_enemy_definitions != 0xFFFFFFFF) {
ret.emplace_back(string_printf(".random_enemy_definitions %zu", floor));
ret.emplace_back(phosg::string_printf(".random_enemy_definitions %zu", floor));
const auto& header = r.pget<SectionHeader>(floor_sections.random_enemy_definitions);
size_t offset = floor_sections.random_enemy_definitions + sizeof(SectionHeader);
auto sub_r = r.sub(offset, header.data_size);
ret.emplace_back(format_data(sub_r.getv(sub_r.remaining()), header.data_size, offset));
ret.emplace_back(phosg::format_data(sub_r.getv(sub_r.remaining()), header.data_size, offset));
}
}
return join(ret, "\n") + "\n";
return phosg::join(ret, "\n") + "\n";
}
SetDataTableBase::SetDataTableBase(Version version) : version(version) {}
@@ -1925,21 +1925,19 @@ SetDataTable::SetDataTable(Version version, const string& data) : SetDataTableBa
}
}
template <bool IsBigEndian>
template <bool BE>
void SetDataTable::load_table_t(const string& data) {
using U32T = typename conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
StringReader r(data);
phosg::StringReader r(data);
struct Footer {
U32T table3_offset;
U32T table3_count; // In le_uint16_ts (so *2 for size in bytes)
U32T unknown_a3; // == 1
U32T unknown_a4; // == 0
U32T root_table_offset_offset;
U32T unknown_a6; // == 0
U32T unknown_a7; // == 0
U32T unknown_a8; // == 0
U32T<BE> table3_offset;
U32T<BE> table3_count; // In le_uint16_ts (so *2 for size in bytes)
U32T<BE> unknown_a3; // == 1
U32T<BE> unknown_a4; // == 0
U32T<BE> root_table_offset_offset;
U32T<BE> unknown_a6; // == 0
U32T<BE> unknown_a7; // == 0
U32T<BE> unknown_a8; // == 0
} __packed_ws__(Footer, 0x20);
if (r.size() < sizeof(Footer)) {
@@ -1947,23 +1945,23 @@ void SetDataTable::load_table_t(const string& data) {
}
auto& footer = r.pget<Footer>(r.size() - sizeof(Footer));
uint32_t root_table_offset = r.pget<U32T>(footer.root_table_offset_offset);
uint32_t root_table_offset = r.pget<U32T<BE>>(footer.root_table_offset_offset);
auto root_r = r.sub(root_table_offset, footer.root_table_offset_offset - root_table_offset);
while (!root_r.eof()) {
auto& var1_v = this->entries.emplace_back();
uint32_t var1_table_offset = root_r.template get<U32T>();
uint32_t var1_table_count = root_r.template get<U32T>();
uint32_t var1_table_offset = root_r.template get<U32T<BE>>();
uint32_t var1_table_count = root_r.template get<U32T<BE>>();
auto var1_r = r.sub(var1_table_offset, var1_table_count * 0x08);
while (!var1_r.eof()) {
auto& var2_v = var1_v.emplace_back();
uint32_t var2_table_offset = var1_r.get<U32T>();
uint32_t var2_table_count = var1_r.get<U32T>();
uint32_t var2_table_offset = var1_r.get<U32T<BE>>();
uint32_t var2_table_count = var1_r.get<U32T<BE>>();
auto var2_r = r.sub(var2_table_offset, var2_table_count * 0x0C);
while (!var2_r.eof()) {
auto& entry = var2_v.emplace_back();
entry.object_list_basename = r.pget_cstr(var2_r.get<U32T>());
entry.enemy_and_event_list_basename = r.pget_cstr(var2_r.get<U32T>());
entry.area_setup_filename = r.pget_cstr(var2_r.get<U32T>());
entry.object_list_basename = r.pget_cstr(var2_r.get<U32T<BE>>());
entry.enemy_and_event_list_basename = r.pget_cstr(var2_r.get<U32T<BE>>());
entry.area_setup_filename = r.pget_cstr(var2_r.get<U32T<BE>>());
}
}
}
@@ -2066,19 +2064,19 @@ string SetDataTable::map_filename_for_variation(
string SetDataTable::str() const {
vector<string> lines;
lines.emplace_back(string_printf("FL/V1/V2 => ----------------------OBJECT -----------------ENEMY+EVENT -----------------------SETUP\n"));
lines.emplace_back(phosg::string_printf("FL/V1/V2 => ----------------------OBJECT -----------------ENEMY+EVENT -----------------------SETUP\n"));
for (size_t a = 0; a < this->entries.size(); a++) {
const auto& v1_v = this->entries[a];
for (size_t v1 = 0; v1 < v1_v.size(); v1++) {
const auto& v2_v = v1_v[v1];
for (size_t v2 = 0; v2 < v2_v.size(); v2++) {
const auto& e = v2_v[v2];
lines.emplace_back(string_printf("%02zX/%02zX/%02zX => %28s %28s %28s\n",
lines.emplace_back(phosg::string_printf("%02zX/%02zX/%02zX => %28s %28s %28s\n",
a, v1, v2, e.object_list_basename.c_str(), e.enemy_and_event_list_basename.c_str(), e.area_setup_filename.c_str()));
}
}
}
return join(lines, "");
return phosg::join(lines, "");
}
struct AreaMapFileInfo {
@@ -2515,10 +2513,10 @@ vector<string> map_filenames_for_variation_deprecated(
string filename = "map_";
filename += a.name_token;
if (!a.variation1_values.empty()) {
filename += string_printf("_%02" PRIX32, a.variation1_values.at(var1));
filename += phosg::string_printf("_%02" PRIX32, a.variation1_values.at(var1));
}
if (!a.variation2_values.empty()) {
filename += string_printf("_%02" PRIX32, a.variation2_values.at(var2));
filename += phosg::string_printf("_%02" PRIX32, a.variation2_values.at(var2));
}
vector<string> ret;
+8 -8
View File
@@ -200,9 +200,9 @@ struct Map {
uint32_t kondrieu; // {SAINT_MILLION, SHAMBERTIN} -> KONDRIEU
RareEnemyRates(uint32_t enemy_rate, uint32_t boss_rate);
explicit RareEnemyRates(const JSON& json);
explicit RareEnemyRates(const phosg::JSON& json);
JSON json() const;
phosg::JSON json() const;
};
static const std::shared_ptr<const RareEnemyRates> NO_RARE_ENEMIES;
@@ -295,7 +295,7 @@ struct Map {
DATParserRandomState(uint32_t rare_seed);
size_t rand_int_biased(size_t min_v, size_t max_v);
uint32_t next_location_index();
void generate_shuffled_location_table(const Map::RandomEnemyLocationsHeader& header, StringReader r, uint16_t section);
void generate_shuffled_location_table(const Map::RandomEnemyLocationsHeader& header, phosg::StringReader r, uint16_t section);
};
Map(Version version, uint32_t lobby_id, uint32_t rare_seed, std::shared_ptr<PSOLFGEncryption> opt_rand_crypt);
@@ -327,9 +327,9 @@ struct Map {
uint8_t difficulty,
uint8_t event,
uint8_t floor,
StringReader wave_events_r,
StringReader random_enemy_locations_r,
StringReader random_enemy_definitions_r,
phosg::StringReader wave_events_r,
phosg::StringReader random_enemy_locations_r,
phosg::StringReader random_enemy_definitions_r,
std::shared_ptr<DATParserRandomState> random_state,
std::shared_ptr<const RareEnemyRates> rare_rates = DEFAULT_RARE_ENEMIES);
@@ -373,7 +373,7 @@ struct Map {
static std::string disassemble_wave_events_data(const void* data, size_t size, uint8_t floor = 0xFF);
static std::string disassemble_quest_data(const void* data, size_t size);
PrefixedLogger log;
phosg::PrefixedLogger log;
Version version;
uint32_t rare_seed;
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt;
@@ -438,7 +438,7 @@ public:
std::string str() const;
private:
template <bool IsBigEndian>
template <bool BE>
void load_table_t(const std::string& data);
// Indexes are [floor][variation1][variation2]
+6 -6
View File
@@ -19,8 +19,8 @@ using namespace std;
uint32_t resolve_address(const char* address) {
struct addrinfo* res0;
if (getaddrinfo(address, nullptr, nullptr, &res0)) {
auto e = string_for_error(errno);
throw runtime_error(string_printf(
auto e = phosg::string_for_error(errno);
throw runtime_error(phosg::string_printf(
"can\'t resolve hostname %s: %s", address, e.c_str()));
}
@@ -32,7 +32,7 @@ uint32_t resolve_address(const char* address) {
}
}
if (!res4) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"can\'t resolve hostname %s: no usable data", address));
}
@@ -43,8 +43,8 @@ uint32_t resolve_address(const char* address) {
map<string, uint32_t> get_local_addresses() {
struct ifaddrs* ifa_raw;
if (getifaddrs(&ifa_raw)) {
auto s = string_for_error(errno);
throw runtime_error(string_printf("failed to get interface addresses: %s", s.c_str()));
auto s = phosg::string_for_error(errno);
throw runtime_error(phosg::string_printf("failed to get interface addresses: %s", s.c_str()));
}
unique_ptr<struct ifaddrs, void (*)(struct ifaddrs*)> ifa(ifa_raw, freeifaddrs);
@@ -80,7 +80,7 @@ bool is_local_address(const sockaddr_storage& daddr) {
}
string string_for_address(uint32_t address) {
return string_printf("%hhu.%hhu.%hhu.%hhu",
return phosg::string_printf("%hhu.%hhu.%hhu.%hhu",
static_cast<uint8_t>(address >> 24), static_cast<uint8_t>(address >> 16),
static_cast<uint8_t>(address >> 8), static_cast<uint8_t>(address));
}
+10 -14
View File
@@ -37,44 +37,40 @@ uint32_t PSOLFGEncryption::next(bool advance) {
return ret;
}
template <bool IsBigEndian>
template <bool BE>
void PSOLFGEncryption::encrypt_t(void* vdata, size_t size, bool advance) {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
if (!advance && (size != 4)) {
throw logic_error("cannot peek-encrypt/decrypt with size > 4");
}
size_t uint32_count = size >> 2;
size_t extra_bytes = size & 3;
U32T* data = reinterpret_cast<U32T*>(vdata);
U32T<BE>* data = reinterpret_cast<U32T<BE>*>(vdata);
for (size_t x = 0; x < uint32_count; x++) {
data[x] ^= this->next(advance);
}
if (extra_bytes) {
U32T last = 0;
U32T<BE> last = 0;
memcpy(&last, &data[uint32_count], extra_bytes);
last ^= this->next(advance);
memcpy(&data[uint32_count], &last, extra_bytes);
}
}
template <bool IsBigEndian>
template <bool BE>
void PSOLFGEncryption::encrypt_minus_t(void* vdata, size_t size, bool advance) {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
if (!advance && (size != 4)) {
throw logic_error("cannot peek-encrypt/decrypt with size > 4");
}
size_t uint32_count = size >> 2;
size_t extra_bytes = size & 3;
U32T* data = reinterpret_cast<U32T*>(vdata);
U32T<BE>* data = reinterpret_cast<U32T<BE>*>(vdata);
for (size_t x = 0; x < uint32_count; x++) {
data[x] = this->next(advance) - data[x];
}
if (extra_bytes) {
U32T last = 0;
U32T<BE> last = 0;
memcpy(&last, &data[uint32_count], extra_bytes);
last = this->next(advance) - last;
memcpy(&data[uint32_count], &last, extra_bytes);
@@ -699,11 +695,11 @@ void PSOV2OrV3DetectorEncryption::encrypt(void* data, size_t size, bool advance)
bool v2_match = this->v2_matches.count(decrypted_v2);
bool v3_match = this->v3_matches.count(decrypted_v3);
if (!v2_match && !v3_match) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"unable to determine crypt version (input=%08" PRIX32 ", v2=%08" PRIX32 ", v3=%08" PRIX32 ")",
encrypted.load(), decrypted_v2.load(), decrypted_v3.load()));
} else if (v2_match && v3_match) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"ambiguous crypt version (v2=%08" PRIX32 ", v3=%08" PRIX32 ")",
decrypted_v2.load(), decrypted_v3.load()));
} else if (v2_match) {
@@ -881,9 +877,9 @@ uint32_t encrypt_challenge_time(uint16_t value) {
vector<uint8_t> available_bits({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
uint16_t mask = 0;
uint8_t num_one_bits = (random_object<uint8_t>() % 9) + 4; // Range [4, 12]
uint8_t num_one_bits = (phosg::random_object<uint8_t>() % 9) + 4; // Range [4, 12]
for (; num_one_bits; num_one_bits--) {
uint8_t index = random_object<uint8_t>() % available_bits.size();
uint8_t index = phosg::random_object<uint8_t>() % available_bits.size();
auto it = available_bits.begin() + index;
mask |= (1 << *it);
available_bits.erase(it);
+20 -24
View File
@@ -12,6 +12,7 @@
#include "Compression.hh"
#include "Text.hh"
#include "Types.hh"
class PSOEncryption {
public:
@@ -48,9 +49,9 @@ public:
void encrypt_big_endian_minus(void* data, size_t size, bool advance = true);
void encrypt_both_endian(void* le_data, void* be_data, size_t size, bool advance = true);
template <bool IsBigEndian>
template <bool BE>
void encrypt_t(void* data, size_t size, bool advance = true);
template <bool IsBigEndian>
template <bool BE>
void encrypt_minus_t(void* data, size_t size, bool advance = true);
uint32_t next(bool advance = true);
@@ -253,11 +254,10 @@ void decrypt_trivial_gci_data(void* data, size_t size, uint8_t basis);
uint32_t encrypt_challenge_time(uint16_t value);
uint16_t decrypt_challenge_time(uint32_t value);
template <bool IsBigEndian>
template <bool BE>
class ChallengeTimeT {
private:
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
U32T value;
U32T<BE> value;
public:
ChallengeTimeT() = default;
@@ -287,8 +287,8 @@ public:
this->value = ((v == 0) || (v == 0xFFFF)) ? 0 : encrypt_challenge_time(v);
}
operator ChallengeTimeT<!IsBigEndian>() const {
ChallengeTimeT<!IsBigEndian> ret;
operator ChallengeTimeT<!BE>() const {
ChallengeTimeT<!BE> ret;
ret.store_raw(this->value);
return ret;
}
@@ -305,19 +305,17 @@ struct DecryptedPR2 {
size_t decompressed_size;
};
template <bool IsBigEndian>
template <bool BE>
DecryptedPR2 decrypt_pr2_data(const std::string& data) {
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
if (data.size() < 8) {
throw std::runtime_error("not enough data for PR2 header");
}
StringReader r(data);
phosg::StringReader r(data);
DecryptedPR2 ret = {
.compressed_data = data.substr(8),
.decompressed_size = r.get<U32T>()};
PSOV2Encryption crypt(r.get<U32T>());
if (IsBigEndian) {
.decompressed_size = r.get<U32T<BE>>()};
PSOV2Encryption crypt(r.get<U32T<BE>>());
if (BE) {
crypt.encrypt_big_endian(ret.compressed_data.data(), ret.compressed_data.size());
} else {
crypt.decrypt(ret.compressed_data.data(), ret.compressed_data.size());
@@ -325,9 +323,9 @@ DecryptedPR2 decrypt_pr2_data(const std::string& data) {
return ret;
}
template <bool IsBigEndian>
template <bool BE>
std::string decrypt_and_decompress_pr2_data(const std::string& data) {
auto decrypted = decrypt_pr2_data<IsBigEndian>(data);
auto decrypted = decrypt_pr2_data<BE>(data);
std::string decompressed = prs_decompress(decrypted.compressed_data);
if (decompressed.size() != decrypted.decompressed_size) {
throw std::runtime_error("decompressed size does not match expected size");
@@ -335,18 +333,16 @@ std::string decrypt_and_decompress_pr2_data(const std::string& data) {
return decompressed;
}
template <bool IsBigEndian>
template <bool BE>
std::string encrypt_pr2_data(const std::string& data, size_t decompressed_size, uint32_t seed) {
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
StringWriter w;
w.put<U32T>(decompressed_size);
w.put<U32T>(seed);
phosg::StringWriter w;
w.put<U32T<BE>>(decompressed_size);
w.put<U32T<BE>>(seed);
w.write(data);
std::string ret = std::move(w.str());
PSOV2Encryption crypt(seed);
if (IsBigEndian) {
if (BE) {
crypt.encrypt_big_endian(ret.data() + 8, ret.size() - 8);
} else {
crypt.decrypt(ret.data() + 8, ret.size() - 8);
@@ -355,5 +351,5 @@ std::string encrypt_pr2_data(const std::string& data, size_t decompressed_size,
}
inline uint32_t random_from_optional_crypt(std::shared_ptr<PSOLFGEncryption> random_crypt) {
return random_crypt ? random_crypt->next() : random_object<uint32_t>();
return random_crypt ? random_crypt->next() : phosg::random_object<uint32_t>();
}
+17 -20
View File
@@ -5,33 +5,31 @@
using namespace std;
struct TObjectVTable {
be_uint32_t unused_a1;
be_uint32_t unused_a2;
be_uint32_t destroy;
be_uint32_t update;
be_uint32_t render;
be_uint32_t render_shadow;
phosg::be_uint32_t unused_a1;
phosg::be_uint32_t unused_a2;
phosg::be_uint32_t destroy;
phosg::be_uint32_t update;
phosg::be_uint32_t render;
phosg::be_uint32_t render_shadow;
} __packed_ws__(TObjectVTable, 0x18);
struct TObject {
be_uint32_t type_name_addr;
be_uint16_t flags;
phosg::be_uint32_t type_name_addr;
phosg::be_uint16_t flags;
parray<uint8_t, 2> unused;
be_uint32_t prev_sibling_addr;
be_uint32_t next_sibling_addr;
be_uint32_t parent_addr;
be_uint32_t children_head_addr;
be_uint32_t vtable_addr;
phosg::be_uint32_t prev_sibling_addr;
phosg::be_uint32_t next_sibling_addr;
phosg::be_uint32_t parent_addr;
phosg::be_uint32_t children_head_addr;
phosg::be_uint32_t vtable_addr;
} __packed_ws__(TObject, 0x1C);
PSOGCObjectGraph::PSOGCObjectGraph(
const string& memory_data, uint32_t root_address) {
StringReader r(memory_data);
PSOGCObjectGraph::PSOGCObjectGraph(const string& memory_data, uint32_t root_address) {
phosg::StringReader r(memory_data);
this->root = this->parse_object_memo(r, root_address);
}
shared_ptr<PSOGCObjectGraph::VTable> PSOGCObjectGraph::parse_vtable_memo(
StringReader& r, uint32_t addr) {
shared_ptr<PSOGCObjectGraph::VTable> PSOGCObjectGraph::parse_vtable_memo(phosg::StringReader& r, uint32_t addr) {
try {
return this->all_vtables.at(addr);
} catch (const out_of_range&) {
@@ -47,8 +45,7 @@ shared_ptr<PSOGCObjectGraph::VTable> PSOGCObjectGraph::parse_vtable_memo(
return ret;
}
shared_ptr<PSOGCObjectGraph::Object> PSOGCObjectGraph::parse_object_memo(
StringReader& r, uint32_t addr) {
shared_ptr<PSOGCObjectGraph::Object> PSOGCObjectGraph::parse_object_memo(phosg::StringReader& r, uint32_t addr) {
try {
return this->all_objects.at(addr);
} catch (const out_of_range&) {
+2 -2
View File
@@ -37,6 +37,6 @@ struct PSOGCObjectGraph {
std::unordered_map<uint32_t, std::shared_ptr<Object>> all_objects;
std::unordered_map<uint32_t, std::shared_ptr<VTable>> all_vtables;
std::shared_ptr<Object> parse_object_memo(StringReader& r, uint32_t addr);
std::shared_ptr<VTable> parse_vtable_memo(StringReader& r, uint32_t addr);
std::shared_ptr<Object> parse_object_memo(phosg::StringReader& r, uint32_t addr);
std::shared_ptr<VTable> parse_vtable_memo(phosg::StringReader& r, uint32_t addr);
};
+3 -3
View File
@@ -190,7 +190,7 @@ void PSOCommandHeader::set_flag(Version version, uint32_t flag) {
void check_size_v(size_t size, size_t min_size, size_t max_size) {
if (size < min_size) {
throw std::runtime_error(string_printf(
throw std::runtime_error(phosg::string_printf(
"command too small (expected at least 0x%zX bytes, received 0x%zX bytes)",
min_size, size));
}
@@ -198,7 +198,7 @@ void check_size_v(size_t size, size_t min_size, size_t max_size) {
max_size = min_size;
}
if (size > max_size) {
throw std::runtime_error(string_printf(
throw std::runtime_error(phosg::string_printf(
"command too large (expected at most 0x%zX bytes, received 0x%zX bytes)",
max_size, size));
}
@@ -210,7 +210,7 @@ std::string prepend_command_header(
uint16_t cmd,
uint32_t flag,
const std::string& data) {
StringWriter ret;
phosg::StringWriter ret;
switch (version) {
case Version::DC_NTE:
case Version::DC_V1_11_2000_PROTOTYPE:
+2 -2
View File
@@ -56,12 +56,12 @@ RetT& check_size_generic(
size_t min_size,
size_t max_size) {
if (size < min_size) {
throw std::runtime_error(string_printf(
throw std::runtime_error(phosg::string_printf(
"command too small (expected at least 0x%zX bytes, received 0x%zX bytes)",
min_size, size));
}
if (size > max_size) {
throw std::runtime_error(string_printf(
throw std::runtime_error(phosg::string_printf(
"command too large (expected at most 0x%zX bytes, received 0x%zX bytes)",
max_size, size));
}
+19 -19
View File
@@ -20,10 +20,10 @@ PatchFileIndex::File::File(PatchFileIndex* index)
std::shared_ptr<const std::string> PatchFileIndex::File::load_data() {
if (!this->loaded_data) {
string relative_path = join(this->path_directories, "/") + "/" + this->name;
string relative_path = phosg::join(this->path_directories, "/") + "/" + this->name;
string full_path = this->index->root_dir + "/" + relative_path;
patch_index_log.info("Loading data for %s", relative_path.c_str());
this->loaded_data = make_shared<string>(load_file(full_path));
this->loaded_data = make_shared<string>(phosg::load_file(full_path));
this->size = this->loaded_data->size();
}
return this->loaded_data;
@@ -33,49 +33,49 @@ PatchFileIndex::PatchFileIndex(const string& root_dir)
: root_dir(root_dir) {
string metadata_cache_filename = root_dir + "/.metadata-cache.json";
JSON metadata_cache_json;
phosg::JSON metadata_cache_json;
try {
string metadata_text = load_file(metadata_cache_filename);
metadata_cache_json = JSON::parse(metadata_text);
string metadata_text = phosg::load_file(metadata_cache_filename);
metadata_cache_json = phosg::JSON::parse(metadata_text);
patch_index_log.info("Loaded patch metadata cache from %s", metadata_cache_filename.c_str());
} catch (const exception& e) {
metadata_cache_json = JSON::dict();
metadata_cache_json = phosg::JSON::dict();
patch_index_log.warning("Cannot load patch metadata cache from %s: %s", metadata_cache_filename.c_str(), e.what());
}
// Assuming it's rare for patch files to change, we skip writing the metadata
// cache if no files were changed at all (which should usually be the case)
bool should_write_metadata_cache = false;
JSON new_metadata_cache_json = JSON::dict();
phosg::JSON new_metadata_cache_json = phosg::JSON::dict();
vector<string> path_directories;
function<void(const string&)> collect_dir = [&](const string& dir) -> void {
path_directories.emplace_back(dir);
string relative_dirs = join(path_directories, "/");
string relative_dirs = phosg::join(path_directories, "/");
string full_dir_path = root_dir + '/' + relative_dirs;
patch_index_log.info("Listing directory %s", full_dir_path.c_str());
for (const auto& item : list_directory(full_dir_path)) {
for (const auto& item : phosg::list_directory(full_dir_path)) {
// Skip invisible files (e.g. .DS_Store on macOS)
if (starts_with(item, ".")) {
if (phosg::starts_with(item, ".")) {
continue;
}
string relative_item_path = relative_dirs + '/' + item;
string full_item_path = root_dir + '/' + relative_item_path;
if (isdir(full_item_path)) {
if (phosg::isdir(full_item_path)) {
collect_dir(item);
} else if (isfile(full_item_path)) {
} else if (phosg::isfile(full_item_path)) {
auto st = stat(full_item_path);
auto st = phosg::stat(full_item_path);
auto f = make_shared<File>(this);
f->path_directories = path_directories;
f->name = item;
string compute_crc32s_message; // If not empty, should compute crc32s
JSON cache_item_json;
phosg::JSON cache_item_json;
try {
cache_item_json = metadata_cache_json.at(relative_item_path);
uint64_t cached_size = cache_item_json.get_int(0);
@@ -98,19 +98,19 @@ PatchFileIndex::PatchFileIndex(const string& root_dir)
if (!compute_crc32s_message.empty()) {
auto data = f->load_data(); // Sets f->size
f->crc32 = crc32(data->data(), f->size);
f->crc32 = phosg::crc32(data->data(), f->size);
for (size_t x = 0; x < data->size(); x += 0x4000) {
size_t chunk_bytes = min<size_t>(f->size - x, 0x4000);
f->chunk_crcs.emplace_back(::crc32(data->data() + x, chunk_bytes));
f->chunk_crcs.emplace_back(phosg::crc32(data->data() + x, chunk_bytes));
}
// File was modified or cache item was missing; make a new cache item
auto chunk_crcs_item = JSON::list();
auto chunk_crcs_item = phosg::JSON::list();
for (uint32_t chunk_crc : f->chunk_crcs) {
chunk_crcs_item.emplace_back(chunk_crc);
}
new_metadata_cache_json.emplace(
relative_item_path, JSON::list({f->size, st.st_mtime, f->crc32, std::move(chunk_crcs_item)}));
relative_item_path, phosg::JSON::list({f->size, st.st_mtime, f->crc32, std::move(chunk_crcs_item)}));
should_write_metadata_cache = true;
} else {
@@ -141,7 +141,7 @@ PatchFileIndex::PatchFileIndex(const string& root_dir)
if (should_write_metadata_cache) {
try {
save_file(metadata_cache_filename, new_metadata_cache_json.serialize());
phosg::save_file(metadata_cache_filename, new_metadata_cache_json.serialize());
patch_index_log.info("Saved patch metadata cache to %s", metadata_cache_filename.c_str());
} catch (const exception& e) {
patch_index_log.warning("Cannot save patch metadata cache to %s: %s", metadata_cache_filename.c_str(), e.what());
+17 -17
View File
@@ -37,8 +37,8 @@ PatchServer::Client::Client(
bool hide_data_from_logs)
: server(server),
id(next_id++),
log(string_printf("[C-%" PRIX64 "] ", this->id), client_log.min_level),
channel(bev, 0, version, 1, nullptr, nullptr, this, string_printf("C-%" PRIX64, this->id), TerminalFormat::FG_YELLOW, TerminalFormat::FG_GREEN),
log(phosg::string_printf("[C-%" PRIX64 "] ", this->id), client_log.min_level),
channel(bev, 0, version, 1, nullptr, nullptr, this, phosg::string_printf("C-%" PRIX64, this->id), phosg::TerminalFormat::FG_YELLOW, phosg::TerminalFormat::FG_GREEN),
idle_timeout_usecs(idle_timeout_usecs),
idle_timeout_event(
event_new(bufferevent_get_base(bev), -1, EV_TIMEOUT, &PatchServer::Client::dispatch_idle_timeout, this),
@@ -49,15 +49,15 @@ PatchServer::Client::Client(
// protocol is fully understood and data logs for patch clients are generally
// more annoying than helpful at this point.
if (hide_data_from_logs) {
this->channel.terminal_recv_color = TerminalFormat::END;
this->channel.terminal_send_color = TerminalFormat::END;
this->channel.terminal_recv_color = phosg::TerminalFormat::END;
this->channel.terminal_send_color = phosg::TerminalFormat::END;
}
this->log.info("Created");
}
void PatchServer::Client::reschedule_timeout_event() {
struct timeval idle_tv = usecs_to_timeval(this->idle_timeout_usecs);
struct timeval idle_tv = phosg::usecs_to_timeval(this->idle_timeout_usecs);
event_add(this->idle_timeout_event.get(), &idle_tv);
}
@@ -78,8 +78,8 @@ void PatchServer::Client::idle_timeout() {
}
void PatchServer::send_server_init(shared_ptr<Client> c) const {
uint32_t server_key = random_object<uint32_t>();
uint32_t client_key = random_object<uint32_t>();
uint32_t server_key = phosg::random_object<uint32_t>();
uint32_t client_key = phosg::random_object<uint32_t>();
S_ServerInit_Patch_02 cmd;
cmd.copyright.encode("Patch Server. Copyright SonicTeam, LTD. 2001");
@@ -92,7 +92,7 @@ void PatchServer::send_server_init(shared_ptr<Client> c) const {
}
void PatchServer::send_message_box(shared_ptr<Client> c, const string& text) const {
StringWriter w;
phosg::StringWriter w;
try {
if (c->version() == Version::PC_PATCH) {
w.write(tt_encode_marked_optional(text, c->channel.language, true));
@@ -102,7 +102,7 @@ void PatchServer::send_message_box(shared_ptr<Client> c, const string& text) con
throw logic_error("non-patch client on patch server");
}
} catch (const runtime_error& e) {
log_warning("Failed to encode message for patch message box command: %s", e.what());
phosg::log_warning("Failed to encode message for patch message box command: %s", e.what());
return;
}
w.put_u16(0);
@@ -168,13 +168,13 @@ void PatchServer::on_04(shared_ptr<Client> c, string& data) {
this->config->account_index->from_bb_credentials(username, &password, false);
} catch (const AccountIndex::incorrect_password& e) {
this->send_message_box(c, string_printf("Login failed: %s", e.what()));
this->send_message_box(c, phosg::string_printf("Login failed: %s", e.what()));
this->disconnect_client(c);
return;
} catch (const AccountIndex::missing_account& e) {
if (!this->config->allow_unregistered_users) {
this->send_message_box(c, string_printf("Login failed: %s", e.what()));
this->send_message_box(c, phosg::string_printf("Login failed: %s", e.what()));
this->disconnect_client(c);
return;
}
@@ -184,7 +184,7 @@ void PatchServer::on_04(shared_ptr<Client> c, string& data) {
try {
this->config->account_index->from_bb_credentials(username, nullptr, false);
} catch (const AccountIndex::missing_account& e) {
this->send_message_box(c, string_printf("Login failed: %s", e.what()));
this->send_message_box(c, phosg::string_printf("Login failed: %s", e.what()));
this->disconnect_client(c);
return;
}
@@ -300,7 +300,7 @@ void PatchServer::disconnect_client(shared_ptr<Client> c) {
}
void PatchServer::enqueue_destroy_clients() {
auto tv = usecs_to_timeval(0);
auto tv = phosg::usecs_to_timeval(0);
event_add(this->destroy_clients_ev.get(), &tv);
}
@@ -321,7 +321,7 @@ void PatchServer::dispatch_on_listen_error(
void PatchServer::on_listen_accept(struct evconnlistener* listener, evutil_socket_t fd, struct sockaddr*, int) {
struct sockaddr_storage remote_addr;
get_socket_addresses(fd, nullptr, &remote_addr);
phosg::get_socket_addresses(fd, nullptr, &remote_addr);
if (this->config->banned_ipv4_ranges->check(remote_addr)) {
close(fd);
return;
@@ -430,7 +430,7 @@ void PatchServer::wait_for_stop() {
}
void PatchServer::listen(const std::string& addr_str, const string& socket_path, Version version) {
int fd = ::listen(socket_path, 0, SOMAXCONN);
int fd = phosg::listen(socket_path, 0, SOMAXCONN);
server_log.info("Listening on Unix socket %s on fd %d as %s", socket_path.c_str(), fd, addr_str.c_str());
this->add_socket(addr_str, fd, version);
}
@@ -439,8 +439,8 @@ void PatchServer::listen(const std::string& addr_str, const string& addr, int po
if (port == 0) {
this->listen(addr_str, addr, version);
} else {
int fd = ::listen(addr, port, SOMAXCONN);
string netloc_str = render_netloc(addr, port);
int fd = phosg::listen(addr, port, SOMAXCONN);
string netloc_str = phosg::render_netloc(addr, port);
server_log.info("Listening on TCP interface %s on fd %d as %s", netloc_str.c_str(), fd, addr_str.c_str());
this->add_socket(addr_str, fd, version);
}
+1 -1
View File
@@ -50,7 +50,7 @@ private:
public:
std::weak_ptr<PatchServer> server;
uint64_t id;
PrefixedLogger log;
phosg::PrefixedLogger log;
Channel channel;
std::vector<PatchFileChecksumRequest> patch_file_checksum_requests;
+1 -1
View File
@@ -24,7 +24,7 @@ PlayerFilesManager::PlayerFilesManager(std::shared_ptr<struct event_base> base)
clear_expired_files_event(
event_new(this->base.get(), -1, EV_TIMEOUT | EV_PERSIST, &PlayerFilesManager::clear_expired_files, this),
event_free) {
auto tv = usecs_to_timeval(30 * 1000 * 1000);
auto tv = phosg::usecs_to_timeval(30 * 1000 * 1000);
event_add(this->clear_expired_files_event.get(), &tv);
}
+22 -28
View File
@@ -45,16 +45,14 @@ class ItemParameterTable;
// items[13].extension_data2 through items[15].extension_data2:
// Unknown. These are not an array, but do appear to be related.
template <bool IsBigEndian>
template <bool BE>
struct PlayerInventoryItemT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 00 */ uint8_t present = 0;
/* 01 */ uint8_t unknown_a1 = 0;
// See note above about these fields
/* 02 */ uint8_t extension_data1 = 0;
/* 03 */ uint8_t extension_data2 = 0;
/* 04 */ U32T flags = 0; // 8 = equipped
/* 04 */ U32T<BE> flags = 0; // 8 = equipped
/* 08 */ ItemData data;
/* 1C */
@@ -68,15 +66,15 @@ struct PlayerInventoryItemT {
flags(equipped ? 8 : 0),
data(item) {}
operator PlayerInventoryItemT<!IsBigEndian>() const {
PlayerInventoryItemT<!IsBigEndian> ret;
operator PlayerInventoryItemT<!BE>() const {
PlayerInventoryItemT<!BE> ret;
ret.present = this->present;
ret.unknown_a1 = this->unknown_a1;
ret.extension_data1 = this->extension_data1;
ret.extension_data2 = this->extension_data2;
ret.flags = this->flags.load();
ret.data = this->data;
ret.data.id.store_raw(bswap32(ret.data.id.load_raw()));
ret.data.id.store_raw(phosg::bswap32(ret.data.id.load_raw()));
return ret;
}
} __packed__;
@@ -85,21 +83,19 @@ using PlayerInventoryItemBE = PlayerInventoryItemT<true>;
check_struct_size(PlayerInventoryItem, 0x1C);
check_struct_size(PlayerInventoryItemBE, 0x1C);
template <bool IsBigEndian>
template <bool BE>
struct PlayerBankItemT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
/* 00 */ ItemData data;
/* 14 */ U16T amount = 0;
/* 16 */ U16T present = 0;
/* 14 */ U16T<BE> amount = 0;
/* 16 */ U16T<BE> present = 0;
/* 18 */
inline bool operator<(const PlayerBankItemT<IsBigEndian>& other) const {
inline bool operator<(const PlayerBankItemT<BE>& other) const {
return this->data < other.data;
}
operator PlayerBankItemT<!IsBigEndian>() const {
PlayerBankItemT<!IsBigEndian> ret;
operator PlayerBankItemT<!BE>() const {
PlayerBankItemT<!BE> ret;
ret.data = this->data;
ret.amount = this->amount.load();
ret.present = this->present.load();
@@ -111,13 +107,13 @@ using PlayerBankItemBE = PlayerBankItemT<true>;
check_struct_size(PlayerBankItem, 0x18);
check_struct_size(PlayerBankItemBE, 0x18);
template <bool IsBigEndian>
template <bool BE>
struct PlayerInventoryT {
/* 0000 */ uint8_t num_items = 0;
/* 0001 */ uint8_t hp_from_materials = 0;
/* 0002 */ uint8_t tp_from_materials = 0;
/* 0003 */ uint8_t language = 0;
/* 0004 */ parray<PlayerInventoryItemT<IsBigEndian>, 30> items;
/* 0004 */ parray<PlayerInventoryItemT<BE>, 30> items;
/* 034C */
size_t find_item(uint32_t item_id) const {
@@ -287,8 +283,8 @@ struct PlayerInventoryT {
}
}
operator PlayerInventoryT<!IsBigEndian>() const {
PlayerInventoryT<!IsBigEndian> ret;
operator PlayerInventoryT<!BE>() const {
PlayerInventoryT<!BE> ret;
ret.num_items = this->num_items;
ret.hp_from_materials = this->hp_from_materials;
ret.tp_from_materials = this->tp_from_materials;
@@ -302,13 +298,11 @@ using PlayerInventoryBE = PlayerInventoryT<true>;
check_struct_size(PlayerInventory, 0x34C);
check_struct_size(PlayerInventoryBE, 0x34C);
template <size_t SlotCount, bool IsBigEndian>
template <size_t SlotCount, bool BE>
struct PlayerBankT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 0000 */ U32T num_items = 0;
/* 0004 */ U32T meseta = 0;
/* 0008 */ parray<PlayerBankItemT<IsBigEndian>, SlotCount> items;
/* 0000 */ U32T<BE> num_items = 0;
/* 0004 */ U32T<BE> meseta = 0;
/* 0008 */ parray<PlayerBankItemT<BE>, SlotCount> items;
/* 05A8 for 60 items (v1/v2), 12C8 for 200 items (v3/v4) */
void add_item(const ItemData& item, const ItemData::StackLimits& limits) {
@@ -408,9 +402,9 @@ struct PlayerBankT {
}
}
template <size_t DestSlotCount, bool DestIsBigEndian>
operator PlayerBankT<DestSlotCount, DestIsBigEndian>() const {
PlayerBankT<DestSlotCount, DestIsBigEndian> ret;
template <size_t DestSlotCount, bool DestBE>
operator PlayerBankT<DestSlotCount, DestBE>() const {
PlayerBankT<DestSlotCount, DestBE> ret;
ret.num_items = std::min<size_t>(ret.items.size(), this->num_items.load());
ret.meseta = this->meseta.load();
for (size_t z = 0; z < std::min<size_t>(ret.items.size(), this->items.size()); z++) {
+21 -21
View File
@@ -324,8 +324,8 @@ QuestFlagsV1::operator QuestFlags() const {
return ret;
}
BattleRules::BattleRules(const JSON& json) {
static const JSON empty_list = JSON::list();
BattleRules::BattleRules(const phosg::JSON& json) {
static const phosg::JSON empty_list = phosg::JSON::list();
this->tech_disk_mode = json.get_enum("TechDiskMode", this->tech_disk_mode);
this->weapon_and_armor_mode = json.get_enum("WeaponAndArmorMode", this->weapon_and_armor_mode);
@@ -340,7 +340,7 @@ BattleRules::BattleRules(const JSON& json) {
this->hide_target_reticle = json.get_int("HideTargetReticle", this->hide_target_reticle);
this->meseta_mode = json.get_enum("MesetaMode", this->meseta_mode);
this->death_level_up = json.get_int("DeathLevelUp", this->death_level_up);
const JSON& trap_counts_json = json.get("TrapCounts", empty_list);
const phosg::JSON& trap_counts_json = json.get("TrapCounts", empty_list);
for (size_t z = 0; z < trap_counts_json.size(); z++) {
this->trap_counts[z] = trap_counts_json.at(z).as_int();
}
@@ -355,8 +355,8 @@ BattleRules::BattleRules(const JSON& json) {
this->box_drop_area = json.get_int("BoxDropArea", this->box_drop_area);
}
JSON BattleRules::json() const {
return JSON::dict({
phosg::JSON BattleRules::json() const {
return phosg::JSON::dict({
{"TechDiskMode", this->tech_disk_mode},
{"WeaponAndArmorMode", this->weapon_and_armor_mode},
{"MagMode", this->mag_mode},
@@ -370,7 +370,7 @@ JSON BattleRules::json() const {
{"HideTargetReticle", this->hide_target_reticle},
{"MesetaMode", this->meseta_mode},
{"DeathLevelUp", this->death_level_up},
{"TrapCounts", JSON::list({this->trap_counts[0], this->trap_counts[1], this->trap_counts[2], this->trap_counts[3]})},
{"TrapCounts", phosg::JSON::list({this->trap_counts[0], this->trap_counts[1], this->trap_counts[2], this->trap_counts[3]})},
{"EnableSonar", this->enable_sonar},
{"SonarCount", this->sonar_count},
{"ForbidScapeDolls", this->forbid_scape_dolls},
@@ -384,7 +384,7 @@ JSON BattleRules::json() const {
}
template <>
const char* name_for_enum<BattleRules::TechDiskMode>(BattleRules::TechDiskMode v) {
const char* phosg::name_for_enum<BattleRules::TechDiskMode>(BattleRules::TechDiskMode v) {
switch (v) {
case BattleRules::TechDiskMode::ALLOW:
return "ALLOW";
@@ -397,7 +397,7 @@ const char* name_for_enum<BattleRules::TechDiskMode>(BattleRules::TechDiskMode v
}
}
template <>
BattleRules::TechDiskMode enum_for_name<BattleRules::TechDiskMode>(const char* name) {
BattleRules::TechDiskMode phosg::enum_for_name<BattleRules::TechDiskMode>(const char* name) {
if (!strcmp(name, "ALLOW")) {
return BattleRules::TechDiskMode::ALLOW;
} else if (!strcmp(name, "FORBID_ALL")) {
@@ -410,7 +410,7 @@ BattleRules::TechDiskMode enum_for_name<BattleRules::TechDiskMode>(const char* n
}
template <>
const char* name_for_enum<BattleRules::WeaponAndArmorMode>(BattleRules::WeaponAndArmorMode v) {
const char* phosg::name_for_enum<BattleRules::WeaponAndArmorMode>(BattleRules::WeaponAndArmorMode v) {
switch (v) {
case BattleRules::WeaponAndArmorMode::ALLOW:
return "ALLOW";
@@ -425,7 +425,7 @@ const char* name_for_enum<BattleRules::WeaponAndArmorMode>(BattleRules::WeaponAn
}
}
template <>
BattleRules::WeaponAndArmorMode enum_for_name<BattleRules::WeaponAndArmorMode>(const char* name) {
BattleRules::WeaponAndArmorMode phosg::enum_for_name<BattleRules::WeaponAndArmorMode>(const char* name) {
if (!strcmp(name, "ALLOW")) {
return BattleRules::WeaponAndArmorMode::ALLOW;
} else if (!strcmp(name, "CLEAR_AND_ALLOW")) {
@@ -440,7 +440,7 @@ BattleRules::WeaponAndArmorMode enum_for_name<BattleRules::WeaponAndArmorMode>(c
}
template <>
const char* name_for_enum<BattleRules::MagMode>(BattleRules::MagMode v) {
const char* phosg::name_for_enum<BattleRules::MagMode>(BattleRules::MagMode v) {
switch (v) {
case BattleRules::MagMode::ALLOW:
return "ALLOW";
@@ -451,7 +451,7 @@ const char* name_for_enum<BattleRules::MagMode>(BattleRules::MagMode v) {
}
}
template <>
BattleRules::MagMode enum_for_name<BattleRules::MagMode>(const char* name) {
BattleRules::MagMode phosg::enum_for_name<BattleRules::MagMode>(const char* name) {
if (!strcmp(name, "ALLOW")) {
return BattleRules::MagMode::ALLOW;
} else if (!strcmp(name, "FORBID_ALL")) {
@@ -462,7 +462,7 @@ BattleRules::MagMode enum_for_name<BattleRules::MagMode>(const char* name) {
}
template <>
const char* name_for_enum<BattleRules::ToolMode>(BattleRules::ToolMode v) {
const char* phosg::name_for_enum<BattleRules::ToolMode>(BattleRules::ToolMode v) {
switch (v) {
case BattleRules::ToolMode::ALLOW:
return "ALLOW";
@@ -475,7 +475,7 @@ const char* name_for_enum<BattleRules::ToolMode>(BattleRules::ToolMode v) {
}
}
template <>
BattleRules::ToolMode enum_for_name<BattleRules::ToolMode>(const char* name) {
BattleRules::ToolMode phosg::enum_for_name<BattleRules::ToolMode>(const char* name) {
if (!strcmp(name, "ALLOW")) {
return BattleRules::ToolMode::ALLOW;
} else if (!strcmp(name, "CLEAR_AND_ALLOW")) {
@@ -488,7 +488,7 @@ BattleRules::ToolMode enum_for_name<BattleRules::ToolMode>(const char* name) {
}
template <>
const char* name_for_enum<BattleRules::TrapMode>(BattleRules::TrapMode v) {
const char* phosg::name_for_enum<BattleRules::TrapMode>(BattleRules::TrapMode v) {
switch (v) {
case BattleRules::TrapMode::DEFAULT:
return "DEFAULT";
@@ -499,7 +499,7 @@ const char* name_for_enum<BattleRules::TrapMode>(BattleRules::TrapMode v) {
}
}
template <>
BattleRules::TrapMode enum_for_name<BattleRules::TrapMode>(const char* name) {
BattleRules::TrapMode phosg::enum_for_name<BattleRules::TrapMode>(const char* name) {
if (!strcmp(name, "DEFAULT")) {
return BattleRules::TrapMode::DEFAULT;
} else if (!strcmp(name, "ALL_PLAYERS")) {
@@ -510,7 +510,7 @@ BattleRules::TrapMode enum_for_name<BattleRules::TrapMode>(const char* name) {
}
template <>
const char* name_for_enum<BattleRules::MesetaMode>(BattleRules::MesetaMode v) {
const char* phosg::name_for_enum<BattleRules::MesetaMode>(BattleRules::MesetaMode v) {
switch (v) {
case BattleRules::MesetaMode::ALLOW:
return "ALLOW";
@@ -523,7 +523,7 @@ const char* name_for_enum<BattleRules::MesetaMode>(BattleRules::MesetaMode v) {
}
}
template <>
BattleRules::MesetaMode enum_for_name<BattleRules::MesetaMode>(const char* name) {
BattleRules::MesetaMode phosg::enum_for_name<BattleRules::MesetaMode>(const char* name) {
if (!strcmp(name, "ALLOW")) {
return BattleRules::MesetaMode::ALLOW;
} else if (!strcmp(name, "FORBID_ALL")) {
@@ -536,7 +536,7 @@ BattleRules::MesetaMode enum_for_name<BattleRules::MesetaMode>(const char* name)
}
template <>
const char* name_for_enum<BattleRules::RespawnMode>(BattleRules::RespawnMode v) {
const char* phosg::name_for_enum<BattleRules::RespawnMode>(BattleRules::RespawnMode v) {
switch (v) {
case BattleRules::RespawnMode::ALLOW:
return "ALLOW";
@@ -549,7 +549,7 @@ const char* name_for_enum<BattleRules::RespawnMode>(BattleRules::RespawnMode v)
}
}
template <>
BattleRules::RespawnMode enum_for_name<BattleRules::RespawnMode>(const char* name) {
BattleRules::RespawnMode phosg::enum_for_name<BattleRules::RespawnMode>(const char* name) {
if (!strcmp(name, "ALLOW")) {
return BattleRules::RespawnMode::ALLOW;
} else if (!strcmp(name, "FORBID")) {
@@ -709,7 +709,7 @@ void RecentSwitchFlags::add(uint16_t flag_num) {
}
string RecentSwitchFlags::enable_commands(uint8_t floor) const {
StringWriter w;
phosg::StringWriter w;
uint64_t flag_nums = this->flag_nums;
for (size_t z = 0; z < 4; z++) {
uint16_t flag_num = flag_nums;
+74 -91
View File
@@ -25,15 +25,11 @@ class ItemParameterTable;
struct PlayerDispDataBB;
template <bool IsBigEndian>
template <bool BE>
struct PlayerVisualConfigT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
/* 00 */ pstring<TextEncoding::ASCII, 0x10> name;
/* 10 */ parray<uint8_t, 8> unknown_a2;
/* 18 */ U32T name_color = 0xFFFFFFFF; // ARGB
/* 18 */ U32T<BE> name_color = 0xFFFFFFFF; // ARGB
/* 1C */ uint8_t extra_model = 0;
/* 1D */ parray<uint8_t, 0x0F> unused;
// See compute_name_color_checksum for details on how this is computed. If the
@@ -41,7 +37,7 @@ struct PlayerVisualConfigT {
// default color instead. This field is ignored on GC; on BB (and presumably
// Xbox), if this has a nonzero value, the "Change Name" option appears in the
// character selection menu.
/* 2C */ U32T name_color_checksum = 0;
/* 2C */ U32T<BE> name_color_checksum = 0;
/* 30 */ uint8_t section_id = 0;
/* 31 */ uint8_t char_class = 0;
// validation_flags specifies that some parts of this structure are not valid
@@ -57,22 +53,22 @@ struct PlayerVisualConfigT {
// F = force, R = ranger, H = hunter
// A = android, N = newman, M = human
// f = female, m = male
/* 34 */ U32T class_flags = 0;
/* 38 */ U16T costume = 0;
/* 3A */ U16T skin = 0;
/* 3C */ U16T face = 0;
/* 3E */ U16T head = 0;
/* 40 */ U16T hair = 0;
/* 42 */ U16T hair_r = 0;
/* 44 */ U16T hair_g = 0;
/* 46 */ U16T hair_b = 0;
/* 48 */ F32T proportion_x = 0.0;
/* 4C */ F32T proportion_y = 0.0;
/* 34 */ U32T<BE> class_flags = 0;
/* 38 */ U16T<BE> costume = 0;
/* 3A */ U16T<BE> skin = 0;
/* 3C */ U16T<BE> face = 0;
/* 3E */ U16T<BE> head = 0;
/* 40 */ U16T<BE> hair = 0;
/* 42 */ U16T<BE> hair_r = 0;
/* 44 */ U16T<BE> hair_g = 0;
/* 46 */ U16T<BE> hair_b = 0;
/* 48 */ F32T<BE> proportion_x = 0.0;
/* 4C */ F32T<BE> proportion_y = 0.0;
/* 50 */
static uint32_t compute_name_color_checksum(uint32_t name_color) {
uint8_t x = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t y = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t x = (phosg::random_object<uint32_t>() % 0xFF) + 1;
uint8_t y = (phosg::random_object<uint32_t>() % 0xFF) + 1;
// name_color (ARGB) = ABCDEFGHabcdefghIJKLMNOPijklmnop
// name_color_checksum = 000000000ijklmabcdeIJKLM00000000 ^ xxxxxxxxyyyyyyyyxxxxxxxxyyyyyyyy
uint32_t xbrgx95558 = ((name_color << 15) & 0x007C0000) | ((name_color >> 6) & 0x0003E000) | ((name_color >> 3) & 0x00001F00);
@@ -208,8 +204,8 @@ struct PlayerVisualConfigT {
this->name.clear_after_bytes(0x0C);
}
operator PlayerVisualConfigT<!IsBigEndian>() const {
PlayerVisualConfigT<!IsBigEndian> ret;
operator PlayerVisualConfigT<!BE>() const {
PlayerVisualConfigT<!BE> ret;
ret.name = this->name;
ret.unknown_a2 = this->unknown_a2;
ret.name_color = this->name_color.load();
@@ -239,10 +235,10 @@ using PlayerVisualConfigBE = PlayerVisualConfigT<true>;
check_struct_size(PlayerVisualConfig, 0x50);
check_struct_size(PlayerVisualConfigBE, 0x50);
template <bool IsBigEndian>
template <bool BE>
struct PlayerDispDataDCPCV3T {
/* 00 */ PlayerStatsT<IsBigEndian> stats;
/* 24 */ PlayerVisualConfigT<IsBigEndian> visual;
/* 00 */ PlayerStatsT<BE> stats;
/* 24 */ PlayerVisualConfigT<BE> visual;
/* 74 */ parray<uint8_t, 0x48> config;
/* BC */ parray<uint8_t, 0x14> technique_levels_v1;
/* D0 */
@@ -283,9 +279,9 @@ struct PlayerDispDataBB {
this->name.clear_after_bytes(0x18); // 12 characters
}
template <bool IsBigEndian>
PlayerDispDataDCPCV3T<IsBigEndian> to_dcpcv3(uint8_t to_language, uint8_t from_language) const {
PlayerDispDataDCPCV3T<IsBigEndian> ret;
template <bool BE>
PlayerDispDataDCPCV3T<BE> to_dcpcv3(uint8_t to_language, uint8_t from_language) const {
PlayerDispDataDCPCV3T<BE> ret;
ret.stats = this->stats;
ret.visual = this->visual;
std::string decoded_name = this->name.decode(from_language);
@@ -299,8 +295,8 @@ struct PlayerDispDataBB {
void apply_dressing_room(const PlayerDispDataBBPreview&);
} __packed_ws__(PlayerDispDataBB, 0x190);
template <bool IsBigEndian>
PlayerDispDataBB PlayerDispDataDCPCV3T<IsBigEndian>::to_bb(uint8_t to_language, uint8_t from_language) const {
template <bool BE>
PlayerDispDataBB PlayerDispDataDCPCV3T<BE>::to_bb(uint8_t to_language, uint8_t from_language) const {
PlayerDispDataBB bb;
bb.stats = this->stats;
bb.visual = this->visual;
@@ -371,13 +367,11 @@ struct GuildCardPC {
// 0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
// 00A0 | 00 00 00 00 00 00 00 00 01 00 06 00 |
template <bool IsBigEndian, size_t DescriptionLength>
template <bool BE, size_t DescriptionLength>
struct GuildCardGCT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* NTE:Final */
/* 00:00 */ U32T player_tag = 0x00010000;
/* 04:04 */ U32T guild_card_number = 0;
/* 00:00 */ U32T<BE> player_tag = 0x00010000;
/* 04:04 */ U32T<BE> guild_card_number = 0;
/* 08:08 */ pstring<TextEncoding::ASCII, 0x18> name;
/* 20:20 */ pstring<TextEncoding::MARKED, DescriptionLength> description;
/* 8C:8C */ uint8_t present = 0;
@@ -429,9 +423,9 @@ struct GuildCardBB {
operator GuildCardDCNTE() const;
operator GuildCardDC() const;
operator GuildCardPC() const;
template <bool IsBigEndian, size_t DescriptionLength>
operator GuildCardGCT<IsBigEndian, DescriptionLength>() const {
GuildCardGCT<IsBigEndian, DescriptionLength> ret;
template <bool BE, size_t DescriptionLength>
operator GuildCardGCT<BE, DescriptionLength>() const {
GuildCardGCT<BE, DescriptionLength> ret;
ret.player_tag = 0x00010000;
ret.guild_card_number = this->guild_card_number.load();
ret.name.encode(this->name.decode(this->language), this->language);
@@ -445,8 +439,8 @@ struct GuildCardBB {
operator GuildCardXB() const;
} __packed_ws__(GuildCardBB, 0x108);
template <bool IsBigEndian, size_t DescriptionLength>
GuildCardGCT<IsBigEndian, DescriptionLength>::operator GuildCardBB() const {
template <bool BE, size_t DescriptionLength>
GuildCardGCT<BE, DescriptionLength>::operator GuildCardBB() const {
GuildCardBB ret;
ret.guild_card_number = this->guild_card_number.load();
ret.name.encode(this->name.decode(this->language), this->language);
@@ -524,14 +518,13 @@ struct PlayerLobbyDataBB {
void clear();
} __packed_ws__(PlayerLobbyDataBB, 0x44);
template <bool IsBigEndian>
template <bool BE>
struct ChallengeAwardStateT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
U32T rank_award_flags = 0;
ChallengeTimeT<IsBigEndian> maximum_rank;
U32T<BE> rank_award_flags = 0;
ChallengeTimeT<BE> maximum_rank;
operator ChallengeAwardStateT<!IsBigEndian>() const {
ChallengeAwardStateT<!IsBigEndian> ret;
operator ChallengeAwardStateT<!BE>() const {
ChallengeAwardStateT<!BE> ret;
ret.rank_award_flags = this->rank_award_flags.load();
ret.maximum_rank = this->maximum_rank;
return ret;
@@ -575,38 +568,34 @@ using PlayerRecordsChallengePC = PlayerRecordsChallengeDCPCT<TextEncoding::UTF16
check_struct_size(PlayerRecordsChallengeDC, 0xA0);
check_struct_size(PlayerRecordsChallengePC, 0xD8);
template <bool IsBigEndian>
template <bool BE>
struct PlayerRecordsChallengeV3T {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
using F32T = typename std::conditional<IsBigEndian, be_float, le_float>::type;
// Offsets are (1) relative to start of C5 entry, and (2) relative to start
// of save file structure
struct Stats {
/* 00:1C */ U16T title_color = 0x7FFF; // XRGB1555
/* 00:1C */ U16T<BE> title_color = 0x7FFF; // XRGB1555
/* 02:1E */ parray<uint8_t, 2> unknown_u0;
/* 04:20 */ parray<ChallengeTimeT<IsBigEndian>, 9> times_ep1_online;
/* 28:44 */ parray<ChallengeTimeT<IsBigEndian>, 5> times_ep2_online;
/* 3C:58 */ parray<ChallengeTimeT<IsBigEndian>, 9> times_ep1_offline;
/* 04:20 */ parray<ChallengeTimeT<BE>, 9> times_ep1_online;
/* 28:44 */ parray<ChallengeTimeT<BE>, 5> times_ep2_online;
/* 3C:58 */ parray<ChallengeTimeT<BE>, 9> times_ep1_offline;
/* 60:7C */ uint8_t grave_is_ep2 = 0;
/* 61:7D */ uint8_t grave_stage_num = 0;
/* 62:7E */ uint8_t grave_floor = 0;
/* 63:7F */ uint8_t unknown_g0 = 0;
/* 64:80 */ U16T grave_deaths = 0;
/* 64:80 */ U16T<BE> grave_deaths = 0;
/* 66:82 */ parray<uint8_t, 2> unknown_u4;
/* 68:84 */ U32T grave_time = 0; // Encoded as in PlayerRecordsChallengeDCPC
/* 6C:88 */ U32T grave_defeated_by_enemy_rt_index = 0;
/* 70:8C */ F32T grave_x = 0.0f;
/* 74:90 */ F32T grave_y = 0.0f;
/* 78:94 */ F32T grave_z = 0.0f;
/* 68:84 */ U32T<BE> grave_time = 0; // Encoded as in PlayerRecordsChallengeDCPC
/* 6C:88 */ U32T<BE> grave_defeated_by_enemy_rt_index = 0;
/* 70:8C */ F32T<BE> grave_x = 0.0f;
/* 74:90 */ F32T<BE> grave_y = 0.0f;
/* 78:94 */ F32T<BE> grave_z = 0.0f;
/* 7C:98 */ pstring<TextEncoding::ASCII, 0x14> grave_team;
/* 90:AC */ pstring<TextEncoding::ASCII, 0x20> grave_message;
/* B0:CC */ parray<uint8_t, 4> unknown_m5;
/* B4:D0 */ parray<U32T, 3> unknown_t6;
/* C0:DC */ ChallengeAwardStateT<IsBigEndian> ep1_online_award_state;
/* C8:E4 */ ChallengeAwardStateT<IsBigEndian> ep2_online_award_state;
/* D0:EC */ ChallengeAwardStateT<IsBigEndian> ep1_offline_award_state;
/* B4:D0 */ parray<U32T<BE>, 3> unknown_t6;
/* C0:DC */ ChallengeAwardStateT<BE> ep1_online_award_state;
/* C8:E4 */ ChallengeAwardStateT<BE> ep2_online_award_state;
/* D0:EC */ ChallengeAwardStateT<BE> ep1_offline_award_state;
/* D8:F4 */
} __packed__;
/* 0000:001C */ Stats stats;
@@ -661,8 +650,8 @@ struct PlayerRecordsChallengeBB {
PlayerRecordsChallengeBB(const PlayerRecordsChallengeDC& rec);
PlayerRecordsChallengeBB(const PlayerRecordsChallengePC& rec);
template <bool IsBigEndian>
PlayerRecordsChallengeBB(const PlayerRecordsChallengeV3T<IsBigEndian>& rec)
template <bool BE>
PlayerRecordsChallengeBB(const PlayerRecordsChallengeV3T<BE>& rec)
: title_color(rec.stats.title_color.load()),
unknown_u0(rec.stats.unknown_u0),
times_ep1_online(rec.stats.times_ep1_online),
@@ -694,9 +683,9 @@ struct PlayerRecordsChallengeBB {
operator PlayerRecordsChallengeDC() const;
operator PlayerRecordsChallengePC() const;
template <bool IsBigEndian>
operator PlayerRecordsChallengeV3T<IsBigEndian>() const {
PlayerRecordsChallengeV3T<IsBigEndian> ret;
template <bool BE>
operator PlayerRecordsChallengeV3T<BE>() const {
PlayerRecordsChallengeV3T<BE> ret;
ret.stats.title_color = this->title_color.load();
ret.stats.unknown_u0 = this->unknown_u0;
ret.stats.times_ep1_online = this->times_ep1_online;
@@ -728,20 +717,17 @@ struct PlayerRecordsChallengeBB {
}
} __packed_ws__(PlayerRecordsChallengeBB, 0x140);
template <bool IsBigEndian>
template <bool BE>
struct PlayerRecordsBattleT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
// On Episode 3, place_counts[0] is win count and [1] is loss count
/* 00 */ parray<U16T, 4> place_counts;
/* 08 */ U16T disconnect_count = 0;
/* 0A */ parray<U16T, 3> unknown_a1;
/* 10 */ parray<U32T, 2> unknown_a2;
/* 00 */ parray<U16T<BE>, 4> place_counts;
/* 08 */ U16T<BE> disconnect_count = 0;
/* 0A */ parray<U16T<BE>, 3> unknown_a1;
/* 10 */ parray<U32T<BE>, 2> unknown_a2;
/* 18 */
operator PlayerRecordsBattleT<!IsBigEndian>() const {
PlayerRecordsBattleT<!IsBigEndian> ret;
operator PlayerRecordsBattleT<!BE>() const {
PlayerRecordsBattleT<!BE> ret;
for (size_t z = 0; z < this->place_counts.size(); z++) {
ret.place_counts[z] = this->place_counts[z].load();
}
@@ -762,7 +748,7 @@ check_struct_size(PlayerRecordsBattleBE, 0x18);
template <typename DestT, typename SrcT = DestT>
DestT convert_player_disp_data(const SrcT&, uint8_t, uint8_t) {
static_assert(always_false<DestT, SrcT>::v,
static_assert(phosg::always_false<DestT, SrcT>::v,
"unspecialized convert_player_disp_data should never be called");
}
@@ -971,8 +957,8 @@ struct BattleRules {
/* 30 */
BattleRules() = default;
explicit BattleRules(const JSON& json);
JSON json() const;
explicit BattleRules(const phosg::JSON& json);
phosg::JSON json() const;
bool operator==(const BattleRules& other) const = default;
bool operator!=(const BattleRules& other) const = default;
@@ -998,20 +984,17 @@ struct SymbolChatFacePart {
uint8_t flags = 0;
} __packed_ws__(SymbolChatFacePart, 4);
template <bool IsBigEndian>
template <bool BE>
struct SymbolChatT {
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
// Bits: ----------------------DMSSSCCCFF
// S = sound, C = face color, F = face shape, D = capture, M = mute sound
/* 00 */ U32T spec = 0;
/* 00 */ U32T<BE> spec = 0;
// Corner objects are specified in reading order ([0] is the top-left one).
// Bits (each entry): ---VHCCCZZZZZZZZ
// V = reverse vertical, H = reverse horizontal, C = color, Z = object
// If Z is all 1 bits (0xFF), no corner object is rendered.
/* 04 */ parray<U16T, 4> corner_objects;
/* 04 */ parray<U16T<BE>, 4> corner_objects;
/* 0C */ parray<SymbolChatFacePart, 12> face_parts;
/* 3C */
@@ -1020,8 +1003,8 @@ struct SymbolChatT {
corner_objects(0x00FF),
face_parts() {}
operator SymbolChatT<!IsBigEndian>() const {
SymbolChatT<!IsBigEndian> ret;
operator SymbolChatT<!BE>() const {
SymbolChatT<!BE> ret;
ret.spec = this->spec.load();
for (size_t z = 0; z < this->corner_objects.size(); z++) {
ret.corner_objects[z] = this->corner_objects[z].load();
+59 -60
View File
@@ -95,8 +95,8 @@ static HandlerResult default_handler(shared_ptr<ProxyServer::LinkedSession>, uin
static HandlerResult S_invalid(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t command, uint32_t flag, string&) {
ses->log.error("Server sent invalid command");
string error_str = is_v4(ses->version())
? string_printf("Server sent invalid\ncommand: %04hX %08" PRIX32, command, flag)
: string_printf("Server sent invalid\ncommand: %02hX %02" PRIX32, command, flag);
? phosg::string_printf("Server sent invalid\ncommand: %04hX %08" PRIX32, command, flag)
: phosg::string_printf("Server sent invalid\ncommand: %02hX %02" PRIX32, command, flag);
ses->send_to_game_server(error_str.c_str());
return HandlerResult::Type::SUPPRESS;
}
@@ -110,7 +110,7 @@ static HandlerResult C_05(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
static HandlerResult C_1D(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string&) {
if (ses->client_ping_start_time) {
uint64_t ping_usecs = now() - ses->client_ping_start_time;
uint64_t ping_usecs = phosg::now() - ses->client_ping_start_time;
ses->client_ping_start_time = 0;
double ping_ms = static_cast<double>(ping_usecs) / 1000.0;
send_text_message_printf(ses->client_channel, "To proxy: %gms", ping_ms);
@@ -138,7 +138,7 @@ static HandlerResult S_97(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
static HandlerResult C_G_9E(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string&) {
if (ses->config.check_flag(Client::Flag::PROXY_SUPPRESS_REMOTE_LOGIN) && ses->login) {
le_uint64_t checksum = random_object<uint64_t>() & 0x0000FFFFFFFFFFFF;
le_uint64_t checksum = phosg::random_object<uint64_t>() & 0x0000FFFFFFFFFFFF;
ses->server_channel.send(0x96, 0x00, &checksum, sizeof(checksum));
S_UpdateClientConfig_V3_04 cmd;
@@ -172,7 +172,7 @@ static HandlerResult S_G_9A(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
cmd.sub_version = ses->effective_sub_version();
cmd.is_extended = (ses->remote_guild_card_number < 0) ? 1 : 0;
cmd.language = ses->language();
cmd.serial_number.encode(string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.access_key.encode(ses->login->gc_license->access_key);
cmd.serial_number2 = cmd.serial_number;
cmd.access_key2 = cmd.access_key;
@@ -259,7 +259,7 @@ static HandlerResult S_V123P_02_17(
}
if (command == 0x17) {
C_LoginV1_DC_PC_V3_90 cmd;
cmd.serial_number.encode(string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.access_key.encode(ses->login->dc_license->access_key);
cmd.access_key.clear_after_bytes(8);
ses->server_channel.send(0x90, 0x00, &cmd, sizeof(cmd));
@@ -278,7 +278,7 @@ static HandlerResult S_V123P_02_17(
cmd.sub_version = ses->effective_sub_version();
cmd.is_extended = 0;
cmd.language = ses->language();
cmd.serial_number.encode(string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.access_key.encode(ses->login->dc_license->access_key);
cmd.access_key.clear_after_bytes(8);
cmd.hardware_id.encode(ses->hardware_id);
@@ -314,7 +314,7 @@ static HandlerResult S_V123P_02_17(
cmd.guild_card_number = ses->remote_guild_card_number;
}
cmd.sub_version = ses->effective_sub_version();
cmd.serial_number.encode(string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.access_key.encode(*access_key);
if (ses->version() != Version::GC_NTE) {
cmd.access_key.clear_after_bytes(8);
@@ -340,7 +340,7 @@ static HandlerResult S_V123P_02_17(
cmd.sub_version = ses->effective_sub_version();
cmd.is_extended = 0;
cmd.language = ses->language();
cmd.serial_number.encode(string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.access_key.encode(*access_key);
if (ses->version() != Version::GC_NTE) {
cmd.access_key.clear_after_bytes(8);
@@ -365,7 +365,7 @@ static HandlerResult S_V123P_02_17(
}
if (command == 0x17) {
C_VerifyAccount_V3_DB cmd;
cmd.serial_number.encode(string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32 "", ses->login->account->account_id));
cmd.access_key.encode(ses->login->gc_license->access_key);
cmd.sub_version = ses->effective_sub_version();
cmd.serial_number2 = cmd.serial_number;
@@ -378,15 +378,15 @@ static HandlerResult S_V123P_02_17(
uint32_t guild_card_number;
if (ses->remote_guild_card_number >= 0) {
guild_card_number = ses->remote_guild_card_number;
log_info("Using Guild Card number %" PRIu32 " from session", guild_card_number);
ses->log.info("Using Guild Card number %" PRIu32 " from session", guild_card_number);
} else {
guild_card_number = random_object<uint32_t>();
log_info("Using Guild Card number %" PRIu32 " from random generator", guild_card_number);
guild_card_number = phosg::random_object<uint32_t>();
ses->log.info("Using Guild Card number %" PRIu32 " from random generator", guild_card_number);
}
uint32_t fake_serial_number = random_object<uint32_t>() & 0x7FFFFFFF;
uint64_t fake_access_key = random_object<uint64_t>();
string fake_access_key_str = string_printf("00000000000%" PRIu64, fake_access_key);
uint32_t fake_serial_number = phosg::random_object<uint32_t>() & 0x7FFFFFFF;
uint64_t fake_access_key = phosg::random_object<uint64_t>();
string fake_access_key_str = phosg::string_printf("00000000000%" PRIu64, fake_access_key);
if (fake_access_key_str.size() > 12) {
fake_access_key_str = fake_access_key_str.substr(fake_access_key_str.size() - 12);
}
@@ -399,7 +399,7 @@ static HandlerResult S_V123P_02_17(
cmd.sub_version = ses->effective_sub_version();
cmd.is_extended = 0;
cmd.language = ses->language();
cmd.serial_number.encode(string_printf("%08" PRIX32, fake_serial_number));
cmd.serial_number.encode(phosg::string_printf("%08" PRIX32, fake_serial_number));
cmd.access_key.encode(fake_access_key_str);
cmd.serial_number2 = cmd.serial_number;
cmd.access_key2 = cmd.access_key;
@@ -436,7 +436,7 @@ static HandlerResult S_V123P_02_17(
cmd.is_extended = (ses->remote_guild_card_number < 0) ? 1 : 0;
cmd.language = ses->language();
cmd.serial_number.encode(ses->login->xb_license->gamertag);
cmd.access_key.encode(string_printf("%016" PRIX64, ses->login->xb_license->user_id));
cmd.access_key.encode(phosg::string_printf("%016" PRIX64, ses->login->xb_license->user_id));
cmd.serial_number2 = cmd.serial_number;
cmd.access_key2 = cmd.access_key;
if (ses->config.check_flag(Client::Flag::PROXY_BLANK_NAME_ENABLED)) {
@@ -519,7 +519,7 @@ static HandlerResult S_B_03(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
static HandlerResult S_V123_04(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string& data) {
// Suppress extremely short commands from the server instead of disconnecting.
if (data.size() < offsetof(S_UpdateClientConfig_V3_04, client_config)) {
le_uint64_t checksum = random_object<uint64_t>() & 0x0000FFFFFFFFFFFF;
le_uint64_t checksum = phosg::random_object<uint64_t>() & 0x0000FFFFFFFFFFFF;
ses->server_channel.send(0x96, 0x00, &checksum, sizeof(checksum));
return HandlerResult::Type::SUPPRESS;
}
@@ -539,7 +539,7 @@ static HandlerResult S_V123_04(shared_ptr<ProxyServer::LinkedSession> ses, uint1
ses->remote_guild_card_number = cmd.guild_card_number;
ses->log.info("Remote guild card number set to %" PRId64,
ses->remote_guild_card_number);
string message = string_printf(
string message = phosg::string_printf(
"The remote server\nhas assigned your\nGuild Card number:\n$C6%" PRId64,
ses->remote_guild_card_number);
send_ship_info(ses->client_channel, message);
@@ -567,7 +567,7 @@ static HandlerResult S_V123_04(shared_ptr<ProxyServer::LinkedSession> ses, uint1
// the first 04 command the client has received. The client responds with a 96
// (checksum) in that case.
if (!had_guild_card_number) {
le_uint64_t checksum = random_object<uint64_t>() & 0x0000FFFFFFFFFFFF;
le_uint64_t checksum = phosg::random_object<uint64_t>() & 0x0000FFFFFFFFFFFF;
ses->server_channel.send(0x96, 0x00, &checksum, sizeof(checksum));
}
@@ -606,7 +606,7 @@ static HandlerResult S_41(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
if ((cmd.searcher_guild_card_number == ses->remote_guild_card_number) &&
(cmd.result_guild_card_number == ses->remote_guild_card_number) &&
ses->server_ping_start_time) {
uint64_t ping_usecs = now() - ses->server_ping_start_time;
uint64_t ping_usecs = phosg::now() - ses->server_ping_start_time;
ses->server_ping_start_time = 0;
double ping_ms = static_cast<double>(ping_usecs) / 1000.0;
send_text_message_printf(ses->client_channel, "To server: %gms", ping_ms);
@@ -677,16 +677,16 @@ static HandlerResult S_B1(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
return HandlerResult::Type::SUPPRESS;
}
template <bool IsBigEndian>
template <bool BE>
static HandlerResult S_B2(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t flag, string& data) {
const auto& cmd = check_size_t<S_ExecuteCode_B2>(data, 0xFFFF);
if (cmd.code_size && ses->config.check_flag(Client::Flag::PROXY_SAVE_FILES)) {
uint64_t filename_timestamp = now();
uint64_t filename_timestamp = phosg::now();
string code = data.substr(sizeof(S_ExecuteCode_B2));
if (ses->config.check_flag(Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL)) {
StringReader r(code);
phosg::StringReader r(code);
bool is_big_endian = ::is_big_endian(ses->version());
uint32_t decompressed_size = is_big_endian ? r.get_u32b() : r.get_u32l();
uint32_t key = is_big_endian ? r.get_u32b() : r.get_u32l();
@@ -694,7 +694,7 @@ static HandlerResult S_B2(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
PSOV2Encryption crypt(key);
string decrypted_data;
if (is_big_endian) {
StringWriter w;
phosg::StringWriter w;
while (!r.eof()) {
w.put_u32b(r.get_u32b() ^ crypt.next());
}
@@ -718,14 +718,13 @@ static HandlerResult S_B2(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
}
}
string output_filename = string_printf("code.%" PRId64 ".bin", filename_timestamp);
save_file(output_filename, data);
string output_filename = phosg::string_printf("code.%" PRId64 ".bin", filename_timestamp);
phosg::save_file(output_filename, data);
ses->log.info("Wrote code from server to file %s", output_filename.c_str());
#ifdef HAVE_RESOURCE_FILE
using FooterT = S_ExecuteCode_FooterT_B2<IsBigEndian>;
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
using FooterT = S_ExecuteCode_FooterT_B2<BE>;
// TODO: Support SH-4 disassembly too
bool is_ppc = ::is_ppc(ses->version());
bool is_x86 = ::is_x86(ses->version());
@@ -738,19 +737,19 @@ static HandlerResult S_B2(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
size_t footer_offset = code.size() - sizeof(FooterT);
StringReader r(code.data(), code.size());
phosg::StringReader r(code.data(), code.size());
const auto& footer = r.pget<FooterT>(footer_offset);
multimap<uint32_t, string> labels;
r.go(footer.relocations_offset);
uint32_t reloc_offset = 0;
for (size_t x = 0; x < footer.num_relocations; x++) {
reloc_offset += (r.get<U16T>() * 4);
labels.emplace(reloc_offset, string_printf("reloc%zu", x));
reloc_offset += (r.get<U16T<BE>>() * 4);
labels.emplace(reloc_offset, phosg::string_printf("reloc%zu", x));
}
labels.emplace(footer.entrypoint_addr_offset.load(), "entry_ptr");
labels.emplace(footer_offset, "footer");
labels.emplace(r.pget<U32T>(footer.entrypoint_addr_offset), "start");
labels.emplace(r.pget<U32T<BE>>(footer.entrypoint_addr_offset), "start");
string disassembly;
if (is_ppc) {
@@ -776,13 +775,13 @@ static HandlerResult S_B2(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
throw logic_error("unsupported architecture");
}
output_filename = string_printf("code.%" PRId64 ".txt", filename_timestamp);
output_filename = phosg::string_printf("code.%" PRId64 ".txt", filename_timestamp);
{
auto f = fopen_unique(output_filename, "wt");
auto f = phosg::fopen_unique(output_filename, "wt");
fprintf(f.get(), "// code_size = 0x%" PRIX32 "\n", cmd.code_size.load());
fprintf(f.get(), "// checksum_addr = 0x%" PRIX32 "\n", cmd.checksum_start.load());
fprintf(f.get(), "// checksum_size = 0x%" PRIX32 "\n", cmd.checksum_size.load());
fwritex(f.get(), disassembly);
phosg::fwritex(f.get(), disassembly);
}
ses->log.info("Wrote disassembly to file %s", output_filename.c_str());
@@ -825,8 +824,8 @@ static HandlerResult C_B3(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
static HandlerResult S_B_E7(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string& data) {
if (ses->config.check_flag(Client::Flag::PROXY_SAVE_FILES)) {
string output_filename = string_printf("player.%" PRId64 ".bin", now());
save_file(output_filename, data);
string output_filename = phosg::string_printf("player.%" PRId64 ".bin", phosg::now());
phosg::save_file(output_filename, data);
ses->log.info("Wrote player data to file %s", output_filename.c_str());
}
return HandlerResult::Type::FORWARD;
@@ -877,7 +876,7 @@ static HandlerResult S_B_22(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
// hence the hash here instead of a direct string comparison. I'd love to hear
// the story behind why they put that string there.
if ((data.size() == 0x2C) &&
(fnv1a64(data.data(), data.size()) == 0x8AF8314316A27994)) {
(phosg::fnv1a64(data.data(), data.size()) == 0x8AF8314316A27994)) {
ses->log.info("Enabling remote IP CRC patch");
ses->enable_remote_ip_crc_patch = true;
}
@@ -902,7 +901,7 @@ static HandlerResult S_19_P_14(shared_ptr<ProxyServer::LinkedSession> ses, uint1
}
if (ses->enable_remote_ip_crc_patch) {
ses->remote_ip_crc = crc32(data.data(), 4);
ses->remote_ip_crc = phosg::crc32(data.data(), 4);
}
// Set the destination netloc appropriately
@@ -1052,11 +1051,11 @@ static HandlerResult S_6x(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
const auto& header = check_size_t<G_MapSubsubcommand_Ep3_6xB6>(data, 0xFFFF);
if (header.subsubcommand == 0x00000041) {
const auto& cmd = check_size_t<G_MapData_Ep3_6xB6x41>(data, 0xFFFF);
string filename = string_printf("map%08" PRIX32 ".%" PRIu64 ".mnmd",
cmd.map_number.load(), now());
string filename = phosg::string_printf("map%08" PRIX32 ".%" PRIu64 ".mnmd",
cmd.map_number.load(), phosg::now());
string map_data = prs_decompress(
data.data() + sizeof(cmd), data.size() - sizeof(cmd));
save_file(filename, map_data);
phosg::save_file(filename, map_data);
if (map_data.size() != sizeof(Episode3::MapDefinition) && map_data.size() != sizeof(Episode3::MapDefinitionTrial)) {
ses->log.warning("Wrote %zu bytes to %s (expected %zu or %zu bytes; the file may be invalid)",
map_data.size(), filename.c_str(), sizeof(Episode3::MapDefinitionTrial), sizeof(Episode3::MapDefinition));
@@ -1285,10 +1284,10 @@ static HandlerResult S_44_A6(shared_ptr<ProxyServer::LinkedSession> ses, uint16_
} else {
basename = filename;
}
output_filename = string_printf("%s.%s.%" PRIu64 "%s",
output_filename = phosg::string_printf("%s.%s.%" PRIu64 "%s",
basename.c_str(),
is_download ? "download" : "online",
now(),
phosg::now(),
extension.c_str());
for (size_t x = 0; x < output_filename.size(); x++) {
@@ -1354,16 +1353,16 @@ static HandlerResult S_13_A7(shared_ptr<ProxyServer::LinkedSession> ses, uint16_
if (sf->remaining_bytes == 0) {
if (ses->config.check_flag(Client::Flag::PROXY_SAVE_FILES)) {
ses->log.info("Writing file %s => %s", sf->basename.c_str(), sf->output_filename.c_str());
string data = join(sf->blocks);
if (sf->is_download && (ends_with(sf->basename, ".bin") || ends_with(sf->basename, ".dat") || ends_with(sf->basename, ".pvr"))) {
string data = phosg::join(sf->blocks);
if (sf->is_download && (phosg::ends_with(sf->basename, ".bin") || phosg::ends_with(sf->basename, ".dat") || phosg::ends_with(sf->basename, ".pvr"))) {
data = decode_dlq_data(data);
}
save_file(sf->output_filename, data);
if (ends_with(sf->basename, ".bin")) {
phosg::save_file(sf->output_filename, data);
if (phosg::ends_with(sf->basename, ".bin")) {
try {
string decompressed = prs_decompress(data);
auto disassembly = disassemble_quest_script(decompressed.data(), decompressed.size(), ses->version(), ses->language(), false);
save_file(sf->output_filename + ".txt", disassembly);
phosg::save_file(sf->output_filename + ".txt", disassembly);
} catch (const exception& e) {
ses->log.warning("Failed to disassemble quest file: %s", e.what());
}
@@ -1372,8 +1371,8 @@ static HandlerResult S_13_A7(shared_ptr<ProxyServer::LinkedSession> ses, uint16_
ses->log.info("Download complete for file %s", sf->basename.c_str());
}
if (!sf->is_download && ends_with(sf->basename, ".dat")) {
auto quest_dat_data = make_shared<std::string>(join(sf->blocks));
if (!sf->is_download && phosg::ends_with(sf->basename, ".dat")) {
auto quest_dat_data = make_shared<std::string>(phosg::join(sf->blocks));
try {
ses->map = Lobby::load_maps(
ses->version(),
@@ -1419,15 +1418,15 @@ static HandlerResult S_G_B8(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
return HandlerResult::Type::FORWARD;
}
StringReader r(data);
phosg::StringReader r(data);
size_t size = r.get_u32l();
if (r.remaining() < size) {
ses->log.warning("Card list data size extends beyond end of command; not saving file");
return HandlerResult::Type::FORWARD;
}
string output_filename = string_printf("card-definitions.%" PRIu64 ".mnr", now());
save_file(output_filename, r.read(size));
string output_filename = phosg::string_printf("card-definitions.%" PRIu64 ".mnr", phosg::now());
phosg::save_file(output_filename, r.read(size));
ses->log.info("Wrote %zu bytes to %s", size, output_filename.c_str());
}
@@ -1450,7 +1449,7 @@ static HandlerResult S_G_B9(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
string decompressed_data = prs_decompress(
data.data() + sizeof(header), data.size() - sizeof(header));
string output_filename = string_printf("media-update.%" PRIu64, now());
string output_filename = phosg::string_printf("media-update.%" PRIu64, phosg::now());
if (header.type == 1) {
output_filename += ".gvm";
} else if (header.type == 2 || header.type == 3) {
@@ -1458,7 +1457,7 @@ static HandlerResult S_G_B9(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t
} else {
output_filename += ".bin";
}
save_file(output_filename, decompressed_data);
phosg::save_file(output_filename, decompressed_data);
ses->log.info("Wrote %zu bytes to %s",
decompressed_data.size(), output_filename.c_str());
} catch (const exception& e) {
@@ -1862,7 +1861,7 @@ static HandlerResult C_06(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
const auto& cmd = check_size_t<SC_TextHeader_01_06_11_B0_EE>(data, 0xFFFF);
string text = data.substr(sizeof(cmd));
strip_trailing_zeroes(text);
phosg::strip_trailing_zeroes(text);
uint8_t private_flags = 0;
try {
+30 -30
View File
@@ -58,9 +58,9 @@ ProxyServer::ListeningSocket::ListeningSocket(
Version version,
const struct sockaddr_storage* default_destination)
: server(server),
log(string_printf("[ProxyServer:T-%hu] ", port), proxy_server_log.min_level),
log(phosg::string_printf("[ProxyServer:T-%hu] ", port), proxy_server_log.min_level),
port(port),
fd(::listen(addr, port, SOMAXCONN)),
fd(phosg::listen(addr, port, SOMAXCONN)),
listener(nullptr, evconnlistener_free),
version(version) {
if (!this->fd.is_open()) {
@@ -85,7 +85,7 @@ ProxyServer::ListeningSocket::ListeningSocket(
this->default_destination.ss_family = 0;
}
this->log.info("Listening on TCP port %hu (%s) on fd %d", this->port, name_for_enum(this->version), static_cast<int>(this->fd));
this->log.info("Listening on TCP port %hu (%s) on fd %d", this->port, phosg::name_for_enum(this->version), static_cast<int>(this->fd));
}
void ProxyServer::ListeningSocket::dispatch_on_listen_accept(
@@ -100,13 +100,13 @@ void ProxyServer::ListeningSocket::dispatch_on_listen_error(
void ProxyServer::ListeningSocket::on_listen_accept(int fd) {
struct sockaddr_storage remote_addr;
get_socket_addresses(fd, nullptr, &remote_addr);
phosg::get_socket_addresses(fd, nullptr, &remote_addr);
if (this->server->state->banned_ipv4_ranges->check(remote_addr)) {
close(fd);
return;
}
this->log.info("Client connected on fd %d (port %hu, version %s)", fd, this->port, name_for_enum(this->version));
this->log.info("Client connected on fd %d (port %hu, version %s)", fd, this->port, phosg::name_for_enum(this->version));
auto* bev = bufferevent_socket_new(this->server->base.get(), fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
this->server->on_client_connect(bev, 0, this->port, this->version,
(this->default_destination.ss_family == AF_INET) ? &this->default_destination : nullptr);
@@ -159,7 +159,7 @@ void ProxyServer::on_client_connect(
auto ses = emplace_ret.first->second;
ses->log.info("Opened linked session");
Channel ch(bev, virtual_network_id, version, 1, nullptr, nullptr, ses.get(), "", TerminalFormat::FG_YELLOW, TerminalFormat::FG_GREEN);
Channel ch(bev, virtual_network_id, version, 1, nullptr, nullptr, ses.get(), "", phosg::TerminalFormat::FG_YELLOW, phosg::TerminalFormat::FG_GREEN);
ses->resume(std::move(ch));
} else {
@@ -200,8 +200,8 @@ void ProxyServer::on_client_connect(
case Version::GC_EP3_NTE:
case Version::GC_EP3:
case Version::XB_V3: {
uint32_t server_key = random_object<uint32_t>();
uint32_t client_key = random_object<uint32_t>();
uint32_t server_key = phosg::random_object<uint32_t>();
uint32_t client_key = phosg::random_object<uint32_t>();
auto cmd = prepare_server_init_contents_console(server_key, client_key, 0);
ses->channel.send(0x02, 0x00, &cmd, sizeof(cmd));
if (uses_v2_encryption(version)) {
@@ -216,8 +216,8 @@ void ProxyServer::on_client_connect(
case Version::BB_V4: {
parray<uint8_t, 0x30> server_key;
parray<uint8_t, 0x30> client_key;
random_data(server_key.data(), server_key.bytes());
random_data(client_key.data(), client_key.bytes());
phosg::random_data(server_key.data(), server_key.bytes());
phosg::random_data(client_key.data(), client_key.bytes());
auto cmd = prepare_server_init_contents_bb(server_key, client_key, 0);
ses->channel.send(0x03, 0x00, &cmd, sizeof(cmd));
ses->detector_crypt = make_shared<PSOBBMultiKeyDetectorEncryption>(
@@ -248,7 +248,7 @@ ProxyServer::UnlinkedSession::UnlinkedSession(
Version version)
: server(server),
id(id),
log(string_printf("[ProxyServer:US-%" PRIX64 "] ", this->id), proxy_server_log.min_level),
log(phosg::string_printf("[ProxyServer:US-%" PRIX64 "] ", this->id), proxy_server_log.min_level),
channel(
bev,
virtual_network_id,
@@ -258,11 +258,11 @@ ProxyServer::UnlinkedSession::UnlinkedSession(
ProxyServer::UnlinkedSession::on_error,
this,
"",
TerminalFormat::FG_YELLOW,
TerminalFormat::FG_GREEN),
phosg::TerminalFormat::FG_YELLOW,
phosg::TerminalFormat::FG_GREEN),
local_port(local_port) {
string ip_str = server->state->format_address_for_channel_name(this->channel.remote_addr, this->channel.virtual_network_id);
this->channel.name = string_printf("US-%" PRIX64 " @ %s", this->id, ip_str.c_str());
this->channel.name = phosg::string_printf("US-%" PRIX64 " @ %s", this->id, ip_str.c_str());
memset(&this->next_destination, 0, sizeof(this->next_destination));
}
@@ -506,7 +506,7 @@ ProxyServer::LinkedSession::LinkedSession(
Version version)
: server(server),
id(id),
log(string_printf("[ProxyServer:LS-%" PRIX64 "] ", this->id), proxy_server_log.min_level),
log(phosg::string_printf("[ProxyServer:LS-%" PRIX64 "] ", this->id), proxy_server_log.min_level),
timeout_event(event_new(server->base.get(), -1, EV_TIMEOUT, &LinkedSession::dispatch_on_timeout, this), event_free),
login(nullptr),
client_channel(
@@ -515,18 +515,18 @@ ProxyServer::LinkedSession::LinkedSession(
nullptr,
nullptr,
this,
string_printf("LS-%" PRIX64 "-C", this->id),
TerminalFormat::FG_YELLOW,
TerminalFormat::FG_GREEN),
phosg::string_printf("LS-%" PRIX64 "-C", this->id),
phosg::TerminalFormat::FG_YELLOW,
phosg::TerminalFormat::FG_GREEN),
server_channel(
version,
1,
nullptr,
nullptr,
this,
string_printf("LS-%" PRIX64 "-S", this->id),
TerminalFormat::FG_YELLOW,
TerminalFormat::FG_RED),
phosg::string_printf("LS-%" PRIX64 "-S", this->id),
phosg::TerminalFormat::FG_YELLOW,
phosg::TerminalFormat::FG_RED),
local_port(local_port),
disconnect_action(DisconnectAction::LONG_TIMEOUT),
remote_ip_crc(0),
@@ -676,14 +676,14 @@ void ProxyServer::LinkedSession::connect() {
throw runtime_error("destination is not AF_INET");
}
string netloc_str = render_sockaddr_storage(this->next_destination);
string netloc_str = phosg::render_sockaddr_storage(this->next_destination);
this->log.info("Connecting to %s", netloc_str.c_str());
this->server_channel.set_bufferevent(
bufferevent_socket_new(this->require_server()->base.get(), -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS), 0);
if (bufferevent_socket_connect(this->server_channel.bev.get(),
reinterpret_cast<const sockaddr*>(dest_sin), sizeof(*dest_sin)) != 0) {
throw runtime_error(string_printf("failed to connect (%d)", EVUTIL_SOCKET_ERROR()));
throw runtime_error(phosg::string_printf("failed to connect (%d)", EVUTIL_SOCKET_ERROR()));
}
this->server_channel.on_command_received = ProxyServer::LinkedSession::on_input;
@@ -701,8 +701,8 @@ void ProxyServer::LinkedSession::update_channel_names() {
auto client_ip_str = s->format_address_for_channel_name(
this->client_channel.remote_addr, this->client_channel.virtual_network_id);
auto server_ip_str = s->format_address_for_channel_name(this->server_channel.remote_addr, 0);
this->client_channel.name = string_printf("LS-%08" PRIX64 "-C @ %s", this->id, client_ip_str.c_str());
this->server_channel.name = string_printf("LS-%08" PRIX64 "-S @ %s", this->id, server_ip_str.c_str());
this->client_channel.name = phosg::string_printf("LS-%08" PRIX64 "-C @ %s", this->id, client_ip_str.c_str());
this->server_channel.name = phosg::string_printf("LS-%08" PRIX64 "-S @ %s", this->id, server_ip_str.c_str());
}
ProxyServer::LinkedSession::SavingFile::SavingFile(
@@ -730,7 +730,7 @@ void ProxyServer::LinkedSession::on_error(Channel& ch, short events) {
if (events & BEV_EVENT_CONNECTED) {
ses->log.info("%s channel connected", is_server_stream ? "Server" : "Client");
if (is_server_stream) {
get_socket_addresses(bufferevent_getfd(ch.bev.get()), &ch.local_addr, &ch.remote_addr);
phosg::get_socket_addresses(bufferevent_getfd(ch.bev.get()), &ch.local_addr, &ch.remote_addr);
ses->update_channel_names();
}
@@ -853,11 +853,11 @@ void ProxyServer::LinkedSession::send_to_game_server(const char* error_message)
auto s = this->require_server_state();
if (this->is_in_game) {
send_ship_info(this->client_channel, string_printf("You cannot return\nto $C6%s$C7\nwhile in a game.\n\n%s", s->name.c_str(), error_message ? error_message : ""));
send_ship_info(this->client_channel, phosg::string_printf("You cannot return\nto $C6%s$C7\nwhile in a game.\n\n%s", s->name.c_str(), error_message ? error_message : ""));
this->disconnect();
} else {
send_ship_info(this->client_channel, string_printf("You\'ve returned to\n$C6%s$C7\n\n%s", s->name.c_str(), error_message ? error_message : ""));
send_ship_info(this->client_channel, phosg::string_printf("You\'ve returned to\n$C6%s$C7\n\n%s", s->name.c_str(), error_message ? error_message : ""));
// Restore newserv_client_config, so the login server gets the client flags
if (is_v3(this->version())) {
@@ -915,7 +915,7 @@ void ProxyServer::LinkedSession::disconnect() {
// Set a timeout to delete the session entirely (in case the client doesn't
// reconnect)
struct timeval tv = usecs_to_timeval(this->timeout_for_disconnect_action(this->disconnect_action));
struct timeval tv = phosg::usecs_to_timeval(this->timeout_for_disconnect_action(this->disconnect_action));
event_add(this->timeout_event.get(), &tv);
}
@@ -998,7 +998,7 @@ void ProxyServer::delete_session(uint64_t id) {
this->unlinked_sessions_to_destroy.emplace(std::move(it->second));
this->id_to_unlinked_session.erase(it);
auto tv = usecs_to_timeval(0);
auto tv = phosg::usecs_to_timeval(0);
event_add(this->destroy_sessions_ev.get(), &tv);
}
}
+4 -4
View File
@@ -33,7 +33,7 @@ public:
struct LinkedSession : std::enable_shared_from_this<LinkedSession> {
std::weak_ptr<ProxyServer> server;
uint64_t id;
PrefixedLogger log;
phosg::PrefixedLogger log;
std::unique_ptr<struct event, void (*)(struct event*)> timeout_event;
@@ -221,9 +221,9 @@ private:
struct ListeningSocket {
ProxyServer* server;
PrefixedLogger log;
phosg::PrefixedLogger log;
uint16_t port;
scoped_fd fd;
phosg::scoped_fd fd;
std::unique_ptr<struct evconnlistener, void (*)(struct evconnlistener*)> listener;
Version version;
struct sockaddr_storage default_destination;
@@ -246,7 +246,7 @@ private:
std::weak_ptr<ProxyServer> server;
uint64_t id;
PrefixedLogger log;
phosg::PrefixedLogger log;
Channel channel;
uint16_t local_port;
struct sockaddr_storage next_destination;
+72 -74
View File
@@ -21,7 +21,7 @@
using namespace std;
QuestCategoryIndex::Category::Category(uint32_t category_id, const JSON& json)
QuestCategoryIndex::Category::Category(uint32_t category_id, const phosg::JSON& json)
: category_id(category_id) {
this->enabled_flags = json.get_int(0);
this->directory_name = json.get_string(1);
@@ -29,7 +29,7 @@ QuestCategoryIndex::Category::Category(uint32_t category_id, const JSON& json)
this->description = json.get_string(3);
}
QuestCategoryIndex::QuestCategoryIndex(const JSON& json) {
QuestCategoryIndex::QuestCategoryIndex(const phosg::JSON& json) {
uint32_t next_category_id = 1;
for (const auto& it : json.as_list()) {
this->categories.emplace_back(make_shared<Category>(next_category_id++, *it));
@@ -42,15 +42,13 @@ shared_ptr<const QuestCategoryIndex::Category> QuestCategoryIndex::at(uint32_t c
// GCI decoding logic
template <bool IsBigEndian>
template <bool BE>
struct PSOMemCardDLQFileEncryptedHeaderT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
U32T round2_seed;
U32T<BE> round2_seed;
// To compute checksum, set checksum to zero, then compute the CRC32 of the
// entire data section, including this header struct (but not the unencrypted
// header struct).
U32T checksum;
U32T<BE> checksum;
le_uint32_t decompressed_size;
le_uint32_t round3_seed;
// Data follows here.
@@ -60,10 +58,10 @@ using PSOGCIDLQFileEncryptedHeader = PSOMemCardDLQFileEncryptedHeaderT<true>;
check_struct_size(PSOVMSDLQFileEncryptedHeader, 0x10);
check_struct_size(PSOGCIDLQFileEncryptedHeader, 0x10);
template <bool IsBigEndian>
template <bool BE>
string decrypt_download_quest_data_section(
const void* data_section, size_t size, uint32_t seed, bool skip_checksum = false, bool is_ep3_trial = false) {
string decrypted = decrypt_data_section<IsBigEndian>(data_section, size, seed);
string decrypted = decrypt_data_section<BE>(data_section, size, seed);
size_t orig_size = decrypted.size();
decrypted.resize((decrypted.size() + 3) & (~3));
@@ -72,14 +70,14 @@ string decrypt_download_quest_data_section(
// not at the beginning. Presumably they did this because the system,
// character, and Guild Card files are a constant size, but download quest
// files can vary in size.
using HeaderT = PSOMemCardDLQFileEncryptedHeaderT<IsBigEndian>;
using HeaderT = PSOMemCardDLQFileEncryptedHeaderT<BE>;
auto* header = reinterpret_cast<HeaderT*>(decrypted.data());
PSOV2Encryption round2_crypt(header->round2_seed);
round2_crypt.encrypt_t<IsBigEndian>(
round2_crypt.encrypt_t<BE>(
decrypted.data() + 4, (decrypted.size() - 4));
if (is_ep3_trial) {
StringReader r(decrypted);
phosg::StringReader r(decrypted);
r.skip(16);
if (r.readx(15) != "SONICTEAM,SEGA.") {
throw runtime_error("Episode 3 GCI file is not a quest");
@@ -93,7 +91,7 @@ string decrypt_download_quest_data_section(
size_t decompressed_size = prs_decompress_size(
r.getv(r.remaining(), false), r.remaining(), sizeof(Episode3::MapDefinitionTrial), true);
if (decompressed_size < sizeof(Episode3::MapDefinitionTrial)) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed size (%zu) does not match expected size (%zu)",
decompressed_size, sizeof(Episode3::MapDefinitionTrial)));
}
@@ -101,17 +99,17 @@ string decrypt_download_quest_data_section(
} else {
if (header->decompressed_size & 0xFFF00000) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed_size too large (%08" PRIX32 ")", header->decompressed_size.load()));
}
if (!skip_checksum) {
uint32_t expected_crc = header->checksum;
header->checksum = 0;
uint32_t actual_crc = crc32(decrypted.data(), orig_size);
uint32_t actual_crc = phosg::crc32(decrypted.data(), orig_size);
header->checksum = expected_crc;
if (expected_crc != actual_crc && expected_crc != bswap32(actual_crc)) {
throw runtime_error(string_printf(
if (expected_crc != actual_crc && expected_crc != phosg::bswap32(actual_crc)) {
throw runtime_error(phosg::string_printf(
"incorrect decrypted data section checksum: expected %08" PRIX32 "; received %08" PRIX32,
expected_crc, actual_crc));
}
@@ -132,7 +130,7 @@ string decrypt_download_quest_data_section(
size_t expected_decompressed_size = header->decompressed_size.load();
if ((decompressed_size != expected_decompressed_size) &&
(decompressed_size != expected_decompressed_size - 8)) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed size (%zu) does not match expected size (%zu)",
decompressed_size, expected_decompressed_size));
}
@@ -142,7 +140,7 @@ string decrypt_download_quest_data_section(
}
string decrypt_vms_v1_data_section(const void* data_section, size_t size) {
StringReader r(data_section, size);
phosg::StringReader r(data_section, size);
uint32_t expected_decompressed_size = r.get_u32l();
uint32_t seed = r.get_u32l();
@@ -155,7 +153,7 @@ string decrypt_vms_v1_data_section(const void* data_section, size_t size) {
size_t actual_decompressed_size = prs_decompress_size(data);
if (actual_decompressed_size != expected_decompressed_size) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed size (%zu) does not match size in header (%" PRId32 ")",
actual_decompressed_size, expected_decompressed_size));
}
@@ -163,14 +161,14 @@ string decrypt_vms_v1_data_section(const void* data_section, size_t size) {
return data;
}
template <bool IsBigEndian>
template <bool BE>
string find_seed_and_decrypt_download_quest_data_section(
const void* data_section, size_t size, bool skip_checksum, bool is_ep3_trial, size_t num_threads) {
mutex result_lock;
string result;
uint64_t result_seed = parallel_range<uint64_t>([&](uint64_t seed, size_t) {
uint64_t result_seed = phosg::parallel_range<uint64_t>([&](uint64_t seed, size_t) {
try {
string ret = decrypt_download_quest_data_section<IsBigEndian>(
string ret = decrypt_download_quest_data_section<BE>(
data_section, size, seed, skip_checksum, is_ep3_trial);
lock_guard<mutex> g(result_lock);
result = std::move(ret);
@@ -242,7 +240,7 @@ VersionedQuest::VersionedQuest(
auto* header = reinterpret_cast<const PSOQuestHeaderDCNTE*>(bin_decompressed.data());
this->episode = Episode::EP1;
if (this->quest_number == 0xFFFFFFFF) {
this->quest_number = fnv1a32(header, sizeof(header)) & 0xFFFF;
this->quest_number = phosg::fnv1a32(header, sizeof(header)) & 0xFFFF;
}
this->name = header->name.decode(this->language);
break;
@@ -343,9 +341,9 @@ VersionedQuest::VersionedQuest(
string VersionedQuest::bin_filename() const {
if (this->episode == Episode::EP3) {
return string_printf("m%06" PRIu32 "p_e.bin", this->quest_number);
return phosg::string_printf("m%06" PRIu32 "p_e.bin", this->quest_number);
} else {
return string_printf("quest%" PRIu32 ".bin", this->quest_number);
return phosg::string_printf("quest%" PRIu32 ".bin", this->quest_number);
}
}
@@ -353,7 +351,7 @@ string VersionedQuest::dat_filename() const {
if (this->episode == Episode::EP3) {
throw logic_error("Episode 3 quests do not have .dat files");
} else {
return string_printf("quest%" PRIu32 ".dat", this->quest_number);
return phosg::string_printf("quest%" PRIu32 ".dat", this->quest_number);
}
}
@@ -361,7 +359,7 @@ string VersionedQuest::pvr_filename() const {
if (this->episode == Episode::EP3) {
throw logic_error("Episode 3 quests do not have .pvr files");
} else {
return string_printf("quest%" PRIu32 ".pvr", this->quest_number);
return phosg::string_printf("quest%" PRIu32 ".pvr", this->quest_number);
}
}
@@ -369,18 +367,18 @@ string VersionedQuest::xb_filename() const {
if (this->episode == Episode::EP3) {
throw logic_error("Episode 3 quests do not have Xbox filenames");
} else {
return string_printf("quest%" PRIu32 "_%c.dat", this->quest_number, tolower(char_for_language_code(this->language)));
return phosg::string_printf("quest%" PRIu32 "_%c.dat", this->quest_number, tolower(char_for_language_code(this->language)));
}
}
string VersionedQuest::encode_qst() const {
unordered_map<string, shared_ptr<const string>> files;
files.emplace(string_printf("quest%" PRIu32 ".bin", this->quest_number), this->bin_contents);
files.emplace(string_printf("quest%" PRIu32 ".dat", this->quest_number), this->dat_contents);
files.emplace(phosg::string_printf("quest%" PRIu32 ".bin", this->quest_number), this->bin_contents);
files.emplace(phosg::string_printf("quest%" PRIu32 ".dat", this->quest_number), this->dat_contents);
if (this->pvr_contents) {
files.emplace(string_printf("quest%" PRIu32 ".pvr", this->quest_number), this->pvr_contents);
files.emplace(phosg::string_printf("quest%" PRIu32 ".pvr", this->quest_number), this->pvr_contents);
}
string xb_filename = string_printf("quest%" PRIu32 "_%c.dat", quest_number, tolower(char_for_language_code(language)));
string xb_filename = phosg::string_printf("quest%" PRIu32 "_%c.dat", quest_number, tolower(char_for_language_code(language)));
return encode_qst_file(files, this->name, this->quest_number, xb_filename, this->version, this->is_dlq_encoded);
}
@@ -525,11 +523,11 @@ QuestIndex::QuestIndex(
};
string cat_path = directory + "/" + cat->directory_name;
if (!isdir(cat_path)) {
if (!phosg::isdir(cat_path)) {
static_game_data_log.warning("Quest category directory %s is missing; skipping it", cat_path.c_str());
continue;
}
for (string filename : list_directory_sorted(cat_path)) {
for (string filename : phosg::list_directory_sorted(cat_path)) {
if (filename == ".DS_Store") {
continue;
}
@@ -538,34 +536,34 @@ QuestIndex::QuestIndex(
try {
string orig_filename = filename;
string file_data;
if (ends_with(filename, ".gci")) {
file_data = decode_gci_data(load_file(file_path));
if (phosg::ends_with(filename, ".gci")) {
file_data = decode_gci_data(phosg::load_file(file_path));
filename.resize(filename.size() - 4);
} else if (ends_with(filename, ".vms")) {
file_data = decode_vms_data(load_file(file_path));
} else if (phosg::ends_with(filename, ".vms")) {
file_data = decode_vms_data(phosg::load_file(file_path));
filename.resize(filename.size() - 4);
} else if (ends_with(filename, ".dlq")) {
file_data = decode_dlq_data(load_file(file_path));
} else if (phosg::ends_with(filename, ".dlq")) {
file_data = decode_dlq_data(phosg::load_file(file_path));
filename.resize(filename.size() - 4);
} else if (ends_with(filename, ".txt")) {
string include_dir = dirname(file_path);
file_data = assemble_quest_script(load_file(file_path), include_dir);
} else if (phosg::ends_with(filename, ".txt")) {
string include_dir = phosg::dirname(file_path);
file_data = assemble_quest_script(phosg::load_file(file_path), include_dir);
filename.resize(filename.size() - 4);
if (ends_with(filename, ".bin")) {
if (phosg::ends_with(filename, ".bin")) {
filename.push_back('d');
}
} else {
file_data = load_file(file_path);
file_data = phosg::load_file(file_path);
}
size_t dot_pos = filename.rfind('.');
string file_basename;
string extension;
if (dot_pos != string::npos) {
file_basename = tolower(filename.substr(0, dot_pos));
extension = tolower(filename.substr(dot_pos + 1));
file_basename = phosg::tolower(filename.substr(0, dot_pos));
extension = phosg::tolower(filename.substr(dot_pos + 1));
} else {
file_basename = tolower(filename);
file_basename = phosg::tolower(filename);
}
if (extension == "json") {
@@ -583,11 +581,11 @@ QuestIndex::QuestIndex(
} else if (extension == "qst") {
auto files = decode_qst_data(file_data);
for (auto& it : files) {
if (ends_with(it.first, ".bin")) {
if (phosg::ends_with(it.first, ".bin")) {
add_file(bin_files, file_basename, orig_filename, std::move(it.second), true);
} else if (ends_with(it.first, ".dat")) {
} else if (phosg::ends_with(it.first, ".dat")) {
add_file(dat_files, file_basename, orig_filename, std::move(it.second), true);
} else if (ends_with(it.first, ".pvr")) {
} else if (phosg::ends_with(it.first, ".pvr")) {
add_file(pvr_files, file_basename, orig_filename, std::move(it.second), true);
} else {
throw runtime_error("qst file contains unsupported file type: " + it.first);
@@ -619,7 +617,7 @@ QuestIndex::QuestIndex(
// parse the remaining fields.
string quest_number_token, version_token, language_token;
{
vector<string> filename_tokens = split(basename, '-');
vector<string> filename_tokens = phosg::split(basename, '-');
if (filename_tokens.size() != 3) {
throw invalid_argument("incorrect filename format");
}
@@ -686,7 +684,7 @@ QuestIndex::QuestIndex(
}
}
// Load the quest's metadata JSON file, if it exists
// Load the quest's metadata phosg::JSON file, if it exists
const FileData* json_filedata = nullptr;
shared_ptr<BattleRules> battle_rules;
ssize_t challenge_template_index = -1;
@@ -709,7 +707,7 @@ QuestIndex::QuestIndex(
}
}
if (json_filedata) {
auto metadata_json = JSON::parse(*json_filedata->data);
auto metadata_json = phosg::JSON::parse(*json_filedata->data);
try {
battle_rules = make_shared<BattleRules>(metadata_json.at("BattleRules"));
} catch (const out_of_range&) {
@@ -764,20 +762,20 @@ QuestIndex::QuestIndex(
auto category_name = this->category_index->at(vq->category_id)->name;
string filenames_str = bin_filedata->filename;
if (dat_filedata) {
filenames_str += string_printf("/%s", dat_filedata->filename.c_str());
filenames_str += phosg::string_printf("/%s", dat_filedata->filename.c_str());
}
if (pvr_filedata) {
filenames_str += string_printf("/%s", pvr_filedata->filename.c_str());
filenames_str += phosg::string_printf("/%s", pvr_filedata->filename.c_str());
}
if (json_filedata) {
filenames_str += string_printf("/%s", json_filedata->filename.c_str());
filenames_str += phosg::string_printf("/%s", json_filedata->filename.c_str());
}
auto q_it = this->quests_by_number.find(vq->quest_number);
if (q_it != this->quests_by_number.end()) {
q_it->second->add_version(vq);
static_game_data_log.info("(%s) Added %s %c version of quest %" PRIu32 " (%s)",
filenames_str.c_str(),
name_for_enum(vq->version),
phosg::name_for_enum(vq->version),
char_for_language_code(vq->language),
vq->quest_number,
vq->name.c_str());
@@ -788,7 +786,7 @@ QuestIndex::QuestIndex(
this->quests_by_category_id_and_number[q->category_id].emplace(vq->quest_number, q);
static_game_data_log.info("(%s) Created %s %c quest %" PRIu32 " (%s) (%s, %s (%" PRIu32 "), %s)",
filenames_str.c_str(),
name_for_enum(vq->version),
phosg::name_for_enum(vq->version),
char_for_language_code(vq->language),
vq->quest_number,
vq->name.c_str(),
@@ -869,7 +867,7 @@ string encode_download_quest_data(const string& compressed_data, size_t decompre
// header (PSODownloadQuestHeader) is prepended to the encrypted data.
if (encryption_seed == 0) {
encryption_seed = random_object<uint32_t>();
encryption_seed = phosg::random_object<uint32_t>();
}
if (decompressed_size == 0) {
decompressed_size = prs_decompress_size(compressed_data);
@@ -969,7 +967,7 @@ string decode_gci_data(
ssize_t find_seed_num_threads,
int64_t known_seed,
bool skip_checksum) {
StringReader r(data);
phosg::StringReader r(data);
const auto& header = r.get<PSOGCIFileHeader>();
header.check();
@@ -1005,7 +1003,7 @@ string decode_gci_data(
size_t expected_decompressed_bytes = dlq_header.decompressed_size - 8;
if (decompressed_bytes < expected_decompressed_bytes) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"GCI decompressed data is smaller than expected size (have 0x%zX bytes, expected 0x%zX bytes)",
decompressed_bytes, expected_decompressed_bytes));
}
@@ -1054,7 +1052,7 @@ string decode_gci_data(
size_t decompressed_size = prs_decompress_size(decrypted);
if (decompressed_size != sizeof(Episode3::MapDefinition)) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed quest is 0x%zX bytes; expected 0x%zX bytes",
decompressed_size, sizeof(Episode3::MapDefinition)));
}
@@ -1071,7 +1069,7 @@ string decode_vms_data(
ssize_t find_seed_num_threads,
int64_t known_seed,
bool skip_checksum) {
StringReader r(data);
phosg::StringReader r(data);
const auto& header = r.get<PSOVMSFileHeader>();
if (!header.checksum_correct()) {
throw runtime_error("VMS file unencrypted header checksum is incorrect");
@@ -1101,7 +1099,7 @@ string decode_vms_data(
}
string decode_dlq_data(const string& data) {
StringReader r(data);
phosg::StringReader r(data);
uint32_t decompressed_size = r.get_u32l();
uint32_t key = r.get_u32l();
@@ -1125,7 +1123,7 @@ string decode_dlq_data(const string& data) {
template <typename HeaderT, typename OpenFileT>
static unordered_map<string, string> decode_qst_data_t(const string& data) {
StringReader r(data);
phosg::StringReader r(data);
unordered_map<string, string> files;
unordered_map<string, size_t> file_remaining_bytes;
@@ -1201,7 +1199,7 @@ static unordered_map<string, string> decode_qst_data_t(const string& data) {
for (const auto& it : file_remaining_bytes) {
if (it.second) {
throw runtime_error(string_printf("expected %zu (0x%zX) more bytes for file %s", it.second, it.second, it.first.c_str()));
throw runtime_error(phosg::string_printf("expected %zu (0x%zX) more bytes for file %s", it.second, it.second, it.first.c_str()));
}
}
@@ -1222,7 +1220,7 @@ unordered_map<string, string> decode_qst_data(const string& data) {
// - PC: 3C 00 44 ?? or 3C 00 A6 ??
// - DC/GC: 44 ?? 3C 00 or A6 ?? 3C 00
// - XB: 44 ?? 54 00 or A6 ?? 54 00
StringReader r(data);
phosg::StringReader r(data);
uint32_t signature = r.get_u32b();
if ((signature == 0x58004400) || (signature == 0x5800A600)) {
return decode_qst_data_t<PSOCommandHeaderBB, S_OpenFile_BB_44_A6>(data);
@@ -1246,7 +1244,7 @@ unordered_map<string, string> decode_qst_data(const string& data) {
}
template <typename HeaderT>
void add_command_header(StringWriter& w, uint8_t command, uint8_t flag, uint16_t size) {
void add_command_header(phosg::StringWriter& w, uint8_t command, uint8_t flag, uint16_t size) {
HeaderT header;
header.command = command;
header.flag = flag;
@@ -1256,7 +1254,7 @@ void add_command_header(StringWriter& w, uint8_t command, uint8_t flag, uint16_t
template <typename HeaderT, typename CmdT>
void add_open_file_command_t(
StringWriter& w,
phosg::StringWriter& w,
const std::string& name,
const std::string& filename,
const std::string&,
@@ -1276,7 +1274,7 @@ void add_open_file_command_t(
template <>
void add_open_file_command_t<PSOCommandHeaderDCV3, S_OpenFile_XB_44_A6>(
StringWriter& w,
phosg::StringWriter& w,
const std::string& name,
const std::string& filename,
const std::string& xb_filename,
@@ -1296,7 +1294,7 @@ void add_open_file_command_t<PSOCommandHeaderDCV3, S_OpenFile_XB_44_A6>(
template <typename HeaderT>
void add_write_file_commands_t(
StringWriter& w,
phosg::StringWriter& w,
const string& filename,
const string& data,
bool is_download,
@@ -1325,7 +1323,7 @@ string encode_qst_file(
const string& xb_filename,
Version version,
bool is_dlq_encoded) {
StringWriter w;
phosg::StringWriter w;
// Some tools expect both open file commands at the beginning, hence this
// unfortunate abstraction-breaking.
+2 -2
View File
@@ -42,7 +42,7 @@ struct QuestCategoryIndex {
std::string name;
std::string description;
explicit Category(uint32_t category_id, const JSON& json);
explicit Category(uint32_t category_id, const phosg::JSON& json);
[[nodiscard]] inline bool check_flag(QuestMenuType menu_type) const {
return this->enabled_flags & (1 << static_cast<uint8_t>(menu_type));
@@ -57,7 +57,7 @@ struct QuestCategoryIndex {
std::vector<std::shared_ptr<Category>> categories;
explicit QuestCategoryIndex(const JSON& json);
explicit QuestCategoryIndex(const phosg::JSON& json);
std::shared_ptr<const Category> at(uint32_t category_id) const;
};
+219 -219
View File
@@ -74,10 +74,10 @@ static string escape_string(const string& data, TextEncoding encoding = TextEnco
decoded = tt_ascii_to_utf8(data);
break;
default:
return format_data_string(data);
return phosg::format_data_string(data);
}
} catch (const runtime_error&) {
return format_data_string(data);
return phosg::format_data_string(data);
}
string ret = "\"";
@@ -89,7 +89,7 @@ static string escape_string(const string& data, TextEncoding encoding = TextEnco
} else if (ch == '\t') {
ret += "\\t";
} else if (static_cast<uint8_t>(ch) < 0x20) {
ret += string_printf("\\x%02hhX", ch);
ret += phosg::string_printf("\\x%02hhX", ch);
} else if (ch == '\'') {
ret += "\\\'";
} else if (ch == '\"') {
@@ -108,7 +108,7 @@ static string format_and_indent_data(const void* data, size_t size, uint64_t sta
iov.iov_len = size;
string ret = " ";
format_data(
phosg::format_data(
[&ret](const void* vdata, size_t size) -> void {
const char* data = reinterpret_cast<const char*>(vdata);
for (size_t z = 0; z < size; z++) {
@@ -119,9 +119,9 @@ static string format_and_indent_data(const void* data, size_t size, uint64_t sta
}
}
},
&iov, 1, start_address, nullptr, 0, PrintDataFlags::PRINT_ASCII);
&iov, 1, start_address, nullptr, 0, phosg::PrintDataFlags::PRINT_ASCII);
strip_trailing_whitespace(ret);
phosg::strip_trailing_whitespace(ret);
return ret;
}
@@ -878,7 +878,7 @@ opcodes_for_version(Version v) {
continue;
}
if (!index.emplace(def.opcode, &def).second) {
throw logic_error(string_printf("duplicate definition for opcode %04hX", def.opcode));
throw logic_error(phosg::string_printf("duplicate definition for opcode %04hX", def.opcode));
}
}
}
@@ -904,7 +904,7 @@ opcodes_by_name_for_version(Version v) {
continue;
}
if (!index.emplace(def.name, &def).second) {
throw logic_error(string_printf("duplicate definition for opcode %04hX", def.opcode));
throw logic_error(phosg::string_printf("duplicate definition for opcode %04hX", def.opcode));
}
}
}
@@ -912,9 +912,9 @@ opcodes_by_name_for_version(Version v) {
}
std::string disassemble_quest_script(const void* data, size_t size, Version version, uint8_t override_language, bool reassembly_mode) {
StringReader r(data, size);
phosg::StringReader r(data, size);
deque<string> lines;
lines.emplace_back(string_printf(".version %s", name_for_enum(version)));
lines.emplace_back(phosg::string_printf(".version %s", phosg::name_for_enum(version)));
bool use_wstrs = false;
size_t code_offset = 0;
@@ -942,8 +942,8 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
} else {
language = 1;
}
lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(string_printf(".language %hhu", header.language));
lines.emplace_back(phosg::string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(phosg::string_printf(".language %hhu", header.language));
lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
@@ -962,8 +962,8 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
} else {
language = 1;
}
lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(string_printf(".language %hhu", header.language));
lines.emplace_back(phosg::string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(phosg::string_printf(".language %hhu", header.language));
lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
@@ -984,9 +984,9 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
} else {
language = 1;
}
lines.emplace_back(string_printf(".quest_num %hhu", header.quest_number));
lines.emplace_back(string_printf(".language %hhu", header.language));
lines.emplace_back(string_printf(".episode %s", name_for_header_episode_number(header.episode)));
lines.emplace_back(phosg::string_printf(".quest_num %hhu", header.quest_number));
lines.emplace_back(phosg::string_printf(".language %hhu", header.language));
lines.emplace_back(phosg::string_printf(".episode %s", name_for_header_episode_number(header.episode)));
lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
@@ -1002,9 +1002,9 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
} else {
language = 1;
}
lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(string_printf(".episode %s", name_for_header_episode_number(header.episode)));
lines.emplace_back(string_printf(".max_players %hhu", header.max_players ? header.max_players : 4));
lines.emplace_back(phosg::string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(phosg::string_printf(".episode %s", name_for_header_episode_number(header.episode)));
lines.emplace_back(phosg::string_printf(".max_players %hhu", header.max_players ? header.max_players : 4));
if (header.joinable) {
lines.emplace_back(".joinable");
}
@@ -1018,7 +1018,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
}
const auto& opcodes = opcodes_for_version(version);
StringReader cmd_r = r.sub(code_offset, function_table_offset - code_offset);
phosg::StringReader cmd_r = r.sub(code_offset, function_table_offset - code_offset);
struct Label {
string name;
@@ -1042,11 +1042,11 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
vector<shared_ptr<Label>> function_table;
multimap<size_t, shared_ptr<Label>> offset_to_label;
StringReader function_table_r = r.sub(function_table_offset);
phosg::StringReader function_table_r = r.sub(function_table_offset);
while (!function_table_r.eof()) {
try {
uint32_t function_id = function_table.size();
string name = (function_id == 0) ? "start" : string_printf("label%04" PRIX32, function_id);
string name = (function_id == 0) ? "start" : phosg::string_printf("label%04" PRIX32, function_id);
uint32_t offset = function_table_r.get_u32l();
auto l = make_shared<Label>(name, offset, function_id);
if (function_id == 0) {
@@ -1123,9 +1123,9 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
}
if (def == nullptr) {
dasm_line = string_printf(".unknown %04hX", opcode);
dasm_line = phosg::string_printf(".unknown %04hX", opcode);
} else {
dasm_line = def->name ? def->name : string_printf("[%04hX]", opcode);
dasm_line = def->name ? def->name : phosg::string_printf("[%04hX]", opcode);
if (!version_has_args || !(def->flags & F_ARGS)) {
dasm_line.resize(0x20, ' ');
bool is_first_arg = true;
@@ -1140,13 +1140,13 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
arg_stack_values.emplace_back(ArgStackValue::Type::LABEL, label_id);
}
if (label_id >= function_table.size()) {
dasm_arg = string_printf("label%04" PRIX32, label_id);
dasm_arg = phosg::string_printf("label%04" PRIX32, label_id);
} else {
auto& l = function_table.at(label_id);
if (reassembly_mode) {
dasm_arg = string_printf("label%04" PRIX32, label_id);
dasm_arg = phosg::string_printf("label%04" PRIX32, label_id);
} else {
dasm_arg = string_printf("label%04" PRIX32 " /* %04" PRIX32 " */", label_id, l->offset);
dasm_arg = phosg::string_printf("label%04" PRIX32 " /* %04" PRIX32 " */", label_id, l->offset);
}
l->references.emplace(opcode_start_offset);
l->add_data_type(arg.data_type);
@@ -1165,13 +1165,13 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
dasm_arg += (dasm_arg.empty() ? "[" : ", ");
uint32_t label_id = cmd_r.get_u16l();
if (label_id >= function_table.size()) {
dasm_arg += string_printf("label%04" PRIX32, label_id);
dasm_arg += phosg::string_printf("label%04" PRIX32, label_id);
} else {
auto& l = function_table.at(label_id);
if (reassembly_mode) {
dasm_arg += string_printf("label%04" PRIX32, label_id);
dasm_arg += phosg::string_printf("label%04" PRIX32, label_id);
} else {
dasm_arg += string_printf("label%04" PRIX32 " /* %04" PRIX32 " */", label_id, l->offset);
dasm_arg += phosg::string_printf("label%04" PRIX32 " /* %04" PRIX32 " */", label_id, l->offset);
}
l->references.emplace(opcode_start_offset);
l->add_data_type(arg.data_type);
@@ -1192,7 +1192,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (def->flags & F_PASS) {
arg_stack_values.emplace_back((def->opcode == 0x004C) ? ArgStackValue::Type::REG_PTR : ArgStackValue::Type::REG, reg);
}
dasm_arg = string_printf("r%hhu", reg);
dasm_arg = phosg::string_printf("r%hhu", reg);
break;
}
case Type::REG_SET: {
@@ -1201,7 +1201,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
}
uint8_t num_regs = cmd_r.get_u8();
for (size_t z = 0; z < num_regs; z++) {
dasm_arg += string_printf("%sr%hhu", (dasm_arg.empty() ? "[" : ", "), cmd_r.get_u8());
dasm_arg += phosg::string_printf("%sr%hhu", (dasm_arg.empty() ? "[" : ", "), cmd_r.get_u8());
}
if (dasm_arg.empty()) {
dasm_arg = "[]";
@@ -1215,7 +1215,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
throw logic_error("REG_SET_FIXED cannot be pushed to arg stack");
}
uint8_t first_reg = cmd_r.get_u8();
dasm_arg = string_printf("r%hhu-r%hhu", first_reg, static_cast<uint8_t>(first_reg + arg.count - 1));
dasm_arg = phosg::string_printf("r%hhu-r%hhu", first_reg, static_cast<uint8_t>(first_reg + arg.count - 1));
break;
}
case Type::REG32_SET_FIXED: {
@@ -1223,7 +1223,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
throw logic_error("REG32_SET_FIXED cannot be pushed to arg stack");
}
uint32_t first_reg = cmd_r.get_u32l();
dasm_arg = string_printf("r%" PRIu32 "-r%" PRIu32, first_reg, static_cast<uint32_t>(first_reg + arg.count - 1));
dasm_arg = phosg::string_printf("r%" PRIu32 "-r%" PRIu32, first_reg, static_cast<uint32_t>(first_reg + arg.count - 1));
break;
}
case Type::INT8: {
@@ -1231,7 +1231,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (def->flags & F_PASS) {
arg_stack_values.emplace_back(ArgStackValue::Type::INT, v);
}
dasm_arg = string_printf("0x%02hhX", v);
dasm_arg = phosg::string_printf("0x%02hhX", v);
break;
}
case Type::INT16: {
@@ -1239,7 +1239,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (def->flags & F_PASS) {
arg_stack_values.emplace_back(ArgStackValue::Type::INT, v);
}
dasm_arg = string_printf("0x%04hX", v);
dasm_arg = phosg::string_printf("0x%04hX", v);
break;
}
case Type::INT32: {
@@ -1247,7 +1247,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (def->flags & F_PASS) {
arg_stack_values.emplace_back(ArgStackValue::Type::INT, v);
}
dasm_arg = string_printf("0x%08" PRIX32, v);
dasm_arg = phosg::string_printf("0x%08" PRIX32, v);
break;
}
case Type::FLOAT32: {
@@ -1255,12 +1255,12 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (def->flags & F_PASS) {
arg_stack_values.emplace_back(ArgStackValue::Type::INT, as_type<uint32_t>(v));
}
dasm_arg = string_printf("%g", v);
dasm_arg = phosg::string_printf("%g", v);
break;
}
case Type::CSTRING:
if (use_wstrs) {
StringWriter w;
phosg::StringWriter w;
for (uint16_t ch = cmd_r.get_u16l(); ch; ch = cmd_r.get_u16l()) {
w.put_u16l(ch);
}
@@ -1295,7 +1295,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
dasm_line += "... ";
if (def->args.size() != arg_stack_values.size()) {
dasm_line += string_printf("/* matching error: expected %zu arguments, received %zu arguments */",
dasm_line += phosg::string_printf("/* matching error: expected %zu arguments, received %zu arguments */",
def->args.size(), arg_stack_values.size());
} else {
bool is_first_arg = true;
@@ -1309,11 +1309,11 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
case Arg::Type::LABEL32:
switch (arg_value.type) {
case ArgStackValue::Type::REG:
dasm_arg = string_printf("r%" PRIu32 "/* warning: cannot determine label data type */", arg_value.as_int);
dasm_arg = phosg::string_printf("r%" PRIu32 "/* warning: cannot determine label data type */", arg_value.as_int);
break;
case ArgStackValue::Type::LABEL:
case ArgStackValue::Type::INT:
dasm_arg = string_printf("label%04" PRIX32, arg_value.as_int);
dasm_arg = phosg::string_printf("label%04" PRIX32, arg_value.as_int);
try {
auto l = function_table.at(arg_value.as_int);
l->add_data_type(arg_def.data_type);
@@ -1329,10 +1329,10 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
case Arg::Type::REG32:
switch (arg_value.type) {
case ArgStackValue::Type::REG:
dasm_arg = string_printf("regs[r%" PRIu32 "]", arg_value.as_int);
dasm_arg = phosg::string_printf("regs[r%" PRIu32 "]", arg_value.as_int);
break;
case ArgStackValue::Type::INT:
dasm_arg = string_printf("r%" PRIu32, arg_value.as_int);
dasm_arg = phosg::string_printf("r%" PRIu32, arg_value.as_int);
break;
default:
dasm_arg = "/* invalid-type */";
@@ -1342,10 +1342,10 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
case Arg::Type::REG32_SET_FIXED:
switch (arg_value.type) {
case ArgStackValue::Type::REG:
dasm_arg = string_printf("regs[r%" PRIu32 "]-regs[r%" PRIu32 "+%hhu]", arg_value.as_int, arg_value.as_int, static_cast<uint8_t>(arg_def.count - 1));
dasm_arg = phosg::string_printf("regs[r%" PRIu32 "]-regs[r%" PRIu32 "+%hhu]", arg_value.as_int, arg_value.as_int, static_cast<uint8_t>(arg_def.count - 1));
break;
case ArgStackValue::Type::INT:
dasm_arg = string_printf("r%" PRIu32 "-r%hhu", arg_value.as_int, static_cast<uint8_t>(arg_value.as_int + arg_def.count - 1));
dasm_arg = phosg::string_printf("r%" PRIu32 "-r%hhu", arg_value.as_int, static_cast<uint8_t>(arg_value.as_int + arg_def.count - 1));
break;
default:
dasm_arg = "/* invalid-type */";
@@ -1356,13 +1356,13 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
case Arg::Type::INT32:
switch (arg_value.type) {
case ArgStackValue::Type::REG:
dasm_arg = string_printf("r%" PRIu32, arg_value.as_int);
dasm_arg = phosg::string_printf("r%" PRIu32, arg_value.as_int);
break;
case ArgStackValue::Type::REG_PTR:
dasm_arg = string_printf("&r%" PRIu32, arg_value.as_int);
dasm_arg = phosg::string_printf("&r%" PRIu32, arg_value.as_int);
break;
case ArgStackValue::Type::INT:
dasm_arg = string_printf("0x%" PRIX32 " /* %" PRIu32 " */", arg_value.as_int, arg_value.as_int);
dasm_arg = phosg::string_printf("0x%" PRIX32 " /* %" PRIu32 " */", arg_value.as_int, arg_value.as_int);
break;
default:
dasm_arg = "/* invalid-type */";
@@ -1371,10 +1371,10 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
case Arg::Type::FLOAT32:
switch (arg_value.type) {
case ArgStackValue::Type::REG:
dasm_arg = string_printf("f%" PRIu32, arg_value.as_int);
dasm_arg = phosg::string_printf("f%" PRIu32, arg_value.as_int);
break;
case ArgStackValue::Type::INT:
dasm_arg = string_printf("%g", as_type<float>(arg_value.as_int));
dasm_arg = phosg::string_printf("%g", as_type<float>(arg_value.as_int));
break;
default:
dasm_arg = "/* invalid-type */";
@@ -1409,21 +1409,21 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
}
}
} catch (const exception& e) {
dasm_line = string_printf(".failed (%s)", e.what());
dasm_line = phosg::string_printf(".failed (%s)", e.what());
}
strip_trailing_whitespace(dasm_line);
phosg::strip_trailing_whitespace(dasm_line);
string line_text;
if (reassembly_mode) {
line_text = string_printf(" %s", dasm_line.c_str());
line_text = phosg::string_printf(" %s", dasm_line.c_str());
} else {
string hex_data = format_data_string(cmd_r.preadx(opcode_start_offset, cmd_r.where() - opcode_start_offset), nullptr, FormatDataFlags::HEX_ONLY);
string hex_data = phosg::format_data_string(cmd_r.preadx(opcode_start_offset, cmd_r.where() - opcode_start_offset), nullptr, phosg::FormatDataFlags::HEX_ONLY);
if (hex_data.size() > 14) {
hex_data.resize(12);
hex_data += "...";
}
hex_data.resize(16, ' ');
line_text = string_printf(" %04zX %s %s", opcode_start_offset, hex_data.c_str(), dasm_line.c_str());
line_text = phosg::string_printf(" %04zX %s %s", opcode_start_offset, hex_data.c_str(), dasm_line.c_str());
}
dasm_lines.emplace(opcode_start_offset, DisassemblyLine(std::move(line_text), cmd_r.where()));
}
@@ -1438,23 +1438,23 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
lines.emplace_back();
}
if (reassembly_mode) {
lines.emplace_back(string_printf("%s@0x%04" PRIX32 ":", l->name.c_str(), l->function_id));
lines.emplace_back(phosg::string_printf("%s@0x%04" PRIX32 ":", l->name.c_str(), l->function_id));
} else {
lines.emplace_back(string_printf("%s:", l->name.c_str()));
lines.emplace_back(phosg::string_printf("%s:", l->name.c_str()));
if (l->references.size() == 1) {
lines.emplace_back(string_printf(" // Referenced by instruction at %04zX", *l->references.begin()));
lines.emplace_back(phosg::string_printf(" // Referenced by instruction at %04zX", *l->references.begin()));
} else if (!l->references.empty()) {
vector<string> tokens;
tokens.reserve(l->references.size());
for (size_t reference_offset : l->references) {
tokens.emplace_back(string_printf("%04zX", reference_offset));
tokens.emplace_back(phosg::string_printf("%04zX", reference_offset));
}
lines.emplace_back(" // Referenced by instructions at " + join(tokens, ", "));
lines.emplace_back(" // Referenced by instructions at " + phosg::join(tokens, ", "));
}
}
if (l->type_flags == 0) {
lines.emplace_back(string_printf(" // Could not determine data type; disassembling as code"));
lines.emplace_back(phosg::string_printf(" // Could not determine data type; disassembling as code"));
l->add_data_type(Arg::DataType::SCRIPT);
}
@@ -1474,7 +1474,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (l->has_data_type(Arg::DataType::SCRIPT)) {
add_disassembly_lines(l->offset, size);
} else {
lines.emplace_back(".data " + format_data_string(cmd_r.pgetv(l->offset, size), size));
lines.emplace_back(".data " + phosg::format_data_string(cmd_r.pgetv(l->offset, size), size));
}
} else {
@@ -1489,20 +1489,20 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
lines.emplace_back(format_and_indent_data(cmd_r.pgetv(struct_end_offset, remaining_size), remaining_size, struct_end_offset));
}
} else {
lines.emplace_back(string_printf(" // As raw data (0x%zX bytes; too small for referenced type)", size));
lines.emplace_back(phosg::string_printf(" // As raw data (0x%zX bytes; too small for referenced type)", size));
lines.emplace_back(format_and_indent_data(cmd_r.pgetv(l->offset, size), size, l->offset));
}
}
};
if (l->has_data_type(Arg::DataType::DATA)) {
lines.emplace_back(string_printf(" // As raw data (0x%zX bytes)", size));
lines.emplace_back(phosg::string_printf(" // As raw data (0x%zX bytes)", size));
lines.emplace_back(format_and_indent_data(cmd_r.pgetv(l->offset, size), size, l->offset));
}
if (l->has_data_type(Arg::DataType::CSTRING)) {
lines.emplace_back(string_printf(" // As C string (0x%zX bytes)", size));
lines.emplace_back(phosg::string_printf(" // As C string (0x%zX bytes)", size));
string str_data = cmd_r.pread(l->offset, size);
strip_trailing_zeroes(str_data);
phosg::strip_trailing_zeroes(str_data);
if (use_wstrs) {
if (str_data.size() & 1) {
str_data.push_back(0);
@@ -1510,100 +1510,100 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
str_data = tt_utf16_to_utf8(str_data);
}
string formatted = escape_string(str_data, use_wstrs ? TextEncoding::UTF16 : encoding_for_language(language));
lines.emplace_back(string_printf(" %04" PRIX32 " %s", l->offset, formatted.c_str()));
lines.emplace_back(phosg::string_printf(" %04" PRIX32 " %s", l->offset, formatted.c_str()));
}
print_as_struct.template operator()<Arg::DataType::PLAYER_VISUAL_CONFIG, PlayerVisualConfig>([&](const PlayerVisualConfig& visual) -> void {
lines.emplace_back(" // As PlayerVisualConfig");
string name = escape_string(visual.name.decode(language));
lines.emplace_back(string_printf(" %04zX name %s", l->offset + offsetof(PlayerVisualConfig, name), name.c_str()));
lines.emplace_back(string_printf(" %04zX name_color %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, name_color), visual.name_color.load()));
string a2_str = format_data_string(visual.unknown_a2.data(), sizeof(visual.unknown_a2));
lines.emplace_back(string_printf(" %04zX a2 %s", l->offset + offsetof(PlayerVisualConfig, unknown_a2), a2_str.c_str()));
lines.emplace_back(string_printf(" %04zX extra_model %02hhX", l->offset + offsetof(PlayerVisualConfig, extra_model), visual.extra_model));
string unused = format_data_string(visual.unused.data(), visual.unused.bytes());
lines.emplace_back(string_printf(" %04zX unused %s", l->offset + offsetof(PlayerVisualConfig, unused), unused.c_str()));
lines.emplace_back(string_printf(" %04zX name_color_checksum %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, name_color_checksum), visual.name_color_checksum.load()));
lines.emplace_back(string_printf(" %04zX section_id %02hhX (%s)", l->offset + offsetof(PlayerVisualConfig, section_id), visual.section_id, name_for_section_id(visual.section_id)));
lines.emplace_back(string_printf(" %04zX char_class %02hhX (%s)", l->offset + offsetof(PlayerVisualConfig, char_class), visual.char_class, name_for_char_class(visual.char_class)));
lines.emplace_back(string_printf(" %04zX validation_flags %02hhX", l->offset + offsetof(PlayerVisualConfig, validation_flags), visual.validation_flags));
lines.emplace_back(string_printf(" %04zX version %02hhX", l->offset + offsetof(PlayerVisualConfig, version), visual.version));
lines.emplace_back(string_printf(" %04zX class_flags %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, class_flags), visual.class_flags.load()));
lines.emplace_back(string_printf(" %04zX costume %04hX", l->offset + offsetof(PlayerVisualConfig, costume), visual.costume.load()));
lines.emplace_back(string_printf(" %04zX skin %04hX", l->offset + offsetof(PlayerVisualConfig, skin), visual.skin.load()));
lines.emplace_back(string_printf(" %04zX face %04hX", l->offset + offsetof(PlayerVisualConfig, face), visual.face.load()));
lines.emplace_back(string_printf(" %04zX head %04hX", l->offset + offsetof(PlayerVisualConfig, head), visual.head.load()));
lines.emplace_back(string_printf(" %04zX hair %04hX", l->offset + offsetof(PlayerVisualConfig, hair), visual.hair.load()));
lines.emplace_back(string_printf(" %04zX hair_color %04hX, %04hX, %04hX", l->offset + offsetof(PlayerVisualConfig, hair_r), visual.hair_r.load(), visual.hair_g.load(), visual.hair_b.load()));
lines.emplace_back(string_printf(" %04zX proportion %g, %g", l->offset + offsetof(PlayerVisualConfig, proportion_x), visual.proportion_x.load(), visual.proportion_y.load()));
lines.emplace_back(phosg::string_printf(" %04zX name %s", l->offset + offsetof(PlayerVisualConfig, name), name.c_str()));
lines.emplace_back(phosg::string_printf(" %04zX name_color %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, name_color), visual.name_color.load()));
string a2_str = phosg::format_data_string(visual.unknown_a2.data(), sizeof(visual.unknown_a2));
lines.emplace_back(phosg::string_printf(" %04zX a2 %s", l->offset + offsetof(PlayerVisualConfig, unknown_a2), a2_str.c_str()));
lines.emplace_back(phosg::string_printf(" %04zX extra_model %02hhX", l->offset + offsetof(PlayerVisualConfig, extra_model), visual.extra_model));
string unused = phosg::format_data_string(visual.unused.data(), visual.unused.bytes());
lines.emplace_back(phosg::string_printf(" %04zX unused %s", l->offset + offsetof(PlayerVisualConfig, unused), unused.c_str()));
lines.emplace_back(phosg::string_printf(" %04zX name_color_checksum %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, name_color_checksum), visual.name_color_checksum.load()));
lines.emplace_back(phosg::string_printf(" %04zX section_id %02hhX (%s)", l->offset + offsetof(PlayerVisualConfig, section_id), visual.section_id, name_for_section_id(visual.section_id)));
lines.emplace_back(phosg::string_printf(" %04zX char_class %02hhX (%s)", l->offset + offsetof(PlayerVisualConfig, char_class), visual.char_class, name_for_char_class(visual.char_class)));
lines.emplace_back(phosg::string_printf(" %04zX validation_flags %02hhX", l->offset + offsetof(PlayerVisualConfig, validation_flags), visual.validation_flags));
lines.emplace_back(phosg::string_printf(" %04zX version %02hhX", l->offset + offsetof(PlayerVisualConfig, version), visual.version));
lines.emplace_back(phosg::string_printf(" %04zX class_flags %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, class_flags), visual.class_flags.load()));
lines.emplace_back(phosg::string_printf(" %04zX costume %04hX", l->offset + offsetof(PlayerVisualConfig, costume), visual.costume.load()));
lines.emplace_back(phosg::string_printf(" %04zX skin %04hX", l->offset + offsetof(PlayerVisualConfig, skin), visual.skin.load()));
lines.emplace_back(phosg::string_printf(" %04zX face %04hX", l->offset + offsetof(PlayerVisualConfig, face), visual.face.load()));
lines.emplace_back(phosg::string_printf(" %04zX head %04hX", l->offset + offsetof(PlayerVisualConfig, head), visual.head.load()));
lines.emplace_back(phosg::string_printf(" %04zX hair %04hX", l->offset + offsetof(PlayerVisualConfig, hair), visual.hair.load()));
lines.emplace_back(phosg::string_printf(" %04zX hair_color %04hX, %04hX, %04hX", l->offset + offsetof(PlayerVisualConfig, hair_r), visual.hair_r.load(), visual.hair_g.load(), visual.hair_b.load()));
lines.emplace_back(phosg::string_printf(" %04zX proportion %g, %g", l->offset + offsetof(PlayerVisualConfig, proportion_x), visual.proportion_x.load(), visual.proportion_y.load()));
});
print_as_struct.template operator()<Arg::DataType::PLAYER_STATS, PlayerStats>([&](const PlayerStats& stats) -> void {
lines.emplace_back(" // As PlayerStats");
lines.emplace_back(string_printf(" %04zX atp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.atp), stats.char_stats.atp.load(), stats.char_stats.atp.load()));
lines.emplace_back(string_printf(" %04zX mst %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.mst), stats.char_stats.mst.load(), stats.char_stats.mst.load()));
lines.emplace_back(string_printf(" %04zX evp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.evp), stats.char_stats.evp.load(), stats.char_stats.evp.load()));
lines.emplace_back(string_printf(" %04zX hp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.hp), stats.char_stats.hp.load(), stats.char_stats.hp.load()));
lines.emplace_back(string_printf(" %04zX dfp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.dfp), stats.char_stats.dfp.load(), stats.char_stats.dfp.load()));
lines.emplace_back(string_printf(" %04zX ata %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.ata), stats.char_stats.ata.load(), stats.char_stats.ata.load()));
lines.emplace_back(string_printf(" %04zX lck %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.lck), stats.char_stats.lck.load(), stats.char_stats.lck.load()));
lines.emplace_back(string_printf(" %04zX esp %04hX /* %hu */", l->offset + offsetof(PlayerStats, esp), stats.esp.load(), stats.esp.load()));
lines.emplace_back(string_printf(" %04zX height %08" PRIX32 " /* %g */", l->offset + offsetof(PlayerStats, height), stats.height.load_raw(), stats.height.load()));
lines.emplace_back(string_printf(" %04zX a3 %08" PRIX32 " /* %g */", l->offset + offsetof(PlayerStats, unknown_a3), stats.unknown_a3.load_raw(), stats.unknown_a3.load()));
lines.emplace_back(string_printf(" %04zX level %08" PRIX32 " /* level %" PRIu32 " */", l->offset + offsetof(PlayerStats, level), stats.level.load(), stats.level.load() + 1));
lines.emplace_back(string_printf(" %04zX experience %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(PlayerStats, experience), stats.experience.load(), stats.experience.load()));
lines.emplace_back(string_printf(" %04zX meseta %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(PlayerStats, meseta), stats.meseta.load(), stats.meseta.load()));
lines.emplace_back(phosg::string_printf(" %04zX atp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.atp), stats.char_stats.atp.load(), stats.char_stats.atp.load()));
lines.emplace_back(phosg::string_printf(" %04zX mst %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.mst), stats.char_stats.mst.load(), stats.char_stats.mst.load()));
lines.emplace_back(phosg::string_printf(" %04zX evp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.evp), stats.char_stats.evp.load(), stats.char_stats.evp.load()));
lines.emplace_back(phosg::string_printf(" %04zX hp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.hp), stats.char_stats.hp.load(), stats.char_stats.hp.load()));
lines.emplace_back(phosg::string_printf(" %04zX dfp %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.dfp), stats.char_stats.dfp.load(), stats.char_stats.dfp.load()));
lines.emplace_back(phosg::string_printf(" %04zX ata %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.ata), stats.char_stats.ata.load(), stats.char_stats.ata.load()));
lines.emplace_back(phosg::string_printf(" %04zX lck %04hX /* %hu */", l->offset + offsetof(PlayerStats, char_stats.lck), stats.char_stats.lck.load(), stats.char_stats.lck.load()));
lines.emplace_back(phosg::string_printf(" %04zX esp %04hX /* %hu */", l->offset + offsetof(PlayerStats, esp), stats.esp.load(), stats.esp.load()));
lines.emplace_back(phosg::string_printf(" %04zX height %08" PRIX32 " /* %g */", l->offset + offsetof(PlayerStats, height), stats.height.load_raw(), stats.height.load()));
lines.emplace_back(phosg::string_printf(" %04zX a3 %08" PRIX32 " /* %g */", l->offset + offsetof(PlayerStats, unknown_a3), stats.unknown_a3.load_raw(), stats.unknown_a3.load()));
lines.emplace_back(phosg::string_printf(" %04zX level %08" PRIX32 " /* level %" PRIu32 " */", l->offset + offsetof(PlayerStats, level), stats.level.load(), stats.level.load() + 1));
lines.emplace_back(phosg::string_printf(" %04zX experience %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(PlayerStats, experience), stats.experience.load(), stats.experience.load()));
lines.emplace_back(phosg::string_printf(" %04zX meseta %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(PlayerStats, meseta), stats.meseta.load(), stats.meseta.load()));
});
print_as_struct.template operator()<Arg::DataType::RESIST_DATA, ResistData>([&](const ResistData& resist) -> void {
lines.emplace_back(" // As ResistData");
lines.emplace_back(string_printf(" %04zX evp_bonus %04hX /* %hu */", l->offset + offsetof(ResistData, evp_bonus), resist.evp_bonus.load(), resist.evp_bonus.load()));
lines.emplace_back(string_printf(" %04zX efr %04hX /* %hu */", l->offset + offsetof(ResistData, efr), resist.efr.load(), resist.efr.load()));
lines.emplace_back(string_printf(" %04zX eic %04hX /* %hu */", l->offset + offsetof(ResistData, eic), resist.eic.load(), resist.eic.load()));
lines.emplace_back(string_printf(" %04zX eth %04hX /* %hu */", l->offset + offsetof(ResistData, eth), resist.eth.load(), resist.eth.load()));
lines.emplace_back(string_printf(" %04zX elt %04hX /* %hu */", l->offset + offsetof(ResistData, elt), resist.elt.load(), resist.elt.load()));
lines.emplace_back(string_printf(" %04zX edk %04hX /* %hu */", l->offset + offsetof(ResistData, edk), resist.edk.load(), resist.edk.load()));
lines.emplace_back(string_printf(" %04zX a6 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a6), resist.unknown_a6.load(), resist.unknown_a6.load()));
lines.emplace_back(string_printf(" %04zX a7 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a7), resist.unknown_a7.load(), resist.unknown_a7.load()));
lines.emplace_back(string_printf(" %04zX a8 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a8), resist.unknown_a8.load(), resist.unknown_a8.load()));
lines.emplace_back(string_printf(" %04zX a9 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a9), resist.unknown_a9.load(), resist.unknown_a9.load()));
lines.emplace_back(string_printf(" %04zX dfp_bonus %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, dfp_bonus), resist.dfp_bonus.load(), resist.dfp_bonus.load()));
lines.emplace_back(phosg::string_printf(" %04zX evp_bonus %04hX /* %hu */", l->offset + offsetof(ResistData, evp_bonus), resist.evp_bonus.load(), resist.evp_bonus.load()));
lines.emplace_back(phosg::string_printf(" %04zX efr %04hX /* %hu */", l->offset + offsetof(ResistData, efr), resist.efr.load(), resist.efr.load()));
lines.emplace_back(phosg::string_printf(" %04zX eic %04hX /* %hu */", l->offset + offsetof(ResistData, eic), resist.eic.load(), resist.eic.load()));
lines.emplace_back(phosg::string_printf(" %04zX eth %04hX /* %hu */", l->offset + offsetof(ResistData, eth), resist.eth.load(), resist.eth.load()));
lines.emplace_back(phosg::string_printf(" %04zX elt %04hX /* %hu */", l->offset + offsetof(ResistData, elt), resist.elt.load(), resist.elt.load()));
lines.emplace_back(phosg::string_printf(" %04zX edk %04hX /* %hu */", l->offset + offsetof(ResistData, edk), resist.edk.load(), resist.edk.load()));
lines.emplace_back(phosg::string_printf(" %04zX a6 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a6), resist.unknown_a6.load(), resist.unknown_a6.load()));
lines.emplace_back(phosg::string_printf(" %04zX a7 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a7), resist.unknown_a7.load(), resist.unknown_a7.load()));
lines.emplace_back(phosg::string_printf(" %04zX a8 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a8), resist.unknown_a8.load(), resist.unknown_a8.load()));
lines.emplace_back(phosg::string_printf(" %04zX a9 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, unknown_a9), resist.unknown_a9.load(), resist.unknown_a9.load()));
lines.emplace_back(phosg::string_printf(" %04zX dfp_bonus %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(ResistData, dfp_bonus), resist.dfp_bonus.load(), resist.dfp_bonus.load()));
});
print_as_struct.template operator()<Arg::DataType::ATTACK_DATA, AttackData>([&](const AttackData& attack) -> void {
lines.emplace_back(" // As AttackData");
lines.emplace_back(string_printf(" %04zX a1 %04hX /* %hd */", l->offset + offsetof(AttackData, unknown_a1), attack.unknown_a1.load(), attack.unknown_a1.load()));
lines.emplace_back(string_printf(" %04zX atp %04hX /* %hd */", l->offset + offsetof(AttackData, atp), attack.atp.load(), attack.atp.load()));
lines.emplace_back(string_printf(" %04zX ata_bonus %04hX /* %hd */", l->offset + offsetof(AttackData, ata_bonus), attack.ata_bonus.load(), attack.ata_bonus.load()));
lines.emplace_back(string_printf(" %04zX a4 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a4), attack.unknown_a4.load(), attack.unknown_a4.load()));
lines.emplace_back(string_printf(" %04zX distance_x %08" PRIX32 " /* %g */", l->offset + offsetof(AttackData, distance_x), attack.distance_x.load_raw(), attack.distance_x.load()));
lines.emplace_back(string_printf(" %04zX angle_x %08" PRIX32 " /* %" PRIu32 "/65536 */", l->offset + offsetof(AttackData, angle_x), attack.angle_x.load_raw(), attack.angle_x.load()));
lines.emplace_back(string_printf(" %04zX distance_y %08" PRIX32 " /* %g */", l->offset + offsetof(AttackData, distance_y), attack.distance_y.load_raw(), attack.distance_y.load()));
lines.emplace_back(string_printf(" %04zX a8 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a8), attack.unknown_a8.load(), attack.unknown_a8.load()));
lines.emplace_back(string_printf(" %04zX a9 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a9), attack.unknown_a9.load(), attack.unknown_a9.load()));
lines.emplace_back(string_printf(" %04zX a10 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a10), attack.unknown_a10.load(), attack.unknown_a10.load()));
lines.emplace_back(string_printf(" %04zX a11 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a11), attack.unknown_a11.load(), attack.unknown_a11.load()));
lines.emplace_back(string_printf(" %04zX a12 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a12), attack.unknown_a12.load(), attack.unknown_a12.load()));
lines.emplace_back(string_printf(" %04zX a13 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a13), attack.unknown_a13.load(), attack.unknown_a13.load()));
lines.emplace_back(string_printf(" %04zX a14 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a14), attack.unknown_a14.load(), attack.unknown_a14.load()));
lines.emplace_back(string_printf(" %04zX a15 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a15), attack.unknown_a15.load(), attack.unknown_a15.load()));
lines.emplace_back(string_printf(" %04zX a16 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a16), attack.unknown_a16.load(), attack.unknown_a16.load()));
lines.emplace_back(phosg::string_printf(" %04zX a1 %04hX /* %hd */", l->offset + offsetof(AttackData, unknown_a1), attack.unknown_a1.load(), attack.unknown_a1.load()));
lines.emplace_back(phosg::string_printf(" %04zX atp %04hX /* %hd */", l->offset + offsetof(AttackData, atp), attack.atp.load(), attack.atp.load()));
lines.emplace_back(phosg::string_printf(" %04zX ata_bonus %04hX /* %hd */", l->offset + offsetof(AttackData, ata_bonus), attack.ata_bonus.load(), attack.ata_bonus.load()));
lines.emplace_back(phosg::string_printf(" %04zX a4 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a4), attack.unknown_a4.load(), attack.unknown_a4.load()));
lines.emplace_back(phosg::string_printf(" %04zX distance_x %08" PRIX32 " /* %g */", l->offset + offsetof(AttackData, distance_x), attack.distance_x.load_raw(), attack.distance_x.load()));
lines.emplace_back(phosg::string_printf(" %04zX angle_x %08" PRIX32 " /* %" PRIu32 "/65536 */", l->offset + offsetof(AttackData, angle_x), attack.angle_x.load_raw(), attack.angle_x.load()));
lines.emplace_back(phosg::string_printf(" %04zX distance_y %08" PRIX32 " /* %g */", l->offset + offsetof(AttackData, distance_y), attack.distance_y.load_raw(), attack.distance_y.load()));
lines.emplace_back(phosg::string_printf(" %04zX a8 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a8), attack.unknown_a8.load(), attack.unknown_a8.load()));
lines.emplace_back(phosg::string_printf(" %04zX a9 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a9), attack.unknown_a9.load(), attack.unknown_a9.load()));
lines.emplace_back(phosg::string_printf(" %04zX a10 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a10), attack.unknown_a10.load(), attack.unknown_a10.load()));
lines.emplace_back(phosg::string_printf(" %04zX a11 %04hX /* %hu */", l->offset + offsetof(AttackData, unknown_a11), attack.unknown_a11.load(), attack.unknown_a11.load()));
lines.emplace_back(phosg::string_printf(" %04zX a12 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a12), attack.unknown_a12.load(), attack.unknown_a12.load()));
lines.emplace_back(phosg::string_printf(" %04zX a13 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a13), attack.unknown_a13.load(), attack.unknown_a13.load()));
lines.emplace_back(phosg::string_printf(" %04zX a14 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a14), attack.unknown_a14.load(), attack.unknown_a14.load()));
lines.emplace_back(phosg::string_printf(" %04zX a15 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a15), attack.unknown_a15.load(), attack.unknown_a15.load()));
lines.emplace_back(phosg::string_printf(" %04zX a16 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(AttackData, unknown_a16), attack.unknown_a16.load(), attack.unknown_a16.load()));
});
print_as_struct.template operator()<Arg::DataType::MOVEMENT_DATA, MovementData>([&](const MovementData& movement) -> void {
lines.emplace_back(" // As MovementData");
lines.emplace_back(string_printf(" %04zX idle_move_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, idle_move_speed), movement.idle_move_speed.load_raw(), movement.idle_move_speed.load()));
lines.emplace_back(string_printf(" %04zX idle_animation_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, idle_animation_speed), movement.idle_animation_speed.load_raw(), movement.idle_animation_speed.load()));
lines.emplace_back(string_printf(" %04zX move_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, move_speed), movement.move_speed.load_raw(), movement.move_speed.load()));
lines.emplace_back(string_printf(" %04zX animation_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, animation_speed), movement.animation_speed.load_raw(), movement.animation_speed.load()));
lines.emplace_back(string_printf(" %04zX a1 %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, unknown_a1), movement.unknown_a1.load_raw(), movement.unknown_a1.load()));
lines.emplace_back(string_printf(" %04zX a2 %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, unknown_a2), movement.unknown_a2.load_raw(), movement.unknown_a2.load()));
lines.emplace_back(string_printf(" %04zX a3 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a3), movement.unknown_a3.load(), movement.unknown_a3.load()));
lines.emplace_back(string_printf(" %04zX a4 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a4), movement.unknown_a4.load(), movement.unknown_a4.load()));
lines.emplace_back(string_printf(" %04zX a5 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a5), movement.unknown_a5.load(), movement.unknown_a5.load()));
lines.emplace_back(string_printf(" %04zX a6 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a6), movement.unknown_a6.load(), movement.unknown_a6.load()));
lines.emplace_back(string_printf(" %04zX a7 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a7), movement.unknown_a7.load(), movement.unknown_a7.load()));
lines.emplace_back(string_printf(" %04zX a8 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a8), movement.unknown_a8.load(), movement.unknown_a8.load()));
lines.emplace_back(phosg::string_printf(" %04zX idle_move_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, idle_move_speed), movement.idle_move_speed.load_raw(), movement.idle_move_speed.load()));
lines.emplace_back(phosg::string_printf(" %04zX idle_animation_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, idle_animation_speed), movement.idle_animation_speed.load_raw(), movement.idle_animation_speed.load()));
lines.emplace_back(phosg::string_printf(" %04zX move_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, move_speed), movement.move_speed.load_raw(), movement.move_speed.load()));
lines.emplace_back(phosg::string_printf(" %04zX animation_speed %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, animation_speed), movement.animation_speed.load_raw(), movement.animation_speed.load()));
lines.emplace_back(phosg::string_printf(" %04zX a1 %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, unknown_a1), movement.unknown_a1.load_raw(), movement.unknown_a1.load()));
lines.emplace_back(phosg::string_printf(" %04zX a2 %08" PRIX32 " /* %g */", l->offset + offsetof(MovementData, unknown_a2), movement.unknown_a2.load_raw(), movement.unknown_a2.load()));
lines.emplace_back(phosg::string_printf(" %04zX a3 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a3), movement.unknown_a3.load(), movement.unknown_a3.load()));
lines.emplace_back(phosg::string_printf(" %04zX a4 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a4), movement.unknown_a4.load(), movement.unknown_a4.load()));
lines.emplace_back(phosg::string_printf(" %04zX a5 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a5), movement.unknown_a5.load(), movement.unknown_a5.load()));
lines.emplace_back(phosg::string_printf(" %04zX a6 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a6), movement.unknown_a6.load(), movement.unknown_a6.load()));
lines.emplace_back(phosg::string_printf(" %04zX a7 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a7), movement.unknown_a7.load(), movement.unknown_a7.load()));
lines.emplace_back(phosg::string_printf(" %04zX a8 %08" PRIX32 " /* %" PRIu32 " */", l->offset + offsetof(MovementData, unknown_a8), movement.unknown_a8.load(), movement.unknown_a8.load()));
});
if (l->has_data_type(Arg::DataType::IMAGE_DATA)) {
const void* data = cmd_r.pgetv(l->offset, size);
auto decompressed = prs_decompress_with_meta(data, size);
lines.emplace_back(string_printf(" // As decompressed image data (0x%zX bytes)", decompressed.data.size()));
lines.emplace_back(phosg::string_printf(" // As decompressed image data (0x%zX bytes)", decompressed.data.size()));
lines.emplace_back(format_and_indent_data(decompressed.data.data(), decompressed.data.size(), 0));
if (decompressed.input_bytes_used < size) {
size_t compressed_end_offset = l->offset + decompressed.input_bytes_used;
@@ -1613,12 +1613,12 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
}
}
if (l->has_data_type(Arg::DataType::UNKNOWN_F8F2_DATA)) {
StringReader r = cmd_r.sub(l->offset, size);
phosg::StringReader r = cmd_r.sub(l->offset, size);
lines.emplace_back(" // As F8F2 entries");
while (r.remaining() >= sizeof(UnknownF8F2Entry)) {
size_t offset = l->offset + cmd_r.where();
const auto& e = r.get<UnknownF8F2Entry>();
lines.emplace_back(string_printf(" %04zX entry %g, %g, %g, %g", offset, e.unknown_a1[0].load(), e.unknown_a1[1].load(), e.unknown_a1[2].load(), e.unknown_a1[3].load()));
lines.emplace_back(phosg::string_printf(" %04zX entry %g, %g, %g, %g", offset, e.unknown_a1[0].load(), e.unknown_a1[1].load(), e.unknown_a1[2].load(), e.unknown_a1[3].load()));
}
if (r.remaining() > 0) {
size_t struct_end_offset = l->offset + r.where();
@@ -1634,11 +1634,11 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
}
lines.emplace_back(); // Add a \n on the end
return join(lines, "\n");
return phosg::join(lines, "\n");
}
Episode find_quest_episode_from_script(const void* data, size_t size, Version version) {
StringReader r(data, size);
phosg::StringReader r(data, size);
bool use_wstrs = false;
size_t code_offset = 0;
@@ -1680,7 +1680,7 @@ Episode find_quest_episode_from_script(const void* data, size_t size, Version ve
try {
const auto& opcodes = opcodes_for_version(version);
// The set_episode opcode should always be in the first function (0)
StringReader cmd_r = r.sub(code_offset + r.pget_u32l(function_table_offset));
phosg::StringReader cmd_r = r.sub(code_offset + r.pget_u32l(function_table_offset));
while (!cmd_r.eof()) {
uint16_t opcode = cmd_r.get_u8();
@@ -1695,7 +1695,7 @@ Episode find_quest_episode_from_script(const void* data, size_t size, Version ve
}
if (def == nullptr) {
throw runtime_error(string_printf("unknown quest opcode %04hX", opcode));
throw runtime_error(phosg::string_printf("unknown quest opcode %04hX", opcode));
}
if (def->flags & F_RET) {
@@ -1772,7 +1772,7 @@ Episode find_quest_episode_from_script(const void* data, size_t size, Version ve
}
}
} catch (const exception& e) {
log_warning("Cannot determine episode from quest script (%s)", e.what());
phosg::log_warning("Cannot determine episode from quest script (%s)", e.what());
}
if (found_episodes.size() > 1) {
@@ -1794,7 +1794,7 @@ Episode episode_for_quest_episode_number(uint8_t episode_number) {
case 0x02:
return Episode::EP4;
default:
throw runtime_error(string_printf("invalid episode number %02hhX", episode_number));
throw runtime_error(phosg::string_printf("invalid episode number %02hhX", episode_number));
}
}
@@ -1807,7 +1807,7 @@ struct RegisterAssigner {
unordered_set<size_t> offsets;
std::string str() const {
return string_printf("Register(%p, name=\"%s\", number=%hd)", this, this->name.c_str(), this->number);
return phosg::string_printf("Register(%p, name=\"%s\", number=%hd)", this, this->name.c_str(), this->number);
}
};
@@ -1853,7 +1853,7 @@ struct RegisterAssigner {
}
this->numbered_regs.at(reg->number) = reg;
} else if (reg->number != number) {
throw runtime_error(string_printf("register %s is assigned multiple numbers", reg->name.c_str()));
throw runtime_error(phosg::string_printf("register %s is assigned multiple numbers", reg->name.c_str()));
}
}
@@ -1861,10 +1861,10 @@ struct RegisterAssigner {
if (reg->name.empty()) {
reg->name = name;
if (!this->named_regs.emplace(reg->name, reg).second) {
throw runtime_error(string_printf("name %s is already assigned to a different register", reg->name.c_str()));
throw runtime_error(phosg::string_printf("name %s is already assigned to a different register", reg->name.c_str()));
}
} else if (reg->name != name) {
throw runtime_error(string_printf("register %hd is assigned multiple names", reg->number));
throw runtime_error(phosg::string_printf("register %hd is assigned multiple names", reg->number));
}
}
@@ -1875,11 +1875,11 @@ struct RegisterAssigner {
if (reg->number < 0) {
reg->number = number;
if (this->numbered_regs.at(reg->number)) {
throw logic_error(string_printf("register number %hd assigned multiple times", reg->number));
throw logic_error(phosg::string_printf("register number %hd assigned multiple times", reg->number));
}
this->numbered_regs.at(reg->number) = reg;
} else if (reg->number != static_cast<int16_t>(number)) {
throw runtime_error(string_printf("assigning different register number %hhu over existing register number %hd", number, reg->number));
throw runtime_error(phosg::string_printf("assigning different register number %hhu over existing register number %hd", number, reg->number));
}
}
@@ -1887,15 +1887,15 @@ struct RegisterAssigner {
if (!first_reg->next) {
first_reg->next = second_reg;
} else if (first_reg->next != second_reg) {
throw runtime_error(string_printf("register %s must come after %s, but is already constrained to another register", second_reg->name.c_str(), first_reg->name.c_str()));
throw runtime_error(phosg::string_printf("register %s must come after %s, but is already constrained to another register", second_reg->name.c_str(), first_reg->name.c_str()));
}
if (!second_reg->prev) {
second_reg->prev = first_reg;
} else if (second_reg->prev != first_reg) {
throw runtime_error(string_printf("register %s must come before %s, but is already constrained to another register", first_reg->name.c_str(), second_reg->name.c_str()));
throw runtime_error(phosg::string_printf("register %s must come before %s, but is already constrained to another register", first_reg->name.c_str(), second_reg->name.c_str()));
}
if ((first_reg->number >= 0) && (second_reg->number >= 0) && (first_reg->number != ((second_reg->number - 1) & 0xFF))) {
throw runtime_error(string_printf("register %s must come before %s, but both registers already have non-consecutive numbers", first_reg->name.c_str(), second_reg->name.c_str()));
throw runtime_error(phosg::string_printf("register %s must come before %s, but both registers already have non-consecutive numbers", first_reg->name.c_str(), second_reg->name.c_str()));
}
}
@@ -1952,13 +1952,13 @@ struct RegisterAssigner {
// At this point, all registers should be assigned
for (const auto& it : this->named_regs) {
if (it.second->number < 0) {
throw logic_error(string_printf("register %s was not assigned", it.second->name.c_str()));
throw logic_error(phosg::string_printf("register %s was not assigned", it.second->name.c_str()));
}
}
for (size_t z = 0; z < 0x100; z++) {
auto reg = this->numbered_regs[z];
if (reg && (reg->number != static_cast<int16_t>(z))) {
throw logic_error(string_printf("register %zu has incorrect number %hd", z, reg->number));
throw logic_error(phosg::string_printf("register %zu has incorrect number %hd", z, reg->number));
}
}
}
@@ -1983,7 +1983,7 @@ struct RegisterAssigner {
};
std::string assemble_quest_script(const std::string& text, const std::string& include_directory) {
auto lines = split(text, '\n');
auto lines = phosg::split(text, '\n');
// Strip comments and whitespace
for (auto& line : lines) {
@@ -2000,8 +2000,8 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
if (comment_start != string::npos) {
line.resize(comment_start);
}
strip_trailing_whitespace(line);
strip_leading_whitespace(line);
phosg::strip_trailing_whitespace(line);
phosg::strip_leading_whitespace(line);
}
// Collect metadata directives
@@ -2019,24 +2019,24 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
continue;
}
if (line[0] == '.') {
if (starts_with(line, ".version ")) {
if (phosg::starts_with(line, ".version ")) {
string name = line.substr(9);
quest_version = enum_for_name<Version>(name.c_str());
} else if (starts_with(line, ".name ")) {
quest_name = parse_data_string(line.substr(6));
} else if (starts_with(line, ".short_desc ")) {
quest_short_desc = parse_data_string(line.substr(12));
} else if (starts_with(line, ".long_desc ")) {
quest_long_desc = parse_data_string(line.substr(11));
} else if (starts_with(line, ".quest_num ")) {
quest_version = phosg::enum_for_name<Version>(name.c_str());
} else if (phosg::starts_with(line, ".name ")) {
quest_name = phosg::parse_data_string(line.substr(6));
} else if (phosg::starts_with(line, ".short_desc ")) {
quest_short_desc = phosg::parse_data_string(line.substr(12));
} else if (phosg::starts_with(line, ".long_desc ")) {
quest_long_desc = phosg::parse_data_string(line.substr(11));
} else if (phosg::starts_with(line, ".quest_num ")) {
quest_num = stoul(line.substr(11), nullptr, 0);
} else if (starts_with(line, ".language ")) {
} else if (phosg::starts_with(line, ".language ")) {
quest_language = stoul(line.substr(10), nullptr, 0);
} else if (starts_with(line, ".episode ")) {
} else if (phosg::starts_with(line, ".episode ")) {
quest_episode = episode_for_token_name(line.substr(9));
} else if (starts_with(line, ".max_players ")) {
} else if (phosg::starts_with(line, ".max_players ")) {
quest_max_players = stoul(line.substr(12), nullptr, 0);
} else if (starts_with(line, ".joinable ")) {
} else if (phosg::starts_with(line, ".joinable ")) {
quest_joinable = true;
}
}
@@ -2061,7 +2061,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
map<ssize_t, shared_ptr<Label>> labels_by_index;
for (size_t line_num = 1; line_num <= lines.size(); line_num++) {
const auto& line = lines[line_num - 1];
if (ends_with(line, ":")) {
if (phosg::ends_with(line, ":")) {
auto label = make_shared<Label>();
label->name = line.substr(0, line.size() - 1);
size_t at_offset = label->name.find('@');
@@ -2069,7 +2069,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
try {
label->index = stoul(label->name.substr(at_offset + 1), nullptr, 0);
} catch (const exception& e) {
throw runtime_error(string_printf("(line %zu) invalid index in label (%s)", line_num, e.what()));
throw runtime_error(phosg::string_printf("(line %zu) invalid index in label (%s)", line_num, e.what()));
}
label->name.resize(at_offset);
if (label->name == "start" && label->index != 0) {
@@ -2079,12 +2079,12 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
label->index = 0;
}
if (!labels_by_name.emplace(label->name, label).second) {
throw runtime_error(string_printf("(line %zu) duplicate label name: %s", line_num, label->name.c_str()));
throw runtime_error(phosg::string_printf("(line %zu) duplicate label name: %s", line_num, label->name.c_str()));
}
if (label->index >= 0) {
auto index_emplace_ret = labels_by_index.emplace(label->index, label);
if (label->index >= 0 && !index_emplace_ret.second) {
throw runtime_error(string_printf("(line %zu) duplicate label index: %zd (0x%zX) from %s and %s", line_num, label->index, label->index, label->name.c_str(), index_emplace_ret.first->second->name.c_str()));
throw runtime_error(phosg::string_printf("(line %zu) duplicate label index: %zd (0x%zX) from %s and %s", line_num, label->index, label->index, label->name.c_str(), index_emplace_ret.first->second->name.c_str()));
}
}
}
@@ -2120,7 +2120,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
string name;
ssize_t number = -1;
if (arg[1] == ':') {
auto tokens = split(arg.substr(2), '@');
auto tokens = phosg::split(arg.substr(2), '@');
if (tokens.size() == 1) {
name = std::move(tokens[0]);
} else if (tokens.size() == 2) {
@@ -2149,20 +2149,20 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
}
vector<shared_ptr<RegisterAssigner::Register>> regs;
if ((name[0] == '(') && (name.back() == ')')) {
auto tokens = split(name.substr(1, name.size() - 2), ',');
auto tokens = phosg::split(name.substr(1, name.size() - 2), ',');
if (tokens.size() != expected_count) {
throw runtime_error("incorrect number of registers in REG_SET_FIXED");
}
for (auto& token : tokens) {
strip_trailing_whitespace(token);
strip_leading_whitespace(token);
phosg::strip_trailing_whitespace(token);
phosg::strip_leading_whitespace(token);
regs.emplace_back(parse_reg(token));
if (regs.size() > 1) {
reg_assigner.constrain(regs.at(regs.size() - 2), regs.back());
}
}
} else {
auto tokens = split(name, '-');
auto tokens = phosg::split(name, '-');
if (tokens.size() == 1) {
regs.emplace_back(parse_reg(tokens[0], false));
while (regs.size() < expected_count) {
@@ -2193,7 +2193,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
// Assemble code segment
bool version_has_args = F_HAS_ARGS & v_flag(quest_version);
const auto& opcodes = opcodes_by_name_for_version(quest_version);
StringWriter code_w;
phosg::StringWriter code_w;
for (size_t line_num = 1; line_num <= lines.size(); line_num++) {
try {
const auto& line = lines[line_num - 1];
@@ -2201,7 +2201,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
continue;
}
if (ends_with(line, ":")) {
if (phosg::ends_with(line, ":")) {
size_t at_offset = line.find('@');
string label_name = line.substr(0, (at_offset == string::npos) ? (line.size() - 1) : at_offset);
labels_by_name.at(label_name)->offset = code_w.size();
@@ -2209,20 +2209,20 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
}
if (line[0] == '.') {
if (starts_with(line, ".data ")) {
code_w.write(parse_data_string(line.substr(6)));
} else if (starts_with(line, ".zero ")) {
if (phosg::starts_with(line, ".data ")) {
code_w.write(phosg::parse_data_string(line.substr(6)));
} else if (phosg::starts_with(line, ".zero ")) {
size_t size = stoull(line.substr(6), nullptr, 0);
code_w.extend_by(size, 0x00);
} else if (starts_with(line, ".include_bin ")) {
} else if (phosg::starts_with(line, ".include_bin ")) {
string filename = line.substr(13);
strip_whitespace(filename);
code_w.write(load_file(include_directory + "/" + filename));
} else if (starts_with(line, ".include_native ")) {
phosg::strip_whitespace(filename);
code_w.write(phosg::load_file(include_directory + "/" + filename));
} else if (phosg::starts_with(line, ".include_native ")) {
#ifdef HAVE_RESOURCE_FILE
string filename = line.substr(16);
strip_whitespace(filename);
string native_text = load_file(include_directory + "/" + filename);
phosg::strip_whitespace(filename);
string native_text = phosg::load_file(include_directory + "/" + filename);
string code;
if (is_ppc(quest_version)) {
code = std::move(ResourceDASM::PPC32Emulator::assemble(native_text).code);
@@ -2241,7 +2241,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
continue;
}
auto line_tokens = split(line, ' ', 1);
auto line_tokens = phosg::split(line, ' ', 1);
const auto& opcode_def = opcodes.at(line_tokens.at(0));
bool use_args = version_has_args && (opcode_def->flags & F_ARGS);
@@ -2255,26 +2255,26 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
if (opcode_def->args.empty()) {
if (line_tokens.size() > 1) {
throw runtime_error(string_printf("(line %zu) arguments not allowed for %s", line_num, opcode_def->name));
throw runtime_error(phosg::string_printf("(line %zu) arguments not allowed for %s", line_num, opcode_def->name));
}
continue;
}
if (line_tokens.size() < 2) {
throw runtime_error(string_printf("(line %zu) arguments required for %s", line_num, opcode_def->name));
throw runtime_error(phosg::string_printf("(line %zu) arguments required for %s", line_num, opcode_def->name));
}
strip_trailing_whitespace(line_tokens[1]);
strip_leading_whitespace(line_tokens[1]);
phosg::strip_trailing_whitespace(line_tokens[1]);
phosg::strip_leading_whitespace(line_tokens[1]);
if (starts_with(line_tokens[1], "...")) {
if (phosg::starts_with(line_tokens[1], "...")) {
if (!use_args) {
throw runtime_error(string_printf("(line %zu) \'...\' can only be used with F_ARGS opcodes", line_num));
throw runtime_error(phosg::string_printf("(line %zu) \'...\' can only be used with F_ARGS opcodes", line_num));
}
} else { // Not "..."
auto args = split_context(line_tokens[1], ',');
auto args = phosg::split_context(line_tokens[1], ',');
if (args.size() != opcode_def->args.size()) {
throw runtime_error(string_printf("(line %zu) incorrect argument count for %s", line_num, opcode_def->name));
throw runtime_error(phosg::string_printf("(line %zu) incorrect argument count for %s", line_num, opcode_def->name));
}
for (size_t z = 0; z < args.size(); z++) {
@@ -2282,8 +2282,8 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
string& arg = args[z];
const auto& arg_def = opcode_def->args[z];
strip_trailing_whitespace(arg);
strip_leading_whitespace(arg);
phosg::strip_trailing_whitespace(arg);
phosg::strip_leading_whitespace(arg);
try {
auto add_cstr = [&](const string& text) -> void {
@@ -2374,7 +2374,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
if (write_as_str) {
if (arg[0] == '\"') {
code_w.put_u8(0x4E); // arg_pushs
add_cstr(parse_data_string(arg));
add_cstr(phosg::parse_data_string(arg));
} else {
throw runtime_error("invalid argument syntax");
}
@@ -2402,10 +2402,10 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
};
auto split_set = [&](const string& text) -> vector<string> {
if (!starts_with(text, "[") || !ends_with(text, "]")) {
if (!phosg::starts_with(text, "[") || !phosg::ends_with(text, "]")) {
throw runtime_error("incorrect syntax for set-valued argument");
}
auto values = split(text.substr(1, text.size() - 2), ',');
auto values = phosg::split(text.substr(1, text.size() - 2), ',');
if (values.size() > 0xFF) {
throw runtime_error("too many labels in set-valued argument");
}
@@ -2421,8 +2421,8 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
auto label_names = split_set(arg);
code_w.put_u8(label_names.size());
for (auto name : label_names) {
strip_trailing_whitespace(name);
strip_leading_whitespace(name);
phosg::strip_trailing_whitespace(name);
phosg::strip_leading_whitespace(name);
add_label(name, false);
}
break;
@@ -2441,8 +2441,8 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
auto regs = split_set(arg);
code_w.put_u8(regs.size());
for (auto reg_arg : regs) {
strip_trailing_whitespace(reg_arg);
strip_leading_whitespace(reg_arg);
phosg::strip_trailing_whitespace(reg_arg);
phosg::strip_leading_whitespace(reg_arg);
add_reg(parse_reg(reg_arg), false);
}
break;
@@ -2460,14 +2460,14 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
code_w.put_u32l(stof(arg, nullptr));
break;
case Type::CSTRING:
add_cstr(parse_data_string(arg));
add_cstr(phosg::parse_data_string(arg));
break;
default:
throw logic_error("unknown argument type");
}
}
} catch (const exception& e) {
throw runtime_error(string_printf("(arg %zu) %s", z + 1, e.what()));
throw runtime_error(phosg::string_printf("(arg %zu) %s", z + 1, e.what()));
}
}
}
@@ -2481,7 +2481,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
}
} catch (const exception& e) {
throw runtime_error(string_printf("(line %zu) %s", line_num, e.what()));
throw runtime_error(phosg::string_printf("(line %zu) %s", line_num, e.what()));
}
}
while (code_w.size() & 3) {
@@ -2524,7 +2524,7 @@ std::string assemble_quest_script(const std::string& text, const std::string& in
}
// Generate header
StringWriter w;
phosg::StringWriter w;
switch (quest_version) {
case Version::DC_NTE: {
PSOQuestHeaderDCNTE header;
+45 -50
View File
@@ -11,9 +11,9 @@
using namespace std;
string RareItemSet::ExpandedDrop::str() const {
auto frac = reduce_fraction<uint64_t>(this->probability, 0x100000000);
auto frac = phosg::reduce_fraction<uint64_t>(this->probability, 0x100000000);
auto hex = this->data.hex();
return string_printf(
return phosg::string_printf(
"(%08" PRIX32 " => %" PRIu64 "/%" PRIu64 ") %s",
this->probability, frac.first, frac.second, hex.c_str());
}
@@ -92,21 +92,19 @@ RareItemSet::ExpandedDrop RareItemSet::ParsedRELData::PackedDrop::expand() const
return ret;
}
template <bool IsBigEndian>
void RareItemSet::ParsedRELData::parse_t(StringReader r, bool is_v1) {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
template <bool BE>
void RareItemSet::ParsedRELData::parse_t(phosg::StringReader r, bool is_v1) {
uint32_t root_offset = r.pget<U32T<BE>>(r.size() - 0x10);
const auto& root = r.pget<OffsetsT<BE>>(root_offset);
uint32_t root_offset = r.pget<U32T>(r.size() - 0x10);
const auto& root = r.pget<OffsetsT<IsBigEndian>>(root_offset);
StringReader monsters_r = r.sub(root.monster_rares_offset);
phosg::StringReader monsters_r = r.sub(root.monster_rares_offset);
for (size_t z = 0; z < (is_v1 ? 0x33 : 0x65); z++) {
const auto& d = monsters_r.get<PackedDrop>();
this->monster_rares.emplace_back(d.expand());
}
StringReader box_areas_r = r.sub(root.box_areas_offset, root.box_count * sizeof(uint8_t));
StringReader box_drops_r = r.sub(root.box_rares_offset, root.box_count * sizeof(PackedDrop));
phosg::StringReader box_areas_r = r.sub(root.box_areas_offset, root.box_count * sizeof(uint8_t));
phosg::StringReader box_drops_r = r.sub(root.box_rares_offset, root.box_count * sizeof(PackedDrop));
for (size_t z = 0; z < root.box_count; z++) {
uint8_t area = box_areas_r.get_u8();
const auto& drop = box_drops_r.get<PackedDrop>();
@@ -118,17 +116,14 @@ void RareItemSet::ParsedRELData::parse_t(StringReader r, bool is_v1) {
}
}
template <bool IsBigEndian>
template <bool BE>
std::string RareItemSet::ParsedRELData::serialize_t(bool is_v1) const {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
using U16T = typename std::conditional<IsBigEndian, be_uint16_t, le_uint16_t>::type;
static const PackedDrop empty_drop;
OffsetsT<IsBigEndian> root;
OffsetsT<BE> root;
root.box_count = this->box_rares.size();
StringWriter w;
phosg::StringWriter w;
root.monster_rares_offset = w.size();
for (const auto& drop : this->monster_rares) {
w.put(PackedDrop(drop));
@@ -159,24 +154,24 @@ std::string RareItemSet::ParsedRELData::serialize_t(bool is_v1) const {
w.put_u8(0);
}
uint32_t relocations_offset = w.size();
w.put<U16T>(root_offset >> 2);
w.put<U16T>(2);
w.put<U16T>(1);
w.put<U16T<BE>>(root_offset >> 2);
w.put<U16T<BE>>(2);
w.put<U16T<BE>>(1);
while (w.size() & 0x1F) {
w.put_u8(0);
}
w.put<U32T>(relocations_offset);
w.put<U32T>(3); // num_relocations
w.put<U32T>(1); // TODO: What is this used for?
w.put<U32T>(0);
w.put<U32T>(root_offset);
w.put<U32T>(0);
w.put<U32T>(0);
w.put<U32T>(0);
w.put<U32T<BE>>(relocations_offset);
w.put<U32T<BE>>(3); // num_relocations
w.put<U32T<BE>>(1); // TODO: What is this used for?
w.put<U32T<BE>>(0);
w.put<U32T<BE>>(root_offset);
w.put<U32T<BE>>(0);
w.put<U32T<BE>>(0);
w.put<U32T<BE>>(0);
return std::move(w.str());
}
RareItemSet::ParsedRELData::ParsedRELData(StringReader r, bool big_endian, bool is_v1) {
RareItemSet::ParsedRELData::ParsedRELData(phosg::StringReader r, bool big_endian, bool is_v1) {
if (big_endian) {
this->parse_t<true>(r, is_v1);
} else {
@@ -258,7 +253,7 @@ RareItemSet::RareItemSet(const AFSArchive& afs, bool is_v1) {
}
string RareItemSet::gsl_entry_name_for_table(GameMode mode, Episode episode, uint8_t difficulty, uint8_t section_id) {
return string_printf("ItemRT%s%s%c%1hhu.rel",
return phosg::string_printf("ItemRT%s%s%c%1hhu.rel",
((mode == GameMode::CHALLENGE) ? "c" : ""),
((episode == Episode::EP2) ? "l" : ""),
tolower(abbreviation_for_difficulty(difficulty)), // One of "nhvu"
@@ -288,7 +283,7 @@ RareItemSet::RareItemSet(const GSLArchive& gsl, bool is_big_endian) {
RareItemSet::RareItemSet(const string& rel_data, bool is_big_endian) {
// Tables are 0x280 bytes in size in this format, laid out sequentially
StringReader r(rel_data);
phosg::StringReader r(rel_data);
array<Episode, 3> episodes = {Episode::EP1, Episode::EP2, Episode::EP4};
for (size_t ep_index = 0; ep_index < episodes.size(); ep_index++) {
for (size_t difficulty = 0; difficulty < 4; difficulty++) {
@@ -306,7 +301,7 @@ RareItemSet::RareItemSet(const string& rel_data, bool is_big_endian) {
}
}
RareItemSet::RareItemSet(const JSON& json, shared_ptr<const ItemNameIndex> name_index) {
RareItemSet::RareItemSet(const phosg::JSON& json, shared_ptr<const ItemNameIndex> name_index) {
for (const auto& mode_it : json.as_dict()) {
static const unordered_map<string, GameMode> mode_keys(
{{"Normal", GameMode::NORMAL}, {"Battle", GameMode::BATTLE}, {"Challenge", GameMode::CHALLENGE}, {"Solo", GameMode::SOLO}});
@@ -328,14 +323,14 @@ RareItemSet::RareItemSet(const JSON& json, shared_ptr<const ItemNameIndex> name_
auto& collection = this->collections[this->key_for_params(mode, episode, difficulty, section_id)];
for (const auto& item_it : section_id_it.second->as_dict()) {
vector<ExpandedDrop>* target;
if (starts_with(item_it.first, "Box-")) {
if (phosg::starts_with(item_it.first, "Box-")) {
uint8_t area = floor_for_name(item_it.first.substr(4));
if (collection.box_area_to_specs.size() <= area) {
collection.box_area_to_specs.resize(area + 1);
}
target = &collection.box_area_to_specs[area];
} else {
size_t index = rare_table_index_for_enemy_type(enum_for_name<EnemyType>(item_it.first.c_str()));
size_t index = rare_table_index_for_enemy_type(phosg::enum_for_name<EnemyType>(item_it.first.c_str()));
if (collection.rt_index_to_specs.size() <= index) {
collection.rt_index_to_specs.resize(index + 1);
}
@@ -349,7 +344,7 @@ RareItemSet::RareItemSet(const JSON& json, shared_ptr<const ItemNameIndex> name_
if (prob_desc.is_int()) {
d.probability = prob_desc.as_int();
} else if (prob_desc.is_string()) {
auto tokens = split(prob_desc.as_string(), '/');
auto tokens = phosg::split(prob_desc.as_string(), '/');
if (tokens.size() != 2) {
throw runtime_error("invalid probability specification");
}
@@ -427,18 +422,18 @@ std::string RareItemSet::serialize_gsl(bool big_endian) const {
return GSLArchive::generate(files, big_endian);
}
JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const {
auto modes_dict = JSON::dict();
phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const {
auto modes_dict = phosg::JSON::dict();
static const array<GameMode, 4> modes = {GameMode::NORMAL, GameMode::BATTLE, GameMode::CHALLENGE, GameMode::SOLO};
for (const auto& mode : modes) {
auto episodes_dict = JSON::dict();
auto episodes_dict = phosg::JSON::dict();
static const array<Episode, 3> episodes = {Episode::EP1, Episode::EP2, Episode::EP4};
for (const auto& episode : episodes) {
auto difficulty_dict = JSON::dict();
auto difficulty_dict = phosg::JSON::dict();
for (uint8_t difficulty = 0; difficulty < 4; difficulty++) {
auto section_id_dict = JSON::dict();
auto section_id_dict = phosg::JSON::dict();
for (uint8_t section_id = 0; section_id < 10; section_id++) {
auto collection_dict = JSON::dict();
auto collection_dict = phosg::JSON::dict();
for (size_t rt_index = 0; rt_index < 0x80; rt_index++) {
const auto& enemy_types = enemy_types_for_rare_table_index(episode, rt_index);
if (enemy_types.empty()) {
@@ -449,8 +444,8 @@ JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const {
if (spec.data.empty()) {
continue;
}
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
auto spec_json = JSON::list({string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)});
auto frac = phosg::reduce_fraction<uint64_t>(spec.probability, 0x100000000);
auto spec_json = phosg::JSON::list({phosg::string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)});
if (spec.data.can_be_encoded_in_rel_rare_table()) {
spec_json.emplace_back((spec.data.data1[0] << 16) | (spec.data.data1[1] << 8) | spec.data.data1[2]);
} else {
@@ -461,22 +456,22 @@ JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const {
}
for (const auto& enemy_type : enemy_types) {
if (enemy_type_valid_for_episode(episode, enemy_type)) {
JSON this_spec_json = spec_json;
collection_dict.emplace(name_for_enum(enemy_type), JSON::list()).first->second->emplace_back(std::move(this_spec_json));
phosg::JSON this_spec_json = spec_json;
collection_dict.emplace(phosg::name_for_enum(enemy_type), phosg::JSON::list()).first->second->emplace_back(std::move(this_spec_json));
}
}
}
}
for (size_t area = 0; area < 0x12; area++) {
auto area_list = JSON::list();
auto area_list = phosg::JSON::list();
for (const auto& spec : this->get_box_specs(GameMode::NORMAL, episode, difficulty, section_id, area)) {
if (spec.data.empty()) {
continue;
}
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
auto spec_json = JSON::list({string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)});
auto frac = phosg::reduce_fraction<uint64_t>(spec.probability, 0x100000000);
auto spec_json = phosg::JSON::list({phosg::string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)});
if (spec.data.can_be_encoded_in_rel_rare_table()) {
spec_json.emplace_back((spec.data.data1[0] << 16) | (spec.data.data1[1] << 8) | spec.data.data1[2]);
} else {
@@ -490,7 +485,7 @@ JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const {
if (!area_list.empty()) {
collection_dict.emplace(
string_printf("Box-%s", name_for_floor(episode, area)),
phosg::string_printf("Box-%s", name_for_floor(episode, area)),
std::move(area_list));
}
}
@@ -549,7 +544,7 @@ void RareItemSet::print_collection(
string enemy_types_str;
const auto& enemy_types = enemy_types_for_rare_table_index(episode, z);
for (EnemyType enemy_type : enemy_types) {
enemy_types_str += name_for_enum(enemy_type);
enemy_types_str += phosg::name_for_enum(enemy_type);
enemy_types_str.push_back(',');
}
if (!enemy_types_str.empty()) {
+11 -12
View File
@@ -29,7 +29,7 @@ public:
RareItemSet(const AFSArchive& afs, bool is_v1);
RareItemSet(const GSLArchive& gsl, bool is_big_endian);
RareItemSet(const std::string& rel, bool is_big_endian);
RareItemSet(const JSON& json, std::shared_ptr<const ItemNameIndex> name_index = nullptr);
RareItemSet(const phosg::JSON& json, std::shared_ptr<const ItemNameIndex> name_index = nullptr);
~RareItemSet() = default;
std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const;
@@ -37,7 +37,7 @@ public:
std::string serialize_afs(bool is_v1) const;
std::string serialize_gsl(bool big_endian) const;
JSON json(std::shared_ptr<const ItemNameIndex> name_index = nullptr) const;
phosg::JSON json(std::shared_ptr<const ItemNameIndex> name_index = nullptr) const;
void multiply_all_rates(double factor);
@@ -66,13 +66,12 @@ protected:
ExpandedDrop expand() const;
} __packed_ws__(PackedDrop, 4);
template <bool IsBigEndian>
template <bool BE>
struct OffsetsT {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 00 */ U32T monster_rares_offset; // -> parray<PackedDrop, 0x65> (or 0x33 on v1)
/* 04 */ U32T box_count; // Usually 30 (0x1E)
/* 08 */ U32T box_areas_offset; // -> parray<uint8_t, 0x1E>
/* 0C */ U32T box_rares_offset; // -> parray<PackedDrop, 0x1E>
/* 00 */ U32T<BE> monster_rares_offset; // -> parray<PackedDrop, 0x65> (or 0x33 on v1)
/* 04 */ U32T<BE> box_count; // Usually 30 (0x1E)
/* 08 */ U32T<BE> box_areas_offset; // -> parray<uint8_t, 0x1E>
/* 0C */ U32T<BE> box_rares_offset; // -> parray<PackedDrop, 0x1E>
/* 10 */
} __packed__;
using Offsets = OffsetsT<false>;
@@ -89,13 +88,13 @@ protected:
std::vector<BoxRare> box_rares;
ParsedRELData() = default;
ParsedRELData(StringReader r, bool big_endian, bool is_v1);
ParsedRELData(phosg::StringReader r, bool big_endian, bool is_v1);
explicit ParsedRELData(const SpecCollection& collection);
std::string serialize(bool big_endian, bool is_v1) const;
template <bool IsBigEndian>
void parse_t(StringReader r, bool is_v1);
template <bool IsBigEndian>
template <bool BE>
void parse_t(phosg::StringReader r, bool is_v1);
template <bool BE>
std::string serialize_t(bool is_v1) const;
SpecCollection as_collection() const;
+52 -54
View File
@@ -311,7 +311,7 @@ static void send_main_menu(shared_ptr<Client> c) {
}
}
}
return string_printf(
return phosg::string_printf(
"$C6%zu$C7 players online\n$C6%zu$C7 games\n$C6%zu$C7 compatible games",
num_players, num_games, num_compatible_games);
},
@@ -472,7 +472,7 @@ void on_disconnect(shared_ptr<Client> c) {
static void on_1D(shared_ptr<Client> c, uint16_t, uint32_t, string&) {
if (c->ping_start_time) {
uint64_t ping_usecs = now() - c->ping_start_time;
uint64_t ping_usecs = phosg::now() - c->ping_start_time;
c->ping_start_time = 0;
double ping_ms = static_cast<double>(ping_usecs) / 1000.0;
send_text_message_printf(c, "To server: %gms", ping_ms);
@@ -1065,12 +1065,12 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
c->config.parse_from(config_data);
} else {
string version_string = config_data.as_string();
strip_trailing_zeroes(version_string);
phosg::strip_trailing_zeroes(version_string);
// If the version string starts with "Ver.", assume it's Sega and apply the
// normal version encoding logic. Otherwise, assume it's a community mod,
// almost all of which are based on TethVer12513, so assume that version
// otherwise.
if (starts_with(version_string, "Ver.")) {
if (phosg::starts_with(version_string, "Ver.")) {
// Basic algorithm: take all numeric characters from the version string
// and ignore everything else. Treat that as a decimal integer, then
// base36-encode it into the low 3 bytes of specific_version.
@@ -1112,7 +1112,7 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
// files replaced with English text/graphics/etc. For this reason, it still
// reports its language as Japanese, so we have to account for that
// manually here.
if (starts_with(version_string, "TethVer")) {
if (phosg::starts_with(version_string, "TethVer")) {
c->log.info("Client is TethVer subtype; forcing English language");
c->config.set_flag(Client::Flag::FORCE_ENGLISH_LANGUAGE_BB);
}
@@ -1142,8 +1142,8 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
// The BB data server protocol is fairly well-understood and has some large
// commands, so we omit data logging for clients on the data server.
c->log.info("Client is in the BB data server phase; disabling command data logging for the rest of this client\'s session");
c->channel.terminal_recv_color = TerminalFormat::END;
c->channel.terminal_send_color = TerminalFormat::END;
c->channel.terminal_recv_color = phosg::TerminalFormat::END;
c->channel.terminal_send_color = phosg::TerminalFormat::END;
}
}
@@ -1273,7 +1273,7 @@ static bool add_next_game_client(shared_ptr<Lobby> l) {
state_cmd.state.tournament_flag = 0x01;
state_cmd.state.client_sc_card_types.clear(Episode3::CardType::INVALID_FF);
if ((c->version() != Version::GC_EP3_NTE) && !(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) {
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t mask_key = (phosg::random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(&state_cmd, sizeof(state_cmd), mask_key);
}
send_command_t(c, 0xC9, 0x00, state_cmd);
@@ -1461,7 +1461,7 @@ static bool start_ep3_battle_table_game_if_ready(shared_ptr<Lobby> l, int16_t ta
send_self_leave_notification(other_c);
string message;
if (tourn) {
message = string_printf(
message = phosg::string_printf(
"$C7Waiting to begin match in tournament\n$C6%s$C7...\n\n(Hold B+X+START to abort)",
tourn->get_name().c_str());
} else {
@@ -1632,8 +1632,8 @@ static void on_CA_Ep3(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
} catch (const exception& e) {
c->log.error("Episode 3 engine returned an error: %s", e.what());
if (l->battle_record) {
string filename = string_printf("system/ep3/battle-records/exc.%" PRIu64 ".mzrd", now());
save_file(filename, l->battle_record->serialize());
string filename = phosg::string_printf("system/ep3/battle-records/exc.%" PRIu64 ".mzrd", phosg::now());
phosg::save_file(filename, l->battle_record->serialize());
c->log.error("Saved partial battle record as %s", filename.c_str());
}
throw;
@@ -1832,7 +1832,7 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
if (game_c.get()) {
auto player = game_c->character();
string name = escape_player_name(player->disp.name.decode(game_c->language()));
info += string_printf("%s\n %s Lv%" PRIu32 " %c\n",
info += phosg::string_printf("%s\n %s Lv%" PRIu32 " %c\n",
name.c_str(),
name_for_char_class(player->disp.visual.char_class),
player->disp.stats.level + 1,
@@ -1845,15 +1845,15 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
// time, send page 2 (extended info)
if (info.empty()) {
c->last_game_info_requested = 0;
info += string_printf("Section ID: %s\n", name_for_section_id(game->effective_section_id()));
info += phosg::string_printf("Section ID: %s\n", name_for_section_id(game->effective_section_id()));
if (game->max_level != 0xFFFFFFFF) {
info += string_printf("Req. level: %" PRIu32 "-%" PRIu32 "\n", game->min_level + 1, game->max_level + 1);
info += phosg::string_printf("Req. level: %" PRIu32 "-%" PRIu32 "\n", game->min_level + 1, game->max_level + 1);
} else if (game->min_level != 0) {
info += string_printf("Req. level: %" PRIu32 "+\n", game->min_level + 1);
info += phosg::string_printf("Req. level: %" PRIu32 "+\n", game->min_level + 1);
}
if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
info += string_printf("%s\n", name_for_enum(game->base_version));
info += phosg::string_printf("%s\n", phosg::name_for_enum(game->base_version));
}
if (game->check_flag(Lobby::Flag::CHEATS_ENABLED)) {
@@ -1893,7 +1893,7 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
break;
}
}
strip_trailing_whitespace(info);
phosg::strip_trailing_whitespace(info);
send_ship_info(c, info);
}
break;
@@ -1928,13 +1928,13 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
if (team_name.empty()) {
message = "(No registrant)";
} else if (team->max_players == 1) {
message = string_printf("$C6%s$C7\n%zu %s (%s)\nPlayers:",
message = phosg::string_printf("$C6%s$C7\n%zu %s (%s)\nPlayers:",
team_name.c_str(),
team->num_rounds_cleared,
team->num_rounds_cleared == 1 ? "win" : "wins",
team->is_active ? "active" : "defeated");
} else {
message = string_printf("$C6%s$C7\n%zu %s (%s)%s\nPlayers:",
message = phosg::string_printf("$C6%s$C7\n%zu %s (%s)%s\nPlayers:",
team_name.c_str(),
team->num_rounds_cleared,
team->num_rounds_cleared == 1 ? "win" : "wins",
@@ -1944,15 +1944,15 @@ static void on_09(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
for (const auto& player : team->players) {
if (player.is_human()) {
if (player.player_name.empty()) {
message += string_printf("\n $C6%08" PRIX32 "$C7", player.account_id);
message += phosg::string_printf("\n $C6%08" PRIX32 "$C7", player.account_id);
} else {
string player_name = escape_player_name(player.player_name);
message += string_printf("\n $C6%s$C7 (%08" PRIX32 ")", player_name.c_str(), player.account_id);
message += phosg::string_printf("\n $C6%s$C7 (%08" PRIX32 ")", player_name.c_str(), player.account_id);
}
} else {
string player_name = escape_player_name(player.com_deck->player_name);
string deck_name = escape_player_name(player.com_deck->deck_name);
message += string_printf("\n $C3%s \"%s\"$C7", player_name.c_str(), deck_name.c_str());
message += phosg::string_printf("\n $C3%s \"%s\"$C7", player_name.c_str(), deck_name.c_str());
}
}
send_ship_info(c, message);
@@ -2427,7 +2427,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
send_ep3_confirm_tournament_entry(c, nullptr);
}
c->config.proxy_destination_address = resolve_ipv4(dest->first);
c->config.proxy_destination_address = phosg::resolve_ipv4(dest->first);
c->config.proxy_destination_port = dest->second;
if (c->config.check_flag(Client::Flag::SHOULD_SEND_ENABLE_SAVE)) {
c->should_send_to_proxy_server = true;
@@ -2496,13 +2496,13 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
send_lobby_message_box(c, "$C7Incorrect password.");
break;
case Lobby::JoinError::LEVEL_TOO_LOW: {
string msg = string_printf("$C7You must be level\n%zu or above to\njoin this game.",
string msg = phosg::string_printf("$C7You must be level\n%zu or above to\njoin this game.",
static_cast<size_t>(game->min_level + 1));
send_lobby_message_box(c, msg);
break;
}
case Lobby::JoinError::LEVEL_TOO_HIGH: {
string msg = string_printf("$C7You must be level\n%zu or below to\njoin this game.",
string msg = phosg::string_printf("$C7You must be level\n%zu or below to\njoin this game.",
static_cast<size_t>(game->max_level + 1));
send_lobby_message_box(c, msg);
break;
@@ -2684,7 +2684,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
}
if (team_name.empty()) {
team_name = c->character()->disp.name.decode(c->language());
team_name += string_printf("/%" PRIX32, c->login->account->account_id);
team_name += phosg::string_printf("/%" PRIX32, c->login->account->account_id);
}
auto s = c->require_server_state();
uint16_t tourn_num = item_id >> 16;
@@ -2697,7 +2697,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
team->register_player(c, team_name, password);
c->ep3_tournament_team = team;
tourn->send_all_state_updates();
string message = string_printf("$C7You are registered in $C6%s$C7.\n\
string message = phosg::string_printf("$C7You are registered in $C6%s$C7.\n\
\n\
After the tournament begins, start your matches\n\
by standing at any Battle Table along with your\n\
@@ -2708,7 +2708,7 @@ partner (if any) and opponent(s).",
s->ep3_tournament_index->save();
} catch (const exception& e) {
string message = string_printf("Cannot join team:\n%s", e.what());
string message = phosg::string_printf("Cannot join team:\n%s", e.what());
send_lobby_message_box(c, message);
}
} else {
@@ -2845,7 +2845,7 @@ static void send_dol_file_chunk(shared_ptr<Client> c, uint32_t start_addr) {
send_function_call(c, fn, label_writes, data_to_send.data(), data_to_send.size());
size_t progress_percent = ((offset + bytes_to_send) * 100) / c->loading_dol_file->data.size();
send_ship_info(c, string_printf("%zu%%%%", progress_percent));
send_ship_info(c, phosg::string_printf("%zu%%%%", progress_percent));
}
static void on_B3(shared_ptr<Client> c, uint16_t, uint32_t flag, string& data) {
@@ -2995,7 +2995,7 @@ static void on_AA(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
static void on_D7_GC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
string filename(data);
strip_trailing_zeroes(filename);
phosg::strip_trailing_zeroes(filename);
if (filename.find('/') != string::npos) {
send_command(c, 0xD7, 0x00);
} else {
@@ -3005,19 +3005,17 @@ static void on_D7_GC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
send_open_quest_file(c, "", filename, "", 0, QuestFileType::GBA_DEMO, f->data);
} catch (const out_of_range&) {
send_command(c, 0xD7, 0x00);
} catch (const cannot_open_file&) {
} catch (const phosg::cannot_open_file&) {
send_command(c, 0xD7, 0x00);
}
}
}
static void on_13_A7_GC(shared_ptr<Client> c, uint16_t command, uint32_t flag, string& data) {
// See comment in send_open_quest_file about why we only have logic here for
// GC clients, and ignore this command on all other versions
static void on_13_A7_V3_V4(shared_ptr<Client> c, uint16_t command, uint32_t flag, string& data) {
const auto& cmd = check_size_t<C_WriteFileConfirmation_V3_BB_13_A7>(data);
bool is_download_quest = (command == 0xA7);
string filename = cmd.filename.decode();
size_t chunk_to_send = flag + GC_QUEST_LOAD_MAX_CHUNKS_IN_FLIGHT;
size_t chunk_to_send = flag + V3_V4_QUEST_LOAD_MAX_CHUNKS_IN_FLIGHT;
shared_ptr<const string> file_data;
try {
@@ -3085,7 +3083,7 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
c->import_blocked_senders(cmd.blocked_senders);
if (cmd.auto_reply_enabled) {
string auto_reply = data.substr(sizeof(cmd));
strip_trailing_zeroes(auto_reply);
phosg::strip_trailing_zeroes(auto_reply);
if (auto_reply.size() & 1) {
auto_reply.push_back(0);
}
@@ -3115,7 +3113,7 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
c->import_blocked_senders(cmd.blocked_senders);
if (cmd.auto_reply_enabled) {
string auto_reply = data.substr(sizeof(cmd), 0xAC);
strip_trailing_zeroes(auto_reply);
phosg::strip_trailing_zeroes(auto_reply);
try {
string encoded = tt_decode_marked(auto_reply, player->inventory.language, false);
player->auto_reply.encode(encoded, player->inventory.language);
@@ -3191,7 +3189,7 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
c->import_blocked_senders(cmd->blocked_senders);
if (cmd->auto_reply_enabled) {
string auto_reply = data.substr(sizeof(cmd), 0xAC);
strip_trailing_zeroes(auto_reply);
phosg::strip_trailing_zeroes(auto_reply);
try {
string encoded = tt_decode_marked(auto_reply, player->inventory.language, false);
player->auto_reply.encode(encoded, player->inventory.language);
@@ -3217,7 +3215,7 @@ static void on_61_98(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
c->import_blocked_senders(cmd.blocked_senders);
if (cmd.auto_reply_enabled) {
string auto_reply = data.substr(sizeof(cmd), 0xAC);
strip_trailing_zeroes(auto_reply);
phosg::strip_trailing_zeroes(auto_reply);
if (auto_reply.size() & 1) {
auto_reply.push_back(0);
}
@@ -3408,7 +3406,7 @@ static void on_6x_C9_CB(shared_ptr<Client> c, uint16_t command, uint32_t flag, s
static void on_06(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
const auto& cmd = check_size_t<SC_TextHeader_01_06_11_B0_EE>(data, 0xFFFF);
string text = data.substr(sizeof(cmd));
strip_trailing_zeroes(text);
phosg::strip_trailing_zeroes(text);
if (text.empty()) {
return;
}
@@ -3716,7 +3714,7 @@ static void on_E5_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
try {
c->character()->disp.apply_dressing_room(cmd.preview);
} catch (const exception& e) {
send_message_box(c, string_printf("$C6Character could not be modified:\n%s", e.what()));
send_message_box(c, phosg::string_printf("$C6Character could not be modified:\n%s", e.what()));
return;
}
} else {
@@ -3724,7 +3722,7 @@ static void on_E5_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
auto s = c->require_server_state();
c->create_character_file(c->login->account->account_id, c->language(), cmd.preview, s->level_table(c->version()));
} catch (const exception& e) {
send_message_box(c, string_printf("$C6New character could not be created:\n%s", e.what()));
send_message_box(c, phosg::string_printf("$C6New character could not be created:\n%s", e.what()));
return;
}
}
@@ -3881,7 +3879,7 @@ static void on_DF_BB(shared_ptr<Client> c, uint16_t command, uint32_t, string& d
auto& threshold = cp->rank_thresholds[cmd.rank];
threshold.bitmask = cmd.rank_bitmask;
threshold.seconds = cmd.seconds;
string time_str = format_duration(static_cast<uint64_t>(threshold.seconds) * 1000000);
string time_str = phosg::format_duration(static_cast<uint64_t>(threshold.seconds) * 1000000);
l->log.info("(Challenge mode) Rank %c threshold set to %s (bitmask %08" PRIX32 ")",
char_for_challenge_rank(cmd.rank), time_str.c_str(), threshold.bitmask);
break;
@@ -3968,18 +3966,18 @@ static void on_choice_search_t(shared_ptr<Client> c, const ChoiceSearchConfig& c
auto& result = results.emplace_back();
result.guild_card_number = lc->login->account->account_id;
result.name.encode(lp->disp.name.decode(lc->language()), c->language());
string info_string = string_printf("%s Lv%zu\n%s\n",
string info_string = phosg::string_printf("%s Lv%zu\n%s\n",
name_for_char_class(lp->disp.visual.char_class),
static_cast<size_t>(lp->disp.stats.level + 1),
name_for_section_id(lp->disp.visual.section_id));
result.info_string.encode(info_string, c->language());
string location_string;
if (l->is_game()) {
location_string = string_printf("%s,,BLOCK01,%s", l->name.c_str(), s->name.c_str());
location_string = phosg::string_printf("%s,,BLOCK01,%s", l->name.c_str(), s->name.c_str());
} else if (l->is_ep3()) {
location_string = string_printf("BLOCK01-C%02" PRIu32 ",,BLOCK01,%s", l->lobby_id - 15, s->name.c_str());
location_string = phosg::string_printf("BLOCK01-C%02" PRIu32 ",,BLOCK01,%s", l->lobby_id - 15, s->name.c_str());
} else {
location_string = string_printf("BLOCK01-%02" PRIu32 ",,BLOCK01,%s", l->lobby_id, s->name.c_str());
location_string = phosg::string_printf("BLOCK01-%02" PRIu32 ",,BLOCK01,%s", l->lobby_id, s->name.c_str());
}
result.location_string.encode(location_string, c->language());
result.reconnect_command_header.command = 0x19;
@@ -4133,7 +4131,7 @@ static void on_D8(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
}
void on_D9(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
strip_trailing_zeroes(data);
phosg::strip_trailing_zeroes(data);
bool is_w = uses_utf16(c->version());
if (is_w && (data.size() & 1)) {
data.push_back(0);
@@ -4146,7 +4144,7 @@ void on_D9(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
}
void on_C7(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
strip_trailing_zeroes(data);
phosg::strip_trailing_zeroes(data);
bool is_w = uses_utf16(c->version());
if (is_w && (data.size() & 1)) {
data.push_back(0);
@@ -4218,7 +4216,7 @@ shared_ptr<Lobby> create_game_generic(
if (!c->login->account->check_flag(Account::Flag::FREE_JOIN_GAMES) && (min_level > p->disp.stats.level)) {
// Note: We don't throw here because this is a situation players might
// actually encounter while playing the game normally
string msg = string_printf("You must be level %zu\nor above to play\nthis difficulty.", static_cast<size_t>(min_level + 1));
string msg = phosg::string_printf("You must be level %zu\nor above to play\nthis difficulty.", static_cast<size_t>(min_level + 1));
send_lobby_message_box(c, msg);
return nullptr;
}
@@ -4664,7 +4662,7 @@ static void on_6F(shared_ptr<Client> c, uint16_t command, uint32_t, string& data
if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
string variations_str;
for (size_t z = 0; z < l->variations.size(); z++) {
variations_str += string_printf("%" PRIX32, l->variations[z].load());
variations_str += phosg::string_printf("%" PRIX32, l->variations[z].load());
}
send_text_message_printf(c, "Rare seed: %08" PRIX32 "\nRare enemies: %zu\nVariations: %s\n",
l->random_seed, l->map->rare_enemy_indexes.size(), variations_str.c_str());
@@ -5147,7 +5145,7 @@ static void on_EA_BB(shared_ptr<Client> c, uint16_t command, uint32_t flag, stri
if (team) {
check_size_v(data.size(), sizeof(SC_TeamChat_BB_07EA) + 4, 0xFFFF);
static const string required_end("\0\0", 2);
if (ends_with(data, required_end)) {
if (phosg::ends_with(data, required_end)) {
for (const auto& it : team->members) {
try {
auto target_c = s->find_client(nullptr, it.second.account_id);
@@ -5383,7 +5381,7 @@ static on_command_t handlers[0x100][NUM_NON_PATCH_VERSIONS] = {
/* 10 */ {on_10, on_10, on_10, on_10, on_10, on_10, on_10, on_10, on_10, on_10, on_10, on_10},
/* 11 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 12 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 13 */ {on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_13_A7_GC, on_13_A7_GC, on_13_A7_GC, on_13_A7_GC, on_ignored, on_ignored},
/* 13 */ {on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4},
/* 14 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 15 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 16 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
@@ -5540,7 +5538,7 @@ static on_command_t handlers[0x100][NUM_NON_PATCH_VERSIONS] = {
/* A4 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* A5 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* A6 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored, nullptr},
/* A7 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, on_13_A7_GC, on_13_A7_GC, on_13_A7_GC, on_13_A7_GC, on_ignored, nullptr},
/* A7 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4, on_13_A7_V3_V4},
/* A8 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* A9 */ {on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9, on_A9},
/* AA */ {nullptr, nullptr, nullptr, nullptr, on_AA, on_AA, on_AA, on_AA, on_AA, on_AA, on_AA, on_AA},
+50 -50
View File
@@ -364,7 +364,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
c->log.info("Decompressed sync data (%zX -> %zX bytes; expected %zX):",
compressed_size, decompressed.size(), decompressed_size);
print_data(stderr, decompressed);
phosg::print_data(stderr, decompressed);
}
switch (subcommand_def->final_subcommand) {
@@ -372,7 +372,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
auto l = c->require_lobby();
if (l->map) {
l->log.info("Checking client enemy state against server state");
StringReader r(decompressed);
phosg::StringReader r(decompressed);
size_t count = r.size() / sizeof(G_SyncEnemyState_6x6B_Entry_Decompressed);
if (count != l->map->enemies.size()) {
l->log.warning("Enemy count from client (%zu) does not match enemy count from map (%zu)",
@@ -410,7 +410,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
auto l = c->require_lobby();
if (l->map) {
l->log.info("Checking client object state against server state");
StringReader r(decompressed);
phosg::StringReader r(decompressed);
size_t count = r.size() / sizeof(G_SyncObjectState_6x6C_Entry_Decompressed);
if (count > l->map->objects.size()) {
l->log.warning("Object count from client (%zu) exceeds object count from map (%zu)",
@@ -446,7 +446,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
case 0x6D: {
if (decompressed.size() < sizeof(G_SyncItemState_6x6D_Decompressed)) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed 6x6D data (0x%zX bytes) is too short for header (0x%zX bytes)",
decompressed.size(), sizeof(G_SyncItemState_6x6D_Decompressed)));
}
@@ -459,7 +459,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
size_t required_size = sizeof(G_SyncItemState_6x6D_Decompressed) + num_floor_items * sizeof(FloorItem);
if (decompressed.size() < required_size) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"decompressed 6x6D data (0x%zX bytes) is too short for all floor items (0x%zX bytes)",
decompressed.size(), required_size));
}
@@ -486,7 +486,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
break;
}
case 0x6E: {
StringReader r(decompressed);
phosg::StringReader r(decompressed);
const auto& dec_header = r.get<G_SyncSetFlagState_6x6E_Decompressed>();
if (dec_header.total_size != dec_header.entity_set_flags_size + dec_header.event_set_flags_size + dec_header.switch_flags_size) {
throw runtime_error("incorrect size fields in 6x6E header");
@@ -496,12 +496,12 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
if (l->map) {
l->log.info("Checking client set flag state against server state");
StringReader set_flags_r = r.sub(r.where(), dec_header.entity_set_flags_size);
phosg::StringReader set_flags_r = r.sub(r.where(), dec_header.entity_set_flags_size);
const auto& set_flags_header = set_flags_r.get<G_SyncSetFlagState_6x6E_Decompressed::EntitySetFlags>();
if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
c->log.info("Set flags data:");
print_data(stderr, set_flags_r.all());
phosg::print_data(stderr, set_flags_r.all());
}
if (set_flags_header.num_object_sets > l->map->objects.size()) {
@@ -539,10 +539,10 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
}
}
StringReader event_set_flags_r = r.sub(r.where() + dec_header.entity_set_flags_size, dec_header.event_set_flags_size);
phosg::StringReader event_set_flags_r = r.sub(r.where() + dec_header.entity_set_flags_size, dec_header.event_set_flags_size);
if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
c->log.info("Event flags data:");
print_data(stderr, event_set_flags_r.all());
phosg::print_data(stderr, event_set_flags_r.all());
}
size_t num_event_flags = event_set_flags_r.size() / sizeof(le_uint16_t);
if (num_event_flags != l->map->events.size()) {
@@ -571,7 +571,7 @@ static void on_sync_joining_player_compressed_state(shared_ptr<Client> c, uint8_
l->log.info("Switch flags size matches expected size (0x%zX)", expected_switch_flags_size);
}
if (l->switch_flags) {
StringReader switch_flags_r = r.sub(r.where() + dec_header.entity_set_flags_size + dec_header.event_set_flags_size);
phosg::StringReader switch_flags_r = r.sub(r.where() + dec_header.entity_set_flags_size + dec_header.event_set_flags_size);
for (size_t floor = 0; floor < expected_switch_flag_num_floors; floor++) {
// There is a bug in most (perhaps all) versions of the game, which
// causes this array to be too small. It looks like Sega forgot to
@@ -948,7 +948,7 @@ G_SyncPlayerDispAndInventory_BB_6x70 Parsed6x70Data::as_bb(shared_ptr<ServerStat
G_SyncPlayerDispAndInventory_BB_6x70 ret;
ret.base = this->base_v1();
ret.name.encode(this->name, language);
ret.base.visual.name.encode(string_printf("%10" PRId32, this->guild_card_number), language);
ret.base.visual.name.encode(phosg::string_printf("%10" PRId32, this->guild_card_number), language);
ret.stats = this->stats;
ret.num_items = this->num_items;
ret.items = this->items;
@@ -1202,7 +1202,7 @@ static void on_ep3_battle_subs(shared_ptr<Client> c, uint8_t command, uint8_t fl
}
if (!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING) && (c->version() != Version::GC_EP3_NTE)) {
set_mask_for_ep3_game_command(data.data(), data.size(), (random_object<uint32_t>() % 0xFF) + 1);
set_mask_for_ep3_game_command(data.data(), data.size(), (phosg::random_object<uint32_t>() % 0xFF) + 1);
}
forward_subcommand(c, command, flag, data.data(), data.size());
@@ -1267,9 +1267,9 @@ static void on_symbol_chat(shared_ptr<Client> c, uint8_t command, uint8_t flag,
}
}
template <bool SenderIsBigEndian>
template <bool SenderBE>
static void on_word_select_t(shared_ptr<Client> c, uint8_t command, uint8_t, void* data, size_t size) {
const auto& cmd = check_size_t<G_WordSelectT_6x74<SenderIsBigEndian>>(data, size);
const auto& cmd = check_size_t<G_WordSelectT_6x74<SenderBE>>(data, size);
if (c->can_chat && (cmd.client_id == c->lobby_client_id)) {
if (command_is_private(command)) {
return;
@@ -1695,7 +1695,7 @@ static void on_player_drop_item(shared_ptr<Client> c, uint8_t command, uint8_t f
auto item = p->remove_item(cmd.item_id, 0, *s->item_stack_limits(c->version()));
l->add_item(cmd.floor, item, cmd.x, cmd.z, 0x00F);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto s = c->require_server_state();
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu dropped item %08" PRIX32 " (%s) at %hu:(%g, %g)",
@@ -1764,7 +1764,7 @@ static void on_create_inventory_item_t(shared_ptr<Client> c, uint8_t command, ui
return;
}
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu created inventory item %08" PRIX32 " (%s) in inventory of NPC %02hX; ignoring", c->lobby_client_id, item.id.load(), name.c_str(), cmd.header.client_id.load());
}
@@ -1772,7 +1772,7 @@ static void on_create_inventory_item_t(shared_ptr<Client> c, uint8_t command, ui
} else {
c->character()->add_item(item, *s->item_stack_limits(c->version()));
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu created inventory item %08" PRIX32 " (%s)", c->lobby_client_id, item.id.load(), name.c_str());
c->print_inventory(stderr);
@@ -1812,7 +1812,7 @@ static void on_drop_partial_stack_t(shared_ptr<Client> c, uint8_t command, uint8
l->on_item_id_generated_externally(item.id);
l->add_item(cmd.floor, item, cmd.x, cmd.z, 0x00F);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto s = c->require_server_state();
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu split stack to create floor item %08" PRIX32 " (%s) at %hu:(%g, %g)",
@@ -1862,7 +1862,7 @@ static void on_drop_partial_stack_bb(shared_ptr<Client> c, uint8_t command, uint
l->add_item(cmd.floor, item, cmd.x, cmd.z, 0x00F);
send_drop_stacked_item_to_lobby(l, item, cmd.floor, cmd.x, cmd.z);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto s = c->require_server_state();
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu split stack %08" PRIX32 " (removed: %s) at %hu:(%g, %g)",
@@ -1897,7 +1897,7 @@ static void on_buy_shop_item(shared_ptr<Client> c, uint8_t command, uint8_t flag
size_t price = s->item_parameter_table(c->version())->price_for_item(item);
p->remove_meseta(price, c->version() != Version::BB_V4);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu bought item %08" PRIX32 " (%s) from shop (%zu Meseta)",
cmd.header.client_id.load(), item.id.load(), name.c_str(), price);
@@ -2040,7 +2040,7 @@ static void on_pick_up_item_generic(
return;
}
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto s = c->require_server_state();
auto name = s->describe_item(c->version(), fi->data, false);
l->log.info("Player %hu picked up %08" PRIX32 " (%s)", client_id, item_id, name.c_str());
@@ -2079,12 +2079,12 @@ static void on_pick_up_item_generic(
string desc_http = s->describe_item(c->version(), fi->data, false);
if (s->http_server) {
auto message = make_shared<JSON>(JSON::dict({
auto message = make_shared<phosg::JSON>(phosg::JSON::dict({
{"PlayerAccountID", c->login->account->account_id},
{"PlayerName", p_name},
{"PlayerVersion", name_for_enum(c->version())},
{"PlayerVersion", phosg::name_for_enum(c->version())},
{"GameName", l->name},
{"GameDropMode", name_for_enum(l->drop_mode)},
{"GameDropMode", phosg::name_for_enum(l->drop_mode)},
{"ItemData", fi->data.hex()},
{"ItemDescription", desc_http},
{"NotifyGame", should_send_game_notif},
@@ -2093,8 +2093,8 @@ static void on_pick_up_item_generic(
s->http_server->send_rare_drop_notification(message);
}
string message = string_printf("$C6%s$C7 found\n%s", p_name.c_str(), desc_ingame.c_str());
string bb_message = string_printf("$C6%s$C7 has found %s", p_name.c_str(), desc_ingame.c_str());
string message = phosg::string_printf("$C6%s$C7 found\n%s", p_name.c_str(), desc_ingame.c_str());
string bb_message = phosg::string_printf("$C6%s$C7 has found %s", p_name.c_str(), desc_ingame.c_str());
if (should_send_global_notif) {
for (auto& it : s->channel_to_client) {
if (it.second->login &&
@@ -2177,7 +2177,7 @@ static void on_use_item(
}
player_use_item(c, index, l->opt_rand_crypt);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
l->log.info("Player %hhu used item %hu:%08" PRIX32 " (%s)",
c->lobby_client_id, cmd.header.client_id.load(), cmd.item_id.load(), name.c_str());
c->print_inventory(stderr);
@@ -2222,7 +2222,7 @@ static void on_feed_mag(
p->remove_item(cmd.fed_item_id, 1, *s->item_stack_limits(c->version()));
}
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
l->log.info("Player %hhu fed item %hu:%08" PRIX32 " (%s) to mag %hu:%08" PRIX32 " (%s)",
c->lobby_client_id, cmd.header.client_id.load(), cmd.fed_item_id.load(), fed_name.c_str(),
cmd.header.client_id.load(), cmd.mag_item_id.load(), mag_name.c_str());
@@ -2372,7 +2372,7 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint
bank.add_item(item, limits);
send_destroy_item_to_lobby(c, cmd.item_id, cmd.item_amount, true);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
string name = s->describe_item(Version::BB_V4, item, false);
l->log.info("Player %hu deposited item %08" PRIX32 " (x%hhu) (%s) in the bank",
c->lobby_client_id, cmd.item_id.load(), cmd.item_amount, name.c_str());
@@ -2402,7 +2402,7 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint
p->add_item(item, limits);
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
string name = s->describe_item(Version::BB_V4, item, false);
l->log.info("Player %hu withdrew item %08" PRIX32 " (x%hhu) (%s) from the bank",
c->lobby_client_id, item.id.load(), cmd.item_amount, name.c_str());
@@ -2559,7 +2559,7 @@ G_SpecializableItemDropRequest_6xA2 normalize_drop_request(const void* data, siz
}
DropReconcileResult reconcile_drop_request_with_map(
PrefixedLogger& log,
phosg::PrefixedLogger& log,
Channel& client_channel,
G_SpecializableItemDropRequest_6xA2& cmd,
Version version,
@@ -2605,7 +2605,7 @@ DropReconcileResult reconcile_drop_request_with_map(
} else {
if (map) {
map_enemy = &map->enemies.at(cmd.entity_id);
log.info("Drop check for E-%hX %s", map_enemy->enemy_id, name_for_enum(map_enemy->type));
log.info("Drop check for E-%hX %s", map_enemy->enemy_id, phosg::name_for_enum(map_enemy->type));
res.effective_rt_index = rare_table_index_for_enemy_type(map_enemy->type);
// rt_indexes in Episode 4 don't match those sent in the command; we just
// ignore what the client sends.
@@ -2630,7 +2630,7 @@ DropReconcileResult reconcile_drop_request_with_map(
cmd.floor, map_enemy->floor);
}
if (config.check_flag(Client::Flag::DEBUG_ENABLED)) {
send_text_message_printf(client_channel, "$C5E-%hX %s", map_enemy->enemy_id, name_for_enum(map_enemy->type));
send_text_message_printf(client_channel, "$C5E-%hX %s", map_enemy->enemy_id, phosg::name_for_enum(map_enemy->type));
}
}
}
@@ -2835,7 +2835,7 @@ static void on_set_quest_flag(shared_ptr<Client> c, uint8_t command, uint8_t fla
}
if (boss_enemy_type != EnemyType::NONE) {
l->log.info("Creating item from final boss (%s)", name_for_enum(boss_enemy_type));
l->log.info("Creating item from final boss (%s)", phosg::name_for_enum(boss_enemy_type));
uint16_t enemy_id = 0xFFFF;
if (l->map) {
try {
@@ -2959,7 +2959,7 @@ static void on_set_entity_set_flag(shared_ptr<Client> c, uint8_t command, uint8_
event->flags = (event->flags | 0x18) & (~4);
l->log.info("Set flags on W-%02hhX-%" PRIX32 " to %04hX", event->floor, event->event_id, event->flags);
StringReader actions_r(l->map->event_action_stream);
phosg::StringReader actions_r(l->map->event_action_stream);
actions_r.go(event->action_stream_offset);
while (!actions_r.eof()) {
uint8_t opcode = actions_r.get_u8();
@@ -3284,9 +3284,9 @@ static void send_max_level_notification_if_needed(shared_ptr<Client> c) {
if (p->disp.stats.level == max_level) {
string name = p->disp.name.decode(c->language());
size_t level_for_str = max_level + 1;
string message = string_printf("$C6%s$C7\nGC: %" PRIu32 "\nhas reached Level $C6%zu",
string message = phosg::string_printf("$C6%s$C7\nGC: %" PRIu32 "\nhas reached Level $C6%zu",
name.c_str(), c->login->account->account_id, level_for_str);
string bb_message = string_printf("$C6%s$C7 (GC: %" PRIu32 ") has reached Level $C6%zu",
string bb_message = phosg::string_printf("$C6%s$C7 (GC: %" PRIu32 ") has reached Level $C6%zu",
name.c_str(), c->login->account->account_id, level_for_str);
for (auto& it : s->channel_to_client) {
if ((it.second != c) && it.second->login && !is_patch(it.second->version()) && it.second->lobby.lock()) {
@@ -3409,7 +3409,7 @@ static void on_steal_exp_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* data,
c->log.info("Stolen EXP with bp_index=%" PRIX32 " enemy_exp=%" PRIu32 " percent=%g stolen_exp=%" PRIu32,
bp_index, enemy_exp, percent, stolen_exp);
send_text_message_printf(c, "$C5+%" PRIu32 " E-%hX %s",
stolen_exp, cmd.enemy_index.load(), name_for_enum(enemy.type));
stolen_exp, cmd.enemy_index.load(), phosg::name_for_enum(enemy.type));
}
add_player_exp(c, stolen_exp);
}
@@ -3500,7 +3500,7 @@ static void on_enemy_exp_request_bb(shared_ptr<Client> c, uint8_t, uint8_t, void
lc, "$C5+%" PRIu32 " E-%hX %s",
player_exp,
cmd.enemy_index.load(),
name_for_enum(e.type));
phosg::name_for_enum(e.type));
}
if (lc->character()->disp.stats.level < 199) {
add_player_exp(lc, player_exp);
@@ -3570,7 +3570,7 @@ void on_item_reward_request_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* dat
try {
c->character()->add_item(item, limits);
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu created inventory item %08" PRIX32 " (%s) via quest command",
c->lobby_client_id, item.id.load(), name.c_str());
@@ -3578,7 +3578,7 @@ void on_item_reward_request_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* dat
}
} catch (const out_of_range&) {
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hu attempted to create inventory item %08" PRIX32 " (%s) via quest command, but it cannot be placed in their inventory",
c->lobby_client_id, item.id.load(), name.c_str());
@@ -3610,7 +3610,7 @@ void on_transfer_item_via_mail_message_bb(shared_ptr<Client> c, uint8_t command,
const auto& limits = *s->item_stack_limits(c->version());
auto item = p->remove_item(cmd.item_id, cmd.amount, limits);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hhu sent inventory item %hu:%08" PRIX32 " (%s) x%" PRIu32 " to player %08" PRIX32,
c->lobby_client_id, cmd.header.client_id.load(), cmd.item_id.load(), name.c_str(), cmd.amount.load(), cmd.target_guild_card_number.load());
@@ -3671,7 +3671,7 @@ void on_exchange_item_for_team_points_bb(shared_ptr<Client> c, uint8_t command,
size_t points = s->item_parameter_table(Version::BB_V4)->get_item_team_points(item);
s->team_index->add_member_points(c->login->account->account_id, points);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hhu exchanged inventory item %hu:%08" PRIX32 " (%s) for %zu team points",
c->lobby_client_id, cmd.header.client_id.load(), cmd.item_id.load(), name.c_str(), points);
@@ -3696,7 +3696,7 @@ static void on_destroy_inventory_item(shared_ptr<Client> c, uint8_t command, uin
auto p = c->character();
auto item = p->remove_item(cmd.item_id, cmd.amount, *s->item_stack_limits(c->version()));
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hhu destroyed inventory item %hu:%08" PRIX32 " (%s)",
c->lobby_client_id, cmd.header.client_id.load(), cmd.item_id.load(), name.c_str());
@@ -3843,7 +3843,7 @@ static void on_sell_item_at_shop_bb(shared_ptr<Client> c, uint8_t command, uint8
size_t price = (s->item_parameter_table(c->version())->price_for_item(item) >> 3) * cmd.amount;
p->add_meseta(price);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hhu sold inventory item %08" PRIX32 " (%s) for %zu Meseta",
c->lobby_client_id, cmd.item_id.load(), name.c_str(), price);
@@ -3879,7 +3879,7 @@ static void on_buy_shop_item_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* da
p->add_item(item, limits);
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item, true);
if (l->log.should_log(LogLevel::INFO)) {
if (l->log.should_log(phosg::LogLevel::INFO)) {
auto s = c->require_server_state();
auto name = s->describe_item(c->version(), item, false);
l->log.info("Player %hhu purchased item %08" PRIX32 " (%s) for %zu meseta",
@@ -4395,7 +4395,7 @@ static void on_quest_F960_result_bb(shared_ptr<Client> c, uint8_t, uint8_t, void
auto s = c->require_server_state();
auto p = c->character();
time_t t_secs = now() / 1000000;
time_t t_secs = phosg::now() / 1000000;
struct tm t_parsed;
gmtime_r(&t_secs, &t_parsed);
size_t weekday = t_parsed.tm_wday;
@@ -4442,12 +4442,12 @@ static void on_quest_F960_result_bb(shared_ptr<Client> c, uint8_t, uint8_t, void
try {
p->add_item(item, *s->item_stack_limits(c->version()));
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
if (c->log.should_log(LogLevel::INFO)) {
if (c->log.should_log(phosg::LogLevel::INFO)) {
string name = s->describe_item(c->version(), item, false);
c->log.info("Awarded item %s", name.c_str());
}
} catch (const out_of_range&) {
if (c->log.should_log(LogLevel::INFO)) {
if (c->log.should_log(phosg::LogLevel::INFO)) {
string name = s->describe_item(c->version(), item, false);
c->log.info("Attempted to award item %s, but inventory was full", name.c_str());
}
+1 -1
View File
@@ -28,7 +28,7 @@ struct DropReconcileResult {
};
DropReconcileResult reconcile_drop_request_with_map(
PrefixedLogger& log,
phosg::PrefixedLogger& log,
Channel& client_channel,
G_SpecializableItemDropRequest_6xA2& cmd,
Version version,
+51 -53
View File
@@ -19,13 +19,13 @@ ReplaySession::Event::Event(Type type, uint64_t client_id, size_t line_num)
string ReplaySession::Event::str() const {
string ret;
if (this->type == Type::CONNECT) {
ret = string_printf("Event[%" PRIu64 ", CONNECT", this->client_id);
ret = phosg::string_printf("Event[%" PRIu64 ", CONNECT", this->client_id);
} else if (this->type == Type::DISCONNECT) {
ret = string_printf("Event[%" PRIu64 ", DISCONNECT", this->client_id);
ret = phosg::string_printf("Event[%" PRIu64 ", DISCONNECT", this->client_id);
} else if (this->type == Type::SEND) {
ret = string_printf("Event[%" PRIu64 ", SEND %04zX", this->client_id, this->data.size());
ret = phosg::string_printf("Event[%" PRIu64 ", SEND %04zX", this->client_id, this->data.size());
} else if (this->type == Type::RECEIVE) {
ret = string_printf("Event[%" PRIu64 ", RECEIVE %04zX", this->client_id, this->data.size());
ret = phosg::string_printf("Event[%" PRIu64 ", RECEIVE %04zX", this->client_id, this->data.size());
}
if (this->allow_size_disparity) {
ret += ", size disparity allowed";
@@ -33,7 +33,7 @@ string ReplaySession::Event::str() const {
if (this->complete) {
ret += ", done";
}
ret += string_printf(", ev-line %zu]", this->line_num);
ret += phosg::string_printf(", ev-line %zu]", this->line_num);
return ret;
}
@@ -48,11 +48,10 @@ ReplaySession::Client::Client(
&ReplaySession::dispatch_on_command_received,
&ReplaySession::dispatch_on_error,
session,
string_printf("R-%" PRIX64, this->id)) {}
phosg::string_printf("R-%" PRIX64, this->id)) {}
string ReplaySession::Client::str() const {
return string_printf("Client[%" PRIu64 ", T-%hu, %s]",
this->id, this->port, name_for_enum(this->version));
return phosg::string_printf("Client[%" PRIu64 ", T-%hu, %s]", this->id, this->port, phosg::name_for_enum(this->version));
}
shared_ptr<ReplaySession::Event> ReplaySession::create_event(
@@ -88,14 +87,14 @@ void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
auto check_pw = [&](const string& pw) {
if (this->require_basic_credentials && !string_is_basic(pw)) {
print_data(stderr, ev->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(string_printf("(ev-line %zu) sent password is incorrect", ev->line_num));
phosg::print_data(stderr, ev->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(phosg::string_printf("(ev-line %zu) sent password is incorrect", ev->line_num));
}
};
auto check_ak = [&](const string& ak) {
if (this->require_basic_credentials && !ak.empty() && !string_is_basic(ak)) {
print_data(stderr, ev->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(string_printf("(ev-line %zu) sent access key is incorrect", ev->line_num));
phosg::print_data(stderr, ev->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(phosg::string_printf("(ev-line %zu) sent access key is incorrect", ev->line_num));
}
};
auto check_either = [&](const string& s) {
@@ -472,8 +471,8 @@ ReplaySession::ReplaySession(
size_t num_events = 0;
while (!feof(input_log)) {
line_num++;
string line = fgets(input_log);
if (ends_with(line, "\n")) {
string line = phosg::fgets(input_log);
if (phosg::ends_with(line, "\n")) {
line.resize(line.size() - 1);
}
if (line.empty()) {
@@ -481,12 +480,11 @@ ReplaySession::ReplaySession(
}
if (parsing_command.get()) {
string expected_start = string_printf("%04zX |", parsing_command->data.size());
if (starts_with(line, expected_start)) {
string expected_start = phosg::string_printf("%04zX |", parsing_command->data.size());
if (phosg::starts_with(line, expected_start)) {
// Parse out the hex part of the hex/ASCII dump
string mask_bytes;
string data_bytes = parse_data_string(
line.substr(expected_start.size(), 16 * 3 + 1), &mask_bytes);
string data_bytes = phosg::parse_data_string(line.substr(expected_start.size(), 16 * 3 + 1), &mask_bytes);
parsing_command->data += data_bytes;
parsing_command->mask += mask_bytes;
continue;
@@ -500,30 +498,30 @@ ReplaySession::ReplaySession(
}
}
if (starts_with(line, "I ")) {
if (phosg::starts_with(line, "I ")) {
// I <pid/ts> - [Server] Client connected: C-%X on fd %d via %d (T-%hu-%s-%s-%s)
// I <pid/ts> - [Server] Client connected: C-%X on virtual connection %p via T-%hu-VI
size_t offset = line.find(" - [Server] Client connected: C-");
if (offset != string::npos) {
auto tokens = split(line, ' ');
auto tokens = phosg::split(line, ' ');
if (tokens.size() != 15) {
throw runtime_error(string_printf("(ev-line %zu) client connection message has incorrect token count", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) client connection message has incorrect token count", line_num));
}
if (!starts_with(tokens[8], "C-")) {
throw runtime_error(string_printf("(ev-line %zu) client connection message missing client ID token", line_num));
if (!phosg::starts_with(tokens[8], "C-")) {
throw runtime_error(phosg::string_printf("(ev-line %zu) client connection message missing client ID token", line_num));
}
auto listen_tokens = split(tokens[14], '-');
auto listen_tokens = phosg::split(tokens[14], '-');
if (listen_tokens.size() < 4) {
throw runtime_error(string_printf("(ev-line %zu) client connection message listening socket token format is incorrect", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) client connection message listening socket token format is incorrect", line_num));
}
auto c = make_shared<Client>(
this,
stoull(tokens[8].substr(2), nullptr, 16),
stoul(listen_tokens[1], nullptr, 10),
enum_for_name<Version>(listen_tokens[2].c_str()));
phosg::enum_for_name<Version>(listen_tokens[2].c_str()));
if (!this->clients.emplace(c->id, c).second) {
throw runtime_error(string_printf("(ev-line %zu) duplicate client ID in input log", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) duplicate client ID in input log", line_num));
}
this->create_event(Event::Type::CONNECT, c, line_num);
num_events++;
@@ -533,23 +531,23 @@ ReplaySession::ReplaySession(
// I <pid/ts> - [Server] Disconnecting C-%X on fd %d
offset = line.find(" - [Server] Client disconnected: C-");
if (offset != string::npos) {
auto tokens = split(line, ' ');
auto tokens = phosg::split(line, ' ');
if (tokens.size() < 9) {
throw runtime_error(string_printf("(ev-line %zu) client disconnection message has incorrect token count", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) client disconnection message has incorrect token count", line_num));
}
if (!starts_with(tokens[8], "C-")) {
throw runtime_error(string_printf("(ev-line %zu) client disconnection message missing client ID token", line_num));
if (!phosg::starts_with(tokens[8], "C-")) {
throw runtime_error(phosg::string_printf("(ev-line %zu) client disconnection message missing client ID token", line_num));
}
uint64_t client_id = stoul(tokens[8].substr(2), nullptr, 16);
try {
auto& c = this->clients.at(client_id);
if (c->disconnect_event.get()) {
throw runtime_error(string_printf("(ev-line %zu) client has multiple disconnect events", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) client has multiple disconnect events", line_num));
}
c->disconnect_event = this->create_event(Event::Type::DISCONNECT, c, line_num);
num_events++;
} catch (const out_of_range&) {
throw runtime_error(string_printf("(ev-line %zu) unknown disconnecting client ID in input log", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) unknown disconnecting client ID in input log", line_num));
}
continue;
}
@@ -561,9 +559,9 @@ ReplaySession::ReplaySession(
offset = line.find(" - [Commands] Received from C-");
}
if (offset != string::npos) {
auto tokens = split(line, ' ');
auto tokens = phosg::split(line, ' ');
if (tokens.size() < 10) {
throw runtime_error(string_printf("(ev-line %zu) command header line too short", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) command header line too short", line_num));
}
bool from_client = (tokens[6] == "Received");
uint64_t client_id = stoull(tokens[8].substr(2), nullptr, 16);
@@ -574,7 +572,7 @@ ReplaySession::ReplaySession(
line_num);
num_events++;
} catch (const out_of_range&) {
throw runtime_error(string_printf("(ev-line %zu) input log contains command for missing client", line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) input log contains command for missing client", line_num));
}
continue;
}
@@ -605,7 +603,7 @@ void ReplaySession::update_timeout_event() {
event_new(this->base.get(), -1, EV_TIMEOUT, this->dispatch_on_timeout, this),
event_free);
}
struct timeval tv = usecs_to_timeval(3000000);
struct timeval tv = phosg::usecs_to_timeval(3000000);
event_add(this->timeout_ev.get(), &tv);
}
@@ -624,7 +622,7 @@ void ReplaySession::execute_pending_events() {
switch (this->first_event->type) {
case Event::Type::CONNECT: {
if (c->channel.connected()) {
throw runtime_error(string_printf("(ev-line %zu) connect event on already-connected client", this->first_event->line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) connect event on already-connected client", this->first_event->line_num));
}
struct bufferevent* bevs[2];
@@ -638,17 +636,17 @@ void ReplaySession::execute_pending_events() {
port_config = this->state->number_to_port_config.at(c->port);
} catch (const out_of_range&) {
bufferevent_free(bevs[1]);
throw runtime_error(string_printf("(ev-line %zu) client connected to port missing from configuration", this->first_event->line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) client connected to port missing from configuration", this->first_event->line_num));
}
if (port_config->behavior == ServerBehavior::PROXY_SERVER) {
// TODO: We should support this at some point in the future
throw runtime_error(string_printf("(ev-line %zu) client connected to proxy server", this->first_event->line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) client connected to proxy server", this->first_event->line_num));
} else if (this->state->game_server.get()) {
this->state->game_server->connect_virtual_client(bevs[1], 0, 0x20202020,
1025, c->port, port_config->version, port_config->behavior);
} else {
throw runtime_error(string_printf("(ev-line %zu) no server available for connection", this->first_event->line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) no server available for connection", this->first_event->line_num));
bufferevent_free(bevs[1]);
}
break;
@@ -659,7 +657,7 @@ void ReplaySession::execute_pending_events() {
break;
case Event::Type::SEND:
if (!c->channel.connected()) {
throw runtime_error(string_printf("(ev-line %zu) send event attempted on unconnected client", this->first_event->line_num));
throw runtime_error(phosg::string_printf("(ev-line %zu) send event attempted on unconnected client", this->first_event->line_num));
}
c->channel.send(this->first_event->data);
this->commands_sent++;
@@ -706,7 +704,7 @@ void ReplaySession::dispatch_on_error(Channel& ch, short events) {
void ReplaySession::on_command_received(
shared_ptr<Client> c, uint16_t command, uint32_t flag, string& data) {
// TODO: Use the iovec form of print_data here instead of
// TODO: Use the iovec form of phosg::print_data here instead of
// prepend_command_header (which copies the string)
string full_command = prepend_command_header(
c->version, c->channel.crypt_in.get(), command, flag, data);
@@ -714,25 +712,25 @@ void ReplaySession::on_command_received(
this->bytes_received += full_command.size();
if (c->receive_events.empty()) {
print_data(stderr, full_command, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stderr, full_command, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
throw runtime_error("received unexpected command for client");
}
auto& ev = c->receive_events.front();
if ((full_command.size() != ev->data.size()) && !ev->allow_size_disparity) {
replay_log.error("Expected command:");
print_data(stderr, ev->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stderr, ev->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
replay_log.error("Received command:");
print_data(stderr, full_command, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(string_printf("(ev-line %zu) received command sizes do not match", ev->line_num));
phosg::print_data(stderr, full_command, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(phosg::string_printf("(ev-line %zu) received command sizes do not match", ev->line_num));
}
for (size_t x = 0; x < min<size_t>(full_command.size(), ev->data.size()); x++) {
if ((full_command[x] & ev->mask[x]) != (ev->data[x] & ev->mask[x])) {
replay_log.error("Expected command:");
print_data(stderr, ev->data, 0, nullptr, PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
phosg::print_data(stderr, ev->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
replay_log.error("Received command:");
print_data(stderr, full_command, 0, ev->data.data(), PrintDataFlags::PRINT_ASCII | PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(string_printf("(ev-line %zu) received command data does not match expected data", ev->line_num));
phosg::print_data(stderr, full_command, 0, ev->data.data(), phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::OFFSET_16_BITS);
throw runtime_error(phosg::string_printf("(ev-line %zu) received command data does not match expected data", ev->line_num));
}
}
@@ -792,15 +790,15 @@ void ReplaySession::on_command_received(
void ReplaySession::on_error(shared_ptr<Client> c, short events) {
if (events & BEV_EVENT_ERROR) {
throw runtime_error(string_printf("C-%" PRIX64 " caused stream error", c->id));
throw runtime_error(phosg::string_printf("C-%" PRIX64 " caused stream error", c->id));
}
if (events & BEV_EVENT_EOF) {
if (!c->disconnect_event.get()) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"C-%" PRIX64 " disconnected, but has no disconnect event", c->id));
}
if (!c->receive_events.empty()) {
throw runtime_error(string_printf(
throw runtime_error(phosg::string_printf(
"C-%" PRIX64 " disconnected, but has pending receive events", c->id));
}
c->disconnect_event->complete = true;
+15 -15
View File
@@ -144,13 +144,13 @@ bool PSOVMSFileHeader::checksum_correct() const {
}
bool PSOGCIFileHeader::checksum_correct() const {
uint32_t cs = crc32(&this->game_name, this->game_name.bytes());
cs = crc32(&this->embedded_seed, sizeof(this->embedded_seed), cs);
cs = crc32(&this->file_name, this->file_name.bytes(), cs);
cs = crc32(&this->banner, this->banner.bytes(), cs);
cs = crc32(&this->icon, this->icon.bytes(), cs);
cs = crc32(&this->data_size, sizeof(this->data_size), cs);
cs = crc32("\0\0\0\0", 4, cs); // this->checksum (treated as zero)
uint32_t cs = phosg::crc32(&this->game_name, this->game_name.bytes());
cs = phosg::crc32(&this->embedded_seed, sizeof(this->embedded_seed), cs);
cs = phosg::crc32(&this->file_name, this->file_name.bytes(), cs);
cs = phosg::crc32(&this->banner, this->banner.bytes(), cs);
cs = phosg::crc32(&this->icon, this->icon.bytes(), cs);
cs = phosg::crc32(&this->data_size, sizeof(this->data_size), cs);
cs = phosg::crc32("\0\0\0\0", 4, cs); // this->checksum (treated as zero)
return (cs == this->checksum);
}
@@ -217,8 +217,8 @@ string decrypt_gci_fixed_size_data_section_for_salvage(
}
bool PSOGCSnapshotFile::checksum_correct() const {
uint32_t crc = crc32("\0\0\0\0", 4);
crc = crc32(&this->width, sizeof(*this) - sizeof(this->checksum), crc);
uint32_t crc = phosg::crc32("\0\0\0\0", 4);
crc = phosg::crc32(&this->width, sizeof(*this) - sizeof(this->checksum), crc);
return (crc == this->checksum);
}
@@ -231,7 +231,7 @@ static uint32_t decode_rgb565(uint16_t c) {
0x000000FF; // A
}
Image PSOGCSnapshotFile::decode_image() const {
phosg::Image PSOGCSnapshotFile::decode_image() const {
size_t width = this->width ? this->width.load() : 256;
size_t height = this->height ? this->height.load() : 192;
if (width != 256) {
@@ -242,7 +242,7 @@ Image PSOGCSnapshotFile::decode_image() const {
}
// 4x4 blocks of pixels
Image ret(width, height, false);
phosg::Image ret(width, height, false);
size_t offset = 0;
for (size_t y = 0; y < this->height; y += 4) {
for (size_t x = 0; x < this->width; x += 4) {
@@ -322,12 +322,12 @@ void PSOBBGuildCardFile::Entry::clear() {
}
uint32_t PSOBBGuildCardFile::checksum() const {
return crc32(this, sizeof(*this));
return phosg::crc32(this, sizeof(*this));
}
PSOBBBaseSystemFile::PSOBBBaseSystemFile() {
// This field is based on 1/1/2000, not 1/1/1970, so adjust appropriately
this->base.creation_timestamp = (now() - 946684800000000ULL) / 1000000;
this->base.creation_timestamp = (phosg::now() - 946684800000000ULL) / 1000000;
for (size_t z = 0; z < DEFAULT_KEY_CONFIG.size(); z++) {
this->key_config[z] = DEFAULT_KEY_CONFIG[z];
}
@@ -1170,7 +1170,7 @@ static uint16_t crc16(const void* data, size_t size) {
};
uint16_t ret = 0xFFFF;
StringReader r(data, size);
phosg::StringReader r(data, size);
while (!r.eof()) {
ret = (ret >> 8) ^ table[r.get_u8() ^ (ret & 0xFF)];
}
@@ -1184,7 +1184,7 @@ string encode_psobb_hangame_credentials(const string& user_id, const string& tok
if (user_id.size() > 12) {
throw runtime_error("user_id must be at most 12 characters");
}
if (!ends_with(user_id, "@HG")) {
if (!phosg::ends_with(user_id, "@HG")) {
throw runtime_error("user_id must end with \"@HG\"");
}
if (token.empty()) {
+51 -62
View File
@@ -98,14 +98,12 @@ struct ShuffleTables {
void shuffle(void* vdest, const void* vsrc, size_t size, bool reverse) const;
};
template <bool IsBigEndian, TextEncoding Encoding, size_t NameLength>
template <bool BE, TextEncoding Encoding, size_t NameLength>
struct SaveFileSymbolChatEntryT {
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
/* PC:GC:XB:BB */
/* 00:00:00:00 */ U32T present;
/* 00:00:00:00 */ U32T<BE> present;
/* 04:04:04:04 */ pstring<Encoding, NameLength> name;
/* 34:1C:1C:2C */ SymbolChatT<IsBigEndian> spec;
/* 34:1C:1C:2C */ SymbolChatT<BE> spec;
/* 70:58:58:68 */
} __packed__;
using SaveFileSymbolChatEntryPC = SaveFileSymbolChatEntryT<false, TextEncoding::UTF16, 0x18>;
@@ -117,19 +115,16 @@ check_struct_size(SaveFileSymbolChatEntryGC, 0x58);
check_struct_size(SaveFileSymbolChatEntryDCXB, 0x58);
check_struct_size(SaveFileSymbolChatEntryBB, 0x68);
template <bool IsBigEndian>
template <bool BE>
struct WordSelectMessageT {
using U16T = std::conditional_t<IsBigEndian, be_uint16_t, le_uint16_t>;
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
U16T<BE> num_tokens = 0;
U16T<BE> target_type = 0;
parray<U16T<BE>, 8> tokens;
U32T<BE> numeric_parameter = 0;
U32T<BE> unknown_a4 = 0;
U16T num_tokens = 0;
U16T target_type = 0;
parray<U16T, 8> tokens;
U32T numeric_parameter = 0;
U32T unknown_a4 = 0;
operator WordSelectMessageT<!IsBigEndian>() const {
WordSelectMessageT<!IsBigEndian> ret;
operator WordSelectMessageT<!BE>() const {
WordSelectMessageT<!BE> ret;
ret.num_tokens = this->num_tokens.load();
ret.target_type = this->target_type.load();
for (size_t z = 0; z < this->tokens.size(); z++) {
@@ -145,14 +140,12 @@ using WordSelectMessageBE = WordSelectMessageT<true>;
check_struct_size(WordSelectMessage, 0x1C);
check_struct_size(WordSelectMessageBE, 0x1C);
template <bool IsBigEndian, TextEncoding Encoding, size_t MaxChars>
template <bool BE, TextEncoding Encoding, size_t MaxChars>
struct SaveFileChatShortcutEntryT {
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
union Definition {
pstring<Encoding, MaxChars> text;
WordSelectMessageT<IsBigEndian> word_select;
SymbolChatT<IsBigEndian> symbol_chat;
WordSelectMessageT<BE> word_select;
SymbolChatT<BE> symbol_chat;
Definition() : text() {}
Definition(const Definition& other) : text(other.text) {}
@@ -163,13 +156,13 @@ struct SaveFileChatShortcutEntryT {
} __packed__;
/* DC:GC:BB */
/* 00:00:00 */ U32T type; // 1 = text, 2 = word select, 3 = symbol chat
/* 00:00:00 */ U32T<BE> type; // 1 = text, 2 = word select, 3 = symbol chat
/* 04:04:04 */ Definition definition;
/* 40:54:A4 */
template <bool RetIsBigEndian, TextEncoding RetEncoding, size_t RetMaxSize>
SaveFileChatShortcutEntryT<RetIsBigEndian, RetEncoding, RetMaxSize> convert(uint8_t language) const {
SaveFileChatShortcutEntryT<RetIsBigEndian, RetEncoding, RetMaxSize> ret;
template <bool RetBE, TextEncoding RetEncoding, size_t RetMaxSize>
SaveFileChatShortcutEntryT<RetBE, RetEncoding, RetMaxSize> convert(uint8_t language) const {
SaveFileChatShortcutEntryT<RetBE, RetEncoding, RetMaxSize> ret;
ret.type = this->type.load();
switch (ret.type) {
case 1:
@@ -835,7 +828,7 @@ struct PSOGCSnapshotFile {
/* 1818C */
bool checksum_correct() const;
Image decode_image() const;
phosg::Image decode_image() const;
} __packed_ws__(PSOGCSnapshotFile, 0x1818C);
////////////////////////////////////////////////////////////////////////////////
@@ -882,7 +875,7 @@ struct LegacySavedAccountDataBB { // .nsa file format
////////////////////////////////////////////////////////////////////////////////
// Encoding/decoding functions
template <bool IsBigEndian>
template <bool BE>
std::string decrypt_data_section(const void* data_section, size_t size, uint32_t round1_seed, size_t max_decrypt_bytes = 0) {
if (max_decrypt_bytes == 0) {
max_decrypt_bytes = size;
@@ -899,19 +892,19 @@ std::string decrypt_data_section(const void* data_section, size_t size, uint32_t
decrypted.resize((decrypted.size() + 3) & (~3));
PSOV2Encryption round1_crypt(round1_seed);
round1_crypt.encrypt_minus_t<IsBigEndian>(decrypted.data(), decrypted.size());
round1_crypt.encrypt_minus_t<BE>(decrypted.data(), decrypted.size());
decrypted.resize(orig_size);
return decrypted;
}
template <bool IsBigEndian>
template <bool BE>
std::string encrypt_data_section(const void* data_section, size_t size, uint32_t round1_seed) {
std::string encrypted(reinterpret_cast<const char*>(data_section), size);
encrypted.resize((encrypted.size() + 3) & (~3));
PSOV2Encryption crypt(round1_seed);
crypt.encrypt_minus_t<IsBigEndian>(encrypted.data(), encrypted.size());
crypt.encrypt_minus_t<BE>(encrypted.data(), encrypted.size());
std::string ret(size, '\0');
PSOV2Encryption shuf_crypt(round1_seed);
@@ -921,38 +914,36 @@ std::string encrypt_data_section(const void* data_section, size_t size, uint32_t
return ret;
}
template <bool IsBigEndian>
template <bool BE>
std::string decrypt_fixed_size_data_section_s(
const void* data_section,
size_t size,
uint32_t round1_seed,
bool skip_checksum = false,
uint64_t override_round2_seed = 0xFFFFFFFFFFFFFFFF) {
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
if (size < 2 * sizeof(U32T)) {
if (size < 2 * sizeof(U32T<BE>)) {
throw std::runtime_error("data size is too small");
}
std::string decrypted = decrypt_data_section<IsBigEndian>(data_section, size, round1_seed);
std::string decrypted = decrypt_data_section<BE>(data_section, size, round1_seed);
uint32_t round2_seed = override_round2_seed < 0x100000000
? static_cast<uint32_t>(override_round2_seed)
: reinterpret_cast<const U32T*>(decrypted.data() + decrypted.size() - sizeof(U32T))->load();
: reinterpret_cast<const U32T<BE>*>(decrypted.data() + decrypted.size() - sizeof(U32T<BE>))->load();
PSOV2Encryption round2_crypt(round2_seed);
if (IsBigEndian) {
round2_crypt.encrypt_big_endian(decrypted.data(), decrypted.size() - sizeof(U32T));
if (BE) {
round2_crypt.encrypt_big_endian(decrypted.data(), decrypted.size() - sizeof(U32T<BE>));
} else {
round2_crypt.encrypt(decrypted.data(), decrypted.size() - sizeof(U32T));
round2_crypt.encrypt(decrypted.data(), decrypted.size() - sizeof(U32T<BE>));
}
if (!skip_checksum) {
U32T& checksum = *reinterpret_cast<U32T*>(decrypted.data());
U32T<BE>& checksum = *reinterpret_cast<U32T<BE>*>(decrypted.data());
uint32_t expected_crc = checksum;
checksum = 0;
uint32_t actual_crc = crc32(decrypted.data(), decrypted.size());
uint32_t actual_crc = phosg::crc32(decrypted.data(), decrypted.size());
checksum = expected_crc;
if (expected_crc != actual_crc) {
throw std::runtime_error(string_printf(
throw std::runtime_error(phosg::string_printf(
"incorrect decrypted data section checksum: expected %08" PRIX32 "; received %08" PRIX32,
expected_crc, actual_crc));
}
@@ -961,7 +952,7 @@ std::string decrypt_fixed_size_data_section_s(
return decrypted;
}
template <typename StructT, bool IsBigEndian>
template <typename StructT, bool BE>
StructT decrypt_fixed_size_data_section_t(
const void* data_section,
size_t size,
@@ -969,14 +960,14 @@ StructT decrypt_fixed_size_data_section_t(
bool skip_checksum = false,
uint64_t override_round2_seed = 0xFFFFFFFFFFFFFFFF) {
std::string decrypted = decrypt_data_section<IsBigEndian>(data_section, size, round1_seed);
std::string decrypted = decrypt_data_section<BE>(data_section, size, round1_seed);
if (decrypted.size() < sizeof(StructT)) {
throw std::runtime_error("file too small for structure");
}
StructT ret = *reinterpret_cast<const StructT*>(decrypted.data());
PSOV2Encryption round2_crypt(override_round2_seed < 0x100000000 ? override_round2_seed : ret.round2_seed.load());
if (IsBigEndian) {
if (BE) {
round2_crypt.encrypt_big_endian(&ret, offsetof(StructT, round2_seed));
} else {
round2_crypt.encrypt(&ret, offsetof(StructT, round2_seed));
@@ -985,10 +976,10 @@ StructT decrypt_fixed_size_data_section_t(
if (!skip_checksum) {
uint32_t expected_crc = ret.checksum;
ret.checksum = 0;
uint32_t actual_crc = crc32(&ret, sizeof(ret));
uint32_t actual_crc = phosg::crc32(&ret, sizeof(ret));
ret.checksum = expected_crc;
if (expected_crc != actual_crc) {
throw std::runtime_error(string_printf(
throw std::runtime_error(phosg::string_printf(
"incorrect decrypted data section checksum: expected %08" PRIX32 "; received %08" PRIX32,
expected_crc, actual_crc));
}
@@ -997,46 +988,44 @@ StructT decrypt_fixed_size_data_section_t(
return ret;
}
template <bool IsBigEndian>
template <bool BE>
std::string encrypt_fixed_size_data_section_s(const void* data, size_t size, uint32_t round1_seed) {
using U32T = std::conditional_t<IsBigEndian, be_uint32_t, le_uint32_t>;
if (size < 2 * sizeof(U32T)) {
if (size < 2 * sizeof(U32T<BE>)) {
throw std::runtime_error("data size is too small");
}
uint32_t round2_seed = random_object<uint32_t>();
uint32_t round2_seed = phosg::random_object<uint32_t>();
std::string encrypted(reinterpret_cast<const char*>(data), size);
*reinterpret_cast<U32T*>(encrypted.data()) = 0;
*reinterpret_cast<U32T*>(encrypted.data() + encrypted.size() - sizeof(U32T)) = round2_seed;
*reinterpret_cast<U32T*>(encrypted.data()) = crc32(encrypted.data(), encrypted.size());
*reinterpret_cast<U32T<BE>*>(encrypted.data()) = 0;
*reinterpret_cast<U32T<BE>*>(encrypted.data() + encrypted.size() - sizeof(U32T<BE>)) = round2_seed;
*reinterpret_cast<U32T<BE>*>(encrypted.data()) = phosg::crc32(encrypted.data(), encrypted.size());
PSOV2Encryption round2_crypt(round2_seed);
if (IsBigEndian) {
if (BE) {
round2_crypt.encrypt_big_endian(encrypted.data(), encrypted.size());
} else {
round2_crypt.encrypt(encrypted.data(), encrypted.size());
}
return encrypt_data_section<IsBigEndian>(encrypted.data(), encrypted.size(), round1_seed);
return encrypt_data_section<BE>(encrypted.data(), encrypted.size(), round1_seed);
}
template <typename StructT, bool IsBigEndian>
template <typename StructT, bool BE>
std::string encrypt_fixed_size_data_section_t(const StructT& s, uint32_t round1_seed) {
StructT encrypted = s;
encrypted.checksum = 0;
encrypted.round2_seed = random_object<uint32_t>();
encrypted.checksum = crc32(&encrypted, sizeof(encrypted));
encrypted.round2_seed = phosg::random_object<uint32_t>();
encrypted.checksum = phosg::crc32(&encrypted, sizeof(encrypted));
PSOV2Encryption round2_crypt(encrypted.round2_seed);
if (IsBigEndian) {
if (BE) {
round2_crypt.encrypt_big_endian(&encrypted, offsetof(StructT, round2_seed));
} else {
round2_crypt.encrypt(&encrypted, offsetof(StructT, round2_seed));
}
return encrypt_data_section<IsBigEndian>(&encrypted, sizeof(StructT), round1_seed);
return encrypt_data_section<BE>(&encrypted, sizeof(StructT), round1_seed);
}
std::string decrypt_gci_fixed_size_data_section_for_salvage(
+43 -43
View File
@@ -171,8 +171,8 @@ prepare_server_init_contents_console(
void send_server_init_dc_pc_v3(shared_ptr<Client> c, uint8_t flags) {
bool initial_connection = (flags & SendServerInitFlag::IS_INITIAL_CONNECTION);
uint8_t command = initial_connection ? 0x17 : 0x02;
uint32_t server_key = random_object<uint32_t>();
uint32_t client_key = random_object<uint32_t>();
uint32_t server_key = phosg::random_object<uint32_t>();
uint32_t client_key = phosg::random_object<uint32_t>();
auto cmd = prepare_server_init_contents_console(server_key, client_key, initial_connection);
send_command_t(c, command, 0x00, cmd);
@@ -224,8 +224,8 @@ void send_server_init_bb(shared_ptr<Client> c, uint8_t flags) {
bool use_secondary_message = (flags & SendServerInitFlag::USE_SECONDARY_MESSAGE);
parray<uint8_t, 0x30> server_key;
parray<uint8_t, 0x30> client_key;
random_data(server_key.data(), server_key.bytes());
random_data(client_key.data(), client_key.bytes());
phosg::random_data(server_key.data(), server_key.bytes());
phosg::random_data(client_key.data(), client_key.bytes());
auto cmd = prepare_server_init_contents_bb(server_key, client_key, flags);
send_command_t(c, use_secondary_message ? 0x9B : 0x03, 0x00, cmd);
@@ -408,11 +408,11 @@ string prepare_send_function_call_data(
data = code->generate_client_command(label_writes, suffix_data, suffix_size, override_relocations_offset);
if (use_encrypted_format) {
uint32_t key = random_object<uint32_t>();
uint32_t key = phosg::random_object<uint32_t>();
// This format was probably never used on any little-endian system, but we
// implement the way it would probably work there if it was used.
StringWriter w;
phosg::StringWriter w;
if (code->is_big_endian()) {
w.put_u32b(data.size());
w.put_u32b(key);
@@ -437,7 +437,7 @@ string prepare_send_function_call_data(
}
}
StringWriter w;
phosg::StringWriter w;
w.put(S_ExecuteCode_B2{data.size(), checksum_addr, checksum_size});
w.write(data);
return std::move(w.str());
@@ -524,7 +524,7 @@ bool send_protected_command(std::shared_ptr<Client> c, const void* data, size_t
try {
auto s = c->require_server_state();
auto fn = s->function_code_index->get_patch("CallProtectedHandler", c->config.specific_version);
uint32_t size_label_value = is_big_endian(c->version()) ? data.size() : bswap32(data.size());
uint32_t size_label_value = is_big_endian(c->version()) ? data.size() : phosg::bswap32(data.size());
send_function_call(c, fn, {{"size", size_label_value}}, data.data(), data.size());
c->function_call_response_queue.emplace_back(empty_function_call_response_handler);
if (echo_to_lobby) {
@@ -777,7 +777,7 @@ enum class ColorMode {
static void send_text(
Channel& ch,
StringWriter& w,
phosg::StringWriter& w,
uint16_t command,
uint32_t flag,
const string& text,
@@ -800,7 +800,7 @@ static void send_text(
break;
}
} catch (const runtime_error& e) {
log_warning("Failed to encode message for %02hX command: %s", command, e.what());
phosg::log_warning("Failed to encode message for %02hX command: %s", command, e.what());
return;
}
@@ -817,12 +817,12 @@ static void send_text(
}
static void send_text(Channel& ch, uint16_t command, uint32_t flag, const string& text, ColorMode color_mode) {
StringWriter w;
phosg::StringWriter w;
send_text(ch, w, command, flag, text, color_mode);
}
static void send_header_text(Channel& ch, uint16_t command, uint32_t guild_card_number, const string& text, ColorMode color_mode) {
StringWriter w;
phosg::StringWriter w;
w.put(SC_TextHeader_01_06_11_B0_EE({0, guild_card_number}));
send_text(ch, w, command, 0x00, text, color_mode);
}
@@ -861,10 +861,10 @@ void send_ep3_timed_message_box(Channel& ch, uint32_t frames, const string& mess
try {
encoded = tt_encode_marked(add_color(message), ch.language, false);
} catch (const runtime_error& e) {
log_warning("Failed to encode message for EA command: %s", e.what());
phosg::log_warning("Failed to encode message for EA command: %s", e.what());
return;
}
StringWriter w;
phosg::StringWriter w;
w.put<S_TimedMessageBoxHeader_Ep3_EA>({frames});
w.write(encoded);
w.put_u8(0);
@@ -926,7 +926,7 @@ void send_text_message(shared_ptr<ServerState> s, const string& text) {
__attribute__((format(printf, 2, 3))) void send_ep3_text_message_printf(shared_ptr<ServerState> s, const char* format, ...) {
va_list va;
va_start(va, format);
string buf = string_vprintf(format, va);
string buf = phosg::string_vprintf(format, va);
va_end(va);
for (auto& it : s->id_to_lobby) {
for (auto& c : it.second->clients) {
@@ -976,7 +976,7 @@ string prepare_chat_data(
}
data.append(from_name);
if (version == Version::DC_NTE) {
data.append(string_printf(">%X", from_client_id));
data.append(phosg::string_printf(">%X", from_client_id));
} else {
data.append(1, '\t');
}
@@ -1012,7 +1012,7 @@ void send_chat_message_from_client(Channel& ch, const string& text, char private
}
void send_prepared_chat_message(shared_ptr<Client> c, uint32_t from_guild_card_number, const string& prepared_data) {
StringWriter w;
phosg::StringWriter w;
w.put(SC_TextHeader_01_06_11_B0_EE{0, from_guild_card_number});
w.write(prepared_data);
w.put_u8(0);
@@ -1066,7 +1066,7 @@ void send_simple_mail_bb(shared_ptr<Client> c, uint32_t from_guild_card_number,
cmd.from_guild_card_number = from_guild_card_number;
cmd.from_name.encode(from_name, c->language());
cmd.to_guild_card_number = c->login->account->account_id;
cmd.received_date.encode(format_time(now()), c->language());
cmd.received_date.encode(phosg::format_time(phosg::now()), c->language());
cmd.text.encode(text, c->language());
send_command_t(c, 0x81, 0x00, cmd);
}
@@ -1191,11 +1191,11 @@ void send_card_search_result_t(
string location_string;
if (result_lobby->is_game()) {
location_string = string_printf("%s,,BLOCK01,%s", result_lobby->name.c_str(), s->name.c_str());
location_string = phosg::string_printf("%s,,BLOCK01,%s", result_lobby->name.c_str(), s->name.c_str());
} else if (result_lobby->is_ep3()) {
location_string = string_printf("BLOCK01-C%02" PRIu32 ",,BLOCK01,%s", result_lobby->lobby_id - 15, s->name.c_str());
location_string = phosg::string_printf("BLOCK01-C%02" PRIu32 ",,BLOCK01,%s", result_lobby->lobby_id - 15, s->name.c_str());
} else {
location_string = string_printf("BLOCK01-%02" PRIu32 ",,BLOCK01,%s", result_lobby->lobby_id, s->name.c_str());
location_string = phosg::string_printf("BLOCK01-%02" PRIu32 ",,BLOCK01,%s", result_lobby->lobby_id, s->name.c_str());
}
cmd.location_string.encode(location_string, c->language());
cmd.extension.lobby_refs[0].menu_id = MenuID::LOBBY;
@@ -2610,7 +2610,7 @@ void send_game_join_sync_command_compressed(
uint8_t dc_nte_sc,
uint8_t dc_11_2000_sc,
uint8_t sc) {
StringWriter w;
phosg::StringWriter w;
if (is_pre_v1(c->version())) {
G_SyncGameStateHeader_DCNTE_6x6B_6x6C_6x6D_6x6E compressed_header;
compressed_header.header.basic_header.subcommand = (c->version() == Version::DC_NTE) ? dc_nte_sc : dc_11_2000_sc;
@@ -2648,7 +2648,7 @@ void send_game_join_sync_command_compressed(
void send_game_item_state(shared_ptr<Client> c) {
auto l = c->require_lobby();
auto s = c->require_server_state();
StringWriter floor_items_w;
phosg::StringWriter floor_items_w;
G_SyncItemState_6x6D_Decompressed decompressed_header;
for (size_t z = 0; z < 12; z++) {
@@ -2689,7 +2689,7 @@ void send_game_item_state(shared_ptr<Client> c) {
}
}
StringWriter decompressed_w;
phosg::StringWriter decompressed_w;
decompressed_w.put(decompressed_header);
decompressed_w.write(floor_items_w.str());
const auto& data = decompressed_w.str();
@@ -2756,7 +2756,7 @@ void send_game_set_state(shared_ptr<Client> c) {
header.switch_flags_size = is_v1(c->version()) ? 0x200 : 0x240;
header.total_size = header.entity_set_flags_size + header.event_set_flags_size + header.switch_flags_size;
StringWriter w;
phosg::StringWriter w;
w.put(header);
w.put(entity_set_flags_header);
for (const auto& obj : l->map->objects) {
@@ -2783,7 +2783,7 @@ void send_game_flag_state_t(shared_ptr<Client> c) {
auto l = c->require_lobby();
if (l->quest_flags_known) { // Not all flags known; send multiple 6x75s
StringWriter w;
phosg::StringWriter w;
bool use_v3_cmd = !is_v1_or_v2(c->version()) || (c->version() == Version::GC_NTE);
for (uint8_t difficulty = 0; difficulty < 4; difficulty++) {
if ((difficulty != l->difficulty) && !use_v3_cmd) {
@@ -3053,7 +3053,7 @@ void send_bank(shared_ptr<Client> c) {
G_BankContentsHeader_BB_6xBC cmd = {
{{0xBC, 0, 0}, sizeof(G_BankContentsHeader_BB_6xBC) + items.size() * sizeof(PlayerBankItem)},
random_object<uint32_t>(),
phosg::random_object<uint32_t>(),
bank.num_items,
bank.meseta};
@@ -3161,7 +3161,7 @@ void send_ep3_card_list_update(shared_ptr<Client> c) {
? s->ep3_card_index_trial->get_compressed_definitions()
: s->ep3_card_index->get_compressed_definitions();
StringWriter w;
phosg::StringWriter w;
w.put_u32l(data.size());
w.write(data);
@@ -3174,7 +3174,7 @@ void send_ep3_media_update(
uint32_t type,
uint32_t which,
const string& compressed_data) {
StringWriter w;
phosg::StringWriter w;
w.put<S_UpdateMediaHeader_Ep3_B9>({type, which, compressed_data.size(), 0});
w.write(compressed_data);
while (w.size() & 3) {
@@ -3371,7 +3371,7 @@ string ep3_description_for_client(shared_ptr<Client> c) {
throw runtime_error("client is not Episode 3");
}
auto p = c->character();
return string_printf(
return phosg::string_printf(
"%s CLv%" PRIu32 " %c",
name_for_char_class(p->disp.visual.char_class),
p->disp.stats.level + 1,
@@ -3558,7 +3558,7 @@ void send_ep3_set_tournament_player_decks_t(shared_ptr<Client> c) {
if ((c->version() != Version::GC_EP3_NTE) &&
!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) {
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t mask_key = (phosg::random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key);
}
@@ -3604,8 +3604,8 @@ void send_ep3_tournament_match_result(shared_ptr<Lobby> l, uint32_t meseta_rewar
G_TournamentMatchResult_Ep3_6xB4x51 cmd;
cmd.match_description.encode((match == tourn->get_final_match())
? string_printf("(%s) Final match", tourn->get_name().c_str())
: string_printf("(%s) Round %zu", tourn->get_name().c_str(), match->round_num),
? phosg::string_printf("(%s) Final match", tourn->get_name().c_str())
: phosg::string_printf("(%s) Round %zu", tourn->get_name().c_str(), match->round_num),
lc->language());
cmd.names_entries[0].team_name.encode(match->preceding_a->winner_team->name, lc->language());
write_player_names(cmd.names_entries[0], match->preceding_a->winner_team);
@@ -3620,7 +3620,7 @@ void send_ep3_tournament_match_result(shared_ptr<Lobby> l, uint32_t meseta_rewar
cmd.meseta_reward_text.encode("You got %s meseta!", 1);
if ((lc->version() != Version::GC_EP3_NTE) &&
!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) {
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t mask_key = (phosg::random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key);
}
send_command_t(lc, 0xC9, 0x00, cmd);
@@ -3656,7 +3656,7 @@ void send_ep3_update_game_metadata(shared_ptr<Lobby> l) {
cmd.total_spectators = total_spectators;
if ((l->base_version != Version::GC_EP3_NTE) &&
!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) {
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t mask_key = (phosg::random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key);
}
// Note: We can't use send_command_t(l, ...) here because that would send
@@ -3674,9 +3674,9 @@ void send_ep3_update_game_metadata(shared_ptr<Lobby> l) {
auto tourn = l->tournament_match ? l->tournament_match->tournament.lock() : 0;
if (l->tournament_match && tourn) {
if (tourn->get_final_match() == l->tournament_match) {
text = string_printf("Viewing final match of tournament %s", tourn->get_name().c_str());
text = phosg::string_printf("Viewing final match of tournament %s", tourn->get_name().c_str());
} else {
text = string_printf(
text = phosg::string_printf(
"Viewing match in round %zu of tournament %s",
l->tournament_match->round_num, tourn->get_name().c_str());
}
@@ -3695,7 +3695,7 @@ void send_ep3_update_game_metadata(shared_ptr<Lobby> l) {
cmd.text.encode(text, 1);
if ((watcher_l->base_version != Version::GC_EP3_NTE) &&
!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) {
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
uint8_t mask_key = (phosg::random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key);
}
send_command_t(watcher_l, 0xC9, 0x00, cmd);
@@ -3864,7 +3864,7 @@ void send_open_quest_file(
// the client should apply backpressure to avoid bad situations, but we have
// to deal with it here instead.
size_t total_chunks = (contents->size() + 0x3FF) / 0x400;
size_t chunks_to_send = is_gc(c->version()) ? min<size_t>(GC_QUEST_LOAD_MAX_CHUNKS_IN_FLIGHT, total_chunks) : total_chunks;
size_t chunks_to_send = is_v1_or_v2(c->version()) ? total_chunks : min<size_t>(V3_V4_QUEST_LOAD_MAX_CHUNKS_IN_FLIGHT, total_chunks);
for (size_t z = 0; z < chunks_to_send; z++) {
size_t offset = z * 0x400;
@@ -3964,7 +3964,7 @@ void send_ep3_card_auction(shared_ptr<Lobby> l) {
num_cards = s->ep3_card_auction_min_size;
} else {
num_cards = s->ep3_card_auction_min_size +
(random_object<uint16_t>() % (s->ep3_card_auction_max_size - s->ep3_card_auction_min_size + 1));
(phosg::random_object<uint16_t>() % (s->ep3_card_auction_max_size - s->ep3_card_auction_min_size + 1));
}
num_cards = min<uint16_t>(num_cards, 0x14);
@@ -3980,7 +3980,7 @@ void send_ep3_card_auction(shared_ptr<Lobby> l) {
S_StartCardAuction_Ep3_EF cmd;
cmd.points_available = s->ep3_card_auction_points;
for (size_t z = 0; z < num_cards; z++) {
uint64_t v = random_object<uint64_t>() % distribution_size;
uint64_t v = phosg::random_object<uint64_t>() % distribution_size;
for (const auto& e : s->ep3_card_auction_pool) {
if (v >= e.probability) {
v -= e.probability;
@@ -4005,7 +4005,7 @@ void send_ep3_disband_watcher_lobbies(shared_ptr<Lobby> primary_l) {
}
void send_server_time(shared_ptr<Client> c) {
uint64_t t = now();
uint64_t t = phosg::now();
time_t t_secs = t / 1000000;
struct tm t_parsed;
@@ -4015,7 +4015,7 @@ void send_server_time(shared_ptr<Client> c) {
size_t len = strftime(time_str.data(), time_str.size(),
"%Y:%m:%d: %H:%M:%S.000", &t_parsed);
if (len == 0) {
throw runtime_error("format_time buffer too short");
throw runtime_error("phosg::format_time buffer too short");
}
time_str.resize(len);

Some files were not shown because too many files have changed in this diff Show More