diff --git a/ExternalCoreProjects/Virtu/DiskDsk.cs b/ExternalCoreProjects/Virtu/DiskDsk.cs index ff60fc1771..9165e10382 100644 --- a/ExternalCoreProjects/Virtu/DiskDsk.cs +++ b/ExternalCoreProjects/Virtu/DiskDsk.cs @@ -3,7 +3,7 @@ namespace Jellyfish.Virtu { // ReSharper disable once UnusedMember.Global - internal enum SectorSkew { None = 0, Dos, ProDos }; + internal enum SectorSkew { None = 0, Dos, ProDos } internal sealed class DiskDsk : Disk525 { @@ -314,6 +314,8 @@ namespace Jellyfish.Virtu 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; +#pragma warning disable SA1137 + private static readonly byte[] NibbleToByte = { // padding for offset (not used) @@ -329,7 +331,7 @@ namespace Jellyfish.Virtu 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, // nibble translate table - 0x00, 0x01, 0x98, 0x99, 0x02, 0x03, 0x9C, 0x04, 0x05, 0x06, + 0x00, 0x01, 0x98, 0x99, 0x02, 0x03, 0x9C, 0x04, 0x05, 0x06, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x07, 0x08, 0xA8, 0xA9, 0xAA, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xB0, 0xB1, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xB8, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x1B, 0xCC, 0x1C, 0x1D, 0x1E, @@ -337,5 +339,7 @@ namespace Jellyfish.Virtu 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x29, 0x2A, 0x2B, 0xE8, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0xF0, 0xF1, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xF8, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; + +#pragma warning restore SA1137 } } diff --git a/ExternalCoreProjects/Virtu/MachineEvents.cs b/ExternalCoreProjects/Virtu/MachineEvents.cs index 0f7d97414d..6ee5d3d558 100644 --- a/ExternalCoreProjects/Virtu/MachineEvents.cs +++ b/ExternalCoreProjects/Virtu/MachineEvents.cs @@ -37,10 +37,10 @@ namespace Jellyfish.Virtu { if (ser.IsReader) { - int[] usedDelta = new int[0]; - int[] usedType = new int[0]; - int[] freeDelta = new int[0]; - int[] freeType = new int[0]; + int[] usedDelta = Array.Empty(); + int[] usedType = Array.Empty(); + int[] freeDelta = Array.Empty(); + int[] freeType = Array.Empty(); ser.Sync("UsedDelta", ref usedDelta, false); ser.Sync("UsedType", ref usedType, false); diff --git a/ExternalCoreProjects/Virtu/Memory.cs b/ExternalCoreProjects/Virtu/Memory.cs index 7f73313332..199110de20 100644 --- a/ExternalCoreProjects/Virtu/Memory.cs +++ b/ExternalCoreProjects/Virtu/Memory.cs @@ -334,6 +334,80 @@ namespace Jellyfish.Virtu _zeroPage[address] = (byte)data; } + public byte PeekMainRam(int address) + { + return address switch + { + > 0 and < 0x0200 => _ramMainRegion0001[address - 0], + > 0x0200 and < 0xC000 => _ramMainRegion02BF[address - 0x0200], + > 0xC000 and < 0xD000 => _ramMainBank1RegionD0DF[address - 0xC000], + > 0xD000 and < 0xE000 => _ramMainBank2RegionD0DF[address - 0xD000], + > 0xE000 and < 0x10000 => _ramMainRegionE0FF[address - 0xE000], + _ => throw new InvalidOperationException() + }; + } + + public void PokeMainRam(int address, byte value) + { + switch (address) + { + case > 0 and < 0x0200: + _ramMainRegion0001[address - 0] = value; + break; + case > 0x0200 and < 0xC000: + _ramMainRegion02BF[address - 0x0200] = value; + break; + case > 0xC000 and < 0xD000: + _ramMainBank1RegionD0DF[address - 0xC000] = value; + break; + case > 0xD000 and < 0xE000: + _ramMainBank2RegionD0DF[address - 0xD000] = value; + break; + case > 0xE000 and < 0x10000: + _ramMainRegionE0FF[address - 0xE000] = value; + break; + default: + throw new InvalidOperationException(); + } + } + + public byte PeekAuxRam(int address) + { + return address switch + { + > 0 and < 0x0200 => _ramAuxRegion0001[address - 0], + > 0x0200 and < 0xC000 => _ramAuxRegion02BF[address - 0x0200], + > 0xC000 and < 0xD000 => _ramAuxBank1RegionD0DF[address - 0xC000], + > 0xD000 and < 0xE000 => _ramAuxBank2RegionD0DF[address - 0xD000], + > 0xE000 and < 0x10000 => _ramAuxRegionE0FF[address - 0xE000], + _ => throw new InvalidOperationException() + }; + } + + public void PokeAuxRam(int address, byte value) + { + switch (address) + { + case > 0 and < 0x0200: + _ramAuxRegion0001[address - 0] = value; + break; + case > 0x0200 and < 0xC000: + _ramAuxRegion02BF[address - 0x0200] = value; + break; + case > 0xC000 and < 0xD000: + _ramAuxBank1RegionD0DF[address - 0xC000] = value; + break; + case > 0xD000 and < 0xE000: + _ramAuxBank2RegionD0DF[address - 0xD000] = value; + break; + case > 0xE000 and < 0x10000: + _ramAuxRegionE0FF[address - 0xE000] = value; + break; + default: + throw new InvalidOperationException(); + } + } + private int ReadIoRegionC0CF(int address) { switch (address & 0xFF00) diff --git a/References/Virtu.dll b/References/Virtu.dll index 88f17b8aa3..4bbedb7817 100644 Binary files a/References/Virtu.dll and b/References/Virtu.dll differ diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs index 8d51ed29e1..9c296b2720 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs @@ -507,6 +507,10 @@ namespace BizHawk.Client.EmuHawk // todo: make this MainMemory mfs.Add(new(domains["RAM"], 0, domains["RAM"].Size)); break; + case ConsoleID.AppleII: + mfs.Add(new(domains["Main RAM"], 0, domains["Main RAM"].Size)); + mfs.Add(new(domains["Auxiliary RAM"], 0, domains["Auxiliary RAM"].Size)); + break; case ConsoleID.Saturn: // todo: add System Bus so this isn't needed mfs.Add(new(domains["Work Ram Low"], 0, domains["Work Ram Low"].Size)); diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs index 7ae2a80591..13042fc2eb 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs @@ -11,20 +11,34 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII { var domains = new List(); - var mainRamDomain = new MemoryDomainDelegate("Main Ram", 0xC000, MemoryDomain.Endian.Little, + var mainRamDomain = new MemoryDomainDelegate("Main RAM", 0x10000, MemoryDomain.Endian.Little, addr => { - if (addr is < 0 or > 0xBFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - return (byte)_machine.Memory.Peek((int)addr); + if (addr is < 0 or > 0x10000) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + return (byte)_machine.Memory.PeekMainRam((int)addr); }, (addr, value) => { - if (addr is < 0 or > 0xBFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - _machine.Memory.Write((int)addr, value); + if (addr is < 0 or > 0x10000) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + _machine.Memory.PokeMainRam((int)addr, value); }, 1); domains.Add(mainRamDomain); + var auxRamDomain = new MemoryDomainDelegate("Auxiliary RAM", 0x10000, MemoryDomain.Endian.Little, + addr => + { + if (addr is < 0 or > 0x10000) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + return (byte)_machine.Memory.PeekAuxRam((int)addr); + }, + (addr, value) => + { + if (addr is < 0 or > 0x10000) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + _machine.Memory.PokeAuxRam((int)addr, value); + }, 1); + + domains.Add(auxRamDomain); + var systemBusDomain = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little, addr => {