Commodore64: Rewrote cassette, serial, 6522, 6526 and 6510 port code.

This commit is contained in:
saxxonpike 2013-08-13 12:23:32 +00:00
parent a061e898a6
commit e075982a00
12 changed files with 203 additions and 419 deletions

View File

@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
// ------------------------------------
private Motherboard board;
private VIC1541 disk;
//private VIC1541 disk;
// ------------------------------------
@ -51,7 +51,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
byte[] diskRom = new byte[0x4000]; //GetFirmware("dos1541", 0x4000);
disk = new VIC1541(initRegion, diskRom);
//disk = new VIC1541(initRegion, diskRom);
//disk.Connect(board.serPort);
}
@ -90,14 +90,15 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
get
{
return (disk.PeekVia1(0x00) & 0x08) != 0;
//return (disk.PeekVia1(0x00) & 0x08) != 0;
return false;
}
}
public void HardReset()
{
board.HardReset();
disk.HardReset();
//disk.HardReset();
}
// ------------------------------------

View File

@ -28,6 +28,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
static private byte[] inputBitMask = new byte[] { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
static private byte[] inputBitSelect = new byte[] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
private byte cia0InputLatchA;
private byte cia0InputLatchB;
public void PollInput()
{
// scan joysticks
@ -51,8 +54,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
private void WriteInputPort()
{
byte portA = Port.ExternalWrite(cia0DataA, 0xFF, cia0DirA);
byte portB = Port.ExternalWrite(cia0DataB, 0xFF, cia0DirB);
byte portA = cia0.PortAData;
byte portB = cia0.PortBData;
byte resultA = 0xFF;
byte resultB = 0xFF;
byte joyA = 0xFF;
@ -84,8 +87,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
resultA &= joyA;
resultB &= joyB;
cia0DataA = Port.ExternalWrite(cia0DataA, resultA, cia0DirA);
cia0DataB = Port.ExternalWrite(cia0DataB, resultB, cia0DirB);
cia0InputLatchA = resultA;
cia0InputLatchB = resultB;
}
}
}

View File

@ -20,28 +20,15 @@ namespace BizHawk.Emulation.Computers.Commodore64
// ports
public CartridgePort cartPort;
public CassettePort cassPort;
public IController controller;
public IController controller;
public SerialPort serPort;
public UserPort userPort;
// state
public ushort address;
public byte bus;
public byte cia0DataA;
public byte cia0DataB;
public byte cia0DirA;
public byte cia0DirB;
public bool cia0FlagCassette;
public bool cia0FlagSerial;
public byte cia1DataA;
public byte cia1DataB;
public byte cia1DirA;
public byte cia1DirB;
public bool inputRead;
// cache
private ushort vicBank;
public Motherboard(Region initRegion)
{
// note: roms need to be added on their own externally
@ -49,7 +36,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
cartPort = new CartridgePort();
cassPort = new CassettePort();
cia0 = new MOS6526(initRegion);
cia1 = new MOS6526(initRegion);
cia1 = new MOS6526(initRegion);
colorRam = new Chip2114();
cpu = new MOS6510();
pla = new MOSPLA();
@ -68,8 +55,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void Execute()
{
WriteInputPort();
cia0.ExecutePhase1();
cia1.ExecutePhase1();
sid.ExecutePhase1();
@ -89,16 +74,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
address = 0xFFFF;
bus = 0xFF;
cia0DataA = 0xFF;
cia0DataB = 0xFF;
cia0DirA = 0xFF;
cia0DirB = 0xFF;
cia0FlagCassette = true;
cia0FlagSerial = true;
cia1DataA = 0xFF;
cia1DataB = 0xFF;
cia1DirA = 0xFF;
cia1DirB = 0xFF;
inputRead = false;
cpu.HardReset();
@ -113,45 +88,27 @@ namespace BizHawk.Emulation.Computers.Commodore64
// because of how mapping works, the cpu needs to be hard reset twice
cpu.HardReset();
// now reset the cache
UpdateVicBank();
}
public void Init()
{
cassPort.DeviceReadLevel = CassPort_DeviceReadLevel;
cassPort.DeviceReadMotor = CassPort_DeviceReadMotor;
cassPort.DeviceWriteButton = CassPort_DeviceWriteButton;
cassPort.DeviceWriteLevel = CassPort_DeviceWriteLevel;
cassPort.SystemReadButton = CassPort_SystemReadLevel;
cassPort.SystemReadLevel = CassPort_SystemReadLevel;
cassPort.SystemWriteLevel = CassPort_SystemWriteLevel;
cassPort.SystemWriteMotor = CassPort_SystemWriteMotor;
cassPort.ReadDataOutput = CassPort_DeviceReadLevel;
cassPort.ReadMotor = CassPort_DeviceReadMotor;
cia0.ReadDirA = Cia0_ReadDirA;
cia0.ReadDirB = Cia0_ReadDirB;
cia0.ReadFlag = Cia0_ReadFlag;
cia0.ReadPortA = Cia0_ReadPortA;
cia0.ReadPortB = Cia0_ReadPortB;
cia0.WriteDirA = Cia0_WriteDirA;
cia0.WriteDirB = Cia0_WriteDirB;
cia0.WritePortA = Cia0_WritePortA;
cia0.WritePortB = Cia0_WritePortB;
cia1.ReadDirA = Cia1_ReadDirA;
cia1.ReadDirB = Cia1_ReadDirB;
cia1.ReadPortA = Cia1_ReadPortA;
cia1.ReadFlag = Cia1_ReadFlag;
cia1.ReadPortA = Cia1_ReadPortA;
cia1.ReadPortB = Cia1_ReadPortB;
cia1.WriteDirA = Cia1_WriteDirA;
cia1.WriteDirB = Cia1_WriteDirB;
cia1.WritePortA = Cia1_WritePortA;
cia1.WritePortB = Cia1_WritePortB;
cpu.PeekMemory = pla.Peek;
cpu.PokeMemory = pla.Poke;
cpu.ReadAEC = Cpu_ReadAEC;
cpu.ReadIRQ = Cpu_ReadIRQ;
cpu.ReadNMI = Cpu_ReadNMI;
cpu.ReadPort = Cpu_ReadPort;
cpu.ReadRDY = Cpu_ReadRDY;
cpu.ReadMemory = pla.Read;
cpu.WriteMemory = pla.Write;
@ -230,16 +187,5 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void SyncState(Serializer ser)
{
}
private void UpdateVicBank()
{
switch (cia1DataA & 0x3)
{
case 0: vicBank = 0xC000; break;
case 1: vicBank = 0x8000; break;
case 2: vicBank = 0x4000; break;
default: vicBank = 0x0000; break;
}
}
}
}

View File

@ -11,127 +11,45 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
bool CassPort_DeviceReadLevel()
{
return cpu.CassetteOutputLevel;
return (cpu.PortData & 0x08) != 0;
}
bool CassPort_DeviceReadMotor()
{
return cpu.CassetteMotor;
return (cpu.PortData & 0x20) != 0;
}
void CassPort_DeviceWriteButton(bool val)
bool Cia0_ReadFlag()
{
cpu.CassetteButton = val;
}
void CassPort_DeviceWriteLevel(bool val)
{
cia0FlagCassette = val;
cia0.FLAG = cia0FlagCassette & cia0FlagSerial;
}
bool CassPort_SystemReadButton()
{
return true;
}
bool CassPort_SystemReadLevel()
{
return true;
}
void CassPort_SystemWriteLevel(bool val)
{
return;
}
void CassPort_SystemWriteMotor(bool val)
{
return;
}
byte Cia0_ReadDirA()
{
return cia0DirA;
}
byte Cia0_ReadDirB()
{
return cia0DirB;
return cassPort.DataInput;
}
byte Cia0_ReadPortA()
{
return cia0DataA;
WriteInputPort();
return cia0InputLatchA;
}
byte Cia0_ReadPortB()
{
return cia0DataB;
WriteInputPort();
return cia0InputLatchB;
}
void Cia0_WriteDirA(byte val)
bool Cia1_ReadFlag()
{
cia0DirA = val;
}
void Cia0_WriteDirB(byte val)
{
cia0DirB = val;
}
void Cia0_WritePortA(byte val)
{
cia0DataA = Port.CPUWrite(cia0DataA, val, cia0DirA);
}
void Cia0_WritePortB(byte val)
{
cia0DataB = Port.CPUWrite(cia0DataB, val, cia0DirB);
}
byte Cia1_ReadDirA()
{
return cia1DirA;
}
byte Cia1_ReadDirB()
{
return cia1DirB;
return true;
}
byte Cia1_ReadPortA()
{
return cia1DataA;
// the low bits are actually the VIC memory address.
return 0x3F;
}
byte Cia1_ReadPortB()
{
return cia1DataB;
}
void Cia1_WriteDirA(byte val)
{
cia1DirA = val;
}
void Cia1_WriteDirB(byte val)
{
cia1DirB = val;
}
void Cia1_WritePortA(byte val)
{
cia1DataA = Port.CPUWrite(cia1DataA, val, cia1DirA);
UpdateVicBank();
serPort.SystemWriteAtn((cia1DataA & 0x08) == 0);
serPort.SystemWriteClock((cia1DataA & 0x10) == 0);
serPort.SystemWriteData((cia1DataA & 0x20) == 0);
}
void Cia1_WritePortB(byte val)
{
cia1DataB = Port.CPUWrite(cia1DataB, val, cia1DirB);
return 0xFF;
}
bool Cpu_ReadAEC()
@ -139,6 +57,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
return vic.AEC;
}
bool Cpu_ReadCassetteButton()
{
return true;
}
bool Cpu_ReadIRQ()
{
return cia0.IRQ & vic.IRQ & cartPort.IRQ;
@ -149,6 +72,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
return cia1.IRQ;
}
byte Cpu_ReadPort()
{
return 0xFF;
}
bool Cpu_ReadRDY()
{
return vic.BA;
@ -187,7 +115,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
bool Pla_ReadCharen()
{
return cpu.Charen;
return (cpu.PortData & 0x04) != 0;
}
byte Pla_ReadCharRom(ushort addr)
@ -247,7 +175,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
bool Pla_ReadHiRam()
{
return cpu.HiRam;
return (cpu.PortData & 0x02) != 0;
}
byte Pla_ReadKernalRom(ushort addr)
@ -259,7 +187,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
bool Pla_ReadLoRam()
{
return cpu.LoRam;
return (cpu.PortData & 0x01) != 0;
}
byte Pla_ReadMemory(ushort addr)
@ -355,17 +283,17 @@ namespace BizHawk.Emulation.Computers.Commodore64
bool SerPort_DeviceReadAtn()
{
return (cia1DataA & 0x08) == 0;
return (cia1.PortBData & 0x08) == 0;
}
bool SerPort_DeviceReadClock()
{
return (cia1DataA & 0x10) == 0;
return (cia1.PortAData & 0x10) == 0;
}
bool SerPort_DeviceReadData()
{
return (cia1DataA & 0x20) == 0;
return (cia1.PortAData & 0x20) == 0;
}
bool SerPort_DeviceReadReset()
@ -381,18 +309,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
void SerPort_DeviceWriteClock(bool val)
{
cia1DataA = Port.ExternalWrite(cia1DataA, (byte)((cia1DataA & 0xBF) | (val ? 0x00 : 0x40)), cia1DirA);
//cia1DataA = Port.ExternalWrite(cia1DataA, (byte)((cia1DataA & 0xBF) | (val ? 0x00 : 0x40)), cia1DirA);
}
void SerPort_DeviceWriteData(bool val)
{
cia1DataA = Port.ExternalWrite(cia1DataA, (byte)((cia1DataA & 0x7F) | (val ? 0x00 : 0x80)), cia1DirA);
//cia1DataA = Port.ExternalWrite(cia1DataA, (byte)((cia1DataA & 0x7F) | (val ? 0x00 : 0x80)), cia1DirA);
}
void SerPort_DeviceWriteSrq(bool val)
{
cia0FlagSerial = val;
cia0.FLAG = cia0FlagCassette & cia0FlagSerial;
//cia0FlagSerial = val;
//cia0.FLAG = cia0FlagCassette & cia0FlagSerial;
}
byte Sid_ReadPotX()
@ -407,7 +335,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
byte Vic_ReadMemory(ushort addr)
{
addr |= vicBank;
switch (cia1.PortAData & 0x3)
{
case 0:
addr |= 0xC000;
break;
case 1:
addr |= 0x8000;
break;
case 2:
addr |= 0x4000;
break;
}
address = addr;
if ((addr & 0x7000) == 0x1000)
bus = charRom.Read(addr);

View File

@ -120,7 +120,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
LagCount++;
_frame++;
Console.WriteLine("CPUPC: " + C64Util.ToHex(board.cpu.PC, 4) + " 1541PC: " + C64Util.ToHex(disk.PC, 4));
//Console.WriteLine("CPUPC: " + C64Util.ToHex(board.cpu.PC, 4) + " 1541PC: " + C64Util.ToHex(disk.PC, 4));
CoreComm.DriveLED = DriveLED;
}
@ -152,10 +152,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
domains.Add(new MemoryDomain("CIA1", 0x10, Endian.Little, new Func<int, byte>(board.cia1.Peek), new Action<int, byte>(board.cia1.Poke)));
domains.Add(new MemoryDomain("VIC", 0x40, Endian.Little, new Func<int, byte>(board.vic.Peek), new Action<int, byte>(board.vic.Poke)));
domains.Add(new MemoryDomain("SID", 0x20, Endian.Little, new Func<int, byte>(board.sid.Peek), new Action<int, byte>(board.sid.Poke)));
domains.Add(new MemoryDomain("1541 Bus", 0x10000, Endian.Little, new Func<int, byte>(disk.Peek), new Action<int, byte>(disk.Poke)));
domains.Add(new MemoryDomain("1541 VIA0", 0x10, Endian.Little, new Func<int, byte>(disk.PeekVia0), new Action<int, byte>(disk.PokeVia0)));
domains.Add(new MemoryDomain("1541 VIA1", 0x10, Endian.Little, new Func<int, byte>(disk.PeekVia1), new Action<int, byte>(disk.PokeVia1)));
domains.Add(new MemoryDomain("1541 RAM", 0x1000, Endian.Little, new Func<int, byte>(disk.PeekRam), new Action<int, byte>(disk.PokeRam)));
//domains.Add(new MemoryDomain("1541 Bus", 0x10000, Endian.Little, new Func<int, byte>(disk.Peek), new Action<int, byte>(disk.Poke)));
//domains.Add(new MemoryDomain("1541 VIA0", 0x10, Endian.Little, new Func<int, byte>(disk.PeekVia0), new Action<int, byte>(disk.PokeVia0)));
//domains.Add(new MemoryDomain("1541 VIA1", 0x10, Endian.Little, new Func<int, byte>(disk.PeekVia1), new Action<int, byte>(disk.PokeVia1)));
//domains.Add(new MemoryDomain("1541 RAM", 0x1000, Endian.Little, new Func<int, byte>(disk.PeekRam), new Action<int, byte>(disk.PokeRam)));
memoryDomains = domains.AsReadOnly();
}
}

View File

@ -2,6 +2,8 @@
using BizHawk.Emulation.Computers.Commodore64.MOS;
using System;
#if false
namespace BizHawk.Emulation.Computers.Commodore64.Disk
{
public class VIC1541
@ -262,3 +264,4 @@ namespace BizHawk.Emulation.Computers.Commodore64.Disk
}
}
}
#endif

View File

@ -4,19 +4,27 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public class CassettePort
{
public Func<bool> DeviceReadLevel;
public Func<bool> DeviceReadMotor;
public Action<bool> DeviceWriteButton;
public Action<bool> DeviceWriteLevel;
public Func<bool> SystemReadButton;
public Func<bool> SystemReadLevel;
public Action<bool> SystemWriteLevel;
public Action<bool> SystemWriteMotor;
// Connect() needs to set System functions above
public Func<bool> ReadDataOutput;
public Func<bool> ReadMotor;
public void HardReset()
{
}
public bool DataInput
{
get
{
return true;
}
}
public bool Sense
{
get
{
return true;
}
}
}
}

View File

@ -14,14 +14,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private MOS6502X cpu;
private List<GCHandle> disposeList = new List<GCHandle>();
private bool freezeCpu;
private bool pinCassetteButton; // note: these are only
private bool pinCassetteMotor; // latches!
private bool pinCassetteOutput;
private bool pinCharen;
private bool pinLoram;
private bool pinHiram;
private bool pinNMILast;
private byte portDir;
private LatchedPort port;
private bool unusedPin0;
private bool unusedPin1;
private uint unusedPinTTL0;
@ -31,13 +25,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public Func<int, byte> PeekMemory;
public Action<int, byte> PokeMemory;
public Func<bool> ReadAEC;
public Func<bool> ReadCassetteButton;
public Func<bool> ReadIRQ;
public Func<bool> ReadNMI;
public Func<bool> ReadRDY;
public Func<ushort, byte> ReadMemory;
public Action<bool> WriteCassetteLevel;
public Action<bool> WriteCassetteMotor;
public Func<byte> ReadPort;
public Action<ushort, byte> WriteMemory;
// ------------------------------------
@ -76,8 +68,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8));
// configure data port defaults
portDir = 0x00;
SetPortData(0x1F);
port = new LatchedPort();
port.Direction = 0x00;
port.Latch = 0x1F;
// NMI is high on startup (todo: verify)
pinNMILast = true;
@ -138,7 +131,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public byte Peek(int addr)
{
if (addr == 0x0000)
return PortDirection;
return port.Direction;
else if (addr == 0x0001)
return PortData;
else
@ -148,153 +141,58 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public void Poke(int addr, byte val)
{
if (addr == 0x0000)
SetPortDir(val);
port.Direction = val;
else if (addr == 0x0001)
SetPortData(val);
port.Latch = val;
else
PokeMemory(addr, val);
}
public byte Read(ushort addr)
public byte PortData
{
get
{
return port.ReadOutput();
}
set
{
port.Latch = value;
}
}
public byte Read(ushort addr)
{
// cpu freezes after first read when RDY is low
if (!ReadRDY())
freezeCpu = true;
if (addr == 0x0000)
return PortDirection;
return port.Direction;
else if (addr == 0x0001)
return PortData;
else
return ReadMemory(addr);
}
public void Write(ushort addr, byte val)
public void SyncState(Serializer ser)
{
cpu.SyncState(ser);
ser.Sync("freezeCpu", ref freezeCpu);
ser.Sync("pinNMILast", ref pinNMILast);
ser.Sync("unusedPin0", ref unusedPin0);
ser.Sync("unusedPin1", ref unusedPin1);
ser.Sync("unusedPinTTL0", ref unusedPinTTL0);
ser.Sync("unusedPinTTL1", ref unusedPinTTL1);
ser.Sync("unusedPinTTLCycles", ref unusedPinTTLCycles);
}
public void Write(ushort addr, byte val)
{
if (addr == 0x0000)
PortDirection = val;
port.Direction = val;
else if (addr == 0x0001)
PortData = val;
port.Latch = val;
WriteMemory(addr, val);
}
// ------------------------------------
public bool CassetteButton
{
get { return pinCassetteButton; }
set { pinCassetteButton = value; }
}
public bool CassetteMotor
{
get { return pinCassetteMotor; }
}
public bool CassetteOutputLevel
{
get { return pinCassetteOutput; }
}
public bool Charen
{
get { return pinCharen; }
}
public bool HiRam
{
get { return pinHiram; }
}
public bool LoRam
{
get { return pinLoram; }
}
public byte PortData
{
get
{
//byte result = 0x00;
byte result = (byte)(~portDir & 0xEF);
result |= pinLoram ? (byte)0x01 : (byte)0x00;
result |= pinHiram ? (byte)0x02 : (byte)0x00;
result |= pinCharen ? (byte)0x04 : (byte)0x00;
result |= pinCassetteOutput ? (byte)0x08 : (byte)0x00;
result |= pinCassetteButton ? (byte)0x10 : (byte)0x00;
result |= pinCassetteMotor ? (byte)0x20 : (byte)0x00;
result |= unusedPin0 ? (byte)0x40 : (byte)0x00;
result |= unusedPin1 ? (byte)0x80 : (byte)0x00;
return result;
}
set
{
byte val = Port.CPUWrite(PortData, value, portDir);
SetPortData(val);
}
}
public byte PortDirection
{
get { return portDir; }
set
{
SetPortDir(value);
}
}
public byte ReadPortData()
{
return PortData;
}
private void SetPortData(byte val)
{
pinCassetteOutput = ((val & 0x08) != 0);
pinCassetteButton = ((val & 0x10) != 0);
pinCassetteMotor = ((val & 0x20) != 0);
pinLoram = ((val & 0x01) != 0) || ((portDir & 0x01) == 0);
pinHiram = ((val & 0x02) != 0) || ((portDir & 0x02) == 0);
pinCharen = ((val & 0x04) != 0) || ((portDir & 0x04) == 0);
unusedPin0 = ((val & 0x40) != 0);
unusedPin1 = ((val & 0x80) != 0);
unusedPinTTL0 = unusedPinTTLCycles;
unusedPinTTL1 = unusedPinTTLCycles;
}
private void SetPortDir(byte val)
{
portDir = val;
SetPortData(PortData);
}
public void SyncState(Serializer ser)
{
cpu.SyncState(ser);
ser.Sync("freezeCpu", ref freezeCpu);
ser.Sync("pinCassetteButton", ref pinCassetteButton);
ser.Sync("pinCassetteMotor", ref pinCassetteMotor);
ser.Sync("pinCassetteOutput", ref pinCassetteOutput);
ser.Sync("pinCharen", ref pinCharen);
ser.Sync("pinLoram", ref pinLoram);
ser.Sync("pinHiram", ref pinHiram);
ser.Sync("pinNMILast", ref pinNMILast);
ser.Sync("portDir", ref portDir);
ser.Sync("unusedPin0", ref unusedPin0);
ser.Sync("unusedPin1", ref unusedPin1);
ser.Sync("unusedPinTTL0", ref unusedPinTTL0);
ser.Sync("unusedPinTTL1", ref unusedPinTTL1);
ser.Sync("unusedPinTTLCycles", ref unusedPinTTLCycles);
}
public void WritePortData(byte data)
{
PortData = data;
}
// ------------------------------------
}
}

View File

@ -1,5 +1,6 @@
using System;
#if false
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// via
@ -566,3 +567,4 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// ------------------------------------
}
}
#endif

View File

@ -1,4 +1,6 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
using System;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// MOS technology 6526 "CIA"
//
@ -41,7 +43,12 @@
// ------------------------------------
private bool alarmSelect;
public Func<bool> ReadCNT;
public Func<bool> ReadFlag;
// ------------------------------------
private bool alarmSelect;
private Region chipRegion;
private bool cntPos;
private bool enableIntAlarm;
@ -53,7 +60,6 @@
private bool intSP;
private bool[] intTimer;
private bool pinCnt;
private bool pinFlag;
private bool pinPC;
private byte sr;
private uint[] timerDelay;
@ -88,7 +94,6 @@
todAlarm = new byte[4];
SetTodIn(chipRegion);
pinFlag = true;
}
// ------------------------------------
@ -100,18 +105,17 @@
public void ExecutePhase2()
{
{
pinPC = true;
TODRun();
if (timerPulse[0])
{
WritePortA((byte)(ReadPortA() & PBOnMask[0]));
portA.Latch &= PBOnMask[0];
}
if (timerPulse[1])
{
WritePortB((byte)(ReadPortA() & PBOnMask[1]));
portB.Latch &= PBOnMask[1];
}
if (timerDelay[0] == 0)
@ -291,15 +295,15 @@
if (timerPortEnable[index])
{
// force port B bit to output
WriteDirB((byte)(ReadDirB() | PBOnBit[index]));
portB.Direction |= PBOnBit[index];
switch (timerOutMode[index])
{
case OutMode.Pulse:
timerPulse[index] = true;
WritePortB((byte)(ReadPortB() | PBOnBit[index]));
portB.Latch |= PBOnBit[index];
break;
case OutMode.Toggle:
WritePortB((byte)(ReadPortB() ^ PBOnBit[index]));
portB.Latch ^= PBOnBit[index];
break;
}
}
@ -358,17 +362,6 @@
set { cntPos |= (!pinCnt && value); pinCnt = value; }
}
public bool FLAG
{
get { return pinFlag; }
set
{
if (pinFlag && !value)
intFlag = true;
pinFlag = value;
}
}
public bool PC
{
get { return pinPC; }
@ -426,16 +419,16 @@
switch (addr)
{
case 0x0:
val = ReadPortA();
val = portA.ReadInput(ReadPortA());
break;
case 0x1:
val = ReadPortB();
val = portB.ReadInput(ReadPortB());
break;
case 0x2:
val = ReadDirA();
val = portA.Direction;
break;
case 0x3:
val = ReadDirB();
val = portB.Direction;
break;
case 0x4:
timerVal = ReadTimerValue(0);
@ -560,7 +553,6 @@
ser.Sync("intTimer0", ref intTimer[0]);
ser.Sync("intTimer1", ref intTimer[1]);
ser.Sync("pinCnt", ref pinCnt);
ser.Sync("pinFlag", ref pinFlag);
ser.Sync("pinPC", ref pinPC);
ser.Sync("sr", ref sr);
ser.Sync("timerDelay0", ref timerDelay[0]);
@ -650,16 +642,16 @@
switch (addr)
{
case 0x0:
WritePortA(val);
portA.Latch = val;
break;
case 0x1:
WritePortB(val);
portB.Latch = val;
break;
case 0x2:
WriteDirA(val);
portA.Direction = val;
break;
case 0x3:
WriteDirB(val);
portB.Direction = val;
break;
case 0x4:
timerLatch[0] &= 0xFF00;

View File

@ -2,58 +2,38 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
static public class Port
{
static public byte CPUWrite(byte latch, byte val, byte dir)
{
byte result;
result = (byte)(latch & (dir ^ 0xFF));
result |= (byte)(val & dir);
return result;
}
public class LatchedPort
{
public byte Direction;
public byte Latch;
static public byte ExternalWrite(byte latch, byte val, byte dir)
{
byte result;
result = (byte)(latch & dir);
result |= (byte)(val & (dir ^ 0xFF));
return result;
}
public LatchedPort()
{
Direction = 0x00;
Latch = 0x00;
}
static public PortAdapter GetAdapter(Func<byte> newRead, Action<byte> newWrite, Action<byte> newWriteForce)
{
return new PortAdapter(newRead, newWrite, newWriteForce);
}
}
// data works like this in these types of systems:
//
// directionA directionB result
// 0 0 1
// 1 0 latchA
// 0 1 latchB
// 1 1 latchA && latchB
//
// however because this uses transistor logic, there are cases where wired-ands
// cause the pull-up resistors not to be enough to keep the bus bit set to 1 when
// both the direction and latch are 1 (the keyboard and joystick port 2 can do this.)
// the class does not handle this case as it must be handled differently in every occurrence.
public class PortAdapter
{
private Action<byte> actWrite;
private Action<byte> actWriteMask;
private Func<byte> funcRead;
public byte ReadInput(byte bus)
{
return (byte)((Latch & Direction) | ((Direction ^ 0xFF) & bus));
}
public PortAdapter(Func<byte> newRead, Action<byte> newWrite, Action<byte> newWriteMask)
{
funcRead = newRead;
actWrite = newWrite;
actWriteMask = newWriteMask;
}
public byte Data
{
get
{
return funcRead();
}
set
{
actWrite(value);
}
}
public void MaskWrite(byte val)
{
actWriteMask(val);
}
}
public byte ReadOutput()
{
return (byte)((Latch & Direction) | (Direction ^ 0xFF));
}
}
}

View File

@ -7,22 +7,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public abstract class Timer
{
protected bool pinIRQ;
protected uint[] timer;
protected LatchedPort portA;
protected LatchedPort portB;
protected uint[] timer;
protected uint[] timerLatch;
protected bool[] timerOn;
protected bool[] underflow;
public Func<byte> ReadDirA = (() => { return 0xFF; });
public Func<byte> ReadDirB = (() => { return 0xFF; });
public Func<byte> ReadPortA = (() => { return 0xFF; });
public Func<byte> ReadPortB = (() => { return 0xFF; });
public Action<byte> WriteDirA = ((byte val) => { });
public Action<byte> WriteDirB = ((byte val) => { });
public Action<byte> WritePortA = ((byte val) => { });
public Action<byte> WritePortB = ((byte val) => { });
public Timer()
{
portA = new LatchedPort();
portB = new LatchedPort();
timer = new uint[2];
timerLatch = new uint[2];
timerOn = new bool[2];
@ -31,8 +29,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
protected void HardResetInternal()
{
WriteDirA(0x00);
WriteDirB(0x00);
timer[0] = 0xFFFF;
timer[1] = 0xFFFF;
timerLatch[0] = timer[0];
@ -48,6 +44,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
}
}
public byte PortAData
{
get
{
return portA.ReadOutput();
}
}
public byte PortBData
{
get
{
return portB.ReadOutput();
}
}
protected void SyncInternal(Serializer ser)
{
ser.Sync("pinIRQ", ref pinIRQ);