Skip to content

Instantly share code, notes, and snippets.

@modeco80
Last active October 4, 2019 18:04
Show Gist options
  • Save modeco80/732de5aca3f73209308882cc0c202e62 to your computer and use it in GitHub Desktop.
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).
//
// 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