diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 0eaa55819..5f27c4b45 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -47,21 +47,21 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) bool CN64Disk::SaveDiskImage() { + WriteTrace(TraceN64System, TraceDebug, "Trying to open %s", m_FileName); + m_DiskFile.Close(); + if (!m_DiskFile.Open(m_FileName.c_str(), CFileBase::modeWrite)) + { + WriteTrace(TraceN64System, TraceError, "Failed to open %s", m_FileName); + return false; + } + + m_DiskFile.SeekToBegin(); ForceByteSwapDisk(); if (m_DiskFormat == DiskFormatMAME) { //If original file was MAME format, just copy - //SDK format protection - WriteTrace(TraceN64System, TraceDebug, "Trying to open %s", m_FileName); - m_DiskFile.Close(); - if (!m_DiskFile.Open(m_FileName.c_str(), CFileBase::modeWrite)) - { - WriteTrace(TraceN64System, TraceError, "Failed to open %s", m_FileName); - return false; - } - - m_DiskFile.SeekToBegin(); + WriteTrace(TraceN64System, TraceDebug, "64DD disk is MAME format"); if (!m_DiskFile.Write(m_DiskImage, MameFormatSize)) { m_DiskFile.Close(); @@ -72,6 +72,8 @@ bool CN64Disk::SaveDiskImage() else if (m_DiskFormat == DiskFormatSDK) { //If original file was SDK format, we need to convert it back + WriteTrace(TraceN64System, TraceDebug, "64DD disk is SDK format"); + ConvertDiskFormatBack(); } m_DiskFile.Close(); @@ -406,4 +408,178 @@ void CN64Disk::ConvertDiskFormat() OutOffset += BLOCKSIZE(zone); } } +} + +void CN64Disk::ConvertDiskFormatBack() +{ + //Original code by Happy_ + const uint32_t ZoneSecSize[16] = { 232, 216, 208, 192, 176, 160, 144, 128, + 216, 208, 192, 176, 160, 144, 128, 112 }; + const uint32_t ZoneTracks[16] = { 158, 158, 149, 149, 149, 149, 149, 114, + 158, 158, 149, 149, 149, 149, 149, 114 }; + const uint32_t DiskTypeZones[7][16] = { + { 0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10 }, + { 0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11 }, + { 0, 1, 2, 3, 4, 11, 10, 9, 8, 5, 6, 7, 15, 14, 13, 12 }, + { 0, 1, 2, 3, 4, 5, 12, 11, 10, 9, 8, 6, 7, 15, 14, 13 }, + { 0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 } + }; + const uint32_t RevDiskTypeZones[7][16] = { + { 0, 1, 2, 5, 6, 7, 8, 9, 4, 3, 15, 14, 13, 12, 11, 10 }, + { 0, 1, 2, 3, 7, 8, 9, 10, 6, 5, 4, 15, 14, 13, 12, 11 }, + { 0, 1, 2, 3, 4, 9, 10, 11, 8, 7, 6, 5, 15, 14, 13, 12 }, + { 0, 1, 2, 3, 4, 5, 11, 12, 10, 9, 8, 7, 6, 15, 14, 13 }, + { 0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 } + }; + const uint32_t StartBlock[7][16] = { + { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1 }, + { 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 } + }; + + uint32_t disktype = 0; + uint32_t zone, track = 0; + int32_t atrack = 0; + int32_t block = 0; + uint8_t SystemData[0xE8]; + uint8_t BlockData0[0x100 * SECTORS_PER_BLOCK]; + uint8_t BlockData1[0x100 * SECTORS_PER_BLOCK]; + uint32_t InOffset, OutOffset = 0; + uint32_t InStart[16]; + uint32_t OutStart[16]; + + //SDK DISK RAM + WriteTrace(TraceN64System, TraceDebug, "Allocating memory for disk SDK format"); + std::auto_ptr ImageBase(new uint8_t[SDKFormatSize + 0x1000]); + if (ImageBase.get() == NULL) + { + SetError(MSG_MEM_ALLOC_ERROR); + WriteTrace(TraceN64System, TraceError, "Failed to allocate memory for disk SDK format (size: 0x%X)", SDKFormatSize); + return; + } + uint8_t * Image = (uint8_t *)(((uint64_t)ImageBase.get() + 0xFFF) & ~0xFFF); // start at begining of memory page + WriteTrace(TraceN64System, TraceDebug, "Allocated disk SDK format memory (%p)", Image); + + //save information about the disk loaded + uint8_t * s_DiskImageBase = ImageBase.release(); + uint8_t * s_DiskImage = Image; + //END + + InStart[0] = 0; + OutStart[0] = 0; + + //Read System Area + memcpy(&SystemData, m_DiskImage, 0xE8); + + disktype = SystemData[5] & 0xF; + + //Prepare Input Offsets + for (zone = 1; zone < 16; zone++) + { + InStart[zone] = InStart[zone - 1] + + VZONESIZE(DiskTypeZones[disktype][zone - 1]); + } + + //Prepare Output Offsets + for (zone = 1; zone < 16; zone++) + { + OutStart[zone] = OutStart[zone - 1] + ZONESIZE(zone - 1); + } + + //Copy Head 0 + for (zone = 0; zone < 8; zone++) + { + block = StartBlock[disktype][zone]; + atrack = 0; + for (track = 0; track < ZoneTracks[zone]; track++) + { + InOffset = OutStart[zone] + (track)* TRACKSIZE(zone); + OutOffset = InStart[RevDiskTypeZones[disktype][zone]] + (track - atrack) * TRACKSIZE(zone); + + if (atrack < 0xC && track == SystemData[0x20 + zone * 0xC + atrack]) + { + atrack += 1; + } + else + { + if ((block % 2) == 1) + { + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + else + { + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + block = 1 - block; + memcpy(s_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + memcpy(s_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + } + } + } + + //Copy Head 1 + for (zone = 8; zone < 16; zone++) + { + block = StartBlock[disktype][zone]; + atrack = 0xB; + for (track = 1; track < ZoneTracks[zone] + 1; track++) + { + InOffset = OutStart[zone] + (ZoneTracks[zone] - track) * TRACKSIZE(zone); + OutOffset = InStart[RevDiskTypeZones[disktype][zone]] + (track - (0xB - atrack) - 1) * TRACKSIZE(zone); + + if (atrack > -1 && (ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack]) + { + atrack -= 1; + } + else + { + if ((block % 2) == 1) + { + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + else + { + memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone)); + InOffset += BLOCKSIZE(zone); + } + block = 1 - block; + memcpy(s_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + memcpy(s_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone)); + OutOffset += BLOCKSIZE(zone); + } + } + } + + if (!m_DiskFile.Write(s_DiskImage, SDKFormatSize)) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceError, "Failed to write file"); + } + + WriteTrace(TraceN64System, TraceDebug, "Unallocating disk SDK format memory"); + delete[] s_DiskImageBase; + s_DiskImageBase = NULL; + s_DiskImage = NULL; } \ No newline at end of file