Last active
October 4, 2019 18:04
-
-
Save modeco80/732de5aca3f73209308882cc0c202e62 to your computer and use it in GitHub Desktop.
Tool to get the Playstation 2 Runtime Library version used to compile a singular or set of Playstation 2 ELF, ERX, or IRX module(s).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Tool to get the Playstation 2 Runtime Library version used to compile a singular or set of Playstation 2 | |
// ELF, ERX, or IRX module(s). | |
// | |
// (c) 2019 modeco80, in the public domain. | |
// | |
// Compile with: | |
// g++ -std=c++17 -O2 rtver.cpp -o rtver | |
#include <fstream> | |
#include <iostream> | |
#include <vector> | |
// 'PsII' | |
#define PSII_MAGIC 0x50734949 | |
struct PsModule { | |
char ModuleName[9]; | |
char RtVersion[4]; // stored as XXYY | |
}; | |
struct PsModuleVersion { | |
const char* ElfName; // from file paramater in GetModuleVersion | |
std::vector<PsModule> modules; | |
bool fail = false; // if true assume getting stuff failed | |
}; | |
// Gets a module version | |
PsModuleVersion GetModuleVersion(const char* file) { | |
std::ifstream stream(file); | |
if(!stream) { | |
return { | |
.ElfName = file, | |
.fail = true | |
}; | |
} | |
unsigned int magic; | |
bool found = false; | |
PsModuleVersion v; | |
v.ElfName = file; | |
v.fail = true; | |
while(stream) { | |
const char c = stream.get(); | |
// cursed hell pulled from prver | |
magic = magic << 8; | |
magic |= c; | |
if(magic == PSII_MAGIC) { | |
v.fail = false; | |
found = true; | |
PsModule m; | |
// Get internal module name | |
stream.get(m.ModuleName, 9); | |
if(!stream) return { .ElfName = file, .fail = true }; | |
// Get the Runtime Library version | |
stream.get(m.RtVersion, 4); | |
if(!stream) return { .ElfName = file, .fail = true }; | |
v.modules.push_back(m); | |
} | |
} | |
if(!found) { | |
// Didn't find anything. Fail. | |
return v; | |
} | |
return v; | |
} | |
int main(int argc, char** argv) { | |
std::vector<PsModuleVersion> versions; | |
if(argc < 2) { | |
std::cout << "rtver - Tool to get the Runtime Library version\n"; | |
std::cout << " used to compile a Playstation 2\n"; | |
std::cout << " ELF, ERX, or IRX module. (C) 2019 modeco80\n"; | |
std::cout << "Usage:\n"; | |
std::cout << " rtver <Single or multiple file input>\n"; | |
return 0; | |
} | |
// Happier. Fitter. More productive. | |
for(int i = 1; i < argc; ++i) | |
versions.push_back(GetModuleVersion(argv[i])); | |
for(auto v: versions) { | |
if(!v.fail) { | |
if(v.modules.size() == 1) { | |
// ERX/IRX will only have one module version. | |
auto m = *v.modules.begin(); | |
std::cout << v.ElfName << ": IRX/ERX Module " << m.ModuleName << ": Runtime Library " << m.RtVersion[0] << '.' << m.RtVersion[1] << '.' << m.RtVersion[2] << '\n'; | |
} else { | |
for(auto m: v.modules) | |
std::cout << v.ElfName << ": Module " << m.ModuleName << ": Runtime Library " << m.RtVersion[0] << '.' << m.RtVersion[1] << '.' << m.RtVersion[2] << '\n'; | |
} | |
} else { | |
std::cout << v.ElfName << ": Not a Playstation 2 SDK compiled binary, or file doesn't exist\n"; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment