C64: Better lifecycle management and 1541-II support.

This commit is contained in:
Anthony Konzel 2016-03-04 16:06:25 -06:00
parent 87200593b6
commit f4f45f73a8
12 changed files with 374 additions and 344 deletions

View File

@ -261,6 +261,7 @@
<Compile Include="Computers\Commodore64\Serial\Drive1541.IDebuggable.cs" />
<Compile Include="Computers\Commodore64\Serial\Drive1541.IDisassemblable.cs" />
<Compile Include="Computers\Commodore64\Serial\Drive1541.Motor.cs" />
<Compile Include="Computers\Commodore64\Serial\Drive1541.Registers.cs" />
<Compile Include="Computers\Commodore64\Serial\SerialPort.cs" />
<Compile Include="Computers\Commodore64\Serial\SerialPortDevice.cs" />
<Compile Include="Computers\Commodore64\User\UserPort.cs" />

View File

@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public enum DiskDriveType
{
None, Commodore1541
None, Commodore1541, Commodore1541II
}
}
}

View File

@ -130,6 +130,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
switch (diskDriveType)
{
case C64.DiskDriveType.Commodore1541:
case C64.DiskDriveType.Commodore1541II:
DiskDrive = new Drive1541(ClockNumerator, ClockDenominator);
Serial.Connect(DiskDrive);
break;

View File

@ -117,7 +117,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public void Dispose()
{
}
if (_board != null)
{
if (_board.TapeDrive != null)
{
_board.TapeDrive.RemoveMedia();
}
if (_board.DiskDrive != null)
{
_board.DiskDrive.RemoveMedia();
}
_board = null;
}
}
private int _frameCycles;
@ -266,19 +278,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
private void InitRoms(DiskDriveType diskDriveType)
{
var basicRom = GetFirmware(0x2000, "Basic");
var charRom = GetFirmware(0x1000, "Chargen");
var kernalRom = GetFirmware(0x2000, "Kernal");
_board.BasicRom.Flash(GetFirmware(0x2000, "Basic"));
_board.KernalRom.Flash(GetFirmware(0x1000, "Chargen"));
_board.CharRom.Flash(GetFirmware(0x2000, "Kernal"));
_board.BasicRom.Flash(basicRom);
_board.KernalRom.Flash(kernalRom);
_board.CharRom.Flash(charRom);
if (diskDriveType == DiskDriveType.Commodore1541)
switch (diskDriveType)
{
var diskRom = GetFirmware(0x4000, "Drive1541", "Drive1541II");
_board.DiskDrive.DriveRom.Flash(diskRom);
}
case DiskDriveType.Commodore1541:
_board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541"));
break;
case DiskDriveType.Commodore1541II:
_board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541II"));
break;
}
}
// ------------------------------------

View File

@ -37,5 +37,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
{
_tape = tape;
}
public void RemoveMedia()
{
_tape = null;
}
}
}

View File

@ -76,30 +76,32 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
private static byte[] ConvertSectorToGcr(byte[] source, byte sectorNo, byte trackNo, byte formatA, byte formatB, out int bitsWritten)
{
var mem = new MemoryStream();
var writer = new BinaryWriter(mem);
var headerChecksum = (byte)(sectorNo ^ trackNo ^ formatA ^ formatB);
using (var mem = new MemoryStream())
{
var writer = new BinaryWriter(mem);
var headerChecksum = (byte)(sectorNo ^ trackNo ^ formatA ^ formatB);
// assemble written data for GCR encoding
var writtenData = new byte[260];
Array.Copy(source, 0, writtenData, 1, 256);
writtenData[0] = 0x07;
writtenData[0x101] = Checksum(source);
writtenData[0x102] = 0x00;
writtenData[0x103] = 0x00;
// assemble written data for GCR encoding
var writtenData = new byte[260];
Array.Copy(source, 0, writtenData, 1, 256);
writtenData[0] = 0x07;
writtenData[0x101] = Checksum(source);
writtenData[0x102] = 0x00;
writtenData[0x103] = 0x00;
writer.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); // sync
writer.Write(EncodeGcr(new byte[] { 0x08, headerChecksum, sectorNo, trackNo, formatA, formatB, 0x0F, 0x0F })); // header
writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap
writer.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); // sync
writer.Write(EncodeGcr(writtenData)); // data
writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap
writer.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); // sync
writer.Write(EncodeGcr(new byte[] { 0x08, headerChecksum, sectorNo, trackNo, formatA, formatB, 0x0F, 0x0F })); // header
writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap
writer.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); // sync
writer.Write(EncodeGcr(writtenData)); // data
writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap
bitsWritten = (int)mem.Length * 8;
bitsWritten = (int)mem.Length * 8;
writer.Flush();
return mem.ToArray();
}
writer.Flush();
return mem.ToArray();
}
}
private static byte[] EncodeGcr(byte[] source)
{
@ -107,113 +109,101 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
var gcr = new int[8];
var data = new byte[4];
var count = source.Length;
var mem = new MemoryStream();
var writer = new BinaryWriter(mem);
using (var mem = new MemoryStream())
{
var writer = new BinaryWriter(mem);
for (var i = 0; i < count; i += 4)
{
Array.Copy(source, i, data, 0, 4);
gcr[0] = gcrEncodeTable[data[0] >> 4];
gcr[1] = gcrEncodeTable[data[0] & 0xF];
gcr[2] = gcrEncodeTable[data[1] >> 4];
gcr[3] = gcrEncodeTable[data[1] & 0xF];
gcr[4] = gcrEncodeTable[data[2] >> 4];
gcr[5] = gcrEncodeTable[data[2] & 0xF];
gcr[6] = gcrEncodeTable[data[3] >> 4];
gcr[7] = gcrEncodeTable[data[3] & 0xF];
for (var i = 0; i < count; i += 4)
{
Array.Copy(source, i, data, 0, 4);
gcr[0] = gcrEncodeTable[data[0] >> 4];
gcr[1] = gcrEncodeTable[data[0] & 0xF];
gcr[2] = gcrEncodeTable[data[1] >> 4];
gcr[3] = gcrEncodeTable[data[1] & 0xF];
gcr[4] = gcrEncodeTable[data[2] >> 4];
gcr[5] = gcrEncodeTable[data[2] & 0xF];
gcr[6] = gcrEncodeTable[data[3] >> 4];
gcr[7] = gcrEncodeTable[data[3] & 0xF];
// -------- -------- -------- -------- --------
// 00000111 11222223 33334444 45555566 66677777
// -------- -------- -------- -------- --------
// 00000111 11222223 33334444 45555566 66677777
var outputValue = (gcr[0] << 3) | (gcr[1] >> 2);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[1] << 6) | (gcr[2] << 1) | (gcr[3] >> 4);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[3] << 4) | (gcr[4] >> 1);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[4] << 7) | (gcr[5] << 2) | (gcr[6] >> 3);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[6] << 5) | (gcr[7]);
writer.Write((byte)(outputValue & 0xFF));
/*
// -------- -------- -------- -------- --------
// 11100000 32222211 44443333 66555554 77777666
var outputValue = (gcr[0]) | (gcr[1] << 5);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[1] >> 3) | (gcr[2] << 2) | (gcr[3] << 7);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[3] >> 1) | (gcr[4] << 4);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[4] >> 4) | (gcr[5] << 1) | (gcr[6] << 6);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[6] >> 2) | (gcr[7] << 3);
writer.Write((byte)(outputValue & 0xFF));
*/
var outputValue = (gcr[0] << 3) | (gcr[1] >> 2);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[1] << 6) | (gcr[2] << 1) | (gcr[3] >> 4);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[3] << 4) | (gcr[4] >> 1);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[4] << 7) | (gcr[5] << 2) | (gcr[6] >> 3);
writer.Write((byte)(outputValue & 0xFF));
outputValue = (gcr[6] << 5) | (gcr[7]);
writer.Write((byte)(outputValue & 0xFF));
}
writer.Flush();
return mem.ToArray();
}
writer.Flush();
return mem.ToArray();
}
}
public static Disk Read(byte[] source)
{
var mem = new MemoryStream(source);
var reader = new BinaryReader(mem);
var trackDatas = new List<byte[]>();
var trackLengths = new List<int>();
var trackNumbers = new List<int>();
var trackDensities = new List<int>();
int trackCount;
using (var mem = new MemoryStream(source))
{
var reader = new BinaryReader(mem);
var trackDatas = new List<byte[]>();
var trackLengths = new List<int>();
var trackNumbers = new List<int>();
var trackDensities = new List<int>();
int trackCount;
switch (source.Length)
{
case 174848: // 35 tracks no errors
trackCount = 35;
break;
case 175531: // 35 tracks with errors
trackCount = 35;
break;
case 196608: // 40 tracks no errors
trackCount = 40;
break;
case 197376: // 40 tracks with errors
trackCount = 40;
break;
default:
throw new Exception("Not able to identify capacity of the D64 file.");
}
for (var i = 0; i < trackCount; i++)
{
var sectors = sectorsPerTrack[i];
var trackLengthBits = 0;
using (var trackMem = new MemoryStream())
{
for (var j = 0; j < sectors; j++)
{
int bitsWritten;
var sectorData = reader.ReadBytes(256);
var diskData = ConvertSectorToGcr(sectorData, (byte)j, (byte)(i + 1), 0xA0, 0xA0, out bitsWritten);
trackMem.Write(diskData, 0, diskData.Length);
trackLengthBits += bitsWritten;
}
var density = densityTable[i];
// we pad the tracks with extra gap bytes to meet MNIB standards
while (trackMem.Length < standardTrackLengthBytes[density])
{
trackMem.WriteByte(0x55);
}
trackDatas.Add(trackMem.ToArray());
trackLengths.Add(trackLengthBits);
trackNumbers.Add(i * 2);
trackDensities.Add(densityTable[i]);
switch (source.Length)
{
case 174848: // 35 tracks no errors
trackCount = 35;
break;
case 175531: // 35 tracks with errors
trackCount = 35;
break;
case 196608: // 40 tracks no errors
trackCount = 40;
break;
case 197376: // 40 tracks with errors
trackCount = 40;
break;
default:
throw new Exception("Not able to identify capacity of the D64 file.");
}
}
return new Disk(trackDatas, trackNumbers, trackDensities, trackLengths, 84);
}
for (var i = 0; i < trackCount; i++)
{
var sectors = sectorsPerTrack[i];
var trackLengthBits = 0;
using (var trackMem = new MemoryStream())
{
for (var j = 0; j < sectors; j++)
{
int bitsWritten;
var sectorData = reader.ReadBytes(256);
var diskData = ConvertSectorToGcr(sectorData, (byte)j, (byte)(i + 1), 0xA0, 0xA0, out bitsWritten);
trackMem.Write(diskData, 0, diskData.Length);
trackLengthBits += bitsWritten;
}
var density = densityTable[i];
// we pad the tracks with extra gap bytes to meet MNIB standards
while (trackMem.Length < standardTrackLengthBytes[density])
{
trackMem.WriteByte(0x55);
}
trackDatas.Add(trackMem.ToArray());
trackLengths.Add(trackLengthBits);
trackNumbers.Add(i * 2);
trackDensities.Add(densityTable[i]);
}
}
return new Disk(trackDatas, trackNumbers, trackDensities, trackLengths, 84);
}
}
}
}

View File

@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
FillMissingTracks();
_originalMedia = SerializeTracks(_tracks);
Valid = true;
}
}
/// <summary>
/// Create an expanded representation of a magnetic disk.

View File

@ -9,54 +9,56 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
{
public static Disk Read(byte[] source)
{
var mem = new MemoryStream(source);
var reader = new BinaryReader(mem);
var id = new string(reader.ReadChars(8));
var trackDatas = new List<byte[]>();
var trackLengths = new List<int>();
var trackNumbers = new List<int>();
var trackDensities = new List<int>();
using (var mem = new MemoryStream(source))
{
var reader = new BinaryReader(mem);
var id = new string(reader.ReadChars(8));
var trackDatas = new List<byte[]>();
var trackLengths = new List<int>();
var trackNumbers = new List<int>();
var trackDensities = new List<int>();
if (id == @"GCR-1541")
{
if (id == @"GCR-1541")
{
reader.ReadByte(); //version
int trackCount = reader.ReadByte();
reader.ReadInt16(); //max track size in bytes
reader.ReadByte(); //version
int trackCount = reader.ReadByte();
reader.ReadInt16(); //max track size in bytes
var trackOffsetTable = new int[trackCount];
var trackSpeedTable = new int[trackCount];
var trackOffsetTable = new int[trackCount];
var trackSpeedTable = new int[trackCount];
for (var i = 0; i < trackCount; i++)
trackOffsetTable[i] = reader.ReadInt32();
for (var i = 0; i < trackCount; i++)
trackOffsetTable[i] = reader.ReadInt32();
for (var i = 0; i < trackCount; i++)
trackSpeedTable[i] = reader.ReadInt32();
for (var i = 0; i < trackCount; i++)
trackSpeedTable[i] = reader.ReadInt32();
for (var i = 0; i < trackCount; i++)
{
if (trackOffsetTable[i] > 0)
{
mem.Position = trackOffsetTable[i];
int trackLength = reader.ReadInt16();
var trackData = reader.ReadBytes(trackLength);
for (var i = 0; i < trackCount; i++)
{
if (trackOffsetTable[i] > 0)
{
mem.Position = trackOffsetTable[i];
int trackLength = reader.ReadInt16();
var trackData = reader.ReadBytes(trackLength);
trackDatas.Add(trackData);
trackLengths.Add(trackLength * 8);
trackDensities.Add(trackSpeedTable[i]);
trackNumbers.Add(i);
}
}
trackDatas.Add(trackData);
trackLengths.Add(trackLength * 8);
trackDensities.Add(trackSpeedTable[i]);
trackNumbers.Add(i);
}
}
if (trackSpeedTable.Any(ts => ts > 3 || ts < 0))
{
throw new Exception("Byte-level speeds are not yet supported in the G64 loader.");
}
if (trackSpeedTable.Any(ts => ts > 3 || ts < 0))
{
throw new Exception("Byte-level speeds are not yet supported in the G64 loader.");
}
return new Disk(trackDatas, trackNumbers, trackDensities, trackLengths, 84);
}
return new Disk(trackDatas, trackNumbers, trackDensities, trackLengths, 84);
}
return new Disk(84);
}
return new Disk(84);
}
}
}
}

View File

@ -32,6 +32,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
private int _countsBeforeRandomTransition;
[SaveState.SaveWithName("CurrentRNG")]
private int _rngCurrent;
[SaveState.SaveWithName("Clocks")]
private int _clocks;
[SaveState.SaveWithName("CpuClocks")]
private int _cpuClocks;
// Lehmer RNG
private void AdvanceRng()
@ -43,8 +47,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
private void ExecuteFlux()
{
for (_diskCycle = 0; _diskCycle < 16; _diskCycle++)
// This actually executes the main 16mhz clock
while (_clocks > 0)
{
_clocks--;
// rotate disk
if (_motorEnabled)
{
@ -144,7 +151,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
_diskSupplementaryCounter = 0;
}
_cpuClocks--;
if (_cpuClocks <= 0)
{
ExecuteSystem();
_cpuClocks = 16;
}
_diskDensityCounter++;
_diskCycle = (_diskCycle + 1) & 0xF;
}
}
}

View File

@ -11,18 +11,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
[SaveState.DoNotSave] private int _tempStep;
[SaveState.DoNotSave] private int _tempPrB1;
private int _overflowFlagDelaySr;
private int ReadVia1PrA()
{
return _bitHistory & 0xFF;
}
private int ReadVia1PrB()
{
return (_motorStep & 0x03) | (_motorEnabled ? 0x04 : 0x00) | (_sync ? 0x00 : 0x80);
}
private void ExecuteMotor()
{
_tempPrB1 = Via1.EffectivePrB;

View File

@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{
public sealed partial class Drive1541
{
[SaveState.SaveWithName("OverflowFlagDelayShiftRegister")]
private int _overflowFlagDelaySr;
private byte CpuPeek(ushort addr)
{
return unchecked((byte)Peek(addr));
}
private byte CpuRead(ushort addr)
{
return unchecked((byte)Read(addr));
}
private void CpuWrite(ushort addr, byte val)
{
Write(addr, val);
}
private bool ViaReadClock()
{
var inputClock = ReadMasterClk();
var outputClock = ReadDeviceClk();
return !(inputClock && outputClock);
}
private bool ViaReadData()
{
var inputData = ReadMasterData();
var outputData = ReadDeviceData();
return !(inputData && outputData);
}
private bool ViaReadAtn()
{
var inputAtn = ReadMasterAtn();
return !inputAtn;
}
private int ReadVia1PrA()
{
return _bitHistory & 0xFF;
}
private int ReadVia1PrB()
{
return (_motorStep & 0x03) | (_motorEnabled ? 0x04 : 0x00) | (_sync ? 0x00 : 0x80);
}
public int Peek(int addr)
{
switch (addr & 0xFC00)
{
case 0x1800:
return Via0.Peek(addr);
case 0x1C00:
return Via1.Peek(addr);
}
if ((addr & 0x8000) != 0)
return DriveRom.Peek(addr & 0x3FFF);
if ((addr & 0x1F00) < 0x800)
return _ram[addr & 0x7FF];
return (addr >> 8) & 0xFF;
}
public int PeekVia0(int addr)
{
return Via0.Peek(addr);
}
public int PeekVia1(int addr)
{
return Via1.Peek(addr);
}
public void Poke(int addr, int val)
{
switch (addr & 0xFC00)
{
case 0x1800:
Via0.Poke(addr, val);
break;
case 0x1C00:
Via1.Poke(addr, val);
break;
default:
if ((addr & 0x8000) == 0 && (addr & 0x1F00) < 0x800)
_ram[addr & 0x7FF] = val & 0xFF;
break;
}
}
public void PokeVia0(int addr, int val)
{
Via0.Poke(addr, val);
}
public void PokeVia1(int addr, int val)
{
Via1.Poke(addr, val);
}
public int Read(int addr)
{
switch (addr & 0xFC00)
{
case 0x1800:
return Via0.Read(addr);
case 0x1C00:
return Via1.Read(addr);
}
if ((addr & 0x8000) != 0)
return DriveRom.Read(addr & 0x3FFF);
if ((addr & 0x1F00) < 0x800)
return _ram[addr & 0x7FF];
return (addr >> 8) & 0xFF;
}
public void Write(int addr, int val)
{
switch (addr & 0xFC00)
{
case 0x1800:
Via0.Write(addr, val);
break;
case 0x1C00:
Via1.Write(addr, val);
break;
default:
if ((addr & 0x8000) == 0 && (addr & 0x1F00) < 0x800)
_ram[addr & 0x7FF] = val & 0xFF;
break;
}
}
public override bool ReadDeviceClk()
{
var viaOutputClock = (Via0.DdrB & 0x08) != 0 && (Via0.PrB & 0x08) != 0;
return !viaOutputClock;
}
public override bool ReadDeviceData()
{
var viaOutputData = (Via0.DdrB & 0x02) != 0 && (Via0.PrB & 0x02) != 0;
var viaInputAtn = ViaReadAtn();
var viaOutputAtna = (Via0.DdrB & 0x10) != 0 && (Via0.PrB & 0x10) != 0;
return !(viaOutputAtna ^ viaInputAtn) && !viaOutputData;
}
public override bool ReadDeviceLight()
{
return _driveLightOffTime > 0;
}
}
}

View File

@ -25,6 +25,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
private bool _byteReady;
[SaveState.SaveWithName("DriveCpuClockNumerator")]
private readonly int _driveCpuClockNum;
[SaveState.SaveWithName("DriveCpuClockDenominator")]
private readonly int _driveCpuClockDen;
[SaveState.SaveWithName("TrackNumber")]
private int _trackNumber;
[SaveState.SaveWithName("MotorEnabled")]
@ -75,74 +77,30 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
Via1 = Chip6522.Create(ReadVia1PrA, ReadVia1PrB);
_cpuClockNum = clockNum;
_driveCpuClockNum = clockDen*1000000; // 1mhz
}
private byte CpuPeek(ushort addr)
{
return unchecked((byte)Peek(addr));
}
private byte CpuRead(ushort addr)
{
return unchecked((byte) Read(addr));
}
private void CpuWrite(ushort addr, byte val)
{
Write(addr, val);
}
private bool ViaReadClock()
{
var inputClock = ReadMasterClk();
var outputClock = ReadDeviceClk();
return !(inputClock && outputClock);
}
private bool ViaReadData()
{
var inputData = ReadMasterData();
var outputData = ReadDeviceData();
return !(inputData && outputData);
}
private bool ViaReadAtn()
{
var inputAtn = ReadMasterAtn();
return !inputAtn;
_driveCpuClockNum = clockDen*16000000; // 16mhz
}
public override void ExecutePhase()
{
if (_cpuClockNum > _driveCpuClockNum)
_ratioDifference += _driveCpuClockNum;
while (_ratioDifference > _cpuClockNum)
{
_ratioDifference += _cpuClockNum - _driveCpuClockNum;
if (_ratioDifference > _cpuClockNum)
{
_ratioDifference -= _cpuClockNum;
return;
}
}
else if (_cpuClockNum <= _driveCpuClockNum)
{
_ratioDifference += _driveCpuClockNum - _cpuClockNum;
while (_ratioDifference > _driveCpuClockNum)
{
_ratioDifference -= _driveCpuClockNum;
ExecutePhaseInternal();
}
_ratioDifference -= _cpuClockNum;
_clocks++;
}
ExecutePhaseInternal();
}
private void ExecutePhaseInternal()
{
Via0.Ca1 = ViaReadAtn();
// clock output from 325572-01 drives CPU clock (phi0)
ExecuteMotor();
ExecuteFlux();
}
private void ExecuteSystem()
{
Via0.Ca1 = ViaReadAtn();
Via0.ExecutePhase();
Via1.ExecutePhase();
@ -220,111 +178,5 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{
_disk = null;
}
public int Peek(int addr)
{
switch (addr & 0xFC00)
{
case 0x1800:
return Via0.Peek(addr);
case 0x1C00:
return Via1.Peek(addr);
}
if ((addr & 0x8000) != 0)
return DriveRom.Peek(addr & 0x3FFF);
if ((addr & 0x1F00) < 0x800)
return _ram[addr & 0x7FF];
return (addr >> 8) & 0xFF;
}
public int PeekVia0(int addr)
{
return Via0.Peek(addr);
}
public int PeekVia1(int addr)
{
return Via1.Peek(addr);
}
public void Poke(int addr, int val)
{
switch (addr & 0xFC00)
{
case 0x1800:
Via0.Poke(addr, val);
break;
case 0x1C00:
Via1.Poke(addr, val);
break;
default:
if ((addr & 0x8000) == 0 && (addr & 0x1F00) < 0x800)
_ram[addr & 0x7FF] = val & 0xFF;
break;
}
}
public void PokeVia0(int addr, int val)
{
Via0.Poke(addr, val);
}
public void PokeVia1(int addr, int val)
{
Via1.Poke(addr, val);
}
public int Read(int addr)
{
switch (addr & 0xFC00)
{
case 0x1800:
return Via0.Read(addr);
case 0x1C00:
return Via1.Read(addr);
}
if ((addr & 0x8000) != 0)
return DriveRom.Read(addr & 0x3FFF);
if ((addr & 0x1F00) < 0x800)
return _ram[addr & 0x7FF];
return (addr >> 8) & 0xFF;
}
public void Write(int addr, int val)
{
switch (addr & 0xFC00)
{
case 0x1800:
Via0.Write(addr, val);
break;
case 0x1C00:
Via1.Write(addr, val);
break;
default:
if ((addr & 0x8000) == 0 && (addr & 0x1F00) < 0x800)
_ram[addr & 0x7FF] = val & 0xFF;
break;
}
}
public override bool ReadDeviceClk()
{
var viaOutputClock = (Via0.DdrB & 0x08) != 0 && (Via0.PrB & 0x08) != 0;
return !viaOutputClock;
}
public override bool ReadDeviceData()
{
var viaOutputData = (Via0.DdrB & 0x02) != 0 && (Via0.PrB & 0x02) != 0;
var viaInputAtn = ViaReadAtn();
var viaOutputAtna = (Via0.DdrB & 0x10) != 0 && (Via0.PrB & 0x10) != 0;
return !(viaOutputAtna ^ viaInputAtn) && !viaOutputData;
}
public override bool ReadDeviceLight()
{
return _driveLightOffTime > 0;
}
}
}