Exemple #1
0
        private void DoVisibleScanline()
        {
            if (_dot >= 1 && _dot <= 256)
            {
                var tX        = (byte)(_cntTile % 32);
                var tY        = (byte)(_cntTile / 32 / 8);
                var tileId    = tY * 32 + tX;
                var bX        = tX / 2;
                var bY        = tY / 2;
                var aX        = bX / 2;
                var aY        = bY / 2;
                var aId       = aY * 8 + aX;
                var attrShift = (bY % 2 * 2 + bX % 2) * 2;

                switch (_nextTileFetchStatus)
                {
                case TileFetchStatus.Nametable_1:
                    _masterClient.Read((ushort)(_nametableBaseAddr + tileId));
                    _nextTileFetchStatus = TileFetchStatus.Nametable_2;
                    break;

                case TileFetchStatus.Nametable_2:
                    _nametable           = _masterClient.Value;
                    _nextTileFetchStatus = TileFetchStatus.Attribute_1;
                    break;

                case TileFetchStatus.Attribute_1:
                    _masterClient.Read((ushort)(0x23C0 + aId));
                    _nextTileFetchStatus = TileFetchStatus.Attribute_2;
                    break;

                case TileFetchStatus.Attribute_2:
                    _attribute           = (byte)((_masterClient.Value & (0b11 << attrShift)) >> attrShift);
                    _nextTileFetchStatus = TileFetchStatus.BitmapLow_1;
                    break;

                case TileFetchStatus.BitmapLow_1:
                    _masterClient.Read(GetBgPatternTableAddress());
                    _nextTileFetchStatus = TileFetchStatus.BitmapLow_2;
                    break;

                case TileFetchStatus.BitmapLow_2:
                    _bitmapLow           = _masterClient.Value;
                    _nextTileFetchStatus = TileFetchStatus.BitmapHigh_1;
                    break;

                case TileFetchStatus.BitmapHigh_1:
                    _masterClient.Read((ushort)(GetBgPatternTableAddress() + 8));
                    _nextTileFetchStatus = TileFetchStatus.BitmapHigh_2;
                    break;

                case TileFetchStatus.BitmapHigh_2:
                    _bitmapHigh = _masterClient.Value;
                    OutputPixel();
                    _cntTile++;
                    _nextTileFetchStatus = TileFetchStatus.Nametable_1;
                    break;
                }
            }
        }
Exemple #2
0
        void IClockSink.OnTick()
        {
            if (_enabled)
            {
                _masterClient.Read(_srcAddr++);
                _masterClient.Write(0x2014);
                _writeCount++;

                if (_writeCount == 0)
                {
                    _enabled = false;
                    _masterClient.Release();
                }
            }
        }
Exemple #3
0
        private void DispatchAddressing()
        {
            void ReadSource(AddressOperand addressOperand, ref byte result)
            {
                switch (addressOperand)
                {
                // In Result
                case AddressOperand.None:
                    break;

                case AddressOperand.Memory:
                    if (_addressState.Destination != AddressOperand.PC)
                    {
                        _masterClient.Read(_addressState.MemoryAddress);
                        result = _masterClient.Value;
                    }

                    break;

                case AddressOperand.X:
                    result = Registers.X;
                    break;

                case AddressOperand.Y:
                    result = Registers.Y;
                    break;

                case AddressOperand.A:
                    result = Registers.A;
                    break;

                default:
                    throw new ArgumentException(nameof(_addressState.SourceA));
                }
            }

            // Read Source
            ReadSource(_addressState.SourceA, ref _addressState.ResultA);
            ReadSource(_addressState.SourceB, ref _addressState.ResultB);

            // Do Operation
            switch (_addressState.Operation)
            {
            case AddressOperation.None:
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
                break;

            case AddressOperation.Inc:
                _addressState.ResultA++;
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
                break;

            case AddressOperation.Dec:
                _addressState.ResultA--;
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
                break;

            case AddressOperation.BitTest:
                if (_addressState.AffectFlags)
                {
                    Status.Z = (_addressState.ResultA & _addressState.ResultB) == 0;
                    Status.N = (_addressState.ResultB & 0x80) != 0;
                    Status.V = (_addressState.ResultB & 0x40) != 0;
                }

                break;

            case AddressOperation.Compare:
                if (_addressState.AffectFlags)
                {
                    Status.C = _addressState.ResultA >= _addressState.ResultB;
                    UpdateNZ((byte)(_addressState.ResultA - _addressState.ResultB));
                }

                break;

            case AddressOperation.And:
                _addressState.ResultA &= _addressState.ResultB;
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
                break;

            case AddressOperation.Or:
                _addressState.ResultA |= _addressState.ResultB;
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
                break;

            case AddressOperation.Adc:
            {
                var value = (short)(_addressState.ResultA + _addressState.ResultB + (Status.C ? 1 : 0));
                if (_addressState.AffectFlags)
                {
                    UpdateCV(_addressState.ResultA, _addressState.ResultB, value);
                }
                _addressState.ResultA = (byte)value;
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
            }

            break;

            case AddressOperation.Rol:
            {
                var c = Status.C;
                if (_addressState.AffectFlags)
                {
                    Status.C = (_addressState.ResultA & 0x80) != 0;
                }
                _addressState.ResultA = (byte)((_addressState.ResultA << 1) | (Status.C ? 1 : 0));
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
            }

            break;

            case AddressOperation.Asl:
            {
                if (_addressState.AffectFlags)
                {
                    Status.C = (_addressState.ResultA & 0x80) != 0;
                }
                _addressState.ResultA = (byte)(_addressState.ResultA << 1);
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
            }

            break;

            case AddressOperation.Xor:
                _addressState.ResultA ^= _addressState.ResultB;
                if (_addressState.AffectFlags)
                {
                    UpdateNZ(_addressState.ResultA);
                }
                break;

            default:
                throw new ArgumentException(nameof(_addressState.Operation));
            }

            // Write Destination
            switch (_addressState.Destination)
            {
            case AddressOperand.None:
                break;

            case AddressOperand.Memory:
                _masterClient.Value = _addressState.ResultA;
                _masterClient.Write(_addressState.MemoryAddress);
                break;

            case AddressOperand.X:
                Registers.X = _addressState.ResultA;
                break;

            case AddressOperand.Y:
                Registers.Y = _addressState.ResultA;
                break;

            case AddressOperand.A:
                Registers.A = _addressState.ResultA;
                break;

            case AddressOperand.S:
                Registers.S = _addressState.ResultA;
                break;

            case AddressOperand.PC:
                Registers.PC = _addressState.MemoryAddress;
                break;

            default:
                throw new ArgumentException(nameof(_addressState.Destination));
            }
        }