From f4f45f73a84daa2f62dc81bf5c90a3ce853c8249 Mon Sep 17 00:00:00 2001 From: Anthony Konzel Date: Fri, 4 Mar 2016 16:06:25 -0600 Subject: [PATCH] C64: Better lifecycle management and 1541-II support. --- .../BizHawk.Emulation.Cores.csproj | 1 + .../Computers/Commodore64/C64.ISettable.cs | 2 +- .../Computers/Commodore64/C64.Motherboard.cs | 1 + .../Computers/Commodore64/C64.cs | 36 ++- .../Commodore64/Cassette/TapeDrive.cs | 5 + .../Computers/Commodore64/Media/D64.cs | 226 +++++++++--------- .../Computers/Commodore64/Media/Disk.cs | 2 +- .../Computers/Commodore64/Media/G64.cs | 80 ++++--- .../Serial/Drive1541.FluxTransitions.cs | 17 +- .../Commodore64/Serial/Drive1541.Motor.cs | 12 - .../Commodore64/Serial/Drive1541.Registers.cs | 164 +++++++++++++ .../Computers/Commodore64/Serial/Drive1541.cs | 172 +------------ 12 files changed, 374 insertions(+), 344 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Registers.cs diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 50f0b3a832..728146771b 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -261,6 +261,7 @@ + diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs index 5ea9385b54..b0cf805828 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs @@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public enum DiskDriveType { - None, Commodore1541 + None, Commodore1541, Commodore1541II } } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs index 217b5aadff..071e3f2dff 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs @@ -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; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs index b14a3787e0..5f98b51a0a 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs @@ -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; + } } // ------------------------------------ diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/TapeDrive.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/TapeDrive.cs index d91a8975f3..2687e2824b 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/TapeDrive.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/TapeDrive.cs @@ -37,5 +37,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette { _tape = tape; } + + public void RemoveMedia() + { + _tape = null; + } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs index 5fd8bf9e2d..188f69acf8 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs @@ -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(); - var trackLengths = new List(); - var trackNumbers = new List(); - var trackDensities = new List(); - int trackCount; + using (var mem = new MemoryStream(source)) + { + var reader = new BinaryReader(mem); + var trackDatas = new List(); + var trackLengths = new List(); + var trackNumbers = new List(); + var trackDensities = new List(); + 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); + } + } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs index 339d7b215e..00175d06bb 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs @@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media FillMissingTracks(); _originalMedia = SerializeTracks(_tracks); Valid = true; - } + } /// /// Create an expanded representation of a magnetic disk. diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs index 1d22f557ef..2ddac42728 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs @@ -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(); - var trackLengths = new List(); - var trackNumbers = new List(); - var trackDensities = new List(); + using (var mem = new MemoryStream(source)) + { + var reader = new BinaryReader(mem); + var id = new string(reader.ReadChars(8)); + var trackDatas = new List(); + var trackLengths = new List(); + var trackNumbers = new List(); + var trackDensities = new List(); - 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); + } + } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs index ae2b18361e..903472aa28 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs @@ -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; } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Motor.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Motor.cs index 65dfca8b0f..b1b4087334 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Motor.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Motor.cs @@ -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; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Registers.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Registers.cs new file mode 100644 index 0000000000..9f0fb5a890 --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.Registers.cs @@ -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; + } + } +} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs index 306352c90d..2ce00085d4 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs @@ -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; - } } }