fix some ipc fifo bugs (fixes Defc0n-Zero demo and some recent libnds fifosystem changes)

This commit is contained in:
zeromus 2010-12-01 08:08:52 +00:00
parent fde699f8d9
commit be8b6906c8
5 changed files with 63 additions and 45 deletions

View File

@ -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();
}
@ -100,11 +102,13 @@ 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_r &= ~IPCFIFOCNT_RECVFULL;
}
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);

View File

@ -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 :
case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM9, val);
return;
case REG_IPCFIFOCNT :
case REG_IPCFIFOCNT:
IPC_FIFOcnt(ARMCPU_ARM9, val);
return;
case REG_TM0CNTL :
case REG_TM1CNTL :
case REG_TM2CNTL :
@ -3094,16 +3091,17 @@ 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 :
case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM9, val);
return;
case REG_IPCFIFOSEND :
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,11 +3939,13 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
}
case REG_IPCSYNC :
case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM7, val);
return;
case REG_IPCFIFOSEND :
case REG_IPCFIFOCNT:
IPC_FIFOcnt(ARMCPU_ARM7, val);
return;
case REG_IPCFIFOSEND:
IPC_FIFOsend(ARMCPU_ARM7, val);
return;

View File

@ -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;

View File

@ -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

View File

@ -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;