Fix extracting from MQ rom padded to 64MB (#7376)

Also show error message instead of just proceeding to start if vanilla o2r already extracted
This commit is contained in:
Philip Dubé
2026-10-12 02:08:14 +00:00
committed by GitHub
parent 88f98c63b6
commit 5c6006ee0f
2 changed files with 51 additions and 16 deletions
+8 -1
View File
@@ -366,7 +366,7 @@ size_t Extractor::GetCurRomSize() const {
bool Extractor::ValidateAndFixRom() {
// The MQ debug rom sometimes has the header patched to look like a US rom.
// Check the crc as if it were changed back, but leave mRomData as the original dump for torch.
// Check the crc as if it were changed back. CallTorch changes it back for real.
const uint8_t region = mRomData[0x3E];
if (GetRomVerCrc() == OOT_PAL_GC_MQ_DBG) {
mRomData[0x3E] = 'P';
@@ -666,6 +666,13 @@ bool Extractor::CallTorch(std::string installPath, std::string exportdir, std::a
*totalExtract = SohTorch::CountAssetFiles(srcDir + "/" + GetTorchVersionDir());
*extractCount = 0;
// MQ debug dumps only hold 54MB of data, the rest is dump-specific padding, and some have
// the region byte changed. Trim and restore it so every dump matches the one config.yml hash.
if (GetRomVerCrc() == OOT_PAL_GC_MQ_DBG && mRomData.size() == MB64) {
mRomData.resize(MB54);
mRomData[0x3E] = 'P';
}
// config.yml decides whether this is oot.o2r or oot-mq.o2r.
std::string archiveName = SohTorch::Extract(std::move(mRomData), srcDir, tempdir, portVersion, extractCount);
bool success = !archiveName.empty();
+43 -15
View File
@@ -430,7 +430,12 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
Extractor extract;
PromptSteps promptStep = PS_FILE_CHECK;
bool generatedIsMQ = false;
// Whether generatedIsMQ is set, i.e. the first prompted rom extracted fine
bool generatedFirst = false;
bool lastExtractFailed = false;
std::atomic<size_t> extractCount = 0, totalExtract = 0;
// Set by the extraction thread, shown as a popup by the main thread once the task finishes
std::atomic<bool> extractFailed = false;
std::string installPath = std::filesystem::absolute(Ship::Context::GetAppBundlePath()).string();
std::string dataPath = std::filesystem::absolute(Ship::Context::GetAppDirectoryPath(appShortName)).string();
@@ -613,15 +618,17 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
std::string msg = "Archive for current ROM, " + archive + ", already exists.\nExtract again?";
SohGui::RegisterPopup("Confirm Re-extract", msg.c_str(), "Yes", "No", [&]() {
extractionTask = threadPool->submit_task([&]() -> void {
extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
extractFailed =
!extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
extractCount = totalExtract = 0;
});
});
} else {
extractionTask = threadPool->submit_task([&]() -> void {
extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
extractFailed =
!extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
extractCount = totalExtract = 0;
});
}
@@ -677,9 +684,13 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
continue;
}
extractionTask = threadPool->submit_task([&]() -> void {
extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
generatedIsMQ = extract.IsMasterQuest();
extractFailed =
!extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
if (!extractFailed) {
generatedIsMQ = extract.IsMasterQuest();
generatedFirst = true;
}
promptStep = PS_SECOND;
extractCount = 0;
totalExtract = 0;
@@ -687,17 +698,28 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
continue;
}
case PS_SECOND: {
// Keep asking until the user says no, so a failed or cancelled rom can be retried
SohGui::RegisterPopup(
"Extraction Complete", "ROM Extracted. Extract another?", "Yes", "No",
lastExtractFailed ? "Extract Another" : "Extraction Complete",
lastExtractFailed ? "Try extracting another ROM?" : "ROM Extracted. Extract another?",
"Yes", "No",
[&]() {
if (!extract.ManuallySearchForRomMatchingType(generatedIsMQ ? RomSearchMode::Vanilla
: RomSearchMode::MQ)) {
extractStep = ES_VERIFY;
} else {
RomSearchMode mode = RomSearchMode::Both;
if (generatedFirst) {
mode = generatedIsMQ ? RomSearchMode::Vanilla : RomSearchMode::MQ;
}
if (extract.ManuallySearchForRomMatchingType(mode)) {
extractionTask = threadPool->submit_task([&]() -> void {
extract.CallTorch(installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
extractStep = ES_VERIFY;
extractFailed = !extract.CallTorch(
installPath, Ship::Context::GetAppDirectoryPath(appShortName),
&extractCount, &totalExtract);
if (!extractFailed && generatedFirst) {
extractStep = ES_VERIFY;
} else if (!extractFailed) {
// A retry of the first rom worked, so still offer the other type
generatedIsMQ = extract.IsMasterQuest();
generatedFirst = true;
}
extractCount = 0;
totalExtract = 0;
});
@@ -754,6 +776,12 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
} catch (const std::exception& e) {
SohGui::RegisterPopup("Extraction Crashed", e.what(), "Close", "", []() { exit(1); });
}
lastExtractFailed = extractFailed;
if (extractFailed) {
SohGui::RegisterPopup("Extraction Failed",
"The ROM could not be extracted. Check the log for details.", "OK", "");
extractFailed = false;
}
extractionTask.reset();
} else {
if (!ImGui::IsPopupOpen("ROM Extraction")) {