Commodore64: Rewrote cassette, serial, 6522, 6526 and 6510 port code.
This commit is contained in:
parent
a061e898a6
commit
e075982a00
|
@ -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();
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue