diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index c2e21af8..61eaf455 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -827,6 +827,9 @@ void process_menu_selection(shared_ptr s, shared_ptr c, } if (l) { + if (is_ep3 || !dat_contents) { + throw runtime_error("episode 3 quests cannot be loaded during games"); + } if (q->joinable) { l->flags |= Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS; } else { @@ -842,10 +845,10 @@ void process_menu_selection(shared_ptr s, shared_ptr c, // cause GC clients to crash in rare cases. Find a way to slow this down // (perhaps by only sending each new chunk when they acknowledge the // previous chunk with a 44 [first chunk] or 13 [later chunks] command). - send_quest_file(l->clients[x], bin_basename + ".bin", bin_basename, *bin_contents, false, is_ep3); - if (dat_contents) { - send_quest_file(l->clients[x], dat_basename + ".dat", dat_basename, *dat_contents, false, is_ep3); - } + send_quest_file(l->clients[x], bin_basename + ".bin", bin_basename, + *bin_contents, QuestFileType::ONLINE); + send_quest_file(l->clients[x], dat_basename + ".dat", dat_basename, + *dat_contents, QuestFileType::ONLINE); // There is no such thing as command AC on PSO PC - quests just start // immediately when they're done downloading. There are also no chunk @@ -865,9 +868,11 @@ void process_menu_selection(shared_ptr s, shared_ptr c, if (!is_ep3) { q = q->create_download_quest(); } - send_quest_file(c, quest_name, bin_basename, *q->bin_contents(), true, is_ep3); + send_quest_file(c, quest_name, bin_basename, *q->bin_contents(), + is_ep3 ? QuestFileType::EPISODE_3 : QuestFileType::DOWNLOAD); if (dat_contents) { - send_quest_file(c, quest_name, dat_basename, *q->dat_contents(), true, is_ep3); + send_quest_file(c, quest_name, dat_basename, *q->dat_contents(), + is_ep3 ? QuestFileType::EPISODE_3 : QuestFileType::DOWNLOAD); } } break; @@ -1024,9 +1029,9 @@ void process_gba_file_request(shared_ptr, shared_ptr c, uint16_t, uint32_t, const string& data) { // D7 string filename(data); strip_trailing_zeroes(filename); - auto contents = file_cache.get(filename); + auto contents = file_cache.get("system/gba/" + filename); - send_quest_file(c, filename, filename, *contents, false, false); + send_quest_file(c, "", filename, *contents, QuestFileType::GBA_DEMO); } diff --git a/src/SendCommands.cc b/src/SendCommands.cc index ff751fdb..5f31e946 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1348,21 +1348,37 @@ void send_quest_open_file_t( const string& quest_name, const string& filename, uint32_t file_size, - bool is_download_quest, - bool is_ep3_quest) { + QuestFileType type) { CommandT cmd; - cmd.unused = 0; - if (is_ep3_quest) { - cmd.flags = 3; - } else if (is_download_quest) { - cmd.flags = 0; - } else { - cmd.flags = 2; + uint8_t command_num; + switch (type) { + case QuestFileType::ONLINE: + command_num = 0x44; + cmd.name = "PSO/" + quest_name; + cmd.flags = 2; + break; + case QuestFileType::GBA_DEMO: + command_num = 0xA6; + cmd.name = "GBA Demo"; + cmd.flags = 2; + break; + case QuestFileType::DOWNLOAD: + command_num = 0xA6; + cmd.name = "PSO/" + quest_name; + cmd.flags = 0; + break; + case QuestFileType::EPISODE_3: + command_num = 0xA6; + cmd.name = "PSO/" + quest_name; + cmd.flags = 3; + break; + default: + throw logic_error("invalid quest file type"); } + cmd.unused = 0; cmd.file_size = file_size; - cmd.name = "PSO/" + quest_name; cmd.filename = filename.c_str(); - send_command_t(c, is_download_quest ? 0xA6 : 0x44, 0x00, cmd); + send_command_t(c, command_num, 0x00, cmd); } void send_quest_file_chunk( @@ -1371,7 +1387,7 @@ void send_quest_file_chunk( size_t chunk_index, const void* data, size_t size, - bool is_download_quest) { + QuestFileType type) { if (size > 0x400) { throw invalid_argument("quest file chunks must be 1KB or smaller"); } @@ -1384,19 +1400,18 @@ void send_quest_file_chunk( } cmd.data_size = size; - send_command_t(c, is_download_quest ? 0xA7 : 0x13, chunk_index, cmd); + send_command_t(c, (type == QuestFileType::ONLINE) ? 0x13 : 0xA7, chunk_index, cmd); } void send_quest_file(shared_ptr c, const string& quest_name, - const string& basename, const string& contents, bool is_download_quest, - bool is_ep3_quest) { + const string& basename, const string& contents, QuestFileType type) { if (c->version == GameVersion::PC || c->version == GameVersion::GC) { send_quest_open_file_t( - c, quest_name, basename, contents.size(), is_download_quest, is_ep3_quest); + c, quest_name, basename, contents.size(), type); } else if (c->version == GameVersion::BB) { send_quest_open_file_t( - c, quest_name, basename, contents.size(), is_download_quest, is_ep3_quest); + c, quest_name, basename, contents.size(), type); } else { throw invalid_argument("cannot send quest files to this version of client"); } @@ -1407,7 +1422,7 @@ void send_quest_file(shared_ptr c, const string& quest_name, chunk_bytes = 0x400; } send_quest_file_chunk(c, basename.c_str(), offset / 0x400, - contents.data() + offset, chunk_bytes, is_download_quest); + contents.data() + offset, chunk_bytes, type); } } diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 39216950..4212f673 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -209,9 +209,16 @@ void send_ep3_rank_update(std::shared_ptr c); void send_ep3_map_list(std::shared_ptr l); void send_ep3_map_data(std::shared_ptr l, uint32_t map_id); +enum class QuestFileType { + ONLINE = 0, + DOWNLOAD, + EPISODE_3, + GBA_DEMO, +}; + void send_quest_file(std::shared_ptr c, const std::string& quest_name, const std::string& basename, const std::string& contents, - bool is_download_quest, bool is_ep3_quest); + QuestFileType type); void send_server_time(std::shared_ptr c); diff --git a/system/gba/chuclg_e.gba b/system/gba/chuclg_e.gba new file mode 100644 index 00000000..994927aa Binary files /dev/null and b/system/gba/chuclg_e.gba differ diff --git a/system/gba/chupuz_e.gba b/system/gba/chupuz_e.gba new file mode 100644 index 00000000..99638fd6 Binary files /dev/null and b/system/gba/chupuz_e.gba differ diff --git a/system/quests/nights_e.gba b/system/gba/nights_e.gba similarity index 100% rename from system/quests/nights_e.gba rename to system/gba/nights_e.gba diff --git a/system/quests/puyo_e.gba b/system/gba/puyo_e.gba similarity index 100% rename from system/quests/puyo_e.gba rename to system/gba/puyo_e.gba