public void AddDevice(IMemoryMappedDevice dev) { // // Add the new device to the hash; this is done by adding // one entry for every address claimed by the device. Since we have only 64K of address // space, this isn't too awful. // foreach (MemoryRange range in dev.Addresses) { for (ushort addr = range.Start; addr <= range.End; addr++) { if (_bus.ContainsKey(addr)) { throw new InvalidOperationException( String.Format("Memory mapped address collision for dev {0} at address {1} with {2}", dev, Conversion.ToOctal(addr), _bus[addr])); } else { _bus.Add(addr, dev); } } } if (dev is Memory) { _mainMemory = (Memory)dev; } }
protected IMemoryMapping MapPpuRange(IMemoryMappedDevice device, int startAddress, int endAddress) { IMemoryMapping mapping = this.PpuBus.RegisterMappedDevice(device, startAddress, endAddress); this.ppuMappings.Add(mapping); return(mapping); }
IMemoryMapping IMemoryBus.RegisterMappedDevice(IMemoryMappedDevice device, int startAddress, int endAddress) { MemoryMapping mapping = new MemoryMapping(device, startAddress, endAddress); this.mappings.Add(mapping); this.mappingsArray = this.mappings.ToArray(); return(mapping); }
/// <summary> /// Set a memory based device at a specific location of memory /// </summary> /// <param name="device">The device to set</param> /// <param name="startAddres">The addres the device is based from.</param> /// <param name="size">The size (in bytes) of memory the device fills</param> public void AddDevice(IMemoryMappedDevice device) { device.SetMemory(memory.AsMemory(device.BaseAddress, device.Size)); DevicesByName.Add(device.Name, device); int index = 0; if (DevicesByIndex.Keys.Count != 0) { index = DevicesByIndex.Keys.Max() + 1; } DevicesByIndex.Add(index, device); memoryMap.AsSpan(device.BaseAddress, device.Size).Fill(index); }
/// <summary> /// Determine whehter the address being read from or written to is an I/O device or a memory cell. /// If the location is an I/O device, return that device. Otherwise, return the memory being referenced. /// </summary> /// <param name="address"></param> /// <param name="device"></param> /// <param name="deviceStartAddress"></param> public void GetDeviceAt(int address, out IMemoryMappedDevice device, out int deviceStartAddress) { int deviceIndex = memoryMap[address]; if (deviceIndex != -1) { device = DevicesByIndex[deviceIndex]; deviceStartAddress = address - device.BaseAddress; } else { device = null; deviceStartAddress = address; } }
/// <summary> /// Dispatches writes to memory mapped hardware (RAM, I/O) /// </summary> /// <param name="address"></param> /// <param name="data"></param> /// <returns></returns> private void WriteToBus(ushort address, ushort data, TaskType task, bool extendedMemoryReference) { if (address <= Memory.RamTop) { // Main memory access; shortcut hashtable lookup for performance reasons. _mainMemory.Load(address, data, task, extendedMemoryReference); } else { // Memory-mapped device access: // Look up address in hash; if populated ask the device // to store a value otherwise do nothing. IMemoryMappedDevice memoryMappedDevice = null; if (_bus.TryGetValue(address, out memoryMappedDevice)) { memoryMappedDevice.Load(address, data, task, extendedMemoryReference); } } }
void IMemoryBus.Write(int address, byte value) { if (this.writeBreakpointsArray.Length != 0) { for (int i = 0; i < this.writeBreakpointsArray.Length; i++) { if (this.writeBreakpointsArray[i].TargetAddress == address) { this.writeBreakpointsArray[i].OnBreakpointHit(); } } } IMemoryMappedDevice device = this.GetDeviceAtAddress(ref address); if (device == null) { Debug.WriteLine("Write of unmapped address 0x{0:X8} = 0x{1:X2} on bus '{2}'!", address, value, this.Name); return; } device.Write(address, value); }
byte IMemoryBus.Read(int address) { if (this.readBreakpointsArray.Length != 0) { for (int i = 0; i < this.readBreakpointsArray.Length; i++) { if (this.readBreakpointsArray[i].TargetAddress == address) { this.readBreakpointsArray[i].OnBreakpointHit(); } } } IMemoryMappedDevice device = this.GetDeviceAtAddress(ref address); if (device == null) { Debug.WriteLine("Read of unmapped address 0x{0,8:X8} on bus '{1}'!", address, this.Name); return(4); // Uninitialized memory contents, generated by fair dice roll; } return(device.Read(address)); }
/// <summary> /// Dispatches reads to memory mapped hardware (RAM, I/O) /// </summary> /// <param name="address"></param> /// <returns></returns> private ushort ReadFromBus(ushort address, TaskType task, bool extendedMemoryReference) { if (address <= Memory.RamTop) { // Main memory access; shortcut hashtable lookup for performance reasons. return(_mainMemory.Read(address, task, extendedMemoryReference)); } else { // Memory-mapped device access: // Look up address in hash; if populated ask the device // to return a value otherwise return 0. IMemoryMappedDevice memoryMappedDevice = null; if (_bus.TryGetValue(address, out memoryMappedDevice)) { return(memoryMappedDevice.Read(address, task, extendedMemoryReference)); } else { return(0); } } }
internal MemoryMapping(IMemoryMappedDevice device, int startAddress, int endAddress) { this.Device = device; this.StartAddress = startAddress; this.EndAddress = endAddress; }
public void RemoveDevice(IMemoryMappedDevice device) { memoryMap.AsSpan(device.BaseAddress, device.Size).Fill(-1); DevicesByName.Remove(device.Name); DevicesByIndex.Remove(DevicesByIndex.Single(x => x.Value == device).Key); }