[Disk] Perform heuristics to find System Data and Disk ID for *.ndd

This commit is contained in:
LuigiBlood 2019-08-12 11:40:44 +02:00
parent 075c82a3e3
commit c8947e93ea
2 changed files with 124 additions and 6 deletions

View File

@ -89,8 +89,9 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc)
} }
} }
m_RomName = RomName; m_RomName = RomName;
m_Country = (Country)GetDiskAddressID()[0]; m_Country = GetDiskCountryCode();
m_DiskType = GetDiskAddressSys()[5 ^ 3] & 0x0F; m_DiskType = GetDiskAddressSys()[5 ^ 3] & 0x0F;
GenerateLBAToPhysTable(); GenerateLBAToPhysTable();
InitSysDataD64(); InitSysDataD64();
@ -313,8 +314,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc)
return false; return false;
} }
m_DiskSysAddress = 0; DetectSystemArea();
m_DiskIDAddress = 0x43670;
g_Notify->DisplayMessage(5, MSG_BYTESWAP); g_Notify->DisplayMessage(5, MSG_BYTESWAP);
ByteSwapDisk(); ByteSwapDisk();
@ -361,8 +361,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc)
return false; return false;
} }
m_DiskSysAddress = 0; DetectSystemArea();
m_DiskIDAddress = 0x100;
g_Notify->DisplayMessage(5, MSG_BYTESWAP); g_Notify->DisplayMessage(5, MSG_BYTESWAP);
ForceByteSwapDisk(); ForceByteSwapDisk();
@ -543,6 +542,116 @@ uint32_t CN64Disk::GetDiskAddressBlock(uint16_t head, uint16_t track, uint16_t b
return offset; 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() void CN64Disk::InitSysDataD64()
{ {
//Else the disk will not work properly. //Else the disk will not work properly.

View File

@ -47,6 +47,10 @@ private:
void ByteSwapDisk(); void ByteSwapDisk();
void ForceByteSwapDisk(); void ForceByteSwapDisk();
void SetError(LanguageStringID ErrorMsg); void SetError(LanguageStringID ErrorMsg);
void DetectSystemArea();
bool IsSysSectorGood(uint32_t block, uint32_t sectorsize);
Country GetDiskCountryCode();
void InitSysDataD64(); void InitSysDataD64();
void DeinitSysDataD64(); void DeinitSysDataD64();
void GenerateLBAToPhysTable(); void GenerateLBAToPhysTable();
@ -75,11 +79,16 @@ private:
uint8_t m_DiskFormat; //0 = MAME, 1 = SDK, 2 = D64 uint8_t m_DiskFormat; //0 = MAME, 1 = SDK, 2 = D64
uint8_t m_DiskType; uint8_t m_DiskType;
//Disk Calculations //Disk Defines
#define MAX_LBA 0x10DB #define MAX_LBA 0x10DB
#define SIZE_LBA MAX_LBA+1 #define SIZE_LBA MAX_LBA+1
#define SYSTEM_LBAS 24 #define SYSTEM_LBAS 24
#define DISKID_LBA 14 #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 SECTORS_PER_BLOCK 85
#define BLOCKS_PER_TRACK 2 #define BLOCKS_PER_TRACK 2