mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-16 15:20:11 -05:00
improve built in extraction detection (#2865)
This commit is contained in:
parent
72358eb4d7
commit
c70bdb7700
@ -54,10 +54,10 @@ static constexpr uint32_t OOT_PAL_GC_DBG2 = 0x87121EFE; // 03-13-2002 build
|
|||||||
static constexpr uint32_t OOT_PAL_GC_MQ_DBG = 0x917D18F6;
|
static constexpr uint32_t OOT_PAL_GC_MQ_DBG = 0x917D18F6;
|
||||||
|
|
||||||
static const std::unordered_map<uint32_t, const char*> verMap = {
|
static const std::unordered_map<uint32_t, const char*> verMap = {
|
||||||
{ OOT_PAL_GC, "Pal Gamecube" },
|
{ OOT_PAL_GC, "PAL GameCube" },
|
||||||
{ OOT_PAL_GC_DBG1, "PAL Debug 1" },
|
{ OOT_PAL_GC_DBG1, "PAL GameCube Debug 1" },
|
||||||
{ OOT_PAL_GC_DBG2, "PAL Debug 2" },
|
{ OOT_PAL_GC_DBG2, "PAL GameCube Debug 2" },
|
||||||
{ OOT_PAL_GC_MQ_DBG, "PAL MQ Debug" },
|
{ OOT_PAL_GC_MQ_DBG, "PAL GameCube MQ Debug" },
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO only check the first 54MB of the rom.
|
// TODO only check the first 54MB of the rom.
|
||||||
@ -156,6 +156,40 @@ void Extractor::SetRomInfo(const std::string& path) {
|
|||||||
mCurRomSize = GetCurRomSize();
|
mCurRomSize = GetCurRomSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Extractor::FilterRoms(std::vector<std::string>& roms, RomSearchMode searchMode) {
|
||||||
|
std::ifstream inFile;
|
||||||
|
std::vector<std::string>::iterator it = roms.begin();
|
||||||
|
|
||||||
|
while (it != roms.end()) {
|
||||||
|
std::string rom = *it;
|
||||||
|
SetRomInfo(rom);
|
||||||
|
|
||||||
|
// Skip. We will handle rom size errors later on after filtering
|
||||||
|
if (!ValidateRomSize()) {
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
inFile.open(rom, std::ios::in | std::ios::binary);
|
||||||
|
inFile.read((char*)mRomData.get(), mCurRomSize);
|
||||||
|
inFile.clear();
|
||||||
|
inFile.close();
|
||||||
|
|
||||||
|
RomToBigEndian(mRomData.get(), mCurRomSize);
|
||||||
|
|
||||||
|
// Rom doesn't claim to be valid
|
||||||
|
// Game type doesn't match search mode
|
||||||
|
if (!verMap.contains(GetRomVerCrc()) ||
|
||||||
|
(searchMode == RomSearchMode::Vanilla && IsMasterQuest()) ||
|
||||||
|
(searchMode == RomSearchMode::MQ && !IsMasterQuest())) {
|
||||||
|
it = roms.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Extractor::GetRoms(std::vector<std::string>& roms) {
|
void Extractor::GetRoms(std::vector<std::string>& roms) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FIND_DATAA ffd;
|
WIN32_FIND_DATAA ffd;
|
||||||
@ -258,6 +292,7 @@ bool Extractor::GetRomPathFromBox() {
|
|||||||
mCurRomSize = GetCurRomSize();
|
mCurRomSize = GetCurRomSize();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Extractor::GetRomVerCrc() const {
|
uint32_t Extractor::GetRomVerCrc() const {
|
||||||
return BSWAP32(((uint32_t*)mRomData.get())[4]);
|
return BSWAP32(((uint32_t*)mRomData.get())[4]);
|
||||||
}
|
}
|
||||||
@ -303,28 +338,73 @@ bool Extractor::ValidateRom(bool skipCrcTextBox) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Extractor::Run() {
|
bool Extractor::ManuallySearchForRom() {
|
||||||
|
std::ifstream inFile;
|
||||||
|
|
||||||
|
if (!GetRomPathFromBox()) {
|
||||||
|
ShowErrorBox("No rom selected", "No Rom selected. Exiting");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inFile.open(mCurrentRomPath, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!inFile.is_open()) {
|
||||||
|
return false; // TODO Handle error
|
||||||
|
}
|
||||||
|
|
||||||
|
inFile.read((char*)mRomData.get(), mCurRomSize);
|
||||||
|
inFile.close();
|
||||||
|
RomToBigEndian(mRomData.get(), mCurRomSize);
|
||||||
|
|
||||||
|
if (!ValidateRom()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Extractor::ManuallySearchForRomMatchingType(RomSearchMode searchMode) {
|
||||||
|
if (!ManuallySearchForRom()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char msgBuf[150];
|
||||||
|
snprintf(msgBuf, 150, "The selected rom does not match the expected game type\nExpected type: %s.\n\nDo you want to search again?",
|
||||||
|
searchMode == RomSearchMode::MQ ? "Master Quest" : "Vanilla");
|
||||||
|
|
||||||
|
while ((searchMode == RomSearchMode::Vanilla && IsMasterQuest()) ||
|
||||||
|
(searchMode == RomSearchMode::MQ && !IsMasterQuest())) {
|
||||||
|
int ret = ShowYesNoBox("Wrong Game Type", msgBuf);
|
||||||
|
switch (ret) {
|
||||||
|
case IDYES:
|
||||||
|
if (!ManuallySearchForRom()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case IDNO:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
UNREACHABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Extractor::Run(RomSearchMode searchMode) {
|
||||||
std::vector<std::string> roms;
|
std::vector<std::string> roms;
|
||||||
std::ifstream inFile;
|
std::ifstream inFile;
|
||||||
uint32_t verCrc;
|
|
||||||
|
|
||||||
GetRoms(roms);
|
GetRoms(roms);
|
||||||
|
FilterRoms(roms, searchMode);
|
||||||
|
|
||||||
if (roms.empty()) {
|
if (roms.empty()) {
|
||||||
int ret = ShowYesNoBox("No roms found", "No roms found. Look for one?");
|
int ret = ShowYesNoBox("No roms found", "No roms found. Look for one?");
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case IDYES:
|
case IDYES:
|
||||||
if (!GetRomPathFromBox()) {
|
if (!ManuallySearchForRomMatchingType(searchMode)) {
|
||||||
ShowErrorBox("No rom selected", "No rom selected. Exiting");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inFile.open(mCurrentRomPath, std::ios::in | std::ios::binary);
|
|
||||||
if (!inFile.is_open()) {
|
|
||||||
return false; // TODO Handle error
|
|
||||||
}
|
|
||||||
inFile.read((char*)mRomData.get(), mCurRomSize);
|
|
||||||
if (!ValidateRom()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -338,27 +418,21 @@ bool Extractor::Run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& rom : roms) {
|
for (const auto& rom : roms) {
|
||||||
int option;
|
|
||||||
|
|
||||||
SetRomInfo(rom);
|
SetRomInfo(rom);
|
||||||
if (inFile.is_open()) {
|
|
||||||
inFile.close();
|
|
||||||
}
|
|
||||||
inFile.open(rom, std::ios::in | std::ios::binary);
|
|
||||||
if (!ValidateRomSize()) {
|
if (!ValidateRomSize()) {
|
||||||
ShowSizeErrorBox();
|
ShowSizeErrorBox();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inFile.open(rom, std::ios::in | std::ios::binary);
|
||||||
inFile.read((char*)mRomData.get(), mCurRomSize);
|
inFile.read((char*)mRomData.get(), mCurRomSize);
|
||||||
|
inFile.clear();
|
||||||
|
inFile.close();
|
||||||
RomToBigEndian(mRomData.get(), mCurRomSize);
|
RomToBigEndian(mRomData.get(), mCurRomSize);
|
||||||
verCrc = GetRomVerCrc();
|
|
||||||
|
|
||||||
// Rom doesn't claim to be valid
|
int option = ShowRomPickBox(GetRomVerCrc());
|
||||||
if (!verMap.contains(verCrc)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
option = ShowRomPickBox(verCrc);
|
|
||||||
if (option == (int)ButtonId::YES) {
|
if (option == (int)ButtonId::YES) {
|
||||||
if (!ValidateRom(true)) {
|
if (!ValidateRom(true)) {
|
||||||
if (rom == roms.back()) {
|
if (rom == roms.back()) {
|
||||||
@ -371,21 +445,11 @@ bool Extractor::Run() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (option == (int)ButtonId::FIND) {
|
} else if (option == (int)ButtonId::FIND) {
|
||||||
if (!GetRomPathFromBox()) {
|
if (!ManuallySearchForRomMatchingType(searchMode)) {
|
||||||
ShowErrorBox("No rom selected", "No Rom selected. Exiting");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inFile.open(mCurrentRomPath, std::ios::in | std::ios::binary);
|
|
||||||
if (!inFile.is_open()) {
|
|
||||||
return false; // TODO Handle error
|
|
||||||
}
|
|
||||||
inFile.read((char*)mRomData.get(), mCurRomSize);
|
|
||||||
if (!ValidateRom()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (option == (int)ButtonId::NO) {
|
} else if (option == (int)ButtonId::NO) {
|
||||||
inFile.close();
|
|
||||||
if (rom == roms.back()) {
|
if (rom == roms.back()) {
|
||||||
ShowErrorBox("No rom provided", "No rom provided. Exiting");
|
ShowErrorBox("No rom provided", "No rom provided. Exiting");
|
||||||
return false;
|
return false;
|
||||||
|
@ -19,6 +19,12 @@ static constexpr size_t MB32 = 32 * MB_BASE;
|
|||||||
static constexpr size_t MB54 = 54 * MB_BASE;
|
static constexpr size_t MB54 = 54 * MB_BASE;
|
||||||
static constexpr size_t MB64 = 64 * MB_BASE;
|
static constexpr size_t MB64 = 64 * MB_BASE;
|
||||||
|
|
||||||
|
enum class RomSearchMode {
|
||||||
|
Both = 0,
|
||||||
|
Vanilla = 1,
|
||||||
|
MQ = 2,
|
||||||
|
};
|
||||||
|
|
||||||
class Extractor {
|
class Extractor {
|
||||||
std::unique_ptr<unsigned char[]> mRomData = std::make_unique<unsigned char[]>(MB64);
|
std::unique_ptr<unsigned char[]> mRomData = std::make_unique<unsigned char[]>(MB64);
|
||||||
std::string mCurrentRomPath;
|
std::string mCurrentRomPath;
|
||||||
@ -33,21 +39,24 @@ class Extractor {
|
|||||||
|
|
||||||
bool ValidateRom(bool skipCrcBox = false);
|
bool ValidateRom(bool skipCrcBox = false);
|
||||||
const char* GetZapdVerStr() const;
|
const char* GetZapdVerStr() const;
|
||||||
bool IsMasterQuest() const;
|
|
||||||
|
|
||||||
void SetRomInfo(const std::string& path);
|
void SetRomInfo(const std::string& path);
|
||||||
|
|
||||||
|
void FilterRoms(std::vector<std::string>& roms, RomSearchMode searchMode);
|
||||||
void GetRoms(std::vector<std::string>& roms);
|
void GetRoms(std::vector<std::string>& roms);
|
||||||
void ShowSizeErrorBox() const;
|
void ShowSizeErrorBox() const;
|
||||||
void ShowCrcErrorBox() const;
|
void ShowCrcErrorBox() const;
|
||||||
int ShowRomPickBox(uint32_t verCrc) const;
|
int ShowRomPickBox(uint32_t verCrc) const;
|
||||||
|
bool ManuallySearchForRom();
|
||||||
|
bool ManuallySearchForRomMatchingType(RomSearchMode searchMode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//TODO create some kind of abstraction for message boxes.
|
//TODO create some kind of abstraction for message boxes.
|
||||||
static int ShowYesNoBox(const char* title, const char* text);
|
static int ShowYesNoBox(const char* title, const char* text);
|
||||||
static void ShowErrorBox(const char* title, const char* text);
|
static void ShowErrorBox(const char* title, const char* text);
|
||||||
|
bool IsMasterQuest() const;
|
||||||
|
|
||||||
bool Run();
|
bool Run(RomSearchMode searchMode = RomSearchMode::Both);
|
||||||
bool CallZapd();
|
bool CallZapd();
|
||||||
const char* GetZapdStr();
|
const char* GetZapdStr();
|
||||||
};
|
};
|
||||||
|
@ -710,6 +710,7 @@ extern "C" void InitOTR() {
|
|||||||
#if not defined (__SWITCH__) && not defined(__WIIU__)
|
#if not defined (__SWITCH__) && not defined(__WIIU__)
|
||||||
if (!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("oot-mq.otr")) &&
|
if (!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("oot-mq.otr")) &&
|
||||||
!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("oot.otr"))){
|
!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("oot.otr"))){
|
||||||
|
bool generatedOtrIsMQ = false;
|
||||||
if (Extractor::ShowYesNoBox("No OTR Files", "No OTR files found. Generate one now?") == IDYES) {
|
if (Extractor::ShowYesNoBox("No OTR Files", "No OTR files found. Generate one now?") == IDYES) {
|
||||||
Extractor extract;
|
Extractor extract;
|
||||||
if (!extract.Run()) {
|
if (!extract.Run()) {
|
||||||
@ -717,12 +718,13 @@ extern "C" void InitOTR() {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
extract.CallZapd();
|
extract.CallZapd();
|
||||||
|
generatedOtrIsMQ = extract.IsMasterQuest();
|
||||||
} else {
|
} else {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (Extractor::ShowYesNoBox("Extraction Complete", "ROM Extracted. Extract another?") == IDYES) {
|
if (Extractor::ShowYesNoBox("Extraction Complete", "ROM Extracted. Extract another?") == IDYES) {
|
||||||
Extractor extract;
|
Extractor extract;
|
||||||
if (!extract.Run()) {
|
if (!extract.Run(generatedOtrIsMQ ? RomSearchMode::Vanilla : RomSearchMode::MQ)) {
|
||||||
Extractor::ShowErrorBox("Error", "An error occured, an OTR file may have been generated by a different step. Continuing...");
|
Extractor::ShowErrorBox("Error", "An error occured, an OTR file may have been generated by a different step. Continuing...");
|
||||||
} else {
|
} else {
|
||||||
extract.CallZapd();
|
extract.CallZapd();
|
||||||
|
Loading…
Reference in New Issue
Block a user