Skip to content

Commit 7a89e1e

Browse files
FortranmMorilliYoshiRulz
authored
Simplify SGB related UIs and make it possible to use SGB under Gambatte link (#3635)
* merge SGB into a mode option of Gambatte * merge the core choices for SGB * GBL compatibility * rename SGB mode to SGB2 for Gambatte and fix BSNES initialization * SGB border in GBL * adjust sgb core detection * reformat controller button naming * adjust for 2.9 * adjust for 2.9 again * revert changes to BSNES CoreConstructor The system id will still be SGB for BSNES cores by default * one Player tab per SNES controller for SGB * idiomatic rephrase for showAnyBorder * no dummy for CreateSGBVideoBuffer * fix SGB conversion in LsmvImport * add legacy BSNES option for (S)GB * minor cosmetic changes * Fix `.vbm` importer when Gambatte isn't the preferred GB core * Fix button mapping spaghetti * Code style nitpicks * minor cleanups in Gambatte.cs * Remove special SGB handling and mark bsnes* as GB/GBC cores * remove SGB from CorePickerUIData This fixes failures in CorePickerStabilityTests (https://ci.appveyor.com/project/zeromus/bizhawk-udexo/builds/50119675). It's not necessary to put SGB there as the system id is only ever switched to SGB after a relevant core is already initiated. * Un-revert submodule pull * Un-revert other submodule pulls * fix the crash from Toggle Link Connection * remove inaccurate description of how Auto works for console * Remove unused import * do not change overall GUI * fix byte-order markers * do not mutate sync setting * text --------- Co-authored-by: Morilli <35152647+Morilli@users.noreply.github.com> Co-authored-by: YoshiRulz <OSSYoshiRulz+git@gmail.com>
1 parent 710fc4e commit 7a89e1e

File tree

8 files changed

+116
-36
lines changed

8 files changed

+116
-36
lines changed

src/BizHawk.Client.Common/movie/import/LsmvImport.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ protected override void RunImport()
158158
break;
159159
case "sgb_ntsc":
160160
case "sgb_pal":
161-
platform = VSystemID.Raw.SNES;
162-
Config.GbAsSgb = true;
161+
platform = VSystemID.Raw.SGB;
163162
break;
164163
}
165164

src/BizHawk.Client.Common/movie/import/VbmImport.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,15 @@ recording time in Unix epoch format
122122
Result.Movie.HeaderEntries.Add("IsCGBMode", "1");
123123
}
124124

125+
var finalCoreName = Config.PreferredCores[VSystemID.Raw.GB];
125126
if (isSGB)
126127
{
127-
Result.Errors.Add("SGB imports are not currently supported");
128+
platform = VSystemID.Raw.SGB;
129+
if (finalCoreName is not CoreNames.Gambatte)
130+
{
131+
Result.Warnings.Add($"{finalCoreName} doesn't support SGB; will use {CoreNames.Gambatte}");
132+
finalCoreName = CoreNames.Gambatte;
133+
}
128134
}
129135

130136
Result.Movie.HeaderEntries[HeaderKeys.Platform] = platform;
@@ -277,13 +283,15 @@ A stream of 2-byte bitvectors which indicate which buttons are pressed at each p
277283
}
278284
else
279285
{
280-
Result.Movie.HeaderEntries[HeaderKeys.Core] = Config.PreferredCores[VSystemID.Raw.GB];
281-
switch (Config.PreferredCores[VSystemID.Raw.GB])
286+
Result.Movie.HeaderEntries[HeaderKeys.Core] = finalCoreName;
287+
switch (finalCoreName)
282288
{
283289
case CoreNames.Gambatte:
284290
Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(new Gameboy.GambatteSyncSettings
285291
{
286-
ConsoleMode = is_GBC ? Gameboy.GambatteSyncSettings.ConsoleModeType.GBC : Gameboy.GambatteSyncSettings.ConsoleModeType.GB,
292+
ConsoleMode = isSGB
293+
? Gameboy.GambatteSyncSettings.ConsoleModeType.SGB2
294+
: is_GBC ? Gameboy.GambatteSyncSettings.ConsoleModeType.GBC : Gameboy.GambatteSyncSettings.ConsoleModeType.GB,
287295
});
288296
break;
289297
case CoreNames.GbHawk:

src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,12 @@ public enum ConsoleModeType
110110
Auto,
111111
GB,
112112
GBC,
113-
GBA
113+
GBA,
114+
SGB2,
114115
}
115116

116117
[DisplayName("Console Mode")]
117-
[Description("Pick which console to run, 'Auto' chooses from ROM header; 'GB', 'GBC', and 'GBA' chooses the respective system. Does nothing in SGB mode.")]
118+
[Description("Picks which console to emulate. 'SGB2' is always in effect when 'GB in SGB' is checked.")]
118119
[DefaultValue(ConsoleModeType.Auto)]
119120
public ConsoleModeType ConsoleMode { get; set; }
120121

src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public Gameboy(CoreComm comm, IGameInfo game, byte[] file, GambatteSettings sett
4747

4848
var flags = LibGambatte.LoadFlags.READONLY_SAV;
4949

50-
switch (_syncSettings.ConsoleMode)
50+
switch (game.System is VSystemID.Raw.SGB ? GambatteSyncSettings.ConsoleModeType.SGB2 : _syncSettings.ConsoleMode)
5151
{
5252
case GambatteSyncSettings.ConsoleModeType.GB:
5353
break;
@@ -57,6 +57,10 @@ public Gameboy(CoreComm comm, IGameInfo game, byte[] file, GambatteSettings sett
5757
case GambatteSyncSettings.ConsoleModeType.GBA:
5858
flags |= LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG;
5959
break;
60+
case GambatteSyncSettings.ConsoleModeType.SGB2:
61+
flags |= LibGambatte.LoadFlags.SGB_MODE;
62+
IsSgb = true;
63+
break;
6064
case GambatteSyncSettings.ConsoleModeType.Auto:
6165
if (game.System == VSystemID.Raw.GBC)
6266
flags |= LibGambatte.LoadFlags.CGB_MODE;
@@ -65,13 +69,6 @@ public Gameboy(CoreComm comm, IGameInfo game, byte[] file, GambatteSettings sett
6569
throw new InvalidOperationException();
6670
}
6771

68-
if (game.System == VSystemID.Raw.SGB)
69-
{
70-
flags &= ~(LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG);
71-
flags |= LibGambatte.LoadFlags.SGB_MODE;
72-
IsSgb = true;
73-
}
74-
7572
IsCgb = (flags & LibGambatte.LoadFlags.CGB_MODE) == LibGambatte.LoadFlags.CGB_MODE;
7673

7774
bool ForceBios()

src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using BizHawk.Common.StringExtensions;
12
using BizHawk.Emulation.Common;
23

34
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
@@ -17,16 +18,26 @@ public bool FrameAdvance(IController controller, bool render, bool rendersound =
1718

1819
foreach (var s in GBLinkController.BoolButtons)
1920
{
20-
if (controller.IsPressed(s))
21+
if (!controller.IsPressed(s)) continue;
22+
if (s[0] is not 'P') continue;
23+
var iSpace = s.IndexOf(' ');
24+
var playerNum = int.Parse(s.Substring(startIndex: 1, length: iSpace - 1));
25+
var consoleNum = 0;
26+
var isSGB = false;
27+
while (consoleNum < _numCores)
2128
{
22-
for (int i = 0; i < _numCores; i++)
23-
{
24-
if (s.Contains($"P{i + 1} "))
25-
{
26-
_linkedConts[i].Set(s.Replace($"P{i + 1} ", ""));
27-
}
28-
}
29+
isSGB = IsSgb(consoleNum);
30+
var playersForConsole = isSGB ? 4 : 1;
31+
if (playerNum <= playersForConsole) break;
32+
playerNum -= playersForConsole;
33+
consoleNum++;
2934
}
35+
//TODO rather than this string manipulation, could construct a lookup ahead of time
36+
_linkedConts[consoleNum].Set(s.EndsWithOrdinal("Power")
37+
? "Power"
38+
: isSGB
39+
? $"P{playerNum} {s.Substring(startIndex: iSpace + 1)}"
40+
: s.Substring(startIndex: iSpace + 1));
3041
}
3142

3243
bool linkDiscoSignalNew = controller.IsPressed("Toggle Link Connection");
@@ -66,10 +77,11 @@ public bool FrameAdvance(IController controller, bool render, bool rendersound =
6677

6778
unsafe
6879
{
69-
fixed (int* fbuff = &FrameBuffer[0])
80+
fixed (int* fbuff = &FrameBuffer[0], svbuff = SgbVideoBuffer)
7081
{
7182
// use pitch to have both cores write to the same frame buffer, interleaved
7283
int Pitch = 160 * _numCores;
84+
int sgbPitch = 256 * _numCores;
7385

7486
fixed (short* sbuff = &SoundBuffer[0])
7587
{
@@ -102,6 +114,27 @@ public bool FrameAdvance(IController controller, bool render, bool rendersound =
102114
{
103115
Array.Copy(FrameBuffer, (i * 160) + (j * Pitch), VideoBuffer, (i * 160) + (j * Pitch), 160);
104116
}
117+
if (IsAnySgb)
118+
{
119+
// all SGB borders will be displayed when any of them has the option enabled
120+
if (IsSgb(i))
121+
{
122+
if (LibGambatte.gambatte_updatescreenborder(
123+
_linkedCores[i].GambatteState,
124+
svbuff + (i * 256),
125+
sgbPitch) is not 0)
126+
{
127+
throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_updatescreenborder)}() returned non-zero (border error???)");
128+
}
129+
}
130+
else
131+
{
132+
for (int j = 0; j < 144; j++)
133+
{
134+
Array.Copy(FrameBuffer, (i * 160) + (j * Pitch), SgbVideoBuffer, (i * 256 + 48) + (40 + j) * sgbPitch, 160);
135+
}
136+
}
137+
}
105138
}
106139

107140
n[i] += (int)nsamp;

src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IVideoProvider.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
44
{
55
public partial class GambatteLink : IVideoProvider
66
{
7-
public int VirtualWidth => 160 * _numCores;
8-
public int VirtualHeight => 144;
9-
public int BufferWidth => 160 * _numCores;
10-
public int BufferHeight => 144;
7+
public int VirtualWidth
8+
=> (ShowAnyBorder() ? 256 : 160) * _numCores;
9+
10+
public int VirtualHeight
11+
=> ShowAnyBorder() ? 224 : 144;
12+
13+
public int BufferWidth
14+
=> VirtualWidth;
15+
16+
public int BufferHeight
17+
=> VirtualHeight;
1118

1219
public int VsyncNumerator => _linkedCores[P1].VsyncNumerator;
1320

@@ -17,18 +24,24 @@ public partial class GambatteLink : IVideoProvider
1724

1825
private readonly int[] FrameBuffer;
1926

20-
public int[] GetVideoBuffer() => VideoBuffer;
27+
public int[] GetVideoBuffer()
28+
=> ShowAnyBorder() ? SgbVideoBuffer : VideoBuffer;
2129

2230
private readonly int[] VideoBuffer;
2331

32+
private readonly int[] SgbVideoBuffer;
33+
2434
private int[] CreateVideoBuffer()
2535
{
26-
var b = new int[BufferWidth * BufferHeight];
36+
var b = new int[160 * _numCores * 144];
2737
for (int i = 0; i < b.Length; i++)
2838
{
2939
b[i] = -1; // GB/C screen is disabled on bootup, so it always starts as white, not black
3040
}
3141
return b;
3242
}
43+
44+
private int[] CreateSGBVideoBuffer()
45+
=> IsAnySgb ? new int[256 * _numCores * 224] : null;
3346
}
3447
}

src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ public GambatteLink(CoreLoadParameters<GambatteLinkSettings, GambatteLinkSyncSet
4848
_linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested);
4949
_linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks);
5050
_linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks, i);
51-
_linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: false, rumble: false, remote: false));
51+
IsAnySgb |= IsSgb(i);
52+
_linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(sgb: IsSgb(i), sub: false, tilt: false, rumble: false, remote: false));
5253
_linkedBlips[i] = new BlipBuffer(1024);
5354
_linkedBlips[i].SetRates(2097152 * 2, 44100);
5455
_linkedOverflow[i] = 0;
@@ -66,6 +67,7 @@ public GambatteLink(CoreLoadParameters<GambatteLinkSettings, GambatteLinkSyncSet
6667

6768
FrameBuffer = CreateVideoBuffer();
6869
VideoBuffer = CreateVideoBuffer();
70+
SgbVideoBuffer = CreateSGBVideoBuffer();
6971

7072
GBLinkController = CreateControllerDefinition();
7173

@@ -142,12 +144,23 @@ public IGameboyCommon First
142144

143145
private ControllerDefinition CreateControllerDefinition()
144146
{
147+
static void AddGBButtonsForPlayer(int p, ControllerDefinition ret)
148+
{
149+
var pfx = $"P{p} ";
150+
ret.BoolButtons.AddRange(new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start" }
151+
.Select(s => pfx + s));
152+
}
145153
ControllerDefinition ret = new($"GB Link {_numCores}x Controller");
146-
for (int i = 0; i < _numCores; i++)
154+
for (int i = 0, p = 1; i < _numCores; i++)
147155
{
148-
ret.BoolButtons.AddRange(
149-
new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start", "Power" }
150-
.Select(s => $"P{i + 1} {s}"));
156+
AddGBButtonsForPlayer(p, ret);
157+
ret.BoolButtons.Add($"P{p} Power");
158+
p++;
159+
if (IsSgb(i))
160+
{
161+
// add 3 more gamepads without a Power button
162+
for (int e = p + 3; p < e; p++) AddGBButtonsForPlayer(p, ret);
163+
}
151164
}
152165
ret.BoolButtons.Add("Toggle Link Connection");
153166
if (_numCores > 2)
@@ -158,6 +171,20 @@ private ControllerDefinition CreateControllerDefinition()
158171
return ret.MakeImmutable();
159172
}
160173

174+
private bool IsSgb(int i)
175+
=> _linkedCores[i].IsSgb;
176+
177+
public bool IsAnySgb { get; private set; }
178+
179+
private bool ShowBorder(int i)
180+
=> IsSgb(i) && _settings._linkedSettings[i].ShowBorder;
181+
182+
public bool ShowAnyBorder()
183+
{
184+
for (var i = 0; i < _numCores; i++) if (ShowBorder(i)) return true;
185+
return false;
186+
}
187+
161188
private const int P1 = 0;
162189
private const int P2 = 1;
163190
private const int P3 = 2;

src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public enum CDLog_Flags : int
9595

9696
[DllImport("libgambatte", CallingConvention = CallingConvention.Cdecl)]
9797
public static extern int gambatte_updatescreenborder(IntPtr core, int[] videobuf, int pitch);
98+
[DllImport("libgambatte", CallingConvention = CallingConvention.Cdecl)]
99+
public static extern unsafe int gambatte_updatescreenborder(IntPtr core, int* videobuf, int pitch);
98100

99101
[DllImport("libgambatte", CallingConvention = CallingConvention.Cdecl)]
100102
public static extern int gambatte_generatesgbsamples(IntPtr core, short[] soundbuf, out uint samples);

0 commit comments

Comments
 (0)