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+ }
0 commit comments