Exemplo n.º 1
0
        // Expected to be called at the rate of the base clock of 4,194,304 Hz.
        public void Tick()
        {
            // DIV counter
            _divCounter++;
            if (_divCounter == 256)
            {
                _divCounter = 0;
                _div++;
            }

            // TIMA counter
            if (!_timerEnabled)
            {
                return;
            }

            _timerCounter++;
            if (_timerCounter == _timerDivider)
            {
                _timerCounter = 0;
                _timer++;

                // overflow happened
                if (_timer == 0)
                {
                    _timerInterrupt.Trigger();
                    _timer = TMA.Value;
                }
            }
        }
Exemplo n.º 2
0
        private void ChangeMode(LcdMode newMode)
        {
            _currentMode = newMode;
            _counter     = 0;

            if (newMode == LcdMode.OamSearch)
            {
                if (_stat.OamSearchInterruptEnabled.Value)
                {
                    _lcdStatusInterrupt.Trigger();
                }
            }
            else if (newMode == LcdMode.DataTransfer)
            {
                // Do nothing.
            }
            else if (newMode == LcdMode.HorizontalBlank)
            {
                RenderScanline(_ly.Value);

                if (_stat.HBlankInterruptEnabled.Value)
                {
                    _lcdStatusInterrupt.Trigger();
                }
            }
            else if (newMode == LcdMode.VerticalBlank)
            {
                //Console.WriteLine($"Vblank after {_globalCounter - _lastVblank} cycles.");
                _lastVblank = _globalCounter;


                OnCompletedFrame();

                _vblankInterrupt.Trigger();

                // TODO does vblank really have two interrupts?
                if (_stat.VBlankInterruptEnabled.Value)
                {
                    _vblankInterrupt.Trigger();
                }
            }
        }
Exemplo n.º 3
0
        // TODO: Make this more efficient. Currently one clock per call.
        // TODO: Timing is not accurate. (Depends on sprite count etc)
        public int Tick()
        {
            if (!_lcdc.LcdEnabled.Value)
            {
                return(1);
            }

            _counter++;

            _globalCounter++;

            switch (_currentMode)
            {
            case LcdMode.OamSearch:
                if (_counter >= 80)
                {
                    ChangeMode(LcdMode.DataTransfer);
                }
                break;

            case LcdMode.DataTransfer:
                if (_counter >= 172)
                {
                    ChangeMode(LcdMode.HorizontalBlank);
                }
                break;

            case LcdMode.HorizontalBlank:
                if (_counter >= 204)
                {
                    _ly.Value++;
                    if (_ly.Value == 144)     // TODO maybe 143???
                    {
                        ChangeMode(LcdMode.VerticalBlank);
                    }
                    else
                    {
                        ChangeMode(LcdMode.OamSearch);
                    }
                }
                break;

            case LcdMode.VerticalBlank:
                // TODO this is wrong, maybe?
                if (_counter >= 456)
                {
                    _ly.Value++;
                    _counter = 0;     // TODO re-check
                }
                if (_ly.Value == 154)
                {
                    _ly.Value = 0;
                    ChangeMode(LcdMode.OamSearch);
                }
                break;
            }

            if (_ly.Value == _lyc.Value && _stat.ScanlineCoincidenceInterruptEnabled.Value)
            {
                _lcdStatusInterrupt.Trigger();
            }

            _stat.Mode = _currentMode; // TODO
            return(1);
        }