Example #1
0
        /// <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();
            }
        }
Example #2
0
        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();
        }
Example #3
0
        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);
        }
Example #4
0
 public Cartridge(byte[] romData)
 {
     _romHeader = new RomHeader(romData);
     _mbc       = (romData[0x0147]) switch
     {
         _ => new MbcRomOnly(romData),
     };
 }
Example #5
0
 /// <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)
 {
 }
Example #6
0
 /// <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;
 }
Example #7
0
        /// <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));
        }
Example #8
0
 /// <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];
            };
        }