GBHawk: expose 4x core

This commit is contained in:
alyosha-tas 2019-10-04 13:52:29 -04:00
parent 905fc1ac1e
commit d2fe217869
16 changed files with 320 additions and 31 deletions

View File

@ -114,6 +114,9 @@ namespace BizHawk.Client.ApiHawk
case "GB3x":
return CoreSystem.GB3x;
case "GB4x":
return CoreSystem.GB3x;
case "VB":
case "NGP":
case "DNGP":

View File

@ -35,6 +35,7 @@
AmstradCPC,
GGL,
ChannelF,
GB3x
GB3x,
GB4x
}
}

View File

@ -138,6 +138,8 @@ namespace BizHawk.Client.Common
return SystemInfo.DualGB;
case "GB3x":
return SystemInfo.GB3x;
case "GB4x":
return SystemInfo.GB4x;
case "WSWAN":
return SystemInfo.WonderSwan;
case "Lynx":

View File

@ -16,6 +16,7 @@ using BizHawk.Emulation.Cores.Nintendo.Gameboy;
using BizHawk.Emulation.Cores.Nintendo.GBHawk;
using BizHawk.Emulation.Cores.Nintendo.GBHawkLink;
using BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x;
using BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x;
using BizHawk.Emulation.Cores.Nintendo.SNES;
using BizHawk.Emulation.Cores.PCEngine;
using BizHawk.Emulation.Cores.Sega.GGHawkLink;
@ -681,6 +682,31 @@ namespace BizHawk.Client.Common
GetCoreSettings<GBHawkLink3x>(),
GetCoreSyncSettings<GBHawkLink3x>());
break;
case "GB4x":
var A_Bytes4x = xmlGame.Assets.First().Value;
var B_Bytes4x = xmlGame.Assets.Skip(1).First().Value;
var C_Bytes4x = xmlGame.Assets.Skip(2).First().Value;
var D_Bytes4x = xmlGame.Assets.Skip(3).First().Value;
var A_4x = Database.GetGameInfo(A_Bytes4x, "A.gb");
var B_4x = Database.GetGameInfo(B_Bytes4x, "B.gb");
var C_4x = Database.GetGameInfo(C_Bytes4x, "C.gb");
var D_4x = Database.GetGameInfo(D_Bytes4x, "D.gb");
nextEmulator = new GBHawkLink4x(
nextComm,
A_4x,
B_Bytes4x,
B_4x,
B_Bytes4x,
C_4x,
C_Bytes4x,
D_4x,
D_Bytes4x,
GetCoreSettings<GBHawkLink4x>(),
GetCoreSyncSettings<GBHawkLink4x>());
break;
case "AppleII":
var assets = xmlGame.Assets.Select(a => Database.GetGameInfo(a.Value, a.Key));

View File

@ -74,10 +74,15 @@ namespace BizHawk.Client.Common
public static SystemInfo Coleco { get; } = new SystemInfo("ColecoVision", CoreSystem.ColecoVision, 1);
/// <summary>
/// Gets the <see cref="SystemInfo"/> instance for Dual Gameboy
/// Gets the <see cref="SystemInfo"/> instance for Triple Gameboy
/// </summary>
public static SystemInfo GB3x { get; } = new SystemInfo("Game Boy Link 3x", CoreSystem.GB3x, 3, StandardButtons);
/// <summary>
/// Gets the <see cref="SystemInfo"/> instance for Quad Gameboy
/// </summary>
public static SystemInfo GB4x { get; } = new SystemInfo("Game Boy Link 4x", CoreSystem.GB4x, 4, StandardButtons);
/// <summary>
/// Gets the <see cref="SystemInfo"/> instance for Dual Gameboy
/// </summary>

View File

@ -396,6 +396,13 @@ namespace BizHawk.Client.Common
new PathEntry { System = "GB3x", SystemDisplayName = "GB3x", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 },
new PathEntry { System = "GB3x", SystemDisplayName = "GB3x", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 },
new PathEntry { System = "GB4x", SystemDisplayName = "GB4x", Type = "Base", Path = Path.Combine(".", "GB4x"), Ordinal = 0 },
new PathEntry { System = "GB4x", SystemDisplayName = "GB4x", Type = "ROM", Path = ".", Ordinal = 1 },
new PathEntry { System = "GB4x", SystemDisplayName = "GB4x", Type = "Savestates", Path = Path.Combine(".", "State"), Ordinal = 2 },
new PathEntry { System = "GB4x", SystemDisplayName = "GB4x", Type = "Save RAM", Path = Path.Combine(".", "SaveRAM"), Ordinal = 3 },
new PathEntry { System = "GB4x", SystemDisplayName = "GB4x", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 },
new PathEntry { System = "GB4x", SystemDisplayName = "GB4x", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 },
new PathEntry { System = "VEC", SystemDisplayName = "VEC", Type = "Base", Path = Path.Combine(".", "VEC"), Ordinal = 0 },
new PathEntry { System = "VEC", SystemDisplayName = "VEC", Type = "ROM", Path = ".", Ordinal = 1 },
new PathEntry { System = "VEC", SystemDisplayName = "VEC", Type = "Savestates", Path = Path.Combine(".", "State"), Ordinal = 2 },

View File

@ -344,6 +344,13 @@ namespace BizHawk.Client.Common
["Toggle Cable CR"] = 'C',
["Toggle Cable RL"] = 'R'
},
["GB4x"] = new Dictionary<string, char>
{
["Toggle Cable UD"] = 'U',
["Toggle Cable LR"] = 'L',
["Toggle Cable X"] = 'X',
["Toggle Cable 4x"] = '4'
},
["Lynx"] = new Dictionary<string, char>
{
["Option 1"] = '1',

View File

@ -217,6 +217,7 @@ namespace BizHawk.Client.DBMan
NGP,
ChannelF,
VEC,
GB3x
GB3x,
GB4x
}
}

View File

@ -357,6 +357,8 @@
this.DGBHawksettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GB3xSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.GB3xsettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GB4xSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.GB4xsettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GGLSubMenu = new System.Windows.Forms.ToolStripMenuItem();
this.GGLsettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.VectrexSubMenu = new System.Windows.Forms.ToolStripMenuItem();
@ -515,6 +517,7 @@
this.DGBSubMenu,
this.DGBHawkSubMenu,
this.GB3xSubMenu,
this.GB4xSubMenu,
this.GGLSubMenu,
this.GenesisSubMenu,
this.wonderSwanToolStripMenuItem,
@ -3236,6 +3239,21 @@
this.GB3xsettingsToolStripMenuItem.Text = "Settings...";
this.GB3xsettingsToolStripMenuItem.Click += new System.EventHandler(this.GB3xSettingsMenuItem_Click);
//
// GB4xSubMenu
//
this.GB4xSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.GB4xsettingsToolStripMenuItem});
this.GB4xSubMenu.Name = "GB4xSubMenu";
this.GB4xSubMenu.Size = new System.Drawing.Size(59, 19);
this.GB4xSubMenu.Text = "&GB Link 4x";
//
// GB4xsettingsToolStripMenuItem
//
this.GB4xsettingsToolStripMenuItem.Name = "GB4xsettingsToolStripMenuItem";
this.GB4xsettingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
this.GB4xsettingsToolStripMenuItem.Text = "Settings...";
this.GB4xsettingsToolStripMenuItem.Click += new System.EventHandler(this.GB4xSettingsMenuItem_Click);
//
// GGLSubMenu
//
this.GGLSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -4597,6 +4615,8 @@
private System.Windows.Forms.ToolStripMenuItem DGBHawksettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem GB3xSubMenu;
private System.Windows.Forms.ToolStripMenuItem GB3xsettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem GB4xSubMenu;
private System.Windows.Forms.ToolStripMenuItem GB4xsettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem GGLSubMenu;
private System.Windows.Forms.ToolStripMenuItem GGLsettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem VectrexSubMenu;

View File

@ -2395,6 +2395,15 @@ namespace BizHawk.Client.EmuHawk
#endregion
#region GB4x
private void GB4xSettingsMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "Gameboy Settings");
}
#endregion
#region GGL
private void GGLSettingsMenuItem_Click(object sender, EventArgs e)

View File

@ -1730,6 +1730,7 @@ namespace BizHawk.Client.EmuHawk
DGBSubMenu.Visible = false;
DGBHawkSubMenu.Visible = false;
GB3xSubMenu.Visible = false;
GB4xSubMenu.Visible = false;
GGLSubMenu.Visible = false;
GenesisSubMenu.Visible = false;
wonderSwanToolStripMenuItem.Visible = false;
@ -1864,6 +1865,9 @@ namespace BizHawk.Client.EmuHawk
case "GB3x":
GB3xSubMenu.Visible = true;
break;
case "GB4x":
GB4xSubMenu.Visible = true;
break;
}
}

View File

@ -142,7 +142,8 @@
"C64",
"GB",
"GB3x",
"PCFX",
"GB4x",
"PCFX",
"PSX",
"SAT",
"ZXSpectrum",

View File

@ -91,33 +91,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
HardReset();
}
if (controller.IsPressed("Toggle Cable LC") | controller.IsPressed("Toggle Cable CR") | controller.IsPressed("Toggle Cable RL"))
if (controller.IsPressed("Toggle Cable UD") | controller.IsPressed("Toggle Cable LR") | controller.IsPressed("Toggle Cable X") | controller.IsPressed("Toggle Cable 4x"))
{
// if any connection exists, disconnect it
// otherwise connect in order of precedence
// only one event can happen per frame, either a connection or disconnection
if (_cableconnected_LC | _cableconnected_CR | _cableconnected_RL)
if (_cableconnected_UD | _cableconnected_LR | _cableconnected_X | _cableconnected_4x)
{
_cableconnected_LC = _cableconnected_CR = _cableconnected_RL = false;
_cableconnected_UD = _cableconnected_LR = _cableconnected_X = _cableconnected_4x = false;
do_2_next = false;
}
else if (controller.IsPressed("Toggle Cable LC"))
else if (controller.IsPressed("Toggle Cable UD"))
{
_cableconnected_LC = true;
_cableconnected_UD = true;
}
else if (controller.IsPressed("Toggle Cable CR"))
else if (controller.IsPressed("Toggle Cable LR"))
{
_cableconnected_CR = true;
_cableconnected_LR = true;
}
else if (controller.IsPressed("Toggle Cable RL"))
else if (controller.IsPressed("Toggle Cable X"))
{
_cableconnected_RL = true;
_cableconnected_X = true;
}
else if (controller.IsPressed("Toggle Cable 4x"))
{
_cableconnected_4x = true;
}
Console.WriteLine("Cable connect status:");
Console.WriteLine("LC: " + _cableconnected_LC);
Console.WriteLine("CR: " + _cableconnected_CR);
Console.WriteLine("RL: " + _cableconnected_RL);
Console.WriteLine("UD: " + _cableconnected_UD);
Console.WriteLine("LR: " + _cableconnected_LR);
Console.WriteLine("X: " + _cableconnected_X);
Console.WriteLine("4x: " + _cableconnected_4x);
}
_islag = true;
@ -125,7 +130,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
GetControllerState(controller);
do_frame_fill = false;
do_frame();
if (_cableconnected_4x)
{
do_frame_4x();
}
else
{
do_frame_2x2();
}
if (do_frame_fill)
{
FillVideoBuffer();
@ -141,7 +155,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
return true;
}
public void do_frame()
public void do_frame_4x()
{
// advance one full frame
for (int i = 0; i < 70224; i++)
@ -151,7 +165,193 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
C.do_single_step();
D.do_single_step();
if (_cableconnected_LC)
/*
// the signal to shift out a bit is when serial_clock = 1
if (((A.serialport.serial_clock == 1) || (A.serialport.serial_clock == 2)) && (A.serialport.clk_rate > 0) && !do_2_next)
{
A.serialport.going_out = (byte)(A.serialport.serial_data >> 7);
if ((C.serialport.clk_rate == -1) && C.serialport.serial_start && A.serialport.can_pulse)
{
C.serialport.serial_clock = A.serialport.serial_clock;
C.serialport.going_out = (byte)(C.serialport.serial_data >> 7);
C.serialport.coming_in = A.serialport.going_out;
}
A.serialport.coming_in = C.serialport.going_out;
A.serialport.can_pulse = false;
}
else if (((C.serialport.serial_clock == 1) || (C.serialport.serial_clock == 2)) && (C.serialport.clk_rate > 0))
{
do_2_next = false;
C.serialport.going_out = (byte)(C.serialport.serial_data >> 7);
if ((A.serialport.clk_rate == -1) && A.serialport.serial_start && C.serialport.can_pulse)
{
A.serialport.serial_clock = C.serialport.serial_clock;
A.serialport.going_out = (byte)(A.serialport.serial_data >> 7);
A.serialport.coming_in = C.serialport.going_out;
}
C.serialport.coming_in = A.serialport.going_out;
C.serialport.can_pulse = false;
if (C.serialport.serial_clock == 2) { do_2_next = true; }
}
else
{
do_2_next = false;
}
// the signal to shift out a bit is when serial_clock = 1
if (((C.serialport.serial_clock == 1) || (C.serialport.serial_clock == 2)) && (C.serialport.clk_rate > 0) && !do_2_next)
{
C.serialport.going_out = (byte)(C.serialport.serial_data >> 7);
if ((D.serialport.clk_rate == -1) && D.serialport.serial_start && C.serialport.can_pulse)
{
D.serialport.serial_clock = C.serialport.serial_clock;
D.serialport.going_out = (byte)(D.serialport.serial_data >> 7);
D.serialport.coming_in = C.serialport.going_out;
}
C.serialport.coming_in = D.serialport.going_out;
C.serialport.can_pulse = false;
}
else if (((D.serialport.serial_clock == 1) || (D.serialport.serial_clock == 2)) && (D.serialport.clk_rate > 0))
{
do_2_next = false;
D.serialport.going_out = (byte)(D.serialport.serial_data >> 7);
if ((C.serialport.clk_rate == -1) && C.serialport.serial_start && D.serialport.can_pulse)
{
C.serialport.serial_clock = D.serialport.serial_clock;
C.serialport.going_out = (byte)(C.serialport.serial_data >> 7);
C.serialport.coming_in = D.serialport.going_out;
}
D.serialport.coming_in = C.serialport.going_out;
D.serialport.can_pulse = false;
if (D.serialport.serial_clock == 2) { do_2_next = true; }
}
else
{
do_2_next = false;
}
// the signal to shift out a bit is when serial_clock = 1
if (((D.serialport.serial_clock == 1) || (D.serialport.serial_clock == 2)) && (D.serialport.clk_rate > 0) && !do_2_next)
{
D.serialport.going_out = (byte)(D.serialport.serial_data >> 7);
if ((A.serialport.clk_rate == -1) && A.serialport.serial_start && D.serialport.can_pulse)
{
A.serialport.serial_clock = D.serialport.serial_clock;
A.serialport.going_out = (byte)(A.serialport.serial_data >> 7);
A.serialport.coming_in = D.serialport.going_out;
}
D.serialport.coming_in = A.serialport.going_out;
D.serialport.can_pulse = false;
}
else if (((A.serialport.serial_clock == 1) || (A.serialport.serial_clock == 2)) && (A.serialport.clk_rate > 0))
{
do_2_next = false;
A.serialport.going_out = (byte)(A.serialport.serial_data >> 7);
if ((D.serialport.clk_rate == -1) && D.serialport.serial_start && A.serialport.can_pulse)
{
D.serialport.serial_clock = A.serialport.serial_clock;
D.serialport.going_out = (byte)(D.serialport.serial_data >> 7);
D.serialport.coming_in = A.serialport.going_out;
}
A.serialport.coming_in = D.serialport.going_out;
A.serialport.can_pulse = false;
if (A.serialport.serial_clock == 2) { do_2_next = true; }
}
else
{
do_2_next = false;
}
*/
// if we hit a frame boundary, update video
if (A.vblank_rise)
{
// update the controller state on VBlank
A.controller_state = A_controller;
// check if controller state caused interrupt
A.do_controller_check();
// send the image on VBlank
A.SendVideoBuffer();
A.vblank_rise = false;
do_frame_fill = true;
}
if (B.vblank_rise)
{
// update the controller state on VBlank
B.controller_state = B_controller;
// check if controller state caused interrupt
B.do_controller_check();
// send the image on VBlank
B.SendVideoBuffer();
B.vblank_rise = false;
do_frame_fill = true;
}
if (C.vblank_rise)
{
// update the controller state on VBlank
C.controller_state = C_controller;
// check if controller state caused interrupt
C.do_controller_check();
// send the image on VBlank
C.SendVideoBuffer();
C.vblank_rise = false;
do_frame_fill = true;
}
if (D.vblank_rise)
{
// update the controller state on VBlank
D.controller_state = D_controller;
// check if controller state caused interrupt
D.do_controller_check();
// send the image on VBlank
D.SendVideoBuffer();
D.vblank_rise = false;
do_frame_fill = true;
}
}
}
public void do_frame_2x2()
{
// advance one full frame
for (int i = 0; i < 70224; i++)
{
A.do_single_step();
B.do_single_step();
C.do_single_step();
D.do_single_step();
if (_cableconnected_UD)
{
// the signal to shift out a bit is when serial_clock = 1
if (((A.serialport.serial_clock == 1) || (A.serialport.serial_clock == 2)) && (A.serialport.clk_rate > 0) && !do_2_next)
@ -191,7 +391,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
do_2_next = false;
}
}
else if (_cableconnected_CR)
else if (_cableconnected_LR)
{
// the signal to shift out a bit is when serial_clock = 1
if (((C.serialport.serial_clock == 1) || (C.serialport.serial_clock == 2)) && (C.serialport.clk_rate > 0) && !do_2_next)
@ -231,7 +431,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
do_2_next = false;
}
}
else if (_cableconnected_RL)
else if (_cableconnected_X)
{
// the signal to shift out a bit is when serial_clock = 1
if (((D.serialport.serial_clock == 1) || (D.serialport.serial_clock == 2)) && (D.serialport.clk_rate > 0) && !do_2_next)

View File

@ -65,9 +65,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
ser.Sync("Lag", ref _lagcount);
ser.Sync("Frame", ref _frame);
ser.Sync("IsLag", ref _islag);
ser.Sync(nameof(_cableconnected_LC), ref _cableconnected_LC);
ser.Sync(nameof(_cableconnected_CR), ref _cableconnected_CR);
ser.Sync(nameof(_cableconnected_RL), ref _cableconnected_RL);
ser.Sync(nameof(_cableconnected_UD), ref _cableconnected_UD);
ser.Sync(nameof(_cableconnected_LR), ref _cableconnected_LR);
ser.Sync(nameof(_cableconnected_X), ref _cableconnected_X);
ser.Sync(nameof(_cableconnected_4x), ref _cableconnected_4x);
ser.Sync(nameof(do_2_next), ref do_2_next);
ser.Sync(nameof(A_controller), ref A_controller);
ser.Sync(nameof(B_controller), ref B_controller);

View File

@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
"GBHawkLink4x",
"",
isPorted: false,
isReleased: true)]
isReleased: false)]
[ServiceNotApplicable(typeof(IDriveLight))]
public partial class GBHawkLink4x : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable,
ISettable<GBHawkLink4x.GBLink4xSettings, GBHawkLink4x.GBLink4xSyncSettings>
@ -22,9 +22,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
public GBHawk.GBHawk D;
// if true, the link cable is currently connected
private bool _cableconnected_LC = false;
private bool _cableconnected_CR = false;
private bool _cableconnected_RL = false;
private bool _cableconnected_LR = false;
private bool _cableconnected_UD = false;
private bool _cableconnected_X = false;
private bool _cableconnected_4x = true;
private bool do_2_next = false;

View File

@ -44,9 +44,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
.Concat(Port2.Definition.BoolButtons)
.Concat(Port3.Definition.BoolButtons)
.Concat(Port4.Definition.BoolButtons)
.Concat(new[] { "Toggle Cable LC" } )
.Concat(new[] { "Toggle Cable CR" } )
.Concat(new[] { "Toggle Cable RL" } )
.Concat(new[] { "Toggle Cable UD" } )
.Concat(new[] { "Toggle Cable LR" } )
.Concat(new[] { "Toggle Cable X" } )
.Concat(new[] { "Toggle Cable 4x" })
.ToList()
};
}