#include "ZRom.h" #include "Utils/BitConverter.h" #include #include "Utils/Directory.h" #include "yaz0/yaz0.h" #ifdef __linux__ #include #endif #include namespace fs = std::filesystem; #define DMA_ENTRY_SIZE 16 #if defined(_MSC_VER) #define __bswap_32 _byteswap_ulong #define bswap_32 _byteswap_ulong #endif #if defined __APPLE__ #define __bswap32 __builtin_bswap32 #define bswap32 __builtin_bswap32 #endif // ROM DMA Table Start #define OOT_OFF_NTSC_10_RC 0x7430 #define OOT_OFF_NTSC_10 0x7430 #define OOT_OFF_NTSC_11 0x7430 #define OOT_OFF_PAL_10 0x7950 #define OOT_OFF_NTSC_12 0x7960 #define OOT_OFF_PAL_11 0x7950 #define OOT_OFF_JP_GC 0x7170 #define OOT_OFF_JP_MQ 0x7170 #define OOT_OFF_US_GC 0x7170 #define OOT_OFF_US_MQ 0x7170 #define OOT_OFF_PAL_GC_DBG1 0x12F70 #define OOT_OFF_PAL_MQ_DBG 0x12F70 #define OOT_OFF_PAL_GC_DBG2 0x12F70 #define OOT_OFF_PAL_GC 0x7170 #define OOT_OFF_PAL_MQ 0x7170 #define OOT_OFF_JP_GC_CE 0x7170 #define OOT_OFF_CN_IQUE 0xB7A0 #define OOT_OFF_TW_IQUE 0xB240 #define MM_OFF_US_10 0x1A500 #define MM_OFF_US_GC 0x1AE90 #define MM_OFF_JP_GC 0x1AE90 #define MM_OFF_JP_10 0x1C110 #define MM_OFF_JP_11 0x1C050 #define MM_OFF_DBG 0x24F60 #define OOT_NTSC_10 0xEC7011B7 #define OOT_NTSC_11 0xD43DA81F #define OOT_NTSC_12 0x693BA2AE #define OOT_PAL_10 0xB044B569 #define OOT_PAL_11 0xB2055FBD #define OOT_NTSC_JP_GC_CE 0xF7F52DB8 #define OOT_NTSC_JP_GC 0xF611F4BA #define OOT_NTSC_US_GC 0xF3DD35BA #define OOT_PAL_GC 0x09465AC3 #define OOT_NTSC_JP_MQ 0xF43B45BA #define OOT_NTSC_US_MQ 0xF034001A #define OOT_PAL_MQ 0x1D4136F3 #define OOT_PAL_GC_DBG1 0x871E1C92 // 03-21-2002 build #define OOT_PAL_GC_DBG2 0x87121EFE // 03-13-2002 build #define OOT_PAL_GC_MQ_DBG 0x917D18F6 #define OOT_IQUE_TW 0x3D81FB3E #define OOT_IQUE_CN 0xB1E1E07B #define UNKNOWN 0xFFFFFFFF #define MM_NTSC_10 0x5354631C #define MM_NTSC_10_UNCOMPRESSED 0xDA6983E7 #define MM_NTSC_GC 0xB443EB08 #define MM_NTSC_JP_GC 0x8473D0C1 bool ZRom::IsMQ() { int crc = BitConverter::ToInt32BE(romData, 0x10); switch (crc) { case OOT_NTSC_10: case OOT_NTSC_11: case OOT_NTSC_12: case OOT_PAL_10: case OOT_PAL_11: case OOT_NTSC_JP_GC: case OOT_NTSC_JP_GC_CE: case OOT_NTSC_US_GC: case OOT_PAL_GC: case OOT_PAL_GC_DBG1: case OOT_PAL_GC_DBG2: case OOT_IQUE_CN: case OOT_IQUE_TW: // MM - Always not MQ case MM_NTSC_10: case MM_NTSC_10_UNCOMPRESSED: case MM_NTSC_GC: case MM_NTSC_JP_GC: default: return false; case OOT_NTSC_JP_MQ: case OOT_NTSC_US_MQ: case OOT_PAL_MQ: case OOT_PAL_GC_MQ_DBG: return true; } } ZRom::ZRom(std::string romPath) { RomVersion version; romData = DiskFile::ReadAllBytes(romPath); BitConverter::RomToBigEndian(romData.data(), romData.size()); version.crc = BitConverter::ToInt32BE(romData, 0x10); switch (version.crc) { case OOT_NTSC_10: version.version = "N64 NTSC 1.0"; version.listPath = "ntsc_oot.txt"; version.offset = OOT_OFF_NTSC_10; break; case OOT_NTSC_11: version.version = "N64 NTSC 1.1"; version.listPath = "ntsc_oot.txt"; version.offset = OOT_OFF_NTSC_11; break; case OOT_NTSC_12: version.version = "N64 NTSC 1.2"; version.listPath = "ntsc_12_oot.txt"; version.offset = OOT_OFF_NTSC_12; break; case OOT_PAL_10: version.version = "N64 PAL 1.0"; version.listPath = "pal_oot.txt"; version.offset = OOT_OFF_PAL_10; break; case OOT_PAL_11: version.version = "N64 PAL 1.1"; version.listPath = "pal_oot.txt"; version.offset = OOT_OFF_PAL_11; break; case OOT_NTSC_JP_GC: version.version = "JP GameCube (MQ Disk)"; version.listPath = "gamecube.txt"; version.offset = OOT_OFF_JP_GC; break; case OOT_NTSC_JP_GC_CE: version.version = "GameCube (Collectors Edition Disk)"; version.listPath = "gamecube.txt"; version.offset = OOT_OFF_JP_GC_CE; break; case OOT_NTSC_JP_MQ: version.version = "JP Master Quest"; version.listPath = "gamecube.txt"; version.offset = OOT_OFF_JP_MQ; break; case OOT_NTSC_US_MQ: version.version = "NTSC Master Quest"; version.listPath = "gamecube.txt"; version.offset = OOT_OFF_JP_MQ; break; case OOT_NTSC_US_GC: version.version = "NTSC GameCube"; version.listPath = "gamecube.txt"; version.offset = OOT_OFF_US_MQ; break; case OOT_PAL_GC: version.version = "PAL GameCube"; version.listPath = "gamecube_pal.txt"; version.offset = OOT_OFF_PAL_GC; break; case OOT_PAL_MQ: version.version = "PAL Master Quest"; version.listPath = "gamecube_pal.txt"; version.offset = OOT_OFF_PAL_MQ; break; case OOT_PAL_GC_DBG1: version.version = "GameCube Debug 1.0"; version.listPath = "dbg.txt"; version.offset = OOT_OFF_PAL_GC_DBG1; break; case OOT_PAL_GC_DBG2: version.version = "GameCube Debug 2.0"; version.listPath = "dbg.txt"; version.offset = OOT_OFF_PAL_GC_DBG2; break; case OOT_PAL_GC_MQ_DBG: version.version = "GameCube MQ-Debug"; version.listPath = "dbg.txt"; version.offset = OOT_OFF_PAL_MQ_DBG; break; case OOT_IQUE_CN: version.version = "OoT IQue"; version.listPath = "ique.txt"; version.offset = OOT_OFF_CN_IQUE; break; case OOT_IQUE_TW: version.version = "TW IQue"; version.listPath = "ique.txt"; version.offset = OOT_OFF_TW_IQUE; break; case MM_NTSC_10: version.version = "MM US 1.0"; version.listPath = "mm.txt"; version.offset = MM_OFF_US_10; break; case MM_NTSC_10_UNCOMPRESSED: version.version = "MM US 1.0"; version.listPath = "mm.txt"; version.offset = MM_OFF_US_10; break; case MM_NTSC_GC: version.version = "MM US GC"; version.listPath = "mm_gc.txt"; version.offset = MM_OFF_US_GC; break; case MM_NTSC_JP_GC: version.version = "MM JP GC"; version.listPath = "mm_gc_jp.txt"; version.offset = MM_OFF_JP_GC; break; } auto path = StringHelper::Sprintf("%s/%s", Globals::Instance->fileListPath.string().c_str(), version.listPath.c_str()); auto txt = DiskFile::ReadAllText(path); std::vector lines = StringHelper::Split(txt, "\n"); std::vector decompressedData(1); for (unsigned int i = 0; i < lines.size(); i++) { lines[i] = StringHelper::Strip(lines[i], "\r"); bool yarCompressed = false; const int romOffset = version.offset + (DMA_ENTRY_SIZE * i); const int virtStart = BitConverter::ToInt32BE(romData, romOffset + 0); const int virtEnd = BitConverter::ToInt32BE(romData, romOffset + 4); const int physStart = BitConverter::ToInt32BE(romData, romOffset + 8); const int physEnd = BitConverter::ToInt32BE(romData, romOffset + 12); // File Deleted if (physEnd == 0xFFFFFFFF && physStart == 0xFFFFFFFF) { // MM has some other checks that we might need to do //if (virtEnd - virtStart == 0) continue; } const bool compressed = physEnd != 0; int size = compressed ? physEnd - physStart : virtEnd - virtStart; auto outData = std::vector(); outData.resize(size); memcpy(outData.data(), romData.data() + physStart, size); // 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) { yarCompressed = true; } #endif if (compressed) { int decSize = virtEnd - virtStart; decompressedData = std::vector(); decompressedData.resize(decSize); yaz0_decode(outData.data(), decompressedData.data(), decSize); files[lines[i]] = decompressedData; } else if (yarCompressed) { //int decSize = virtEnd - virtStart; decompressedData = std::vector(); decompressedData.resize(1024*1024); //TODO FIX THIS PLEASE yaz0_decodeYarArchive(outData.data(), decompressedData.data(), size); files[lines[i]] = decompressedData; } else files[lines[i]] = outData; //DiskFile::WriteAllBytes(StringHelper::Sprintf("baserom/%s", lines[i].c_str()), files[lines[i]]); } } std::vector ZRom::GetFile(std::string fileName) { return files[fileName]; }