From 2b629b4c43c1155d6c6d90c6a8ba4cae0ae0f683 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sun, 25 Aug 2024 03:15:26 +0200 Subject: [PATCH 1/3] debug: added support for SummerCart64 AUX register --- include/debug.h | 11 +++++- include/n64sys.h | 5 +++ include/regsinternal.h | 2 + src/debug.c | 84 ++++++++++++++++++++++++++++++++++++++++++ src/entrypoint.S | 14 ++++--- src/n64sys.c | 70 ++++++++++++++++++++++++++++++----- 6 files changed, 170 insertions(+), 16 deletions(-) diff --git a/include/debug.h b/include/debug.h index 54323fefa2..aa8a6bfc56 100644 --- a/include/debug.h +++ b/include/debug.h @@ -116,6 +116,9 @@ extern "C" { #define DEBUG_FEATURE_FILE_SD (1 << 3) +#define DEBUG_FEATURE_CART_INTERRUPT (1 << 4) + + /** * @brief Flag to activate all supported debugging features. * @@ -142,6 +145,10 @@ extern "C" { /** @brief Shutdown SD filesystem. */ void debug_close_sdfs(void); + + bool debug_init_cart_interrupt(void); + void debug_close_cart_interrupt(void); + /** * @brief Initialize debugging features of libdragon. * @@ -163,7 +170,9 @@ extern "C" { if (features & DEBUG_FEATURE_FILE_SD) ok = debug_init_sdfs("sd:/", -1) || ok; if (features & DEBUG_FEATURE_LOG_SD) - ok = debug_init_sdlog("sd:/libdragon.log", "a"); + ok = debug_init_sdlog("sd:/libdragon.log", "a") || ok; + if (features & DEBUG_FEATURE_CART_INTERRUPT) + ok = debug_init_cart_interrupt() || ok; return ok; } diff --git a/include/n64sys.h b/include/n64sys.h index 910636c989..42be8d05e1 100644 --- a/include/n64sys.h +++ b/include/n64sys.h @@ -279,6 +279,8 @@ void wait_ticks( unsigned long wait ); */ void wait_ms( unsigned long wait_ms ); +void halt(void); + /** * @brief Force a complete halt of all processors * @@ -292,6 +294,9 @@ void wait_ms( unsigned long wait_ms ); __attribute__((noreturn)) void die(void); +__attribute__((noreturn)) +void reboot(void); + /** * @brief Force a data cache invalidate over a memory region * diff --git a/include/regsinternal.h b/include/regsinternal.h index ca702a91b8..910c409a99 100644 --- a/include/regsinternal.h +++ b/include/regsinternal.h @@ -115,6 +115,8 @@ typedef struct PI_regs_s { uint32_t dom1_latency; /** @brief Cartridge domain 1 pulse width in RCP clock cycles. Requires DMA status bit guards to work reliably */ uint32_t dom1_pulse_width; + uint32_t dom1_page_size; + uint32_t dom1_release; // TODO: add remaining registers } PI_regs_t; diff --git a/src/debug.c b/src/debug.c index 050b02d7e4..4782599b53 100644 --- a/src/debug.c +++ b/src/debug.c @@ -669,6 +669,90 @@ void debug_close_sdfs(void) } } +#define SC64_SCR (0x1FFF0000) +#define SC64_IRQ (0x1FFF0014) +#define SC64_AUX (0x1FFF0018) + +#define SC64_SCR_AUX_IRQ_PENDING (1 << 23) +#define SC64_SCR_AUX_IRQ_MASK (1 << 22) + +#define SC64_IRQ_AUX_CLEAR (1 << 28) +#define SC64_IRQ_AUX_DISABLE (1 << 9) +#define SC64_IRQ_AUX_ENABLE (1 << 8) + +#define AUX_PING (0xFF000000) +#define AUX_HALT (0xFF000001) +#define AUX_REBOOT (0xFF000002) + +static void debug_cart_handler_sc64(void) +{ + bool halt_requested = false; + + do { + uint32_t scr = io_read(SC64_SCR); + + if ((scr & SC64_SCR_AUX_IRQ_MASK) && (scr & SC64_SCR_AUX_IRQ_PENDING)) { + io_write(SC64_IRQ, SC64_IRQ_AUX_CLEAR); + + switch (io_read(SC64_AUX)) { + case AUX_PING: + io_write(SC64_AUX, AUX_PING); + break; + + case AUX_HALT: + if (!halt_requested) { + halt(); + halt_requested = true; + } + io_write(SC64_AUX, AUX_HALT); + break; + + case AUX_REBOOT: + io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE); + io_write(SC64_AUX, AUX_REBOOT); + reboot(); + break; + + default: + break; + } + } + } while (halt_requested); +} + +bool debug_init_cart_interrupt(void) +{ + if (!sd_initialize_once()) + return false; + + if (cart_type == CART_SC) { + register_CART_handler(debug_cart_handler_sc64); + set_CART_interrupt(true); + + io_write(SC64_IRQ, SC64_IRQ_AUX_ENABLE); + + enabled_features |= DEBUG_FEATURE_CART_INTERRUPT; + + return true; + } + + return false; +} + +void debug_close_cart_interrupt(void) +{ + if (enabled_features & DEBUG_FEATURE_CART_INTERRUPT) { + enabled_features &= ~(DEBUG_FEATURE_CART_INTERRUPT); + + if (cart_type == CART_SC) { + io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE); + + set_CART_interrupt(false); + unregister_CART_handler(debug_cart_handler_sc64); + } + } +} + void debug_assert_func_f(const char *file, int line, const char *func, const char *failedexpr, const char *msg, ...) { disable_interrupts(); diff --git a/src/entrypoint.S b/src/entrypoint.S index 63bf35a349..a756669148 100644 --- a/src/entrypoint.S +++ b/src/entrypoint.S @@ -32,12 +32,14 @@ _start: sw t1, %gprel(__entropy_state+4)(gp) /* Copy other bootcode flags */ - lbu t0, 0x0009(v0) - lbu t1, 0x000A(v0) - lbu t2, 0x000B(v0) - sw t0, %gprel(__boot_tvtype)(gp) - sw t1, %gprel(__boot_resettype)(gp) - sw t2, %gprel(__boot_consoletype)(gp) + lbu t0, 0x0008(v0) + lbu t1, 0x0009(v0) + lbu t2, 0x000A(v0) + lbu t3, 0x000B(v0) + sw t0, %gprel(__boot_romtype)(gp) + sw t1, %gprel(__boot_tvtype)(gp) + sw t2, %gprel(__boot_resettype)(gp) + sw t3, %gprel(__boot_consoletype)(gp) la t0, debug_assert_func /* install assert function in system.c */ la t1, __assert_func_ptr diff --git a/src/n64sys.c b/src/n64sys.c index 0d72973f58..027ec56a44 100644 --- a/src/n64sys.c +++ b/src/n64sys.c @@ -10,6 +10,7 @@ #include #include "n64sys.h" #include "regsinternal.h" +#include "dma.h" #include "interrupt.h" #include "vi.h" #include "rsp.h" @@ -17,6 +18,7 @@ #include "utils.h" int __boot_memsize; ///< Memory size as detected by IPL3 +int __boot_romtype; ///< ROM type as detected by IPL3 int __boot_tvtype; ///< TV type as detected by IPL3 int __boot_resettype; ///< Reset type as detected by IPL3 int __boot_consoletype; ///< Console type as detected by IPL3 @@ -27,6 +29,9 @@ static uint32_t ticks64_base_tick; /** @brief Last value of the 64-bit counter */ static uint64_t ticks64_base; +/** @brief Structure used to interact with the PI registers */ +static volatile struct PI_regs_s * const PI_regs = (struct PI_regs_s *)0xa4600000; + /** * @brief Helper macro to perform cache refresh operations * @@ -175,6 +180,19 @@ void wait_ms( unsigned long wait_ms ) wait_ticks(TICKS_FROM_MS(wait_ms)); } +void halt(void) +{ + // Can't have any interrupts here + disable_interrupts(); + // Halt the RSP + *SP_STATUS = SP_WSTATUS_SET_HALT; + // Flush the RDP + *DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE; + *DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE; + // Shut the video off + *VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE); +} + /** * @brief Force a complete halt of all processors * @@ -187,19 +205,53 @@ void wait_ms( unsigned long wait_ms ) */ void die(void) { - // Can't have any interrupts here - disable_interrupts(); - // Halt the RSP - *SP_STATUS = SP_WSTATUS_SET_HALT; - // Flush the RDP - *DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE; - *DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE; - // Shut the video off - *VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE); + // Terminate the RCP execution + halt(); // Terminate the CPU execution abort(); } +void reboot(void) +{ + halt(); + + const uint32_t ROM_ADDRESS = 0x10000000; + + const int IPL3_SIZE = 0xFC0; + const uint32_t IPL3_OFFSET = 0x40; + + uint8_t ipl3_data[IPL3_SIZE] __attribute__((aligned(8))); + + C0_WRITE_STATUS(0x34000000); + + uint32_t pi_config = io_read(ROM_ADDRESS); + + PI_regs->dom1_latency = pi_config; + PI_regs->dom1_pulse_width = (pi_config >> 8); + PI_regs->dom1_page_size = (pi_config >> 16); + PI_regs->dom1_release = (pi_config >> 20); + + dma_read_raw_async(&ipl3_data, (ROM_ADDRESS + IPL3_OFFSET), sizeof(ipl3_data)); + dma_wait(); + rsp_load_data(ipl3_data, sizeof(ipl3_data), IPL3_OFFSET); + + void (*run_ipl3)(void) = (void (*)(void))((uint32_t)(SP_DMEM) + IPL3_OFFSET); + + register uint32_t rom_type asm ("s3") = __boot_romtype; + register uint32_t tv_type asm ("s4") = __boot_tvtype; + register uint32_t reset_type asm ("s5") = RESET_WARM; + + asm volatile ( + "jalr %[run_ipl3] \n" :: + [run_ipl3] "r" (run_ipl3), + [rom_type] "r" (rom_type), + [tv_type] "r" (tv_type), + [reset_type] "r" (reset_type) + ); + + abort(); +} + /** * @brief Initialize COP1 with default settings that prevent undesirable exceptions. * From d9b193e205c3e4f8920afee509b3c7680bbb5e0e Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sun, 25 Aug 2024 22:04:56 +0200 Subject: [PATCH 2/3] feedback --- include/debug.h | 10 +++---- include/dma.h | 16 ++++++++++ include/n64sys.h | 4 +-- src/debug.c | 77 ++++++++++++++++++++++++++++-------------------- src/dma.c | 12 +------- src/inspector.c | 3 ++ src/n64sys.c | 58 +++++++++++++++++++++++++++--------- src/rsp.c | 5 ++++ 8 files changed, 121 insertions(+), 64 deletions(-) diff --git a/include/debug.h b/include/debug.h index aa8a6bfc56..be634e310b 100644 --- a/include/debug.h +++ b/include/debug.h @@ -116,7 +116,7 @@ extern "C" { #define DEBUG_FEATURE_FILE_SD (1 << 3) -#define DEBUG_FEATURE_CART_INTERRUPT (1 << 4) +#define DEBUG_FEATURE_HOST_COMMANDS (1 << 4) /** @@ -146,8 +146,8 @@ extern "C" { void debug_close_sdfs(void); - bool debug_init_cart_interrupt(void); - void debug_close_cart_interrupt(void); + bool debug_init_host_commands(void); + void debug_close_host_commands(void); /** * @brief Initialize debugging features of libdragon. @@ -171,8 +171,8 @@ extern "C" { ok = debug_init_sdfs("sd:/", -1) || ok; if (features & DEBUG_FEATURE_LOG_SD) ok = debug_init_sdlog("sd:/libdragon.log", "a") || ok; - if (features & DEBUG_FEATURE_CART_INTERRUPT) - ok = debug_init_cart_interrupt() || ok; + if (features & DEBUG_FEATURE_HOST_COMMANDS) + ok = debug_init_host_commands() || ok; return ok; } diff --git a/include/dma.h b/include/dma.h index ecfcd1777b..02200a16dd 100644 --- a/include/dma.h +++ b/include/dma.h @@ -40,6 +40,22 @@ extern "C" { #define PI_WR_LEN ((volatile uint32_t*)0xA460000C) ///< PI DMA: write length register #define PI_STATUS ((volatile uint32_t*)0xA4600010) ///< PI: status register +/** + * @name PI Status Register Bit Definitions + * @{ + */ +/** @brief PI DMA Busy */ +#define PI_STATUS_DMA_BUSY ( 1 << 0 ) +/** @brief PI IO Busy */ +#define PI_STATUS_IO_BUSY ( 1 << 1 ) +/** @brief PI Error */ +#define PI_STATUS_ERROR ( 1 << 2 ) +/** @brief PI Reset */ +#define PI_STATUS_RESET ( 1 << 0 ) +/** @brief PI Clear interrupt */ +#define PI_STATUS_CLEAR_INTERRUPT ( 1 << 1 ) +/** @} */ + /** * @brief Start writing data to a peripheral through PI DMA (low-level) * diff --git a/include/n64sys.h b/include/n64sys.h index 42be8d05e1..ca596a2eb1 100644 --- a/include/n64sys.h +++ b/include/n64sys.h @@ -279,7 +279,7 @@ void wait_ticks( unsigned long wait ); */ void wait_ms( unsigned long wait_ms ); -void halt(void); +void sys_rcp_halt(void); /** * @brief Force a complete halt of all processors @@ -295,7 +295,7 @@ __attribute__((noreturn)) void die(void); __attribute__((noreturn)) -void reboot(void); +void sys_reboot(void); /** * @brief Force a data cache invalidate over a memory region diff --git a/src/debug.c b/src/debug.c index 4782599b53..619fe0097e 100644 --- a/src/debug.c +++ b/src/debug.c @@ -669,9 +669,9 @@ void debug_close_sdfs(void) } } -#define SC64_SCR (0x1FFF0000) -#define SC64_IRQ (0x1FFF0014) -#define SC64_AUX (0x1FFF0018) +#define SC64_REG_SCR (0x1FFF0000) +#define SC64_REG_IRQ (0x1FFF0014) +#define SC64_REG_AUX (0x1FFF0018) #define SC64_SCR_AUX_IRQ_PENDING (1 << 23) #define SC64_SCR_AUX_IRQ_MASK (1 << 22) @@ -680,58 +680,71 @@ void debug_close_sdfs(void) #define SC64_IRQ_AUX_DISABLE (1 << 9) #define SC64_IRQ_AUX_ENABLE (1 << 8) -#define AUX_PING (0xFF000000) -#define AUX_HALT (0xFF000001) -#define AUX_REBOOT (0xFF000002) +#define SC64_AUX_MSG_PING (0xFF000000) +#define SC64_AUX_MSG_HALT (0xFF000001) +#define SC64_AUX_MSG_REBOOT (0xFF000002) -static void debug_cart_handler_sc64(void) +static void debug_cart_interrupt_handler_sc64(void) { - bool halt_requested = false; + bool rcp_halted = false; do { - uint32_t scr = io_read(SC64_SCR); + uint32_t scr = io_read(SC64_REG_SCR); if ((scr & SC64_SCR_AUX_IRQ_MASK) && (scr & SC64_SCR_AUX_IRQ_PENDING)) { - io_write(SC64_IRQ, SC64_IRQ_AUX_CLEAR); + io_write(SC64_REG_IRQ, SC64_IRQ_AUX_CLEAR); - switch (io_read(SC64_AUX)) { - case AUX_PING: - io_write(SC64_AUX, AUX_PING); + switch (io_read(SC64_REG_AUX)) { + case SC64_AUX_MSG_PING: + io_write(SC64_REG_AUX, SC64_AUX_MSG_PING); break; - case AUX_HALT: - if (!halt_requested) { - halt(); - halt_requested = true; + case SC64_AUX_MSG_HALT: + if (!rcp_halted) { + sys_rcp_halt(); + rcp_halted = true; } - io_write(SC64_AUX, AUX_HALT); + io_write(SC64_REG_AUX, SC64_AUX_MSG_HALT); break; - case AUX_REBOOT: - io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE); - io_write(SC64_AUX, AUX_REBOOT); - reboot(); + case SC64_AUX_MSG_REBOOT: + io_write(SC64_REG_IRQ, SC64_IRQ_AUX_DISABLE); + io_write(SC64_REG_AUX, SC64_AUX_MSG_REBOOT); + sys_reboot(); break; default: break; } } - } while (halt_requested); + } while (rcp_halted); } -bool debug_init_cart_interrupt(void) +bool debug_poll_host_commands(void) +{ + if (!(enabled_features & DEBUG_FEATURE_HOST_COMMANDS)) + return false; + + if (cart_type == CART_SC) { + debug_cart_interrupt_handler_sc64(); + return true; + } + + return false; +} + +bool debug_init_host_commands(void) { if (!sd_initialize_once()) return false; if (cart_type == CART_SC) { - register_CART_handler(debug_cart_handler_sc64); + register_CART_handler(debug_cart_interrupt_handler_sc64); set_CART_interrupt(true); - io_write(SC64_IRQ, SC64_IRQ_AUX_ENABLE); + io_write(SC64_REG_IRQ, SC64_IRQ_AUX_ENABLE); - enabled_features |= DEBUG_FEATURE_CART_INTERRUPT; + enabled_features |= DEBUG_FEATURE_HOST_COMMANDS; return true; } @@ -739,16 +752,16 @@ bool debug_init_cart_interrupt(void) return false; } -void debug_close_cart_interrupt(void) +void debug_close_host_commands(void) { - if (enabled_features & DEBUG_FEATURE_CART_INTERRUPT) { - enabled_features &= ~(DEBUG_FEATURE_CART_INTERRUPT); + if (enabled_features & DEBUG_FEATURE_HOST_COMMANDS) { + enabled_features &= ~(DEBUG_FEATURE_HOST_COMMANDS); if (cart_type == CART_SC) { - io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE); + io_write(SC64_REG_IRQ, SC64_IRQ_AUX_DISABLE); set_CART_interrupt(false); - unregister_CART_handler(debug_cart_handler_sc64); + unregister_CART_handler(debug_cart_interrupt_handler_sc64); } } } diff --git a/src/dma.c b/src/dma.c index be26590e9f..f7e4d1ba0a 100644 --- a/src/dma.c +++ b/src/dma.c @@ -4,6 +4,7 @@ * @ingroup dma */ #include +#include "dma.h" #include "n64types.h" #include "n64sys.h" #include "interrupt.h" @@ -11,17 +12,6 @@ #include "utils.h" #include "regsinternal.h" -/** - * @name PI Status Register Bit Definitions - * @{ - */ -/** @brief PI DMA Busy */ -#define PI_STATUS_DMA_BUSY ( 1 << 0 ) -/** @brief PI IO Busy */ -#define PI_STATUS_IO_BUSY ( 1 << 1 ) -/** @brief PI Error */ -#define PI_STATUS_ERROR ( 1 << 2 ) -/** @} */ /** @brief Structure used to interact with the PI registers */ static volatile struct PI_regs_s * const PI_regs = (struct PI_regs_s *)0xa4600000; diff --git a/src/inspector.c b/src/inspector.c index 45dbb233db..318240fd3d 100644 --- a/src/inspector.c +++ b/src/inspector.c @@ -548,6 +548,9 @@ static void inspector(exception_t* ex, enum Mode mode) { backtrace = true; break; } + // Poll incoming commands from the host + extern bool debug_poll_host_commands(void); + debug_poll_host_commands(); // Avoid constantly banging the PIF with controller reads, that // would prevent the RESET button from working. wait_ms(1); diff --git a/src/n64sys.c b/src/n64sys.c index 027ec56a44..7b44541d3a 100644 --- a/src/n64sys.c +++ b/src/n64sys.c @@ -180,17 +180,37 @@ void wait_ms( unsigned long wait_ms ) wait_ticks(TICKS_FROM_MS(wait_ms)); } -void halt(void) +void sys_rcp_halt(void) { // Can't have any interrupts here disable_interrupts(); + + // Stop PI transaction + *PI_STATUS = PI_STATUS_CLEAR_INTERRUPT | PI_STATUS_RESET; + // Halt the RSP *SP_STATUS = SP_WSTATUS_SET_HALT; - // Flush the RDP - *DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE; - *DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE; + + // Wait for RSP to halt execution + while( !(*SP_STATUS & (SP_STATUS_HALTED)) ); + + // Wait for RSP IO and DMA operations to finish + while( *SP_STATUS & (SP_STATUS_IO_BUSY | SP_STATUS_DMA_BUSY) ); + // Shut the video off - *VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE); + if ( vi_is_active() ) { vi_wait_for_vblank(); } + vi_set_blank_image(); + + // Turn off and clear VI interrupt + *VI_V_INTR = 0x3FF; + *VI_V_CURRENT = 0; + + // Wait for RDP to finish fetching commands + RSP_WAIT_LOOP(200) { + if ( !(*DP_STATUS & (DP_STATUS_DMA_BUSY)) ) { + break; + } + } } /** @@ -206,41 +226,51 @@ void halt(void) void die(void) { // Terminate the RCP execution - halt(); + sys_rcp_halt(); + // Terminate the CPU execution abort(); } -void reboot(void) +void sys_reboot(void) { - halt(); - - const uint32_t ROM_ADDRESS = 0x10000000; - + const uint32_t ROM_ADDRESS = __boot_romtype ? 0x06000000 : 0x10000000; const int IPL3_SIZE = 0xFC0; const uint32_t IPL3_OFFSET = 0x40; uint8_t ipl3_data[IPL3_SIZE] __attribute__((aligned(8))); - C0_WRITE_STATUS(0x34000000); + // Halt RCP execution before soft rebooting + sys_rcp_halt(); - uint32_t pi_config = io_read(ROM_ADDRESS); + // Set the default PI DOM1 timings + PI_regs->dom1_latency = 0xFF; + PI_regs->dom1_pulse_width = 0xFF; + PI_regs->dom1_page_size = 0x0F; + PI_regs->dom1_release = 0x03; + // Read and set PI DOM1 timings from the ROM header + uint32_t pi_config = io_read(ROM_ADDRESS); PI_regs->dom1_latency = pi_config; PI_regs->dom1_pulse_width = (pi_config >> 8); PI_regs->dom1_page_size = (pi_config >> 16); PI_regs->dom1_release = (pi_config >> 20); + // Load IPL3 into RSP DMEM dma_read_raw_async(&ipl3_data, (ROM_ADDRESS + IPL3_OFFSET), sizeof(ipl3_data)); dma_wait(); rsp_load_data(ipl3_data, sizeof(ipl3_data), IPL3_OFFSET); + // Prepare entry arguments void (*run_ipl3)(void) = (void (*)(void))((uint32_t)(SP_DMEM) + IPL3_OFFSET); - register uint32_t rom_type asm ("s3") = __boot_romtype; register uint32_t tv_type asm ("s4") = __boot_tvtype; register uint32_t reset_type asm ("s5") = RESET_WARM; + // Set CU1, CU0 and FR bits + C0_WRITE_STATUS((1 << 29) | (1 << 28) | (1 << 26)); + + // Jump to IPL3 asm volatile ( "jalr %[run_ipl3] \n" :: [run_ipl3] "r" (run_ipl3), diff --git a/src/rsp.c b/src/rsp.c index 98c423343f..e1a6575340 100644 --- a/src/rsp.c +++ b/src/rsp.c @@ -449,6 +449,11 @@ void __rsp_crash(const char *file, int line, const char *func, const char *msg, // OK we're done. Render on the screen and abort console_render(); + + // Poll incoming commands from the host + extern bool debug_poll_host_commands(void); + while (debug_poll_host_commands()); + abort(); } /// @endcond From 2aee508336fbc270d388b451ca7d06056cfec62a Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sun, 25 Aug 2024 22:41:13 +0200 Subject: [PATCH 3/3] restore RDP flush --- src/n64sys.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/n64sys.c b/src/n64sys.c index 7b44541d3a..a8fd20efb6 100644 --- a/src/n64sys.c +++ b/src/n64sys.c @@ -192,11 +192,20 @@ void sys_rcp_halt(void) *SP_STATUS = SP_WSTATUS_SET_HALT; // Wait for RSP to halt execution - while( !(*SP_STATUS & (SP_STATUS_HALTED)) ); + while( !(*SP_STATUS & SP_STATUS_HALTED) ); // Wait for RSP IO and DMA operations to finish while( *SP_STATUS & (SP_STATUS_IO_BUSY | SP_STATUS_DMA_BUSY) ); + // Flush the RDP and wait for DMA to finish fetching commands + *DP_STATUS = DP_WSTATUS_SET_FLUSH; + RSP_WAIT_LOOP(200) { + if ( !(*DP_STATUS & DP_STATUS_DMA_BUSY) ) { + break; + } + } + *DP_STATUS = DP_WSTATUS_RESET_FLUSH; + // Shut the video off if ( vi_is_active() ) { vi_wait_for_vblank(); } vi_set_blank_image(); @@ -204,13 +213,6 @@ void sys_rcp_halt(void) // Turn off and clear VI interrupt *VI_V_INTR = 0x3FF; *VI_V_CURRENT = 0; - - // Wait for RDP to finish fetching commands - RSP_WAIT_LOOP(200) { - if ( !(*DP_STATUS & (DP_STATUS_DMA_BUSY)) ) { - break; - } - } } /**