based on tests on ther real thing.
static void io_write_dma_icr32(u32 value)
{
- u32 tmp = ~value & HW_DMA_ICR;
- HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp;
+ u32 tmp = value & 0x00ff803f;
+ tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000;
+ if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000)
+ || tmp & HW_DMA_ICR_BUS_ERROR) {
+ if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT))
+ psxHu32ref(0x1070) |= SWAP32(8);
+ tmp |= HW_DMA_ICR_IRQ_SENT;
+ }
+ HW_DMA_ICR = SWAPu32(tmp);
}
#define make_dma_func(n) \
#include "mdec.h"
#include "cdrom.h"
+//#undef PSXHW_LOG
+//#define PSXHW_LOG printf
+
void psxHwReset() {
if (Config.Sio) psxHu32ref(0x1070) |= SWAP32(0x80);
if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAP32(0x200);
PSXHW_LOG("DMA ICR 32bit write %x\n", value);
#endif
{
- u32 tmp = (~value) & SWAPu32(HW_DMA_ICR);
- HW_DMA_ICR = SWAPu32(((tmp ^ value) & 0xffffff) ^ tmp);
+ u32 tmp = value & 0x00ff803f;
+ tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000;
+ if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000)
+ || tmp & HW_DMA_ICR_BUS_ERROR) {
+ if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT))
+ psxHu32ref(0x1070) |= SWAP32(8);
+ tmp |= HW_DMA_ICR_IRQ_SENT;
+ }
+ HW_DMA_ICR = SWAPu32(tmp);
return;
}
#define HW_DMA_PCR (psxHu32ref(0x10f0))
#define HW_DMA_ICR (psxHu32ref(0x10f4))
-#define DMA_INTERRUPT(n) \
- if (SWAPu32(HW_DMA_ICR) & (1 << (16 + n))) { \
- HW_DMA_ICR |= SWAP32(1 << (24 + n)); \
- psxHu32ref(0x1070) |= SWAP32(8); \
- }
+#define HW_DMA_ICR_BUS_ERROR (1<<15)
+#define HW_DMA_ICR_GLOBAL_ENABLE (1<<23)
+#define HW_DMA_ICR_IRQ_SENT (1<<31)
+
+#define DMA_INTERRUPT(n) { \
+ u32 icr = SWAPu32(HW_DMA_ICR); \
+ if (icr & (1 << (16 + n))) { \
+ icr |= 1 << (24 + n); \
+ if (icr & HW_DMA_ICR_GLOBAL_ENABLE && !(icr & HW_DMA_ICR_IRQ_SENT)) { \
+ psxHu32ref(0x1070) |= SWAP32(8); \
+ icr |= HW_DMA_ICR_IRQ_SENT; \
+ } \
+ HW_DMA_ICR = SWAP32(icr); \
+ } \
+}
void psxHwReset();
u8 psxHwRead8(u32 add);