/// <summary> /// Initializes a new instance of the <see cref="CpuCoreBase" /> class. /// </summary> /// <param name="registers">The registers.</param> /// <param name="interruptManager">The interrupt manager.</param> /// <param name="peripheralManager">The peripheral manager.</param> /// <param name="mmu">The mmu.</param> /// <param name="instructionTimer">The instruction timer.</param> /// <param name="alu">The alu.</param> /// <param name="opCodeDecoder">The opcode decoder.</param> /// <param name="instructionBlockFactory">The instruction block decoder.</param> /// <param name="dmaController">The dma controller.</param> /// <param name="messageBus">The message bus.</param> /// <param name="requireInstructionBlockCaching">if set to <c>true</c> [require instruction block caching].</param> /// <exception cref="ArgumentException">Instruction block decoder must support caching</exception> protected CpuCoreBase(IRegisters registers, IInterruptManager interruptManager, IPeripheralManager peripheralManager, IMmu mmu, IInstructionTimer instructionTimer, IAlu alu, IOpCodeDecoder opCodeDecoder, IInstructionBlockFactory instructionBlockFactory, IDmaController dmaController, IMessageBus messageBus, bool requireInstructionBlockCaching) { CoreId = Guid.NewGuid(); _registers = registers; _interruptManager = interruptManager; _peripheralManager = peripheralManager; _mmu = mmu; _instructionTimer = instructionTimer; _alu = alu; _opCodeDecoder = opCodeDecoder; _instructionBlockFactory = instructionBlockFactory; _dmaController = dmaController; _messageBus = messageBus; messageBus.RegisterHandler(Message.PauseCpu, Pause); messageBus.RegisterHandler(Message.ResumeCpu, Resume); if (requireInstructionBlockCaching && !_instructionBlockFactory.SupportsInstructionBlockCaching) { throw new ArgumentException("Instruction block decoder must support caching"); } }
/// <summary> /// Initializes a new instance of the <see cref="Gpu"/> class. /// </summary> /// <param name="gameBoyConfig">The game boy configuration.</param> /// <param name="interruptFlagsRegister">The interrupt flags register.</param> /// <param name="gpuRegisters">The gpu registers.</param> /// <param name="renderer">The renderer.</param> /// <param name="timer">The timer.</param> public Gpu(IGameBoyConfig gameBoyConfig, IInterruptFlagsRegister interruptFlagsRegister, IGpuRegisters gpuRegisters, IRenderer renderer, IInstructionTimer timer) { _interruptFlagsRegister = interruptFlagsRegister; _gpuRegisters = gpuRegisters; _renderer = renderer; _spriteRam = new ArrayBackedMemoryBank(SpriteRamConfig); _tileRam = new ArrayBackedMemoryBank(MapRamConfig); _gpuRegisters.GpuMode = GpuMode.VerticalBlank; _currentTimings = 0; _gpuRegisters.GpuMode = GpuMode.VerticalBlank; _currentTimings = 0; _gpuRegisters.CurrentScanlineRegister.Scanline = 0x92; if (gameBoyConfig.RunGpu) { timer.TimingSync += Sync; } _lcdBuffer = new Frame(LcdWidth, LcdHeight); _paintingTaskCompletionSource = new TaskCompletionSource <bool>(); _disposed = false; Task.Factory.StartNew(() => PaintLoop().Wait(), TaskCreationOptions.LongRunning); var timerFrequency = TimeSpan.FromSeconds(1); _metricsTimer = new Timer(UpdateMetricsCallback, null, timerFrequency, timerFrequency); }
/// <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="InterruptManager"/> class. /// </summary> /// <param name="registers">The registers.</param> /// <param name="instructionTimer">The instruction timer.</param> public InterruptManager(IRegisters registers, IInstructionTimer instructionTimer) { _registers = registers; _instructionTimer = instructionTimer; _haltTaskSource = new TaskCompletionSource <bool>(); _nextInterruptSource = new TaskCompletionSource <ushort>(); _cancellationSource = new CancellationTokenSource(); Task.Factory.StartNew(InterruptTask, TaskCreationOptions.LongRunning); }
/// <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> /// Initializes a new instance of the <see cref="CpuCore" /> class. /// </summary> /// <param name="registers">The registers.</param> /// <param name="interruptManager">The interrupt manager.</param> /// <param name="peripheralManager">The peripheral manager.</param> /// <param name="mmu">The mmu.</param> /// <param name="instructionTimer">The instruction timer.</param> /// <param name="alu">The alu.</param> /// <param name="opCodeDecoder">The opcode decoder.</param> /// <param name="instructionBlockFactory">The instruction block decoder.</param> /// <param name="dmaController">The dma controller.</param> /// <param name="messageBus">The message bus.</param> public CpuCore(IRegisters registers, IInterruptManager interruptManager, IPeripheralManager peripheralManager, IMmu mmu, IInstructionTimer instructionTimer, IAlu alu, IOpCodeDecoder opCodeDecoder, IInstructionBlockFactory instructionBlockFactory, IDmaController dmaController, IMessageBus messageBus) : base(registers, interruptManager, peripheralManager, mmu, instructionTimer, alu, opCodeDecoder, instructionBlockFactory, dmaController, messageBus, false) { }
/// <summary> /// Initializes a new instance of the <see cref="SegmentMmu" /> class. /// </summary> /// <param name="addressSegments">The address segments.</param> /// <param name="dmaController">The dma controller.</param> /// <param name="instructionTimer">The instruction timer.</param> public SegmentMmu(IEnumerable <IAddressSegment> addressSegments, IDmaController dmaController, IInstructionTimer instructionTimer) { _dmaController = dmaController; _instructionTimer = instructionTimer; var sortedSegments = addressSegments.OrderBy(x => x.Address).ToArray(); _readSegments = sortedSegments.OfType <IReadableAddressSegment>().ToArray(); _readSegmentAddresses = _readSegments.Select(x => x.Address).ToArray(); _writeSegments = sortedSegments.OfType <IWriteableAddressSegment>().ToArray(); _writeSegmentAddresses = _writeSegments.Select(x => x.Address).ToArray(); CheckSegments(_readSegments); CheckSegments(_writeSegments); _lockedAddressRanges = new List <AddressRange>(); // Dma task. _dmaThreadCancellation = new CancellationTokenSource(); Task.Factory.StartNew(DmaTask, TaskCreationOptions.LongRunning); }
/// <summary> /// Initializes a new instance of the <see cref="TimerRegisters"/> class. /// </summary> /// <param name="timerControlRegister">The timer control register.</param> /// <param name="interruptFlagsRegister">The interrupt flags register.</param> /// <param name="instructionTimer">The instruction timer.</param> public TimerRegisters(ITimerControlRegister timerControlRegister, IInterruptFlagsRegister interruptFlagsRegister, IInstructionTimer instructionTimer) { TimerControlRegister = timerControlRegister; _interruptFlagsRegister = interruptFlagsRegister; TimerModuloRegister = new SimpleRegister(0xff06, "Timer Modulo (TMA R/W)"); TimerCounterRegister = new SimpleRegister(0xff05, "Timer counter (TIMA R/W)"); instructionTimer.TimingSync += timings => { if (!TimerControlRegister.TimerEnabled) { return; } _cyclesSinceLastIncrement += timings.MachineCycles; if (_cyclesSinceLastIncrement > TimerControlRegister.TimerFrequency) { if (TimerCounterRegister.Register == 0xff) { // Overflow. TimerCounterRegister.Register = TimerModuloRegister.Register; _interruptFlagsRegister.UpdateInterrupts(InterruptFlag.TimerOverflow); } else { TimerCounterRegister.Register++; } } _cyclesSinceLastIncrement -= TimerControlRegister.TimerFrequency; }; }