diff --git a/src/GSLArchive.cc b/src/GSLArchive.cc index 0104dffb..06df2e04 100644 --- a/src/GSLArchive.cc +++ b/src/GSLArchive.cc @@ -10,20 +10,20 @@ using namespace std; -// TODO: Support big-endian GSLs also (e.g. from PSO GC) - +template struct GSLHeaderEntry { ptext filename; - le_uint32_t offset; // In pages, so actual offset is this * 0x800 - le_uint32_t size; + LongT offset; // In pages, so actual offset is this * 0x800 + LongT size; uint64_t unused; -}; +} __attribute__((packed)); -GSLArchive::GSLArchive(shared_ptr data) : data(data) { +template +void GSLArchive::load_t() { StringReader r(*this->data); uint64_t min_data_offset = 0xFFFFFFFFFFFFFFFF; while (r.where() < min_data_offset) { - const auto& entry = r.get(); + const auto& entry = r.get>(); if (entry.filename.len() == 0) { break; } @@ -35,6 +35,15 @@ GSLArchive::GSLArchive(shared_ptr data) : data(data) { } } +GSLArchive::GSLArchive(shared_ptr data, bool big_endian) + : data(data) { + if (big_endian) { + this->load_t(); + } else { + this->load_t(); + } +} + const unordered_map GSLArchive::all_entries() const { return this->entries; } diff --git a/src/GSLArchive.hh b/src/GSLArchive.hh index 4f0635dc..96c863b4 100644 --- a/src/GSLArchive.hh +++ b/src/GSLArchive.hh @@ -12,7 +12,7 @@ class GSLArchive { public: - GSLArchive(std::shared_ptr data); + GSLArchive(std::shared_ptr data, bool big_endian); ~GSLArchive() = default; struct Entry { @@ -26,6 +26,9 @@ public: StringReader get_reader(const std::string& name) const; private: + template + void load_t(); + std::shared_ptr data; std::unordered_map entries; diff --git a/src/Main.cc b/src/Main.cc index db088d21..d9582d74 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -364,9 +364,8 @@ The options are:\n\ Extract all files from a GSL archive into the current directory.\n\ input-filename may be specified. If output-filename is specified, then it\n\ is treated as a prefix which is prepended to the filename of each file\n\ - contained in the GSL archive. Importantly, if you want to put the files\n\ - into a directory, you'll have to create the directory first, and include\n\ - a trailing / on output-filename.\n\ + contained in the GSL archive. If --big-endian is given, the GSL header is\n\ + read in GameCube format; otherwise it is read in PC/BB format.\n\ \n\ A few options apply to multiple modes described above:\n\ --parse-data\n\ @@ -825,7 +824,7 @@ int main(int argc, char** argv) { string data = read_input_data(); shared_ptr data_shared(new string(move(data))); - GSLArchive gsl(data_shared); + GSLArchive gsl(data_shared, big_endian); for (const auto& entry_it : gsl.all_entries()) { auto e = gsl.get(entry_it.first); save_file(output_filename + entry_it.first, e.first, e.second); @@ -930,7 +929,7 @@ int main(int argc, char** argv) { state->bb_patch_file_index.reset(new PatchFileIndex("system/patch-bb")); try { auto gsl_file = state->bb_patch_file_index->get("./data/data.gsl"); - state->bb_data_gsl.reset(new GSLArchive(gsl_file->load_data())); + state->bb_data_gsl.reset(new GSLArchive(gsl_file->load_data(), false)); config_log.info("data.gsl found in BB patch files"); } catch (const out_of_range&) { config_log.info("data.gsl is not present in BB patch files");