document patch server commands

This commit is contained in:
Martin Michelsen
2022-05-08 00:04:39 -07:00
parent 8ef256917c
commit 1e3dd6a274
4 changed files with 153 additions and 34 deletions
+144 -27
View File
@@ -77,6 +77,150 @@ struct ClientConfigBB {
// Patch server commands
// A patch server session generally goes like this:
// Server: 02
// Client: 02
// Server: 04
// Client: 04
// Server: 13 (if desired)
// Server: 0B
// Server: 09 (with directory name ".")
// For each directory to be checked:
// Server: 09
// Server: (commands to check subdirectories - more 09/0A/0C)
// For each file in the directory:
// Server: 0C
// Server: 0A
// Server: 0D
// For each 0C sent by the server earlier:
// Client: 0F
// Client: 10
// If there are any files to be updated:
// Server: 11
// For each directory containing files to be updated:
// Server: 09
// Server: (commands to update subdirectories)
// For each file to be updated in this directory:
// Server: 06
// Server: 07 (possibly multiple 07s if the file is large)
// Server: 08
// Server: 0A
// Server: 12
// 02 (S->C): Start encryption
struct S_ServerInit_Patch_02 {
ptext<char, 0x40> copyright;
le_uint32_t server_key;
le_uint32_t client_key;
// BB rejects the command if it's larger than this size, so we can't add the
// after_message like we do in the other server init commands
};
// 04 (S->C): Request login information (no arguments); max. size 4
// 04 (C->S): Log in (patch)
struct C_Login_Patch_04 {
parray<le_uint32_t, 3> unused;
ptext<char, 0x10> username;
ptext<char, 0x10> password;
ptext<char, 0x40> email; // Note: this field is blank on BB
};
// 05 (S->C): Unknown
// No arguments
// 06 (S->C): Open file for writing
struct S_OpenFile_Patch_06 {
le_uint32_t unknown; // Seems to always be zero
le_uint32_t size;
ptext<char, 0x30> filename;
};
// 07 (S->C): Write file
// The client's handler table says this command's maximum size is 0x6010
// including the header, but the only servers I've seen use this command limit
// chunks to 0x4010 (including the header).
struct S_WriteFileHeader_Patch_07 {
le_uint32_t chunk_index;
le_uint32_t chunk_checksum; // crc32
le_uint32_t chunk_size;
// The chunk data immediately follows here
};
// 08 (S->C): Close current file
// Maximum size 8 (including header)
struct S_CloseCurrentFile_Patch_08 {
le_uint32_t unknown; // Seems to always be zero
};
// 09 (S->C): Enter directory
struct S_EnterDirectory_Patch_09 {
ptext<char, 0x40> name;
};
// 0A (S->C): Exit directory
// No arguments
// 0B (S->C): Unknown; possibly start patch session
// No arguments
// 0C (S->C): File checksum request
struct S_FileChecksumRequest_Patch_0C {
le_uint32_t request_id;
ptext<char, 0x20> filename;
};
// 0D (S->C): End of file check requests
// No arguments
// 0F (C->S): File information
struct C_FileInformation_Patch_0F {
le_uint32_t request_id;
le_uint32_t checksum;
le_uint32_t size;
};
// 10 (C->S): End of file information command list
// No arguments
// 11 (S->C): Start file downloads
struct S_Unknown_Patch_11 {
le_uint32_t total_bytes;
le_uint32_t num_files;
};
// 12 (S->C): End patch session successfully
// No arguments
// 13 (S->C): Message box
// Same as 1A/D5 on the game server. On PSOBB, the message appears in the upper
// message box and functions like a normal PSO message box. On PSOPC, the
// message appears in a Windows edit field, so line breaks must be \r\n (as
// opposed to just \n on PSOBB) and standard PSO color escapes don't work.
// THe maximum size of this command is 0x2004 bytes, including the header.
// 14 (S->C): Reconnect
// Same as 19 on the game server.
// 15 (S->C): Unknown
// No arguments
// No commands beyond 15 are valid on the patch server.
// Game server commands
// 00: Invalid command
// 01 (S->C): Lobby message box
@@ -100,14 +244,6 @@ struct S_ServerInit_DC_PC_GC_02_17 {
ptext<char, 0xC0> after_message;
};
struct S_ServerInit_Patch_02 {
ptext<char, 0x40> copyright;
le_uint32_t server_key;
le_uint32_t client_key;
// BB rejects the command if it's not exactly this size, so we can't add the
// after_message like we do in the other server init commands
};
// 03 (S->C): Start encryption (BB)
// Client will respond with a 93 command.
@@ -140,16 +276,6 @@ struct S_UpdateClientConfig_DC_PC_GC_04 {
ClientConfig cfg;
};
// 04 (S->C): Request login information (patch server) (no arguments)
// 04 (C->S): Log in (patch server)
struct C_Login_Patch_04 {
parray<le_uint32_t, 3> unused;
ptext<char, 0x10> username;
ptext<char, 0x10> password;
ptext<char, 0x40> email; // Note: this field is blank on BB
};
// 05: Disconnect
// No arguments
@@ -203,12 +329,6 @@ struct S_GameMenuEntry {
struct S_GameMenuEntry_PC_BB_08 : S_GameMenuEntry<char16_t> { };
struct S_GameMenuEntry_GC_08 : S_GameMenuEntry<char> { };
// 09 (S->C): Check directory (patch server)
struct S_CheckDirectory_Patch_09 {
ptext<char, 0x40> name;
};
// 09 (C->S): Menu item info request
// Server will respond with an 11 command, or an A3 if it's the quest menu.
@@ -217,9 +337,6 @@ struct C_MenuItemInfoRequest_09 {
le_uint32_t item_id;
};
// 0A: Done checking directory (patch server)
// No arguemnts
// 0B: Invalid command
// 0C: Create game (DCv1)
+3 -3
View File
@@ -1744,9 +1744,9 @@ independently.\r\n\
}
send_message_box(c, message.c_str());
send_check_directory_patch(c, ".");
send_check_directory_patch(c, "data");
send_check_directory_patch(c, "scene");
send_enter_directory_patch(c, ".");
send_enter_directory_patch(c, "data");
send_enter_directory_patch(c, "scene");
send_command(c, 0x0A, 0x00);
send_command(c, 0x0A, 0x00);
send_command(c, 0x0A, 0x00);
+5 -3
View File
@@ -267,7 +267,9 @@ void send_update_client_config(shared_ptr<Client> c) {
void send_reconnect(shared_ptr<Client> c, uint32_t address, uint16_t port) {
S_Reconnect_19 cmd = {address, port, 0};
send_command_t(c, 0x19, 0x00, cmd);
// On the patch server, 14 is the reconnect command, but it works exactly the
// same way as 19 on the game server.
send_command_t(c, (c->version == GameVersion::PATCH) ? 0x14 : 0x19, 0x00, cmd);
}
// Sends the command (first used by Schthack) that separates PC and GC users
@@ -426,8 +428,8 @@ void send_complete_player_bb(shared_ptr<Client> c) {
////////////////////////////////////////////////////////////////////////////////
// patch functions
void send_check_directory_patch(shared_ptr<Client> c, const string& dir) {
S_CheckDirectory_Patch_09 cmd = {dir};
void send_enter_directory_patch(shared_ptr<Client> c, const string& dir) {
S_EnterDirectory_Patch_09 cmd = {dir};
send_command_t(c, 0x09, 0x00, cmd);
}
+1 -1
View File
@@ -114,7 +114,7 @@ void send_stream_file_chunk_bb(std::shared_ptr<Client> c, uint32_t chunk_index);
void send_approve_player_choice_bb(std::shared_ptr<Client> c);
void send_complete_player_bb(std::shared_ptr<Client> c);
void send_check_directory_patch(std::shared_ptr<Client> c, const std::string& dir);
void send_enter_directory_patch(std::shared_ptr<Client> c, const std::string& dir);
void send_message_box(std::shared_ptr<Client> c, const std::u16string& text);
void send_lobby_name(std::shared_ptr<Client> c, const std::u16string& text);