From cb3ada6ece10b6648805937545ea16c354be8f43 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 9 Feb 2016 16:59:46 -0800 Subject: [PATCH 01/31] Optimize CheckInterrupts Using local variables significantly improves the performance. --- .../N64System/Mips/RegisterClass.cpp | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/RegisterClass.cpp b/Source/Project64-core/N64System/Mips/RegisterClass.cpp index f0283f6d3..aac7e23a9 100644 --- a/Source/Project64-core/N64System/Mips/RegisterClass.cpp +++ b/Source/Project64-core/N64System/Mips/RegisterClass.cpp @@ -307,14 +307,15 @@ void CRegisters::SetAsCurrentSystem() void CRegisters::CheckInterrupts() { + uint32_t mi_intr_reg = MI_INTR_REG, status_register; if (!m_System->bFixedAudio() && CpuType() != CPU_SyncCores) { - MI_INTR_REG &= ~MI_INTR_AI; - MI_INTR_REG |= (m_AudioIntrReg & MI_INTR_AI); + mi_intr_reg &= ~MI_INTR_AI; + mi_intr_reg |= (m_AudioIntrReg & MI_INTR_AI); } - MI_INTR_REG |= (m_RspIntrReg & MI_INTR_SP); - MI_INTR_REG |= (m_GfxIntrReg & MI_INTR_DP); - if ((MI_INTR_MASK_REG & MI_INTR_REG) != 0) + mi_intr_reg |= (m_RspIntrReg & MI_INTR_SP); + mi_intr_reg |= (m_GfxIntrReg & MI_INTR_DP); + if ((MI_INTR_MASK_REG & mi_intr_reg) != 0) { FAKE_CAUSE_REGISTER |= CAUSE_IP2; } @@ -322,21 +323,23 @@ void CRegisters::CheckInterrupts() { FAKE_CAUSE_REGISTER &= ~CAUSE_IP2; } + MI_INTR_REG = mi_intr_reg; + status_register = STATUS_REGISTER; - if ((STATUS_REGISTER & STATUS_IE) == 0) + if ((status_register & STATUS_IE) == 0) { return; } - if ((STATUS_REGISTER & STATUS_EXL) != 0) + if ((status_register & STATUS_EXL) != 0) { return; } - if ((STATUS_REGISTER & STATUS_ERL) != 0) + if ((status_register & STATUS_ERL) != 0) { return; } - if ((STATUS_REGISTER & FAKE_CAUSE_REGISTER & 0xFF00) != 0) + if ((status_register & FAKE_CAUSE_REGISTER & 0xFF00) != 0) { if (m_FirstInterupt) { From ad5370a252815e868564dfa55b519a4dbdf4d66c Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 9 Feb 2016 17:21:29 -0800 Subject: [PATCH 02/31] Statically round up PI_WR_LEN_REG to nearest even --- Source/Project64-core/N64System/Mips/Dma.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/Dma.cpp b/Source/Project64-core/N64System/Mips/Dma.cpp index 86d7fde61..9c7120e53 100644 --- a/Source/Project64-core/N64System/Mips/Dma.cpp +++ b/Source/Project64-core/N64System/Mips/Dma.cpp @@ -198,12 +198,8 @@ void CDMA::PI_DMA_READ() void CDMA::PI_DMA_WRITE() { - uint32_t PI_WR_LEN_REG = ((g_Reg->PI_WR_LEN_REG) & 0x00FFFFFFul) + 1; - - if ((PI_WR_LEN_REG & 1) != 0) - { - PI_WR_LEN_REG += 1; /* fixes AI Shougi 3, Doraemon 3, etc. */ - } + uint32_t PI_WR_LEN_REG = ((g_Reg->PI_WR_LEN_REG) & 0x00FFFFFEul) + 2; + /* rounding PI_WR_LEN_REG up to the nearest even number fixes AI Shougi 3, Doraemon 3, etc. */ g_Reg->PI_STATUS_REG |= PI_STATUS_DMA_BUSY; if (g_Reg->PI_DRAM_ADDR_REG + PI_WR_LEN_REG > g_MMU->RdramSize()) From b066192abf4809ec08ffae9cacb5377725ec8979 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 9 Feb 2016 18:13:21 -0800 Subject: [PATCH 03/31] Optimize commonly executed loop in PI_DMA_WRITE --- Source/Project64-core/N64System/Mips/Dma.cpp | 58 +++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/Dma.cpp b/Source/Project64-core/N64System/Mips/Dma.cpp index 9c7120e53..26d62defa 100644 --- a/Source/Project64-core/N64System/Mips/Dma.cpp +++ b/Source/Project64-core/N64System/Mips/Dma.cpp @@ -362,9 +362,63 @@ void CDMA::PI_DMA_WRITE() g_Reg->PI_CART_ADDR_REG -= 0x10000000; if (g_Reg->PI_CART_ADDR_REG + PI_WR_LEN_REG < g_Rom->GetRomSize()) { - for (i = 0; i < PI_WR_LEN_REG; i++) + size_t alignment; + RDRAM += g_Reg->PI_DRAM_ADDR_REG; + ROM += g_Reg->PI_CART_ADDR_REG; + alignment = PI_WR_LEN_REG | (size_t)RDRAM | (size_t)ROM; + if ((alignment & 0x3) == 0) { - *(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((g_Reg->PI_CART_ADDR_REG + i) ^ 3)); + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint32_t *)(RDRAM + i) = *(uint32_t *)(ROM + i); + } + } + else if ((alignment & 1) == 0) + { + if ((PI_WR_LEN_REG & 2) == 0) + { + if (((size_t)RDRAM & 2) == 0) + { + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint16_t *)(((size_t)RDRAM + i) + 2) = *(uint16_t *)(((size_t)ROM + i) - 2); + *(uint16_t *)(((size_t)RDRAM + i) + 0) = *(uint16_t *)(((size_t)ROM + i) + 4); + } + } + else + { + if (((size_t)ROM & 2) == 0) + { + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint16_t *)(((size_t)RDRAM + i) - 2) = *(uint16_t *)(((size_t)ROM + i) + 2); + *(uint16_t *)(((size_t)RDRAM + i) + 4) = *(uint16_t *)(((size_t)ROM + i) + 0); + } + } + else + { + for (i = 0; i < PI_WR_LEN_REG; i += 4) + { + *(uint16_t *)(((size_t)RDRAM + i) - 2) = *(uint16_t *)(((size_t)ROM + i) - 2); + *(uint16_t *)(((size_t)RDRAM + i) + 4) = *(uint16_t *)(((size_t)ROM + i) + 4); + } + } + } + } + else + { + for (i = 0; i < PI_WR_LEN_REG; i += 2) + { + *(uint16_t *)(((size_t)RDRAM + i) ^ 2) = *(uint16_t *)(((size_t)ROM + i) ^ 2); + } + } + } + else + { + for (i = 0; i < PI_WR_LEN_REG; i++) + { + *(uint8_t *)(((size_t)RDRAM + i) ^ 3) = *(uint8_t *)(((size_t)ROM + i) ^ 3); + } } } else if (g_Reg->PI_CART_ADDR_REG >= g_Rom->GetRomSize()) From b483b76504de02e5ff4cbc2dfd1388ccd741f5be Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 9 Feb 2016 18:20:05 -0800 Subject: [PATCH 04/31] Optimize UpdateTimers for when wired != 0 --- Source/Project64-core/N64System/Mips/SystemTiming.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/SystemTiming.cpp b/Source/Project64-core/N64System/Mips/SystemTiming.cpp index 736e9518b..fec090eeb 100644 --- a/Source/Project64-core/N64System/Mips/SystemTiming.cpp +++ b/Source/Project64-core/N64System/Mips/SystemTiming.cpp @@ -161,12 +161,12 @@ void CSystemTimer::UpdateTimers() int TimeTaken = m_LastUpdate - m_NextTimer; if (TimeTaken != 0) { - uint32_t random, wired; + int32_t random, wired; m_LastUpdate = m_NextTimer; g_Reg->COUNT_REGISTER += TimeTaken; random = g_Reg->RANDOM_REGISTER - (TimeTaken / g_System->CountPerOp()); wired = g_Reg->WIRED_REGISTER; - if ((int)random < (int)wired) + if (random < wired) { if (wired == 0) { @@ -175,10 +175,7 @@ void CSystemTimer::UpdateTimers() else { uint32_t increment = 32 - wired; - do - { - random += increment; - } while ((int)random < (int)wired); + random += ((wired - random + increment - 1) / increment) * increment; } } g_Reg->RANDOM_REGISTER = random; From 6cc6f1ca90104c8dfb5bea8cc23120aab6909ea6 Mon Sep 17 00:00:00 2001 From: AmbientMalice Date: Wed, 30 Mar 2016 12:04:27 +1000 Subject: [PATCH 05/31] MMProtoGlide64 --- Config/Glide64.rdb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Config/Glide64.rdb b/Config/Glide64.rdb index f1aac62bc..ed6efb2eb 100644 --- a/Config/Glide64.rdb +++ b/Config/Glide64.rdb @@ -1946,6 +1946,12 @@ optimize_texrect=0 swapmode=2 useless_is_useless=1 +[27C985A8-ED7CE5C6-C:0] +Good Name=Mega Man 64 (Proto) +Internal Name=Megaman 64 +depthmode=1 +increase_texrect_edge=1 + [0EC158F5-FB3E6896-C:45] Good Name=Mega Man 64 (U) Internal Name=Mega Man 64 From 594544e467f35a21fd38944d4f6a1dd8576239e9 Mon Sep 17 00:00:00 2001 From: AmbientMalice Date: Wed, 30 Mar 2016 12:05:57 +1000 Subject: [PATCH 06/31] MMProtoCfg --- Config/Project64.rdb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Config/Project64.rdb b/Config/Project64.rdb index acefa20cf..13afc5e88 100644 --- a/Config/Project64.rdb +++ b/Config/Project64.rdb @@ -3380,6 +3380,11 @@ Plugin Note=[Glide64] errors:various RDRAM Size=8 Save Type=16kbit Eeprom +[27C985A8-ED7CE5C6-C:0] +Good Name=Mega Man 64 (Proto) +Internal Name=Megaman 64 +Status=Compatible + [0EC158F5-FB3E6896-C:45] Good Name=Mega Man 64 (U) Internal Name=Mega Man 64 From ff4bd28e3ea867699ad5f733377c95d0a5346421 Mon Sep 17 00:00:00 2001 From: Emmet Young Date: Mon, 16 May 2016 18:23:31 +1000 Subject: [PATCH 07/31] Change up Mempak so it uses CFile class. Also modify the way mempaks are loaded and written. We only write the bytes that have been changed now, rather then writing the whole file every time the mempak is written to. --- Source/Project64-core/N64System/Mips/Mempak.H | 5 ++- .../Project64-core/N64System/Mips/Mempak.cpp | 44 ++++++++++++------- Source/Project64-core/N64System/N64Class.cpp | 3 -- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/Mempak.H b/Source/Project64-core/N64System/Mips/Mempak.H index 1f0fda70f..e55c0156c 100644 --- a/Source/Project64-core/N64System/Mips/Mempak.H +++ b/Source/Project64-core/N64System/Mips/Mempak.H @@ -14,8 +14,9 @@ class Mempak { public: static uint8_t CalculateCrc(uint8_t * DataToCrc); - static void Load(int32_t Control); - static void Format(int32_t Control); static void ReadFrom(int32_t Control, uint32_t address, uint8_t * data); static void WriteTo(int32_t Control, uint32_t address, uint8_t * data); +private: + static void LoadMempak(int32_t Control); + static void Format(int32_t Control); }; \ No newline at end of file diff --git a/Source/Project64-core/N64System/Mips/Mempak.cpp b/Source/Project64-core/N64System/Mips/Mempak.cpp index 8d9a8ea87..121829292 100644 --- a/Source/Project64-core/N64System/Mips/Mempak.cpp +++ b/Source/Project64-core/N64System/Mips/Mempak.cpp @@ -15,33 +15,37 @@ #include uint8_t Mempaks[4][128 * 256]; /* [CONTROLLERS][PAGES][BYTES_PER_PAGE] */ -CPath MempakNames[4]; +CFile MempakHandle[4]; -void Mempak::Load(int32_t Control) +void Mempak::LoadMempak(int32_t Control) { stdstr MempakName; - MempakName.Format("%s_Cont_%d", g_Settings->LoadStringVal(Game_GameName).c_str(), Control + 1); - MempakNames[Control] = CPath(g_Settings->LoadStringVal(Directory_NativeSave).c_str(), stdstr_f("%s.mpk",MempakName.c_str()).c_str()); + CPath MempakPath(g_Settings->LoadStringVal(Directory_NativeSave).c_str(), stdstr_f("%s.mpk",MempakName.c_str()).c_str()); + if (g_Settings->LoadBool(Setting_UniqueSaveDir)) { - MempakNames[Control].AppendDirectory(g_Settings->LoadStringVal(Game_UniqueSaveDir).c_str()); + MempakPath.AppendDirectory(g_Settings->LoadStringVal(Game_UniqueSaveDir).c_str()); } - if (!MempakNames[Control].DirectoryExists()) + if (!MempakPath.DirectoryExists()) { - MempakNames[Control].DirectoryCreate(); + MempakPath.DirectoryCreate(); } - if (MempakNames[Control].Exists()) + bool formatMempak = !MempakPath.Exists(); + + MempakHandle[Control].Open(MempakPath, CFileBase::modeReadWrite | CFileBase::modeNoTruncate | CFileBase::modeCreate); + MempakHandle[Control].SeekToBegin(); + + if (formatMempak) { - FILE *mempak = fopen(MempakNames[Control], "rb"); - fread(Mempaks[Control], 1, 0x8000, mempak); - fclose(mempak); + Mempak::Format(Control); + MempakHandle[Control].Write(Mempaks[Control], 0x8000); } else { - Mempak::Format(Control); + MempakHandle[Control].Read(Mempaks[Control], 0x8000); } } @@ -113,6 +117,11 @@ void Mempak::ReadFrom(int32_t Control, uint32_t address, uint8_t * data) { if (address < 0x8000) { + if (!MempakHandle[Control].IsOpen()) + { + LoadMempak(Control); + } + memcpy(data, &Mempaks[Control][address], 0x20); } else @@ -126,11 +135,16 @@ void Mempak::WriteTo(int32_t Control, uint32_t address, uint8_t * data) { if (address < 0x8000) { + if (!MempakHandle[Control].IsOpen()) + { + LoadMempak(Control); + } + memcpy(&Mempaks[Control][address], data, 0x20); - FILE* mempak = fopen(MempakNames[Control], "wb"); - fwrite(Mempaks[Control], 1, 0x8000, mempak); - fclose(mempak); + MempakHandle[Control].Seek(address, CFile::begin); + MempakHandle[Control].Write(data, 0x20); + MempakHandle[Control].Flush(); } else { diff --git a/Source/Project64-core/N64System/N64Class.cpp b/Source/Project64-core/N64System/N64Class.cpp index 5969b123b..2817bc63b 100644 --- a/Source/Project64-core/N64System/N64Class.cpp +++ b/Source/Project64-core/N64System/N64Class.cpp @@ -699,9 +699,6 @@ bool CN64System::SetActiveSystem(bool bActive) case PLUGIN_TANSFER_PAK: Transferpak::Init(); break; - case PLUGIN_MEMPAK: - Mempak::Load(i); - break; } } } From 6e45f2d90f1849ad70e4fd5078327b0db96bd2bf Mon Sep 17 00:00:00 2001 From: Emmet Young Date: Mon, 16 May 2016 20:20:00 +1000 Subject: [PATCH 08/31] Make the Transferpak only init the GBCart when we have either a read or a load to the transferpak. --- .../N64System/Mips/Transferpak.cpp | 18 +++++++++++++++++- Source/Project64-core/N64System/N64Class.cpp | 16 ---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Source/Project64-core/N64System/Mips/Transferpak.cpp b/Source/Project64-core/N64System/Mips/Transferpak.cpp index dfa77a0d4..f089a77a1 100644 --- a/Source/Project64-core/N64System/Mips/Transferpak.cpp +++ b/Source/Project64-core/N64System/Mips/Transferpak.cpp @@ -32,13 +32,22 @@ void Transferpak::Init() void Transferpak::Release() { - GBCart::release_gb_cart(&tpak.gb_cart); + if (tpak.gb_cart.rom != NULL) + { + GBCart::release_gb_cart(&tpak.gb_cart); + } } void Transferpak::ReadFrom(uint16_t address, uint8_t * data) { if ((address >= 0x8000) && (address <= 0x8FFF)) { + //Ensure we actually have a ROM loaded in first. + if (tpak.gb_cart.rom == NULL) + { + Init(); + } + //Get whether the GB cart is enabled or disabled uint8_t value = (tpak.enabled) ? 0x84 : 0x00; @@ -71,8 +80,15 @@ void Transferpak::ReadFrom(uint16_t address, uint8_t * data) void Transferpak::WriteTo(uint16_t address, uint8_t * data) { + if ((address >= 0x8000) && (address <= 0x8FFF)) { + //Ensure we actually have a ROM loaded in first. + if (tpak.gb_cart.rom == NULL) + { + Init(); + } + //Set whether the gb cart is enabled or disabled. switch (*data) { diff --git a/Source/Project64-core/N64System/N64Class.cpp b/Source/Project64-core/N64System/N64Class.cpp index 2817bc63b..11ad12de7 100644 --- a/Source/Project64-core/N64System/N64Class.cpp +++ b/Source/Project64-core/N64System/N64Class.cpp @@ -687,22 +687,6 @@ bool CN64System::SetActiveSystem(bool bActive) { WriteTrace(TraceN64System, TraceError, "g_Plugins->Initiate Failed"); } - else - { - CONTROL * Controllers = g_Plugins->Control()->PluginControllers(); - for (int i = 0; i < 3; i++) - { - if (Controllers[i].Present) - { - switch (Controllers[i].Plugin) - { - case PLUGIN_TANSFER_PAK: - Transferpak::Init(); - break; - } - } - } - } } if (bReset) From 09d146c66842d56f09453a896c6b05d25e25c5d7 Mon Sep 17 00:00:00 2001 From: Nekokabu Date: Sat, 21 May 2016 19:00:59 +0900 Subject: [PATCH 09/31] Update Japanese.pj.Lang --- Lang/Japanese.pj.Lang | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lang/Japanese.pj.Lang b/Lang/Japanese.pj.Lang index bd59acc57..204887059 100644 --- a/Lang/Japanese.pj.Lang +++ b/Lang/Japanese.pj.Lang @@ -246,8 +246,9 @@ #463# "前回使ったチートを記憶する(&R)" #464# "ロムの実行中はスクリーンセーバーを無効にする" #465# "フレームレートを表示" -#466# "表示形式によってフレームレートを変更する:" +#466# "フレームレートの表示形式" #467# "Project64がすでに起動しているかチェックする" +#468# "ゲーム毎にセーブディレクトリを作成する" //ROM Browser Tab #480# "最近開いたロムファイルの表示する数(0~10):" From 35c1aa2c73e72d62a9c8eb4830d327f9900530a0 Mon Sep 17 00:00:00 2001 From: Nekokabu Date: Sun, 22 May 2016 20:41:21 +0900 Subject: [PATCH 10/31] Update PifRam.cpp Wonder Project J2 are using 0xFD --- Source/Project64-core/N64System/Mips/PifRam.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Project64-core/N64System/Mips/PifRam.cpp b/Source/Project64-core/N64System/Mips/PifRam.cpp index 932acd658..5f8d83c98 100644 --- a/Source/Project64-core/N64System/Mips/PifRam.cpp +++ b/Source/Project64-core/N64System/Mips/PifRam.cpp @@ -118,6 +118,7 @@ void CPifRam::PifRamRead() CurPos = 0x40; } break; + case 0xFD: CurPos = 0x40; break; case 0xFE: CurPos = 0x40; break; case 0xFF: break; case 0xB4: case 0x56: case 0xB8: break; /* ??? */ @@ -227,6 +228,7 @@ void CPifRam::PifRamWrite() CurPos = 0x40; } break; + case 0xFD: CurPos = 0x40; break; case 0xFE: CurPos = 0x40; break; case 0xFF: break; case 0xB4: case 0x56: case 0xB8: break; /* ??? */ From 7789de016e7b3bbb8cc5c2c88517694e63848457 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Sun, 22 May 2016 14:55:23 +0200 Subject: [PATCH 11/31] [64DD] Disk dump loading from command line / drag 'n' drop to EXE file --- Source/Project64/main.cpp | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Source/Project64/main.cpp b/Source/Project64/main.cpp index d403532a9..4b2afb963 100644 --- a/Source/Project64/main.cpp +++ b/Source/Project64/main.cpp @@ -24,7 +24,42 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR / if (g_Settings->LoadStringVal(Cmd_RomFile).length() > 0) { MainWindow.Show(true); //Show the main window - CN64System::RunFileImage(g_Settings->LoadStringVal(Cmd_RomFile).c_str()); + //N64 ROM or 64DD Disk + stdstr ext = CPath(g_Settings->LoadStringVal(Cmd_RomFile)).GetExtension(); + if (!(_stricmp(ext.c_str(), "ndd") == 0)) + { + //File Extension is not *.ndd so it should be a N64 ROM + CN64System::RunFileImage(g_Settings->LoadStringVal(Cmd_RomFile).c_str()); + } + else + { + //Ext is *.ndd, so it should be a disk file. + if (CN64System::RunDiskImage(g_Settings->LoadStringVal(Cmd_RomFile).c_str())) + { + stdstr IPLROM = g_Settings->LoadStringVal(File_DiskIPLPath); + if ((IPLROM.length() <= 0) || (!CN64System::RunFileImage(IPLROM.c_str()))) + { + // Open DDROM + OPENFILENAME openfilename; + char FileName[_MAX_PATH], Directory[_MAX_PATH]; + memset(&FileName, 0, sizeof(FileName)); + memset(&openfilename, 0, sizeof(openfilename)); + + openfilename.lStructSize = sizeof(openfilename); + //openfilename.hwndOwner = (HWND)hWnd; + openfilename.lpstrFilter = "64DD IPL ROM Image (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0"; + openfilename.lpstrFile = FileName; + openfilename.lpstrInitialDir = Directory; + openfilename.nMaxFile = MAX_PATH; + openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileName(&openfilename)) + { + CN64System::RunFileImage(FileName); + } + } + } + } } else { From b2b10969c92e168ae77d299cee3e618dbcf0e12b Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Sun, 22 May 2016 23:20:49 -0700 Subject: [PATCH 12/31] Implement COP1_S_ROUND_L in cpu interpreter --- .../N64System/Interpreter/InterpreterOps.cpp | 8 +++++++- .../Project64-core/N64System/Interpreter/InterpreterOps.h | 1 + .../N64System/Interpreter/InterpreterOps32.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 5759e0f65..946387469 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -481,7 +481,7 @@ R4300iOp::Func * R4300iOp::BuildInterpreter() Jump_CoP1_S[5] = COP1_S_ABS; Jump_CoP1_S[6] = COP1_S_MOV; Jump_CoP1_S[7] = COP1_S_NEG; - Jump_CoP1_S[8] = UnknownOpcode; + Jump_CoP1_S[8] = COP1_S_ROUND_L; Jump_CoP1_S[9] = COP1_S_TRUNC_L; Jump_CoP1_S[10] = COP1_S_CEIL_L; //added by Witten Jump_CoP1_S[11] = COP1_S_FLOOR_L; //added by Witten @@ -2461,6 +2461,12 @@ void R4300iOp::COP1_S_NEG() *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] * -1.0f); } +void R4300iOp::COP1_S_ROUND_L() +{ + TEST_COP1_USABLE_EXCEPTION(); + Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_TONEAREST); +} + void R4300iOp::COP1_S_TRUNC_L() { TEST_COP1_USABLE_EXCEPTION(); diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h index 6aeb7000d..12f2d9b9d 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h @@ -160,6 +160,7 @@ public: static void COP1_S_ABS(); static void COP1_S_MOV(); static void COP1_S_NEG(); + static void COP1_S_ROUND_L(); static void COP1_S_TRUNC_L(); static void COP1_S_CEIL_L(); //added by Witten static void COP1_S_FLOOR_L(); //added by Witten diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp index 09447ae6d..a459f3b9e 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp @@ -376,7 +376,7 @@ R4300iOp32::Func * R4300iOp32::BuildInterpreter() Jump_CoP1_S[5] = R4300iOp::COP1_S_ABS; Jump_CoP1_S[6] = R4300iOp::COP1_S_MOV; Jump_CoP1_S[7] = R4300iOp::COP1_S_NEG; - Jump_CoP1_S[8] = R4300iOp::UnknownOpcode; + Jump_CoP1_S[8] = R4300iOp::COP1_S_ROUND_L; Jump_CoP1_S[9] = R4300iOp::COP1_S_TRUNC_L; Jump_CoP1_S[10] = R4300iOp::COP1_S_CEIL_L; //added by Witten Jump_CoP1_S[11] = R4300iOp::COP1_S_FLOOR_L; //added by Witten From de0017174792c44e7783faea955df1ce9b534306 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Sun, 22 May 2016 23:28:07 -0700 Subject: [PATCH 13/31] Implement COP1_S_ROUND_L in cpu recompiler --- .../N64System/Recompiler/CodeSection.cpp | 1 + .../N64System/Recompiler/RecompilerOps.cpp | 12 ++++++++++++ .../N64System/Recompiler/RecompilerOps.h | 1 + 3 files changed, 14 insertions(+) diff --git a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp index 9cfc153db..ea9fb0888 100644 --- a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp +++ b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp @@ -1292,6 +1292,7 @@ bool CCodeSection::GenerateX86Code(uint32_t Test) case R4300i_COP1_FUNCT_NEG: COP1_S_NEG(); break; case R4300i_COP1_FUNCT_SQRT: COP1_S_SQRT(); break; case R4300i_COP1_FUNCT_MOV: COP1_S_MOV(); break; + case R4300i_COP1_FUNCT_ROUND_L: COP1_S_ROUND_L(); break; case R4300i_COP1_FUNCT_TRUNC_L: COP1_S_TRUNC_L(); break; case R4300i_COP1_FUNCT_CEIL_L: COP1_S_CEIL_L(); break; //added by Witten case R4300i_COP1_FUNCT_FLOOR_L: COP1_S_FLOOR_L(); break; //added by Witten diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp index c7dd1f425..0fe25f0bd 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp @@ -5946,6 +5946,18 @@ void CRecompilerOps::COP1_S_MOV() Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); } +void CRecompilerOps::COP1_S_ROUND_L() +{ + CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); + + m_Section->CompileCop1Test(); + if (m_Opcode.fd != m_Opcode.fs || !RegInStack(m_Opcode.fd, CRegInfo::FPU_Float)) + { + Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); + } + ChangeFPURegFormat(m_Opcode.fd, CRegInfo::FPU_Float, CRegInfo::FPU_Qword, CRegInfo::RoundNearest); +} + void CRecompilerOps::COP1_S_TRUNC_L() { CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h index 0bcc46866..983f85eb7 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h @@ -160,6 +160,7 @@ protected: static void COP1_S_NEG (); static void COP1_S_SQRT (); static void COP1_S_MOV (); + static void COP1_S_ROUND_L (); static void COP1_S_TRUNC_L (); static void COP1_S_CEIL_L (); //added by Witten static void COP1_S_FLOOR_L (); //added by Witten From 32ade84138fe44ab8a7e5c43cc5a0708ba72ed01 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Sun, 22 May 2016 23:37:45 -0700 Subject: [PATCH 14/31] Implement COP1_D_ROUND_L in cpu interpreter --- .../N64System/Interpreter/InterpreterOps.cpp | 8 +++++++- .../Project64-core/N64System/Interpreter/InterpreterOps.h | 1 + .../N64System/Interpreter/InterpreterOps32.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 946387469..af100bf17 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -546,7 +546,7 @@ R4300iOp::Func * R4300iOp::BuildInterpreter() Jump_CoP1_D[5] = COP1_D_ABS; Jump_CoP1_D[6] = COP1_D_MOV; Jump_CoP1_D[7] = COP1_D_NEG; - Jump_CoP1_D[8] = UnknownOpcode; + Jump_CoP1_D[8] = COP1_D_ROUND_L; Jump_CoP1_D[9] = COP1_D_TRUNC_L; //added by Witten Jump_CoP1_D[10] = COP1_D_CEIL_L; //added by Witten Jump_CoP1_D[11] = COP1_D_FLOOR_L; //added by Witten @@ -2658,6 +2658,12 @@ void R4300iOp::COP1_D_NEG() *(double *)_FPR_D[m_Opcode.fd] = (*(double *)_FPR_D[m_Opcode.fs] * -1.0); } +void R4300iOp::COP1_D_ROUND_L() +{ + TEST_COP1_USABLE_EXCEPTION(); + Double_RoundToInteger64(&*(uint64_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_TONEAREST); +} + void R4300iOp::COP1_D_TRUNC_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h index 12f2d9b9d..cf370db61 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h @@ -182,6 +182,7 @@ public: static void COP1_D_ABS(); static void COP1_D_MOV(); static void COP1_D_NEG(); + static void COP1_D_ROUND_L(); static void COP1_D_TRUNC_L(); //added by Witten static void COP1_D_CEIL_L(); //added by Witten static void COP1_D_FLOOR_L(); //added by Witten diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp index a459f3b9e..6d8324b36 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp @@ -441,7 +441,7 @@ R4300iOp32::Func * R4300iOp32::BuildInterpreter() Jump_CoP1_D[5] = R4300iOp::COP1_D_ABS; Jump_CoP1_D[6] = R4300iOp::COP1_D_MOV; Jump_CoP1_D[7] = R4300iOp::COP1_D_NEG; - Jump_CoP1_D[8] = R4300iOp::UnknownOpcode; + Jump_CoP1_D[8] = R4300iOp::COP1_D_ROUND_L; Jump_CoP1_D[9] = R4300iOp::COP1_D_TRUNC_L; //added by Witten Jump_CoP1_D[10] = R4300iOp::COP1_D_CEIL_L; //added by Witten Jump_CoP1_D[11] = R4300iOp::COP1_D_FLOOR_L; //added by Witten From dd581741d680e270741e3d305a4a7c82717641a3 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Sun, 22 May 2016 23:47:02 -0700 Subject: [PATCH 15/31] Implement COP1_D_ROUND_L in cpu recompiler --- .../N64System/Recompiler/CodeSection.cpp | 1 + .../N64System/Recompiler/RecompilerOps.cpp | 16 ++++++++++++++++ .../N64System/Recompiler/RecompilerOps.h | 1 + 3 files changed, 18 insertions(+) diff --git a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp index ea9fb0888..f98aef1c2 100644 --- a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp +++ b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp @@ -1327,6 +1327,7 @@ bool CCodeSection::GenerateX86Code(uint32_t Test) case R4300i_COP1_FUNCT_NEG: COP1_D_NEG(); break; case R4300i_COP1_FUNCT_SQRT: COP1_D_SQRT(); break; case R4300i_COP1_FUNCT_MOV: COP1_D_MOV(); break; + case R4300i_COP1_FUNCT_ROUND_L: COP1_D_ROUND_L(); break; case R4300i_COP1_FUNCT_TRUNC_L: COP1_D_TRUNC_L(); break; //added by Witten case R4300i_COP1_FUNCT_CEIL_L: COP1_D_CEIL_L(); break; //added by Witten case R4300i_COP1_FUNCT_FLOOR_L: COP1_D_FLOOR_L(); break; //added by Witten diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp index 0fe25f0bd..d697e157d 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp @@ -6308,6 +6308,22 @@ void CRecompilerOps::COP1_D_MOV() Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); } +void CRecompilerOps::COP1_D_ROUND_L() +{ + CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); + + m_Section->CompileCop1Test(); + if (RegInStack(m_Opcode.fs, CRegInfo::FPU_Double) || RegInStack(m_Opcode.fs, CRegInfo::FPU_Qword)) + { + UnMap_FPR(m_Opcode.fs, true); + } + if (m_Opcode.fd != m_Opcode.fs || !RegInStack(m_Opcode.fd, CRegInfo::FPU_Double)) + { + Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + } + ChangeFPURegFormat(m_Opcode.fd, CRegInfo::FPU_Double, CRegInfo::FPU_Qword, CRegInfo::RoundNearest); +} + void CRecompilerOps::COP1_D_TRUNC_L() //added by Witten { CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h index 983f85eb7..281829bba 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h @@ -182,6 +182,7 @@ protected: static void COP1_D_NEG (); static void COP1_D_SQRT (); static void COP1_D_MOV (); + static void COP1_D_ROUND_L (); static void COP1_D_TRUNC_L (); //added by Witten static void COP1_D_CEIL_L (); //added by Witten static void COP1_D_FLOOR_L (); //added by Witten From 5f342e73df9c6a00f1aecaa322480b3cb7d9e217 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Mon, 23 May 2016 18:23:32 +0200 Subject: [PATCH 16/31] [64DD] 64DD disk conversion fix --- Source/Project64-core/N64System/N64DiskClass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp index 813a559ec..cecc83c5c 100644 --- a/Source/Project64-core/N64System/N64DiskClass.cpp +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -290,7 +290,7 @@ void CN64Disk::ConvertDiskFormat() atrack = 0; for (track = 0; track < ZoneTracks[zone]; track++) { - if (track == SystemData[0x20 + zone * 0xC + atrack]) + if (atrack < 0xC && track == SystemData[0x20 + zone * 0xC + atrack]) { memset((void *)(&BlockData0), 0, BLOCKSIZE(zone)); memset((void *)(&BlockData1), 0, BLOCKSIZE(zone)); @@ -327,7 +327,7 @@ void CN64Disk::ConvertDiskFormat() atrack = 0xB; for (track = 1; track < ZoneTracks[zone] + 1; track++) { - if ((ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack]) + if (atrack > -1 && (ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack]) { memset((void *)(&BlockData0), 0, BLOCKSIZE(zone)); memset((void *)(&BlockData1), 0, BLOCKSIZE(zone)); From ea5c4abc098429cd6147fd50f145a29eda4ea208 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Tue, 24 May 2016 21:26:05 +0200 Subject: [PATCH 17/31] [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 18/31] [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 19/31] [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 20/31] [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 b187ad9b816eb34f07b3c08bc659e1cc9b7dd875 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Wed, 25 May 2016 17:10:21 -0700 Subject: [PATCH 21/31] Improve alist_resample New algorithm is faster and more accurate --- Source/Android/PluginRSP/alist.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Android/PluginRSP/alist.cpp b/Source/Android/PluginRSP/alist.cpp index 8e37e993b..06817e31a 100644 --- a/Source/Android/PluginRSP/alist.cpp +++ b/Source/Android/PluginRSP/alist.cpp @@ -633,11 +633,11 @@ void alist_resample( CHle * hle, bool init, bool flag2, uint16_t dmemo, uint16_t { const int16_t* lut = RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8); - *sample(hle, opos++) = clamp_s16( - ((*sample(hle, ipos) * lut[0]) >> 15) + - ((*sample(hle, ipos + 1) * lut[1]) >> 15) + - ((*sample(hle, ipos + 2) * lut[2]) >> 15) + - ((*sample(hle, ipos + 3) * lut[3]) >> 15)); + *sample(hle, opos++) = clamp_s16( ( + (*sample(hle, ipos ) * lut[0]) + + (*sample(hle, ipos + 1) * lut[1]) + + (*sample(hle, ipos + 2) * lut[2]) + + (*sample(hle, ipos + 3) * lut[3]) ) >> 15); pitch_accu += pitch; ipos += (pitch_accu >> 16); From c495edd17e6ae3ffe55fd6164e0fe644becc04a1 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Thu, 26 May 2016 18:18:07 +0200 Subject: [PATCH 22/31] [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 23/31] [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: From 4a5f3476e2bd4b3a7b06ededb7c50650d8367c4c Mon Sep 17 00:00:00 2001 From: Date: Thu, 2 Jun 2016 03:16:02 -0400 Subject: [PATCH 24/31] #include if one is provided. --- Source/Project64/Support.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Project64/Support.h b/Source/Project64/Support.h index 2380ecee0..d4ff9b1f3 100644 --- a/Source/Project64/Support.h +++ b/Source/Project64/Support.h @@ -1,4 +1,6 @@ +#if defined(_WIN32) #include +#endif #include #include From d8e820dfbfe68685fa2b8f8b030f590245d7e89e Mon Sep 17 00:00:00 2001 From: Date: Thu, 2 Jun 2016 03:16:38 -0400 Subject: [PATCH 25/31] s/memtest.h/MemTest.h --- Source/Project64/Support.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Project64/Support.h b/Source/Project64/Support.h index d4ff9b1f3..eb7f72cd1 100644 --- a/Source/Project64/Support.h +++ b/Source/Project64/Support.h @@ -2,7 +2,7 @@ #include #endif -#include +#include #include #include #include From 4036971653183a4b71ae7b8d78dba94471032608 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Thu, 2 Jun 2016 16:35:10 +0200 Subject: [PATCH 26/31] [64DD] Make sure at boot that the disk is inserted Fixes F-Zero X Expansion Kit loading too late --- Source/Project64-core/N64System/Mips/Disk.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Project64-core/N64System/Mips/Disk.cpp b/Source/Project64-core/N64System/Mips/Disk.cpp index 77191ec43..707de645f 100644 --- a/Source/Project64-core/N64System/Mips/Disk.cpp +++ b/Source/Project64-core/N64System/Mips/Disk.cpp @@ -83,6 +83,10 @@ void DiskCommand() //Unset Reset Bit g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; + //F-Zero X + Expansion Kit fix so it doesn't enable "swapping" at boot + dd_swapdelay = 0; + if (g_Disk != NULL) + g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES; break; case 0x00120000: //RTC Get Year & Month From 210832c61854862c2c23b9255a1dd644f768496a Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Thu, 2 Jun 2016 20:54:52 -0700 Subject: [PATCH 27/31] Improve alist_polef This change fixes Body Harvest. --- Source/Android/PluginRSP/alist.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Android/PluginRSP/alist.cpp b/Source/Android/PluginRSP/alist.cpp index 06817e31a..3bf003726 100644 --- a/Source/Android/PluginRSP/alist.cpp +++ b/Source/Android/PluginRSP/alist.cpp @@ -868,6 +868,7 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t unsigned i; int16_t l1, l2; int16_t h2_before[8]; + int32_t state[2]; count = align(count, 16); @@ -875,9 +876,11 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t { l1 = 0; l2 = 0; + state[0] = 0; } else { + state[0] = *dram_u32(hle, address); l1 = *dram_u16(hle, address + 4); l2 = *dram_u16(hle, address + 6); } @@ -911,7 +914,8 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t count -= 16; } while (count != 0); - dram_store_u16(hle, (uint16_t*)(dst - 4), address, 4); + state[1] = (l1 << 16) + l2; + dram_store_u32(hle, (uint32_t*)(state), address, 2); } void alist_iirf(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t* table, uint32_t address) From c06ad3a276729e2fccc0523964271157f65fee2c Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Thu, 2 Jun 2016 22:55:44 -0700 Subject: [PATCH 28/31] Fix a mistake with previous commit I double checked and realized that the doc I read was not consistent with the RSP microcode. It should be good now. --- Source/Android/PluginRSP/alist.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Android/PluginRSP/alist.cpp b/Source/Android/PluginRSP/alist.cpp index 3bf003726..6318cc54d 100644 --- a/Source/Android/PluginRSP/alist.cpp +++ b/Source/Android/PluginRSP/alist.cpp @@ -868,7 +868,6 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t unsigned i; int16_t l1, l2; int16_t h2_before[8]; - int32_t state[2]; count = align(count, 16); @@ -876,11 +875,9 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t { l1 = 0; l2 = 0; - state[0] = 0; } else { - state[0] = *dram_u32(hle, address); l1 = *dram_u16(hle, address + 4); l2 = *dram_u16(hle, address + 6); } @@ -914,8 +911,7 @@ void alist_polef(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t count -= 16; } while (count != 0); - state[1] = (l1 << 16) + l2; - dram_store_u32(hle, (uint32_t*)(state), address, 2); + dram_store_u32(hle, (uint32_t*)(dst - 4), address, 2); } void alist_iirf(CHle * hle, bool init, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t* table, uint32_t address) From efd82e1a991a6498da81c97f7475979b7d83b931 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 3 Jun 2016 00:19:21 -0700 Subject: [PATCH 29/31] Disable 32-bit Engine for NBA Live 2000 This gets rid of some graphical issues. --- Config/Project64.rdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Config/Project64.rdb b/Config/Project64.rdb index acefa20cf..0f0e4207a 100644 --- a/Config/Project64.rdb +++ b/Config/Project64.rdb @@ -3753,12 +3753,14 @@ Status=Compatible Good Name=NBA Live 2000 (E) (M4) Internal Name=NBA LIVE 2000 Status=Compatible +32bit=No [5F25B0EE-6227C1DB-C:45] Good Name=NBA Live 2000 (U) (M4) Internal Name=NBA LIVE 2000 Status=Compatible Culling=1 +32bit=No [CF84F45F-00E4F6EB-C:50] Good Name=NBA Live 99 (E) (M5) From c73004118e76c3f68829ea06d0afe7bd31f79abc Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 3 Jun 2016 00:21:21 -0700 Subject: [PATCH 30/31] Disable 32-bit Engine for NFL Blitz 2000 This gets rid of sync errors. --- Config/Project64.rdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Config/Project64.rdb b/Config/Project64.rdb index 0f0e4207a..c1e14d8ce 100644 --- a/Config/Project64.rdb +++ b/Config/Project64.rdb @@ -3815,11 +3815,13 @@ Status=Compatible Good Name=NFL Blitz 2000 (U) (V1.0) Internal Name=blitz2k Status=Compatible +32bit=No [5B755842-6CA39C7A-C:45] Good Name=NFL Blitz 2000 (U) (V1.1) Internal Name=blitz2k Status=Compatible +32bit=No [36FA35EB-E85E2E36-C:45] Good Name=NFL Blitz 2001 (U) From 3711a9bad5532ef365380ceb43166c732afa8a93 Mon Sep 17 00:00:00 2001 From: luigiblood Date: Fri, 3 Jun 2016 14:09:51 +0200 Subject: [PATCH 31/31] [RDB] Update F-Zero X (J) for Expansion Kit support --- Config/Project64.rdb | 1 + 1 file changed, 1 insertion(+) diff --git a/Config/Project64.rdb b/Config/Project64.rdb index acefa20cf..7144b3d7d 100644 --- a/Config/Project64.rdb +++ b/Config/Project64.rdb @@ -1811,6 +1811,7 @@ Status=Compatible Plugin Note=[Glide64] missing menu effects 32bit=No Culling=1 +Fixed Audio=0 [B30ED978-3003C9F9-C:45] Good Name=F-ZERO X (U)