[Core] Perform more thorough disk validity checks & change DiskIdent for Config/RDB

- It didn't detect NUD-4567-JPN dump.
This commit is contained in:
LuigiBlood 2019-08-12 17:50:04 +02:00
parent 0cee922767
commit 0c6936d67e
5 changed files with 146 additions and 49 deletions

View File

@ -26,7 +26,8 @@ m_DiskHeaderBase(NULL),
m_ErrorMsg(EMPTY_STRING), m_ErrorMsg(EMPTY_STRING),
m_DiskBufAddress(0), m_DiskBufAddress(0),
m_DiskSysAddress(0), m_DiskSysAddress(0),
m_DiskIDAddress(0) m_DiskIDAddress(0),
m_DiskRomAddress(0)
{ {
} }
@ -57,10 +58,13 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc)
char RomName[5]; char RomName[5];
m_FileName = FileLoc; m_FileName = FileLoc;
uint32_t crc1 = CalculateCrc();
uint32_t crc2 = ~crc1;
m_DiskIdent.Format("%08X-%08X-C:%X", crc1, crc2, GetDiskAddressID()[0]);
//Get the disk ID from the disk image
if (*(uint32_t *)(&GetDiskAddressID()[0]) != 0) if (*(uint32_t *)(&GetDiskAddressID()[0]) != 0)
{ {
m_DiskIdent.Format("%08X-%08X-C:%X", *(uint32_t *)(&GetDiskAddressSys()[0]), *(uint32_t *)(&GetDiskAddressID()[0]), GetDiskAddressID()[0]); //if not 0x00000000
//Get the disk ID from the disk image
RomName[0] = (char)*(GetDiskAddressID() + 3); RomName[0] = (char)*(GetDiskAddressID() + 3);
RomName[1] = (char)*(GetDiskAddressID() + 2); RomName[1] = (char)*(GetDiskAddressID() + 2);
RomName[2] = (char)*(GetDiskAddressID() + 1); RomName[2] = (char)*(GetDiskAddressID() + 1);
@ -69,14 +73,7 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc)
} }
else else
{ {
uint32_t crc = 0; //if 0x00000000 then use a made up one
for (uint8_t i = 0; i < 0xE8; i += 4)
{
crc += *(uint32_t *)(m_DiskImage + i);
}
m_DiskIdent.Format("%08X-%08X-C:%X", *(uint32_t *)(&GetDiskAddressSys()[0]), crc, GetDiskAddressID()[0]);
//Get the disk ID from the disk image
RomName[0] = m_DiskIdent[12]; RomName[0] = m_DiskIdent[12];
RomName[1] = m_DiskIdent[11]; RomName[1] = m_DiskIdent[11];
RomName[2] = m_DiskIdent[10]; RomName[2] = m_DiskIdent[10];
@ -158,8 +155,21 @@ void CN64Disk::SwapDiskImage(const char * FileLoc)
LoadDiskImage(FileLoc); LoadDiskImage(FileLoc);
} }
bool CN64Disk::IsValidDiskImage(uint8_t Test[4]) bool CN64Disk::IsValidDiskImage(uint8_t Test[0x20])
{ {
//Basic System Data Check (first 0x20 bytes is enough)
//Disk Type
if ((Test[0x05] & 0xEF) > 6) return false;
//IPL Load Block
uint16_t ipl_load_blk = ((Test[0x06] << 16) | Test[0x07]);
if (ipl_load_blk > 0x10C3 || ipl_load_blk == 0x0000) return false;
//IPL Load Address
uint32_t ipl_load_addr = (Test[0x1C] << 32) | (Test[0x1D] << 24) | (Test[0x1E] << 16) | Test[0x1F];
if (ipl_load_addr < 0x80000000 && ipl_load_addr >= 0x80800000) return false;
//Country Code
if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; } if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; }
else if (*((uint32_t *)&Test[0]) == 0x56EE6322) { return true; } else if (*((uint32_t *)&Test[0]) == 0x56EE6322) { return true; }
else if (*((uint32_t *)&Test[0]) == 0x00000000) { return true; } else if (*((uint32_t *)&Test[0]) == 0x00000000) { return true; }
@ -242,19 +252,29 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc)
return false; return false;
} }
//Read the first 4 bytes and make sure it is a valid disk image //Make sure it is a valid disk image
uint8_t Test[4]; uint8_t Test[0x20];
m_DiskFile.SeekToBegin(); bool isValidDisk = false;
const uint8_t blocks[8] = { 0, 1, 2, 3, 8, 9, 10, 11 };
for (int i = 0; i < 8; i++)
{
m_DiskFile.Seek(0x4D08 * blocks[i], CFileBase::SeekPosition::begin);
if (m_DiskFile.Read(Test, sizeof(Test)) != sizeof(Test)) if (m_DiskFile.Read(Test, sizeof(Test)) != sizeof(Test))
{ {
m_DiskFile.Close(); m_DiskFile.Close();
WriteTrace(TraceN64System, TraceError, "Failed to read ident bytes"); WriteTrace(TraceN64System, TraceError, "Failed to read ident bytes");
return false; return false;
} }
if (!IsValidDiskImage(Test))
isValidDisk = IsValidDiskImage(Test);
if (isValidDisk)
break;
}
if (!isValidDisk)
{ {
m_DiskFile.Close(); m_DiskFile.Close();
WriteTrace(TraceN64System, TraceError, "invalid image file %X %X %X %X", Test[0], Test[1], Test[2], Test[3]); WriteTrace(TraceN64System, TraceError, "invalid disk image file");
return false; return false;
} }
uint32_t DiskFileSize = m_DiskFile.GetLength(); uint32_t DiskFileSize = m_DiskFile.GetLength();
@ -387,10 +407,10 @@ void CN64Disk::ByteSwapDisk()
{ {
uint32_t count; uint32_t count;
switch (*((uint32_t *)&m_DiskImage[0])) switch (*((uint32_t *)&GetDiskAddressSys()[8]))
{ {
case 0x16D348E8: case 0x281E140A:
case 0x56EE6322: case 0x3024180C:
for (count = 0; count < m_DiskFileSize; count += 4) for (count = 0; count < m_DiskFileSize; count += 4)
{ {
m_DiskImage[count] ^= m_DiskImage[count + 3]; m_DiskImage[count] ^= m_DiskImage[count + 3];
@ -401,10 +421,10 @@ void CN64Disk::ByteSwapDisk()
m_DiskImage[count + 1] ^= m_DiskImage[count + 2]; m_DiskImage[count + 1] ^= m_DiskImage[count + 2];
} }
break; break;
case 0xE848D316: break; case 0x0A141E28: break;
case 0x2263EE56: break; case 0x0C182430: break;
default: default:
g_Notify->DisplayError(stdstr_f("ByteSwapDisk: %X", m_DiskImage[0]).c_str()); g_Notify->DisplayError(stdstr_f("ByteSwapDisk: %08X - %08X", *((uint32_t *)&GetDiskAddressSys()[8]), m_DiskSysAddress).c_str());
} }
} }
@ -449,6 +469,17 @@ void CN64Disk::UnallocateDiskImage()
m_DiskImage = NULL; m_DiskImage = NULL;
} }
uint32_t CN64Disk::CalculateCrc()
{
//Custom CRC
int crc = 0;
for (int i = 0; i < 0x200; i += 4)
{
crc += *(uint32_t*)(&GetDiskAddressRom()[i]);
}
return crc;
}
uint32_t CN64Disk::GetDiskAddressBlock(uint16_t head, uint16_t track, uint16_t block, uint16_t sector, uint16_t sectorsize) uint32_t CN64Disk::GetDiskAddressBlock(uint16_t head, uint16_t track, uint16_t block, uint16_t sector, uint16_t sectorsize)
{ {
uint32_t offset = 0; uint32_t offset = 0;
@ -549,6 +580,7 @@ void CN64Disk::DetectSystemArea()
//MAME / SDK (System Area can be handled identically) //MAME / SDK (System Area can be handled identically)
m_DiskSysAddress = 0; m_DiskSysAddress = 0;
m_DiskIDAddress = DISKID_LBA * 0x4D08; m_DiskIDAddress = DISKID_LBA * 0x4D08;
m_DiskRomAddress = SYSTEM_LBAS * 0x4D08;
//Handle System Data //Handle System Data
const uint16_t sysblocks[4] = { 9, 8, 1, 0 }; const uint16_t sysblocks[4] = { 9, 8, 1, 0 };
@ -590,6 +622,7 @@ void CN64Disk::DetectSystemArea()
//D64 (uses fixed addresses) //D64 (uses fixed addresses)
m_DiskSysAddress = 0x000; m_DiskSysAddress = 0x000;
m_DiskIDAddress = 0x100; m_DiskIDAddress = 0x100;
m_DiskRomAddress = 0x200;
} }
} }

View File

@ -22,16 +22,18 @@ public:
bool LoadDiskImage(const char * FileLoc); bool LoadDiskImage(const char * FileLoc);
bool SaveDiskImage(); bool SaveDiskImage();
void SwapDiskImage(const char * FileLoc); void SwapDiskImage(const char * FileLoc);
static bool IsValidDiskImage(uint8_t Test[4]); static bool IsValidDiskImage(uint8_t Test[0x20]);
void SaveDiskSettingID(bool temp); void SaveDiskSettingID(bool temp);
void ClearDiskSettingID(); void ClearDiskSettingID();
uint8_t * GetDiskAddress() { return m_DiskImage; } uint8_t * GetDiskAddress() { return m_DiskImage; }
uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; } uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; }
uint8_t * GetDiskAddressSys() { return m_DiskImage + m_DiskSysAddress; } uint8_t * GetDiskAddressSys() { return m_DiskImage + m_DiskSysAddress; }
uint8_t * GetDiskAddressID() { return m_DiskImage + m_DiskIDAddress; } uint8_t * GetDiskAddressID() { return m_DiskImage + m_DiskIDAddress; }
uint8_t * GetDiskAddressRom() { return m_DiskImage + m_DiskRomAddress; }
uint8_t * GetDiskHeader() { return m_DiskHeader; } uint8_t * GetDiskHeader() { return m_DiskHeader; }
void SetDiskAddressBuffer(uint32_t address) { m_DiskBufAddress = address; } void SetDiskAddressBuffer(uint32_t address) { m_DiskBufAddress = address; }
uint32_t GetDiskAddressBlock(uint16_t head, uint16_t track, uint16_t block, uint16_t sector, uint16_t sectorsize); uint32_t GetDiskAddressBlock(uint16_t head, uint16_t track, uint16_t block, uint16_t sector, uint16_t sectorsize);
uint32_t CalculateCrc();
stdstr GetRomName() const { return m_RomName; } stdstr GetRomName() const { return m_RomName; }
stdstr GetFileName() const { return m_FileName; } stdstr GetFileName() const { return m_FileName; }
stdstr GetDiskIdent() const { return m_DiskIdent; } stdstr GetDiskIdent() const { return m_DiskIdent; }
@ -73,6 +75,7 @@ private:
uint32_t m_DiskBufAddress; uint32_t m_DiskBufAddress;
uint32_t m_DiskSysAddress; uint32_t m_DiskSysAddress;
uint32_t m_DiskIDAddress; uint32_t m_DiskIDAddress;
uint32_t m_DiskRomAddress;
LanguageStringID m_ErrorMsg; LanguageStringID m_ErrorMsg;
Country m_Country; Country m_Country;
stdstr m_RomName, m_FileName, m_DiskIdent; stdstr m_RomName, m_FileName, m_DiskIdent;

View File

@ -341,7 +341,7 @@ void CRomList::RefreshRomListStatic(CRomList * _this)
bool CRomList::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat) bool CRomList::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat)
{ {
uint8_t Test[4]; uint8_t Test[0x20];
if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0) if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0)
{ {
@ -412,10 +412,6 @@ bool CRomList::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_
{ {
return false; return false;
} }
if (!CN64Rom::IsValidRomImage(Test) && !CN64Disk::IsValidDiskImage(Test))
{
return false;
}
if (CN64Rom::IsValidRomImage(Test)) if (CN64Rom::IsValidRomImage(Test))
{ {
@ -425,21 +421,85 @@ bool CRomList::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_
return false; return false;
} }
} }
else if (!CN64Disk::IsValidDiskImage(Test) && (File.GetLength() == DISKSIZE_MAME || File.GetLength() == DISKSIZE_SDK))
if (CN64Disk::IsValidDiskImage(Test))
{ {
//Is a Disk Image uint32_t sysdataoffset = 0;
File.SeekToBegin(); uint32_t diskidoffset = 0x43670;
uint32_t romdataoffset = 0x738C0;
bool isValidDisk = false;
//Could still be a Disk Image
//System Data
const uint8_t blocks[7] = { 2, 3, 10, 11, 1, 8, 9 };
for (int i = 0; i < 7; i++)
{
sysdataoffset = 0x4D08 * blocks[i];
File.Seek(sysdataoffset, CFileBase::begin);
if (File.Read(Test, sizeof(Test)) != sizeof(Test))
{
return false;
}
isValidDisk = CN64Disk::IsValidDiskImage(Test);
if (isValidDisk)
break;
}
if (!isValidDisk)
{
return false;
}
File.Seek(sysdataoffset, CFileBase::begin);
if (!File.Read(Data, 0x100)) if (!File.Read(Data, 0x100))
{ {
return false; return false;
} }
File.Seek(0x43670, CFileBase::begin); File.Seek(diskidoffset, CFileBase::begin);
if (!File.Read(Data + 0x100, 0x20)) if (!File.Read(Data + 0x100, 0x20))
{ {
return false; return false;
} }
File.Seek(romdataoffset, CFileBase::begin);
if (!File.Read(Data + 0x200, 0x200))
{
return false;
} }
}
else if (CN64Disk::IsValidDiskImage(Test))
{
//Is a Disk Image
uint32_t sysdataoffset = 0;
uint32_t diskidoffset = 0x100;
uint32_t romdataoffset = 0x200;
if ((File.GetLength() == DISKSIZE_MAME) || (File.GetLength() == DISKSIZE_SDK))
{
diskidoffset = 0x43670;
romdataoffset = 0x738C0;
}
File.Seek(sysdataoffset, CFileBase::begin);
if (!File.Read(Data, 0x100))
{
return false;
}
File.Seek(diskidoffset, CFileBase::begin);
if (!File.Read(Data + 0x100, 0x20))
{
return false;
}
File.Seek(romdataoffset, CFileBase::begin);
if (!File.Read(Data + 0x200, 0x200))
{
return false;
}
}
else
{
return false;
}
*RomSize = File.GetLength(); *RomSize = File.GetLength();
FileFormat = Format_Uncompressed; FileFormat = Format_Uncompressed;
} }
@ -494,15 +554,12 @@ bool CRomList::FillRomInfo(ROM_INFO * pRomInfo)
pRomInfo->CartID[2] = *(RomData + 0x102); pRomInfo->CartID[2] = *(RomData + 0x102);
pRomInfo->Manufacturer = '\0'; pRomInfo->Manufacturer = '\0';
pRomInfo->Country = *(RomData + 0x100); pRomInfo->Country = *(RomData + 0x100);
pRomInfo->CRC1 = *(uint32_t *)(RomData + 0x00); pRomInfo->CRC1 = 0;
pRomInfo->CRC2 = *(uint32_t *)(RomData + 0x100); for (uint32_t i = 0; i < 0x200; i += 4)
if (pRomInfo->CRC2 == 0)
{ {
for (uint8_t i = 0; i < 0xE8; i += 4) pRomInfo->CRC1 += *(uint32_t *)(&RomData[0x200 + i]);
{
pRomInfo->CRC2 += *(uint32_t *)(RomData + i);
}
} }
pRomInfo->CRC2 = ~pRomInfo->CRC1;
pRomInfo->CicChip = CIC_NUS_8303; pRomInfo->CicChip = CIC_NUS_8303;
FillRomExtensionInfo(pRomInfo); FillRomExtensionInfo(pRomInfo);
} }
@ -582,6 +639,7 @@ void CRomList::ByteSwapRomData(uint8_t * Data, int32_t DataLen)
case 0x07408027: //64DD IPL case 0x07408027: //64DD IPL
case 0xD316E848: //64DD JP Disk case 0xD316E848: //64DD JP Disk
case 0xEE562263: //64DD US Disk case 0xEE562263: //64DD US Disk
case 0x00000000: //64DD DEV Disk
for (count = 0; count < DataLen; count += 4) for (count = 0; count < DataLen; count += 4)
{ {
Data[count] ^= Data[count + 2]; Data[count] ^= Data[count + 2];

View File

@ -85,7 +85,7 @@ private:
static void RefreshSettings(CRomList *); static void RefreshSettings(CRomList *);
static void NotificationCB(const char * Status, CRomList * _this); static void NotificationCB(const char * Status, CRomList * _this);
static void RefreshRomListStatic(CRomList * _this); static void RefreshRomListStatic(CRomList * _this);
static void ByteSwapRomData(uint8_t * Data, int DataLen); static void ByteSwapRomData(uint8_t * Data, int32_t DataLen);
CPath m_GameDir; CPath m_GameDir;
CIniFile * m_NotesIniFile; CIniFile * m_NotesIniFile;
@ -95,4 +95,7 @@ private:
CIniFile * m_ZipIniFile; CIniFile * m_ZipIniFile;
#endif #endif
CThread m_RefreshThread; CThread m_RefreshThread;
#define DISKSIZE_MAME 0x0435B0C0
#define DISKSIZE_SDK 0x03DEC800
}; };

View File

@ -189,7 +189,7 @@ DWORD CALLBACK RomInfoProc(HWND hDlg, DWORD uMsg, DWORD wParam, DWORD lParam)
//SetDlgItemTextW(hDlg, IDC_INFO_MD5, _this->m_pRomInfo->GetRomMD5().ToUTF16().c_str()); //SetDlgItemTextW(hDlg, IDC_INFO_MD5, _this->m_pRomInfo->GetRomMD5().ToUTF16().c_str());
//SetDlgItemTextW(hDlg, IDC_INFO_ROMSIZE, stdstr_f("%.1f MBit", (float)_this->m_pDiskInfo->GetRomSize() / 0x20000).ToUTF16().c_str()); //SetDlgItemTextW(hDlg, IDC_INFO_ROMSIZE, stdstr_f("%.1f MBit", (float)_this->m_pDiskInfo->GetRomSize() / 0x20000).ToUTF16().c_str());
BYTE * DiskHeader = _this->m_pDiskInfo->GetDiskAddress() + 0x43670; BYTE * DiskHeader = _this->m_pDiskInfo->GetDiskAddressID();
SetDlgItemTextW(hDlg, IDC_INFO_CARTID, stdstr_f("%c%c", DiskHeader[0x02], DiskHeader[0x01]).ToUTF16().c_str()); SetDlgItemTextW(hDlg, IDC_INFO_CARTID, stdstr_f("%c%c", DiskHeader[0x02], DiskHeader[0x01]).ToUTF16().c_str());
/*switch (DiskHeader[0x00]) /*switch (DiskHeader[0x00])
@ -217,8 +217,8 @@ DWORD CALLBACK RomInfoProc(HWND hDlg, DWORD uMsg, DWORD wParam, DWORD lParam)
default: default:
SetDlgItemTextW(hDlg, IDC_INFO_COUNTRY, stdstr_f(" Unknown %c (%02X)", DiskHeader[0x03], DiskHeader[0x03]).ToUTF16().c_str()); SetDlgItemTextW(hDlg, IDC_INFO_COUNTRY, stdstr_f(" Unknown %c (%02X)", DiskHeader[0x03], DiskHeader[0x03]).ToUTF16().c_str());
} }
SetDlgItemTextW(hDlg, IDC_INFO_CRC1, stdstr_f("0x%08X", *(uint32_t *)(_this->m_pDiskInfo->GetDiskAddress())).ToUTF16().c_str()); SetDlgItemTextW(hDlg, IDC_INFO_CRC1, stdstr_f("0x%08X", (_this->m_pDiskInfo->CalculateCrc())).ToUTF16().c_str());
SetDlgItemTextW(hDlg, IDC_INFO_CRC2, stdstr_f("0x%08X", *(DWORD *)(DiskHeader)).ToUTF16().c_str()); SetDlgItemTextW(hDlg, IDC_INFO_CRC2, stdstr_f("0x%08X", (~_this->m_pDiskInfo->CalculateCrc())).ToUTF16().c_str());
/* /*
std::wstring CicChip; std::wstring CicChip;
switch (_this->m_pRomInfo->CicChipID()) switch (_this->m_pRomInfo->CicChipID())