Skip to content

Commit 9b75d9c

Browse files
committed
Merge pull request #592 from TASVideos/feature-drag-drop
Expanded drag and drop
2 parents 234cc2e + 2db8f7e commit 9b75d9c

File tree

3 files changed

+356
-0
lines changed

3 files changed

+356
-0
lines changed

BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,9 @@
595595
<Compile Include="Extensions\ControlExtensions.cs" />
596596
<Compile Include="Extensions\CoreExtensions.cs" />
597597
<Compile Include="Extensions\ToolExtensions.cs" />
598+
<Compile Include="FileLoader.cs">
599+
<SubType>Form</SubType>
600+
</Compile>
598601
<Compile Include="GLManager.cs" />
599602
<Compile Include="GlobalWin.cs" />
600603
<Compile Include="Input\GamePad.cs" Condition=" '$(OS)' == 'Windows_NT' " />
Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
using System;
2+
using System.Drawing;
3+
using System.IO;
4+
using System.Windows.Forms;
5+
using System.Reflection;
6+
using System.Linq;
7+
using System.Collections.Generic;
8+
9+
using BizHawk.Emulation.Common;
10+
using BizHawk.Emulation.Common.IEmulatorExtensions;
11+
using BizHawk.Emulation.Cores.Calculators;
12+
using BizHawk.Emulation.Cores.ColecoVision;
13+
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
14+
using BizHawk.Emulation.Cores.Nintendo.NES;
15+
using BizHawk.Emulation.Cores.Nintendo.N64;
16+
using BizHawk.Emulation.Cores.Nintendo.SNES;
17+
using BizHawk.Emulation.Cores.PCEngine;
18+
using BizHawk.Emulation.Cores.Sega.MasterSystem;
19+
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
20+
21+
using BizHawk.Client.Common;
22+
23+
using BizHawk.Client.EmuHawk.CustomControls;
24+
using BizHawk.Client.EmuHawk.WinFormExtensions;
25+
using BizHawk.Client.EmuHawk.ToolExtensions;
26+
using BizHawk.Emulation.Cores.Computers.AppleII;
27+
using BizHawk.Client.ApiHawk;
28+
29+
namespace BizHawk.Client.EmuHawk
30+
{
31+
partial class MainForm
32+
{
33+
private enum LoadOrdering
34+
{
35+
ROM,
36+
STATE,
37+
WATCH,
38+
CDLFILE,
39+
LUASESSION,
40+
LUASCRIPT,
41+
CHEAT,
42+
MOVIEFILE,
43+
LEGACYMOVIEFILE
44+
}
45+
46+
public struct FileInformation
47+
{
48+
public string directoryName;
49+
public string fileName;
50+
public string archiveName;
51+
52+
public FileInformation(string directory, string file, string archive)
53+
{
54+
directoryName = directory;
55+
fileName = file;
56+
archiveName = archive;
57+
}
58+
}
59+
60+
readonly string[] knownROMExtensions = { ".M3U", ".ISO", ".CUE", ".CCD", ".XML", ".PSF", ".MINIPSF",
61+
".EXE", ".NES", ".83P", ".SNES", ".GB", ".GBC", ".A78",
62+
".C64", ".GBA", ".PSX" };
63+
readonly string[] nonArchive = { ".ISO", ".CUE", ".CCD" };
64+
65+
#region Loaders
66+
67+
// According to the documentation (http://tasvideos.org/Bizhawk/CodeDataLogger.html),
68+
// Currently supported for: PCE, GB/GBC, SMS/GG, Genesis, SNES
69+
// Perhaps the 'is PCEngine' requirement needs to be expanded.
70+
private void _LoadCDL(string filename, string archive = null)
71+
{
72+
if (!(Global.Emulator is PCEngine))
73+
return;
74+
75+
GlobalWin.Tools.Load<CDL>();
76+
(GlobalWin.Tools.Get<CDL>() as CDL).LoadFile(filename);
77+
}
78+
79+
private void _LoadCheats(string filename, string archive = null)
80+
{
81+
Global.CheatList.Load(filename, false);
82+
GlobalWin.Tools.Load<Cheats>();
83+
}
84+
85+
private void _LoadLegacyMovie(string filename, string archive = null)
86+
{
87+
if (Global.Emulator.IsNull())
88+
{
89+
OpenRom();
90+
}
91+
92+
if (Global.Emulator.IsNull())
93+
{
94+
return;
95+
}
96+
97+
// tries to open a legacy movie format by importing it
98+
string errorMsg;
99+
string warningMsg;
100+
var movie = MovieImport.ImportFile(filename, out errorMsg, out warningMsg);
101+
if (!string.IsNullOrEmpty(errorMsg))
102+
{
103+
MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error);
104+
}
105+
else
106+
{
107+
// fix movie extension to something palatable for these purposes.
108+
// for instance, something which doesnt clobber movies you already may have had.
109+
// 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:
110+
StartNewMovie(movie, false);
111+
}
112+
113+
GlobalWin.OSD.AddMessage(warningMsg);
114+
}
115+
116+
private void _LoadLuaFile(string filename, string archive = null)
117+
{
118+
OpenLuaConsole();
119+
if (GlobalWin.Tools.Has<LuaConsole>())
120+
{
121+
GlobalWin.Tools.LuaConsole.LoadLuaFile(filename);
122+
}
123+
}
124+
125+
private void _LoadLuaSession(string filename, string archive = null)
126+
{
127+
OpenLuaConsole();
128+
if (GlobalWin.Tools.Has<LuaConsole>())
129+
{
130+
GlobalWin.Tools.LuaConsole.LoadLuaSession(filename);
131+
}
132+
}
133+
134+
private void _LoadMovie(string filename, string archive = null)
135+
{
136+
if (Global.Emulator.IsNull())
137+
{
138+
OpenRom();
139+
}
140+
141+
if (Global.Emulator.IsNull())
142+
{
143+
return;
144+
}
145+
146+
StartNewMovie(MovieService.Get(filename), false);
147+
}
148+
149+
private void _LoadRom(string filename, string archive = null)
150+
{
151+
var args = new LoadRomArgs();
152+
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filename };
153+
LoadRom(filename, args);
154+
}
155+
156+
private void _LoadState(string filename, string archive = null)
157+
{
158+
LoadState(filename, Path.GetFileName(filename));
159+
}
160+
161+
private void _LoadWatch(string filename, string archive = null)
162+
{
163+
GlobalWin.Tools.LoadRamWatch(true);
164+
(GlobalWin.Tools.Get<RamWatch>() as RamWatch).LoadWatchFile(new FileInfo(filename), false);
165+
}
166+
167+
#endregion
168+
169+
private void ProcessFileList(string[] fileList, ref Dictionary<LoadOrdering, List<FileInformation>> sortedFiles, string archive = null)
170+
{
171+
foreach (string file in fileList)
172+
{
173+
var ext = Path.GetExtension(file).ToUpper() ?? String.Empty;
174+
FileInformation fileInformation = new FileInformation(Path.GetDirectoryName(file), Path.GetFileName(file), archive);
175+
176+
switch (ext)
177+
{
178+
case ".LUA":
179+
sortedFiles[LoadOrdering.LUASCRIPT].Add(fileInformation);
180+
break;
181+
case ".LUASES":
182+
sortedFiles[LoadOrdering.LUASESSION].Add(fileInformation);
183+
break;
184+
case ".STATE":
185+
sortedFiles[LoadOrdering.STATE].Add(fileInformation);
186+
break;
187+
case ".CHT":
188+
sortedFiles[LoadOrdering.CHEAT].Add(fileInformation);
189+
break;
190+
case ".WCH":
191+
sortedFiles[LoadOrdering.WATCH].Add(fileInformation);
192+
break;
193+
case ".CDL":
194+
sortedFiles[LoadOrdering.CDLFILE].Add(fileInformation);
195+
break;
196+
default:
197+
if (MovieService.IsValidMovieExtension(ext))
198+
sortedFiles[LoadOrdering.MOVIEFILE].Add(fileInformation);
199+
else if (MovieImport.IsValidMovieExtension(ext))
200+
sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Add(fileInformation);
201+
else if (knownROMExtensions.Contains(ext))
202+
{
203+
if (String.IsNullOrEmpty(archive) || !nonArchive.Contains(ext))
204+
sortedFiles[LoadOrdering.ROM].Add(fileInformation);
205+
}
206+
else
207+
{
208+
/* Because the existing behaviour for archives is to try loading
209+
* ROMs out of them, that is exactly what we are going to continue
210+
* to do at present. Ideally, the archive should be scanned and
211+
* relevant files should be extracted, but see the note below for
212+
* further details.
213+
*/
214+
int offset = 0;
215+
bool executable = false;
216+
var archiveHandler = new SevenZipSharpArchiveHandler();
217+
218+
if (String.IsNullOrEmpty(archive) && archiveHandler.CheckSignature(file, out offset, out executable))
219+
sortedFiles[LoadOrdering.ROM].Add(fileInformation);
220+
221+
/*
222+
* This is where handling archives would go.
223+
* Right now, that's going to be a HUGE hassle, because of the problem with
224+
* saving things into the archive (no) and with everything requiring filenames
225+
* and not streams (also no), so for the purposes of making drag/drop more robust,
226+
* I am not building this out just yet.
227+
* -- Adam Michaud (Invariel)
228+
229+
int offset = 0;
230+
bool executable = false;
231+
var archiveHandler = new SevenZipSharpArchiveHandler();
232+
233+
// Not going to process nested archives at the moment.
234+
if (String.IsNullOrEmpty (archive) && archiveHandler.CheckSignature(file, out offset, out executable))
235+
{
236+
List<string> fileNames = new List<string>();
237+
var openedArchive = archiveHandler.Construct (file);
238+
239+
foreach (BizHawk.Common.HawkFileArchiveItem item in openedArchive.Scan ())
240+
fileNames.Add(item.Name);
241+
242+
ProcessFileList(fileNames.ToArray(), ref sortedFiles, file);
243+
244+
openedArchive.Dispose();
245+
}
246+
archiveHandler.Dispose();
247+
*/
248+
}
249+
break;
250+
}
251+
}
252+
}
253+
254+
private void _FormDragDrop_internal(object sender, DragEventArgs e)
255+
{
256+
/*
257+
* Refactor, moving the loading of particular files into separate functions that can
258+
* then be used by this code, and loading individual files through the file dialogue.
259+
*
260+
* Step 1:
261+
* Build a dictionary of relevant files from everything that was dragged and dropped.
262+
* This includes peeking into all relevant archives and using their files.
263+
*
264+
* Step 2:
265+
* Perhaps ask the user which of a particular file type they want to use.
266+
* Example: rom1.nes, rom2.smc, rom3.cue are drag-dropped, ask the user which they want to use.
267+
*
268+
* Step 3:
269+
* Load all of the relevant files, in priority order:
270+
* 1) The ROM
271+
* 2) State
272+
* 3) Watch files
273+
* 4) Code Data Logger (CDL)
274+
* 5) LUA sessions
275+
* 6) LUA scripts
276+
* 7) Cheat files
277+
* 8) Movie Playback Files
278+
*
279+
* Bonus:
280+
* Make that order easy to change in the code, heavily suggesting ROM and playback as first and last respectively.
281+
*/
282+
283+
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
284+
Dictionary<LoadOrdering, List<FileInformation>> sortedFiles = new Dictionary<LoadOrdering, List<FileInformation>>();
285+
286+
// Initialize the dictionary's lists.
287+
foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
288+
{
289+
sortedFiles.Add(value, new List<FileInformation>());
290+
}
291+
292+
ProcessFileList(filePaths, ref sortedFiles, null);
293+
294+
// For each of the different types of item, if there are no items of that type, skip them.
295+
// If there is exactly one of that type of item, load it.
296+
// If there is more than one, ask.
297+
298+
foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
299+
{
300+
switch (sortedFiles[value].Count)
301+
{
302+
case 0:
303+
break;
304+
case 1:
305+
FileInformation fileInformation = sortedFiles[value].First<FileInformation>();
306+
string filename = Path.Combine(new string[] { fileInformation.directoryName, fileInformation.fileName });
307+
308+
switch (value)
309+
{
310+
case LoadOrdering.ROM:
311+
_LoadRom(filename, fileInformation.archiveName);
312+
break;
313+
case LoadOrdering.STATE:
314+
_LoadState(filename, fileInformation.archiveName);
315+
break;
316+
case LoadOrdering.WATCH:
317+
_LoadWatch(filename, fileInformation.archiveName);
318+
break;
319+
case LoadOrdering.CDLFILE:
320+
_LoadCDL(filename, fileInformation.archiveName);
321+
break;
322+
case LoadOrdering.LUASESSION:
323+
_LoadLuaSession(filename, fileInformation.archiveName);
324+
break;
325+
case LoadOrdering.LUASCRIPT:
326+
_LoadLuaFile(filename, fileInformation.archiveName);
327+
break;
328+
case LoadOrdering.CHEAT:
329+
_LoadCheats(filename, fileInformation.archiveName);
330+
break;
331+
case LoadOrdering.MOVIEFILE:
332+
case LoadOrdering.LEGACYMOVIEFILE:
333+
// I don't really like this hack, but for now, we only want to load one movie file.
334+
if (sortedFiles[LoadOrdering.MOVIEFILE].Count + sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Count > 1)
335+
break;
336+
337+
if (value == LoadOrdering.MOVIEFILE)
338+
_LoadMovie(filename, fileInformation.archiveName);
339+
else
340+
_LoadLegacyMovie(filename, fileInformation.archiveName);
341+
break;
342+
}
343+
break;
344+
default:
345+
break;
346+
}
347+
}
348+
}
349+
}
350+
}

BizHawk.Client.EmuHawk/MainForm.Events.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,8 @@ private void FormDragDrop(object sender, DragEventArgs e)
27532753

27542754
private void FormDragDrop_internal(object sender, DragEventArgs e)
27552755
{
2756+
_FormDragDrop_internal(sender, e);
2757+
/*
27562758
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
27572759
var isLua = false;
27582760
foreach (var path in filePaths)
@@ -2853,6 +2855,7 @@ private void FormDragDrop_internal(object sender, DragEventArgs e)
28532855
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePaths[0] };
28542856
LoadRom(filePaths[0], args);
28552857
}
2858+
*/
28562859
}
28572860

28582861
#endregion

0 commit comments

Comments
 (0)