Moved members in their respective place.
parent
c323daf588
commit
66e5efff59
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DotN64
|
||||
{
|
||||
|
@ -9,9 +8,13 @@ namespace DotN64
|
|||
public class Nintendo64
|
||||
{
|
||||
#region Properties
|
||||
public IReadOnlyList<MappingEntry> MemoryMaps { get; }
|
||||
|
||||
public VR4300 CPU { get; }
|
||||
|
||||
public RealityCoprocessor RCP { get; } = new RealityCoprocessor();
|
||||
public RealityCoprocessor RCP { get; }
|
||||
|
||||
public byte[] RAM { get; } = new byte[0x00400000]; // The base system has 4 MB of RAM installed.
|
||||
|
||||
public Cartridge Cartridge { get; set; }
|
||||
#endregion
|
||||
|
@ -19,7 +22,8 @@ namespace DotN64
|
|||
#region Constructors
|
||||
public Nintendo64()
|
||||
{
|
||||
var memoryMaps = new[]
|
||||
RCP = new RealityCoprocessor(this);
|
||||
MemoryMaps = new[]
|
||||
{
|
||||
new MappingEntry(0x1FC00000, 0x1FC007BF, false) // PIF Boot ROM.
|
||||
{
|
||||
|
@ -61,9 +65,9 @@ namespace DotN64
|
|||
Read = RCP.SI.ReadWord,
|
||||
Write = RCP.SI.WriteWord
|
||||
},
|
||||
new MappingEntry(0x10000000, 0x1FBFFFFF) // Cartridge Domain 1 Address 2.
|
||||
new MappingEntry(0x10000000, 0x1FBFFFFF, false) // Cartridge Domain 1 Address 2.
|
||||
{
|
||||
Read = o => (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(Cartridge.ROM, (int)o))
|
||||
Read = RCP.PI.ReadWord
|
||||
},
|
||||
new MappingEntry(0x04100000, 0x041FFFFF, false) // DP command registers.
|
||||
{
|
||||
|
@ -81,7 +85,7 @@ namespace DotN64
|
|||
Write = RCP.RI.WriteWord
|
||||
}
|
||||
};
|
||||
CPU = new VR4300(memoryMaps)
|
||||
CPU = new VR4300(MemoryMaps)
|
||||
{
|
||||
DivMode = 0b01 // Assuming this value as the CPU is clocked at 93.75 MHz, and the RCP would be clocked at 93.75 / 3 * 2 = 62.5 MHz.
|
||||
};
|
||||
|
@ -89,71 +93,12 @@ namespace DotN64
|
|||
#endregion
|
||||
|
||||
#region Methods
|
||||
private void EmulatePIFBootROM()
|
||||
{
|
||||
// Replicating the memory writes to properly initialise the subsystems.
|
||||
var writes = new uint[,]
|
||||
{
|
||||
{ 0x4040010, 0xA },
|
||||
{ 0x4600010, 0x3 },
|
||||
{ 0x440000C, 0x3FF },
|
||||
{ 0x4400024, 0x0 },
|
||||
{ 0x4400010, 0x0 },
|
||||
{ 0x4500000, 0x0 },
|
||||
{ 0x4500004, 0x0 },
|
||||
{ 0x4600014, 0x40 }, // These four are likely cartridge-specific (PI domain 1 values).
|
||||
{ 0x4600018, 0xFF803712 },
|
||||
{ 0x460001C, 0xFFFF8037 },
|
||||
{ 0x4600020, 0xFFFFF803 },
|
||||
// Omitted the CIC result.
|
||||
{ 0x1FC007FC, 0xC0 }
|
||||
};
|
||||
|
||||
for (int i = 0; i < writes.GetLength(0); i++)
|
||||
{
|
||||
var address = writes[i, 0] + 0xFFFFFFFFA0000000; // The constant converts them back to virtual addresses.
|
||||
|
||||
CPU.CP0.Map(ref address).WriteWord(address, writes[i, 1]);
|
||||
}
|
||||
|
||||
for (int i = 0x40; i < 0x1000; i += sizeof(uint)) // Copying the bootstrap code from the cartridge to the RSP's DMEM.
|
||||
{
|
||||
var dmemAddress = 0xFFFFFFFFA4000000 + (uint)i;
|
||||
|
||||
CPU.CP0.Map(ref dmemAddress).WriteWord(dmemAddress, (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(Cartridge.ROM, i)));
|
||||
}
|
||||
|
||||
// Restoring CPU state.
|
||||
CPU.CP0.Registers[12] = 0x34000000;
|
||||
CPU.CP0.Registers[16] = 0x6E463;
|
||||
CPU.GPR[1] = 0x1;
|
||||
CPU.GPR[2] = 0x6459969A;
|
||||
CPU.GPR[3] = 0x6459969A;
|
||||
// Omitted the CIC result.
|
||||
CPU.GPR[6] = 0xFFFFFFFFA4001F0C;
|
||||
CPU.GPR[7] = 0xFFFFFFFFA4001F08;
|
||||
CPU.GPR[8] = 0xC0;
|
||||
CPU.GPR[10] = 0x40;
|
||||
CPU.GPR[11] = 0xFFFFFFFFA4000040;
|
||||
CPU.GPR[12] = 0xFFFFFFFFD19AE574;
|
||||
CPU.GPR[13] = 0x4A459BAE;
|
||||
CPU.GPR[14] = 0xFFFFFFFFE8EAD626;
|
||||
CPU.GPR[15] = 0x6459969A;
|
||||
CPU.GPR[20] = 0x1;
|
||||
CPU.GPR[25] = 0x453CA37B;
|
||||
CPU.GPR[29] = 0xFFFFFFFFA4001FF0;
|
||||
CPU.GPR[31] = 0xFFFFFFFFA4001550;
|
||||
CPU.HI = 0x6459969A;
|
||||
CPU.LO = 0x6459969A;
|
||||
CPU.PC = 0xFFFFFFFFA4000040;
|
||||
}
|
||||
|
||||
public void PowerOn()
|
||||
{
|
||||
CPU.Reset();
|
||||
|
||||
if (RCP.PI.BootROM == null)
|
||||
EmulatePIFBootROM();
|
||||
RCP.PI.EmulateBootROM();
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace DotN64.RCP
|
|||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public AudioInterface()
|
||||
public AudioInterface(RealityCoprocessor rcp)
|
||||
: base(rcp)
|
||||
{
|
||||
memoryMaps = new[]
|
||||
{
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace DotN64.RCP
|
|||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public MIPSInterface()
|
||||
public MIPSInterface(RealityCoprocessor rcp)
|
||||
: base(rcp)
|
||||
{
|
||||
memoryMaps = new[]
|
||||
{
|
||||
|
|
|
@ -4,6 +4,8 @@ using System.Net;
|
|||
|
||||
namespace DotN64.RCP
|
||||
{
|
||||
using Extensions;
|
||||
|
||||
public partial class RealityCoprocessor
|
||||
{
|
||||
public partial class PeripheralInterface : Interface
|
||||
|
@ -47,7 +49,8 @@ namespace DotN64.RCP
|
|||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public PeripheralInterface()
|
||||
public PeripheralInterface(RealityCoprocessor rcp)
|
||||
: base(rcp)
|
||||
{
|
||||
memoryMaps = new[]
|
||||
{
|
||||
|
@ -111,6 +114,10 @@ namespace DotN64.RCP
|
|||
new MappingEntry(0x0460000C, 0x0460000F) // PI write length.
|
||||
{
|
||||
Write = (o, v) => WriteLength = v & ((1 << 24) - 1)
|
||||
},
|
||||
new MappingEntry(0x10000000, 0x1FBFFFFF) // Cartridge Domain 1 Address 2.
|
||||
{
|
||||
Read = o => (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(rcp.Nintendo64.Cartridge.ROM, (int)o))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -120,6 +127,65 @@ namespace DotN64.RCP
|
|||
private void ClearInterrupt() { /* TODO: Implement. */ }
|
||||
|
||||
private void ResetController() { /* TODO: Implement. */ }
|
||||
|
||||
public void EmulateBootROM()
|
||||
{
|
||||
// Replicating the memory writes to properly initialise the subsystems.
|
||||
var writes = new uint[,]
|
||||
{
|
||||
{ 0x4040010, 0xA },
|
||||
{ 0x4600010, 0x3 },
|
||||
{ 0x440000C, 0x3FF },
|
||||
{ 0x4400024, 0x0 },
|
||||
{ 0x4400010, 0x0 },
|
||||
{ 0x4500000, 0x0 },
|
||||
{ 0x4500004, 0x0 },
|
||||
{ 0x4600014, 0x40 }, // These four are likely cartridge-specific (PI domain 1 values).
|
||||
{ 0x4600018, 0xFF803712 },
|
||||
{ 0x460001C, 0xFFFF8037 },
|
||||
{ 0x4600020, 0xFFFFF803 },
|
||||
// Omitted the CIC result.
|
||||
{ 0x1FC007FC, 0xC0 }
|
||||
};
|
||||
|
||||
for (int i = 0; i < writes.GetLength(0); i++)
|
||||
{
|
||||
var address = (ulong)writes[i, 0];
|
||||
|
||||
rcp.Nintendo64.MemoryMaps.GetEntry(address).WriteWord(address, writes[i, 1]);
|
||||
}
|
||||
|
||||
for (int i = 0x40; i < 0x1000; i += sizeof(uint)) // Copying the bootstrap code from the cartridge to the RSP's DMEM.
|
||||
{
|
||||
var address = (ulong)(0x04000000 + i);
|
||||
|
||||
rcp.Nintendo64.MemoryMaps.GetEntry(address).WriteWord(address, (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(rcp.Nintendo64.Cartridge.ROM, i)));
|
||||
}
|
||||
|
||||
// Restoring CPU state.
|
||||
rcp.Nintendo64.CPU.CP0.Registers[12] = 0x34000000;
|
||||
rcp.Nintendo64.CPU.CP0.Registers[16] = 0x6E463;
|
||||
rcp.Nintendo64.CPU.GPR[1] = 0x1;
|
||||
rcp.Nintendo64.CPU.GPR[2] = 0x6459969A;
|
||||
rcp.Nintendo64.CPU.GPR[3] = 0x6459969A;
|
||||
// Omitted the CIC result.
|
||||
rcp.Nintendo64.CPU.GPR[6] = 0xFFFFFFFFA4001F0C;
|
||||
rcp.Nintendo64.CPU.GPR[7] = 0xFFFFFFFFA4001F08;
|
||||
rcp.Nintendo64.CPU.GPR[8] = 0xC0;
|
||||
rcp.Nintendo64.CPU.GPR[10] = 0x40;
|
||||
rcp.Nintendo64.CPU.GPR[11] = 0xFFFFFFFFA4000040;
|
||||
rcp.Nintendo64.CPU.GPR[12] = 0xFFFFFFFFD19AE574;
|
||||
rcp.Nintendo64.CPU.GPR[13] = 0x4A459BAE;
|
||||
rcp.Nintendo64.CPU.GPR[14] = 0xFFFFFFFFE8EAD626;
|
||||
rcp.Nintendo64.CPU.GPR[15] = 0x6459969A;
|
||||
rcp.Nintendo64.CPU.GPR[20] = 0x1;
|
||||
rcp.Nintendo64.CPU.GPR[25] = 0x453CA37B;
|
||||
rcp.Nintendo64.CPU.GPR[29] = 0xFFFFFFFFA4001FF0;
|
||||
rcp.Nintendo64.CPU.GPR[31] = 0xFFFFFFFFA4001550;
|
||||
rcp.Nintendo64.CPU.HI = 0x6459969A;
|
||||
rcp.Nintendo64.CPU.LO = 0x6459969A;
|
||||
rcp.Nintendo64.CPU.PC = 0xFFFFFFFFA4000040;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,11 @@ namespace DotN64.RCP
|
|||
public ModeRegister Mode { get; set; } = 0x0E;
|
||||
|
||||
public RefreshRegister Refresh { get; set; } = 0x00063634;
|
||||
|
||||
public byte[] RAM { get; } = new byte[0x00400000]; // The base system has 4 MB of RAM installed.
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public RDRAMInterface()
|
||||
public RDRAMInterface(RealityCoprocessor rcp)
|
||||
: base(rcp)
|
||||
{
|
||||
memoryMaps = new[]
|
||||
{
|
||||
|
@ -52,12 +51,12 @@ namespace DotN64.RCP
|
|||
},
|
||||
new MappingEntry(0x00000000, 0x03EFFFFF) // RDRAM memory.
|
||||
{
|
||||
Read = o => BitConverter.ToUInt32(RAM, (int)o),
|
||||
Read = o => BitConverter.ToUInt32(rcp.Nintendo64.RAM, (int)o),
|
||||
Write = (o, v) =>
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* data = &RAM[(int)o])
|
||||
fixed (byte* data = &rcp.Nintendo64.RAM[(int)o])
|
||||
{
|
||||
*(uint*)data = v;
|
||||
}
|
||||
|
|
|
@ -8,10 +8,21 @@ namespace DotN64.RCP
|
|||
{
|
||||
public abstract class Interface
|
||||
{
|
||||
#region Fields
|
||||
protected readonly RealityCoprocessor rcp;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
protected abstract IReadOnlyList<MappingEntry> MemoryMaps { get; }
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
protected Interface(RealityCoprocessor rcp)
|
||||
{
|
||||
this.rcp = rcp;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public uint ReadWord(ulong address) => MemoryMaps.GetEntry(address).ReadWord(address);
|
||||
|
||||
|
|
|
@ -3,21 +3,36 @@
|
|||
public partial class RealityCoprocessor
|
||||
{
|
||||
#region Properties
|
||||
public Nintendo64 Nintendo64 { get; }
|
||||
|
||||
public SignalProcessor SP { get; } = new SignalProcessor();
|
||||
|
||||
public DisplayProcessor DP { get; } = new DisplayProcessor();
|
||||
|
||||
public PeripheralInterface PI { get; } = new PeripheralInterface();
|
||||
public PeripheralInterface PI { get; }
|
||||
|
||||
public SerialInterface SI { get; } = new SerialInterface();
|
||||
public SerialInterface SI { get; }
|
||||
|
||||
public AudioInterface AI { get; } = new AudioInterface();
|
||||
public AudioInterface AI { get; }
|
||||
|
||||
public VideoInterface VI { get; } = new VideoInterface();
|
||||
public VideoInterface VI { get; }
|
||||
|
||||
public MIPSInterface MI { get; } = new MIPSInterface();
|
||||
public MIPSInterface MI { get; }
|
||||
|
||||
public RDRAMInterface RI { get; } = new RDRAMInterface();
|
||||
public RDRAMInterface RI { get; }
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public RealityCoprocessor(Nintendo64 nintendo64)
|
||||
{
|
||||
Nintendo64 = nintendo64;
|
||||
PI = new PeripheralInterface(this);
|
||||
SI = new SerialInterface(this);
|
||||
AI = new AudioInterface(this);
|
||||
VI = new VideoInterface(this);
|
||||
MI = new MIPSInterface(this);
|
||||
RI = new RDRAMInterface(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ namespace DotN64.RCP
|
|||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public SerialInterface()
|
||||
public SerialInterface(RealityCoprocessor rcp)
|
||||
: base(rcp)
|
||||
{
|
||||
memoryMaps = new[]
|
||||
{
|
||||
|
|
|
@ -42,7 +42,8 @@ namespace DotN64.RCP
|
|||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public VideoInterface()
|
||||
public VideoInterface(RealityCoprocessor rcp)
|
||||
: base(rcp)
|
||||
{
|
||||
memoryMaps = new[]
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue