diff --git a/DotN64/DotN64.csproj b/DotN64/DotN64.csproj
index 884235f..0b62a3a 100644
--- a/DotN64/DotN64.csproj
+++ b/DotN64/DotN64.csproj
@@ -103,6 +103,7 @@
+
@@ -124,5 +125,10 @@
+
+
+ PreserveNewest
+
+
\ No newline at end of file
diff --git a/DotN64/DotN64.dll.config b/DotN64/DotN64.dll.config
new file mode 100644
index 0000000..5473619
--- /dev/null
+++ b/DotN64/DotN64.dll.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.Angrylion.cs b/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.Angrylion.cs
new file mode 100644
index 0000000..30379ff
--- /dev/null
+++ b/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.Angrylion.cs
@@ -0,0 +1,25 @@
+using System.Runtime.InteropServices;
+
+namespace DotN64.RCP
+{
+ public partial class RealityCoprocessor
+ {
+ public partial class DisplayProcessor
+ {
+ public static class Angrylion
+ {
+ #region Fields
+ private const string LibraryName = "n64video.dll";
+ #endregion
+
+ #region Methods
+ [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void angrylion_rdp_init();
+
+ [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe uint rdp_process_list(uint* dp_start, uint* dp_current, uint* dp_end, uint* dp_status, uint* rsp_dmem, uint* rdram, out uint crashed);
+ #endregion
+ }
+ }
+ }
+}
diff --git a/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.cs b/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.cs
index c767a78..61e22b8 100644
--- a/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.cs
+++ b/DotN64/RCP/DP/RealityCoprocessor.DisplayProcessor.cs
@@ -2,6 +2,8 @@
namespace DotN64.RCP
{
+ using static RealityCoprocessor.DisplayProcessor.Angrylion;
+
public partial class RealityCoprocessor
{
public partial class DisplayProcessor
@@ -13,7 +15,46 @@ namespace DotN64.RCP
#region Properties
public IReadOnlyList MemoryMaps { get; }
- public Statuses Status { get; set; }
+ private uint status;
+ public Statuses Status
+ {
+ get => (Statuses)status;
+ set => status = (uint)value;
+ }
+
+ private uint startAddress;
+ ///
+ /// DMEM/RDRAM start address.
+ ///
+ public uint StartAddress
+ {
+ get => startAddress;
+ set => startAddress = currentAddress = value;
+ }
+
+ private uint currentAddress;
+ ///
+ /// DMEM/RDRAM current address.
+ ///
+ public uint CurrentAddress
+ {
+ get => currentAddress;
+ set => currentAddress = value;
+ }
+
+ private uint endAddress;
+ ///
+ /// DMEM/RDRAM end address.
+ ///
+ public uint EndAddress
+ {
+ get => endAddress;
+ set
+ {
+ endAddress = value;
+ ProcessCommands();
+ }
+ }
#endregion
#region Constructors
@@ -22,11 +63,39 @@ namespace DotN64.RCP
this.rcp = rcp;
MemoryMaps = new[]
{
+ new MappingEntry(0x04100000, 0x04100003) // DP CMD DMA start.
+ {
+ Write = (o, d) => StartAddress = d & ((1 << 24) - 1)
+ },
+ new MappingEntry(0x04100004, 0x04100007) // DP CMD DMA end.
+ {
+ Write = (o, d) => EndAddress = d & ((1 << 24) - 1)
+ },
new MappingEntry(0x0410000C, 0x0410000F) // DP CMD status.
{
Read = o => (uint)Status
}
};
+
+ angrylion_rdp_init();
+ }
+ #endregion
+
+ #region Methods
+ private unsafe void ProcessCommands()
+ {
+ fixed (byte* dmem = &rcp.SP.DMEM[0])
+ fixed (byte* rdram = &rcp.nintendo64.RAM.Memory[0])
+ fixed (uint* startAddressPtr = &startAddress)
+ fixed (uint* currentAddressPtr = ¤tAddress)
+ fixed (uint* endAddressPtr = &endAddress)
+ fixed (uint* statusPtr = &status)
+ {
+ var fullSynced = rdp_process_list(startAddressPtr, currentAddressPtr, endAddressPtr, statusPtr, (uint*)dmem, (uint*)rdram, out var crashed);
+
+ if (fullSynced != 0)
+ rcp.MI.Interrupt |= MIPSInterface.Interrupts.DP;
+ }
}
#endregion
}