/// <summary> /// Gets the address segment. /// </summary> /// <param name="configs">The configs.</param> /// <param name="memoryBankController">The memory bank controller.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException"> /// </exception> /// <exception cref="System.NotImplementedException">Banked RAM</exception> private static IAddressSegment GetAddressSegment(ICollection <IMemoryBankConfig> configs, IMemoryBankController memoryBankController) { var config = configs.First(); if (configs.Count == 1) { switch (config.Type) { case MemoryBankType.RandomAccessMemory: return(new ArrayBackedMemoryBank(config)); case MemoryBankType.ReadOnlyMemory: return(new ReadOnlyMemoryBank(config)); case MemoryBankType.Unused: return(new NullMemoryBank(config)); default: throw new ArgumentOutOfRangeException(); } } switch (config.Type) { case MemoryBankType.RandomAccessMemory: throw new NotImplementedException("Banked RAM"); case MemoryBankType.ReadOnlyMemory: return(new BankedReadOnlyMemoryBank(configs, memoryBankController)); default: throw new ArgumentOutOfRangeException(); } }
public MemoryMap(IoAddresses ioAddresses) { this.IoAddresses = ioAddresses; // TODO: Fix this. this.IoAddresses.Parent = this; this.mbc_ = new MemoryBankController(this.romBank0_, this.romBankX_); var f = IMemorySourceFactory.INSTANCE; this.Vram = f.NewArray(0x2000); var ram = f.NewArray(0xfe00 - 0xe000); this.Oam = f.NewArray(0xa0); this.impl_ = f.BuildMapper(0xffff + 1) .Register(0x0000, this.romBank0_) .Register(0x4000, this.romBankX_) .Register(0x8000, this.Vram) .Register(0xc000, ram) .Register(0xe000, ram) .Register(0xfe00, this.Oam) .Register(0xff00, this.IoAddresses) .Build(); Asserts.Equal(10, this.impl_.SourceCount); this.Reset(); }
public GameBoy(string romPath) { _logger = new Logger(); _mainMemory = new MainMemory(); _dmaController = new DmaController(_mainMemory); _timer = new Timer(_mainMemory); _joypad = new Joypad(); _serialController = new SerialController(_mainMemory); _pixelProcessingUnit = new PixelProcessingUnit(_mainMemory, _logger); _audioProcessingUnit = new AudioProcessingUnit(); IRandomAccessMemory mainMemoryProxy = new MainMemoryDmaProxy(_mainMemory, _dmaController); _cpuCore = new CpuCore(mainMemoryProxy, new CpuState(), _logger); IRomLoader romLoader = new FileRomLoader(romPath); _ramManager = new FileRamManager(Path.ChangeExtension(romPath, ".sav")); _memoryBankController = MBCFactory.CreateMBC(romLoader); _memoryBankController.LoadRam(_ramManager); _mainMemory.RegisterMemoryAccessDelegate(_memoryBankController as IMemoryAccessDelegate); _mainMemory.RegisterMemoryAccessDelegate(_pixelProcessingUnit); _mainMemory.RegisterMemoryAccessDelegate(_timer); _mainMemory.RegisterMemoryAccessDelegate(_joypad); _mainMemory.RegisterMemoryAccessDelegate(_audioProcessingUnit); _mainMemory.RegisterMemoryAccessDelegate(_serialController); }
public Cartridge(byte[] romData) { _romHeader = new RomHeader(romData); _mbc = (romData[0x0147]) switch { _ => new MbcRomOnly(romData), }; }
/// <summary> /// Initializes a new instance of the <see cref="CacheAwareZ80Mmu"/> class. /// </summary> /// <param name="peripheralManager">The peripheral manager.</param> /// <param name="platformConfig">The platform configuration.</param> /// <param name="memoryBankController">The memory bank controller.</param> /// <param name="dmaController">The dma controller.</param> /// <param name="instructionTimer">The instruction timer.</param> public Z80Mmu(IPeripheralManager peripheralManager, IPlatformConfig platformConfig, IMemoryBankController memoryBankController, IDmaController dmaController, IInstructionTimer instructionTimer) : base(GetAddressSegments(peripheralManager, platformConfig, memoryBankController), dmaController, instructionTimer) { }
/// <summary> /// Initializes a new instance of the <see cref="CacheAwareZ80Mmu"/> class. /// </summary> /// <param name="peripheralManager">The peripheral manager.</param> /// <param name="platformConfig">The platform configuration.</param> /// <param name="memoryBankController">The memory bank controller.</param> /// <param name="dmaController">The dma controller.</param> /// <param name="instructionTimer">The instruction timer.</param> public CacheAwareZ80Mmu(IPeripheralManager peripheralManager, IPlatformConfig platformConfig, IMemoryBankController memoryBankController, IDmaController dmaController, IInstructionTimer instructionTimer, IInstructionBlockCache instructionBlockCache) : base(peripheralManager, platformConfig, memoryBankController, dmaController, instructionTimer) { _instructionBlockCache = instructionBlockCache; }
/// <summary> /// Gets the address segments. /// </summary> /// <param name="peripheralManager">The peripheral manager.</param> /// <param name="platformConfig">The platform configuration.</param> /// <param name="memoryBankController">The memory bank controller.</param> /// <returns></returns> private static IEnumerable <IAddressSegment> GetAddressSegments(IPeripheralManager peripheralManager, IPlatformConfig platformConfig, IMemoryBankController memoryBankController) { var memoryBanks = platformConfig.MemoryBanks.GroupBy(x => x.Address) .Select(x => GetAddressSegment(x.ToArray(), memoryBankController)) .ToArray(); return(memoryBanks.Concat(peripheralManager.MemoryMap)); }
/// <summary> /// Initializes a new instance of the <see cref="GameBoyMemoryMappedIo" /> class. /// </summary> /// <param name="hardwareRegisters">The hardware registers.</param> /// <param name="interruptRegister">The interrupt register.</param> /// <param name="gpu">The gpu.</param> /// <param name="renderer">The renderer.</param> /// <param name="memoryBankController">The memory bank controller.</param> public GameBoyMemoryMappedIo(IHardwareRegisters hardwareRegisters, IInterruptEnableRegister interruptRegister, IGpu gpu, IRenderer renderer, IMemoryBankController memoryBankController) { HardwareRegisters = hardwareRegisters; _interruptRegister = interruptRegister; Gpu = gpu; Renderer = renderer; _memoryBankController = memoryBankController; }
/// <summary> /// Initializes a new instance of the <see cref="BankedReadOnlyMemoryBank" /> class. /// </summary> /// <param name="bankConfigs">The bank configs.</param> /// <param name="memoryBankController">The memory bank controller.</param> /// <exception cref="System.ArgumentException"> /// Must provide at least one bank configuration, all must have a bank id and must be unique. /// or /// All bank configurations must have same address and length - this address segment is banked, remember. /// </exception> /// <exception cref="MemoryConfigStateException"></exception> public BankedReadOnlyMemoryBank(ICollection <IMemoryBankConfig> bankConfigs, IMemoryBankController memoryBankController) { if (bankConfigs == null || !bankConfigs.Any() || !bankConfigs.All(x => x.BankId.HasValue) || bankConfigs.Select(x => x.BankId.Value).Distinct().Count() != bankConfigs.Count) { throw new ArgumentException( "Must provide at least one bank configuration, all must have a bank id and must be unique.", nameof(bankConfigs)); } var distinct = bankConfigs.Select(x => new { x.Address, x.Length }).Distinct().ToArray(); if (distinct.Length > 1) { throw new ArgumentException( "All bank configurations must have same address and length - this address segment is banked, remember.", nameof(bankConfigs)); } Address = distinct[0].Address; Length = distinct[0].Length; var badBank = bankConfigs.FirstOrDefault(x => x.InitialState == null || x.Length != Length); if (badBank != null) { throw new MemoryConfigStateException(Address, Length, badBank.InitialState?.Length ?? 0); } IDictionary <byte, byte[]> banks = bankConfigs.ToDictionary(x => x.BankId.Value, x => { var memory = new byte[Length]; Array.Copy(x.InitialState, 0, memory, 0, Length); return(memory); }); _bank = banks[memoryBankController.RomBankNumber]; memoryBankController.MemoryBankSwitch += target => { if (target != MemoryBankControllerEventTarget.RomBankSwitch) { return; } _bank = banks[memoryBankController.RomBankNumber]; }; }