diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
index 1e676bbed1..4c12369180 100644
--- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
+++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
@@ -595,6 +595,9 @@
+
+ Form
+
diff --git a/BizHawk.Client.EmuHawk/FileLoader.cs b/BizHawk.Client.EmuHawk/FileLoader.cs
new file mode 100644
index 0000000000..b8935bcb91
--- /dev/null
+++ b/BizHawk.Client.EmuHawk/FileLoader.cs
@@ -0,0 +1,350 @@
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using System.Reflection;
+using System.Linq;
+using System.Collections.Generic;
+
+using BizHawk.Emulation.Common;
+using BizHawk.Emulation.Common.IEmulatorExtensions;
+using BizHawk.Emulation.Cores.Calculators;
+using BizHawk.Emulation.Cores.ColecoVision;
+using BizHawk.Emulation.Cores.Nintendo.Gameboy;
+using BizHawk.Emulation.Cores.Nintendo.NES;
+using BizHawk.Emulation.Cores.Nintendo.N64;
+using BizHawk.Emulation.Cores.Nintendo.SNES;
+using BizHawk.Emulation.Cores.PCEngine;
+using BizHawk.Emulation.Cores.Sega.MasterSystem;
+using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
+
+using BizHawk.Client.Common;
+
+using BizHawk.Client.EmuHawk.CustomControls;
+using BizHawk.Client.EmuHawk.WinFormExtensions;
+using BizHawk.Client.EmuHawk.ToolExtensions;
+using BizHawk.Emulation.Cores.Computers.AppleII;
+using BizHawk.Client.ApiHawk;
+
+namespace BizHawk.Client.EmuHawk
+{
+ partial class MainForm
+ {
+ private enum LoadOrdering
+ {
+ ROM,
+ STATE,
+ WATCH,
+ CDLFILE,
+ LUASESSION,
+ LUASCRIPT,
+ CHEAT,
+ MOVIEFILE,
+ LEGACYMOVIEFILE
+ }
+
+ public struct FileInformation
+ {
+ public string directoryName;
+ public string fileName;
+ public string archiveName;
+
+ public FileInformation(string directory, string file, string archive)
+ {
+ directoryName = directory;
+ fileName = file;
+ archiveName = archive;
+ }
+ }
+
+ readonly string[] knownROMExtensions = { ".M3U", ".ISO", ".CUE", ".CCD", ".XML", ".PSF", ".MINIPSF",
+ ".EXE", ".NES", ".83P", ".SNES", ".GB", ".GBC", ".A78",
+ ".C64", ".GBA", ".PSX" };
+ readonly string[] nonArchive = { ".ISO", ".CUE", ".CCD" };
+
+ #region Loaders
+
+ // According to the documentation (http://tasvideos.org/Bizhawk/CodeDataLogger.html),
+ // Currently supported for: PCE, GB/GBC, SMS/GG, Genesis, SNES
+ // Perhaps the 'is PCEngine' requirement needs to be expanded.
+ private void _LoadCDL(string filename, string archive = null)
+ {
+ if (!(Global.Emulator is PCEngine))
+ return;
+
+ GlobalWin.Tools.Load();
+ (GlobalWin.Tools.Get() as CDL).LoadFile(filename);
+ }
+
+ private void _LoadCheats(string filename, string archive = null)
+ {
+ Global.CheatList.Load(filename, false);
+ GlobalWin.Tools.Load();
+ }
+
+ private void _LoadLegacyMovie(string filename, string archive = null)
+ {
+ if (Global.Emulator.IsNull())
+ {
+ OpenRom();
+ }
+
+ if (Global.Emulator.IsNull())
+ {
+ return;
+ }
+
+ // tries to open a legacy movie format by importing it
+ string errorMsg;
+ string warningMsg;
+ var movie = MovieImport.ImportFile(filename, out errorMsg, out warningMsg);
+ if (!string.IsNullOrEmpty(errorMsg))
+ {
+ MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ else
+ {
+ // fix movie extension to something palatable for these purposes.
+ // for instance, something which doesnt clobber movies you already may have had.
+ // i'm evenly torn between this, and a file in %TEMP%, but since we dont really have a way to clean up this tempfile, i choose this:
+ StartNewMovie(movie, false);
+ }
+
+ GlobalWin.OSD.AddMessage(warningMsg);
+ }
+
+ private void _LoadLuaFile(string filename, string archive = null)
+ {
+ OpenLuaConsole();
+ if (GlobalWin.Tools.Has())
+ {
+ GlobalWin.Tools.LuaConsole.LoadLuaFile(filename);
+ }
+ }
+
+ private void _LoadLuaSession(string filename, string archive = null)
+ {
+ OpenLuaConsole();
+ if (GlobalWin.Tools.Has())
+ {
+ GlobalWin.Tools.LuaConsole.LoadLuaSession(filename);
+ }
+ }
+
+ private void _LoadMovie(string filename, string archive = null)
+ {
+ if (Global.Emulator.IsNull())
+ {
+ OpenRom();
+ }
+
+ if (Global.Emulator.IsNull())
+ {
+ return;
+ }
+
+ StartNewMovie(MovieService.Get(filename), false);
+ }
+
+ private void _LoadRom(string filename, string archive = null)
+ {
+ var args = new LoadRomArgs();
+ args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filename };
+ LoadRom(filename, args);
+ }
+
+ private void _LoadState(string filename, string archive = null)
+ {
+ LoadState(filename, Path.GetFileName(filename));
+ }
+
+ private void _LoadWatch(string filename, string archive = null)
+ {
+ GlobalWin.Tools.LoadRamWatch(true);
+ (GlobalWin.Tools.Get() as RamWatch).LoadWatchFile(new FileInfo(filename), false);
+ }
+
+ #endregion
+
+ private void ProcessFileList(string[] fileList, ref Dictionary> sortedFiles, string archive = null)
+ {
+ foreach (string file in fileList)
+ {
+ var ext = Path.GetExtension(file).ToUpper() ?? String.Empty;
+ FileInformation fileInformation = new FileInformation(Path.GetDirectoryName(file), Path.GetFileName(file), archive);
+
+ switch (ext)
+ {
+ case ".LUA":
+ sortedFiles[LoadOrdering.LUASCRIPT].Add(fileInformation);
+ break;
+ case ".LUASES":
+ sortedFiles[LoadOrdering.LUASESSION].Add(fileInformation);
+ break;
+ case ".STATE":
+ sortedFiles[LoadOrdering.STATE].Add(fileInformation);
+ break;
+ case ".CHT":
+ sortedFiles[LoadOrdering.CHEAT].Add(fileInformation);
+ break;
+ case ".WCH":
+ sortedFiles[LoadOrdering.WATCH].Add(fileInformation);
+ break;
+ case ".CDL":
+ sortedFiles[LoadOrdering.CDLFILE].Add(fileInformation);
+ break;
+ default:
+ if (MovieService.IsValidMovieExtension(ext))
+ sortedFiles[LoadOrdering.MOVIEFILE].Add(fileInformation);
+ else if (MovieImport.IsValidMovieExtension(ext))
+ sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Add(fileInformation);
+ else if (knownROMExtensions.Contains(ext))
+ {
+ if (String.IsNullOrEmpty(archive) || !nonArchive.Contains(ext))
+ sortedFiles[LoadOrdering.ROM].Add(fileInformation);
+ }
+ else
+ {
+ /* Because the existing behaviour for archives is to try loading
+ * ROMs out of them, that is exactly what we are going to continue
+ * to do at present. Ideally, the archive should be scanned and
+ * relevant files should be extracted, but see the note below for
+ * further details.
+ */
+ int offset = 0;
+ bool executable = false;
+ var archiveHandler = new SevenZipSharpArchiveHandler();
+
+ if (String.IsNullOrEmpty(archive) && archiveHandler.CheckSignature(file, out offset, out executable))
+ sortedFiles[LoadOrdering.ROM].Add(fileInformation);
+
+ /*
+ * This is where handling archives would go.
+ * Right now, that's going to be a HUGE hassle, because of the problem with
+ * saving things into the archive (no) and with everything requiring filenames
+ * and not streams (also no), so for the purposes of making drag/drop more robust,
+ * I am not building this out just yet.
+ * -- Adam Michaud (Invariel)
+
+ int offset = 0;
+ bool executable = false;
+ var archiveHandler = new SevenZipSharpArchiveHandler();
+
+ // Not going to process nested archives at the moment.
+ if (String.IsNullOrEmpty (archive) && archiveHandler.CheckSignature(file, out offset, out executable))
+ {
+ List fileNames = new List();
+ var openedArchive = archiveHandler.Construct (file);
+
+ foreach (BizHawk.Common.HawkFileArchiveItem item in openedArchive.Scan ())
+ fileNames.Add(item.Name);
+
+ ProcessFileList(fileNames.ToArray(), ref sortedFiles, file);
+
+ openedArchive.Dispose();
+ }
+ archiveHandler.Dispose();
+ */
+ }
+ break;
+ }
+ }
+ }
+
+ private void _FormDragDrop_internal(object sender, DragEventArgs e)
+ {
+ /*
+ * Refactor, moving the loading of particular files into separate functions that can
+ * then be used by this code, and loading individual files through the file dialogue.
+ *
+ * Step 1:
+ * Build a dictionary of relevant files from everything that was dragged and dropped.
+ * This includes peeking into all relevant archives and using their files.
+ *
+ * Step 2:
+ * Perhaps ask the user which of a particular file type they want to use.
+ * Example: rom1.nes, rom2.smc, rom3.cue are drag-dropped, ask the user which they want to use.
+ *
+ * Step 3:
+ * Load all of the relevant files, in priority order:
+ * 1) The ROM
+ * 2) State
+ * 3) Watch files
+ * 4) Code Data Logger (CDL)
+ * 5) LUA sessions
+ * 6) LUA scripts
+ * 7) Cheat files
+ * 8) Movie Playback Files
+ *
+ * Bonus:
+ * Make that order easy to change in the code, heavily suggesting ROM and playback as first and last respectively.
+ */
+
+ var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
+ Dictionary> sortedFiles = new Dictionary>();
+
+ // Initialize the dictionary's lists.
+ foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
+ {
+ sortedFiles.Add(value, new List());
+ }
+
+ ProcessFileList(filePaths, ref sortedFiles, null);
+
+ // For each of the different types of item, if there are no items of that type, skip them.
+ // If there is exactly one of that type of item, load it.
+ // If there is more than one, ask.
+
+ foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
+ {
+ switch (sortedFiles[value].Count)
+ {
+ case 0:
+ break;
+ case 1:
+ FileInformation fileInformation = sortedFiles[value].First();
+ string filename = Path.Combine(new string[] { fileInformation.directoryName, fileInformation.fileName });
+
+ switch (value)
+ {
+ case LoadOrdering.ROM:
+ _LoadRom(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.STATE:
+ _LoadState(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.WATCH:
+ _LoadWatch(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.CDLFILE:
+ _LoadCDL(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.LUASESSION:
+ _LoadLuaSession(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.LUASCRIPT:
+ _LoadLuaFile(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.CHEAT:
+ _LoadCheats(filename, fileInformation.archiveName);
+ break;
+ case LoadOrdering.MOVIEFILE:
+ case LoadOrdering.LEGACYMOVIEFILE:
+ // I don't really like this hack, but for now, we only want to load one movie file.
+ if (sortedFiles[LoadOrdering.MOVIEFILE].Count + sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Count > 1)
+ break;
+
+ if (value == LoadOrdering.MOVIEFILE)
+ _LoadMovie(filename, fileInformation.archiveName);
+ else
+ _LoadLegacyMovie(filename, fileInformation.archiveName);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs
index 8becdb2a94..f022b3959a 100644
--- a/BizHawk.Client.EmuHawk/MainForm.Events.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs
@@ -2753,6 +2753,8 @@ namespace BizHawk.Client.EmuHawk
private void FormDragDrop_internal(object sender, DragEventArgs e)
{
+ _FormDragDrop_internal(sender, e);
+/*
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
var isLua = false;
foreach (var path in filePaths)
@@ -2853,6 +2855,7 @@ namespace BizHawk.Client.EmuHawk
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePaths[0] };
LoadRom(filePaths[0], args);
}
+ */
}
#endregion