diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 056c92cb2f..cca2e27108 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -408,6 +408,7 @@ + @@ -455,6 +456,7 @@ + diff --git a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs index 1de0f6e41d..d6d98d94fe 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -114,7 +114,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES { var msu1 = romxml["cartridge"]["msu1"]; if (is_msu1_rom && msu1["rom"].Attributes["name"] != null) - return CoreComm.AcquireSubfilePath(msu1["rom"].Attributes["name"].Value); + return CoreComm.CoreFileProvider.PathSubfile(msu1["rom"].Attributes["name"].Value); if (is_msu1_pcm) { //return @"D:\roms\snes\SuperRoadBlaster\SuperRoadBlaster-1.pcm"; @@ -125,7 +125,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES foreach (var child in msu1.ChildNodes.Cast()) { if (child.Name == "track" && child.Attributes["number"].Value == wantsTrackString) - return CoreComm.AcquireSubfilePath(child.Attributes["name"].Value); + return CoreComm.CoreFileProvider.PathSubfile(child.Attributes["name"].Value); } } } @@ -231,7 +231,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES //bsnes wont inspect the xml to load the necessary sfc file. //so, we have to do that here and pass it in as the romData :/ if (romxml["cartridge"] != null && romxml["cartridge"]["rom"] != null) - romData = File.ReadAllBytes(CoreComm.AcquireSubfilePath(romxml["cartridge"]["rom"].Attributes["name"].Value)); + romData = File.ReadAllBytes(CoreComm.CoreFileProvider.PathSubfile(romxml["cartridge"]["rom"].Attributes["name"].Value)); else throw new Exception("Could not find rom file specification in xml file. Please check the integrity of your xml file"); } diff --git a/BizHawk.Emulation/Database/FirmwareDatabase.cs b/BizHawk.Emulation/Database/FirmwareDatabase.cs new file mode 100644 index 0000000000..6b70f1686c --- /dev/null +++ b/BizHawk.Emulation/Database/FirmwareDatabase.cs @@ -0,0 +1,151 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +namespace BizHawk +{ + public static class FirmwareDatabase + { + static FirmwareDatabase() + { + FirmwareAndOption("E4E41472C454F928E53EB10E0509BF7D1146ECC1", "NES", "Bios_FDS", "disksys.rom", "FDS Bios"); + FirmwareAndOption("973E10840DB683CF3FAF61BD443090786B3A9F04", "SNES", "Rom_SGB", "sgb.sfc", "Super GameBoy Rom"); + FirmwareAndOption("A002F4EFBA42775A31185D443F3ED1790B0E949A", "SNES", "CX4", "cx4.rom", "CX4 Rom"); + FirmwareAndOption("188D471FEFEA71EB53F0EE7064697FF0971B1014", "SNES", "DSP1", "dsp1.rom", "DSP1 Rom"); + FirmwareAndOption("78B724811F5F18D8C67669D9390397EB1A47A5E2", "SNES", "DSP1b", "dsp1b.rom", "DSP1b Rom"); + FirmwareAndOption("198C4B1C3BFC6D69E734C5957AF3DBFA26238DFB", "SNES", "DSP2", "dsp2.rom", "DSP2 Rom"); + FirmwareAndOption("558DA7CB3BD3876A6CA693661FFC6C110E948CF9", "SNES", "DSP3", "dsp3.rom", "DSP3 Rom"); + FirmwareAndOption("AF6478AECB6F1B67177E79C82CA04C56250A8C72", "SNES", "DSP4", "dsp4.rom", "DSP4 Rom"); + FirmwareAndOption("6472828403DE3589433A906E2C3F3D274C0FF008", "SNES", "ST010", "st010.rom", "ST010 Rom"); + FirmwareAndOption("FECBAE2CEC76C710422486BAA186FFA7CA1CF925", "SNES", "ST011", "st011.rom", "ST011 Rom"); + FirmwareAndOption("91383B92745CC7CC4F15409AC5BC2C2F699A43F1", "SNES", "ST018", "st018.rom", "ST018 Rom"); + FirmwareAndOption("79F5FF55DD10187C7FD7B8DAAB0B3FFBD1F56A2C", "PCECD", "Bios", "pcecd-3.0-(J).pce", "Super CD-ROM System (J)"); + FirmwareAndOption("D9D134BB6B36907C615A594CC7688F7BFCEF5B43", "A78", "Bios_NTSC", "7800NTSCBIOS.bin", "Atari 7800 NTSC Bios"); + FirmwareAndOption("5A140136A16D1D83E4FF32A19409CA376A8DF874", "A78", "Bios_PAL", "7800PALBIOS.bin", "Atari 7800 PAL Bios"); + FirmwareAndOption("A3AF676991391A6DD716C79022D4947206B78164", "A78", "Bios_HSC", "7800highscore.bin", "Atari 7800 Highscore Bios"); + FirmwareAndOption("45BEDC4CBDEAC66C7DF59E9E599195C778D86A92", "Coleco", "Bios", "ColecoBios.bin", "Colecovision Bios"); + FirmwareAndOption("300C20DF6731A33952DED8C436F7F186D25D3492", "GBA", "Bios", "gbabios.rom", "GBA Bios"); + //FirmwareAndOption("24F67BDEA115A2C847C8813A262502EE1607B7DF", "NDS", "Bios_Arm7", "biosnds7.rom", "NDS ARM7 Bios"); + //FirmwareAndOption("BFAAC75F101C135E32E2AAF541DE6B1BE4C8C62D", "NDS", "Bios_Arm9", "biosnds9.rom", "NDS ARM9 Bios"); + FirmwareAndOption("EF66DAD3E7B2B6A86F326765E7DFD7D1A308AD8F", "TI83", "Rom", "ti83_1.rom", "TI-83 Rom"); + FirmwareAndOption("5A65B922B562CB1F57DAB51B73151283F0E20C7A", "INTV", "EROM", "erom.bin", "Intellivision Executive Rom"); + FirmwareAndOption("F9608BB4AD1CFE3640D02844C7AD8E0BCD974917", "INTV", "GROM", "grom.bin", "Intellivision Graphics Rom"); + FirmwareAndOption("1D503E56DF85A62FEE696E7618DC5B4E781DF1BB", "C64", "Kernal", "c64-kernal.bin", "C64 Kernal Rom"); + FirmwareAndOption("79015323128650C742A3694C9429AA91F355905E", "C64", "Basic", "c64-basic.bin", "C64 Basic Rom"); + FirmwareAndOption("ADC7C31E18C7C7413D54802EF2F4193DA14711AA", "C64", "Chargen", "c64-chargen.bin", "C64 Chargen Rom"); + + //for saturn, we think any bios region can pretty much run any iso + //so, we're going to lay this out carefully so that we choose things in a sensible order, but prefer the correct region + var ss_100_j = File("2B8CB4F87580683EB4D760E4ED210813D667F0A2", "Sega Saturn Bios v1.00 (J)", "saturn-1.00-(J).bin"); + var ss_100_ue = File("FAA8EA183A6D7BBE5D4E03BB1332519800D3FBC3", "Sega Saturn Bios v1.00 (U+E)", "saturn-1.00-(U+E).bin"); + var ss_100a_ue = File("3BB41FEB82838AB9A35601AC666DE5AACFD17A58", "Sega Saturn Bios v1.00a (U+E)", "saturn-1.00a-(U+E).bin"); + var ss_101_j = File("DF94C5B4D47EB3CC404D88B33A8FDA237EAF4720", "Sega Saturn Bios v1.01 (J)", "saturn-1.01-(J).bin"); + Firmware("SAT", "J", "Sega Saturn Bios (J)"); + Option("SAT", "J", ss_100_j); + Option("SAT", "J", ss_101_j); + Option("SAT", "J", ss_100_ue); + Option("SAT", "J", ss_100a_ue); + Firmware("SAT", "U", "Sega Saturn Bios (U)"); + Option("SAT", "U", ss_100_ue); + Option("SAT", "U", ss_100a_ue); + Option("SAT", "U", ss_100_j); + Option("SAT", "U", ss_101_j); + Firmware("SAT", "E", "Sega Saturn Bios (E)"); + Option("SAT", "E", ss_100_ue); + Option("SAT", "E", ss_100a_ue); + Option("SAT", "E", ss_100_j); + Option("SAT", "E", ss_101_j); + } + + //adds a defined firmware ID to the database + static void Firmware(string systemId, string id, string descr) + { + var fr = new FirmwareRecord(); + fr.systemId = systemId; + fr.firmwareId = id; + + fr.descr = descr; + FirmwareRecords.Add(fr); + } + + //adds an acceptable option for a firmware ID to the database + static void Option(string hash, string systemId, string id) + { + var fo = new FirmwareOption(); + fo.systemId = systemId; + fo.firmwareId = id; + fo.hash = hash; + + FirmwareOptions.Add(fo); + } + + //adds an acceptable option for a firmware ID to the database + static void Option(string systemId, string id, FirmwareFile ff) + { + Option(ff.hash, systemId, id); + } + + //defines a firmware file + static FirmwareFile File(string hash, string recommendedName, string descr) + { + var ff = new FirmwareFile(); + ff.hash = hash; + ff.recommendedName = recommendedName; + ff.descr = descr; + FirmwareFiles.Add(ff); + FirmwareFilesByHash[hash] = ff; + return ff; + } + + //adds a defined firmware ID and one file and option + static void FirmwareAndOption(string hash, string systemId, string id, string name, string descr) + { + Firmware(systemId, id, descr); + File(hash, name, descr); + Option(hash, systemId, id); + } + + + public static List FirmwareRecords = new List(); + public static List FirmwareOptions = new List(); + public static List FirmwareFiles = new List(); + + public static Dictionary FirmwareFilesByHash = new Dictionary(); + + public class FirmwareFile + { + public string hash; + public string recommendedName; + public string descr; + } + + public class FirmwareRecord + { + public string systemId; + public string firmwareId; + public string descr; + public string ConfigKey { get { return string.Format("{0}+{1}", systemId, firmwareId); } } + } + + public class FirmwareOption + { + public string systemId; + public string firmwareId; + public string hash; + public string ConfigKey { get { return string.Format("{0}+{1}", systemId, firmwareId); } } + } + + + public static FirmwareRecord LookupFirmwareRecord(string sysId, string firmwareId) + { + var found = + (from fr in FirmwareRecords + where fr.firmwareId == firmwareId + && fr.systemId == sysId + select fr).First(); + + return found; + } + + } //static class FirmwareDatabase +} \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/CoreComms.cs b/BizHawk.Emulation/Interfaces/CoreComms.cs index 9df45dbaf6..36602df63a 100644 --- a/BizHawk.Emulation/Interfaces/CoreComms.cs +++ b/BizHawk.Emulation/Interfaces/CoreComms.cs @@ -17,7 +17,7 @@ namespace BizHawk public string SNES_FirmwaresPath; public string C64_FirmwaresPath; - public Func AcquireSubfilePath; + public ICoreFileProvider CoreFileProvider; public string SNES_ExePath; public string SNES_Profile; diff --git a/BizHawk.Emulation/Interfaces/ICoreFileProvider.cs b/BizHawk.Emulation/Interfaces/ICoreFileProvider.cs new file mode 100644 index 0000000000..247a768d77 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/ICoreFileProvider.cs @@ -0,0 +1,22 @@ +using System.IO; + +namespace BizHawk +{ + public interface ICoreFileProvider + { + /// + /// Opens a firmware according to the specified firmware ID key + /// + Stream OpenFirmware(string sysId, string key); + + /// + /// Returns the path to a firmware according to the specified firmware ID key. Use OpenFirmware instead + /// + string PathFirmware(string sysId, string key); + + /// + /// Produces a path to the requested file, expected to be parallel to the running rom. for example: cue+bin files or sfc+pcm (MSU-1 games) + /// + string PathSubfile(string fname); + } +} diff --git a/BizHawk.Emulation/Util.cs b/BizHawk.Emulation/Util.cs index 5b84f4433c..4f0b48463c 100644 --- a/BizHawk.Emulation/Util.cs +++ b/BizHawk.Emulation/Util.cs @@ -260,14 +260,18 @@ namespace BizHawk writer.WriteLine(); } - static readonly char[] HexConv = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - public static void SaveAsHexFast(this byte[] buffer, TextWriter writer) + public unsafe static void SaveAsHexFast(this byte[] buffer, TextWriter writer) { - for (int i = 0; i < buffer.Length; i++) + char* table = Util.HexConvPtr; + if (buffer.Length > 0) { - writer.Write(HexConv[buffer[i] >> 4]); - writer.Write(HexConv[buffer[i] & 15]); + int len = buffer.Length; + fixed (byte* src = &buffer[0]) + for (int i = 0; i < len; i++) + { + writer.Write(table[src[i] >> 4]); + writer.Write(table[src[i] & 15]); + } } writer.WriteLine(); } @@ -495,8 +499,17 @@ namespace BizHawk - public static class Util + public unsafe static class Util { + static readonly char[] HexConvArr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static System.Runtime.InteropServices.GCHandle HexConvHandle; + public static char* HexConvPtr; + static unsafe Util() + { + HexConvHandle = System.Runtime.InteropServices.GCHandle.Alloc(HexConvArr, System.Runtime.InteropServices.GCHandleType.Pinned); + HexConvPtr = (char*)HexConvHandle.AddrOfPinnedObject().ToPointer(); + } + public static string Hash_MD5(byte[] data, int offset, int len) { using (var md5 = System.Security.Cryptography.MD5.Create()) diff --git a/BizHawk.MultiClient/BizBox.Designer.cs b/BizHawk.MultiClient/BizBox.Designer.cs index eebfde5834..e46b61feb1 100644 --- a/BizHawk.MultiClient/BizBox.Designer.cs +++ b/BizHawk.MultiClient/BizBox.Designer.cs @@ -344,7 +344,7 @@ this.label25.Name = "label25"; this.label25.Size = new System.Drawing.Size(105, 13); this.label25.TabIndex = 17; - this.label25.Text = "Created by: Zeromus"; + this.label25.Text = "Created by: zeromus"; // // label26 // @@ -470,7 +470,7 @@ this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(105, 13); this.label9.TabIndex = 1; - this.label9.Text = "Created by: Zeromus"; + this.label9.Text = "Created by: zeromus"; // // label8 // diff --git a/BizHawk.MultiClient/BizHawk.MultiClient.csproj b/BizHawk.MultiClient/BizHawk.MultiClient.csproj index d86142c874..7e8662df2e 100644 --- a/BizHawk.MultiClient/BizHawk.MultiClient.csproj +++ b/BizHawk.MultiClient/BizHawk.MultiClient.csproj @@ -46,7 +46,7 @@ prompt 4 x86 - false + true true AllRules.ruleset @@ -239,8 +239,10 @@ SoundConfig.cs + + Form diff --git a/BizHawk.MultiClient/Config.cs b/BizHawk.MultiClient/Config.cs index 75e74279b1..8809b15602 100644 --- a/BizHawk.MultiClient/Config.cs +++ b/BizHawk.MultiClient/Config.cs @@ -184,16 +184,7 @@ namespace BizHawk.MultiClient }; //BIOS Paths - public string FilenamePCEBios = "[BIOS] Super CD-ROM System (Japan) (v3.0).pce"; - public string FilenameFDSBios = "disksys.rom"; - public string FilenameGBABIOS = "gbabios.rom"; - public string FilenameCOLBios = "ColecoBios.bin"; - public string FilenameINTVGROM = "grom.bin"; - public string FilenameA78NTSCBios = "7800NTSCBIOS.bin"; - public string FilenameA78PALBios = "7800PALBIOS.bin"; - public string FilenameA78HSCBios = "7800highscore.bin"; - public string FilenameINTVEROM = "erom.bin"; - public string FilenameSaturnBios = "Sega Saturn BIOS v1.01 (JAP).bin"; + public Dictionary FirmwareUserSpecifications = new Dictionary(); //key: sysid+firmwareId; value: absolute path public string FFMpegPath = "%exe%/dll/ffmpeg.exe"; diff --git a/BizHawk.MultiClient/CoreFileProvider.cs b/BizHawk.MultiClient/CoreFileProvider.cs new file mode 100644 index 0000000000..43536dc876 --- /dev/null +++ b/BizHawk.MultiClient/CoreFileProvider.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using System.Collections.Generic; + +namespace BizHawk.MultiClient +{ + class CoreFileProvider : ICoreFileProvider + { + public string SubfileDirectory; + public FirmwareManager FirmwareManager; + + public Stream OpenFirmware(string sysId, string key) + { + var fn = PathFirmware(sysId, key); + return new FileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + public string PathFirmware(string sysId, string key) + { + return FirmwareManager.Request(sysId, key); + } + + public string PathSubfile(string fname) + { + return Path.Combine(Path.GetDirectoryName(SubfileDirectory), fname); + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/FirmwareManager.cs b/BizHawk.MultiClient/FirmwareManager.cs new file mode 100644 index 0000000000..e7a2e4f111 --- /dev/null +++ b/BizHawk.MultiClient/FirmwareManager.cs @@ -0,0 +1,185 @@ +using System; +using System.Linq; +using System.IO; +using System.Collections.Generic; + +//IDEA: put filesizes in DB too. then scans can go real quick by only scanning filesizes that match (and then scanning filesizes that dont match, in case of an emergency) +//this would be adviseable if we end up with a very large firmware file + +namespace BizHawk.MultiClient +{ + public class FirmwareManager + { + //represents a file found on disk in the user's firmware directory matching a file in our database + class RealFirmwareFile + { + public FileInfo fi; + public string hash; + } + + public class ResolutionInfo + { + public bool UserSpecified; + public bool Missing; + public bool KnownMismatching; + public FirmwareDatabase.FirmwareFile KnownFirmwareFile; + public string FilePath; + public string Hash; + } + + Dictionary ResolutionDictionary = new Dictionary(); + + + public ResolutionInfo Resolve(string sysId, string firmwareId) + { + return Resolve(FirmwareDatabase.LookupFirmwareRecord(sysId, firmwareId)); + } + + public ResolutionInfo Resolve(FirmwareDatabase.FirmwareRecord record) + { + bool first = true; + + RETRY: + + ResolutionInfo resolved = null; + ResolutionDictionary.TryGetValue(record, out resolved); + + //couldnt find it! do a scan and resolve to try harder + if (resolved == null && first) + { + DoScanAndResolve(); + first = false; + goto RETRY; + } + + return resolved; + } + + //Requests the spcified firmware. tries really hard to scan and resolve as necessary + public string Request(string sysId, string firmwareId) + { + var resolved = Resolve(sysId, firmwareId); + if (resolved == null) return null; + return resolved.FilePath; + } + + class RealFirmwareReader + { + byte[] buffer = new byte[0]; + public RealFirmwareFile Read(FileInfo fi) + { + RealFirmwareFile rff = new RealFirmwareFile(); + rff.fi = fi; + long len = fi.Length; + if (len > buffer.Length) buffer = new byte[len]; + using (var fs = fi.OpenRead()) fs.Read(buffer, 0, (int)len); + rff.hash = Util.Hash_SHA1(buffer, 0, (int)len); + dict[rff.hash] = rff; + files.Add(rff); + return rff; + } + public Dictionary dict = new Dictionary(); + public List files = new List(); + } + + public void DoScanAndResolve() + { + RealFirmwareReader reader = new RealFirmwareReader(); + + //build a list of files under the global firmwares path, and build a hash for each of them while we're at it + var todo = new Queue(new[] { new DirectoryInfo(Global.Config.FirmwaresPath) }); + + while (todo.Count != 0) + { + var di = todo.Dequeue(); + + //we're going to allow recursing into subdirectories, now. its been verified to work OK + foreach (var disub in di.GetDirectories()) todo.Enqueue(disub); + + foreach (var fi in di.GetFiles()) + { + reader.Read(fi); + } + } + + //now, for each firmware record, try to resolve it + foreach (var fr in FirmwareDatabase.FirmwareRecords) + { + //clear previous resolution results + ResolutionDictionary.Remove(fr); + + //get all options for this firmware (in order) + var options = + from fo in FirmwareDatabase.FirmwareOptions + where fo.systemId == fr.systemId && fo.firmwareId == fr.firmwareId + select fo; + + //try each option + foreach (var fo in options) + { + var hash = fo.hash; + //did we find this firmware? + if (reader.dict.ContainsKey(hash)) + { + //rad! then we can use it + var ri = new ResolutionInfo(); + ri.FilePath = reader.dict[hash].fi.FullName; + ri.KnownFirmwareFile = FirmwareDatabase.FirmwareFilesByHash[hash]; + ri.Hash = hash; + ResolutionDictionary[fr] = ri; + goto DONE_FIRMWARE; + } + } + + DONE_FIRMWARE: ; + + } + + //apply user overrides + foreach (var fr in FirmwareDatabase.FirmwareRecords) + { + string userSpec = null; + + //do we have a user specification for this firmware record? + if (Global.Config.FirmwareUserSpecifications.TryGetValue(fr.ConfigKey, out userSpec)) + { + //flag it as user specified + var ri = ResolutionDictionary[fr]; + ri.UserSpecified = true; + ri.KnownFirmwareFile = null; + ri.FilePath = userSpec; + ri.Hash = null; + + //check whether it exists + var fi = new FileInfo(userSpec); + if (!fi.Exists) + { + ri.Missing = true; + continue; + } + + //compute its hash + var rff = reader.Read(fi); + ri.Hash = rff.hash; + + //check whether it was a known file anyway, and go ahead and bind to the known file, as a perk (the firmwares config doesnt really use this information right now) + FirmwareDatabase.FirmwareFile ff = null; + if(FirmwareDatabase.FirmwareFilesByHash.TryGetValue(rff.hash,out ff)) + { + ri.KnownFirmwareFile = ff; + + //if the known firmware file is for a different firmware, flag it so we can show a warning + var option = + (from fo in FirmwareDatabase.FirmwareOptions + where fo.hash == rff.hash && fo.ConfigKey != fr.ConfigKey + select fr).FirstOrDefault(); + if (option != null) + ri.KnownMismatching = true; + } + } + } + } + + } + +} \ No newline at end of file diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index f1ef3ef3b6..7431dbd6fe 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -74,6 +74,8 @@ namespace BizHawk.MultiClient private readonly Throttle throttle; private bool unthrottled; + public FirmwareManager FirmwareManager = new FirmwareManager(); + //For handling automatic pausing when entering the menu private bool wasPaused; private bool didMenuPause; @@ -83,52 +85,52 @@ namespace BizHawk.MultiClient //tool dialogs - private RamWatch _ramwatch = null; - private RamSearch _ramsearch = null; - private HexEditor _hexeditor = null; - private TraceLogger _tracelogger = null; - private SNESGraphicsDebugger _snesgraphicsdebugger = null; - private NESNameTableViewer _nesnametableview = null; - private NESPPU _nesppu = null; - private NESDebugger _nesdebugger = null; - private GBtools.GBGPUView _gbgpuview = null; - private GBAtools.GBAGPUView _gbagpuview = null; - private PCEBGViewer _pcebgviewer = null; - private Cheats _cheats = null; - private ToolBox _toolbox = null; - private TI83KeyPad _ti83pad = null; - private TAStudio _tastudio = null; - private VirtualPadForm _vpad = null; - private NESGameGenie _ngg = null; - private SNESGameGenie _sgg = null; - private GBGameGenie _gbgg = null; - private GenGameGenie _gengg = null; - private NESSoundConfig _nessound = null; + private RamWatch _ramwatch = null; + private RamSearch _ramsearch = null; + private HexEditor _hexeditor = null; + private TraceLogger _tracelogger = null; + private SNESGraphicsDebugger _snesgraphicsdebugger = null; + private NESNameTableViewer _nesnametableview = null; + private NESPPU _nesppu = null; + private NESDebugger _nesdebugger = null; + private GBtools.GBGPUView _gbgpuview = null; + private GBAtools.GBAGPUView _gbagpuview = null; + private PCEBGViewer _pcebgviewer = null; + private Cheats _cheats = null; + private ToolBox _toolbox = null; + private TI83KeyPad _ti83pad = null; + private TAStudio _tastudio = null; + private VirtualPadForm _vpad = null; + private NESGameGenie _ngg = null; + private SNESGameGenie _sgg = null; + private GBGameGenie _gbgg = null; + private GenGameGenie _gengg = null; + private NESSoundConfig _nessound = null; - //TODO: this is a lazy way to refactor things, but works for now. The point is to not have these objects created until needed, without refactoring a lot of code - public RamWatch RamWatch1 { get { if (_ramwatch == null) _ramwatch = new RamWatch(); return _ramwatch; } set { _ramwatch = value; } } - public RamSearch RamSearch1 { get { if (_ramsearch == null) _ramsearch = new RamSearch(); return _ramsearch; } set { _ramsearch = value; } } - public HexEditor HexEditor1 { get { if (_hexeditor == null) _hexeditor = new HexEditor(); return _hexeditor; } set { _hexeditor = value; } } - public TraceLogger TraceLogger1 { get { if (_tracelogger == null) _tracelogger = new TraceLogger(); return _tracelogger; } set { _tracelogger = value; } } + //TODO: this is a lazy way to refactor things, but works for now. The point is to not have these objects created until needed, without refactoring a lot of code + public RamWatch RamWatch1 { get { if (_ramwatch == null) _ramwatch = new RamWatch(); return _ramwatch; } set { _ramwatch = value; } } + public RamSearch RamSearch1 { get { if (_ramsearch == null) _ramsearch = new RamSearch(); return _ramsearch; } set { _ramsearch = value; } } + public HexEditor HexEditor1 { get { if (_hexeditor == null) _hexeditor = new HexEditor(); return _hexeditor; } set { _hexeditor = value; } } + public TraceLogger TraceLogger1 { get { if (_tracelogger == null) _tracelogger = new TraceLogger(); return _tracelogger; } set { _tracelogger = value; } } public SNESGraphicsDebugger SNESGraphicsDebugger1 { get { if (_snesgraphicsdebugger == null) _snesgraphicsdebugger = new SNESGraphicsDebugger(); return _snesgraphicsdebugger; } set { _snesgraphicsdebugger = value; } } - public NESNameTableViewer NESNameTableViewer1 { get { if (_nesnametableview == null) _nesnametableview = new NESNameTableViewer(); return _nesnametableview; } set { _nesnametableview = value; } } - public NESPPU NESPPU1 { get { if (_nesppu == null) _nesppu = new NESPPU(); return _nesppu; } set { _nesppu = value; } } + public NESNameTableViewer NESNameTableViewer1 { get { if (_nesnametableview == null) _nesnametableview = new NESNameTableViewer(); return _nesnametableview; } set { _nesnametableview = value; } } + public NESPPU NESPPU1 { get { if (_nesppu == null) _nesppu = new NESPPU(); return _nesppu; } set { _nesppu = value; } } public NESDebugger NESDebug1 { get { if (_nesdebugger == null) _nesdebugger = new NESDebugger(); return _nesdebugger; } set { _nesdebugger = value; } } - public GBtools.GBGPUView GBGPUView1 { get { if (_gbgpuview == null) _gbgpuview = new GBtools.GBGPUView(); return _gbgpuview; } set { _gbgpuview = value; } } - public GBAtools.GBAGPUView GBAGPUView1 { get { if (_gbagpuview == null) _gbagpuview = new GBAtools.GBAGPUView(); return _gbagpuview; } set { _gbagpuview = value; } } - public PCEBGViewer PCEBGViewer1 { get { if (_pcebgviewer == null) _pcebgviewer = new PCEBGViewer(); return _pcebgviewer; } set { _pcebgviewer = value; } } - public Cheats Cheats1 { get { if (_cheats == null) _cheats = new Cheats(); return _cheats; } set { _cheats = value; } } - public ToolBox ToolBox1 { get { if (_toolbox == null) _toolbox = new ToolBox(); return _toolbox; } set { _toolbox = value; } } - public TI83KeyPad TI83KeyPad1 { get { if (_ti83pad == null) _ti83pad = new TI83KeyPad(); return _ti83pad; } set { _ti83pad = value; } } + public GBtools.GBGPUView GBGPUView1 { get { if (_gbgpuview == null) _gbgpuview = new GBtools.GBGPUView(); return _gbgpuview; } set { _gbgpuview = value; } } + public GBAtools.GBAGPUView GBAGPUView1 { get { if (_gbagpuview == null) _gbagpuview = new GBAtools.GBAGPUView(); return _gbagpuview; } set { _gbagpuview = value; } } + public PCEBGViewer PCEBGViewer1 { get { if (_pcebgviewer == null) _pcebgviewer = new PCEBGViewer(); return _pcebgviewer; } set { _pcebgviewer = value; } } + public Cheats Cheats1 { get { if (_cheats == null) _cheats = new Cheats(); return _cheats; } set { _cheats = value; } } + public ToolBox ToolBox1 { get { if (_toolbox == null) _toolbox = new ToolBox(); return _toolbox; } set { _toolbox = value; } } + public TI83KeyPad TI83KeyPad1 { get { if (_ti83pad == null) _ti83pad = new TI83KeyPad(); return _ti83pad; } set { _ti83pad = value; } } public TAStudio TAStudio1 { get { if (_tastudio == null) _tastudio = new TAStudio(); return _tastudio; } set { _tastudio = value; } } public VirtualPadForm VirtualPadForm1 { get { if (_vpad == null) _vpad = new VirtualPadForm(); return _vpad; } set { _vpad = value; } } public NESGameGenie NESgg { get { if (_ngg == null) _ngg = new NESGameGenie(); return _ngg; } set { _ngg = value; } } - public SNESGameGenie SNESgg { get { if (_sgg == null) _sgg = new SNESGameGenie(); return _sgg; } set { _sgg = value; } } + public SNESGameGenie SNESgg { get { if (_sgg == null) _sgg = new SNESGameGenie(); return _sgg; } set { _sgg = value; } } public GBGameGenie GBgg { get { if (_gbgg == null) _gbgg = new GBGameGenie(); return _gbgg; } set { _gbgg = value; } } public GenGameGenie Gengg { get { if (_gengg == null) _gengg = new GenGameGenie(); return _gengg; } set { _gengg = value; } } public NESSoundConfig NesSound { get { if (_nessound == null) _nessound = new NESSoundConfig(); return _nessound; } set { _nessound = value; } } #if WINDOWS - private LuaConsole _luaconsole = null; + private LuaConsole _luaconsole = null; public LuaConsole LuaConsole1 { get { if (_luaconsole == null) _luaconsole = new LuaConsole(); return _luaconsole; } set { _luaconsole = value; } } #endif @@ -435,8 +437,13 @@ namespace BizHawk.MultiClient SNES_prepared[profile] = exePath; } + public void SyncCoreCommInputSignals(CoreComm target) { + var cfp = new CoreFileProvider(); + target.CoreFileProvider = cfp; + cfp.FirmwareManager = FirmwareManager; + target.NES_BackdropColor = Global.Config.NESBackgroundColor; target.NES_UnlimitedSprites = Global.Config.NESAllowMoreThanEightSprites; target.NES_ShowBG = Global.Config.NESDispBackground; @@ -1087,7 +1094,7 @@ namespace BizHawk.MultiClient { case "SAT": { - string biosPath = PathManager.StandardFirmwareName(Global.Config.FilenameSaturnBios); + string biosPath = this.FirmwareManager.Request("SAT", "J"); if (!File.Exists(biosPath)) { MessageBox.Show("Saturn BIOS not found. Please check firmware configurations."); @@ -1115,7 +1122,7 @@ namespace BizHawk.MultiClient case "PCE": case "PCECD": { - string biosPath = PathManager.StandardFirmwareName(Global.Config.FilenamePCEBios); //PathManager.MakeAbsolutePath(Global.Config.PathPCEBios, "PCE"); + string biosPath = this.FirmwareManager.Request("PCECD", "Bios"); if (File.Exists(biosPath) == false) { MessageBox.Show("PCE-CD System Card not found. Please check the BIOS path in Config->Paths->PC Engine."); @@ -1207,13 +1214,7 @@ namespace BizHawk.MultiClient game.System = "SNES"; nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile); - //this isnt completely correct. might need to deal with the archive somehow. - //once done, code should be factored out to be useful in other platforms as well - //BUT!!! right now bsnes needs to open the file itself. lame. - //nextComm.AcquireSubfile = (subpath) => - // File.OpenRead(Path.Combine(Path.GetDirectoryName(path),subpath)); - nextComm.AcquireSubfilePath = (subpath) => - Path.Combine(Path.GetDirectoryName(path),subpath); + ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path); var snes = new LibsnesCore(nextComm); nextEmulator = snes; @@ -1257,7 +1258,8 @@ namespace BizHawk.MultiClient break; case "NES": { - string biosPath = PathManager.StandardFirmwareName(Global.Config.FilenameFDSBios); + //TODO - move into nes core + string biosPath = nextComm.CoreFileProvider.PathFirmware("NES","Bios_FDS"); byte[] bios = null; if (File.Exists(biosPath)) { @@ -1319,8 +1321,7 @@ namespace BizHawk.MultiClient } else { - // todo: get these bioses into a gamedb?? then we could demand different filenames for different regions? - string sgbromPath = PathManager.StandardFirmwareName("sgb.sfc"); //Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathSNESFirmwares, "SNES"), "sgb.sfc"); + string sgbromPath = this.FirmwareManager.Request("SNES","Rom_SGB"); byte[] sgbrom = null; try { @@ -1356,7 +1357,7 @@ namespace BizHawk.MultiClient //} break; case "Coleco": - string colbiosPath = PathManager.StandardFirmwareName(Global.Config.FilenameCOLBios); + string colbiosPath = this.FirmwareManager.Request("Coleco", "Bios"); FileInfo colfile = new FileInfo(colbiosPath); if (!colfile.Exists) { @@ -1372,11 +1373,11 @@ namespace BizHawk.MultiClient case "INTV": { Intellivision intv = new Intellivision(nextComm, game, rom.RomData); - string eromPath = PathManager.StandardFirmwareName(Global.Config.FilenameINTVEROM); + string eromPath = this.FirmwareManager.Request("INTV", "EROM"); if (!File.Exists(eromPath)) throw new InvalidOperationException("Specified EROM path does not exist:\n\n" + eromPath); intv.LoadExecutiveRom(eromPath); - string gromPath = PathManager.StandardFirmwareName(Global.Config.FilenameINTVGROM); + string gromPath = this.FirmwareManager.Request("INTV", "GROM"); if (!File.Exists(gromPath)) throw new InvalidOperationException("Specified GROM path does not exist:\n\n" + gromPath); intv.LoadGraphicsRom(gromPath); @@ -1384,9 +1385,9 @@ namespace BizHawk.MultiClient } break; case "A78": - string ntsc_biospath = PathManager.StandardFirmwareName(Global.Config.FilenameA78NTSCBios); - string pal_biospath = PathManager.StandardFirmwareName(Global.Config.FilenameA78PALBios); - string hsbiospath = PathManager.StandardFirmwareName(Global.Config.FilenameA78HSCBios); + string ntsc_biospath = this.FirmwareManager.Request("A78", "Bios_NTSC"); + string pal_biospath = this.FirmwareManager.Request("A78", "Bios_PAL"); + string hsbiospath = this.FirmwareManager.Request("A78", "Bios_HSC"); FileInfo ntscfile = new FileInfo(ntsc_biospath); FileInfo palfile = new FileInfo(pal_biospath); @@ -1430,14 +1431,14 @@ namespace BizHawk.MultiClient nextEmulator = a78; break; case "C64": - C64 c64 = new C64(nextComm, game, rom.RomData, rom.Extension); - c64.HardReset(); - nextEmulator = c64; + //C64 c64 = new C64(nextComm, game, rom.RomData, rom.Extension); + //c64.HardReset(); + //nextEmulator = c64; break; case "GBA": if (INTERIM) { - string gbabiospath = PathManager.StandardFirmwareName(Global.Config.FilenameGBABIOS); + string gbabiospath = FirmwareManager.Request("GBA", "Bios"); byte[] gbabios = null; if (File.Exists(gbabiospath)) @@ -2399,6 +2400,7 @@ namespace BizHawk.MultiClient Global.Config.SaveStateType == Config.SaveStateTypeE.Text || (Global.Config.SaveStateType == Config.SaveStateTypeE.Default && !Global.Emulator.BinarySaveStatesPreferred)) { + //DateTime start = DateTime.UtcNow; var writer = new StreamWriter(filename); Global.Emulator.SaveStateText(writer); HandleMovieSaveState(writer); @@ -2408,10 +2410,13 @@ namespace BizHawk.MultiClient Global.Emulator.VideoProvider.GetVideoBuffer().SaveAsHex(writer); } writer.Close(); + //DateTime end = DateTime.UtcNow; + //Console.WriteLine("n64 savestate BINARY time: {0}", (end - start).TotalMilliseconds); } else { // binary savestate + //DateTime start = DateTime.UtcNow; var writer = new BinaryWriter(new FileStream(filename, FileMode.Create)); Global.Emulator.SaveStateBinary(writer); if (Global.Config.SaveScreenshotWithStates) @@ -2422,6 +2427,8 @@ namespace BizHawk.MultiClient writer.Write(buff); } writer.Close(); + //DateTime end = DateTime.UtcNow; + //Console.WriteLine("n64 savestate TEXT time: {0}", (end - start).TotalMilliseconds); } Global.OSD.AddMessage("Saved state: " + name); diff --git a/BizHawk.MultiClient/config/FirmwaresConfig.Designer.cs b/BizHawk.MultiClient/config/FirmwaresConfig.Designer.cs index 8782602d02..59c6ceaf4b 100644 --- a/BizHawk.MultiClient/config/FirmwaresConfig.Designer.cs +++ b/BizHawk.MultiClient/config/FirmwaresConfig.Designer.cs @@ -34,8 +34,6 @@ this.lvFirmwares = new System.Windows.Forms.ListView(); this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.panel1 = new System.Windows.Forms.Panel(); this.toolStrip1 = new System.Windows.Forms.ToolStrip(); @@ -44,9 +42,18 @@ this.tbbScan = new System.Windows.Forms.ToolStripButton(); this.tbbOrganize = new System.Windows.Forms.ToolStripButton(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.lvFirmwaresContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); + this.tsmiClearCustomization = new System.Windows.Forms.ToolStripMenuItem(); + this.tsmiSetCustomization = new System.Windows.Forms.ToolStripMenuItem(); this.panel1.SuspendLayout(); this.toolStrip1.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); + this.lvFirmwaresContextMenuStrip.SuspendLayout(); this.SuspendLayout(); // // imageList1 @@ -60,9 +67,12 @@ this.lvFirmwares.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader5, this.columnHeader1, + this.columnHeader6, + this.columnHeader4, this.columnHeader2, this.columnHeader3, - this.columnHeader4}); + this.columnHeader7}); + this.lvFirmwares.ContextMenuStrip = this.lvFirmwaresContextMenuStrip; this.lvFirmwares.Dock = System.Windows.Forms.DockStyle.Fill; this.lvFirmwares.FullRowSelect = true; this.lvFirmwares.GridLines = true; @@ -75,6 +85,7 @@ this.lvFirmwares.View = System.Windows.Forms.View.Details; this.lvFirmwares.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lvFirmwares_ColumnClick); this.lvFirmwares.KeyDown += new System.Windows.Forms.KeyEventHandler(this.lvFirmwares_KeyDown); + this.lvFirmwares.MouseClick += new System.Windows.Forms.MouseEventHandler(this.lvFirmwares_MouseClick); // // columnHeader5 // @@ -85,20 +96,10 @@ // this.columnHeader1.Text = "System"; // - // columnHeader2 - // - this.columnHeader2.Text = "Hash"; - this.columnHeader2.Width = 475; - // - // columnHeader3 - // - this.columnHeader3.Text = "Normal Filename"; - this.columnHeader3.Width = 93; - // // columnHeader4 // this.columnHeader4.Text = "Description"; - this.columnHeader4.Width = 220; + this.columnHeader4.Width = 165; // // panel1 // @@ -177,6 +178,47 @@ this.tableLayoutPanel1.Size = new System.Drawing.Size(779, 478); this.tableLayoutPanel1.TabIndex = 25; // + // columnHeader6 + // + this.columnHeader6.Text = "Id"; + // + // columnHeader2 + // + this.columnHeader2.Text = "Resolved With"; + this.columnHeader2.Width = 116; + // + // columnHeader7 + // + this.columnHeader7.Text = "Hash"; + this.columnHeader7.Width = 340; + // + // columnHeader3 + // + this.columnHeader3.Text = "Location"; + this.columnHeader3.Width = 252; + // + // lvFirmwaresContextMenuStrip + // + this.lvFirmwaresContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsmiSetCustomization, + this.tsmiClearCustomization}); + this.lvFirmwaresContextMenuStrip.Name = "lvFirmwaresContextMenuStrip"; + this.lvFirmwaresContextMenuStrip.Size = new System.Drawing.Size(170, 48); + // + // tsmiClearCustomization + // + this.tsmiClearCustomization.Name = "tsmiClearCustomization"; + this.tsmiClearCustomization.Size = new System.Drawing.Size(169, 22); + this.tsmiClearCustomization.Text = "&Clear Customization"; + this.tsmiClearCustomization.Click += new System.EventHandler(this.tsmiClearCustomization_Click); + // + // tsmiSetCustomization + // + this.tsmiSetCustomization.Name = "tsmiSetCustomization"; + this.tsmiSetCustomization.Size = new System.Drawing.Size(169, 22); + this.tsmiSetCustomization.Text = "&Set Customization"; + this.tsmiSetCustomization.Click += new System.EventHandler(this.tsmiSetCustomization_Click); + // // FirmwaresConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -193,6 +235,7 @@ this.toolStrip1.ResumeLayout(false); this.toolStrip1.PerformLayout(); this.tableLayoutPanel1.ResumeLayout(false); + this.lvFirmwaresContextMenuStrip.ResumeLayout(false); this.ResumeLayout(false); } @@ -203,8 +246,6 @@ private System.Windows.Forms.ListView lvFirmwares; private System.Windows.Forms.ColumnHeader columnHeader5; private System.Windows.Forms.ColumnHeader columnHeader1; - private System.Windows.Forms.ColumnHeader columnHeader2; - private System.Windows.Forms.ColumnHeader columnHeader3; private System.Windows.Forms.ColumnHeader columnHeader4; private System.Windows.Forms.Panel panel1; private System.Windows.Forms.ToolStrip toolStrip1; @@ -213,5 +254,13 @@ private System.Windows.Forms.ToolStripButton tbbScan; private System.Windows.Forms.ToolStripButton tbbOrganize; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader7; + private System.Windows.Forms.ContextMenuStrip lvFirmwaresContextMenuStrip; + private System.Windows.Forms.ToolStripMenuItem tsmiSetCustomization; + private System.Windows.Forms.ToolStripMenuItem tsmiClearCustomization; } } \ No newline at end of file diff --git a/BizHawk.MultiClient/config/FirmwaresConfig.cs b/BizHawk.MultiClient/config/FirmwaresConfig.cs index 3222e33c74..4465017119 100644 --- a/BizHawk.MultiClient/config/FirmwaresConfig.cs +++ b/BizHawk.MultiClient/config/FirmwaresConfig.cs @@ -19,41 +19,13 @@ using System.Windows.Forms; //IDEA: show current path in tooltip +//TODO - display some kind if [!] if you have a user-specified file which is known but defined as incompatible by the firmware DB + namespace BizHawk.MultiClient { public partial class FirmwaresConfig : Form { - //master firmware DB.. for now. might need to go somewhere else later - FDR[] dbItems = new[] { - new FDR("E4E41472C454F928E53EB10E0509BF7D1146ECC1", "NES", "disksys.rom", "FDS Bios", "FilenameFDSBios"), - new FDR("973E10840DB683CF3FAF61BD443090786B3A9F04", "SNES", "sgb.sfc", "Super GameBoy Rom"), - new FDR("A002F4EFBA42775A31185D443F3ED1790B0E949A", "SNES", "cx4.rom", "CX4 Rom"), - new FDR("188D471FEFEA71EB53F0EE7064697FF0971B1014", "SNES", "dsp1.rom", "DSP1 Rom"), - new FDR("78B724811F5F18D8C67669D9390397EB1A47A5E2", "SNES", "dsp1b.rom", "DSP1b Rom"), - new FDR("198C4B1C3BFC6D69E734C5957AF3DBFA26238DFB", "SNES", "dsp2.rom", "DSP2 Rom"), - new FDR("558DA7CB3BD3876A6CA693661FFC6C110E948CF9", "SNES", "dsp3.rom", "DSP3 Rom"), - new FDR("AF6478AECB6F1B67177E79C82CA04C56250A8C72", "SNES", "dsp4.rom", "DSP4 Rom"), - new FDR("6472828403DE3589433A906E2C3F3D274C0FF008", "SNES", "st010.rom", "ST010 Rom"), - new FDR("FECBAE2CEC76C710422486BAA186FFA7CA1CF925", "SNES", "st011.rom", "ST011 Rom"), - new FDR("91383B92745CC7CC4F15409AC5BC2C2F699A43F1", "SNES", "st018.rom", "ST018 Rom"), - new FDR("79F5FF55DD10187C7FD7B8DAAB0B3FFBD1F56A2C", "PCECD", "pcecd-3.0-J.pce", "Super CD-ROM System v3.0 (J)","FilenamePCEBios"), - new FDR("2B8CB4F87580683EB4D760E4ED210813D667F0A2", "SAT", "saturn-1.00-NTSC.bin", "Sega Saturn Bios v1.00 (NTSC)"), - new FDR("FAA8EA183A6D7BBE5D4E03BB1332519800D3FBC3", "SAT", "saturn-1.00-PAL.bin", "Sega Saturn Bios v1.00 (PAL)"), - new FDR("DF94C5B4D47EB3CC404D88B33A8FDA237EAF4720", "SAT", "saturn-1.01-J.bin", "Sega Saturn Bios v1.01 (J)", "FilenameSaturnBios"), - new FDR("D9D134BB6B36907C615A594CC7688F7BFCEF5B43", "A78", "7800NTSCBIOS.bin", "Atari 7800 NTSC Bios", "FilenameA78NTSCBios"), - new FDR("5A140136A16D1D83E4FF32A19409CA376A8DF874", "A78", "7800PALBIOS.bin", "Atari 7800 PAL Bios", "FilenameA78PALBios"), - new FDR("A3AF676991391A6DD716C79022D4947206B78164", "A78", "7800highscore.bin", "Atari 7800 Highscore Bios", "FilenameA78HSCBios"), - new FDR("45BEDC4CBDEAC66C7DF59E9E599195C778D86A92", "Coleco", "ColecoBios.bin", "Colecovision Bios", "FilenameCOLBios"), - new FDR("300C20DF6731A33952DED8C436F7F186D25D3492", "GBA", "gbabios.rom", "GBA Bios", "FilenameGBABIOS"), - new FDR("EF66DAD3E7B2B6A86F326765E7DFD7D1A308AD8F", "TI83", "ti83_1.rom", "TI-83 Rom"), - new FDR("5A65B922B562CB1F57DAB51B73151283F0E20C7A", "INTV", "erom.bin", "Intellivision Executive Rom", "FilenameINTVEROM"), - new FDR("F9608BB4AD1CFE3640D02844C7AD8E0BCD974917", "INTV", "grom.bin", "Intellivision Graphics Rom", "FilenameINTVGROM"), - new FDR("1D503E56DF85A62FEE696E7618DC5B4E781DF1BB", "C64", "c64-kernal.bin", "C64 Kernal Rom"), - new FDR("79015323128650C742A3694C9429AA91F355905E", "C64", "c64-basic.bin", "C64 Basic Rom"), - new FDR("ADC7C31E18C7C7413D54802EF2F4193DA14711AA", "C64", "c64-chargen.bin", "C64 Chargen Rom") - }; - - //friendly names than the system Ids + //friendlier names than the system Ids static readonly Dictionary systemGroupNames = new Dictionary() { { "NES", "NES" }, @@ -68,33 +40,13 @@ namespace BizHawk.MultiClient { "C64", "C64" }, }; - class FDR - { - public FDR(string hash, string systemId, string recommendedName, string descr, string configMember = null) - { - this.hash = hash; - this.systemId = systemId; - this.recommendedName = recommendedName; - this.descr = descr; - this.configMember = configMember; - } - public string hash; - public string systemId; - public string recommendedName; - public string descr; - public string configMember; - //sort of sloppy to store this here.. - public FileInfo userPath; - } - private const int idUnsure = 0; private const int idMissing = 1; private const int idOk = 2; - Font fixedFont; - + Font fixedFont, boldFont, boldFixedFont; class ListViewSorter : IComparer { @@ -110,10 +62,11 @@ namespace BizHawk.MultiClient { var lva = (ListViewItem)a; var lvb = (ListViewItem)b; - return sign*string.Compare(lva.SubItems[column].Text, lvb.SubItems[column].Text); + return sign * string.Compare(lva.SubItems[column].Text, lvb.SubItems[column].Text); } } + string currSelectorDir; ListViewSorter listviewSorter; public FirmwaresConfig() @@ -124,39 +77,45 @@ namespace BizHawk.MultiClient imageList1.Images.AddRange(new[] { MultiClient.Properties.Resources.RetroQuestion, MultiClient.Properties.Resources.ExclamationRed, MultiClient.Properties.Resources.GreenCheck }); listviewSorter = new ListViewSorter(this, -1); + + currSelectorDir = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath); } - + private void FirmwaresConfig_Load(object sender, EventArgs e) { //we'll use this font for displaying the hash, so they dont look all jagged in a long list fixedFont = new Font(new FontFamily("Courier New"), 8); + boldFont = new Font(lvFirmwares.Font, FontStyle.Bold); + boldFixedFont = new Font(fixedFont, FontStyle.Bold); //populate listview from firmware DB var groups = new Dictionary(); - foreach (var fdr in dbItems) + foreach (var fr in FirmwareDatabase.FirmwareRecords) { var lvi = new ListViewItem(); - lvi.Tag = fdr; + lvi.Tag = fr; lvi.UseItemStyleForSubItems = false; lvi.ImageIndex = idUnsure; - lvi.SubItems.Add(fdr.systemId); - lvi.SubItems.Add("sha1:" + fdr.hash); - lvi.SubItems.Add(fdr.recommendedName); - lvi.SubItems.Add(fdr.descr); - lvi.SubItems[2].Font = fixedFont; + lvi.SubItems.Add(fr.systemId); + lvi.SubItems.Add(fr.firmwareId); + lvi.SubItems.Add(fr.descr); + lvi.SubItems.Add(""); //resolved with + lvi.SubItems.Add(""); //location + lvi.SubItems.Add(""); //hash + lvi.SubItems[6].Font = fixedFont; //would be used for hash lvFirmwares.Items.Add(lvi); //build the groups in the listview as we go: - if (!groups.ContainsKey(fdr.systemId)) + if (!groups.ContainsKey(fr.systemId)) { - lvFirmwares.Groups.Add(fdr.systemId, systemGroupNames[fdr.systemId]); + lvFirmwares.Groups.Add(fr.systemId, systemGroupNames[fr.systemId]); var lvg = lvFirmwares.Groups[lvFirmwares.Groups.Count - 1]; - groups[fdr.systemId] = lvg; + groups[fr.systemId] = lvg; } - lvi.Group = groups[fdr.systemId]; + lvi.Group = groups[fr.systemId]; } - //now that we have some items in the listview, we can size the hash column to something sensible. why not the others, too? + //now that we have some items in the listview, we can size some columns to sensible widths lvFirmwares.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent); lvFirmwares.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent); lvFirmwares.AutoResizeColumn(2, ColumnHeaderAutoResizeStyle.ColumnContent); @@ -167,6 +126,8 @@ namespace BizHawk.MultiClient private void FirmwaresConfig_FormClosed(object sender, FormClosedEventArgs e) { fixedFont.Dispose(); + boldFont.Dispose(); + boldFixedFont.Dispose(); } private void tbbGroup_Click(object sender, EventArgs e) @@ -194,107 +155,103 @@ namespace BizHawk.MultiClient DoScan(); } - //represents a file found on disk in the user's firmware directory. - class RealFirmwareFile - { - public FileInfo fi; - public string hash; - } + FirmwareManager Manager { get { return Global.MainForm.FirmwareManager; } } private void DoScan() { - //build a list of files under the global firmwares path, and build a hash for each of them while we're at it - var todo = new Queue(new[] { new DirectoryInfo(Global.Config.FirmwaresPath) }); - var files = new List(); - while (todo.Count != 0) - { - var di = todo.Dequeue(); - foreach (var disub in di.GetDirectories()) todo.Enqueue(disub); - byte[] buffer = new byte[0]; - foreach (var fi in di.GetFiles()) - { - var rff = new RealFirmwareFile(); - rff.fi = fi; - long len = fi.Length; - if (len > buffer.Length) - buffer = new byte[len]; - using (var fs = fi.OpenRead()) fs.Read(buffer, 0, (int)len); - rff.hash = Util.Hash_SHA1(buffer, 0, (int)len); - files.Add(rff); - } - } + lvFirmwares.BeginUpdate(); + Manager.DoScanAndResolve(); - //clean out our runtime state to get ready for a new scan result - foreach (var fdr in dbItems) - fdr.userPath = null; + //for each type of firmware, try resolving and record the result foreach (ListViewItem lvi in lvFirmwares.Items) - lvi.ImageIndex = idUnsure; - - //now, contemplate each file and see if it matches a known firmware (this algorithm is slow) - //if it matches, make a note for later use - foreach (var f in files) { - foreach (var fdr in dbItems) - { - if (fdr.hash == f.hash) - { - foreach (ListViewItem lvi in lvFirmwares.Items) - { - if (lvi.Tag == fdr) - { - lvi.ImageIndex = idOk; - fdr.userPath = f.fi; - } - } - } - } - } + var fr = lvi.Tag as FirmwareDatabase.FirmwareRecord; + var ri = Manager.Resolve(fr); + for(int i=4;i<=6;i++) + lvi.SubItems[i].Text = ""; - //set unfound firmwares to missing icon (theres no good reason for this, but its a reminder that if we thread this later we may want to start it that way, or something like that) - foreach (ListViewItem lvi in lvFirmwares.Items) - if(lvi.ImageIndex == idUnsure) + if (ri == null) + { lvi.ImageIndex = idMissing; + } + else + { + //lazy substring extraction. really should do a better job + var basePath = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath) + Path.DirectorySeparatorChar; + + var path = ri.FilePath.Replace(basePath, ""); - //set entries in the Global.Config class for firmwares that have been bound to emulator cores. - //this system is due to be replaced with something else - foreach (var fdr in dbItems) - { - if(fdr.configMember == null) continue; - if (fdr.userPath == null) continue; + //bolden the item if the user has specified a path for it + bool bolden = ri.UserSpecified; - //ehhh... this wont be working if this file was outside of the configured firmwares directory. - //maybe we should check that: http://stackoverflow.com/questions/5617320/given-full-path-check-if-path-is-subdirectory-of-some-other-path-or-otherwise - string path = Path.GetFileName(fdr.userPath.FullName); + //set columns based on whether it was a known file + if (ri.KnownFirmwareFile == null) + { + lvi.ImageIndex = idUnsure; + lvi.SubItems[4].Text = "-custom-"; + } + else + { + lvi.ImageIndex = idOk; + lvi.SubItems[4].Text = ri.KnownFirmwareFile.descr; + } - typeof(Config).GetField(fdr.configMember).SetValue(Global.Config, path); + //bolden the item if necessary + if (bolden) + { + foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems) lvsi.Font = boldFont; + lvi.SubItems[6].Font = boldFixedFont; + } + else + { + foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems) lvsi.Font = lvFirmwares.Font; + lvi.SubItems[6].Font = fixedFont; + } + + //if the user specified a file but its missing, mark it as such + if(ri.Missing) + lvi.ImageIndex = idMissing; + + //if the user specified a known firmware file but its for some other firmware, it was probably a mistake. mark it as suspicious + if (ri.KnownMismatching) + lvi.ImageIndex = idUnsure; + + lvi.SubItems[5].Text = path; + if (ri.Hash != null) lvi.SubItems[6].Text = "sha1:" + ri.Hash; + else lvi.SubItems[6].Text = ""; + } } + + lvFirmwares.EndUpdate(); } private void tbbOrganize_Click(object sender, EventArgs e) { - if (System.Windows.Forms.MessageBox.Show(this, "This is going to move/rename files under your configured firmwares directory to match our recommended organizational scheme (which is not super great right now). Proceed?", "Firmwares Organization Confirm", MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.Cancel) - return; + if (System.Windows.Forms.MessageBox.Show(this, "This is going to move/rename every automatically-selected firmware file under your configured firmwares directory to match our recommended organizational scheme (which is not super great right now). Proceed?", "Firmwares Organization Confirm", MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.Cancel) + return; - foreach (var fdr in dbItems) + Manager.DoScanAndResolve(); + + foreach (var fr in FirmwareDatabase.FirmwareRecords) { - if (fdr.userPath == null) - continue; + var ri = Manager.Resolve(fr); + if (ri.KnownFirmwareFile == null) continue; + if (ri.UserSpecified) continue; + + string fpTarget = PathManager.StandardFirmwareName(ri.KnownFirmwareFile.recommendedName); + string fpSource = ri.FilePath; - string fpTarget = Path.Combine(Global.Config.FirmwaresPath, fdr.recommendedName); - string fpSource = fdr.userPath.FullName; - try { - File.Move(fpSource, fpTarget); + File.Move(fpSource, fpTarget); } catch { - //sometimes moves fail. especially in newer versions of windows with explorers more fragile than your great-grandma. - //I am embarassed that I know that. + //sometimes moves fail. especially in newer versions of windows with explorers more fragile than your great-grandma. + //I am embarassed that I know that. about windows, not your great-grandma. } } - //to be safe, better do this. we want the db to track the state of the files after theyre moved. DoScan(); } @@ -302,37 +259,52 @@ namespace BizHawk.MultiClient { if (e.KeyCode == Keys.C && e.Control && !e.Alt && !e.Shift) { - ListviewCopy(); + var str = lvFirmwares.CopyItemsAsText(); + if (str.Length > 0) Clipboard.SetDataObject(str); } } - void ListviewCopy() + private void lvFirmwares_MouseClick(object sender, MouseEventArgs e) { - ListView.SelectedIndexCollection indexes = lvFirmwares.SelectedIndices; - if (indexes.Count <= 0) - return; - - StringBuilder sb = new StringBuilder(); - - //walk over each selected item and subitem within it to generate a string from it - foreach (int index in indexes) - { - foreach (ListViewItem.ListViewSubItem item in lvFirmwares.Items[index].SubItems) - { - if (!String.IsNullOrWhiteSpace(item.Text)) - sb.Append(item.Text).Append('\t'); - } - //remove the last tab - sb.Remove(sb.Length - 1, 1); - - sb.Append("\r\n"); - } - - //remove last newline - sb.Length -= 2; - - if (sb.Length > 0) Clipboard.SetDataObject(sb.ToString()); + if (e.Button == System.Windows.Forms.MouseButtons.Right && lvFirmwares.GetItemAt(e.X, e.Y) != null) + lvFirmwaresContextMenuStrip.Show(lvFirmwares, e.Location); } - } + private void tsmiSetCustomization_Click(object sender, EventArgs e) + { + using (var ofd = new OpenFileDialog()) + { + ofd.InitialDirectory = currSelectorDir; + ofd.RestoreDirectory = true; + + if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + //remember the location we selected this firmware from, maybe there are others + currSelectorDir = Path.GetDirectoryName(ofd.FileName); + + //for each selected item, set the user choice (hey, thats the expected semantic + foreach (ListViewItem lvi in lvFirmwares.SelectedItems) + { + var fr = lvi.Tag as FirmwareDatabase.FirmwareRecord; + Global.Config.FirmwareUserSpecifications[fr.ConfigKey] = ofd.FileName; + } + + DoScan(); + } + } + } + + private void tsmiClearCustomization_Click(object sender, EventArgs e) + { + //for each selected item, clear the user choice + foreach (ListViewItem lvi in lvFirmwares.SelectedItems) + { + var fr = lvi.Tag as FirmwareDatabase.FirmwareRecord; + Global.Config.FirmwareUserSpecifications.Remove(fr.ConfigKey); + } + + DoScan(); + } + + } //class FirmwaresConfig } diff --git a/BizHawk.MultiClient/config/FirmwaresConfig.resx b/BizHawk.MultiClient/config/FirmwaresConfig.resx index 989925dacc..cb8e4f87cc 100644 --- a/BizHawk.MultiClient/config/FirmwaresConfig.resx +++ b/BizHawk.MultiClient/config/FirmwaresConfig.resx @@ -120,6 +120,9 @@ 17, 17 + + 313, 17 + 122, 17 @@ -169,4 +172,7 @@ TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + 221, 17 + \ No newline at end of file diff --git a/BizHawk.MultiClient/config/NewControllerConfig.cs b/BizHawk.MultiClient/config/NewControllerConfig.cs index 3e8411e709..0f8273781a 100644 --- a/BizHawk.MultiClient/config/NewControllerConfig.cs +++ b/BizHawk.MultiClient/config/NewControllerConfig.cs @@ -211,7 +211,9 @@ namespace BizHawk.MultiClient.config if (c is ControllerConfigPanel) (c as ControllerConfigPanel).SetAutoTab(value); else if (c is AnalogBindPanel) - ;// TODO + { + // TODO + } else if (c.HasChildren) foreach (Control cc in c.Controls) SetAutoTab(cc, value); diff --git a/BizHawk.MultiClient/config/NewPathConfig.cs b/BizHawk.MultiClient/config/NewPathConfig.cs index dd68e3570b..1628f0e2ac 100644 --- a/BizHawk.MultiClient/config/NewPathConfig.cs +++ b/BizHawk.MultiClient/config/NewPathConfig.cs @@ -104,7 +104,7 @@ namespace BizHawk.MultiClient private void BrowseFolder(TextBox box, string _Name, string System) { - FolderBrowserDialog f = new FolderBrowserDialog + FolderBrowserEx f = new FolderBrowserEx { Description = "Set the directory for " + _Name, SelectedPath = PathManager.MakeAbsolutePath(box.Text, System) diff --git a/BizHawk.MultiClient/config/PathConfig.Designer.cs b/BizHawk.MultiClient/config/PathConfig.Designer.cs index 7fae42dc41..7c67262dfd 100644 --- a/BizHawk.MultiClient/config/PathConfig.Designer.cs +++ b/BizHawk.MultiClient/config/PathConfig.Designer.cs @@ -83,9 +83,6 @@ this.BrowseMovieBackups = new System.Windows.Forms.Button(); this.MovieBackupsDescription = new System.Windows.Forms.Label(); this.tabPageNES = new System.Windows.Forms.TabPage(); - this.label3 = new System.Windows.Forms.Label(); - this.NESBrowseFDSBIOS = new System.Windows.Forms.Button(); - this.FDSBIOSBox = new System.Windows.Forms.TextBox(); this.NESBaseBox = new System.Windows.Forms.TextBox(); this.NESPaletteDescription = new System.Windows.Forms.Label(); this.NESBrowsePalette = new System.Windows.Forms.Button(); @@ -179,9 +176,6 @@ this.GenesisBrowseScreenshots = new System.Windows.Forms.Button(); this.GenesisROMsBox = new System.Windows.Forms.TextBox(); this.tabPagePCE = new System.Windows.Forms.TabPage(); - this.button2 = new System.Windows.Forms.Button(); - this.label2 = new System.Windows.Forms.Label(); - this.PCEBIOSBox = new System.Windows.Forms.TextBox(); this.PCEBaseBox = new System.Windows.Forms.TextBox(); this.PCECheatsDescription = new System.Windows.Forms.Label(); this.PCEBrowseCheats = new System.Windows.Forms.Button(); @@ -223,9 +217,6 @@ this.GBSaveRAMDescription = new System.Windows.Forms.Label(); this.GBSaveRAMBox = new System.Windows.Forms.TextBox(); this.tabPageGBA = new System.Windows.Forms.TabPage(); - this.label5 = new System.Windows.Forms.Label(); - this.button4 = new System.Windows.Forms.Button(); - this.GBABIOSBox = new System.Windows.Forms.TextBox(); this.GBABaseBox = new System.Windows.Forms.TextBox(); this.GBACheatsDescription = new System.Windows.Forms.Label(); this.GBABrowseCheats = new System.Windows.Forms.Button(); @@ -280,15 +271,6 @@ this.Atari2600ROMsDescription = new System.Windows.Forms.Label(); this.Atari2600BrowseROMs = new System.Windows.Forms.Button(); this.tabPageAtari7800 = new System.Windows.Forms.TabPage(); - this.label8 = new System.Windows.Forms.Label(); - this.label7 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.Atari7800BrowseHSCBIOS = new System.Windows.Forms.Button(); - this.Atari7800BrowsePALBIOS = new System.Windows.Forms.Button(); - this.Atari7800BrowseNTSCBIOS = new System.Windows.Forms.Button(); - this.Atari7800HighScoreBIOSBox = new System.Windows.Forms.TextBox(); - this.Atari7800PALBIOSBox = new System.Windows.Forms.TextBox(); - this.Atari7800NTSCBIOSBox = new System.Windows.Forms.TextBox(); this.Atari7800SaveRAMsDescription = new System.Windows.Forms.Label(); this.BrowseAtari7800SaveRAM = new System.Windows.Forms.Button(); this.Atari7800SaveRAMBox = new System.Windows.Forms.TextBox(); @@ -327,9 +309,6 @@ this.INTVSaveRAMDescription = new System.Windows.Forms.Label(); this.INTVSaveRAMBox = new System.Windows.Forms.TextBox(); this.tabPageColeco = new System.Windows.Forms.TabPage(); - this.label4 = new System.Windows.Forms.Label(); - this.button3 = new System.Windows.Forms.Button(); - this.ColecoBIOSBox = new System.Windows.Forms.TextBox(); this.COLBaseBox = new System.Windows.Forms.TextBox(); this.COLCheatsDescription = new System.Windows.Forms.Label(); this.COLBrowseCheats = new System.Windows.Forms.Button(); @@ -404,7 +383,7 @@ this.BaseDescription = new System.Windows.Forms.Label(); this.RecentForROMs = new System.Windows.Forms.CheckBox(); this.SaveButton = new System.Windows.Forms.Button(); - this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); + this.folderBrowserDialog1 = new BizHawk.FolderBrowserEx(); this.button1 = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); @@ -1002,9 +981,6 @@ // // tabPageNES // - this.tabPageNES.Controls.Add(this.label3); - this.tabPageNES.Controls.Add(this.NESBrowseFDSBIOS); - this.tabPageNES.Controls.Add(this.FDSBIOSBox); this.tabPageNES.Controls.Add(this.NESBaseBox); this.tabPageNES.Controls.Add(this.NESPaletteDescription); this.tabPageNES.Controls.Add(this.NESBrowsePalette); @@ -1034,37 +1010,6 @@ this.tabPageNES.Text = "NES"; this.tabPageNES.UseVisualStyleBackColor = true; // - // label3 - // - this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(474, 242); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(56, 13); - this.label3.TabIndex = 29; - this.label3.Text = "FDS BIOS"; - // - // NESBrowseFDSBIOS - // - this.NESBrowseFDSBIOS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.NESBrowseFDSBIOS.Image = ((System.Drawing.Image)(resources.GetObject("NESBrowseFDSBIOS.Image"))); - this.NESBrowseFDSBIOS.Location = new System.Drawing.Point(442, 239); - this.NESBrowseFDSBIOS.Name = "NESBrowseFDSBIOS"; - this.NESBrowseFDSBIOS.Size = new System.Drawing.Size(26, 23); - this.NESBrowseFDSBIOS.TabIndex = 28; - this.NESBrowseFDSBIOS.UseVisualStyleBackColor = true; - this.NESBrowseFDSBIOS.Click += new System.EventHandler(this.NESBrowseFDSBIOS_Click); - // - // FDSBIOSBox - // - this.FDSBIOSBox.AcceptsTab = true; - this.FDSBIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.FDSBIOSBox.Location = new System.Drawing.Point(13, 239); - this.FDSBIOSBox.Name = "FDSBIOSBox"; - this.FDSBIOSBox.Size = new System.Drawing.Size(421, 20); - this.FDSBIOSBox.TabIndex = 27; - // // NESBaseBox // this.NESBaseBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) @@ -2077,9 +2022,6 @@ // // tabPagePCE // - this.tabPagePCE.Controls.Add(this.button2); - this.tabPagePCE.Controls.Add(this.label2); - this.tabPagePCE.Controls.Add(this.PCEBIOSBox); this.tabPagePCE.Controls.Add(this.PCEBaseBox); this.tabPagePCE.Controls.Add(this.PCECheatsDescription); this.tabPagePCE.Controls.Add(this.PCEBrowseCheats); @@ -2105,36 +2047,6 @@ this.tabPagePCE.Text = "PC Engine"; this.tabPagePCE.UseVisualStyleBackColor = true; // - // button2 - // - this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.button2.Image = ((System.Drawing.Image)(resources.GetObject("button2.Image"))); - this.button2.Location = new System.Drawing.Point(442, 209); - this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(26, 23); - this.button2.TabIndex = 91; - this.button2.UseVisualStyleBackColor = true; - this.button2.Click += new System.EventHandler(this.button2_Click); - // - // label2 - // - this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(474, 213); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(32, 13); - this.label2.TabIndex = 90; - this.label2.Text = "BIOS"; - // - // PCEBIOSBox - // - this.PCEBIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.PCEBIOSBox.Location = new System.Drawing.Point(12, 209); - this.PCEBIOSBox.Name = "PCEBIOSBox"; - this.PCEBIOSBox.Size = new System.Drawing.Size(421, 20); - this.PCEBIOSBox.TabIndex = 89; - // // PCEBaseBox // this.PCEBaseBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) @@ -2560,9 +2472,6 @@ // // tabPageGBA // - this.tabPageGBA.Controls.Add(this.label5); - this.tabPageGBA.Controls.Add(this.button4); - this.tabPageGBA.Controls.Add(this.GBABIOSBox); this.tabPageGBA.Controls.Add(this.GBABaseBox); this.tabPageGBA.Controls.Add(this.GBACheatsDescription); this.tabPageGBA.Controls.Add(this.GBABrowseCheats); @@ -2588,36 +2497,6 @@ this.tabPageGBA.Text = "GBA"; this.tabPageGBA.UseVisualStyleBackColor = true; // - // label5 - // - this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(474, 213); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(32, 13); - this.label5.TabIndex = 125; - this.label5.Text = "BIOS"; - // - // button4 - // - this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.button4.Image = ((System.Drawing.Image)(resources.GetObject("button4.Image"))); - this.button4.Location = new System.Drawing.Point(440, 209); - this.button4.Name = "button4"; - this.button4.Size = new System.Drawing.Size(26, 23); - this.button4.TabIndex = 124; - this.button4.UseVisualStyleBackColor = true; - this.button4.Click += new System.EventHandler(this.button4_Click); - // - // GBABIOSBox - // - this.GBABIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.GBABIOSBox.Location = new System.Drawing.Point(13, 209); - this.GBABIOSBox.Name = "GBABIOSBox"; - this.GBABIOSBox.Size = new System.Drawing.Size(421, 20); - this.GBABIOSBox.TabIndex = 123; - // // GBABaseBox // this.GBABaseBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) @@ -3184,15 +3063,6 @@ // // tabPageAtari7800 // - this.tabPageAtari7800.Controls.Add(this.label8); - this.tabPageAtari7800.Controls.Add(this.label7); - this.tabPageAtari7800.Controls.Add(this.label6); - this.tabPageAtari7800.Controls.Add(this.Atari7800BrowseHSCBIOS); - this.tabPageAtari7800.Controls.Add(this.Atari7800BrowsePALBIOS); - this.tabPageAtari7800.Controls.Add(this.Atari7800BrowseNTSCBIOS); - this.tabPageAtari7800.Controls.Add(this.Atari7800HighScoreBIOSBox); - this.tabPageAtari7800.Controls.Add(this.Atari7800PALBIOSBox); - this.tabPageAtari7800.Controls.Add(this.Atari7800NTSCBIOSBox); this.tabPageAtari7800.Controls.Add(this.Atari7800SaveRAMsDescription); this.tabPageAtari7800.Controls.Add(this.BrowseAtari7800SaveRAM); this.tabPageAtari7800.Controls.Add(this.Atari7800SaveRAMBox); @@ -3218,99 +3088,6 @@ this.tabPageAtari7800.Text = "A. 7800"; this.tabPageAtari7800.UseVisualStyleBackColor = true; // - // label8 - // - this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(474, 264); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(83, 13); - this.label8.TabIndex = 110; - this.label8.Text = "Highscore BIOS"; - // - // label7 - // - this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(474, 235); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(55, 13); - this.label7.TabIndex = 109; - this.label7.Text = "PAL BIOS"; - // - // label6 - // - this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(474, 209); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(64, 13); - this.label6.TabIndex = 108; - this.label6.Text = "NTSC BIOS"; - // - // Atari7800BrowseHSCBIOS - // - this.Atari7800BrowseHSCBIOS.AccessibleName = "Atari7800BrowseCheats"; - this.Atari7800BrowseHSCBIOS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.Atari7800BrowseHSCBIOS.Image = ((System.Drawing.Image)(resources.GetObject("Atari7800BrowseHSCBIOS.Image"))); - this.Atari7800BrowseHSCBIOS.Location = new System.Drawing.Point(442, 259); - this.Atari7800BrowseHSCBIOS.Name = "Atari7800BrowseHSCBIOS"; - this.Atari7800BrowseHSCBIOS.Size = new System.Drawing.Size(26, 23); - this.Atari7800BrowseHSCBIOS.TabIndex = 107; - this.Atari7800BrowseHSCBIOS.UseVisualStyleBackColor = true; - this.Atari7800BrowseHSCBIOS.Click += new System.EventHandler(this.Atari7800BrowseHSCBIOS_Click); - // - // Atari7800BrowsePALBIOS - // - this.Atari7800BrowsePALBIOS.AccessibleName = "Atari7800BrowseCheats"; - this.Atari7800BrowsePALBIOS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.Atari7800BrowsePALBIOS.Image = ((System.Drawing.Image)(resources.GetObject("Atari7800BrowsePALBIOS.Image"))); - this.Atari7800BrowsePALBIOS.Location = new System.Drawing.Point(442, 232); - this.Atari7800BrowsePALBIOS.Name = "Atari7800BrowsePALBIOS"; - this.Atari7800BrowsePALBIOS.Size = new System.Drawing.Size(26, 23); - this.Atari7800BrowsePALBIOS.TabIndex = 106; - this.Atari7800BrowsePALBIOS.UseVisualStyleBackColor = true; - this.Atari7800BrowsePALBIOS.Click += new System.EventHandler(this.Atari7800BrowsePALBIOS_Click); - // - // Atari7800BrowseNTSCBIOS - // - this.Atari7800BrowseNTSCBIOS.AccessibleName = "Atari7800BrowseCheats"; - this.Atari7800BrowseNTSCBIOS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.Atari7800BrowseNTSCBIOS.Image = ((System.Drawing.Image)(resources.GetObject("Atari7800BrowseNTSCBIOS.Image"))); - this.Atari7800BrowseNTSCBIOS.Location = new System.Drawing.Point(442, 206); - this.Atari7800BrowseNTSCBIOS.Name = "Atari7800BrowseNTSCBIOS"; - this.Atari7800BrowseNTSCBIOS.Size = new System.Drawing.Size(26, 23); - this.Atari7800BrowseNTSCBIOS.TabIndex = 105; - this.Atari7800BrowseNTSCBIOS.UseVisualStyleBackColor = true; - this.Atari7800BrowseNTSCBIOS.Click += new System.EventHandler(this.Atari7800BrowseNTSCBIOS_Click); - // - // Atari7800HighScoreBIOSBox - // - this.Atari7800HighScoreBIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.Atari7800HighScoreBIOSBox.Location = new System.Drawing.Point(13, 259); - this.Atari7800HighScoreBIOSBox.Name = "Atari7800HighScoreBIOSBox"; - this.Atari7800HighScoreBIOSBox.Size = new System.Drawing.Size(421, 20); - this.Atari7800HighScoreBIOSBox.TabIndex = 104; - // - // Atari7800PALBIOSBox - // - this.Atari7800PALBIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.Atari7800PALBIOSBox.Location = new System.Drawing.Point(13, 232); - this.Atari7800PALBIOSBox.Name = "Atari7800PALBIOSBox"; - this.Atari7800PALBIOSBox.Size = new System.Drawing.Size(421, 20); - this.Atari7800PALBIOSBox.TabIndex = 103; - // - // Atari7800NTSCBIOSBox - // - this.Atari7800NTSCBIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.Atari7800NTSCBIOSBox.Location = new System.Drawing.Point(13, 206); - this.Atari7800NTSCBIOSBox.Name = "Atari7800NTSCBIOSBox"; - this.Atari7800NTSCBIOSBox.Size = new System.Drawing.Size(421, 20); - this.Atari7800NTSCBIOSBox.TabIndex = 102; - // // Atari7800SaveRAMsDescription // this.Atari7800SaveRAMsDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); @@ -3704,9 +3481,6 @@ // // tabPageColeco // - this.tabPageColeco.Controls.Add(this.label4); - this.tabPageColeco.Controls.Add(this.button3); - this.tabPageColeco.Controls.Add(this.ColecoBIOSBox); this.tabPageColeco.Controls.Add(this.COLBaseBox); this.tabPageColeco.Controls.Add(this.COLCheatsDescription); this.tabPageColeco.Controls.Add(this.COLBrowseCheats); @@ -3729,36 +3503,6 @@ this.tabPageColeco.Text = "Col. V."; this.tabPageColeco.UseVisualStyleBackColor = true; // - // label4 - // - this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(474, 183); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(32, 13); - this.label4.TabIndex = 112; - this.label4.Text = "BIOS"; - // - // button3 - // - this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.button3.Image = ((System.Drawing.Image)(resources.GetObject("button3.Image"))); - this.button3.Location = new System.Drawing.Point(442, 179); - this.button3.Name = "button3"; - this.button3.Size = new System.Drawing.Size(26, 23); - this.button3.TabIndex = 111; - this.button3.UseVisualStyleBackColor = true; - this.button3.Click += new System.EventHandler(this.button3_Click); - // - // ColecoBIOSBox - // - this.ColecoBIOSBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.ColecoBIOSBox.Location = new System.Drawing.Point(13, 179); - this.ColecoBIOSBox.Name = "ColecoBIOSBox"; - this.ColecoBIOSBox.Size = new System.Drawing.Size(421, 20); - this.ColecoBIOSBox.TabIndex = 110; - // // COLBaseBox // this.COLBaseBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) @@ -4873,7 +4617,7 @@ private System.Windows.Forms.Label SNESROMsDescription; private System.Windows.Forms.TextBox SNESSaveRAMBox; private System.Windows.Forms.Button SNESBrowseROMs; - private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; + private BizHawk.FolderBrowserEx folderBrowserDialog1; private System.Windows.Forms.Label LogDescription; private System.Windows.Forms.Button BrowseLog; private System.Windows.Forms.TextBox LogBox; @@ -4953,30 +4697,9 @@ private System.Windows.Forms.Label labelFirmware; private System.Windows.Forms.Button buttonFirmware; private System.Windows.Forms.TextBox textBoxFirmware; - private System.Windows.Forms.TextBox PCEBIOSBox; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.TextBox FDSBIOSBox; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.Button NESBrowseFDSBIOS; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.Button button3; - private System.Windows.Forms.TextBox ColecoBIOSBox; - private System.Windows.Forms.Label label5; - private System.Windows.Forms.Button button4; - private System.Windows.Forms.TextBox GBABIOSBox; private System.Windows.Forms.TextBox BaseROMSBox; private System.Windows.Forms.Label BaseROMLabel; private System.Windows.Forms.Button BrowseBaseROM; - private System.Windows.Forms.TextBox Atari7800PALBIOSBox; - private System.Windows.Forms.TextBox Atari7800NTSCBIOSBox; - private System.Windows.Forms.TextBox Atari7800HighScoreBIOSBox; - private System.Windows.Forms.Button Atari7800BrowseHSCBIOS; - private System.Windows.Forms.Button Atari7800BrowsePALBIOS; - private System.Windows.Forms.Button Atari7800BrowseNTSCBIOS; - private System.Windows.Forms.Label label8; - private System.Windows.Forms.Label label7; - private System.Windows.Forms.Label label6; private System.Windows.Forms.TabPage tabPageN64; private System.Windows.Forms.TabPage tabPageSaturn; private System.Windows.Forms.TextBox N64BaseBox; diff --git a/BizHawk.MultiClient/config/PathConfig.cs b/BizHawk.MultiClient/config/PathConfig.cs index 230df250c7..8c8dd1ffea 100644 --- a/BizHawk.MultiClient/config/PathConfig.cs +++ b/BizHawk.MultiClient/config/PathConfig.cs @@ -134,9 +134,6 @@ namespace BizHawk.MultiClient Atari7800SaveRAMBox.Text = Global.Config.PathAtari7800SaveRAM; Atari7800ScreenshotsBox.Text = Global.Config.PathAtari7800Screenshots; Atari7800CheatsBox.Text = Global.Config.PathAtari7800Cheats; - Atari7800NTSCBIOSBox.Text = Global.Config.FilenameA78NTSCBios; - Atari7800PALBIOSBox.Text = Global.Config.FilenameA78PALBios; - Atari7800HighScoreBIOSBox.Text = Global.Config.FilenameA78HSCBios; C64BaseBox.Text = Global.Config.BaseC64; C64ROMsBox.Text = Global.Config.PathC64ROMs; @@ -173,11 +170,6 @@ namespace BizHawk.MultiClient textBoxFirmware.Text = Global.Config.FirmwaresPath; BaseROMSBox.Text = Global.Config.BaseROMPath; - PCEBIOSBox.Text = Global.Config.FilenamePCEBios; - FDSBIOSBox.Text = Global.Config.FilenameFDSBios; - ColecoBIOSBox.Text = Global.Config.FilenameCOLBios; - GBABIOSBox.Text = Global.Config.FilenameGBABIOS; - SetTabByPlatform(); if (!MainForm.INTERIM) @@ -328,7 +320,6 @@ namespace BizHawk.MultiClient Global.Config.PathGBASaveRAM = GBASaveRAMBox.Text; Global.Config.PathGBAScreenshots = GBAScreenshotsBox.Text; Global.Config.PathGBACheats = GBACheatsBox.Text; - Global.Config.FilenameGBABIOS = GBABIOSBox.Text; Global.Config.BaseTI83 = TI83BaseBox.Text; Global.Config.PathTI83ROMs = TI83ROMsBox.Text; @@ -349,9 +340,6 @@ namespace BizHawk.MultiClient Global.Config.PathAtari7800SaveRAM = Atari7800SaveRAMBox.Text; Global.Config.PathAtari7800Screenshots = Atari7800ScreenshotsBox.Text; Global.Config.PathAtari7800Cheats = Atari7800CheatsBox.Text; - Global.Config.FilenameA78NTSCBios = Atari7800NTSCBIOSBox.Text; - Global.Config.FilenameA78PALBios = Atari7800PALBIOSBox.Text; - Global.Config.FilenameA78HSCBios = Atari7800HighScoreBIOSBox.Text; Global.Config.BaseC64 = C64BaseBox.Text; Global.Config.PathC64ROMs = C64ROMsBox.Text; @@ -388,11 +376,6 @@ namespace BizHawk.MultiClient Global.Config.FirmwaresPath = textBoxFirmware.Text; Global.Config.BaseROMPath = BaseROMSBox.Text; - Global.Config.FilenamePCEBios = PCEBIOSBox.Text; - Global.Config.FilenameFDSBios = FDSBIOSBox.Text; - Global.Config.FilenameCOLBios = ColecoBIOSBox.Text; - Global.Config.FilenameGBABIOS = GBABIOSBox.Text; - BasePathBox.Focus(); Global.MainForm.UpdateStatusSlots(); } @@ -494,7 +477,7 @@ namespace BizHawk.MultiClient private void BrowseFolder(TextBox box, string _Name) { - FolderBrowserDialog f = new FolderBrowserDialog + FolderBrowserEx f = new FolderBrowserEx { Description = "Set the directory for " + _Name, SelectedPath = PathManager.MakeAbsolutePath(box.Text) @@ -1005,123 +988,11 @@ namespace BizHawk.MultiClient BrowseFolder(textBoxFirmware, labelFirmware.Text); } - private void button2_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin,*.pce)|*.rom;*.bin;*.pce|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - PCEBIOSBox.Text = file.Name; - } - } - - private void NESBrowseFDSBIOS_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin)|*.rom;*.bin|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - FDSBIOSBox.Text = file.Name; - } - } - - private void button3_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin)|*.rom;*.bin|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - ColecoBIOSBox.Text = file.Name; - } - } - - private void button4_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin)|*.rom;*.bin|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - GBABIOSBox.Text = file.Name; - } - } - private void BrowseBaseROM_Click(object sender, EventArgs e) { BrowseFolder(BaseROMSBox, BaseROMLabel.Text, ""); } - private void Atari7800BrowseNTSCBIOS_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin)|*.rom;*.bin|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - Atari7800NTSCBIOSBox.Text = file.Name; - } - } - - private void Atari7800BrowsePALBIOS_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin)|*.rom;*.bin|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - Atari7800PALBIOSBox.Text = file.Name; - } - } - - private void Atari7800BrowseHSCBIOS_Click(object sender, EventArgs e) - { - OpenFileDialog ofd = new OpenFileDialog - { - InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.FirmwaresPath), - Filter = "Binary Files (*.rom,*.bin)|*.rom;*.bin|All Files|*.*", - RestoreDirectory = false - }; - DialogResult result = ofd.ShowDialog(); - if (result == DialogResult.OK) - { - var file = new FileInfo(ofd.FileName); - Atari7800HighScoreBIOSBox.Text = file.Name; - } - } - private void N64BrowseBase_Click(object sender, EventArgs e) { BrowseFolder(N64BaseBox, N64BaseDescription.Text); diff --git a/BizHawk.MultiClient/config/PathConfig.resx b/BizHawk.MultiClient/config/PathConfig.resx index 3f3bbcee29..718b96d3e6 100644 --- a/BizHawk.MultiClient/config/PathConfig.resx +++ b/BizHawk.MultiClient/config/PathConfig.resx @@ -320,111 +320,6 @@ KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - True - - - - 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 @@ -493,23 +388,6 @@ KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC @@ -955,23 +833,6 @@ KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC @@ -1193,23 +1054,6 @@ KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC @@ -1482,57 +1326,6 @@ KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC @@ -1720,23 +1513,6 @@ KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAr2AAAK9gHCr3ADAAACeUlE - QVQ4T6WSWUiUURiG/4suurJIjUIwskQsEAMjqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF - sEIoFInQcqHE1CwoKsXUUMnt6XfEye0munjgnO+c9+HjO0cA/osNi2tJLdA6SXN13MwoI12lJ06uiV8+ - W3d5IwIjVXiGKvwX11djSs2TRFlUito7ILIAoVab7SvCWhqrZYq1omXC4gpPe4Ur8AjNMQjo69IwPVZj - 4PeojtlhNfoyBXXalKSNBJ5hSjxCcnELzkeoKVcyNVq5Kjz/rZDZnggqSzOoKEpDXZBEcU4id+Sx5Mui - RcdfmVClyWLqh8YYXhDD9MVCT/CGrBPcK5Hx62uxMdxUm2XgiT6Tep2MhxVp6NXJ6IqllKlucTc3niJl - LKqsGINMqChOY+JTnqHtwRYJdZVK5gelMJSymo9ibSAOeiPhXTid1T5cD3IvF9SqZMb7M+CznEdVCtqe - ypcurWz9bQC0ezHX6sr0M0c+lNtx5cKJcVGwXyjJlfDzvZSh1gTqdHIWBiTQHbIU7AwSg+eYa3Nnuvk4 - E41HGak9gDTUmvPOZjmGGRQqExjpiuG+NouOl2InvRGi4BJ0+LPw6gwzL04x2XSM0ToHvlfZ0p66FT9X - KxxsTGwMAlVmLN3NiTzQZkJ/IrwR233tzUyLG5PPHRmrP8Sw3o4vmr30yE2RBO/Bfp9Fg/EV8tKjqSnL - oOdxGO3ZgpE2+SaaZZtpSNpCdbw56mgLbt/YhZ/L7oVD9pYuRkF2ShTZksukxwQSd813cbJc9HHm7MnD - OB2x46CdNbZWFljuNGP7NhN2mJqIuRX/YOXm30H4A70P0TsBWkcYAAAAAElFTkSuQmCC @@ -1958,6 +1734,108 @@ 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 @@ -1966,7 +1844,4 @@ 186, 17 - - 186, 17 - \ No newline at end of file diff --git a/BizHawk.Util/Util.cs b/BizHawk.Util/Util.cs index 7b95814dab..5ecd9dac91 100644 --- a/BizHawk.Util/Util.cs +++ b/BizHawk.Util/Util.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.ComponentModel; using System.Runtime.InteropServices; using System.Windows.Forms; @@ -64,6 +65,35 @@ namespace BizHawk [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref HDITEM lParam); + public static string CopyItemsAsText(this ListView listViewControl) + { + ListView.SelectedIndexCollection indexes = listViewControl.SelectedIndices; + if (indexes.Count <= 0) + return ""; + + StringBuilder sb = new StringBuilder(); + + //walk over each selected item and subitem within it to generate a string from it + foreach (int index in indexes) + { + foreach (ListViewItem.ListViewSubItem item in listViewControl.Items[index].SubItems) + { + if (!String.IsNullOrWhiteSpace(item.Text)) + sb.Append(item.Text).Append('\t'); + } + //remove the last tab + sb.Remove(sb.Length - 1, 1); + + sb.Append("\r\n"); + } + + //remove last newline + sb.Length -= 2; + + + return sb.ToString(); + } + public static void SetSortIcon(this ListView listViewControl, int columnIndex, SortOrder order) { IntPtr columnHeader = SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);