Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Registers.cs
2 views
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
    public sealed partial class Via
    {
        public int Peek(int addr)
        {
            return ReadRegister(addr & 0xF);
        }

        public void Poke(int addr, int val)
        {
            WriteRegister(addr & 0xF, val);
        }

        public int Read(int addr)
        {
            addr &= 0xF;
            switch (addr)
            {
                case 0x0:
                    _ifr &= 0xE7;
                    if (_acrPbLatchEnable)
                    {
                        return _pbLatch;
                    }
                    break;
                case 0x1:
                    _ifr &= 0xFC;
                    if (_acrPaLatchEnable)
                    {
                        return _paLatch;
                    }
                    break;
                case 0x4:
                    _ifr &= 0xBF;
                    break;
                case 0x8:
                    _ifr &= 0xDF;
                    break;
                case 0xA:
                    _ifr &= 0xFB;
                    break;
                case 0xF:
                    if (_acrPaLatchEnable)
                    {
                        return _paLatch;
                    }
                    break;
            }
            return ReadRegister(addr);
        }

        private int ReadRegister(int addr)
        {
            switch (addr)
            {
                case 0x0:
                    return _port.ReadPrb(_prb, _ddrb);
                case 0x1:
                    return _port.ReadPra(_pra, _ddra);
                case 0x2:
                    return _ddrb;
                case 0x3:
                    return _ddra;
                case 0x4:
                    return _t1C & 0xFF;
                case 0x5:
                    return (_t1C >> 8) & 0xFF;
                case 0x6:
                    return _t1L & 0xFF;
                case 0x7:
                    return (_t1L >> 8) & 0xFF;
                case 0x8:
                    return _t2C & 0xFF;
                case 0x9:
                    return (_t2C >> 8) & 0xFF;
                case 0xA:
                    return _sr;
                case 0xB:
                    return _acr;
                case 0xC:
                    return _pcr;
                case 0xD:
                    return _ifr;
                case 0xE:
                    return _ier | 0x80;
                case 0xF:
                    return _port.ReadPra(_pra, _ddra);
            }
            return 0xFF;
        }

        public void Write(int addr, int val)
        {
            addr &= 0xF;
            switch (addr)
            {
                case 0x0:
                    _ifr &= 0xE7;
                    if (_pcrCb2Control == PCR_CONTROL_HANDSHAKE_OUTPUT || _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT)
                    {
                        _handshakeCb2NextClock = true;
                    }
                    WriteRegister(addr, val);
                    break;
                case 0x1:
                    _ifr &= 0xFC;
                    if (_pcrCa2Control == PCR_CONTROL_HANDSHAKE_OUTPUT || _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT)
                    {
                        _handshakeCa2NextClock = true;
                    }
                    WriteRegister(addr, val);
                    break;
                case 0x4:
                case 0x6:
                    _t1L = (_t1L & 0xFF00) | (val & 0xFF);
                    break;
                case 0x5:
                    _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8);
                    _ifr &= 0xBF;
                    _t1C = _t1L;
                    _t1CLoaded = true;
                    _t1Delayed = 1;
                    break;
                case 0x7:
                    _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8);
                    _ifr &= 0xBF;
                    break;
                case 0x8:
                    _t2L = (_t2L & 0xFF00) | (val & 0xFF);
                    break;
                case 0x9:
                    _t2L = (_t2L & 0xFF) | ((val & 0xFF) << 8);
                    _ifr &= 0xDF;
                    if (_acrT2Control == ACR_T2_CONTROL_TIMED)
                    {
                        _t2C = _t2L;
                        _t2CLoaded = true;
                    }
                    _t2Delayed = 1;
                    break;
                case 0xA:
                    _ifr &= 0xFB;
                    WriteRegister(addr, val);
                    break;
                case 0xD:
                    _ifr &= ~val;
                    break;
                case 0xE:
                    if ((val & 0x80) != 0)
                        _ier |= val & 0x7F;
                    else
                        _ier &= ~val;
                    break;
                default:
                    WriteRegister(addr, val);
                    break;
            }
        }

        private void WriteRegister(int addr, int val)
        {
            addr &= 0xF;
            switch (addr)
            {
                case 0x0:
                    _prb = val & 0xFF;
                    break;
                case 0x1:
                case 0xF:
                    _pra = val & 0xFF;
                    break;
                case 0x2:
                    _ddrb = val & 0xFF;
                    break;
                case 0x3:
                    _ddra = val & 0xFF;
                    break;
                case 0x4:
                    _t1C = (_t1C & 0xFF00) | (val & 0xFF);
                    break;
                case 0x5:
                    _t1C = (_t1C & 0xFF) | ((val & 0xFF) << 8);
                    break;
                case 0x6:
                    _t1L = (_t1L & 0xFF00) | (val & 0xFF);
                    break;
                case 0x7:
                    _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8);
                    break;
                case 0x8:
                    _t2C = (_t2C & 0xFF00) | (val & 0xFF);
                    break;
                case 0x9:
                    _t2C = (_t2C & 0xFF) | ((val & 0xFF) << 8);
                    break;
                case 0xA:
                    _sr = val & 0xFF;
                    break;
                case 0xB:
                    _acr = val & 0xFF;
                    _acrPaLatchEnable = (val & 0x01) != 0;
                    _acrPbLatchEnable = (val & 0x02) != 0;
                    _acrSrControl = (val & 0x1C);
                    _acrT2Control = (val & 0x20);
                    _acrT1Control = (val & 0xC0);
                    break;
                case 0xC:
                    _pcr = val & 0xFF;
                    _pcrCa1IntControl = _pcr & 0x01;
                    _pcrCa2Control = _pcr & 0x0E;
                    _pcrCb1IntControl = (_pcr & 0x10) >> 4;
                    _pcrCb2Control = (_pcr & 0xE0) >> 4;
                    break;
                case 0xD:
                    _ifr = val & 0xFF;
                    break;
                case 0xE:
                    _ier = val & 0xFF;
                    break;
            }
        }

        [SaveState.DoNotSave]
        public int DdrA
        {
            get { return _ddra; }
        }

        [SaveState.DoNotSave]
        public int DdrB
        {
            get { return _ddrb; }
        }

        [SaveState.DoNotSave]
        public int PrA
        {
            get { return _pra; }
        }

        [SaveState.DoNotSave]
        public int PrB
        {
            get { return _prb; }
        }

        [SaveState.DoNotSave]
        public int EffectivePrA
        {
            get { return _pra | ~_ddra; }
        }

        [SaveState.DoNotSave]
        public int EffectivePrB
        {
            get { return _prb | ~_ddrb; }
        }

        [SaveState.DoNotSave]
        public int ActualPrA
        {
            get { return _acrPaLatchEnable ? _paLatch : _port.ReadPra(_pra, _ddra); }
        }

        [SaveState.DoNotSave]
        public int ActualPrB
        {
            get { return _acrPbLatchEnable ? _pbLatch : _port.ReadPrb(_prb, _ddrb); }
        }
    }
}