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"); bool linkDiscoSignalNew = controller.IsPressed("Toggle Link Connection");
if (cableDiscoSignalNew && !_cableDiscoSignal) if (linkDiscoSignalNew && !_linkDiscoSignal)
{ {
_cableConnected ^= true; _linkConnected ^= true;
Console.WriteLine("Cable connect status to {0}", _cableConnected); Console.WriteLine("Link connect status to {0}", _linkConnected);
} }
_cableDiscoSignal = cableDiscoSignalNew; _linkDiscoSignal = linkDiscoSignalNew;
if (_numCores > 2) if (_numCores > 2)
{ {
bool cableShiftSignalNew = controller.IsPressed("Toggle Cable Shift"); bool linkShiftSignalNew = controller.IsPressed("Toggle Link Shift");
if (cableShiftSignalNew && !_cableShiftSignal) if (linkShiftSignalNew && !_linkShiftSignal)
{ {
_cableShifted ^= true; _linkShifted ^= true;
Console.WriteLine("Cable shift status to {0}", _cableShifted); Console.WriteLine("Link shift status to {0}", _linkShifted);
} }
_cableShifted = cableShiftSignalNew; _linkShifted = linkShiftSignalNew;
bool cableSpaceSignalNew = controller.IsPressed("Toggle Cable Spacing"); bool linkSpaceSignalNew = controller.IsPressed("Toggle Link Spacing");
if (cableSpaceSignalNew && !_cableSpaceSignal) if (linkSpaceSignalNew && !_linkSpaceSignal)
{ {
_cableSpaced ^= true; _linkSpaced ^= true;
Console.WriteLine("Cable spacing status to {0}", _cableSpaceSignal); Console.WriteLine("Link spacing status to {0}", _linkSpaceSignal);
} }
_cableSpaceSignal = cableSpaceSignalNew; _linkSpaceSignal = linkSpaceSignalNew;
} }
for (int i = 0; i < _numCores; i++) for (int i = 0; i < _numCores; i++)
@ -75,7 +75,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
fixed (short* sbuff = &SoundBuffer[0]) fixed (short* sbuff = &SoundBuffer[0])
{ {
const int Step = 32; // could be 1024 for GB const int Step = 4;
int[] n = new int[_numCores]; int[] n = new int[_numCores];
for (int i = 0; i < _numCores; i++) 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 // poll link cable statuses, but not when the cable is disconnected
if (!_cableConnected) if (!_linkConnected)
{ {
continue; continue;
} }
@ -120,51 +120,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{ {
case 2: case 2:
{ {
TryCableBytewiseTransfer(P1, P2); TryLinkTransfer(P1, P2);
TryCableBytewiseTransfer(P2, P1);
break; break;
} }
case 3: case 3:
{ {
if (_cableSpaced) if (_linkSpaced)
{ {
TryCableBytewiseTransfer(P1, P3); TryLinkTransfer(P1, P3);
TryCableBytewiseTransfer(P3, P1);
} }
else if (_cableShifted) else if (_linkShifted)
{ {
TryCableBytewiseTransfer(P2, P3); TryLinkTransfer(P2, P3);
TryCableBytewiseTransfer(P3, P2);
} }
else else
{ {
TryCableBytewiseTransfer(P1, P2); TryLinkTransfer(P1, P2);
TryCableBytewiseTransfer(P2, P1);
} }
break; break;
} }
case 4: case 4:
{ {
if (_cableSpaced) if (_linkSpaced)
{ {
TryCableBytewiseTransfer(P1, P3); TryLinkTransfer(P1, P3);
TryCableBytewiseTransfer(P3, P1); TryLinkTransfer(P2, P4);
TryCableBytewiseTransfer(P2, P4);
TryCableBytewiseTransfer(P4, P2);
} }
else if (_cableShifted) else if (_linkShifted)
{ {
TryCableBytewiseTransfer(P2, P3); TryLinkTransfer(P2, P3);
TryCableBytewiseTransfer(P3, P2); TryLinkTransfer(P4, P1);
TryCableBytewiseTransfer(P4, P1);
TryCableBytewiseTransfer(P1, P4);
} }
else else
{ {
TryCableBytewiseTransfer(P1, P2); TryLinkTransfer(P1, P2);
TryCableBytewiseTransfer(P2, P1); TryLinkTransfer(P3, P4);
TryCableBytewiseTransfer(P3, P4);
TryCableBytewiseTransfer(P4, P3);
} }
break; break;
} }
@ -217,16 +207,62 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
return true; 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 LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 257); // ack
int om = LibGambatte.gambatte_linkstatus(_linkedCores[master].GambatteState, 258); // GetOut int oo = LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 258); // GetOut
int os = LibGambatte.gambatte_linkstatus(_linkedCores[slave].GambatteState, 258); int ot = LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 258);
LibGambatte.gambatte_linkstatus(_linkedCores[slave].GambatteState, om & 0xff); // ShiftIn LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, oo & 0xff); // ShiftIn
LibGambatte.gambatte_linkstatus(_linkedCores[master].GambatteState, os & 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; } public int Frame { get; private set; }

View File

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

View File

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

View File

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

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