From c8947e93ea1e2b7eba995d92c7867438c5ba19b2 Mon Sep 17 00:00:00 2001 From: LuigiBlood Date: Mon, 12 Aug 2019 11:40:44 +0200 Subject: [PATCH] [Disk] Perform heuristics to find System Data and Disk ID for *.ndd --- .../Project64-core/N64System/N64DiskClass.cpp | 119 +++++++++++++++++- .../Project64-core/N64System/N64DiskClass.h | 11 +- 2 files changed, 124 insertions(+), 6 deletions(-) diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 3ba012f48..a5eced575 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -89,8 +89,9 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) } } m_RomName = RomName; - m_Country = (Country)GetDiskAddressID()[0]; + m_Country = GetDiskCountryCode(); m_DiskType = GetDiskAddressSys()[5 ^ 3] & 0x0F; + GenerateLBAToPhysTable(); InitSysDataD64(); @@ -313,8 +314,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) return false; } - m_DiskSysAddress = 0; - m_DiskIDAddress = 0x43670; + DetectSystemArea(); g_Notify->DisplayMessage(5, MSG_BYTESWAP); ByteSwapDisk(); @@ -361,8 +361,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) return false; } - m_DiskSysAddress = 0; - m_DiskIDAddress = 0x100; + DetectSystemArea(); g_Notify->DisplayMessage(5, MSG_BYTESWAP); ForceByteSwapDisk(); @@ -543,6 +542,116 @@ uint32_t CN64Disk::GetDiskAddressBlock(uint16_t head, uint16_t track, uint16_t b return offset; } +void CN64Disk::DetectSystemArea() +{ + if ((m_DiskFormat == DiskFormatMAME) || (m_DiskFormat == DiskFormatSDK)) + { + //MAME / SDK (System Area can be handled identically) + m_DiskSysAddress = 0; + m_DiskIDAddress = DISKID_LBA * 0x4D08; + + //Handle System Data + const uint16_t sysblocks[4] = { 9, 8, 1, 0 }; + //Check if Disk is development disk + bool isDevDisk = false; + + for (int i = 0; i < 4; i++) + { + if (IsSysSectorGood(sysblocks[i] + 2, 0xC0)) + { + m_DiskSysAddress = ((sysblocks[i] + 2) * 0x4D08); + isDevDisk = true; + } + } + + if (!isDevDisk) + { + for (int i = 0; i < 4; i++) + { + if (IsSysSectorGood(sysblocks[i], 0xE8)) + { + m_DiskSysAddress = (sysblocks[i] * 0x4D08); + } + } + } + + //Handle Disk ID + for (int i = 2; i > 0; i--) + { + //There are two Disk ID Blocks + if (IsSysSectorGood(DISKID_LBA + i, 0xE8)) + { + m_DiskIDAddress = ((DISKID_LBA + i) * 0x4D08); + } + } + } + else //if (m_DiskFormat == DiskFormatD64) + { + //D64 (uses fixed addresses) + m_DiskSysAddress = 0x000; + m_DiskIDAddress = 0x100; + } +} + +bool CN64Disk::IsSysSectorGood(uint32_t block, uint32_t sectorsize) +{ + //Checks if all sectors are identical (meant only to be used for System Area for MAME and SDK formats) + for (int j = 1; j < SECTORS_PER_BLOCK; j++) + { + for (int k = 0; k < sectorsize; k++) + { + if (m_DiskImage[(block * 0x4D08) + (j * sectorsize) + k] != m_DiskImage[(block * 0x4D08) + k]) + { + return false; + } + } + } + + if (block < DISKID_LBA) + { + //Check System Data + + //System Format + if (m_DiskImage[(block * 0x4D08) + 4] != 0x10) + return false; + + //Disk Format + if ((m_DiskImage[(block * 0x4D08) + 5] & 0xF0) != 0x10) + return false; + + //Always 0xFFFFFFFF + if (*(uint32_t*)&m_DiskImage[(block * 0x4D08) + 0x18] != 0xFFFFFFFF) + return false; + + uint8_t alt = 0xC; //Retail + if ((block & 2) != 0) + alt = 0xA; //Development + + //Alternate Tracks Offsets (always the same) + for (int i = 0; i < 16; i++) + { + if (m_DiskImage[(block * 0x4D08) + 8 + i] != ((i + 1) * alt)) + return false; + } + } + + return true; +} + +Country CN64Disk::GetDiskCountryCode() +{ + switch (*(uint32_t*)&GetDiskAddressSys()[0]) + { + case DISK_COUNTRY_JPN: + return Country::Japan; + case DISK_COUNTRY_USA: + return Country::USA; + case DISK_COUNTRY_DEV: + default: + return Country::UnknownCountry; + } +} + void CN64Disk::InitSysDataD64() { //Else the disk will not work properly. diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h index 1daeeace9..d9666834c 100644 --- a/Source/Project64-core/N64System/N64DiskClass.h +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -47,6 +47,10 @@ private: void ByteSwapDisk(); void ForceByteSwapDisk(); void SetError(LanguageStringID ErrorMsg); + + void DetectSystemArea(); + bool IsSysSectorGood(uint32_t block, uint32_t sectorsize); + Country GetDiskCountryCode(); void InitSysDataD64(); void DeinitSysDataD64(); void GenerateLBAToPhysTable(); @@ -75,11 +79,16 @@ private: uint8_t m_DiskFormat; //0 = MAME, 1 = SDK, 2 = D64 uint8_t m_DiskType; - //Disk Calculations + //Disk Defines #define MAX_LBA 0x10DB #define SIZE_LBA MAX_LBA+1 #define SYSTEM_LBAS 24 #define DISKID_LBA 14 + + #define DISK_COUNTRY_JPN 0xE848D316 + #define DISK_COUNTRY_USA 0x2263EE56 + #define DISK_COUNTRY_DEV 0x00000000 + #define SECTORS_PER_BLOCK 85 #define BLOCKS_PER_TRACK 2