GBC IR Emulation for GambatteLink

This commit is contained in:
CasualPokePlayer 2021-11-20 23:47:06 -08:00
parent d9893b1d27
commit 72ad5c7b0b
6 changed files with 133 additions and 97 deletions

Binary file not shown.

View File

@ -31,34 +31,34 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
}
}
bool cableDiscoSignalNew = controller.IsPressed("Toggle Cable Connection");
if (cableDiscoSignalNew && !_cableDiscoSignal)
bool linkDiscoSignalNew = controller.IsPressed("Toggle Link Connection");
if (linkDiscoSignalNew && !_linkDiscoSignal)
{
_cableConnected ^= true;
Console.WriteLine("Cable connect status to {0}", _cableConnected);
_linkConnected ^= true;
Console.WriteLine("Link connect status to {0}", _linkConnected);
}
_cableDiscoSignal = cableDiscoSignalNew;
_linkDiscoSignal = linkDiscoSignalNew;
if (_numCores > 2)
{
bool cableShiftSignalNew = controller.IsPressed("Toggle Cable Shift");
if (cableShiftSignalNew && !_cableShiftSignal)
bool linkShiftSignalNew = controller.IsPressed("Toggle Link Shift");
if (linkShiftSignalNew && !_linkShiftSignal)
{
_cableShifted ^= true;
Console.WriteLine("Cable shift status to {0}", _cableShifted);
_linkShifted ^= true;
Console.WriteLine("Link shift status to {0}", _linkShifted);
}
_cableShifted = cableShiftSignalNew;
_linkShifted = linkShiftSignalNew;
bool cableSpaceSignalNew = controller.IsPressed("Toggle Cable Spacing");
if (cableSpaceSignalNew && !_cableSpaceSignal)
bool linkSpaceSignalNew = controller.IsPressed("Toggle Link Spacing");
if (linkSpaceSignalNew && !_linkSpaceSignal)
{
_cableSpaced ^= true;
Console.WriteLine("Cable spacing status to {0}", _cableSpaceSignal);
_linkSpaced ^= true;
Console.WriteLine("Link spacing status to {0}", _linkSpaceSignal);
}
_cableSpaceSignal = cableSpaceSignalNew;
_linkSpaceSignal = linkSpaceSignalNew;
}
for (int i = 0; i < _numCores; i++)
@ -75,7 +75,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
fixed (short* sbuff = &SoundBuffer[0])
{
const int Step = 32; // could be 1024 for GB
const int Step = 4;
int[] n = new int[_numCores];
for (int i = 0; i < _numCores; i++)
@ -111,7 +111,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
}
// poll link cable statuses, but not when the cable is disconnected
if (!_cableConnected)
if (!_linkConnected)
{
continue;
}
@ -120,51 +120,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
case 2:
{
TryCableBytewiseTransfer(P1, P2);
TryCableBytewiseTransfer(P2, P1);
TryLinkTransfer(P1, P2);
break;
}
case 3:
{
if (_cableSpaced)
if (_linkSpaced)
{
TryCableBytewiseTransfer(P1, P3);
TryCableBytewiseTransfer(P3, P1);
TryLinkTransfer(P1, P3);
}
else if (_cableShifted)
else if (_linkShifted)
{
TryCableBytewiseTransfer(P2, P3);
TryCableBytewiseTransfer(P3, P2);
TryLinkTransfer(P2, P3);
}
else
{
TryCableBytewiseTransfer(P1, P2);
TryCableBytewiseTransfer(P2, P1);
TryLinkTransfer(P1, P2);
}
break;
}
case 4:
{
if (_cableSpaced)
if (_linkSpaced)
{
TryCableBytewiseTransfer(P1, P3);
TryCableBytewiseTransfer(P3, P1);
TryCableBytewiseTransfer(P2, P4);
TryCableBytewiseTransfer(P4, P2);
TryLinkTransfer(P1, P3);
TryLinkTransfer(P2, P4);
}
else if (_cableShifted)
else if (_linkShifted)
{
TryCableBytewiseTransfer(P2, P3);
TryCableBytewiseTransfer(P3, P2);
TryCableBytewiseTransfer(P4, P1);
TryCableBytewiseTransfer(P1, P4);
TryLinkTransfer(P2, P3);
TryLinkTransfer(P4, P1);
}
else
{
TryCableBytewiseTransfer(P1, P2);
TryCableBytewiseTransfer(P2, P1);
TryCableBytewiseTransfer(P3, P4);
TryCableBytewiseTransfer(P4, P3);
TryLinkTransfer(P1, P2);
TryLinkTransfer(P3, P4);
}
break;
}
@ -217,16 +207,62 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
return true;
}
private void TryCableBytewiseTransfer(int master, int slave)
private void TryLinkTransfer(int one, int two)
{
if (LibGambatte.gambatte_linkstatus(_linkedCores[master].GambatteState, 256) != 0) // ClockTrigger
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 256) != 0) // ClockTrigger
{
LibGambatte.gambatte_linkstatus(_linkedCores[master].GambatteState, 257); // ack
int om = LibGambatte.gambatte_linkstatus(_linkedCores[master].GambatteState, 258); // GetOut
int os = LibGambatte.gambatte_linkstatus(_linkedCores[slave].GambatteState, 258);
LibGambatte.gambatte_linkstatus(_linkedCores[slave].GambatteState, om & 0xff); // ShiftIn
LibGambatte.gambatte_linkstatus(_linkedCores[master].GambatteState, os & 0xff); // ShiftIn
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 257); // ack
int oo = LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 258); // GetOut
int ot = LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 258);
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, oo & 0xff); // ShiftIn
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, ot & 0xff); // ShiftIn
}
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 256) != 0) // ClockTrigger
{
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 257); // ack
int ot = LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 258); // GetOut
int oo = LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 258);
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, ot & 0xff); // ShiftIn
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, oo & 0xff); // ShiftIn
}
if (CanIR(one, two))
{
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 260) != 0) // InfraredTrigger
{
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 261); // ack
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 262) != 0) // GetOut
{
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 263); // ShiftInOn
}
else
{
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 264); // ShiftInOff
}
}
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 260) != 0) // InfraredTrigger
{
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 261); // ack
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 262) != 0) // GetOut
{
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 263); // ShiftInOn
}
else
{
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 264); // ShiftInOff
}
}
}
}
private bool CanIR(int one, int two)
{
// the GB and GBA have no IR port, so ignore them for now
// todo: cart based IR
return _syncSettings._linkedSyncSettings[one].ConsoleMode is Gameboy.GambatteSyncSettings.ConsoleModeType.GBC
&& _syncSettings._linkedSyncSettings[two].ConsoleMode is Gameboy.GambatteSyncSettings.ConsoleModeType.GBC;
}
public int Frame { get; private set; }

View File

@ -19,23 +19,23 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
public PutSettingsDirtyBits PutSettings(GambatteLinkSettings o)
{
_settings = o;
var ret = PutSettingsDirtyBits.None;
for (int i = 0; i < _numCores; i++)
{
ret |= _linkedCores[i].PutSettings(o._linkedSettings[i]);
}
_settings = o;
return ret;
}
public PutSettingsDirtyBits PutSyncSettings(GambatteLinkSyncSettings o)
{
_syncSettings = o;
var ret = PutSettingsDirtyBits.None;
for (int i = 0; i < _numCores; i++)
{
ret |= _linkedCores[i].PutSyncSettings(o._linkedSyncSettings[i]);
}
_syncSettings = o;
return ret;
}

View File

@ -30,12 +30,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
IsLagFrame = s.IsLagFrame;
LagCount = s.LagCount;
Frame = s.Frame;
_cableConnected = s.CableConnected;
_cableDiscoSignal = s.CableDiscoSignal;
_cableShifted = s.CableShifted;
_cableShiftSignal = s.CableShiftSignal;
_cableSpaced = s.CableSpaced;
_cableSpaceSignal = s.CableSpaceSignal;
_linkConnected = s.LinkConnected;
_linkDiscoSignal = s.LinkDiscoSignal;
_linkShifted = s.LinkShifted;
_linkShiftSignal = s.LinkShiftSignal;
_linkSpaced = s.LinkSpaced;
_linkSpaceSignal = s.LinkSpaceSignal;
}
public void SaveStateBinary(BinaryWriter writer)
@ -51,12 +51,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
writer.Write(IsLagFrame);
writer.Write(LagCount);
writer.Write(Frame);
writer.Write(_cableConnected);
writer.Write(_cableDiscoSignal);
writer.Write(_cableShifted);
writer.Write(_cableShiftSignal);
writer.Write(_cableSpaced);
writer.Write(_cableSpaceSignal);
writer.Write(_linkConnected);
writer.Write(_linkDiscoSignal);
writer.Write(_linkShifted);
writer.Write(_linkShiftSignal);
writer.Write(_linkSpaced);
writer.Write(_linkSpaceSignal);
}
public void LoadStateBinary(BinaryReader reader)
@ -75,12 +75,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
IsLagFrame = reader.ReadBoolean();
LagCount = reader.ReadInt32();
Frame = reader.ReadInt32();
_cableConnected = reader.ReadBoolean();
_cableDiscoSignal = reader.ReadBoolean();
_cableShifted = reader.ReadBoolean();
_cableShiftSignal = reader.ReadBoolean();
_cableSpaced = reader.ReadBoolean();
_cableSpaceSignal = reader.ReadBoolean();
_linkConnected = reader.ReadBoolean();
_linkDiscoSignal = reader.ReadBoolean();
_linkShifted = reader.ReadBoolean();
_linkShiftSignal = reader.ReadBoolean();
_linkSpaced = reader.ReadBoolean();
_linkSpaceSignal = reader.ReadBoolean();
}
private readonly JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented };
@ -95,12 +95,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
public int Frame;
public int[] LinkedOverflow;
public int[] LinkedLatches;
public bool CableConnected;
public bool CableDiscoSignal;
public bool CableShifted;
public bool CableShiftSignal;
public bool CableSpaced;
public bool CableSpaceSignal;
public bool LinkConnected;
public bool LinkDiscoSignal;
public bool LinkShifted;
public bool LinkShiftSignal;
public bool LinkSpaced;
public bool LinkSpaceSignal;
public DGBSerialized(GambatteLink linkcore)
{
@ -117,12 +117,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
IsLagFrame = linkcore.IsLagFrame;
LagCount = linkcore.LagCount;
Frame = linkcore.Frame;
CableConnected = linkcore._cableConnected;
CableDiscoSignal = linkcore._cableDiscoSignal;
CableShifted = linkcore._cableShifted;
CableShiftSignal = linkcore._cableShiftSignal;
CableSpaced = linkcore._cableSpaced;
CableSpaceSignal = linkcore._cableSpaceSignal;
LinkConnected = linkcore._linkConnected;
LinkDiscoSignal = linkcore._linkDiscoSignal;
LinkShifted = linkcore._linkShifted;
LinkShiftSignal = linkcore._linkShiftSignal;
LinkSpaced = linkcore._linkSpaced;
LinkSpaceSignal = linkcore._linkSpaceSignal;
}
}
}

View File

@ -75,8 +75,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
public bool LinkConnected
{
get => _cableConnected;
set => _cableConnected = value;
get => _linkConnected;
set => _linkConnected = value;
}
private int _numCores = 0;
@ -89,23 +89,23 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
// counters to ensure we do 35112 samples per frame
private readonly int[] _linkedOverflow;
// if true, the link cable is currently connected
private bool _cableConnected = true;
// if true, the link connection is currently active
private bool _linkConnected = true;
// if true, the link cable is currently shifted (3x/4x only)
private bool _cableShifted = false;
// if true, the link is currently shifted (3x/4x only)
private bool _linkShifted = false;
// if true, the link cable is currently spaced outwards (3x/4x only)
private bool _cableSpaced = false;
// if true, the link is currently spaced outwards (3x/4x only)
private bool _linkSpaced = false;
// if true, the link cable toggle signal is currently asserted
private bool _cableDiscoSignal = false;
// if true, the link toggle signal is currently asserted
private bool _linkDiscoSignal = false;
// if true, the link cable shift signal is currently asserted
private bool _cableShiftSignal = false;
// if true, the link shift signal is currently asserted
private bool _linkShiftSignal = false;
// if true, the link cable spacing signal is currently asserted
private bool _cableSpaceSignal = false;
private bool _linkSpaceSignal = false;
private const int SampPerFrame = 35112;
private const int MaxSampsPerFrame = (SampPerFrame + 2064) * 2;
@ -128,11 +128,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start", "Power" }
.Select(s => $"P{i + 1} {s}"));
}
ret.BoolButtons.Add("Toggle Cable Connection");
ret.BoolButtons.Add("Toggle Link Connection");
if (_numCores > 2)
{
ret.BoolButtons.Add("Toggle Cable Shift");
ret.BoolButtons.Add("Toggle Cable Spacing");
ret.BoolButtons.Add("Toggle Link Shift");
ret.BoolButtons.Add("Toggle Link Spacing");
}
return ret;
}

@ -1 +1 @@
Subproject commit f1ae63f57778f9869bd79000f1d300ed532400ff
Subproject commit d5abea79e1571a2078c1fc689969b839e08d82e7