summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorinspectredc <78732756+inspectredc@users.noreply.github.com>2026-01-21 00:14:31 +0000
committerGitHub <noreply@github.com>2026-01-21 00:14:31 +0000
commit6859565909d8cfe02d813964afa0ae8a6da4018d (patch)
tree395942a9f45ea19c0d2e2511fb6986a2f78990ab
parentee3397a365c5f350a60538c88f0643f155944836 (diff)
MM PAL Support (#32)
* Support MM GC PAL * Fix GC PAL Yar compression and add Message Table File Support * Add PAL 1.1 Support
-rw-r--r--ZAPD/ZRom.cpp31
-rw-r--r--ZAPD/ZTextMM.cpp48
2 files changed, 72 insertions, 7 deletions
diff --git a/ZAPD/ZRom.cpp b/ZAPD/ZRom.cpp
index ae5343b..f18f3c9 100644
--- a/ZAPD/ZRom.cpp
+++ b/ZAPD/ZRom.cpp
@@ -44,7 +44,9 @@ namespace fs = std::filesystem;
#define MM_OFF_US_10 0x1A500
#define MM_OFF_US_GC 0x1AE90
+#define MM_OFF_PAL_11 0x1A8D0
#define MM_OFF_JP_GC 0x1AE90
+#define MM_OFF_PAL_GC 0x1AE90
#define MM_OFF_JP_10 0x1C110
#define MM_OFF_JP_11 0x1C050
#define MM_OFF_DBG 0x24F60
@@ -70,8 +72,10 @@ namespace fs = std::filesystem;
#define MM_NTSC_10 0x5354631C
#define MM_NTSC_10_UNCOMPRESSED 0xDA6983E7
+#define MM_PAL_11 0x0A5D8F83
#define MM_NTSC_GC 0xB443EB08
#define MM_NTSC_JP_GC 0x8473D0C1
+#define MM_PAL_GC 0x6AECEC4F
bool ZRom::IsMQ() {
int crc = BitConverter::ToInt32BE(romData, 0x10);
@@ -92,7 +96,9 @@ bool ZRom::IsMQ() {
// MM - Always not MQ
case MM_NTSC_10:
case MM_NTSC_10_UNCOMPRESSED:
+ case MM_PAL_11:
case MM_NTSC_GC:
+ case MM_PAL_GC:
case MM_NTSC_JP_GC:
default:
return false;
@@ -220,6 +226,16 @@ ZRom::ZRom(std::string romPath)
version.listPath = "mm_gc_jp.txt";
version.offset = MM_OFF_JP_GC;
break;
+ case MM_PAL_11:
+ version.version = "MM PAL 1.1";
+ version.listPath = "mm_pal.txt";
+ version.offset = MM_OFF_PAL_11;
+ break;
+ case MM_PAL_GC:
+ version.version = "MM PAL GC";
+ version.listPath = "mm_gc_pal.txt";
+ version.offset = MM_OFF_PAL_GC;
+ break;
}
auto path = StringHelper::Sprintf("%s/%s", Globals::Instance->fileListPath.string().c_str(), version.listPath.c_str());
@@ -255,9 +271,20 @@ ZRom::ZRom(std::string romPath)
// An ifdef is used here because at this point the XMLs haven't been parsed, and we don't
// know if this is MM or OOT
#ifdef GAME_MM
- if ((i >= 15 && i <= 20) || i == 22)
+ // PAL filelists differ For yar file locations, TODO: Find way to avoid special casing numbers
+ if (version.crc == MM_PAL_11 || version.crc == MM_PAL_GC)
+ {
+ if ((i >= 17 && i <= 28) || i == 30)
+ {
+ yarCompressed = true;
+ }
+ }
+ else
{
- yarCompressed = true;
+ if ((i >= 15 && i <= 20) || i == 22)
+ {
+ yarCompressed = true;
+ }
}
#endif
diff --git a/ZAPD/ZTextMM.cpp b/ZAPD/ZTextMM.cpp
index 5c63676..7c57941 100644
--- a/ZAPD/ZTextMM.cpp
+++ b/ZAPD/ZTextMM.cpp
@@ -11,7 +11,8 @@ REGISTER_ZFILENODE(TextMM, ZTextMM);
ZTextMM::ZTextMM(ZFile* nParent) : ZResource(nParent)
{
- RegisterRequiredAttribute("CodeOffset");
+ RegisterOptionalAttribute("CodeOffset");
+ RegisterOptionalAttribute("SegmentName");
RegisterOptionalAttribute("LangOffset", "0");
}
@@ -25,7 +26,19 @@ void ZTextMM::ParseRawData()
void ZTextMM::ParseMM()
{
const auto& rawData = parent->GetRawData();
- uint32_t currentPtr = StringHelper::StrToL(registeredAttributes.at("CodeOffset").value, 16);
+ uint32_t currentPtr;
+ bool messageTableInOwnSegment = false;
+
+ if (StringHelper::StrToL(registeredAttributes.at("CodeOffset").value, 16) != 0)
+ {
+ currentPtr = StringHelper::StrToL(registeredAttributes.at("CodeOffset").value, 16);
+ messageTableInOwnSegment = false;
+ }
+ else
+ {
+ currentPtr = 0;
+ messageTableInOwnSegment = true;
+ }
uint32_t langPtr = currentPtr;
bool isPalLang = false;
@@ -40,10 +53,35 @@ void ZTextMM::ParseMM()
std::vector<uint8_t> codeData;
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
- codeData = Globals::Instance->GetBaseromFile("code");
+ if (messageTableInOwnSegment)
+ {
+ if (registeredAttributes.at("SegmentName").value == "")
+ {
+ throw std::runtime_error(
+ StringHelper::Sprintf("ZTextMM: Missing one of required attributes: CodeOffset or SegmentName"));
+ }
+
+ codeData = Globals::Instance->GetBaseromFile(registeredAttributes.at("SegmentName").value);
+ }
+ else {
+ codeData = Globals::Instance->GetBaseromFile("code");
+ }
else
- codeData =
- Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code");
+ if (messageTableInOwnSegment)
+ {
+ if (registeredAttributes.at("SegmentName").value == "")
+ {
+ throw std::runtime_error(
+ StringHelper::Sprintf("ZTextMM: Missing one of required attributes: CodeOffset or SegmentName"));
+ }
+ codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string()
+ + registeredAttributes.at("SegmentName").value);
+ }
+ else
+ {
+ codeData =
+ Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code");
+ }
while (true)
{