fix some ipc fifo bugs (fixes Defc0n-Zero demo and some recent libnds fifosystem changes)
This commit is contained in:
parent
fde699f8d9
commit
be8b6906c8
|
@ -26,8 +26,7 @@
|
|||
#include "gfx3d.h"
|
||||
|
||||
// ========================================================= IPC FIFO
|
||||
IPC_FIFO ipc_fifo[2]; // 0 - ARM9
|
||||
// 1 - ARM7
|
||||
IPC_FIFO ipc_fifo[2];
|
||||
|
||||
void IPC_FIFOinit(u8 proc)
|
||||
{
|
||||
|
@ -69,6 +68,9 @@ void IPC_FIFOsend(u8 proc, u32 val)
|
|||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
|
||||
|
||||
if(cnt_r&IPCFIFOCNT_RECVIRQEN)
|
||||
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
|
@ -99,12 +101,14 @@ u32 IPC_FIFOrecv(u8 proc)
|
|||
|
||||
//LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
|
||||
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
|
||||
|
||||
|
||||
if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty
|
||||
{
|
||||
cnt_l |= 0x0101;
|
||||
cnt_l |= 0x0100;
|
||||
cnt_r |= 0x0001;
|
||||
|
||||
if(cnt_r&IPCFIFOCNT_SENDIRQEN)
|
||||
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY);
|
||||
}
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
|
@ -117,6 +121,7 @@ u32 IPC_FIFOrecv(u8 proc)
|
|||
|
||||
void IPC_FIFOcnt(u8 proc, u16 val)
|
||||
{
|
||||
u8 proc_remote = proc ^ 1;
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
|
||||
|
||||
|
@ -131,14 +136,24 @@ void IPC_FIFOcnt(u8 proc, u16 val)
|
|||
ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0;
|
||||
|
||||
cnt_l |= IPCFIFOCNT_SENDEMPTY;
|
||||
cnt_l &= ~IPCFIFOCNT_SENDFULL;
|
||||
cnt_r |= IPCFIFOCNT_RECVEMPTY;
|
||||
|
||||
cnt_l &= ~IPCFIFOCNT_SENDFULL;
|
||||
cnt_r &= ~IPCFIFOCNT_RECVFULL;
|
||||
}
|
||||
|
||||
}
|
||||
cnt_l &= ~IPCFIFOCNT_WRITEABLE;
|
||||
cnt_l |= val & IPCFIFOCNT_WRITEABLE;
|
||||
|
||||
//IPCFIFOCNT_SENDIRQEN may have been set (and/or the fifo may have been cleared) so we may need to trigger this irq
|
||||
//(this approach is used by libnds fifo system on occasion in fifoInternalSend, and began happening frequently for value32 with r4326)
|
||||
if(cnt_l&IPCFIFOCNT_SENDIRQEN) if(cnt_l & IPCFIFOCNT_SENDEMPTY)
|
||||
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_SENDEMPTY);
|
||||
|
||||
//IPCFIFOCNT_RECVIRQEN may have been set so we may need to trigger this irq
|
||||
if(cnt_l&IPCFIFOCNT_RECVIRQEN) if(!(cnt_l & IPCFIFOCNT_RECVEMPTY))
|
||||
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);
|
||||
|
||||
|
|
|
@ -1212,16 +1212,19 @@ static void validateIF_arm9()
|
|||
template<int PROCNUM> static void REG_IF_WriteByte(u32 addr, u8 val)
|
||||
{
|
||||
//the following bits are generated from logic and should not be affected here
|
||||
//Bit 17 IPC Send FIFO Empty
|
||||
//Bit 18 IPC Recv FIFO Not Empty
|
||||
//Bit 21 NDS9 only: Geometry Command FIFO
|
||||
//arm9: IF &= ~0x00260000;
|
||||
//arm7: IF &= ~0x00060000;
|
||||
//arm9: IF &= ~0x00200000;
|
||||
//arm7: IF &= ~0x00000000;
|
||||
//UPDATE IN setIF() ALSO!!!!!!!!!!!!!!!!
|
||||
//UPDATE IN mmu_loadstate ALSO!!!!!!!!!!!!
|
||||
if(addr==2)
|
||||
if(PROCNUM==ARMCPU_ARM9)
|
||||
val &= ~0x26;
|
||||
val &= ~0x20;
|
||||
else
|
||||
val &= ~0x06;
|
||||
val &= ~0x00;
|
||||
|
||||
//ZERO 01-dec-2010 : I am no longer sure this approach is correct.. it proved to be wrong for IPC fifo.......
|
||||
//it seems as if IF bits should always be cached (only the user can clear them)
|
||||
|
||||
MMU.reg_IF_bits[PROCNUM] &= (~(((u32)val)<<(addr<<3)));
|
||||
NDS_Reschedule();
|
||||
|
@ -1267,16 +1270,6 @@ u32 MMU_struct::gen_IF()
|
|||
}
|
||||
}
|
||||
|
||||
//generate IPC IF states from the ipc registers
|
||||
u16 ipc = T1ReadWord(MMU.MMU_MEM[PROCNUM][0x40], 0x184);
|
||||
if(ipc&IPCFIFOCNT_FIFOENABLE)
|
||||
{
|
||||
if(ipc&IPCFIFOCNT_SENDIRQEN) if(ipc&IPCFIFOCNT_SENDEMPTY)
|
||||
IF |= IRQ_MASK_IPCFIFO_SENDEMPTY;
|
||||
if(ipc&IPCFIFOCNT_RECVIRQEN) if(!(ipc&IPCFIFOCNT_RECVEMPTY))
|
||||
IF |= IRQ_MASK_IPCFIFO_RECVNONEMPTY;
|
||||
}
|
||||
|
||||
return IF;
|
||||
}
|
||||
|
||||
|
@ -1435,6 +1428,10 @@ static INLINE void MMU_IPCSync(u8 proc, u32 val)
|
|||
|
||||
if ((sync_l & 0x2000) && (sync_r & 0x4000))
|
||||
setIF(proc^1, ( 1 << 16 ));
|
||||
|
||||
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
static INLINE u16 read_timer(int proc, int timerIndex)
|
||||
|
@ -2643,13 +2640,13 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
|
|||
case REG_IF: REG_IF_WriteWord<ARMCPU_ARM9>(0,val); return;
|
||||
case REG_IF+2: REG_IF_WriteWord<ARMCPU_ARM9>(2,val); return;
|
||||
|
||||
case REG_IPCSYNC :
|
||||
MMU_IPCSync(ARMCPU_ARM9, val);
|
||||
case REG_IPCSYNC:
|
||||
MMU_IPCSync(ARMCPU_ARM9, val);
|
||||
return;
|
||||
case REG_IPCFIFOCNT:
|
||||
IPC_FIFOcnt(ARMCPU_ARM9, val);
|
||||
return;
|
||||
|
||||
case REG_IPCFIFOCNT :
|
||||
IPC_FIFOcnt(ARMCPU_ARM9, val);
|
||||
return;
|
||||
case REG_TM0CNTL :
|
||||
case REG_TM1CNTL :
|
||||
case REG_TM2CNTL :
|
||||
|
@ -3094,17 +3091,18 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
|
|||
return;
|
||||
}
|
||||
case REG_SQRTPARAM+4 :
|
||||
{
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2BC, val);
|
||||
execsqrt();
|
||||
return;
|
||||
}
|
||||
case REG_IPCSYNC :
|
||||
MMU_IPCSync(ARMCPU_ARM9, val);
|
||||
|
||||
case REG_IPCSYNC:
|
||||
MMU_IPCSync(ARMCPU_ARM9, val);
|
||||
return;
|
||||
|
||||
case REG_IPCFIFOSEND :
|
||||
IPC_FIFOsend(ARMCPU_ARM9, val);
|
||||
case REG_IPCFIFOCNT:
|
||||
IPC_FIFOcnt(ARMCPU_ARM9, val);
|
||||
return;
|
||||
case REG_IPCFIFOSEND:
|
||||
IPC_FIFOsend(ARMCPU_ARM9, val);
|
||||
return;
|
||||
|
||||
|
||||
|
@ -3840,13 +3838,13 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
|
|||
case REG_IF: REG_IF_WriteWord<ARMCPU_ARM7>(0,val); return;
|
||||
case REG_IF+2: REG_IF_WriteWord<ARMCPU_ARM7>(2,val); return;
|
||||
|
||||
case REG_IPCSYNC :
|
||||
case REG_IPCSYNC:
|
||||
MMU_IPCSync(ARMCPU_ARM7, val);
|
||||
return;
|
||||
|
||||
case REG_IPCFIFOCNT :
|
||||
case REG_IPCFIFOCNT:
|
||||
IPC_FIFOcnt(ARMCPU_ARM7, val);
|
||||
return;
|
||||
|
||||
case REG_TM0CNTL :
|
||||
case REG_TM1CNTL :
|
||||
case REG_TM2CNTL :
|
||||
|
@ -3941,12 +3939,14 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
|
|||
}
|
||||
|
||||
|
||||
case REG_IPCSYNC :
|
||||
MMU_IPCSync(ARMCPU_ARM7, val);
|
||||
case REG_IPCSYNC:
|
||||
MMU_IPCSync(ARMCPU_ARM7, val);
|
||||
return;
|
||||
|
||||
case REG_IPCFIFOSEND :
|
||||
IPC_FIFOsend(ARMCPU_ARM7, val);
|
||||
case REG_IPCFIFOCNT:
|
||||
IPC_FIFOcnt(ARMCPU_ARM7, val);
|
||||
return;
|
||||
case REG_IPCFIFOSEND:
|
||||
IPC_FIFOsend(ARMCPU_ARM7, val);
|
||||
return;
|
||||
|
||||
case REG_GCROMCTRL :
|
||||
|
|
|
@ -260,7 +260,7 @@ extern armcpu_t NDS_ARM9;
|
|||
static INLINE void setIF(int PROCNUM, u32 flag)
|
||||
{
|
||||
//don't set generated bits!!!
|
||||
assert(!(flag&0x00260000));
|
||||
assert(!(flag&0x00200000));
|
||||
|
||||
MMU.reg_IF_bits[PROCNUM] |= flag;
|
||||
|
||||
|
|
|
@ -358,6 +358,9 @@
|
|||
#define IPCFIFOCNT_FIFOENABLE 0x8000
|
||||
#define IPCFIFOCNT_WRITEABLE (IPCFIFOCNT_SENDIRQEN | IPCFIFOCNT_RECVIRQEN | IPCFIFOCNT_FIFOENABLE)
|
||||
|
||||
#define IPCSYNC_IRQ_SEND 0x2000
|
||||
#define IPCSYNC_IRQ_RECV 0x4000
|
||||
|
||||
#define IRQ_BIT_LCD_VBLANK 0
|
||||
#define IRQ_BIT_LCD_HBLANK 1
|
||||
#define IRQ_BIT_LCD_VMATCH 2
|
||||
|
|
|
@ -448,8 +448,8 @@ static bool mmu_loadstate(EMUFILE* is, int size)
|
|||
ok &= MMU_new.div.loadstate(is,version);
|
||||
|
||||
//to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated
|
||||
MMU.reg_IF_bits[0] &= ~0x00260000;
|
||||
MMU.reg_IF_bits[1] &= ~0x00060000;
|
||||
MMU.reg_IF_bits[0] &= ~0x00200000;
|
||||
MMU.reg_IF_bits[1] &= ~0x00000000;
|
||||
|
||||
MMU_new.gxstat.fifo_low = gxFIFO.size <= 127;
|
||||
MMU_new.gxstat.fifo_empty = gxFIFO.size == 0;
|
||||
|
|
Loading…
Reference in New Issue