public Gpu(IDisplay display, InterruptManager interruptManager, Dma dma, Ram oamRam, bool gbc) { _r = new MemoryRegisters(GpuRegister.Values().ToArray()); _lcdc = new Lcdc(); _interruptManager = interruptManager; _gbc = gbc; _videoRam0 = new Ram(0x8000, 0x2000); _videoRam1 = gbc ? new Ram(0x8000, 0x2000) : null; _oamRam = oamRam; _dma = dma; _bgPalette = new ColorPalette(0xff68); _oamPalette = new ColorPalette(0xff6a); _oamPalette.FillWithFf(); _oamSearchPhase = new OamSearch(oamRam, _lcdc, _r); _pixelTransferPhase = new PixelTransfer(_videoRam0, _videoRam1, oamRam, display, _lcdc, _r, gbc, _bgPalette, _oamPalette); _hBlankPhase = new HBlankPhase(); _vBlankPhase = new VBlankPhase(); _mode = Mode.OamSearch; _phase = _oamSearchPhase.Start(); _display = display; }
private void DisableLcd() { _r.Put(GpuRegister.Ly, 0); _ticksInLine = 0; _phase = _hBlankPhase.Start(250); _mode = Mode.HBlank; _lcdEnabled = false; _lcdEnabledDelay = -1; _display.Enabled = false; }
public Mode?Tick() { if (!_lcdEnabled) { if (_lcdEnabledDelay != -1) { if (--_lcdEnabledDelay == 0) { _display.Enabled = true; _lcdEnabled = true; } } } if (!_lcdEnabled) { return(null); } var oldMode = _mode; _ticksInLine++; if (_phase.Tick()) { // switch line 153 to 0 if (_ticksInLine == 4 && _mode == Mode.VBlank && _r.Get(GpuRegister.Ly) == 153) { _r.Put(GpuRegister.Ly, 0); RequestLycEqualsLyInterrupt(); } } else { switch (oldMode) { case Mode.OamSearch: _mode = Mode.PixelTransfer; _phase = _pixelTransferPhase.Start(_oamSearchPhase.GetSprites()); break; case Mode.PixelTransfer: _mode = Mode.HBlank; _phase = _hBlankPhase.Start(_ticksInLine); RequestLcdcInterrupt(3); break; case Mode.HBlank: _ticksInLine = 0; if (_r.PreIncrement(GpuRegister.Ly) == 144) { _mode = Mode.VBlank; _phase = _vBlankPhase.Start(); _interruptManager.RequestInterrupt(InterruptManager.InterruptType.VBlank); RequestLcdcInterrupt(4); } else { _mode = Mode.OamSearch; _phase = _oamSearchPhase.Start(); } RequestLcdcInterrupt(5); RequestLycEqualsLyInterrupt(); break; case Mode.VBlank: _ticksInLine = 0; if (_r.PreIncrement(GpuRegister.Ly) == 1) { _mode = Mode.OamSearch; _r.Put(GpuRegister.Ly, 0); _phase = _oamSearchPhase.Start(); RequestLcdcInterrupt(5); } else { _phase = _vBlankPhase.Start(); } RequestLycEqualsLyInterrupt(); break; } } if (oldMode == _mode) { return(null); } return(_mode); }