spaces to tabs in C64 files

This commit is contained in:
adelikat 2017-04-24 08:35:05 -05:00
parent 5247e1d357
commit 3dd5478efd
78 changed files with 6901 additions and 6896 deletions

View File

@ -7,57 +7,57 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
public partial class C64 : IDebuggable public partial class C64 : IDebuggable
{ {
[SaveState.DoNotSave] private IDebuggable _selectedDebuggable; [SaveState.DoNotSave] private IDebuggable _selectedDebuggable;
private IEnumerable<IDebuggable> GetAvailableDebuggables() private IEnumerable<IDebuggable> GetAvailableDebuggables()
{
yield return _board.Cpu;
if (_board.DiskDrive != null)
{
yield return _board.DiskDrive;
}
}
private void SetDefaultDebuggable()
{
_selectedDebuggable = GetAvailableDebuggables().First();
}
IDictionary<string, RegisterValue> IDebuggable.GetCpuFlagsAndRegisters()
{ {
if (_selectedDebuggable == null) yield return _board.Cpu;
{ if (_board.DiskDrive != null)
SetDefaultDebuggable(); {
} yield return _board.DiskDrive;
return _selectedDebuggable.GetCpuFlagsAndRegisters(); }
}
private void SetDefaultDebuggable()
{
_selectedDebuggable = GetAvailableDebuggables().First();
}
IDictionary<string, RegisterValue> IDebuggable.GetCpuFlagsAndRegisters()
{
if (_selectedDebuggable == null)
{
SetDefaultDebuggable();
}
return _selectedDebuggable.GetCpuFlagsAndRegisters();
} }
void IDebuggable.SetCpuRegister(string register, int value) void IDebuggable.SetCpuRegister(string register, int value)
{ {
if (_selectedDebuggable == null) if (_selectedDebuggable == null)
{ {
SetDefaultDebuggable(); SetDefaultDebuggable();
} }
_selectedDebuggable.SetCpuRegister(register, value); _selectedDebuggable.SetCpuRegister(register, value);
} }
bool IDebuggable.CanStep(StepType type) bool IDebuggable.CanStep(StepType type)
{ {
if (_selectedDebuggable == null) if (_selectedDebuggable == null)
{ {
SetDefaultDebuggable(); SetDefaultDebuggable();
} }
return _selectedDebuggable.CanStep(type); return _selectedDebuggable.CanStep(type);
} }
void IDebuggable.Step(StepType type) void IDebuggable.Step(StepType type)
{ {
if (_selectedDebuggable == null) if (_selectedDebuggable == null)
{ {
SetDefaultDebuggable(); SetDefaultDebuggable();
} }
_selectedDebuggable.Step(type); _selectedDebuggable.Step(type);
} }
[FeatureNotImplemented] [FeatureNotImplemented]
@ -66,10 +66,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
get { return _selectedDebuggable.TotalExecutedCycles; } get { return _selectedDebuggable.TotalExecutedCycles; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly IMemoryCallbackSystem _memoryCallbacks; private readonly IMemoryCallbackSystem _memoryCallbacks;
[SaveState.DoNotSave] [SaveState.DoNotSave]
IMemoryCallbackSystem IDebuggable.MemoryCallbacks { get { return _memoryCallbacks; } } IMemoryCallbackSystem IDebuggable.MemoryCallbacks { get { return _memoryCallbacks; } }
} }
} }

View File

@ -7,70 +7,70 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
public partial class C64 : IDisassemblable public partial class C64 : IDisassemblable
{ {
[SaveState.DoNotSave] private IDisassemblable _selectedDisassemblable; [SaveState.DoNotSave] private IDisassemblable _selectedDisassemblable;
private IEnumerable<IDisassemblable> GetAvailableDisassemblables() private IEnumerable<IDisassemblable> GetAvailableDisassemblables()
{
yield return _board.Cpu;
if (_board.DiskDrive != null)
{
yield return _board.DiskDrive;
}
}
private void SetDefaultDisassemblable()
{
_selectedDisassemblable = GetAvailableDisassemblables().First();
}
[SaveState.DoNotSave]
public string Cpu
{
get
{
if (_selectedDisassemblable == null)
{
SetDefaultDisassemblable();
}
return _selectedDisassemblable.Cpu;
}
set
{
var currentSelectedDisassemblable = _selectedDisassemblable;
_selectedDisassemblable = GetAvailableDisassemblables().FirstOrDefault(d => d.Cpu == value) ?? currentSelectedDisassemblable;
if (_selectedDisassemblable is IDebuggable)
{
_selectedDebuggable = _selectedDisassemblable as IDebuggable;
}
}
}
[SaveState.DoNotSave]
public string PCRegisterName
{ {
get yield return _board.Cpu;
{ if (_board.DiskDrive != null)
if (_selectedDisassemblable == null) {
{ yield return _board.DiskDrive;
SetDefaultDisassemblable(); }
}
return _selectedDisassemblable.PCRegisterName;
}
} }
[SaveState.DoNotSave] private void SetDefaultDisassemblable()
public IEnumerable<string> AvailableCpus
{ {
get { return GetAvailableDisassemblables().SelectMany(d => d.AvailableCpus); } _selectedDisassemblable = GetAvailableDisassemblables().First();
}
[SaveState.DoNotSave]
public string Cpu
{
get
{
if (_selectedDisassemblable == null)
{
SetDefaultDisassemblable();
}
return _selectedDisassemblable.Cpu;
}
set
{
var currentSelectedDisassemblable = _selectedDisassemblable;
_selectedDisassemblable = GetAvailableDisassemblables().FirstOrDefault(d => d.Cpu == value) ?? currentSelectedDisassemblable;
if (_selectedDisassemblable is IDebuggable)
{
_selectedDebuggable = _selectedDisassemblable as IDebuggable;
}
}
}
[SaveState.DoNotSave]
public string PCRegisterName
{
get
{
if (_selectedDisassemblable == null)
{
SetDefaultDisassemblable();
}
return _selectedDisassemblable.PCRegisterName;
}
}
[SaveState.DoNotSave]
public IEnumerable<string> AvailableCpus
{
get { return GetAvailableDisassemblables().SelectMany(d => d.AvailableCpus); }
} }
public string Disassemble(MemoryDomain m, uint addr, out int length) public string Disassemble(MemoryDomain m, uint addr, out int length)
{ {
if (_selectedDisassemblable == null) if (_selectedDisassemblable == null)
{ {
SetDefaultDisassemblable(); SetDefaultDisassemblable();
} }
return _selectedDisassemblable.Disassemble(m, addr, out length); return _selectedDisassemblable.Disassemble(m, addr, out length);
} }
} }
} }

View File

@ -5,6 +5,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public partial class C64 : IDriveLight public partial class C64 : IDriveLight
{ {
public bool DriveLightEnabled { get { return _board != null && (_board.CartPort.DriveLightEnabled || _board.Serial.DriveLightEnabled); } } public bool DriveLightEnabled { get { return _board != null && (_board.CartPort.DriveLightEnabled || _board.Serial.DriveLightEnabled); } }
public bool DriveLightOn { get { return _board != null && (_board.CartPort.DriveLightOn || _board.Serial.DriveLightOn);} } public bool DriveLightOn { get { return _board != null && (_board.CartPort.DriveLightOn || _board.Serial.DriveLightOn); } }
} }
} }

View File

@ -5,9 +5,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public partial class C64 : IInputPollable public partial class C64 : IInputPollable
{ {
public bool IsLagFrame { get; set; } public bool IsLagFrame { get; set; }
public int LagCount { get; set; } public int LagCount { get; set; }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public IInputCallbackSystem InputCallbacks { get; private set; } public IInputCallbackSystem InputCallbacks { get; private set; }
} }
} }

View File

@ -10,36 +10,36 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
private void SetupMemoryDomains(bool diskDriveEnabled) private void SetupMemoryDomains(bool diskDriveEnabled)
{ {
var domains = new List<MemoryDomain> var domains = new List<MemoryDomain>
{ {
C64MemoryDomainFactory.Create("System Bus", 0x10000, a => _board.Cpu.Peek(a), (a, v) => _board.Cpu.Poke(a, v)), C64MemoryDomainFactory.Create("System Bus", 0x10000, a => _board.Cpu.Peek(a), (a, v) => _board.Cpu.Poke(a, v)),
C64MemoryDomainFactory.Create("RAM", 0x10000, a => _board.Ram.Peek(a), (a, v) => _board.Ram.Poke(a, v)), C64MemoryDomainFactory.Create("RAM", 0x10000, a => _board.Ram.Peek(a), (a, v) => _board.Ram.Poke(a, v)),
C64MemoryDomainFactory.Create("CIA0", 0x10, a => _board.Cia0.Peek(a), (a, v) => _board.Cia0.Poke(a, v)), C64MemoryDomainFactory.Create("CIA0", 0x10, a => _board.Cia0.Peek(a), (a, v) => _board.Cia0.Poke(a, v)),
C64MemoryDomainFactory.Create("CIA1", 0x10, a => _board.Cia1.Peek(a), (a, v) => _board.Cia1.Poke(a, v)), C64MemoryDomainFactory.Create("CIA1", 0x10, a => _board.Cia1.Peek(a), (a, v) => _board.Cia1.Poke(a, v)),
C64MemoryDomainFactory.Create("VIC", 0x40, a => _board.Vic.Peek(a), (a, v) => _board.Vic.Poke(a, v)), C64MemoryDomainFactory.Create("VIC", 0x40, a => _board.Vic.Peek(a), (a, v) => _board.Vic.Poke(a, v)),
C64MemoryDomainFactory.Create("SID", 0x20, a => _board.Sid.Peek(a), (a, v) => _board.Sid.Poke(a, v)), C64MemoryDomainFactory.Create("SID", 0x20, a => _board.Sid.Peek(a), (a, v) => _board.Sid.Poke(a, v)),
}; };
if (diskDriveEnabled) if (diskDriveEnabled)
{ {
domains.AddRange(new[] domains.AddRange(new[]
{ {
C64MemoryDomainFactory.Create("1541 Bus", 0x10000, a => _board.DiskDrive.Peek(a), (a, v) => _board.DiskDrive.Poke(a, v)), C64MemoryDomainFactory.Create("1541 Bus", 0x10000, a => _board.DiskDrive.Peek(a), (a, v) => _board.DiskDrive.Poke(a, v)),
C64MemoryDomainFactory.Create("1541 RAM", 0x800, a => _board.DiskDrive.Peek(a), (a, v) => _board.DiskDrive.Poke(a, v)), C64MemoryDomainFactory.Create("1541 RAM", 0x800, a => _board.DiskDrive.Peek(a), (a, v) => _board.DiskDrive.Poke(a, v)),
C64MemoryDomainFactory.Create("1541 VIA0", 0x10, a => _board.DiskDrive.PeekVia0(a), (a, v) => _board.DiskDrive.PokeVia0(a, v)), C64MemoryDomainFactory.Create("1541 VIA0", 0x10, a => _board.DiskDrive.PeekVia0(a), (a, v) => _board.DiskDrive.PokeVia0(a, v)),
C64MemoryDomainFactory.Create("1541 VIA1", 0x10, a => _board.DiskDrive.PeekVia1(a), (a, v) => _board.DiskDrive.PokeVia1(a, v)) C64MemoryDomainFactory.Create("1541 VIA1", 0x10, a => _board.DiskDrive.PeekVia1(a), (a, v) => _board.DiskDrive.PokeVia1(a, v))
}); });
} }
_memoryDomains = new MemoryDomainList(domains); _memoryDomains = new MemoryDomainList(domains);
((BasicServiceProvider) ServiceProvider).Register(_memoryDomains); ((BasicServiceProvider)ServiceProvider).Register(_memoryDomains);
} }
private static class C64MemoryDomainFactory private static class C64MemoryDomainFactory
{ {
public static MemoryDomain Create(string name, int size, Func<int, int> peekByte, Action<int, int> pokeByte) public static MemoryDomain Create(string name, int size, Func<int, int> peekByte, Action<int, int> pokeByte)
{ {
return new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Little, addr => unchecked((byte)peekByte((int)addr)), (addr, val) => pokeByte(unchecked((int)addr), val), 1); return new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Little, addr => unchecked((byte)peekByte((int)addr)), (addr, val) => pokeByte(unchecked((int)addr), val), 1);
} }
} }
} }
} }

View File

@ -39,10 +39,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public class C64Settings public class C64Settings
{ {
[DisplayName("Border type")] [DisplayName("Border type")]
[Description("Select how to show the border area")] [Description("Select how to show the border area")]
[DefaultValue(BorderType.SmallProportional)] [DefaultValue(BorderType.SmallProportional)]
public BorderType BorderType { get; set; } public BorderType BorderType { get; set; }
public C64Settings Clone() public C64Settings Clone()
{ {
@ -62,22 +62,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
[DefaultValue(VicType.Pal)] [DefaultValue(VicType.Pal)]
public VicType VicType { get; set; } public VicType VicType { get; set; }
[DisplayName("SID type")] [DisplayName("SID type")]
[Description("Set the type of sound chip to use")] [Description("Set the type of sound chip to use")]
[DefaultValue(SidType.OldR2)] [DefaultValue(SidType.OldR2)]
public SidType SidType { get; set; } public SidType SidType { get; set; }
[DisplayName("Tape drive type")] [DisplayName("Tape drive type")]
[Description("Set the type of tape drive attached")] [Description("Set the type of tape drive attached")]
[DefaultValue(TapeDriveType.None)] [DefaultValue(TapeDriveType.None)]
public TapeDriveType TapeDriveType { get; set; } public TapeDriveType TapeDriveType { get; set; }
[DisplayName("Disk drive type")] [DisplayName("Disk drive type")]
[Description("Set the type of disk drive attached")] [Description("Set the type of disk drive attached")]
[DefaultValue(DiskDriveType.None)] [DefaultValue(DiskDriveType.None)]
public DiskDriveType DiskDriveType { get; set; } public DiskDriveType DiskDriveType { get; set; }
public C64SyncSettings Clone() public C64SyncSettings Clone()
{ {
return (C64SyncSettings)MemberwiseClone(); return (C64SyncSettings)MemberwiseClone();
} }
@ -93,29 +93,29 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
Pal, Ntsc, NtscOld, Drean Pal, Ntsc, NtscOld, Drean
} }
public enum CiaType public enum CiaType
{ {
Pal, Ntsc, PalRevA, NtscRevA Pal, Ntsc, PalRevA, NtscRevA
} }
public enum BorderType public enum BorderType
{ {
SmallProportional, SmallFixed, Normal, Full SmallProportional, SmallFixed, Normal, Full
} }
public enum SidType public enum SidType
{ {
OldR2, OldR3, OldR4AR, NewR5 OldR2, OldR3, OldR4AR, NewR5
} }
public enum TapeDriveType public enum TapeDriveType
{ {
None, Commodore1530 None, Commodore1530
} }
public enum DiskDriveType public enum DiskDriveType
{ {
None, Commodore1541, Commodore1541II None, Commodore1541, Commodore1541II
} }
} }
} }

View File

@ -15,36 +15,36 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
/// </summary> /// </summary>
public sealed partial class Motherboard public sealed partial class Motherboard
{ {
// chips // chips
public readonly Chip23128 BasicRom; public readonly Chip23128 BasicRom;
public readonly Chip23128 CharRom; public readonly Chip23128 CharRom;
public readonly Cia Cia0; public readonly Cia Cia0;
public readonly Cia Cia1; public readonly Cia Cia1;
public readonly Chip2114 ColorRam; public readonly Chip2114 ColorRam;
public readonly Chip6510 Cpu; public readonly Chip6510 Cpu;
public readonly Chip23128 KernalRom; public readonly Chip23128 KernalRom;
public readonly Chip90611401 Pla; public readonly Chip90611401 Pla;
public readonly Chip4864 Ram; public readonly Chip4864 Ram;
public readonly Sid Sid; public readonly Sid Sid;
public readonly Vic Vic; public readonly Vic Vic;
// ports // ports
public readonly CartridgePort CartPort; public readonly CartridgePort CartPort;
public readonly CassettePort Cassette; public readonly CassettePort Cassette;
public IController Controller; public IController Controller;
public readonly SerialPort Serial; public readonly SerialPort Serial;
public readonly TapeDrive TapeDrive; public readonly TapeDrive TapeDrive;
public readonly UserPort User; public readonly UserPort User;
// devices // devices
public readonly Drive1541 DiskDrive; public readonly Drive1541 DiskDrive;
// state // state
//public int address; //public int address;
public int Bus; public int Bus;
public bool InputRead; public bool InputRead;
public bool Irq; public bool Irq;
public bool Nmi; public bool Nmi;
private readonly C64 _c64; private readonly C64 _c64;
@ -58,115 +58,115 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
case C64.VicType.Pal: case C64.VicType.Pal:
clockNum = 17734475; clockNum = 17734475;
clockDen = 18; clockDen = 18;
break; break;
case C64.VicType.Ntsc: case C64.VicType.Ntsc:
clockNum = 14318181; clockNum = 14318181;
clockDen = 14; clockDen = 14;
break; break;
case C64.VicType.NtscOld: case C64.VicType.NtscOld:
clockNum = 11250000; clockNum = 11250000;
clockDen = 11; clockDen = 11;
break; break;
case C64.VicType.Drean: case C64.VicType.Drean:
clockNum = 14328225; clockNum = 14328225;
clockDen = 14; clockDen = 14;
break; break;
default: default:
throw new System.Exception(); throw new System.Exception();
} }
CartPort = new CartridgePort(); CartPort = new CartridgePort();
Cassette = new CassettePort(); Cassette = new CassettePort();
ColorRam = new Chip2114(); ColorRam = new Chip2114();
Cpu = new Chip6510(); Cpu = new Chip6510();
Pla = new Chip90611401(); Pla = new Chip90611401();
Ram = new Chip4864(); Ram = new Chip4864();
Serial = new SerialPort(); Serial = new SerialPort();
switch (sidType) switch (sidType)
{ {
case C64.SidType.OldR2: case C64.SidType.OldR2:
Sid = Chip6581R2.Create(44100, clockNum, clockDen); Sid = Chip6581R2.Create(44100, clockNum, clockDen);
break; break;
case C64.SidType.OldR3: case C64.SidType.OldR3:
Sid = Chip6581R3.Create(44100, clockNum, clockDen); Sid = Chip6581R3.Create(44100, clockNum, clockDen);
break; break;
case C64.SidType.OldR4AR: case C64.SidType.OldR4AR:
Sid = Chip6581R4AR.Create(44100, clockNum, clockDen); Sid = Chip6581R4AR.Create(44100, clockNum, clockDen);
break; break;
case C64.SidType.NewR5: case C64.SidType.NewR5:
Sid = Chip8580R5.Create(44100, clockNum, clockDen); Sid = Chip8580R5.Create(44100, clockNum, clockDen);
break; break;
} }
switch (initRegion) switch (initRegion)
{ {
case C64.VicType.Ntsc: case C64.VicType.Ntsc:
Vic = Chip6567R8.Create(borderType); Vic = Chip6567R8.Create(borderType);
Cia0 = Chip6526.Create(C64.CiaType.Ntsc, Input_ReadKeyboard, Input_ReadJoysticks); Cia0 = Chip6526.Create(C64.CiaType.Ntsc, Input_ReadKeyboard, Input_ReadJoysticks);
Cia1 = Chip6526.Create(C64.CiaType.Ntsc, Cia1_ReadPortA); Cia1 = Chip6526.Create(C64.CiaType.Ntsc, Cia1_ReadPortA);
break; break;
case C64.VicType.Pal: case C64.VicType.Pal:
Vic = Chip6569.Create(borderType); Vic = Chip6569.Create(borderType);
Cia0 = Chip6526.Create(C64.CiaType.Pal, Input_ReadKeyboard, Input_ReadJoysticks); Cia0 = Chip6526.Create(C64.CiaType.Pal, Input_ReadKeyboard, Input_ReadJoysticks);
Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA); Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA);
break; break;
case C64.VicType.NtscOld: case C64.VicType.NtscOld:
Vic = Chip6567R56A.Create(borderType); Vic = Chip6567R56A.Create(borderType);
Cia0 = Chip6526.Create(C64.CiaType.NtscRevA, Input_ReadKeyboard, Input_ReadJoysticks); Cia0 = Chip6526.Create(C64.CiaType.NtscRevA, Input_ReadKeyboard, Input_ReadJoysticks);
Cia1 = Chip6526.Create(C64.CiaType.NtscRevA, Cia1_ReadPortA); Cia1 = Chip6526.Create(C64.CiaType.NtscRevA, Cia1_ReadPortA);
break; break;
case C64.VicType.Drean: case C64.VicType.Drean:
Vic = Chip6572.Create(borderType); Vic = Chip6572.Create(borderType);
Cia0 = Chip6526.Create(C64.CiaType.Pal, Input_ReadKeyboard, Input_ReadJoysticks); Cia0 = Chip6526.Create(C64.CiaType.Pal, Input_ReadKeyboard, Input_ReadJoysticks);
Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA); Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA);
break; break;
} }
User = new UserPort(); User = new UserPort();
ClockNumerator = clockNum; ClockNumerator = clockNum;
ClockDenominator = clockDen; ClockDenominator = clockDen;
// Initialize disk drive // Initialize disk drive
switch (diskDriveType) switch (diskDriveType)
{ {
case C64.DiskDriveType.Commodore1541: case C64.DiskDriveType.Commodore1541:
case C64.DiskDriveType.Commodore1541II: case C64.DiskDriveType.Commodore1541II:
DiskDrive = new Drive1541(ClockNumerator, ClockDenominator); DiskDrive = new Drive1541(ClockNumerator, ClockDenominator);
Serial.Connect(DiskDrive); Serial.Connect(DiskDrive);
break; break;
} }
// Initialize tape drive // Initialize tape drive
switch (tapeDriveType) switch (tapeDriveType)
{ {
case C64.TapeDriveType.Commodore1530: case C64.TapeDriveType.Commodore1530:
TapeDrive = new TapeDrive(); TapeDrive = new TapeDrive();
Cassette.Connect(TapeDrive); Cassette.Connect(TapeDrive);
break; break;
} }
BasicRom = new Chip23128(); BasicRom = new Chip23128();
CharRom = new Chip23128(); CharRom = new Chip23128();
KernalRom = new Chip23128(); KernalRom = new Chip23128();
} }
[SaveState.DoNotSave] public int ClockNumerator { get; private set; } [SaveState.DoNotSave] public int ClockNumerator { get; private set; }
[SaveState.DoNotSave] public int ClockDenominator { get; private set; } [SaveState.DoNotSave] public int ClockDenominator { get; private set; }
// ----------------------------------------- // -----------------------------------------
public void Execute() public void Execute()
{ {
_vicBank = (0x3 - ((Cia1.PrA | ~Cia1.DdrA) & 0x3)) << 14; _vicBank = (0x3 - ((Cia1.PrA | ~Cia1.DdrA) & 0x3)) << 14;
Vic.ExecutePhase(); Vic.ExecutePhase();
CartPort.ExecutePhase(); CartPort.ExecutePhase();
Cassette.ExecutePhase(); Cassette.ExecutePhase();
Serial.ExecutePhase(); Serial.ExecutePhase();
Sid.ExecutePhase(); Sid.ExecutePhase();
Cia0.ExecutePhase(); Cia0.ExecutePhase();
Cia1.ExecutePhase(); Cia1.ExecutePhase();
Cpu.ExecutePhase(); Cpu.ExecutePhase();
} }
public void Flush() public void Flush()
@ -190,19 +190,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
Vic.HardReset(); Vic.HardReset();
User.HardReset(); User.HardReset();
Cassette.HardReset(); Cassette.HardReset();
Serial.HardReset(); Serial.HardReset();
Cpu.HardReset(); Cpu.HardReset();
CartPort.HardReset(); CartPort.HardReset();
} }
public void Init() public void Init()
{ {
CartPort.ReadOpenBus = ReadOpenBus; CartPort.ReadOpenBus = ReadOpenBus;
Cassette.ReadDataOutput = CassPort_ReadDataOutput; Cassette.ReadDataOutput = CassPort_ReadDataOutput;
Cassette.ReadMotor = CassPort_ReadMotor; Cassette.ReadMotor = CassPort_ReadMotor;
Cia0.ReadFlag = Cassette.ReadDataInputBuffer; Cia0.ReadFlag = Cassette.ReadDataInputBuffer;
Cpu.PeekMemory = Pla.Peek; Cpu.PeekMemory = Pla.Peek;
Cpu.PokeMemory = Pla.Poke; Cpu.PokeMemory = Pla.Poke;
@ -215,7 +215,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
Cpu.WriteMemory = Pla.Write; Cpu.WriteMemory = Pla.Write;
Cpu.WriteMemoryPort = Cpu_WriteMemoryPort; Cpu.WriteMemoryPort = Cpu_WriteMemoryPort;
Pla.PeekBasicRom = BasicRom.Peek; Pla.PeekBasicRom = BasicRom.Peek;
Pla.PeekCartridgeHi = CartPort.PeekHiRom; Pla.PeekCartridgeHi = CartPort.PeekHiRom;
Pla.PeekCartridgeLo = CartPort.PeekLoRom; Pla.PeekCartridgeLo = CartPort.PeekLoRom;
Pla.PeekCharRom = CharRom.Peek; Pla.PeekCharRom = CharRom.Peek;
@ -276,13 +276,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
Sid.ReadPotX = Sid_ReadPotX; Sid.ReadPotX = Sid_ReadPotX;
Sid.ReadPotY = Sid_ReadPotY; Sid.ReadPotY = Sid_ReadPotY;
Vic.ReadMemory = Vic_ReadMemory; Vic.ReadMemory = Vic_ReadMemory;
Vic.ReadColorRam = ColorRam.Read; Vic.ReadColorRam = ColorRam.Read;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }

View File

@ -7,27 +7,27 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
public sealed partial class Motherboard public sealed partial class Motherboard
{ {
private int _lastReadVicAddress = 0x3FFF; private int _lastReadVicAddress = 0x3FFF;
private int _lastReadVicData = 0xFF; private int _lastReadVicData = 0xFF;
private int _vicBank = 0xC000; private int _vicBank = 0xC000;
private bool CassPort_ReadDataOutput() private bool CassPort_ReadDataOutput()
{ {
return (Cpu.PortData & 0x08) != 0; return (Cpu.PortData & 0x08) != 0;
} }
private bool CassPort_ReadMotor() private bool CassPort_ReadMotor()
{ {
return (Cpu.PortData & 0x20) != 0; return (Cpu.PortData & 0x20) != 0;
} }
/* /*
private bool Cia0_ReadCnt() private bool Cia0_ReadCnt()
{ {
return User.ReadCounter1() && Cia0.ReadCntBuffer(); return User.ReadCounter1() && Cia0.ReadCntBuffer();
} }
private int Cia0_ReadPortA() private int Cia0_ReadPortA()
{ {
return cia0InputLatchA; return cia0InputLatchA;
} }
@ -37,12 +37,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
return cia0InputLatchB; return cia0InputLatchB;
} }
private bool Cia0_ReadSP() private bool Cia0_ReadSP()
{ {
return User.ReadSerial1() && Cia0.ReadSpBuffer(); return User.ReadSerial1() && Cia0.ReadSpBuffer();
} }
private bool Cia1_ReadSP() private bool Cia1_ReadSP()
{ {
return User.ReadSerial2() && Cia1.ReadSpBuffer(); return User.ReadSerial2() && Cia1.ReadSpBuffer();
} }
@ -51,21 +51,21 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
return User.ReadCounter2() && Cia1.ReadCntBuffer(); return User.ReadCounter2() && Cia1.ReadCntBuffer();
} }
*/ */
private int Cia1_ReadPortA() private int Cia1_ReadPortA()
{ {
// the low bits are actually the VIC memory address. // the low bits are actually the VIC memory address.
return (SerPort_ReadDataOut() && Serial.ReadDeviceData() ? 0x80 : 0x00) | return (SerPort_ReadDataOut() && Serial.ReadDeviceData() ? 0x80 : 0x00) |
(SerPort_ReadClockOut() && Serial.ReadDeviceClock() ? 0x40 : 0x00); (SerPort_ReadClockOut() && Serial.ReadDeviceClock() ? 0x40 : 0x00);
} }
private int Cia1_ReadPortB() private int Cia1_ReadPortB()
{ {
return 0xFF; return 0xFF;
} }
private int Cpu_ReadPort() private int Cpu_ReadPort()
{ {
var data = 0x1F; var data = 0x1F;
if (!Cassette.ReadSenseBuffer()) if (!Cassette.ReadSenseBuffer())
@ -73,37 +73,37 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
return data; return data;
} }
private void Cpu_WriteMemoryPort(int addr, int val) private void Cpu_WriteMemoryPort(int addr, int val)
{ {
Pla.WriteMemory(addr, Bus); Pla.WriteMemory(addr, Bus);
} }
private bool Glue_ReadIRQ() private bool Glue_ReadIRQ()
{ {
return Cia0.ReadIrq() && Vic.ReadIrq() && CartPort.ReadIrq(); return Cia0.ReadIrq() && Vic.ReadIrq() && CartPort.ReadIrq();
} }
private bool Glue_ReadNMI() private bool Glue_ReadNMI()
{ {
return !_restorePressed && Cia1.ReadIrq() && CartPort.ReadNmi(); return !_restorePressed && Cia1.ReadIrq() && CartPort.ReadNmi();
} }
private bool[] Input_ReadJoysticks() private bool[] Input_ReadJoysticks()
{ {
return _joystickPressed; return _joystickPressed;
} }
private bool[] Input_ReadKeyboard() private bool[] Input_ReadKeyboard()
{ {
return _keyboardPressed; return _keyboardPressed;
} }
private bool Pla_ReadCharen() private bool Pla_ReadCharen()
{ {
return (Cpu.PortData & 0x04) != 0; return (Cpu.PortData & 0x04) != 0;
} }
private int Pla_ReadCia0(int addr) private int Pla_ReadCia0(int addr)
{ {
if (addr == 0xDC00 || addr == 0xDC01) if (addr == 0xDC00 || addr == 0xDC01)
{ {
@ -112,70 +112,70 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
return Cia0.Read(addr); return Cia0.Read(addr);
} }
private int Pla_ReadColorRam(int addr) private int Pla_ReadColorRam(int addr)
{ {
var result = Bus; var result = Bus;
result &= 0xF0; result &= 0xF0;
result |= ColorRam.Read(addr); result |= ColorRam.Read(addr);
return result; return result;
} }
private bool Pla_ReadHiRam() private bool Pla_ReadHiRam()
{ {
return (Cpu.PortData & 0x02) != 0; return (Cpu.PortData & 0x02) != 0;
} }
private bool Pla_ReadLoRam() private bool Pla_ReadLoRam()
{ {
return (Cpu.PortData & 0x01) != 0; return (Cpu.PortData & 0x01) != 0;
} }
private int Pla_ReadExpansion0(int addr) private int Pla_ReadExpansion0(int addr)
{ {
return CartPort.IsConnected ? CartPort.ReadLoExp(addr) : _lastReadVicData; return CartPort.IsConnected ? CartPort.ReadLoExp(addr) : _lastReadVicData;
} }
private int Pla_ReadExpansion1(int addr) private int Pla_ReadExpansion1(int addr)
{ {
return CartPort.IsConnected ? CartPort.ReadHiExp(addr) : _lastReadVicData; return CartPort.IsConnected ? CartPort.ReadHiExp(addr) : _lastReadVicData;
} }
private bool SerPort_ReadAtnOut() private bool SerPort_ReadAtnOut()
{ {
return !((Cia1.DdrA & 0x08) != 0 && (Cia1.PrA & 0x08) != 0); return !((Cia1.DdrA & 0x08) != 0 && (Cia1.PrA & 0x08) != 0);
} }
private bool SerPort_ReadClockOut() private bool SerPort_ReadClockOut()
{ {
return !((Cia1.DdrA & 0x10) != 0 && (Cia1.PrA & 0x10) != 0); return !((Cia1.DdrA & 0x10) != 0 && (Cia1.PrA & 0x10) != 0);
} }
private bool SerPort_ReadDataOut() private bool SerPort_ReadDataOut()
{ {
return !((Cia1.DdrA & 0x20) != 0 && (Cia1.PrA & 0x20) != 0); return !((Cia1.DdrA & 0x20) != 0 && (Cia1.PrA & 0x20) != 0);
} }
private int Sid_ReadPotX() private int Sid_ReadPotX()
{ {
return 0; return 0;
} }
private int Sid_ReadPotY() private int Sid_ReadPotY()
{ {
return 0; return 0;
} }
private int Vic_ReadMemory(int addr) private int Vic_ReadMemory(int addr)
{ {
// the system sees (cia1.PortAData & 0x3) but we use a shortcut // the system sees (cia1.PortAData & 0x3) but we use a shortcut
_lastReadVicAddress = addr | _vicBank; _lastReadVicAddress = addr | _vicBank;
_lastReadVicData = Pla.VicRead(_lastReadVicAddress); _lastReadVicData = Pla.VicRead(_lastReadVicAddress);
return _lastReadVicData; return _lastReadVicData;
} }
private int ReadOpenBus() private int ReadOpenBus()
{ {
return _lastReadVicData; return _lastReadVicData;
} }
} }
} }

View File

@ -15,45 +15,45 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
)] )]
[ServiceNotApplicable(typeof(ISettable<,>))] [ServiceNotApplicable(typeof(ISettable<,>))]
public sealed partial class C64 : IEmulator, IRegionable public sealed partial class C64 : IEmulator, IRegionable
{ {
#region Internals #region Internals
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int _cyclesPerFrame; private readonly int _cyclesPerFrame;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public GameInfo Game; public GameInfo Game;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public IEnumerable<byte[]> Roms { get; private set; } public IEnumerable<byte[]> Roms { get; private set; }
[SaveState.DoNotSave] [SaveState.DoNotSave]
private static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition private static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition
{ {
Name = "Commodore 64 Controller", Name = "Commodore 64 Controller",
BoolButtons = BoolButtons =
{ {
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button", "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button",
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button", "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button",
"Key Left Arrow", "Key 1", "Key 2", "Key 3", "Key 4", "Key 5", "Key 6", "Key 7", "Key 8", "Key 9", "Key 0", "Key Plus", "Key Minus", "Key Pound", "Key Clear/Home", "Key Insert/Delete", "Key Left Arrow", "Key 1", "Key 2", "Key 3", "Key 4", "Key 5", "Key 6", "Key 7", "Key 8", "Key 9", "Key 0", "Key Plus", "Key Minus", "Key Pound", "Key Clear/Home", "Key Insert/Delete",
"Key Control", "Key Q", "Key W", "Key E", "Key R", "Key T", "Key Y", "Key U", "Key I", "Key O", "Key P", "Key At", "Key Asterisk", "Key Up Arrow", "Key Restore", "Key Control", "Key Q", "Key W", "Key E", "Key R", "Key T", "Key Y", "Key U", "Key I", "Key O", "Key P", "Key At", "Key Asterisk", "Key Up Arrow", "Key Restore",
"Key Run/Stop", "Key Lck", "Key A", "Key S", "Key D", "Key F", "Key G", "Key H", "Key J", "Key K", "Key L", "Key Colon", "Key Semicolon", "Key Equal", "Key Return", "Key Run/Stop", "Key Lck", "Key A", "Key S", "Key D", "Key F", "Key G", "Key H", "Key J", "Key K", "Key L", "Key Colon", "Key Semicolon", "Key Equal", "Key Return",
"Key Commodore", "Key Left Shift", "Key Z", "Key X", "Key C", "Key V", "Key B", "Key N", "Key M", "Key Comma", "Key Period", "Key Slash", "Key Right Shift", "Key Cursor Up/Down", "Key Cursor Left/Right", "Key Commodore", "Key Left Shift", "Key Z", "Key X", "Key C", "Key V", "Key B", "Key N", "Key M", "Key Comma", "Key Period", "Key Slash", "Key Right Shift", "Key Cursor Up/Down", "Key Cursor Left/Right",
"Key Space", "Key Space",
"Key F1", "Key F3", "Key F5", "Key F7" "Key F1", "Key F3", "Key F5", "Key F7"
} }
}; };
[SaveState.SaveWithName("Board")] [SaveState.SaveWithName("Board")]
private Motherboard _board; private Motherboard _board;
private int _frameCycles; private int _frameCycles;
#endregion #endregion
#region Ctor #region Ctor
public C64(CoreComm comm, IEnumerable<byte[]> roms, object settings, object syncSettings) public C64(CoreComm comm, IEnumerable<byte[]> roms, object settings, object syncSettings)
{ {
PutSyncSettings((C64SyncSettings)syncSettings ?? new C64SyncSettings()); PutSyncSettings((C64SyncSettings)syncSettings ?? new C64SyncSettings());
PutSettings((C64Settings)settings ?? new C64Settings()); PutSettings((C64Settings)settings ?? new C64Settings());
@ -61,108 +61,108 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
ServiceProvider = new BasicServiceProvider(this); ServiceProvider = new BasicServiceProvider(this);
InputCallbacks = new InputCallbackSystem(); InputCallbacks = new InputCallbackSystem();
CoreComm = comm; CoreComm = comm;
Roms = roms; Roms = roms;
Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType); Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType);
_cyclesPerFrame = _board.Vic.CyclesPerFrame; _cyclesPerFrame = _board.Vic.CyclesPerFrame;
SetupMemoryDomains(_board.DiskDrive != null); SetupMemoryDomains(_board.DiskDrive != null);
_memoryCallbacks = new MemoryCallbackSystem(); _memoryCallbacks = new MemoryCallbackSystem();
HardReset(); HardReset();
switch (SyncSettings.VicType) switch (SyncSettings.VicType)
{ {
case VicType.Ntsc: case VicType.Ntsc:
case VicType.Drean: case VicType.Drean:
case VicType.NtscOld: case VicType.NtscOld:
Region = DisplayType.NTSC; Region = DisplayType.NTSC;
break; break;
case VicType.Pal: case VicType.Pal:
Region = DisplayType.PAL; Region = DisplayType.PAL;
break; break;
} }
if (_board.Sid != null) if (_board.Sid != null)
{ {
_soundProvider = new DCFilter(_board.Sid, 512); _soundProvider = new DCFilter(_board.Sid, 512);
((BasicServiceProvider)ServiceProvider).Register<ISoundProvider>(_soundProvider); ((BasicServiceProvider)ServiceProvider).Register<ISoundProvider>(_soundProvider);
} }
DeterministicEmulation = true; DeterministicEmulation = true;
((BasicServiceProvider) ServiceProvider).Register<IVideoProvider>(_board.Vic); ((BasicServiceProvider)ServiceProvider).Register<IVideoProvider>(_board.Vic);
((BasicServiceProvider) ServiceProvider).Register<IDriveLight>(this); ((BasicServiceProvider)ServiceProvider).Register<IDriveLight>(this);
} }
#endregion #endregion
#region IDisposable #region IDisposable
public void Dispose() public void Dispose()
{ {
if (_board != null) if (_board != null)
{ {
if (_board.TapeDrive != null) if (_board.TapeDrive != null)
{ {
_board.TapeDrive.RemoveMedia(); _board.TapeDrive.RemoveMedia();
} }
if (_board.DiskDrive != null) if (_board.DiskDrive != null)
{ {
_board.DiskDrive.RemoveMedia(); _board.DiskDrive.RemoveMedia();
} }
_board = null; _board = null;
} }
} }
#endregion #endregion
#region IRegionable #region IRegionable
[SaveState.DoNotSave]
public DisplayType Region
{
get;
private set;
}
#endregion
#region IEmulator
[SaveState.DoNotSave]
public CoreComm CoreComm { get; private set; }
[SaveState.DoNotSave]
public string SystemId { get { return "C64"; } }
[SaveState.DoNotSave]
public string BoardName { get { return null; } }
[SaveState.SaveWithName("DeterministicEmulation")]
public bool DeterministicEmulation { get; set; }
[SaveState.SaveWithName("Frame")]
public int Frame { get; set; }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } } public DisplayType Region
[SaveState.DoNotSave] {
public IController Controller { get { return _board.Controller; } set { _board.Controller = value; } } get;
[SaveState.DoNotSave] private set;
public IEmulatorServiceProvider ServiceProvider { get; private set; } }
public void ResetCounters() #endregion
{
Frame = 0;
LagCount = 0;
IsLagFrame = false;
_frameCycles = 0;
}
// process frame #region IEmulator
public void FrameAdvance(bool render, bool rendersound)
{ [SaveState.DoNotSave]
do public CoreComm CoreComm { get; private set; }
{ [SaveState.DoNotSave]
DoCycle(); public string SystemId { get { return "C64"; } }
} [SaveState.DoNotSave]
while (_frameCycles != 0); public string BoardName { get { return null; } }
} [SaveState.SaveWithName("DeterministicEmulation")]
public bool DeterministicEmulation { get; set; }
[SaveState.SaveWithName("Frame")]
public int Frame { get; set; }
[SaveState.DoNotSave]
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } }
[SaveState.DoNotSave]
public IController Controller { get { return _board.Controller; } set { _board.Controller = value; } }
[SaveState.DoNotSave]
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public void ResetCounters()
{
Frame = 0;
LagCount = 0;
IsLagFrame = false;
_frameCycles = 0;
}
// process frame
public void FrameAdvance(bool render, bool rendersound)
{
do
{
DoCycle();
}
while (_frameCycles != 0);
}
#endregion #endregion
@ -175,32 +175,33 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
private void DoCycle() private void DoCycle()
{ {
if (_frameCycles == 0) { if (_frameCycles == 0)
{
_board.InputRead = false; _board.InputRead = false;
_board.PollInput(); _board.PollInput();
_board.Cpu.LagCycles = 0; _board.Cpu.LagCycles = 0;
} }
_board.Execute(); _board.Execute();
_frameCycles++; _frameCycles++;
if (_frameCycles != _cyclesPerFrame) if (_frameCycles != _cyclesPerFrame)
{ {
return; return;
} }
_board.Flush(); _board.Flush();
IsLagFrame = !_board.InputRead; IsLagFrame = !_board.InputRead;
if (IsLagFrame) if (IsLagFrame)
LagCount++; LagCount++;
_frameCycles -= _cyclesPerFrame; _frameCycles -= _cyclesPerFrame;
Frame++; Frame++;
} }
private byte[] GetFirmware(int length, params string[] names) private byte[] GetFirmware(int length, params string[] names)
{ {
var result = names.Select(n => CoreComm.CoreFileProvider.GetFirmware("C64", n, false)).FirstOrDefault(b => b != null && b.Length == length); var result = names.Select(n => CoreComm.CoreFileProvider.GetFirmware("C64", n, false)).FirstOrDefault(b => b != null && b.Length == length);
if (result == null) if (result == null)
throw new MissingFirmwareException(string.Format("At least one of these firmwares is required: {0}", string.Join(", ", names))); throw new MissingFirmwareException(string.Format("At least one of these firmwares is required: {0}", string.Join(", ", names)));
return result; return result;
@ -208,129 +209,129 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
private void Init(VicType initRegion, BorderType borderType, SidType sidType, TapeDriveType tapeDriveType, DiskDriveType diskDriveType) private void Init(VicType initRegion, BorderType borderType, SidType sidType, TapeDriveType tapeDriveType, DiskDriveType diskDriveType)
{ {
// Force certain drive types to be available depending on ROM type // Force certain drive types to be available depending on ROM type
foreach (var rom in Roms) foreach (var rom in Roms)
{ {
switch (C64FormatFinder.GetFormat(rom)) switch (C64FormatFinder.GetFormat(rom))
{ {
case C64Format.D64: case C64Format.D64:
case C64Format.G64: case C64Format.G64:
case C64Format.X64: case C64Format.X64:
if (diskDriveType == DiskDriveType.None) if (diskDriveType == DiskDriveType.None)
diskDriveType = DiskDriveType.Commodore1541; diskDriveType = DiskDriveType.Commodore1541;
break; break;
case C64Format.T64: case C64Format.T64:
case C64Format.TAP: case C64Format.TAP:
if (tapeDriveType == TapeDriveType.None) if (tapeDriveType == TapeDriveType.None)
{ {
tapeDriveType = TapeDriveType.Commodore1530; tapeDriveType = TapeDriveType.Commodore1530;
} }
break; break;
case C64Format.CRT: case C64Format.CRT:
// Nothing required. // Nothing required.
break; break;
case C64Format.Unknown: case C64Format.Unknown:
if (rom.Length >= 0xFE00) if (rom.Length >= 0xFE00)
{ {
throw new Exception("The image format is not known, and too large to be used as a PRG."); throw new Exception("The image format is not known, and too large to be used as a PRG.");
} }
if (diskDriveType == DiskDriveType.None) if (diskDriveType == DiskDriveType.None)
diskDriveType = DiskDriveType.Commodore1541; diskDriveType = DiskDriveType.Commodore1541;
break; break;
default: default:
throw new Exception("The image format is not yet supported by the Commodore 64 core."); throw new Exception("The image format is not yet supported by the Commodore 64 core.");
} }
} }
_board = new Motherboard(this, initRegion, borderType, sidType, tapeDriveType, diskDriveType); _board = new Motherboard(this, initRegion, borderType, sidType, tapeDriveType, diskDriveType);
InitRoms(diskDriveType); InitRoms(diskDriveType);
_board.Init(); _board.Init();
// configure video // configure video
CoreComm.VsyncDen = _board.Vic.CyclesPerFrame; CoreComm.VsyncDen = _board.Vic.CyclesPerFrame;
CoreComm.VsyncNum = _board.Vic.CyclesPerSecond; CoreComm.VsyncNum = _board.Vic.CyclesPerSecond;
} }
private void InitMedia() private void InitMedia()
{ {
foreach (var rom in Roms) foreach (var rom in Roms)
{ {
switch (C64FormatFinder.GetFormat(rom)) switch (C64FormatFinder.GetFormat(rom))
{ {
case C64Format.D64: case C64Format.D64:
var d64 = D64.Read(rom); var d64 = D64.Read(rom);
if (d64 != null) if (d64 != null)
{ {
_board.DiskDrive.InsertMedia(d64); _board.DiskDrive.InsertMedia(d64);
} }
break; break;
case C64Format.G64: case C64Format.G64:
var g64 = G64.Read(rom); var g64 = G64.Read(rom);
if (g64 != null) if (g64 != null)
{ {
_board.DiskDrive.InsertMedia(g64); _board.DiskDrive.InsertMedia(g64);
} }
break; break;
case C64Format.CRT: case C64Format.CRT:
var cart = CartridgeDevice.Load(rom); var cart = CartridgeDevice.Load(rom);
if (cart != null) if (cart != null)
{ {
_board.CartPort.Connect(cart); _board.CartPort.Connect(cart);
} }
break; break;
case C64Format.TAP: case C64Format.TAP:
var tape = Tape.Load(rom); var tape = Tape.Load(rom);
if (tape != null) if (tape != null)
{ {
_board.TapeDrive.Insert(tape); _board.TapeDrive.Insert(tape);
} }
break; break;
case C64Format.Unknown: case C64Format.Unknown:
var prgDisk = new DiskBuilder var prgDisk = new DiskBuilder
{ {
Entries = new List<DiskBuilder.Entry> Entries = new List<DiskBuilder.Entry>
{ {
new DiskBuilder.Entry new DiskBuilder.Entry
{ {
Closed = true, Closed = true,
Data = rom, Data = rom,
Locked = false, Locked = false,
Name = "PRG", Name = "PRG",
RecordLength = 0, RecordLength = 0,
Type = DiskBuilder.FileType.Program Type = DiskBuilder.FileType.Program
} }
} }
}.Build(); }.Build();
if (prgDisk != null) if (prgDisk != null)
{ {
_board.DiskDrive.InsertMedia(prgDisk); _board.DiskDrive.InsertMedia(prgDisk);
} }
break; break;
} }
} }
} }
private void InitRoms(DiskDriveType diskDriveType) private void InitRoms(DiskDriveType diskDriveType)
{ {
_board.BasicRom.Flash(GetFirmware(0x2000, "Basic")); _board.BasicRom.Flash(GetFirmware(0x2000, "Basic"));
_board.KernalRom.Flash(GetFirmware(0x2000, "Kernal")); _board.KernalRom.Flash(GetFirmware(0x2000, "Kernal"));
_board.CharRom.Flash(GetFirmware(0x1000, "Chargen")); _board.CharRom.Flash(GetFirmware(0x1000, "Chargen"));
switch (diskDriveType) switch (diskDriveType)
{ {
case DiskDriveType.Commodore1541: case DiskDriveType.Commodore1541:
_board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541")); _board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541"));
break; break;
case DiskDriveType.Commodore1541II: case DiskDriveType.Commodore1541II:
_board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541II")); _board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541II"));
break; break;
} }
} }
public void HardReset() public void HardReset()
{ {
InitMedia(); InitMedia();
_board.HardReset(); _board.HardReset();
} }
} }
} }

View File

@ -5,20 +5,20 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64 namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
public enum C64Format public enum C64Format
{ {
Unknown, Unknown,
D64, D64,
D71, D71,
D81, D81,
X64, X64,
G64, G64,
T64, T64,
TAP, TAP,
CRT, CRT,
P64, P64,
P00, P00,
D82, D82,
D80, D80,
} }
} }

View File

@ -6,42 +6,42 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64 namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
public static class C64FormatFinder public static class C64FormatFinder
{ {
public static C64Format GetFormat(byte[] data) public static C64Format GetFormat(byte[] data)
{ {
if (data == null || data.Length < 0x10) if (data == null || data.Length < 0x10)
return C64Format.Unknown; return C64Format.Unknown;
using (var mem = new MemoryStream(data)) using (var mem = new MemoryStream(data))
{ {
var reader = new BinaryReader(mem); var reader = new BinaryReader(mem);
var header = Encoding.GetEncoding(437).GetString(reader.ReadBytes(0x10)); var header = Encoding.GetEncoding(437).GetString(reader.ReadBytes(0x10));
if (header.StartsWith("C64 CARTRIDGE ")) if (header.StartsWith("C64 CARTRIDGE "))
return C64Format.CRT; return C64Format.CRT;
if (header.StartsWith("GCR-1541")) if (header.StartsWith("GCR-1541"))
return C64Format.G64; return C64Format.G64;
if (header.StartsWith("C64S tape image ")) if (header.StartsWith("C64S tape image "))
return C64Format.T64; return C64Format.T64;
if (header.StartsWith("C64-TAPE-RAW")) if (header.StartsWith("C64-TAPE-RAW"))
return C64Format.TAP; return C64Format.TAP;
if (header.StartsWith("C64File")) if (header.StartsWith("C64File"))
return C64Format.P00; return C64Format.P00;
if (header.StartsWith("P64-1541")) if (header.StartsWith("P64-1541"))
return C64Format.P64; return C64Format.P64;
if (data[0] == 0x43 && data[1] == 0x15 && data[2] == 0x41 && data[3] == 0x64) if (data[0] == 0x43 && data[1] == 0x15 && data[2] == 0x41 && data[3] == 0x64)
return C64Format.X64; return C64Format.X64;
if (data.Length == 174848 || data.Length == 175531 || data.Length == 196608 || data.Length == 197376) if (data.Length == 174848 || data.Length == 175531 || data.Length == 196608 || data.Length == 197376)
return C64Format.D64; return C64Format.D64;
if (data.Length == 349696 || data.Length == 351062) if (data.Length == 349696 || data.Length == 351062)
return C64Format.D71; return C64Format.D71;
if (data.Length == 533248) if (data.Length == 533248)
return C64Format.D80; return C64Format.D80;
if (data.Length == 819200 || data.Length == 822400) if (data.Length == 819200 || data.Length == 822400)
return C64Format.D81; return C64Format.D81;
if (data.Length == 1066496) if (data.Length == 1066496)
return C64Format.D82; return C64Format.D82;
} }
return C64Format.Unknown; return C64Format.Unknown;
} }
} }
} }

View File

@ -21,11 +21,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public static string ToHex(int n, int charsmin) public static string ToHex(int n, int charsmin)
{ {
var result = new StringBuilder(string.Empty); var result = new StringBuilder(string.Empty);
while (n > 0 || charsmin > 0) while (n > 0 || charsmin > 0)
{ {
result.Insert(0, "0123456789ABCDEF".Substring(n & 0xF, 1)); result.Insert(0, "0123456789ABCDEF".Substring(n & 0xF, 1));
n >>= 4; n >>= 4;
if (charsmin > 0) if (charsmin > 0)
charsmin--; charsmin--;

View File

@ -9,143 +9,143 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
public abstract partial class CartridgeDevice : IDriveLight public abstract partial class CartridgeDevice : IDriveLight
{ {
public Func<int> ReadOpenBus; public Func<int> ReadOpenBus;
public static CartridgeDevice Load(byte[] crtFile) public static CartridgeDevice Load(byte[] crtFile)
{ {
using (var mem = new MemoryStream(crtFile)) using (var mem = new MemoryStream(crtFile))
{ {
var reader = new BinaryReader(mem); var reader = new BinaryReader(mem);
if (new string(reader.ReadChars(16)) != "C64 CARTRIDGE ") if (new string(reader.ReadChars(16)) != "C64 CARTRIDGE ")
{ {
return null; return null;
} }
var chipAddress = new List<int>(); var chipAddress = new List<int>();
var chipBank = new List<int>(); var chipBank = new List<int>();
var chipData = new List<int[]>(); var chipData = new List<int[]>();
var chipType = new List<int>(); var chipType = new List<int>();
var headerLength = ReadCRTInt(reader); var headerLength = ReadCRTInt(reader);
var version = ReadCRTShort(reader); var version = ReadCRTShort(reader);
var mapper = ReadCRTShort(reader); var mapper = ReadCRTShort(reader);
var exrom = reader.ReadByte() != 0; var exrom = reader.ReadByte() != 0;
var game = reader.ReadByte() != 0; var game = reader.ReadByte() != 0;
// reserved // reserved
reader.ReadBytes(6); reader.ReadBytes(6);
// cartridge name // cartridge name
reader.ReadBytes(0x20); reader.ReadBytes(0x20);
// skip extra header bytes // skip extra header bytes
if (headerLength > 0x40) if (headerLength > 0x40)
{ {
reader.ReadBytes(headerLength - 0x40); reader.ReadBytes(headerLength - 0x40);
} }
// read chips // read chips
while (reader.PeekChar() >= 0) while (reader.PeekChar() >= 0)
{ {
if (new string(reader.ReadChars(4)) != "CHIP") if (new string(reader.ReadChars(4)) != "CHIP")
{ {
break; break;
} }
var chipLength = ReadCRTInt(reader); var chipLength = ReadCRTInt(reader);
chipType.Add(ReadCRTShort(reader)); chipType.Add(ReadCRTShort(reader));
chipBank.Add(ReadCRTShort(reader)); chipBank.Add(ReadCRTShort(reader));
chipAddress.Add(ReadCRTShort(reader)); chipAddress.Add(ReadCRTShort(reader));
var chipDataLength = ReadCRTShort(reader); var chipDataLength = ReadCRTShort(reader);
chipData.Add(reader.ReadBytes(chipDataLength).Select(x => (int)x).ToArray()); chipData.Add(reader.ReadBytes(chipDataLength).Select(x => (int)x).ToArray());
chipLength -= chipDataLength + 0x10; chipLength -= chipDataLength + 0x10;
if (chipLength > 0) if (chipLength > 0)
reader.ReadBytes(chipLength); reader.ReadBytes(chipLength);
} }
if (chipData.Count <= 0) if (chipData.Count <= 0)
{ {
return null; return null;
} }
CartridgeDevice result; CartridgeDevice result;
switch (mapper) switch (mapper)
{ {
case 0x0000: // Standard Cartridge case 0x0000: // Standard Cartridge
result = new Mapper0000(chipAddress, chipData, game, exrom); result = new Mapper0000(chipAddress, chipData, game, exrom);
break; break;
case 0x0001: // Action Replay (4.2 and up) case 0x0001: // Action Replay (4.2 and up)
result = new Mapper0001(chipAddress, chipBank, chipData); result = new Mapper0001(chipAddress, chipBank, chipData);
break; break;
case 0x0005: // Ocean case 0x0005: // Ocean
result = new Mapper0005(chipAddress, chipBank, chipData); result = new Mapper0005(chipAddress, chipBank, chipData);
break; break;
case 0x000A: // Epyx FastLoad case 0x000A: // Epyx FastLoad
result = new Mapper000A(chipData); result = new Mapper000A(chipData);
break; break;
case 0x000B: // Westermann Learning case 0x000B: // Westermann Learning
result = new Mapper000B(chipAddress, chipData); result = new Mapper000B(chipAddress, chipData);
break; break;
case 0x000F: // C64 Game System / System 3 case 0x000F: // C64 Game System / System 3
result = new Mapper000F(chipAddress, chipBank, chipData); result = new Mapper000F(chipAddress, chipBank, chipData);
break; break;
case 0x0011: // Dinamic case 0x0011: // Dinamic
result = new Mapper0011(chipAddress, chipBank, chipData); result = new Mapper0011(chipAddress, chipBank, chipData);
break; break;
case 0x0012: // Zaxxon / Super Zaxxon case 0x0012: // Zaxxon / Super Zaxxon
result = new Mapper0012(chipAddress, chipBank, chipData); result = new Mapper0012(chipAddress, chipBank, chipData);
break; break;
case 0x0013: // Domark case 0x0013: // Domark
result = new Mapper0013(chipAddress, chipBank, chipData); result = new Mapper0013(chipAddress, chipBank, chipData);
break; break;
case 0x0020: // EasyFlash case 0x0020: // EasyFlash
result = new Mapper0020(chipAddress, chipBank, chipData); result = new Mapper0020(chipAddress, chipBank, chipData);
break; break;
case 0x002B: // Prophet 64 case 0x002B: // Prophet 64
result = new Mapper002B(chipAddress, chipBank, chipData); result = new Mapper002B(chipAddress, chipBank, chipData);
break; break;
default: default:
throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper); throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper);
} }
result.HardReset(); result.HardReset();
return result; return result;
} }
} }
private static int ReadCRTShort(BinaryReader reader) private static int ReadCRTShort(BinaryReader reader)
{ {
return (reader.ReadByte() << 8) | return (reader.ReadByte() << 8) |
reader.ReadByte(); reader.ReadByte();
} }
private static int ReadCRTInt(BinaryReader reader) private static int ReadCRTInt(BinaryReader reader)
{ {
return (reader.ReadByte() << 24) | return (reader.ReadByte() << 24) |
(reader.ReadByte() << 16) | (reader.ReadByte() << 16) |
(reader.ReadByte() << 8) | (reader.ReadByte() << 8) |
reader.ReadByte(); reader.ReadByte();
} }
[SaveState.SaveWithName("ExRom")] [SaveState.SaveWithName("ExRom")]
protected bool pinExRom; protected bool pinExRom;
[SaveState.SaveWithName("Game")] [SaveState.SaveWithName("Game")]
protected bool pinGame; protected bool pinGame;
[SaveState.SaveWithName("IRQ")] [SaveState.SaveWithName("IRQ")]
protected bool pinIRQ; protected bool pinIRQ;
[SaveState.SaveWithName("NMI")] [SaveState.SaveWithName("NMI")]
protected bool pinNMI; protected bool pinNMI;
[SaveState.SaveWithName("Reset")] [SaveState.SaveWithName("Reset")]
protected bool pinReset; protected bool pinReset;
[SaveState.DoNotSave] [SaveState.DoNotSave]
protected bool validCartridge; protected bool validCartridge;
public virtual void ExecutePhase() public virtual void ExecutePhase()
{ {
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool ExRom public bool ExRom
{ {
get get
@ -154,8 +154,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool Game public bool Game
{ {
get get
{ {
@ -170,8 +170,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
pinReset = true; pinReset = true;
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool IRQ public bool IRQ
{ {
get get
{ {
@ -179,8 +179,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool NMI public bool NMI
{ {
get get
{ {
@ -244,8 +244,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
return ReadOpenBus(); return ReadOpenBus();
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool Reset public bool Reset
{ {
get get
{ {
@ -258,8 +258,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool Valid public bool Valid
{ {
get get
{ {
@ -283,7 +283,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
} }
public bool DriveLightEnabled { get; protected set; } public bool DriveLightEnabled { get; protected set; }
public bool DriveLightOn { get; protected set; } public bool DriveLightOn { get; protected set; }
} }
} }

View File

@ -5,108 +5,108 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
public sealed class CartridgePort : IDriveLight public sealed class CartridgePort : IDriveLight
{ {
public Func<int> ReadOpenBus; public Func<int> ReadOpenBus;
private CartridgeDevice _cartridgeDevice; private CartridgeDevice _cartridgeDevice;
private bool _connected; private bool _connected;
public CartridgePort() public CartridgePort()
{ {
// start up with no media connected // start up with no media connected
Disconnect(); Disconnect();
} }
// ------------------------------------------ // ------------------------------------------
public int PeekHiExp(int addr) public int PeekHiExp(int addr)
{ {
return _connected ? _cartridgeDevice.PeekDF00(addr & 0x00FF) : 0xFF; return _connected ? _cartridgeDevice.PeekDF00(addr & 0x00FF) : 0xFF;
} }
public int PeekHiRom(int addr) public int PeekHiRom(int addr)
{ {
return _connected ? _cartridgeDevice.PeekA000(addr & 0x1FFF) : 0xFF; return _connected ? _cartridgeDevice.PeekA000(addr & 0x1FFF) : 0xFF;
} }
public int PeekLoExp(int addr) public int PeekLoExp(int addr)
{ {
return _connected ? _cartridgeDevice.PeekDE00(addr & 0x00FF) : 0xFF; return _connected ? _cartridgeDevice.PeekDE00(addr & 0x00FF) : 0xFF;
} }
public int PeekLoRom(int addr) public int PeekLoRom(int addr)
{ {
return _connected ? _cartridgeDevice.Peek8000(addr & 0x1FFF) : 0xFF; return _connected ? _cartridgeDevice.Peek8000(addr & 0x1FFF) : 0xFF;
} }
public void PokeHiExp(int addr, int val) { if (_connected) { _cartridgeDevice.PokeDF00(addr & 0x00FF, val); } } public void PokeHiExp(int addr, int val) { if (_connected) { _cartridgeDevice.PokeDF00(addr & 0x00FF, val); } }
public void PokeHiRom(int addr, int val) { if (_connected) { _cartridgeDevice.PokeA000(addr & 0x1FFF, val); } } public void PokeHiRom(int addr, int val) { if (_connected) { _cartridgeDevice.PokeA000(addr & 0x1FFF, val); } }
public void PokeLoExp(int addr, int val) { if (_connected) { _cartridgeDevice.PokeDE00(addr & 0x00FF, val); } } public void PokeLoExp(int addr, int val) { if (_connected) { _cartridgeDevice.PokeDE00(addr & 0x00FF, val); } }
public void PokeLoRom(int addr, int val) { if (_connected) { _cartridgeDevice.Poke8000(addr & 0x1FFF, val); } } public void PokeLoRom(int addr, int val) { if (_connected) { _cartridgeDevice.Poke8000(addr & 0x1FFF, val); } }
public bool ReadExRom() public bool ReadExRom()
{ {
return !_connected || _cartridgeDevice.ExRom; return !_connected || _cartridgeDevice.ExRom;
} }
public bool ReadGame() public bool ReadGame()
{ {
return !_connected || _cartridgeDevice.Game; return !_connected || _cartridgeDevice.Game;
} }
public int ReadHiExp(int addr) public int ReadHiExp(int addr)
{ {
return _connected ? _cartridgeDevice.ReadDF00(addr & 0x00FF) : 0xFF; return _connected ? _cartridgeDevice.ReadDF00(addr & 0x00FF) : 0xFF;
} }
public int ReadHiRom(int addr) public int ReadHiRom(int addr)
{ {
return _connected ? _cartridgeDevice.ReadA000(addr & 0x1FFF) : 0xFF; return _connected ? _cartridgeDevice.ReadA000(addr & 0x1FFF) : 0xFF;
} }
public int ReadLoExp(int addr) public int ReadLoExp(int addr)
{ {
return _connected ? _cartridgeDevice.ReadDE00(addr & 0x00FF) : 0xFF; return _connected ? _cartridgeDevice.ReadDE00(addr & 0x00FF) : 0xFF;
} }
public int ReadLoRom(int addr) public int ReadLoRom(int addr)
{ {
return _connected ? _cartridgeDevice.Read8000(addr & 0x1FFF) : 0xFF; return _connected ? _cartridgeDevice.Read8000(addr & 0x1FFF) : 0xFF;
} }
public void WriteHiExp(int addr, int val) { if (_connected) { _cartridgeDevice.WriteDF00(addr & 0x00FF, val); } } public void WriteHiExp(int addr, int val) { if (_connected) { _cartridgeDevice.WriteDF00(addr & 0x00FF, val); } }
public void WriteHiRom(int addr, int val) { if (_connected) { _cartridgeDevice.WriteA000(addr & 0x1FFF, val); } } public void WriteHiRom(int addr, int val) { if (_connected) { _cartridgeDevice.WriteA000(addr & 0x1FFF, val); } }
public void WriteLoExp(int addr, int val) { if (_connected) { _cartridgeDevice.WriteDE00(addr & 0x00FF, val); } } public void WriteLoExp(int addr, int val) { if (_connected) { _cartridgeDevice.WriteDE00(addr & 0x00FF, val); } }
public void WriteLoRom(int addr, int val) { if (_connected) { _cartridgeDevice.Write8000(addr & 0x1FFF, val); } } public void WriteLoRom(int addr, int val) { if (_connected) { _cartridgeDevice.Write8000(addr & 0x1FFF, val); } }
// ------------------------------------------ // ------------------------------------------
public void Connect(CartridgeDevice newCartridgeDevice) public void Connect(CartridgeDevice newCartridgeDevice)
{ {
_connected = true; _connected = true;
_cartridgeDevice = newCartridgeDevice; _cartridgeDevice = newCartridgeDevice;
newCartridgeDevice.ReadOpenBus = ReadOpenBus; newCartridgeDevice.ReadOpenBus = ReadOpenBus;
} }
public void Disconnect() public void Disconnect()
{ {
_cartridgeDevice = null; _cartridgeDevice = null;
_connected = false; _connected = false;
}
public void ExecutePhase()
{
if (_connected)
_cartridgeDevice.ExecutePhase();
} }
public void ExecutePhase()
{
if (_connected)
_cartridgeDevice.ExecutePhase();
}
public void HardReset() public void HardReset()
{ {
// note: this will not disconnect any attached media // note: this will not disconnect any attached media
if (_connected) if (_connected)
{ {
_cartridgeDevice.HardReset(); _cartridgeDevice.HardReset();
} }
} }
public bool IsConnected public bool IsConnected
@ -123,16 +123,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
} }
public bool ReadNmi() public bool ReadNmi()
{ {
return !_connected || _cartridgeDevice.NMI; return !_connected || _cartridgeDevice.NMI;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
public bool DriveLightEnabled { get { return _connected && _cartridgeDevice.DriveLightEnabled; } } public bool DriveLightEnabled { get { return _connected && _cartridgeDevice.DriveLightEnabled; } }
public bool DriveLightOn { get { return _connected && _cartridgeDevice.DriveLightOn; } } public bool DriveLightOn { get { return _connected && _cartridgeDevice.DriveLightOn; } }
} }
} }

View File

@ -4,101 +4,101 @@ using System.Linq;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper0000 : CartridgeDevice private sealed class Mapper0000 : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _romA; private readonly int[] _romA;
[SaveState.SaveWithName("RomMaskA")] [SaveState.SaveWithName("RomMaskA")]
private readonly int _romAMask; private readonly int _romAMask;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _romB; private readonly int[] _romB;
[SaveState.SaveWithName("RomMaskB")] [SaveState.SaveWithName("RomMaskB")]
private readonly int _romBMask; private readonly int _romBMask;
// standard cartridge mapper (Commodore) // standard cartridge mapper (Commodore)
// note that this format also covers Ultimax carts // note that this format also covers Ultimax carts
public Mapper0000(IList<int> newAddresses, IList<int[]> newData, bool game, bool exrom) public Mapper0000(IList<int> newAddresses, IList<int[]> newData, bool game, bool exrom)
{ {
pinGame = game; pinGame = game;
pinExRom = exrom; pinExRom = exrom;
validCartridge = true; validCartridge = true;
// default to empty banks // default to empty banks
_romA = new int[1]; _romA = new int[1];
_romB = new int[1]; _romB = new int[1];
_romA[0] = 0xFF; _romA[0] = 0xFF;
_romB[0] = 0xFF; _romB[0] = 0xFF;
for (var i = 0; i < newAddresses.Count; i++) for (var i = 0; i < newAddresses.Count; i++)
{ {
if (newAddresses[i] == 0x8000) if (newAddresses[i] == 0x8000)
{ {
switch (newData[i].Length) switch (newData[i].Length)
{ {
case 0x1000: case 0x1000:
_romAMask = 0x0FFF; _romAMask = 0x0FFF;
_romA = newData[i]; _romA = newData[i];
break; break;
case 0x2000: case 0x2000:
_romAMask = 0x1FFF; _romAMask = 0x1FFF;
_romA = newData[i]; _romA = newData[i];
break; break;
case 0x4000: case 0x4000:
_romAMask = 0x1FFF; _romAMask = 0x1FFF;
_romBMask = 0x1FFF; _romBMask = 0x1FFF;
// split the rom into two banks // split the rom into two banks
_romA = new int[0x2000]; _romA = new int[0x2000];
_romB = new int[0x2000]; _romB = new int[0x2000];
Array.Copy(newData[i], 0x0000, _romA, 0x0000, 0x2000); Array.Copy(newData[i], 0x0000, _romA, 0x0000, 0x2000);
Array.Copy(newData[i], 0x2000, _romB, 0x0000, 0x2000); Array.Copy(newData[i], 0x2000, _romB, 0x0000, 0x2000);
break; break;
default: default:
validCartridge = false; validCartridge = false;
return; return;
} }
} }
else if (newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000) else if (newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000)
{ {
switch (newData[i].Length) switch (newData[i].Length)
{ {
case 0x1000: case 0x1000:
_romBMask = 0x0FFF; _romBMask = 0x0FFF;
break; break;
case 0x2000: case 0x2000:
_romBMask = 0x1FFF; _romBMask = 0x1FFF;
break; break;
default: default:
validCartridge = false; validCartridge = false;
return; return;
} }
_romB = newData[i]; _romB = newData[i];
} }
} }
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _romA[addr & _romAMask]; return _romA[addr & _romAMask];
} }
public override int PeekA000(int addr) public override int PeekA000(int addr)
{ {
return _romB[addr & _romBMask]; return _romB[addr & _romBMask];
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return _romA[addr & _romAMask]; return _romA[addr & _romAMask];
} }
public override int ReadA000(int addr) public override int ReadA000(int addr)
{ {
return _romB[addr & _romBMask]; return _romB[addr & _romBMask];
} }
} }
} }
} }

View File

@ -5,150 +5,150 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper0001 : CartridgeDevice private sealed class Mapper0001 : CartridgeDevice
{ {
[SaveState.SaveWithName("RAM")] private readonly int[] _ram = new int[0x2000]; [SaveState.SaveWithName("RAM")] private readonly int[] _ram = new int[0x2000];
[SaveState.SaveWithName("RAMEnabled")] private bool _ramEnabled; [SaveState.SaveWithName("RAMEnabled")] private bool _ramEnabled;
[SaveState.DoNotSave] private readonly int[] _rom = new int[0x8000]; [SaveState.DoNotSave] private readonly int[] _rom = new int[0x8000];
[SaveState.SaveWithName("ROMOffset")] private int _romOffset; [SaveState.SaveWithName("ROMOffset")] private int _romOffset;
[SaveState.SaveWithName("CartEnabled")] private bool _cartEnabled; [SaveState.SaveWithName("CartEnabled")] private bool _cartEnabled;
public Mapper0001(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper0001(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
pinExRom = false; pinExRom = false;
pinGame = false; pinGame = false;
for (var i = 0; i < newData.Count; i++) for (var i = 0; i < newData.Count; i++)
{ {
if (newAddresses[i] == 0x8000) if (newAddresses[i] == 0x8000)
Array.Copy(newData[i], 0, _rom, 0x2000 * newBanks[i], 0x2000); Array.Copy(newData[i], 0, _rom, 0x2000 * newBanks[i], 0x2000);
} }
_romOffset = 0; _romOffset = 0;
_cartEnabled = true; _cartEnabled = true;
} }
public override void HardReset() public override void HardReset()
{ {
base.HardReset(); base.HardReset();
pinExRom = false; pinExRom = false;
pinGame = false; pinGame = false;
for (var i = 0; i < 0x2000; i++) for (var i = 0; i < 0x2000; i++)
_ram[i] = 0x00; _ram[i] = 0x00;
_romOffset = 0; _romOffset = 0;
_cartEnabled = true; _cartEnabled = true;
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return GetLoRom(addr); return GetLoRom(addr);
} }
public override int PeekA000(int addr) public override int PeekA000(int addr)
{ {
return Peek8000(addr); return Peek8000(addr);
} }
public override int PeekDF00(int addr) public override int PeekDF00(int addr)
{ {
return GetIo2(addr); return GetIo2(addr);
} }
public override void Poke8000(int addr, int val) public override void Poke8000(int addr, int val)
{ {
SetLoRom(addr, val); SetLoRom(addr, val);
} }
public override void PokeA000(int addr, int val) public override void PokeA000(int addr, int val)
{ {
Poke8000(addr, val); Poke8000(addr, val);
} }
public override void PokeDE00(int addr, int val) public override void PokeDE00(int addr, int val)
{ {
SetState(val); SetState(val);
} }
public override void PokeDF00(int addr, int val) public override void PokeDF00(int addr, int val)
{ {
SetIo2(addr, val); SetIo2(addr, val);
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return GetLoRom(addr); return GetLoRom(addr);
} }
public override int ReadA000(int addr) public override int ReadA000(int addr)
{ {
return GetHiRom(addr); return GetHiRom(addr);
} }
public override int ReadDF00(int addr) public override int ReadDF00(int addr)
{ {
return GetIo2(addr); return GetIo2(addr);
} }
public override void Write8000(int addr, int val) public override void Write8000(int addr, int val)
{ {
SetLoRom(addr, val); SetLoRom(addr, val);
} }
public override void WriteA000(int addr, int val) public override void WriteA000(int addr, int val)
{ {
SetLoRom(addr, val); SetLoRom(addr, val);
} }
public override void WriteDE00(int addr, int val) public override void WriteDE00(int addr, int val)
{ {
SetState(val); SetState(val);
} }
public override void WriteDF00(int addr, int val) public override void WriteDF00(int addr, int val)
{ {
SetIo2(addr, val); SetIo2(addr, val);
} }
private void SetState(int val) private void SetState(int val)
{ {
pinGame = (val & 0x01) == 0; pinGame = (val & 0x01) == 0;
pinExRom = (val & 0x02) != 0; pinExRom = (val & 0x02) != 0;
_cartEnabled = (val & 0x04) == 0; _cartEnabled = (val & 0x04) == 0;
_romOffset = (val & 0x18) << 10; _romOffset = (val & 0x18) << 10;
_ramEnabled = (val & 0x20) == 0; _ramEnabled = (val & 0x20) == 0;
} }
private int GetLoRom(int addr) private int GetLoRom(int addr)
{ {
return _ramEnabled return _ramEnabled
? _ram[addr & 0x1FFF] ? _ram[addr & 0x1FFF]
: _rom[(addr & 0x1FFF) | _romOffset]; : _rom[(addr & 0x1FFF) | _romOffset];
} }
private int GetHiRom(int addr) private int GetHiRom(int addr)
{ {
return _rom[(addr & 0x1FFF) | _romOffset]; return _rom[(addr & 0x1FFF) | _romOffset];
} }
private void SetLoRom(int addr, int val) private void SetLoRom(int addr, int val)
{ {
_ram[addr & 0x1FFF] = val; _ram[addr & 0x1FFF] = val;
} }
private int GetIo2(int addr) private int GetIo2(int addr)
{ {
if (!_cartEnabled) if (!_cartEnabled)
return ReadOpenBus(); return ReadOpenBus();
return _ramEnabled return _ramEnabled
? _ram[(addr & 0xFF) | 0x1F00] ? _ram[(addr & 0xFF) | 0x1F00]
: _rom[(addr & 0xFF) | _romOffset | 0x1F00]; : _rom[(addr & 0xFF) | _romOffset | 0x1F00];
} }
private void SetIo2(int addr, int val) private void SetIo2(int addr, int val)
{ {
_ram[addr & 0x1FFF] = val & 0xFF; _ram[addr & 0x1FFF] = val & 0xFF;
} }
} }
} }
} }

View File

@ -5,153 +5,153 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper0005 : CartridgeDevice private sealed class Mapper0005 : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[][] _banksA; //8000 private readonly int[][] _banksA; //8000
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[][] _banksB = new int[0][]; //A000 private readonly int[][] _banksB = new int[0][]; //A000
[SaveState.SaveWithName("BankMask")] [SaveState.SaveWithName("BankMask")]
private readonly int _bankMask; private readonly int _bankMask;
[SaveState.SaveWithName("BankNumber")] [SaveState.SaveWithName("BankNumber")]
private int _bankNumber; private int _bankNumber;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int[] _currentBankA; private int[] _currentBankA;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int[] _currentBankB; private int[] _currentBankB;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _dummyBank; private readonly int[] _dummyBank;
public Mapper0005(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper0005(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
var count = newAddresses.Count; var count = newAddresses.Count;
// build dummy bank // build dummy bank
_dummyBank = new int[0x2000]; _dummyBank = new int[0x2000];
for (var i = 0; i < 0x2000; i++) for (var i = 0; i < 0x2000; i++)
_dummyBank[i] = 0xFF; // todo: determine if this is correct _dummyBank[i] = 0xFF; // todo: determine if this is correct
switch (count) switch (count)
{ {
case 64: case 64:
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_bankMask = 0x3F; _bankMask = 0x3F;
_banksA = new int[64][]; _banksA = new int[64][];
break; break;
case 32: case 32:
// this specific config is a weird exception // this specific config is a weird exception
pinGame = false; pinGame = false;
pinExRom = false; pinExRom = false;
_bankMask = 0x0F; _bankMask = 0x0F;
_banksA = new int[16][]; _banksA = new int[16][];
_banksB = new int[16][]; _banksB = new int[16][];
break; break;
case 16: case 16:
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_bankMask = 0x0F; _bankMask = 0x0F;
_banksA = new int[16][]; _banksA = new int[16][];
break; break;
case 8: case 8:
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_bankMask = 0x07; _bankMask = 0x07;
_banksA = new int[8][]; _banksA = new int[8][];
break; break;
case 4: case 4:
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_bankMask = 0x03; _bankMask = 0x03;
_banksA = new int[4][]; _banksA = new int[4][];
break; break;
case 2: case 2:
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_bankMask = 0x01; _bankMask = 0x01;
_banksA = new int[2][]; _banksA = new int[2][];
break; break;
case 1: case 1:
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_bankMask = 0x00; _bankMask = 0x00;
_banksA = new int[1][]; _banksA = new int[1][];
break; break;
default: default:
throw new Exception("This looks like an Ocean cartridge but cannot be loaded..."); throw new Exception("This looks like an Ocean cartridge but cannot be loaded...");
} }
// for safety, initialize all banks to dummy // for safety, initialize all banks to dummy
for (var i = 0; i < _banksA.Length; i++) for (var i = 0; i < _banksA.Length; i++)
_banksA[i] = _dummyBank; _banksA[i] = _dummyBank;
for (var i = 0; i < _banksB.Length; i++) for (var i = 0; i < _banksB.Length; i++)
_banksB[i] = _dummyBank; _banksB[i] = _dummyBank;
// now load in the banks // now load in the banks
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)
{ {
switch (newAddresses[i]) switch (newAddresses[i])
{ {
case 0x8000: case 0x8000:
_banksA[newBanks[i] & _bankMask] = newData[i]; _banksA[newBanks[i] & _bankMask] = newData[i];
break; break;
case 0xA000: case 0xA000:
case 0xE000: case 0xE000:
_banksB[newBanks[i] & _bankMask] = newData[i]; _banksB[newBanks[i] & _bankMask] = newData[i];
break; break;
} }
} }
BankSet(0); BankSet(0);
} }
private void BankSet(int index) private void BankSet(int index)
{ {
_bankNumber = index & _bankMask; _bankNumber = index & _bankMask;
_currentBankA = !pinExRom ? _banksA[_bankNumber] : _dummyBank; _currentBankA = !pinExRom ? _banksA[_bankNumber] : _dummyBank;
_currentBankB = !pinGame ? _banksB[_bankNumber] : _dummyBank; _currentBankB = !pinGame ? _banksB[_bankNumber] : _dummyBank;
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _currentBankA[addr]; return _currentBankA[addr];
} }
public override int PeekA000(int addr) public override int PeekA000(int addr)
{ {
return _currentBankB[addr]; return _currentBankB[addr];
} }
public override void PokeDE00(int addr, int val) public override void PokeDE00(int addr, int val)
{ {
if (addr == 0x00) if (addr == 0x00)
BankSet(val); BankSet(val);
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return _currentBankA[addr]; return _currentBankA[addr];
} }
public override int ReadA000(int addr) public override int ReadA000(int addr)
{ {
return _currentBankB[addr]; return _currentBankB[addr];
} }
public override void WriteDE00(int addr, int val) public override void WriteDE00(int addr, int val)
{ {
if (addr == 0x00) if (addr == 0x00)
BankSet(val); BankSet(val);
} }
public override void SyncState(Serializer ser) public override void SyncState(Serializer ser)
{ {
base.SyncState(ser); base.SyncState(ser);
if (ser.IsReader) if (ser.IsReader)
BankSet(_bankNumber); BankSet(_bankNumber);
} }
} }
} }
} }

View File

@ -5,79 +5,79 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// Epyx Fastload. Uppermost page is always visible at DFxx. // Epyx Fastload. Uppermost page is always visible at DFxx.
// They use a capacitor that is discharged by accesses to DExx // They use a capacitor that is discharged by accesses to DExx
// to pull down EXROM. Also, accesses to LOROM while it is active // to pull down EXROM. Also, accesses to LOROM while it is active
// discharge the capacitor. // discharge the capacitor.
// Thanks to VICE team for the info: http://vice-emu.sourceforge.net/vice_15.html // Thanks to VICE team for the info: http://vice-emu.sourceforge.net/vice_15.html
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private class Mapper000A : CartridgeDevice private class Mapper000A : CartridgeDevice
{ {
// This constant differs depending on whose research you reference. TODO: Verify. // This constant differs depending on whose research you reference. TODO: Verify.
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const int RESET_CAPACITOR_CYCLES = 512; private const int RESET_CAPACITOR_CYCLES = 512;
[SaveState.SaveWithName("CapacitorCycles")] [SaveState.SaveWithName("CapacitorCycles")]
private int _capacitorCycles; private int _capacitorCycles;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _rom; private readonly int[] _rom;
public Mapper000A(IList<int[]> newData) public Mapper000A(IList<int[]> newData)
{ {
_rom = new int[0x2000]; _rom = new int[0x2000];
Array.Copy(newData.First(), _rom, 0x2000); Array.Copy(newData.First(), _rom, 0x2000);
pinGame = true; pinGame = true;
} }
public override void ExecutePhase() public override void ExecutePhase()
{ {
pinExRom = !(_capacitorCycles > 0); pinExRom = !(_capacitorCycles > 0);
if (!pinExRom) if (!pinExRom)
{ {
_capacitorCycles--; _capacitorCycles--;
} }
} }
public override void HardReset() public override void HardReset()
{ {
_capacitorCycles = RESET_CAPACITOR_CYCLES; _capacitorCycles = RESET_CAPACITOR_CYCLES;
base.HardReset(); base.HardReset();
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _rom[addr & 0x1FFF]; return _rom[addr & 0x1FFF];
} }
public override int PeekDE00(int addr) public override int PeekDE00(int addr)
{ {
return 0x00; return 0x00;
} }
public override int PeekDF00(int addr) public override int PeekDF00(int addr)
{ {
return _rom[(addr & 0xFF) | 0x1F00]; return _rom[(addr & 0xFF) | 0x1F00];
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
_capacitorCycles = RESET_CAPACITOR_CYCLES; _capacitorCycles = RESET_CAPACITOR_CYCLES;
return _rom[addr & 0x1FFF]; return _rom[addr & 0x1FFF];
} }
public override int ReadDE00(int addr) public override int ReadDE00(int addr)
{ {
_capacitorCycles = RESET_CAPACITOR_CYCLES; _capacitorCycles = RESET_CAPACITOR_CYCLES;
return 0x00; return 0x00;
} }
public override int ReadDF00(int addr) public override int ReadDF00(int addr)
{ {
return _rom[(addr & 0xFF) | 0x1F00]; return _rom[(addr & 0xFF) | 0x1F00];
} }
} }
} }
} }

View File

@ -3,62 +3,62 @@ using System.Collections.Generic;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// Westermann Learning mapper. // Westermann Learning mapper.
// Starts up with both banks enabled, any read to DFxx // Starts up with both banks enabled, any read to DFxx
// turns off the high bank by bringing GAME high. // turns off the high bank by bringing GAME high.
// I suspect that the game loads by copying all hirom to // I suspect that the game loads by copying all hirom to
// the RAM underneath (BASIC variable values probably) // the RAM underneath (BASIC variable values probably)
// and then disables once loaded. // and then disables once loaded.
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper000B : CartridgeDevice private sealed class Mapper000B : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _rom = new int[0x4000]; private readonly int[] _rom = new int[0x4000];
public Mapper000B(IList<int> newAddresses, IList<int[]> newData) public Mapper000B(IList<int> newAddresses, IList<int[]> newData)
{ {
validCartridge = false; validCartridge = false;
for (var i = 0; i < 0x4000; i++) for (var i = 0; i < 0x4000; i++)
_rom[i] = 0xFF; _rom[i] = 0xFF;
if (newAddresses[0] != 0x8000) if (newAddresses[0] != 0x8000)
{ {
return; return;
} }
Array.Copy(newData[0], _rom, Math.Min(newData[0].Length, 0x4000)); Array.Copy(newData[0], _rom, Math.Min(newData[0].Length, 0x4000));
validCartridge = true; validCartridge = true;
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _rom[addr]; return _rom[addr];
} }
public override int PeekA000(int addr) public override int PeekA000(int addr)
{ {
return _rom[addr | 0x2000]; return _rom[addr | 0x2000];
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return _rom[addr]; return _rom[addr];
} }
public override int ReadA000(int addr) public override int ReadA000(int addr)
{ {
return _rom[addr | 0x2000]; return _rom[addr | 0x2000];
} }
public override int ReadDF00(int addr) public override int ReadDF00(int addr)
{ {
pinGame = true; pinGame = true;
return base.ReadDF00(addr); return base.ReadDF00(addr);
} }
} }
} }
} }

View File

@ -5,125 +5,125 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// This is a mapper used commonly by System 3. It is // This is a mapper used commonly by System 3. It is
// also utilized by the short-lived C64 Game System. // also utilized by the short-lived C64 Game System.
// Bank select is DExx. You select them by writing to the // Bank select is DExx. You select them by writing to the
// register DE00+BankNr. For example, bank 01 is a write // register DE00+BankNr. For example, bank 01 is a write
// to DE01. // to DE01.
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private class Mapper000F : CartridgeDevice private class Mapper000F : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[][] _banks; //8000 private readonly int[][] _banks; //8000
[SaveState.SaveWithName("BankMask")] [SaveState.SaveWithName("BankMask")]
private readonly int _bankMask; private readonly int _bankMask;
[SaveState.SaveWithName("BankNumber")] [SaveState.SaveWithName("BankNumber")]
private int _bankNumber; private int _bankNumber;
[SaveState.SaveWithName("CurrentBank")] [SaveState.SaveWithName("CurrentBank")]
private int[] _currentBank; private int[] _currentBank;
public Mapper000F(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper000F(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
var count = newAddresses.Count; var count = newAddresses.Count;
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
// build dummy bank // build dummy bank
var dummyBank = new int[0x2000]; var dummyBank = new int[0x2000];
for (var i = 0; i < 0x2000; i++) for (var i = 0; i < 0x2000; i++)
dummyBank[i] = 0xFF; // todo: determine if this is correct dummyBank[i] = 0xFF; // todo: determine if this is correct
switch (count) switch (count)
{ {
case 64: case 64:
_bankMask = 0x3F; _bankMask = 0x3F;
_banks = new int[64][]; _banks = new int[64][];
break; break;
case 32: case 32:
_bankMask = 0x1F; _bankMask = 0x1F;
_banks = new int[32][]; _banks = new int[32][];
break; break;
case 16: case 16:
_bankMask = 0x0F; _bankMask = 0x0F;
_banks = new int[16][]; _banks = new int[16][];
break; break;
case 8: case 8:
_bankMask = 0x07; _bankMask = 0x07;
_banks = new int[8][]; _banks = new int[8][];
break; break;
case 4: case 4:
_bankMask = 0x03; _bankMask = 0x03;
_banks = new int[4][]; _banks = new int[4][];
break; break;
case 2: case 2:
_bankMask = 0x01; _bankMask = 0x01;
_banks = new int[2][]; _banks = new int[2][];
break; break;
case 1: case 1:
_bankMask = 0x00; _bankMask = 0x00;
_banks = new int[1][]; _banks = new int[1][];
break; break;
default: default:
throw new Exception("This looks like a System 3/C64GS cartridge but cannot be loaded..."); throw new Exception("This looks like a System 3/C64GS cartridge but cannot be loaded...");
} }
// for safety, initialize all banks to dummy // for safety, initialize all banks to dummy
for (var i = 0; i < _banks.Length; i++) for (var i = 0; i < _banks.Length; i++)
_banks[i] = dummyBank; _banks[i] = dummyBank;
// now load in the banks // now load in the banks
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)
{ {
if (newAddresses[i] == 0x8000) if (newAddresses[i] == 0x8000)
{ {
_banks[newBanks[i] & _bankMask] = newData[i]; _banks[newBanks[i] & _bankMask] = newData[i];
} }
} }
BankSet(0); BankSet(0);
} }
protected void BankSet(int index) protected void BankSet(int index)
{ {
_bankNumber = index & _bankMask; _bankNumber = index & _bankMask;
UpdateState(); UpdateState();
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _currentBank[addr]; return _currentBank[addr];
} }
public override void PokeDE00(int addr, int val) public override void PokeDE00(int addr, int val)
{ {
BankSet(addr); BankSet(addr);
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return _currentBank[addr]; return _currentBank[addr];
} }
private void UpdateState() private void UpdateState()
{ {
_currentBank = _banks[_bankNumber]; _currentBank = _banks[_bankNumber];
} }
public override void WriteDE00(int addr, int val) public override void WriteDE00(int addr, int val)
{ {
BankSet(addr); BankSet(addr);
} }
public override void SyncState(Serializer ser) public override void SyncState(Serializer ser)
{ {
base.SyncState(ser); base.SyncState(ser);
if (ser.IsReader) if (ser.IsReader)
BankSet(_bankNumber); BankSet(_bankNumber);
} }
} }
} }
} }

View File

@ -2,36 +2,36 @@
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// This mapper comes from Dinamic. It is in fact identical // This mapper comes from Dinamic. It is in fact identical
// to the System 3 mapper (000F) except that bank switching is // to the System 3 mapper (000F) except that bank switching is
// done by reads to the DExx region instead of writes. // done by reads to the DExx region instead of writes.
// This is why mapper 0011 inherits directly from 000F. // This is why mapper 0011 inherits directly from 000F.
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private class Mapper0011 : Mapper000F private class Mapper0011 : Mapper000F
{ {
public Mapper0011(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper0011(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
: base(newAddresses, newBanks, newData) : base(newAddresses, newBanks, newData)
{ {
// required to pass information to base class // required to pass information to base class
} }
public override void PokeDE00(int addr, int val) public override void PokeDE00(int addr, int val)
{ {
// do nothing // do nothing
} }
public override int ReadDE00(int addr) public override int ReadDE00(int addr)
{ {
BankSet(addr); BankSet(addr);
return base.ReadDE00(addr); return base.ReadDE00(addr);
} }
public override void WriteDE00(int addr, int val) public override void WriteDE00(int addr, int val)
{ {
// do nothing // do nothing
} }
} }
} }
} }

View File

@ -4,83 +4,83 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper0012 : CartridgeDevice private sealed class Mapper0012 : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _bankMain; private readonly int[] _bankMain;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[][] _bankHigh; private readonly int[][] _bankHigh;
[SaveState.SaveWithName("BankHighSelected")] [SaveState.SaveWithName("BankHighSelected")]
private int[] _bankHighSelected; private int[] _bankHighSelected;
[SaveState.SaveWithName("BankIndex")] [SaveState.SaveWithName("BankIndex")]
private int _bankIndex; private int _bankIndex;
// Zaxxon and Super Zaxxon cartridges // Zaxxon and Super Zaxxon cartridges
// - read to 8xxx selects bank 0 in A000-BFFF // - read to 8xxx selects bank 0 in A000-BFFF
// - read to 9xxx selects bank 1 in A000-BFFF // - read to 9xxx selects bank 1 in A000-BFFF
public Mapper0012(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper0012(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
_bankMain = new int[0x2000]; _bankMain = new int[0x2000];
_bankHigh = new int[2][]; _bankHigh = new int[2][];
var dummyBank = new int[0x2000]; var dummyBank = new int[0x2000];
// create dummy bank just in case // create dummy bank just in case
for (var i = 0; i < 0x2000; i++) for (var i = 0; i < 0x2000; i++)
dummyBank[i] = 0xFF; dummyBank[i] = 0xFF;
_bankHigh[0] = dummyBank; _bankHigh[0] = dummyBank;
_bankHigh[1] = dummyBank; _bankHigh[1] = dummyBank;
// load in the banks // load in the banks
for (var i = 0; i < newAddresses.Count; i++) for (var i = 0; i < newAddresses.Count; i++)
{ {
if (newAddresses[i] == 0x8000) if (newAddresses[i] == 0x8000)
Array.Copy(newData[i], _bankMain, 0x1000); Array.Copy(newData[i], _bankMain, 0x1000);
else if ((newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000) && newBanks[i] < 2) else if ((newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000) && newBanks[i] < 2)
_bankHigh[newBanks[i]] = newData[i]; _bankHigh[newBanks[i]] = newData[i];
} }
// mirror the main rom from 8000 to 9000 // mirror the main rom from 8000 to 9000
Array.Copy(_bankMain, 0x0000, _bankMain, 0x1000, 0x1000); Array.Copy(_bankMain, 0x0000, _bankMain, 0x1000, 0x1000);
// set both pins low for 16k rom config // set both pins low for 16k rom config
pinExRom = false; pinExRom = false;
pinGame = false; pinGame = false;
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _bankMain[addr]; return _bankMain[addr];
} }
public override int PeekA000(int addr) public override int PeekA000(int addr)
{ {
return _bankHighSelected[addr]; return _bankHighSelected[addr];
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
_bankIndex = (addr & 0x1000) >> 12; _bankIndex = (addr & 0x1000) >> 12;
_bankHighSelected = _bankHigh[_bankIndex]; _bankHighSelected = _bankHigh[_bankIndex];
return _bankMain[addr]; return _bankMain[addr];
} }
public override int ReadA000(int addr) public override int ReadA000(int addr)
{ {
return _bankHighSelected[addr]; return _bankHighSelected[addr];
} }
public override void SyncState(Serializer ser) public override void SyncState(Serializer ser)
{ {
base.SyncState(ser); base.SyncState(ser);
if (ser.IsReader) if (ser.IsReader)
_bankHighSelected = _bankHigh[_bankIndex]; _bankHighSelected = _bankHigh[_bankIndex];
} }
} }
} }
} }

View File

@ -4,126 +4,126 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// Mapper for a few Domark and HES Australia games. // Mapper for a few Domark and HES Australia games.
// It seems a lot of people dumping these have remapped // It seems a lot of people dumping these have remapped
// them to the Ocean mapper (0005) but this is still here // them to the Ocean mapper (0005) but this is still here
// for compatibility. // for compatibility.
// //
// Bank select is DE00, bit 7 enabled means to disable // Bank select is DE00, bit 7 enabled means to disable
// ROM in 8000-9FFF. // ROM in 8000-9FFF.
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper0013 : CartridgeDevice private sealed class Mapper0013 : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[][] _banks; //8000 private readonly int[][] _banks; //8000
[SaveState.SaveWithName("BankMask")] [SaveState.SaveWithName("BankMask")]
private readonly int _bankMask; private readonly int _bankMask;
[SaveState.SaveWithName("BankNumber")] [SaveState.SaveWithName("BankNumber")]
private int _bankNumber; private int _bankNumber;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int[] _currentBank; private int[] _currentBank;
[SaveState.SaveWithName("ROMEnable")] [SaveState.SaveWithName("ROMEnable")]
private bool _romEnable; private bool _romEnable;
public Mapper0013(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper0013(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
var count = newAddresses.Count; var count = newAddresses.Count;
pinGame = true; pinGame = true;
pinExRom = false; pinExRom = false;
_romEnable = true; _romEnable = true;
// build dummy bank // build dummy bank
var dummyBank = new int[0x2000]; var dummyBank = new int[0x2000];
for (var i = 0; i < 0x2000; i++) for (var i = 0; i < 0x2000; i++)
dummyBank[i] = 0xFF; // todo: determine if this is correct dummyBank[i] = 0xFF; // todo: determine if this is correct
switch (count) switch (count)
{ {
case 16: case 16:
_bankMask = 0x0F; _bankMask = 0x0F;
_banks = new int[16][]; _banks = new int[16][];
break; break;
case 8: case 8:
_bankMask = 0x07; _bankMask = 0x07;
_banks = new int[8][]; _banks = new int[8][];
break; break;
case 4: case 4:
_bankMask = 0x03; _bankMask = 0x03;
_banks = new int[4][]; _banks = new int[4][];
break; break;
default: default:
throw new Exception("This looks like a Domark/HES cartridge but cannot be loaded..."); throw new Exception("This looks like a Domark/HES cartridge but cannot be loaded...");
} }
// for safety, initialize all banks to dummy // for safety, initialize all banks to dummy
for (var i = 0; i < _banks.Length; i++) for (var i = 0; i < _banks.Length; i++)
_banks[i] = dummyBank; _banks[i] = dummyBank;
// now load in the banks // now load in the banks
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)
{ {
if (newAddresses[i] == 0x8000) if (newAddresses[i] == 0x8000)
{ {
_banks[newBanks[i] & _bankMask] = newData[i]; _banks[newBanks[i] & _bankMask] = newData[i];
} }
} }
BankSet(0); BankSet(0);
} }
private void BankSet(int index) private void BankSet(int index)
{ {
_bankNumber = index & _bankMask; _bankNumber = index & _bankMask;
_romEnable = (index & 0x80) == 0; _romEnable = (index & 0x80) == 0;
UpdateState(); UpdateState();
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _currentBank[addr]; return _currentBank[addr];
} }
public override void PokeDE00(int addr, int val) public override void PokeDE00(int addr, int val)
{ {
if (addr == 0x00) if (addr == 0x00)
BankSet(val); BankSet(val);
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return _currentBank[addr]; return _currentBank[addr];
} }
private void UpdateState() private void UpdateState()
{ {
_currentBank = _banks[_bankNumber]; _currentBank = _banks[_bankNumber];
if (_romEnable) if (_romEnable)
{ {
pinExRom = false; pinExRom = false;
pinGame = true; pinGame = true;
} }
else else
{ {
pinExRom = true; pinExRom = true;
pinGame = true; pinGame = true;
} }
} }
public override void WriteDE00(int addr, int val) public override void WriteDE00(int addr, int val)
{ {
if (addr == 0x00) if (addr == 0x00)
BankSet(val); BankSet(val);
} }
public override void SyncState(Serializer ser) public override void SyncState(Serializer ser)
{ {
base.SyncState(ser); base.SyncState(ser);
if (ser.IsReader) if (ser.IsReader)
BankSet(_bankNumber | (_romEnable ? 0x00 : 0x80)); BankSet(_bankNumber | (_romEnable ? 0x00 : 0x80));
} }
} }
} }
} }

View File

@ -5,294 +5,294 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// EasyFlash cartridge // EasyFlash cartridge
// No official games came on one of these but there // No official games came on one of these but there
// are a few dumps from GameBase64 that use this mapper // are a few dumps from GameBase64 that use this mapper
// There are 64 banks total, DE00 is bank select. // There are 64 banks total, DE00 is bank select.
// Selecing a bank will select both Lo and Hi ROM. // Selecing a bank will select both Lo and Hi ROM.
// DE02 will switch exrom/game bits: bit 0=game, // DE02 will switch exrom/game bits: bit 0=game,
// bit 1=exrom, bit 2=for our cases, always set true. // bit 1=exrom, bit 2=for our cases, always set true.
// These two registers are write only. // These two registers are write only.
// This cartridge always starts up in Ultimax mode, // This cartridge always starts up in Ultimax mode,
// with Game set high and ExRom set low. // with Game set high and ExRom set low.
// There is also 256 bytes RAM at DF00-DFFF. // There is also 256 bytes RAM at DF00-DFFF.
// We emulate having the AM29F040 chip. // We emulate having the AM29F040 chip.
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private sealed class Mapper0020 : CartridgeDevice private sealed class Mapper0020 : CartridgeDevice
{ {
[SaveState.SaveWithName("BankOffset")] [SaveState.SaveWithName("BankOffset")]
private int _bankOffset = 63 << 13; private int _bankOffset = 63 << 13;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int[] _banksA = new int[64 << 13]; //8000 private int[] _banksA = new int[64 << 13]; //8000
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int[] _banksB = new int[64 << 13]; //A000 private int[] _banksB = new int[64 << 13]; //A000
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _originalMediaA; //8000 private readonly int[] _originalMediaA; //8000
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _originalMediaB; //A000 private readonly int[] _originalMediaB; //A000
[SaveState.SaveWithName("BoardLed")] [SaveState.SaveWithName("BoardLed")]
private bool _boardLed; private bool _boardLed;
[SaveState.SaveWithName("Jumper")] [SaveState.SaveWithName("Jumper")]
private bool _jumper = false; private bool _jumper = false;
[SaveState.SaveWithName("StateBits")] [SaveState.SaveWithName("StateBits")]
private int _stateBits; private int _stateBits;
[SaveState.SaveWithName("RAM")] [SaveState.SaveWithName("RAM")]
private readonly int[] _ram = new int[256]; private readonly int[] _ram = new int[256];
[SaveState.SaveWithName("CommandLatch55")] [SaveState.SaveWithName("CommandLatch55")]
private bool _commandLatch55; private bool _commandLatch55;
[SaveState.SaveWithName("CommandLatchAA")] [SaveState.SaveWithName("CommandLatchAA")]
private bool _commandLatchAa; private bool _commandLatchAa;
[SaveState.SaveWithName("InternalROMState")] [SaveState.SaveWithName("InternalROMState")]
private int _internalRomState; private int _internalRomState;
public Mapper0020(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper0020(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
DriveLightEnabled = true; DriveLightEnabled = true;
var count = newAddresses.Count; var count = newAddresses.Count;
// force ultimax mode (the cart SHOULD set this // force ultimax mode (the cart SHOULD set this
// otherwise on load, according to the docs) // otherwise on load, according to the docs)
pinGame = false; pinGame = false;
pinExRom = true; pinExRom = true;
// for safety, initialize all banks to dummy // for safety, initialize all banks to dummy
for (var i = 0; i < 64*0x2000; i++) for (var i = 0; i < 64 * 0x2000; i++)
{ {
_banksA[i] = 0xFF; _banksA[i] = 0xFF;
_banksB[i] = 0xFF; _banksB[i] = 0xFF;
} }
// load in all banks // load in all banks
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)
{ {
switch (newAddresses[i]) switch (newAddresses[i])
{ {
case 0x8000: case 0x8000:
Array.Copy(newData[i], 0, _banksA, newBanks[i] * 0x2000, 0x2000); Array.Copy(newData[i], 0, _banksA, newBanks[i] * 0x2000, 0x2000);
break; break;
case 0xA000: case 0xA000:
case 0xE000: case 0xE000:
Array.Copy(newData[i], 0, _banksB, newBanks[i] * 0x2000, 0x2000); Array.Copy(newData[i], 0, _banksB, newBanks[i] * 0x2000, 0x2000);
break; break;
} }
} }
// default to bank 0 // default to bank 0
BankSet(0); BankSet(0);
// internal operation settings // internal operation settings
_commandLatch55 = false; _commandLatch55 = false;
_commandLatchAa = false; _commandLatchAa = false;
_internalRomState = 0; _internalRomState = 0;
// back up original media // back up original media
_originalMediaA = _banksA.Select(d => d).ToArray(); _originalMediaA = _banksA.Select(d => d).ToArray();
_originalMediaB = _banksB.Select(d => d).ToArray(); _originalMediaB = _banksB.Select(d => d).ToArray();
} }
private void BankSet(int index) private void BankSet(int index)
{ {
_bankOffset = (index & 0x3F) << 13; _bankOffset = (index & 0x3F) << 13;
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
addr &= 0x1FFF; addr &= 0x1FFF;
return _banksA[addr | _bankOffset]; return _banksA[addr | _bankOffset];
} }
public override int PeekA000(int addr) public override int PeekA000(int addr)
{ {
addr &= 0x1FFF; addr &= 0x1FFF;
return _banksB[addr | _bankOffset]; return _banksB[addr | _bankOffset];
} }
public override int PeekDE00(int addr) public override int PeekDE00(int addr)
{ {
// normally you can't read these regs // normally you can't read these regs
// but Peek is provided here for debug reasons // but Peek is provided here for debug reasons
// and may not stay around // and may not stay around
addr &= 0x02; addr &= 0x02;
return addr == 0x00 ? _bankOffset >> 13 : _stateBits; return addr == 0x00 ? _bankOffset >> 13 : _stateBits;
} }
public override int PeekDF00(int addr) public override int PeekDF00(int addr)
{ {
addr &= 0xFF; addr &= 0xFF;
return _ram[addr]; return _ram[addr];
} }
public override void PokeDE00(int addr, int val) public override void PokeDE00(int addr, int val)
{ {
addr &= 0x02; addr &= 0x02;
if (addr == 0x00) if (addr == 0x00)
BankSet(val); BankSet(val);
else else
StateSet(val); StateSet(val);
} }
public override void PokeDF00(int addr, int val) public override void PokeDF00(int addr, int val)
{ {
addr &= 0xFF; addr &= 0xFF;
_ram[addr] = val & 0xFF; _ram[addr] = val & 0xFF;
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return ReadInternal(addr & 0x1FFF, _banksA); return ReadInternal(addr & 0x1FFF, _banksA);
} }
public override int ReadA000(int addr) public override int ReadA000(int addr)
{ {
return ReadInternal(addr & 0x1FFF, _banksB); return ReadInternal(addr & 0x1FFF, _banksB);
} }
public override int ReadDF00(int addr) public override int ReadDF00(int addr)
{ {
addr &= 0xFF; addr &= 0xFF;
return _ram[addr]; return _ram[addr];
} }
private int ReadInternal(int addr, int[] bank) private int ReadInternal(int addr, int[] bank)
{ {
switch (_internalRomState) switch (_internalRomState)
{ {
case 0x80: case 0x80:
break; break;
case 0x90: case 0x90:
switch (addr & 0x1FFF) switch (addr & 0x1FFF)
{ {
case 0x0000: case 0x0000:
return 0x01; return 0x01;
case 0x0001: case 0x0001:
return 0xA4; return 0xA4;
case 0x0002: case 0x0002:
return 0x00; return 0x00;
} }
break; break;
case 0xA0: case 0xA0:
break; break;
case 0xF0: case 0xF0:
break; break;
} }
return bank[addr | _bankOffset]; return bank[addr | _bankOffset];
} }
private void StateSet(int val) private void StateSet(int val)
{ {
_stateBits = val &= 0x87; _stateBits = val &= 0x87;
if ((val & 0x04) != 0) if ((val & 0x04) != 0)
pinGame = (val & 0x01) == 0; pinGame = (val & 0x01) == 0;
else else
pinGame = _jumper; pinGame = _jumper;
pinExRom = (val & 0x02) == 0; pinExRom = (val & 0x02) == 0;
_boardLed = (val & 0x80) != 0; _boardLed = (val & 0x80) != 0;
_internalRomState = 0; _internalRomState = 0;
DriveLightOn = _boardLed; DriveLightOn = _boardLed;
} }
public override void Write8000(int addr, int val) public override void Write8000(int addr, int val)
{ {
WriteInternal(addr, val); WriteInternal(addr, val);
} }
public override void WriteA000(int addr, int val) public override void WriteA000(int addr, int val)
{ {
WriteInternal(addr | 0x2000, val); WriteInternal(addr | 0x2000, val);
} }
private void WriteInternal(int addr, int val) private void WriteInternal(int addr, int val)
{ {
if (pinGame || !pinExRom) if (pinGame || !pinExRom)
{ {
return; return;
} }
if (val == 0xF0) // any address, resets flash if (val == 0xF0) // any address, resets flash
{ {
_internalRomState = 0; _internalRomState = 0;
_commandLatch55 = false; _commandLatch55 = false;
_commandLatchAa = false; _commandLatchAa = false;
} }
else if (_internalRomState != 0x00 && _internalRomState != 0xF0) else if (_internalRomState != 0x00 && _internalRomState != 0xF0)
{ {
switch (_internalRomState) switch (_internalRomState)
{ {
case 0xA0: case 0xA0:
if ((addr & 0x2000) == 0) if ((addr & 0x2000) == 0)
{ {
addr &= 0x1FFF; addr &= 0x1FFF;
_banksA[addr | _bankOffset] = val & 0xFF; _banksA[addr | _bankOffset] = val & 0xFF;
} }
else else
{ {
addr &= 0x1FFF; addr &= 0x1FFF;
_banksB[addr | _bankOffset] = val & 0xFF; _banksB[addr | _bankOffset] = val & 0xFF;
} }
break; break;
} }
} }
else if (addr == 0x0555) // $8555 else if (addr == 0x0555) // $8555
{ {
if (!_commandLatchAa) if (!_commandLatchAa)
{ {
if (val == 0xAA) if (val == 0xAA)
{ {
_commandLatch55 = true; _commandLatch55 = true;
} }
} }
else else
{ {
// process EZF command // process EZF command
_internalRomState = val; _internalRomState = val;
} }
} }
else if (addr == 0x02AA) // $82AA else if (addr == 0x02AA) // $82AA
{ {
if (_commandLatch55 && val == 0x55) if (_commandLatch55 && val == 0x55)
{ {
_commandLatchAa = true; _commandLatchAa = true;
} }
else else
{ {
_commandLatch55 = false; _commandLatch55 = false;
} }
} }
else else
{ {
_commandLatch55 = false; _commandLatch55 = false;
_commandLatchAa = false; _commandLatchAa = false;
} }
} }
public override void WriteDE00(int addr, int val) public override void WriteDE00(int addr, int val)
{ {
addr &= 0x02; addr &= 0x02;
if (addr == 0x00) if (addr == 0x00)
BankSet(val); BankSet(val);
else else
StateSet(val); StateSet(val);
} }
public override void WriteDF00(int addr, int val) public override void WriteDF00(int addr, int val)
{ {
_ram[addr] = val & 0xFF; _ram[addr] = val & 0xFF;
} }
public override void SyncState(Serializer ser) public override void SyncState(Serializer ser)
{ {
SaveState.SyncDelta("MediaStateA", ser, _originalMediaA, ref _banksA); SaveState.SyncDelta("MediaStateA", ser, _originalMediaA, ref _banksA);
SaveState.SyncDelta("MediaStateB", ser, _originalMediaB, ref _banksB); SaveState.SyncDelta("MediaStateB", ser, _originalMediaB, ref _banksB);
base.SyncState(ser); base.SyncState(ser);
DriveLightOn = _boardLed; DriveLightOn = _boardLed;
} }
} }
} }
} }

View File

@ -5,76 +5,76 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{ {
// Prophet 64 cartridge. Because we can. // Prophet 64 cartridge. Because we can.
// 32 banks of 8KB. // 32 banks of 8KB.
// DFxx = status register, xxABBBBB. A=enable cart, B=bank // DFxx = status register, xxABBBBB. A=enable cart, B=bank
// Thanks to VICE team for the info: http://vice-emu.sourceforge.net/vice_15.html // Thanks to VICE team for the info: http://vice-emu.sourceforge.net/vice_15.html
public abstract partial class CartridgeDevice public abstract partial class CartridgeDevice
{ {
private class Mapper002B : CartridgeDevice private class Mapper002B : CartridgeDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private readonly int[] _rom; private readonly int[] _rom;
[SaveState.SaveWithName("RomOffset")] [SaveState.SaveWithName("RomOffset")]
private int _romOffset; private int _romOffset;
[SaveState.SaveWithName("RomEnabled")] [SaveState.SaveWithName("RomEnabled")]
private bool _romEnabled; private bool _romEnabled;
public Mapper002B(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData) public Mapper002B(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{ {
pinExRom = false; pinExRom = false;
pinGame = true; pinGame = true;
_rom = new int[0x40000]; _rom = new int[0x40000];
Array.Copy(newData.First(), _rom, 0x2000); Array.Copy(newData.First(), _rom, 0x2000);
pinGame = true; pinGame = true;
for (var i = 0; i < newData.Count; i++) for (var i = 0; i < newData.Count; i++)
{ {
if (newAddresses[i] == 0x8000) if (newAddresses[i] == 0x8000)
{ {
Array.Copy(newData[i], 0, _rom, newBanks[i] * 0x2000, 0x2000); Array.Copy(newData[i], 0, _rom, newBanks[i] * 0x2000, 0x2000);
} }
} }
} }
public override void HardReset() public override void HardReset()
{ {
_romEnabled = true; _romEnabled = true;
_romOffset = 0; _romOffset = 0;
} }
public override int Peek8000(int addr) public override int Peek8000(int addr)
{ {
return _romOffset | (addr & 0x1FFF); return _romOffset | (addr & 0x1FFF);
} }
public override int PeekDF00(int addr) public override int PeekDF00(int addr)
{ {
// For debugging only. The processor does not see this. // For debugging only. The processor does not see this.
return ((_romOffset >> 13) & 0x1F) | (_romEnabled ? 0x20 : 0x00); return ((_romOffset >> 13) & 0x1F) | (_romEnabled ? 0x20 : 0x00);
} }
public override void PokeDF00(int addr, int val) public override void PokeDF00(int addr, int val)
{ {
_romOffset = (val & 0x1F) << 13; _romOffset = (val & 0x1F) << 13;
_romEnabled = (val & 0x20) != 0; _romEnabled = (val & 0x20) != 0;
} }
public override int Read8000(int addr) public override int Read8000(int addr)
{ {
return _romOffset | (addr & 0x1FFF); return _romOffset | (addr & 0x1FFF);
} }
public override int ReadDF00(int addr) public override int ReadDF00(int addr)
{ {
return 0x00; return 0x00;
} }
public override void WriteDF00(int addr, int val) public override void WriteDF00(int addr, int val)
{ {
_romOffset = (val & 0x1F) << 13; _romOffset = (val & 0x1F) << 13;
_romEnabled = (val & 0x20) != 0; _romEnabled = (val & 0x20) != 0;
} }
} }
} }
} }

View File

@ -3,60 +3,60 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
{ {
public sealed class CassettePort public sealed class CassettePort
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadDataOutput = () => true; public Func<bool> ReadDataOutput = () => true;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMotor = () => true; public Func<bool> ReadMotor = () => true;
[SaveState.SaveWithName("Device")] [SaveState.SaveWithName("Device")]
private CassettePortDevice _device; private CassettePortDevice _device;
[SaveState.SaveWithName("Connected")] [SaveState.SaveWithName("Connected")]
private bool _connected; private bool _connected;
public void HardReset() public void HardReset()
{ {
if (_connected) if (_connected)
{ {
_device.HardReset(); _device.HardReset();
} }
} }
public void ExecutePhase() public void ExecutePhase()
{ {
if (_connected) if (_connected)
{ {
_device.ExecutePhase2(); _device.ExecutePhase2();
} }
} }
public bool ReadDataInputBuffer() public bool ReadDataInputBuffer()
{ {
return !_connected || _device.ReadDataInputBuffer(); return !_connected || _device.ReadDataInputBuffer();
} }
public bool ReadSenseBuffer() public bool ReadSenseBuffer()
{ {
return !_connected || _device.ReadSenseBuffer(); return !_connected || _device.ReadSenseBuffer();
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
public void Connect(CassettePortDevice device) public void Connect(CassettePortDevice device)
{ {
_connected = device != null; _connected = device != null;
_device = device; _device = device;
if (_device == null) if (_device == null)
{ {
return; return;
} }
_device.ReadDataOutput = () => ReadDataOutput(); _device.ReadDataOutput = () => ReadDataOutput();
_device.ReadMotor = () => ReadMotor(); _device.ReadMotor = () => ReadMotor();
} }
} }
} }

View File

@ -3,34 +3,34 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
{ {
public abstract class CassettePortDevice public abstract class CassettePortDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadDataOutput; public Func<bool> ReadDataOutput;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMotor; public Func<bool> ReadMotor;
public virtual void ExecutePhase2() public virtual void ExecutePhase2()
{ {
} }
public virtual void HardReset() public virtual void HardReset()
{ {
} }
public virtual bool ReadDataInputBuffer() public virtual bool ReadDataInputBuffer()
{ {
return true; return true;
} }
public virtual bool ReadSenseBuffer() public virtual bool ReadSenseBuffer()
{ {
return true; return true;
} }
public virtual void SyncState(Serializer ser) public virtual void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }

View File

@ -3,44 +3,44 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
{ {
public class TapeDrive : CassettePortDevice public class TapeDrive : CassettePortDevice
{ {
[SaveState.SaveWithName("Tape")] [SaveState.SaveWithName("Tape")]
private Tape _tape; private Tape _tape;
public override void ExecutePhase2() public override void ExecutePhase2()
{ {
if (_tape != null && !ReadMotor()) _tape.ExecuteCycle(); if (_tape != null && !ReadMotor()) _tape.ExecuteCycle();
} }
public override void HardReset() public override void HardReset()
{ {
if (_tape != null) _tape.Rewind(); if (_tape != null) _tape.Rewind();
} }
public override bool ReadDataInputBuffer() public override bool ReadDataInputBuffer()
{ {
return _tape == null || _tape.Read(); return _tape == null || _tape.Read();
} }
public override bool ReadSenseBuffer() public override bool ReadSenseBuffer()
{ {
return _tape == null; return _tape == null;
} }
public override void SyncState(Serializer ser) public override void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
public void Insert(Tape tape) public void Insert(Tape tape)
{ {
_tape = tape; _tape = tape;
} }
public void RemoveMedia() public void RemoveMedia()
{ {
_tape = null; _tape = null;
} }
} }
} }

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public sealed class Chip2114 public sealed class Chip2114
{ {
private int[] _ram = new int[0x400]; private int[] _ram = new int[0x400];
public Chip2114() public Chip2114()
{ {
@ -15,10 +15,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void HardReset() public void HardReset()
{ {
for (var i = 0; i < 0x400; i++) for (var i = 0; i < 0x400; i++)
{ {
_ram[i] = 0x0; _ram[i] = 0x0;
} }
} }
public int Peek(int addr) public int Peek(int addr)

View File

@ -6,28 +6,28 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
// ROM chips // ROM chips
public sealed class Chip23128 public sealed class Chip23128
{ {
[SaveState.DoNotSave] private readonly int[] _rom; [SaveState.DoNotSave] private readonly int[] _rom;
public Chip23128() public Chip23128()
{
_rom = new int[0x4000];
}
public Chip23128(byte[] data) : this()
{ {
Flash(data); _rom = new int[0x4000];
} }
public void Flash(byte[] data) public Chip23128(byte[] data) : this()
{ {
// ensures ROM is mirrored Flash(data);
for (var i = 0; i < _rom.Length; i += data.Length) }
{
Array.Copy(data, 0, _rom, i, data.Length);
}
}
public int Peek(int addr) public void Flash(byte[] data)
{
// ensures ROM is mirrored
for (var i = 0; i < _rom.Length; i += data.Length)
{
Array.Copy(data, 0, _rom, i, data.Length);
}
}
public int Peek(int addr)
{ {
return _rom[addr & 0x3FFF]; return _rom[addr & 0x3FFF];
} }

View File

@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public sealed class Chip4864 public sealed class Chip4864
{ {
private int[] _ram; private int[] _ram;
public Chip4864() public Chip4864()
{ {

View File

@ -6,159 +6,159 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Chip6510 : IDebuggable public sealed partial class Chip6510 : IDebuggable
{ {
IDictionary<string, RegisterValue> IDebuggable.GetCpuFlagsAndRegisters() IDictionary<string, RegisterValue> IDebuggable.GetCpuFlagsAndRegisters()
{ {
return new Dictionary<string, RegisterValue> return new Dictionary<string, RegisterValue>
{ {
{ "A", _cpu.A }, { "A", _cpu.A },
{ "X", _cpu.X }, { "X", _cpu.X },
{ "Y", _cpu.Y }, { "Y", _cpu.Y },
{ "S", _cpu.S }, { "S", _cpu.S },
{ "PC", _cpu.PC }, { "PC", _cpu.PC },
{ "Flag C", _cpu.FlagC }, { "Flag C", _cpu.FlagC },
{ "Flag Z", _cpu.FlagZ }, { "Flag Z", _cpu.FlagZ },
{ "Flag I", _cpu.FlagI }, { "Flag I", _cpu.FlagI },
{ "Flag D", _cpu.FlagD }, { "Flag D", _cpu.FlagD },
{ "Flag B", _cpu.FlagB }, { "Flag B", _cpu.FlagB },
{ "Flag V", _cpu.FlagV }, { "Flag V", _cpu.FlagV },
{ "Flag N", _cpu.FlagN }, { "Flag N", _cpu.FlagN },
{ "Flag T", _cpu.FlagT } { "Flag T", _cpu.FlagT }
}; };
} }
void IDebuggable.SetCpuRegister(string register, int value) void IDebuggable.SetCpuRegister(string register, int value)
{ {
switch (register) switch (register)
{ {
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
case "A": case "A":
_cpu.A = (byte)value; _cpu.A = (byte)value;
break; break;
case "X": case "X":
_cpu.X = (byte)value; _cpu.X = (byte)value;
break; break;
case "Y": case "Y":
_cpu.Y = (byte)value; _cpu.Y = (byte)value;
break; break;
case "S": case "S":
_cpu.S = (byte)value; _cpu.S = (byte)value;
break; break;
case "PC": case "PC":
_cpu.PC = (ushort)value; _cpu.PC = (ushort)value;
break; break;
} }
} }
bool IDebuggable.CanStep(StepType type) bool IDebuggable.CanStep(StepType type)
{ {
switch (type) switch (type)
{ {
case StepType.Into: case StepType.Into:
case StepType.Over: case StepType.Over:
case StepType.Out: case StepType.Out:
return DebuggerStep != null; return DebuggerStep != null;
default: default:
return false; return false;
} }
} }
void IDebuggable.Step(StepType type) void IDebuggable.Step(StepType type)
{ {
switch (type) switch (type)
{ {
case StepType.Into: case StepType.Into:
StepInto(); StepInto();
break; break;
case StepType.Out: case StepType.Out:
StepOut(); StepOut();
break; break;
case StepType.Over: case StepType.Over:
StepOver(); StepOver();
break; break;
} }
} }
int IDebuggable.TotalExecutedCycles int IDebuggable.TotalExecutedCycles
{ {
get { return _cpu.TotalExecutedCycles; } get { return _cpu.TotalExecutedCycles; }
} }
private void StepInto() private void StepInto()
{ {
while (_cpu.AtInstructionStart()) while (_cpu.AtInstructionStart())
{ {
DebuggerStep(); DebuggerStep();
} }
while (!_cpu.AtInstructionStart()) while (!_cpu.AtInstructionStart())
{ {
DebuggerStep(); DebuggerStep();
} }
} }
private void StepOver() private void StepOver()
{ {
var instruction = CpuPeek(_cpu.PC); var instruction = CpuPeek(_cpu.PC);
if (instruction == Jsr) if (instruction == Jsr)
{ {
var destination = _cpu.PC + JsrSize; var destination = _cpu.PC + JsrSize;
while (_cpu.PC != destination) while (_cpu.PC != destination)
{ {
StepInto(); StepInto();
} }
} }
else else
{ {
StepInto(); StepInto();
} }
} }
private void StepOut() private void StepOut()
{ {
var instructionsBeforeBailout = 1000000; var instructionsBeforeBailout = 1000000;
var instr = CpuPeek(_cpu.PC); var instr = CpuPeek(_cpu.PC);
_jsrCount = instr == Jsr ? 1 : 0; _jsrCount = instr == Jsr ? 1 : 0;
while (--instructionsBeforeBailout > 0) while (--instructionsBeforeBailout > 0)
{ {
StepInto(); StepInto();
instr = CpuPeek(_cpu.PC); instr = CpuPeek(_cpu.PC);
if (instr == Jsr) if (instr == Jsr)
{ {
_jsrCount++; _jsrCount++;
} }
else if ((instr == Rts || instr == Rti) && _jsrCount <= 0) else if ((instr == Rts || instr == Rti) && _jsrCount <= 0)
{ {
StepInto(); StepInto();
_jsrCount = 0; _jsrCount = 0;
break; break;
} }
else if (instr == Rts || instr == Rti) else if (instr == Rts || instr == Rti)
{ {
_jsrCount--; _jsrCount--;
} }
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int _jsrCount; private int _jsrCount;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte Jsr = 0x20; private const byte Jsr = 0x20;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte Rti = 0x40; private const byte Rti = 0x40;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte Rts = 0x60; private const byte Rts = 0x60;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte JsrSize = 3; private const byte JsrSize = 3;
[SaveState.DoNotSave] private IMemoryCallbackSystem _memoryCallbacks = new MemoryCallbackSystem(); [SaveState.DoNotSave] private IMemoryCallbackSystem _memoryCallbacks = new MemoryCallbackSystem();
[SaveState.DoNotSave] [SaveState.DoNotSave]
IMemoryCallbackSystem IDebuggable.MemoryCallbacks { get { return _memoryCallbacks; } } IMemoryCallbackSystem IDebuggable.MemoryCallbacks { get { return _memoryCallbacks; } }
} }
} }

View File

@ -6,29 +6,29 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Chip6510 : IDisassemblable public sealed partial class Chip6510 : IDisassemblable
{ {
public IEnumerable<string> AvailableCpus public IEnumerable<string> AvailableCpus
{ {
get { yield return "6510"; } get { yield return "6510"; }
} }
public string Cpu public string Cpu
{ {
get { return "6510"; } get { return "6510"; }
set set
{ {
} }
} }
public string PCRegisterName public string PCRegisterName
{ {
get { return "PC"; } get { return "PC"; }
} }
public string Disassemble(MemoryDomain m, uint addr, out int length) public string Disassemble(MemoryDomain m, uint addr, out int length)
{ {
return Components.M6502.MOS6502X.Disassemble((ushort)addr, out length, CpuPeek); return Components.M6502.MOS6502X.Disassemble((ushort)addr, out length, CpuPeek);
} }
} }
} }

View File

@ -13,10 +13,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
// ------------------------------------ // ------------------------------------
private MOS6502X _cpu; private MOS6502X _cpu;
private bool _pinNmiLast; private bool _pinNmiLast;
private LatchedPort _port; private LatchedPort _port;
private bool _thisNmi; private bool _thisNmi;
public Func<int, int> PeekMemory; public Func<int, int> PeekMemory;
public Action<int, int> PokeMemory; public Action<int, int> PokeMemory;
@ -29,52 +29,52 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public Action<int, int> WriteMemory; public Action<int, int> WriteMemory;
public Action<int, int> WriteMemoryPort; public Action<int, int> WriteMemoryPort;
public Action DebuggerStep; public Action DebuggerStep;
// ------------------------------------ // ------------------------------------
public Chip6510() public Chip6510()
{ {
// configure cpu r/w // configure cpu r/w
_cpu = new MOS6502X _cpu = new MOS6502X
{ {
DummyReadMemory = CpuRead, DummyReadMemory = CpuRead,
ReadMemory = CpuRead, ReadMemory = CpuRead,
WriteMemory = CpuWrite, WriteMemory = CpuWrite,
PeekMemory = CpuPeek PeekMemory = CpuPeek
}; };
// perform hard reset // perform hard reset
HardReset(); HardReset();
} }
public void SetOverflow() public void SetOverflow()
{ {
} }
private byte CpuPeek(ushort addr) private byte CpuPeek(ushort addr)
{ {
return unchecked((byte)Peek(addr)); return unchecked((byte)Peek(addr));
} }
private byte CpuRead(ushort addr) private byte CpuRead(ushort addr)
{ {
return unchecked((byte) Read(addr)); return unchecked((byte)Read(addr));
} }
private void CpuWrite(ushort addr, byte val) private void CpuWrite(ushort addr, byte val)
{ {
Write(addr, val); Write(addr, val);
} }
public void HardReset() public void HardReset()
{ {
_cpu.NESSoftReset(); _cpu.NESSoftReset();
_port = new LatchedPort _port = new LatchedPort
{ {
Direction = 0x00, Direction = 0x00,
Latch = 0xFF Latch = 0xFF
}; };
_pinNmiLast = true; _pinNmiLast = true;
} }
@ -82,33 +82,33 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void ExecutePhase() public void ExecutePhase()
{ {
_cpu.RDY = ReadRdy(); _cpu.RDY = ReadRdy();
if (ReadAec()) if (ReadAec())
{ {
_cpu.IRQ = !ReadIrq(); _cpu.IRQ = !ReadIrq();
_pinNmiLast = _thisNmi; _pinNmiLast = _thisNmi;
_thisNmi = ReadNmi(); _thisNmi = ReadNmi();
_cpu.NMI |= _pinNmiLast && !_thisNmi; _cpu.NMI |= _pinNmiLast && !_thisNmi;
_cpu.ExecuteOne(); _cpu.ExecuteOne();
} }
else else
{ {
LagCycles++; LagCycles++;
} }
} }
public int LagCycles; public int LagCycles;
internal bool AtInstructionStart() internal bool AtInstructionStart()
{ {
return _cpu.AtInstructionStart(); return _cpu.AtInstructionStart();
} }
// ------------------------------------ // ------------------------------------
[SaveState.DoNotSave] [SaveState.DoNotSave]
public ushort Pc public ushort Pc
{ {
get get
{ {
@ -120,78 +120,82 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int A public int A
{ {
get { return _cpu.A; } set { _cpu.A = unchecked((byte)value); } get { return _cpu.A; }
set { _cpu.A = unchecked((byte)value); }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int X public int X
{ {
get { return _cpu.X; } set { _cpu.X = unchecked((byte)value); } get { return _cpu.X; }
set { _cpu.X = unchecked((byte)value); }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int Y public int Y
{ {
get { return _cpu.Y; } set { _cpu.Y = unchecked((byte)value); } get { return _cpu.Y; }
set { _cpu.Y = unchecked((byte)value); }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int S public int S
{ {
get { return _cpu.S; } set { _cpu.S = unchecked((byte)value); } get { return _cpu.S; }
set { _cpu.S = unchecked((byte)value); }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagC { get { return _cpu.FlagC; } } public bool FlagC { get { return _cpu.FlagC; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagZ { get { return _cpu.FlagZ; } } public bool FlagZ { get { return _cpu.FlagZ; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagI { get { return _cpu.FlagI; } } public bool FlagI { get { return _cpu.FlagI; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagD { get { return _cpu.FlagD; } } public bool FlagD { get { return _cpu.FlagD; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagB { get { return _cpu.FlagB; } } public bool FlagB { get { return _cpu.FlagB; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagV { get { return _cpu.FlagV; } } public bool FlagV { get { return _cpu.FlagV; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagN { get { return _cpu.FlagN; } } public bool FlagN { get { return _cpu.FlagN; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool FlagT { get { return _cpu.FlagT; } } public bool FlagT { get { return _cpu.FlagT; } }
public int Peek(int addr) public int Peek(int addr)
{ {
switch (addr) switch (addr)
{ {
case 0x0000: case 0x0000:
return _port.Direction; return _port.Direction;
case 0x0001: case 0x0001:
return PortData; return PortData;
default: default:
return PeekMemory(addr); return PeekMemory(addr);
} }
} }
public void Poke(int addr, int val) public void Poke(int addr, int val)
{ {
switch (addr) switch (addr)
{ {
case 0x0000: case 0x0000:
_port.Direction = val; _port.Direction = val;
break; break;
case 0x0001: case 0x0001:
_port.Latch = val; _port.Latch = val;
break; break;
default: default:
PokeMemory(addr, val); PokeMemory(addr, val);
break; break;
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int PortData public int PortData
{ {
get get
{ {
@ -205,38 +209,38 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public int Read(int addr) public int Read(int addr)
{ {
switch (addr) switch (addr)
{ {
case 0x0000: case 0x0000:
return _port.Direction; return _port.Direction;
case 0x0001: case 0x0001:
return PortData; return PortData;
default: default:
return ReadMemory(addr); return ReadMemory(addr);
} }
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
public void Write(int addr, int val) public void Write(int addr, int val)
{ {
switch (addr) switch (addr)
{ {
case 0x0000: case 0x0000:
_port.Direction = val; _port.Direction = val;
WriteMemoryPort(addr, val); WriteMemoryPort(addr, val);
break; break;
case 0x0001: case 0x0001:
_port.Latch = val; _port.Latch = val;
WriteMemoryPort(addr, val); WriteMemoryPort(addr, val);
break; break;
default: default:
WriteMemory(addr, val); WriteMemory(addr, val);
break; break;
} }
} }
} }
} }

View File

@ -5,16 +5,16 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public static class Chip6522 public static class Chip6522
{ {
public static Via Create(Func<int> readPrA, Func<int> readPrB) public static Via Create(Func<int> readPrA, Func<int> readPrB)
{ {
return new Via(readPrA, readPrB); return new Via(readPrA, readPrB);
} }
public static Via Create(Func<bool> readClock, Func<bool> readData, Func<bool> readAtn, int driveNumber) public static Via Create(Func<bool> readClock, Func<bool> readData, Func<bool> readAtn, int driveNumber)
{ {
return new Via(readClock, readData, readAtn, driveNumber); return new Via(readClock, readData, readAtn, driveNumber);
} }
} }
} }

View File

@ -11,62 +11,62 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public static class Chip6526 public static class Chip6526
{ {
public static Cia Create(C64.CiaType type, Func<int> readIec) public static Cia Create(C64.CiaType type, Func<int> readIec)
{ {
switch (type) switch (type)
{ {
case C64.CiaType.Ntsc: case C64.CiaType.Ntsc:
return new Cia(14318181, 14*60, readIec) return new Cia(14318181, 14 * 60, readIec)
{ {
DelayedInterrupts = true DelayedInterrupts = true
}; };
case C64.CiaType.NtscRevA: case C64.CiaType.NtscRevA:
return new Cia(14318181, 14 * 60, readIec) return new Cia(14318181, 14 * 60, readIec)
{ {
DelayedInterrupts = false DelayedInterrupts = false
}; };
case C64.CiaType.Pal: case C64.CiaType.Pal:
return new Cia(17734472, 18 * 50, readIec) return new Cia(17734472, 18 * 50, readIec)
{ {
DelayedInterrupts = true DelayedInterrupts = true
}; };
case C64.CiaType.PalRevA: case C64.CiaType.PalRevA:
return new Cia(17734472, 18 * 50, readIec) return new Cia(17734472, 18 * 50, readIec)
{ {
DelayedInterrupts = false DelayedInterrupts = false
}; };
default: default:
throw new Exception("Unrecognized CIA timer type."); throw new Exception("Unrecognized CIA timer type.");
} }
} }
public static Cia Create(C64.CiaType type, Func<bool[]> keyboard, Func<bool[]> joysticks) public static Cia Create(C64.CiaType type, Func<bool[]> keyboard, Func<bool[]> joysticks)
{ {
switch (type) switch (type)
{ {
case C64.CiaType.Ntsc: case C64.CiaType.Ntsc:
return new Cia(14318181, 14 * 60, keyboard, joysticks) return new Cia(14318181, 14 * 60, keyboard, joysticks)
{ {
DelayedInterrupts = true DelayedInterrupts = true
}; };
case C64.CiaType.NtscRevA: case C64.CiaType.NtscRevA:
return new Cia(14318181, 14 * 60, keyboard, joysticks) return new Cia(14318181, 14 * 60, keyboard, joysticks)
{ {
DelayedInterrupts = false DelayedInterrupts = false
}; };
case C64.CiaType.Pal: case C64.CiaType.Pal:
return new Cia(17734472, 18 * 50, keyboard, joysticks) return new Cia(17734472, 18 * 50, keyboard, joysticks)
{ {
DelayedInterrupts = true DelayedInterrupts = true
}; };
case C64.CiaType.PalRevA: case C64.CiaType.PalRevA:
return new Cia(17734472, 18 * 50, keyboard, joysticks) return new Cia(17734472, 18 * 50, keyboard, joysticks)
{ {
DelayedInterrupts = false DelayedInterrupts = false
}; };
default: default:
throw new Exception("Unrecognized CIA timer type."); throw new Exception("Unrecognized CIA timer type.");
} }
} }
} }
} }

View File

@ -3,21 +3,21 @@
// vic ntsc old // vic ntsc old
public static class Chip6567R56A public static class Chip6567R56A
{ {
private static readonly int Cycles = 64; private static readonly int Cycles = 64;
private static readonly int ScanWidth = Cycles * 8; private static readonly int ScanWidth = Cycles * 8;
private static readonly int Lines = 262; private static readonly int Lines = 262;
private static readonly int Vblankstart = 0x00D % Lines; private static readonly int Vblankstart = 0x00D % Lines;
private static readonly int VblankEnd = 0x018 % Lines; private static readonly int VblankEnd = 0x018 % Lines;
private static readonly int HblankOffset = 24; private static readonly int HblankOffset = 24;
private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth; private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth;
private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth; private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth;
private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, ScanWidth, -1, -1); private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, ScanWidth, -1, -1);
private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x16C); private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x16C);
private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch); private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch);
private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x154, 0x164); private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x154, 0x164);
private static readonly int[][] Pipeline = { private static readonly int[][] Pipeline = {
Timing, Timing,
Fetch, Fetch,
Ba, Ba,
@ -32,8 +32,8 @@
14318181 / 14, 14318181 / 14,
HblankStart, HblankEnd, HblankStart, HblankEnd,
Vblankstart, VblankEnd, Vblankstart, VblankEnd,
borderType, borderType,
762, 1000 762, 1000
); );
} }
} }

View File

@ -3,25 +3,25 @@
// vic ntsc // vic ntsc
public static class Chip6567R8 public static class Chip6567R8
{ {
private static readonly int Cycles = 65; private static readonly int Cycles = 65;
private static readonly int ScanWidth = Cycles * 8; private static readonly int ScanWidth = Cycles * 8;
private static readonly int Lines = 263; private static readonly int Lines = 263;
private static readonly int VblankStart = 0x00D % Lines; private static readonly int VblankStart = 0x00D % Lines;
private static readonly int VblankEnd = 0x018 % Lines; private static readonly int VblankEnd = 0x018 % Lines;
private static readonly int HblankOffset = 24; private static readonly int HblankOffset = 24;
private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth; private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth;
private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth; private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth;
private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, ScanWidth, 0x184, 8); private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, ScanWidth, 0x184, 8);
private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x174); private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x174);
private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch); private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch);
private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x154, 0x16C); private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x154, 0x16C);
private static readonly int[][] Pipeline = { private static readonly int[][] Pipeline = {
Timing, Timing,
Fetch, Fetch,
Ba, Ba,
Act Act
}; };
public static Vic Create(C64.BorderType borderType) public static Vic Create(C64.BorderType borderType)
@ -33,8 +33,8 @@
HblankStart, HblankEnd, HblankStart, HblankEnd,
VblankStart, VblankEnd, VblankStart, VblankEnd,
borderType, borderType,
6136, 8182 6136, 8182
); );
} }
} }
} }

View File

@ -3,21 +3,21 @@
// vic pal // vic pal
public static class Chip6569 public static class Chip6569
{ {
private static readonly int Cycles = 63; private static readonly int Cycles = 63;
private static readonly int ScanWidth = Cycles * 8; private static readonly int ScanWidth = Cycles * 8;
private static readonly int Lines = 312; private static readonly int Lines = 312;
private static readonly int VblankStart = 0x120 % Lines; private static readonly int VblankStart = 0x120 % Lines;
private static readonly int VblankEnd = 0x00F % Lines; private static readonly int VblankEnd = 0x00F % Lines;
private static readonly int HblankOffset = 24; private static readonly int HblankOffset = 24;
private static readonly int HblankStart = (0x178 + HblankOffset) % ScanWidth; private static readonly int HblankStart = (0x178 + HblankOffset) % ScanWidth;
private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth; private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth;
private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, ScanWidth, -1, -1); private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, ScanWidth, -1, -1);
private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x164); private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x164);
private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch); private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch);
private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x14C, 0x164); private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x14C, 0x164);
private static readonly int[][] Pipeline = { private static readonly int[][] Pipeline = {
Timing, Timing,
Fetch, Fetch,
Ba, Ba,
@ -32,8 +32,8 @@
17734472 / 18, 17734472 / 18,
HblankStart, HblankEnd, HblankStart, HblankEnd,
VblankStart, VblankEnd, VblankStart, VblankEnd,
borderType, borderType,
7375, 7882 7375, 7882
); );
} }
} }

View File

@ -3,21 +3,21 @@
// pal n / drean - TODO correct? // pal n / drean - TODO correct?
public static class Chip6572 public static class Chip6572
{ {
private static readonly int Cycles = 65; private static readonly int Cycles = 65;
private static readonly int ScanWidth = Cycles * 8; private static readonly int ScanWidth = Cycles * 8;
private static readonly int Lines = 312; private static readonly int Lines = 312;
private static readonly int VblankStart = 0x12C % Lines; private static readonly int VblankStart = 0x12C % Lines;
private static readonly int VblankEnd = 0x00F % Lines; private static readonly int VblankEnd = 0x00F % Lines;
private static readonly int HblankOffset = 24; private static readonly int HblankOffset = 24;
private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth; private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth;
private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth; private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth;
private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, ScanWidth, 0x18C, 8); private static readonly int[] Timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, ScanWidth, 0x18C, 8);
private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x174); private static readonly int[] Fetch = Vic.TimingBuilder_Fetch(Timing, 0x174);
private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch); private static readonly int[] Ba = Vic.TimingBuilder_BA(Fetch);
private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x154, 0x16C); private static readonly int[] Act = Vic.TimingBuilder_Act(Timing, 0x004, 0x154, 0x16C);
private static readonly int[][] Pipeline = { private static readonly int[][] Pipeline = {
Timing, Timing,
Fetch, Fetch,
Ba, Ba,
@ -32,8 +32,8 @@
14328225 / 14, 14328225 / 14,
HblankStart, HblankEnd, HblankStart, HblankEnd,
VblankStart, VblankEnd, VblankStart, VblankEnd,
borderType, borderType,
908, 1000 908, 1000
); );
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -33,8 +33,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public Action<int, int> PokeMemory; public Action<int, int> PokeMemory;
public Action<int, int> PokeSid; public Action<int, int> PokeSid;
public Action<int, int> PokeVic; public Action<int, int> PokeVic;
public Func<bool> ReadAec; public Func<bool> ReadAec;
public Func<bool> ReadBa; public Func<bool> ReadBa;
public Func<int, int> ReadBasicRom; public Func<int, int> ReadBasicRom;
public Func<int, int> ReadCartridgeLo; public Func<int, int> ReadCartridgeLo;
public Func<int, int> ReadCartridgeHi; public Func<int, int> ReadCartridgeHi;
@ -63,10 +63,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public Action<int, int> WriteMemory; public Action<int, int> WriteMemory;
public Action<int, int> WriteSid; public Action<int, int> WriteSid;
public Action<int, int> WriteVic; public Action<int, int> WriteVic;
// ------------------------------------ // ------------------------------------
private enum PlaBank private enum PlaBank
{ {
None, None,
Ram, Ram,
@ -86,94 +86,94 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
// ------------------------------------ // ------------------------------------
private bool _p24; private bool _p24;
private bool _p25; private bool _p25;
private bool _p26; private bool _p26;
private bool _p27; private bool _p27;
private bool _p28; private bool _p28;
private bool _loram; private bool _loram;
private bool _hiram; private bool _hiram;
private bool _game; private bool _game;
private bool _exrom; private bool _exrom;
private bool _charen; private bool _charen;
private bool _a15; private bool _a15;
private bool _a14; private bool _a14;
private bool _a13; private bool _a13;
private bool _a12; private bool _a12;
private PlaBank Bank(int addr, bool read) private PlaBank Bank(int addr, bool read)
{ {
_loram = ReadLoRam(); _loram = ReadLoRam();
_hiram = ReadHiRam(); _hiram = ReadHiRam();
_game = ReadGame(); _game = ReadGame();
_a15 = (addr & 0x08000) != 0; _a15 = (addr & 0x08000) != 0;
_a14 = (addr & 0x04000) != 0; _a14 = (addr & 0x04000) != 0;
_a13 = (addr & 0x02000) != 0; _a13 = (addr & 0x02000) != 0;
_a12 = (addr & 0x01000) != 0; _a12 = (addr & 0x01000) != 0;
// upper memory regions 8000-FFFF // upper memory regions 8000-FFFF
_exrom = ReadExRom(); _exrom = ReadExRom();
if (_a15) if (_a15)
{ {
// io/character access // io/character access
if (_a14 && !_a13 && _a12) if (_a14 && !_a13 && _a12)
{ {
// character rom, banked in at D000-DFFF // character rom, banked in at D000-DFFF
_charen = ReadCharen(); _charen = ReadCharen();
if (read && !_charen && (((_hiram || _loram) && _game) || (_hiram && !_exrom && !_game))) if (read && !_charen && (((_hiram || _loram) && _game) || (_hiram && !_exrom && !_game)))
return PlaBank.CharRom; return PlaBank.CharRom;
// io block, banked in at D000-DFFF // io block, banked in at D000-DFFF
if ((_charen && (_hiram || _loram)) || (_exrom && !_game)) if ((_charen && (_hiram || _loram)) || (_exrom && !_game))
{ {
if (addr < 0xD400) if (addr < 0xD400)
return PlaBank.Vic; return PlaBank.Vic;
if (addr < 0xD800) if (addr < 0xD800)
return PlaBank.Sid; return PlaBank.Sid;
if (addr < 0xDC00) if (addr < 0xDC00)
return PlaBank.ColorRam; return PlaBank.ColorRam;
if (addr < 0xDD00) if (addr < 0xDD00)
return PlaBank.Cia0; return PlaBank.Cia0;
if (addr < 0xDE00) if (addr < 0xDE00)
return PlaBank.Cia1; return PlaBank.Cia1;
return addr < 0xDF00 return addr < 0xDF00
? PlaBank.Expansion0 ? PlaBank.Expansion0
: PlaBank.Expansion1; : PlaBank.Expansion1;
} }
} }
// cartridge high, banked either at A000-BFFF or E000-FFFF depending // cartridge high, banked either at A000-BFFF or E000-FFFF depending
if (_a13 && !_game && ((_hiram && !_a14 && read && !_exrom) || (_a14 && _exrom))) if (_a13 && !_game && ((_hiram && !_a14 && read && !_exrom) || (_a14 && _exrom)))
return PlaBank.CartridgeHi; return PlaBank.CartridgeHi;
// cartridge low, banked at 8000-9FFF // cartridge low, banked at 8000-9FFF
if (!_a14 && !_a13 && ((_loram && _hiram && read && !_exrom) || (_exrom && !_game))) if (!_a14 && !_a13 && ((_loram && _hiram && read && !_exrom) || (_exrom && !_game)))
return PlaBank.CartridgeLo; return PlaBank.CartridgeLo;
// kernal rom, banked at E000-FFFF // kernal rom, banked at E000-FFFF
if (_hiram && _a14 && _a13 && read && (_game || (!_exrom && !_game))) if (_hiram && _a14 && _a13 && read && (_game || (!_exrom && !_game)))
return PlaBank.KernalRom; return PlaBank.KernalRom;
// basic rom, banked at A000-BFFF // basic rom, banked at A000-BFFF
if (_loram && _hiram && !_a14 && _a13 && read && _game) if (_loram && _hiram && !_a14 && _a13 && read && _game)
return PlaBank.BasicRom; return PlaBank.BasicRom;
} }
// ultimax mode ram exclusion // ultimax mode ram exclusion
if (_exrom && !_game) if (_exrom && !_game)
{ {
_p24 = !_a15 && !_a14 && _a12; //00x1 1000-1FFF, 3000-3FFF _p24 = !_a15 && !_a14 && _a12; //00x1 1000-1FFF, 3000-3FFF
_p25 = !_a15 && !_a14 && _a13; //001x 2000-3FFF _p25 = !_a15 && !_a14 && _a13; //001x 2000-3FFF
_p26 = !_a15 && _a14; //01xx 4000-7FFF _p26 = !_a15 && _a14; //01xx 4000-7FFF
_p27 = _a15 && !_a14 && _a13; //101x A000-BFFF _p27 = _a15 && !_a14 && _a13; //101x A000-BFFF
_p28 = _a15 && _a14 && !_a13 && !_a12; //1100 C000-CFFF _p28 = _a15 && _a14 && !_a13 && !_a12; //1100 C000-CFFF
if (_p24 || _p25 || _p26 || _p27 || _p28) if (_p24 || _p25 || _p26 || _p27 || _p28)
return PlaBank.None; return PlaBank.None;
} }
return PlaBank.Ram; return PlaBank.Ram;
} }
public int Peek(int addr) public int Peek(int addr)
{ {
@ -280,47 +280,47 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
return 0xFF; return 0xFF;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
public int VicRead(int addr) public int VicRead(int addr)
{ {
_game = ReadGame(); _game = ReadGame();
_exrom = ReadExRom(); _exrom = ReadExRom();
_a14 = (addr & 0x04000) == 0; _a14 = (addr & 0x04000) == 0;
_a13 = (addr & 0x02000) != 0; _a13 = (addr & 0x02000) != 0;
_a12 = (addr & 0x01000) != 0; _a12 = (addr & 0x01000) != 0;
// read char rom at 1000-1FFF and 9000-9FFF // read char rom at 1000-1FFF and 9000-9FFF
if (_a14 && !_a13 && _a12 && (_game || !_exrom)) if (_a14 && !_a13 && _a12 && (_game || !_exrom))
return ReadCharRom(addr); return ReadCharRom(addr);
// read cartridge rom in ultimax mode // read cartridge rom in ultimax mode
if (_a13 && _a12 && _exrom && !_game) if (_a13 && _a12 && _exrom && !_game)
return ReadCartridgeHi(addr); return ReadCartridgeHi(addr);
return ReadMemory(addr); return ReadMemory(addr);
} }
public void Write(int addr, int val) public void Write(int addr, int val)
{ {
switch (Bank(addr, false)) switch (Bank(addr, false))
{ {
case PlaBank.CartridgeHi: case PlaBank.CartridgeHi:
WriteCartridgeHi(addr, val); WriteCartridgeHi(addr, val);
if (ReadGame() || !ReadExRom()) if (ReadGame() || !ReadExRom())
{ {
WriteMemory(addr, val); WriteMemory(addr, val);
} }
break; break;
case PlaBank.CartridgeLo: case PlaBank.CartridgeLo:
WriteCartridgeLo(addr, val); WriteCartridgeLo(addr, val);
if (ReadGame() || !ReadExRom()) if (ReadGame() || !ReadExRom())
{ {
WriteMemory(addr, val); WriteMemory(addr, val);
} }
break; break;
case PlaBank.Cia0: case PlaBank.Cia0:
WriteCia0(addr, val); WriteCia0(addr, val);
@ -336,9 +336,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
return; return;
case PlaBank.Expansion1: case PlaBank.Expansion1:
WriteExpansionHi(addr, val); WriteExpansionHi(addr, val);
return; return;
case PlaBank.Ram: case PlaBank.Ram:
WriteMemory(addr, val); WriteMemory(addr, val);
break; break;
case PlaBank.Sid: case PlaBank.Sid:
WriteSid(addr, val); WriteSid(addr, val);

View File

@ -6,147 +6,147 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Cia public sealed partial class Cia
{ {
private abstract class Port private abstract class Port
{ {
public abstract int ReadPra(int pra, int ddra, int prb, int ddrb); public abstract int ReadPra(int pra, int ddra, int prb, int ddrb);
public abstract int ReadPrb(int pra, int ddra, int prb, int ddrb); public abstract int ReadPrb(int pra, int ddra, int prb, int ddrb);
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
private sealed class DisconnectedPort : Port private sealed class DisconnectedPort : Port
{ {
public override int ReadPra(int pra, int ddra, int prb, int ddrb) public override int ReadPra(int pra, int ddra, int prb, int ddrb)
{ {
return (pra | ~ddra) & 0xFF; return (pra | ~ddra) & 0xFF;
} }
public override int ReadPrb(int pra, int ddra, int prb, int ddrb) public override int ReadPrb(int pra, int ddra, int prb, int ddrb)
{ {
return (prb | ~ddrb) & 0xFF; return (prb | ~ddrb) & 0xFF;
} }
} }
private sealed class JoystickKeyboardPort : Port private sealed class JoystickKeyboardPort : Port
{ {
[SaveState.DoNotSave] private int _ret; [SaveState.DoNotSave] private int _ret;
[SaveState.DoNotSave] private int _tst; [SaveState.DoNotSave] private int _tst;
[SaveState.DoNotSave] private readonly Func<bool[]> _readJoyData; [SaveState.DoNotSave] private readonly Func<bool[]> _readJoyData;
[SaveState.DoNotSave] private readonly Func<bool[]> _readKeyData; [SaveState.DoNotSave] private readonly Func<bool[]> _readKeyData;
public JoystickKeyboardPort(Func<bool[]> readJoyData, Func<bool[]> readKeyData) public JoystickKeyboardPort(Func<bool[]> readJoyData, Func<bool[]> readKeyData)
{ {
_readJoyData = readJoyData; _readJoyData = readJoyData;
_readKeyData = readKeyData; _readKeyData = readKeyData;
} }
private int GetJoystick1() private int GetJoystick1()
{ {
var joyData = _readJoyData(); var joyData = _readJoyData();
return 0xE0 | return 0xE0 |
(joyData[0] ? 0x00 : 0x01) | (joyData[0] ? 0x00 : 0x01) |
(joyData[1] ? 0x00 : 0x02) | (joyData[1] ? 0x00 : 0x02) |
(joyData[2] ? 0x00 : 0x04) | (joyData[2] ? 0x00 : 0x04) |
(joyData[3] ? 0x00 : 0x08) | (joyData[3] ? 0x00 : 0x08) |
(joyData[4] ? 0x00 : 0x10); (joyData[4] ? 0x00 : 0x10);
} }
private int GetJoystick2() private int GetJoystick2()
{ {
var joyData = _readJoyData(); var joyData = _readJoyData();
return 0xE0 | return 0xE0 |
(joyData[5] ? 0x00 : 0x01) | (joyData[5] ? 0x00 : 0x01) |
(joyData[6] ? 0x00 : 0x02) | (joyData[6] ? 0x00 : 0x02) |
(joyData[7] ? 0x00 : 0x04) | (joyData[7] ? 0x00 : 0x04) |
(joyData[8] ? 0x00 : 0x08) | (joyData[8] ? 0x00 : 0x08) |
(joyData[9] ? 0x00 : 0x10); (joyData[9] ? 0x00 : 0x10);
} }
private int GetKeyboardRows(int activeColumns) private int GetKeyboardRows(int activeColumns)
{ {
var keyData = _readKeyData(); var keyData = _readKeyData();
var result = 0xFF; var result = 0xFF;
for (var r = 0; r < 8; r++) for (var r = 0; r < 8; r++)
{ {
if ((activeColumns & 0x1) == 0) if ((activeColumns & 0x1) == 0)
{ {
var i = r << 3; var i = r << 3;
for (var c = 0; c < 8; c++) for (var c = 0; c < 8; c++)
{ {
if (keyData[i++]) if (keyData[i++])
{ {
result &= ~(1 << c); result &= ~(1 << c);
} }
} }
} }
activeColumns >>= 1; activeColumns >>= 1;
} }
return result; return result;
} }
private int GetKeyboardColumns(int activeRows) private int GetKeyboardColumns(int activeRows)
{ {
var keyData = _readKeyData(); var keyData = _readKeyData();
var result = 0xFF; var result = 0xFF;
for (var c = 0; c < 8; c++) for (var c = 0; c < 8; c++)
{ {
if ((activeRows & 0x1) == 0) if ((activeRows & 0x1) == 0)
{ {
var i = c; var i = c;
for (var r = 0; r < 8; r++) for (var r = 0; r < 8; r++)
{ {
if (keyData[i]) if (keyData[i])
{ {
result &= ~(1 << r); result &= ~(1 << r);
} }
i += 0x8; i += 0x8;
} }
} }
activeRows >>= 1; activeRows >>= 1;
} }
return result; return result;
} }
public override int ReadPra(int pra, int ddra, int prb, int ddrb) public override int ReadPra(int pra, int ddra, int prb, int ddrb)
{ {
_ret = (pra | ~ddra) & 0xFF; _ret = (pra | ~ddra) & 0xFF;
_tst = (prb | ~ddrb) & GetJoystick1(); _tst = (prb | ~ddrb) & GetJoystick1();
_ret &= GetKeyboardColumns(_tst); _ret &= GetKeyboardColumns(_tst);
return _ret & GetJoystick2(); return _ret & GetJoystick2();
} }
public override int ReadPrb(int pra, int ddra, int prb, int ddrb) public override int ReadPrb(int pra, int ddra, int prb, int ddrb)
{ {
_ret = ~ddrb & 0xFF; _ret = ~ddrb & 0xFF;
_tst = (pra | ~ddra) & GetJoystick2(); _tst = (pra | ~ddra) & GetJoystick2();
_ret &= GetKeyboardRows(_tst); _ret &= GetKeyboardRows(_tst);
return (_ret | (prb & ddrb)) & GetJoystick1(); return (_ret | (prb & ddrb)) & GetJoystick1();
} }
} }
private sealed class IecPort : Port private sealed class IecPort : Port
{ {
private readonly Func<int> _readIec; private readonly Func<int> _readIec;
public IecPort(Func<int> readIec) public IecPort(Func<int> readIec)
{ {
_readIec = readIec; _readIec = readIec;
} }
public override int ReadPra(int pra, int ddra, int prb, int ddrb) public override int ReadPra(int pra, int ddra, int prb, int ddrb)
{ {
return (pra & ddra) | (~ddra & _readIec()); return (pra & ddra) | (~ddra & _readIec());
} }
public override int ReadPrb(int pra, int ddra, int prb, int ddrb) public override int ReadPrb(int pra, int ddra, int prb, int ddrb)
{ {
return (prb | ~ddrb) & 0xFF; return (prb | ~ddrb) & 0xFF;
} }
} }
} }
} }

View File

@ -5,296 +5,296 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Cia public sealed partial class Cia
{ {
public int Peek(int addr) public int Peek(int addr)
{ {
return ReadRegister(addr & 0xF); return ReadRegister(addr & 0xF);
} }
public bool ReadIrq() public bool ReadIrq()
{ {
return (_icr & 0x80) == 0; return (_icr & 0x80) == 0;
} }
public int ReadPortA() public int ReadPortA()
{ {
return (_pra | ~_ddra) & 0xFF; return (_pra | ~_ddra) & 0xFF;
} }
public int Read(int addr) public int Read(int addr)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr) switch (addr)
{ {
case 0x8: case 0x8:
_todLatch = false; _todLatch = false;
return _latch10Ths; return _latch10Ths;
case 0x9: case 0x9:
return _latchSec; return _latchSec;
case 0xA: case 0xA:
return _latchMin; return _latchMin;
case 0xB: case 0xB:
_todLatch = true; _todLatch = true;
return _latchHr; return _latchHr;
case 0xD: case 0xD:
var icrTemp = _icr; var icrTemp = _icr;
_icr = 0; _icr = 0;
return icrTemp; return icrTemp;
} }
return ReadRegister(addr); return ReadRegister(addr);
} }
private int ReadRegister(int addr) private int ReadRegister(int addr)
{ {
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
return _port.ReadPra(_pra, _ddra, _prb, _ddrb); return _port.ReadPra(_pra, _ddra, _prb, _ddrb);
case 0x1: case 0x1:
return _port.ReadPrb(_pra, _ddra, _prb, _ddrb); return _port.ReadPrb(_pra, _ddra, _prb, _ddrb);
case 0x2: case 0x2:
return _ddra; return _ddra;
case 0x3: case 0x3:
return _ddrb; return _ddrb;
case 0x4: case 0x4:
return _ta & 0xFF; return _ta & 0xFF;
case 0x5: case 0x5:
return (_ta >> 8) & 0xFF; return (_ta >> 8) & 0xFF;
case 0x6: case 0x6:
return _tb & 0xFF; return _tb & 0xFF;
case 0x7: case 0x7:
return (_tb >> 8) & 0xFF; return (_tb >> 8) & 0xFF;
case 0x8: case 0x8:
return _tod10Ths; return _tod10Ths;
case 0x9: case 0x9:
return _todSec; return _todSec;
case 0xA: case 0xA:
return _todMin; return _todMin;
case 0xB: case 0xB:
return _todHr; return _todHr;
case 0xC: case 0xC:
return _sdr; return _sdr;
case 0xD: case 0xD:
return _icr; return _icr;
case 0xE: case 0xE:
return _cra; return _cra;
case 0xF: case 0xF:
return _crb; return _crb;
} }
return 0; return 0;
} }
public void Poke(int addr, int val) public void Poke(int addr, int val)
{ {
WriteRegister(addr, val); WriteRegister(addr, val);
} }
public void Write(int addr, int val) public void Write(int addr, int val)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr) switch (addr)
{ {
case 0x4: case 0x4:
_latcha = (_latcha & 0xFF00) | val; _latcha = (_latcha & 0xFF00) | val;
break; break;
case 0x5: case 0x5:
_latcha = (_latcha & 0xFF) | (val << 8); _latcha = (_latcha & 0xFF) | (val << 8);
if ((_cra & 0x01) == 0) if ((_cra & 0x01) == 0)
{ {
_ta = _latcha; _ta = _latcha;
} }
break; break;
case 0x6: case 0x6:
_latchb = (_latchb & 0xFF00) | val; _latchb = (_latchb & 0xFF00) | val;
break; break;
case 0x7: case 0x7:
_latchb = (_latchb & 0xFF) | (val << 8); _latchb = (_latchb & 0xFF) | (val << 8);
if ((_crb & 0x01) == 0) if ((_crb & 0x01) == 0)
{ {
_tb = _latchb; _tb = _latchb;
} }
break; break;
case 0x8: case 0x8:
if ((_crb & 0x80) != 0) if ((_crb & 0x80) != 0)
{ {
_alm10Ths = val & 0xF; _alm10Ths = val & 0xF;
} }
else else
{ {
_tod10Ths = val & 0xF; _tod10Ths = val & 0xF;
} }
break; break;
case 0x9: case 0x9:
if ((_crb & 0x80) != 0) if ((_crb & 0x80) != 0)
{ {
_almSec = val & 0x7F; _almSec = val & 0x7F;
} }
else else
{ {
_todSec = val & 0x7F; _todSec = val & 0x7F;
} }
break; break;
case 0xA: case 0xA:
if ((_crb & 0x80) != 0) if ((_crb & 0x80) != 0)
{ {
_almMin = val & 0x7F; _almMin = val & 0x7F;
} }
else else
{ {
_todMin = val & 0x7F; _todMin = val & 0x7F;
} }
break; break;
case 0xB: case 0xB:
if ((_crb & 0x80) != 0) if ((_crb & 0x80) != 0)
{ {
_almHr = val & 0x9F; _almHr = val & 0x9F;
} }
else else
{ {
_todHr = val & 0x9F; _todHr = val & 0x9F;
} }
break; break;
case 0xC: case 0xC:
WriteRegister(addr, val); WriteRegister(addr, val);
TriggerInterrupt(8); TriggerInterrupt(8);
break; break;
case 0xD: case 0xD:
if ((val & 0x80) != 0) if ((val & 0x80) != 0)
{ {
_intMask |= (val & 0x7F); _intMask |= (val & 0x7F);
} }
else else
{ {
_intMask &= ~val; _intMask &= ~val;
} }
if ((_icr & _intMask & 0x1F) != 0) if ((_icr & _intMask & 0x1F) != 0)
{ {
_icr |= 0x80; _icr |= 0x80;
} }
break; break;
case 0xE: case 0xE:
var oldCra = _cra; var oldCra = _cra;
WriteRegister(addr, val); WriteRegister(addr, val);
// Toggle output begins high when timer starts.
if ((_cra & 0x05) == 0x05 && (oldCra & 0x01) == 0)
_prb |= 0x40;
break;
case 0xF:
var oldCrb = _crb;
WriteRegister(addr, val);
// Toggle output begins high when timer starts. // Toggle output begins high when timer starts.
if ((_crb & 0x05) == 0x05 && (oldCrb & 0x01) == 0) if ((_cra & 0x05) == 0x05 && (oldCra & 0x01) == 0)
_prb |= 0x80; _prb |= 0x40;
break; break;
default: case 0xF:
WriteRegister(addr, val); var oldCrb = _crb;
break; WriteRegister(addr, val);
}
}
private void WriteRegister(int addr, int val) // Toggle output begins high when timer starts.
{ if ((_crb & 0x05) == 0x05 && (oldCrb & 0x01) == 0)
switch (addr) _prb |= 0x80;
{ break;
case 0x0: default:
_pra = val; WriteRegister(addr, val);
break; break;
case 0x1: }
_prb = val; }
break;
case 0x2:
_ddra = val;
break;
case 0x3:
_ddrb = val;
break;
case 0x4:
_latcha = (_latcha & 0xFF00) | val;
_ta = _latcha;
break;
case 0x5:
_latcha = (_latcha & 0xFF) | (val << 8);
_ta = _latcha;
break;
case 0x6:
_latchb = (_latchb & 0xFF00) | val;
_tb = _latchb;
break;
case 0x7:
_latchb = (_latchb & 0xFF) | (val << 8);
_tb = _latchb;
break;
case 0x8:
_tod10Ths = val & 0xF;
break;
case 0x9:
_todSec = val & 0x7F;
break;
case 0xA:
_todMin = val & 0x7F;
break;
case 0xB:
_todHr = val & 0x9F;
break;
case 0xC:
_sdr = val;
break;
case 0xD:
_intMask = val;
break;
case 0xE:
_hasNewCra = true;
_newCra = val;
_taCntPhi2 = ((val & 0x20) == 0);
_taCntCnt = ((val & 0x20) == 0x20);
break;
case 0xF:
_hasNewCrb = true;
_newCrb = val;
_tbCntPhi2 = ((val & 0x60) == 0);
_tbCntTa = ((val & 0x40) == 0x40);
_tbCntCnt = ((val & 0x20) == 0x20);
break;
}
}
[SaveState.DoNotSave] private void WriteRegister(int addr, int val)
public int DdrA {
{ switch (addr)
get { return _ddra; } {
} case 0x0:
_pra = val;
break;
case 0x1:
_prb = val;
break;
case 0x2:
_ddra = val;
break;
case 0x3:
_ddrb = val;
break;
case 0x4:
_latcha = (_latcha & 0xFF00) | val;
_ta = _latcha;
break;
case 0x5:
_latcha = (_latcha & 0xFF) | (val << 8);
_ta = _latcha;
break;
case 0x6:
_latchb = (_latchb & 0xFF00) | val;
_tb = _latchb;
break;
case 0x7:
_latchb = (_latchb & 0xFF) | (val << 8);
_tb = _latchb;
break;
case 0x8:
_tod10Ths = val & 0xF;
break;
case 0x9:
_todSec = val & 0x7F;
break;
case 0xA:
_todMin = val & 0x7F;
break;
case 0xB:
_todHr = val & 0x9F;
break;
case 0xC:
_sdr = val;
break;
case 0xD:
_intMask = val;
break;
case 0xE:
_hasNewCra = true;
_newCra = val;
_taCntPhi2 = ((val & 0x20) == 0);
_taCntCnt = ((val & 0x20) == 0x20);
break;
case 0xF:
_hasNewCrb = true;
_newCrb = val;
_tbCntPhi2 = ((val & 0x60) == 0);
_tbCntTa = ((val & 0x40) == 0x40);
_tbCntCnt = ((val & 0x20) == 0x20);
break;
}
}
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int DdrB public int DdrA
{ {
get { return _ddrb; } get { return _ddra; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int PrA public int DdrB
{ {
get { return _pra; } get { return _ddrb; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int PrB public int PrA
{ {
get { return _prb; } get { return _pra; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int EffectivePrA public int PrB
{ {
get { return _pra | ~_ddra; } get { return _prb; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int EffectivePrB public int EffectivePrA
{ {
get { return _prb | ~_ddrb; } get { return _pra | ~_ddra; }
} }
}
[SaveState.DoNotSave]
public int EffectivePrB
{
get { return _prb | ~_ddrb; }
}
}
} }

View File

@ -1,69 +1,69 @@
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Cia public sealed partial class Cia
{ {
private void CountTod() private void CountTod()
{ {
if (_todCounter > 0) if (_todCounter > 0)
{ {
_todCounter -= _todDen; _todCounter -= _todDen;
return; return;
} }
_todCounter += _todNum * ((_cra & 0x80) != 0 ? 6 : 5); _todCounter += _todNum * ((_cra & 0x80) != 0 ? 6 : 5);
_tod10Ths++; _tod10Ths++;
if (_tod10Ths > 9) if (_tod10Ths > 9)
{ {
_tod10Ths = 0; _tod10Ths = 0;
_todlo = (_todSec & 0x0F) + 1; _todlo = (_todSec & 0x0F) + 1;
_todhi = (_todSec >> 4); _todhi = (_todSec >> 4);
if (_todlo > 9) if (_todlo > 9)
{ {
_todlo = 0; _todlo = 0;
_todhi++; _todhi++;
} }
if (_todhi > 5) if (_todhi > 5)
{ {
_todSec = 0; _todSec = 0;
_todlo = (_todMin & 0x0F) + 1; _todlo = (_todMin & 0x0F) + 1;
_todhi = (_todMin >> 4); _todhi = (_todMin >> 4);
if (_todlo > 9) if (_todlo > 9)
{ {
_todlo = 0; _todlo = 0;
_todhi++; _todhi++;
} }
if (_todhi > 5) if (_todhi > 5)
{ {
_todMin = 0; _todMin = 0;
_todlo = (_todHr & 0x0F) + 1; _todlo = (_todHr & 0x0F) + 1;
_todhi = (_todHr >> 4); _todhi = (_todHr >> 4);
_todHr &= 0x80; _todHr &= 0x80;
if (_todlo > 9) if (_todlo > 9)
{ {
_todlo = 0; _todlo = 0;
_todhi++; _todhi++;
} }
_todHr |= (_todhi << 4) | _todlo; _todHr |= (_todhi << 4) | _todlo;
if ((_todHr & 0x1F) > 0x11) if ((_todHr & 0x1F) > 0x11)
{ {
_todHr &= 0x80 ^ 0x80; _todHr &= 0x80 ^ 0x80;
} }
} }
else else
{ {
_todMin = (_todhi << 4) | _todlo; _todMin = (_todhi << 4) | _todlo;
} }
} }
else else
{ {
_todSec = (_todhi << 4) | _todlo; _todSec = (_todhi << 4) | _todlo;
} }
} }
if (_tod10Ths == _alm10Ths && _todSec == _almSec && _todMin == _almMin && _todHr == _almHr) if (_tod10Ths == _alm10Ths && _todSec == _almSec && _todMin == _almMin && _todHr == _almHr)
{ {
TriggerInterrupt(4); TriggerInterrupt(4);
} }
} }
} }
} }

View File

@ -3,9 +3,9 @@ using System;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Cia public sealed partial class Cia
{ {
/* /*
Commodore CIA 6526 core. Commodore CIA 6526 core.
Many thanks to: Many thanks to:
@ -15,494 +15,494 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
http://frodo.cebix.net/ http://frodo.cebix.net/
*/ */
private enum TimerState private enum TimerState
{ {
Stop = 0, Stop = 0,
WaitThenCount = 1, WaitThenCount = 1,
LoadThenStop = 2, LoadThenStop = 2,
LoadThenCount = 3, LoadThenCount = 3,
LoadThenWaitThenCount = 4, LoadThenWaitThenCount = 4,
Count = 5, Count = 5,
CountThenStop = 6 CountThenStop = 6
} }
public Func<bool> ReadFlag = () => true; public Func<bool> ReadFlag = () => true;
public bool DelayedInterrupts = true; public bool DelayedInterrupts = true;
private int _pra; private int _pra;
private int _prb; private int _prb;
private int _ddra; private int _ddra;
private int _ddrb; private int _ddrb;
private int _ta; private int _ta;
private int _tb; private int _tb;
private int _latcha; private int _latcha;
private int _latchb; private int _latchb;
private int _tod10Ths; private int _tod10Ths;
private int _todSec; private int _todSec;
private int _todMin; private int _todMin;
private int _todHr; private int _todHr;
private int _latch10Ths; private int _latch10Ths;
private int _latchSec; private int _latchSec;
private int _latchMin; private int _latchMin;
private int _latchHr; private int _latchHr;
private int _alm10Ths; private int _alm10Ths;
private int _almSec; private int _almSec;
private int _almMin; private int _almMin;
private int _almHr; private int _almHr;
private int _sdr; private int _sdr;
private int _icr; private int _icr;
private int _cra; private int _cra;
private int _crb; private int _crb;
private int _intMask; private int _intMask;
private bool _todLatch; private bool _todLatch;
private bool _taCntPhi2; private bool _taCntPhi2;
private bool _taCntCnt; private bool _taCntCnt;
private bool _tbCntPhi2; private bool _tbCntPhi2;
private bool _tbCntTa; private bool _tbCntTa;
private bool _tbCntCnt; private bool _tbCntCnt;
private bool _taIrqNextCycle; private bool _taIrqNextCycle;
private bool _taPrb6NegativeNextCycle; private bool _taPrb6NegativeNextCycle;
private bool _tbIrqNextCycle; private bool _tbIrqNextCycle;
private bool _tbPrb7NegativeNextCycle; private bool _tbPrb7NegativeNextCycle;
private bool _hasNewCra; private bool _hasNewCra;
private bool _hasNewCrb; private bool _hasNewCrb;
private TimerState _taState; private TimerState _taState;
private TimerState _tbState; private TimerState _tbState;
private int _newCra; private int _newCra;
private int _newCrb; private int _newCrb;
private bool _flagLatch; private bool _flagLatch;
[SaveState.DoNotSave] private bool _flagInput; [SaveState.DoNotSave] private bool _flagInput;
[SaveState.DoNotSave] private bool _taUnderflow; [SaveState.DoNotSave] private bool _taUnderflow;
private readonly Port _port; private readonly Port _port;
[SaveState.DoNotSave] private int _todlo; [SaveState.DoNotSave] private int _todlo;
[SaveState.DoNotSave] private int _todhi; [SaveState.DoNotSave] private int _todhi;
[SaveState.DoNotSave] private readonly int _todNum; [SaveState.DoNotSave] private readonly int _todNum;
[SaveState.DoNotSave] private readonly int _todDen; [SaveState.DoNotSave] private readonly int _todDen;
private int _todCounter; private int _todCounter;
private Cia(int todNum, int todDen) private Cia(int todNum, int todDen)
{ {
_todNum = todNum; _todNum = todNum;
_todDen = todDen; _todDen = todDen;
} }
public Cia(int todNum, int todDen, Func<bool[]> keyboard, Func<bool[]> joysticks) : this(todNum, todDen) public Cia(int todNum, int todDen, Func<bool[]> keyboard, Func<bool[]> joysticks) : this(todNum, todDen)
{ {
_port = new JoystickKeyboardPort(joysticks, keyboard); _port = new JoystickKeyboardPort(joysticks, keyboard);
} }
public Cia(int todNum, int todDen, Func<int> readIec) : this(todNum, todDen) public Cia(int todNum, int todDen, Func<int> readIec) : this(todNum, todDen)
{ {
_port = new IecPort(readIec); _port = new IecPort(readIec);
} }
public void HardReset() public void HardReset()
{ {
_pra = 0; _pra = 0;
_prb = 0; _prb = 0;
_ddra = 0; _ddra = 0;
_ddrb = 0; _ddrb = 0;
_ta = 0xFFFF; _ta = 0xFFFF;
_tb = 0xFFFF; _tb = 0xFFFF;
_latcha = 1; _latcha = 1;
_latchb = 1; _latchb = 1;
_tod10Ths = 0; _tod10Ths = 0;
_todSec = 0; _todSec = 0;
_todMin = 0; _todMin = 0;
_todHr = 0; _todHr = 0;
_alm10Ths = 0; _alm10Ths = 0;
_almSec = 0; _almSec = 0;
_almMin = 0; _almMin = 0;
_almHr = 0; _almHr = 0;
_sdr = 0; _sdr = 0;
_icr = 0; _icr = 0;
_cra = 0; _cra = 0;
_crb = 0; _crb = 0;
_intMask = 0; _intMask = 0;
_todLatch = false; _todLatch = false;
_taCntPhi2 = false; _taCntPhi2 = false;
_taCntCnt = false; _taCntCnt = false;
_tbCntPhi2 = false; _tbCntPhi2 = false;
_tbCntTa = false; _tbCntTa = false;
_tbCntCnt = false; _tbCntCnt = false;
_taIrqNextCycle = false; _taIrqNextCycle = false;
_tbIrqNextCycle = false; _tbIrqNextCycle = false;
_taState = TimerState.Stop; _taState = TimerState.Stop;
_tbState = TimerState.Stop; _tbState = TimerState.Stop;
} }
private void CheckIrqs() private void CheckIrqs()
{ {
if (_taIrqNextCycle) if (_taIrqNextCycle)
{ {
_taIrqNextCycle = false; _taIrqNextCycle = false;
TriggerInterrupt(1); TriggerInterrupt(1);
} }
if (_tbIrqNextCycle) if (_tbIrqNextCycle)
{ {
_tbIrqNextCycle = false; _tbIrqNextCycle = false;
TriggerInterrupt(2); TriggerInterrupt(2);
} }
} }
public void ExecutePhase() public void ExecutePhase()
{ {
_taUnderflow = false; _taUnderflow = false;
if (DelayedInterrupts) if (DelayedInterrupts)
{ {
CheckIrqs(); CheckIrqs();
} }
if (_taPrb6NegativeNextCycle) if (_taPrb6NegativeNextCycle)
{ {
_prb &= 0xBF; _prb &= 0xBF;
_taPrb6NegativeNextCycle = false; _taPrb6NegativeNextCycle = false;
} }
if (_tbPrb7NegativeNextCycle) if (_tbPrb7NegativeNextCycle)
{ {
_prb &= 0x7F; _prb &= 0x7F;
_tbPrb7NegativeNextCycle = false; _tbPrb7NegativeNextCycle = false;
} }
switch (_taState) switch (_taState)
{ {
case TimerState.WaitThenCount: case TimerState.WaitThenCount:
_taState = TimerState.Count; _taState = TimerState.Count;
Ta_Idle(); Ta_Idle();
break; break;
case TimerState.Stop: case TimerState.Stop:
Ta_Idle(); Ta_Idle();
break; break;
case TimerState.LoadThenStop: case TimerState.LoadThenStop:
_taState = TimerState.Stop; _taState = TimerState.Stop;
_ta = _latcha; _ta = _latcha;
Ta_Idle(); Ta_Idle();
break; break;
case TimerState.LoadThenCount: case TimerState.LoadThenCount:
_taState = TimerState.Count; _taState = TimerState.Count;
_ta = _latcha; _ta = _latcha;
Ta_Idle(); Ta_Idle();
break; break;
case TimerState.LoadThenWaitThenCount: case TimerState.LoadThenWaitThenCount:
_taState = TimerState.WaitThenCount; _taState = TimerState.WaitThenCount;
if (_ta == 1) if (_ta == 1)
{ {
Ta_Interrupt(); Ta_Interrupt();
_taUnderflow = true; _taUnderflow = true;
} }
else else
{ {
_ta = _latcha; _ta = _latcha;
} }
Ta_Idle(); Ta_Idle();
break; break;
case TimerState.Count: case TimerState.Count:
Ta_Count(); Ta_Count();
break; break;
case TimerState.CountThenStop: case TimerState.CountThenStop:
_taState = TimerState.Stop; _taState = TimerState.Stop;
Ta_Count(); Ta_Count();
break; break;
} }
switch (_tbState) switch (_tbState)
{ {
case TimerState.WaitThenCount: case TimerState.WaitThenCount:
_tbState = TimerState.Count; _tbState = TimerState.Count;
Tb_Idle(); Tb_Idle();
break; break;
case TimerState.Stop: case TimerState.Stop:
Tb_Idle(); Tb_Idle();
break; break;
case TimerState.LoadThenStop: case TimerState.LoadThenStop:
_tbState = TimerState.Stop; _tbState = TimerState.Stop;
_tb = _latchb; _tb = _latchb;
Tb_Idle(); Tb_Idle();
break; break;
case TimerState.LoadThenCount: case TimerState.LoadThenCount:
_tbState = TimerState.Count; _tbState = TimerState.Count;
_tb = _latchb; _tb = _latchb;
Tb_Idle(); Tb_Idle();
break; break;
case TimerState.LoadThenWaitThenCount: case TimerState.LoadThenWaitThenCount:
_tbState = TimerState.WaitThenCount; _tbState = TimerState.WaitThenCount;
if (_tb == 1) if (_tb == 1)
{ {
Tb_Interrupt(); Tb_Interrupt();
} }
else else
{ {
_tb = _latchb; _tb = _latchb;
} }
Tb_Idle(); Tb_Idle();
break; break;
case TimerState.Count: case TimerState.Count:
Tb_Count(); Tb_Count();
break; break;
case TimerState.CountThenStop: case TimerState.CountThenStop:
_tbState = TimerState.Stop; _tbState = TimerState.Stop;
Tb_Count(); Tb_Count();
break; break;
} }
CountTod(); CountTod();
if (!_todLatch) if (!_todLatch)
{ {
_latch10Ths = _tod10Ths; _latch10Ths = _tod10Ths;
_latchSec = _todSec; _latchSec = _todSec;
_latchMin = _todMin; _latchMin = _todMin;
_latchHr = _todHr; _latchHr = _todHr;
} }
_flagInput = ReadFlag(); _flagInput = ReadFlag();
if (!_flagInput && _flagLatch) if (!_flagInput && _flagLatch)
{ {
TriggerInterrupt(16); TriggerInterrupt(16);
} }
_flagLatch = _flagInput; _flagLatch = _flagInput;
if (!DelayedInterrupts) if (!DelayedInterrupts)
{ {
CheckIrqs(); CheckIrqs();
} }
if ((_cra & 0x02) != 0) if ((_cra & 0x02) != 0)
_ddra |= 0x40; _ddra |= 0x40;
if ((_crb & 0x02) != 0) if ((_crb & 0x02) != 0)
_ddrb |= 0x80; _ddrb |= 0x80;
} }
private void Ta_Count() private void Ta_Count()
{ {
if (_taCntPhi2) if (_taCntPhi2)
{ {
if (_ta <= 0 || --_ta == 0) if (_ta <= 0 || --_ta == 0)
{ {
if (_taState != TimerState.Stop) if (_taState != TimerState.Stop)
{ {
Ta_Interrupt(); Ta_Interrupt();
} }
_taUnderflow = true; _taUnderflow = true;
} }
} }
Ta_Idle(); Ta_Idle();
} }
private void Ta_Interrupt() private void Ta_Interrupt()
{ {
_ta = _latcha; _ta = _latcha;
_taIrqNextCycle = true; _taIrqNextCycle = true;
_icr |= 1; _icr |= 1;
if ((_cra & 0x08) != 0) if ((_cra & 0x08) != 0)
{ {
_cra &= 0xFE; _cra &= 0xFE;
_newCra &= 0xFE; _newCra &= 0xFE;
_taState = TimerState.LoadThenStop; _taState = TimerState.LoadThenStop;
} }
else else
{ {
_taState = TimerState.LoadThenCount; _taState = TimerState.LoadThenCount;
} }
if ((_cra & 0x02) != 0) if ((_cra & 0x02) != 0)
{ {
if ((_cra & 0x04) != 0) if ((_cra & 0x04) != 0)
{ {
_taPrb6NegativeNextCycle = true; _taPrb6NegativeNextCycle = true;
_prb |= 0x40; _prb |= 0x40;
} }
else else
{ {
_prb ^= 0x40; _prb ^= 0x40;
} }
_ddrb |= 0x40; _ddrb |= 0x40;
} }
} }
private void Ta_Idle() private void Ta_Idle()
{ {
if (_hasNewCra) if (_hasNewCra)
{ {
switch (_taState) switch (_taState)
{ {
case TimerState.Stop: case TimerState.Stop:
case TimerState.LoadThenStop: case TimerState.LoadThenStop:
if ((_newCra & 0x01) != 0) if ((_newCra & 0x01) != 0)
{ {
_taState = (_newCra & 0x10) != 0 _taState = (_newCra & 0x10) != 0
? TimerState.LoadThenWaitThenCount ? TimerState.LoadThenWaitThenCount
: TimerState.WaitThenCount; : TimerState.WaitThenCount;
} }
else else
{ {
if ((_newCra & 0x10) != 0) if ((_newCra & 0x10) != 0)
{ {
_taState = TimerState.LoadThenStop; _taState = TimerState.LoadThenStop;
} }
} }
break; break;
case TimerState.Count: case TimerState.Count:
if ((_newCra & 0x01) != 0) if ((_newCra & 0x01) != 0)
{ {
if ((_newCra & 0x10) != 0) if ((_newCra & 0x10) != 0)
{ {
_taState = TimerState.LoadThenWaitThenCount; _taState = TimerState.LoadThenWaitThenCount;
} }
} }
else else
{ {
_taState = (_newCra & 0x10) != 0 _taState = (_newCra & 0x10) != 0
? TimerState.LoadThenStop ? TimerState.LoadThenStop
: TimerState.CountThenStop; : TimerState.CountThenStop;
} }
break; break;
case TimerState.LoadThenCount: case TimerState.LoadThenCount:
case TimerState.WaitThenCount: case TimerState.WaitThenCount:
if ((_newCra & 0x01) != 0) if ((_newCra & 0x01) != 0)
{ {
if ((_newCra & 0x08) != 0) if ((_newCra & 0x08) != 0)
{ {
_newCra &= 0xFE; _newCra &= 0xFE;
_taState = TimerState.Stop; _taState = TimerState.Stop;
} }
else if ((_newCra & 0x10) != 0) else if ((_newCra & 0x10) != 0)
{ {
_taState = TimerState.LoadThenWaitThenCount; _taState = TimerState.LoadThenWaitThenCount;
} }
} }
else else
{ {
_taState = TimerState.Stop; _taState = TimerState.Stop;
} }
break; break;
} }
_cra = _newCra & 0xEF; _cra = _newCra & 0xEF;
_hasNewCra = false; _hasNewCra = false;
} }
} }
private void Tb_Count() private void Tb_Count()
{ {
if (_tbCntPhi2 || (_tbCntTa && _taUnderflow)) if (_tbCntPhi2 || (_tbCntTa && _taUnderflow))
{ {
if (_tb <= 0 || --_tb == 0) if (_tb <= 0 || --_tb == 0)
{ {
if (_tbState != TimerState.Stop) if (_tbState != TimerState.Stop)
{ {
Tb_Interrupt(); Tb_Interrupt();
} }
} }
} }
Tb_Idle(); Tb_Idle();
} }
private void Tb_Interrupt() private void Tb_Interrupt()
{ {
_tb = _latchb; _tb = _latchb;
_tbIrqNextCycle = true; _tbIrqNextCycle = true;
_icr |= 2; _icr |= 2;
if ((_crb & 0x08) != 0) if ((_crb & 0x08) != 0)
{ {
_crb &= 0xFE; _crb &= 0xFE;
_newCrb &= 0xFE; _newCrb &= 0xFE;
_tbState = TimerState.LoadThenStop; _tbState = TimerState.LoadThenStop;
} }
else else
{ {
_tbState = TimerState.LoadThenCount; _tbState = TimerState.LoadThenCount;
} }
if ((_crb & 0x02) != 0) if ((_crb & 0x02) != 0)
{ {
if ((_crb & 0x04) != 0) if ((_crb & 0x04) != 0)
{ {
_tbPrb7NegativeNextCycle = true; _tbPrb7NegativeNextCycle = true;
_prb |= 0x80; _prb |= 0x80;
} }
else else
{ {
_prb ^= 0x80; _prb ^= 0x80;
} }
} }
} }
private void Tb_Idle() private void Tb_Idle()
{ {
if (_hasNewCrb) if (_hasNewCrb)
{ {
switch (_tbState) switch (_tbState)
{ {
case TimerState.Stop: case TimerState.Stop:
case TimerState.LoadThenStop: case TimerState.LoadThenStop:
if ((_newCrb & 0x01) != 0) if ((_newCrb & 0x01) != 0)
{ {
_tbState = (_newCrb & 0x10) != 0 _tbState = (_newCrb & 0x10) != 0
? TimerState.LoadThenWaitThenCount ? TimerState.LoadThenWaitThenCount
: TimerState.WaitThenCount; : TimerState.WaitThenCount;
} }
else else
{ {
if ((_newCrb & 0x10) != 0) if ((_newCrb & 0x10) != 0)
{ {
_tbState = TimerState.LoadThenStop; _tbState = TimerState.LoadThenStop;
} }
} }
break; break;
case TimerState.Count: case TimerState.Count:
if ((_newCrb & 0x01) != 0) if ((_newCrb & 0x01) != 0)
{ {
if ((_newCrb & 0x10) != 0) if ((_newCrb & 0x10) != 0)
{ {
_tbState = TimerState.LoadThenWaitThenCount; _tbState = TimerState.LoadThenWaitThenCount;
} }
} }
else else
{ {
_tbState = (_newCrb & 0x10) != 0 _tbState = (_newCrb & 0x10) != 0
? TimerState.LoadThenStop ? TimerState.LoadThenStop
: TimerState.CountThenStop; : TimerState.CountThenStop;
} }
break; break;
case TimerState.LoadThenCount: case TimerState.LoadThenCount:
case TimerState.WaitThenCount: case TimerState.WaitThenCount:
if ((_newCrb & 0x01) != 0) if ((_newCrb & 0x01) != 0)
{ {
if ((_newCrb & 0x08) != 0) if ((_newCrb & 0x08) != 0)
{ {
_newCrb &= 0xFE; _newCrb &= 0xFE;
_tbState = TimerState.Stop; _tbState = TimerState.Stop;
} }
else if ((_newCrb & 0x10) != 0) else if ((_newCrb & 0x10) != 0)
{ {
_tbState = TimerState.LoadThenWaitThenCount; _tbState = TimerState.LoadThenWaitThenCount;
} }
} }
else else
{ {
_tbState = TimerState.Stop; _tbState = TimerState.Stop;
} }
break; break;
} }
_crb = _newCrb & 0xEF; _crb = _newCrb & 0xEF;
_hasNewCrb = false; _hasNewCrb = false;
} }
} }
private void TriggerInterrupt(int bit) private void TriggerInterrupt(int bit)
{ {
_icr |= bit; _icr |= bit;
if ((_intMask & bit) == 0) return; if ((_intMask & bit) == 0) return;
_icr |= 0x80; _icr |= 0x80;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }

View File

@ -9,42 +9,42 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Sid public sealed partial class Sid
{ {
private sealed class Envelope private sealed class Envelope
{ {
[SaveState.DoNotSave] private const int StateAttack = 0; [SaveState.DoNotSave] private const int StateAttack = 0;
[SaveState.DoNotSave] private const int StateDecay = 1; [SaveState.DoNotSave] private const int StateDecay = 1;
[SaveState.DoNotSave] private const int StateRelease = 2; [SaveState.DoNotSave] private const int StateRelease = 2;
private int _attack; private int _attack;
private int _decay; private int _decay;
private bool _delay; private bool _delay;
private int _envCounter; private int _envCounter;
private int _expCounter; private int _expCounter;
private int _expPeriod; private int _expPeriod;
private bool _freeze; private bool _freeze;
private int _lfsr; private int _lfsr;
private bool _gate; private bool _gate;
private int _rate; private int _rate;
private int _release; private int _release;
private int _state; private int _state;
private int _sustain; private int _sustain;
private static readonly int[] AdsrTable = { private static readonly int[] AdsrTable = {
0x7F00, 0x0006, 0x003C, 0x0330, 0x7F00, 0x0006, 0x003C, 0x0330,
0x20C0, 0x6755, 0x3800, 0x500E, 0x20C0, 0x6755, 0x3800, 0x500E,
0x1212, 0x0222, 0x1848, 0x59B8, 0x1212, 0x0222, 0x1848, 0x59B8,
0x3840, 0x77E2, 0x7625, 0x0A93 0x3840, 0x77E2, 0x7625, 0x0A93
}; };
private static readonly int[] ExpCounterTable = { private static readonly int[] ExpCounterTable = {
0xFF, 0x5D, 0x36, 0x1A, 0x0E, 0x06, 0x00 0xFF, 0x5D, 0x36, 0x1A, 0x0E, 0x06, 0x00
}; };
private static readonly int[] ExpPeriodTable = { private static readonly int[] ExpPeriodTable = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x1E, 0x01 0x01, 0x02, 0x04, 0x08, 0x10, 0x1E, 0x01
}; };
private static readonly int[] SustainTable = { private static readonly int[] SustainTable = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
}; };
@ -73,43 +73,43 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
if (_state != StateAttack && ++_expCounter != _expPeriod) if (_state != StateAttack && ++_expCounter != _expPeriod)
{ {
return; return;
} }
_expCounter = 0; _expCounter = 0;
if (_freeze) if (_freeze)
return; return;
switch (_state) switch (_state)
{ {
case StateAttack: case StateAttack:
_envCounter++; _envCounter++;
if (_envCounter == 0xFF) if (_envCounter == 0xFF)
{ {
_state = StateDecay; _state = StateDecay;
_rate = AdsrTable[_decay]; _rate = AdsrTable[_decay];
} }
break; break;
case StateDecay: case StateDecay:
if (_envCounter == SustainTable[_sustain]) if (_envCounter == SustainTable[_sustain])
{ {
return; return;
} }
if (_expPeriod != 1) if (_expPeriod != 1)
{ {
_delay = false; _delay = false;
return; return;
} }
_envCounter--; _envCounter--;
break; break;
case StateRelease: case StateRelease:
if (_expPeriod != 1) if (_expPeriod != 1)
{ {
_delay = false; _delay = false;
return; return;
} }
_envCounter--; _envCounter--;
break; break;
} }
_envCounter &= 0xFF; _envCounter &= 0xFF;
UpdateExpCounter(); UpdateExpCounter();

View File

@ -20,7 +20,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public int Read(int addr) public int Read(int addr)
{ {
addr &= 0x1F; addr &= 0x1F;
var result = 0x00; var result = 0x00;
switch (addr) switch (addr)
{ {
case 0x19: case 0x19:
@ -36,7 +36,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private int ReadRegister(int addr) private int ReadRegister(int addr)
{ {
var result = 0x00; var result = 0x00;
switch (addr) switch (addr)
{ {
@ -46,18 +46,18 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
case 0x03: result = _voice0.PulseWidthHi; break; case 0x03: result = _voice0.PulseWidthHi; break;
case 0x04: case 0x04:
result = (_envelope0.Gate ? 0x01 : 0x00) | result = (_envelope0.Gate ? 0x01 : 0x00) |
(_voice0.Sync ? 0x02 : 0x00) | (_voice0.Sync ? 0x02 : 0x00) |
(_voice0.RingMod ? 0x04 : 0x00) | (_voice0.RingMod ? 0x04 : 0x00) |
(_voice0.Test ? 0x08 : 0x00) | (_voice0.Test ? 0x08 : 0x00) |
(_voice0.Waveform << 4); (_voice0.Waveform << 4);
break; break;
case 0x05: case 0x05:
result = (_envelope0.Attack << 4) | result = (_envelope0.Attack << 4) |
_envelope0.Decay; _envelope0.Decay;
break; break;
case 0x06: case 0x06:
result = (_envelope0.Sustain << 4) | result = (_envelope0.Sustain << 4) |
_envelope0.Release; _envelope0.Release;
break; break;
case 0x07: result = _voice1.FrequencyLo; break; case 0x07: result = _voice1.FrequencyLo; break;
case 0x08: result = _voice1.FrequencyHi; break; case 0x08: result = _voice1.FrequencyHi; break;
@ -65,18 +65,18 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
case 0x0A: result = _voice1.PulseWidthHi; break; case 0x0A: result = _voice1.PulseWidthHi; break;
case 0x0B: case 0x0B:
result = (_envelope1.Gate ? 0x01 : 0x00) | result = (_envelope1.Gate ? 0x01 : 0x00) |
(_voice1.Sync ? 0x02 : 0x00) | (_voice1.Sync ? 0x02 : 0x00) |
(_voice1.RingMod ? 0x04 : 0x00) | (_voice1.RingMod ? 0x04 : 0x00) |
(_voice1.Test ? 0x08 : 0x00) | (_voice1.Test ? 0x08 : 0x00) |
(_voice1.Waveform << 4); (_voice1.Waveform << 4);
break; break;
case 0x0C: case 0x0C:
result = (_envelope1.Attack << 4) | result = (_envelope1.Attack << 4) |
_envelope1.Decay; _envelope1.Decay;
break; break;
case 0x0D: case 0x0D:
result = (_envelope1.Sustain << 4) | result = (_envelope1.Sustain << 4) |
_envelope1.Release; _envelope1.Release;
break; break;
case 0x0E: result = _voice2.FrequencyLo; break; case 0x0E: result = _voice2.FrequencyLo; break;
case 0x0F: result = _voice2.FrequencyHi; break; case 0x0F: result = _voice2.FrequencyHi; break;
@ -84,33 +84,33 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
case 0x11: result = _voice2.PulseWidthHi; break; case 0x11: result = _voice2.PulseWidthHi; break;
case 0x12: case 0x12:
result = (_envelope2.Gate ? 0x01 : 0x00) | result = (_envelope2.Gate ? 0x01 : 0x00) |
(_voice2.Sync ? 0x02 : 0x00) | (_voice2.Sync ? 0x02 : 0x00) |
(_voice2.RingMod ? 0x04 : 0x00) | (_voice2.RingMod ? 0x04 : 0x00) |
(_voice2.Test ? 0x08 : 0x00) | (_voice2.Test ? 0x08 : 0x00) |
(_voice2.Waveform << 4); (_voice2.Waveform << 4);
break; break;
case 0x13: case 0x13:
result = (_envelope2.Attack << 4) | result = (_envelope2.Attack << 4) |
_envelope2.Decay; _envelope2.Decay;
break; break;
case 0x14: case 0x14:
result = (_envelope2.Sustain << 4) | result = (_envelope2.Sustain << 4) |
_envelope2.Release; _envelope2.Release;
break; break;
case 0x15: result = _filterFrequency & 0x7; break; case 0x15: result = _filterFrequency & 0x7; break;
case 0x16: result = (_filterFrequency >> 3) & 0xFF; break; case 0x16: result = (_filterFrequency >> 3) & 0xFF; break;
case 0x17: case 0x17:
result = (_filterEnable[0] ? 0x01 : 0x00) | result = (_filterEnable[0] ? 0x01 : 0x00) |
(_filterEnable[1] ? 0x02 : 0x00) | (_filterEnable[1] ? 0x02 : 0x00) |
(_filterEnable[2] ? 0x04 : 0x00) | (_filterEnable[2] ? 0x04 : 0x00) |
(_filterResonance << 4); (_filterResonance << 4);
break; break;
case 0x18: case 0x18:
result = _volume | result = _volume |
(_filterSelectLoPass ? 0x10 : 0x00) | (_filterSelectLoPass ? 0x10 : 0x00) |
(_filterSelectBandPass ? 0x20 : 0x00) | (_filterSelectBandPass ? 0x20 : 0x00) |
(_filterSelectHiPass ? 0x40 : 0x00) | (_filterSelectHiPass ? 0x40 : 0x00) |
(_disableVoice3 ? 0x80 : 0x00); (_disableVoice3 ? 0x80 : 0x00);
break; break;
case 0x19: result = _potX; break; case 0x19: result = _potX; break;
case 0x1A: result = _potY; break; case 0x1A: result = _potY; break;

View File

@ -9,34 +9,34 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Sid public sealed partial class Sid
{ {
private sealed class Voice private sealed class Voice
{ {
private int _accBits; private int _accBits;
private int _accNext; private int _accNext;
private int _accumulator; private int _accumulator;
private bool _controlTestPrev; private bool _controlTestPrev;
private int _controlWavePrev; private int _controlWavePrev;
private int _delay; private int _delay;
private int _floatOutputTtl; private int _floatOutputTtl;
private int _frequency; private int _frequency;
private bool _msbRising; private bool _msbRising;
private int _noise; private int _noise;
private int _noNoise; private int _noNoise;
private int _noNoiseOrNoise; private int _noNoiseOrNoise;
private int _noPulse; private int _noPulse;
private int _output; private int _output;
private int _pulse; private int _pulse;
private int _pulseWidth; private int _pulseWidth;
private bool _ringMod; private bool _ringMod;
private int _ringMsbMask; private int _ringMsbMask;
private int _shiftRegister; private int _shiftRegister;
private int _shiftRegisterReset; private int _shiftRegisterReset;
private bool _sync; private bool _sync;
private bool _test; private bool _test;
[SaveState.DoNotSave] private int[] _wave; [SaveState.DoNotSave] private int[] _wave;
private int _waveform; private int _waveform;
private int _waveformIndex; private int _waveformIndex;
[SaveState.DoNotSave] private readonly int[][] _waveTable; [SaveState.DoNotSave] private readonly int[][] _waveTable;
public Voice(int[][] newWaveTable) public Voice(int[][] newWaveTable)
{ {
@ -304,8 +304,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
_wave = _waveTable[_waveform & 0x07]; _wave = _waveTable[_waveform & 0x07];
} }
} }
} }

View File

@ -7,7 +7,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Sid public sealed partial class Sid
{ {
/* /*
Commodore SID 6581/8580 core. Commodore SID 6581/8580 core.
Many thanks to: Many thanks to:
@ -21,72 +21,72 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
https://sourceforge.net/projects/sidplay-residfp/ https://sourceforge.net/projects/sidplay-residfp/
*/ */
// ------------------------------------ // ------------------------------------
private int _cachedCycles; private int _cachedCycles;
private bool _disableVoice3; private bool _disableVoice3;
private int _envelopeOutput0; private int _envelopeOutput0;
private int _envelopeOutput1; private int _envelopeOutput1;
private int _envelopeOutput2; private int _envelopeOutput2;
private readonly Envelope[] _envelopes; private readonly Envelope[] _envelopes;
[SaveState.DoNotSave] private readonly Envelope _envelope0; [SaveState.DoNotSave] private readonly Envelope _envelope0;
[SaveState.DoNotSave] private readonly Envelope _envelope1; [SaveState.DoNotSave] private readonly Envelope _envelope1;
[SaveState.DoNotSave] private readonly Envelope _envelope2; [SaveState.DoNotSave] private readonly Envelope _envelope2;
private readonly bool[] _filterEnable; private readonly bool[] _filterEnable;
private int _filterFrequency; private int _filterFrequency;
private int _filterResonance; private int _filterResonance;
private bool _filterSelectBandPass; private bool _filterSelectBandPass;
private bool _filterSelectLoPass; private bool _filterSelectLoPass;
private bool _filterSelectHiPass; private bool _filterSelectHiPass;
private int _mixer; private int _mixer;
[SaveState.DoNotSave] private readonly short[] _outputBuffer; [SaveState.DoNotSave] private readonly short[] _outputBuffer;
[SaveState.DoNotSave] private int _outputBufferIndex; [SaveState.DoNotSave] private int _outputBufferIndex;
private int _potCounter; private int _potCounter;
private int _potX; private int _potX;
private int _potY; private int _potY;
private short _sample; private short _sample;
private int _voiceOutput0; private int _voiceOutput0;
private int _voiceOutput1; private int _voiceOutput1;
private int _voiceOutput2; private int _voiceOutput2;
private readonly Voice[] _voices; private readonly Voice[] _voices;
[SaveState.DoNotSave] private readonly Voice _voice0; [SaveState.DoNotSave] private readonly Voice _voice0;
[SaveState.DoNotSave] private readonly Voice _voice1; [SaveState.DoNotSave] private readonly Voice _voice1;
[SaveState.DoNotSave] private readonly Voice _voice2; [SaveState.DoNotSave] private readonly Voice _voice2;
private int _volume; private int _volume;
public Func<int> ReadPotX; public Func<int> ReadPotX;
public Func<int> ReadPotY; public Func<int> ReadPotY;
[SaveState.DoNotSave] private readonly int _cpuCyclesNum; [SaveState.DoNotSave] private readonly int _cpuCyclesNum;
[SaveState.DoNotSave] private int _sampleCyclesNum; [SaveState.DoNotSave] private int _sampleCyclesNum;
[SaveState.DoNotSave] private readonly int _sampleCyclesDen; [SaveState.DoNotSave] private readonly int _sampleCyclesDen;
[SaveState.DoNotSave] private readonly int _sampleRate; [SaveState.DoNotSave] private readonly int _sampleRate;
public Sid(int[][] newWaveformTable, int sampleRate, int cyclesNum, int cyclesDen) public Sid(int[][] newWaveformTable, int sampleRate, int cyclesNum, int cyclesDen)
{ {
_sampleRate = sampleRate; _sampleRate = sampleRate;
_cpuCyclesNum = cyclesNum; _cpuCyclesNum = cyclesNum;
_sampleCyclesDen = cyclesDen*sampleRate; _sampleCyclesDen = cyclesDen * sampleRate;
_envelopes = new Envelope[3]; _envelopes = new Envelope[3];
for (var i = 0; i < 3; i++) for (var i = 0; i < 3; i++)
_envelopes[i] = new Envelope(); _envelopes[i] = new Envelope();
_envelope0 = _envelopes[0]; _envelope0 = _envelopes[0];
_envelope1 = _envelopes[1]; _envelope1 = _envelopes[1];
_envelope2 = _envelopes[2]; _envelope2 = _envelopes[2];
_voices = new Voice[3]; _voices = new Voice[3];
for (var i = 0; i < 3; i++) for (var i = 0; i < 3; i++)
_voices[i] = new Voice(newWaveformTable); _voices[i] = new Voice(newWaveformTable);
_voice0 = _voices[0]; _voice0 = _voices[0];
_voice1 = _voices[1]; _voice1 = _voices[1];
_voice2 = _voices[2]; _voice2 = _voices[2];
_filterEnable = new bool[3]; _filterEnable = new bool[3];
for (var i = 0; i < 3; i++) for (var i = 0; i < 3; i++)
_filterEnable[i] = false; _filterEnable[i] = false;
_outputBuffer = new short[sampleRate]; _outputBuffer = new short[sampleRate];
} }
// ------------------------------------ // ------------------------------------
@ -121,9 +121,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void Flush() public void Flush()
{ {
while (_cachedCycles > 0) while (_cachedCycles > 0)
{ {
_cachedCycles--; _cachedCycles--;
// process voices and envelopes // process voices and envelopes
_voice0.ExecutePhase2(); _voice0.ExecutePhase2();
@ -133,50 +133,50 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_envelope1.ExecutePhase2(); _envelope1.ExecutePhase2();
_envelope2.ExecutePhase2(); _envelope2.ExecutePhase2();
_voice0.Synchronize(_voice1, _voice2); _voice0.Synchronize(_voice1, _voice2);
_voice1.Synchronize(_voice2, _voice0); _voice1.Synchronize(_voice2, _voice0);
_voice2.Synchronize(_voice0, _voice1); _voice2.Synchronize(_voice0, _voice1);
// get output // get output
_voiceOutput0 = _voice0.Output(_voice2); _voiceOutput0 = _voice0.Output(_voice2);
_voiceOutput1 = _voice1.Output(_voice0); _voiceOutput1 = _voice1.Output(_voice0);
_voiceOutput2 = _voice2.Output(_voice1); _voiceOutput2 = _voice2.Output(_voice1);
_envelopeOutput0 = _envelope0.Level; _envelopeOutput0 = _envelope0.Level;
_envelopeOutput1 = _envelope1.Level; _envelopeOutput1 = _envelope1.Level;
_envelopeOutput2 = _envelope2.Level; _envelopeOutput2 = _envelope2.Level;
_sampleCyclesNum += _sampleCyclesDen; _sampleCyclesNum += _sampleCyclesDen;
if (_sampleCyclesNum >= _cpuCyclesNum) if (_sampleCyclesNum >= _cpuCyclesNum)
{ {
_sampleCyclesNum -= _cpuCyclesNum; _sampleCyclesNum -= _cpuCyclesNum;
_mixer = (_voiceOutput0 * _envelopeOutput0) >> 7; _mixer = (_voiceOutput0 * _envelopeOutput0) >> 7;
_mixer += (_voiceOutput1 * _envelopeOutput1) >> 7; _mixer += (_voiceOutput1 * _envelopeOutput1) >> 7;
_mixer += (_voiceOutput2 * _envelopeOutput2) >> 7; _mixer += (_voiceOutput2 * _envelopeOutput2) >> 7;
_mixer = (_mixer * _volume) >> 4; _mixer = (_mixer * _volume) >> 4;
_mixer -= _volume << 8; _mixer -= _volume << 8;
if (_mixer > 0x7FFF) if (_mixer > 0x7FFF)
{ {
_mixer = 0x7FFF; _mixer = 0x7FFF;
} }
if (_mixer < -0x8000) if (_mixer < -0x8000)
{ {
_mixer = -0x8000; _mixer = -0x8000;
} }
_sample = unchecked((short)_mixer); _sample = unchecked((short)_mixer);
if (_outputBufferIndex < _sampleRate) if (_outputBufferIndex < _sampleRate)
{ {
_outputBuffer[_outputBufferIndex++] = _sample; _outputBuffer[_outputBufferIndex++] = _sample;
_outputBuffer[_outputBufferIndex++] = _sample; _outputBuffer[_outputBufferIndex++] = _sample;
} }
} }
} }
} }
// ---------------------------------- // ----------------------------------
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }

View File

@ -7,120 +7,120 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Via public sealed partial class Via
{ {
private abstract class Port private abstract class Port
{ {
public abstract int ReadPra(int pra, int ddra); public abstract int ReadPra(int pra, int ddra);
public abstract int ReadPrb(int prb, int ddrb); public abstract int ReadPrb(int prb, int ddrb);
public abstract int ReadExternalPra(); public abstract int ReadExternalPra();
public abstract int ReadExternalPrb(); public abstract int ReadExternalPrb();
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
private sealed class DisconnectedPort : Port private sealed class DisconnectedPort : Port
{ {
public override int ReadPra(int pra, int ddra) public override int ReadPra(int pra, int ddra)
{ {
return (pra | ~ddra) & 0xFF; return (pra | ~ddra) & 0xFF;
} }
public override int ReadPrb(int prb, int ddrb) public override int ReadPrb(int prb, int ddrb)
{ {
return (prb | ~ddrb) & 0xFF; return (prb | ~ddrb) & 0xFF;
} }
public override int ReadExternalPra() public override int ReadExternalPra()
{ {
return 0xFF; return 0xFF;
} }
public override int ReadExternalPrb() public override int ReadExternalPrb()
{ {
return 0xFF; return 0xFF;
} }
} }
private sealed class DriverPort : Port private sealed class DriverPort : Port
{ {
private readonly Func<int> _readPrA; private readonly Func<int> _readPrA;
private readonly Func<int> _readPrB; private readonly Func<int> _readPrB;
public DriverPort(Func<int> readPrA, Func<int> readPrB) public DriverPort(Func<int> readPrA, Func<int> readPrB)
{ {
_readPrA = readPrA; _readPrA = readPrA;
_readPrB = readPrB; _readPrB = readPrB;
} }
public override int ReadPra(int pra, int ddra) public override int ReadPra(int pra, int ddra)
{ {
return _readPrA(); return _readPrA();
} }
public override int ReadPrb(int prb, int ddrb) public override int ReadPrb(int prb, int ddrb)
{ {
return (prb & ddrb) | (_readPrB() & ~ddrb); return (prb & ddrb) | (_readPrB() & ~ddrb);
} }
public override int ReadExternalPra() public override int ReadExternalPra()
{ {
return _readPrA(); return _readPrA();
} }
public override int ReadExternalPrb() public override int ReadExternalPrb()
{ {
return _readPrB(); return _readPrB();
} }
} }
private sealed class IecPort : Port private sealed class IecPort : Port
{ {
private readonly Func<bool> _readClock; private readonly Func<bool> _readClock;
private readonly Func<bool> _readData; private readonly Func<bool> _readData;
private readonly Func<bool> _readAtn; private readonly Func<bool> _readAtn;
private readonly int _driveNumber; private readonly int _driveNumber;
public IecPort(Func<bool> readClock, Func<bool> readData, Func<bool> readAtn, int driveNumber) public IecPort(Func<bool> readClock, Func<bool> readData, Func<bool> readAtn, int driveNumber)
{ {
_readClock = readClock; _readClock = readClock;
_readData = readData; _readData = readData;
_readAtn = readAtn; _readAtn = readAtn;
_driveNumber = (driveNumber & 0x3) << 5; _driveNumber = (driveNumber & 0x3) << 5;
} }
public override int ReadPra(int pra, int ddra) public override int ReadPra(int pra, int ddra)
{ {
return (pra | ~ddra) & 0xFF; return (pra | ~ddra) & 0xFF;
} }
public override int ReadPrb(int prb, int ddrb) public override int ReadPrb(int prb, int ddrb)
{ {
return (prb & ddrb) | return (prb & ddrb) |
(~ddrb & 0xE5 & ( (~ddrb & 0xE5 & (
(_readClock() ? 0x04 : 0x00) | (_readClock() ? 0x04 : 0x00) |
(_readData() ? 0x01 : 0x00) | (_readData() ? 0x01 : 0x00) |
(_readAtn() ? 0x80 : 0x00) | (_readAtn() ? 0x80 : 0x00) |
_driveNumber) _driveNumber)
); );
} }
public override int ReadExternalPra() public override int ReadExternalPra()
{ {
return 0xFF; return 0xFF;
} }
public override int ReadExternalPrb() public override int ReadExternalPrb()
{ {
return return
(_readClock() ? 0x04 : 0x00) | (_readClock() ? 0x04 : 0x00) |
(_readData() ? 0x01 : 0x00) | (_readData() ? 0x01 : 0x00) |
(_readAtn() ? 0x80 : 0x00) | (_readAtn() ? 0x80 : 0x00) |
_driveNumber; _driveNumber;
} }
} }
} }
} }

View File

@ -5,273 +5,273 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Via public sealed partial class Via
{ {
public int Peek(int addr) public int Peek(int addr)
{ {
return ReadRegister(addr & 0xF); return ReadRegister(addr & 0xF);
} }
public void Poke(int addr, int val) public void Poke(int addr, int val)
{ {
WriteRegister(addr & 0xF, val); WriteRegister(addr & 0xF, val);
} }
public int Read(int addr) public int Read(int addr)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
_ifr &= 0xE7; _ifr &= 0xE7;
if (_acrPbLatchEnable) if (_acrPbLatchEnable)
{ {
return _pbLatch; return _pbLatch;
} }
break; break;
case 0x1: case 0x1:
_ifr &= 0xFC; _ifr &= 0xFC;
if (_acrPaLatchEnable) if (_acrPaLatchEnable)
{ {
return _paLatch; return _paLatch;
} }
break; break;
case 0x4: case 0x4:
_ifr &= 0xBF; _ifr &= 0xBF;
break; break;
case 0x8: case 0x8:
_ifr &= 0xDF; _ifr &= 0xDF;
break; break;
case 0xA: case 0xA:
_ifr &= 0xFB; _ifr &= 0xFB;
break; break;
case 0xF: case 0xF:
if (_acrPaLatchEnable) if (_acrPaLatchEnable)
{ {
return _paLatch; return _paLatch;
} }
break; break;
} }
return ReadRegister(addr); return ReadRegister(addr);
} }
private int ReadRegister(int addr) private int ReadRegister(int addr)
{ {
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
return _port.ReadPrb(_prb, _ddrb); return _port.ReadPrb(_prb, _ddrb);
case 0x1: case 0x1:
return _port.ReadPra(_pra, _ddra); return _port.ReadPra(_pra, _ddra);
case 0x2: case 0x2:
return _ddrb; return _ddrb;
case 0x3: case 0x3:
return _ddra; return _ddra;
case 0x4: case 0x4:
return _t1C & 0xFF; return _t1C & 0xFF;
case 0x5: case 0x5:
return (_t1C >> 8) & 0xFF; return (_t1C >> 8) & 0xFF;
case 0x6: case 0x6:
return _t1L & 0xFF; return _t1L & 0xFF;
case 0x7: case 0x7:
return (_t1L >> 8) & 0xFF; return (_t1L >> 8) & 0xFF;
case 0x8: case 0x8:
return _t2C & 0xFF; return _t2C & 0xFF;
case 0x9: case 0x9:
return (_t2C >> 8) & 0xFF; return (_t2C >> 8) & 0xFF;
case 0xA: case 0xA:
return _sr; return _sr;
case 0xB: case 0xB:
return _acr; return _acr;
case 0xC: case 0xC:
return _pcr; return _pcr;
case 0xD: case 0xD:
return _ifr; return _ifr;
case 0xE: case 0xE:
return _ier | 0x80; return _ier | 0x80;
case 0xF: case 0xF:
return _port.ReadPra(_pra, _ddra); return _port.ReadPra(_pra, _ddra);
} }
return 0xFF; return 0xFF;
} }
public void Write(int addr, int val) public void Write(int addr, int val)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
_ifr &= 0xE7; _ifr &= 0xE7;
if (_pcrCb2Control == PCR_CONTROL_HANDSHAKE_OUTPUT || _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT) if (_pcrCb2Control == PCR_CONTROL_HANDSHAKE_OUTPUT || _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT)
{ {
_handshakeCb2NextClock = true; _handshakeCb2NextClock = true;
} }
WriteRegister(addr, val); WriteRegister(addr, val);
break; break;
case 0x1: case 0x1:
_ifr &= 0xFC; _ifr &= 0xFC;
if (_pcrCa2Control == PCR_CONTROL_HANDSHAKE_OUTPUT || _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT) if (_pcrCa2Control == PCR_CONTROL_HANDSHAKE_OUTPUT || _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT)
{ {
_handshakeCa2NextClock = true; _handshakeCa2NextClock = true;
} }
WriteRegister(addr, val); WriteRegister(addr, val);
break; break;
case 0x4: case 0x4:
case 0x6: case 0x6:
_t1L = (_t1L & 0xFF00) | (val & 0xFF); _t1L = (_t1L & 0xFF00) | (val & 0xFF);
break; break;
case 0x5: case 0x5:
_t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8); _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8);
_ifr &= 0xBF; _ifr &= 0xBF;
_t1C = _t1L; _t1C = _t1L;
_t1CLoaded = true; _t1CLoaded = true;
_t1Delayed = 1; _t1Delayed = 1;
break; break;
case 0x7: case 0x7:
_t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8); _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8);
_ifr &= 0xBF; _ifr &= 0xBF;
break; break;
case 0x8: case 0x8:
_t2L = (_t2L & 0xFF00) | (val & 0xFF); _t2L = (_t2L & 0xFF00) | (val & 0xFF);
break; break;
case 0x9: case 0x9:
_t2L = (_t2L & 0xFF) | ((val & 0xFF) << 8); _t2L = (_t2L & 0xFF) | ((val & 0xFF) << 8);
_ifr &= 0xDF; _ifr &= 0xDF;
if (_acrT2Control == ACR_T2_CONTROL_TIMED) if (_acrT2Control == ACR_T2_CONTROL_TIMED)
{ {
_t2C = _t2L; _t2C = _t2L;
_t2CLoaded = true; _t2CLoaded = true;
} }
_t2Delayed = 1; _t2Delayed = 1;
break; break;
case 0xA: case 0xA:
_ifr &= 0xFB; _ifr &= 0xFB;
WriteRegister(addr, val); WriteRegister(addr, val);
break; break;
case 0xD: case 0xD:
_ifr &= ~val; _ifr &= ~val;
break; break;
case 0xE: case 0xE:
if ((val & 0x80) != 0) if ((val & 0x80) != 0)
_ier |= val & 0x7F; _ier |= val & 0x7F;
else else
_ier &= ~val; _ier &= ~val;
break; break;
default: default:
WriteRegister(addr, val); WriteRegister(addr, val);
break; break;
} }
} }
private void WriteRegister(int addr, int val) private void WriteRegister(int addr, int val)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr) switch (addr)
{ {
case 0x0: case 0x0:
_prb = val & 0xFF; _prb = val & 0xFF;
break; break;
case 0x1: case 0x1:
case 0xF: case 0xF:
_pra = val & 0xFF; _pra = val & 0xFF;
break; break;
case 0x2: case 0x2:
_ddrb = val & 0xFF; _ddrb = val & 0xFF;
break; break;
case 0x3: case 0x3:
_ddra = val & 0xFF; _ddra = val & 0xFF;
break; break;
case 0x4: case 0x4:
_t1C = (_t1C & 0xFF00) | (val & 0xFF); _t1C = (_t1C & 0xFF00) | (val & 0xFF);
break; break;
case 0x5: case 0x5:
_t1C = (_t1C & 0xFF) | ((val & 0xFF) << 8); _t1C = (_t1C & 0xFF) | ((val & 0xFF) << 8);
break; break;
case 0x6: case 0x6:
_t1L = (_t1L & 0xFF00) | (val & 0xFF); _t1L = (_t1L & 0xFF00) | (val & 0xFF);
break; break;
case 0x7: case 0x7:
_t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8); _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8);
break; break;
case 0x8: case 0x8:
_t2C = (_t2C & 0xFF00) | (val & 0xFF); _t2C = (_t2C & 0xFF00) | (val & 0xFF);
break; break;
case 0x9: case 0x9:
_t2C = (_t2C & 0xFF) | ((val & 0xFF) << 8); _t2C = (_t2C & 0xFF) | ((val & 0xFF) << 8);
break; break;
case 0xA: case 0xA:
_sr = val & 0xFF; _sr = val & 0xFF;
break; break;
case 0xB: case 0xB:
_acr = val & 0xFF; _acr = val & 0xFF;
_acrPaLatchEnable = (val & 0x01) != 0; _acrPaLatchEnable = (val & 0x01) != 0;
_acrPbLatchEnable = (val & 0x02) != 0; _acrPbLatchEnable = (val & 0x02) != 0;
_acrSrControl = (val & 0x1C); _acrSrControl = (val & 0x1C);
_acrT2Control = (val & 0x20); _acrT2Control = (val & 0x20);
_acrT1Control = (val & 0xC0); _acrT1Control = (val & 0xC0);
break; break;
case 0xC: case 0xC:
_pcr = val & 0xFF; _pcr = val & 0xFF;
_pcrCa1IntControl = _pcr & 0x01; _pcrCa1IntControl = _pcr & 0x01;
_pcrCa2Control = _pcr & 0x0E; _pcrCa2Control = _pcr & 0x0E;
_pcrCb1IntControl = (_pcr & 0x10) >> 4; _pcrCb1IntControl = (_pcr & 0x10) >> 4;
_pcrCb2Control = (_pcr & 0xE0) >> 4; _pcrCb2Control = (_pcr & 0xE0) >> 4;
break; break;
case 0xD: case 0xD:
_ifr = val & 0xFF; _ifr = val & 0xFF;
break; break;
case 0xE: case 0xE:
_ier = val & 0xFF; _ier = val & 0xFF;
break; break;
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int DdrA public int DdrA
{ {
get { return _ddra; } get { return _ddra; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int DdrB public int DdrB
{ {
get { return _ddrb; } get { return _ddrb; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int PrA public int PrA
{ {
get { return _pra; } get { return _pra; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int PrB public int PrB
{ {
get { return _prb; } get { return _prb; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int EffectivePrA public int EffectivePrA
{ {
get { return _pra | ~_ddra; } get { return _pra | ~_ddra; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int EffectivePrB public int EffectivePrB
{ {
get { return _prb | ~_ddrb; } get { return _prb | ~_ddrb; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int ActualPrA public int ActualPrA
{ {
get { return _acrPaLatchEnable ? _paLatch : _port.ReadPra(_pra, _ddra); } get { return _acrPaLatchEnable ? _paLatch : _port.ReadPra(_pra, _ddra); }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int ActualPrB public int ActualPrB
{ {
get { return _acrPbLatchEnable ? _pbLatch : _port.ReadPrb(_prb, _ddrb); } get { return _acrPbLatchEnable ? _pbLatch : _port.ReadPrb(_prb, _ddrb); }
} }
} }
} }

View File

@ -7,406 +7,406 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Via public sealed partial class Via
{ {
[SaveState.DoNotSave] private const int PCR_INT_CONTROL_NEGATIVE_EDGE = 0x00; [SaveState.DoNotSave] private const int PCR_INT_CONTROL_NEGATIVE_EDGE = 0x00;
[SaveState.DoNotSave] private const int PCR_INT_CONTROL_POSITIVE_EDGE = 0x01; [SaveState.DoNotSave] private const int PCR_INT_CONTROL_POSITIVE_EDGE = 0x01;
[SaveState.DoNotSave] private const int PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE = 0x00; [SaveState.DoNotSave] private const int PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE = 0x00;
[SaveState.DoNotSave] private const int PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE = 0x02; [SaveState.DoNotSave] private const int PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE = 0x02;
[SaveState.DoNotSave] private const int PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE = 0x04; [SaveState.DoNotSave] private const int PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE = 0x04;
[SaveState.DoNotSave] private const int PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE = 0x06; [SaveState.DoNotSave] private const int PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE = 0x06;
[SaveState.DoNotSave] private const int PCR_CONTROL_HANDSHAKE_OUTPUT = 0x08; [SaveState.DoNotSave] private const int PCR_CONTROL_HANDSHAKE_OUTPUT = 0x08;
[SaveState.DoNotSave] private const int PCR_CONTROL_PULSE_OUTPUT = 0x0A; [SaveState.DoNotSave] private const int PCR_CONTROL_PULSE_OUTPUT = 0x0A;
[SaveState.DoNotSave] private const int PCR_CONTROL_LOW_OUTPUT = 0x0C; [SaveState.DoNotSave] private const int PCR_CONTROL_LOW_OUTPUT = 0x0C;
[SaveState.DoNotSave] private const int PCR_CONTROL_HIGH_OUTPUT = 0x0E; [SaveState.DoNotSave] private const int PCR_CONTROL_HIGH_OUTPUT = 0x0E;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_DISABLED = 0x00; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_DISABLED = 0x00;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_IN_T2_ONCE = 0x04; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_IN_T2_ONCE = 0x04;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_IN_PHI2 = 0x08; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_IN_PHI2 = 0x08;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_IN_CLOCK = 0x0C; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_IN_CLOCK = 0x0C;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_T2 = 0x10; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_T2 = 0x10;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_T2_ONCE = 0x14; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_T2_ONCE = 0x14;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_PHI2 = 0x18; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_PHI2 = 0x18;
[SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_CLOCK = 0x1C; [SaveState.DoNotSave] private const int ACR_SR_CONTROL_SHIFT_OUT_CLOCK = 0x1C;
[SaveState.DoNotSave] private const int ACR_T2_CONTROL_TIMED = 0x00; [SaveState.DoNotSave] private const int ACR_T2_CONTROL_TIMED = 0x00;
[SaveState.DoNotSave] private const int ACR_T2_CONTROL_COUNT_ON_PB6 = 0x20; [SaveState.DoNotSave] private const int ACR_T2_CONTROL_COUNT_ON_PB6 = 0x20;
[SaveState.DoNotSave] private const int ACR_T1_CONTROL_INTERRUPT_ON_LOAD = 0x00; [SaveState.DoNotSave] private const int ACR_T1_CONTROL_INTERRUPT_ON_LOAD = 0x00;
[SaveState.DoNotSave] private const int ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS = 0x40; [SaveState.DoNotSave] private const int ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS = 0x40;
[SaveState.DoNotSave] private const int ACR_T1_CONTROL_INTERRUPT_ON_LOAD_AND_ONESHOT_PB7 = 0x80; [SaveState.DoNotSave] private const int ACR_T1_CONTROL_INTERRUPT_ON_LOAD_AND_ONESHOT_PB7 = 0x80;
[SaveState.DoNotSave] private const int ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7 = 0xC0; [SaveState.DoNotSave] private const int ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7 = 0xC0;
[SaveState.SaveWithName("PortOutputA")] [SaveState.SaveWithName("PortOutputA")]
private int _pra; private int _pra;
[SaveState.SaveWithName("PortDirectionA")] [SaveState.SaveWithName("PortDirectionA")]
private int _ddra; private int _ddra;
[SaveState.SaveWithName("PortOutputB")] [SaveState.SaveWithName("PortOutputB")]
private int _prb; private int _prb;
[SaveState.SaveWithName("PortDirectionB")] [SaveState.SaveWithName("PortDirectionB")]
private int _ddrb; private int _ddrb;
[SaveState.SaveWithName("Timer1Counter")] [SaveState.SaveWithName("Timer1Counter")]
private int _t1C; private int _t1C;
[SaveState.SaveWithName("Timer1Latch")] [SaveState.SaveWithName("Timer1Latch")]
private int _t1L; private int _t1L;
[SaveState.SaveWithName("Timer2Counter")] [SaveState.SaveWithName("Timer2Counter")]
private int _t2C; private int _t2C;
[SaveState.SaveWithName("Timer2Latch")] [SaveState.SaveWithName("Timer2Latch")]
private int _t2L; private int _t2L;
[SaveState.SaveWithName("ShiftRegister")] [SaveState.SaveWithName("ShiftRegister")]
private int _sr; private int _sr;
[SaveState.SaveWithName("AuxiliaryControlRegister")] [SaveState.SaveWithName("AuxiliaryControlRegister")]
private int _acr; private int _acr;
[SaveState.SaveWithName("PeripheralControlRegister")] [SaveState.SaveWithName("PeripheralControlRegister")]
private int _pcr; private int _pcr;
[SaveState.SaveWithName("InterruptFlagRegister")] [SaveState.SaveWithName("InterruptFlagRegister")]
private int _ifr; private int _ifr;
[SaveState.SaveWithName("InterruptEnableRegister")] [SaveState.SaveWithName("InterruptEnableRegister")]
private int _ier; private int _ier;
[SaveState.SaveWithName("Port")] [SaveState.SaveWithName("Port")]
private readonly Port _port; private readonly Port _port;
[SaveState.SaveWithName("PortLatchA")] [SaveState.SaveWithName("PortLatchA")]
private int _paLatch; private int _paLatch;
[SaveState.SaveWithName("PortLatchB")] [SaveState.SaveWithName("PortLatchB")]
private int _pbLatch; private int _pbLatch;
[SaveState.SaveWithName("CA1InterruptControl")] [SaveState.SaveWithName("CA1InterruptControl")]
private int _pcrCa1IntControl; private int _pcrCa1IntControl;
[SaveState.SaveWithName("CA2Control")] [SaveState.SaveWithName("CA2Control")]
private int _pcrCa2Control; private int _pcrCa2Control;
[SaveState.SaveWithName("CB1InterruptControl")] [SaveState.SaveWithName("CB1InterruptControl")]
private int _pcrCb1IntControl; private int _pcrCb1IntControl;
[SaveState.SaveWithName("CB2Control")] [SaveState.SaveWithName("CB2Control")]
private int _pcrCb2Control; private int _pcrCb2Control;
[SaveState.SaveWithName("PortLatchEnableA")] [SaveState.SaveWithName("PortLatchEnableA")]
private bool _acrPaLatchEnable; private bool _acrPaLatchEnable;
[SaveState.SaveWithName("PortLatchEnableB")] [SaveState.SaveWithName("PortLatchEnableB")]
private bool _acrPbLatchEnable; private bool _acrPbLatchEnable;
[SaveState.SaveWithName("ShiftRegisterControl")] [SaveState.SaveWithName("ShiftRegisterControl")]
private int _acrSrControl; private int _acrSrControl;
[SaveState.SaveWithName("Timer1Control")] [SaveState.SaveWithName("Timer1Control")]
private int _acrT1Control; private int _acrT1Control;
[SaveState.SaveWithName("Timer2Control")] [SaveState.SaveWithName("Timer2Control")]
private int _acrT2Control; private int _acrT2Control;
[SaveState.SaveWithName("PreviousCA1")] [SaveState.SaveWithName("PreviousCA1")]
private bool _ca1L; private bool _ca1L;
[SaveState.SaveWithName("PreviousCA2")] [SaveState.SaveWithName("PreviousCA2")]
private bool _ca2L; private bool _ca2L;
[SaveState.SaveWithName("PreviousCB1")] [SaveState.SaveWithName("PreviousCB1")]
private bool _cb1L; private bool _cb1L;
[SaveState.SaveWithName("PreviousCB2")] [SaveState.SaveWithName("PreviousCB2")]
private bool _cb2L; private bool _cb2L;
[SaveState.SaveWithName("PreviousPB6")] [SaveState.SaveWithName("PreviousPB6")]
private bool _pb6L; private bool _pb6L;
[SaveState.SaveWithName("ResetCa2NextClock")] [SaveState.SaveWithName("ResetCa2NextClock")]
private bool _resetCa2NextClock; private bool _resetCa2NextClock;
[SaveState.SaveWithName("ResetCb2NextClock")] [SaveState.SaveWithName("ResetCb2NextClock")]
private bool _resetCb2NextClock; private bool _resetCb2NextClock;
[SaveState.SaveWithName("HandshakeCa2NextClock")] [SaveState.SaveWithName("HandshakeCa2NextClock")]
private bool _handshakeCa2NextClock; private bool _handshakeCa2NextClock;
[SaveState.SaveWithName("HandshakeCb2NextClock")] [SaveState.SaveWithName("HandshakeCb2NextClock")]
private bool _handshakeCb2NextClock; private bool _handshakeCb2NextClock;
[SaveState.SaveWithName("CA1")] [SaveState.SaveWithName("CA1")]
public bool Ca1; public bool Ca1;
[SaveState.SaveWithName("CA2")] [SaveState.SaveWithName("CA2")]
public bool Ca2; public bool Ca2;
[SaveState.SaveWithName("CB1")] [SaveState.SaveWithName("CB1")]
public bool Cb1; public bool Cb1;
[SaveState.SaveWithName("CB2")] [SaveState.SaveWithName("CB2")]
public bool Cb2; public bool Cb2;
[SaveState.SaveWithName("PB6")] [SaveState.SaveWithName("PB6")]
private bool _pb6; private bool _pb6;
[SaveState.SaveWithName("InterruptNextClock")] [SaveState.SaveWithName("InterruptNextClock")]
private int _interruptNextClock; private int _interruptNextClock;
[SaveState.SaveWithName("T1Loaded")] [SaveState.SaveWithName("T1Loaded")]
private bool _t1CLoaded; private bool _t1CLoaded;
[SaveState.SaveWithName("T2Loaded")] [SaveState.SaveWithName("T2Loaded")]
private bool _t2CLoaded; private bool _t2CLoaded;
[SaveState.SaveWithName("T1Delayed")] [SaveState.SaveWithName("T1Delayed")]
private int _t1Delayed; private int _t1Delayed;
[SaveState.SaveWithName("T2Delayed")] [SaveState.SaveWithName("T2Delayed")]
private int _t2Delayed; private int _t2Delayed;
public Via() public Via()
{ {
_port = new DisconnectedPort(); _port = new DisconnectedPort();
} }
public Via(Func<int> readPrA, Func<int> readPrB) public Via(Func<int> readPrA, Func<int> readPrB)
{ {
_port = new DriverPort(readPrA, readPrB); _port = new DriverPort(readPrA, readPrB);
} }
public Via(Func<bool> readClock, Func<bool> readData, Func<bool> readAtn, int driveNumber) public Via(Func<bool> readClock, Func<bool> readData, Func<bool> readAtn, int driveNumber)
{ {
_port = new IecPort(readClock, readData, readAtn, driveNumber); _port = new IecPort(readClock, readData, readAtn, driveNumber);
_ca1L = true; _ca1L = true;
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool Irq public bool Irq
{ {
get { return (_ifr & 0x80) == 0; } get { return (_ifr & 0x80) == 0; }
} }
public void HardReset() public void HardReset()
{ {
_pra = 0; _pra = 0;
_prb = 0; _prb = 0;
_ddra = 0; _ddra = 0;
_ddrb = 0; _ddrb = 0;
_t1C = 0; _t1C = 0;
_t1L = 0; _t1L = 0;
_t2C = 0; _t2C = 0;
_t2L = 0; _t2L = 0;
_sr = 0; _sr = 0;
_acr = 0; _acr = 0;
_pcr = 0; _pcr = 0;
_ifr = 0; _ifr = 0;
_ier = 0; _ier = 0;
_paLatch = 0; _paLatch = 0;
_pbLatch = 0; _pbLatch = 0;
_pcrCa1IntControl = 0; _pcrCa1IntControl = 0;
_pcrCa2Control = 0; _pcrCa2Control = 0;
_pcrCb1IntControl = 0; _pcrCb1IntControl = 0;
_pcrCb2Control = 0; _pcrCb2Control = 0;
_acrPaLatchEnable = false; _acrPaLatchEnable = false;
_acrPbLatchEnable = false; _acrPbLatchEnable = false;
_acrSrControl = 0; _acrSrControl = 0;
_acrT1Control = 0; _acrT1Control = 0;
_acrT2Control = 0; _acrT2Control = 0;
_ca1L = false; _ca1L = false;
_cb1L = false; _cb1L = false;
Ca1 = false; Ca1 = false;
Ca2 = false; Ca2 = false;
Cb1 = false; Cb1 = false;
Cb2 = false; Cb2 = false;
_pb6L = false; _pb6L = false;
_pb6 = false; _pb6 = false;
_resetCa2NextClock = false; _resetCa2NextClock = false;
_resetCb2NextClock = false; _resetCb2NextClock = false;
_handshakeCa2NextClock = false; _handshakeCa2NextClock = false;
_handshakeCb2NextClock = false; _handshakeCb2NextClock = false;
_interruptNextClock = 0; _interruptNextClock = 0;
_t1CLoaded = false; _t1CLoaded = false;
_t2CLoaded = false; _t2CLoaded = false;
} }
public void ExecutePhase() public void ExecutePhase()
{ {
// Process delayed interrupts // Process delayed interrupts
_ifr |= _interruptNextClock; _ifr |= _interruptNextClock;
_interruptNextClock = 0; _interruptNextClock = 0;
// Process 'pulse' and 'handshake' outputs on CA2 and CB2 // Process 'pulse' and 'handshake' outputs on CA2 and CB2
if (_resetCa2NextClock) if (_resetCa2NextClock)
{ {
Ca2 = true; Ca2 = true;
_resetCa2NextClock = false; _resetCa2NextClock = false;
} }
else if (_handshakeCa2NextClock) else if (_handshakeCa2NextClock)
{ {
Ca2 = false; Ca2 = false;
_resetCa2NextClock = _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT; _resetCa2NextClock = _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT;
_handshakeCa2NextClock = false; _handshakeCa2NextClock = false;
} }
if (_resetCb2NextClock) if (_resetCb2NextClock)
{ {
Cb2 = true; Cb2 = true;
_resetCb2NextClock = false; _resetCb2NextClock = false;
} }
else if (_handshakeCb2NextClock) else if (_handshakeCb2NextClock)
{ {
Cb2 = false; Cb2 = false;
_resetCb2NextClock = _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT; _resetCb2NextClock = _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT;
_handshakeCb2NextClock = false; _handshakeCb2NextClock = false;
} }
// Count timers // Count timers
if (_t1Delayed > 0) if (_t1Delayed > 0)
{ {
_t1Delayed--; _t1Delayed--;
} }
else else
{ {
_t1C--; _t1C--;
if (_t1C < 0) if (_t1C < 0)
{ {
if (_t1CLoaded) if (_t1CLoaded)
{ {
_interruptNextClock |= 0x40; _interruptNextClock |= 0x40;
_t1CLoaded = false; _t1CLoaded = false;
} }
switch (_acrT1Control) switch (_acrT1Control)
{ {
case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS: case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS:
_t1C = _t1L; _t1C = _t1L;
_t1CLoaded = true; _t1CLoaded = true;
break; break;
case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7: case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7:
_t1C = _t1L; _t1C = _t1L;
_prb ^= 0x80; _prb ^= 0x80;
_t1CLoaded = true; _t1CLoaded = true;
break; break;
} }
_t1C &= 0xFFFF; _t1C &= 0xFFFF;
} }
} }
if (_t2Delayed > 0) if (_t2Delayed > 0)
{ {
_t2Delayed--; _t2Delayed--;
} }
else else
{ {
switch (_acrT2Control) switch (_acrT2Control)
{ {
case ACR_T2_CONTROL_TIMED: case ACR_T2_CONTROL_TIMED:
_t2C--; _t2C--;
if (_t2C < 0) if (_t2C < 0)
{ {
if (_t2CLoaded) if (_t2CLoaded)
{ {
_interruptNextClock |= 0x20; _interruptNextClock |= 0x20;
_t2CLoaded = false; _t2CLoaded = false;
} }
_t2C = _t2L; _t2C = _t2L;
} }
break; break;
case ACR_T2_CONTROL_COUNT_ON_PB6: case ACR_T2_CONTROL_COUNT_ON_PB6:
_pb6L = _pb6; _pb6L = _pb6;
_pb6 = (_port.ReadExternalPrb() & 0x40) != 0; _pb6 = (_port.ReadExternalPrb() & 0x40) != 0;
if (!_pb6 && _pb6L) if (!_pb6 && _pb6L)
{ {
_t2C--; _t2C--;
if (_t2C < 0) if (_t2C < 0)
{ {
_ifr |= 0x20; _ifr |= 0x20;
_t2C = 0xFFFF; _t2C = 0xFFFF;
} }
} }
break; break;
} }
} }
// Process CA2 // Process CA2
switch (_pcrCa2Control) switch (_pcrCa2Control)
{ {
case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE: case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE:
case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE: case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE:
if (_ca2L && !Ca2) if (_ca2L && !Ca2)
_ifr |= 0x01; _ifr |= 0x01;
break; break;
case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE: case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE:
case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE: case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE:
if (!_ca2L && Ca2) if (!_ca2L && Ca2)
_ifr |= 0x01; _ifr |= 0x01;
break; break;
case PCR_CONTROL_HANDSHAKE_OUTPUT: case PCR_CONTROL_HANDSHAKE_OUTPUT:
if (_ca1L && !Ca1) if (_ca1L && !Ca1)
{ {
Ca2 = true; Ca2 = true;
_ifr |= 0x01; _ifr |= 0x01;
} }
break; break;
case PCR_CONTROL_PULSE_OUTPUT: case PCR_CONTROL_PULSE_OUTPUT:
break; break;
case PCR_CONTROL_LOW_OUTPUT: case PCR_CONTROL_LOW_OUTPUT:
Ca2 = false; Ca2 = false;
break; break;
case PCR_CONTROL_HIGH_OUTPUT: case PCR_CONTROL_HIGH_OUTPUT:
Ca2 = true; Ca2 = true;
break; break;
} }
// Process CB2 // Process CB2
switch (_pcrCb2Control) switch (_pcrCb2Control)
{ {
case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE: case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE:
case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE: case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE:
if (_cb2L && !Cb2) if (_cb2L && !Cb2)
_ifr |= 0x08; _ifr |= 0x08;
break; break;
case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE: case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE:
case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE: case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE:
if (!_cb2L && Cb2) if (!_cb2L && Cb2)
_ifr |= 0x08; _ifr |= 0x08;
break; break;
case PCR_CONTROL_HANDSHAKE_OUTPUT: case PCR_CONTROL_HANDSHAKE_OUTPUT:
if (_cb1L && !Cb1) if (_cb1L && !Cb1)
{ {
Cb2 = true; Cb2 = true;
_ifr |= 0x08; _ifr |= 0x08;
} }
break; break;
case PCR_CONTROL_PULSE_OUTPUT: case PCR_CONTROL_PULSE_OUTPUT:
break; break;
case PCR_CONTROL_LOW_OUTPUT: case PCR_CONTROL_LOW_OUTPUT:
Cb2 = false; Cb2 = false;
break; break;
case PCR_CONTROL_HIGH_OUTPUT: case PCR_CONTROL_HIGH_OUTPUT:
Cb2 = true; Cb2 = true;
break; break;
} }
// interrupt generation // interrupt generation
if ((_pcrCb1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Cb1 && !_cb1L) || if ((_pcrCb1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Cb1 && !_cb1L) ||
(_pcrCb1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Cb1 && _cb1L)) (_pcrCb1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Cb1 && _cb1L))
{ {
_ifr |= 0x10; _ifr |= 0x10;
if (_acrPbLatchEnable) if (_acrPbLatchEnable)
{ {
_pbLatch = _port.ReadExternalPrb(); _pbLatch = _port.ReadExternalPrb();
} }
} }
if ((_pcrCa1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Ca1 && !_ca1L) || if ((_pcrCa1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Ca1 && !_ca1L) ||
(_pcrCa1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Ca1 && _ca1L)) (_pcrCa1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Ca1 && _ca1L))
{ {
_ifr |= 0x02; _ifr |= 0x02;
if (_acrPaLatchEnable) if (_acrPaLatchEnable)
{ {
_paLatch = _port.ReadExternalPra(); _paLatch = _port.ReadExternalPra();
} }
} }
switch (_acrSrControl) switch (_acrSrControl)
{ {
case ACR_SR_CONTROL_DISABLED: case ACR_SR_CONTROL_DISABLED:
_ifr &= 0xFB; _ifr &= 0xFB;
break; break;
default: default:
break; break;
} }
if ((_ifr & _ier & 0x7F) != 0) if ((_ifr & _ier & 0x7F) != 0)
{ {
_ifr |= 0x80; _ifr |= 0x80;
} }
else else
{ {
_ifr &= 0x7F; _ifr &= 0x7F;
} }
_ca1L = Ca1; _ca1L = Ca1;
_ca2L = Ca2; _ca2L = Ca2;
_cb1L = Cb1; _cb1L = Cb1;
_cb2L = Cb2; _cb2L = Cb2;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }

View File

@ -2,37 +2,37 @@
{ {
public sealed partial class Vic public sealed partial class Vic
{ {
private const int BaResetCounter = 4; private const int BaResetCounter = 4;
private const int PipelineUpdateVc = 0x00000001; // vc/rc rule 2 private const int PipelineUpdateVc = 0x00000001; // vc/rc rule 2
private const int PipelineSpriteCrunch = 0x00000002; private const int PipelineSpriteCrunch = 0x00000002;
private const int PipelineUpdateMcBase = 0x00000004; private const int PipelineUpdateMcBase = 0x00000004;
private const int PipelineBorderLeft1 = 0x00000008; private const int PipelineBorderLeft1 = 0x00000008;
private const int PipelineBorderLeft0 = 0x00000010; private const int PipelineBorderLeft0 = 0x00000010;
private const int PipelineSpriteDma = 0x00000020; // sprite rule 3 private const int PipelineSpriteDma = 0x00000020; // sprite rule 3
private const int PipelineBorderRight0 = 0x00000040; private const int PipelineBorderRight0 = 0x00000040;
private const int PipelineSpriteExpansion = 0x00000080; // sprite rule 2 private const int PipelineSpriteExpansion = 0x00000080; // sprite rule 2
private const int PipelineBorderRight1 = 0x00000100; private const int PipelineBorderRight1 = 0x00000100;
private const int PipelineSpriteDisplay = 0x00000200; // sprite rule 4 private const int PipelineSpriteDisplay = 0x00000200; // sprite rule 4
private const int PipelineUpdateRc = 0x00000400; // vc/rc rule 5 private const int PipelineUpdateRc = 0x00000400; // vc/rc rule 5
private const int PipelineHoldX = 0x40000000; private const int PipelineHoldX = 0x40000000;
private const int RasterIrqLine0Cycle = 2; private const int RasterIrqLine0Cycle = 2;
private const int RasterIrqLineXCycle = 1; private const int RasterIrqLineXCycle = 1;
private const int FetchTypeSprite = 0x0000; private const int FetchTypeSprite = 0x0000;
private const int FetchTypeRefresh = 0x0100; private const int FetchTypeRefresh = 0x0100;
private const int FetchTypeColor = 0x0200; private const int FetchTypeColor = 0x0200;
private const int FetchTypeGraphics = 0x0300; private const int FetchTypeGraphics = 0x0300;
private const int FetchTypeIdle = 0x0400; private const int FetchTypeIdle = 0x0400;
private const int FetchTypeNone = 0x0500; private const int FetchTypeNone = 0x0500;
private const int BaTypeNone = 0x0888; private const int BaTypeNone = 0x0888;
private const int BaTypeCharacter = 0x1000; private const int BaTypeCharacter = 0x1000;
private const int BaTypeMaskSprite0 = 0x000F; private const int BaTypeMaskSprite0 = 0x000F;
private const int BaTypeMaskSprite1 = 0x00F0; private const int BaTypeMaskSprite1 = 0x00F0;
private const int BaTypeMaskSprite2 = 0x0F00; private const int BaTypeMaskSprite2 = 0x0F00;
private const int AddressMask = 0x3FFF; private const int AddressMask = 0x3FFF;
private const int AddressMaskEc = 0x39FF; private const int AddressMaskEc = 0x39FF;
private const int AddressMaskRefresh = 0x3F00; private const int AddressMaskRefresh = 0x3F00;
[SaveState.DoNotSave] private int _parseAddr; [SaveState.DoNotSave] private int _parseAddr;
[SaveState.DoNotSave] private int _parseCycleBaSprite0; [SaveState.DoNotSave] private int _parseCycleBaSprite0;
[SaveState.DoNotSave] private int _parseCycleBaSprite1; [SaveState.DoNotSave] private int _parseCycleBaSprite1;
[SaveState.DoNotSave] private int _parseCycleBaSprite2; [SaveState.DoNotSave] private int _parseCycleBaSprite2;
@ -41,11 +41,11 @@
[SaveState.DoNotSave] private int _parseFetchType; [SaveState.DoNotSave] private int _parseFetchType;
[SaveState.DoNotSave] private int _parseBa; [SaveState.DoNotSave] private int _parseBa;
[SaveState.DoNotSave] private int _parseAct; [SaveState.DoNotSave] private int _parseAct;
private bool _parseIsSprCrunch; private bool _parseIsSprCrunch;
private void ParseCycle() private void ParseCycle()
{ {
// initialization // initialization
_parseAddr = AddressMask; _parseAddr = AddressMask;
_parseFetch = _fetchPipeline[_cycleIndex]; _parseFetch = _fetchPipeline[_cycleIndex];
_parseBa = _baPipeline[_cycleIndex]; _parseBa = _baPipeline[_cycleIndex];
@ -59,89 +59,89 @@
_parseFetchType = _parseFetch & 0xFF00; _parseFetchType = _parseFetch & 0xFF00;
switch (_parseFetchType) switch (_parseFetchType)
{ {
case FetchTypeColor: case FetchTypeColor:
// fetch C // fetch C
if (!_idle) if (!_idle)
{ {
if (_badline) if (_badline)
{ {
_parseAddr = _pointerVm | _vc; _parseAddr = _pointerVm | _vc;
_dataC = ReadMemory(_parseAddr); _dataC = ReadMemory(_parseAddr);
_dataC |= (ReadColorRam(_parseAddr) & 0xF) << 8; _dataC |= (ReadColorRam(_parseAddr) & 0xF) << 8;
_bufferC[_vmli] = _dataC; _bufferC[_vmli] = _dataC;
} }
else else
{ {
_dataC = _bufferC[_vmli]; _dataC = _bufferC[_vmli];
} }
} }
else else
{ {
_dataC = 0; _dataC = 0;
_bufferC[_vmli] = _dataC; _bufferC[_vmli] = _dataC;
} }
_srColorSync |= 0x01 << (7 - _xScroll); _srColorSync |= 0x01 << (7 - _xScroll);
break; break;
case FetchTypeGraphics: case FetchTypeGraphics:
// fetch G // fetch G
if (!_idle) if (!_idle)
{ {
if (_bitmapMode) if (_bitmapMode)
_parseAddr = _rc | (_vc << 3) | ((_pointerCb & 0x4) << 11); _parseAddr = _rc | (_vc << 3) | ((_pointerCb & 0x4) << 11);
else else
_parseAddr = _rc | ((_dataC & 0xFF) << 3) | (_pointerCb << 11); _parseAddr = _rc | ((_dataC & 0xFF) << 3) | (_pointerCb << 11);
} }
if (_extraColorModeBuffer) if (_extraColorModeBuffer)
_parseAddr &= AddressMaskEc; _parseAddr &= AddressMaskEc;
_dataG = ReadMemory(_parseAddr); _dataG = ReadMemory(_parseAddr);
_sr |= _dataG << (7 - _xScroll); _sr |= _dataG << (7 - _xScroll);
_srSync |= 0xAA << (7 - _xScroll); _srSync |= 0xAA << (7 - _xScroll);
if (!_idle) if (!_idle)
{ {
_bufferG[_vmli] = _dataG; _bufferG[_vmli] = _dataG;
_vmli = (_vmli + 1) & 0x3F; _vmli = (_vmli + 1) & 0x3F;
_vc = (_vc + 1) & 0x3FF; _vc = (_vc + 1) & 0x3FF;
} }
break; break;
case FetchTypeNone: case FetchTypeNone:
// fetch none // fetch none
break; break;
case FetchTypeRefresh: case FetchTypeRefresh:
// fetch R // fetch R
_refreshCounter = (_refreshCounter - 1) & 0xFF; _refreshCounter = (_refreshCounter - 1) & 0xFF;
_parseAddr = AddressMaskRefresh | _refreshCounter; _parseAddr = AddressMaskRefresh | _refreshCounter;
ReadMemory(_parseAddr); ReadMemory(_parseAddr);
break; break;
case FetchTypeIdle: case FetchTypeIdle:
// fetch I // fetch I
ReadMemory(AddressMask); ReadMemory(AddressMask);
break; break;
default: default:
_parseCycleFetchSpriteIndex = _parseFetch & 0x7; _parseCycleFetchSpriteIndex = _parseFetch & 0x7;
if ((_parseFetch & 0xF0) == 0) // sprite rule 5 if ((_parseFetch & 0xF0) == 0) // sprite rule 5
{ {
// fetch P // fetch P
_parseAddr = 0x3F8 | _pointerVm | _parseCycleFetchSpriteIndex; _parseAddr = 0x3F8 | _pointerVm | _parseCycleFetchSpriteIndex;
_sprites[_parseCycleFetchSpriteIndex].Pointer = ReadMemory(_parseAddr); _sprites[_parseCycleFetchSpriteIndex].Pointer = ReadMemory(_parseAddr);
_sprites[_parseCycleFetchSpriteIndex].ShiftEnable = false; _sprites[_parseCycleFetchSpriteIndex].ShiftEnable = false;
} }
else else
{ {
// fetch S // fetch S
var spr = _sprites[_parseCycleFetchSpriteIndex]; var spr = _sprites[_parseCycleFetchSpriteIndex];
if (spr.Dma) if (spr.Dma)
{ {
_parseAddr = spr.Mc | (spr.Pointer << 6); _parseAddr = spr.Mc | (spr.Pointer << 6);
spr.Sr |= ReadMemory(_parseAddr) << ((0x30 - (_parseFetch & 0x30)) >> 1); spr.Sr |= ReadMemory(_parseAddr) << ((0x30 - (_parseFetch & 0x30)) >> 1);
spr.Mc++; spr.Mc++;
spr.Loaded |= 0x800000; spr.Loaded |= 0x800000;
} }
else if ((_parseFetch & 0xF0) == 0x20) else if ((_parseFetch & 0xF0) == 0x20)
{ {
ReadMemory(AddressMask); ReadMemory(AddressMask);
} }
} }
break; break;
} }
// perform actions // perform actions
@ -154,22 +154,22 @@
spr.YCrunch = true; spr.YCrunch = true;
} }
if ((_parseAct & PipelineUpdateMcBase) != 0) // VIC addendum sprite rule 7 if ((_parseAct & PipelineUpdateMcBase) != 0) // VIC addendum sprite rule 7
{ {
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
if (spr.YCrunch) if (spr.YCrunch)
{ {
spr.Mcbase = spr.Mc; spr.Mcbase = spr.Mc;
if (spr.Mcbase == 63) if (spr.Mcbase == 63)
{ {
spr.Dma = false; spr.Dma = false;
} }
} }
} }
} }
if ((_parseAct & PipelineSpriteDma) != 0) // sprite rule 3 if ((_parseAct & PipelineSpriteDma) != 0) // sprite rule 3
{ {
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
@ -182,24 +182,24 @@
} }
} }
if ((_parseAct & PipelineSpriteExpansion) != 0) // sprite rule 2 if ((_parseAct & PipelineSpriteExpansion) != 0) // sprite rule 2
{ {
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
if (spr.Dma && spr.YExpand) if (spr.Dma && spr.YExpand)
spr.YCrunch ^= true; spr.YCrunch ^= true;
} }
} }
if ((_parseAct & PipelineSpriteDisplay) != 0) // VIC addendum on sprite rule 4 if ((_parseAct & PipelineSpriteDisplay) != 0) // VIC addendum on sprite rule 4
{ {
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
spr.Mc = spr.Mcbase; spr.Mc = spr.Mcbase;
if (spr.Dma) if (spr.Dma)
{ {
if (spr.Enable && spr.Y == (_rasterLine & 0xFF)) if (spr.Enable && spr.Y == (_rasterLine & 0xFF))
spr.Display = true; spr.Display = true;
} }
else else
{ {
@ -208,52 +208,52 @@
} }
} }
_parseIsSprCrunch = (_parseAct & PipelineSpriteCrunch) != 0; // VIC addendum sprite rule 7 _parseIsSprCrunch = (_parseAct & PipelineSpriteCrunch) != 0; // VIC addendum sprite rule 7
if ((_parseAct & PipelineUpdateVc) != 0) // VC/RC rule 2 if ((_parseAct & PipelineUpdateVc) != 0) // VC/RC rule 2
{ {
_vc = _vcbase; _vc = _vcbase;
_srColorIndexLatch = 0; _srColorIndexLatch = 0;
_vmli = 0; _vmli = 0;
if (_badline) if (_badline)
_rc = 0; _rc = 0;
} }
if ((_parseAct & PipelineUpdateRc) != 0) // VC/RC rule 5 if ((_parseAct & PipelineUpdateRc) != 0) // VC/RC rule 5
{ {
if (_rc == 7) if (_rc == 7)
{ {
_idle = true; _idle = true;
_vcbase = _vc; _vcbase = _vc;
} }
if (!_idle || _badline) if (!_idle || _badline)
{ {
_rc = (_rc + 1) & 0x7; _rc = (_rc + 1) & 0x7;
_idle = false; _idle = false;
} }
} }
// perform BA flag manipulation // perform BA flag manipulation
_pinBa = true; _pinBa = true;
switch (_parseBa) switch (_parseBa)
{ {
case BaTypeNone: case BaTypeNone:
break; break;
case BaTypeCharacter: case BaTypeCharacter:
_pinBa = !_badline; _pinBa = !_badline;
break; break;
default: default:
_parseCycleBaSprite0 = _parseBa & BaTypeMaskSprite0; _parseCycleBaSprite0 = _parseBa & BaTypeMaskSprite0;
_parseCycleBaSprite1 = (_parseBa & BaTypeMaskSprite1) >> 4; _parseCycleBaSprite1 = (_parseBa & BaTypeMaskSprite1) >> 4;
_parseCycleBaSprite2 = (_parseBa & BaTypeMaskSprite2) >> 8; _parseCycleBaSprite2 = (_parseBa & BaTypeMaskSprite2) >> 8;
if ((_parseCycleBaSprite0 < 8 && _sprites[_parseCycleBaSprite0].Dma) || if ((_parseCycleBaSprite0 < 8 && _sprites[_parseCycleBaSprite0].Dma) ||
(_parseCycleBaSprite1 < 8 && _sprites[_parseCycleBaSprite1].Dma) || (_parseCycleBaSprite1 < 8 && _sprites[_parseCycleBaSprite1].Dma) ||
(_parseCycleBaSprite2 < 8 && _sprites[_parseCycleBaSprite2].Dma)) (_parseCycleBaSprite2 < 8 && _sprites[_parseCycleBaSprite2].Dma))
_pinBa = false; _pinBa = false;
break; break;
} }
_cycleIndex++; _cycleIndex++;
} }
} }
} }

View File

@ -19,10 +19,10 @@
switch (addr) switch (addr)
{ {
case 0x1E: case 0x1E:
_spriteSpriteCollisionClearPending = true; _spriteSpriteCollisionClearPending = true;
return ReadRegister(addr); return ReadRegister(addr);
case 0x1F: case 0x1F:
_spriteBackgroundCollisionClearPending = true; _spriteBackgroundCollisionClearPending = true;
return ReadRegister(addr); return ReadRegister(addr);
default: default:
return ReadRegister(addr); return ReadRegister(addr);
@ -53,20 +53,20 @@
return _sprites[addr >> 1].Y & 0xFF; return _sprites[addr >> 1].Y & 0xFF;
case 0x10: case 0x10:
return ((_sprite0.X >> 8) & 0x01) | return ((_sprite0.X >> 8) & 0x01) |
((_sprite1.X >> 7) & 0x02) | ((_sprite1.X >> 7) & 0x02) |
((_sprite2.X >> 6) & 0x04) | ((_sprite2.X >> 6) & 0x04) |
((_sprite3.X >> 5) & 0x08) | ((_sprite3.X >> 5) & 0x08) |
((_sprite4.X >> 4) & 0x10) | ((_sprite4.X >> 4) & 0x10) |
((_sprite5.X >> 3) & 0x20) | ((_sprite5.X >> 3) & 0x20) |
((_sprite6.X >> 2) & 0x40) | ((_sprite6.X >> 2) & 0x40) |
((_sprite7.X >> 1) & 0x80); ((_sprite7.X >> 1) & 0x80);
case 0x11: case 0x11:
return (_yScroll & 0x7) | return (_yScroll & 0x7) |
(_rowSelect ? 0x08 : 0x00) | (_rowSelect ? 0x08 : 0x00) |
(_displayEnable ? 0x10 : 0x00) | (_displayEnable ? 0x10 : 0x00) |
(_bitmapMode ? 0x20 : 0x00) | (_bitmapMode ? 0x20 : 0x00) |
(_extraColorMode ? 0x40 : 0x00) | (_extraColorMode ? 0x40 : 0x00) |
((_rasterLine & 0x100) >> 1); ((_rasterLine & 0x100) >> 1);
case 0x12: case 0x12:
return _rasterLine & 0xFF; return _rasterLine & 0xFF;
case 0x13: case 0x13:
@ -75,99 +75,99 @@
return _lightPenY & 0xFF; return _lightPenY & 0xFF;
case 0x15: case 0x15:
return (_sprite0.Enable ? 0x01 : 0x00) | return (_sprite0.Enable ? 0x01 : 0x00) |
(_sprite1.Enable ? 0x02 : 0x00) | (_sprite1.Enable ? 0x02 : 0x00) |
(_sprite2.Enable ? 0x04 : 0x00) | (_sprite2.Enable ? 0x04 : 0x00) |
(_sprite3.Enable ? 0x08 : 0x00) | (_sprite3.Enable ? 0x08 : 0x00) |
(_sprite4.Enable ? 0x10 : 0x00) | (_sprite4.Enable ? 0x10 : 0x00) |
(_sprite5.Enable ? 0x20 : 0x00) | (_sprite5.Enable ? 0x20 : 0x00) |
(_sprite6.Enable ? 0x40 : 0x00) | (_sprite6.Enable ? 0x40 : 0x00) |
(_sprite7.Enable ? 0x80 : 0x00); (_sprite7.Enable ? 0x80 : 0x00);
case 0x16: case 0x16:
return 0xC0 | (_xScroll & 0x7) | return 0xC0 | (_xScroll & 0x7) |
(_columnSelect ? 0x08 : 0x00) | (_columnSelect ? 0x08 : 0x00) |
(_multicolorMode ? 0x10 : 0x00); (_multicolorMode ? 0x10 : 0x00);
case 0x17: case 0x17:
return (_sprite0.YExpand ? 0x01 : 0x00) | return (_sprite0.YExpand ? 0x01 : 0x00) |
(_sprite1.YExpand ? 0x02 : 0x00) | (_sprite1.YExpand ? 0x02 : 0x00) |
(_sprite2.YExpand ? 0x04 : 0x00) | (_sprite2.YExpand ? 0x04 : 0x00) |
(_sprite3.YExpand ? 0x08 : 0x00) | (_sprite3.YExpand ? 0x08 : 0x00) |
(_sprite4.YExpand ? 0x10 : 0x00) | (_sprite4.YExpand ? 0x10 : 0x00) |
(_sprite5.YExpand ? 0x20 : 0x00) | (_sprite5.YExpand ? 0x20 : 0x00) |
(_sprite6.YExpand ? 0x40 : 0x00) | (_sprite6.YExpand ? 0x40 : 0x00) |
(_sprite7.YExpand ? 0x80 : 0x00); (_sprite7.YExpand ? 0x80 : 0x00);
case 0x18: case 0x18:
return 0x01 | ((_pointerVm & 0x3C00) >> 6) | return 0x01 | ((_pointerVm & 0x3C00) >> 6) |
((_pointerCb & 0x7) << 1); ((_pointerCb & 0x7) << 1);
case 0x19: case 0x19:
return 0x70 | (_intRaster ? 0x01 : 0x00) | return 0x70 | (_intRaster ? 0x01 : 0x00) |
(_intSpriteDataCollision ? 0x02 : 0x00) | (_intSpriteDataCollision ? 0x02 : 0x00) |
(_intSpriteCollision ? 0x04 : 0x00) | (_intSpriteCollision ? 0x04 : 0x00) |
(_intLightPen ? 0x08 : 0x00) | (_intLightPen ? 0x08 : 0x00) |
(_pinIrq ? 0x00 : 0x80); (_pinIrq ? 0x00 : 0x80);
case 0x1A: case 0x1A:
return 0xF0 | (_enableIntRaster ? 0x01 : 0x00) | return 0xF0 | (_enableIntRaster ? 0x01 : 0x00) |
(_enableIntSpriteDataCollision ? 0x02 : 0x00) | (_enableIntSpriteDataCollision ? 0x02 : 0x00) |
(_enableIntSpriteCollision ? 0x04 : 0x00) | (_enableIntSpriteCollision ? 0x04 : 0x00) |
(_enableIntLightPen ? 0x08 : 0x00); (_enableIntLightPen ? 0x08 : 0x00);
case 0x1B: case 0x1B:
return (_sprite0.Priority ? 0x01 : 0x00) | return (_sprite0.Priority ? 0x01 : 0x00) |
(_sprite1.Priority ? 0x02 : 0x00) | (_sprite1.Priority ? 0x02 : 0x00) |
(_sprite2.Priority ? 0x04 : 0x00) | (_sprite2.Priority ? 0x04 : 0x00) |
(_sprite3.Priority ? 0x08 : 0x00) | (_sprite3.Priority ? 0x08 : 0x00) |
(_sprite4.Priority ? 0x10 : 0x00) | (_sprite4.Priority ? 0x10 : 0x00) |
(_sprite5.Priority ? 0x20 : 0x00) | (_sprite5.Priority ? 0x20 : 0x00) |
(_sprite6.Priority ? 0x40 : 0x00) | (_sprite6.Priority ? 0x40 : 0x00) |
(_sprite7.Priority ? 0x80 : 0x00); (_sprite7.Priority ? 0x80 : 0x00);
case 0x1C: case 0x1C:
return (_sprite0.Multicolor ? 0x01 : 0x00) | return (_sprite0.Multicolor ? 0x01 : 0x00) |
(_sprite1.Multicolor ? 0x02 : 0x00) | (_sprite1.Multicolor ? 0x02 : 0x00) |
(_sprite2.Multicolor ? 0x04 : 0x00) | (_sprite2.Multicolor ? 0x04 : 0x00) |
(_sprite3.Multicolor ? 0x08 : 0x00) | (_sprite3.Multicolor ? 0x08 : 0x00) |
(_sprite4.Multicolor ? 0x10 : 0x00) | (_sprite4.Multicolor ? 0x10 : 0x00) |
(_sprite5.Multicolor ? 0x20 : 0x00) | (_sprite5.Multicolor ? 0x20 : 0x00) |
(_sprite6.Multicolor ? 0x40 : 0x00) | (_sprite6.Multicolor ? 0x40 : 0x00) |
(_sprite7.Multicolor ? 0x80 : 0x00); (_sprite7.Multicolor ? 0x80 : 0x00);
case 0x1D: case 0x1D:
return (_sprite0.XExpand ? 0x01 : 0x00) | return (_sprite0.XExpand ? 0x01 : 0x00) |
(_sprite1.XExpand ? 0x02 : 0x00) | (_sprite1.XExpand ? 0x02 : 0x00) |
(_sprite2.XExpand ? 0x04 : 0x00) | (_sprite2.XExpand ? 0x04 : 0x00) |
(_sprite3.XExpand ? 0x08 : 0x00) | (_sprite3.XExpand ? 0x08 : 0x00) |
(_sprite4.XExpand ? 0x10 : 0x00) | (_sprite4.XExpand ? 0x10 : 0x00) |
(_sprite5.XExpand ? 0x20 : 0x00) | (_sprite5.XExpand ? 0x20 : 0x00) |
(_sprite6.XExpand ? 0x40 : 0x00) | (_sprite6.XExpand ? 0x40 : 0x00) |
(_sprite7.XExpand ? 0x80 : 0x00); (_sprite7.XExpand ? 0x80 : 0x00);
case 0x1E: case 0x1E:
return (_sprite0.CollideSprite ? 0x01 : 0x00) | return (_sprite0.CollideSprite ? 0x01 : 0x00) |
(_sprite1.CollideSprite ? 0x02 : 0x00) | (_sprite1.CollideSprite ? 0x02 : 0x00) |
(_sprite2.CollideSprite ? 0x04 : 0x00) | (_sprite2.CollideSprite ? 0x04 : 0x00) |
(_sprite3.CollideSprite ? 0x08 : 0x00) | (_sprite3.CollideSprite ? 0x08 : 0x00) |
(_sprite4.CollideSprite ? 0x10 : 0x00) | (_sprite4.CollideSprite ? 0x10 : 0x00) |
(_sprite5.CollideSprite ? 0x20 : 0x00) | (_sprite5.CollideSprite ? 0x20 : 0x00) |
(_sprite6.CollideSprite ? 0x40 : 0x00) | (_sprite6.CollideSprite ? 0x40 : 0x00) |
(_sprite7.CollideSprite ? 0x80 : 0x00); (_sprite7.CollideSprite ? 0x80 : 0x00);
case 0x1F: case 0x1F:
return (_sprite0.CollideData ? 0x01 : 0x00) | return (_sprite0.CollideData ? 0x01 : 0x00) |
(_sprite1.CollideData ? 0x02 : 0x00) | (_sprite1.CollideData ? 0x02 : 0x00) |
(_sprite2.CollideData ? 0x04 : 0x00) | (_sprite2.CollideData ? 0x04 : 0x00) |
(_sprite3.CollideData ? 0x08 : 0x00) | (_sprite3.CollideData ? 0x08 : 0x00) |
(_sprite4.CollideData ? 0x10 : 0x00) | (_sprite4.CollideData ? 0x10 : 0x00) |
(_sprite5.CollideData ? 0x20 : 0x00) | (_sprite5.CollideData ? 0x20 : 0x00) |
(_sprite6.CollideData ? 0x40 : 0x00) | (_sprite6.CollideData ? 0x40 : 0x00) |
(_sprite7.CollideData ? 0x80 : 0x00); (_sprite7.CollideData ? 0x80 : 0x00);
case 0x20: case 0x20:
return 0xF0 | _borderColor & 0x0F; return 0xF0 | _borderColor & 0x0F;
case 0x21: case 0x21:
return 0xF0 | _backgroundColor0 & 0x0F; return 0xF0 | _backgroundColor0 & 0x0F;
case 0x22: case 0x22:
return 0xF0 | _backgroundColor1 & 0x0F; return 0xF0 | _backgroundColor1 & 0x0F;
case 0x23: case 0x23:
return 0xF0 | _backgroundColor2 & 0x0F; return 0xF0 | _backgroundColor2 & 0x0F;
case 0x24: case 0x24:
return 0xF0 | _backgroundColor3 & 0x0F; return 0xF0 | _backgroundColor3 & 0x0F;
case 0x25: case 0x25:
return 0xF0 | _spriteMulticolor0 & 0x0F; return 0xF0 | _spriteMulticolor0 & 0x0F;
case 0x26: case 0x26:
return 0xF0 | _spriteMulticolor1 & 0x0F; return 0xF0 | _spriteMulticolor1 & 0x0F;
case 0x27: case 0x27:
case 0x28: case 0x28:
case 0x29: case 0x29:
@ -177,8 +177,8 @@
case 0x2D: case 0x2D:
case 0x2E: case 0x2E:
return 0xF0 | _sprites[addr - 0x27].Color & 0xF; return 0xF0 | _sprites[addr - 0x27].Color & 0xF;
default: default:
return 0xFF; return 0xFF;
} }
} }
@ -187,21 +187,21 @@
addr &= 0x3F; addr &= 0x3F;
switch (addr) switch (addr)
{ {
case 0x17: case 0x17:
// vic-ii addendum rule 7 // vic-ii addendum rule 7
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
if ((val & 1) == 0 && !spr.YCrunch) if ((val & 1) == 0 && !spr.YCrunch)
{ {
if (_parseIsSprCrunch) if (_parseIsSprCrunch)
{ {
spr.Mc = (0x2a & spr.Mcbase & spr.Mc) | (0x15 & (spr.Mcbase | spr.Mc)); spr.Mc = (0x2a & spr.Mcbase & spr.Mc) | (0x15 & (spr.Mcbase | spr.Mc));
} }
spr.YCrunch = true; spr.YCrunch = true;
} }
} }
WriteRegister(addr, val); WriteRegister(addr, val);
break; break;
case 0x19: case 0x19:
// interrupts are cleared by writing a 1 // interrupts are cleared by writing a 1
if ((val & 0x01) != 0) if ((val & 0x01) != 0)

View File

@ -2,9 +2,9 @@
{ {
public sealed partial class Vic public sealed partial class Vic
{ {
[SaveState.DoNotSave] private int _borderPixel; [SaveState.DoNotSave] private int _borderPixel;
[SaveState.DoNotSave] private int _bufferPixel; [SaveState.DoNotSave] private int _bufferPixel;
[SaveState.DoNotSave] private int _ecmPixel; [SaveState.DoNotSave] private int _ecmPixel;
[SaveState.DoNotSave] private int _pixel; [SaveState.DoNotSave] private int _pixel;
[SaveState.DoNotSave] private int _pixelCounter; [SaveState.DoNotSave] private int _pixelCounter;
[SaveState.DoNotSave] private int _pixelData; [SaveState.DoNotSave] private int _pixelData;
@ -12,51 +12,51 @@
[SaveState.DoNotSave] private int _sprData; [SaveState.DoNotSave] private int _sprData;
[SaveState.DoNotSave] private int _sprIndex; [SaveState.DoNotSave] private int _sprIndex;
[SaveState.DoNotSave] private int _sprPixel; [SaveState.DoNotSave] private int _sprPixel;
private int _srSync; private int _srSync;
private int _srColorSync; private int _srColorSync;
private int _srColorIndexLatch; private int _srColorIndexLatch;
private int _videoMode; private int _videoMode;
private int _borderOnShiftReg; private int _borderOnShiftReg;
[SaveState.DoNotSave] private const int VideoMode000 = 0; [SaveState.DoNotSave] private const int VideoMode000 = 0;
[SaveState.DoNotSave] private const int VideoMode001 = 1; [SaveState.DoNotSave] private const int VideoMode001 = 1;
[SaveState.DoNotSave] private const int VideoMode010 = 2; [SaveState.DoNotSave] private const int VideoMode010 = 2;
[SaveState.DoNotSave] private const int VideoMode011 = 3; [SaveState.DoNotSave] private const int VideoMode011 = 3;
[SaveState.DoNotSave] private const int VideoMode100 = 4; [SaveState.DoNotSave] private const int VideoMode100 = 4;
[SaveState.DoNotSave] private const int VideoModeInvalid = -1; [SaveState.DoNotSave] private const int VideoModeInvalid = -1;
[SaveState.DoNotSave] private const int SrMask1 = 0x20000; [SaveState.DoNotSave] private const int SrMask1 = 0x20000;
[SaveState.DoNotSave] private const int SrMask2 = SrMask1 << 1; [SaveState.DoNotSave] private const int SrMask2 = SrMask1 << 1;
[SaveState.DoNotSave] private const int SrMask3 = SrMask1 | SrMask2; [SaveState.DoNotSave] private const int SrMask3 = SrMask1 | SrMask2;
[SaveState.DoNotSave] private const int SrColorMask = 0x8000; [SaveState.DoNotSave] private const int SrColorMask = 0x8000;
[SaveState.DoNotSave] private const int SrSpriteMask = SrSpriteMask2; [SaveState.DoNotSave] private const int SrSpriteMask = SrSpriteMask2;
[SaveState.DoNotSave] private const int SrSpriteMask1 = 0x400000; [SaveState.DoNotSave] private const int SrSpriteMask1 = 0x400000;
[SaveState.DoNotSave] private const int SrSpriteMask2 = SrSpriteMask1 << 1; [SaveState.DoNotSave] private const int SrSpriteMask2 = SrSpriteMask1 << 1;
[SaveState.DoNotSave] private const int SrSpriteMask3 = SrSpriteMask1 | SrSpriteMask2; [SaveState.DoNotSave] private const int SrSpriteMask3 = SrSpriteMask1 | SrSpriteMask2;
[SaveState.DoNotSave] private const int SrSpriteMaskMc = SrSpriteMask3; [SaveState.DoNotSave] private const int SrSpriteMaskMc = SrSpriteMask3;
private void Render() private void Render()
{ {
if (_rasterX == _hblankEndCheckXRaster) if (_rasterX == _hblankEndCheckXRaster)
_hblank = false; _hblank = false;
if (_rasterX == _hblankStartCheckXRaster) if (_rasterX == _hblankStartCheckXRaster)
_hblank = true; _hblank = true;
_renderEnabled = !_hblank && !_vblank; _renderEnabled = !_hblank && !_vblank;
_pixelCounter = -1; _pixelCounter = -1;
while (_pixelCounter++ < 3) while (_pixelCounter++ < 3)
{ {
if ((_srColorSync & SrColorMask) != 0) if ((_srColorSync & SrColorMask) != 0)
{ {
_displayC = _bufferC[_srColorIndexLatch]; _displayC = _bufferC[_srColorIndexLatch];
_srColorIndexLatch = (_srColorIndexLatch + 1) & 0x3F; _srColorIndexLatch = (_srColorIndexLatch + 1) & 0x3F;
} }
#region PRE-RENDER BORDER #region PRE-RENDER BORDER
// check left border // check left border
if (_borderCheckLEnable && (_rasterX == _borderL)) if (_borderCheckLEnable && (_rasterX == _borderL))
{ {
if (_rasterLine == _borderB) if (_rasterLine == _borderB)
_borderOnVertical = true; _borderOnVertical = true;
@ -66,14 +66,14 @@
_borderOnMain = false; _borderOnMain = false;
} }
// check right border // check right border
if (_borderCheckREnable && (_rasterX == _borderR)) if (_borderCheckREnable && (_rasterX == _borderR))
_borderOnMain = true; _borderOnMain = true;
#endregion #endregion
#region CHARACTER GRAPHICS #region CHARACTER GRAPHICS
switch (_videoMode) switch (_videoMode)
{ {
case VideoMode000: case VideoMode000:
_pixelData = _sr & SrMask2; _pixelData = _sr & SrMask2;
@ -82,25 +82,25 @@
case VideoMode001: case VideoMode001:
if ((_displayC & 0x800) != 0) if ((_displayC & 0x800) != 0)
{ {
// multicolor 001 // multicolor 001
if ((_srSync & SrMask2) != 0) if ((_srSync & SrMask2) != 0)
_pixelData = _sr & SrMask3; _pixelData = _sr & SrMask3;
switch (_pixelData) switch (_pixelData)
{ {
case 0: case 0:
_pixel = _backgroundColor0; _pixel = _backgroundColor0;
break; break;
case SrMask1: case SrMask1:
_pixel = _backgroundColor1; _pixel = _backgroundColor1;
break; break;
case SrMask2: case SrMask2:
_pixel = _backgroundColor2; _pixel = _backgroundColor2;
break; break;
default: default:
_pixel = (_displayC & 0x700) >> 8; _pixel = (_displayC & 0x700) >> 8;
break; break;
} }
} }
else else
{ {
@ -119,18 +119,18 @@
switch (_pixelData) switch (_pixelData)
{ {
case 0: case 0:
_pixel = _backgroundColor0; _pixel = _backgroundColor0;
break; break;
case SrMask1: case SrMask1:
_pixel = _displayC >> 4; _pixel = _displayC >> 4;
break; break;
case SrMask2: case SrMask2:
_pixel = _displayC; _pixel = _displayC;
break; break;
default: default:
_pixel = _displayC >> 8; _pixel = _displayC >> 8;
break; break;
} }
break; break;
case VideoMode100: case VideoMode100:
@ -141,24 +141,24 @@
} }
else else
{ {
_ecmPixel = (_displayC & 0xC0) >> 6; _ecmPixel = (_displayC & 0xC0) >> 6;
switch (_ecmPixel) switch (_ecmPixel)
{ {
case 0: case 0:
_pixel = _backgroundColor0; _pixel = _backgroundColor0;
break; break;
case 1: case 1:
_pixel = _backgroundColor1; _pixel = _backgroundColor1;
break; break;
case 2: case 2:
_pixel = _backgroundColor2; _pixel = _backgroundColor2;
break; break;
default: default:
_pixel = _backgroundColor3; _pixel = _backgroundColor3;
break; break;
} }
} }
break; break;
default: default:
_pixelData = 0; _pixelData = 0;
_pixel = 0; _pixel = 0;
@ -167,12 +167,12 @@
_pixel &= 0xF; _pixel &= 0xF;
_sr <<= 1; _sr <<= 1;
_srSync <<= 1; _srSync <<= 1;
_srColorSync <<= 1; _srColorSync <<= 1;
#endregion #endregion
#region SPRITES #region SPRITES
// render sprites // render sprites
_pixelOwner = -1; _pixelOwner = -1;
_sprIndex = 0; _sprIndex = 0;
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
@ -226,19 +226,19 @@
// sprite-sprite collision // sprite-sprite collision
if (_pixelOwner < 0) if (_pixelOwner < 0)
{ {
switch (_sprData) switch (_sprData)
{ {
case SrSpriteMask1: case SrSpriteMask1:
_sprPixel = _spriteMulticolor0; _sprPixel = _spriteMulticolor0;
break; break;
case SrSpriteMask2: case SrSpriteMask2:
_sprPixel = spr.Color; _sprPixel = spr.Color;
break; break;
case SrSpriteMask3: case SrSpriteMask3:
_sprPixel = _spriteMulticolor1; _sprPixel = _spriteMulticolor1;
break; break;
} }
_pixelOwner = _sprIndex; _pixelOwner = _sprIndex;
} }
else else
{ {
@ -270,38 +270,38 @@
_sprIndex++; _sprIndex++;
} }
#endregion #endregion
#region POST-RENDER BORDER #region POST-RENDER BORDER
// border doesn't work with the background buffer // border doesn't work with the background buffer
_borderPixel = _pixBorderBuffer[_pixBufferBorderIndex]; _borderPixel = _pixBorderBuffer[_pixBufferBorderIndex];
_pixBorderBuffer[_pixBufferBorderIndex] = _borderColor; _pixBorderBuffer[_pixBufferBorderIndex] = _borderColor;
#endregion #endregion
// plot pixel if within viewing area // plot pixel if within viewing area
if (_renderEnabled) if (_renderEnabled)
{ {
_bufferPixel = (_borderOnShiftReg & 0x80000) != 0 ? _borderPixel : _pixBuffer[_pixBufferIndex]; _bufferPixel = (_borderOnShiftReg & 0x80000) != 0 ? _borderPixel : _pixBuffer[_pixBufferIndex];
_buf[_bufOffset] = Palette[_bufferPixel]; _buf[_bufOffset] = Palette[_bufferPixel];
_bufOffset++; _bufOffset++;
if (_bufOffset == _bufLength) if (_bufOffset == _bufLength)
_bufOffset = 0; _bufOffset = 0;
} }
_borderOnShiftReg <<= 1; _borderOnShiftReg <<= 1;
_borderOnShiftReg |= (_borderOnVertical || _borderOnMain) ? 1 : 0; _borderOnShiftReg |= (_borderOnVertical || _borderOnMain) ? 1 : 0;
_pixBuffer[_pixBufferIndex] = _pixel; _pixBuffer[_pixBufferIndex] = _pixel;
_pixBufferIndex++; _pixBufferIndex++;
_pixBufferBorderIndex++; _pixBufferBorderIndex++;
if (!_rasterXHold) if (!_rasterXHold)
_rasterX++; _rasterX++;
} }
if (_pixBufferBorderIndex >= PixBorderBufferSize) if (_pixBufferBorderIndex >= PixBorderBufferSize)
_pixBufferBorderIndex = 0; _pixBufferBorderIndex = 0;
if (_pixBufferIndex >= PixBufferSize) if (_pixBufferIndex >= PixBufferSize)
_pixBufferIndex = 0; _pixBufferIndex = 0;
} }
} }

View File

@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private int _baCount; private int _baCount;
private bool _badline; private bool _badline;
private bool _badlineEnable; private bool _badlineEnable;
private bool _bitmapMode; private bool _bitmapMode;
private int _borderB; private int _borderB;
private bool _borderCheckLEnable; private bool _borderCheckLEnable;
private bool _borderCheckREnable; private bool _borderCheckREnable;
@ -36,19 +36,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private int _dataG; private int _dataG;
private bool _displayEnable; private bool _displayEnable;
private int _displayC; private int _displayC;
private bool _enableIntLightPen; private bool _enableIntLightPen;
private bool _enableIntRaster; private bool _enableIntRaster;
private bool _enableIntSpriteCollision; private bool _enableIntSpriteCollision;
private bool _enableIntSpriteDataCollision; private bool _enableIntSpriteDataCollision;
private bool _extraColorMode; private bool _extraColorMode;
private bool _extraColorModeBuffer; private bool _extraColorModeBuffer;
[SaveState.DoNotSave] private bool _hblank; [SaveState.DoNotSave] private bool _hblank;
private bool _idle; private bool _idle;
private bool _intLightPen; private bool _intLightPen;
private bool _intRaster; private bool _intRaster;
private bool _intSpriteCollision; private bool _intSpriteCollision;
private bool _intSpriteDataCollision; private bool _intSpriteDataCollision;
private int _lightPenX; private int _lightPenX;
private int _lightPenY; private int _lightPenY;
private bool _multicolorMode; private bool _multicolorMode;
private bool _pinAec = true; private bool _pinAec = true;
@ -57,7 +57,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private int _pointerCb; private int _pointerCb;
private int _pointerVm; private int _pointerVm;
private int _rasterInterruptLine; private int _rasterInterruptLine;
private bool _rasterInterruptTriggered; private bool _rasterInterruptTriggered;
private int _rasterLine; private int _rasterLine;
private int _rasterX; private int _rasterX;
private bool _rasterXHold; private bool _rasterXHold;
@ -65,23 +65,23 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private int _refreshCounter; private int _refreshCounter;
private bool _renderEnabled; private bool _renderEnabled;
private bool _rowSelect; private bool _rowSelect;
private bool _spriteBackgroundCollisionClearPending; private bool _spriteBackgroundCollisionClearPending;
private bool _spriteSpriteCollisionClearPending; private bool _spriteSpriteCollisionClearPending;
private int _spriteMulticolor0; private int _spriteMulticolor0;
private int _spriteMulticolor1; private int _spriteMulticolor1;
[SaveState.DoNotSave] private readonly Sprite _sprite0; [SaveState.DoNotSave] private readonly Sprite _sprite0;
[SaveState.DoNotSave] private readonly Sprite _sprite1; [SaveState.DoNotSave] private readonly Sprite _sprite1;
[SaveState.DoNotSave] private readonly Sprite _sprite2; [SaveState.DoNotSave] private readonly Sprite _sprite2;
[SaveState.DoNotSave] private readonly Sprite _sprite3; [SaveState.DoNotSave] private readonly Sprite _sprite3;
[SaveState.DoNotSave] private readonly Sprite _sprite4; [SaveState.DoNotSave] private readonly Sprite _sprite4;
[SaveState.DoNotSave] private readonly Sprite _sprite5; [SaveState.DoNotSave] private readonly Sprite _sprite5;
[SaveState.DoNotSave] private readonly Sprite _sprite6; [SaveState.DoNotSave] private readonly Sprite _sprite6;
[SaveState.DoNotSave] private readonly Sprite _sprite7; [SaveState.DoNotSave] private readonly Sprite _sprite7;
private readonly Sprite[] _sprites; private readonly Sprite[] _sprites;
private int _sr; private int _sr;
[SaveState.DoNotSave] private bool _vblank; [SaveState.DoNotSave] private bool _vblank;
[SaveState.DoNotSave] private int _vblankEnd; [SaveState.DoNotSave] private int _vblankEnd;
[SaveState.DoNotSave] private int _vblankStart; [SaveState.DoNotSave] private int _vblankStart;
private int _vc; private int _vc;
private int _vcbase; private int _vcbase;
private int _vmli; private int _vmli;
@ -132,9 +132,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_rc = 7; _rc = 7;
_refreshCounter = 0xFF; _refreshCounter = 0xFF;
_rowSelect = false; _rowSelect = false;
_spriteBackgroundCollisionClearPending = false; _spriteBackgroundCollisionClearPending = false;
_spriteSpriteCollisionClearPending = false; _spriteSpriteCollisionClearPending = false;
_spriteMulticolor0 = 0; _spriteMulticolor0 = 0;
_spriteMulticolor1 = 0; _spriteMulticolor1 = 0;
_sr = 0; _sr = 0;
_vc = 0; _vc = 0;
@ -142,7 +142,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_vmli = 0; _vmli = 0;
_xScroll = 0; _xScroll = 0;
_yScroll = 0; _yScroll = 0;
_cycle = 0; _cycle = 0;
// reset sprites // reset sprites
for (var i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
@ -156,21 +156,21 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
} }
_pixBuffer = new int[PixBufferSize]; _pixBuffer = new int[PixBufferSize];
_pixBorderBuffer = new int[PixBorderBufferSize]; _pixBorderBuffer = new int[PixBorderBufferSize];
_pixBufferIndex = 0; _pixBufferIndex = 0;
_pixBufferBorderIndex = 0; _pixBufferBorderIndex = 0;
UpdateBorder(); UpdateBorder();
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
if (ser.IsReader) if (ser.IsReader)
{ {
UpdateBorder(); UpdateBorder();
UpdatePins(); UpdatePins();
UpdateVideoMode(); UpdateVideoMode();
} }
} }
} }
} }

View File

@ -8,24 +8,24 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Vic public sealed partial class Vic
{ {
[SaveState.DoNotSave] private const int BorderLeft38 = 0x023; [SaveState.DoNotSave] private const int BorderLeft38 = 0x023;
[SaveState.DoNotSave] private const int BorderLeft40 = 0x01C; [SaveState.DoNotSave] private const int BorderLeft40 = 0x01C;
[SaveState.DoNotSave] private const int BorderRight38 = 0x153; [SaveState.DoNotSave] private const int BorderRight38 = 0x153;
[SaveState.DoNotSave] private const int BorderRight40 = 0x15C; [SaveState.DoNotSave] private const int BorderRight40 = 0x15C;
[SaveState.DoNotSave] private const int BorderTop25 = 0x033; [SaveState.DoNotSave] private const int BorderTop25 = 0x033;
[SaveState.DoNotSave] private const int BorderTop24 = 0x037; [SaveState.DoNotSave] private const int BorderTop24 = 0x037;
[SaveState.DoNotSave] private const int BorderBottom25 = 0x0FB; [SaveState.DoNotSave] private const int BorderBottom25 = 0x0FB;
[SaveState.DoNotSave] private const int BorderBottom24 = 0x0F7; [SaveState.DoNotSave] private const int BorderBottom24 = 0x0F7;
[SaveState.DoNotSave] private const int FirstDmaLine = 0x030; [SaveState.DoNotSave] private const int FirstDmaLine = 0x030;
[SaveState.DoNotSave] private const int LastDmaLine = 0x0F7; [SaveState.DoNotSave] private const int LastDmaLine = 0x0F7;
// The special actions taken by the Vic are in the same order and interval on all chips, just different offsets. // The special actions taken by the Vic are in the same order and interval on all chips, just different offsets.
[SaveState.DoNotSave] [SaveState.DoNotSave]
private static readonly int[] TimingBuilderCycle14Act = { private static readonly int[] TimingBuilderCycle14Act = {
PipelineUpdateVc, 0, PipelineUpdateVc, 0,
PipelineSpriteCrunch, 0, PipelineSpriteCrunch, 0,
PipelineUpdateMcBase, 0, PipelineUpdateMcBase, 0,
}; };
// This builds a table of special actions to take on each half-cycle. Cycle14 is the X-raster position where // This builds a table of special actions to take on each half-cycle. Cycle14 is the X-raster position where
// pre-display operations happen, and Cycle55 is the X-raster position where post-display operations happen. // pre-display operations happen, and Cycle55 is the X-raster position where post-display operations happen.
@ -59,15 +59,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
if (timing[i] == (BorderRight40 & 0xFFC)) if (timing[i] == (BorderRight40 & 0xFFC))
result[i] |= PipelineBorderRight1; result[i] |= PipelineBorderRight1;
// right side timing // right side timing
if (timing[i] == 0x0158) if (timing[i] == 0x0158)
result[i] |= PipelineSpriteExpansion; result[i] |= PipelineSpriteExpansion;
if (timing[i] == 0x0168) if (timing[i] == 0x0168)
result[i] |= PipelineUpdateRc; result[i] |= PipelineUpdateRc;
if (timing[i] == sprite0Ba || timing[i] == sprite0Ba + 8) if (timing[i] == sprite0Ba || timing[i] == sprite0Ba + 8)
result[i] |= PipelineSpriteDma; result[i] |= PipelineSpriteDma;
if (timing[i] == sprDisp) if (timing[i] == sprDisp)
result[i] |= PipelineSpriteDisplay; result[i] |= PipelineSpriteDisplay;
} }
@ -151,7 +151,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
var length = timing.Length; var length = timing.Length;
var result = new int[length]; var result = new int[length];
var index = -1; var index = -1;
var refreshCounter = 0; var refreshCounter = 0;
var spriteActive = false; var spriteActive = false;
var spriteIndex = 0; var spriteIndex = 0;
@ -160,11 +160,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
for (var i = 0; i < length; i++) for (var i = 0; i < length; i++)
{ {
result[i++] = FetchTypeIdle; result[i++] = FetchTypeIdle;
result[i] = FetchTypeNone; result[i] = FetchTypeNone;
} }
while (true) while (true)
{ {
index++; index++;
if (index >= length) if (index >= length)
@ -213,14 +213,14 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
} }
// This uses the vBlank values to determine the height of the visible screen. // This uses the vBlank values to determine the height of the visible screen.
private static int TimingBuilder_ScreenHeight(int vblankStart, int vblankEnd, int lines) private static int TimingBuilder_ScreenHeight(int vblankStart, int vblankEnd, int lines)
{ {
if (vblankStart < 0 || vblankEnd < 0) if (vblankStart < 0 || vblankEnd < 0)
{ {
return lines; return lines;
} }
var offset = vblankEnd; var offset = vblankEnd;
var result = 0; var result = 0;
while (true) while (true)
{ {
@ -234,12 +234,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
} }
// This uses the hBlank values to determine the width of the visible screen. // This uses the hBlank values to determine the width of the visible screen.
private static int TimingBuilder_ScreenWidth(IList<int> timing, int hblankStart, int hblankEnd) private static int TimingBuilder_ScreenWidth(IList<int> timing, int hblankStart, int hblankEnd)
{ {
if (hblankStart < 0 || hblankEnd < 0) if (hblankStart < 0 || hblankEnd < 0)
{ {
return timing.Count * 4; return timing.Count * 4;
} }
var length = timing.Count; var length = timing.Count;
var result = 0; var result = 0;

View File

@ -7,22 +7,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Vic : IVideoProvider public sealed partial class Vic : IVideoProvider
{ {
[SaveState.DoNotSave] private static readonly int BgColor = Colors.ARGB(0, 0, 0); [SaveState.DoNotSave] private static readonly int BgColor = Colors.ARGB(0, 0, 0);
[SaveState.DoNotSave] private int[] _buf; [SaveState.DoNotSave] private int[] _buf;
[SaveState.DoNotSave] private int _bufHeight; [SaveState.DoNotSave] private int _bufHeight;
[SaveState.DoNotSave] private int _bufLength; [SaveState.DoNotSave] private int _bufLength;
private int _bufOffset; private int _bufOffset;
[SaveState.DoNotSave] private int _bufWidth; [SaveState.DoNotSave] private int _bufWidth;
[SaveState.DoNotSave] private const int PixBufferSize = 24; [SaveState.DoNotSave] private const int PixBufferSize = 24;
[SaveState.DoNotSave] private const int PixBorderBufferSize = 12; [SaveState.DoNotSave] private const int PixBorderBufferSize = 12;
private int[] _pixBuffer; private int[] _pixBuffer;
private int _pixBufferIndex; private int _pixBufferIndex;
private int[] _pixBorderBuffer; private int[] _pixBorderBuffer;
private int _pixBufferBorderIndex; private int _pixBufferBorderIndex;
// palette // palette
[SaveState.DoNotSave] [SaveState.DoNotSave]
private static readonly int[] Palette = private static readonly int[] Palette =
{ {
Colors.ARGB(0x00, 0x00, 0x00), Colors.ARGB(0x00, 0x00, 0x00),
Colors.ARGB(0xFF, 0xFF, 0xFF), Colors.ARGB(0xFF, 0xFF, 0xFF),
@ -42,20 +42,20 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
Colors.ARGB(0x95, 0x95, 0x95) Colors.ARGB(0x95, 0x95, 0x95)
}; };
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int BackgroundColor public int BackgroundColor
{ {
get { return BgColor; } get { return BgColor; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int BufferHeight public int BufferHeight
{ {
get { return _bufHeight; } get { return _bufHeight; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int BufferWidth public int BufferWidth
{ {
get { return _bufWidth; } get { return _bufWidth; }
} }
@ -65,10 +65,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
return _buf; return _buf;
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int VirtualWidth { get; private set; } public int VirtualWidth { get; private set; }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public int VirtualHeight { get; private set; } public int VirtualHeight { get; private set; }
} }
} }

View File

@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{ {
public sealed partial class Vic public sealed partial class Vic
{ {
/* /*
Commodore VIC-II 6567/6569/6572 core. Commodore VIC-II 6567/6569/6572 core.
Many thanks to: Many thanks to:
@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
http://mail.lipsia.de/~enigma/neu/6581.html http://mail.lipsia.de/~enigma/neu/6581.html
*/ */
public Func<int, int> ReadColorRam; public Func<int, int> ReadColorRam;
public Func<int, int> ReadMemory; public Func<int, int> ReadMemory;
public bool ReadAec() { return _pinAec; } public bool ReadAec() { return _pinAec; }
@ -31,144 +31,144 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public bool ReadIrq() { return _pinIrq; } public bool ReadIrq() { return _pinIrq; }
[SaveState.DoNotSave] private readonly int _cyclesPerSec; [SaveState.DoNotSave] private readonly int _cyclesPerSec;
[SaveState.DoNotSave] private readonly int[] _rasterXPipeline; [SaveState.DoNotSave] private readonly int[] _rasterXPipeline;
[SaveState.DoNotSave] private readonly int[] _fetchPipeline; [SaveState.DoNotSave] private readonly int[] _fetchPipeline;
[SaveState.DoNotSave] private readonly int[] _baPipeline; [SaveState.DoNotSave] private readonly int[] _baPipeline;
[SaveState.DoNotSave] private readonly int[] _actPipeline; [SaveState.DoNotSave] private readonly int[] _actPipeline;
[SaveState.DoNotSave] private readonly int _totalCycles; [SaveState.DoNotSave] private readonly int _totalCycles;
[SaveState.DoNotSave] private readonly int _totalLines; [SaveState.DoNotSave] private readonly int _totalLines;
private int _cyclesExecuted; private int _cyclesExecuted;
[SaveState.DoNotSave] private int _hblankStartCheckXRaster; [SaveState.DoNotSave] private int _hblankStartCheckXRaster;
[SaveState.DoNotSave] private int _hblankEndCheckXRaster; [SaveState.DoNotSave] private int _hblankEndCheckXRaster;
[SaveState.DoNotSave] private int _pixelRatioNum; [SaveState.DoNotSave] private int _pixelRatioNum;
[SaveState.DoNotSave] private int _pixelRatioDen; [SaveState.DoNotSave] private int _pixelRatioDen;
public Vic(int newCycles, int newLines, IList<int[]> newPipeline, int newCyclesPerSec, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd, C64.BorderType borderType, int pixelRatioNum, int pixelRatioDen) public Vic(int newCycles, int newLines, IList<int[]> newPipeline, int newCyclesPerSec, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd, C64.BorderType borderType, int pixelRatioNum, int pixelRatioDen)
{ {
Debug.WriteLine("C64 VIC timings:"); Debug.WriteLine("C64 VIC timings:");
Debug.WriteLine("RX FTCH BA ACT"); Debug.WriteLine("RX FTCH BA ACT");
for (var i = 0; i < newPipeline[0].Length; i++) for (var i = 0; i < newPipeline[0].Length; i++)
{ {
Debug.WriteLine("{0:x4} {1:x4} {2:x4} {3:x8}", newPipeline[0][i], newPipeline[1][i], newPipeline[2][i], newPipeline[3][i]); Debug.WriteLine("{0:x4} {1:x4} {2:x4} {3:x8}", newPipeline[0][i], newPipeline[1][i], newPipeline[2][i], newPipeline[3][i]);
} }
_pixelRatioNum = pixelRatioNum; _pixelRatioNum = pixelRatioNum;
_pixelRatioDen = pixelRatioDen; _pixelRatioDen = pixelRatioDen;
_rasterXPipeline = newPipeline[0]; _rasterXPipeline = newPipeline[0];
_fetchPipeline = newPipeline[1]; _fetchPipeline = newPipeline[1];
_baPipeline = newPipeline[2]; _baPipeline = newPipeline[2];
_actPipeline = newPipeline[3]; _actPipeline = newPipeline[3];
_totalCycles = newCycles; _totalCycles = newCycles;
_totalLines = newLines; _totalLines = newLines;
_cyclesPerSec = newCyclesPerSec; _cyclesPerSec = newCyclesPerSec;
ConfigureBlanking(newLines, hblankStart, hblankEnd, vblankStart, vblankEnd, borderType); ConfigureBlanking(newLines, hblankStart, hblankEnd, vblankStart, vblankEnd, borderType);
_sprites = new Sprite[8]; _sprites = new Sprite[8];
for (var i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
_sprites[i] = new Sprite(); _sprites[i] = new Sprite();
_sprite0 = _sprites[0]; _sprite0 = _sprites[0];
_sprite1 = _sprites[1]; _sprite1 = _sprites[1];
_sprite2 = _sprites[2]; _sprite2 = _sprites[2];
_sprite3 = _sprites[3]; _sprite3 = _sprites[3];
_sprite4 = _sprites[4]; _sprite4 = _sprites[4];
_sprite5 = _sprites[5]; _sprite5 = _sprites[5];
_sprite6 = _sprites[6]; _sprite6 = _sprites[6];
_sprite7 = _sprites[7]; _sprite7 = _sprites[7];
_bufferC = new int[40]; _bufferC = new int[40];
_bufferG = new int[40]; _bufferG = new int[40];
} }
private void ConfigureBlanking(int lines, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd, private void ConfigureBlanking(int lines, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd,
C64.BorderType borderType) C64.BorderType borderType)
{ {
var newHblankStart = hblankStart; var newHblankStart = hblankStart;
var newHblankEnd = hblankEnd; var newHblankEnd = hblankEnd;
var newVblankStart = vblankStart; var newVblankStart = vblankStart;
var newVblankEnd = vblankEnd; var newVblankEnd = vblankEnd;
var hBorderSize = 16; // must be a multiple of 4 var hBorderSize = 16; // must be a multiple of 4
var vBorderSize = hBorderSize*_pixelRatioNum/_pixelRatioDen; // to keep top and bottom in proportion var vBorderSize = hBorderSize * _pixelRatioNum / _pixelRatioDen; // to keep top and bottom in proportion
var maxWidth = _rasterXPipeline.Max(); var maxWidth = _rasterXPipeline.Max();
switch (borderType) switch (borderType)
{ {
case C64.BorderType.Full: case C64.BorderType.Full:
newHblankStart = -1; newHblankStart = -1;
newHblankEnd = -1; newHblankEnd = -1;
_hblank = false; _hblank = false;
newVblankStart = -1; newVblankStart = -1;
newVblankEnd = -1; newVblankEnd = -1;
_vblank = false; _vblank = false;
break; break;
case C64.BorderType.Normal: case C64.BorderType.Normal:
newHblankStart = hblankStart; newHblankStart = hblankStart;
newHblankEnd = hblankEnd; newHblankEnd = hblankEnd;
newVblankStart = vblankStart; newVblankStart = vblankStart;
newVblankEnd = vblankEnd; newVblankEnd = vblankEnd;
_vblank = true; _vblank = true;
_hblank = true; _hblank = true;
break; break;
case C64.BorderType.SmallProportional: case C64.BorderType.SmallProportional:
_vblank = true; _vblank = true;
_hblank = true; _hblank = true;
newHblankStart = 0x158 + PixBufferSize + hBorderSize; newHblankStart = 0x158 + PixBufferSize + hBorderSize;
newHblankEnd = 0x018 + PixBufferSize - hBorderSize; newHblankEnd = 0x018 + PixBufferSize - hBorderSize;
newVblankStart = 0xFA + vBorderSize; newVblankStart = 0xFA + vBorderSize;
newVblankEnd = 0x32 - vBorderSize; newVblankEnd = 0x32 - vBorderSize;
break; break;
case C64.BorderType.SmallFixed: case C64.BorderType.SmallFixed:
_vblank = true; _vblank = true;
_hblank = true; _hblank = true;
newHblankStart = 0x158 + PixBufferSize + hBorderSize; newHblankStart = 0x158 + PixBufferSize + hBorderSize;
newHblankEnd = 0x018 + PixBufferSize - hBorderSize; newHblankEnd = 0x018 + PixBufferSize - hBorderSize;
newVblankStart = 0xFA + hBorderSize; newVblankStart = 0xFA + hBorderSize;
newVblankEnd = 0x32 - hBorderSize; newVblankEnd = 0x32 - hBorderSize;
break; break;
} }
// wrap values // wrap values
newHblankStart = WrapValue(0, maxWidth, newHblankStart); newHblankStart = WrapValue(0, maxWidth, newHblankStart);
newHblankEnd = WrapValue(0, maxWidth, newHblankEnd); newHblankEnd = WrapValue(0, maxWidth, newHblankEnd);
newVblankStart = WrapValue(0, lines, newVblankStart); newVblankStart = WrapValue(0, lines, newVblankStart);
newVblankEnd = WrapValue(0, lines, newVblankEnd); newVblankEnd = WrapValue(0, lines, newVblankEnd);
// calculate output dimensions // calculate output dimensions
_hblankStartCheckXRaster = newHblankStart & 0xFFC; _hblankStartCheckXRaster = newHblankStart & 0xFFC;
_hblankEndCheckXRaster = newHblankEnd & 0xFFC; _hblankEndCheckXRaster = newHblankEnd & 0xFFC;
_vblankStart = newVblankStart; _vblankStart = newVblankStart;
_vblankEnd = newVblankEnd; _vblankEnd = newVblankEnd;
_bufWidth = TimingBuilder_ScreenWidth(_rasterXPipeline, newHblankStart, newHblankEnd); _bufWidth = TimingBuilder_ScreenWidth(_rasterXPipeline, newHblankStart, newHblankEnd);
_bufHeight = TimingBuilder_ScreenHeight(newVblankStart, newVblankEnd, lines); _bufHeight = TimingBuilder_ScreenHeight(newVblankStart, newVblankEnd, lines);
_buf = new int[_bufWidth * _bufHeight]; _buf = new int[_bufWidth * _bufHeight];
_bufLength = _buf.Length; _bufLength = _buf.Length;
VirtualWidth = _bufWidth*_pixelRatioNum/_pixelRatioDen; VirtualWidth = _bufWidth * _pixelRatioNum / _pixelRatioDen;
VirtualHeight = _bufHeight; VirtualHeight = _bufHeight;
} }
private int WrapValue(int min, int max, int val) private int WrapValue(int min, int max, int val)
{ {
if (min == max) if (min == max)
{ {
return min; return min;
} }
var width = Math.Abs(min - max); var width = Math.Abs(min - max);
while (val > max) while (val > max)
{ {
val -= width; val -= width;
} }
while (val < min) while (val < min)
{ {
val += width; val += width;
} }
return val; return val;
} }
public int CyclesPerFrame public int CyclesPerFrame
{ {
get get
{ {
@ -184,145 +184,145 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
} }
} }
public void ExecutePhase() public void ExecutePhase()
{ {
// phi1 // phi1
// advance cycle and optionally raster line // advance cycle and optionally raster line
_cycle++; _cycle++;
if (_cycle > _totalCycles) if (_cycle > _totalCycles)
{ {
// border check // border check
if (_rasterLine == _borderB) if (_rasterLine == _borderB)
_borderOnVertical = true; _borderOnVertical = true;
if (_rasterLine == _borderT && _displayEnable) if (_rasterLine == _borderT && _displayEnable)
_borderOnVertical = false; _borderOnVertical = false;
// vblank check // vblank check
if (_rasterLine == _vblankStart) if (_rasterLine == _vblankStart)
_vblank = true; _vblank = true;
if (_rasterLine == _vblankEnd) if (_rasterLine == _vblankEnd)
_vblank = false; _vblank = false;
// reset to beginning of rasterline // reset to beginning of rasterline
_cycleIndex = 0; _cycleIndex = 0;
_cycle = 1; _cycle = 1;
_rasterLine++; _rasterLine++;
if (_rasterLine == _totalLines) if (_rasterLine == _totalLines)
{ {
// reset to rasterline 0 // reset to rasterline 0
_rasterLine = 0; _rasterLine = 0;
_vcbase = 0; _vcbase = 0;
_vc = 0; _vc = 0;
_badlineEnable = false; _badlineEnable = false;
_refreshCounter = 0xFF; _refreshCounter = 0xFF;
_cyclesExecuted = 0; _cyclesExecuted = 0;
} }
} }
// bg collision clear // bg collision clear
if (_spriteBackgroundCollisionClearPending) if (_spriteBackgroundCollisionClearPending)
{ {
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
spr.CollideData = false; spr.CollideData = false;
} }
_spriteBackgroundCollisionClearPending = false; _spriteBackgroundCollisionClearPending = false;
} }
// sprite collision clear // sprite collision clear
if (_spriteSpriteCollisionClearPending) if (_spriteSpriteCollisionClearPending)
{ {
foreach (var spr in _sprites) foreach (var spr in _sprites)
{ {
spr.CollideSprite = false; spr.CollideSprite = false;
} }
_spriteSpriteCollisionClearPending = false; _spriteSpriteCollisionClearPending = false;
} }
// phi2 // phi2
// start of rasterline // start of rasterline
if ((_cycle == RasterIrqLineXCycle && _rasterLine > 0) || (_cycle == RasterIrqLine0Cycle && _rasterLine == 0)) if ((_cycle == RasterIrqLineXCycle && _rasterLine > 0) || (_cycle == RasterIrqLine0Cycle && _rasterLine == 0))
{ {
_rasterInterruptTriggered = false; _rasterInterruptTriggered = false;
if (_rasterLine == LastDmaLine) if (_rasterLine == LastDmaLine)
_badlineEnable = false; _badlineEnable = false;
} }
// rasterline IRQ compare // rasterline IRQ compare
if (_rasterLine != _rasterInterruptLine) if (_rasterLine != _rasterInterruptLine)
{ {
_rasterInterruptTriggered = false; _rasterInterruptTriggered = false;
} }
else else
{ {
if (!_rasterInterruptTriggered) if (!_rasterInterruptTriggered)
{ {
_rasterInterruptTriggered = true; _rasterInterruptTriggered = true;
_intRaster = true; _intRaster = true;
} }
} }
// check top and bottom border // check top and bottom border
if (_rasterLine == _borderB) if (_rasterLine == _borderB)
{ {
_borderOnVertical = true; _borderOnVertical = true;
} }
if (_displayEnable && _rasterLine == _borderT) if (_displayEnable && _rasterLine == _borderT)
{ {
_borderOnVertical = false; _borderOnVertical = false;
} }
// display enable compare // display enable compare
if (_rasterLine == FirstDmaLine) if (_rasterLine == FirstDmaLine)
_badlineEnable |= _displayEnable; _badlineEnable |= _displayEnable;
// badline compare // badline compare
if (_badlineEnable) if (_badlineEnable)
{ {
if ((_rasterLine & 0x7) == _yScroll) if ((_rasterLine & 0x7) == _yScroll)
{ {
_badline = true; _badline = true;
// go into display state on a badline // go into display state on a badline
_idle = false; _idle = false;
} }
else else
{ {
_badline = false; _badline = false;
} }
} }
else else
{ {
_badline = false; _badline = false;
} }
// render // render
ParseCycle(); ParseCycle();
Render(); Render();
ParseCycle(); ParseCycle();
Render(); Render();
_extraColorModeBuffer = _extraColorMode; _extraColorModeBuffer = _extraColorMode;
// if the BA counter is nonzero, allow CPU bus access // if the BA counter is nonzero, allow CPU bus access
if (_pinBa) if (_pinBa)
_baCount = BaResetCounter; _baCount = BaResetCounter;
else if (_baCount > 0) else if (_baCount > 0)
_baCount--; _baCount--;
_pinAec = _pinBa || _baCount > 0; _pinAec = _pinBa || _baCount > 0;
// must always come last // must always come last
UpdatePins(); UpdatePins();
_cyclesExecuted++; _cyclesExecuted++;
} }
private void UpdateBorder() private void UpdateBorder()
{ {
_borderL = _columnSelect ? BorderLeft40 : BorderLeft38; _borderL = _columnSelect ? BorderLeft40 : BorderLeft38;
_borderR = _columnSelect ? BorderRight40 : BorderRight38; _borderR = _columnSelect ? BorderRight40 : BorderRight38;
_borderT = _rowSelect ? BorderTop25 : BorderTop24; _borderT = _rowSelect ? BorderTop25 : BorderTop24;
_borderB = _rowSelect ? BorderBottom25 : BorderBottom24; _borderB = _rowSelect ? BorderBottom25 : BorderBottom24;
@ -346,27 +346,27 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_videoMode = VideoMode000; _videoMode = VideoMode000;
return; return;
} }
if (!_extraColorMode && !_bitmapMode && _multicolorMode) if (!_extraColorMode && !_bitmapMode && _multicolorMode)
{ {
_videoMode = VideoMode001; _videoMode = VideoMode001;
return; return;
} }
if (!_extraColorMode && _bitmapMode && !_multicolorMode) if (!_extraColorMode && _bitmapMode && !_multicolorMode)
{ {
_videoMode = VideoMode010; _videoMode = VideoMode010;
return; return;
} }
if (!_extraColorMode && _bitmapMode && _multicolorMode) if (!_extraColorMode && _bitmapMode && _multicolorMode)
{ {
_videoMode = VideoMode011; _videoMode = VideoMode011;
return; return;
} }
if (_extraColorMode && !_bitmapMode && !_multicolorMode) if (_extraColorMode && !_bitmapMode && !_multicolorMode)
{ {
_videoMode = VideoMode100; _videoMode = VideoMode100;
return; return;
} }
_videoMode = VideoModeInvalid; _videoMode = VideoModeInvalid;
} }
} }
} }

View File

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

View File

@ -7,173 +7,173 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
{ {
public sealed class Disk public sealed class Disk
{ {
[SaveState.DoNotSave] public const int FluxBitsPerEntry = 32; [SaveState.DoNotSave] public const int FluxBitsPerEntry = 32;
[SaveState.DoNotSave] public const int FluxBitsPerTrack = 16000000 / 5; [SaveState.DoNotSave] public const int FluxBitsPerTrack = 16000000 / 5;
[SaveState.DoNotSave] public const int FluxEntriesPerTrack = FluxBitsPerTrack/FluxBitsPerEntry; [SaveState.DoNotSave] public const int FluxEntriesPerTrack = FluxBitsPerTrack / FluxBitsPerEntry;
[SaveState.DoNotSave] private int[][] _tracks; [SaveState.DoNotSave] private int[][] _tracks;
[SaveState.DoNotSave] private readonly int[] _originalMedia; [SaveState.DoNotSave] private readonly int[] _originalMedia;
[SaveState.DoNotSave] public bool Valid; [SaveState.DoNotSave] public bool Valid;
[SaveState.SaveWithName("DiskIsWriteProtected")] public bool WriteProtected; [SaveState.SaveWithName("DiskIsWriteProtected")] public bool WriteProtected;
/// <summary> /// <summary>
/// Create a blank, unformatted disk. /// Create a blank, unformatted disk.
/// </summary> /// </summary>
public Disk(int trackCapacity) public Disk(int trackCapacity)
{ {
WriteProtected = false; WriteProtected = false;
_tracks = new int[trackCapacity][]; _tracks = new int[trackCapacity][];
FillMissingTracks(); FillMissingTracks();
_originalMedia = SerializeTracks(_tracks); _originalMedia = SerializeTracks(_tracks);
Valid = true; Valid = true;
} }
/// <summary> /// <summary>
/// Create an expanded representation of a magnetic disk. /// Create an expanded representation of a magnetic disk.
/// </summary> /// </summary>
/// <param name="trackData">Raw bit data.</param> /// <param name="trackData">Raw bit data.</param>
/// <param name="trackNumbers">Track numbers for the raw bit data.</param> /// <param name="trackNumbers">Track numbers for the raw bit data.</param>
/// <param name="trackDensities">Density zones for the raw bit data.</param> /// <param name="trackDensities">Density zones for the raw bit data.</param>
/// <param name="trackLengths">Length, in bits, of each raw bit data.</param> /// <param name="trackLengths">Length, in bits, of each raw bit data.</param>
/// <param name="trackCapacity">Total number of tracks on the media.</param> /// <param name="trackCapacity">Total number of tracks on the media.</param>
public Disk(IList<byte[]> trackData, IList<int> trackNumbers, IList<int> trackDensities, int trackCapacity) public Disk(IList<byte[]> trackData, IList<int> trackNumbers, IList<int> trackDensities, int trackCapacity)
{ {
WriteProtected = true; WriteProtected = true;
_tracks = new int[trackCapacity][]; _tracks = new int[trackCapacity][];
for (var i = 0; i < trackData.Count; i++) for (var i = 0; i < trackData.Count; i++)
{ {
_tracks[trackNumbers[i]] = ConvertToFluxTransitions(trackDensities[i], trackData[i], 0); _tracks[trackNumbers[i]] = ConvertToFluxTransitions(trackDensities[i], trackData[i], 0);
} }
FillMissingTracks(); FillMissingTracks();
Valid = true; Valid = true;
_originalMedia = SerializeTracks(_tracks); _originalMedia = SerializeTracks(_tracks);
} }
private int[] ConvertToFluxTransitions(int density, byte[] bytes, int fluxBitOffset) private int[] ConvertToFluxTransitions(int density, byte[] bytes, int fluxBitOffset)
{ {
var paddedLength = bytes.Length; var paddedLength = bytes.Length;
switch (density) switch (density)
{ {
case 3: case 3:
paddedLength = Math.Max(bytes.Length, 7692); paddedLength = Math.Max(bytes.Length, 7692);
break; break;
case 2: case 2:
paddedLength = Math.Max(bytes.Length, 7142); paddedLength = Math.Max(bytes.Length, 7142);
break; break;
case 1: case 1:
paddedLength = Math.Max(bytes.Length, 6666); paddedLength = Math.Max(bytes.Length, 6666);
break; break;
case 0: case 0:
paddedLength = Math.Max(bytes.Length, 6250); paddedLength = Math.Max(bytes.Length, 6250);
break; break;
} }
paddedLength++; paddedLength++;
var paddedBytes = new byte[paddedLength]; var paddedBytes = new byte[paddedLength];
Array.Copy(bytes, paddedBytes, bytes.Length); Array.Copy(bytes, paddedBytes, bytes.Length);
for (var i = bytes.Length; i < paddedLength; i++) for (var i = bytes.Length; i < paddedLength; i++)
{ {
paddedBytes[i] = 0xAA; paddedBytes[i] = 0xAA;
} }
var result = new int[FluxEntriesPerTrack]; var result = new int[FluxEntriesPerTrack];
var lengthBits = (paddedLength * 8) - 7; var lengthBits = (paddedLength * 8) - 7;
var offsets = new List<long>(); var offsets = new List<long>();
var remainingBits = lengthBits; var remainingBits = lengthBits;
const long bitsNum = FluxEntriesPerTrack * FluxBitsPerEntry; const long bitsNum = FluxEntriesPerTrack * FluxBitsPerEntry;
long bitsDen = lengthBits; long bitsDen = lengthBits;
for (var i = 0; i < paddedLength; i++) for (var i = 0; i < paddedLength; i++)
{ {
var byteData = paddedBytes[i]; var byteData = paddedBytes[i];
for (var j = 0; j < 8; j++) for (var j = 0; j < 8; j++)
{ {
var offset = fluxBitOffset + ((i * 8 + j) * bitsNum / bitsDen); var offset = fluxBitOffset + ((i * 8 + j) * bitsNum / bitsDen);
var byteOffset = (int)(offset / FluxBitsPerEntry); var byteOffset = (int)(offset / FluxBitsPerEntry);
var bitOffset = (int)(offset % FluxBitsPerEntry); var bitOffset = (int)(offset % FluxBitsPerEntry);
offsets.Add(offset); offsets.Add(offset);
result[byteOffset] |= ((byteData & 0x80) != 0 ? 1 : 0) << bitOffset; result[byteOffset] |= ((byteData & 0x80) != 0 ? 1 : 0) << bitOffset;
byteData <<= 1; byteData <<= 1;
remainingBits--; remainingBits--;
if (remainingBits <= 0) if (remainingBits <= 0)
break; break;
} }
if (remainingBits <= 0) if (remainingBits <= 0)
break; break;
} }
return result; return result;
} }
private void FillMissingTracks() private void FillMissingTracks()
{ {
// Fill half tracks (should assist with EA "fat-track" protections) // Fill half tracks (should assist with EA "fat-track" protections)
for (var i = 1; i < _tracks.Length; i += 2) for (var i = 1; i < _tracks.Length; i += 2)
{ {
if (_tracks[i] == null && _tracks[i - 1] != null) if (_tracks[i] == null && _tracks[i - 1] != null)
{ {
_tracks[i] = new int[FluxEntriesPerTrack]; _tracks[i] = new int[FluxEntriesPerTrack];
Array.Copy(_tracks[i - 1], _tracks[i], FluxEntriesPerTrack); Array.Copy(_tracks[i - 1], _tracks[i], FluxEntriesPerTrack);
} }
} }
// Fill vacant tracks // Fill vacant tracks
for (var i = 0; i < _tracks.Length; i++) for (var i = 0; i < _tracks.Length; i++)
{ {
if (_tracks[i] == null) if (_tracks[i] == null)
{ {
_tracks[i] = new int[FluxEntriesPerTrack]; _tracks[i] = new int[FluxEntriesPerTrack];
} }
} }
} }
public int[] GetDataForTrack(int halftrack) public int[] GetDataForTrack(int halftrack)
{ {
return _tracks[halftrack]; return _tracks[halftrack];
} }
/// <summary> /// <summary>
/// Combine the tracks into a single bitstream. /// Combine the tracks into a single bitstream.
/// </summary> /// </summary>
private int[] SerializeTracks(int[][] tracks) private int[] SerializeTracks(int[][] tracks)
{ {
var trackCount = tracks.Length; var trackCount = tracks.Length;
var result = new int[trackCount * FluxEntriesPerTrack]; var result = new int[trackCount * FluxEntriesPerTrack];
for (var i = 0; i < trackCount; i++) for (var i = 0; i < trackCount; i++)
{ {
Array.Copy(tracks[i], 0, result, i * FluxEntriesPerTrack, FluxEntriesPerTrack); Array.Copy(tracks[i], 0, result, i * FluxEntriesPerTrack, FluxEntriesPerTrack);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Split a bitstream into tracks. /// Split a bitstream into tracks.
/// </summary> /// </summary>
private int[][] DeserializeTracks(int[] data) private int[][] DeserializeTracks(int[] data)
{ {
var trackCount = data.Length/FluxEntriesPerTrack; var trackCount = data.Length / FluxEntriesPerTrack;
var result = new int[trackCount][]; var result = new int[trackCount][];
for (var i = 0; i < trackCount; i++) for (var i = 0; i < trackCount; i++)
{ {
result[i] = new int[FluxEntriesPerTrack]; result[i] = new int[FluxEntriesPerTrack];
Array.Copy(data, i * FluxEntriesPerTrack, result[i], 0, FluxEntriesPerTrack); Array.Copy(data, i * FluxEntriesPerTrack, result[i], 0, FluxEntriesPerTrack);
} }
return result; return result;
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
if (ser.IsReader) if (ser.IsReader)
{ {
var mediaState = new int[_originalMedia.Length]; var mediaState = new int[_originalMedia.Length];
SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState); SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState);
_tracks = DeserializeTracks(mediaState); _tracks = DeserializeTracks(mediaState);
} }
else if (ser.IsWriter) else if (ser.IsWriter)
{ {
var mediaState = SerializeTracks(_tracks); var mediaState = SerializeTracks(_tracks);
SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState); SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState);
} }
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }

View File

@ -7,302 +7,302 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
{ {
public class DiskBuilder public class DiskBuilder
{ {
public enum FileType public enum FileType
{ {
Deleted = 0, Deleted = 0,
Sequential = 1, Sequential = 1,
Program = 2, Program = 2,
User = 3, User = 3,
Relative = 4 Relative = 4
} }
protected class BamEntry protected class BamEntry
{ {
public int Data { get; private set; } public int Data { get; private set; }
public int Sectors { get; private set; } public int Sectors { get; private set; }
public BamEntry(int sectors) public BamEntry(int sectors)
{ {
Data = 0; Data = 0;
for (var i = 0; i < sectors; i++) for (var i = 0; i < sectors; i++)
{ {
Data >>= 1; Data >>= 1;
Data |= 0x800000; Data |= 0x800000;
} }
Data |= (sectors << 24); Data |= (sectors << 24);
Sectors = sectors; Sectors = sectors;
} }
private int GetBit(int sector) private int GetBit(int sector)
{ {
if (sector < 0 || sector >= Sectors) if (sector < 0 || sector >= Sectors)
{ {
return 0; return 0;
} }
return 0x800000 >> sector; return 0x800000 >> sector;
} }
public void Allocate(int sector) public void Allocate(int sector)
{ {
var bit = GetBit(sector); var bit = GetBit(sector);
if (bit != 0 && (Data & bit) != 0) if (bit != 0 && (Data & bit) != 0)
{ {
Data &= ~bit; Data &= ~bit;
Data -= 0x1000000; Data -= 0x1000000;
} }
} }
public void Free(int sector) public void Free(int sector)
{ {
var bit = GetBit(sector); var bit = GetBit(sector);
if (bit != 0 && (Data & bit) == 0) if (bit != 0 && (Data & bit) == 0)
{ {
Data |= bit; Data |= bit;
Data += 0x1000000; Data += 0x1000000;
} }
} }
public int SectorsRemaining public int SectorsRemaining
{ {
get { return (Data >> 24) & 0xFF; } get { return (Data >> 24) & 0xFF; }
} }
public bool this[int sector] public bool this[int sector]
{ {
get { return (Data & (1 << sector)) != 0; } get { return (Data & (1 << sector)) != 0; }
set set
{ {
if (value) if (value)
Free(sector); Free(sector);
else else
Allocate(sector); Allocate(sector);
} }
} }
public byte[] GetBytes() public byte[] GetBytes()
{ {
return GetBytesEnumerable().ToArray(); return GetBytesEnumerable().ToArray();
} }
private IEnumerable<byte> GetBytesEnumerable() private IEnumerable<byte> GetBytesEnumerable()
{ {
yield return unchecked((byte)(Data >> 24)); yield return unchecked((byte)(Data >> 24));
yield return unchecked((byte)(Data >> 16)); yield return unchecked((byte)(Data >> 16));
yield return unchecked((byte)(Data >> 8)); yield return unchecked((byte)(Data >> 8));
yield return unchecked((byte)Data); yield return unchecked((byte)Data);
} }
public IEnumerable<bool> Entries public IEnumerable<bool> Entries
{ {
get get
{ {
var d = Data; var d = Data;
for (var i = 0; i < Sectors; i++) for (var i = 0; i < Sectors; i++)
{ {
d <<= 1; d <<= 1;
yield return (d & 0x1000000) != 0; yield return (d & 0x1000000) != 0;
} }
} }
} }
} }
protected class LocatedEntry protected class LocatedEntry
{ {
public Entry Entry { get; set; } public Entry Entry { get; set; }
public int DirectoryTrack { get; set; } public int DirectoryTrack { get; set; }
public int DirectorySector { get; set; } public int DirectorySector { get; set; }
public int Track { get; set; } public int Track { get; set; }
public int Sector { get; set; } public int Sector { get; set; }
public int SideTrack { get; set; } public int SideTrack { get; set; }
public int SideSector { get; set; } public int SideSector { get; set; }
public int LengthInSectors { get; set; } public int LengthInSectors { get; set; }
} }
public class Entry public class Entry
{ {
public FileType Type { get; set; } public FileType Type { get; set; }
public bool Locked { get; set; } public bool Locked { get; set; }
public bool Closed { get; set; } public bool Closed { get; set; }
public string Name { get; set; } public string Name { get; set; }
public int RecordLength { get; set; } public int RecordLength { get; set; }
public byte[] Data { get; set; } public byte[] Data { get; set; }
} }
private static readonly int[] SectorsPerTrack = private static readonly int[] SectorsPerTrack =
{ {
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 19, 19, 19, 21, 21, 19, 19, 19,
19, 19, 19, 19, 18, 19, 19, 19, 19, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17 17, 17, 17, 17, 17
}; };
public List<Entry> Entries { get; set; } public List<Entry> Entries { get; set; }
public int VersionType { get; set; } public int VersionType { get; set; }
public string Title { get; set; } public string Title { get; set; }
public DiskBuilder() public DiskBuilder()
{ {
Entries = new List<Entry>(); Entries = new List<Entry>();
VersionType = 0x41; VersionType = 0x41;
} }
public Disk Build() public Disk Build()
{ {
const int tracks = 35; const int tracks = 35;
var trackByteOffsets = new int[tracks]; var trackByteOffsets = new int[tracks];
var bam = new BamEntry[tracks]; var bam = new BamEntry[tracks];
var diskFull = false; var diskFull = false;
for (var i = 0; i < tracks; i++) for (var i = 0; i < tracks; i++)
{ {
bam[i] = new BamEntry(SectorsPerTrack[i]); bam[i] = new BamEntry(SectorsPerTrack[i]);
if (i > 0) if (i > 0)
{ {
trackByteOffsets[i] = trackByteOffsets[i - 1] + (SectorsPerTrack[i - 1] * 256); trackByteOffsets[i] = trackByteOffsets[i - 1] + (SectorsPerTrack[i - 1] * 256);
} }
} }
var bytes = new byte[trackByteOffsets[tracks - 1] + (SectorsPerTrack[tracks - 1] *256)]; var bytes = new byte[trackByteOffsets[tracks - 1] + (SectorsPerTrack[tracks - 1] * 256)];
var currentTrack = 16; var currentTrack = 16;
var currentSector = 0; var currentSector = 0;
var interleaveStart = 0; var interleaveStart = 0;
var sectorInterleave = 3; var sectorInterleave = 3;
var directory = new List<LocatedEntry>(); var directory = new List<LocatedEntry>();
Func<int, int, int> GetOutputOffset = (t, s) => trackByteOffsets[t] + (s*256); Func<int, int, int> GetOutputOffset = (t, s) => trackByteOffsets[t] + (s * 256);
foreach (var entry in Entries) foreach (var entry in Entries)
{ {
var sourceOffset = 0; var sourceOffset = 0;
var dataLength = entry.Data == null ? 0 : entry.Data.Length; var dataLength = entry.Data == null ? 0 : entry.Data.Length;
var lengthInSectors = dataLength / 254; var lengthInSectors = dataLength / 254;
var dataRemaining = dataLength; var dataRemaining = dataLength;
var directoryEntry = new LocatedEntry var directoryEntry = new LocatedEntry
{ {
Entry = entry, Entry = entry,
LengthInSectors = lengthInSectors + 1, LengthInSectors = lengthInSectors + 1,
Track = currentTrack, Track = currentTrack,
Sector = currentSector Sector = currentSector
}; };
directory.Add(directoryEntry); directory.Add(directoryEntry);
while (!diskFull) while (!diskFull)
{ {
var outputOffset = GetOutputOffset(currentTrack, currentSector); var outputOffset = GetOutputOffset(currentTrack, currentSector);
if (dataRemaining > 254) if (dataRemaining > 254)
{ {
Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, 254); Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, 254);
dataRemaining -= 254; dataRemaining -= 254;
sourceOffset += 254; sourceOffset += 254;
} }
else else
{ {
if (dataRemaining > 0) if (dataRemaining > 0)
{ {
Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, dataRemaining); Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, dataRemaining);
bytes[outputOffset + 0] = 0; bytes[outputOffset + 0] = 0;
bytes[outputOffset + 1] = (byte)(dataRemaining + 1); bytes[outputOffset + 1] = (byte)(dataRemaining + 1);
dataRemaining = 0; dataRemaining = 0;
} }
} }
bam[currentTrack].Allocate(currentSector); bam[currentTrack].Allocate(currentSector);
currentSector += sectorInterleave; currentSector += sectorInterleave;
if (currentSector >= SectorsPerTrack[currentTrack]) if (currentSector >= SectorsPerTrack[currentTrack])
{ {
interleaveStart++; interleaveStart++;
if (interleaveStart >= sectorInterleave) if (interleaveStart >= sectorInterleave)
{ {
interleaveStart = 0; interleaveStart = 0;
if (currentTrack >= 17) if (currentTrack >= 17)
{ {
currentTrack++; currentTrack++;
if (currentTrack >= 35) if (currentTrack >= 35)
{ {
diskFull = true; diskFull = true;
break; break;
} }
} }
else else
{ {
currentTrack--; currentTrack--;
if (currentTrack < 0) if (currentTrack < 0)
currentTrack = 18; currentTrack = 18;
} }
} }
currentSector = interleaveStart; currentSector = interleaveStart;
} }
if (dataRemaining <= 0) if (dataRemaining <= 0)
break; break;
bytes[outputOffset + 0] = (byte)(currentTrack + 1); bytes[outputOffset + 0] = (byte)(currentTrack + 1);
bytes[outputOffset + 1] = (byte) currentSector; bytes[outputOffset + 1] = (byte)currentSector;
} }
if (diskFull) if (diskFull)
break; break;
} }
// write Directory // write Directory
var directoryOffset = -(0x20); var directoryOffset = -(0x20);
currentTrack = 17; currentTrack = 17;
currentSector = 1; currentSector = 1;
var directoryOutputOffset = GetOutputOffset(currentTrack, currentSector); var directoryOutputOffset = GetOutputOffset(currentTrack, currentSector);
var fileIndex = 0; var fileIndex = 0;
bam[currentTrack].Allocate(currentSector); bam[currentTrack].Allocate(currentSector);
foreach (var entry in directory) foreach (var entry in directory)
{ {
directoryOffset += 0x20; directoryOffset += 0x20;
if (directoryOffset == 0x100) if (directoryOffset == 0x100)
{ {
directoryOffset = 0; directoryOffset = 0;
currentSector += 3; currentSector += 3;
bytes[directoryOutputOffset] = (byte) currentTrack; bytes[directoryOutputOffset] = (byte)currentTrack;
bytes[directoryOutputOffset + 1] = (byte) currentSector; bytes[directoryOutputOffset + 1] = (byte)currentSector;
directoryOutputOffset = GetOutputOffset(currentTrack, currentSector); directoryOutputOffset = GetOutputOffset(currentTrack, currentSector);
bam[currentTrack].Allocate(currentSector); bam[currentTrack].Allocate(currentSector);
} }
bytes[directoryOutputOffset + directoryOffset + 0x00] = 0x00; bytes[directoryOutputOffset + directoryOffset + 0x00] = 0x00;
bytes[directoryOutputOffset + directoryOffset + 0x01] = 0x00; bytes[directoryOutputOffset + directoryOffset + 0x01] = 0x00;
bytes[directoryOutputOffset + directoryOffset + 0x02] = (byte)((int)entry.Entry.Type | (entry.Entry.Locked ? 0x40 : 0x00) | (entry.Entry.Closed ? 0x80 : 0x00)); bytes[directoryOutputOffset + directoryOffset + 0x02] = (byte)((int)entry.Entry.Type | (entry.Entry.Locked ? 0x40 : 0x00) | (entry.Entry.Closed ? 0x80 : 0x00));
bytes[directoryOutputOffset + directoryOffset + 0x03] = (byte)(entry.Track + 1); bytes[directoryOutputOffset + directoryOffset + 0x03] = (byte)(entry.Track + 1);
bytes[directoryOutputOffset + directoryOffset + 0x04] = (byte)entry.Sector; bytes[directoryOutputOffset + directoryOffset + 0x04] = (byte)entry.Sector;
for (var i = 0x05; i <= 0x14; i++) for (var i = 0x05; i <= 0x14; i++)
bytes[directoryOutputOffset + directoryOffset + i] = 0xA0; bytes[directoryOutputOffset + directoryOffset + i] = 0xA0;
var fileNameBytes = Encoding.ASCII.GetBytes(entry.Entry.Name ?? string.Format("FILE{0:D3}", fileIndex)); var fileNameBytes = Encoding.ASCII.GetBytes(entry.Entry.Name ?? string.Format("FILE{0:D3}", fileIndex));
Array.Copy(fileNameBytes, 0, bytes, directoryOutputOffset + directoryOffset + 0x05, Math.Min(fileNameBytes.Length, 0x10)); Array.Copy(fileNameBytes, 0, bytes, directoryOutputOffset + directoryOffset + 0x05, Math.Min(fileNameBytes.Length, 0x10));
bytes[directoryOutputOffset + directoryOffset + 0x1E] = (byte)(entry.LengthInSectors & 0xFF); bytes[directoryOutputOffset + directoryOffset + 0x1E] = (byte)(entry.LengthInSectors & 0xFF);
bytes[directoryOutputOffset + directoryOffset + 0x1F] = (byte)((entry.LengthInSectors >> 8) & 0xFF); bytes[directoryOutputOffset + directoryOffset + 0x1F] = (byte)((entry.LengthInSectors >> 8) & 0xFF);
fileIndex++; fileIndex++;
} }
bytes[directoryOutputOffset + 0x00] = 0x00; bytes[directoryOutputOffset + 0x00] = 0x00;
bytes[directoryOutputOffset + 0x01] = 0xFF; bytes[directoryOutputOffset + 0x01] = 0xFF;
// write BAM // write BAM
var bamOutputOffset = GetOutputOffset(17, 0); var bamOutputOffset = GetOutputOffset(17, 0);
bytes[bamOutputOffset + 0x00] = 18; bytes[bamOutputOffset + 0x00] = 18;
bytes[bamOutputOffset + 0x01] = 1; bytes[bamOutputOffset + 0x01] = 1;
bytes[bamOutputOffset + 0x02] = (byte)VersionType; bytes[bamOutputOffset + 0x02] = (byte)VersionType;
for (var i = 0; i < 35; i++) for (var i = 0; i < 35; i++)
{ {
Array.Copy(bam[i].GetBytes(), 0, bytes, bamOutputOffset + 4 + (i * 4), 4); Array.Copy(bam[i].GetBytes(), 0, bytes, bamOutputOffset + 4 + (i * 4), 4);
} }
for (var i = 0x90; i <= 0xAA; i++) for (var i = 0x90; i <= 0xAA; i++)
{ {
bytes[bamOutputOffset + i] = 0xA0; bytes[bamOutputOffset + i] = 0xA0;
} }
var titleBytes = Encoding.ASCII.GetBytes(Title ?? "UNTITLED"); var titleBytes = Encoding.ASCII.GetBytes(Title ?? "UNTITLED");
Array.Copy(titleBytes, 0, bytes, bamOutputOffset + 0x90, Math.Min(titleBytes.Length, 0x10)); Array.Copy(titleBytes, 0, bytes, bamOutputOffset + 0x90, Math.Min(titleBytes.Length, 0x10));
return D64.Read(bytes); return D64.Read(bytes);
} }
} }
} }

View File

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

View File

@ -7,22 +7,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
public static void Load(Chip90611401 pla, byte[] prgFile) public static void Load(Chip90611401 pla, byte[] prgFile)
{ {
var length = prgFile.Length; var length = prgFile.Length;
if (length <= 2) if (length <= 2)
{ {
return; return;
} }
var addr = prgFile[0] | (prgFile[1] << 8); var addr = prgFile[0] | (prgFile[1] << 8);
var offset = 2; var offset = 2;
unchecked unchecked
{ {
while (offset < length) while (offset < length)
{ {
pla.Write(addr, prgFile[offset]); pla.Write(addr, prgFile[offset]);
offset++; offset++;
addr++; addr++;
} }
} }
} }
} }
} }

View File

@ -13,305 +13,305 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{ {
internal static class SaveState internal static class SaveState
{ {
public class DoNotSave : Attribute public class DoNotSave : Attribute
{ {
} }
public class SaveWithName : Attribute public class SaveWithName : Attribute
{ {
public string Name { get; set; } public string Name { get; set; }
public SaveWithName(string name) public SaveWithName(string name)
{ {
Name = name; Name = name;
} }
} }
private static readonly Encoding Encoding = Encoding.Unicode; private static readonly Encoding Encoding = Encoding.Unicode;
private static int[] GetDelta(IList<int> source, IList<int> data) private static int[] GetDelta(IList<int> source, IList<int> data)
{ {
var length = Math.Min(source.Count, data.Count); var length = Math.Min(source.Count, data.Count);
var delta = new int[length]; var delta = new int[length];
for (var i = 0; i < length; i++) for (var i = 0; i < length; i++)
{ {
delta[i] = source[i] ^ data[i]; delta[i] = source[i] ^ data[i];
} }
return delta; return delta;
} }
private static byte[] CompressInts(int[] data) private static byte[] CompressInts(int[] data)
{ {
unchecked unchecked
{ {
var length = data.Length; var length = data.Length;
var bytes = new byte[length * 4]; var bytes = new byte[length * 4];
for (int i = 0, j = 0; i < length; i++) for (int i = 0, j = 0; i < length; i++)
{ {
var c = data[i]; var c = data[i];
bytes[j++] = (byte)(c); bytes[j++] = (byte)(c);
bytes[j++] = (byte)(c >> 8); bytes[j++] = (byte)(c >> 8);
bytes[j++] = (byte)(c >> 16); bytes[j++] = (byte)(c >> 16);
bytes[j++] = (byte)(c >> 24); bytes[j++] = (byte)(c >> 24);
} }
using (var mem = new MemoryStream()) using (var mem = new MemoryStream())
{ {
using (var compressor = new DeflateStream(mem, CompressionMode.Compress)) using (var compressor = new DeflateStream(mem, CompressionMode.Compress))
{ {
var writer = new BinaryWriter(compressor); var writer = new BinaryWriter(compressor);
writer.Write(bytes.Length); writer.Write(bytes.Length);
writer.Write(bytes); writer.Write(bytes);
compressor.Flush(); compressor.Flush();
} }
mem.Flush(); mem.Flush();
return mem.ToArray(); return mem.ToArray();
} }
} }
} }
private static int[] DecompressInts(byte[] data) private static int[] DecompressInts(byte[] data)
{ {
unchecked unchecked
{ {
using (var mem = new MemoryStream(data)) using (var mem = new MemoryStream(data))
{ {
using (var decompressor = new DeflateStream(mem, CompressionMode.Decompress)) using (var decompressor = new DeflateStream(mem, CompressionMode.Decompress))
{ {
var reader = new BinaryReader(decompressor); var reader = new BinaryReader(decompressor);
var length = reader.ReadInt32(); var length = reader.ReadInt32();
var bytes = reader.ReadBytes(length); var bytes = reader.ReadBytes(length);
var result = new int[length >> 2]; var result = new int[length >> 2];
for (int i = 0, j = 0; i < length; i++) for (int i = 0, j = 0; i < length; i++)
{ {
int d = bytes[i++]; int d = bytes[i++];
d |= bytes[i++] << 8; d |= bytes[i++] << 8;
d |= bytes[i++] << 16; d |= bytes[i++] << 16;
d |= bytes[i] << 24; d |= bytes[i] << 24;
result[j++] = d; result[j++] = d;
} }
return result; return result;
} }
} }
} }
} }
public static void SyncDelta(string name, Serializer ser, int[] source, ref int[] data) public static void SyncDelta(string name, Serializer ser, int[] source, ref int[] data)
{ {
int[] delta = null; int[] delta = null;
if (ser.IsWriter && data != null) if (ser.IsWriter && data != null)
{ {
delta = GetDelta(source, data); delta = GetDelta(source, data);
} }
ser.Sync(name, ref delta, false); ser.Sync(name, ref delta, false);
if (ser.IsReader && delta != null) if (ser.IsReader && delta != null)
{ {
data = GetDelta(source, delta); data = GetDelta(source, delta);
} }
} }
public static void SyncObject(Serializer ser, object obj) public static void SyncObject(Serializer ser, object obj)
{ {
const BindingFlags defaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; const BindingFlags defaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
var objType = obj.GetType(); var objType = obj.GetType();
var members = objType.GetMembers(defaultFlags); var members = objType.GetMembers(defaultFlags);
foreach (var member in members) foreach (var member in members)
{ {
if (member.GetCustomAttributes(true).Any(a => a is DoNotSave)) if (member.GetCustomAttributes(true).Any(a => a is DoNotSave))
{ {
continue; continue;
} }
var name = member.Name; var name = member.Name;
var nameAttribute = member.GetCustomAttributes(true).FirstOrDefault(a => a is SaveWithName); var nameAttribute = member.GetCustomAttributes(true).FirstOrDefault(a => a is SaveWithName);
if (nameAttribute != null) if (nameAttribute != null)
{ {
name = ((SaveWithName) nameAttribute).Name; name = ((SaveWithName)nameAttribute).Name;
} }
object currentValue = null; object currentValue = null;
var fail = false; var fail = false;
var fieldInfo = member as FieldInfo; var fieldInfo = member as FieldInfo;
Type valueType = null; Type valueType = null;
if ((member.MemberType == MemberTypes.Field) && member.ReflectedType != null) if ((member.MemberType == MemberTypes.Field) && member.ReflectedType != null)
{ {
valueType = fieldInfo.FieldType; valueType = fieldInfo.FieldType;
currentValue = fieldInfo.GetValue(obj); currentValue = fieldInfo.GetValue(obj);
} }
if (currentValue != null) if (currentValue != null)
{ {
ByteBuffer refByteBuffer; ByteBuffer refByteBuffer;
int refInt32; int refInt32;
IntBuffer refIntBuffer; IntBuffer refIntBuffer;
int refPointX; int refPointX;
int refPointY; int refPointY;
switch (valueType.Name) switch (valueType.Name)
{ {
case "Action`1": case "Action`1":
case "Action`2": case "Action`2":
break; break;
case "Bit": case "Bit":
var refBit = (Bit)currentValue; var refBit = (Bit)currentValue;
ser.Sync(name, ref refBit); ser.Sync(name, ref refBit);
currentValue = refBit; currentValue = refBit;
break; break;
case "Boolean": case "Boolean":
var refBool = (bool)currentValue; var refBool = (bool)currentValue;
ser.Sync(name, ref refBool); ser.Sync(name, ref refBool);
currentValue = refBool; currentValue = refBool;
break; break;
case "Boolean[]": case "Boolean[]":
{ {
var tmp = (bool[])currentValue; var tmp = (bool[])currentValue;
ser.Sync(name, ref tmp, false); ser.Sync(name, ref tmp, false);
currentValue = tmp; currentValue = tmp;
} }
break; break;
case "Byte": case "Byte":
var refByte = (byte)currentValue; var refByte = (byte)currentValue;
ser.Sync(name, ref refByte); ser.Sync(name, ref refByte);
currentValue = refByte; currentValue = refByte;
break; break;
case "Byte[]": case "Byte[]":
refByteBuffer = new ByteBuffer((byte[])currentValue); refByteBuffer = new ByteBuffer((byte[])currentValue);
ser.Sync(name, ref refByteBuffer); ser.Sync(name, ref refByteBuffer);
currentValue = refByteBuffer.Arr.Select(d => d).ToArray(); currentValue = refByteBuffer.Arr.Select(d => d).ToArray();
refByteBuffer.Dispose(); refByteBuffer.Dispose();
break; break;
case "ByteBuffer": case "ByteBuffer":
refByteBuffer = (ByteBuffer)currentValue; refByteBuffer = (ByteBuffer)currentValue;
ser.Sync(name, ref refByteBuffer); ser.Sync(name, ref refByteBuffer);
currentValue = refByteBuffer; currentValue = refByteBuffer;
break; break;
case "Func`1": case "Func`1":
case "Func`2": case "Func`2":
break; break;
case "Int16": case "Int16":
var refInt16 = (short)currentValue; var refInt16 = (short)currentValue;
ser.Sync(name, ref refInt16); ser.Sync(name, ref refInt16);
currentValue = refInt16; currentValue = refInt16;
break; break;
case "Int32": case "Int32":
refInt32 = (int)currentValue; refInt32 = (int)currentValue;
ser.Sync(name, ref refInt32); ser.Sync(name, ref refInt32);
currentValue = refInt32; currentValue = refInt32;
break; break;
case "Int32[]": case "Int32[]":
refIntBuffer = new IntBuffer((int[])currentValue); refIntBuffer = new IntBuffer((int[])currentValue);
ser.Sync(name, ref refIntBuffer); ser.Sync(name, ref refIntBuffer);
currentValue = refIntBuffer.Arr.Select(d => d).ToArray(); currentValue = refIntBuffer.Arr.Select(d => d).ToArray();
refIntBuffer.Dispose(); refIntBuffer.Dispose();
break; break;
case "IntBuffer": case "IntBuffer":
refIntBuffer = (IntBuffer)currentValue; refIntBuffer = (IntBuffer)currentValue;
ser.Sync(name, ref refIntBuffer); ser.Sync(name, ref refIntBuffer);
currentValue = refIntBuffer; currentValue = refIntBuffer;
break; break;
case "Point": case "Point":
refPointX = ((Point)currentValue).X; refPointX = ((Point)currentValue).X;
refPointY = ((Point)currentValue).Y; refPointY = ((Point)currentValue).Y;
ser.Sync(name + "_X", ref refPointX); ser.Sync(name + "_X", ref refPointX);
ser.Sync(name + "_Y", ref refPointY); ser.Sync(name + "_Y", ref refPointY);
currentValue = new Point(refPointX, refPointY); currentValue = new Point(refPointX, refPointY);
break; break;
case "Rectangle": case "Rectangle":
refPointX = ((Rectangle)currentValue).X; refPointX = ((Rectangle)currentValue).X;
refPointY = ((Rectangle)currentValue).Y; refPointY = ((Rectangle)currentValue).Y;
var refRectWidth = ((Rectangle)currentValue).Width; var refRectWidth = ((Rectangle)currentValue).Width;
var refRectHeight = ((Rectangle)currentValue).Height; var refRectHeight = ((Rectangle)currentValue).Height;
ser.Sync(name + "_X", ref refPointX); ser.Sync(name + "_X", ref refPointX);
ser.Sync(name + "_Y", ref refPointY); ser.Sync(name + "_Y", ref refPointY);
ser.Sync(name + "_Height", ref refRectHeight); ser.Sync(name + "_Height", ref refRectHeight);
ser.Sync(name + "_Width", ref refRectWidth); ser.Sync(name + "_Width", ref refRectWidth);
currentValue = new Rectangle(refPointX, refPointY, refRectWidth, refRectHeight); currentValue = new Rectangle(refPointX, refPointY, refRectWidth, refRectHeight);
break; break;
case "SByte": case "SByte":
var refSByte = (sbyte)currentValue; var refSByte = (sbyte)currentValue;
ser.Sync(name, ref refSByte); ser.Sync(name, ref refSByte);
currentValue = refSByte; currentValue = refSByte;
break; break;
case "String": case "String":
var refString = (string)currentValue; var refString = (string)currentValue;
var refVal = new ByteBuffer(Encoding.GetBytes(refString)); var refVal = new ByteBuffer(Encoding.GetBytes(refString));
ser.Sync(name, ref refVal); ser.Sync(name, ref refVal);
currentValue = Encoding.GetString(refVal.Arr); currentValue = Encoding.GetString(refVal.Arr);
refVal.Dispose(); refVal.Dispose();
break; break;
case "UInt16": case "UInt16":
var refUInt16 = (ushort)currentValue; var refUInt16 = (ushort)currentValue;
ser.Sync(name, ref refUInt16); ser.Sync(name, ref refUInt16);
currentValue = refUInt16; currentValue = refUInt16;
break; break;
case "UInt32": case "UInt32":
var refUInt32 = (uint)currentValue; var refUInt32 = (uint)currentValue;
ser.Sync(name, ref refUInt32); ser.Sync(name, ref refUInt32);
currentValue = refUInt32; currentValue = refUInt32;
break; break;
default: default:
var t = currentValue.GetType(); var t = currentValue.GetType();
if (t.IsEnum) if (t.IsEnum)
{ {
refInt32 = (int)currentValue; refInt32 = (int)currentValue;
ser.Sync(name, ref refInt32); ser.Sync(name, ref refInt32);
currentValue = refInt32; currentValue = refInt32;
} }
else if (t.IsArray) else if (t.IsArray)
{ {
var currentValueArray = (Array) currentValue; var currentValueArray = (Array)currentValue;
for (var i = 0; i < currentValueArray.Length; i++) for (var i = 0; i < currentValueArray.Length; i++)
{ {
ser.BeginSection(string.Format("{0}_{1}", name, i)); ser.BeginSection(string.Format("{0}_{1}", name, i));
SyncObject(ser, currentValueArray.GetValue(i)); SyncObject(ser, currentValueArray.GetValue(i));
ser.EndSection(); ser.EndSection();
} }
} }
else if (t.IsValueType) else if (t.IsValueType)
{ {
fail = true; fail = true;
} }
else if (t.IsClass) else if (t.IsClass)
{ {
fail = true; fail = true;
foreach (var method in t.GetMethods().Where(method => method.Name == "SyncState")) foreach (var method in t.GetMethods().Where(method => method.Name == "SyncState"))
{ {
ser.BeginSection(fieldInfo.Name); ser.BeginSection(fieldInfo.Name);
method.Invoke(currentValue, new object[] { ser }); method.Invoke(currentValue, new object[] { ser });
ser.EndSection(); ser.EndSection();
fail = false; fail = false;
break; break;
} }
} }
else else
{ {
fail = true; fail = true;
} }
break; break;
} }
} }
if (!fail) if (!fail)
{ {
if (member.MemberType == MemberTypes.Property) if (member.MemberType == MemberTypes.Property)
{ {
var propInfo = member as PropertyInfo; var propInfo = member as PropertyInfo;
if (propInfo.CanWrite) if (propInfo.CanWrite)
{ {
var setMethod = propInfo.GetSetMethod(); var setMethod = propInfo.GetSetMethod();
if (setMethod != null) if (setMethod != null)
{ {
setMethod.Invoke(obj, new[] { currentValue }); setMethod.Invoke(obj, new[] { currentValue });
} }
} }
} }
else if (member.MemberType == MemberTypes.Field) else if (member.MemberType == MemberTypes.Field)
{ {
fieldInfo.SetValue(obj, currentValue); fieldInfo.SetValue(obj, currentValue);
} }
} }
} }
} }
} }
} }

View File

@ -6,161 +6,161 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public sealed partial class Drive1541 public sealed partial class Drive1541
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const long LEHMER_RNG_PRIME = 48271; private const long LEHMER_RNG_PRIME = 48271;
[SaveState.SaveWithName("DiskDensityCounter")] [SaveState.SaveWithName("DiskDensityCounter")]
private int _diskDensityCounter; // density .. 16 private int _diskDensityCounter; // density .. 16
[SaveState.SaveWithName("DiskSupplementaryCounter")] [SaveState.SaveWithName("DiskSupplementaryCounter")]
private int _diskSupplementaryCounter; // 0 .. 16 private int _diskSupplementaryCounter; // 0 .. 16
[SaveState.SaveWithName("DiskFluxReversalDetected")] [SaveState.SaveWithName("DiskFluxReversalDetected")]
private bool _diskFluxReversalDetected; private bool _diskFluxReversalDetected;
[SaveState.SaveWithName("DiskBitsRemainingInDataEntry")] [SaveState.SaveWithName("DiskBitsRemainingInDataEntry")]
private int _diskBitsLeft; private int _diskBitsLeft;
[SaveState.SaveWithName("DiskDataEntryIndex")] [SaveState.SaveWithName("DiskDataEntryIndex")]
private int _diskByteOffset; private int _diskByteOffset;
[SaveState.SaveWithName("DiskDataEntry")] [SaveState.SaveWithName("DiskDataEntry")]
private int _diskBits; private int _diskBits;
[SaveState.SaveWithName("DiskCurrentCycle")] [SaveState.SaveWithName("DiskCurrentCycle")]
private int _diskCycle; private int _diskCycle;
[SaveState.SaveWithName("DiskDensityConfig")] [SaveState.SaveWithName("DiskDensityConfig")]
private int _diskDensity; private int _diskDensity;
[SaveState.SaveWithName("PreviousCA1")] [SaveState.SaveWithName("PreviousCA1")]
private bool _previousCa1; private bool _previousCa1;
[SaveState.SaveWithName("CountsBeforeRandomTransition")] [SaveState.SaveWithName("CountsBeforeRandomTransition")]
private int _countsBeforeRandomTransition; private int _countsBeforeRandomTransition;
[SaveState.SaveWithName("CurrentRNG")] [SaveState.SaveWithName("CurrentRNG")]
private int _rngCurrent; private int _rngCurrent;
[SaveState.SaveWithName("Clocks")] [SaveState.SaveWithName("Clocks")]
private int _clocks; private int _clocks;
[SaveState.SaveWithName("CpuClocks")] [SaveState.SaveWithName("CpuClocks")]
private int _cpuClocks; private int _cpuClocks;
// Lehmer RNG // Lehmer RNG
private void AdvanceRng() private void AdvanceRng()
{ {
if (_rngCurrent == 0) if (_rngCurrent == 0)
_rngCurrent = 1; _rngCurrent = 1;
_rngCurrent = (int)(_rngCurrent * LEHMER_RNG_PRIME % int.MaxValue); _rngCurrent = (int)(_rngCurrent * LEHMER_RNG_PRIME % int.MaxValue);
} }
private void ExecuteFlux() private void ExecuteFlux()
{ {
// This actually executes the main 16mhz clock // This actually executes the main 16mhz clock
while (_clocks > 0) while (_clocks > 0)
{ {
_clocks--; _clocks--;
// rotate disk // rotate disk
if (_motorEnabled) if (_motorEnabled)
{ {
if (_disk == null) if (_disk == null)
{ {
_diskBitsLeft = 1; _diskBitsLeft = 1;
_diskBits = 0; _diskBits = 0;
} }
else else
{ {
if (_diskBitsLeft <= 0) if (_diskBitsLeft <= 0)
{ {
_diskByteOffset++; _diskByteOffset++;
if (_diskByteOffset == Disk.FluxEntriesPerTrack) if (_diskByteOffset == Disk.FluxEntriesPerTrack)
{ {
_diskByteOffset = 0; _diskByteOffset = 0;
} }
_diskBits = _trackImageData[_diskByteOffset]; _diskBits = _trackImageData[_diskByteOffset];
_diskBitsLeft = Disk.FluxBitsPerEntry; _diskBitsLeft = Disk.FluxBitsPerEntry;
} }
} }
if ((_diskBits & 1) != 0) if ((_diskBits & 1) != 0)
{ {
_countsBeforeRandomTransition = 0; _countsBeforeRandomTransition = 0;
_diskFluxReversalDetected = true; _diskFluxReversalDetected = true;
} }
_diskBits >>= 1; _diskBits >>= 1;
_diskBitsLeft--; _diskBitsLeft--;
} }
// random flux transition readings for unformatted data // random flux transition readings for unformatted data
if (_countsBeforeRandomTransition > 0) if (_countsBeforeRandomTransition > 0)
{ {
_countsBeforeRandomTransition--; _countsBeforeRandomTransition--;
if (_countsBeforeRandomTransition == 0) if (_countsBeforeRandomTransition == 0)
{ {
_diskFluxReversalDetected = true; _diskFluxReversalDetected = true;
AdvanceRng(); AdvanceRng();
// This constant is what VICE uses. TODO: Determine accuracy. // This constant is what VICE uses. TODO: Determine accuracy.
_countsBeforeRandomTransition = (_rngCurrent % 367) + 33; _countsBeforeRandomTransition = (_rngCurrent % 367) + 33;
} }
} }
// flux transition circuitry // flux transition circuitry
if (_diskFluxReversalDetected) if (_diskFluxReversalDetected)
{ {
_diskDensityCounter = _diskDensity; _diskDensityCounter = _diskDensity;
_diskSupplementaryCounter = 0; _diskSupplementaryCounter = 0;
_diskFluxReversalDetected = false; _diskFluxReversalDetected = false;
if (_countsBeforeRandomTransition == 0) if (_countsBeforeRandomTransition == 0)
{ {
AdvanceRng(); AdvanceRng();
// This constant is what VICE uses. TODO: Determine accuracy. // This constant is what VICE uses. TODO: Determine accuracy.
_countsBeforeRandomTransition = (_rngCurrent & 0x1F) + 289; _countsBeforeRandomTransition = (_rngCurrent & 0x1F) + 289;
} }
} }
// counter circuitry // counter circuitry
if (_diskDensityCounter >= 16) if (_diskDensityCounter >= 16)
{ {
_diskDensityCounter = _diskDensity; _diskDensityCounter = _diskDensity;
_diskSupplementaryCounter++; _diskSupplementaryCounter++;
if ((_diskSupplementaryCounter & 0x3) == 0x2) if ((_diskSupplementaryCounter & 0x3) == 0x2)
{ {
_bitsRemainingInLatchedByte--; _bitsRemainingInLatchedByte--;
_byteReady = false; _byteReady = false;
_bitHistory = (_bitHistory << 1) | ((_diskSupplementaryCounter & 0xC) == 0x0 ? 1 : 0); _bitHistory = (_bitHistory << 1) | ((_diskSupplementaryCounter & 0xC) == 0x0 ? 1 : 0);
_sync = false; _sync = false;
if (Via1.Cb2 && (_bitHistory & 0x3FF) == 0x3FF) if (Via1.Cb2 && (_bitHistory & 0x3FF) == 0x3FF)
{ {
_sync = true; _sync = true;
_bitsRemainingInLatchedByte = 8; _bitsRemainingInLatchedByte = 8;
_byteReady = false; _byteReady = false;
} }
if (_bitsRemainingInLatchedByte <= 0) if (_bitsRemainingInLatchedByte <= 0)
{ {
_bitsRemainingInLatchedByte = 8; _bitsRemainingInLatchedByte = 8;
// SOE (sync output enabled) // SOE (sync output enabled)
_byteReady = Via1.Ca2; _byteReady = Via1.Ca2;
} }
// negative transition activates SO pin on CPU // negative transition activates SO pin on CPU
_previousCa1 = Via1.Ca1; _previousCa1 = Via1.Ca1;
Via1.Ca1 = !_byteReady; Via1.Ca1 = !_byteReady;
if (_previousCa1 && !Via1.Ca1) if (_previousCa1 && !Via1.Ca1)
{ {
// cycle 6 is roughly 400ns // cycle 6 is roughly 400ns
_overflowFlagDelaySr |= _diskCycle > 6 ? 4 : 2; _overflowFlagDelaySr |= _diskCycle > 6 ? 4 : 2;
} }
} }
} }
if (_diskSupplementaryCounter >= 16) if (_diskSupplementaryCounter >= 16)
{ {
_diskSupplementaryCounter = 0; _diskSupplementaryCounter = 0;
} }
_cpuClocks--; _cpuClocks--;
if (_cpuClocks <= 0) if (_cpuClocks <= 0)
{ {
ExecuteSystem(); ExecuteSystem();
_cpuClocks = 16; _cpuClocks = 16;
} }
_diskDensityCounter++; _diskDensityCounter++;
_diskCycle = (_diskCycle + 1) & 0xF; _diskCycle = (_diskCycle + 1) & 0xF;
} }
} }
} }
} }

View File

@ -6,157 +6,157 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public sealed partial class Drive1541 : IDebuggable public sealed partial class Drive1541 : IDebuggable
{ {
IDictionary<string, RegisterValue> IDebuggable.GetCpuFlagsAndRegisters() IDictionary<string, RegisterValue> IDebuggable.GetCpuFlagsAndRegisters()
{ {
return new Dictionary<string, RegisterValue> return new Dictionary<string, RegisterValue>
{ {
{ "A", _cpu.A }, { "A", _cpu.A },
{ "X", _cpu.X }, { "X", _cpu.X },
{ "Y", _cpu.Y }, { "Y", _cpu.Y },
{ "S", _cpu.S }, { "S", _cpu.S },
{ "PC", _cpu.PC }, { "PC", _cpu.PC },
{ "Flag C", _cpu.FlagC }, { "Flag C", _cpu.FlagC },
{ "Flag Z", _cpu.FlagZ }, { "Flag Z", _cpu.FlagZ },
{ "Flag I", _cpu.FlagI }, { "Flag I", _cpu.FlagI },
{ "Flag D", _cpu.FlagD }, { "Flag D", _cpu.FlagD },
{ "Flag B", _cpu.FlagB }, { "Flag B", _cpu.FlagB },
{ "Flag V", _cpu.FlagV }, { "Flag V", _cpu.FlagV },
{ "Flag N", _cpu.FlagN }, { "Flag N", _cpu.FlagN },
{ "Flag T", _cpu.FlagT } { "Flag T", _cpu.FlagT }
}; };
} }
void IDebuggable.SetCpuRegister(string register, int value) void IDebuggable.SetCpuRegister(string register, int value)
{ {
switch (register) switch (register)
{ {
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
case "A": case "A":
_cpu.A = (byte)value; _cpu.A = (byte)value;
break; break;
case "X": case "X":
_cpu.X = (byte)value; _cpu.X = (byte)value;
break; break;
case "Y": case "Y":
_cpu.Y = (byte)value; _cpu.Y = (byte)value;
break; break;
case "S": case "S":
_cpu.S = (byte)value; _cpu.S = (byte)value;
break; break;
case "PC": case "PC":
_cpu.PC = (ushort)value; _cpu.PC = (ushort)value;
break; break;
} }
} }
bool IDebuggable.CanStep(StepType type) bool IDebuggable.CanStep(StepType type)
{ {
switch (type) switch (type)
{ {
case StepType.Into: case StepType.Into:
case StepType.Over: case StepType.Over:
case StepType.Out: case StepType.Out:
return DebuggerStep != null; return DebuggerStep != null;
default: default:
return false; return false;
} }
} }
void IDebuggable.Step(StepType type) void IDebuggable.Step(StepType type)
{ {
switch (type) switch (type)
{ {
case StepType.Into: case StepType.Into:
StepInto(); StepInto();
break; break;
case StepType.Out: case StepType.Out:
StepOut(); StepOut();
break; break;
case StepType.Over: case StepType.Over:
StepOver(); StepOver();
break; break;
} }
} }
int IDebuggable.TotalExecutedCycles int IDebuggable.TotalExecutedCycles
{ {
get { return _cpu.TotalExecutedCycles; } get { return _cpu.TotalExecutedCycles; }
} }
private void StepInto() private void StepInto()
{ {
while (_cpu.AtInstructionStart()) while (_cpu.AtInstructionStart())
{ {
DebuggerStep(); DebuggerStep();
} }
while (!_cpu.AtInstructionStart()) while (!_cpu.AtInstructionStart())
{ {
DebuggerStep(); DebuggerStep();
} }
} }
private void StepOver() private void StepOver()
{ {
var instruction = CpuPeek(_cpu.PC); var instruction = CpuPeek(_cpu.PC);
if (instruction == Jsr) if (instruction == Jsr)
{ {
var destination = _cpu.PC + JsrSize; var destination = _cpu.PC + JsrSize;
while (_cpu.PC != destination) while (_cpu.PC != destination)
{ {
StepInto(); StepInto();
} }
} }
else else
{ {
StepInto(); StepInto();
} }
} }
private void StepOut() private void StepOut()
{ {
var instructionsBeforeBailout = 1000000; var instructionsBeforeBailout = 1000000;
var instr = CpuPeek(_cpu.PC); var instr = CpuPeek(_cpu.PC);
_jsrCount = instr == Jsr ? 1 : 0; _jsrCount = instr == Jsr ? 1 : 0;
while (--instructionsBeforeBailout > 0) while (--instructionsBeforeBailout > 0)
{ {
StepInto(); StepInto();
instr = CpuPeek(_cpu.PC); instr = CpuPeek(_cpu.PC);
if (instr == Jsr) if (instr == Jsr)
{ {
_jsrCount++; _jsrCount++;
} }
else if ((instr == Rts || instr == Rti) && _jsrCount <= 0) else if ((instr == Rts || instr == Rti) && _jsrCount <= 0)
{ {
StepInto(); StepInto();
_jsrCount = 0; _jsrCount = 0;
break; break;
} }
else if (instr == Rts || instr == Rti) else if (instr == Rts || instr == Rti)
{ {
_jsrCount--; _jsrCount--;
} }
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int _jsrCount; private int _jsrCount;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte Jsr = 0x20; private const byte Jsr = 0x20;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte Rti = 0x40; private const byte Rti = 0x40;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte Rts = 0x60; private const byte Rts = 0x60;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private const byte JsrSize = 3; private const byte JsrSize = 3;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public IMemoryCallbackSystem MemoryCallbacks { get; private set; } public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
} }
} }

View File

@ -6,32 +6,32 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public sealed partial class Drive1541 : IDisassemblable public sealed partial class Drive1541 : IDisassemblable
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
IEnumerable<string> IDisassemblable.AvailableCpus IEnumerable<string> IDisassemblable.AvailableCpus
{ {
get { yield return "Disk Drive 6502"; } get { yield return "Disk Drive 6502"; }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
string IDisassemblable.Cpu string IDisassemblable.Cpu
{ {
get { return "Disk Drive 6502"; } get { return "Disk Drive 6502"; }
set set
{ {
} }
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
string IDisassemblable.PCRegisterName string IDisassemblable.PCRegisterName
{ {
get { return "PC"; } get { return "PC"; }
} }
string IDisassemblable.Disassemble(MemoryDomain m, uint addr, out int length) string IDisassemblable.Disassemble(MemoryDomain m, uint addr, out int length)
{ {
return Components.M6502.MOS6502X.Disassemble((ushort)addr, out length, CpuPeek); return Components.M6502.MOS6502X.Disassemble((ushort)addr, out length, CpuPeek);
} }
} }
} }

View File

@ -6,35 +6,35 @@ using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public sealed partial class Drive1541 public sealed partial class Drive1541
{ {
[SaveState.DoNotSave] private int _tempStep; [SaveState.DoNotSave] private int _tempStep;
[SaveState.DoNotSave] private int _tempPrB1; [SaveState.DoNotSave] private int _tempPrB1;
private void ExecuteMotor() private void ExecuteMotor()
{ {
_tempPrB1 = Via1.EffectivePrB; _tempPrB1 = Via1.EffectivePrB;
_tempStep = _tempPrB1 & 0x3; _tempStep = _tempPrB1 & 0x3;
_diskDensity = (_tempPrB1 & 0x60) >> 5; _diskDensity = (_tempPrB1 & 0x60) >> 5;
_motorEnabled = (_tempPrB1 & 0x04) != 0; _motorEnabled = (_tempPrB1 & 0x04) != 0;
_ledEnabled = (_tempPrB1 & 0x08) != 0; _ledEnabled = (_tempPrB1 & 0x08) != 0;
// motor track stepping // motor track stepping
if (_tempStep != _motorStep) if (_tempStep != _motorStep)
{ {
if (_tempStep == ((_motorStep - 1) & 0x3)) if (_tempStep == ((_motorStep - 1) & 0x3))
_trackNumber--; _trackNumber--;
else if (_tempStep == ((_motorStep + 1) & 0x3)) else if (_tempStep == ((_motorStep + 1) & 0x3))
_trackNumber++; _trackNumber++;
if (_trackNumber < 0) if (_trackNumber < 0)
_trackNumber = 0; _trackNumber = 0;
else if (_trackNumber > 83) else if (_trackNumber > 83)
_trackNumber = 83; _trackNumber = 83;
_motorStep = _tempStep; _motorStep = _tempStep;
UpdateMediaData(); UpdateMediaData();
} }
} }
} }
} }

View File

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

View File

@ -11,167 +11,167 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.MOS;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public sealed partial class Drive1541 : SerialPortDevice public sealed partial class Drive1541 : SerialPortDevice
{ {
[SaveState.SaveWithName("Disk")] [SaveState.SaveWithName("Disk")]
private Disk _disk; private Disk _disk;
[SaveState.SaveWithName("BitHistory")] [SaveState.SaveWithName("BitHistory")]
private int _bitHistory; private int _bitHistory;
[SaveState.SaveWithName("BitsRemainingInLatchedByte")] [SaveState.SaveWithName("BitsRemainingInLatchedByte")]
private int _bitsRemainingInLatchedByte; private int _bitsRemainingInLatchedByte;
[SaveState.SaveWithName("Sync")] [SaveState.SaveWithName("Sync")]
private bool _sync; private bool _sync;
[SaveState.SaveWithName("ByteReady")] [SaveState.SaveWithName("ByteReady")]
private bool _byteReady; private bool _byteReady;
[SaveState.SaveWithName("DriveCpuClockNumerator")] [SaveState.SaveWithName("DriveCpuClockNumerator")]
private readonly int _driveCpuClockNum; private readonly int _driveCpuClockNum;
[SaveState.SaveWithName("TrackNumber")] [SaveState.SaveWithName("TrackNumber")]
private int _trackNumber; private int _trackNumber;
[SaveState.SaveWithName("MotorEnabled")] [SaveState.SaveWithName("MotorEnabled")]
private bool _motorEnabled; private bool _motorEnabled;
[SaveState.SaveWithName("LedEnabled")] [SaveState.SaveWithName("LedEnabled")]
private bool _ledEnabled; private bool _ledEnabled;
[SaveState.SaveWithName("MotorStep")] [SaveState.SaveWithName("MotorStep")]
private int _motorStep; private int _motorStep;
[SaveState.SaveWithName("CPU")] [SaveState.SaveWithName("CPU")]
private readonly MOS6502X _cpu; private readonly MOS6502X _cpu;
[SaveState.SaveWithName("RAM")] [SaveState.SaveWithName("RAM")]
private readonly int[] _ram; private readonly int[] _ram;
[SaveState.SaveWithName("VIA0")] [SaveState.SaveWithName("VIA0")]
public readonly Via Via0; public readonly Via Via0;
[SaveState.SaveWithName("VIA1")] [SaveState.SaveWithName("VIA1")]
public readonly Via Via1; public readonly Via Via1;
[SaveState.SaveWithName("SystemCpuClockNumerator")] [SaveState.SaveWithName("SystemCpuClockNumerator")]
private readonly int _cpuClockNum; private readonly int _cpuClockNum;
[SaveState.SaveWithName("SystemDriveCpuRatioDifference")] [SaveState.SaveWithName("SystemDriveCpuRatioDifference")]
private int _ratioDifference; private int _ratioDifference;
[SaveState.SaveWithName("DriveLightOffTime")] [SaveState.SaveWithName("DriveLightOffTime")]
private int _driveLightOffTime; private int _driveLightOffTime;
[SaveState.DoNotSave] [SaveState.DoNotSave]
private int[] _trackImageData = new int[1]; private int[] _trackImageData = new int[1];
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<int> ReadIec = () => 0xFF; public Func<int> ReadIec = () => 0xFF;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Action DebuggerStep; public Action DebuggerStep;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public readonly Chip23128 DriveRom; public readonly Chip23128 DriveRom;
public Drive1541(int clockNum, int clockDen) public Drive1541(int clockNum, int clockDen)
{ {
DriveRom = new Chip23128(); DriveRom = new Chip23128();
_cpu = new MOS6502X _cpu = new MOS6502X
{ {
ReadMemory = CpuRead, ReadMemory = CpuRead,
WriteMemory = CpuWrite, WriteMemory = CpuWrite,
DummyReadMemory = CpuRead, DummyReadMemory = CpuRead,
PeekMemory = CpuPeek, PeekMemory = CpuPeek,
NMI = false NMI = false
}; };
_ram = new int[0x800]; _ram = new int[0x800];
Via0 = Chip6522.Create(ViaReadClock, ViaReadData, ViaReadAtn, 8); Via0 = Chip6522.Create(ViaReadClock, ViaReadData, ViaReadAtn, 8);
Via1 = Chip6522.Create(ReadVia1PrA, ReadVia1PrB); Via1 = Chip6522.Create(ReadVia1PrA, ReadVia1PrB);
_cpuClockNum = clockNum; _cpuClockNum = clockNum;
_driveCpuClockNum = clockDen*16000000; // 16mhz _driveCpuClockNum = clockDen * 16000000; // 16mhz
} }
public override void ExecutePhase() public override void ExecutePhase()
{ {
_ratioDifference += _driveCpuClockNum; _ratioDifference += _driveCpuClockNum;
while (_ratioDifference > _cpuClockNum) while (_ratioDifference > _cpuClockNum)
{ {
_ratioDifference -= _cpuClockNum; _ratioDifference -= _cpuClockNum;
_clocks++; _clocks++;
} }
ExecutePhaseInternal(); ExecutePhaseInternal();
} }
private void ExecutePhaseInternal() private void ExecutePhaseInternal()
{ {
// clock output from 325572-01 drives CPU clock (phi0) // clock output from 325572-01 drives CPU clock (phi0)
ExecuteMotor(); ExecuteMotor();
ExecuteFlux(); ExecuteFlux();
} }
private void ExecuteSystem() private void ExecuteSystem()
{ {
Via0.Ca1 = ViaReadAtn(); Via0.Ca1 = ViaReadAtn();
Via0.ExecutePhase(); Via0.ExecutePhase();
Via1.ExecutePhase(); Via1.ExecutePhase();
// SO pin pipeline // SO pin pipeline
if ((_overflowFlagDelaySr & 0x01) != 0) if ((_overflowFlagDelaySr & 0x01) != 0)
{ {
_cpu.SetOverflow(); _cpu.SetOverflow();
} }
_overflowFlagDelaySr >>= 1; _overflowFlagDelaySr >>= 1;
_cpu.IRQ = !(Via0.Irq && Via1.Irq); // active low IRQ line _cpu.IRQ = !(Via0.Irq && Via1.Irq); // active low IRQ line
_cpu.ExecuteOne(); _cpu.ExecuteOne();
if (_ledEnabled) if (_ledEnabled)
{ {
_driveLightOffTime = 25000; _driveLightOffTime = 25000;
} }
else if (_driveLightOffTime > 0) else if (_driveLightOffTime > 0)
{ {
_driveLightOffTime--; _driveLightOffTime--;
} }
} }
public override void HardReset() public override void HardReset()
{ {
Via0.HardReset(); Via0.HardReset();
Via1.HardReset(); Via1.HardReset();
_trackNumber = 34; _trackNumber = 34;
for (var i = 0; i < _ram.Length; i++) for (var i = 0; i < _ram.Length; i++)
{ {
_ram[i] = 0x00; _ram[i] = 0x00;
} }
_diskDensity = 0; _diskDensity = 0;
_diskFluxReversalDetected = false; _diskFluxReversalDetected = false;
_diskByteOffset = 0; _diskByteOffset = 0;
_diskBitsLeft = 0; _diskBitsLeft = 0;
_diskBits = 0; _diskBits = 0;
_driveLightOffTime = 0; _driveLightOffTime = 0;
_diskDensityCounter = 0; _diskDensityCounter = 0;
_diskSupplementaryCounter = 0; _diskSupplementaryCounter = 0;
_diskCycle = 0; _diskCycle = 0;
_previousCa1 = false; _previousCa1 = false;
_countsBeforeRandomTransition = 0; _countsBeforeRandomTransition = 0;
SoftReset(); SoftReset();
UpdateMediaData(); UpdateMediaData();
} }
public void SoftReset() public void SoftReset()
{ {
_cpu.NESSoftReset(); _cpu.NESSoftReset();
_overflowFlagDelaySr = 0; _overflowFlagDelaySr = 0;
} }
public void InsertMedia(Disk disk) public void InsertMedia(Disk disk)
{ {
_disk = disk; _disk = disk;
UpdateMediaData(); UpdateMediaData();
} }
private void UpdateMediaData() private void UpdateMediaData()
{ {
if (_disk != null) if (_disk != null)
{ {
_trackImageData = _disk.GetDataForTrack(_trackNumber); _trackImageData = _disk.GetDataForTrack(_trackNumber);
_diskBits = _trackImageData[_diskByteOffset] >> (Disk.FluxBitsPerEntry - _diskBitsLeft); _diskBits = _trackImageData[_diskByteOffset] >> (Disk.FluxBitsPerEntry - _diskBitsLeft);
} }
} }
public void RemoveMedia() public void RemoveMedia()
{ {
_disk = null; _disk = null;
_trackImageData = null; _trackImageData = null;
_diskBits = 0; _diskBits = 0;
} }
} }
} }

View File

@ -8,83 +8,83 @@ using BizHawk.Emulation.Cores.Computers.Commodore64.Cassette;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public sealed class SerialPort : IDriveLight public sealed class SerialPort : IDriveLight
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMasterAtn = () => true; public Func<bool> ReadMasterAtn = () => true;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMasterClk = () => true; public Func<bool> ReadMasterClk = () => true;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMasterData = () => true; public Func<bool> ReadMasterData = () => true;
[SaveState.SaveWithName("Device")] [SaveState.SaveWithName("Device")]
private SerialPortDevice _device; private SerialPortDevice _device;
[SaveState.SaveWithName("Connected")] [SaveState.SaveWithName("Connected")]
private bool _connected; private bool _connected;
public void HardReset() public void HardReset()
{ {
if (_connected) if (_connected)
{ {
_device.HardReset(); _device.HardReset();
} }
} }
public void ExecutePhase() public void ExecutePhase()
{ {
if (_connected) if (_connected)
{ {
_device.ExecutePhase(); _device.ExecutePhase();
} }
} }
public void ExecuteDeferred(int cycles) public void ExecuteDeferred(int cycles)
{ {
if (_connected) if (_connected)
{ {
_device.ExecuteDeferred(cycles); _device.ExecuteDeferred(cycles);
} }
} }
public bool ReadDeviceClock() public bool ReadDeviceClock()
{ {
return !_connected || _device.ReadDeviceClk(); return !_connected || _device.ReadDeviceClk();
} }
public bool ReadDeviceData() public bool ReadDeviceData()
{ {
return !_connected || _device.ReadDeviceData(); return !_connected || _device.ReadDeviceData();
} }
public bool ReadDeviceLight() public bool ReadDeviceLight()
{ {
return _connected && _device.ReadDeviceLight(); return _connected && _device.ReadDeviceLight();
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
public void Connect(SerialPortDevice device) public void Connect(SerialPortDevice device)
{ {
_connected = device != null; _connected = device != null;
_device = device; _device = device;
if (_device == null) if (_device == null)
{ {
return; return;
} }
_device.ReadMasterAtn = () => ReadMasterAtn(); _device.ReadMasterAtn = () => ReadMasterAtn();
_device.ReadMasterClk = () => ReadMasterClk(); _device.ReadMasterClk = () => ReadMasterClk();
_device.ReadMasterData = () => ReadMasterData(); _device.ReadMasterData = () => ReadMasterData();
} }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool DriveLightEnabled { get { return true; } } public bool DriveLightEnabled { get { return true; } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool DriveLightOn { get { return ReadDeviceLight(); } } public bool DriveLightOn { get { return ReadDeviceLight(); } }
[SaveState.DoNotSave] [SaveState.DoNotSave]
public bool IsConnected { get { return _connected; } } public bool IsConnected { get { return _connected; } }
} }
} }

View File

@ -6,45 +6,45 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{ {
public abstract class SerialPortDevice public abstract class SerialPortDevice
{ {
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMasterAtn = () => true; public Func<bool> ReadMasterAtn = () => true;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMasterClk = () => true; public Func<bool> ReadMasterClk = () => true;
[SaveState.DoNotSave] [SaveState.DoNotSave]
public Func<bool> ReadMasterData = () => true; public Func<bool> ReadMasterData = () => true;
public virtual void ExecutePhase() public virtual void ExecutePhase()
{ {
} }
public virtual void ExecuteDeferred(int cycles) public virtual void ExecuteDeferred(int cycles)
{ {
} }
public virtual void HardReset() public virtual void HardReset()
{ {
} }
public virtual bool ReadDeviceClk() public virtual bool ReadDeviceClk()
{ {
return true; return true;
} }
public virtual bool ReadDeviceData() public virtual bool ReadDeviceData()
{ {
return true; return true;
} }
public virtual bool ReadDeviceLight() public virtual bool ReadDeviceLight()
{ {
return false; return false;
} }
public virtual void SyncState(Serializer ser) public virtual void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }

View File

@ -3,73 +3,73 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.User namespace BizHawk.Emulation.Cores.Computers.Commodore64.User
{ {
public sealed class UserPort public sealed class UserPort
{ {
public Func<bool> ReadCounter1; public Func<bool> ReadCounter1;
public Func<bool> ReadCounter2; public Func<bool> ReadCounter2;
public Func<bool> ReadHandshake; public Func<bool> ReadHandshake;
public Func<bool> ReadSerial1; public Func<bool> ReadSerial1;
public Func<bool> ReadSerial2; public Func<bool> ReadSerial2;
private bool _connected; private bool _connected;
private UserPortDevice _device; private UserPortDevice _device;
public void Connect(UserPortDevice device) public void Connect(UserPortDevice device)
{ {
_device = device; _device = device;
_connected = _device != null; _connected = _device != null;
if (_device != null) if (_device != null)
{ {
_device.ReadCounter1 = () => ReadCounter1(); _device.ReadCounter1 = () => ReadCounter1();
_device.ReadCounter2 = () => ReadCounter2(); _device.ReadCounter2 = () => ReadCounter2();
_device.ReadHandshake = () => ReadHandshake(); _device.ReadHandshake = () => ReadHandshake();
_device.ReadSerial1 = () => ReadSerial1(); _device.ReadSerial1 = () => ReadSerial1();
_device.ReadSerial2 = () => ReadSerial2(); _device.ReadSerial2 = () => ReadSerial2();
} }
} }
public void Disconnect() public void Disconnect()
{ {
_connected = false; _connected = false;
_device = null; _device = null;
} }
public void HardReset() public void HardReset()
{ {
if (_connected) if (_connected)
{ {
_device.HardReset(); _device.HardReset();
} }
} }
public bool ReadAtn() public bool ReadAtn()
{ {
return !_connected || _device.ReadAtn(); return !_connected || _device.ReadAtn();
} }
public int ReadData() public int ReadData()
{ {
return !_connected ? 0xFF : _device.ReadData(); return !_connected ? 0xFF : _device.ReadData();
} }
public bool ReadFlag2() public bool ReadFlag2()
{ {
return !_connected || _device.ReadFlag2(); return !_connected || _device.ReadFlag2();
} }
public bool ReadPa2() public bool ReadPa2()
{ {
return !_connected || _device.ReadPa2(); return !_connected || _device.ReadPa2();
} }
public bool ReadReset() public bool ReadReset()
{ {
return !_connected || _device.ReadReset(); return !_connected || _device.ReadReset();
} }
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
} }
} }
} }