From 7984eae35781e342bf6150c6773b0272e7462a2d Mon Sep 17 00:00:00 2001 From: dlbuhtig4096 <> Date: Sun, 20 Oct 2024 13:02:15 +0800 Subject: [PATCH 1/3] Fix ensata sound register emulation. --- desmume/src/MMU.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index f8a7ed159..7c3f440eb 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -2475,6 +2475,7 @@ bool validateIORegsWrite(u32 addr, u8 size, u32 val) if(addrMasked == eng_3D_CLIPMTX_RESULT) return true; if(addrMasked == 0x04FFF000) return true; if(addrMasked == 0x04FFF010) return true; + if(addrMasked == 0x04FFF200) return true; } switch (addrMasked) @@ -3818,6 +3819,11 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) case REG_VRAMCNTI: MMU_VRAMmapControl(adr-REG_VRAMCNTA, val); break; + + + // ensata sound register + case 0x04FFF200: + break; #ifdef LOG_CARD case 0x040001A0 : /* TODO (clear): ??? */ @@ -5482,6 +5488,10 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr) case REG_KEYINPUT: LagFrameFlag=0; break; + + // Ensata sound register + case 0x04FFF200: + return 1; } return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); } From 28f5c76035ef036f31f729923d0787c0dbe55f27 Mon Sep 17 00:00:00 2001 From: dlbuhtig4096 <> Date: Sun, 20 Oct 2024 17:08:19 +0800 Subject: [PATCH 2/3] Proper ensata handshake on reconnection. --- desmume/src/MMU.cpp | 47 +++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 7c3f440eb..a09cc24b5 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -1835,31 +1835,40 @@ static void writereg_POWCNT1(const int size, const u32 adr, const u32 val) static INLINE void MMU_IPCSync(u8 proc, u32 val) { - //INFO("IPC%s sync 0x%04X (0x%02X|%02X)\n", proc?"7":"9", val, val >> 8, val & 0xFF); + u32 sync_l = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x180) & 0xFFFF; u32 sync_r = T1ReadLong(MMU.MMU_MEM[proc^1][0x40], 0x180) & 0xFFFF; + u32 iter = (val & 0x0F00) >> 8; - sync_l = ( sync_l & 0x000F ) | ( val & 0x0F00 ); - sync_r = ( sync_r & 0x6F00 ) | ( (val >> 8) & 0x000F ); + sync_l = ( sync_l & 0x000F ) | ( val & 0x6F00 ); + sync_r = ( sync_r & 0x6F00 ) | ( iter ); - sync_l |= val & 0x6000; + // For some reason, the arm9 doesn't handshake when ensata is detected. + // So we complete the protocol here, which is to mirror the values 8..0 back to + // The arm7 as they are written by the arm7 + if (nds.ensataEmulation) { - if(nds.ensataEmulation && proc==1 && nds.ensataIpcSyncCounter<9) { - u32 iteration = (val&0x0F00)>>8; - - if(iteration==8-nds.ensataIpcSyncCounter) - nds.ensataIpcSyncCounter++; - else printf("ERROR: ENSATA IPC SYNC HACK FAILED; BAD THINGS MAY HAPPEN\n"); - - //for some reason, the arm9 doesn't handshake when ensata is detected. - //so we complete the protocol here, which is to mirror the values 8..0 back to - //the arm7 as they are written by the arm7 - sync_r &= 0xF0FF; - sync_r |= (iteration<<8); - sync_l &= 0xFFF0; - sync_l |= iteration; + if (proc) { + // However this hack would break soft reset because it also syncs through ipcsync. + // So we have to add some additional checks to ensure that it's handshake instead of reset. + if ((iter & 8) || (nds.ensataIpcSyncCounter)) { + // sync_r = (sync_r & 0xF0FF) | (iter << 8); // This is not necessary. + sync_l = (sync_l & 0xFFF0) | iter; + nds.ensataIpcSyncCounter = iter; + } + } + else { + // After ensata handshake, arm9 will write 0x100 as a signal if Ensata is detected. + // This will prevent reset from working, so we have to ignore this. + if (nds.ensataHandshake == ENSATA_HANDSHAKE_complete) { + nds.ensataHandshake = ENSATA_HANDSHAKE_none; + return; + } + } } + // printf("IPCSync(%d, %04x): %04x %04x %d\n", proc, val, sync_l, sync_r, nds.ensataIpcSyncCounter); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, sync_l); T1WriteLong(MMU.MMU_MEM[proc^1][0x40], 0x180, sync_r); @@ -4969,7 +4978,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) //todo - these are usually write only regs (these and 1000 more) //shouldnt we block them from getting written? ugh case eng_3D_CLIPMTX_RESULT: - if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_none && val==0x2468ace0) + if(nds.ensataEmulation /* && nds.ensataHandshake == ENSATA_HANDSHAKE_none */&& val==0x2468ace0) { printf("ENSATA HANDSHAKE BEGIN\n"); nds.ensataHandshake = ENSATA_HANDSHAKE_query; From ff84815acbf1762576c01040121f62a3a518fd01 Mon Sep 17 00:00:00 2001 From: dlbuhtig4096 <> Date: Thu, 24 Oct 2024 16:35:54 +0800 Subject: [PATCH 3/3] Improve console allocation. --- desmume/src/frontend/windows/console.cpp | 5 ++++ tools/nds_firmware_tool/src/console.cpp | 31 +++++++++++++++--------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/desmume/src/frontend/windows/console.cpp b/desmume/src/frontend/windows/console.cpp index 8bdc38ae7..cce950201 100644 --- a/desmume/src/frontend/windows/console.cpp +++ b/desmume/src/frontend/windows/console.cpp @@ -119,6 +119,8 @@ void OpenConsole() //stdout is already connected to something. keep using it and dont let the console interfere bool shouldRedirectStdout = fileType == FILE_TYPE_UNKNOWN; bool attached = false; + +#if 0 if (!AllocConsole()) { HMODULE lib = LoadLibrary("kernel32.dll"); @@ -143,6 +145,9 @@ void OpenConsole() SetConsoleCP(GetACP()); SetConsoleOutputCP(GetACP()); } +#else + attached = AttachConsole(-1) || AllocConsole(); +#endif //newer and improved console title: SetConsoleTitleW(SkipEverythingButProgramInCommandLine(GetCommandLineW()).c_str()); diff --git a/tools/nds_firmware_tool/src/console.cpp b/tools/nds_firmware_tool/src/console.cpp index ed926752c..d45bb311e 100644 --- a/tools/nds_firmware_tool/src/console.cpp +++ b/tools/nds_firmware_tool/src/console.cpp @@ -30,7 +30,7 @@ #include #define BUFFER_SIZE 100 -HANDLE hConsole; +HANDLE hConsole = NULL; void OpenConsole() { COORD csize; @@ -41,27 +41,33 @@ void OpenConsole() //dont do anything if we're already attached if (hConsole) return; +#if 0 //attach to an existing console (if we can; this is circuitous because AttachConsole wasnt added until XP) //remember to abstract this late bound function notion if we end up having to do this anywhere else bool attached = false; - HMODULE lib = LoadLibrary("kernel32.dll"); - if(lib) + + // kernel32.dll is always loaded on windows. + HMODULE lib = GetModuleHandleA("kernel32.dll"); // LoadLibrary("kernel32.dll"); + if (lib) { typedef BOOL (WINAPI *_TAttachConsole)(DWORD dwProcessId); _TAttachConsole _AttachConsole = (_TAttachConsole)GetProcAddress(lib,"AttachConsole"); - if(_AttachConsole) + if (_AttachConsole) { - if(_AttachConsole(-1)) - attached = true; + attached = (bool)_AttachConsole(-1); } - FreeLibrary(lib); + // You cannot free kernel32.dll + // FreeLibrary(lib); } //if we failed to attach, then alloc a new console - if(!attached) + if (!attached) { AllocConsole(); } +#else + if (!AttachConsole(-1)) { AllocConsole(); } +#endif hConsole = GetStdHandle(STD_OUTPUT_HANDLE); @@ -91,9 +97,12 @@ void OpenConsole() srect.Right = srect.Left + 99; srect.Bottom = srect.Top + 64; SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); - SetConsoleCP(GetACP()); - SetConsoleOutputCP(GetACP()); - if(attached) printf("\n"); + + // Use default code page. + // SetConsoleCP(GetACP()); + // SetConsoleOutputCP(GetACP()); + + if (attached) printf("\n"); printf("%s\n",_TITLE); printf("- compiled: %s %s\n\n",__DATE__,__TIME__); }