Exemple #1
0
        void IBusSlave.Write(ushort address, byte value)
        {
            if (address == 0x0000)
            {
                _controller.Value = value;
                UpdateNametableBaseAddress();
                UpdateBgPatternTableBaseAddress();
            }
            else if (address == 0x0001)
            {
                _mask.Value = value;
            }
            else if (address == 0x0003)
            {
                _oamAddress = value;
            }
            else if (address == 0x0004)
            {
                _oamMemory[_oamAddress++] = value;
            }
            else if (address == 0x0005)
            {
                if (_writingCameraPosY)
                {
                    _cameraPosY = value;
                }
                else
                {
                    _cameraPosX = value;
                }
                _writingCameraPosY = !_writingCameraPosY;
            }
            else if (address == 0x0006)
            {
                if (_writingPPUAddrLow)
                {
                    _ppuAddr |= value;
                }
                else
                {
                    _ppuAddr = (ushort)(value << 8);
                }

                _writingPPUAddrLow = !_writingPPUAddrLow;
            }
            else if (address == 0x0007)
            {
                _masterClient.Value = value;
                _masterClient.Write(_ppuAddr);
                _ppuAddr += _controller.I ? (byte)32 : (byte)1;
            }
            else
            {
                throw new NotImplementedException();
            }
        }
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));
            }
        }