diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index f4b8b3c87d..99080284cc 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -181,6 +181,7 @@
+
@@ -205,7 +206,6 @@
-
diff --git a/BizHawk.Emulation/Consoles/Calculator/TI83.cs b/BizHawk.Emulation/Consoles/Calculator/TI83.cs
index 15a661cc59..07c3bfa903 100644
--- a/BizHawk.Emulation/Consoles/Calculator/TI83.cs
+++ b/BizHawk.Emulation/Consoles/Calculator/TI83.cs
@@ -315,7 +315,7 @@ namespace BizHawk.Emulation.Consoles.Calculator
}
}
- public TI83()
+ public TI83(GameInfo game, byte[] rom)
{
CoreOutputComm = new CoreOutputComm();
cpu.ReadMemory = ReadMemory;
@@ -324,6 +324,18 @@ namespace BizHawk.Emulation.Consoles.Calculator
cpu.WriteHardware = WriteHardware;
cpu.IRQCallback = IRQCallback;
cpu.NMICallback = NMICallback;
+
+ this.rom = rom;
+
+ //different calculators (different revisions?) have different initPC. we track this in the game database by rom hash
+ //if( *(unsigned long *)(m_pRom + 0x6ce) == 0x04D3163E ) m_Regs.PC.W = 0x6ce; //KNOWN
+ //else if( *(unsigned long *)(m_pRom + 0x6f6) == 0x04D3163E ) m_Regs.PC.W = 0x6f6; //UNKNOWN
+
+ if (game["initPC"])
+ startPC = ushort.Parse(game.OptionValue("initPC"), NumberStyles.HexNumber);
+
+ HardReset();
+ SetupMemoryDomains();
}
void IRQCallback()
@@ -406,23 +418,6 @@ namespace BizHawk.Emulation.Consoles.Calculator
//configuration
ushort startPC;
- public void LoadGame(IGame game)
- {
- rom = game.GetRomData();
- foreach (string opt in game.GetOptions())
- {
- //different calculators (different revisions?) have different initPC. we track this in the game database by rom hash
- //if( *(unsigned long *)(m_pRom + 0x6ce) == 0x04D3163E ) m_Regs.PC.W = 0x6ce; //KNOWN
- //else if( *(unsigned long *)(m_pRom + 0x6f6) == 0x04D3163E ) m_Regs.PC.W = 0x6f6; //UNKNOWN
-
- if (opt.StartsWith("initPC"))
- startPC = ushort.Parse(opt.Split('=')[1], NumberStyles.HexNumber);
- }
-
- HardReset();
- SetupMemoryDomains();
- }
-
public void FrameAdvance(bool render)
{
lagged = true;
diff --git a/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs b/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs
index 047708992e..dc5c994874 100644
--- a/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs
+++ b/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs
@@ -269,7 +269,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy
{
CoreOutputComm = new CoreOutputComm();
}
-
+ /* TOO BAD gameboy is broken until someone cares about it
public void LoadGame(IGame game)
{
Rom = game.GetRomData();
@@ -281,7 +281,7 @@ namespace BizHawk.Emulation.Consoles.Gameboy
CartFlags.SGB = Rom[0x0146] == 0x03;
HardReset();
- }
+ } */
public bool BootFromBios = true;
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
index 7846d0f19c..d1dfa5531a 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
@@ -215,7 +215,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
///
public class CartInfo
{
- public GameInfo game;
+ public NESGameInfo game;
public BizHawk.GameInfo DB_GameInfo;
public short chr_size;
@@ -241,7 +241,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
///
/// Logical game information. May exist in form of several carts (different revisions)
///
- public class GameInfo
+ public class NESGameInfo
{
public string name;
public List carts = new List();
@@ -285,12 +285,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
var gi = Database.CheckDatabase(hash);
if (gi == null) return null;
- GameInfo game = new GameInfo();
+ NESGameInfo game = new NESGameInfo();
CartInfo cart = new CartInfo();
game.carts.Add(cart);
//try generating a bootgod cart descriptor from the game database
- var dict = gi.ParseOptionsDictionary();
+ var dict = gi.GetOptionsDict();
game.name = gi.Name;
cart.DB_GameInfo = gi;
cart.game = game;
@@ -344,7 +344,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//in anticipation of any slowness annoying people, and just for shits and giggles, i made a super fast parser
int state=0;
var xmlreader = XmlReader.Create(new MemoryStream(GetDatabaseBytes()));
- GameInfo currGame = null;
+ NESGameInfo currGame = null;
CartInfo currCart = null;
while (xmlreader.Read())
{
@@ -353,7 +353,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
case 0:
if (xmlreader.NodeType == XmlNodeType.Element && xmlreader.Name == "game")
{
- currGame = new GameInfo();
+ currGame = new NESGameInfo();
currGame.name = xmlreader.GetAttribute("name");
state = 1;
}
@@ -432,7 +432,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
} //end xmlreader loop
//analyze
- foreach (GameInfo game in games)
+ foreach (NESGameInfo game in games)
{
foreach (CartInfo cart in game.carts)
{
@@ -442,7 +442,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
- List games = new List(); //maybe we dont need to track this
+ List games = new List(); //maybe we dont need to track this
Bag sha1_table = new Bag();
public List Identify(string sha1)
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
index d076284af3..639fbd43c6 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
@@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public partial class NES : IEmulator
{
static readonly bool USE_DATABASE = true;
-
+ public RomStatus RomStatus;
//Game issues:
//Tecmo superbowl - wobbly "NFL" logo at the end of a game (even skipped game) [zeromus cant test this; how do you skip game?]
//Bigfoot (U) seems not to work
@@ -37,14 +37,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//AD&D Hillsfar (U).nes black screen
//Air Wolf - big graphical glitch. seems to be a real bug, but it should never have been released with this. need to verify for sure that it is a real bug?
- public NES()
+ public NES(GameInfo game, byte[] rom)
{
CoreOutputComm = new CoreOutputComm();
BootGodDB.Initialize();
SetPalette(Palettes.FCEUX_Standard);
videoProvider = new MyVideoProvider(this);
+ Init(game, rom);
}
+ private NES()
+ {
+ BootGodDB.Initialize();
+ }
+
public void WriteLogTimestamp()
{
if (ppu != null)
@@ -353,13 +359,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
LoadReport.WriteLine(format, arg);
}
void LoadWriteLine(object arg) { LoadWriteLine("{0}", arg); }
-
- public unsafe void LoadGame(IGame game)
+
+ public unsafe void Init(GameInfo gameInfo, byte[] rom)
{
LoadReport = new StringWriter();
LoadWriteLine("------");
LoadWriteLine("BEGIN NES rom analysis:");
- byte[] file = game.GetFileData();
+ byte[] file = rom;
if (file.Length < 16) throw new Exception("Alleged NES rom too small to be anything useful");
if (file.Take(4).SequenceEqual(System.Text.Encoding.ASCII.GetBytes("UNIF")))
throw new Exception("You've tried to open a UNIF rom. We don't have any UNIF roms to test with. Please consult the developers.");
@@ -437,7 +443,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
LoadWriteLine("Chose board from iNES heuristics: " + iNES_board);
- choice.game.name = game.Name;
+ choice.game.name = gameInfo.Name;
origin = EDetectionOrigin.INES;
}
else
@@ -486,23 +492,23 @@ namespace BizHawk.Emulation.Consoles.Nintendo
if (origin == EDetectionOrigin.BootGodDB)
{
- CoreOutputComm.RomStatus = RomStatus.GoodDump;
+ RomStatus = RomStatus.GoodDump;
CoreOutputComm.RomStatusAnnotation = "Identified from BootGod's database";
}
if (origin == EDetectionOrigin.INES)
{
- CoreOutputComm.RomStatus = RomStatus.NotInDatabase;
+ RomStatus = RomStatus.NotInDatabase;
CoreOutputComm.RomStatusAnnotation = "Inferred from iNES header; potentially wrong";
}
if (origin == EDetectionOrigin.GameDB)
{
if (choice.bad)
{
- CoreOutputComm.RomStatus = RomStatus.BadDump;
+ RomStatus = RomStatus.BadDump;
}
else
{
- CoreOutputComm.RomStatus = choice.DB_GameInfo.Status;
+ RomStatus = choice.DB_GameInfo.Status;
}
}
@@ -525,10 +531,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
if (cart.vram_size != 0)
board.VRAM = new byte[cart.vram_size * 1024];
+
HardReset();
SetupMemoryDomains();
}
-
}
void SyncState(Serializer ser)
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs
index 6f06ec9a72..b966856120 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs
@@ -152,7 +152,7 @@ static string ClassifyTable = @"
public CartInfo Analyze()
{
var ret = new CartInfo();
- ret.game = new GameInfo();
+ ret.game = new NESGameInfo();
int mapper = (ROM_type >> 4);
mapper |= (ROM_type2 & 0xF0);
ret.mapper = (byte)mapper;
diff --git a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs
index 1a9fcfc13f..0f5c5a2070 100644
--- a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs
+++ b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs
@@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// ROM
public byte[] RomData;
public int RomLength;
+ private Disc disc;
// Machine
public NecSystemType Type;
@@ -41,19 +42,31 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// Memory system
public byte[] Ram;
- // Disc
- //private Disc disc = Disc.FromCuePath("D:/lib/roms/Turbo CD/Terra Forming/Syd Mead's Terra Forming [U][CD.SCD][TGXCD1040][Syd Mead][1993][PCE][rigg].cue");
-
// PC Engine timings:
// 21,477,270 Machine clocks / sec
// 7,159,090 Cpu cycles / sec
- public PCEngine(NecSystemType type)
+ public PCEngine(GameInfo game, byte[] rom)
{
- //scsi.disc = disc;
- //Console.WriteLine(disc.GetHash());
CoreOutputComm = new CoreOutputComm();
- Type = type;
+ switch (game.System)
+ {
+ case "PCE": Type = NecSystemType.TurboGrafx; break;
+ case "SGX": Type = NecSystemType.SuperGrafx; break;
+ }
+ Init(game, rom);
+ }
+
+ public PCEngine(GameInfo game, Disc disc, byte[] rom)
+ {
+ CoreOutputComm = new CoreOutputComm();
+ Type = NecSystemType.TurboCD;
+ this.disc = disc;
+ Init(game, rom);
+ }
+
+ private void Init(GameInfo game, byte[] rom)
+ {
Controller = NullController.GetNullController();
Cpu = new HuC6280();
VCE = new VCE();
@@ -77,34 +90,31 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Cpu.WriteMemory21 = WriteMemorySGX;
Cpu.WriteVDC = VDC1.WriteVDC;
}
- }
- public void LoadGame(IGame game)
- {
- if (game.GetRomData().Length == 0x60000)
+ if (rom.Length == 0x60000)
{
// 384k roms require special loading code. Why ;_;
// In memory, 384k roms look like [1st 256k][Then full 384k]
RomData = new byte[0xA0000];
- var origRom = game.GetRomData();
+ var origRom = rom;
for (int i=0; i<0x40000; i++)
RomData[i] = origRom[i];
for (int i = 0; i < 0x60000; i++)
RomData[i+0x40000] = origRom[i];
RomLength = RomData.Length;
- } else if (game.GetRomData().Length > 1024 * 1024) {
+ } else if (rom.Length > 1024 * 1024) {
// If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper
Cpu.ReadMemory21 = ReadMemorySF2;
Cpu.WriteMemory21 = WriteMemorySF2;
- RomData = game.GetRomData();
+ RomData = rom;
RomLength = RomData.Length;
} else {
// normal rom.
- RomData = game.GetRomData();
+ RomData = rom;
RomLength = RomData.Length;
}
- if (game.GetOptions().Contains("BRAM"))
+ if (game["BRAM"])
{
BramEnabled = true;
BRAM = new byte[2048];
@@ -115,14 +125,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80;
}
- if (game.GetOptions().Contains("PopulousSRAM"))
+ if (game["PopulousSRAM"])
{
PopulousRAM = new byte[0x8000];
Cpu.ReadMemory21 = ReadMemoryPopulous;
Cpu.WriteMemory21 = WriteMemoryPopulous;
}
- if (game.GetOptions().Contains("ForceSpriteLimit") || game.GetOptions().Contains("NotInDatabase"))
+ if (game["ForceSpriteLimit"] || game.NotInDatabase)
{
VDC1.PerformSpriteLimit = true;
if (VDC2 != null)
@@ -138,14 +148,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// version of this core. Let's just acknolwedge that the timing is imperfect and fix
// it in the least intrusive and most honest way we can.
- if (game.GetOptions().ContainsStartsWith("HBlankPeriod"))
- VDC1.HBlankCycles = int.Parse(game.GetOptions().GetOptionValue("HBlankPeriod"));
+ if (game["HBlankPeriod"])
+ VDC1.HBlankCycles = int.Parse(game.OptionValue("HBlankPeriod"));
// This is also a hack. Proper multi-res/TV emulation will be a native-code core feature.
- if (game.GetOptions().ContainsStartsWith("MultiResHack"))
+ if (game["MultiResHack"])
{
- VDC1.MultiResHack = int.Parse(game.GetOptions().GetOptionValue("MultiResHack"));
+ VDC1.MultiResHack = int.Parse(game.OptionValue("MultiResHack"));
}
Cpu.ResetPC();
diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs
index 32bbf8a73d..0566a44d88 100644
--- a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs
+++ b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs
@@ -83,6 +83,7 @@ namespace BizHawk.Emulation.Consoles.Sega
Z80Reset = true;
}
+ /* TOO BAD genesis is broken until I finish turbocd
public void LoadGame(IGame game)
{
RomData = new byte[0x400000];
@@ -92,7 +93,7 @@ namespace BizHawk.Emulation.Consoles.Sega
if (MainCPU != null) MainCPU.Reset();
_MainCPU.Reset();
- }
+ }*/
public void StepMine()
{
diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs
index 3db7e793a7..25f1b06e0f 100644
--- a/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs
+++ b/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs
@@ -25,7 +25,6 @@ namespace BizHawk.Emulation.Consoles.Sega
public byte[] RomData;
public byte RomBank0, RomBank1, RomBank2;
public byte RomBanks;
- public IList Options;
// SaveRAM
public byte[] SaveRAM = new byte[BankSize * 2];
@@ -64,76 +63,63 @@ namespace BizHawk.Emulation.Consoles.Sega
public DisplayType DisplayType { get; set; }
public bool DeterministicEmulation { get; set; }
- public SMS()
+ public SMS(GameInfo game, byte[] rom)
{
+ IsGameGear = game.System == "GG";
+ RomData = rom;
CoreOutputComm = new CoreOutputComm();
- }
- public void Init()
- {
- if (Controller == null)
- Controller = NullController.GetNullController();
+ if (RomData.Length % BankSize != 0)
+ Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize);
+ RomBanks = (byte)(RomData.Length / BankSize);
+ DisplayType = DisplayType.NTSC;
+ CoreOutputComm.VsyncRate = DisplayType == DisplayType.NTSC ? 60d : 50d;
+ if (game["PAL"]) DisplayType = DisplayType.PAL;
+ if (game["Japan"]) Region = "Japan";
+ if (game.NotInDatabase || game["FM"] && game["UseFM"])
+ HasYM2413 = true;
- Cpu = new Z80A();
- Cpu.RegisterSP = 0xDFF0;
- Cpu.ReadHardware = ReadPort;
- Cpu.WriteHardware = WritePort;
+ if (Controller == null)
+ Controller = NullController.GetNullController();
- Vdp = new VDP(Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, DisplayType);
- PSG = new SN76489();
- YM2413 = new YM2413();
- SoundMixer = new SoundMixer(YM2413, PSG);
- if (HasYM2413 && Options.Contains("WhenFMDisablePSG"))
- SoundMixer.DisableSource(PSG);
- ActiveSoundProvider = HasYM2413 ? (ISoundProvider)SoundMixer : PSG;
+ Cpu = new Z80A();
+ Cpu.RegisterSP = 0xDFF0;
+ Cpu.ReadHardware = ReadPort;
+ Cpu.WriteHardware = WritePort;
- SystemRam = new byte[0x2000];
- if (Options.Contains("CMMapper") == false)
- InitSegaMapper();
- else
- InitCodeMastersMapper();
+ Vdp = new VDP(Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, DisplayType);
+ PSG = new SN76489();
+ YM2413 = new YM2413();
+ SoundMixer = new SoundMixer(YM2413, PSG);
+ if (HasYM2413 && game["WhenFMDisablePSG"])
+ SoundMixer.DisableSource(PSG);
+ ActiveSoundProvider = HasYM2413 ? (ISoundProvider)SoundMixer : PSG;
- if (Options.Contains("ForceStereo"))
- {
- byte stereoByte = 0xAD;
- if (Options.ContainsStartsWith("StereoByte"))
- {
- stereoByte = byte.Parse(Options.GetOptionValue("StereoByte"));
- }
- PSG.StereoPanning = stereoByte;
- }
+ SystemRam = new byte[0x2000];
+ if (game["CMMapper"] == false)
+ InitSegaMapper();
+ else
+ InitCodeMastersMapper();
- if (Options.Contains("AllowOverclock") && Options.Contains("OverclockSafe"))
- Vdp.IPeriod = 512;
+ if (game["ForceStereo"])
+ {
+ byte stereoByte = 0xAD;
+ if (game["StereoByte"])
+ {
+ stereoByte = byte.Parse(game.OptionValue("StereoByte"));
+ }
+ PSG.StereoPanning = stereoByte;
+ }
- if (Options.Contains("BIOS"))
- {
- Port3E = 0xF7; // Disable cartridge, enable BIOS rom
- InitBiosMapper();
- }
- SetupMemoryDomains();
- }
+ if (game["AllowOverclock"] && game["OverclockSafe"])
+ Vdp.IPeriod = 512;
- public void LoadGame(IGame game)
- {
- RomData = game.GetRomData();
- if (RomData.Length % BankSize != 0)
- Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize);
- RomBanks = (byte)(RomData.Length / BankSize);
- Options = game.GetOptions();
- DisplayType = DisplayType.NTSC;
- CoreOutputComm.VsyncRate = DisplayType == DisplayType.NTSC ? 60d : 50d;
- foreach (string option in Options)
- {
- var args = option.Split('=');
- if (args[0] == "Japan") Region = "Japan";
- else if (args[0] == "PAL") DisplayType = DisplayType.PAL;
- }
-
- if (Options.Contains("NotInDatabase") || (Options.Contains("FM") && Options.Contains("UseFM")))
- HasYM2413 = true;
-
- Init();
+ if (game["BIOS"])
+ {
+ Port3E = 0xF7; // Disable cartridge, enable BIOS rom
+ InitBiosMapper();
+ }
+ SetupMemoryDomains();
}
public byte ReadPort(ushort port)
diff --git a/BizHawk.Emulation/Database/Database.cs b/BizHawk.Emulation/Database/Database.cs
index 22f87122dd..88584c7d4e 100644
--- a/BizHawk.Emulation/Database/Database.cs
+++ b/BizHawk.Emulation/Database/Database.cs
@@ -1,60 +1,22 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Threading;
namespace BizHawk
{
- public enum RomStatus
- {
- GoodDump,
- BadDump,
- Homebrew,
- TranslatedRom,
- Hack,
- BIOS,
- Overdump,
- NotInDatabase
- }
-
- public enum HashType
- {
- CRC32, MD5
- }
-
- public class GameInfo
+ internal class CompactGameInfo
{
public string Name;
public string System;
public string MetaData;
- public string hash;
+ public string Hash;
public RomStatus Status;
-
- public string[] GetOptions()
- {
- if (string.IsNullOrEmpty(MetaData))
- return new string[0];
- return MetaData.Split(';').Where(opt => string.IsNullOrEmpty(opt) == false).ToArray();
- }
-
- public Dictionary ParseOptionsDictionary()
- {
- var ret = new Dictionary();
- foreach (var opt in GetOptions())
- {
- var parts = opt.Split('=');
- var key = parts[0];
- var value = parts.Length > 1 ? parts[1] : "";
- ret[key] = value;
- }
- return ret;
- }
}
public static class Database
{
- private static Dictionary db = new Dictionary();
+ private static Dictionary db = new Dictionary();
static string RemoveHashType(string hash)
{
@@ -66,10 +28,12 @@ namespace BizHawk
public static GameInfo CheckDatabase(string hash)
{
- GameInfo ret = null;
+ CompactGameInfo cgi;
hash = RemoveHashType(hash);
- db.TryGetValue(hash, out ret);
- return ret;
+ db.TryGetValue(hash, out cgi);
+ if (cgi == null)
+ return null;
+ return new GameInfo(cgi);
}
static void LoadDatabase_Escape(string line)
@@ -103,9 +67,9 @@ namespace BizHawk
if (line.Trim().Length == 0) continue;
string[] items = line.Split('\t');
- var Game = new GameInfo();
+ var Game = new CompactGameInfo();
//remove a hash type identifier. well don't really need them for indexing (theyre just there for human purposes)
- Game.hash = RemoveHashType(items[0].ToUpper());
+ Game.Hash = RemoveHashType(items[0].ToUpper());
switch (items[1].Trim())
{
case "B": Game.Status = RomStatus.BadDump; break;
@@ -121,10 +85,10 @@ namespace BizHawk
Game.System = items[3];
Game.MetaData = items.Length >= 6 ? items[5] : null;
- if (db.ContainsKey(Game.hash))
- Console.WriteLine("gamedb: Multiple hash entries {0}, duplicate detected on {1}",Game.hash, Game.Name);
+ if (db.ContainsKey(Game.Hash))
+ Console.WriteLine("gamedb: Multiple hash entries {0}, duplicate detected on {1}",Game.Hash, Game.Name);
- db[Game.hash] = Game;
+ db[Game.Hash] = Game;
} catch
{
Console.WriteLine("Error parsing database entry: "+line);
@@ -135,24 +99,21 @@ namespace BizHawk
public static GameInfo GetGameInfo(byte[] RomData, string fileName)
{
- GameInfo ret;
+ CompactGameInfo cgi;
string hash = string.Format("{0:X8}", CRC32.Calculate(RomData));
- if (db.TryGetValue(hash, out ret))
- return ret;
+ if (db.TryGetValue(hash, out cgi))
+ return new GameInfo(cgi);
hash = Util.BytesToHexString(System.Security.Cryptography.MD5.Create().ComputeHash(RomData));
- if (db.TryGetValue(hash, out ret))
- return ret;
+ if (db.TryGetValue(hash, out cgi))
+ return new GameInfo(cgi);
hash = Util.BytesToHexString(System.Security.Cryptography.SHA1.Create().ComputeHash(RomData));
- if (db.TryGetValue(hash, out ret))
- return ret;
+ if (db.TryGetValue(hash, out cgi))
+ return new GameInfo(cgi);
// rom is not in database. make some best-guesses
- var Game = new GameInfo();
- Game.hash = hash;
- Game.MetaData = "NotInDatabase";
- Game.Status = RomStatus.NotInDatabase;
+ var Game = new GameInfo { Hash = hash, Status = RomStatus.NotInDatabase };
Console.WriteLine("Game was not in DB. CRC: {0:X8} MD5: {1}",
CRC32.Calculate(RomData),
Util.BytesToHexString(System.Security.Cryptography.MD5.Create().ComputeHash(RomData)));
diff --git a/BizHawk.Emulation/ExternalCores/PsxCore.cs b/BizHawk.Emulation/ExternalCores/PsxCore.cs
index b13555d828..2e7297de7b 100644
--- a/BizHawk.Emulation/ExternalCores/PsxCore.cs
+++ b/BizHawk.Emulation/ExternalCores/PsxCore.cs
@@ -68,7 +68,6 @@ namespace BizHawk
public CoreOutputComm CoreOutputComm { get; private set; }
public IVideoProvider VideoProvider { get { return this; } }
public ISoundProvider SoundProvider { get { return this; } }
- public void LoadGame(IGame game) { }
public unsafe void FrameAdvance(bool render)
{
//if (render == false) return;
diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs b/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs
index a850c5c0dc..50c7967164 100644
--- a/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs
+++ b/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs
@@ -28,7 +28,6 @@ namespace BizHawk
Frame = 0;
}
- public void LoadGame(IGame game) { }
public void FrameAdvance(bool render)
{
if (render == false) return;
diff --git a/BizHawk.Emulation/Interfaces/CoreComms.cs b/BizHawk.Emulation/Interfaces/CoreComms.cs
index 535db1ee05..740f61fe14 100644
--- a/BizHawk.Emulation/Interfaces/CoreComms.cs
+++ b/BizHawk.Emulation/Interfaces/CoreComms.cs
@@ -1,6 +1,4 @@
-using System.Collections.Generic;
-
-namespace BizHawk
+namespace BizHawk
{
public class CoreInputComm
{
@@ -12,9 +10,7 @@ namespace BizHawk
public class CoreOutputComm
{
public double VsyncRate = 60;
- public RomStatus RomStatus;
public string RomStatusAnnotation;
public string RomStatusDetails;
}
-
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Interfaces/IEmulator.cs b/BizHawk.Emulation/Interfaces/IEmulator.cs
index df401d493d..80636139c7 100644
--- a/BizHawk.Emulation/Interfaces/IEmulator.cs
+++ b/BizHawk.Emulation/Interfaces/IEmulator.cs
@@ -12,7 +12,6 @@ namespace BizHawk
ControllerDefinition ControllerDefinition { get; }
IController Controller { get; set; }
- void LoadGame(IGame game);
void FrameAdvance(bool render);
int Frame { get; }
@@ -24,8 +23,6 @@ namespace BizHawk
byte[] SaveRam { get; }
bool SaveRamModified { get; set; }
- // TODO: should IEmulator expose a way of enumerating the Options it understands?
- // (the answer is yes)
void ResetFrameCounter();
void SaveStateText(TextWriter writer);
void LoadStateText(TextReader reader);
@@ -33,7 +30,7 @@ namespace BizHawk
void LoadStateBinary(BinaryReader reader);
byte[] SaveStateBinary();
- //arbitrary extensible core comm mechanism
+ // Arbitrary extensible core comm mechanism
CoreInputComm CoreInputComm { get; set; }
CoreOutputComm CoreOutputComm { get; }
diff --git a/BizHawk.Emulation/Interfaces/IGame.cs b/BizHawk.Emulation/Interfaces/IGame.cs
deleted file mode 100644
index d8efc3db89..0000000000
--- a/BizHawk.Emulation/Interfaces/IGame.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.Generic;
-
-namespace BizHawk
-{
- public interface IGame
- {
- byte[] GetRomData();
- byte[] GetFileData();
- IList GetOptions();
-
- //only use this for cosmetic purposes
- string Name { get; }
-
- //use this for path-building purposes
- string FilesystemSafeName { get; }
- }
-}
\ No newline at end of file
diff --git a/BizHawk.Emulation/QuickCollections.cs b/BizHawk.Emulation/QuickCollections.cs
index 20cd7ba92a..877d1e332a 100644
--- a/BizHawk.Emulation/QuickCollections.cs
+++ b/BizHawk.Emulation/QuickCollections.cs
@@ -1,6 +1,7 @@
using System;
+using System.Collections.Generic;
-namespace BizHawk.Emulation
+namespace BizHawk
{
// If you're wondering what the point of this is: It's mostly to have .Clear() be fast.
// only intended to be used with value types. If used on references you may get GC issues.
@@ -84,4 +85,96 @@ namespace BizHawk.Emulation
// TODO serialization functions
}
-}
+
+ // .net has no built-in read only dictionary
+ public class ReadOnlyDictionary : IDictionary
+ {
+ private IDictionary dict;
+
+ public ReadOnlyDictionary(IDictionary dictionary)
+ {
+ dict = dictionary;
+ }
+
+ public void Add(TKey key, TValue value)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public bool ContainsKey(TKey key)
+ {
+ return dict.ContainsKey(key);
+ }
+
+ public ICollection Keys
+ {
+ get { return dict.Keys; }
+ }
+
+ public bool Remove(TKey key)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ return dict.TryGetValue(key, out value);
+ }
+
+ public ICollection Values
+ {
+ get { return dict.Values; }
+ }
+
+ public TValue this[TKey key]
+ {
+ get { return dict[key]; }
+ set { throw new InvalidOperationException(); }
+ }
+
+ public void Add(KeyValuePair item)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public void Clear()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public bool Contains(KeyValuePair item)
+ {
+ return dict.Contains(item);
+ }
+
+ public void CopyTo(KeyValuePair[] array, int arrayIndex)
+ {
+ dict.CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return dict.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return true; }
+ }
+
+ public bool Remove(KeyValuePair item)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public IEnumerator> GetEnumerator()
+ {
+ return dict.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return ((System.Collections.IEnumerable)dict).GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.MultiClient/BizHawk.MultiClient.csproj b/BizHawk.MultiClient/BizHawk.MultiClient.csproj
index 8923d0c560..bb8ef1c295 100644
--- a/BizHawk.MultiClient/BizHawk.MultiClient.csproj
+++ b/BizHawk.MultiClient/BizHawk.MultiClient.csproj
@@ -244,7 +244,6 @@
Component
-
Form
diff --git a/BizHawk.MultiClient/Global.cs b/BizHawk.MultiClient/Global.cs
index 1e34729556..9046443ab6 100644
--- a/BizHawk.MultiClient/Global.cs
+++ b/BizHawk.MultiClient/Global.cs
@@ -14,7 +14,7 @@ namespace BizHawk.MultiClient
public static Config Config;
public static IEmulator Emulator;
public static CoreInputComm CoreInputComm;
- public static RomGame Game;
+ public static GameInfo Game;
public static Controller SMSControls;
public static Controller PCEControls;
public static Controller GenControls;
diff --git a/BizHawk.MultiClient/MainForm.MenuItems.cs b/BizHawk.MultiClient/MainForm.MenuItems.cs
index bbfc54d13d..52438c83a3 100644
--- a/BizHawk.MultiClient/MainForm.MenuItems.cs
+++ b/BizHawk.MultiClient/MainForm.MenuItems.cs
@@ -648,7 +648,7 @@ namespace BizHawk.MultiClient
private void screenshotAsToolStripMenuItem_Click(object sender, EventArgs e)
{
- string path = String.Format(Global.Game.ScreenshotPrefix + ".{0:yyyy-MM-dd HH.mm.ss}.png", DateTime.Now);
+ string path = String.Format(PathManager.ScreenshotPrefix(Global.Game) + ".{0:yyyy-MM-dd HH.mm.ss}.png", DateTime.Now);
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = Path.GetDirectoryName(path);
@@ -873,7 +873,7 @@ namespace BizHawk.MultiClient
else
contextMenuStrip1.Items[7].Enabled = true;
- string path = Global.Game.SaveStatePrefix + "." + "QuickSave" + SaveSlot.ToString() + ".State.bak";
+ string path = PathManager.SaveStatePrefix(Global.Game) + "." + "QuickSave" + SaveSlot + ".State.bak";
var file = new FileInfo(path);
if (file.Exists == true)
{
@@ -1314,7 +1314,7 @@ namespace BizHawk.MultiClient
private void undoSavestateToolStripMenuItem_Click(object sender, EventArgs e)
{
- string path = Global.Game.SaveStatePrefix + "." + "QuickSave" + SaveSlot.ToString() + ".State";
+ string path = PathManager.SaveStatePrefix(Global.Game) + "." + "QuickSave" + SaveSlot + ".State";
SwapBackupSavestate(path);
Global.RenderPanel.AddMessage("Save slot " + SaveSlot.ToString() + " restored.");
}
diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs
index a5ed0a9a31..5907b2d6a4 100644
--- a/BizHawk.MultiClient/MainForm.cs
+++ b/BizHawk.MultiClient/MainForm.cs
@@ -68,7 +68,7 @@ namespace BizHawk.MultiClient
public MainForm(string[] args)
{
InitializeComponent();
- Global.Game = new NullGame();
+ Global.Game = new GameInfo();
if (Global.Config.ShowLogWindow)
{
LogConsole.ShowConsole();
@@ -838,87 +838,88 @@ namespace BizHawk.MultiClient
}
IEmulator nextEmulator = null;
- RomGame game = null;
+ RomGame rom = null;
+ GameInfo game = null;
+
- if (file.Extension.ToLower() == ".iso")
+ try
{
- if (Global.PsxCoreLibrary.IsOpen)
- {
- PsxCore psx = new PsxCore(Global.PsxCoreLibrary);
- nextEmulator = psx;
- game = new RomGame();
- var disc = Disc.FromIsoPath(path);
- Global.DiscHopper.Clear();
- Global.DiscHopper.Enqueue(disc);
- Global.DiscHopper.Insert();
- psx.SetDiscHopper(Global.DiscHopper);
- }
+
+ if (file.Extension.ToLower() == ".iso")
+ {
+ if (Global.PsxCoreLibrary.IsOpen)
+ {
+ // sorry zero ;'( I leave de-RomGameifying this to you
+ //PsxCore psx = new PsxCore(Global.PsxCoreLibrary);
+ //nextEmulator = psx;
+ //game = new RomGame();
+ //var disc = Disc.FromIsoPath(path);
+ //Global.DiscHopper.Clear();
+ //Global.DiscHopper.Enqueue(disc);
+ //Global.DiscHopper.Insert();
+ //psx.SetDiscHopper(Global.DiscHopper);
+ }
+ }
+ else
+ {
+ rom = new RomGame(file);
+ game = rom.GameInfo;
+
+ switch (game.System)
+ {
+ case "SMS":
+ case "SG":
+ if (Global.Config.SmsEnableFM) game.AddOption("UseFM");
+ if (Global.Config.SmsAllowOverlock) game.AddOption("AllowOverclock");
+ if (Global.Config.SmsForceStereoSeparation) game.AddOption("ForceStereo");
+ nextEmulator = new SMS(game, rom.RomData);
+ break;
+ case "GG":
+ if (Global.Config.SmsAllowOverlock) game.AddOption("AllowOverclock");
+ nextEmulator = new SMS(game, rom.RomData);
+ break;
+ case "PCE":
+ case "SGX":
+ nextEmulator = new PCEngine(game, rom.RomData);
+ break;
+ case "GEN":
+ nextEmulator = new Genesis(true); //TODO
+ break;
+ case "TI83":
+ nextEmulator = new TI83(game, rom.RomData);
+ if (Global.Config.TI83autoloadKeyPad)
+ LoadTI83KeyPad();
+ break;
+ case "NES":
+ {
+ NES nes = new NES(game, rom.FileData);
+ Global.Game.Status = nes.RomStatus;
+ nextEmulator = nes;
+ if (Global.Config.NESAutoLoadPalette && Global.Config.NESPaletteFile.Length > 0 &&
+ HawkFile.ExistsAt(Global.Config.NESPaletteFile))
+ {
+ nes.SetPalette(
+ NES.Palettes.Load_FCEUX_Palette(HawkFile.ReadAllBytes(Global.Config.NESPaletteFile)));
+ }
+ }
+ break;
+ case "GB":
+ nextEmulator = new Gameboy();
+ break;
+ }
+ }
+
+ if (nextEmulator == null)
+ throw new Exception();
+ nextEmulator.CoreInputComm = Global.CoreInputComm;
}
- else
+ catch (Exception ex)
{
- game = new RomGame(file);
-
- switch (game.System)
- {
- case "SG":
- case "SMS":
- nextEmulator = new SMS();
- if (Global.Config.SmsEnableFM) game.AddOptions("UseFM");
- if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
- if (Global.Config.SmsForceStereoSeparation) game.AddOptions("ForceStereo");
- break;
- case "GG":
- nextEmulator = new SMS { IsGameGear = true };
- if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
- break;
- case "PCE":
- nextEmulator = new PCEngine(NecSystemType.TurboGrafx);
- break;
- case "SGX":
- nextEmulator = new PCEngine(NecSystemType.SuperGrafx);
- break;
- case "GEN":
- nextEmulator = new Genesis(true);//TODO
- break;
- case "TI83":
- nextEmulator = new TI83();
- if (Global.Config.TI83autoloadKeyPad)
- LoadTI83KeyPad();
- break;
- case "NES":
- {
- NES nes = new NES();
- nextEmulator = nes;
- if (Global.Config.NESAutoLoadPalette && Global.Config.NESPaletteFile.Length > 0 && HawkFile.ExistsAt(Global.Config.NESPaletteFile))
- {
- nes.SetPalette(NES.Palettes.Load_FCEUX_Palette(HawkFile.ReadAllBytes(Global.Config.NESPaletteFile)));
- }
- }
- break;
- case "GB":
- nextEmulator = new Gameboy();
- break;
- }
-
- if (nextEmulator == null) throw new Exception();
-
- try
- {
- nextEmulator.CoreInputComm = Global.CoreInputComm;
-
- //this is a bit hacky, but many cores do not take responsibility for setting this, so we need to set it for them.
- nextEmulator.CoreOutputComm.RomStatus = game.Status;
-
- nextEmulator.LoadGame(game);
- }
- catch (Exception ex)
- {
- MessageBox.Show("Exception during loadgame:\n\n" + ex.ToString());
- return false;
- }
+ MessageBox.Show("Exception during loadgame:\n\n" + ex.ToString());
+ return false;
}
-
+
if (nextEmulator == null) throw new Exception();
@@ -936,7 +937,7 @@ namespace BizHawk.MultiClient
Text = DisplayNameForSystem(game.System) + " - " + game.Name;
ResetRewindBuffer();
Global.Config.RecentRoms.Add(file.CanonicalFullPath);
- if (File.Exists(game.SaveRamPath))
+ if (File.Exists(PathManager.SaveRamPath(game)))
LoadSaveRam();
//setup the throttle based on platform's specifications
@@ -975,7 +976,7 @@ namespace BizHawk.MultiClient
if (Global.Emulator == null) return;
if (Global.Game == null) return;
- var status = Global.Emulator.CoreOutputComm.RomStatus;
+ var status = Global.Game.Status;
string annotation = "";
if (status == RomStatus.BadDump)
{
@@ -1022,7 +1023,7 @@ namespace BizHawk.MultiClient
{
try
{
- using (var reader = new BinaryReader(new FileStream(Global.Game.SaveRamPath, FileMode.Open, FileAccess.Read)))
+ using (var reader = new BinaryReader(new FileStream(PathManager.SaveRamPath(Global.Game), FileMode.Open, FileAccess.Read)))
reader.Read(Global.Emulator.SaveRam, 0, Global.Emulator.SaveRam.Length);
} catch { }
}
@@ -1030,25 +1031,27 @@ namespace BizHawk.MultiClient
private void CloseGame()
{
if (Global.Emulator.SaveRamModified)
- {
- string path = Global.Game.SaveRamPath;
-
- var f = new FileInfo(path);
- if (f.Directory.Exists == false)
- f.Directory.Create();
-
- var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write));
- int len = Util.SaveRamBytesUsed(Global.Emulator.SaveRam);
- //int len = Global.Emulator.SaveRam.Length;
- writer.Write(Global.Emulator.SaveRam, 0, len);
- writer.Close();
- }
+ SaveRam();
Global.Emulator.Dispose();
Global.Emulator = new NullEmulator();
Global.ActiveController = Global.NullControls;
UserMovie.StopMovie();
}
+ private static void SaveRam()
+ {
+ string path = PathManager.SaveRamPath(Global.Game);
+
+ var f = new FileInfo(path);
+ if (f.Directory.Exists == false)
+ f.Directory.Create();
+
+ var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write));
+ int len = Util.SaveRamBytesUsed(Global.Emulator.SaveRam);
+ writer.Write(Global.Emulator.SaveRam, 0, len);
+ writer.Close();
+ }
+
void OnSelectSlot(int num)
{
SaveSlot = num;
@@ -1559,12 +1562,12 @@ namespace BizHawk.MultiClient
private void TakeScreenshot()
{
- MakeScreenshot(String.Format(Global.Game.ScreenshotPrefix + ".{0:yyyy-MM-dd HH.mm.ss}.png", DateTime.Now));
+ MakeScreenshot(String.Format(PathManager.ScreenshotPrefix(Global.Game) + ".{0:yyyy-MM-dd HH.mm.ss}.png", DateTime.Now));
}
private void SaveState(string name)
{
- string path = Global.Game.SaveStatePrefix + "." + name + ".State";
+ string path = PathManager.SaveStatePrefix(Global.Game) + "." + name + ".State";
var file = new FileInfo(path);
if (file.Directory.Exists == false)
@@ -1596,7 +1599,7 @@ namespace BizHawk.MultiClient
private void SaveStateAs()
{
var sfd = new SaveFileDialog();
- string path = Global.Game.SaveStatePrefix;
+ string path = PathManager.SaveStatePrefix(Global.Game);
sfd.InitialDirectory = path;
sfd.FileName = "QuickSave0.State";
var file = new FileInfo(path);
@@ -1629,7 +1632,7 @@ namespace BizHawk.MultiClient
private void LoadState(string name)
{
- string path = Global.Game.SaveStatePrefix + "." + name + ".State";
+ string path = PathManager.SaveStatePrefix(Global.Game) + "." + name + ".State";
if (File.Exists(path) == false)
return;
@@ -1639,7 +1642,7 @@ namespace BizHawk.MultiClient
private void LoadStateAs()
{
var ofd = new OpenFileDialog();
- ofd.InitialDirectory = Global.Game.SaveStatePrefix;
+ ofd.InitialDirectory = PathManager.SaveStatePrefix(Global.Game);
ofd.Filter = "Save States (*.State)|*.State|All Files|*.*";
ofd.RestoreDirectory = true;
@@ -1943,7 +1946,7 @@ namespace BizHawk.MultiClient
{
CloseGame();
Global.Emulator = new NullEmulator();
- Global.Game = new NullGame();
+ Global.Game = new GameInfo();
MemoryPulse.Clear();
RamSearch1.Restart();
RamWatch1.Restart();
@@ -2128,7 +2131,7 @@ namespace BizHawk.MultiClient
var sfd = new SaveFileDialog();
if (!(Global.Emulator is NullEmulator))
{
- sfd.FileName = Global.Game.FilesystemSafeName;
+ sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.AVIPath, "");
}
else
diff --git a/BizHawk.MultiClient/NullGame.cs b/BizHawk.MultiClient/NullGame.cs
deleted file mode 100644
index ca6b776feb..0000000000
--- a/BizHawk.MultiClient/NullGame.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-
-namespace BizHawk.MultiClient
-{
- public class NullGame : RomGame
- {
- private List options;
- private const int BankSize = 4096;
- new public RomStatus Status { get; private set; }
- new public string Name { get { return "Null Game"; } set { } }
- new public string FilesystemSafeName { get { return "Null Game"; } }
-
- public NullGame()
- {
- FileData = new byte[1];
- FileData[0] = new byte();
- RomData = new byte[1];
- RomData[0] = new byte();
- System = "Null";
- Status = RomStatus.GoodDump;
- options = new List();
- options.Add("null");
- }
-
- private byte[] DeInterleaveSMD(byte[] source)
- {
- return FileData;
- }
-
- private void CheckForPatchOptions()
- {
- }
-
- new public string SaveRamPath
- {
- get
- {
- return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.BasePath, ""), "Null Game.SaveRAM");
- }
- }
-
-
-
- new public string SaveStatePrefix
- {
- get
- {
- string Bind = "";
- if (Global.Config.BindSavestatesToMovies && Global.MainForm.UserMovie.Mode != MOVIEMODE.INACTIVE)
- Bind += " - " + Path.GetFileNameWithoutExtension(Global.MainForm.UserMovie.Filename);
-
- return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.BasePath, ""), "Null Game" + Bind);
- }
- }
-
- new public string MoviePrefix
- {
- get
- {
- return PathManager.MakeAbsolutePath(Global.Config.BasePath, "") + "Null Game";
- }
- }
-
- new public string ScreenshotPrefix
- {
- get
- {
- return PathManager.MakeAbsolutePath(Global.Config.BasePath, "") + "/" + "Null Game";
- }
- }
- }
-}
diff --git a/BizHawk.MultiClient/PlayMovie.cs b/BizHawk.MultiClient/PlayMovie.cs
index 7234918d1b..308c007d9e 100644
--- a/BizHawk.MultiClient/PlayMovie.cs
+++ b/BizHawk.MultiClient/PlayMovie.cs
@@ -193,7 +193,7 @@ namespace BizHawk.MultiClient
//Pull out matching names
for (int x = 0; x < MovieList.Count; x++)
{
- if (Global.Game.FilesystemSafeName == MovieList[x].GetGameName())
+ if (PathManager.FilesystemSafeName(Global.Game) == MovieList[x].GetGameName())
Indexes.Add(x);
}
if (Indexes.Count == 0) return;
diff --git a/BizHawk.MultiClient/RecordMovie.cs b/BizHawk.MultiClient/RecordMovie.cs
index 1d891f2e38..5429cfe9a8 100644
--- a/BizHawk.MultiClient/RecordMovie.cs
+++ b/BizHawk.MultiClient/RecordMovie.cs
@@ -59,7 +59,7 @@ namespace BizHawk.MultiClient
MovieToRecord.Header.SetHeaderLine(MovieHeader.GUID, MovieHeader.MakeGUID());
MovieToRecord.Header.SetHeaderLine(MovieHeader.PLATFORM, Global.Emulator.SystemId);
if (Global.Game != null)
- MovieToRecord.Header.SetHeaderLine(MovieHeader.GAMENAME, Global.Game.FilesystemSafeName);
+ MovieToRecord.Header.SetHeaderLine(MovieHeader.GAMENAME, PathManager.FilesystemSafeName(Global.Game));
else
MovieToRecord.Header.SetHeaderLine(MovieHeader.GAMENAME, "NULL");
@@ -111,7 +111,7 @@ namespace BizHawk.MultiClient
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.MoviesPath, "");
sfd.DefaultExt = ".tas";
- sfd.FileName = Global.Game.FilesystemSafeName;
+ sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
sfd.Filter = "Movie files (*.tas)|*.tas";
Global.Sound.StopSound();
diff --git a/BizHawk.MultiClient/RomGame.cs b/BizHawk.MultiClient/RomGame.cs
index 309357e2c7..ace16a0ce9 100644
--- a/BizHawk.MultiClient/RomGame.cs
+++ b/BizHawk.MultiClient/RomGame.cs
@@ -1,20 +1,14 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.IO;
namespace BizHawk.MultiClient
{
- public class RomGame : IGame
+ public class RomGame
{
public byte[] RomData;
public byte[] FileData;
- public string System;
- public RomStatus Status { get; private set; }
+ public GameInfo GameInfo;
- private string name;
- private string filesystemSafeName;
- private List options;
private const int BankSize = 4096;
public RomGame() { }
@@ -40,18 +34,10 @@ namespace BizHawk.MultiClient
if (file.Extension == ".SMD")
RomData = DeInterleaveSMD(RomData);
- var info = Database.GetGameInfo(RomData, file.Name);
- name = info.Name;
- System = info.System;
- Status = info.Status;
- options = new List(info.GetOptions());
+ GameInfo = Database.GetGameInfo(RomData, file.Name);
+
CheckForPatchOptions();
- //build a safe filesystem name for use in auxilary files (savestates, saveram, etc)
- filesystemSafeName = file.CanonicalName.Replace("|", "+");
- filesystemSafeName = Path.Combine(Path.GetDirectoryName(filesystemSafeName), Path.GetFileNameWithoutExtension(filesystemSafeName));
-
-
if (patch != null)
{
using (var patchFile = new HawkFile(patch))
@@ -63,12 +49,7 @@ namespace BizHawk.MultiClient
}
}
- public void AddOptions(params string[] options)
- {
- this.options.AddRange(options);
- }
-
- private byte[] DeInterleaveSMD(byte[] source)
+ private static byte[] DeInterleaveSMD(byte[] source)
{
// SMD files are interleaved in pages of 16k, with the first 8k containing all
// odd bytes and the second 8k containing all even bytes.
@@ -93,113 +74,19 @@ namespace BizHawk.MultiClient
{
try
{
- foreach (var opt in options)
+ if (GameInfo["PatchBytes"])
{
- if (opt.StartsWith("PatchBytes"))
+ string args = GameInfo.OptionValue("PatchBytes");
+ foreach (var val in args.Split(','))
{
- var split1 = opt.Split('=');
- foreach (var val in split1[1].Split(','))
- {
- var split3 = val.Split(':');
- int offset = int.Parse(split3[0], NumberStyles.HexNumber);
- byte value = byte.Parse(split3[1], NumberStyles.HexNumber);
- RomData[offset] = value;
- }
+ var split = val.Split(':');
+ int offset = int.Parse(split[0], NumberStyles.HexNumber);
+ byte value = byte.Parse(split[1], NumberStyles.HexNumber);
+ RomData[offset] = value;
}
}
}
catch (Exception) { } // No need for errors in patching to propagate.
}
-
- public byte[] GetRomData() { return RomData; }
- public byte[] GetFileData() { return FileData; }
- public IList GetOptions() { return options; }
- public string Name { get { return name; } set { name = value; } }
- public string FilesystemSafeName { get { return filesystemSafeName; } }
-
- public string SaveRamPath
- {
- get
- {
- switch (System)
- {
- case "SMS": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathSMSSaveRAM, "SMS"), filesystemSafeName + ".SaveRAM");
- case "GG": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathGGSaveRAM, "GG"), filesystemSafeName + ".SaveRAM");
- case "SG": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathSGSaveRAM, "SG"), filesystemSafeName + ".SaveRAM");
- case "SGX": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathPCESaveRAM, "PCE"), filesystemSafeName + ".SaveRAM");
- case "PCE": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathPCESaveRAM, "PCE"), filesystemSafeName + ".SaveRAM");
- case "GB": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathGBSaveRAM, "GB"), filesystemSafeName + ".SaveRAM");
- case "GEN": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathGenesisSaveRAM, "GEN"), filesystemSafeName + ".SaveRAM");
- case "NES": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathNESSaveRAM, "NES"), filesystemSafeName + ".SaveRAM");
- case "TI83": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathTI83SaveRAM, "TI83"), filesystemSafeName + ".SaveRAM");
- default: return "";
- }
- }
- }
-
- public string SaveStatePrefix
- {
- get
- {
- string Bind = "";
- if (Global.Config.BindSavestatesToMovies && Global.MainForm.UserMovie.Mode != MOVIEMODE.INACTIVE)
- Bind += " - " + Path.GetFileNameWithoutExtension(Global.MainForm.UserMovie.Filename);
- switch (System)
- {
- case "SMS": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathSMSSavestates, "SMS"), filesystemSafeName + Bind);
- case "GG": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathGGSavestates, "GG"), filesystemSafeName + Bind);
- case "SG": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathSGSavestates, "SG"), filesystemSafeName + Bind);
- case "PCE": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathPCESavestates, "PCE"), filesystemSafeName + Bind);
- case "SGX": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathPCESavestates, "PCE"), filesystemSafeName + Bind);
- case "GB": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathGBSavestates, "GB"), filesystemSafeName + Bind);
- case "GEN": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathGenesisSavestates, "GEN"), filesystemSafeName + Bind);
- case "NES": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathNESSavestates, "NES"), filesystemSafeName + Bind);
- case "TI83": return Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathTI83Savestates, "TI83"), filesystemSafeName + Bind);
- default: return "";
- }
-
- }
- }
-
- public string MoviePrefix
- {
- //Obsolete because there is one singular Movie path
- get
- {
- switch (System)
- {
- case "SMS": return "SMS/Movie/" + filesystemSafeName;
- case "GG": return "Game Gear/Movie/" + filesystemSafeName;
- case "SG": return "SG-1000/Movie/" + filesystemSafeName;
- case "PCE": return "TurboGrafx/Movie/" + filesystemSafeName;
- case "SGX": return "TurboGrafx/Movie/" + filesystemSafeName;
- case "GB": return "Gameboy/Movie/" + filesystemSafeName;
- case "GEN": return "Genesis/Movie/" + filesystemSafeName;
- case "NES": return "NES/Movie/" + filesystemSafeName;
- case "TI83": return "TI83/Movie/" + filesystemSafeName;
- default: return "";
- }
- }
- }
-
- public string ScreenshotPrefix
- {
- get
- {
- switch (System)
- {
- case "SMS": return PathManager.MakeAbsolutePath(Global.Config.PathSMSScreenshots, "SMS") + "/" + filesystemSafeName;
- case "GG": return PathManager.MakeAbsolutePath(Global.Config.PathGGScreenshots, "GG") + "/" + filesystemSafeName;
- case "SG": return PathManager.MakeAbsolutePath(Global.Config.PathSGScreenshots, "SG") + "/" + filesystemSafeName;
- case "PCE": return PathManager.MakeAbsolutePath(Global.Config.PathPCEScreenshots, "PCE") + "/" + filesystemSafeName;
- case "SGX": return PathManager.MakeAbsolutePath(Global.Config.PathPCEScreenshots, "PCE") + "/" + filesystemSafeName;
- case "GB": return PathManager.MakeAbsolutePath(Global.Config.PathGBScreenshots, "GB") + "/" + filesystemSafeName;
- case "GEN": return PathManager.MakeAbsolutePath(Global.Config.PathGenesisScreenshots, "GEN") + "/" + filesystemSafeName;
- case "NES": return PathManager.MakeAbsolutePath(Global.Config.PathNESScreenshots, "NES") + "/" + filesystemSafeName;
- case "TI83": return PathManager.MakeAbsolutePath(Global.Config.PathTI83Screenshots, "TI83") + "/" + filesystemSafeName;
- default: return "";
- }
- }
- }
}
}
diff --git a/BizHawk.MultiClient/SavestateManager.cs b/BizHawk.MultiClient/SavestateManager.cs
index 36f8155a0c..940ff3c8d0 100644
--- a/BizHawk.MultiClient/SavestateManager.cs
+++ b/BizHawk.MultiClient/SavestateManager.cs
@@ -27,7 +27,7 @@ namespace BizHawk.MultiClient
}
for (int x = 0; x < 10; x++)
{
- path = Global.Game.SaveStatePrefix + "." + "QuickSave" + x + ".State";
+ path = PathManager.SaveStatePrefix(Global.Game) + "." + "QuickSave" + x + ".State";
var file = new FileInfo(path);
if (file.Directory.Exists == false)
file.Directory.Create();
diff --git a/BizHawk.MultiClient/config/PathManager.cs b/BizHawk.MultiClient/config/PathManager.cs
index 5666e8e0b8..c1a02bb32b 100644
--- a/BizHawk.MultiClient/config/PathManager.cs
+++ b/BizHawk.MultiClient/config/PathManager.cs
@@ -259,5 +259,65 @@ namespace BizHawk.MultiClient
return path;
}
+
+ public static string FilesystemSafeName(GameInfo game)
+ {
+ string filesystemSafeName = game.Name.Replace("|", "+");
+ return Path.Combine(Path.GetDirectoryName(filesystemSafeName), Path.GetFileNameWithoutExtension(filesystemSafeName));
+ }
+
+ public static string SaveRamPath(GameInfo game)
+ {
+ string name = FilesystemSafeName(game);
+ switch (game.System)
+ {
+ case "SMS": return Path.Combine(MakeAbsolutePath(Global.Config.PathSMSSaveRAM, "SMS"), name + ".SaveRAM");
+ case "GG": return Path.Combine(MakeAbsolutePath(Global.Config.PathGGSaveRAM, "GG"), name + ".SaveRAM");
+ case "SG": return Path.Combine(MakeAbsolutePath(Global.Config.PathSGSaveRAM, "SG"), name + ".SaveRAM");
+ case "SGX": return Path.Combine(MakeAbsolutePath(Global.Config.PathPCESaveRAM, "PCE"), name + ".SaveRAM");
+ case "PCE": return Path.Combine(MakeAbsolutePath(Global.Config.PathPCESaveRAM, "PCE"), name + ".SaveRAM");
+ case "GB": return Path.Combine(MakeAbsolutePath(Global.Config.PathGBSaveRAM, "GB"), name + ".SaveRAM");
+ case "GEN": return Path.Combine(MakeAbsolutePath(Global.Config.PathGenesisSaveRAM, "GEN"), name + ".SaveRAM");
+ case "NES": return Path.Combine(MakeAbsolutePath(Global.Config.PathNESSaveRAM, "NES"), name + ".SaveRAM");
+ case "TI83": return Path.Combine(MakeAbsolutePath(Global.Config.PathTI83SaveRAM, "TI83"), name + ".SaveRAM");
+ }
+ return "";
+ }
+
+ public static string SaveStatePrefix(GameInfo game)
+ {
+ string name = FilesystemSafeName(game);
+ switch (game.System)
+ {
+ case "SMS": return Path.Combine(MakeAbsolutePath(Global.Config.PathSMSSavestates, "SMS"), name);
+ case "GG": return Path.Combine(MakeAbsolutePath(Global.Config.PathGGSavestates, "GG"), name);
+ case "SG": return Path.Combine(MakeAbsolutePath(Global.Config.PathSGSavestates, "SG"), name);
+ case "SGX": return Path.Combine(MakeAbsolutePath(Global.Config.PathPCESavestates, "PCE"), name);
+ case "PCE": return Path.Combine(MakeAbsolutePath(Global.Config.PathPCESavestates, "PCE"), name);
+ case "GB": return Path.Combine(MakeAbsolutePath(Global.Config.PathGBSavestates, "GB"), name);
+ case "GEN": return Path.Combine(MakeAbsolutePath(Global.Config.PathGenesisSavestates, "GEN"), name);
+ case "NES": return Path.Combine(MakeAbsolutePath(Global.Config.PathNESSavestates, "NES"), name);
+ case "TI83": return Path.Combine(MakeAbsolutePath(Global.Config.PathTI83Savestates, "TI83"), name);
+ }
+ return "";
+ }
+
+ public static string ScreenshotPrefix(GameInfo game)
+ {
+ string name = FilesystemSafeName(game);
+ switch (game.System)
+ {
+ case "SMS": return Path.Combine(MakeAbsolutePath(Global.Config.PathSMSScreenshots, "SMS"), name);
+ case "GG": return Path.Combine(MakeAbsolutePath(Global.Config.PathGGScreenshots, "GG"), name);
+ case "SG": return Path.Combine(MakeAbsolutePath(Global.Config.PathSGScreenshots, "SG"), name);
+ case "SGX": return Path.Combine(MakeAbsolutePath(Global.Config.PathPCEScreenshots, "PCE"), name);
+ case "PCE": return Path.Combine(MakeAbsolutePath(Global.Config.PathPCEScreenshots, "PCE"), name);
+ case "GB": return Path.Combine(MakeAbsolutePath(Global.Config.PathGBScreenshots, "GB"), name);
+ case "GEN": return Path.Combine(MakeAbsolutePath(Global.Config.PathGenesisScreenshots, "GEN"), name);
+ case "NES": return Path.Combine(MakeAbsolutePath(Global.Config.PathNESScreenshots, "NES"), name);
+ case "TI83": return Path.Combine(MakeAbsolutePath(Global.Config.PathTI83Screenshots, "TI83"), name);
+ }
+ return "";
+ }
}
}
diff --git a/BizHawk.MultiClient/tools/Cheats.cs b/BizHawk.MultiClient/tools/Cheats.cs
index d35a6a0d2a..2fcb3b6a3d 100644
--- a/BizHawk.MultiClient/tools/Cheats.cs
+++ b/BizHawk.MultiClient/tools/Cheats.cs
@@ -58,7 +58,7 @@ namespace BizHawk.MultiClient
private string MakeDefaultFilename()
{
- return Path.Combine(GetCheatsPath(), Global.Game.FilesystemSafeName + ".cht");
+ return Path.Combine(GetCheatsPath(), PathManager.FilesystemSafeName(Global.Game) + ".cht");
}
private void ClearFields()
@@ -397,7 +397,7 @@ namespace BizHawk.MultiClient
if (currentCheatFile.Length > 0)
sfd.FileName = Path.GetFileNameWithoutExtension(currentCheatFile);
else if (!(Global.Emulator is NullEmulator))
- sfd.FileName = Global.Game.FilesystemSafeName;
+ sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
sfd.InitialDirectory = GetCheatsPath();
sfd.Filter = "Cheat Files (*.cht)|*.cht|All Files|*.*";
sfd.RestoreDirectory = true;
diff --git a/BizHawk.MultiClient/tools/RamSearch.cs b/BizHawk.MultiClient/tools/RamSearch.cs
index 486dbd3fe1..9d9a90ccab 100644
--- a/BizHawk.MultiClient/tools/RamSearch.cs
+++ b/BizHawk.MultiClient/tools/RamSearch.cs
@@ -1287,7 +1287,7 @@ namespace BizHawk.MultiClient
}
else if (!(Global.Emulator is NullEmulator))
{
- sfd.FileName = Global.Game.FilesystemSafeName;
+ sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.WatchPath, "");
}
else
diff --git a/BizHawk.MultiClient/tools/RamWatch.cs b/BizHawk.MultiClient/tools/RamWatch.cs
index 46a1ad326c..fc3f11a5e9 100644
--- a/BizHawk.MultiClient/tools/RamWatch.cs
+++ b/BizHawk.MultiClient/tools/RamWatch.cs
@@ -659,7 +659,7 @@ namespace BizHawk.MultiClient
}
else if (!(Global.Emulator is NullEmulator))
{
- sfd.FileName = Global.Game.FilesystemSafeName;
+ sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.WatchPath, "");
}
else