/*
* This file is part of tswow (https://github.com/tswow)
*
* Copyright (C) 2020 tswow
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
inline bool exists(std::string const& name) {
std::ifstream f(name.c_str());
return f.good();
}
bool clearFile(std::string const& file, const char* errorMsg)
{
if (exists(file))
{
remove(file.c_str());
if (exists(file))
{
std::cout << errorMsg << file << "\n";
return false;
}
}
return true;
}
int main(int argc, char **argv)
{
if (argc < 3)
{
std::cout << "Usage: mpqbuilder filelist outputfile";
return -1;
}
// 1. Read input file
std::string fileList = argv[1];
if (!exists(fileList))
{
std::cerr << "File list " << fileList << " does not exist\n";
}
std::ifstream is(fileList);
std::string line;
std::vector> files;
std::vector errors;
while (std::getline(is, line))
{
size_t fst = line.find_first_of('\t');
if (fst == std::string::npos)
{
errors.push_back("Malformed line:" + line);
continue;
}
std::string src = line.substr(0, fst);
std::string dst = line.substr(fst + 1);
if (!exists(src))
{
errors.push_back("Missing file:" + src);
continue;
}
files.push_back(std::make_pair(src,dst));
}
if (errors.size() > 0)
{
std::cerr << "Errors encountered when reading file list:\n";
for (std::string const& error : errors)
{
std::cerr << error << "\n";
}
return -1;
}
if(files.size() == 0)
{
std::cerr << "Tried creating an MPQ with no files\n";
return -1;
}
if (files.size() > 0x80000)
{
std::cerr << "Tried to create an MPQ with more than the maximum supported " << 0x80000 << " files\n";
return -1;
}
// 2. Write MPQ
struct TempFile {
std::string m_file;
TempFile(std::string const& file): m_file(file){}
~TempFile() {
clearFile(m_file, "Failed to remove temp file ");
}
} temp(std::string(argv[2])+".temp");
if (!clearFile(temp.m_file, "Failed to remove old temp file ")) return -1;
HANDLE handle = NULL;
size_t power = 4;
while (power < files.size()) power <<= 1;
if (!SFileCreateArchive(temp.m_file.c_str(), 0, power, &handle))
{
std::cerr << "Failed to create output mpq file " << temp.m_file << "\n";
return -1;
}
for (auto const& pair : files)
{
SFileAddFile(handle, pair.first.c_str(), pair.second.c_str(), 0);
}
SFileFlushArchive(handle);
SFileCloseArchive(handle);
// 3. Save to real output file
std::string outputFile = argv[2];
if (!clearFile(outputFile, "Failed to remove old mpq file "));
std::ifstream src(temp.m_file, std::ios::binary);
std::ofstream dst(outputFile, std::ios::binary);
dst << src.rdbuf();
return 0;
}