refine PC save file format

This commit is contained in:
Martin Michelsen
2024-05-12 15:09:31 -07:00
parent f069622b94
commit b6fb9051b6
2 changed files with 37 additions and 28 deletions
+6 -6
View File
@@ -681,8 +681,8 @@ static void a_encrypt_decrypt_pc_save_fn(Arguments& args) {
for (size_t z = 0; z < charfile->entries.size(); z++) { for (size_t z = 0; z < charfile->entries.size(); z++) {
if (charfile->entries[z].present) { if (charfile->entries[z].present) {
try { try {
charfile->entries[z].character = decrypt_fixed_size_data_section_t<PSOPCCharacterFile::CharacterEntry::Character, false>( charfile->entries[z].encrypted = decrypt_fixed_size_data_section_t<PSOPCCharacterFile::CharacterEntry::EncryptedSection, false>(
&charfile->entries[z].character, sizeof(charfile->entries[z].character), round1_seed, skip_checksum, override_round2_seed); &charfile->entries[z].encrypted, sizeof(charfile->entries[z].encrypted), round1_seed, skip_checksum, override_round2_seed);
} catch (const exception& e) { } catch (const exception& e) {
fprintf(stderr, "warning: cannot decrypt character %zu: %s\n", z, e.what()); fprintf(stderr, "warning: cannot decrypt character %zu: %s\n", z, e.what());
} }
@@ -691,12 +691,12 @@ static void a_encrypt_decrypt_pc_save_fn(Arguments& args) {
} else { } else {
for (size_t z = 0; z < charfile->entries.size(); z++) { for (size_t z = 0; z < charfile->entries.size(); z++) {
if (charfile->entries[z].present) { if (charfile->entries[z].present) {
string encrypted = encrypt_fixed_size_data_section_t<PSOPCCharacterFile::CharacterEntry::Character, false>( string encrypted = encrypt_fixed_size_data_section_t<PSOPCCharacterFile::CharacterEntry::EncryptedSection, false>(
charfile->entries[z].character, round1_seed); charfile->entries[z].encrypted, round1_seed);
if (encrypted.size() != sizeof(PSOPCCharacterFile::CharacterEntry::Character)) { if (encrypted.size() != sizeof(PSOPCCharacterFile::CharacterEntry::EncryptedSection)) {
throw logic_error("incorrect encrypted result size"); throw logic_error("incorrect encrypted result size");
} }
charfile->entries[z].character = *reinterpret_cast<const PSOPCCharacterFile::CharacterEntry::Character*>(encrypted.data()); charfile->entries[z].encrypted = *reinterpret_cast<const PSOPCCharacterFile::CharacterEntry::EncryptedSection*>(encrypted.data());
} }
} }
} }
+31 -22
View File
@@ -188,10 +188,12 @@ struct SaveFileChatShortcutEntryT {
} }
} __packed__; } __packed__;
using SaveFileShortcutEntryDC = SaveFileChatShortcutEntryT<false, TextEncoding::MARKED, 0x3C>; using SaveFileShortcutEntryDC = SaveFileChatShortcutEntryT<false, TextEncoding::MARKED, 0x3C>;
using SaveFileShortcutEntryPC = SaveFileChatShortcutEntryT<false, TextEncoding::UTF16, 0x3C>;
using SaveFileShortcutEntryGC = SaveFileChatShortcutEntryT<true, TextEncoding::MARKED, 0x50>; using SaveFileShortcutEntryGC = SaveFileChatShortcutEntryT<true, TextEncoding::MARKED, 0x50>;
using SaveFileShortcutEntryXB = SaveFileChatShortcutEntryT<false, TextEncoding::MARKED, 0x50>; using SaveFileShortcutEntryXB = SaveFileChatShortcutEntryT<false, TextEncoding::MARKED, 0x50>;
using SaveFileShortcutEntryBB = SaveFileChatShortcutEntryT<false, TextEncoding::UTF16, 0x50>; using SaveFileShortcutEntryBB = SaveFileChatShortcutEntryT<false, TextEncoding::UTF16, 0x50>;
check_struct_size(SaveFileShortcutEntryDC, 0x40); check_struct_size(SaveFileShortcutEntryDC, 0x40);
check_struct_size(SaveFileShortcutEntryPC, 0x7C);
check_struct_size(SaveFileShortcutEntryGC, 0x54); check_struct_size(SaveFileShortcutEntryGC, 0x54);
check_struct_size(SaveFileShortcutEntryXB, 0x54); check_struct_size(SaveFileShortcutEntryXB, 0x54);
check_struct_size(SaveFileShortcutEntryBB, 0xA4); check_struct_size(SaveFileShortcutEntryBB, 0xA4);
@@ -371,31 +373,38 @@ struct PSOPCCharacterFile { // PSO______SYS and PSO______SYD
/* 00010 */ parray<uint8_t, 0x430> unknown_a1; /* 00010 */ parray<uint8_t, 0x430> unknown_a1;
struct CharacterEntry { struct CharacterEntry {
/* 0000 */ le_uint32_t present = 1; // 1 if character present, 0 if empty /* 0000 */ le_uint32_t present = 1; // 1 if character present, 0 if empty
struct Character { struct EncryptedSection {
/* 0000 */ le_uint32_t checksum = 0; /* 0000 */ le_uint32_t checksum = 0;
/* 0004 */ PlayerInventory inventory; struct Character {
/* 0350 */ PlayerDispDataDCPCV3 disp; /* 0000 */ PlayerInventory inventory;
/* 0420 */ be_uint32_t flags = 0; /* 034C */ PlayerDispDataDCPCV3 disp;
/* 0424 */ be_uint32_t creation_timestamp = 0; /* 041C */ be_uint32_t flags = 0;
/* 0428 */ be_uint32_t signature = 0x6C5D889E; /* 0420 */ be_uint32_t creation_timestamp = 0;
/* 042C */ be_uint32_t play_time_seconds = 0; /* 0424 */ be_uint32_t signature = 0x6C5D889E;
/* 0430 */ be_uint32_t option_flags = 0x00040058; /* 0428 */ be_uint32_t play_time_seconds = 0;
/* 0434 */ be_uint32_t save_count = 1; /* 042C */ be_uint32_t option_flags = 0x00040058;
// TODO: Figure out what this is. On GC, this is where the bank data goes. /* 0430 */ be_uint32_t save_count = 1;
/* 0438 */ parray<uint8_t, 0x7D4> unknown_a2; /* 0434 */ pstring<TextEncoding::ASCII, 0x1C> ppp_username;
/* 0C0C */ GuildCardPC guild_card; /* 0450 */ pstring<TextEncoding::ASCII, 0x10> ppp_password;
/* 0CFC */ parray<SaveFileSymbolChatEntryPC, 12> symbol_chats; /* 0460 */ QuestFlags quest_flags;
// TODO: Figure out what this is. On GC, this is where chat shortcuts and /* 0660 */ PlayerBank60 bank;
// challenge/battle records go. /* 0C08 */ GuildCardPC guild_card;
/* 123C */ parray<uint8_t, 0xAA0> unknown_a3; /* 0CF8 */ parray<SaveFileSymbolChatEntryPC, 12> symbol_chats;
/* 1CDC */ parray<le_uint16_t, 20> tech_menu_shortcut_entries; /* 1238 */ parray<SaveFileShortcutEntryPC, 20> shortcuts;
/* 1D04 */ parray<uint8_t, 0x2C> unknown_a4; /* 1BE8 */ PlayerRecordsBattle battle_records;
/* 1D30 */ pstring<TextEncoding::ASCII, 0x10> serial_number; // As %08X (not decimal) /* 1C00 */ PlayerRecordsChallengePC challenge_records;
/* 1D40 */ pstring<TextEncoding::ASCII, 0x10> access_key; // As decimal /* 1CD8 */ parray<le_uint16_t, 20> tech_menu_shortcut_entries;
/* 1D00 */ parray<le_uint32_t, 10> choice_search_config;
/* 1D28 */ parray<uint8_t, 4> unknown_a2;
/* 1D2C */ pstring<TextEncoding::ASCII, 0x10> serial_number; // As %08X (not decimal)
/* 1D3C */ pstring<TextEncoding::ASCII, 0x10> access_key; // As decimal
/* 1D4C */
} __packed_ws__(Character, 0x1D4C);
/* 0004 */ Character character;
/* 1D50 */ le_uint32_t round2_seed = 0; /* 1D50 */ le_uint32_t round2_seed = 0;
/* 1D54 */ /* 1D54 */
} __packed_ws__(Character, 0x1D54); } __packed_ws__(EncryptedSection, 0x1D54);
/* 0004 */ Character character; /* 0004 */ EncryptedSection encrypted;
/* 1D58 */ parray<uint8_t, 0x3C> unused; /* 1D58 */ parray<uint8_t, 0x3C> unused;
/* 1D94 */ /* 1D94 */
} __packed_ws__(CharacterEntry, 0x1D94); } __packed_ws__(CharacterEntry, 0x1D94);