1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.IO.Compression;
5 using System.Linq;
6 using System.Text;
7 using System.Text.RegularExpressions;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10 using Mesen.GUI.Config;
11 using Mesen.GUI.Debugger;
12 using Mesen.GUI.Forms.Cheats;
13 using Mesen.GUI.Forms.HdPackEditor;
14 using Mesen.GUI.Forms.NetPlay;
15 
16 namespace Mesen.GUI.Forms
17 {
18 	public partial class frmMain
19 	{
mnuDebug_DropDownOpening(object sender, EventArgs e)20 		private void mnuDebug_DropDownOpening(object sender, EventArgs e)
21 		{
22 			mnuEditHeader.Enabled = _emuThread != null && InteropEmu.GetRomInfo().Format == RomFormat.iNes;
23 		}
24 
mnuEditHeader_Click(object sender, EventArgs e)25 		private void mnuEditHeader_Click(object sender, EventArgs e)
26 		{
27 			using(frmEditHeader frm = new frmEditHeader()) {
28 				frm.ShowDialog(sender, this);
29 			}
30 		}
31 
mnuPlayMovie_Click(object sender, EventArgs e)32 		private void mnuPlayMovie_Click(object sender, EventArgs e)
33 		{
34 			using(OpenFileDialog ofd = new OpenFileDialog()) {
35 				ofd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
36 				ofd.InitialDirectory = ConfigManager.MovieFolder;
37 				if(ofd.ShowDialog(this) == System.Windows.Forms.DialogResult.OK) {
38 					InteropEmu.MoviePlay(ofd.FileName);
39 				}
40 			}
41 		}
42 
mnuStopMovie_Click(object sender, EventArgs e)43 		private void mnuStopMovie_Click(object sender, EventArgs e)
44 		{
45 			InteropEmu.MovieStop();
46 		}
47 
mnuRecordMovie_Click(object sender, EventArgs e)48 		private void mnuRecordMovie_Click(object sender, EventArgs e)
49 		{
50 			using(frmRecordMovie frm = new frmRecordMovie()) {
51 				frm.ShowDialog(mnuMovies, this);
52 			}
53 		}
54 
mnuWaveRecord_Click(object sender, EventArgs e)55 		private void mnuWaveRecord_Click(object sender, EventArgs e)
56 		{
57 			using(SaveFileDialog sfd = new SaveFileDialog()) {
58 				sfd.SetFilter(ResourceHelper.GetMessage("FilterWave"));
59 				sfd.InitialDirectory = ConfigManager.WaveFolder;
60 				sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".wav";
61 				if(sfd.ShowDialog(this) == System.Windows.Forms.DialogResult.OK) {
62 					InteropEmu.WaveRecord(sfd.FileName);
63 				}
64 			}
65 		}
66 
mnuWaveStop_Click(object sender, EventArgs e)67 		private void mnuWaveStop_Click(object sender, EventArgs e)
68 		{
69 			InteropEmu.WaveStop();
70 		}
71 
mnuAviRecord_Click(object sender, EventArgs e)72 		private void mnuAviRecord_Click(object sender, EventArgs e)
73 		{
74 			using(frmRecordAvi frm = new frmRecordAvi()) {
75 				if(frm.ShowDialog(mnuVideoRecorder, this) == DialogResult.OK) {
76 					InteropEmu.AviRecord(frm.Filename, ConfigManager.Config.AviRecordInfo.Codec, ConfigManager.Config.AviRecordInfo.CompressionLevel);
77 				}
78 			}
79 		}
80 
mnuAviStop_Click(object sender, EventArgs e)81 		private void mnuAviStop_Click(object sender, EventArgs e)
82 		{
83 			InteropEmu.AviStop();
84 		}
85 
mnuCheats_Click(object sender, EventArgs e)86 		private void mnuCheats_Click(object sender, EventArgs e)
87 		{
88 			if(_cheatListWindow == null) {
89 				_cheatListWindow = new frmCheatList();
90 				_cheatListWindow.Show(sender, this);
91 				_cheatListWindow.FormClosed += (s, evt) => {
92 					CheatInfo.ApplyCheats();
93 					_cheatListWindow = null;
94 				};
95 			} else {
96 				_cheatListWindow.WindowState = FormWindowState.Normal;
97 				_cheatListWindow.BringToFront();
98 				_cheatListWindow.Focus();
99 			}
100 		}
101 
mnuHistoryViewer_Click(object sender, EventArgs e)102 		private void mnuHistoryViewer_Click(object sender, EventArgs e)
103 		{
104 			if(_historyViewerWindow == null) {
105 				_historyViewerWindow = new frmHistoryViewer();
106 				_historyViewerWindow.Show(sender, this);
107 				_historyViewerWindow.FormClosed += (s, evt) => {
108 					_historyViewerWindow = null;
109 				};
110 			} else {
111 				_historyViewerWindow.WindowState = FormWindowState.Normal;
112 				_historyViewerWindow.BringToFront();
113 				_historyViewerWindow.Focus();
114 			}
115 		}
116 
LoadRandomGame()117 		private void LoadRandomGame()
118 		{
119 			IEnumerable<string> gameFolders;
120 			SearchOption searchOptions = SearchOption.TopDirectoryOnly;
121 			if(ConfigManager.Config.PreferenceInfo.OverrideGameFolder && Directory.Exists(ConfigManager.Config.PreferenceInfo.GameFolder)) {
122 				gameFolders = new List<string>() { ConfigManager.Config.PreferenceInfo.GameFolder };
123 				searchOptions = SearchOption.AllDirectories;
124 			} else {
125 				gameFolders = ConfigManager.Config.RecentFiles.Select(recentFile => recentFile.RomFile.Folder.ToLowerInvariant()).Distinct();
126 			}
127 			List<string> gameRoms = new List<string>();
128 
129 			foreach(string folder in gameFolders) {
130 				if(Directory.Exists(folder)) {
131 					gameRoms.AddRange(Directory.EnumerateFiles(folder, "*.nes", searchOptions));
132 					gameRoms.AddRange(Directory.EnumerateFiles(folder, "*.unf", searchOptions));
133 					gameRoms.AddRange(Directory.EnumerateFiles(folder, "*.unif", searchOptions));
134 					gameRoms.AddRange(Directory.EnumerateFiles(folder, "*.fds", searchOptions));
135 
136 					if(searchOptions == SearchOption.AllDirectories) {
137 						//When loading from a user-specified folder, assume zip/7z files will likely contain a ROM
138 						gameRoms.AddRange(Directory.EnumerateFiles(folder, "*.zip", searchOptions));
139 						gameRoms.AddRange(Directory.EnumerateFiles(folder, "*.7z", searchOptions));
140 					}
141 				}
142 			}
143 
144 			if(gameRoms.Count == 0) {
145 				MesenMsgBox.Show("RandomGameNoGameFound", MessageBoxButtons.OK, MessageBoxIcon.Information);
146 			} else {
147 				int retryCount = 0;
148 				Random random = new Random();
149 				do {
150 					string randomGame = gameRoms[random.Next(gameRoms.Count)];
151 
152 					if(randomGame.EndsWith(".7z", StringComparison.InvariantCultureIgnoreCase) || randomGame.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) {
153 						List<InteropEmu.ArchiveRomEntry> archiveRomList = InteropEmu.GetArchiveRomList(randomGame);
154 						if(archiveRomList.Count > 0) {
155 							ResourcePath res = new ResourcePath() {
156 								InnerFile = archiveRomList[0].Filename,
157 								Path = randomGame
158 							};
159 							if(!archiveRomList[0].IsUtf8) {
160 								res.InnerFileIndex = 1;
161 							}
162 							LoadROM(res);
163 							break;
164 						} else {
165 							retryCount++;
166 						}
167 					} else {
168 						LoadFile(randomGame);
169 						break;
170 					}
171 				} while(retryCount < 5);
172 			}
173 		}
174 
mnuLogWindow_Click(object sender, EventArgs e)175 		private void mnuLogWindow_Click(object sender, EventArgs e)
176 		{
177 			if(_logWindow == null) {
178 				_logWindow = new frmLogWindow();
179 				_logWindow.Show(sender, this);
180 				_logWindow.FormClosed += (object a, FormClosedEventArgs b) => {
181 					_logWindow = null;
182 				};
183 			} else {
184 				_logWindow.WindowState = FormWindowState.Normal;
185 				_logWindow.BringToFront();
186 				_logWindow.Focus();
187 			}
188 		}
189 
mnuInstallHdPack_Click(object sender, EventArgs e)190 		private void mnuInstallHdPack_Click(object sender, EventArgs e)
191 		{
192 			using(OpenFileDialog ofd = new OpenFileDialog()) {
193 				ofd.SetFilter(ResourceHelper.GetMessage("FilterZipFiles"));
194 				if(ofd.ShowDialog(this) == DialogResult.OK) {
195 					try {
196 						using(FileStream stream = File.Open(ofd.FileName, FileMode.Open)) {
197 							ZipArchive zip = new ZipArchive(stream);
198 
199 							//Find the hires.txt file
200 							ZipArchiveEntry hiresEntry = null;
201 							foreach(ZipArchiveEntry entry in zip.Entries) {
202 								if(entry.Name == "hires.txt") {
203 									hiresEntry = entry;
204 									break;
205 								}
206 							}
207 
208 							if(hiresEntry != null) {
209 								using(Stream entryStream = hiresEntry.Open()) {
210 									using(StreamReader reader = new StreamReader(entryStream)) {
211 										string hiresData = reader.ReadToEnd();
212 										RomInfo romInfo = InteropEmu.GetRomInfo();
213 
214 										//If there's a "supportedRom" tag, check if it matches the current ROM
215 										Regex supportedRomRegex = new Regex("<supportedRom>([^\\n]*)");
216 										Match match = supportedRomRegex.Match(hiresData);
217 										if(match.Success) {
218 											if(!match.Groups[1].Value.ToUpper().Contains(InteropEmu.GetRomInfo().Sha1.ToUpper())) {
219 												MesenMsgBox.Show("InstallHdPackWrongRom", MessageBoxButtons.OK, MessageBoxIcon.Error);
220 												return;
221 											}
222 										}
223 
224 										//Extract HD pack
225 										try {
226 											string targetFolder = Path.Combine(ConfigManager.HdPackFolder, romInfo.GetRomName());
227 											if(Directory.Exists(targetFolder)) {
228 												//Warn if the folder already exists
229 												if(MesenMsgBox.Show("InstallHdPackConfirmOverwrite", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, targetFolder) != DialogResult.OK) {
230 													return;
231 												}
232 											} else {
233 												Directory.CreateDirectory(targetFolder);
234 											}
235 
236 											string hiresFileFolder = hiresEntry.FullName.Substring(0, hiresEntry.FullName.Length - "hires.txt".Length);
237 											foreach(ZipArchiveEntry entry in zip.Entries) {
238 												//Extract only the files in the same subfolder as the hires.txt file (and only if they have a name & size > 0)
239 												if(!string.IsNullOrWhiteSpace(entry.Name) && entry.Length > 0 && entry.FullName.StartsWith(hiresFileFolder)) {
240 													entry.ExtractToFile(Path.Combine(targetFolder, entry.Name), true);
241 												}
242 											}
243 										} catch(Exception ex) {
244 											MesenMsgBox.Show("InstallHdPackError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString());
245 											return;
246 										}
247 									}
248 
249 									//Turn on HD Pack support automatically after installation succeeds
250 									ConfigManager.Config.VideoInfo.UseHdPacks = true;
251 									ConfigManager.ApplyChanges();
252 									ConfigManager.Config.ApplyConfig();
253 
254 									if(MesenMsgBox.Show("InstallHdPackConfirmReset", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) {
255 										//Power cycle game if the user agrees
256 										InteropEmu.PowerCycle();
257 									}
258 								}
259 							} else {
260 								MesenMsgBox.Show("InstallHdPackInvalidPack", MessageBoxButtons.OK, MessageBoxIcon.Error);
261 							}
262 						}
263 					} catch {
264 						//Invalid file (file missing, not a zip file, etc.)
265 						MesenMsgBox.Show("InstallHdPackInvalidZipFile", MessageBoxButtons.OK, MessageBoxIcon.Error);
266 					}
267 				}
268 			}
269 		}
270 
mnuHdPackEditor_Click(object sender, EventArgs e)271 		private void mnuHdPackEditor_Click(object sender, EventArgs e)
272 		{
273 			if(_hdPackEditorWindow == null) {
274 				_hdPackEditorWindow = new frmHdPackEditor();
275 				_hdPackEditorWindow.Show(sender, this);
276 				_hdPackEditorWindow.FormClosed += (object a, FormClosedEventArgs b) => {
277 					_hdPackEditorWindow = null;
278 				};
279 			} else {
280 				_hdPackEditorWindow.WindowState = FormWindowState.Normal;
281 				_hdPackEditorWindow.BringToFront();
282 				_hdPackEditorWindow.Focus();
283 			}
284 		}
285 
mnuStartServer_Click(object sender, EventArgs e)286 		private void mnuStartServer_Click(object sender, EventArgs e)
287 		{
288 			if(InteropEmu.IsServerRunning()) {
289 				Task.Run(() => InteropEmu.StopServer());
290 			} else {
291 				using(frmServerConfig frm = new frmServerConfig()) {
292 					if(frm.ShowDialog(sender, this) == System.Windows.Forms.DialogResult.OK) {
293 						InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port, ConfigManager.Config.ServerInfo.Password, ConfigManager.Config.Profile.PlayerName);
294 					}
295 				}
296 			}
297 		}
298 
mnuConnect_Click(object sender, EventArgs e)299 		private void mnuConnect_Click(object sender, EventArgs e)
300 		{
301 			if(InteropEmu.IsConnected()) {
302 				Task.Run(() => InteropEmu.Disconnect());
303 			} else {
304 				using(frmClientConfig frm = new frmClientConfig()) {
305 					if(frm.ShowDialog(sender, this) == System.Windows.Forms.DialogResult.OK) {
306 						Task.Run(() => {
307 							InteropEmu.Connect(
308 								ConfigManager.Config.ClientConnectionInfo.Host,
309 								ConfigManager.Config.ClientConnectionInfo.Port,
310 								ConfigManager.Config.ClientConnectionInfo.Password,
311 								ConfigManager.Config.Profile.PlayerName,
312 								ConfigManager.Config.ClientConnectionInfo.Spectator
313 							);
314 						});
315 					}
316 				}
317 			}
318 		}
319 
mnuProfile_Click(object sender, EventArgs e)320 		private void mnuProfile_Click(object sender, EventArgs e)
321 		{
322 			using(frmPlayerProfile frm = new frmPlayerProfile()) {
323 				frm.ShowDialog(sender, this);
324 			}
325 		}
326 
mnuNetPlayPlayer1_Click(object sender, EventArgs e)327 		private void mnuNetPlayPlayer1_Click(object sender, EventArgs e)
328 		{
329 			InteropEmu.NetPlaySelectController(0);
330 		}
331 
mnuNetPlayPlayer2_Click(object sender, EventArgs e)332 		private void mnuNetPlayPlayer2_Click(object sender, EventArgs e)
333 		{
334 			InteropEmu.NetPlaySelectController(1);
335 		}
336 
mnuNetPlayPlayer3_Click(object sender, EventArgs e)337 		private void mnuNetPlayPlayer3_Click(object sender, EventArgs e)
338 		{
339 			InteropEmu.NetPlaySelectController(2);
340 		}
341 
mnuNetPlayPlayer4_Click(object sender, EventArgs e)342 		private void mnuNetPlayPlayer4_Click(object sender, EventArgs e)
343 		{
344 			InteropEmu.NetPlaySelectController(3);
345 		}
346 
mnuNetPlayPlayer5_Click(object sender, EventArgs e)347 		private void mnuNetPlayPlayer5_Click(object sender, EventArgs e)
348 		{
349 			InteropEmu.NetPlaySelectController(4);
350 		}
351 
mnuNetPlaySpectator_Click(object sender, EventArgs e)352 		private void mnuNetPlaySpectator_Click(object sender, EventArgs e)
353 		{
354 			InteropEmu.NetPlaySelectController(0xFF);
355 		}
356 
mnuApuViewer_Click(object sender, EventArgs e)357 		private void mnuApuViewer_Click(object sender, EventArgs e)
358 		{
359 			DebugWindowManager.OpenDebugWindow(DebugWindow.ApuViewer);
360 		}
361 
mnuAssembler_Click(object sender, EventArgs e)362 		private void mnuAssembler_Click(object sender, EventArgs e)
363 		{
364 			DebugWindowManager.OpenDebugWindow(DebugWindow.Assembler);
365 		}
366 
mnuDebugger_Click(object sender, EventArgs e)367 		private void mnuDebugger_Click(object sender, EventArgs e)
368 		{
369 			DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger);
370 		}
371 
mnuDebugDebugger_Click(object sender, EventArgs e)372 		private void mnuDebugDebugger_Click(object sender, EventArgs e)
373 		{
374 			DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger);
375 		}
376 
mnuMemoryViewer_Click(object sender, EventArgs e)377 		private void mnuMemoryViewer_Click(object sender, EventArgs e)
378 		{
379 			DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryViewer);
380 		}
381 
mnuEventViewer_Click(object sender, EventArgs e)382 		private void mnuEventViewer_Click(object sender, EventArgs e)
383 		{
384 			DebugWindowManager.OpenDebugWindow(DebugWindow.EventViewer);
385 		}
386 
mnuPpuViewer_Click(object sender, EventArgs e)387 		private void mnuPpuViewer_Click(object sender, EventArgs e)
388 		{
389 			DebugWindowManager.OpenDebugWindow(DebugWindow.PpuViewer);
390 		}
391 
mnuScriptWindow_Click(object sender, EventArgs e)392 		private void mnuScriptWindow_Click(object sender, EventArgs e)
393 		{
394 			DebugWindowManager.OpenDebugWindow(DebugWindow.ScriptWindow);
395 		}
396 
mnuTraceLogger_Click(object sender, EventArgs e)397 		private void mnuTraceLogger_Click(object sender, EventArgs e)
398 		{
399 			DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger);
400 		}
401 
mnuWatchWindow_Click(object sender, EventArgs e)402 		private void mnuWatchWindow_Click(object sender, EventArgs e)
403 		{
404 			DebugWindowManager.OpenDebugWindow(DebugWindow.WatchWindow);
405 		}
406 
mnuTextHooker_Click(object sender, EventArgs e)407 		private void mnuTextHooker_Click(object sender, EventArgs e)
408 		{
409 			DebugWindowManager.OpenDebugWindow(DebugWindow.TextHooker);
410 		}
411 
mnuProfiler_Click(object sender, EventArgs e)412 		private void mnuProfiler_Click(object sender, EventArgs e)
413 		{
414 			DebugWindowManager.OpenDebugWindow(DebugWindow.Profiler);
415 		}
416 
mnuOpenNametableViewer_Click(object sender, EventArgs e)417 		private void mnuOpenNametableViewer_Click(object sender, EventArgs e)
418 		{
419 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.NametableViewer);
420 		}
421 
mnuOpenChrViewer_Click(object sender, EventArgs e)422 		private void mnuOpenChrViewer_Click(object sender, EventArgs e)
423 		{
424 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.ChrViewer);
425 		}
426 
mnuOpenSpriteViewer_Click(object sender, EventArgs e)427 		private void mnuOpenSpriteViewer_Click(object sender, EventArgs e)
428 		{
429 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.SpriteViewer);
430 		}
431 
mnuOpenPaletteViewer_Click(object sender, EventArgs e)432 		private void mnuOpenPaletteViewer_Click(object sender, EventArgs e)
433 		{
434 			DebugWindowManager.OpenPpuViewer(PpuViewerMode.PaletteViewer);
435 		}
436 
mnuDebugDualSystemSecondaryCpu_Click(object sender, EventArgs e)437 		private void mnuDebugDualSystemSecondaryCpu_Click(object sender, EventArgs e)
438 		{
439 			bool switchCpu = false;
440 
441 			if(!DebugWindowManager.HasOpenedWindow) {
442 				switchCpu = true;
443 			} else {
444 				if(MessageBox.Show("Warning: Changing this setting will close all currently opened debug tools!", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) {
445 					DebugWindowManager.CloseAll();
446 					if(!DebugWindowManager.HasOpenedWindow) {
447 						switchCpu = true;
448 					}
449 				}
450 			}
451 
452 			if(switchCpu) {
453 				mnuDebugDualSystemSecondaryCpu.Checked = !mnuDebugDualSystemSecondaryCpu.Checked;
454 				ConfigManager.Config.DebugInfo.DebugConsoleId = mnuDebugDualSystemSecondaryCpu.Checked ? InteropEmu.ConsoleId.Slave : InteropEmu.ConsoleId.Master;
455 				ConfigManager.ApplyChanges();
456 				InteropEmu.DebugSetDebuggerConsole(ConfigManager.Config.DebugInfo.DebugConsoleId);
457 			}
458 		}
459 	}
460 
461 }
462