diff --git a/mupen64plus-core/src/device/rcp/pi/pi_controller.c b/mupen64plus-core/src/device/rcp/pi/pi_controller.c index 8666007..4226153 100644 --- a/mupen64plus-core/src/device/rcp/pi/pi_controller.c +++ b/mupen64plus-core/src/device/rcp/pi/pi_controller.c @@ -54,10 +54,13 @@ static void dma_pi_read(struct pi_controller* pi) return; uint32_t cart_addr = pi->regs[PI_CART_ADDR_REG] & ~UINT32_C(1); - uint32_t dram_addr = pi->regs[PI_DRAM_ADDR_REG] & 0xffffff; - uint32_t length = (pi->regs[PI_RD_LEN_REG] & UINT32_C(0x00fffffe)) + 2; + uint32_t dram_addr = pi->regs[PI_DRAM_ADDR_REG] & 0xfffffe; + uint32_t length = (pi->regs[PI_RD_LEN_REG] & UINT32_C(0x00ffffff)) + 1; const uint8_t* dram = (uint8_t*)pi->ri->rdram->dram; + if (dram_addr & 0x7) + length -= dram_addr & 0x7; + const struct pi_dma_handler* handler = NULL; void* opaque = NULL; @@ -74,6 +77,10 @@ static void dma_pi_read(struct pi_controller* pi) /* Mark DMA as busy */ pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY; + /* Update PI_DRAM_ADDR_REG and PI_CART_ADDR_REG */ + length = (pi->regs[PI_RD_LEN_REG] & UINT32_C(0x00ffffff)) + 1; + pi->regs[PI_DRAM_ADDR_REG] = (pi->regs[PI_DRAM_ADDR_REG] + length + 7) & ~7; + pi->regs[PI_CART_ADDR_REG] = (pi->regs[PI_CART_ADDR_REG] + length + 1) & ~1; /* schedule end of dma interrupt event */ cp0_update_count(pi->mi->r4300); @@ -86,10 +93,13 @@ static void dma_pi_write(struct pi_controller* pi) return; uint32_t cart_addr = pi->regs[PI_CART_ADDR_REG] & ~UINT32_C(1); - uint32_t dram_addr = pi->regs[PI_DRAM_ADDR_REG] & 0xffffff; - uint32_t length = (pi->regs[PI_WR_LEN_REG] & UINT32_C(0x00fffffe)) + 2; + uint32_t dram_addr = pi->regs[PI_DRAM_ADDR_REG] & 0xfffffe; + uint32_t length = (pi->regs[PI_WR_LEN_REG] & UINT32_C(0x00ffffff)) + 1; uint8_t* dram = (uint8_t*)pi->ri->rdram->dram; + if (dram_addr & 0x7) + length -= dram_addr & 0x7; + const struct pi_dma_handler* handler = NULL; void* opaque = NULL; @@ -106,6 +116,10 @@ static void dma_pi_write(struct pi_controller* pi) /* Mark DMA as busy */ pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY; + /* Update PI_DRAM_ADDR_REG and PI_CART_ADDR_REG */ + length = (pi->regs[PI_WR_LEN_REG] & UINT32_C(0x00ffffff)) + 1; + pi->regs[PI_DRAM_ADDR_REG] = (pi->regs[PI_DRAM_ADDR_REG] + length + 7) & ~7; + pi->regs[PI_CART_ADDR_REG] = (pi->regs[PI_CART_ADDR_REG] + length + 1) & ~1; /* schedule end of dma interrupt event */ cp0_update_count(pi->mi->r4300); @@ -140,6 +154,13 @@ void read_pi_regs(void* opaque, uint32_t address, uint32_t* value) uint32_t reg = pi_reg(address); *value = pi->regs[reg]; + + if (reg == PI_WR_LEN_REG || reg == PI_RD_LEN_REG) + *value = 0x7F; + else if (reg == PI_CART_ADDR_REG) + *value &= 0xFFFFFFFE; + else if (reg == PI_DRAM_ADDR_REG) + *value &= 0xFFFFFE; } void write_pi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask) @@ -168,9 +189,12 @@ void write_pi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask return; case PI_STATUS_REG: - if (value & mask & 2) + if (value & mask & PI_STATUS_CLR_INTR) + { + pi->regs[reg] &= ~PI_STATUS_INTERRUPT; clear_rcp_interrupt(pi->mi, MI_INTR_PI); - if (value & mask & 1) + } + if (value & mask & PI_STATUS_RESET) pi->regs[PI_STATUS_REG] = 0; return; @@ -193,6 +217,7 @@ void pi_end_of_dma_event(void* opaque) { struct pi_controller* pi = (struct pi_controller*)opaque; pi->regs[PI_STATUS_REG] &= ~(PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY); + pi->regs[PI_STATUS_REG] |= PI_STATUS_INTERRUPT; if (pi->dd != NULL) { if ((pi->regs[PI_CART_ADDR_REG] == MM_DD_C2S_BUFFER) || diff --git a/mupen64plus-core/src/device/rcp/pi/pi_controller.h b/mupen64plus-core/src/device/rcp/pi/pi_controller.h index bff869c..8f2dafd 100644 --- a/mupen64plus-core/src/device/rcp/pi/pi_controller.h +++ b/mupen64plus-core/src/device/rcp/pi/pi_controller.h @@ -57,6 +57,7 @@ enum PI_STATUS_DMA_BUSY = 0x01, PI_STATUS_IO_BUSY = 0x02, PI_STATUS_ERROR = 0x04, + PI_STATUS_INTERRUPT = 0x08, /* PI_STATUS - write */ PI_STATUS_RESET = 0x01,