diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 88a347a9c..f543486e6 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -26,7 +26,8 @@ m_DiskHeaderBase(NULL), m_ErrorMsg(EMPTY_STRING), m_DiskBufAddress(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]; 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) { - m_DiskIdent.Format("%08X-%08X-C:%X", *(uint32_t *)(&GetDiskAddressSys()[0]), *(uint32_t *)(&GetDiskAddressID()[0]), GetDiskAddressID()[0]); - //Get the disk ID from the disk image + //if not 0x00000000 RomName[0] = (char)*(GetDiskAddressID() + 3); RomName[1] = (char)*(GetDiskAddressID() + 2); RomName[2] = (char)*(GetDiskAddressID() + 1); @@ -69,14 +73,7 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) } else { - uint32_t crc = 0; - 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 + //if 0x00000000 then use a made up one RomName[0] = m_DiskIdent[12]; RomName[1] = m_DiskIdent[11]; RomName[2] = m_DiskIdent[10]; @@ -158,8 +155,21 @@ void CN64Disk::SwapDiskImage(const char * 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; } else if (*((uint32_t *)&Test[0]) == 0x56EE6322) { return true; } else if (*((uint32_t *)&Test[0]) == 0x00000000) { return true; } @@ -242,19 +252,29 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) return false; } - //Read the first 4 bytes and make sure it is a valid disk image - uint8_t Test[4]; - m_DiskFile.SeekToBegin(); - if (m_DiskFile.Read(Test, sizeof(Test)) != sizeof(Test)) + //Make sure it is a valid disk image + uint8_t Test[0x20]; + 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.Close(); - WriteTrace(TraceN64System, TraceError, "Failed to read ident bytes"); - return false; + m_DiskFile.Seek(0x4D08 * blocks[i], CFileBase::SeekPosition::begin); + if (m_DiskFile.Read(Test, sizeof(Test)) != sizeof(Test)) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceError, "Failed to read ident bytes"); + return false; + } + + isValidDisk = IsValidDiskImage(Test); + if (isValidDisk) + break; } - if (!IsValidDiskImage(Test)) + if (!isValidDisk) { 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; } uint32_t DiskFileSize = m_DiskFile.GetLength(); @@ -387,10 +407,10 @@ void CN64Disk::ByteSwapDisk() { uint32_t count; - switch (*((uint32_t *)&m_DiskImage[0])) + switch (*((uint32_t *)&GetDiskAddressSys()[8])) { - case 0x16D348E8: - case 0x56EE6322: + case 0x281E140A: + case 0x3024180C: for (count = 0; count < m_DiskFileSize; count += 4) { m_DiskImage[count] ^= m_DiskImage[count + 3]; @@ -401,10 +421,10 @@ void CN64Disk::ByteSwapDisk() m_DiskImage[count + 1] ^= m_DiskImage[count + 2]; } break; - case 0xE848D316: break; - case 0x2263EE56: break; + case 0x0A141E28: break; + case 0x0C182430: break; 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; } +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 offset = 0; @@ -549,6 +580,7 @@ void CN64Disk::DetectSystemArea() //MAME / SDK (System Area can be handled identically) m_DiskSysAddress = 0; m_DiskIDAddress = DISKID_LBA * 0x4D08; + m_DiskRomAddress = SYSTEM_LBAS * 0x4D08; //Handle System Data const uint16_t sysblocks[4] = { 9, 8, 1, 0 }; @@ -590,6 +622,7 @@ void CN64Disk::DetectSystemArea() //D64 (uses fixed addresses) m_DiskSysAddress = 0x000; m_DiskIDAddress = 0x100; + m_DiskRomAddress = 0x200; } } diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h index d9666834c..e86385da3 100644 --- a/Source/Project64-core/N64System/N64DiskClass.h +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -22,16 +22,18 @@ public: bool LoadDiskImage(const char * FileLoc); bool SaveDiskImage(); void SwapDiskImage(const char * FileLoc); - static bool IsValidDiskImage(uint8_t Test[4]); + static bool IsValidDiskImage(uint8_t Test[0x20]); void SaveDiskSettingID(bool temp); void ClearDiskSettingID(); uint8_t * GetDiskAddress() { return m_DiskImage; } uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; } uint8_t * GetDiskAddressSys() { return m_DiskImage + m_DiskSysAddress; } uint8_t * GetDiskAddressID() { return m_DiskImage + m_DiskIDAddress; } + uint8_t * GetDiskAddressRom() { return m_DiskImage + m_DiskRomAddress; } uint8_t * GetDiskHeader() { return m_DiskHeader; } 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 CalculateCrc(); stdstr GetRomName() const { return m_RomName; } stdstr GetFileName() const { return m_FileName; } stdstr GetDiskIdent() const { return m_DiskIdent; } @@ -73,6 +75,7 @@ private: uint32_t m_DiskBufAddress; uint32_t m_DiskSysAddress; uint32_t m_DiskIDAddress; + uint32_t m_DiskRomAddress; LanguageStringID m_ErrorMsg; Country m_Country; stdstr m_RomName, m_FileName, m_DiskIdent; diff --git a/Source/Project64-core/RomList/RomList.cpp b/Source/Project64-core/RomList/RomList.cpp index 24357c7a5..1880d7bcf 100644 --- a/Source/Project64-core/RomList/RomList.cpp +++ b/Source/Project64-core/RomList/RomList.cpp @@ -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) { - uint8_t Test[4]; + uint8_t Test[0x20]; 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; } - if (!CN64Rom::IsValidRomImage(Test) && !CN64Disk::IsValidDiskImage(Test)) - { - return false; - } if (CN64Rom::IsValidRomImage(Test)) { @@ -425,21 +421,85 @@ bool CRomList::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_ return false; } } - - if (CN64Disk::IsValidDiskImage(Test)) + else if (!CN64Disk::IsValidDiskImage(Test) && (File.GetLength() == DISKSIZE_MAME || File.GetLength() == DISKSIZE_SDK)) { - //Is a Disk Image - File.SeekToBegin(); + uint32_t sysdataoffset = 0; + 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)) { return false; } - File.Seek(0x43670, CFileBase::begin); + 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 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(); FileFormat = Format_Uncompressed; } @@ -494,15 +554,12 @@ bool CRomList::FillRomInfo(ROM_INFO * pRomInfo) pRomInfo->CartID[2] = *(RomData + 0x102); pRomInfo->Manufacturer = '\0'; pRomInfo->Country = *(RomData + 0x100); - pRomInfo->CRC1 = *(uint32_t *)(RomData + 0x00); - pRomInfo->CRC2 = *(uint32_t *)(RomData + 0x100); - if (pRomInfo->CRC2 == 0) + pRomInfo->CRC1 = 0; + for (uint32_t i = 0; i < 0x200; i += 4) { - for (uint8_t i = 0; i < 0xE8; i += 4) - { - pRomInfo->CRC2 += *(uint32_t *)(RomData + i); - } + pRomInfo->CRC1 += *(uint32_t *)(&RomData[0x200 + i]); } + pRomInfo->CRC2 = ~pRomInfo->CRC1; pRomInfo->CicChip = CIC_NUS_8303; FillRomExtensionInfo(pRomInfo); } @@ -582,6 +639,7 @@ void CRomList::ByteSwapRomData(uint8_t * Data, int32_t DataLen) case 0x07408027: //64DD IPL case 0xD316E848: //64DD JP Disk case 0xEE562263: //64DD US Disk + case 0x00000000: //64DD DEV Disk for (count = 0; count < DataLen; count += 4) { Data[count] ^= Data[count + 2]; diff --git a/Source/Project64-core/RomList/RomList.h b/Source/Project64-core/RomList/RomList.h index 294848e95..877eeb405 100644 --- a/Source/Project64-core/RomList/RomList.h +++ b/Source/Project64-core/RomList/RomList.h @@ -85,7 +85,7 @@ private: static void RefreshSettings(CRomList *); static void NotificationCB(const char * Status, 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; CIniFile * m_NotesIniFile; @@ -95,4 +95,7 @@ private: CIniFile * m_ZipIniFile; #endif CThread m_RefreshThread; + + #define DISKSIZE_MAME 0x0435B0C0 + #define DISKSIZE_SDK 0x03DEC800 }; diff --git a/Source/Project64/UserInterface/RomInformationClass.cpp b/Source/Project64/UserInterface/RomInformationClass.cpp index 43855a91e..f9c81ffcd 100644 --- a/Source/Project64/UserInterface/RomInformationClass.cpp +++ b/Source/Project64/UserInterface/RomInformationClass.cpp @@ -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_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()); /*switch (DiskHeader[0x00]) @@ -217,8 +217,8 @@ DWORD CALLBACK RomInfoProc(HWND hDlg, DWORD uMsg, DWORD wParam, DWORD lParam) default: 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_CRC2, stdstr_f("0x%08X", *(DWORD *)(DiskHeader)).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", (~_this->m_pDiskInfo->CalculateCrc())).ToUTF16().c_str()); /* std::wstring CicChip; switch (_this->m_pRomInfo->CicChipID())