diff --git a/FIFO.cpp b/FIFO.cpp
new file mode 100644
index 00000000..e8525eb3
--- /dev/null
+++ b/FIFO.cpp
@@ -0,0 +1,72 @@
+/*
+ Copyright 2016-2017 StapleButter
+
+ This file is part of melonDS.
+
+ melonDS is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include "FIFO.h"
+
+
+FIFO::FIFO(u32 num)
+{
+ NumEntries = num;
+ Entries = new u32[num];
+ Clear();
+}
+
+FIFO::~FIFO()
+{
+ delete[] Entries;
+}
+
+void FIFO::Clear()
+{
+ NumOccupied = 0;
+ ReadPos = 0;
+ WritePos = 0;
+ Entries[ReadPos] = 0;
+}
+
+void FIFO::Write(u32 val)
+{
+ if (IsFull()) return;
+
+ Entries[WritePos] = val;
+
+ WritePos++;
+ if (WritePos >= NumEntries)
+ WritePos = 0;
+
+ NumOccupied++;
+}
+
+u32 FIFO::Read()
+{
+ u32 ret = Entries[ReadPos];
+ if (IsEmpty())
+ return ret;
+
+ ReadPos++;
+ if (ReadPos >= NumEntries)
+ ReadPos = 0;
+
+ NumOccupied--;
+ return ret;
+}
+
+u32 FIFO::Peek()
+{
+ return Entries[ReadPos];
+}
diff --git a/FIFO.h b/FIFO.h
new file mode 100644
index 00000000..98f00793
--- /dev/null
+++ b/FIFO.h
@@ -0,0 +1,47 @@
+/*
+ Copyright 2016-2017 StapleButter
+
+ This file is part of melonDS.
+
+ melonDS is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef FIFO_H
+#define FIFO_H
+
+#include "types.h"
+
+class FIFO
+{
+public:
+ FIFO(u32 num);
+ ~FIFO();
+
+ void Clear();
+
+ void Write(u32 val);
+ u32 Read();
+ u32 Peek();
+
+ u32 Level() { return NumOccupied; }
+ bool IsEmpty() { return NumOccupied == 0; }
+ bool IsFull() { return NumOccupied >= NumEntries; }
+
+private:
+ u32 NumEntries;
+ u32* Entries;
+ u32 NumOccupied;
+ u32 ReadPos, WritePos;
+};
+
+#endif
diff --git a/NDS.cpp b/NDS.cpp
index 5c0ff954..067b2d82 100644
--- a/NDS.cpp
+++ b/NDS.cpp
@@ -21,6 +21,7 @@
#include "NDS.h"
#include "ARM.h"
#include "CP15.h"
+#include "FIFO.h"
#include "GPU2D.h"
#include "SPI.h"
#include "Wifi.h"
@@ -35,6 +36,9 @@ namespace SPI_Firmware
namespace NDS
{
+// TODO: stick all the variables in a big structure?
+// would make it easier to deal with savestates
+
SchedEvent SchedBuffer[SCHED_BUF_LEN];
SchedEvent* SchedQueue;
@@ -76,6 +80,9 @@ u16 PowerControl7;
Timer Timers[8];
u16 IPCSync9, IPCSync7;
+u16 IPCFIFOCnt9, IPCFIFOCnt7;
+FIFO* IPCFIFO9; // FIFO in which the ARM9 writes
+FIFO* IPCFIFO7;
u32 ROMSPIControl;
u32 ROMControl;
@@ -95,6 +102,9 @@ void Init()
ARM9 = new ARM(0);
ARM7 = new ARM(1);
+ IPCFIFO9 = new FIFO(16);
+ IPCFIFO7 = new FIFO(16);
+
SPI::Init();
Reset();
@@ -191,6 +201,10 @@ void Reset()
IPCSync9 = 0;
IPCSync7 = 0;
+ IPCFIFOCnt9 = 0;
+ IPCFIFOCnt7 = 0;
+ IPCFIFO9->Clear();
+ IPCFIFO7->Clear();
ROMSPIControl = 0;
ROMControl = 0;
@@ -726,6 +740,15 @@ u16 ARM9Read16(u32 addr)
case 0x04000130: return KeyInput & 0xFFFF;
case 0x04000180: return IPCSync9;
+ case 0x04000184:
+ {
+ u16 val = IPCFIFOCnt9;
+ if (IPCFIFO9->IsEmpty()) val |= 0x0001;
+ else if (IPCFIFO9->IsFull()) val |= 0x0002;
+ if (IPCFIFO7->IsEmpty()) val |= 0x0100;
+ else if (IPCFIFO7->IsFull()) val |= 0x0200;
+ return val;
+ }
case 0x04000204: return 0;//0xFFFF;
@@ -815,6 +838,27 @@ u32 ARM9Read32(u32 addr)
case 0x04000208: return IME[0];
case 0x04000210: return IE[0];
case 0x04000214: return IF[0];
+
+ case 0x04100000:
+ if (IPCFIFOCnt9 & 0x8000)
+ {
+ u32 ret;
+ if (IPCFIFO7->IsEmpty())
+ {
+ IPCFIFOCnt9 |= 0x4000;
+ ret = IPCFIFO7->Peek();
+ }
+ else
+ {
+ ret = IPCFIFO7->Read();
+
+ if (IPCFIFO7->IsEmpty() && (IPCFIFOCnt7 & 0x0004))
+ TriggerIRQ(1, IRQ_IPCSendDone);
+ }
+ return ret;
+ }
+ else
+ return IPCFIFO7->Peek();
}
printf("unknown arm9 IO read32 %08X | %08X %08X %08X\n", addr, ARM9->R[15], ARM9->R[12], ARM9Read32(0x027FF820));
@@ -955,6 +999,18 @@ void ARM9Write16(u32 addr, u16 val)
CompensateARM7();
return;
+ case 0x04000184:
+ if (val & 0x0008)
+ IPCFIFO9->Clear();
+ if ((val & 0x0004) && (!(IPCFIFOCnt9 & 0x0004)) && IPCFIFO9->IsEmpty())
+ TriggerIRQ(0, IRQ_IPCSendDone);
+ if ((val & 0x0400) && (!(IPCFIFOCnt9 & 0x0400)) && (!IPCFIFO7->IsEmpty()))
+ TriggerIRQ(0, IRQ_IPCRecv);
+ if (val & 0x4000)
+ IPCFIFOCnt9 &= ~0x4000;
+ IPCFIFOCnt9 = val & 0x8404;
+ return;
+
case 0x040001A0:
ROMSPIControl = val;
return;
@@ -1061,6 +1117,20 @@ void ARM9Write32(u32 addr, u32 val)
TimerStart(3, val>>16);
return;
+ case 0x04000188:
+ if (IPCFIFOCnt9 & 0x8000)
+ {
+ if (IPCFIFO9->IsFull())
+ IPCFIFOCnt9 |= 0x4000;
+ else
+ {
+ IPCFIFO9->Write(val);
+ if (IPCFIFOCnt7 & 0x0400)
+ TriggerIRQ(1, IRQ_IPCRecv);
+ }
+ }
+ return;
+
case 0x040001A0:
ROMSPIControl = val & 0xFFFF;
// TODO: SPI shit
@@ -1160,6 +1230,10 @@ u8 ARM7Read8(u32 addr)
case 0x04000300:
printf("ARM7 POSTFLG READ @ %08X\n", ARM7->R[15]);
return 0;
+
+ case 0x04000403:
+ Halt();
+ return 0;
}
printf("unknown arm7 IO read8 %08X\n", addr);
return 0;
@@ -1221,6 +1295,15 @@ u16 ARM7Read16(u32 addr)
case 0x04000138: return 0; // RTC shit
case 0x04000180: return IPCSync7;
+ case 0x04000184:
+ {
+ u16 val = IPCFIFOCnt7;
+ if (IPCFIFO7->IsEmpty()) val |= 0x0001;
+ else if (IPCFIFO7->IsFull()) val |= 0x0002;
+ if (IPCFIFO9->IsEmpty()) val |= 0x0100;
+ else if (IPCFIFO9->IsFull()) val |= 0x0200;
+ return val;
+ }
case 0x040001C0: return SPI::ReadCnt();
case 0x040001C2: return SPI::ReadData();
@@ -1298,6 +1381,27 @@ u32 ARM7Read32(u32 addr)
case 0x04000210: return IE[1];
case 0x04000214: return IF[1];
+ case 0x04100000:
+ if (IPCFIFOCnt7 & 0x8000)
+ {
+ u32 ret;
+ if (IPCFIFO9->IsEmpty())
+ {
+ IPCFIFOCnt7 |= 0x4000;
+ ret = IPCFIFO9->Peek();
+ }
+ else
+ {
+ ret = IPCFIFO9->Read();
+
+ if (IPCFIFO9->IsEmpty() && (IPCFIFOCnt9 & 0x0004))
+ TriggerIRQ(0, IRQ_IPCSendDone);
+ }
+ return ret;
+ }
+ else
+ return IPCFIFO9->Peek();
+
case 0x04100010: return ROMReadData(1);
}
@@ -1458,6 +1562,18 @@ void ARM7Write16(u32 addr, u16 val)
}
return;
+ case 0x04000184:
+ if (val & 0x0008)
+ IPCFIFO7->Clear();
+ if ((val & 0x0004) && (!(IPCFIFOCnt7 & 0x0004)) && IPCFIFO7->IsEmpty())
+ TriggerIRQ(1, IRQ_IPCSendDone);
+ if ((val & 0x0400) && (!(IPCFIFOCnt7 & 0x0400)) && (!IPCFIFO9->IsEmpty()))
+ TriggerIRQ(1, IRQ_IPCRecv);
+ if (val & 0x4000)
+ IPCFIFOCnt7 &= ~0x4000;
+ IPCFIFOCnt7 = val & 0x8404;
+ return;
+
case 0x040001A0:
ROMSPIControl = val;
return;
@@ -1540,6 +1656,20 @@ void ARM7Write32(u32 addr, u32 val)
TimerStart(7, val>>16);
return;
+ case 0x04000188:
+ if (IPCFIFOCnt7 & 0x8000)
+ {
+ if (IPCFIFO7->IsFull())
+ IPCFIFOCnt7 |= 0x4000;
+ else
+ {
+ IPCFIFO7->Write(val);
+ if (IPCFIFOCnt9 & 0x0400)
+ TriggerIRQ(0, IRQ_IPCRecv);
+ }
+ }
+ return;
+
case 0x040001A0:
ROMSPIControl = val & 0xFFFF;
// TODO: SPI shit
diff --git a/melonDS.cbp b/melonDS.cbp
index 76e79d6e..744fbeb1 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -48,6 +48,8 @@
+
+
diff --git a/melonDS.depend b/melonDS.depend
index 020632ed..0b7efd2e 100644
--- a/melonDS.depend
+++ b/melonDS.depend
@@ -10,12 +10,13 @@
1481161027 c:\documents\sources\melonds\types.h
-1484538142 source:c:\documents\sources\melonds\nds.cpp
+1484614470 source:c:\documents\sources\melonds\nds.cpp
"NDS.h"
"ARM.h"
"CP15.h"
+ "FIFO.h"
"GPU2D.h"
"SPI.h"
"Wifi.h"
@@ -95,3 +96,9 @@
"NDS.h"
"Wifi.h"
+1484613078 source:c:\documents\sources\melonds\fifo.cpp
+ "FIFO.h"
+
+1484612398 c:\documents\sources\melonds\fifo.h
+ "types.h"
+