#include "ImageConverter.h" #include "Image/DdsLoader.h" #include "Image/DdsWriter.h" #include "Image/IwiLoader.h" #include "Image/IwiWriter13.h" #include "Image/IwiWriter27.h" #include "Image/IwiWriter6.h" #include "Image/IwiWriter8.h" #include "Image/Texture.h" #include "ImageConverterArgs.h" #include "Utils/StringUtils.h" #include #include #include #include #include namespace fs = std::filesystem; namespace image_converter { constexpr auto EXTENSION_IWI = ".iwi"; constexpr auto EXTENSION_DDS = ".dds"; class ImageConverterImpl final : public ImageConverter { public: ImageConverterImpl() : m_game_to_convert_to(image_converter::Game::UNKNOWN) { } bool Start(const int argc, const char** argv) override { auto shouldContinue = true; if (!m_args.ParseArgs(argc, argv, shouldContinue)) return false; if (!shouldContinue) return true; m_game_to_convert_to = m_args.m_game_to_convert_to; for (const auto& file : m_args.m_files_to_convert) Convert(file); return true; } private: void Convert(const std::string& file) { const fs::path filePath(file); auto extension = filePath.extension().string(); utils::MakeStringLowerCase(extension); if (extension == EXTENSION_IWI) ConvertIwi(filePath); else if (extension == EXTENSION_DDS) ConvertDds(filePath); else std::cerr << std::format("Unsupported extension {}\n", extension); } bool ConvertIwi(const fs::path& iwiPath) { std::ifstream file(iwiPath, std::ios::in | std::ios::binary); if (!file.is_open()) { std::cerr << std::format("Failed to open input file {}\n", iwiPath.string()); return false; } const auto texture = iwi::LoadIwi(file); if (!texture) return false; auto outPath = iwiPath; outPath.replace_extension(".dds"); std::ofstream outFile(outPath, std::ios::out | std::ios::binary); if (!outFile.is_open()) { std::cerr << std::format("Failed to open output file {}\n", outPath.string()); return false; } m_dds_writer.DumpImage(outFile, texture.get()); return true; } bool ConvertDds(const fs::path& ddsPath) { std::ifstream file(ddsPath, std::ios::in | std::ios::binary); if (!file.is_open()) { std::cerr << std::format("Failed to open input file {}\n", ddsPath.string()); return false; } const auto texture = dds::LoadDds(file); if (!texture) return false; if (!EnsureIwiWriterIsPresent()) return false; auto outPath = ddsPath; outPath.replace_extension(".iwi"); std::ofstream outFile(outPath, std::ios::out | std::ios::binary); if (!outFile.is_open()) { std::cerr << std::format("Failed to open output file {}\n", outPath.string()); return false; } m_iwi_writer->DumpImage(outFile, texture.get()); return true; } bool EnsureIwiWriterIsPresent() { if (m_iwi_writer) return true; if (m_game_to_convert_to == Game::UNKNOWN && !ShowGameTui()) return false; switch (m_game_to_convert_to) { case Game::IW3: m_iwi_writer = std::make_unique(); break; case Game::IW4: case Game::IW5: m_iwi_writer = std::make_unique(); break; case Game::T5: m_iwi_writer = std::make_unique(); break; case Game::T6: m_iwi_writer = std::make_unique(); break; default: assert(false); return false; } return true; } bool ShowGameTui() { std::cout << "Select the game to convert to:\n"; std::cout << " 1 - Call Of Duty 4: Modern Warfare (IW3)\n"; std::cout << " 2 - Call Of Duty: Modern Warfare 2 (IW4)\n"; std::cout << " 3 - Call Of Duty: Modern Warfare 3 (IW5)\n"; std::cout << " 4 - Call Of Duty: Black Ops (T5)\n"; std::cout << " 5 - Call Of Duty: Black Ops 2 (T6)\n"; unsigned num; std::cin >> num; switch (num) { case 1: m_game_to_convert_to = Game::IW3; break; case 2: m_game_to_convert_to = Game::IW4; break; case 3: m_game_to_convert_to = Game::IW5; break; case 4: m_game_to_convert_to = Game::T5; break; case 5: m_game_to_convert_to = Game::T6; break; default: std::cerr << "Invalid input\n"; return false; } return true; } ImageConverterArgs m_args; image_converter::Game m_game_to_convert_to; DdsWriter m_dds_writer; std::unique_ptr m_iwi_writer; }; } // namespace image_converter std::unique_ptr ImageConverter::Create() { return std::make_unique(); }