218 lines
6.1 KiB
C#
218 lines
6.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
using BizHawk.Emulation.Common;
|
|
|
|
namespace BizHawk.Emulation.Cores.WonderSwan
|
|
{
|
|
[Core("Cygne/Mednafen", "Dox, Mednafen Team", true, true, "0.9.36.5", "http://mednafen.sourceforge.net/")]
|
|
[ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))]
|
|
public partial class WonderSwan : IEmulator, IVideoProvider, ISoundProvider,
|
|
IInputPollable, IDebuggable
|
|
{
|
|
[CoreConstructor("WSWAN")]
|
|
public WonderSwan(CoreComm comm, byte[] file, bool deterministic, object settings, object syncSettings)
|
|
{
|
|
ServiceProvider = new BasicServiceProvider(this);
|
|
CoreComm = comm;
|
|
_Settings = (Settings)settings ?? new Settings();
|
|
_SyncSettings = (SyncSettings)syncSettings ?? new SyncSettings();
|
|
|
|
DeterministicEmulation = deterministic; // when true, remember to force the RTC flag!
|
|
Core = BizSwan.bizswan_new();
|
|
if (Core == IntPtr.Zero)
|
|
throw new InvalidOperationException("bizswan_new() returned NULL!");
|
|
try
|
|
{
|
|
var ss = _SyncSettings.GetNativeSettings();
|
|
if (deterministic)
|
|
ss.userealtime = false;
|
|
|
|
bool rotate = false;
|
|
|
|
if (!BizSwan.bizswan_load(Core, file, file.Length, ref ss, ref rotate))
|
|
throw new InvalidOperationException("bizswan_load() returned FALSE!");
|
|
|
|
InitISaveRam();
|
|
|
|
InitVideo(rotate);
|
|
PutSettings(_Settings);
|
|
InitIMemoryDomains();
|
|
|
|
InitIStatable();
|
|
InitDebugCallbacks();
|
|
}
|
|
catch
|
|
{
|
|
Dispose();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Core != IntPtr.Zero)
|
|
{
|
|
BizSwan.bizswan_delete(Core);
|
|
Core = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
|
|
{
|
|
Frame++;
|
|
IsLagFrame = true;
|
|
|
|
if (controller.IsPressed("Power"))
|
|
BizSwan.bizswan_reset(Core);
|
|
|
|
bool rotate = false;
|
|
int soundbuffsize = sbuff.Length;
|
|
IsLagFrame = BizSwan.bizswan_advance(Core, GetButtons(controller), !render, vbuff, sbuff, ref soundbuffsize, ref rotate);
|
|
if (soundbuffsize == sbuff.Length)
|
|
throw new Exception();
|
|
sbuffcontains = soundbuffsize;
|
|
InitVideo(rotate);
|
|
|
|
if (IsLagFrame)
|
|
LagCount++;
|
|
}
|
|
|
|
public CoreComm CoreComm { get; private set; }
|
|
|
|
public void ResetCounters()
|
|
{
|
|
Frame = 0;
|
|
IsLagFrame = false;
|
|
LagCount = 0;
|
|
}
|
|
|
|
IntPtr Core;
|
|
|
|
public int Frame { get; private set; }
|
|
public int LagCount { get; set; }
|
|
public bool IsLagFrame { get; set; }
|
|
|
|
public string SystemId { get { return "WSWAN"; } }
|
|
public bool DeterministicEmulation { get; private set; }
|
|
|
|
#region Debugging
|
|
|
|
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
|
|
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } }
|
|
|
|
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" }); // This isn't an actual memory domain in this core (yet), but there's nothing that enforces that it has to be
|
|
public IMemoryCallbackSystem MemoryCallbacks { get { return _memorycallbacks; } }
|
|
|
|
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
|
{
|
|
var ret = new Dictionary<string, RegisterValue>();
|
|
for (int i = (int)BizSwan.NecRegsMin; i <= (int)BizSwan.NecRegsMax; i++)
|
|
{
|
|
BizSwan.NecRegs en = (BizSwan.NecRegs)i;
|
|
uint val = BizSwan.bizswan_getnecreg(Core, en);
|
|
ret[Enum.GetName(typeof(BizSwan.NecRegs), en)] = (ushort)val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
[FeatureNotImplemented]
|
|
public void SetCpuRegister(string register, int value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public bool CanStep(StepType type) { return false; }
|
|
|
|
[FeatureNotImplemented]
|
|
public void Step(StepType type) { throw new NotImplementedException(); }
|
|
|
|
[FeatureNotImplemented]
|
|
public long TotalExecutedCycles { get { throw new NotImplementedException(); } }
|
|
|
|
BizSwan.MemoryCallback ReadCallbackD;
|
|
BizSwan.MemoryCallback WriteCallbackD;
|
|
BizSwan.MemoryCallback ExecCallbackD;
|
|
BizSwan.ButtonCallback ButtonCallbackD;
|
|
|
|
void ReadCallback(uint addr)
|
|
{
|
|
MemoryCallbacks.CallReads(addr, "System Bus");
|
|
}
|
|
void WriteCallback(uint addr)
|
|
{
|
|
MemoryCallbacks.CallWrites(addr, "System Bus");
|
|
}
|
|
void ExecCallback(uint addr)
|
|
{
|
|
MemoryCallbacks.CallExecutes(addr, "System Bus");
|
|
}
|
|
void ButtonCallback()
|
|
{
|
|
InputCallbacks.Call();
|
|
}
|
|
|
|
void InitDebugCallbacks()
|
|
{
|
|
ReadCallbackD = new BizSwan.MemoryCallback(ReadCallback);
|
|
WriteCallbackD = new BizSwan.MemoryCallback(WriteCallback);
|
|
ExecCallbackD = new BizSwan.MemoryCallback(ExecCallback);
|
|
ButtonCallbackD = new BizSwan.ButtonCallback(ButtonCallback);
|
|
_inputCallbacks.ActiveChanged += SetInputCallback;
|
|
_memorycallbacks.ActiveChanged += SetMemoryCallbacks;
|
|
}
|
|
|
|
void SetInputCallback()
|
|
{
|
|
BizSwan.bizswan_setbuttoncallback(Core, InputCallbacks.Any() ? ButtonCallbackD : null);
|
|
}
|
|
|
|
void SetMemoryCallbacks()
|
|
{
|
|
BizSwan.bizswan_setmemorycallbacks(Core,
|
|
MemoryCallbacks.HasReads ? ReadCallbackD : null,
|
|
MemoryCallbacks.HasWrites ? WriteCallbackD : null,
|
|
MemoryCallbacks.HasExecutes ? ExecCallbackD : null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IVideoProvider
|
|
|
|
void InitVideo(bool rotate)
|
|
{
|
|
if (rotate)
|
|
{
|
|
BufferWidth = 144;
|
|
BufferHeight = 224;
|
|
}
|
|
else
|
|
{
|
|
BufferWidth = 224;
|
|
BufferHeight = 144;
|
|
}
|
|
}
|
|
|
|
private int[] vbuff = new int[224 * 144];
|
|
|
|
public int[] GetVideoBuffer()
|
|
{
|
|
return vbuff;
|
|
}
|
|
|
|
public int VirtualWidth { get { return BufferWidth; } }
|
|
public int VirtualHeight { get { return BufferHeight; } }
|
|
public int BufferWidth { get; private set; }
|
|
public int BufferHeight { get; private set; }
|
|
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
|
|
|
public int VsyncNumerator => 3072000; // master CPU clock, also pixel clock
|
|
public int VsyncDenominator => (144 + 15) * (224 + 32); // 144 vislines, 15 vblank lines; 224 vispixels, 32 hblank pixels
|
|
|
|
#endregion
|
|
}
|
|
}
|