Atari 7800 cleanups

This commit is contained in:
adelikat 2017-05-05 14:20:28 -05:00
parent 7b29970ef9
commit 9b1945a81e
7 changed files with 177 additions and 160 deletions

View File

@ -358,6 +358,9 @@
<Compile Include="Consoles\Atari\7800\Atari7800.IDebuggable.cs"> <Compile Include="Consoles\Atari\7800\Atari7800.IDebuggable.cs">
<DependentUpon>Atari7800.cs</DependentUpon> <DependentUpon>Atari7800.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Consoles\Atari\7800\Atari7800.IEmulator.cs">
<DependentUpon>Atari7800.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Atari\7800\Atari7800.IInputPollable.cs"> <Compile Include="Consoles\Atari\7800\Atari7800.IInputPollable.cs">
<DependentUpon>Atari7800.cs</DependentUpon> <DependentUpon>Atari7800.cs</DependentUpon>
</Compile> </Compile>

View File

@ -11,19 +11,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
{ {
return new Dictionary<string, RegisterValue> return new Dictionary<string, RegisterValue>
{ {
["A"] = theMachine.CPU.A, ["A"] = _theMachine.CPU.A,
["P"] = theMachine.CPU.P, ["P"] = _theMachine.CPU.P,
["PC"] = theMachine.CPU.PC, ["PC"] = _theMachine.CPU.PC,
["S"] = theMachine.CPU.S, ["S"] = _theMachine.CPU.S,
["X"] = theMachine.CPU.X, ["X"] = _theMachine.CPU.X,
["Y"] = theMachine.CPU.Y, ["Y"] = _theMachine.CPU.Y,
["Flag B"] = theMachine.CPU.fB, ["Flag B"] = _theMachine.CPU.fB,
["Flag C"] = theMachine.CPU.fC, ["Flag C"] = _theMachine.CPU.fC,
["Flag D"] = theMachine.CPU.fD, ["Flag D"] = _theMachine.CPU.fD,
["Flag I"] = theMachine.CPU.fI, ["Flag I"] = _theMachine.CPU.fI,
["Flag N"] = theMachine.CPU.fN, ["Flag N"] = _theMachine.CPU.fN,
["Flag V"] = theMachine.CPU.fV, ["Flag V"] = _theMachine.CPU.fV,
["Flag Z"] = theMachine.CPU.fZ ["Flag Z"] = _theMachine.CPU.fZ
}; };
} }
@ -34,22 +34,22 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
case "A": case "A":
theMachine.CPU.A = (byte)value; _theMachine.CPU.A = (byte)value;
break; break;
case "P": case "P":
theMachine.CPU.P = (byte)value; _theMachine.CPU.P = (byte)value;
break; break;
case "PC": case "PC":
theMachine.CPU.PC = (ushort)value; _theMachine.CPU.PC = (ushort)value;
break; break;
case "S": case "S":
theMachine.CPU.S = (byte)value; _theMachine.CPU.S = (byte)value;
break; break;
case "X": case "X":
theMachine.CPU.X = (byte)value; _theMachine.CPU.X = (byte)value;
break; break;
case "Y": case "Y":
theMachine.CPU.Y = (byte)value; _theMachine.CPU.Y = (byte)value;
break; break;
} }
} }
@ -71,6 +71,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
throw new NotImplementedException(); throw new NotImplementedException();
} }
public int TotalExecutedCycles => (int)theMachine.CPU.Clock; public int TotalExecutedCycles => (int)_theMachine.CPU.Clock;
} }
} }

View File

@ -0,0 +1,59 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Atari.Atari7800
{
public partial class Atari7800 : IEmulator
{
public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition { get; private set; }
public void FrameAdvance(IController controller, bool render, bool rendersound)
{
_frame++;
if (controller.IsPressed("Power"))
{
// it seems that theMachine.Reset() doesn't clear ram, etc
// this should leave hsram intact but clear most other things
HardReset();
}
ControlAdapter.Convert(controller, _theMachine.InputState);
_theMachine.ComputeNextFrame(_avProvider.Framebuffer);
_islag = _theMachine.InputState.Lagged;
if (_islag)
{
_lagcount++;
}
_avProvider.FillFrameBuffer();
}
public int Frame => _frame;
public string SystemId => "A78"; // TODO 2600?
public bool DeterministicEmulation { get; set; }
public void ResetCounters()
{
_frame = 0;
_lagcount = 0;
_islag = false;
}
public CoreComm CoreComm { get; }
public void Dispose()
{
if (_avProvider != null)
{
_avProvider.Dispose();
_avProvider = null;
}
}
}
}

View File

@ -18,7 +18,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
if (_MemoryDomains == null) if (_MemoryDomains == null)
{ {
_MemoryDomains = new List<MemoryDomain>(); _MemoryDomains = new List<MemoryDomain>();
if (theMachine is Machine7800) if (_theMachine is Machine7800)
{ {
_MemoryDomains.Add(new MemoryDomainDelegate( _MemoryDomains.Add(new MemoryDomainDelegate(
"RAM", 0x1000, MemoryDomain.Endian.Unknown, "RAM", 0x1000, MemoryDomain.Endian.Unknown,
@ -31,10 +31,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
if (addr < 0x800) if (addr < 0x800)
{ {
return ((Machine7800)theMachine).RAM1[(ushort)addr]; return ((Machine7800)_theMachine).RAM1[(ushort)addr];
} }
return ((Machine7800)theMachine).RAM2[(ushort)addr]; return ((Machine7800)_theMachine).RAM2[(ushort)addr];
}, },
delegate(long addr, byte val) delegate(long addr, byte val)
@ -45,25 +45,25 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
} }
else if (addr < 0x800) else if (addr < 0x800)
{ {
((Machine7800)theMachine).RAM1[(ushort)(addr & 0x800)] = val; ((Machine7800)_theMachine).RAM1[(ushort)(addr & 0x800)] = val;
} }
else else
{ {
((Machine7800)theMachine).RAM2[(ushort)addr] = val; ((Machine7800)_theMachine).RAM2[(ushort)addr] = val;
} }
}, 1)); }, 1));
_MemoryDomains.Add(new MemoryDomainByteArray( _MemoryDomains.Add(new MemoryDomainByteArray(
"BIOS ROM", MemoryDomain.Endian.Unknown, "BIOS ROM", MemoryDomain.Endian.Unknown,
bios, false, 1)); _bios, false, 1));
if (hsc7800 != null) if (hsc7800 != null)
{ {
_MemoryDomains.Add(new MemoryDomainByteArray( _MemoryDomains.Add(new MemoryDomainByteArray(
"HSC ROM", MemoryDomain.Endian.Unknown, hsbios, false, 1)); "HSC ROM", MemoryDomain.Endian.Unknown, _hsbios, false, 1));
_MemoryDomains.Add(new MemoryDomainByteArray( _MemoryDomains.Add(new MemoryDomainByteArray(
"HSC RAM", MemoryDomain.Endian.Unknown, hsram, true, 1)); "HSC RAM", MemoryDomain.Endian.Unknown, _hsram, true, 1));
} }
_MemoryDomains.Add(new MemoryDomainDelegate( _MemoryDomains.Add(new MemoryDomainDelegate(
@ -72,13 +72,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
{ {
if (addr < 0 || addr >= 0x10000) if (addr < 0 || addr >= 0x10000)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
return theMachine.Mem[(ushort)addr]; return _theMachine.Mem[(ushort)addr];
}, },
delegate(long addr, byte val) delegate(long addr, byte val)
{ {
if (addr < 0 || addr >= 0x10000) if (addr < 0 || addr >= 0x10000)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
theMachine.Mem[(ushort)addr] = val; _theMachine.Mem[(ushort)addr] = val;
}, 1)); }, 1));
} }
else // todo 2600? else // todo 2600?

View File

@ -8,15 +8,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
{ {
public byte[] CloneSaveRam() public byte[] CloneSaveRam()
{ {
return (byte[])hsram.Clone(); return (byte[])_hsram.Clone();
} }
public void StoreSaveRam(byte[] data) public void StoreSaveRam(byte[] data)
{ {
Buffer.BlockCopy(data, 0, hsram, 0, data.Length); Buffer.BlockCopy(data, 0, _hsram, 0, data.Length);
} }
public bool SaveRamModified => GameInfo.MachineType == MachineType.A7800PAL public bool SaveRamModified => _gameInfo.MachineType == MachineType.A7800PAL
|| GameInfo.MachineType == MachineType.A7800NTSC; || _gameInfo.MachineType == MachineType.A7800NTSC;
} }
} }

View File

@ -45,7 +45,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
if (ser.IsWriter) if (ser.IsWriter)
{ {
var ms = new MemoryStream(); var ms = new MemoryStream();
theMachine.Serialize(new BinaryWriter(ms)); _theMachine.Serialize(new BinaryWriter(ms));
ms.Close(); ms.Close();
core = ms.ToArray(); core = ms.ToArray();
} }
@ -58,8 +58,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
ser.EndSection(); ser.EndSection();
if (ser.IsReader) if (ser.IsReader)
{ {
theMachine = MachineBase.Deserialize(new BinaryReader(new MemoryStream(core, false))); _theMachine = MachineBase.Deserialize(new BinaryReader(new MemoryStream(core, false)));
_avProvider.ConnectToMachine(theMachine, GameInfo); _avProvider.ConnectToMachine(_theMachine, _gameInfo);
} }
} }
} }

View File

@ -3,6 +3,7 @@ using System.IO;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using EMU7800.Core; using EMU7800.Core;
using EMU7800.Win;
namespace BizHawk.Emulation.Cores.Atari.Atari7800 namespace BizHawk.Emulation.Cores.Atari.Atari7800
{ {
@ -44,18 +45,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
public Atari7800(CoreComm comm, GameInfo game, byte[] rom, string GameDBfn) public Atari7800(CoreComm comm, GameInfo game, byte[] rom, string GameDBfn)
{ {
ServiceProvider = new BasicServiceProvider(this); var ser = new BasicServiceProvider(this);
(ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(_avProvider); ser.Register<IVideoProvider>(_avProvider);
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(_avProvider); ser.Register<ISoundProvider>(_avProvider);
ServiceProvider = ser;
CoreComm = comm; CoreComm = comm;
byte[] highscoreBIOS = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS."); byte[] highscoreBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS.");
byte[] pal_bios = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available."); byte[] palBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available.");
byte[] ntsc_bios = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available."); byte[] ntscBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available.");
if (EMU7800.Win.GameProgramLibrary.EMU7800DB == null) if (GameProgramLibrary.EMU7800DB == null)
{ {
EMU7800.Win.GameProgramLibrary.EMU7800DB = new EMU7800.Win.GameProgramLibrary(new StreamReader(GameDBfn)); GameProgramLibrary.EMU7800DB = new GameProgramLibrary(new StreamReader(GameDBfn));
} }
if (rom.Length % 1024 == 128) if (rom.Length % 1024 == 128)
@ -66,18 +68,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
rom = newrom; rom = newrom;
} }
GameInfo = EMU7800.Win.GameProgramLibrary.EMU7800DB.TryRecognizeRom(rom); _gameInfo = GameProgramLibrary.EMU7800DB.TryRecognizeRom(rom);
CoreComm.RomStatusDetails = GameInfo.ToString(); CoreComm.RomStatusDetails = _gameInfo.ToString();
Console.WriteLine("Rom Determiniation from 7800DB:"); Console.WriteLine("Rom Determiniation from 7800DB:");
Console.WriteLine(GameInfo.ToString()); Console.WriteLine(_gameInfo.ToString());
this.rom = rom; _rom = rom;
this.game = game; _hsbios = highscoreBios;
this.hsbios = highscoreBIOS; _bios = _gameInfo.MachineType == MachineType.A7800PAL ? palBios : ntscBios;
this.bios = GameInfo.MachineType == MachineType.A7800PAL ? pal_bios : ntsc_bios; _pal = _gameInfo.MachineType == MachineType.A7800PAL || _gameInfo.MachineType == MachineType.A2600PAL;
_pal = GameInfo.MachineType == MachineType.A7800PAL || GameInfo.MachineType == MachineType.A2600PAL;
if (bios == null) if (_bios == null)
{ {
throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games."); throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games.");
} }
@ -85,70 +86,20 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
HardReset(); HardReset();
} }
public IEmulatorServiceProvider ServiceProvider { get; private set; } public DisplayType Region => _pal ? DisplayType.PAL : DisplayType.NTSC;
private readonly byte[] rom;
public readonly byte[] hsbios;
public readonly byte[] bios;
private Cart cart;
private MachineBase theMachine;
private readonly EMU7800.Win.GameProgram GameInfo;
public readonly byte[] hsram = new byte[2048];
public string SystemId => "A78"; // TODO 2600?
public GameInfo game;
public void FrameAdvance(IController controller, bool render, bool rendersound)
{
_frame++;
if (controller.IsPressed("Power"))
{
// it seems that theMachine.Reset() doesn't clear ram, etc
// this should leave hsram intact but clear most other things
HardReset();
}
ControlAdapter.Convert(controller, theMachine.InputState);
theMachine.ComputeNextFrame(_avProvider.Framebuffer);
_islag = theMachine.InputState.Lagged;
if (_islag)
{
_lagcount++;
}
_avProvider.FillFrameBuffer();
}
public CoreComm CoreComm { get; }
public bool DeterministicEmulation { get; set; }
public int Frame => _frame;
private int _frame = 0;
public void Dispose()
{
if (_avProvider != null)
{
_avProvider.Dispose();
_avProvider = null;
}
}
public void ResetCounters()
{
_frame = 0;
_lagcount = 0;
_islag = false;
}
public Atari7800Control ControlAdapter { get; private set; } public Atari7800Control ControlAdapter { get; private set; }
public ControllerDefinition ControllerDefinition { get; private set; } private readonly byte[] _rom;
private readonly byte[] _hsbios;
private readonly byte[] _bios;
private readonly GameProgram _gameInfo;
private readonly byte[] _hsram = new byte[2048];
private readonly bool _pal;
private Cart _cart;
private MachineBase _theMachine;
private int _frame = 0;
private class ConsoleLogger : ILogger private class ConsoleLogger : ILogger
{ {
@ -173,37 +124,34 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
} }
} }
private readonly bool _pal;
public DisplayType Region => _pal ? DisplayType.PAL : DisplayType.NTSC;
private void HardReset() private void HardReset()
{ {
cart = Cart.Create(rom, GameInfo.CartType); _cart = Cart.Create(_rom, _gameInfo.CartType);
ILogger logger = new ConsoleLogger(); ILogger logger = new ConsoleLogger();
HSC7800 hsc7800 = null; HSC7800 hsc7800 = null;
if (hsbios != null) if (_hsbios != null)
{ {
hsc7800 = new HSC7800(hsbios, hsram); hsc7800 = new HSC7800(_hsbios, _hsram);
} }
Bios7800 bios7800 = new Bios7800(bios); Bios7800 bios7800 = new Bios7800(_bios);
theMachine = MachineBase.Create _theMachine = MachineBase.Create(
(GameInfo.MachineType, _gameInfo.MachineType,
cart, _cart,
bios7800, bios7800,
hsc7800, hsc7800,
GameInfo.LController, _gameInfo.LController,
GameInfo.RController, _gameInfo.RController,
logger); logger);
theMachine.Reset(); _theMachine.Reset();
theMachine.InputState.InputPollCallback = InputCallbacks.Call; _theMachine.InputState.InputPollCallback = InputCallbacks.Call;
ControlAdapter = new Atari7800Control(theMachine); ControlAdapter = new Atari7800Control(_theMachine);
ControllerDefinition = ControlAdapter.ControlType; ControllerDefinition = ControlAdapter.ControlType;
_avProvider.ConnectToMachine(theMachine, GameInfo); _avProvider.ConnectToMachine(_theMachine, _gameInfo);
SetupMemoryDomains(hsc7800); SetupMemoryDomains(hsc7800);
} }
@ -218,52 +166,59 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
private int _frameHz; private int _frameHz;
public FrameBuffer Framebuffer { get; private set; } public FrameBuffer Framebuffer { get; private set; }
public void ConnectToMachine(MachineBase m, EMU7800.Win.GameProgram g) public void ConnectToMachine(MachineBase m, GameProgram g)
{ {
_frameHz = m.FrameHZ; _frameHz = m.FrameHZ;
Framebuffer = m.CreateFrameBuffer(); Framebuffer = m.CreateFrameBuffer();
BufferWidth = Framebuffer.VisiblePitch; BufferWidth = Framebuffer.VisiblePitch;
BufferHeight = Framebuffer.Scanlines; BufferHeight = Framebuffer.Scanlines;
vidbuffer = new int[BufferWidth * BufferHeight]; _vidbuffer = new int[BufferWidth * BufferHeight];
uint newsamplerate = (uint)m.SoundSampleFrequency; uint newsamplerate = (uint)m.SoundSampleFrequency;
if (newsamplerate != samplerate) if (newsamplerate != _samplerate)
{ {
// really shouldn't happen (after init), but if it does, we're ready // really shouldn't happen (after init), but if it does, we're ready
if (resampler != null) _resampler?.Dispose();
resampler.Dispose(); _resampler = new SpeexResampler((SpeexResampler.Quality)3, newsamplerate, 44100, newsamplerate, 44100, null, null);
resampler = new SpeexResampler((SpeexResampler.Quality)3, newsamplerate, 44100, newsamplerate, 44100, null, null); _samplerate = newsamplerate;
samplerate = newsamplerate; _dcfilter = new DCFilter(256);
dcfilter = new DCFilter(256);
} }
if (g.MachineType == MachineType.A2600PAL) if (g.MachineType == MachineType.A2600PAL)
palette = TIATables.PALPalette; {
_palette = TIATables.PALPalette;
}
else if (g.MachineType == MachineType.A7800PAL) else if (g.MachineType == MachineType.A7800PAL)
palette = MariaTables.PALPalette; {
_palette = MariaTables.PALPalette;
}
else if (g.MachineType == MachineType.A2600NTSC) else if (g.MachineType == MachineType.A2600NTSC)
palette = TIATables.NTSCPalette; {
_palette = TIATables.NTSCPalette;
}
else else
palette = MariaTables.NTSCPalette; {
_palette = MariaTables.NTSCPalette;
}
} }
private uint samplerate; private uint _samplerate;
private int[] vidbuffer; private int[] _vidbuffer;
private SpeexResampler resampler; private SpeexResampler _resampler;
private DCFilter dcfilter; private DCFilter _dcfilter;
private int[] palette; private int[] _palette;
public void FillFrameBuffer() public void FillFrameBuffer()
{ {
unsafe unsafe
{ {
fixed (byte* src_ = Framebuffer.VideoBuffer) fixed (byte* src_ = Framebuffer.VideoBuffer)
fixed (int* dst_ = vidbuffer) fixed (int* dst_ = _vidbuffer)
fixed (int* pal = palette) fixed (int* pal = _palette)
{ {
byte* src = src_; byte* src = src_;
int* dst = dst_; int* dst = dst_;
for (int i = 0; i < vidbuffer.Length; i++) for (int i = 0; i < _vidbuffer.Length; i++)
{ {
*dst++ = pal[*src++]; *dst++ = pal[*src++];
} }
@ -273,7 +228,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
public int[] GetVideoBuffer() public int[] GetVideoBuffer()
{ {
return vidbuffer; return _vidbuffer;
} }
public int VirtualWidth => 275; public int VirtualWidth => 275;
@ -300,13 +255,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
// the buffer values don't really get very large at all, // the buffer values don't really get very large at all,
// so this doesn't overflow // so this doesn't overflow
short s = (short)(src[i] * 200); short s = (short)(src[i] * 200);
resampler.EnqueueSample(s, s); _resampler.EnqueueSample(s, s);
} }
} }
} }
resampler.GetSamplesSync(out samples, out nsamp);
dcfilter.PushThroughSamples(samples, nsamp * 2); _resampler.GetSamplesSync(out samples, out nsamp);
_dcfilter.PushThroughSamples(samples, nsamp * 2);
} }
public SyncSoundMode SyncMode => SyncSoundMode.Sync; public SyncSoundMode SyncMode => SyncSoundMode.Sync;
@ -326,17 +281,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
public void DiscardSamples() public void DiscardSamples()
{ {
resampler?.DiscardSamples(); _resampler?.DiscardSamples();
} }
#endregion #endregion
public void Dispose() public void Dispose()
{ {
if (resampler != null) if (_resampler != null)
{ {
resampler.Dispose(); _resampler.Dispose();
resampler = null; _resampler = null;
} }
} }
} }