finish pak loader
This commit is contained in:
		
							parent
							
								
									0df35fc0c9
								
							
						
					
					
						commit
						e5cf9ec68c
					
				| 
						 | 
					@ -4,18 +4,20 @@
 | 
				
			||||||
#include <QtGlobal>
 | 
					#include <QtGlobal>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QCoreApplication>
 | 
					#include <QCoreApplication>
 | 
				
			||||||
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <filesystem>
 | 
					#include <filesystem>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <ios>
 | 
					#include <ios>
 | 
				
			||||||
#include <iostream>
 | 
					 | 
				
			||||||
#include <istream>
 | 
					#include <istream>
 | 
				
			||||||
#include <iterator>
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
#include <stdexcept>
 | 
					#include <stdexcept>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <utility>
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <variant>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline QString trMain(char const *sourceText,
 | 
					static inline QString trMain(char const *sourceText,
 | 
				
			||||||
                             char const *disambiguation = nullptr,
 | 
					                             char const *disambiguation = nullptr,
 | 
				
			||||||
| 
						 | 
					@ -44,33 +46,22 @@ static inline std::array<char, N> readBytes(std::istream &st) {
 | 
				
			||||||
	return std::move(b);
 | 
						return std::move(b);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename It>
 | 
					static inline QDebug operator<<(QDebug debug, std::string const &t) {
 | 
				
			||||||
static inline std::string escapeText(It begin, It end) {
 | 
						debug << QString::fromStdString(t);
 | 
				
			||||||
	std::stringstream out;
 | 
						return debug;
 | 
				
			||||||
	out << std::hex << std::uppercase;
 | 
					}
 | 
				
			||||||
	for(auto it = begin; it != end; ++it) {
 | 
					
 | 
				
			||||||
		unsigned char c = *it;
 | 
					template<typename T>
 | 
				
			||||||
		switch(c) {
 | 
					static inline QDebug operator<<(QDebug debug, std::unique_ptr<T> const &t) {
 | 
				
			||||||
			case '"':  out << "\\\""; break;
 | 
						debug << *t;
 | 
				
			||||||
			case '\0': out << "\\0";  break;
 | 
						return debug;
 | 
				
			||||||
			case '\\': out << "\\\\"; break;
 | 
					}
 | 
				
			||||||
			case '\a': out << "\\a";  break;
 | 
					
 | 
				
			||||||
			case '\b': out << "\\b";  break;
 | 
					template<typename T0, typename... Ts>
 | 
				
			||||||
			case '\f': out << "\\f";  break;
 | 
					static inline QDebug operator <<(QDebug debug,
 | 
				
			||||||
			case '\n': out << "\\n";  break;
 | 
					                                 std::variant<T0, Ts...> const &t) {
 | 
				
			||||||
			case '\r': out << "\\r";  break;
 | 
						std::visit([&](auto &&arg) {debug << arg;}, t);
 | 
				
			||||||
			case '\t': out << "\\t";  break;
 | 
						return debug;
 | 
				
			||||||
			case '\v': out << "\\v";  break;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				if(c >= ' ' && c <= '~') {
 | 
					 | 
				
			||||||
					out << c;
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					out << "\\x" << int(c);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return out.str();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EOF
 | 
					// EOF
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ static int modeText(int argc, char *argv[]) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto fileName = par.value(fileNameOpt).toStdString();
 | 
						auto fileName = par.value(fileNameOpt).toStdString();
 | 
				
			||||||
	std::ifstream st{fileName, std::ios_base::in | std::ios_base::binary};
 | 
						std::ifstream st{fileName, std::ios_base::in | std::ios_base::binary};
 | 
				
			||||||
	readPakFile(st);
 | 
						auto pak = readPak(st);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ struct PakHeader {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct PakEntry {
 | 
					struct PakEntry {
 | 
				
			||||||
	std::string name;
 | 
						std::string name;
 | 
				
			||||||
	QByteArray  data;
 | 
						PakFile     data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static constexpr quint32 sizeOfPakEntry = 64;
 | 
					static constexpr quint32 sizeOfPakEntry = 64;
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ static PakEntry readPakEntry(std::istream &st) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	st.seekg(entOffset);
 | 
						st.seekg(entOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QByteArray bytes;
 | 
						PakFile bytes;
 | 
				
			||||||
	bytes.resize(entSize);
 | 
						bytes.resize(entSize);
 | 
				
			||||||
	st.read(bytes.data(), entSize);
 | 
						st.read(bytes.data(), entSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,27 +50,44 @@ static PakEntry readPakEntry(std::istream &st) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto zero = std::find(entName.cbegin(), entName.cend(), '\0');
 | 
						auto zero = std::find(entName.cbegin(), entName.cend(), '\0');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::string out;
 | 
						std::string name;
 | 
				
			||||||
	std::copy(entName.cbegin(), zero, std::back_inserter(out));
 | 
						std::copy(entName.cbegin(), zero, std::back_inserter(name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(name.front() == '/') {
 | 
				
			||||||
 | 
							name.erase(0, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PakEntry ent;
 | 
						PakEntry ent;
 | 
				
			||||||
	ent.name = std::move(out);
 | 
						ent.name = std::move(name);
 | 
				
			||||||
	ent.data = std::move(bytes);
 | 
						ent.data = std::move(bytes);
 | 
				
			||||||
	return ent;
 | 
						return ent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PakFile readPakFile(std::istream &st) {
 | 
					void insertFile(PakDir &dir, std::string name, PakFile file) {
 | 
				
			||||||
 | 
						if(auto slash = name.find('/'); slash != std::string::npos) {
 | 
				
			||||||
 | 
							auto folder = name.substr(0, slash);
 | 
				
			||||||
 | 
							auto next   = name.substr(slash + 1);
 | 
				
			||||||
 | 
							dir[folder] = std::make_unique<PakNode>(PakDir{});
 | 
				
			||||||
 | 
							insertFile(std::get<PakDir>(*dir[folder]),
 | 
				
			||||||
 | 
							           std::move(next),
 | 
				
			||||||
 | 
							           std::move(file));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							dir[name] = std::make_unique<PakNode>(std::move(file));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PakDir readPak(std::istream &st) {
 | 
				
			||||||
	auto hdr = readPakHeader(st);
 | 
						auto hdr = readPakHeader(st);
 | 
				
			||||||
	st.seekg(hdr.dirOffset);
 | 
						st.seekg(hdr.dirOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PakFile pak;
 | 
						PakDir root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for(quint32 i = 0; i < hdr.dirNum; i++) {
 | 
						for(quint32 i = 0; i < hdr.dirNum; i++) {
 | 
				
			||||||
		auto ent = readPakEntry(st);
 | 
							auto ent = readPakEntry(st);
 | 
				
			||||||
		pak.emplace(std::move(ent.name), std::move(ent.data));
 | 
							insertFile(root, std::move(ent.name), std::move(ent.data));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return pak;
 | 
						return root;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EOF
 | 
					// EOF
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,19 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PakFile : public std::map<std::string, QByteArray> {
 | 
					struct PakNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct PakDir : public std::map<std::string, std::unique_ptr<PakNode>> {
 | 
				
			||||||
 | 
						using std::map<std::string, std::unique_ptr<PakNode>>::map;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PakFile readPakFile(std::istream &st);
 | 
					struct PakFile : public QByteArray {
 | 
				
			||||||
 | 
						using QByteArray::QByteArray;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct PakNode : public std::variant<PakDir, PakFile> {
 | 
				
			||||||
 | 
						using std::variant<PakDir, PakFile>::variant;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PakDir readPak(std::istream &st);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EOF
 | 
					// EOF
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user