Skip to content

Commit b607e2c

Browse files
MalkierianKiritoDv
authored andcommitted
Add ROM archive version checking and re-extraction flow.
1 parent 9baff81 commit b607e2c

2 files changed

Lines changed: 57 additions & 4 deletions

File tree

include/variables.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ extern f32 climbPoleBottom[3];
1818
extern f32 climbPoleTop[3];
1919

2020
extern const char gBuildVersion[];
21+
extern const u16 gBuildVersionMajor;
22+
extern const u16 gBuildVersionMinor;
23+
extern const u16 gBuildVersionPatch;
2124
extern const char gGitBranch[];
2225
extern const char gGitCommitHash[];
2326
extern u8 gGitCommitTag[];

src/port/Engine.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,55 @@ extern "C" {
6767
bool prevAltAssets = false;
6868
}
6969

70+
typedef struct {
71+
uint16_t major;
72+
uint16_t minor;
73+
uint16_t patch;
74+
} OTRVersion;
75+
7076
GameEngine* GameEngine::Instance;
7177

78+
// Read the port version from an OTR file
79+
OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
80+
OTRVersion version = {};
81+
82+
// Use a temporary archive instance to load the otr and read the version file
83+
auto archive = std::make_shared<Ship::O2rArchive>(otrPath);
84+
if (archive->Open()) {
85+
auto t = archive->LoadFile("portVersion");
86+
if (t != nullptr && t->IsLoaded) {
87+
auto stream = std::make_shared<Ship::MemoryStream>(t->Buffer->data(), t->Buffer->size());
88+
auto reader = std::make_shared<Ship::BinaryReader>(stream);
89+
Ship::Endianness endianness = (Ship::Endianness)reader->ReadUByte();
90+
reader->SetEndianness(endianness);
91+
version.major = reader->ReadUInt16();
92+
version.minor = reader->ReadUInt16();
93+
version.patch = reader->ReadUInt16();
94+
}
95+
}
96+
97+
return version;
98+
}
99+
100+
// Checks the program version stored in the otr and compares the major value to soh
101+
// For Windows/Mac/Linux if the version doesn't match, offer to
102+
OTRVersion DetectOTRVersion(std::string fileName) {
103+
bool isOtrOld = false;
104+
std::string otrPath = Ship::Context::LocateFileAcrossAppDirs(fileName, "sm64");
105+
106+
// Doesn't exist so nothing to do here
107+
if (!std::filesystem::exists(otrPath)) {
108+
return { INT16_MAX, INT16_MAX, INT16_MAX };
109+
}
110+
111+
return ReadPortVersionFromOTR(otrPath);
112+
}
113+
114+
bool VerifyArchiveVersion(OTRVersion version) {
115+
return version.major != INT16_MAX && version.minor != INT16_MAX &&
116+
(version.major == gBuildVersionMajor || version.minor == gBuildVersionMinor);
117+
}
118+
72119
GameEngine::GameEngine() : dictionary(nullptr) {
73120
this->context = Ship::Context::CreateUninitializedInstance("Ghostship", "sm64", "ghostship.cfg.json");
74121

@@ -81,16 +128,19 @@ GameEngine::GameEngine() : dictionary(nullptr) {
81128
const std::string main_path = Ship::Context::GetPathRelativeToAppDirectory("sm64.o2r");
82129
const std::string assets_path = Ship::Context::LocateFileAcrossAppDirs("ghostship.o2r");
83130

131+
bool shouldRegen = VerifyArchiveVersion(DetectOTRVersion("sm64.o2r"));
132+
84133
#ifdef _WIN32
85134
AllocConsole();
86135
#endif
87136

88-
if (std::filesystem::exists(main_path)) {
137+
if (std::filesystem::exists(main_path) && !shouldRegen) {
89138
archiveFiles.push_back(main_path);
90139
} else {
91-
if (ShowYesNoBox("Ghostship - Asset Extraction",
92-
"Please provide a Super Mario 64 ROM.\n\nSupported Versions:\nUS\nJP\n\nAssets will be "
93-
"extracted into an O2R file.") == IDYES) {
140+
std::string msg = (shouldRegen ? "Your ROM O2R is outdated, and needs to be re-extracted.\n\n" : "") +
141+
std::string("Please provide a Super Mario 64 ROM.\n\nSupported Versions:\nUS\nJP\n\n"
142+
"Assets will be extracted into an O2R file.");
143+
if (ShowYesNoBox("Ghostship - Asset Extraction", msg.c_str()) == IDYES) {
94144
if (!GenAssetFile()) {
95145
ShowMessage("Error", "An error occured, no O2R file was generated.\n\nExiting...");
96146
exit(1);

0 commit comments

Comments
 (0)