241 lines
7.6 KiB
C#
241 lines
7.6 KiB
C#
using BizHawk.Emulation.Common;
|
|
using System;
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.MSX
|
|
{
|
|
public partial class MSX : IEmulator, ISoundProvider, IVideoProvider
|
|
{
|
|
public IEmulatorServiceProvider ServiceProvider { get; }
|
|
|
|
public ControllerDefinition ControllerDefinition => current_controller;
|
|
|
|
public bool FrameAdvance(IController controller, bool render, bool rendersound)
|
|
{
|
|
_controller = controller;
|
|
|
|
byte ctrl1_byte = 0xFF;
|
|
if (_controller.IsPressed("P1 Up")) ctrl1_byte -= 0x01;
|
|
if (_controller.IsPressed("P1 Down")) ctrl1_byte -= 0x02;
|
|
if (_controller.IsPressed("P1 Left")) ctrl1_byte -= 0x04;
|
|
if (_controller.IsPressed("P1 Right")) ctrl1_byte -= 0x08;
|
|
if (_controller.IsPressed("P1 B1")) ctrl1_byte -= 0x10;
|
|
if (_controller.IsPressed("P1 B2")) ctrl1_byte -= 0x20;
|
|
|
|
byte ctrl2_byte = 0xFF;
|
|
if (_controller.IsPressed("P2 Up")) ctrl2_byte -= 0x01;
|
|
if (_controller.IsPressed("P2 Down")) ctrl2_byte -= 0x02;
|
|
if (_controller.IsPressed("P2 Left")) ctrl2_byte -= 0x04;
|
|
if (_controller.IsPressed("P2 Right")) ctrl2_byte -= 0x08;
|
|
if (_controller.IsPressed("P2 B1")) ctrl2_byte -= 0x10;
|
|
if (_controller.IsPressed("P2 B2")) ctrl2_byte -= 0x20;
|
|
|
|
if (current_controller == MSXControllerKB) { kb_rows_check(controller); }
|
|
|
|
_frame++;
|
|
|
|
if (Tracer.Enabled)
|
|
{
|
|
tracecb = MakeTrace;
|
|
}
|
|
else
|
|
{
|
|
tracecb = null;
|
|
}
|
|
|
|
LibMSX.MSX_settracecallback(MSX_Pntr, tracecb);
|
|
|
|
LibMSX.MSX_frame_advance(MSX_Pntr, ctrl1_byte, ctrl2_byte, kb_rows, true, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
public byte[] kb_rows = new byte[16];
|
|
|
|
public void kb_rows_check(IController controller)
|
|
{
|
|
for(int i = 0; i < 9; i++) { kb_rows[i] = 0; }
|
|
|
|
if (controller.IsPressed("7")) { kb_rows[0] |= 0x80; }
|
|
if (controller.IsPressed("6")) { kb_rows[0] |= 0x40; }
|
|
if (controller.IsPressed("5")) { kb_rows[0] |= 0x20; }
|
|
if (controller.IsPressed("4")) { kb_rows[0] |= 0x10; }
|
|
if (controller.IsPressed("3")) { kb_rows[0] |= 0x08; }
|
|
if (controller.IsPressed("2")) { kb_rows[0] |= 0x04; }
|
|
if (controller.IsPressed("1")) { kb_rows[0] |= 0x02; }
|
|
if (controller.IsPressed("0")) { kb_rows[0] |= 0x01; }
|
|
|
|
if (controller.IsPressed(";")) { kb_rows[1] |= 0x80; }
|
|
if (controller.IsPressed("[")) { kb_rows[1] |= 0x40; }
|
|
if (controller.IsPressed("@")) { kb_rows[1] |= 0x20; }
|
|
if (controller.IsPressed("$")) { kb_rows[1] |= 0x10; }
|
|
if (controller.IsPressed("^")) { kb_rows[1] |= 0x08; }
|
|
if (controller.IsPressed("-")) { kb_rows[1] |= 0x04; }
|
|
if (controller.IsPressed("9")) { kb_rows[1] |= 0x02; }
|
|
if (controller.IsPressed("8")) { kb_rows[1] |= 0x01; }
|
|
|
|
if (controller.IsPressed("B")) { kb_rows[2] |= 0x80; }
|
|
if (controller.IsPressed("A")) { kb_rows[2] |= 0x40; }
|
|
|
|
if (controller.IsPressed("/")) { kb_rows[2] |= 0x10; }
|
|
if (controller.IsPressed(".")) { kb_rows[2] |= 0x08; }
|
|
if (controller.IsPressed(",")) { kb_rows[2] |= 0x04; }
|
|
if (controller.IsPressed("]")) { kb_rows[2] |= 0x02; }
|
|
if (controller.IsPressed(":")) { kb_rows[2] |= 0x01; }
|
|
|
|
if (controller.IsPressed("J")) { kb_rows[3] |= 0x80; }
|
|
if (controller.IsPressed("I")) { kb_rows[3] |= 0x40; }
|
|
if (controller.IsPressed("H")) { kb_rows[3] |= 0x20; }
|
|
if (controller.IsPressed("G")) { kb_rows[3] |= 0x10; }
|
|
if (controller.IsPressed("F")) { kb_rows[3] |= 0x08; }
|
|
if (controller.IsPressed("E")) { kb_rows[3] |= 0x04; }
|
|
if (controller.IsPressed("D")) { kb_rows[3] |= 0x02; }
|
|
if (controller.IsPressed("C")) { kb_rows[3] |= 0x01; }
|
|
|
|
if (controller.IsPressed("R")) { kb_rows[4] |= 0x80; }
|
|
if (controller.IsPressed("Q")) { kb_rows[4] |= 0x40; }
|
|
if (controller.IsPressed("P")) { kb_rows[4] |= 0x20; }
|
|
if (controller.IsPressed("O")) { kb_rows[4] |= 0x10; }
|
|
if (controller.IsPressed("N")) { kb_rows[4] |= 0x08; }
|
|
if (controller.IsPressed("M")) { kb_rows[4] |= 0x04; }
|
|
if (controller.IsPressed("L")) { kb_rows[4] |= 0x02; }
|
|
if (controller.IsPressed("K")) { kb_rows[4] |= 0x01; }
|
|
|
|
if (controller.IsPressed("Z")) { kb_rows[5] |= 0x80; }
|
|
if (controller.IsPressed("Y")) { kb_rows[5] |= 0x40; }
|
|
if (controller.IsPressed("X")) { kb_rows[5] |= 0x20; }
|
|
if (controller.IsPressed("W")) { kb_rows[5] |= 0x10; }
|
|
if (controller.IsPressed("V")) { kb_rows[5] |= 0x08; }
|
|
if (controller.IsPressed("U")) { kb_rows[5] |= 0x04; }
|
|
if (controller.IsPressed("T")) { kb_rows[5] |= 0x02; }
|
|
if (controller.IsPressed("S")) { kb_rows[5] |= 0x01; }
|
|
|
|
if (controller.IsPressed("F3")) { kb_rows[6] |= 0x80; }
|
|
if (controller.IsPressed("F2")) { kb_rows[6] |= 0x40; }
|
|
if (controller.IsPressed("F1")) { kb_rows[6] |= 0x20; }
|
|
if (controller.IsPressed("KANA")) { kb_rows[6] |= 0x10; }
|
|
if (controller.IsPressed("CAP")) { kb_rows[6] |= 0x08; }
|
|
if (controller.IsPressed("GRAPH")) { kb_rows[6] |= 0x04; }
|
|
if (controller.IsPressed("CTRL")) { kb_rows[6] |= 0x02; }
|
|
if (controller.IsPressed("SHIFT")) { kb_rows[6] |= 0x01; }
|
|
|
|
if (controller.IsPressed("RET")) { kb_rows[7] |= 0x80; }
|
|
if (controller.IsPressed("SEL")) { kb_rows[7] |= 0x40; }
|
|
if (controller.IsPressed("BACK")) { kb_rows[7] |= 0x20; }
|
|
if (controller.IsPressed("STOP")) { kb_rows[7] |= 0x10; }
|
|
if (controller.IsPressed("TAB")) { kb_rows[7] |= 0x08; }
|
|
if (controller.IsPressed("ESC")) { kb_rows[7] |= 0x04; }
|
|
if (controller.IsPressed("F5")) { kb_rows[7] |= 0x02; }
|
|
if (controller.IsPressed("F4")) { kb_rows[7] |= 0x01; }
|
|
|
|
if (controller.IsPressed("RIGHT")) { kb_rows[8] |= 0x80; }
|
|
if (controller.IsPressed("DOWN")) { kb_rows[8] |= 0x40; }
|
|
if (controller.IsPressed("UP")) { kb_rows[8] |= 0x20; }
|
|
if (controller.IsPressed("LEFT")) { kb_rows[8] |= 0x10; }
|
|
if (controller.IsPressed("DEL")) { kb_rows[8] |= 0x08; }
|
|
if (controller.IsPressed("INS")) { kb_rows[8] |= 0x04; }
|
|
if (controller.IsPressed("HOME")) { kb_rows[8] |= 0x02; }
|
|
if (controller.IsPressed("SPACE")) { kb_rows[8] |= 0x01; }
|
|
}
|
|
|
|
public int Frame => _frame;
|
|
|
|
public string SystemId => "MSX";
|
|
|
|
public bool DeterministicEmulation => true;
|
|
|
|
public void ResetCounters()
|
|
{
|
|
_frame = 0;
|
|
_lagCount = 0;
|
|
_isLag = false;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (MSX_Pntr != IntPtr.Zero)
|
|
{
|
|
LibMSX.MSX_destroy(MSX_Pntr);
|
|
MSX_Pntr = IntPtr.Zero;
|
|
}
|
|
|
|
if (blip != null)
|
|
{
|
|
blip.Dispose();
|
|
blip = null;
|
|
}
|
|
}
|
|
|
|
#region Audio
|
|
|
|
public BlipBuffer blip = new BlipBuffer(4500);
|
|
|
|
public int[] Aud = new int [9000];
|
|
public uint num_samp;
|
|
|
|
const int blipbuffsize = 4500;
|
|
|
|
public bool CanProvideAsync => 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 => SyncSoundMode.Sync;
|
|
|
|
public void GetSamplesSync(out short[] samples, out int nsamp)
|
|
{
|
|
uint f_clock = LibMSX.MSX_get_audio(MSX_Pntr, Aud, ref num_samp);
|
|
|
|
for (int i = 0; i < num_samp;i++)
|
|
{
|
|
blip.AddDelta((uint)Aud[i * 2], Aud[i * 2 + 1]);
|
|
}
|
|
|
|
blip.EndFrame(f_clock);
|
|
|
|
nsamp = blip.SamplesAvailable();
|
|
samples = new short[nsamp * 2];
|
|
|
|
blip.ReadSamples(samples, nsamp, true);
|
|
}
|
|
|
|
public void DiscardSamples()
|
|
{
|
|
blip.Clear();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Video
|
|
public int _frameHz = 60;
|
|
|
|
public int[] _vidbuffer = new int[192 * 256];
|
|
|
|
public int[] GetVideoBuffer()
|
|
{
|
|
LibMSX.MSX_get_video(MSX_Pntr, _vidbuffer);
|
|
return _vidbuffer;
|
|
}
|
|
|
|
public int VirtualWidth => 256;
|
|
public int VirtualHeight => 192;
|
|
public int BufferWidth => 256;
|
|
public int BufferHeight => 192;
|
|
|
|
public int BackgroundColor => unchecked((int)0xFF000000);
|
|
public int VsyncNumerator => _frameHz;
|
|
public int VsyncDenominator => 1;
|
|
|
|
#endregion
|
|
}
|
|
}
|