romloader stuffs, nag me if it breaks anything, i don't think it breaks anything

This commit is contained in:
goyuken 2014-08-23 19:06:37 +00:00
parent f28f47b941
commit 1d383a62cc
19 changed files with 243 additions and 100 deletions

View File

@ -35,24 +35,31 @@ namespace BizHawk.Client.Common
private object GetCoreSettings<T>()
where T : IEmulator
{
var e = new SettingsLoadArgs(typeof(T));
if (OnLoadSettings != null)
{
OnLoadSettings(this, e);
}
return e.Settings;
return GetCoreSettings(typeof(T));
}
private object GetCoreSyncSettings<T>()
where T : IEmulator
{
var e = new SettingsLoadArgs(typeof(T));
return GetCoreSyncSettings(typeof(T));
}
private object GetCoreSettings(Type t)
{
var e = new SettingsLoadArgs(t);
if (OnLoadSettings != null)
{
OnLoadSettings(this, e);
}
return e.Settings;
}
private object GetCoreSyncSettings(Type t)
{
var e = new SettingsLoadArgs(t);
if (OnLoadSyncSettings != null)
{
OnLoadSyncSettings(this, e);
}
return e.Settings;
}
@ -235,7 +242,7 @@ namespace BizHawk.Client.Common
{
case "GEN":
var genesis = new GPGX(
nextComm, null, disc, "GEN", GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
nextComm, null, disc, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
nextEmulator = genesis;
break;
case "SAT":
@ -317,13 +324,19 @@ namespace BizHawk.Client.Common
isXml = true;
}
CoreInventory.Core core = null;
switch (game.System)
{
default:
core = CoreInventory.Instance[game.System];
break;
case "SNES":
if (Global.Config.SNES_InSnes9x && VersionInfo.DeveloperBuild)
{
var snes = new Emulation.Cores.Nintendo.SNES9X.Snes9x(nextComm, rom.FileData);
nextEmulator = snes;
core = CoreInventory.Instance["SNES", "Snes9x"];
}
else
{
@ -335,44 +348,15 @@ namespace BizHawk.Client.Common
nextEmulator = snes;
}
break;
case "SMS":
case "SG":
case "GG":
nextEmulator = new SMS(nextComm, game, rom.RomData, GetCoreSettings<SMS>(), GetCoreSyncSettings<SMS>());
break;
case "A26":
nextEmulator = new Atari2600(
nextComm,
game,
rom.FileData,
GetCoreSettings<Atari2600>(),
GetCoreSyncSettings<Atari2600>());
break;
case "PCE":
case "PCECD":
case "SGX":
nextEmulator = new PCEngine(nextComm, game, rom.RomData, GetCoreSettings<PCEngine>(), GetCoreSyncSettings<PCEngine>());
break;
case "GEN":
nextEmulator = new GPGX(nextComm, rom.RomData, null, "GEN", GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
break;
case "TI83":
nextEmulator = new TI83(nextComm, game, rom.RomData, GetCoreSettings<TI83>());
break;
case "NES":
if (!Global.Config.NES_InQuickNES || forceAccurateCore)
{
nextEmulator = new NES(
nextComm,
game,
rom.FileData,
GetCoreSettings<NES>(),
GetCoreSyncSettings<NES>());
core = CoreInventory.Instance["NES", "NesHawk"];
}
else
{
nextEmulator = new QuickNES(nextComm, rom.FileData, GetCoreSettings<QuickNES>());
core = CoreInventory.Instance["NES", "QuickNes"];
}
break;
@ -380,13 +364,7 @@ namespace BizHawk.Client.Common
case "GBC":
if (!Global.Config.GB_AsSGB)
{
nextEmulator = new Gameboy(
nextComm,
game,
rom.FileData,
GetCoreSettings<Gameboy>(),
GetCoreSyncSettings<Gameboy>(),
Deterministic);
core = CoreInventory.Instance["GB", "Gambatte"];
}
else
{
@ -406,12 +384,6 @@ namespace BizHawk.Client.Common
}
}
break;
case "Coleco":
nextEmulator = new ColecoVision(nextComm, game, rom.RomData, GetCoreSyncSettings<ColecoVision>());
break;
case "INTV":
nextEmulator = new Intellivision(nextComm, game, rom.RomData);
break;
case "A78":
var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv");
@ -424,24 +396,13 @@ namespace BizHawk.Client.Common
case "GBA":
if (false)
{
var gba = new GBA(nextComm); // meteor
gba.Load(rom.RomData);
nextEmulator = gba;
core = CoreInventory.Instance["GBA", "Meteor"];
}
else
{
var gba = new VBANext(rom.RomData, nextComm, game, Deterministic, GetCoreSyncSettings<VBANext>());
nextEmulator = gba;
core = CoreInventory.Instance["GBA", "VBA-Next"];
}
break;
case "N64":
nextEmulator = new N64(nextComm, game, rom.RomData,
GetCoreSettings<N64>(), GetCoreSyncSettings<N64>());
break;
case "WSWAN":
nextEmulator = new WonderSwan(nextComm, rom.RomData, Deterministic,
GetCoreSettings<WonderSwan>(), GetCoreSyncSettings<WonderSwan>());
break;
case "DEBUG":
if (VersionInfo.DeveloperBuild)
{
@ -450,6 +411,12 @@ namespace BizHawk.Client.Common
break;
}
if (core != null)
{
// use coreinventory
nextEmulator = core.Create(nextComm, game, rom.RomData, null, Deterministic, GetCoreSettings(core.Type), GetCoreSyncSettings(core.Type));
}
}
if (nextEmulator == null)

View File

@ -482,6 +482,7 @@
<Compile Include="Consoles\Sony\PSX\Octoshock.cs" />
<Compile Include="Consoles\WonderSwan\BizSwan.cs" />
<Compile Include="Consoles\WonderSwan\WonderSwan.cs" />
<Compile Include="CoreInventory.cs" />
<Compile Include="CPUs\68000\Diassembler.cs" />
<Compile Include="CPUs\68000\Instructions\BitArithemetic.cs" />
<Compile Include="CPUs\68000\Instructions\DataMovement.cs" />

View File

@ -347,6 +347,7 @@ namespace BizHawk.Emulation.Cores.Calculators
}
}
[CoreConstructor("TI83")]
public TI83(CoreComm comm, GameInfo game, byte[] rom, object Settings)
{
PutSettings(Settings ?? new TI83Settings());

View File

@ -22,6 +22,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private int _lagcount;
private int _frame;
[CoreConstructor("A26")]
public Atari2600(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
{
Ram = new byte[128];

View File

@ -31,6 +31,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public SN76489 PSG;
public byte[] Ram = new byte[1024];
[CoreConstructor("Coleco")]
public ColecoVision(CoreComm comm, GameInfo game, byte[] rom, object SyncSettings)
{
CoreComm = comm;

View File

@ -64,6 +64,7 @@ namespace BizHawk.Emulation.Cores.Intellivision
}
}
[CoreConstructor("INTV")]
public Intellivision(CoreComm comm, GameInfo game, byte[] rom)
{
CoreComm = comm;

View File

@ -43,7 +43,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
public ControllerDefinition ControllerDefinition { get { return GBAController; } }
public IController Controller { get; set; }
public GBA(CoreComm comm)
[CoreConstructor("GBA")]
public GBA(CoreComm comm, byte[] rom)
{
CoreComm = comm;
comm.VsyncNum = 262144;
@ -52,10 +53,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
comm.TraceHeader = " -Addr--- -Opcode- -Instruction------------------- -R0----- -R1----- -R2----- -R3----- -R4----- -R5----- -R6----- -R7----- -R8----- -R9----- -R10---- -R11---- -R12---- -R13(SP) -R14(LR) -R15(PC) -CPSR--- -SPSR---";
comm.NominalWidth = 240;
comm.NominalHeight = 160;
}
public void Load(byte[] rom)
{
byte[] bios = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory.");
if (bios.Length != 16384)

View File

@ -18,26 +18,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
{
IntPtr Core;
public VBANext(byte[] romfile, CoreComm nextComm, GameInfo gi, bool deterministic, object _SS)
[CoreConstructor("GBA")]
public VBANext(byte[] rom, CoreComm comm, GameInfo game, bool deterministic, object syncsettings)
{
CoreComm = nextComm;
CoreComm = comm;
byte[] biosfile = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory.");
if (romfile.Length > 32 * 1024 * 1024)
if (rom.Length > 32 * 1024 * 1024)
throw new ArgumentException("ROM is too big to be a GBA ROM!");
if (biosfile.Length != 16 * 1024)
throw new ArgumentException("BIOS file is not exactly 16K!");
LibVBANext.FrontEndSettings FES = new LibVBANext.FrontEndSettings();
FES.saveType = (LibVBANext.FrontEndSettings.SaveType)gi.GetInt("saveType", 0);
FES.flashSize = (LibVBANext.FrontEndSettings.FlashSize)gi.GetInt("flashSize", 0x10000);
FES.enableRtc = gi.GetInt("rtcEnabled", 0) != 0;
FES.mirroringEnable = gi.GetInt("mirroringEnabled", 0) != 0;
FES.saveType = (LibVBANext.FrontEndSettings.SaveType)game.GetInt("saveType", 0);
FES.flashSize = (LibVBANext.FrontEndSettings.FlashSize)game.GetInt("flashSize", 0x10000);
FES.enableRtc = game.GetInt("rtcEnabled", 0) != 0;
FES.mirroringEnable = game.GetInt("mirroringEnabled", 0) != 0;
Console.WriteLine("GameDB loaded settings: saveType={0}, flashSize={1}, rtcEnabled={2}, mirroringEnabled={3}",
FES.saveType, FES.flashSize, FES.enableRtc, FES.mirroringEnable);
_SyncSettings = (SyncSettings)_SS ?? new SyncSettings();
_SyncSettings = (SyncSettings)syncsettings ?? new SyncSettings();
DeterministicEmulation = deterministic;
FES.skipBios = _SyncSettings.SkipBios;
@ -60,7 +61,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
throw new InvalidOperationException("Create() returned nullptr!");
try
{
if (!LibVBANext.LoadRom(Core, romfile, (uint)romfile.Length, biosfile, (uint)biosfile.Length, FES))
if (!LibVBANext.LoadRom(Core, rom, (uint)rom.Length, biosfile, (uint)biosfile.Length, FES))
throw new InvalidOperationException("LoadRom() returned false!");
CoreComm.VsyncNum = 262144;
@ -68,7 +69,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
CoreComm.NominalWidth = 240;
CoreComm.NominalHeight = 160;
GameCode = Encoding.ASCII.GetString(romfile, 0xac, 4);
GameCode = Encoding.ASCII.GetString(rom, 0xac, 4);
Console.WriteLine("Game code \"{0}\"", GameCode);
savebuff = new byte[LibVBANext.BinStateSize(Core)];

View File

@ -120,7 +120,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
#endregion
public Gameboy(CoreComm comm, GameInfo game, byte[] romdata, object Settings, object SyncSettings, bool deterministic)
[CoreConstructor("GB", "GBC")]
public Gameboy(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings, bool deterministic)
{
CoreComm = comm;
@ -132,8 +133,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
comm.NominalWidth = 160;
comm.NominalHeight = 144;
ThrowExceptionForBadRom(romdata);
BoardName = MapperName(romdata);
ThrowExceptionForBadRom(rom);
BoardName = MapperName(rom);
DeterministicEmulation = deterministic;
@ -158,7 +159,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
if (this._SyncSettings.MulticartCompat)
flags |= LibGambatte.LoadFlags.MULTICART_COMPAT;
if (LibGambatte.gambatte_load(GambatteState, romdata, (uint)romdata.Length, GetCurrentTime(), flags) != 0)
if (LibGambatte.gambatte_load(GambatteState, rom, (uint)rom.Length, GetCurrentTime(), flags) != 0)
throw new InvalidOperationException("gambatte_load() returned non-zero (is this not a gb or gbc rom?)");
// set real default colors (before anyone mucks with them at all)
@ -178,8 +179,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
CoreComm.RomStatusDetails = string.Format("{0}\r\nSHA1:{1}\r\nMD5:{2}\r\n",
game.Name,
romdata.HashSHA1(),
romdata.HashMD5());
rom.HashSHA1(),
rom.HashMD5());
{
byte[] buff = new byte[32];

View File

@ -47,6 +47,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
/// <param name="game">Game information of game to load</param>
/// <param name="rom">Rom that should be loaded</param>
/// <param name="SyncSettings">N64SyncSettings object</param>
[CoreConstructor("N64")]
public N64(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
{
int SaveType = 0;

View File

@ -22,6 +22,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
static readonly bool USE_DATABASE = true;
public RomStatus RomStatus;
[CoreConstructor("NES")]
public NES(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings)
{
byte[] fdsbios = comm.CoreFileProvider.GetFirmware("NES", "Bios_FDS", false);

View File

@ -59,11 +59,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
LibQuickNES.qn_setup_mappers();
}
public QuickNES(CoreComm nextComm, byte[] Rom, object Settings)
[CoreConstructor("NES")]
public QuickNES(CoreComm comm, byte[] Rom, object Settings)
{
using (FP.Save())
{
CoreComm = nextComm;
CoreComm = comm;
Context = LibQuickNES.qn_new();
if (Context == IntPtr.Zero)

View File

@ -27,12 +27,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
{
}
public Snes9x(CoreComm NextComm, byte[] rom)
[CoreConstructor("SNES")]
public Snes9x(CoreComm comm, byte[] rom)
{
if (!LibSnes9x.debug_init(rom, rom.Length))
throw new Exception();
CoreComm = NextComm;
CoreComm = comm;
}
public void FrameAdvance(bool render, bool rendersound = true)

View File

@ -64,6 +64,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
// 21,477,270 Machine clocks / sec
// 7,159,090 Cpu cycles / sec
[CoreConstructor("PCE", "SGX")]
public PCEngine(CoreComm comm, GameInfo game, byte[] rom, object Settings, object syncSettings)
{
CoreComm = comm;

View File

@ -92,6 +92,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
public DisplayType DisplayType { get; set; }
public bool DeterministicEmulation { get { return true; } }
[CoreConstructor("SMS", "SG", "GG")]
public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
{
Settings = (SMSSettings)settings ?? new SMSSettings();

View File

@ -51,14 +51,18 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
Mouse
};
public GPGX(CoreComm NextComm, byte[] romfile, DiscSystem.Disc CD, string romextension, object Settings, object SyncSettings)
[CoreConstructor("GEN")]
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings)
{
// this can influence some things internally
string romextension = "GEN";
// 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
//hack, don't use
//romfile = File.ReadAllBytes(@"D:\encodes\bizhawksrc\output\SANIC CD\PierSolar (E).bin");
if (romfile != null && romfile.Length > 16 * 1024 * 1024)
if (rom != null && rom.Length > 16 * 1024 * 1024)
{
throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?");
}
@ -67,7 +71,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
_SyncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings();
CoreComm = NextComm;
CoreComm = comm;
if (AttachedCore != null)
{
AttachedCore.Dispose();
@ -77,7 +81,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
LoadCallback = new LibGPGX.load_archive_cb(load_archive);
this.romfile = romfile;
this.romfile = rom;
this.CD = CD;
LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;

View File

@ -85,20 +85,21 @@ namespace BizHawk.Emulation.Cores.WonderSwan
#endregion
public WonderSwan(CoreComm comm, byte[] rom, bool deterministicEmulation, object Settings, object SyncSettings)
[CoreConstructor("WSWAN")]
public WonderSwan(CoreComm comm, byte[] rom, bool deterministic, object Settings, object SyncSettings)
{
CoreComm = comm;
_Settings = (Settings)Settings ?? new Settings();
_SyncSettings = (SyncSettings)SyncSettings ?? new SyncSettings();
DeterministicEmulation = deterministicEmulation; // when true, remember to force the RTC flag!
DeterministicEmulation = deterministic; // when true, remember to force the RTC flag!
Core = BizSwan.bizswan_new();
if (Core == IntPtr.Zero)
throw new InvalidOperationException("bizswan_new() returned NULL!");
try
{
var ss = _SyncSettings.GetNativeSettings();
if (deterministicEmulation)
if (deterministic)
ss.userealtime = false;
bool rotate = false;

View File

@ -0,0 +1,159 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.DiscSystem;
namespace BizHawk.Emulation.Cores
{
public class CoreInventory
{
public class Core
{
public readonly string Name;
public readonly Type Type;
public readonly ConstructorInfo CTor;
public Core(string Name, Type Type, ConstructorInfo CTor)
{
this.Name = Name;
this.Type = Type;
this.CTor = CTor;
var pp = CTor.GetParameters();
for (int i = 0; i < pp.Length ; i++)
{
var p = pp[i];
string pname = p.Name.ToLowerInvariant();
Type expectedtype;
if (!paramtypes.TryGetValue(pname, out expectedtype))
throw new InvalidOperationException(string.Format("Unexpected parameter name {0} in constructor for {1}", p.Name, Type));
if (expectedtype != p.ParameterType)
throw new InvalidOperationException(string.Format("Unexpected type mismatch in parameter {0} in constructor for {1}", p.Name, Type));
parammap.Add(pname, i);
}
}
// map parameter names to locations in the constructor
private readonly Dictionary<string, int> parammap = new Dictionary<string, int>();
// expected names and types of the parameters
private static readonly Dictionary<string, Type> paramtypes = new Dictionary<string, Type>();
static Core()
{
var pp = typeof(Core).GetMethod("Create").GetParameters();
foreach (var p in pp)
paramtypes.Add(p.Name.ToLowerInvariant(), p.ParameterType);
}
void bp(object[] parameters, string name, object value)
{
int i;
if (parammap.TryGetValue(name, out i))
parameters[i] = value;
}
public IEmulator Create
(
CoreComm comm,
GameInfo game,
byte[] rom,
Disc cd,
bool deterministic,
object settings,
object syncsettings
)
{
object[] o = new object[parammap.Count];
bp(o, "comm", comm);
bp(o, "game", game);
bp(o, "rom", rom);
bp(o, "cd", cd);
bp(o, "deterministic", deterministic);
bp(o, "settings", settings);
bp(o, "syncsettings", syncsettings);
return (IEmulator)CTor.Invoke(o);
}
}
private readonly Dictionary<string, List<Core>> systems = new Dictionary<string, List<Core>>();
private void ProcessConstructor(Type type, string system, CoreAttributes coreattr, ConstructorInfo cons)
{
Core core = new Core(coreattr.CoreName, type, cons);
List<Core> ss;
if (!systems.TryGetValue(system, out ss))
{
ss = new List<Core>();
systems.Add(system, ss);
}
ss.Add(core);
}
public Core this[string system]
{
get
{
List<Core> ss = systems[system];
if (ss.Count != 1)
throw new InvalidOperationException("Ambiguous core selection!");
return ss[0];
}
}
public Core this[string system, string core]
{
get
{
List<Core> ss = systems[system];
foreach (Core c in ss)
{
if (c.Name == core)
return c;
}
throw new InvalidOperationException("No such core!");
}
}
public CoreInventory(IEnumerable<Assembly> assys)
{
foreach (var assy in assys)
{
foreach (var typ in assy.GetTypes())
{
if (typ.GetInterfaces().Contains(typeof(IEmulator)))
{
var coreattr = typ.GetCustomAttributes(typeof(CoreAttributes), false);
if (coreattr.Length != 1)
throw new InvalidOperationException(string.Format("IEmulator {0} without CoreAttributes!", typ));
var cons = typ.GetConstructors(BindingFlags.Public | BindingFlags.Instance)
.Where(c => c.GetCustomAttributes(typeof(CoreConstructorAttribute), false).Length > 0).ToList();
foreach(var con in cons)
{
foreach (string system in ((CoreConstructorAttribute)con.GetCustomAttributes(typeof(CoreConstructorAttribute), false)[0]).Systems)
{
ProcessConstructor(typ, system, (CoreAttributes)coreattr[0], con);
}
}
}
}
}
}
public static readonly CoreInventory Instance = new CoreInventory(new[] { typeof(CoreInventory).Assembly });
}
[AttributeUsage(AttributeTargets.Constructor)]
public class CoreConstructorAttribute : Attribute
{
public IEnumerable<string> Systems { get { return _systems; } }
private readonly List<string> _systems = new List<string>();
public CoreConstructorAttribute(params string[] Systems)
{
_systems.AddRange(Systems);
}
}
}

View File

@ -8,6 +8,7 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores
{
[CoreAttributes("DEBUG ONLY DON'T USE", "natt")]
public unsafe class LibRetroEmulator : IEmulator, IVideoProvider
{
#region callbacks