#include "DOLFileIndex.hh" #include #include #include #include #include #include #include #include #include #include #include "CommandFormats.hh" #include "CommonFileFormats.hh" #include "Compression.hh" #include "Loggers.hh" DOLFileIndex::DOLFileIndex(const std::string& directory) { if (!std::filesystem::is_directory(directory)) { client_functions_log.info_f("DOL file directory is missing"); return; } auto menu = std::make_shared(MenuID::PROGRAMS, "Programs"); this->menu = menu; menu->items.emplace_back(ProgramsMenuItemID::GO_BACK, "Go back", "Return to the\nmain menu", 0); std::vector filenames; for (const auto& item : std::filesystem::directory_iterator(directory)) { filenames.emplace_back(item.path().filename().string()); } std::sort(filenames.begin(), filenames.end()); uint32_t next_menu_item_id = 0; for (const auto& filename : filenames) { bool is_dol = filename.ends_with(".dol"); bool is_compressed_dol = filename.ends_with(".dol.prs"); if (!is_dol && !is_compressed_dol) { continue; } std::string name = filename.substr(0, filename.size() - (is_compressed_dol ? 8 : 4)); try { auto dol = std::make_shared(); dol->menu_item_id = next_menu_item_id++; dol->name = name; std::string path = directory + "/" + filename; std::string file_data = phosg::load_file(path); std::string description; if (is_compressed_dol) { size_t decompressed_size = prs_decompress_size(file_data); phosg::StringWriter w; w.put_u32b(file_data.size()); w.put_u32b(decompressed_size); w.write(file_data); while (w.size() & 3) { w.put_u8(0); } dol->data = std::move(w.str()); std::string compressed_size_str = phosg::format_size(file_data.size()); std::string decompressed_size_str = phosg::format_size(decompressed_size); client_functions_log.debug_f("Loaded compressed DOL file {} ({} -> {})", dol->name, compressed_size_str, decompressed_size_str); description = std::format("$C6{}$C7\n{}\n{} (orig)", dol->name, compressed_size_str, decompressed_size_str); } else { phosg::StringWriter w; w.put_u32b(0); w.put_u32b(file_data.size()); w.write(file_data); while (w.size() & 3) { w.put_u8(0); } dol->data = std::move(w.str()); std::string size_str = phosg::format_size(dol->data.size()); client_functions_log.debug_f("Loaded DOL file {} ({})", filename, size_str); description = std::format("$C6{}$C7\n{}", dol->name, size_str); } this->item_id_to_file.emplace_back(dol); menu->items.emplace_back(dol->menu_item_id, dol->name, description, MenuItem::Flag::REQUIRES_SEND_FUNCTION_CALL_RUNS_CODE); } catch (const std::exception& e) { client_functions_log.warning_f("Failed to load DOL file {}: {}", filename, e.what()); } } }