Wiring up GPGX as core for SMS, GG, and SG (#3902)
* Adding GPGX as core for SMS and GG * Enabling SMS FM selection * Allow selecting PicoDrive as the preferred core for MD/Genesis --------- Co-authored-by: James Groom <OSSYoshiRulz+GitHub@gmail.com> Co-authored-by: feos <feykomylce@gmail.com>
This commit is contained in:
parent
8a0bf19869
commit
9dcb84336e
|
@ -76,4 +76,4 @@
|
|||
[submodule "waterbox/gpgx/Genesis-Plus-GX"]
|
||||
path = waterbox/gpgx/Genesis-Plus-GX
|
||||
url = https://github.com/TASEmulators/Genesis-Plus-GX.git
|
||||
branch = tasvideos-3
|
||||
branch = tasvideos-2.1
|
||||
|
|
Binary file not shown.
|
@ -36,6 +36,10 @@ namespace BizHawk.Client.Common
|
|||
new[] { CoreNames.Gambatte, CoreNames.Sameboy, CoreNames.GbHawk, CoreNames.SubGbHawk }),
|
||||
(new[] { VSystemID.Raw.GBL },
|
||||
new[] { CoreNames.GambatteLink, CoreNames.GBHawkLink, CoreNames.GBHawkLink3x, CoreNames.GBHawkLink4x }),
|
||||
(new[] { VSystemID.Raw.GEN },
|
||||
new[] { CoreNames.Gpgx, CoreNames.PicoDrive }),
|
||||
(new[] { VSystemID.Raw.SMS, VSystemID.Raw.GG, VSystemID.Raw.SG },
|
||||
new[] { CoreNames.Gpgx, CoreNames.SMSHawk }),
|
||||
(new[] { VSystemID.Raw.PCE, VSystemID.Raw.PCECD, VSystemID.Raw.SGX, VSystemID.Raw.SGXCD },
|
||||
new[] { CoreNames.TurboNyma, CoreNames.HyperNyma, CoreNames.PceHawk }),
|
||||
(new[] { VSystemID.Raw.PSX },
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace BizHawk.Client.Common.movie.import
|
|||
: LibGPGX.INPUT_DEVICE.DEVICE_PAD3B;
|
||||
}
|
||||
|
||||
var controlConverter = new GPGXControlConverter(input, false);
|
||||
GPGXControlConverter controlConverter = new(input, systemId: VSystemID.Raw.GEN, cdButtons: false);
|
||||
|
||||
SimpleController controller = new(controlConverter.ControllerDef);
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public int Frame { get; private set; }
|
||||
|
||||
public string SystemId => VSystemID.Raw.GEN;
|
||||
public string SystemId { get; }
|
||||
|
||||
public bool DeterministicEmulation => true;
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
[CoreSettings]
|
||||
public class GPGXSyncSettings
|
||||
{
|
||||
[DisplayName("Use Six Button Controllers")]
|
||||
[DisplayName("[Genesis/CD] Use Six Button Controllers")]
|
||||
[Description("Controls the type of any attached normal controllers; six button controllers are used if true, otherwise three button controllers. Some games don't work correctly with six button controllers. Not relevant if other controller types are connected.")]
|
||||
[DefaultValue(false)]
|
||||
public bool UseSixButton { get; set; }
|
||||
|
@ -263,7 +263,17 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
[DefaultValue(LibGPGX.Region.Autodetect)]
|
||||
public LibGPGX.Region Region { get; set; }
|
||||
|
||||
[DisplayName("FM Sound Chip Type")]
|
||||
[DisplayName("[SMS/GG] Load BIOS")]
|
||||
[Description("Indicates whether to load the system BIOS rom.")]
|
||||
[DefaultValue(false)]
|
||||
public bool loadBIOS { get; set; }
|
||||
|
||||
[DisplayName("[SMS] FM Sound Chip Type")]
|
||||
[Description("Sets the method used to emulate the FM Sound Unit of the Sega Mark III/Master System. 'MAME' is fast and runs full speed on most systems.'Nuked' is cycle accurate, very high quality, and have substantial CPU requirements.")]
|
||||
[DefaultValue(LibGPGX.InitSettings.SMSFMSoundChipType.YM2413_MAME)]
|
||||
public LibGPGX.InitSettings.SMSFMSoundChipType SMSFMSoundChip { get; set; }
|
||||
|
||||
[DisplayName("[Genesis/CD] FM Sound Chip Type")]
|
||||
[Description("Sets the method used to emulate the FM synthesizer (main sound generator) of the Mega Drive/Genesis. 'MAME' options are fast, and run full speed on most systems. 'Nuked' options are cycle accurate, very high quality, and have substantial CPU requirements. The 'YM2612' chip is used by the original Model 1 Mega Drive/Genesis. The 'YM3438' is used in later Mega Drive/Genesis revisions.")]
|
||||
[DefaultValue(LibGPGX.InitSettings.GenesisFMSoundChipType.MAME_YM2612)]
|
||||
public LibGPGX.InitSettings.GenesisFMSoundChipType GenesisFMSoundChip { get; set; }
|
||||
|
@ -329,8 +339,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
InputSystemA = SystemForSystem(ControlTypeLeft),
|
||||
InputSystemB = SystemForSystem(ControlTypeRight),
|
||||
Region = Region,
|
||||
loadBIOS = loadBIOS,
|
||||
ForceSram = game["sram"],
|
||||
GenesisFMSoundChip = GenesisFMSoundChip,
|
||||
SMSFMSoundChip = SMSFMSoundChip,
|
||||
GenesisFMSoundChip = GenesisFMSoundChip,
|
||||
SpritesAlwaysOnTop = SpritesAlwaysOnTop
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,16 +6,25 @@ using BizHawk.Common.PathExtensions;
|
|||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Waterbox;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.StringExtensions;
|
||||
using BizHawk.Emulation.DiscSystem;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
||||
{
|
||||
[PortedCore(CoreNames.Gpgx, "Eke-Eke", "25a90c6", "https://github.com/ekeeke/Genesis-Plus-GX")]
|
||||
[PortedCore(
|
||||
name: CoreNames.Gpgx,
|
||||
author: "Eke-Eke",
|
||||
portedVersion: "0c45a8a",
|
||||
portedUrl: "https://github.com/ekeeke/Genesis-Plus-GX")]
|
||||
public partial class GPGX : IEmulator, IVideoProvider, ISaveRam, IStatable, IRegionable,
|
||||
IInputPollable, IDebuggable, IDriveLight, ICodeDataLogger, IDisassemblable
|
||||
{
|
||||
[CoreConstructor(VSystemID.Raw.GEN)]
|
||||
[CoreConstructor(VSystemID.Raw.SMS)]
|
||||
[CoreConstructor(VSystemID.Raw.GG)]
|
||||
[CoreConstructor(VSystemID.Raw.SG)]
|
||||
public GPGX(CoreLoadParameters<GPGXSettings, GPGXSyncSettings> lp)
|
||||
{
|
||||
LoadCallback = load_archive;
|
||||
|
@ -26,8 +35,17 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
ServiceProvider = new BasicServiceProvider(this);
|
||||
// this can influence some things internally (autodetect romtype, etc)
|
||||
string romextension = "GEN";
|
||||
|
||||
// Determining system ID from the rom. If no rom provided, assume Genesis (Sega CD)
|
||||
SystemId = VSystemID.Raw.GEN;
|
||||
var RomExtension = string.Empty;
|
||||
if (lp.Roms.Count >= 1)
|
||||
{
|
||||
SystemId = lp.Roms[0].Game.System;
|
||||
// We need to pass the exact file extension to GPGX for it to correctly interpret the console
|
||||
RomExtension = Path.GetExtension(lp.Roms[0].RomPath).RemovePrefix('.');
|
||||
}
|
||||
|
||||
// three or six button?
|
||||
// http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds
|
||||
|
||||
|
@ -82,7 +100,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
LibGPGX.INPUT_SYSTEM system_a = SystemForSystem(_syncSettings.ControlTypeLeft);
|
||||
LibGPGX.INPUT_SYSTEM system_b = SystemForSystem(_syncSettings.ControlTypeRight);
|
||||
|
||||
var initResult = Core.gpgx_init(romextension, LoadCallback, _syncSettings.GetNativeSettings(lp.Game));
|
||||
var initResult = Core.gpgx_init(RomExtension, LoadCallback, _syncSettings.GetNativeSettings(lp.Game));
|
||||
|
||||
if (!initResult)
|
||||
throw new Exception($"{nameof(Core.gpgx_init)}() failed");
|
||||
|
@ -228,22 +246,25 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
{
|
||||
// use fromtend firmware interface
|
||||
|
||||
string firmwareID = null;
|
||||
switch (filename)
|
||||
{
|
||||
case "CD_BIOS_EU": firmwareID = "CD_BIOS_EU"; break;
|
||||
case "CD_BIOS_JP": firmwareID = "CD_BIOS_JP"; break;
|
||||
case "CD_BIOS_US": firmwareID = "CD_BIOS_US"; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
FirmwareID? firmwareID = filename switch
|
||||
{
|
||||
"CD_BIOS_EU" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_EU"),
|
||||
"CD_BIOS_JP" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_JP"),
|
||||
"CD_BIOS_US" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_US"),
|
||||
"GG_BIOS" => new(system: VSystemID.Raw.SMS, firmware: "Japan"),
|
||||
"MS_BIOS_EU" => new(system: VSystemID.Raw.SMS, firmware: "Export"),
|
||||
"MS_BIOS_JP" => new(system: VSystemID.Raw.SMS, firmware: "Japan"),
|
||||
"MS_BIOS_US" => new(system: VSystemID.Raw.SMS, firmware: "Export"),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (firmwareID != null)
|
||||
{
|
||||
// this path will be the most common PEBKAC error, so be a bit more vocal about the problem
|
||||
srcdata = CoreComm.CoreFileProvider.GetFirmware(new("GEN", firmwareID), "GPGX firmwares are usually required.");
|
||||
srcdata = CoreComm.CoreFileProvider.GetFirmware(firmwareID.Value, "GPGX firmwares are usually required.");
|
||||
if (srcdata == null)
|
||||
{
|
||||
Console.WriteLine("Frontend couldn't satisfy firmware request GEN:{0}", firmwareID);
|
||||
Console.WriteLine($"Frontend couldn't satisfy firmware request {firmwareID}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +386,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
if (!Core.gpgx_get_control(input, inputsize))
|
||||
throw new Exception($"{nameof(Core.gpgx_get_control)}() failed");
|
||||
|
||||
ControlConverter = new GPGXControlConverter(input, _cds != null);
|
||||
ControlConverter = new(input, systemId: SystemId, cdButtons: _cds is not null);
|
||||
ControllerDefinition = ControlConverter.ControllerDef;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,27 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly CName[] SMS2B =
|
||||
{
|
||||
new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP),
|
||||
new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN),
|
||||
new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT),
|
||||
new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT),
|
||||
new CName("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1),
|
||||
new CName("B2", LibGPGX.INPUT_KEYS.INPUT_BUTTON2)
|
||||
};
|
||||
|
||||
private static readonly CName[] GameGear =
|
||||
{
|
||||
new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP),
|
||||
new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN),
|
||||
new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT),
|
||||
new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT),
|
||||
new CName("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1),
|
||||
new CName("B2", LibGPGX.INPUT_KEYS.INPUT_BUTTON2),
|
||||
new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START),
|
||||
};
|
||||
|
||||
private static readonly CName[] Genesis3 =
|
||||
{
|
||||
new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP),
|
||||
|
@ -169,7 +190,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
});
|
||||
}
|
||||
|
||||
public GPGXControlConverter(LibGPGX.InputData input, bool cdButtons)
|
||||
public GPGXControlConverter(LibGPGX.InputData input, string systemId, bool cdButtons)
|
||||
{
|
||||
Console.WriteLine("Genesis Controller report:");
|
||||
foreach (var e in input.system)
|
||||
|
@ -215,10 +236,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
player++;
|
||||
break;
|
||||
case LibGPGX.INPUT_DEVICE.DEVICE_PAD2B:
|
||||
AddToController(i, player, systemId is VSystemID.Raw.SMS ? SMS2B : GameGear);
|
||||
player++;
|
||||
break;
|
||||
case LibGPGX.INPUT_DEVICE.DEVICE_PADDLE:
|
||||
case LibGPGX.INPUT_DEVICE.DEVICE_SPORTSPAD:
|
||||
case LibGPGX.INPUT_DEVICE.DEVICE_TEREBI:
|
||||
throw new Exception("Master System only device? Something went wrong.");
|
||||
throw new Exception("Not implemented yet.");
|
||||
case LibGPGX.INPUT_DEVICE.DEVICE_ACTIVATOR:
|
||||
AddToController(i, player, Activator);
|
||||
player++;
|
||||
|
|
|
@ -54,6 +54,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
public bool SixButton;
|
||||
public bool ForceSram;
|
||||
|
||||
public enum SMSFMSoundChipType : byte
|
||||
{
|
||||
YM2413_DISABLED,
|
||||
YM2413_MAME,
|
||||
YM2413_NUKED
|
||||
}
|
||||
public SMSFMSoundChipType SMSFMSoundChip;
|
||||
|
||||
public enum GenesisFMSoundChipType : byte
|
||||
{
|
||||
MAME_YM2612,
|
||||
|
@ -65,6 +73,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
public GenesisFMSoundChipType GenesisFMSoundChip;
|
||||
|
||||
public bool SpritesAlwaysOnTop;
|
||||
public bool loadBIOS;
|
||||
}
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 5ed4f70cf6831331b110357d23495d08f46b2a87
|
||||
Subproject commit 1cc182153291ee69e15c6ad2dc2cb51492b39c58
|
|
@ -619,8 +619,10 @@ struct InitSettings
|
|||
char InputSystemB;
|
||||
char SixButton;
|
||||
char ForceSram;
|
||||
uint8_t SMSFMSoundChip;
|
||||
uint8_t GenesisFMSoundChip;
|
||||
uint8_t SpritesAlwaysOnTop;
|
||||
uint8_t loadBios;
|
||||
};
|
||||
|
||||
|
||||
|
@ -704,6 +706,8 @@ void bk_cpu_hook(hook_type_t type, int width, unsigned int address, unsigned int
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,8 +759,7 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
|
||||
// Selecting FM Sound chip to use for SMS / GG emulation. Using a default for now, until we also
|
||||
// accept this core for SMS/GG emulation in BizHawk
|
||||
int smsFMChipType = YM2413_NUKED;
|
||||
switch (smsFMChipType)
|
||||
switch (settings->SMSFMSoundChip)
|
||||
{
|
||||
case YM2413_DISABLED:
|
||||
config.opll = 0;
|
||||
|
@ -770,7 +773,7 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
|
||||
case YM2413_NUKED:
|
||||
config.opll = 1;
|
||||
config.ym2413 = 0;
|
||||
config.ym2413 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -810,7 +813,7 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
config.master_clock = 0; /* = AUTO (1 = NTSC, 2 = PAL) */
|
||||
config.force_dtack = 0;
|
||||
config.addr_error = 1;
|
||||
config.bios = 0;
|
||||
config.bios = settings->loadBios;
|
||||
config.lock_on = 0; /* = OFF (or TYPE_SK, TYPE_GG & TYPE_AR) */
|
||||
config.add_on = 0; /* = HW_ADDON_AUTO (or HW_ADDON_MEGACD, HW_ADDON_MEGASD & HW_ADDON_ONE) */
|
||||
config.cd_latency = 1;
|
||||
|
@ -836,13 +839,16 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
|
||||
cinterface_custom_backdrop_color = settings->BackdropColor;
|
||||
|
||||
// Default: Genesis
|
||||
// apparently, the only part of config.input used is the padtype identifier,
|
||||
// and that's used only for choosing pad type when system_md
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_INPUTS; i++)
|
||||
config.input[i].padtype = settings->SixButton ? DEVICE_PAD6B : DEVICE_PAD3B;
|
||||
}
|
||||
for (int i = 0; i < MAX_INPUTS; i++)
|
||||
config.input[i].padtype = settings->SixButton ? DEVICE_PAD6B : DEVICE_PAD3B;
|
||||
|
||||
// Hacky but effective. Setting the correct controller type here if this is sms or GG
|
||||
if (system_hw == SYSTEM_SMS || system_hw == SYSTEM_SMS2 || system_hw == SYSTEM_GG || system_hw == SYSTEM_SG)
|
||||
for (int i = 0; i < MAX_INPUTS; i++)
|
||||
config.input[i].padtype = DEVICE_PAD2B;
|
||||
|
||||
// first try to load our main CD
|
||||
if (!load_rom("PRIMARY_CD"))
|
||||
|
|
|
@ -92,3 +92,4 @@ extern char MS_BIOS_JP[256];
|
|||
|
||||
extern void osd_input_update(void);
|
||||
extern int load_archive(const char *filename, unsigned char *buffer, int maxsize, char *extension);
|
||||
extern void real_input_callback(void);
|
||||
|
|
Loading…
Reference in New Issue