From ea5c4abc098429cd6147fd50f145a29eda4ea208 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Tue, 24 May 2016 21:26:05 +0200 Subject: [PATCH 1/6] [64DD] Saving support (MAME dump format only) Replaces the loaded dump file with the new saved content --- Source/Project64-core/N64System/N64Class.cpp | 21 +++++--- .../Project64-core/N64System/N64DiskClass.cpp | 52 +++++++++++++++++++ .../Project64-core/N64System/N64DiskClass.h | 7 ++- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/Source/Project64-core/N64System/N64Class.cpp b/Source/Project64-core/N64System/N64Class.cpp index 5969b123b..6521299d5 100644 --- a/Source/Project64-core/N64System/N64Class.cpp +++ b/Source/Project64-core/N64System/N64Class.cpp @@ -385,6 +385,13 @@ bool CN64System::EmulationStarting(CThread * thread) WriteTrace(TraceN64System, TraceDebug, "Game starting"); g_BaseSystem->StartEmulation2(false); WriteTrace(TraceN64System, TraceDebug, "Game Done"); + //PLACE TO ADD 64DD SAVING CODE + if (g_Disk != NULL) + { + g_Disk->SaveDiskImage(); + //g_Notify->DisplayError(g_Disk->GetError()); + WriteTrace(TraceN64System, TraceDebug, "64DD Save Done"); + } } catch (...) { @@ -411,11 +418,11 @@ void CN64System::StartEmulation2(bool NewThread) StartLog(); } - WriteTrace(TraceN64System, TraceDebug, "Setting up system"); + WriteTrace(TraceN64System, TraceDebug, "Setting up system"); CInterpreterCPU::BuildCPU(); uint32_t CpuType = g_Settings->LoadDword(Game_CpuType); - WriteTrace(TraceN64System, TraceDebug, "CpuType = %d",CpuType); + WriteTrace(TraceN64System, TraceDebug, "CpuType = %d",CpuType); if (CpuType == CPU_SyncCores && !g_Settings->LoadBool(Debugger_Enabled)) { g_Settings->SaveDword(Game_CpuType, CPU_Recompiler); @@ -440,7 +447,7 @@ void CN64System::StartEmulation2(bool NewThread) m_Recomp = new CRecompiler(m_Reg, m_Profile, m_EndEmulation); } - WriteTrace(TraceN64System, TraceDebug, "Setting system as active"); + WriteTrace(TraceN64System, TraceDebug, "Setting system as active"); bool bSetActive = true; if (m_SyncCPU) { @@ -454,13 +461,13 @@ void CN64System::StartEmulation2(bool NewThread) if (!bSetActive) { - WriteTrace(TraceN64System, TraceWarning, "Failed to set system as active"); + WriteTrace(TraceN64System, TraceWarning, "Failed to set system as active"); g_Settings->SaveBool(GameRunning_LoadingInProgress, false); g_Notify->DisplayError(MSG_PLUGIN_NOT_INIT); } else { - WriteTrace(TraceN64System, TraceDebug, "Starting emulation thread"); + WriteTrace(TraceN64System, TraceDebug, "Starting emulation thread"); StartEmulationThead(); } } @@ -468,10 +475,10 @@ void CN64System::StartEmulation2(bool NewThread) { //mark the emulation as starting and fix up menus g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED); - WriteTrace(TraceN64System, TraceDebug, "Start Executing CPU"); + WriteTrace(TraceN64System, TraceDebug, "Start Executing CPU"); ExecuteCPU(); } - WriteTrace(TraceN64System, TraceDebug, "Done"); + WriteTrace(TraceN64System, TraceDebug, "Done"); } void CN64System::StartEmulation(bool NewThread) diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index cecc83c5c..0eaa55819 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -41,6 +41,40 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) g_Settings->SaveBool(GameRunning_LoadingInProgress, false); } + m_FileName = FileLoc; + return true; +} + +bool CN64Disk::SaveDiskImage() +{ + 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(); + if (!m_DiskFile.Write(m_DiskImage, MameFormatSize)) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceError, "Failed to write file"); + return false; + } + } + else if (m_DiskFormat == DiskFormatSDK) + { + //If original file was SDK format, we need to convert it back + } + + m_DiskFile.Close(); return true; } @@ -101,6 +135,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) if (DiskFileSize == MameFormatSize) { //If Disk is MAME Format (size is constant, it should be the same for every file), then continue + m_DiskFormat = DiskFormatMAME; WriteTrace(TraceN64System, TraceDebug, "Disk File is MAME Format"); if (!AllocateDiskImage(DiskFileSize)) @@ -144,6 +179,8 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc) { //If Disk is SDK format (made with SDK based dumpers like LuigiBlood's, or Nintendo's, size is also constant) //We need to convert it. + m_DiskFormat = DiskFormatSDK; + g_Notify->DisplayMessage(5, MSG_LOADING); //Allocate supported size @@ -193,6 +230,21 @@ void CN64Disk::ByteSwapDisk() } } +void CN64Disk::ForceByteSwapDisk() +{ + uint32_t count; + + for (count = 0; count < m_DiskFileSize; count += 4) + { + m_DiskImage[count] ^= m_DiskImage[count + 3]; + m_DiskImage[count + 3] ^= m_DiskImage[count]; + m_DiskImage[count] ^= m_DiskImage[count + 3]; + m_DiskImage[count + 1] ^= m_DiskImage[count + 2]; + m_DiskImage[count + 2] ^= m_DiskImage[count + 1]; + m_DiskImage[count + 1] ^= m_DiskImage[count + 2]; + } +} + void CN64Disk::SetError(LanguageStringID ErrorMsg) { m_ErrorMsg = ErrorMsg; diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h index 2b3938966..991523767 100644 --- a/Source/Project64-core/N64System/N64DiskClass.h +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -18,6 +18,7 @@ public: ~CN64Disk(); bool LoadDiskImage(const char * FileLoc); + bool SaveDiskImage(); static bool IsValidDiskImage(uint8_t Test[4]); uint8_t * GetDiskAddress() { return m_DiskImage; } uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; } @@ -30,11 +31,14 @@ private: bool AllocateDiskImage(uint32_t DiskFileSize); bool AllocateAndLoadDiskImage(const char * FileLoc); void ByteSwapDisk(); + void ForceByteSwapDisk(); void SetError(LanguageStringID ErrorMsg); void ConvertDiskFormat(); + void ConvertDiskFormatBack(); //constant values - enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800 }; + enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800, + DiskFormatMAME = 0x0, DiskFormatSDK = 0x1 }; //class variables CFile m_DiskFile; @@ -44,6 +48,7 @@ private: uint32_t m_DiskBufAddress; LanguageStringID m_ErrorMsg; stdstr m_FileName, m_DiskIdent; + uint8_t m_DiskFormat; //0 = MAME, 1 = SDK //disk convert #define SECTORS_PER_BLOCK 85 From a29fb1f92a82ce734a973e935244731c52457888 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Wed, 25 May 2016 00:07:34 +0200 Subject: [PATCH 2/6] [64DD] Saving support for SDK format dumps --- .../Project64-core/N64System/N64DiskClass.cpp | 196 +++++++++++++++++- 1 file changed, 186 insertions(+), 10 deletions(-) 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 From 810bccc75564789679a1cd3a1694c3dd6f089df9 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Wed, 25 May 2016 04:06:10 +0200 Subject: [PATCH 3/6] [64DD] Swap support --- Source/Project64-core/Multilanguage.h | 1 + .../Multilanguage/LanguageClass.cpp | 1 + Source/Project64-core/N64System/Mips/Disk.cpp | 29 +++++++++++++---- .../Project64-core/N64System/N64DiskClass.cpp | 6 ++++ .../Project64-core/N64System/N64DiskClass.h | 1 + .../Project64/UserInterface/MainMenuClass.cpp | 31 +++++++++++++++++++ .../Project64/UserInterface/MainMenuClass.h | 2 +- 7 files changed, 64 insertions(+), 7 deletions(-) diff --git a/Source/Project64-core/Multilanguage.h b/Source/Project64-core/Multilanguage.h index 0bc0d81b8..5ee4eac8f 100644 --- a/Source/Project64-core/Multilanguage.h +++ b/Source/Project64-core/Multilanguage.h @@ -81,6 +81,7 @@ enum LanguageStringID MENU_RESUME = 132, MENU_RESET_SOFT = 133, //added in build 1.7.50 MENU_RESET_HARD = 134, //added in build 1.7.50 + MENU_SWAPDISK = 135, //added in build 2.2.???? //Options Menu MENU_OPTIONS = 140, diff --git a/Source/Project64-core/Multilanguage/LanguageClass.cpp b/Source/Project64-core/Multilanguage/LanguageClass.cpp index 4b906cfad..3c3eb646c 100644 --- a/Source/Project64-core/Multilanguage/LanguageClass.cpp +++ b/Source/Project64-core/Multilanguage/LanguageClass.cpp @@ -88,6 +88,7 @@ void CLanguage::LoadDefaultStrings(void) DEF_STR(MENU_RESUME, "R&esume"); DEF_STR(MENU_RESET_SOFT, "&Soft Reset"); DEF_STR(MENU_RESET_HARD, "&Hard Reset"); + DEF_STR(MENU_SWAPDISK, "Swap Disk"); //Options Menu DEF_STR(MENU_OPTIONS, "&Options"); diff --git a/Source/Project64-core/N64System/Mips/Disk.cpp b/Source/Project64-core/N64System/Mips/Disk.cpp index 783a6f992..064e708d1 100644 --- a/Source/Project64-core/N64System/Mips/Disk.cpp +++ b/Source/Project64-core/N64System/Mips/Disk.cpp @@ -22,6 +22,8 @@ #include #endif +uint8_t dd_swapdelay; + bool dd_write; bool dd_reset_hold; uint32_t dd_track_offset, dd_zone; @@ -29,11 +31,9 @@ uint32_t dd_start_block, dd_current; void DiskCommand() { - if (g_Disk != NULL) - g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES; - //ASIC_CMD_STATUS - Commands uint32_t cmd = g_Reg->ASIC_CMD; + WriteTrace(TraceN64System, TraceDebug, "DD CMD %08X", cmd); #ifdef _WIN32 SYSTEMTIME sysTime; @@ -81,7 +81,9 @@ void DiskCommand() g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break; case 0x00090000: //Unset Reset Bit - g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; break; + g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; + g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; + break; case 0x00120000: //RTC Get Year & Month g_Reg->ASIC_DATA = (year << 24) | (month << 16); break; @@ -100,7 +102,11 @@ void DiskCommand() void DiskReset(void) { //ASIC_HARD_RESET 0xAAAA0000 + WriteTrace(TraceN64System, TraceDebug, "DD RESET"); g_Reg->ASIC_STATUS |= DD_STATUS_RST_STATE; + dd_swapdelay = 0; + if (g_Disk != NULL) + g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES; } void DiskBMControl(void) @@ -159,6 +165,17 @@ void DiskGapSectorCheck() DiskBMUpdate(); } } + + if (!(g_Reg->ASIC_STATUS & DD_STATUS_DISK_PRES) && g_Disk != NULL) + { + dd_swapdelay++; + if (dd_swapdelay >= 40) + { + g_Reg->ASIC_STATUS |= (DD_STATUS_DISK_PRES | DD_STATUS_DISK_CHNG); + dd_swapdelay = 0; + WriteTrace(TraceN64System, TraceDebug, "DD SWAP DONE"); + } + } } void DiskBMUpdate() @@ -245,7 +262,7 @@ void DiskBMRead() sector += dd_track_offset; sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone]; sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1); - WriteTrace(TraceN64System, TraceDebug, "READ Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); + //WriteTrace(TraceN64System, TraceDebug, "READ Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); g_Disk->SetDiskAddressBuffer(sector); return; } @@ -256,7 +273,7 @@ void DiskBMWrite() sector += dd_track_offset; sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone]; sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1); - WriteTrace(TraceN64System, TraceDebug, "WRITE Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); + //WriteTrace(TraceN64System, TraceDebug, "WRITE Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector); g_Disk->SetDiskAddressBuffer(sector); return; } diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 5f27c4b45..279980cd4 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -13,6 +13,7 @@ #include "SystemGlobals.h" #include #include +#include #include CN64Disk::CN64Disk() : @@ -80,6 +81,11 @@ bool CN64Disk::SaveDiskImage() return true; } +void CN64Disk::SwapDiskImage() +{ + g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_PRES; +} + bool CN64Disk::IsValidDiskImage(uint8_t Test[4]) { if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; } diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h index 991523767..ff8a2305e 100644 --- a/Source/Project64-core/N64System/N64DiskClass.h +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -19,6 +19,7 @@ public: bool LoadDiskImage(const char * FileLoc); bool SaveDiskImage(); + void SwapDiskImage(); static bool IsValidDiskImage(uint8_t Test[4]); uint8_t * GetDiskAddress() { return m_DiskImage; } uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; } diff --git a/Source/Project64/UserInterface/MainMenuClass.cpp b/Source/Project64/UserInterface/MainMenuClass.cpp index c8fe28eb9..a417fd7c8 100644 --- a/Source/Project64/UserInterface/MainMenuClass.cpp +++ b/Source/Project64/UserInterface/MainMenuClass.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "RomInformationClass.h" +#include #include #include @@ -229,6 +230,32 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI g_Settings->SaveBool(GameRunning_LimitFPS, !g_Settings->LoadBool(GameRunning_LimitFPS)); WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_LIMITFPS 1"); break; + case ID_SYSTEM_SWAPDISK: + WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SWAPDISK"); + // Open Disk + OPENFILENAME openfilename; + char FileName[_MAX_PATH], Directory[_MAX_PATH]; + + memset(&FileName, 0, sizeof(FileName)); + memset(&openfilename, 0, sizeof(openfilename)); + + strcpy(Directory, g_Settings->LoadStringVal(RomList_GameDir).c_str()); + + openfilename.lStructSize = sizeof(openfilename); + openfilename.hwndOwner = (HWND)hWnd; + openfilename.lpstrFilter = "N64DD Disk Image (*.ndd)\0*.ndd\0All files (*.*)\0*.*\0"; + openfilename.lpstrFile = FileName; + openfilename.lpstrInitialDir = Directory; + openfilename.nMaxFile = MAX_PATH; + openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileName(&openfilename)) + { + g_Disk->SaveDiskImage(); + g_Disk->SwapDiskImage(); + g_Disk->LoadDiskImage(FileName); + } + break; case ID_SYSTEM_SAVE: WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SAVE"); g_BaseSystem->ExternalEvent(SysEvent_SaveMachineState); @@ -868,6 +895,10 @@ void CMainMenu::FillOutMenu(HMENU hMenu) SystemMenu.push_back(Item); SystemMenu.push_back(MENU_ITEM(SPLITER)); } + Item.Reset(ID_SYSTEM_SWAPDISK, MENU_SWAPDISK); + if (g_Disk == NULL) { Item.SetItemEnabled(false); } + SystemMenu.push_back(Item); + SystemMenu.push_back(MENU_ITEM(SPLITER)); SystemMenu.push_back(MENU_ITEM(ID_SYSTEM_SAVE, MENU_SAVE, m_ShortCuts.ShortCutString(ID_SYSTEM_SAVE, AccessLevel))); if (!inBasicMode) { diff --git a/Source/Project64/UserInterface/MainMenuClass.h b/Source/Project64/UserInterface/MainMenuClass.h index d00474463..2d6760c72 100644 --- a/Source/Project64/UserInterface/MainMenuClass.h +++ b/Source/Project64/UserInterface/MainMenuClass.h @@ -18,7 +18,7 @@ enum MainMenuID //System Menu ID_SYSTEM_RESET_SOFT, ID_SYSTEM_RESET_HARD, ID_SYSTEM_PAUSE, ID_SYSTEM_BITMAP, - ID_SYSTEM_LIMITFPS, ID_SYSTEM_RESTORE, ID_SYSTEM_LOAD, ID_SYSTEM_SAVE, + ID_SYSTEM_LIMITFPS, ID_SYSTEM_SWAPDISK, ID_SYSTEM_RESTORE, ID_SYSTEM_LOAD, ID_SYSTEM_SAVE, ID_SYSTEM_SAVEAS, ID_SYSTEM_CHEAT, ID_SYSTEM_GSBUTTON, //Current Save Slot From f2e4f5abca0ecc85f52dc5b2927f78ed07fdf3a1 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Wed, 25 May 2016 14:41:15 +0200 Subject: [PATCH 4/6] [64DD] Added Swap Disk shortcut (Ctrl+D) Requires resetting/deleting the shortcut list (*.sc3 file) --- Source/Project64-core/Multilanguage/LanguageClass.cpp | 2 +- Source/Project64/UserInterface/MainMenuClass.cpp | 2 +- Source/Project64/UserInterface/MenuShortCuts.cpp | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Project64-core/Multilanguage/LanguageClass.cpp b/Source/Project64-core/Multilanguage/LanguageClass.cpp index 3c3eb646c..2a4bd46f9 100644 --- a/Source/Project64-core/Multilanguage/LanguageClass.cpp +++ b/Source/Project64-core/Multilanguage/LanguageClass.cpp @@ -88,7 +88,7 @@ void CLanguage::LoadDefaultStrings(void) DEF_STR(MENU_RESUME, "R&esume"); DEF_STR(MENU_RESET_SOFT, "&Soft Reset"); DEF_STR(MENU_RESET_HARD, "&Hard Reset"); - DEF_STR(MENU_SWAPDISK, "Swap Disk"); + DEF_STR(MENU_SWAPDISK, "Swap &Disk"); //Options Menu DEF_STR(MENU_OPTIONS, "&Options"); diff --git a/Source/Project64/UserInterface/MainMenuClass.cpp b/Source/Project64/UserInterface/MainMenuClass.cpp index a417fd7c8..9f75710c4 100644 --- a/Source/Project64/UserInterface/MainMenuClass.cpp +++ b/Source/Project64/UserInterface/MainMenuClass.cpp @@ -895,7 +895,7 @@ void CMainMenu::FillOutMenu(HMENU hMenu) SystemMenu.push_back(Item); SystemMenu.push_back(MENU_ITEM(SPLITER)); } - Item.Reset(ID_SYSTEM_SWAPDISK, MENU_SWAPDISK); + Item.Reset(ID_SYSTEM_SWAPDISK, MENU_SWAPDISK, m_ShortCuts.ShortCutString(ID_SYSTEM_SWAPDISK, AccessLevel)); if (g_Disk == NULL) { Item.SetItemEnabled(false); } SystemMenu.push_back(Item); SystemMenu.push_back(MENU_ITEM(SPLITER)); diff --git a/Source/Project64/UserInterface/MenuShortCuts.cpp b/Source/Project64/UserInterface/MenuShortCuts.cpp index 25e50c116..6317ec3d9 100644 --- a/Source/Project64/UserInterface/MenuShortCuts.cpp +++ b/Source/Project64/UserInterface/MenuShortCuts.cpp @@ -316,6 +316,7 @@ void CShortCuts::Load(bool InitialValues) AddShortCut(ID_SYSTEM_PAUSE, STR_SHORTCUT_SYSTEMMENU, MENU_PAUSE, CMenuShortCutKey::GAME_RUNNING); AddShortCut(ID_SYSTEM_BITMAP, STR_SHORTCUT_SYSTEMMENU, MENU_BITMAP, CMenuShortCutKey::GAME_RUNNING); AddShortCut(ID_SYSTEM_LIMITFPS, STR_SHORTCUT_SYSTEMMENU, MENU_LIMIT_FPS, CMenuShortCutKey::GAME_RUNNING); + AddShortCut(ID_SYSTEM_SWAPDISK, STR_SHORTCUT_SYSTEMMENU, MENU_SWAPDISK, CMenuShortCutKey::GAME_RUNNING_WINDOW); AddShortCut(ID_SYSTEM_SAVE, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE, CMenuShortCutKey::GAME_RUNNING); AddShortCut(ID_SYSTEM_SAVEAS, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE_AS, CMenuShortCutKey::GAME_RUNNING_WINDOW); AddShortCut(ID_SYSTEM_RESTORE, STR_SHORTCUT_SYSTEMMENU, MENU_RESTORE, CMenuShortCutKey::GAME_RUNNING); @@ -383,6 +384,7 @@ void CShortCuts::Load(bool InitialValues) m_ShortCuts.find(ID_SYSTEM_PAUSE)->second.AddShortCut(VK_PAUSE, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_BITMAP)->second.AddShortCut(VK_F3, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_LIMITFPS)->second.AddShortCut(VK_F4, false, false, false, CMenuShortCutKey::GAME_RUNNING); + m_ShortCuts.find(ID_SYSTEM_SWAPDISK)->second.AddShortCut('D', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW); m_ShortCuts.find(ID_SYSTEM_SAVE)->second.AddShortCut(VK_F5, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_RESTORE)->second.AddShortCut(VK_F7, false, false, false, CMenuShortCutKey::GAME_RUNNING); m_ShortCuts.find(ID_SYSTEM_LOAD)->second.AddShortCut('L', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW); From c495edd17e6ae3ffe55fd6164e0fe644becc04a1 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Thu, 26 May 2016 18:18:07 +0200 Subject: [PATCH 5/6] [64DD] Use shadow file (*.ndr) instead of replacing loaded disk. (Also ignore saving when disk type is 0x6) --- .../Project64-core/N64System/N64DiskClass.cpp | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 279980cd4..9b95c4353 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -32,9 +32,19 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) { UnallocateDiskImage(); - if (!AllocateAndLoadDiskImage(FileLoc)) + //Assume the file extension is *.ndd (it is the only case where it is loaded) + stdstr ShadowFile = FileLoc; + ShadowFile[ShadowFile.length() - 1] = 'r'; + + WriteTrace(TraceN64System, TraceDebug, "Attempt to load shadow file."); + if (!AllocateAndLoadDiskImage(ShadowFile.c_str())) { - return false; + WriteTrace(TraceN64System, TraceDebug, "Loading Shadow file failed"); + UnallocateDiskImage(); + if (!AllocateAndLoadDiskImage(FileLoc)) + { + return false; + } } if (g_Disk == this) @@ -48,11 +58,24 @@ 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)) + //NO NEED TO SAVE IF DISK TYPE IS 6 + uint8_t disktype = m_DiskImage[5] & 0xF; + if (disktype == 0x6) { - WriteTrace(TraceN64System, TraceError, "Failed to open %s", m_FileName); + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceDebug, "Loaded Disk Type is 0x7. No RAM area. Shadow file is not needed."); + return true; + } + + //Assume the file extension is *.ndd (it is the only case where it is loaded) + stdstr ShadowFile = m_FileName; + ShadowFile[ShadowFile.length() - 1] = 'r'; + + WriteTrace(TraceN64System, TraceDebug, "Trying to open %s (Shadow File)", ShadowFile.c_str()); + m_DiskFile.Close(); + if (!m_DiskFile.Open(ShadowFile.c_str(), CFileBase::modeWrite | CFileBase::modeCreate)) + { + WriteTrace(TraceN64System, TraceError, "Failed to open %s (Shadow File)", ShadowFile.c_str()); return false; } From add7ec7b98ce99df40197dd1b127b1d55733d3e4 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Mon, 30 May 2016 01:09:52 +0200 Subject: [PATCH 6/6] [64DD] Make sure new disk is loaded into memory before swap Fixes hang during swap while recording with OBS Studio --- Source/Project64-core/N64System/Mips/Disk.cpp | 4 ++-- Source/Project64-core/N64System/N64DiskClass.cpp | 5 ++++- Source/Project64-core/N64System/N64DiskClass.h | 2 +- Source/Project64/UserInterface/MainMenuClass.cpp | 3 +-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/Disk.cpp b/Source/Project64-core/N64System/Mips/Disk.cpp index 064e708d1..77191ec43 100644 --- a/Source/Project64-core/N64System/Mips/Disk.cpp +++ b/Source/Project64-core/N64System/Mips/Disk.cpp @@ -166,10 +166,10 @@ void DiskGapSectorCheck() } } - if (!(g_Reg->ASIC_STATUS & DD_STATUS_DISK_PRES) && g_Disk != NULL) + if (!(g_Reg->ASIC_STATUS & DD_STATUS_DISK_PRES) && g_Disk != NULL && g_Settings->LoadBool(GameRunning_LoadingInProgress) == false) { dd_swapdelay++; - if (dd_swapdelay >= 40) + if (dd_swapdelay >= 50) { g_Reg->ASIC_STATUS |= (DD_STATUS_DISK_PRES | DD_STATUS_DISK_CHNG); dd_swapdelay = 0; diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 9b95c4353..4eb7d3c94 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -36,6 +36,8 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc) stdstr ShadowFile = FileLoc; ShadowFile[ShadowFile.length() - 1] = 'r'; + g_Settings->SaveBool(GameRunning_LoadingInProgress, true); + WriteTrace(TraceN64System, TraceDebug, "Attempt to load shadow file."); if (!AllocateAndLoadDiskImage(ShadowFile.c_str())) { @@ -104,9 +106,10 @@ bool CN64Disk::SaveDiskImage() return true; } -void CN64Disk::SwapDiskImage() +void CN64Disk::SwapDiskImage(const char * FileLoc) { g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_PRES; + LoadDiskImage(FileLoc); } bool CN64Disk::IsValidDiskImage(uint8_t Test[4]) diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h index ff8a2305e..594db44db 100644 --- a/Source/Project64-core/N64System/N64DiskClass.h +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -19,7 +19,7 @@ public: bool LoadDiskImage(const char * FileLoc); bool SaveDiskImage(); - void SwapDiskImage(); + void SwapDiskImage(const char * FileLoc); static bool IsValidDiskImage(uint8_t Test[4]); uint8_t * GetDiskAddress() { return m_DiskImage; } uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; } diff --git a/Source/Project64/UserInterface/MainMenuClass.cpp b/Source/Project64/UserInterface/MainMenuClass.cpp index 9f75710c4..b936f83b0 100644 --- a/Source/Project64/UserInterface/MainMenuClass.cpp +++ b/Source/Project64/UserInterface/MainMenuClass.cpp @@ -252,8 +252,7 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI if (GetOpenFileName(&openfilename)) { g_Disk->SaveDiskImage(); - g_Disk->SwapDiskImage(); - g_Disk->LoadDiskImage(FileName); + g_Disk->SwapDiskImage(FileName); } break; case ID_SYSTEM_SAVE: