MSXHawk: Blank core

This commit is contained in:
alyosha-tas 2020-01-09 17:21:58 -05:00
parent ed654f83e1
commit 3e0fd4a2d9
10 changed files with 539 additions and 0 deletions

View File

@ -325,6 +325,7 @@
<Compile Include="Computers\Commodore64\MOS\Vic.VideoProvider.cs" />
<Compile Include="Computers\Commodore64\SaveState.cs" />
<Compile Include="Computers\Commodore64\User\UserPortDevice.cs" />
<Compile Include="Computers\MSX\LibMSX.cs" />
<Compile Include="Computers\SinclairSpectrum\Hardware\Abstraction\IFDDHost.cs" />
<Compile Include="Computers\SinclairSpectrum\Hardware\Input\StandardKeyboard.cs" />
<Compile Include="Computers\SinclairSpectrum\Hardware\SoundOuput\AY38912.cs" />
@ -469,6 +470,28 @@
<Compile Include="Computers\SinclairSpectrum\ZXSpectrum.Controllers.cs">
<DependentUpon>ZXSpectrum.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.cs" />
<Compile Include="Computers\MSX\MSX.IEmulator.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.IInputPollable.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.IMemoryDomains.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.Input.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.ISaveRam.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.ISettable.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Computers\MSX\MSX.IStatable.cs">
<DependentUpon>MSX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Atari\2600\Atari2600.cs" />
<Compile Include="Consoles\Atari\2600\Atari2600.Core.cs">
<DependentUpon>Atari2600.cs</DependentUpon>

View File

@ -0,0 +1,20 @@
using System;
using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
/// <summary>
/// static bindings into libMSX.dll
/// </summary>
public static class LibMSX
{
/// <returns>opaque state pointer</returns>
[DllImport("libMSX.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr MSX_create();
/// <param name="core">opaque state pointer</param>
[DllImport("libMSX.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MSX_destroy(IntPtr core);
}
}

View File

@ -0,0 +1,133 @@
using BizHawk.Emulation.Common;
using System;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX : IEmulator, ISoundProvider
{
public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition
{
get
{
return GGController;
}
}
// not savestated variables
int s_L, s_R;
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
_lagged = true;
_frame++;
if (Tracer.Enabled)
{
}
else
{
}
if (_lagged)
{
_lagCount++;
_isLag = true;
}
else
{
_isLag = false;
}
return true;
}
public int Frame => _frame;
public string SystemId => "MSX";
public bool DeterministicEmulation => true;
public void ResetCounters()
{
_frame = 0;
_lagCount = 0;
_isLag = false;
}
public CoreComm CoreComm { get; }
public void Dispose()
{
if (blip_L != null)
{
blip_L.Dispose();
blip_L = null;
}
if (blip_R != null)
{
blip_R.Dispose();
blip_R = null;
}
}
#region Audio
public BlipBuffer blip_L = new BlipBuffer(4096);
public BlipBuffer blip_R = new BlipBuffer(4096);
const int blipbuffsize = 4096;
public uint sampleclock;
public int old_s_L = 0;
public int old_s_R = 0;
public bool CanProvideAsync { get { return false; } }
public void SetSyncMode(SyncSoundMode mode)
{
if (mode != SyncSoundMode.Sync)
{
throw new NotSupportedException("Only sync mode is supported");
}
}
public void GetSamplesAsync(short[] samples)
{
throw new NotSupportedException("Async not supported");
}
public SyncSoundMode SyncMode
{
get { return SyncSoundMode.Sync; }
}
public void GetSamplesSync(out short[] samples, out int nsamp)
{
blip_L.EndFrame(sampleclock);
blip_R.EndFrame(sampleclock);
nsamp = Math.Max(Math.Max(blip_L.SamplesAvailable(), blip_R.SamplesAvailable()), 1);
samples = new short[nsamp * 2];
blip_L.ReadSamplesLeft(samples, nsamp);
blip_R.ReadSamplesRight(samples, nsamp);
sampleclock = 0;
}
public void DiscardSamples()
{
blip_L.Clear();
blip_R.Clear();
sampleclock = 0;
}
#endregion
}
}

View File

@ -0,0 +1,25 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX : IInputPollable
{
public int LagCount
{
get { return _lagCount; }
set { _lagCount = value; }
}
public bool IsLagFrame
{
get { return _isLag; }
set { _isLag = value; }
}
public IInputCallbackSystem InputCallbacks { get; private set; }
public int _lagCount = 0;
public bool _lagged = true;
public bool _isLag = false;
}
}

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX
{
private MemoryDomainList MemoryDomains;
private readonly Dictionary<string, MemoryDomainByteArray> _byteArrayDomains = new Dictionary<string, MemoryDomainByteArray>();
private bool _memoryDomainsInit = false;
void SetupMemoryDomains()
{
var domains = new List<MemoryDomain>
{
new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little,
(addr) =>
{
if (addr < 0 || addr >= 65536)
{
throw new ArgumentOutOfRangeException();
}
return 0;
},
(addr, value) =>
{
if (addr < 0 || addr >= 65536)
{
throw new ArgumentOutOfRangeException();
}
}, 1)
};
if (SaveRAM != null)
{
var saveRamDomain = new MemoryDomainDelegate("Save RAM", SaveRAM.Length, MemoryDomain.Endian.Little,
addr => SaveRAM[addr],
(addr, value) => { SaveRAM[addr] = value; SaveRamModified = true; }, 1);
domains.Add(saveRamDomain);
}
SyncAllByteArrayDomains();
MemoryDomains = new MemoryDomainList(_byteArrayDomains.Values.Concat(domains).ToList());
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
_memoryDomainsInit = true;
}
private void SyncAllByteArrayDomains()
{
SyncByteArrayDomain("ROM", RomData);
}
private void SyncByteArrayDomain(string name, byte[] data)
{
if (_memoryDomainsInit)
{
var m = _byteArrayDomains[name];
m.Data = data;
}
else
{
var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1);
_byteArrayDomains.Add(name, m);
}
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX : ISaveRam
{
public byte[] CloneSaveRam()
{
if (SaveRAM != null)
{
return (byte[])SaveRAM.Clone();
}
else
{
return null;
}
}
public void StoreSaveRam(byte[] data)
{
if (SaveRAM != null)
{
Array.Copy(data, SaveRAM, data.Length);
}
}
public bool SaveRamModified { get; private set; }
public byte[] SaveRAM;
private byte SaveRamBank;
}
}

View File

@ -0,0 +1,64 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX : ISettable<MSX.MSXSettings, MSX.MSXSyncSettings>
{
public MSXSettings GetSettings()
{
return Settings.Clone();
}
public MSXSyncSettings GetSyncSettings()
{
return SyncSettings.Clone();
}
public bool PutSettings(MSXSettings o)
{
bool ret = MSXSettings.RebootNeeded(Settings, o);
Settings = o;
return ret;
}
public bool PutSyncSettings(MSXSyncSettings o)
{
bool ret = MSXSyncSettings.RebootNeeded(SyncSettings, o);
SyncSettings = o;
return ret;
}
internal MSXSettings Settings { get; private set; }
internal MSXSyncSettings SyncSettings { get; private set; }
public class MSXSettings
{
// graphics settings
public bool DispBG = true;
public bool DispOBJ = true;
public MSXSettings Clone()
{
return (MSXSettings)MemberwiseClone();
}
public static bool RebootNeeded(MSXSettings x, MSXSettings y)
{
return false;
}
}
public class MSXSyncSettings
{
public MSXSyncSettings Clone()
{
return (MSXSyncSettings)MemberwiseClone();
}
public static bool RebootNeeded(MSXSyncSettings x, MSXSyncSettings y)
{
return false;
}
}
}
}

View File

@ -0,0 +1,76 @@
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX : IStatable
{
public bool BinarySaveStatesPreferred => true;
public void SaveStateText(TextWriter writer)
{
SyncState(new Serializer(writer));
}
public void LoadStateText(TextReader reader)
{
SyncState(new Serializer(reader));
}
public void SaveStateBinary(BinaryWriter bw)
{
SyncState(new Serializer(bw));
}
public void LoadStateBinary(BinaryReader br)
{
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
private void SyncState(Serializer ser)
{
byte[] core = null;
if (ser.IsWriter)
{
using var ms = new MemoryStream();
ms.Close();
core = ms.ToArray();
}
ser.BeginSection("MSX");
ser.Sync(nameof(sampleclock), ref sampleclock);
ser.Sync(nameof(old_s_L), ref old_s_L);
ser.Sync(nameof(old_s_R), ref old_s_R);
if (SaveRAM != null)
{
ser.Sync(nameof(SaveRAM), ref SaveRAM, false);
}
ser.Sync(nameof(SaveRamBank), ref SaveRamBank);
ser.Sync("Frame", ref _frame);
ser.Sync("LagCount", ref _lagCount);
ser.Sync("IsLag", ref _isLag);
ser.EndSection();
if (ser.IsReader)
{
SyncAllByteArrayDomains();
}
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
public partial class MSX
{
public static readonly ControllerDefinition GGController = new ControllerDefinition
{
Name = "GG Controller",
BoolButtons =
{
"Reset",
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 B1", "P1 B2", "P1 Start"
}
};
}
}

View File

@ -0,0 +1,69 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.MSX
{
[Core(
"MSXHawk",
"",
isPorted: false,
isReleased: false)]
[ServiceNotApplicable(typeof(IDriveLight))]
public partial class MSX : IEmulator, ISaveRam, IStatable, IInputPollable, IRegionable, ISettable<MSX.MSXSettings, MSX.MSXSyncSettings>
{
[CoreConstructor("MSX")]
public MSX(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
{
ServiceProvider = new BasicServiceProvider(this);
Settings = (MSXSettings)settings ?? new MSXSettings();
SyncSettings = (MSXSyncSettings)syncSettings ?? new MSXSyncSettings();
CoreComm = comm;
RomData = rom;
if (RomData.Length % BankSize != 0)
{
Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize);
}
blip_L.SetRates(3579545, 44100);
blip_R.SetRates(3579545, 44100);
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(this);
SetupMemoryDomains();
//this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete
((ICodeDataLogger)this).SetCDL(null);
InputCallbacks = new InputCallbackSystem();
var serviceProvider = ServiceProvider as BasicServiceProvider;
serviceProvider.Register<ITraceable>(Tracer);
}
public void HardReset()
{
}
// Constants
private const int BankSize = 16384;
// ROM
public byte[] RomData;
// Machine resources
private IController _controller = NullController.Instance;
private int _frame = 0;
public DisplayType Region => DisplayType.NTSC;
private readonly ITraceable Tracer;
private MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
public IMemoryCallbackSystem MemoryCallbacks => _memorycallbacks;
}
}