BizHawk/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.cs

247 lines
4.5 KiB
C#
Raw Normal View History

2016-02-22 23:50:11 +00:00
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BizHawk.Common;
using BizHawk.Emulation.Cores.Components.M6502;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
// an extension of the 6502 processor
public sealed partial class Chip6510
{
// ------------------------------------
2017-04-24 13:35:05 +00:00
private MOS6502X _cpu;
private bool _pinNmiLast;
private LatchedPort _port;
private bool _thisNmi;
2016-02-22 23:50:11 +00:00
public Func<int, int> PeekMemory;
public Action<int, int> PokeMemory;
public Func<bool> ReadAec;
public Func<bool> ReadIrq;
public Func<bool> ReadNmi;
public Func<bool> ReadRdy;
public Func<int, int> ReadMemory;
public Func<int> ReadPort;
public Action<int, int> WriteMemory;
public Action<int, int> WriteMemoryPort;
2017-04-24 13:35:05 +00:00
public Action DebuggerStep;
2016-02-22 23:50:11 +00:00
// ------------------------------------
public Chip6510()
{
2017-04-24 13:35:05 +00:00
// configure cpu r/w
_cpu = new MOS6502X
{
DummyReadMemory = CpuRead,
ReadMemory = CpuRead,
WriteMemory = CpuWrite,
PeekMemory = CpuPeek
};
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
// perform hard reset
2016-02-22 23:50:11 +00:00
HardReset();
}
2017-04-24 13:35:05 +00:00
public void SetOverflow()
{
}
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
private byte CpuPeek(ushort addr)
{
return unchecked((byte)Peek(addr));
}
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
private byte CpuRead(ushort addr)
{
return unchecked((byte)Read(addr));
}
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
private void CpuWrite(ushort addr, byte val)
{
Write(addr, val);
}
2016-02-22 23:50:11 +00:00
public void HardReset()
{
_cpu.NESSoftReset();
2017-04-24 13:35:05 +00:00
_port = new LatchedPort
{
Direction = 0x00,
Latch = 0xFF
};
2016-02-22 23:50:11 +00:00
_pinNmiLast = true;
}
// ------------------------------------
public void ExecutePhase()
{
2017-04-24 13:35:05 +00:00
_cpu.RDY = ReadRdy();
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
if (ReadAec())
{
_cpu.IRQ = !ReadIrq();
_pinNmiLast = _thisNmi;
_thisNmi = ReadNmi();
_cpu.NMI |= _pinNmiLast && !_thisNmi;
_cpu.ExecuteOne();
}
else
{
LagCycles++;
}
2016-02-22 23:50:11 +00:00
}
2017-04-24 13:35:05 +00:00
public int LagCycles;
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
internal bool AtInstructionStart()
2016-02-22 23:50:11 +00:00
{
return _cpu.AtInstructionStart();
}
2017-04-24 13:35:05 +00:00
// ------------------------------------
2016-02-22 23:50:11 +00:00
2017-04-24 13:35:05 +00:00
[SaveState.DoNotSave]
public ushort Pc
2016-02-22 23:50:11 +00:00
{
get
{
return _cpu.PC;
}
set
{
_cpu.PC = value;
}
}
2017-04-24 13:35:05 +00:00
[SaveState.DoNotSave]
public int A
2016-02-22 23:50:11 +00:00
{
2017-04-24 13:35:05 +00:00
get { return _cpu.A; }
set { _cpu.A = unchecked((byte)value); }
2016-02-22 23:50:11 +00:00
}
2017-04-24 13:35:05 +00:00
[SaveState.DoNotSave]
public int X
2016-02-22 23:50:11 +00:00
{
2017-04-24 13:35:05 +00:00
get { return _cpu.X; }
set { _cpu.X = unchecked((byte)value); }
2016-02-22 23:50:11 +00:00
}
2017-04-24 13:35:05 +00:00
[SaveState.DoNotSave]
public int Y
2016-02-22 23:50:11 +00:00
{
2017-04-24 13:35:05 +00:00
get { return _cpu.Y; }
set { _cpu.Y = unchecked((byte)value); }
2016-02-22 23:50:11 +00:00
}
2017-04-24 13:35:05 +00:00
[SaveState.DoNotSave]
public int S
2016-02-22 23:50:11 +00:00
{
2017-04-24 13:35:05 +00:00
get { return _cpu.S; }
set { _cpu.S = unchecked((byte)value); }
2016-02-22 23:50:11 +00:00
}
2017-04-24 13:35:05 +00:00
[SaveState.DoNotSave]
public bool FlagC { get { return _cpu.FlagC; } }
[SaveState.DoNotSave]
public bool FlagZ { get { return _cpu.FlagZ; } }
[SaveState.DoNotSave]
public bool FlagI { get { return _cpu.FlagI; } }
[SaveState.DoNotSave]
public bool FlagD { get { return _cpu.FlagD; } }
[SaveState.DoNotSave]
public bool FlagB { get { return _cpu.FlagB; } }
[SaveState.DoNotSave]
public bool FlagV { get { return _cpu.FlagV; } }
[SaveState.DoNotSave]
public bool FlagN { get { return _cpu.FlagN; } }
[SaveState.DoNotSave]
public bool FlagT { get { return _cpu.FlagT; } }
2016-02-22 23:50:11 +00:00
public int Peek(int addr)
{
2017-04-24 13:35:05 +00:00
switch (addr)
{
case 0x0000:
return _port.Direction;
case 0x0001:
return PortData;
default:
return PeekMemory(addr);
}
}
public void Poke(int addr, int val)
{
switch (addr)
{
case 0x0000:
_port.Direction = val;
break;
case 0x0001:
_port.Latch = val;
break;
default:
PokeMemory(addr, val);
break;
}
}
[SaveState.DoNotSave]
public int PortData
2016-02-22 23:50:11 +00:00
{
get
{
return _port.ReadInput(ReadPort());
}
set
{
_port.Latch = value;
}
}
public int Read(int addr)
{
2017-04-24 13:35:05 +00:00
switch (addr)
{
case 0x0000:
return _port.Direction;
case 0x0001:
return PortData;
default:
return ReadMemory(addr);
}
2016-02-22 23:50:11 +00:00
}
2017-04-24 13:35:05 +00:00
public void SyncState(Serializer ser)
2016-02-22 23:50:11 +00:00
{
SaveState.SyncObject(ser, this);
}
public void Write(int addr, int val)
{
2017-04-24 13:35:05 +00:00
switch (addr)
{
case 0x0000:
_port.Direction = val;
WriteMemoryPort(addr, val);
break;
case 0x0001:
_port.Latch = val;
WriteMemoryPort(addr, val);
break;
default:
WriteMemory(addr, val);
break;
}
2016-02-22 23:50:11 +00:00
}
}
}