Moved members in their respective place.

master
Nabile Rahmani 2017-11-04 17:59:34 +01:00
parent c323daf588
commit 66e5efff59
9 changed files with 123 additions and 83 deletions

View File

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

View File

@ -32,7 +32,8 @@ namespace DotN64.RCP
#endregion
#region Constructors
public AudioInterface()
public AudioInterface(RealityCoprocessor rcp)
: base(rcp)
{
memoryMaps = new[]
{

View File

@ -19,7 +19,8 @@ namespace DotN64.RCP
#endregion
#region Constructors
public MIPSInterface()
public MIPSInterface(RealityCoprocessor rcp)
: base(rcp)
{
memoryMaps = new[]
{

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,8 @@ namespace DotN64.RCP
#endregion
#region Constructors
public SerialInterface()
public SerialInterface(RealityCoprocessor rcp)
: base(rcp)
{
memoryMaps = new[]
{

View File

@ -42,7 +42,8 @@ namespace DotN64.RCP
#endregion
#region Constructors
public VideoInterface()
public VideoInterface(RealityCoprocessor rcp)
: base(rcp)
{
memoryMaps = new[]
{