void IPC_FIFOsend(u8 proc, u32 val) { //LOG("IPC%s send FIFO 0x%08X\n", proc?"7":"9", val); u16 cnt_l,cnt_r; cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); if (!(cnt_l & 0x8000)) return; // FIFO disabled cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184); if (ipc_fifo.sendTail[proc] < 16) // last full == error { ipc_fifo.sendBuf[proc][ipc_fifo.sendTail[proc]] = val; ipc_fifo.sendTail[proc]++; if (ipc_fifo.sendTail[proc] == 16) cnt_l |= 0x02; // full cnt_l &= 0xFFFE; if (ipc_fifo.recvTail[proc^1] < 16) // last full == error { ipc_fifo.recvBuf[proc^1][ipc_fifo.recvTail[proc^1]] = val; ipc_fifo.recvTail[proc^1]++; if (ipc_fifo.recvTail[proc^1] == 16) cnt_r |= 0x0200; // full cnt_r &= 0xFEFF; } else cnt_r |= 0x4200; } else cnt_l |= 0x4002; // save in mem T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r); if ((cnt_r & (1<<10))) NDS_makeInt(proc^1, 18); }
u32 IPC_FIFOrecv(u8 proc) { //LOG("IPC%s recv FIFO:\n", proc?"7":"9"); int i; u32 val = 0; u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184); if (ipc_fifo.recvTail[proc] > 0) // not empty { val = ipc_fifo.recvBuf[proc][0]; for (i = 0; i < ipc_fifo.recvTail[proc]; i++) ipc_fifo.recvBuf[proc][i] = ipc_fifo.recvBuf[proc][i+1]; ipc_fifo.recvTail[proc]--; if (ipc_fifo.recvTail[proc] == 0) // empty cnt_l |= 0x0100; // remove from head for (i = 0; i < ipc_fifo.sendTail[proc^1]; i++) ipc_fifo.sendBuf[proc^1][i] = ipc_fifo.sendBuf[proc^1][i+1]; ipc_fifo.sendTail[proc^1]--; if (ipc_fifo.sendTail[proc^1] == 0) // empty cnt_r |= 0x0001; } else cnt_l |= 0x4100; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r); if ((cnt_l & (1<<3))) NDS_makeInt(proc, 19); return (val); }
void IPC_FIFOcnt(u8 proc, u16 val) { u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184); if (val & IPCFIFOCNT_FIFOERROR) { //at least SPP uses this, maybe every retail game cnt_l &= ~IPCFIFOCNT_FIFOERROR; } if (val & IPCFIFOCNT_SENDCLEAR) { 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_WRITEABLE; cnt_l |= val & IPCFIFOCNT_WRITEABLE; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r); NDS_Reschedule(); }
u32 IPC_FIFOrecv(u8 proc) { u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return (0); // FIFO disabled u8 proc_remote = proc ^ 1; u32 val = 0; if ( ipc_fifo[proc_remote].size == 0 ) // remote FIFO error { cnt_l |= IPCFIFOCNT_FIFOERROR; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); return (0); } u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184); cnt_l &= 0xBCFF; // clear send full bit & empty cnt_r &= 0xBFFC; // set recv full bit & empty val = ipc_fifo[proc_remote].buf[ipc_fifo[proc_remote].head]; ipc_fifo[proc_remote].head++; ipc_fifo[proc_remote].size--; if (ipc_fifo[proc_remote].head > 15) ipc_fifo[proc_remote].head = 0; //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 |= IPCFIFOCNT_RECVEMPTY; cnt_r |= IPCFIFOCNT_SENDEMPTY; if(cnt_r&IPCFIFOCNT_SENDIRQEN) NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY); } T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r); NDS_Reschedule(); return (val); }
static void ExpMemory_write16(u32 procnum, u32 adr, u16 val) { if (adr >= 0x09000000) { u32 offs = (adr - 0x09000000); if (offs >= expMemSize) return; T1WriteWord(expMemory, offs, val); } EXPINFO("ExpMemory: write 16 at 0x%08X = 0x%04X\n", adr, val); }
u32 IPC_FIFOrecv(u8 proc) { u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); if (!(cnt_l & 0x8000)) return (0); // FIFO disabled u8 proc_remote = proc ^ 1; u32 val = 0; if ( ipc_fifo[proc_remote].size == 0 ) // remote FIFO error { cnt_l |= 0x4000; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); return (0); } u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184); cnt_l &= 0xBCFF; // clear send full bit & empty cnt_r &= 0xBFFC; // set recv full bit & empty val = ipc_fifo[proc_remote].buf[ipc_fifo[proc_remote].head]; ipc_fifo[proc_remote].head++; ipc_fifo[proc_remote].size--; if (ipc_fifo[proc_remote].head > 15) ipc_fifo[proc_remote].head = 0; //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_r |= 0x0001; } T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r); NDS_Reschedule(); return (val); }
void FASTCALL Vdp1FrameBufferWriteWord(u32 addr, u16 val) { addr &= 0x3FFFF; if (VIDCore->Vdp1WriteFrameBuffer) { VIDCore->Vdp1WriteFrameBuffer(1, addr, val); return; } T1WriteWord(Vdp1FrameBuffer, addr, val); }
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); if (val & IPCFIFOCNT_FIFOERROR) { //at least SPP uses this, maybe every retail game cnt_l &= ~IPCFIFOCNT_FIFOERROR; } if (val & IPCFIFOCNT_SENDCLEAR) { ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0; cnt_l |= IPCFIFOCNT_SENDEMPTY; 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); NDS_Reschedule(); }
void IPC_FIFOsend(u8 proc, u32 val) { u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return; // FIFO disabled u8 proc_remote = proc ^ 1; if (ipc_fifo[proc].size > 15) { cnt_l |= IPCFIFOCNT_FIFOERROR; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); return; } u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184); //LOG("IPC%s send 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); cnt_l &= 0xBFFC; // clear send empty bit & full cnt_r &= 0xBCFF; // set recv empty bit & full ipc_fifo[proc].buf[ipc_fifo[proc].tail] = val; ipc_fifo[proc].tail++; ipc_fifo[proc].size++; if (ipc_fifo[proc].tail > 15) ipc_fifo[proc].tail = 0; if (ipc_fifo[proc].size > 15) { cnt_l |= IPCFIFOCNT_SENDFULL; // set send full bit cnt_r |= IPCFIFOCNT_RECVFULL; // set recv full bit } 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(); }
void IPC_FIFOsend(u8 proc, u32 val) { u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); if (!(cnt_l & 0x8000)) return; // FIFO disabled u8 proc_remote = proc ^ 1; if (ipc_fifo[proc].size > 15) { cnt_l |= 0x4000; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); return; } u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184); //LOG("IPC%s send 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); cnt_l &= 0xBFFC; // clear send empty bit & full cnt_r &= 0xBCFF; // set recv empty bit & full ipc_fifo[proc].buf[ipc_fifo[proc].tail] = val; ipc_fifo[proc].tail++; ipc_fifo[proc].size++; if (ipc_fifo[proc].tail > 15) ipc_fifo[proc].tail = 0; if (ipc_fifo[proc].size > 15) { cnt_l |= 0x0002; // set send full bit cnt_r |= 0x0200; // set recv full bit } T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r); NDS_Reschedule(); }
void IPC_FIFOcnt(u8 proc, u16 val) { //LOG("IPC%s FIFO context 0x%X\n", proc?"7":"9", val); u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); cnt_l &= ~0x8404; cnt_l |= (val & 0x8404); cnt_l &= (~(val & 0x4000)); if (val & 0x0008) { IPC_FIFOclear(); cnt_l |= 0x0101; } T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); if ((cnt_l & 0x0004)) NDS_makeInt(proc, 18); }
void FASTCALL Vdp1RamWriteWord(u32 addr, u16 val) { addr &= 0x7FFFF; T1WriteWord(Vdp1Ram, addr, val); }
void IPC_FIFOinit(u8 proc) { memset(&ipc_fifo[proc], 0, sizeof(IPC_FIFO)); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, 0x00000101); }