[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_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.

View File

@ -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