1 /***********************************************************************************
2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4 (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
5 Jerremy Koot (jkoot@snes9x.com)
6
7 (c) Copyright 2002 - 2004 Matthew Kendora
8
9 (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
10
11 (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
12
13 (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
14
15 (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
16 Kris Bleakley (codeviolation@hotmail.com)
17
18 (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
19 Nach (n-a-c-h@users.sourceforge.net),
20
21 (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
22
23 (c) Copyright 2006 - 2007 nitsuja
24
25 (c) Copyright 2009 - 2016 BearOso,
26 OV2
27
28
29 BS-X C emulator code
30 (c) Copyright 2005 - 2006 Dreamer Nom,
31 zones
32
33 C4 x86 assembler and some C emulation code
34 (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
35 Nach,
36 zsKnight (zsknight@zsnes.com)
37
38 C4 C++ code
39 (c) Copyright 2003 - 2006 Brad Jorsch,
40 Nach
41
42 DSP-1 emulator code
43 (c) Copyright 1998 - 2006 _Demo_,
44 Andreas Naive (andreasnaive@gmail.com),
45 Gary Henderson,
46 Ivar (ivar@snes9x.com),
47 John Weidman,
48 Kris Bleakley,
49 Matthew Kendora,
50 Nach,
51 neviksti (neviksti@hotmail.com)
52
53 DSP-2 emulator code
54 (c) Copyright 2003 John Weidman,
55 Kris Bleakley,
56 Lord Nightmare (lord_nightmare@users.sourceforge.net),
57 Matthew Kendora,
58 neviksti
59
60 DSP-3 emulator code
61 (c) Copyright 2003 - 2006 John Weidman,
62 Kris Bleakley,
63 Lancer,
64 z80 gaiden
65
66 DSP-4 emulator code
67 (c) Copyright 2004 - 2006 Dreamer Nom,
68 John Weidman,
69 Kris Bleakley,
70 Nach,
71 z80 gaiden
72
73 OBC1 emulator code
74 (c) Copyright 2001 - 2004 zsKnight,
75 pagefault (pagefault@zsnes.com),
76 Kris Bleakley
77 Ported from x86 assembler to C by sanmaiwashi
78
79 SPC7110 and RTC C++ emulator code used in 1.39-1.51
80 (c) Copyright 2002 Matthew Kendora with research by
81 zsKnight,
82 John Weidman,
83 Dark Force
84
85 SPC7110 and RTC C++ emulator code used in 1.52+
86 (c) Copyright 2009 byuu,
87 neviksti
88
89 S-DD1 C emulator code
90 (c) Copyright 2003 Brad Jorsch with research by
91 Andreas Naive,
92 John Weidman
93
94 S-RTC C emulator code
95 (c) Copyright 2001 - 2006 byuu,
96 John Weidman
97
98 ST010 C++ emulator code
99 (c) Copyright 2003 Feather,
100 John Weidman,
101 Kris Bleakley,
102 Matthew Kendora
103
104 Super FX x86 assembler emulator code
105 (c) Copyright 1998 - 2003 _Demo_,
106 pagefault,
107 zsKnight
108
109 Super FX C emulator code
110 (c) Copyright 1997 - 1999 Ivar,
111 Gary Henderson,
112 John Weidman
113
114 Sound emulator code used in 1.5-1.51
115 (c) Copyright 1998 - 2003 Brad Martin
116 (c) Copyright 1998 - 2006 Charles Bilyue'
117
118 Sound emulator code used in 1.52+
119 (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
120
121 S-SMP emulator code used in 1.54+
122 (c) Copyright 2016 byuu
123
124 SH assembler code partly based on x86 assembler code
125 (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
126
127 2xSaI filter
128 (c) Copyright 1999 - 2001 Derek Liauw Kie Fa
129
130 HQ2x, HQ3x, HQ4x filters
131 (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
132
133 NTSC filter
134 (c) Copyright 2006 - 2007 Shay Green
135
136 GTK+ GUI code
137 (c) Copyright 2004 - 2016 BearOso
138
139 Win32 GUI code
140 (c) Copyright 2003 - 2006 blip,
141 funkyass,
142 Matthew Kendora,
143 Nach,
144 nitsuja
145 (c) Copyright 2009 - 2016 OV2
146
147 Mac OS GUI code
148 (c) Copyright 1998 - 2001 John Stiles
149 (c) Copyright 2001 - 2011 zones
150
151
152 Specific ports contains the works of other authors. See headers in
153 individual files.
154
155
156 Snes9x homepage: http://www.snes9x.com/
157
158 Permission to use, copy, modify and/or distribute Snes9x in both binary
159 and source form, for non-commercial purposes, is hereby granted without
160 fee, providing that this license information and copyright notice appear
161 with all copies and any derived work.
162
163 This software is provided 'as-is', without any express or implied
164 warranty. In no event shall the authors be held liable for any damages
165 arising from the use of this software or it's derivatives.
166
167 Snes9x is freeware for PERSONAL USE only. Commercial users should
168 seek permission of the copyright holders first. Commercial use includes,
169 but is not limited to, charging money for Snes9x or software derived from
170 Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
171 using Snes9x as a promotion for your commercial product.
172
173 The copyright holders request that bug fixes and improvements to the code
174 should be forwarded to them so everyone can benefit from the modifications
175 in future versions.
176
177 Super NES and Super Nintendo Entertainment System are trademarks of
178 Nintendo Co., Limited and its subsidiary companies.
179 ***********************************************************************************/
180
181
182 #pragma comment(linker, \
183 "\"/manifestdependency:type='Win32' "\
184 "name='Microsoft.Windows.Common-Controls' "\
185 "version='6.0.0.0' "\
186 "processorArchitecture='*' "\
187 "publicKeyToken='6595b64144ccf1df' "\
188 "language='*'\"")
189
190
191 // Win32 GUI code
192 // (c) Copyright 2003-2006 blip, Nach, Matthew Kendora, funkyass and nitsuja
193
194 #ifdef __MINGW32__
195 #define _WIN32_IE 0x0501
196 #define _WIN32_WINNT 0x0501
197 #endif
198
199 #include <shlobj.h>
200 #include <objidl.h>
201 #include <shlwapi.h>
202 #include <Shobjidl.h>
203 #include <dbt.h>
204
205 #include "wsnes9x.h"
206 #include "win32_sound.h"
207 #include "win32_display.h"
208 #include "CCGShader.h"
209 #include "../snes9x.h"
210 #include "../memmap.h"
211 #include "../cpuexec.h"
212 #include "../display.h"
213 #include "../cheats.h"
214 #include "../netplay.h"
215 #include "../apu/apu.h"
216 #include "../movie.h"
217 #include "../controls.h"
218 #include "../conffile.h"
219 #include "../statemanager.h"
220 #include "AVIOutput.h"
221 #include "InputCustom.h"
222 #include <vector>
223
224 #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__))
225 // both MINGW and VS.NET use fstream instead of fstream.h which is deprecated
226 #include <fstream>
227 using namespace std;
228 #else
229 // for VC++ 6
230 #include <fstream.h>
231 #endif
232
233 #include <sys/stat.h>
234 //#include "string_cache.h"
235 #include "wlanguage.h"
236 #include "../language.h"
237
238 //uncomment to find memory leaks, with a line in WinMain
239 //#define CHECK_MEMORY_LEAKS
240
241 #ifdef CHECK_MEMORY_LEAKS
242 #include <crtdbg.h>
243 #endif
244
245 #include <commctrl.h>
246 #include <io.h>
247 #include <time.h>
248 #include <direct.h>
249
250 extern SNPServer NPServer;
251
252 #include <ctype.h>
253
254 #ifdef _MSC_VER
255 #define F_OK 0
256 #define X_OK 1
257 #define W_OK 2
258 #define R_OK 4
259 #endif
260
261 __int64 PCBase, PCFrameTime, PCFrameTimeNTSC, PCFrameTimePAL, PCStart, PCEnd;
262 DWORD PCStartTicks, PCEndTicks;
263
264 INT_PTR CALLBACK DlgSP7PackConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
265 INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
266 INT_PTR CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
267 INT_PTR CALLBACK DlgAboutProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
268 INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
269
270 INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
271 INT_PTR CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
272 LRESULT CALLBACK DlgChildSplitProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
273 INT_PTR CALLBACK DlgNPProgress(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
274 INT_PTR CALLBACK DlgPackConfigProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
275 INT_PTR CALLBACK DlgNetConnect(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
276 INT_PTR CALLBACK DlgNPOptions(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
277 INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
278 INT_PTR CALLBACK DlgInputConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
279 INT_PTR CALLBACK DlgHotkeyConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
280 INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
281 INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
282 INT_PTR CALLBACK DlgCheatSearchAdd(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
283 INT_PTR CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
284 INT_PTR CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
285 HRESULT CALLBACK EnumModesCallback( LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext);
286
287 VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
288
289 void S9xDetectJoypads();
290
291 #define NOTKNOWN "Unknown Company "
292 #define HEADER_SIZE 512
293 #define INFO_LEN (0xFF - 0xC0)
294
295 #define WM_CUSTKEYDOWN (WM_USER+50)
296 #define WM_CUSTKEYUP (WM_USER+51)
297 #define WM_SCANJOYPADS (WM_APP+10)
298
299 #ifdef UNICODE
300 #define S9XW_SHARD_PATH SHARD_PATHW
301 #else
302 #define S9XW_SHARD_PATH SHARD_PATHA
303 #endif
304
305 /*****************************************************************************/
306 /* Global variables */
307 /*****************************************************************************/
308 struct sGUI GUI;
309 typedef struct sExtList
310 {
311 TCHAR* extension;
312 bool compressed;
313 struct sExtList* next;
314 } ExtList;
315 HANDLE SoundEvent;
316
317 ExtList* valid_ext=NULL;
318 void MakeExtFile(void);
319 void LoadExts(void);
320 static bool ExtensionIsValid(const TCHAR *filename);
321
322 extern FILE *trace_fs;
323 extern SCheatData Cheat;
324 extern bool8 do_frame_adjust;
325
326 HINSTANCE g_hInst;
327
328 #ifdef DEBUGGER
329 #include "../debug.h"
330 #endif
331
332 struct SJoypad Joypad[16] = {
333 {
334 true, /* Joypad 1 enabled */
335 VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, /* Left, Right, Up, Down */
336 0, 0, 0, 0, /* Left_Up, Left_Down, Right_Up, Right_Down */
337 VK_SPACE, VK_RETURN, /* Start, Select */
338 'V', 'C', /* A B */
339 'D', 'X', /* X Y */
340 'A', 'S' /* L R */
341 },
342 {
343 true, /* Joypad 2 enabled */
344 'J', 'L', 'I', 'K', /* Left, Right, Up, Down */
345 0, 0, 0, 0, /* Left_Up, Left_Down, Right_Up, Right_Down */
346 'P', 'O', /* Start, Select */
347 'H', 'G', /* A B */
348 'T', 'F', /* X Y */
349 'Y', 'U' /* L R */
350 },
351 {
352 false, /* Joypad 3 disabled */
353 0, 0, 0, 0,
354 0, 0, 0, 0,
355 0, 0,
356 0, 0, 0, 0, 0, 0
357 },
358 {
359 false, /* Joypad 4 disabled */
360 0, 0, 0, 0,
361 0, 0, 0, 0,
362 0, 0,
363 0, 0, 0, 0, 0, 0
364 },
365 {
366 false, /* Joypad 5 disabled */
367 0, 0, 0, 0,
368 0, 0, 0, 0,
369 0, 0,
370 0, 0, 0, 0, 0, 0
371 },
372 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 6 disabled */
373 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 7 disabled */
374 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 8 disabled */
375 {
376 false, /* Joypad 1 Turbo disabled */
377 0, 0, 0, 0,
378 0, 0, 0, 0,
379 0, 0,
380 0, 0, 0, 0, 0, 0
381 },
382 {
383 false, /* Joypad 2 Turbo disabled */
384 0, 0, 0, 0,
385 0, 0, 0, 0,
386 0, 0,
387 0, 0, 0, 0, 0, 0
388 },
389 {
390 false, /* Joypad 3 Turbo disabled */
391 0, 0, 0, 0,
392 0, 0, 0, 0,
393 0, 0,
394 0, 0, 0, 0, 0, 0
395 },
396 {
397 false, /* Joypad 4 Turbo disabled */
398 0, 0, 0, 0,
399 0, 0, 0, 0,
400 0, 0,
401 0, 0, 0, 0, 0, 0
402 },
403 {
404 false, /* Joypad 5 Turbo disabled */
405 0, 0, 0, 0,
406 0, 0, 0, 0,
407 0, 0,
408 0, 0, 0, 0, 0, 0
409 },
410 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 6 Turbo disabled */
411 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 7 Turbo disabled */
412 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 8 Turbo disabled */
413 };
414
415 // stores on/off toggle info for each key of each controller
416 SJoypad ToggleJoypadStorage [8] = {
417 {
418 false,
419 0, 0, 0, 0,
420 0, 0, 0, 0,
421 0, 0,
422 0, 0, 0, 0, 0, 0
423 },
424 {
425 false,
426 0, 0, 0, 0,
427 0, 0, 0, 0,
428 0, 0,
429 0, 0, 0, 0, 0, 0
430 },
431 {
432 false,
433 0, 0, 0, 0,
434 0, 0, 0, 0,
435 0, 0,
436 0, 0, 0, 0, 0, 0
437 },
438 {
439 false,
440 0, 0, 0, 0,
441 0, 0, 0, 0,
442 0, 0,
443 0, 0, 0, 0, 0, 0
444 },
445 {
446 false,
447 0, 0, 0, 0,
448 0, 0, 0, 0,
449 0, 0,
450 0, 0, 0, 0, 0, 0
451 },
452 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
453 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
454 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
455 };
456
457 SJoypad TurboToggleJoypadStorage [8] = {
458 {
459 false,
460 0, 0, 0, 0,
461 0, 0, 0, 0,
462 0, 0,
463 0, 0, 0, 0, 0, 0
464 },
465 {
466 false,
467 0, 0, 0, 0,
468 0, 0, 0, 0,
469 0, 0,
470 0, 0, 0, 0, 0, 0
471 },
472 {
473 false,
474 0, 0, 0, 0,
475 0, 0, 0, 0,
476 0, 0,
477 0, 0, 0, 0, 0, 0
478 },
479 {
480 false,
481 0, 0, 0, 0,
482 0, 0, 0, 0,
483 0, 0,
484 0, 0, 0, 0, 0, 0
485 },
486 {
487 false,
488 0, 0, 0, 0,
489 0, 0, 0, 0,
490 0, 0,
491 0, 0, 0, 0, 0, 0
492 },
493 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
494 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
495 { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
496 };
497
498 struct SCustomKeys CustomKeys = {
499 {/*VK_OEM_PLUS*/0xBB,0}, // speed+ (=)
500 {/*VK_OEM_MINUS*/0xBD,0}, // speed- (-)
501 {VK_PAUSE,0}, // pause (PAUSE)
502 {/*VK_OEM_5*/0xDC,0}, // frame advance (\)
503 {/*VK_OEM_PLUS*/0xBB,CUSTKEY_SHIFT_MASK}, // skip+ (_)
504 {/*VK_OEM_MINUS*/0xBD,CUSTKEY_SHIFT_MASK}, // skip- (+)
505 {/*VK_OEM_3*/0xC0,0}, // superscope turbo (`)
506 {/*VK_OEM_2*/0xBF,0}, // superscope pause (/)
507 {/*VK_OEM_PERIOD*/0xBE,0}, // frame counter (.)
508 {'8',CUSTKEY_SHIFT_MASK}, // movie read-only (*)
509 {{VK_F1,CUSTKEY_SHIFT_MASK}, // save keys
510 {VK_F2,CUSTKEY_SHIFT_MASK},
511 {VK_F3,CUSTKEY_SHIFT_MASK},
512 {VK_F4,CUSTKEY_SHIFT_MASK},
513 {VK_F5,CUSTKEY_SHIFT_MASK},
514 {VK_F6,CUSTKEY_SHIFT_MASK},
515 {VK_F7,CUSTKEY_SHIFT_MASK},
516 {VK_F8,CUSTKEY_SHIFT_MASK},
517 {VK_F9,CUSTKEY_SHIFT_MASK},
518 {VK_F10,CUSTKEY_SHIFT_MASK}},
519 {{VK_F1,0}, // load keys
520 {VK_F2,0},
521 {VK_F3,0},
522 {VK_F4,0},
523 {VK_F5,0},
524 {VK_F6,0},
525 {VK_F7,0},
526 {VK_F8,0},
527 {VK_F9,0},
528 {VK_F10,0}},
529 {VK_TAB,0}, // fast forward (TAB)
530 {0,0}, // fast forward toggle
531 {/*VK_OEM_COMMA*/0xBC,0}, // show pressed keys/buttons (,)
532 {VK_F12,0}, // save screenshot (F12)
533 {0,0}, // slot plus (disabled by default)
534 {0,0}, // slot minus (disabled by default)
535 {0,0}, // slot save (disabled by default)
536 {0,0}, // slot load (disabled by default)
537 {'1',0}, // background layer 1
538 {'2',0}, // background layer 2
539 {'3',0}, // background layer 3
540 {'4',0}, // background layer 4
541 {'5',0}, // sprite layer
542 {'8',0}, // Clipping Windows
543 // {'8',0}, // BG Layering hack
544 {'9',0}, // Transparency
545 // {'6',CUSTKEY_SHIFT_MASK}, // GLCube Mode
546 // {'9',CUSTKEY_SHIFT_MASK}, // Interpolate Mode 7
547 {'6',0}, // Joypad Swap
548 {'7',0}, // Switch Controllers
549 {VK_NEXT,CUSTKEY_SHIFT_MASK}, // Turbo A
550 {VK_END,CUSTKEY_SHIFT_MASK}, // Turbo B
551 {VK_HOME,CUSTKEY_SHIFT_MASK}, // Turbo Y
552 {VK_PRIOR,CUSTKEY_SHIFT_MASK}, // Turbo X
553 {VK_INSERT,CUSTKEY_SHIFT_MASK}, // Turbo L
554 {VK_DELETE,CUSTKEY_SHIFT_MASK}, // Turbo R
555 {0,0}, // Turbo Start
556 {0,0}, // Turbo Select
557 {0,0}, // Turbo Left
558 {0,0}, // Turbo Up
559 {0,0}, // Turbo Right
560 {0,0}, // Turbo Down
561 {{0,0}, // Select save slot 0
562 {0,0}, // Select save slot 1
563 {0,0}, // Select save slot 2
564 {0,0}, // Select save slot 3
565 {0,0}, // Select save slot 4
566 {0,0}, // Select save slot 5
567 {0,0}, // Select save slot 6
568 {0,0}, // Select save slot 7
569 {0,0}, // Select save slot 8
570 {0,0}}, // Select save slot 9
571 {'R',CUSTKEY_CTRL_MASK|CUSTKEY_SHIFT_MASK}, // Reset Game
572 {0,0}, // Toggle Cheats
573 {0,0},
574 {'R',0}, // Rewind
575 };
576
577
578 struct SSoundRates
579 {
580 uint32 rate;
581 int ident;
582 } SoundRates[9] = {
583 { 8000, ID_SOUND_8000HZ},
584 {11025, ID_SOUND_11025HZ},
585 {16000, ID_SOUND_16000HZ},
586 {22050, ID_SOUND_22050HZ},
587 {30000, ID_SOUND_30000HZ},
588 {32000, ID_SOUND_32000HZ},
589 {35000, ID_SOUND_35000HZ},
590 {44100, ID_SOUND_44100HZ},
591 {48000, ID_SOUND_48000HZ}
592 };
593
594 static uint32 FrameTimings[] = {
595 4000, 4000, 8333, 11667, 16667, 20000, 33333, 66667, 133333, 300000, 500000, 1000000, 1000000
596 };
597
598 // Languages supported by Snes9X: Windows
599 // 0 - English [Default]
600 struct sLanguages Languages[] = {
601 { IDR_MENU_US,
602 TEXT("Failed to initialize currently selected display output!\n Try switching to a different output method in the display settings."),
603 TEXT("DirectDraw failed to set the selected display mode!"),
604 TEXT("DirectSound failed to initialize; no sound will be played."),
605 TEXT("These settings won't take effect until you restart the emulator."),
606 TEXT("The frame timer failed to initialize, please do NOT select the automatic framerate option or Snes9X will crash!")}
607 };
608
609 struct OpenMovieParams
610 {
611 TCHAR Path[_MAX_PATH];
612 bool8 ReadOnly;
613 bool8 DisplayInput;
614 uint8 ControllersMask;
615 uint8 Opts;
616 uint8 SyncFlags;
617 wchar_t Metadata[MOVIE_MAX_METADATA];
618 };
619
620
621
622 StateManager stateMan;
623
624 std::vector<dMode> dm;
625 /*****************************************************************************/
626 /* WinProc */
627 /*****************************************************************************/
628 void DoAVIOpen(const TCHAR* filename);
629 void DoAVIClose(int reason);
630 void RestoreGUIDisplay ();
631 void RestoreSNESDisplay ();
632 void FreezeUnfreeze (int slot, bool8 freeze);
633 void CheckDirectoryIsWritable (const char *filename);
634 static void CheckMenuStates ();
635 static void ResetFrameTimer ();
636 static bool LoadROM (const TCHAR *filename);
637 static bool LoadMultiROM (const TCHAR *filename, const TCHAR *filename2);
638 bool8 S9xLoadROMImage (const TCHAR *string);
639 #ifdef NETPLAY_SUPPORT
640 static void EnableServer (bool8 enable);
641 #endif
642 void WinDeleteRecentGamesList ();
643 const TCHAR* WinParseCommandLineAndLoadConfigFile (TCHAR *line);
644 void WinRegisterConfigItems ();
645 void WinSaveConfigFile ();
646 void WinSetDefaultValues ();
647 void WinLockConfigFile ();
648 void WinUnlockConfigFile ();
649 void WinCleanupConfigData ();
650
651 #include "../ppu.h"
652 #include "../snapshot.h"
653 const char *S9xGetFilenameInc (const char *);
654 void S9xSetRecentGames ();
655 void S9xAddToRecentGames (const TCHAR *filename);
656 void S9xRemoveFromRecentGames (int i);
657
absToRel(TCHAR * relPath,const TCHAR * absPath,const TCHAR * baseDir)658 static void absToRel(TCHAR* relPath, const TCHAR* absPath, const TCHAR* baseDir)
659 {
660 lstrcpy(relPath, absPath);
661 if(!_tcsncicmp(absPath, baseDir, lstrlen(baseDir)))
662 {
663 TCHAR temp [MAX_PATH];
664 temp[MAX_PATH-3]=TEXT('\0');
665 const TCHAR* relative = absPath+lstrlen(baseDir);
666 while(relative[0]==TEXT('\\') || relative[0]==TEXT('/'))
667 relative++;
668 relPath[0]=TEXT('.'); relPath[1]=TEXT('\\');
669 lstrcpy(relPath+2, relative);
670 }
671 }
672
SendMenuCommand(UINT uID)673 BOOL SendMenuCommand (UINT uID)
674 {
675 MENUITEMINFO mii;
676
677 CheckMenuStates();
678
679 mii.cbSize = sizeof(mii);
680 mii.fMask = MIIM_STATE;
681 if (!GetMenuItemInfo(GUI.hMenu, uID, FALSE, &mii))
682 return FALSE;
683 if (!(mii.fState & MFS_DISABLED))
684 return SendMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(uID),(LPARAM)(NULL));
685 else
686 return FALSE;
687 }
688
PostMenuCommand(UINT uID)689 BOOL PostMenuCommand (UINT uID)
690 {
691 MENUITEMINFO mii;
692
693 CheckMenuStates();
694
695 mii.cbSize = sizeof(mii);
696 mii.fMask = MIIM_STATE;
697 if (!GetMenuItemInfo(GUI.hMenu, uID, FALSE, &mii))
698 return FALSE;
699 if (!(mii.fState & MFS_DISABLED))
700 return PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(uID),(LPARAM)(NULL));
701 else
702 return FALSE;
703 }
704
S9xMouseOn()705 void S9xMouseOn ()
706 {
707 if(Settings.StopEmulation)
708 return;
709
710 if (GUI.ControllerOption==SNES_MOUSE || GUI.ControllerOption==SNES_MOUSE_SWAPPED)
711 {
712 if(Settings.Paused)
713 SetCursor (GUI.Arrow);
714 else
715 SetCursor (NULL);
716 }
717 else if (GUI.ControllerOption!=SNES_SUPERSCOPE && GUI.ControllerOption!=SNES_JUSTIFIER && GUI.ControllerOption!=SNES_JUSTIFIER_2)
718 {
719 SetCursor (GUI.Arrow);
720 GUI.CursorTimer = 60;
721 }
722 else
723 {
724 if(Settings.Paused)
725 SetCursor (GUI.GunSight);
726 else
727 SetCursor (NULL);
728 }
729 }
730
ControllerOptionsFromControllers()731 void ControllerOptionsFromControllers()
732 {
733 enum controllers controller[2];
734 int8 ids[4];
735 S9xGetController(0, &controller[0], &ids[0], &ids[1], &ids[2], &ids[3]);
736 S9xGetController(1, &controller[1], &ids[0], &ids[1], &ids[2], &ids[3]);
737
738 GUI.ControllerOption = SNES_JOYPAD;
739
740 if (controller[0] == CTL_JOYPAD && controller[1] == CTL_JOYPAD)
741 GUI.ControllerOption = SNES_JOYPAD;
742 else if (controller[0] == CTL_JOYPAD && controller[1] == CTL_MP5)
743 GUI.ControllerOption = SNES_MULTIPLAYER5;
744 else if (controller[0] == CTL_MP5 && controller[1] == CTL_MP5)
745 GUI.ControllerOption = SNES_MULTIPLAYER8;
746 else if (controller[0] == CTL_MOUSE && controller[1] == CTL_JOYPAD)
747 GUI.ControllerOption = SNES_MOUSE;
748 else if (controller[0] == CTL_JOYPAD && controller[1] == CTL_MOUSE)
749 GUI.ControllerOption = SNES_MOUSE_SWAPPED;
750 else if (controller[0] == CTL_JOYPAD && controller[1] == CTL_SUPERSCOPE)
751 GUI.ControllerOption = SNES_SUPERSCOPE;
752 else if (controller[0] == CTL_JOYPAD && controller[1] == CTL_JUSTIFIER && !ids[0])
753 GUI.ControllerOption = SNES_JUSTIFIER;
754 else if (controller[0] == CTL_JOYPAD && controller[1] == CTL_JUSTIFIER && ids[0])
755 GUI.ControllerOption = SNES_JUSTIFIER_2;
756 }
757
ChangeInputDevice(void)758 void ChangeInputDevice(void)
759 {
760 Settings.MouseMaster = false;
761 Settings.JustifierMaster = false;
762 Settings.SuperScopeMaster = false;
763 Settings.MultiPlayer5Master = false;
764
765 switch(GUI.ControllerOption)
766 {
767 case SNES_MOUSE:
768 Settings.MouseMaster = true;
769 S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0);
770 S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
771 break;
772 case SNES_MOUSE_SWAPPED:
773 Settings.MouseMaster = true;
774 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
775 S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0);
776 break;
777 case SNES_SUPERSCOPE:
778 Settings.SuperScopeMaster = true;
779 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
780 S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0);
781 break;
782 case SNES_MULTIPLAYER5:
783 Settings.MultiPlayer5Master = true;
784 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
785 S9xSetController(1, CTL_MP5, 1, 2, 3, 4);
786 break;
787 case SNES_MULTIPLAYER8:
788 Settings.MultiPlayer5Master = true;
789 S9xSetController(0, CTL_MP5, 0, 1, 2, 3);
790 S9xSetController(1, CTL_MP5, 4, 5, 6, 7);
791 break;
792 case SNES_JUSTIFIER:
793 Settings.JustifierMaster = true;
794 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
795 S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0);
796 break;
797 case SNES_JUSTIFIER_2:
798 Settings.JustifierMaster = true;
799 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
800 S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0);
801 break;
802 default:
803 case SNES_JOYPAD:
804 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
805 S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
806 break;
807 }
808
809 GUI.ControlForced = 0xff;
810 }
811
CenterCursor()812 static void CenterCursor()
813 {
814 if(GUI.ControllerOption==SNES_MOUSE || GUI.ControllerOption==SNES_MOUSE_SWAPPED)
815 {
816 if(GUI.hWnd == GetActiveWindow() && !S9xMoviePlaying())
817 {
818 POINT cur, middle;
819 RECT size;
820
821 GetClientRect (GUI.hWnd, &size);
822 middle.x = (size.right - size.left) >> 1;
823 middle.y = (size.bottom - size.top) >> 1;
824 ClientToScreen (GUI.hWnd, &middle);
825 GetCursorPos (&cur);
826 int dX = middle.x-cur.x;
827 int dY = middle.y-cur.y;
828 if(dX || dY)
829 {
830 GUI.MouseX -= dX;
831 GUI.MouseY -= dY;
832 SetCursorPos (middle.x, middle.y);
833 // GUI.IgnoreNextMouseMove = true;
834 }
835 }
836 }
837 }
838
839
S9xRestoreWindowTitle()840 void S9xRestoreWindowTitle ()
841 {
842 TCHAR buf [100];
843 _stprintf (buf, WINDOW_TITLE, TEXT(VERSION));
844 SetWindowText (GUI.hWnd, buf);
845 }
846
S9xDisplayStateChange(const char * str,bool8 on)847 void S9xDisplayStateChange (const char *str, bool8 on)
848 {
849 static char string [100];
850
851 sprintf (string, "%s %s", str, on ? "on" : "off");
852 S9xSetInfoString (string);
853 }
854
UpdateScale(RenderFilter & Scale,RenderFilter & NextScale)855 static void UpdateScale(RenderFilter & Scale, RenderFilter & NextScale)
856 {
857 Scale = NextScale;
858 }
859
860 static char InfoString [100];
861 static uint32 prevPadReadFrame = (uint32)-1;
862 static bool skipNextFrameStop = false;
863
HandleKeyMessage(WPARAM wParam,LPARAM lParam)864 int HandleKeyMessage(WPARAM wParam, LPARAM lParam)
865 {
866 // update toggles
867 for (int J = 0; J < 5; J++)
868 {
869 extern bool S9xGetState (WORD KeyIdent);
870 if(Joypad[J].Enabled && (!S9xGetState(Joypad[J+8].Autohold))) // enabled and Togglify
871 {
872 SJoypad & p = ToggleJoypadStorage[J];
873 if(wParam == Joypad[J].L) p.L = !p.L;
874 if(wParam == Joypad[J].R) p.R = !p.R;
875 if(wParam == Joypad[J].A) p.A = !p.A;
876 if(wParam == Joypad[J].B) p.B = !p.B;
877 if(wParam == Joypad[J].Y) p.Y = !p.Y;
878 if(wParam == Joypad[J].X) p.X = !p.X;
879 if(wParam == Joypad[J].Start) p.Start = !p.Start;
880 if(wParam == Joypad[J].Select) p.Select = !p.Select;
881 if(wParam == Joypad[J].Left) p.Left = !p.Left;
882 if(wParam == Joypad[J].Right) p.Right = !p.Right;
883 if(wParam == Joypad[J].Up) p.Up = !p.Up;
884 if(wParam == Joypad[J].Down) p.Down = !p.Down;
885 // if(wParam == Joypad[J].Left_Down) p.Left_Down = !p.Left_Down;
886 // if(wParam == Joypad[J].Left_Up) p.Left_Up = !p.Left_Up;
887 // if(wParam == Joypad[J].Right_Down) p.Right_Down = !p.Right_Down;
888 // if(wParam == Joypad[J].Right_Up) p.Right_Up = !p.Right_Up;
889 if(!Settings.UpAndDown)
890 {
891 if(p.Left && p.Right)
892 p.Left = p.Right = false;
893 if(p.Up && p.Down)
894 p.Up = p.Down = false;
895 }
896 }
897 if(Joypad[J].Enabled && (!S9xGetState(Joypad[J+8].Autofire))) // enabled and turbo-togglify (TurboTog)
898 {
899 SJoypad & p = TurboToggleJoypadStorage[J];
900 if(wParam == Joypad[J].L) p.L = !p.L;
901 if(wParam == Joypad[J].R) p.R = !p.R;
902 if(wParam == Joypad[J].A) p.A = !p.A;
903 if(wParam == Joypad[J].B) p.B = !p.B;
904 if(wParam == Joypad[J].Y) p.Y = !p.Y;
905 if(wParam == Joypad[J].X) p.X = !p.X;
906 if(wParam == Joypad[J].Start) p.Start = !p.Start;
907 if(wParam == Joypad[J].Select) p.Select = !p.Select;
908 if(wParam == Joypad[J].Left) p.Left = !p.Left;
909 if(wParam == Joypad[J].Right) p.Right = !p.Right;
910 if(wParam == Joypad[J].Up) p.Up = !p.Up;
911 if(wParam == Joypad[J].Down) p.Down = !p.Down;
912 // if(wParam == Joypad[J].Left_Down) p.Left_Down = !p.Left_Down;
913 // if(wParam == Joypad[J].Left_Up) p.Left_Up = !p.Left_Up;
914 // if(wParam == Joypad[J].Right_Down) p.Right_Down = !p.Right_Down;
915 // if(wParam == Joypad[J].Right_Up) p.Right_Up = !p.Right_Up;
916 if(!Settings.UpAndDown)
917 {
918 if(p.Left && p.Right)
919 p.Left = p.Right = false;
920 if(p.Up && p.Down)
921 p.Up = p.Down = false;
922 }
923 }
924 if(wParam == Joypad[J+8].ClearAll) // clear all
925 {
926 {
927 SJoypad & p = ToggleJoypadStorage[J];
928 p.L = false;
929 p.R = false;
930 p.A = false;
931 p.B = false;
932 p.Y = false;
933 p.X = false;
934 p.Start = false;
935 p.Select = false;
936 p.Left = false;
937 p.Right = false;
938 p.Up = false;
939 p.Down = false;
940 }
941 {
942 SJoypad & p = TurboToggleJoypadStorage[J];
943 p.L = false;
944 p.R = false;
945 p.A = false;
946 p.B = false;
947 p.Y = false;
948 p.X = false;
949 p.Start = false;
950 p.Select = false;
951 p.Left = false;
952 p.Right = false;
953 p.Up = false;
954 p.Down = false;
955 }
956 }
957 }
958
959
960 bool hitHotKey = false;
961
962 if(!(wParam == 0 || wParam == VK_ESCAPE)) // if it's the 'disabled' key, it's never pressed as a hotkey
963 {
964 int modifiers = 0;
965 if(GetAsyncKeyState(VK_MENU))
966 modifiers |= CUSTKEY_ALT_MASK;
967 if(GetAsyncKeyState(VK_CONTROL))
968 modifiers |= CUSTKEY_CTRL_MASK;
969 if(GetAsyncKeyState(VK_SHIFT))
970 modifiers |= CUSTKEY_SHIFT_MASK;
971
972 {
973 for(int i = 0 ; i < 10 ; i++)
974 {
975 if(wParam == CustomKeys.Save[i].key
976 && modifiers == CustomKeys.Save[i].modifiers)
977 {
978 FreezeUnfreeze (i, true);
979 hitHotKey = true;
980 }
981 if(wParam == CustomKeys.Load[i].key
982 && modifiers == CustomKeys.Load[i].modifiers)
983 {
984 FreezeUnfreeze (i, false);
985 hitHotKey = true;
986 }
987 }
988
989 if(wParam == CustomKeys.SlotSave.key
990 && modifiers == CustomKeys.SlotSave.modifiers)
991 {
992 FreezeUnfreeze (GUI.CurrentSaveSlot, true);
993 hitHotKey = true;
994 }
995 if(wParam == CustomKeys.SlotLoad.key
996 && modifiers == CustomKeys.SlotLoad.modifiers)
997 {
998 FreezeUnfreeze (GUI.CurrentSaveSlot, false);
999 hitHotKey = true;
1000 }
1001 if(wParam == CustomKeys.SlotPlus.key
1002 && modifiers == CustomKeys.SlotPlus.modifiers)
1003 {
1004 GUI.CurrentSaveSlot++;
1005 if(GUI.CurrentSaveSlot > 9)
1006 GUI.CurrentSaveSlot = 0;
1007
1008 static char str [64];
1009 sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot);
1010 S9xSetInfoString(str);
1011
1012 hitHotKey = true;
1013 }
1014 if(wParam == CustomKeys.SlotMinus.key
1015 && modifiers == CustomKeys.SlotMinus.modifiers)
1016 {
1017 GUI.CurrentSaveSlot--;
1018 if(GUI.CurrentSaveSlot < 0)
1019 GUI.CurrentSaveSlot = 9;
1020
1021 static char str [64];
1022 sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot);
1023 S9xSetInfoString(str);
1024
1025 hitHotKey = true;
1026 }
1027 }
1028
1029
1030 if(wParam == CustomKeys.FrameAdvance.key
1031 && modifiers == CustomKeys.FrameAdvance.modifiers)
1032 {
1033 static DWORD lastTime = 0;
1034 if((int)(timeGetTime() - lastTime) > 20)
1035 {
1036 lastTime = timeGetTime();
1037 if(Settings.Paused || GUI.FASkipsNonInput)
1038 {
1039 prevPadReadFrame = (uint32)-1;
1040 Settings.Paused = false;
1041 S9xMouseOn();
1042 GUI.IgnoreNextMouseMove = true;
1043 Settings.Paused = true;
1044
1045 Settings.FrameAdvance = true;
1046 GUI.FrameAdvanceJustPressed = 2;
1047 // kick the main thread out of GetMessage (just in case)
1048 SendMessage(GUI.hWnd, WM_NULL, 0, 0);
1049 }
1050 else
1051 {
1052 Settings.Paused = true;
1053 }
1054
1055 CenterCursor();
1056 }
1057
1058 hitHotKey = true;
1059 }
1060 if(wParam == CustomKeys.FrameCount.key
1061 && modifiers == CustomKeys.FrameCount.modifiers)
1062 {
1063 if (S9xMovieActive()
1064 #ifdef NETPLAY_SUPPORT
1065 || Settings.NetPlay
1066 #endif
1067 )
1068 S9xMovieToggleFrameDisplay ();
1069 else
1070 S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_ERR_NOFRAMETOGGLE);
1071 hitHotKey = true;
1072 }
1073 if(wParam == CustomKeys.Pause.key
1074 && modifiers == CustomKeys.Pause.modifiers)
1075 {
1076 Settings.Paused = Settings.Paused ^ true;
1077 Settings.FrameAdvance = false;
1078 GUI.FrameAdvanceJustPressed = 0;
1079 CenterCursor();
1080 if(!Settings.Paused)
1081 S9xMouseOn();
1082 hitHotKey = true;
1083 }
1084 if(wParam == CustomKeys.ReadOnly.key
1085 && modifiers == CustomKeys.ReadOnly.modifiers)
1086 {
1087 if (S9xMovieActive())
1088 S9xMovieToggleRecState();
1089 else
1090 S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_ERR_NOREADONLYTOGGLE);
1091 hitHotKey = true;
1092 }
1093 if(wParam == CustomKeys.FastForward.key
1094 && modifiers == CustomKeys.FastForward.modifiers)
1095 {
1096 if(Settings.SPC7110RTC)
1097 return 1;
1098
1099 if(!Settings.TurboMode)
1100 S9xMessage (S9X_INFO, S9X_TURBO_MODE, WINPROC_TURBOMODE_TEXT);
1101 Settings.TurboMode = TRUE;
1102 hitHotKey = true;
1103 }
1104 if(wParam == CustomKeys.FastForwardToggle.key
1105 && modifiers == CustomKeys.FastForwardToggle.modifiers)
1106 {
1107 if(Settings.SPC7110RTC)
1108 return 1;
1109
1110 Settings.TurboMode ^= TRUE;
1111 if (Settings.TurboMode)
1112 S9xMessage (S9X_INFO, S9X_TURBO_MODE,
1113 WINPROC_TURBOMODE_ON);
1114 else
1115 S9xMessage (S9X_INFO, S9X_TURBO_MODE,
1116 WINPROC_TURBOMODE_OFF);
1117 hitHotKey = true;
1118 }
1119 if(wParam == CustomKeys.ShowPressed.key
1120 && modifiers == CustomKeys.ShowPressed.modifiers)
1121 {
1122 Settings.DisplayPressedKeys = Settings.DisplayPressedKeys?0:2;
1123
1124 if(Settings.DisplayPressedKeys==2)
1125 S9xMessage(S9X_INFO, S9X_MOVIE_INFO, INPUT_INFO_DISPLAY_ENABLED);
1126 else
1127 S9xMessage(S9X_INFO, S9X_MOVIE_INFO, INPUT_INFO_DISPLAY_DISABLED);
1128
1129 hitHotKey = true;
1130 }
1131 if(wParam == CustomKeys.SaveScreenShot.key
1132 && modifiers == CustomKeys.SaveScreenShot.modifiers)
1133 {
1134 Settings.TakeScreenshot=true;
1135 }
1136 if(wParam == CustomKeys.ScopePause.key
1137 && modifiers == CustomKeys.ScopePause.modifiers)
1138 {
1139 GUI.superscope_pause = 1;
1140 hitHotKey = true;
1141 }
1142 if(wParam == CustomKeys.ScopeTurbo.key
1143 && modifiers == CustomKeys.ScopeTurbo.modifiers)
1144 {
1145 GUI.superscope_turbo = 1;
1146 hitHotKey = true;
1147 }
1148 if(wParam == CustomKeys.SkipDown.key
1149 && modifiers == CustomKeys.SkipDown.modifiers)
1150 {
1151 if (Settings.SkipFrames <= 1)
1152 Settings.SkipFrames = AUTO_FRAMERATE;
1153 else
1154 if (Settings.SkipFrames != AUTO_FRAMERATE)
1155 Settings.SkipFrames--;
1156
1157 if (Settings.SkipFrames == AUTO_FRAMERATE)
1158 S9xSetInfoString (WINPROC_AUTOSKIP);
1159 else
1160 {
1161 sprintf (InfoString, WINPROC_FRAMESKIP,
1162 Settings.SkipFrames - 1);
1163 S9xSetInfoString (InfoString);
1164 }
1165 hitHotKey = true;
1166 }
1167 if(wParam == CustomKeys.SkipUp.key
1168 && modifiers == CustomKeys.SkipUp.modifiers)
1169 {
1170 if (Settings.SkipFrames == AUTO_FRAMERATE)
1171 Settings.SkipFrames = 1;
1172 else
1173 if (Settings.SkipFrames < 10)
1174 Settings.SkipFrames++;
1175
1176 if (Settings.SkipFrames == AUTO_FRAMERATE)
1177 S9xSetInfoString (WINPROC_AUTOSKIP);
1178 else
1179 {
1180 sprintf (InfoString, WINPROC_FRAMESKIP,
1181 Settings.SkipFrames - 1);
1182 S9xSetInfoString (InfoString);
1183 }
1184 hitHotKey = true;
1185 }
1186 if(wParam == CustomKeys.SpeedDown.key
1187 && modifiers == CustomKeys.SpeedDown.modifiers)
1188 {
1189 // Increase emulated frame time
1190 int i;
1191 for(i=1; FrameTimings[i]<Settings.FrameTime; ++i)
1192 ;
1193 Settings.FrameTime = FrameTimings[i+1];
1194 ResetFrameTimer ();
1195 // sprintf (InfoString, WINPROC_EMUFRAMETIME,
1196 // Settings.FrameTime / 1);
1197 sprintf (InfoString, "Speed: %.0f%% (%.1f ms/frame)", ((Settings.PAL?Settings.FrameTimePAL:Settings.FrameTimeNTSC) * 100.0f) / (float)Settings.FrameTime, Settings.FrameTime*0.001f);
1198 S9xSetInfoString (InfoString);
1199 hitHotKey = true;
1200 }
1201 if(wParam == CustomKeys.SpeedUp.key
1202 && modifiers == CustomKeys.SpeedUp.modifiers)
1203 {
1204 // Decrease emulated frame time
1205 int i;
1206 for(i=1; FrameTimings[i]<Settings.FrameTime; ++i)
1207 ;
1208 Settings.FrameTime = FrameTimings[i-1];
1209
1210 ResetFrameTimer ();
1211 // sprintf (InfoString, WINPROC_EMUFRAMETIME,
1212 // Settings.FrameTime / 1);
1213 sprintf (InfoString, "Speed: %.0f%% (%.1f ms/frame)", ((Settings.PAL?Settings.FrameTimePAL:Settings.FrameTimeNTSC) * 100.0f) / (float)Settings.FrameTime, Settings.FrameTime*0.001f);
1214 S9xSetInfoString (InfoString);
1215 hitHotKey = true;
1216 }
1217 if(wParam == CustomKeys.BGL1.key
1218 && modifiers == CustomKeys.BGL1.modifiers)
1219 {
1220 Settings.BG_Forced ^= 1;
1221 S9xDisplayStateChange (WINPROC_BG1, !(Settings.BG_Forced & 1));
1222 }
1223 if(wParam == CustomKeys.BGL2.key
1224 && modifiers == CustomKeys.BGL2.modifiers)
1225 {
1226 Settings.BG_Forced ^= 2;
1227 S9xDisplayStateChange (WINPROC_BG2, !(Settings.BG_Forced & 2));
1228 }
1229 if(wParam == CustomKeys.BGL3.key
1230 && modifiers == CustomKeys.BGL3.modifiers)
1231 {
1232 Settings.BG_Forced ^= 4;
1233 S9xDisplayStateChange (WINPROC_BG3, !(Settings.BG_Forced & 4));
1234 }
1235 if(wParam == CustomKeys.BGL4.key
1236 && modifiers == CustomKeys.BGL4.modifiers)
1237 {
1238 Settings.BG_Forced ^= 8;
1239 S9xDisplayStateChange (WINPROC_BG4, !(Settings.BG_Forced & 8));
1240 }
1241 if(wParam == CustomKeys.BGL5.key
1242 && modifiers == CustomKeys.BGL5.modifiers)
1243 {
1244 Settings.BG_Forced ^= 16;
1245 S9xDisplayStateChange (WINPROC_SPRITES, !(Settings.BG_Forced & 16));
1246 }
1247 if(wParam == CustomKeys.ResetGame.key
1248 && modifiers == CustomKeys.ResetGame.modifiers)
1249 {
1250 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_FILE_RESET),(LPARAM)(NULL));
1251 }
1252 if(wParam == CustomKeys.ToggleCheats.key
1253 && modifiers == CustomKeys.ToggleCheats.modifiers)
1254 {
1255 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_CHEAT_APPLY),(LPARAM)(NULL));
1256 }
1257 if(wParam == CustomKeys.JoypadSwap.key
1258 && modifiers == CustomKeys.JoypadSwap.modifiers)
1259 {
1260 if(!S9xMoviePlaying())
1261 {
1262 S9xApplyCommand(S9xGetCommandT("SwapJoypads"),1,0);
1263 }
1264 }
1265 if(wParam == CustomKeys.SwitchControllers.key
1266 && modifiers == CustomKeys.SwitchControllers.modifiers)
1267 {
1268 if((!S9xMovieActive() || !S9xMovieGetFrameCounter()))
1269 {
1270 // int prevControllerOption = GUI.ControllerOption;
1271 // do {
1272 ++GUI.ControllerOption %= SNES_MAX_CONTROLLER_OPTIONS;
1273 // } while(!((1<<GUI.ControllerOption) & GUI.ValidControllerOptions) && prevControllerOption != GUI.ControllerOption);
1274
1275 ChangeInputDevice();
1276
1277 if (GUI.ControllerOption == SNES_MOUSE || GUI.ControllerOption == SNES_MOUSE_SWAPPED)
1278 CenterCursor();
1279
1280 S9xReportControllers();
1281 }
1282 }
1283 if(wParam == CustomKeys.QuitS9X.key
1284 && modifiers == CustomKeys.QuitS9X.modifiers)
1285 {
1286 PostMessage(GUI.hWnd,WM_CLOSE,(WPARAM)NULL,(LPARAM)(NULL));
1287 }
1288 if(wParam == CustomKeys.Rewind.key
1289 && modifiers == CustomKeys.Rewind.modifiers)
1290 {
1291 if(!GUI.rewinding)
1292 S9xMessage (S9X_INFO, 0, GUI.rewindBufferSize?WINPROC_REWINDING_TEXT:WINPROC_REWINDING_DISABLED);
1293 GUI.rewinding = true;
1294 }
1295 //if(wParam == CustomKeys.BGLHack.key
1296 //&& modifiers == CustomKeys.BGLHack.modifiers)
1297 //{
1298 // Settings.BGLayering = !Settings.BGLayering;
1299 // S9xDisplayStateChange (WINPROC_BGHACK,
1300 // Settings.BGLayering);
1301 //}
1302 //if(wParam == CustomKeys.InterpMode7.key
1303 //&& modifiers == CustomKeys.InterpMode7.modifiers)
1304 //{
1305 // Settings.Mode7Interpolate ^= TRUE;
1306 // S9xDisplayStateChange (WINPROC_MODE7INTER,
1307 // Settings.Mode7Interpolate);
1308 //}
1309
1310 if(wParam == CustomKeys.TurboA.key && modifiers == CustomKeys.TurboA.modifiers)
1311 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_A),(LPARAM)(NULL));
1312 if(wParam == CustomKeys.TurboB.key && modifiers == CustomKeys.TurboB.modifiers)
1313 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_B),(LPARAM)(NULL));
1314 if(wParam == CustomKeys.TurboY.key && modifiers == CustomKeys.TurboY.modifiers)
1315 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_Y),(LPARAM)(NULL));
1316 if(wParam == CustomKeys.TurboX.key && modifiers == CustomKeys.TurboX.modifiers)
1317 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_X),(LPARAM)(NULL));
1318 if(wParam == CustomKeys.TurboL.key && modifiers == CustomKeys.TurboL.modifiers)
1319 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_L),(LPARAM)(NULL));
1320 if(wParam == CustomKeys.TurboR.key && modifiers == CustomKeys.TurboR.modifiers)
1321 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_R),(LPARAM)(NULL));
1322 if(wParam == CustomKeys.TurboStart.key && modifiers == CustomKeys.TurboStart.modifiers)
1323 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_START),(LPARAM)(NULL));
1324 if(wParam == CustomKeys.TurboSelect.key && modifiers == CustomKeys.TurboSelect.modifiers)
1325 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_SELECT),(LPARAM)(NULL));
1326 if(wParam == CustomKeys.TurboLeft.key && modifiers == CustomKeys.TurboLeft.modifiers)
1327 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_LEFT),(LPARAM)(NULL));
1328 if(wParam == CustomKeys.TurboUp.key && modifiers == CustomKeys.TurboUp.modifiers)
1329 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_UP),(LPARAM)(NULL));
1330 if(wParam == CustomKeys.TurboRight.key && modifiers == CustomKeys.TurboRight.modifiers)
1331 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_RIGHT),(LPARAM)(NULL));
1332 if(wParam == CustomKeys.TurboDown.key && modifiers == CustomKeys.TurboDown.modifiers)
1333 PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_DOWN),(LPARAM)(NULL));
1334
1335 for(int i = 0 ; i < 10 ; i++)
1336 {
1337 if(wParam == CustomKeys.SelectSave[i].key && modifiers == CustomKeys.SelectSave[i].modifiers)
1338 {
1339 GUI.CurrentSaveSlot = i;
1340
1341 static char str [64];
1342 sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot);
1343 S9xSetInfoString(str);
1344
1345 hitHotKey = true;
1346 }
1347 }
1348
1349 if(wParam == CustomKeys.Transparency.key
1350 && modifiers == CustomKeys.Transparency.modifiers)
1351 {
1352 // if (Settings.SixteenBit)
1353 {
1354 Settings.Transparency = !Settings.Transparency;
1355 S9xDisplayStateChange (WINPROC_TRANSPARENCY,
1356 Settings.Transparency);
1357 }
1358 // else
1359 // {
1360 // S9xSetInfoString ("Transparency requires Sixteen Bit mode.");
1361 // }
1362 }
1363 if(wParam == CustomKeys.ClippingWindows.key
1364 && modifiers == CustomKeys.ClippingWindows.modifiers)
1365 {
1366 Settings.DisableGraphicWindows = !Settings.DisableGraphicWindows;
1367 S9xDisplayStateChange (WINPROC_CLIPWIN,
1368 !Settings.DisableGraphicWindows);
1369 }
1370
1371 // don't pull down menu if alt is a hotkey or the menu isn't there, unless no game is running
1372 if(!Settings.StopEmulation && ((wParam == VK_MENU || wParam == VK_F10) && (hitHotKey || GetMenu (GUI.hWnd) == NULL) && !GetAsyncKeyState(VK_F4)))
1373 return 0;
1374 }
1375
1376 if(!hitHotKey)
1377 switch (wParam)
1378 {
1379 case VK_ESCAPE:
1380 if(GUI.outputMethod!=DIRECTDRAW && GUI.FullScreen && !GUI.EmulateFullscreen)
1381 ToggleFullScreen();
1382 else
1383 if (GetMenu (GUI.hWnd) == NULL)
1384 SetMenu (GUI.hWnd, GUI.hMenu);
1385 else
1386 SetMenu (GUI.hWnd, NULL);
1387
1388 //UpdateBackBuffer();
1389 if (GetMenu( GUI.hWnd) != NULL)
1390 DrawMenuBar (GUI.hWnd);
1391 break;
1392 }
1393 return 1;
1394 }
1395
DoOpenRomDialog(TCHAR filename[_MAX_PATH],bool noCustomDlg=false)1396 static bool DoOpenRomDialog(TCHAR filename [_MAX_PATH], bool noCustomDlg = false)
1397 {
1398 if(GUI.CustomRomOpen && !noCustomDlg)
1399 {
1400 try
1401 {
1402 INITCOMMONCONTROLSEX icex;
1403 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
1404 icex.dwICC = ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES;
1405 InitCommonControlsEx(&icex); // this could cause failure if the common control DLL isn't found
1406
1407 return (1 <= DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_OPEN_ROM), GUI.hWnd, DlgOpenROMProc, (LPARAM)filename));
1408 }
1409 catch(...) {} // use standard dialog if the special one fails
1410
1411 GUI.CustomRomOpen = false; // if crashed, turn off custom for next time
1412 }
1413
1414 // standard file dialog
1415 {
1416 OPENFILENAME ofn;
1417 static TCHAR szFileName[MAX_PATH] = {0};
1418 TCHAR szPathName[MAX_PATH];
1419 _tfullpath(szPathName, S9xGetDirectoryT(ROM_DIR), MAX_PATH);
1420
1421 // a limited strcat that doesn't mind null characters
1422 #define strcat0(to,from) do{memcpy(to,from,sizeof(from)-1);to+=(sizeof(from)/sizeof(TCHAR))-1;}while(false)
1423
1424 // make filter string using entries in valid_ext
1425 TCHAR lpfilter [8192] = {0};
1426 TCHAR* lpfilterptr = lpfilter;
1427 for(int i=0; i<2; i++)
1428 {
1429 if(!i)
1430 strcat0(lpfilterptr, FILE_INFO_ROM_FILE_TYPE);
1431 else
1432 strcat0(lpfilterptr, FILE_INFO_UNCROM_FILE_TYPE);
1433 strcat0(lpfilterptr, TEXT("\0"));
1434 if(valid_ext) // add valid extensions to string
1435 {
1436 ExtList* ext = valid_ext;
1437 int extlen_approx = 0;
1438 bool first = true;
1439 while(ext && (extlen_approx < 2048))
1440 {
1441 if((!i || !ext->compressed) && ext->extension && lstrlen(ext->extension) < 256)
1442 {
1443 if(!first)
1444 lstrcat(lpfilterptr, TEXT(";*."));
1445 else
1446 {
1447 lstrcat(lpfilterptr, TEXT("*."));
1448 first = false;
1449 }
1450 lstrcat(lpfilterptr, ext->extension);
1451 extlen_approx += lstrlen(ext->extension) + 3;
1452 }
1453 ext = ext->next;
1454 }
1455 lpfilterptr += lstrlen(lpfilterptr);
1456 }
1457 else
1458 strcat0(lpfilterptr, TEXT("*.smc"));
1459 strcat0(lpfilterptr, TEXT("\0"));
1460 }
1461 strcat0(lpfilterptr, FILE_INFO_ANY_FILE_TYPE);
1462 strcat0(lpfilterptr, TEXT("\0*.*\0\0"));
1463
1464 memset((LPVOID)&ofn, 0, sizeof(OPENFILENAME));
1465 ofn.lStructSize = sizeof(OPENFILENAME);
1466 ofn.hwndOwner = GUI.hWnd;
1467 ofn.lpstrFilter = lpfilter;
1468 ofn.lpstrFile = szFileName;
1469 ofn.lpstrDefExt = TEXT("smc");
1470 ofn.nMaxFile = MAX_PATH;
1471 ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
1472 ofn.lpstrInitialDir = szPathName;
1473 if(GetOpenFileName(&ofn))
1474 {
1475 _tcsncpy(filename, ofn.lpstrFile, _MAX_PATH);
1476 return true;
1477 }
1478 return false;
1479 }
1480 }
1481
WinMoviePlay(LPCTSTR filename)1482 bool WinMoviePlay(LPCTSTR filename)
1483 {
1484 struct MovieInfo info;
1485 int err;
1486
1487 if (Settings.StopEmulation) {
1488 SendMenuCommand(ID_FILE_LOAD_GAME);
1489 if (Settings.StopEmulation)
1490 return false;
1491 }
1492
1493 err = S9xMovieGetInfo(_tToChar(filename), &info);
1494 if (err != SUCCESS) {
1495 TCHAR* err_string = MOVIE_ERR_COULD_NOT_OPEN;
1496 switch(err)
1497 {
1498 case FILE_NOT_FOUND:
1499 err_string = MOVIE_ERR_NOT_FOUND_SHORT;
1500 break;
1501 case WRONG_FORMAT:
1502 err_string = MOVIE_ERR_WRONG_FORMAT_SHORT;
1503 break;
1504 case WRONG_VERSION:
1505 err_string = MOVIE_ERR_WRONG_VERSION_SHORT;
1506 break;
1507 }
1508 S9xSetInfoString(_tToChar(err_string));
1509 return false;
1510 }
1511
1512 while (info.ROMCRC32 != Memory.ROMCRC32 || strcmp(info.ROMName, Memory.RawROMName) != 0) {
1513 TCHAR temp[512];
1514 wsprintf(temp, TEXT("Movie's ROM: crc32=%08X, name=%s\nCurrent ROM: crc32=%08X, name=%s\n\nstill want to play the movie?"),
1515 info.ROMCRC32, _tFromMS932(info.ROMName), Memory.ROMCRC32, _tFromMS932(Memory.RawROMName));
1516 int sel = MessageBox(GUI.hWnd, temp, SNES9X_INFO, MB_ABORTRETRYIGNORE|MB_ICONQUESTION);
1517 switch (sel) {
1518 case IDABORT:
1519 return false;
1520 case IDRETRY:
1521 SendMenuCommand(ID_FILE_LOAD_GAME);
1522 if (Settings.StopEmulation)
1523 return false;
1524 break;
1525 default:
1526 goto romcheck_exit;
1527 }
1528 }
1529 romcheck_exit:
1530
1531 err = S9xMovieOpen (_tToChar(filename), GUI.MovieReadOnly);
1532 if(err != SUCCESS)
1533 {
1534 TCHAR* err_string = MOVIE_ERR_COULD_NOT_OPEN;
1535 switch(err)
1536 {
1537 case FILE_NOT_FOUND:
1538 err_string = MOVIE_ERR_NOT_FOUND_SHORT;
1539 break;
1540 case WRONG_FORMAT:
1541 err_string = MOVIE_ERR_WRONG_FORMAT_SHORT;
1542 break;
1543 case WRONG_VERSION:
1544 err_string = MOVIE_ERR_WRONG_VERSION_SHORT;
1545 break;
1546 }
1547 S9xSetInfoString(_tToChar(err_string));
1548 return false;
1549 }
1550 return true;
1551 }
1552
1553 TCHAR multiRomA [MAX_PATH] = {0}; // lazy, should put in sGUI and add init to {0} somewhere
1554 TCHAR multiRomB [MAX_PATH] = {0};
1555
1556
1557 static bool startingMovie = false;
1558
1559 HWND cheatSearchHWND = NULL;
1560
1561
1562 #define MOVIE_LOCKED_SETTING if(S9xMovieActive()) {MessageBox(GUI.hWnd,TEXT("That setting is locked while a movie is active."),TEXT("Notice"),MB_OK|MB_ICONEXCLAMATION); break;}
1563
WinProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1564 LRESULT CALLBACK WinProc(
1565 HWND hWnd,
1566 UINT uMsg,
1567 WPARAM wParam,
1568 LPARAM lParam)
1569 {
1570 unsigned int i;
1571 //bool showFPS;
1572 #ifdef NETPLAY_SUPPORT
1573 TCHAR hostname [100];
1574 #endif
1575 switch (uMsg)
1576 {
1577 case WM_CREATE:
1578 g_hInst = ((LPCREATESTRUCT)lParam)->hInstance;
1579 DragAcceptFiles(hWnd, TRUE);
1580 return 0;
1581 case WM_KEYDOWN:
1582 if(GUI.BackgroundInput && !GUI.InactivePause)
1583 break;
1584 case WM_CUSTKEYDOWN:
1585 case WM_SYSKEYDOWN:
1586 {
1587 if(!HandleKeyMessage(wParam,lParam))
1588 return 0;
1589 break;
1590 }
1591
1592 case WM_KEYUP:
1593 case WM_CUSTKEYUP:
1594 {
1595 int modifiers = 0;
1596 if(GetAsyncKeyState(VK_MENU) || wParam == VK_MENU)
1597 modifiers |= CUSTKEY_ALT_MASK;
1598 if(GetAsyncKeyState(VK_CONTROL)|| wParam == VK_CONTROL)
1599 modifiers |= CUSTKEY_CTRL_MASK;
1600 if(GetAsyncKeyState(VK_SHIFT)|| wParam == VK_SHIFT)
1601 modifiers |= CUSTKEY_SHIFT_MASK;
1602
1603 if(wParam == CustomKeys.FastForward.key
1604 && modifiers == CustomKeys.FastForward.modifiers)
1605 {
1606 Settings.TurboMode = FALSE;
1607 }
1608 if(wParam == CustomKeys.ScopePause.key
1609 && modifiers == CustomKeys.ScopePause.modifiers)
1610 {
1611 GUI.superscope_pause = 0;
1612 }
1613 if(wParam == CustomKeys.Rewind.key
1614 && modifiers == CustomKeys.Rewind.modifiers)
1615 {
1616 GUI.rewinding = false;
1617 }
1618
1619 }
1620 break;
1621
1622 case WM_DROPFILES:
1623 HDROP hDrop;
1624 UINT fileCount;
1625 TCHAR droppedFile[PATH_MAX];
1626
1627 hDrop = (HDROP)wParam;
1628 fileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
1629 if (fileCount == 1) {
1630 DragQueryFile(hDrop, 0, droppedFile, PATH_MAX);
1631
1632 LPCTSTR ext = PathFindExtension(droppedFile);
1633 if (ExtensionIsValid(droppedFile)) {
1634 LoadROM(droppedFile);
1635 }
1636 else if (lstrcmpi(ext, TEXT(".smv")) == 0) {
1637 WinMoviePlay(droppedFile);
1638 }
1639 else {
1640 S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Unknown file extension.");
1641 }
1642 }
1643 DragFinish(hDrop);
1644
1645 return 0;
1646
1647 case WM_COMMAND:
1648 switch (wParam & 0xffff)
1649 {
1650 case ID_FILE_AVI_RECORDING:
1651 if (!GUI.AVIOut)
1652 PostMessage(GUI.hWnd, WM_COMMAND, ID_FILE_WRITE_AVI, NULL);
1653 else
1654 PostMessage(GUI.hWnd, WM_COMMAND, ID_FILE_STOP_AVI, NULL);
1655 break;
1656 case ID_FILE_WRITE_AVI:
1657 {
1658 RestoreGUIDisplay (); //exit DirectX
1659 OPENFILENAME ofn;
1660 TCHAR szFileName[MAX_PATH];
1661 TCHAR szPathName[MAX_PATH];
1662 SetCurrentDirectory(S9xGetDirectoryT(DEFAULT_DIR));
1663 _tfullpath(szPathName, GUI.MovieDir, MAX_PATH);
1664 _tmkdir(szPathName);
1665
1666 szFileName[0] = TEXT('\0');
1667
1668 memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) );
1669 ofn.lStructSize = sizeof(OPENFILENAME);
1670 ofn.hwndOwner = GUI.hWnd;
1671 ofn.lpstrFilter = FILE_INFO_AVI_FILE_TYPE TEXT("\0*.avi\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0");
1672 ofn.lpstrFile = szFileName;
1673 ofn.lpstrDefExt = TEXT("avi");
1674 ofn.nMaxFile = MAX_PATH;
1675 ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
1676 ofn.lpstrInitialDir = szPathName;
1677 if(GetSaveFileName( &ofn ))
1678 {
1679 DoAVIOpen(szFileName);
1680 }
1681 RestoreSNESDisplay ();// re-enter after dialog
1682 }
1683 break;
1684 case ID_FILE_STOP_AVI:
1685 DoAVIClose(0);
1686 ReInitSound(); // reenable sound output
1687 break;
1688 case ID_FILE_MOVIE_STOP:
1689 S9xMovieStop(FALSE);
1690 break;
1691 case ID_FILE_MOVIE_PLAY:
1692 {
1693 RestoreGUIDisplay (); //exit DirectX
1694 OpenMovieParams op;
1695 memset(&op, 0, sizeof(op));
1696 if(DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_OPENMOVIE), hWnd, DlgOpenMovie, (LPARAM)&op) &&
1697 op.Path[0]!='\0')
1698 {
1699 int err=S9xMovieOpen (_tToChar(op.Path), op.ReadOnly);
1700 if(err!=SUCCESS)
1701 {
1702 TCHAR* err_string=MOVIE_ERR_COULD_NOT_OPEN;
1703 switch(err)
1704 {
1705 case FILE_NOT_FOUND:
1706 err_string=MOVIE_ERR_NOT_FOUND;
1707 break;
1708 case WRONG_FORMAT:
1709 err_string=MOVIE_ERR_WRONG_FORMAT;
1710 break;
1711 case WRONG_VERSION:
1712 err_string=MOVIE_ERR_WRONG_VERSION;
1713 break;
1714 }
1715 MessageBox( hWnd, err_string, SNES9X_INFO, MB_OK);
1716 }
1717 }
1718 RestoreSNESDisplay ();// re-enter after dialog
1719 }
1720 break;
1721 case ID_FILE_MOVIE_RECORD:
1722 {
1723 RestoreGUIDisplay (); //exit DirectX
1724 OpenMovieParams op;
1725 memset(&op, 0, sizeof(op));
1726 if(DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CREATEMOVIE), hWnd, DlgCreateMovie, (LPARAM)&op) &&
1727 op.Path[0]!='\0')
1728 {
1729 startingMovie = true;
1730 int err=S9xMovieCreate (_tToChar(op.Path), op.ControllersMask, op.Opts, op.Metadata, wcslen(op.Metadata));
1731 startingMovie = false;
1732 if(err!=SUCCESS)
1733 {
1734 TCHAR* err_string=MOVIE_ERR_COULD_NOT_OPEN;
1735 switch(err)
1736 {
1737 case FILE_NOT_FOUND:
1738 err_string=MOVIE_ERR_NOT_FOUND;
1739 break;
1740 case WRONG_FORMAT:
1741 err_string=MOVIE_ERR_WRONG_FORMAT;
1742 break;
1743 case WRONG_VERSION:
1744 err_string=MOVIE_ERR_WRONG_VERSION;
1745 break;
1746 }
1747 MessageBox( hWnd, err_string, SNES9X_INFO, MB_OK);
1748 }
1749 }
1750 RestoreSNESDisplay ();// re-enter after dialog
1751 }
1752 break;
1753 case IDM_SNES_JOYPAD:
1754 MOVIE_LOCKED_SETTING
1755 GUI.ControllerOption = SNES_JOYPAD;
1756 ChangeInputDevice();
1757 break;
1758 case IDM_ENABLE_MULTITAP:
1759 MOVIE_LOCKED_SETTING
1760 GUI.ControllerOption = SNES_MULTIPLAYER5;
1761 ChangeInputDevice();
1762 break;
1763 case IDM_SCOPE_TOGGLE:
1764 MOVIE_LOCKED_SETTING
1765 GUI.ControllerOption = SNES_SUPERSCOPE;
1766 ChangeInputDevice();
1767 break;
1768 case IDM_JUSTIFIER:
1769 MOVIE_LOCKED_SETTING
1770 GUI.ControllerOption = SNES_JUSTIFIER;
1771 ChangeInputDevice();
1772 break;
1773 case IDM_MOUSE_TOGGLE:
1774 MOVIE_LOCKED_SETTING
1775 GUI.ControllerOption = SNES_MOUSE;
1776 ChangeInputDevice();
1777 break;
1778 case IDM_MOUSE_SWAPPED:
1779 MOVIE_LOCKED_SETTING
1780 GUI.ControllerOption = SNES_MOUSE_SWAPPED;
1781 ChangeInputDevice();
1782 break;
1783 case IDM_MULTITAP8:
1784 MOVIE_LOCKED_SETTING
1785 GUI.ControllerOption = SNES_MULTIPLAYER8;
1786 ChangeInputDevice();
1787 break;
1788 case IDM_JUSTIFIERS:
1789 MOVIE_LOCKED_SETTING
1790 GUI.ControllerOption = SNES_JUSTIFIER_2;
1791 ChangeInputDevice();
1792 break;
1793
1794 //start turbo
1795 case ID_TURBO_R:
1796 GUI.TurboMask^=TURBO_R_MASK;
1797 if(GUI.TurboMask&TURBO_R_MASK)
1798 S9xSetInfoString (WINPROC_TURBO_R_ON);
1799 else S9xSetInfoString (WINPROC_TURBO_R_OFF);
1800 break;
1801 case ID_TURBO_L:
1802 GUI.TurboMask^=TURBO_L_MASK;
1803 if(GUI.TurboMask&TURBO_L_MASK)
1804 S9xSetInfoString (WINPROC_TURBO_L_ON);
1805 else S9xSetInfoString (WINPROC_TURBO_L_OFF);
1806 break;
1807 case ID_TURBO_A:
1808 GUI.TurboMask^=TURBO_A_MASK;
1809 if(GUI.TurboMask&TURBO_A_MASK)
1810 S9xSetInfoString (WINPROC_TURBO_A_ON);
1811 else S9xSetInfoString (WINPROC_TURBO_A_OFF);
1812 break;
1813 case ID_TURBO_B:
1814 GUI.TurboMask^=TURBO_B_MASK;
1815 if(GUI.TurboMask&TURBO_B_MASK)
1816 S9xSetInfoString (WINPROC_TURBO_B_ON);
1817 else S9xSetInfoString (WINPROC_TURBO_B_OFF);
1818 break;
1819 case ID_TURBO_Y:
1820 GUI.TurboMask^=TURBO_Y_MASK;
1821 if(GUI.TurboMask&TURBO_Y_MASK)
1822 S9xSetInfoString (WINPROC_TURBO_Y_ON);
1823 else S9xSetInfoString (WINPROC_TURBO_Y_OFF);
1824 break;
1825 case ID_TURBO_X:
1826 GUI.TurboMask^=TURBO_X_MASK;
1827 if(GUI.TurboMask&TURBO_X_MASK)
1828 S9xSetInfoString (WINPROC_TURBO_X_ON);
1829 else S9xSetInfoString (WINPROC_TURBO_X_OFF);
1830 break;
1831 case ID_TURBO_START:
1832 GUI.TurboMask^=TURBO_STA_MASK;
1833 if(GUI.TurboMask&TURBO_STA_MASK)
1834 S9xSetInfoString (WINPROC_TURBO_START_ON);
1835 else S9xSetInfoString (WINPROC_TURBO_START_OFF);
1836 break;
1837 case ID_TURBO_SELECT:
1838 GUI.TurboMask^=TURBO_SEL_MASK;
1839 if(GUI.TurboMask&TURBO_SEL_MASK)
1840 S9xSetInfoString (WINPROC_TURBO_SEL_ON);
1841 else S9xSetInfoString (WINPROC_TURBO_SEL_OFF);
1842 break;
1843 case ID_TURBO_LEFT:
1844 GUI.TurboMask^=TURBO_LEFT_MASK;
1845 if(GUI.TurboMask&TURBO_LEFT_MASK)
1846 S9xSetInfoString (WINPROC_TURBO_LEFT_ON);
1847 else S9xSetInfoString (WINPROC_TURBO_LEFT_OFF);
1848 break;
1849 case ID_TURBO_UP:
1850 GUI.TurboMask^=TURBO_UP_MASK;
1851 if(GUI.TurboMask&TURBO_UP_MASK)
1852 S9xSetInfoString (WINPROC_TURBO_UP_ON);
1853 else S9xSetInfoString (WINPROC_TURBO_UP_OFF);
1854 break;
1855 case ID_TURBO_RIGHT:
1856 GUI.TurboMask^=TURBO_RIGHT_MASK;
1857 if(GUI.TurboMask&TURBO_RIGHT_MASK)
1858 S9xSetInfoString (WINPROC_TURBO_RIGHT_ON);
1859 else S9xSetInfoString (WINPROC_TURBO_RIGHT_OFF);
1860 break;
1861 case ID_TURBO_DOWN:
1862 GUI.TurboMask^=TURBO_DOWN_MASK;
1863 if(GUI.TurboMask&TURBO_DOWN_MASK)
1864 S9xSetInfoString (WINPROC_TURBO_DOWN_ON);
1865 else S9xSetInfoString (WINPROC_TURBO_DOWN_OFF);
1866 break;
1867 //end turbo
1868 case ID_OPTIONS_DISPLAY:
1869 {
1870 RestoreGUIDisplay ();
1871
1872 if(GUI.FullScreen)
1873 ToggleFullScreen();
1874 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NEWDISPLAY), hWnd, DlgFunky);
1875
1876 SwitchToGDI();
1877
1878 RestoreSNESDisplay ();
1879
1880 S9xGraphicsDeinit();
1881 S9xSetWinPixelFormat ();
1882 S9xInitUpdate();
1883 S9xGraphicsInit();
1884
1885 IPPU.RenderThisFrame = false;
1886
1887
1888 RECT rect;
1889 GetClientRect (GUI.hWnd, &rect);
1890 InvalidateRect (GUI.hWnd, &rect, true);
1891 break;
1892 }
1893
1894 case ID_OPTIONS_JOYPAD:
1895 RestoreGUIDisplay ();
1896 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_INPUTCONFIG), hWnd, DlgInputConfig);
1897 RestoreSNESDisplay ();
1898 break;
1899
1900 case ID_OPTIONS_KEYCUSTOM:
1901 RestoreGUIDisplay ();
1902 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_KEYCUSTOM), hWnd, DlgHotkeyConfig);
1903 RestoreSNESDisplay ();
1904 break;
1905
1906 case ID_EMULATION_BACKGROUNDINPUT:
1907 GUI.BackgroundInput = !GUI.BackgroundInput;
1908 if(!GUI.hHotkeyTimer)
1909 GUI.hHotkeyTimer = timeSetEvent (32, 0, (LPTIMECALLBACK)HotkeyTimer, 0, TIME_PERIODIC);
1910 break;
1911
1912 case ID_FILE_LOADMULTICART:
1913 {
1914 #ifdef NETPLAY_SUPPORT
1915 if (Settings.NetPlay && !Settings.NetPlayServer)
1916 {
1917 S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER, WINPROC_DISCONNECT);
1918 break;
1919 }
1920 #endif
1921 RestoreGUIDisplay ();
1922
1923 const bool ok = (1 <= DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_MULTICART), GUI.hWnd, DlgMultiROMProc, (LPARAM)NULL));
1924
1925 if(ok)
1926 {
1927 if (!Settings.StopEmulation)
1928 {
1929 Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR));
1930 S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
1931 }
1932
1933 Settings.StopEmulation = !LoadMultiROM (multiRomA, multiRomB);
1934 if (!Settings.StopEmulation)
1935 {
1936 bool8 loadedSRAM = Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR));
1937 if(!loadedSRAM) // help migration from earlier Snes9x versions by checking ROM directory for savestates
1938 Memory.LoadSRAM (S9xGetFilename (".srm", ROMFILENAME_DIR));
1939 S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
1940 // S9xAddToRecentGames (multiRomA, multiRomB);
1941 CheckDirectoryIsWritable (S9xGetFilename (".---", SNAPSHOT_DIR));
1942 CheckMenuStates ();
1943 #ifdef NETPLAY_SUPPORT
1944 // still valid with multicart ???
1945 if (NPServer.SendROMImageOnConnect)
1946 S9xNPServerQueueSendingROMImage ();
1947 else
1948 S9xNPServerQueueSendingLoadROMRequest (Memory.ROMName);
1949 #endif
1950 }
1951
1952 if(GUI.ControllerOption == SNES_SUPERSCOPE)
1953 SetCursor (GUI.GunSight);
1954 else
1955 {
1956 SetCursor (GUI.Arrow);
1957 GUI.CursorTimer = 60;
1958 }
1959 Settings.Paused = false;
1960 }
1961
1962 RestoreSNESDisplay ();
1963 }
1964 break;
1965
1966 case ID_FILE_LOAD_GAME:
1967 {
1968 TCHAR filename [_MAX_PATH];
1969
1970 RestoreGUIDisplay ();
1971
1972 if(DoOpenRomDialog(filename)) {
1973 LoadROM(filename);
1974 }
1975
1976 RestoreSNESDisplay ();
1977 }
1978 break;
1979
1980 case ID_FILE_EXIT:
1981 S9xSetPause (PAUSE_EXIT);
1982 PostMessage (hWnd, WM_DESTROY, 0, 0);
1983 break;
1984
1985 case ID_WINDOW_HIDEMENUBAR:
1986 if( GetMenu( GUI.hWnd) == NULL)
1987 SetMenu( GUI.hWnd, GUI.hMenu);
1988 else
1989 SetMenu( GUI.hWnd, NULL);
1990 break;
1991
1992 #ifdef NETPLAY_SUPPORT
1993 case ID_NETPLAY_SERVER:
1994 S9xRestoreWindowTitle ();
1995 EnableServer (!Settings.NetPlayServer);
1996 if(Settings.NetPlayServer)
1997 {
1998 TCHAR localhostmsg [512];
1999 // FIXME: need winsock2.h for this, don't know how to include it
2000 //struct addrinfo *aiList = NULL;
2001 //if(getaddrinfo("localhost", Settings.Port, NULL, &aiList) == 0)
2002 //{
2003 // sprintf(localhostmsg, "Your server address is: %s", aiList->ai_canonname);
2004 // MessageBox(GUI.hWnd,localhostmsg,"Note",MB_OK);
2005 //}
2006 //else
2007 {
2008 char localhostname [256];
2009 gethostname(localhostname,256);
2010 _stprintf(localhostmsg, TEXT("Your host name is: %s\nYour port number is: %d"), _tFromChar(localhostname), Settings.Port);
2011 MessageBox(GUI.hWnd,localhostmsg,TEXT("Note"),MB_OK);
2012 }
2013 }
2014 break;
2015 case ID_NETPLAY_CONNECT:
2016 RestoreGUIDisplay ();
2017 if(1<=DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_NETCONNECT), hWnd, DlgNetConnect,(LPARAM)&hostname))
2018
2019 {
2020
2021
2022 S9xSetPause (PAUSE_NETPLAY_CONNECT);
2023
2024 if (!S9xNPConnectToServer (_tToChar(hostname), Settings.Port,
2025 Memory.ROMName))
2026 {
2027 S9xClearPause (PAUSE_NETPLAY_CONNECT);
2028 }
2029 }
2030
2031 RestoreSNESDisplay ();
2032 break;
2033 case ID_NETPLAY_DISCONNECT:
2034 if (Settings.NetPlay)
2035 {
2036 Settings.NetPlay = FALSE;
2037 S9xNPDisconnect ();
2038 }
2039 if (Settings.NetPlayServer)
2040 {
2041 Settings.NetPlayServer = FALSE;
2042 S9xNPStopServer ();
2043 }
2044 break;
2045 case ID_NETPLAY_OPTIONS:
2046 {
2047 bool8 old_netplay_server = Settings.NetPlayServer;
2048 RestoreGUIDisplay ();
2049 if(1<=DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NPOPTIONS), hWnd, DlgNPOptions))
2050 {
2051 if (old_netplay_server != Settings.NetPlayServer)
2052 {
2053 Settings.NetPlayServer = old_netplay_server;
2054 S9xRestoreWindowTitle ();
2055 EnableServer (!Settings.NetPlayServer);
2056 }
2057 }
2058 RestoreSNESDisplay ();
2059 break;
2060 }
2061 case ID_NETPLAY_SYNC:
2062 S9xNPServerQueueSyncAll ();
2063 break;
2064 case ID_NETPLAY_ROM:
2065 if (NPServer.SyncByReset)
2066 {
2067 if (MessageBox (GUI.hWnd, TEXT(WINPROC_NET_RESTART), SNES9X_WARN,
2068 MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL)
2069 break;
2070 }
2071 S9xNPServerQueueSendingROMImage ();
2072 break;
2073 case ID_NETPLAY_SEND_ROM_ON_CONNECT:
2074 NPServer.SendROMImageOnConnect ^= TRUE;
2075 break;
2076 case ID_NETPLAY_SYNC_BY_RESET:
2077 NPServer.SyncByReset ^= TRUE;
2078 break;
2079 #endif
2080 case ID_SOUND_8000HZ:
2081 case ID_SOUND_11025HZ:
2082 case ID_SOUND_16000HZ:
2083 case ID_SOUND_22050HZ:
2084 case ID_SOUND_30000HZ:
2085 case ID_SOUND_35000HZ:
2086 case ID_SOUND_44100HZ:
2087 case ID_SOUND_48000HZ:
2088 case ID_SOUND_32000HZ:
2089 for( i = 0; i < COUNT(SoundRates); i ++)
2090 if (SoundRates[i].ident == (int) wParam)
2091 {
2092 Settings.SoundPlaybackRate = SoundRates [i].rate;
2093 GUI.Mute = false;
2094 ReInitSound();
2095 break;
2096 }
2097 break;
2098
2099 case ID_SOUND_16MS:
2100 GUI.SoundBufferSize = 16;
2101 ReInitSound();
2102 break;
2103 case ID_SOUND_32MS:
2104 GUI.SoundBufferSize = 32;
2105 ReInitSound();
2106 break;
2107 case ID_SOUND_48MS:
2108 GUI.SoundBufferSize = 48;
2109 ReInitSound();
2110 break;
2111 case ID_SOUND_64MS:
2112 GUI.SoundBufferSize = 64;
2113 ReInitSound();
2114 break;
2115 case ID_SOUND_80MS:
2116 GUI.SoundBufferSize = 80;
2117 ReInitSound();
2118 break;
2119 case ID_SOUND_96MS:
2120 GUI.SoundBufferSize = 96;
2121 ReInitSound();
2122 break;
2123 case ID_SOUND_112MS:
2124 GUI.SoundBufferSize = 112;
2125 ReInitSound();
2126 break;
2127 case ID_SOUND_128MS:
2128 GUI.SoundBufferSize = 128;
2129 ReInitSound();
2130 break;
2131 case ID_SOUND_144MS:
2132 GUI.SoundBufferSize = 144;
2133 ReInitSound();
2134 break;
2135 case ID_SOUND_160MS:
2136 GUI.SoundBufferSize = 160;
2137 ReInitSound();
2138 break;
2139 case ID_SOUND_176MS:
2140 GUI.SoundBufferSize = 176;
2141 ReInitSound();
2142 break;
2143 case ID_SOUND_194MS:
2144 GUI.SoundBufferSize = 194;
2145 ReInitSound();
2146 break;
2147 case ID_SOUND_210MS:
2148 GUI.SoundBufferSize = 210;
2149 ReInitSound();
2150 break;
2151
2152
2153 case ID_CHANNELS_CHANNEL1: S9xToggleSoundChannel(0); break;
2154 case ID_CHANNELS_CHANNEL2: S9xToggleSoundChannel(1); break;
2155 case ID_CHANNELS_CHANNEL3: S9xToggleSoundChannel(2); break;
2156 case ID_CHANNELS_CHANNEL4: S9xToggleSoundChannel(3); break;
2157 case ID_CHANNELS_CHANNEL5: S9xToggleSoundChannel(4); break;
2158 case ID_CHANNELS_CHANNEL6: S9xToggleSoundChannel(5); break;
2159 case ID_CHANNELS_CHANNEL7: S9xToggleSoundChannel(6); break;
2160 case ID_CHANNELS_CHANNEL8: S9xToggleSoundChannel(7); break;
2161 case ID_CHANNELS_ENABLEALL: S9xToggleSoundChannel(8); break;
2162
2163 case ID_SOUND_NOSOUND:
2164 S9xSetSoundMute(!GUI.Mute);
2165 GUI.Mute = !GUI.Mute;
2166 break;
2167
2168 case ID_SOUND_STEREO:
2169 Settings.Stereo = !Settings.Stereo;
2170 ReInitSound();
2171 break;
2172 case ID_SOUND_REVERSE_STEREO:
2173 Settings.ReverseStereo = !Settings.ReverseStereo;
2174 break;
2175 case ID_SOUND_16BIT:
2176 Settings.SixteenBitSound = !Settings.SixteenBitSound;
2177 ReInitSound();
2178 break;
2179 case ID_SOUND_SYNC:
2180 Settings.SoundSync = !Settings.SoundSync;
2181 S9xDisplayStateChange (WINPROC_SYNC_SND, Settings.SoundSync);
2182 break;
2183 case ID_SOUND_OPTIONS:
2184 {
2185 RestoreGUIDisplay ();
2186 if(1<=DialogBoxParam(g_hInst,MAKEINTRESOURCE(IDD_SOUND_OPTS),hWnd,DlgSoundConf, (LPARAM)&Settings))
2187 {
2188 ReInitSound();
2189 }
2190 RestoreSNESDisplay ();
2191 break;
2192 }
2193 case ID_WINDOW_FULLSCREEN:
2194 ToggleFullScreen ();
2195 break;
2196 case ID_WINDOW_SIZE_1X:
2197 case ID_WINDOW_SIZE_2X:
2198 case ID_WINDOW_SIZE_3X:
2199 case ID_WINDOW_SIZE_4X:
2200 UINT factor, newWidth, newHeight;
2201 RECT margins;
2202 factor = (wParam & 0xffff) - ID_WINDOW_SIZE_1X + 1;
2203 newWidth = GUI.AspectWidth * factor;
2204 newHeight = (GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * factor;
2205
2206 margins = GetWindowMargins(GUI.hWnd,newWidth);
2207 newHeight += margins.top + margins.bottom;
2208 newWidth += margins.left + margins.right;
2209
2210 SetWindowPos(GUI.hWnd, NULL, 0, 0, newWidth, newHeight, SWP_NOMOVE);
2211 break;
2212 case ID_WINDOW_STRETCH:
2213 GUI.Stretch = !GUI.Stretch;
2214 WinDisplayApplyChanges();
2215 WinRefreshDisplay();
2216 break;
2217 case ID_WINDOW_ASPECTRATIO:
2218 GUI.AspectRatio = !GUI.AspectRatio;
2219 WinDisplayApplyChanges();
2220 WinRefreshDisplay();
2221 break;
2222 case ID_WINDOW_BILINEAR:
2223 GUI.BilinearFilter = !GUI.BilinearFilter;
2224 WinDisplayApplyChanges();
2225 WinRefreshDisplay();
2226 break;
2227 case ID_VIDEO_SHOWFRAMERATE:
2228 Settings.DisplayFrameRate = !Settings.DisplayFrameRate;
2229 break;
2230 case ID_SAVESCREENSHOT:
2231 Settings.TakeScreenshot=true;
2232 break;
2233 case ID_FILE_SAVE_SPC_DATA:
2234 S9xDumpSPCSnapshot();
2235 S9xMessage(S9X_INFO, 0, INFO_SAVE_SPC);
2236 break;
2237 case ID_FILE_SAVE_SRAM_DATA: {
2238 bool8 success = Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR));
2239 if(!success)
2240 S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_INFO, SRM_SAVE_FAILED);
2241 } break;
2242 case ID_FILE_RESET:
2243 #ifdef NETPLAY_SUPPORT
2244 if (Settings.NetPlayServer)
2245 {
2246 S9xNPReset ();
2247 ReInitSound();
2248 }
2249 else
2250 if (!Settings.NetPlay)
2251 #endif
2252 {
2253 S9xMovieUpdateOnReset ();
2254 if(S9xMoviePlaying())
2255 S9xMovieStop (TRUE);
2256 S9xSoftReset ();
2257 ReInitSound();
2258 }
2259 if(!S9xMovieRecording())
2260 Settings.Paused = false;
2261 break;
2262 case ID_FILE_PAUSE:
2263 Settings.Paused = !Settings.Paused;
2264 Settings.FrameAdvance = false;
2265 GUI.FrameAdvanceJustPressed = 0;
2266 break;
2267 case ID_FILE_LOAD0:
2268 FreezeUnfreeze (0, FALSE);
2269 break;
2270 case ID_FILE_LOAD1:
2271 FreezeUnfreeze (1, FALSE);
2272 break;
2273 case ID_FILE_LOAD2:
2274 FreezeUnfreeze (2, FALSE);
2275 break;
2276 case ID_FILE_LOAD3:
2277 FreezeUnfreeze (3, FALSE);
2278 break;
2279 case ID_FILE_LOAD4:
2280 FreezeUnfreeze (4, FALSE);
2281 break;
2282 case ID_FILE_LOAD5:
2283 FreezeUnfreeze (5, FALSE);
2284 break;
2285 case ID_FILE_LOAD6:
2286 FreezeUnfreeze (6, FALSE);
2287 break;
2288 case ID_FILE_LOAD7:
2289 FreezeUnfreeze (7, FALSE);
2290 break;
2291 case ID_FILE_LOAD8:
2292 FreezeUnfreeze (8, FALSE);
2293 break;
2294 case ID_FILE_LOAD9:
2295 FreezeUnfreeze (9, FALSE);
2296 break;
2297 case ID_FILE_SAVE0:
2298 FreezeUnfreeze (0, TRUE);
2299 break;
2300 case ID_FILE_SAVE1:
2301 FreezeUnfreeze (1, TRUE);
2302 break;
2303 case ID_FILE_SAVE2:
2304 FreezeUnfreeze (2, TRUE);
2305 break;
2306 case ID_FILE_SAVE3:
2307 FreezeUnfreeze (3, TRUE);
2308 break;
2309 case ID_FILE_SAVE4:
2310 FreezeUnfreeze (4, TRUE);
2311 break;
2312 case ID_FILE_SAVE5:
2313 FreezeUnfreeze (5, TRUE);
2314 break;
2315 case ID_FILE_SAVE6:
2316 FreezeUnfreeze (6, TRUE);
2317 break;
2318 case ID_FILE_SAVE7:
2319 FreezeUnfreeze (7, TRUE);
2320 break;
2321 case ID_FILE_SAVE8:
2322 FreezeUnfreeze (8, TRUE);
2323 break;
2324 case ID_FILE_SAVE9:
2325 FreezeUnfreeze (9, TRUE);
2326 break;
2327 case ID_CHEAT_ENTER:
2328 RestoreGUIDisplay ();
2329 S9xRemoveCheats ();
2330 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CHEATER), hWnd, DlgCheater);
2331 S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
2332 S9xApplyCheats ();
2333 RestoreSNESDisplay ();
2334 break;
2335 case ID_CHEAT_SEARCH:
2336 RestoreGUIDisplay ();
2337 if(!cheatSearchHWND) // create and show non-modal cheat search window
2338 {
2339 cheatSearchHWND = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_CHEAT_SEARCH), hWnd, DlgCheatSearch); // non-modal/modeless
2340 ShowWindow(cheatSearchHWND, SW_SHOW);
2341 }
2342 else // already open so just reactivate the window
2343 {
2344 SetActiveWindow(cheatSearchHWND);
2345 }
2346 RestoreSNESDisplay ();
2347 break;
2348 case ID_CHEAT_SEARCH_MODAL:
2349 RestoreGUIDisplay ();
2350 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CHEAT_SEARCH), hWnd, DlgCheatSearch); // modal
2351 S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
2352 RestoreSNESDisplay ();
2353 break;
2354 case ID_CHEAT_APPLY:
2355 Settings.ApplyCheats = !Settings.ApplyCheats;
2356 if (!Settings.ApplyCheats){
2357 S9xRemoveCheats ();
2358 S9xMessage (S9X_INFO, S9X_GAME_GENIE_CODE_ERROR, CHEATS_INFO_DISABLED);
2359 }else{
2360 S9xApplyCheats ();
2361 bool on = false;
2362 extern struct SCheatData Cheat;
2363 for (uint32 i = 0; i < Cheat.num_cheats && !on; i++)
2364 if (Cheat.c [i].enabled)
2365 on = true;
2366 S9xMessage (S9X_INFO, S9X_GAME_GENIE_CODE_ERROR, on ? CHEATS_INFO_ENABLED : CHEATS_INFO_ENABLED_NONE);
2367 }
2368 break;
2369 case ID_EMULATION_PAUSEWHENINACTIVE:
2370 GUI.InactivePause = !GUI.InactivePause;
2371 break;
2372 case ID_OPTIONS_SETTINGS:
2373 RestoreGUIDisplay ();
2374 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_EMU_SETTINGS), hWnd, DlgEmulatorProc);
2375 RestoreSNESDisplay ();
2376 break;
2377 case ID_HELP_ABOUT:
2378 RestoreGUIDisplay ();
2379 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, DlgAboutProc);
2380 RestoreSNESDisplay ();
2381 break;
2382 case ID_FRAME_ADVANCE:
2383 Settings.Paused = true;
2384 Settings.FrameAdvance = true;
2385 break;
2386 #ifdef DEBUGGER
2387 case ID_DEBUG_TRACE:
2388 CPU.Flags ^= TRACE_FLAG;
2389 break;
2390
2391 case ID_DEBUG_FRAME_ADVANCE:
2392 CPU.Flags |= FRAME_ADVANCE_FLAG;
2393 ICPU.FrameAdvanceCount = 1;
2394 Settings.Paused = FALSE;
2395 break;
2396 case ID_DEBUG_APU_TRACE:
2397 spc_core->debug_toggle_trace();
2398 break;
2399 #endif
2400 case IDM_ROM_INFO:
2401 RestoreGUIDisplay ();
2402 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ROM_INFO), hWnd, DlgInfoProc);
2403 RestoreSNESDisplay ();
2404 break;
2405 default:
2406 if ((wParam & 0xffff) >= 0xFF00)
2407 {
2408 int i = (wParam & 0xffff) - 0xFF00;
2409 int j = 0;
2410 {
2411 while (j < MAX_RECENT_GAMES_LIST_SIZE && j != i)
2412 j++;
2413 if (i == j)
2414 {
2415
2416 if (!LoadROM(GUI.RecentGames [i])) {
2417 sprintf (String, ERR_ROM_NOT_FOUND, _tToChar(GUI.RecentGames [i]));
2418 S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String);
2419 S9xRemoveFromRecentGames(i);
2420 }
2421 }
2422 }
2423 }
2424 break;
2425 }
2426 break;
2427
2428 case WM_EXITMENULOOP:
2429 UpdateWindow(GUI.hWnd);
2430 DrawMenuBar(GUI.hWnd);
2431 S9xClearPause (PAUSE_MENU);
2432 break;
2433
2434 case WM_ENTERMENULOOP:
2435 S9xSetPause (PAUSE_MENU);
2436 CheckMenuStates ();
2437
2438 SwitchToGDI();
2439 DrawMenuBar(GUI.hWnd);
2440 break;
2441
2442 case WM_CLOSE:
2443 SaveMainWinPos();
2444 break;
2445
2446 case WM_DESTROY:
2447 Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR));
2448 GUI.hWnd = NULL;
2449 PostQuitMessage (0);
2450 return (0);
2451 case WM_PAINT:
2452 {
2453 // refresh screen
2454 WinRefreshDisplay();
2455 break;
2456 }
2457 case WM_SYSCOMMAND:
2458 {
2459 // Prevent screen saver from starting if not paused
2460 //kode54 says add the ! to fix the screensaver pevention.
2461 if (!(Settings.ForcedPause || Settings.StopEmulation ||
2462 (Settings.Paused && !Settings.FrameAdvance)) &&
2463 (wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER))
2464 return (0);
2465 break;
2466 }
2467 case WM_ACTIVATE:
2468 if (LOWORD(wParam) == WA_INACTIVE)
2469 {
2470 if(GUI.InactivePause)
2471 {
2472 S9xSetPause (PAUSE_INACTIVE_WINDOW);
2473 }
2474 }
2475 else
2476 {
2477 Settings.TurboMode = false;
2478 /// if(GUI.InactivePause)
2479 {
2480 S9xClearPause (PAUSE_INACTIVE_WINDOW);
2481 }
2482 IPPU.ColorsChanged = TRUE;
2483 }
2484 break;
2485 case WM_QUERYNEWPALETTE:
2486 // if (!GUI.FullScreen && GUI.ScreenDepth == 8)
2487 // RealizePalette (GUI.WindowDC);
2488 break;
2489 case WM_SIZE:
2490 WinChangeWindowSize(LOWORD(lParam),HIWORD(lParam));
2491 break;
2492 case WM_MOVE:
2493 //if (!VOODOO_MODE && !GUI.FullScreen && !Settings.ForcedPause)
2494 //{
2495 // GetWindowRect (GUI.hWnd, &GUI.window_size);
2496 //}
2497
2498 break;
2499 case WM_ENTERSIZEMOVE:
2500 S9xSetPause(PAUSE_MENU);
2501 break;
2502 case WM_EXITSIZEMOVE:
2503 S9xClearPause(PAUSE_MENU);
2504 break;
2505 case WM_DISPLAYCHANGE:
2506 if (!GUI.FullScreen && !(Settings.ForcedPause & PAUSE_TOGGLE_FULL_SCREEN))
2507 {
2508 WinDisplayReset();
2509 }
2510 break;
2511 case WM_MOUSEMOVE:
2512 if(Settings.StopEmulation)
2513 {
2514 SetCursor (GUI.Arrow);
2515 break;
2516 }
2517 // Lo-word of lparam is xpos, hi-word is ypos
2518 // if (!GUI.IgnoreNextMouseMove)
2519 {
2520 //POINT p;
2521 //p.x = GET_X_LPARAM(lParam);
2522 //p.y = GET_Y_LPARAM(lParam);
2523 //ClientToScreen (GUI.hWnd, &p);
2524 if ((!Settings.ForcedPause && !Settings.StopEmulation &&
2525 !(Settings.Paused && !Settings.FrameAdvance)) &&
2526 (GUI.ControllerOption==SNES_MOUSE || GUI.ControllerOption==SNES_MOUSE_SWAPPED)
2527 )
2528 {
2529 CenterCursor();
2530 }
2531 else if (GUI.ControllerOption==SNES_SUPERSCOPE || GUI.ControllerOption==SNES_JUSTIFIER || GUI.ControllerOption==SNES_JUSTIFIER_2)
2532 {
2533 RECT size;
2534 GetClientRect (GUI.hWnd, &size);
2535 if(!(GUI.Scale)&&!(GUI.Stretch))
2536 {
2537 int x,y, startx, starty;
2538 x=GET_X_LPARAM(lParam);
2539 y=GET_Y_LPARAM(lParam);
2540
2541 // int theight;
2542 // (IPPU.RenderedScreenHeight> 256)? theight= SNES_HEIGHT_EXTENDED<<1: theight = SNES_HEIGHT_EXTENDED;
2543 int theight = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
2544 if(IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED) theight <<= 1;
2545
2546 startx= size.right-IPPU.RenderedScreenWidth;
2547 startx/=2;
2548 starty= size.bottom-theight;
2549 starty/=2;
2550
2551 if(x<startx)
2552 GUI.MouseX=0;
2553 else if(x>(startx+IPPU.RenderedScreenWidth))
2554 GUI.MouseX=IPPU.RenderedScreenWidth;
2555 else GUI.MouseX=x-startx;
2556
2557 if(y<starty)
2558 GUI.MouseY=0;
2559 else if(y>(starty+theight))
2560 GUI.MouseY=theight;
2561 else GUI.MouseY=y-starty;
2562 }
2563 else if(!(GUI.Stretch))
2564 {
2565 int x,y, startx, starty, sizex, sizey;
2566 x=GET_X_LPARAM(lParam);
2567 y=GET_Y_LPARAM(lParam);
2568
2569 if (IPPU.RenderedScreenWidth>256)
2570 sizex=IPPU.RenderedScreenWidth;
2571 else sizex=IPPU.RenderedScreenWidth*2;
2572
2573 int theight = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
2574 sizey = (IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED) ? theight : (theight << 1);
2575
2576 startx= size.right-sizex;
2577 startx/=2;
2578 starty= size.bottom-sizey;
2579 starty/=2;
2580 if(x<startx)
2581 GUI.MouseX=0;
2582 else if(x>(startx+sizex))
2583 GUI.MouseX=sizex;
2584 else GUI.MouseX=x-startx;
2585
2586 if(y<starty)
2587 GUI.MouseY=0;
2588 else if(y>(starty+sizey))
2589 GUI.MouseY=sizey;
2590 else GUI.MouseY=y-starty;
2591
2592 GUI.MouseX=(GUI.MouseX*IPPU.RenderedScreenWidth)/sizex;
2593 GUI.MouseY=(GUI.MouseY*IPPU.RenderedScreenHeight)/sizey;
2594 }
2595 else
2596 {
2597 int sizex = IPPU.RenderedScreenWidth;
2598 int sizey = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
2599 sizey = (IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED) ? (sizey << 1) : sizey;
2600 int width = size.right, height = size.bottom, xdiff = 0, ydiff = 0;
2601 if(GUI.AspectRatio)
2602 {
2603 if(width > sizex*height/sizey)
2604 {
2605 xdiff = width - sizex*height/sizey;
2606 width -= xdiff;
2607 xdiff >>= 1;
2608 }
2609 else if(height > sizey*width/sizex)
2610 {
2611 ydiff = height - sizey*width/sizex;
2612 height -= ydiff;
2613 ydiff >>= 1;
2614 }
2615 }
2616 GUI.MouseX=(GET_X_LPARAM(lParam)-xdiff)*sizex/width;
2617 GUI.MouseY=(GET_Y_LPARAM(lParam)-ydiff)*sizey/height;
2618 }
2619 }
2620 else
2621 {
2622 // GUI.MouseX = p.x;
2623 // GUI.MouseY = p.y;
2624 }
2625 }
2626 // else
2627 // GUI.IgnoreNextMouseMove = false;
2628
2629 if(!GUI.IgnoreNextMouseMove)
2630 S9xMouseOn ();
2631 else
2632 GUI.IgnoreNextMouseMove = false;
2633 return 0;
2634 case WM_LBUTTONDOWN:
2635 S9xMouseOn ();
2636 GUI.MouseButtons |= 1;
2637 break;
2638 case WM_LBUTTONUP:
2639 S9xMouseOn ();
2640 GUI.MouseButtons &= ~1;
2641 break;
2642 case WM_RBUTTONDOWN:
2643 S9xMouseOn ();
2644 GUI.MouseButtons |= 2;
2645 break;
2646 case WM_RBUTTONUP:
2647 S9xMouseOn ();
2648 GUI.MouseButtons &= ~2;
2649 if(GUI.ControllerOption==SNES_JUSTIFIER || GUI.ControllerOption==SNES_JUSTIFIER_2)
2650 {
2651 RECT size;
2652 GetClientRect (GUI.hWnd, &size);
2653 GUI.MouseButtons&=~1;
2654 GUI.MouseX=(IPPU.RenderedScreenWidth*(lParam & 0xffff))/(size.right-size.left);
2655 GUI.MouseY=(((lParam >> 16) & 0xffff)*IPPU.RenderedScreenHeight)/(size.bottom-size.top);
2656 }
2657 break;
2658 case WM_MBUTTONDOWN:
2659 S9xMouseOn ();
2660 GUI.MouseButtons |= 4;
2661 break;
2662 case WM_MBUTTONUP:
2663 S9xMouseOn ();
2664 GUI.MouseButtons &= ~4;
2665 break;
2666 #ifdef NETPLAY_SUPPORT
2667 case WM_USER + 3:
2668 NetPlay.Answer = S9xLoadROMImage (_tFromChar((const char *) lParam));
2669 SetEvent (NetPlay.ReplyEvent);
2670 break;
2671 case WM_USER + 2:
2672 S9xMessage (0, 0, NetPlay.WarningMsg);
2673 break;
2674 case WM_USER + 1:
2675 RestoreGUIDisplay ();
2676 S9xRestoreWindowTitle ();
2677 MessageBox (GUI.hWnd, _tFromChar(NetPlay.ErrorMsg),
2678 SNES9X_NP_ERROR, MB_OK | MB_ICONSTOP);
2679 RestoreSNESDisplay ();
2680 break;
2681 case WM_USER:
2682 if (NetPlay.ActionMsg [0] == 0)
2683 S9xRestoreWindowTitle ();
2684 else
2685 {
2686 TCHAR buf [NP_MAX_ACTION_LEN + 10];
2687
2688 _stprintf (buf, TEXT("%s %3d%%"), _tFromChar(NetPlay.ActionMsg), (int) lParam);
2689 SetWindowText (GUI.hWnd, buf);
2690 }
2691 #if 0
2692 if ((int) lParam >= 0)
2693 {
2694 RestoreGUIDisplay ();
2695 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NETPLAYPROGRESS), hWnd, DlgNPProgress);
2696 }
2697 else
2698 {
2699 DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NETPLAYPROGRESS), hWnd, DlgNPProgress);
2700 RestoreSNESDisplay ();
2701 }
2702 #endif
2703 break;
2704 #endif
2705 case WM_DEVICECHANGE:
2706 if(wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE || wParam == DBT_DEVNODES_CHANGED)
2707 PostMessage(hWnd, WM_SCANJOYPADS, 0, 0);
2708 break;
2709 case WM_SCANJOYPADS:
2710 S9xDetectJoypads();
2711 break;
2712 }
2713 return DefWindowProc (hWnd, uMsg, wParam, lParam);
2714 }
2715
2716 /*****************************************************************************/
2717 /* WinInit */
2718 /*****************************************************************************/
WinInit(HINSTANCE hInstance)2719 BOOL WinInit( HINSTANCE hInstance)
2720 {
2721 WNDCLASSEX wndclass;
2722 memset(&wndclass, 0, sizeof(wndclass));
2723 wndclass.cbSize = sizeof(wndclass);
2724
2725 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
2726 wndclass.lpfnWndProc = WinProc;
2727 wndclass.hInstance = hInstance;
2728 wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
2729 wndclass.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0);
2730 wndclass.hCursor = NULL;
2731 wndclass.lpszMenuName = NULL;
2732 wndclass.lpszClassName = TEXT("Snes9X: WndClass");
2733 wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
2734
2735 GUI.hInstance = hInstance;
2736
2737 if (!RegisterClassEx (&wndclass))
2738 {
2739 MessageBox (NULL, TEXT("Failed to register windows class"), TEXT("Internal Error"), MB_OK | MB_ICONSTOP);
2740 return FALSE;
2741 }
2742
2743 GUI.hMenu = LoadMenu(GUI.hInstance, MAKEINTRESOURCE(IDR_MENU_US));
2744 if (GUI.hMenu == NULL)
2745 {
2746 MessageBox (NULL, TEXT("Failed to initialize the menu.\nThis could indicate a failure of your operating system;\ntry closing some other windows or programs, or restart your computer, before opening Snes9x again.\nOr, if you compiled this program yourself, ensure that Snes9x was built with the proper resource files."), TEXT("Snes9X - Menu Initialization Failure"), MB_OK | MB_ICONSTOP);
2747 // return FALSE; // disabled: try to function without the menu
2748 }
2749 #ifdef DEBUGGER
2750 if(GUI.hMenu) {
2751 InsertMenu(GUI.hMenu,ID_OPTIONS_SETTINGS,MF_BYCOMMAND | MF_STRING | MF_ENABLED,ID_DEBUG_FRAME_ADVANCE,TEXT("&Debug Frame Advance"));
2752 InsertMenu(GUI.hMenu,ID_OPTIONS_SETTINGS,MF_BYCOMMAND | MF_STRING | MF_ENABLED,ID_DEBUG_TRACE,TEXT("&Trace"));
2753 InsertMenu(GUI.hMenu,ID_OPTIONS_SETTINGS,MF_BYCOMMAND | MF_STRING | MF_ENABLED,ID_DEBUG_APU_TRACE,TEXT("&APU Trace"));
2754 InsertMenu(GUI.hMenu,ID_OPTIONS_SETTINGS,MF_BYCOMMAND | MF_SEPARATOR | MF_ENABLED,NULL,NULL);
2755 }
2756 #endif
2757
2758 TCHAR buf [100];
2759 _stprintf (buf, WINDOW_TITLE, TEXT(VERSION));
2760
2761 DWORD dwExStyle;
2762 DWORD dwStyle;
2763 RECT rect;
2764
2765 rect.left = rect.top = 0;
2766 rect.right = MAX_SNES_WIDTH;
2767 rect.bottom = MAX_SNES_HEIGHT;
2768 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
2769 dwStyle = WS_OVERLAPPEDWINDOW;
2770
2771 AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
2772 if ((GUI.hWnd = CreateWindowEx (
2773 dwExStyle,
2774 TEXT("Snes9X: WndClass"),
2775 buf,
2776 WS_CLIPSIBLINGS |
2777 WS_CLIPCHILDREN |
2778 dwStyle,
2779 0, 0,
2780 rect.right - rect.left, rect.bottom - rect.top,
2781 NULL,
2782 GUI.hMenu,
2783 hInstance,
2784 NULL)) == NULL)
2785 return FALSE;
2786
2787 GUI.hDC = GetDC (GUI.hWnd);
2788 GUI.GunSight = LoadCursor (hInstance, MAKEINTRESOURCE (IDC_CURSOR_SCOPE));
2789 GUI.Arrow = LoadCursor (NULL, IDC_ARROW);
2790 GUI.Accelerators = LoadAccelerators (hInstance, MAKEINTRESOURCE (IDR_SNES9X_ACCELERATORS));
2791 Settings.ForcedPause = 0;
2792 Settings.StopEmulation = TRUE;
2793 Settings.Paused = FALSE;
2794
2795 GUI.AVIOut = NULL;
2796
2797 return TRUE;
2798 }
2799
2800
2801
S9xExtraUsage()2802 void S9xExtraUsage ()
2803 {
2804 }
2805
2806 // handles joystick hotkey presses
HotkeyTimer(UINT idEvent,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)2807 VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
2808 {
2809 // static int lastTime = timeGetTime();
2810 // if(timeGetTime() - lastTime > 5)
2811 {
2812 bool S9xGetState (WORD KeyIdent);
2813
2814 if(GUI.JoystickHotkeys)
2815 {
2816 static int counter = 0;
2817 static uint32 joyState[6][53];
2818 for(int j = 0 ; j < 6 ; j++)
2819 {
2820 for(int i = 0 ; i < 53 ; i++)
2821 {
2822 if(counter%2 && !joyState[j][i])
2823 continue;
2824
2825 WPARAM wp = (WPARAM)(0x8000 | (j << 8) | i);
2826 bool active = !S9xGetState(wp);
2827 if(active)
2828 {
2829 if(joyState[j][i] < ULONG_MAX) // 0xffffffffUL
2830 joyState[j][i]++;
2831 if(joyState[j][i] == 1 || joyState[j][i] >= 12)
2832 PostMessage(GUI.hWnd, WM_CUSTKEYDOWN, wp,(LPARAM)(NULL));
2833 }
2834 else
2835 if(joyState[j][i])
2836 {
2837 joyState[j][i] = 0;
2838 PostMessage(GUI.hWnd, WM_CUSTKEYUP, wp,(LPARAM)(NULL));
2839 }
2840 }
2841 }
2842 counter++;
2843 }
2844 if(GUI.BackgroundInput && !GUI.InactivePause)
2845 {
2846 static int counter = 0;
2847 static uint32 joyState [256];
2848 for(int i = 0 ; i < 255 ; i++)
2849 {
2850 if(counter%2 && !joyState[i])
2851 continue;
2852
2853 bool active = !S9xGetState(i);
2854 if(active)
2855 {
2856 if(joyState[i] < ULONG_MAX) // 0xffffffffUL
2857 joyState[i]++;
2858 if(joyState[i] == 1 || joyState[i] >= 12)
2859 PostMessage(GUI.hWnd, WM_CUSTKEYDOWN, (WPARAM)(i),(LPARAM)(NULL));
2860 }
2861 else
2862 if(joyState[i])
2863 {
2864 joyState[i] = 0;
2865 PostMessage(GUI.hWnd, WM_CUSTKEYUP, (WPARAM)(i),(LPARAM)(NULL));
2866 }
2867 }
2868 counter++;
2869 }
2870 // lastTime = timeGetTime();
2871 }
2872 }
2873
FrameTimer(UINT idEvent,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)2874 void CALLBACK FrameTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
2875 {
2876 // QueryPerformanceCounter is unreliable on newfangled frequency-switching computers,
2877 // yet is absolutely necessary for best performance on somewhat older computers (even ones that are capable of frequency switching but don't do it very often).
2878 // Thus, we keep two timers and use the QueryPerformanceCounter one unless the other (more accurate but less precise)
2879 // one differs from it by more than a few milliseconds.
2880
2881 QueryPerformanceCounter((LARGE_INTEGER*)&PCEnd);
2882 PCEndTicks = timeGetTime()*1000;
2883
2884 const __int64 PCElapsedPrecise = PCEnd - PCStart;
2885 const __int64 PCElapsedAccurate = (__int64)(PCEndTicks - PCStartTicks) * PCBase / 1000000;
2886 const bool useTicksTimer = (abs((int)(PCElapsedPrecise - PCElapsedAccurate)) > (PCBase >> 7)); // if > 7.8 ms difference, settle for accuracy at the sacrifice of precision
2887
2888 while ((!useTicksTimer && (PCEnd - PCStart ) >= PCFrameTime) ||
2889 ( useTicksTimer && (PCEndTicks - PCStartTicks) >= PCFrameTime * 1000000 / PCBase))
2890 {
2891 if (GUI.FrameCount == GUI.LastFrameCount)
2892 GUI.IdleCount++;
2893 else
2894 {
2895 GUI.IdleCount = 0;
2896 GUI.LastFrameCount = GUI.FrameCount;
2897 }
2898
2899 #ifdef NETPLAY_SUPPORT
2900 // if (Settings.NetPlay && !Settings.NetPlayServer)
2901 // return;
2902 if (Settings.NetPlay && !Settings.NetPlayServer)
2903 return;
2904
2905 //- if (Settings.NetPlayServer)
2906 //- {
2907 //- if (Settings.Paused || Settings.StopEmulation || Settings.ForcedPause)
2908 if (Settings.NetPlayServer)
2909 {
2910 //- WaitForSingleObject (GUI.ServerTimerSemaphore, 0);
2911 if ((Settings.Paused && !Settings.FrameAdvance) || Settings.StopEmulation || Settings.ForcedPause)
2912 {
2913 WaitForSingleObject (GUI.ServerTimerSemaphore, 0);
2914 return;
2915 }
2916 ReleaseSemaphore (GUI.ServerTimerSemaphore, 1, NULL);
2917
2918 if (Settings.NetPlay)
2919 return;
2920 }
2921 else
2922 #endif
2923 {
2924 if (Settings.SkipFrames != AUTO_FRAMERATE || Settings.TurboMode ||
2925 (Settings.Paused /*&& !Settings.FrameAdvance*/) || Settings.StopEmulation || Settings.ForcedPause)
2926 {
2927 WaitForSingleObject (GUI.FrameTimerSemaphore, 0);
2928 PCStart = PCEnd;
2929 PCStartTicks = PCEndTicks;
2930 return;
2931 }
2932 // ReleaseSemaphore (GUI.ServerTimerSemaphore, 1, NULL);
2933 ReleaseSemaphore (GUI.FrameTimerSemaphore, 1, NULL);
2934
2935 // if (Settings.NetPlay)
2936 // return;
2937 // }
2938 // else
2939 //#endif
2940 // if (Settings.SkipFrames != AUTO_FRAMERATE || Settings.TurboMode ||
2941 // Settings.Paused || Settings.StopEmulation || Settings.ForcedPause)
2942 // {
2943 // WaitForSingleObject (GUI.FrameTimerSemaphore, 0);
2944 // return;
2945 // }
2946 // ReleaseSemaphore (GUI.FrameTimerSemaphore, 1, NULL);
2947 PCStart += PCFrameTime;
2948 PCStartTicks += (DWORD)(PCFrameTime * 1000000 / PCBase);
2949 }
2950 }
2951 }
2952
EnsureInputDisplayUpdated()2953 static void EnsureInputDisplayUpdated()
2954 {
2955 if(GUI.FrameAdvanceJustPressed==1 && Settings.Paused && Settings.DisplayPressedKeys==2 && GUI.ControllerOption != SNES_JOYPAD && GUI.ControllerOption != SNES_MULTIPLAYER5 && GUI.ControllerOption != SNES_MULTIPLAYER8)
2956 WinRefreshDisplay();
2957 }
2958
2959 // for "frame advance skips non-input frames" feature
S9xOnSNESPadRead()2960 void S9xOnSNESPadRead()
2961 {
2962 if(!GUI.FASkipsNonInput)
2963 return;
2964
2965 if(prevPadReadFrame != IPPU.TotalEmulatedFrames) // we want <= 1 calls per frame
2966 {
2967 prevPadReadFrame = IPPU.TotalEmulatedFrames;
2968
2969 if(Settings.FrameAdvance && Settings.Paused && !skipNextFrameStop)
2970 {
2971 Settings.FrameAdvance = false;
2972
2973 EnsureInputDisplayUpdated();
2974
2975 // wait until either unpause or next frame advance
2976 // note: using GUI.hWnd instead of NULL for PeekMessage/GetMessage breaks some non-modal dialogs
2977 MSG msg;
2978 while (Settings.StopEmulation || (Settings.Paused && !Settings.FrameAdvance) ||
2979 Settings.ForcedPause ||
2980 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
2981 {
2982 if (!GetMessage (&msg, NULL, 0, 0))
2983 {
2984 PostMessage(GUI.hWnd, WM_QUIT, 0,0);
2985 return;
2986 }
2987
2988 if (!TranslateAccelerator (GUI.hWnd, GUI.Accelerators, &msg))
2989 {
2990 TranslateMessage (&msg);
2991 DispatchMessage (&msg);
2992 }
2993 }
2994
2995 }
2996 else
2997 {
2998 skipNextFrameStop = false;
2999 }
3000 }
3001 }
3002
3003
3004 enum
3005 {
3006 k_HD = 0x80000000,
3007
3008 k_JP = 0x01000000,
3009 k_MO = 0x02000000,
3010 k_SS = 0x04000000,
3011 k_LG = 0x08000000,
3012
3013 k_BT = 0x00100000,
3014 k_PT = 0x00200000,
3015 k_PS = 0x00400000,
3016
3017 k_C1 = 0x00000100,
3018 k_C2 = 0x00000200,
3019 k_C3 = 0x00000400,
3020 k_C4 = 0x00000800,
3021 k_C5 = 0x00001000,
3022 k_C6 = 0x00002000,
3023 k_C7 = 0x00004000,
3024 k_C8 = 0x00008000
3025 };
3026
3027 enum
3028 {
3029 kWinCMapPad1PX = k_HD | k_BT | k_JP | k_C1,
3030 kWinCMapPad1PA,
3031 kWinCMapPad1PB,
3032 kWinCMapPad1PY,
3033 kWinCMapPad1PL,
3034 kWinCMapPad1PR,
3035 kWinCMapPad1PSelect,
3036 kWinCMapPad1PStart,
3037 kWinCMapPad1PUp,
3038 kWinCMapPad1PDown,
3039 kWinCMapPad1PLeft,
3040 kWinCMapPad1PRight,
3041
3042 kWinCMapPad2PX = k_HD | k_BT | k_JP | k_C2,
3043 kWinCMapPad2PA,
3044 kWinCMapPad2PB,
3045 kWinCMapPad2PY,
3046 kWinCMapPad2PL,
3047 kWinCMapPad2PR,
3048 kWinCMapPad2PSelect,
3049 kWinCMapPad2PStart,
3050 kWinCMapPad2PUp,
3051 kWinCMapPad2PDown,
3052 kWinCMapPad2PLeft,
3053 kWinCMapPad2PRight,
3054
3055 kWinCMapPad3PX = k_HD | k_BT | k_JP | k_C3,
3056 kWinCMapPad3PA,
3057 kWinCMapPad3PB,
3058 kWinCMapPad3PY,
3059 kWinCMapPad3PL,
3060 kWinCMapPad3PR,
3061 kWinCMapPad3PSelect,
3062 kWinCMapPad3PStart,
3063 kWinCMapPad3PUp,
3064 kWinCMapPad3PDown,
3065 kWinCMapPad3PLeft,
3066 kWinCMapPad3PRight,
3067
3068 kWinCMapPad4PX = k_HD | k_BT | k_JP | k_C4,
3069 kWinCMapPad4PA,
3070 kWinCMapPad4PB,
3071 kWinCMapPad4PY,
3072 kWinCMapPad4PL,
3073 kWinCMapPad4PR,
3074 kWinCMapPad4PSelect,
3075 kWinCMapPad4PStart,
3076 kWinCMapPad4PUp,
3077 kWinCMapPad4PDown,
3078 kWinCMapPad4PLeft,
3079 kWinCMapPad4PRight,
3080
3081 kWinCMapPad5PX = k_HD | k_BT | k_JP | k_C5,
3082 kWinCMapPad5PA,
3083 kWinCMapPad5PB,
3084 kWinCMapPad5PY,
3085 kWinCMapPad5PL,
3086 kWinCMapPad5PR,
3087 kWinCMapPad5PSelect,
3088 kWinCMapPad5PStart,
3089 kWinCMapPad5PUp,
3090 kWinCMapPad5PDown,
3091 kWinCMapPad5PLeft,
3092 kWinCMapPad5PRight,
3093
3094 kWinCMapPad6PX = k_HD | k_BT | k_JP | k_C6,
3095 kWinCMapPad6PA,
3096 kWinCMapPad6PB,
3097 kWinCMapPad6PY,
3098 kWinCMapPad6PL,
3099 kWinCMapPad6PR,
3100 kWinCMapPad6PSelect,
3101 kWinCMapPad6PStart,
3102 kWinCMapPad6PUp,
3103 kWinCMapPad6PDown,
3104 kWinCMapPad6PLeft,
3105 kWinCMapPad6PRight,
3106
3107 kWinCMapPad7PX = k_HD | k_BT | k_JP | k_C7,
3108 kWinCMapPad7PA,
3109 kWinCMapPad7PB,
3110 kWinCMapPad7PY,
3111 kWinCMapPad7PL,
3112 kWinCMapPad7PR,
3113 kWinCMapPad7PSelect,
3114 kWinCMapPad7PStart,
3115 kWinCMapPad7PUp,
3116 kWinCMapPad7PDown,
3117 kWinCMapPad7PLeft,
3118 kWinCMapPad7PRight,
3119
3120 kWinCMapPad8PX = k_HD | k_BT | k_JP | k_C8,
3121 kWinCMapPad8PA,
3122 kWinCMapPad8PB,
3123 kWinCMapPad8PY,
3124 kWinCMapPad8PL,
3125 kWinCMapPad8PR,
3126 kWinCMapPad8PSelect,
3127 kWinCMapPad8PStart,
3128 kWinCMapPad8PUp,
3129 kWinCMapPad8PDown,
3130 kWinCMapPad8PLeft,
3131 kWinCMapPad8PRight,
3132
3133 kWinCMapMouse1PL = k_HD | k_BT | k_MO | k_C1,
3134 kWinCMapMouse1PR,
3135 kWinCMapMouse2PL = k_HD | k_BT | k_MO | k_C2,
3136 kWinCMapMouse2PR,
3137
3138 kWinCMapScopeOffscreen = k_HD | k_BT | k_SS | k_C1,
3139 kWinCMapScopeFire,
3140 kWinCMapScopeCursor,
3141 kWinCMapScopeTurbo,
3142 kWinCMapScopePause,
3143
3144 kWinCMapLGun1Offscreen = k_HD | k_BT | k_LG | k_C1,
3145 kWinCMapLGun1Trigger,
3146 kWinCMapLGun1Start,
3147 kWinCMapLGun2Offscreen = k_HD | k_BT | k_LG | k_C2,
3148 kWinCMapLGun2Trigger,
3149 kWinCMapLGun2Start,
3150
3151 kWinCMapMouse1Pointer = k_HD | k_PT | k_MO | k_C1,
3152 kWinCMapMouse2Pointer = k_HD | k_PT | k_MO | k_C2,
3153 kWinCMapSuperscopePointer = k_HD | k_PT | k_SS | k_C1,
3154 kWinCMapJustifier1Pointer = k_HD | k_PT | k_LG | k_C1,
3155
3156 kWinCMapPseudoPtrBase = k_HD | k_PS | k_LG | k_C2 // for Justifier 2P
3157 };
3158
3159
3160
3161 #define ASSIGN_BUTTONf(n, s) S9xMapButton (n, cmd = S9xGetCommandT(s), false)
3162 #define ASSIGN_BUTTONt(n, s) S9xMapButton (n, cmd = S9xGetCommandT(s), true)
3163 #define ASSIGN_POINTRf(n, s) S9xMapPointer(n, cmd = S9xGetCommandT(s), false)
3164 #define ASSIGN_POINTRt(n, s) S9xMapPointer(n, cmd = S9xGetCommandT(s), true)
3165
3166 #define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7)))
3167
S9xSetupDefaultKeymap(void)3168 void S9xSetupDefaultKeymap(void)
3169 {
3170 s9xcommand_t cmd;
3171
3172 ASSIGN_BUTTONf(kWinCMapPad1PX, "Joypad1 X");
3173 ASSIGN_BUTTONf(kWinCMapPad1PA, "Joypad1 A");
3174 ASSIGN_BUTTONf(kWinCMapPad1PB, "Joypad1 B");
3175 ASSIGN_BUTTONf(kWinCMapPad1PY, "Joypad1 Y");
3176 ASSIGN_BUTTONf(kWinCMapPad1PL, "Joypad1 L");
3177 ASSIGN_BUTTONf(kWinCMapPad1PR, "Joypad1 R");
3178 ASSIGN_BUTTONf(kWinCMapPad1PSelect, "Joypad1 Select");
3179 ASSIGN_BUTTONf(kWinCMapPad1PStart, "Joypad1 Start");
3180 ASSIGN_BUTTONf(kWinCMapPad1PUp, "Joypad1 Up");
3181 ASSIGN_BUTTONf(kWinCMapPad1PDown, "Joypad1 Down");
3182 ASSIGN_BUTTONf(kWinCMapPad1PLeft, "Joypad1 Left");
3183 ASSIGN_BUTTONf(kWinCMapPad1PRight, "Joypad1 Right");
3184
3185 ASSIGN_BUTTONf(kWinCMapPad2PX, "Joypad2 X");
3186 ASSIGN_BUTTONf(kWinCMapPad2PA, "Joypad2 A");
3187 ASSIGN_BUTTONf(kWinCMapPad2PB, "Joypad2 B");
3188 ASSIGN_BUTTONf(kWinCMapPad2PY, "Joypad2 Y");
3189 ASSIGN_BUTTONf(kWinCMapPad2PL, "Joypad2 L");
3190 ASSIGN_BUTTONf(kWinCMapPad2PR, "Joypad2 R");
3191 ASSIGN_BUTTONf(kWinCMapPad2PSelect, "Joypad2 Select");
3192 ASSIGN_BUTTONf(kWinCMapPad2PStart, "Joypad2 Start");
3193 ASSIGN_BUTTONf(kWinCMapPad2PUp, "Joypad2 Up");
3194 ASSIGN_BUTTONf(kWinCMapPad2PDown, "Joypad2 Down");
3195 ASSIGN_BUTTONf(kWinCMapPad2PLeft, "Joypad2 Left");
3196 ASSIGN_BUTTONf(kWinCMapPad2PRight, "Joypad2 Right");
3197
3198 ASSIGN_BUTTONf(kWinCMapPad3PX, "Joypad3 X");
3199 ASSIGN_BUTTONf(kWinCMapPad3PA, "Joypad3 A");
3200 ASSIGN_BUTTONf(kWinCMapPad3PB, "Joypad3 B");
3201 ASSIGN_BUTTONf(kWinCMapPad3PY, "Joypad3 Y");
3202 ASSIGN_BUTTONf(kWinCMapPad3PL, "Joypad3 L");
3203 ASSIGN_BUTTONf(kWinCMapPad3PR, "Joypad3 R");
3204 ASSIGN_BUTTONf(kWinCMapPad3PSelect, "Joypad3 Select");
3205 ASSIGN_BUTTONf(kWinCMapPad3PStart, "Joypad3 Start");
3206 ASSIGN_BUTTONf(kWinCMapPad3PUp, "Joypad3 Up");
3207 ASSIGN_BUTTONf(kWinCMapPad3PDown, "Joypad3 Down");
3208 ASSIGN_BUTTONf(kWinCMapPad3PLeft, "Joypad3 Left");
3209 ASSIGN_BUTTONf(kWinCMapPad3PRight, "Joypad3 Right");
3210
3211 ASSIGN_BUTTONf(kWinCMapPad4PX, "Joypad4 X");
3212 ASSIGN_BUTTONf(kWinCMapPad4PA, "Joypad4 A");
3213 ASSIGN_BUTTONf(kWinCMapPad4PB, "Joypad4 B");
3214 ASSIGN_BUTTONf(kWinCMapPad4PY, "Joypad4 Y");
3215 ASSIGN_BUTTONf(kWinCMapPad4PL, "Joypad4 L");
3216 ASSIGN_BUTTONf(kWinCMapPad4PR, "Joypad4 R");
3217 ASSIGN_BUTTONf(kWinCMapPad4PSelect, "Joypad4 Select");
3218 ASSIGN_BUTTONf(kWinCMapPad4PStart, "Joypad4 Start");
3219 ASSIGN_BUTTONf(kWinCMapPad4PUp, "Joypad4 Up");
3220 ASSIGN_BUTTONf(kWinCMapPad4PDown, "Joypad4 Down");
3221 ASSIGN_BUTTONf(kWinCMapPad4PLeft, "Joypad4 Left");
3222 ASSIGN_BUTTONf(kWinCMapPad4PRight, "Joypad4 Right");
3223
3224 ASSIGN_BUTTONf(kWinCMapPad5PX, "Joypad5 X");
3225 ASSIGN_BUTTONf(kWinCMapPad5PA, "Joypad5 A");
3226 ASSIGN_BUTTONf(kWinCMapPad5PB, "Joypad5 B");
3227 ASSIGN_BUTTONf(kWinCMapPad5PY, "Joypad5 Y");
3228 ASSIGN_BUTTONf(kWinCMapPad5PL, "Joypad5 L");
3229 ASSIGN_BUTTONf(kWinCMapPad5PR, "Joypad5 R");
3230 ASSIGN_BUTTONf(kWinCMapPad5PSelect, "Joypad5 Select");
3231 ASSIGN_BUTTONf(kWinCMapPad5PStart, "Joypad5 Start");
3232 ASSIGN_BUTTONf(kWinCMapPad5PUp, "Joypad5 Up");
3233 ASSIGN_BUTTONf(kWinCMapPad5PDown, "Joypad5 Down");
3234 ASSIGN_BUTTONf(kWinCMapPad5PLeft, "Joypad5 Left");
3235 ASSIGN_BUTTONf(kWinCMapPad5PRight, "Joypad5 Right");
3236
3237 ASSIGN_BUTTONf(kWinCMapPad6PX, "Joypad6 X");
3238 ASSIGN_BUTTONf(kWinCMapPad6PA, "Joypad6 A");
3239 ASSIGN_BUTTONf(kWinCMapPad6PB, "Joypad6 B");
3240 ASSIGN_BUTTONf(kWinCMapPad6PY, "Joypad6 Y");
3241 ASSIGN_BUTTONf(kWinCMapPad6PL, "Joypad6 L");
3242 ASSIGN_BUTTONf(kWinCMapPad6PR, "Joypad6 R");
3243 ASSIGN_BUTTONf(kWinCMapPad6PSelect, "Joypad6 Select");
3244 ASSIGN_BUTTONf(kWinCMapPad6PStart, "Joypad6 Start");
3245 ASSIGN_BUTTONf(kWinCMapPad6PUp, "Joypad6 Up");
3246 ASSIGN_BUTTONf(kWinCMapPad6PDown, "Joypad6 Down");
3247 ASSIGN_BUTTONf(kWinCMapPad6PLeft, "Joypad6 Left");
3248 ASSIGN_BUTTONf(kWinCMapPad6PRight, "Joypad6 Right");
3249
3250 ASSIGN_BUTTONf(kWinCMapPad7PX, "Joypad7 X");
3251 ASSIGN_BUTTONf(kWinCMapPad7PA, "Joypad7 A");
3252 ASSIGN_BUTTONf(kWinCMapPad7PB, "Joypad7 B");
3253 ASSIGN_BUTTONf(kWinCMapPad7PY, "Joypad7 Y");
3254 ASSIGN_BUTTONf(kWinCMapPad7PL, "Joypad7 L");
3255 ASSIGN_BUTTONf(kWinCMapPad7PR, "Joypad7 R");
3256 ASSIGN_BUTTONf(kWinCMapPad7PSelect, "Joypad7 Select");
3257 ASSIGN_BUTTONf(kWinCMapPad7PStart, "Joypad7 Start");
3258 ASSIGN_BUTTONf(kWinCMapPad7PUp, "Joypad7 Up");
3259 ASSIGN_BUTTONf(kWinCMapPad7PDown, "Joypad7 Down");
3260 ASSIGN_BUTTONf(kWinCMapPad7PLeft, "Joypad7 Left");
3261 ASSIGN_BUTTONf(kWinCMapPad7PRight, "Joypad7 Right");
3262
3263 ASSIGN_BUTTONf(kWinCMapPad8PX, "Joypad8 X");
3264 ASSIGN_BUTTONf(kWinCMapPad8PA, "Joypad8 A");
3265 ASSIGN_BUTTONf(kWinCMapPad8PB, "Joypad8 B");
3266 ASSIGN_BUTTONf(kWinCMapPad8PY, "Joypad8 Y");
3267 ASSIGN_BUTTONf(kWinCMapPad8PL, "Joypad8 L");
3268 ASSIGN_BUTTONf(kWinCMapPad8PR, "Joypad8 R");
3269 ASSIGN_BUTTONf(kWinCMapPad8PSelect, "Joypad8 Select");
3270 ASSIGN_BUTTONf(kWinCMapPad8PStart, "Joypad8 Start");
3271 ASSIGN_BUTTONf(kWinCMapPad8PUp, "Joypad8 Up");
3272 ASSIGN_BUTTONf(kWinCMapPad8PDown, "Joypad8 Down");
3273 ASSIGN_BUTTONf(kWinCMapPad8PLeft, "Joypad8 Left");
3274 ASSIGN_BUTTONf(kWinCMapPad8PRight, "Joypad8 Right");
3275
3276 ASSIGN_BUTTONt(kWinCMapMouse1PL, "Mouse1 L");
3277 ASSIGN_BUTTONt(kWinCMapMouse1PR, "Mouse1 R");
3278 ASSIGN_BUTTONt(kWinCMapMouse2PL, "Mouse2 L");
3279 ASSIGN_BUTTONt(kWinCMapMouse2PR, "Mouse2 R");
3280
3281 ASSIGN_BUTTONt(kWinCMapScopeOffscreen, "Superscope AimOffscreen");
3282 ASSIGN_BUTTONt(kWinCMapScopeFire, "Superscope Fire");
3283 ASSIGN_BUTTONt(kWinCMapScopeCursor, "Superscope Cursor");
3284 ASSIGN_BUTTONt(kWinCMapScopeTurbo, "Superscope ToggleTurbo");
3285 ASSIGN_BUTTONt(kWinCMapScopePause, "Superscope Pause");
3286
3287 ASSIGN_BUTTONt(kWinCMapLGun1Offscreen, "Justifier1 AimOffscreen");
3288 ASSIGN_BUTTONt(kWinCMapLGun1Trigger, "Justifier1 Trigger");
3289 ASSIGN_BUTTONt(kWinCMapLGun1Start, "Justifier1 Start");
3290 ASSIGN_BUTTONt(kWinCMapLGun2Offscreen, "Justifier2 AimOffscreen");
3291 ASSIGN_BUTTONt(kWinCMapLGun2Trigger, "Justifier2 Trigger");
3292 ASSIGN_BUTTONt(kWinCMapLGun2Start, "Justifier2 Start");
3293
3294 ASSIGN_POINTRt(kWinCMapMouse1Pointer, "Pointer Mouse1");
3295 ASSIGN_POINTRt(kWinCMapMouse2Pointer, "Pointer Mouse2");
3296 ASSIGN_POINTRt(kWinCMapSuperscopePointer, "Pointer Superscope");
3297 ASSIGN_POINTRt(kWinCMapJustifier1Pointer, "Pointer Justifier1");
3298
3299 ASSIGN_POINTRf(PseudoPointerBase, "Pointer Justifier2");
3300 ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 0, "ButtonToPointer 1u Med");
3301 ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 1, "ButtonToPointer 1d Med");
3302 ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 2, "ButtonToPointer 1l Med");
3303 ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 3, "ButtonToPointer 1r Med");
3304 }
3305
ControlPadFlagsToS9xReportButtons(int n,uint32 p)3306 void ControlPadFlagsToS9xReportButtons(int n, uint32 p)
3307 {
3308 uint32 base = k_HD | k_BT | k_JP | (0x100 << n);
3309
3310 S9xReportButton(base + 0, (p & 0x0040) != 0);
3311 S9xReportButton(base + 1, (p & 0x0080) != 0);
3312 S9xReportButton(base + 2, (p & 0x8000) != 0);
3313 S9xReportButton(base + 3, (p & 0x4000) != 0);
3314 S9xReportButton(base + 4, (p & 0x0020) != 0);
3315 S9xReportButton(base + 5, (p & 0x0010) != 0);
3316 S9xReportButton(base + 6, (p & 0x2000) != 0);
3317 S9xReportButton(base + 7, (p & 0x1000) != 0);
3318 S9xReportButton(base + 8, (p & 0x0800) != 0);
3319 S9xReportButton(base + 9, (p & 0x0400) != 0);
3320 S9xReportButton(base + 10, (p & 0x0200) != 0);
3321 S9xReportButton(base + 11, (p & 0x0100) != 0);
3322 }
3323
ControlPadFlagsToS9xPseudoPointer(uint32 p)3324 void ControlPadFlagsToS9xPseudoPointer(uint32 p)
3325 {
3326 // prevent screwiness caused by trying to move the pointer left+right or up+down
3327 if((p & 0x0c00) == 0x0c00) p &= ~0x0c00;
3328 if((p & 0x0300) == 0x0300) p &= ~0x0300;
3329
3330 // checks added to prevent a lack of right/down movement from breaking left/up movement
3331 if(!(p & 0x0400))
3332 S9xReportButton(kWinCMapPseudoPtrBase + 0, (p & 0x0800) != 0);
3333 if(!(p & 0x0800))
3334 S9xReportButton(kWinCMapPseudoPtrBase + 1, (p & 0x0400) != 0);
3335 if(!(p & 0x0100))
3336 S9xReportButton(kWinCMapPseudoPtrBase + 2, (p & 0x0200) != 0);
3337 if(!(p & 0x0200))
3338 S9xReportButton(kWinCMapPseudoPtrBase + 3, (p & 0x0100) != 0);
3339 }
3340
ProcessInput(void)3341 static void ProcessInput(void)
3342 {
3343 extern void S9xWinScanJoypads ();
3344 #ifdef NETPLAY_SUPPORT
3345 if (!Settings.NetPlay)
3346 #endif
3347 S9xWinScanJoypads ();
3348
3349 extern uint32 joypads [8];
3350 for(int i = 0 ; i < 8 ; i++)
3351 ControlPadFlagsToS9xReportButtons(i, joypads[i]);
3352
3353 if (GUI.ControllerOption==SNES_JUSTIFIER_2)
3354 ControlPadFlagsToS9xPseudoPointer(joypads[1]);
3355 }
3356
3357 //static void WinDisplayString (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap);
3358
3359
3360
3361
3362 /*****************************************************************************/
3363 /* WinMain */
3364 /*****************************************************************************/
3365 void DeinitS9x(void);
3366
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)3367 int WINAPI WinMain(
3368 HINSTANCE hInstance,
3369 HINSTANCE hPrevInstance,
3370 LPSTR lpCmdLine,
3371 int nCmdShow)
3372 {
3373 Settings.StopEmulation = TRUE;
3374
3375 SetCurrentDirectory(S9xGetDirectoryT(DEFAULT_DIR));
3376
3377 // Redirect stderr and stdout to file. It wouldn't go to any commandline anyway.
3378 FILE* fout = freopen("stdout.txt", "w", stdout);
3379 if(fout) setvbuf(fout, NULL, _IONBF, 0);
3380 FILE* ferr = freopen("stderr.txt", "w", stderr);
3381 if(ferr) setvbuf(ferr, NULL, _IONBF, 0);
3382
3383 DWORD wSoundTimerRes;
3384
3385 LoadExts();
3386
3387 WinRegisterConfigItems ();
3388
3389 ConfigFile::SetAlphaSort(false);
3390 ConfigFile::SetTimeSort(false);
3391
3392 ChangeInputDevice();
3393
3394 const TCHAR *rom_filename = WinParseCommandLineAndLoadConfigFile (GetCommandLine());
3395 WinSaveConfigFile ();
3396 WinLockConfigFile ();
3397
3398 ControllerOptionsFromControllers();
3399
3400 WinInit (hInstance);
3401 if(GUI.HideMenu)
3402 {
3403 SetMenu (GUI.hWnd, NULL);
3404 }
3405
3406 InitRenderFilters();
3407
3408 GUI.ControlForced = 0xff;
3409 GUI.rewinding = false;
3410
3411 S9xSetRecentGames ();
3412
3413 RestoreMainWinPos();
3414
3415 void InitSnes9X (void);
3416 InitSnes9X ();
3417
3418 if(GUI.FullScreen) {
3419 GUI.FullScreen = false;
3420 ToggleFullScreen();
3421 }
3422
3423 TIMECAPS tc;
3424 if (timeGetDevCaps(&tc, sizeof(TIMECAPS))== TIMERR_NOERROR)
3425 {
3426 #ifdef __MINGW32__
3427 wSoundTimerRes = min<int>(max<int>(tc.wPeriodMin, 1), tc.wPeriodMax);
3428 #else
3429 wSoundTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
3430 #endif
3431 timeBeginPeriod (wSoundTimerRes);
3432 }
3433 else
3434 {
3435 wSoundTimerRes = 5;
3436 timeBeginPeriod (wSoundTimerRes);
3437 }
3438
3439 QueryPerformanceFrequency((LARGE_INTEGER*)&PCBase);
3440 QueryPerformanceCounter((LARGE_INTEGER*)&PCStart);
3441 PCEnd = PCStart;
3442 PCEndTicks = timeGetTime()*1000;
3443 PCStartTicks = timeGetTime()*1000;
3444 PCFrameTime = PCFrameTimeNTSC = (__int64)((float)PCBase / 59.948743718592964824120603015098f);
3445 PCFrameTimePAL = PCBase / 50;
3446
3447
3448 Settings.StopEmulation = TRUE;
3449 GUI.hFrameTimer = timeSetEvent (20, 0, (LPTIMECALLBACK)FrameTimer, 0, TIME_PERIODIC);
3450
3451 if(GUI.JoystickHotkeys || GUI.BackgroundInput)
3452 GUI.hHotkeyTimer = timeSetEvent (32, 0, (LPTIMECALLBACK)HotkeyTimer, 0, TIME_PERIODIC);
3453 else
3454 GUI.hHotkeyTimer = 0;
3455
3456 GUI.FrameTimerSemaphore = CreateSemaphore (NULL, 0, 10, NULL);
3457 GUI.ServerTimerSemaphore = CreateSemaphore (NULL, 0, 10, NULL);
3458
3459 if (GUI.hFrameTimer == 0)
3460 {
3461 MessageBox( GUI.hWnd, Languages[ GUI.Language].errFrameTimer, TEXT("Snes9X - Frame Timer"), MB_OK | MB_ICONINFORMATION);
3462 }
3463
3464 if(rom_filename)
3465 LoadROM(rom_filename);
3466
3467 S9xUnmapAllControls();
3468 S9xSetupDefaultKeymap();
3469
3470 DWORD lastTime = timeGetTime();
3471
3472 MSG msg;
3473
3474 while (TRUE)
3475 {
3476 EnsureInputDisplayUpdated();
3477
3478 // note: using GUI.hWnd instead of NULL for PeekMessage/GetMessage breaks some non-modal dialogs
3479 while (Settings.StopEmulation || (Settings.Paused && !Settings.FrameAdvance) ||
3480 Settings.ForcedPause ||
3481 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
3482 {
3483 if (!GetMessage (&msg, NULL, 0, 0))
3484 goto loop_exit; // got WM_QUIT
3485
3486 if (!TranslateAccelerator (GUI.hWnd, GUI.Accelerators, &msg))
3487 {
3488 TranslateMessage (&msg);
3489 DispatchMessage (&msg);
3490 }
3491
3492 S9xSetSoundMute(GUI.Mute || Settings.ForcedPause || (Settings.Paused && (!Settings.FrameAdvance || GUI.FAMute)));
3493 }
3494
3495 #ifdef NETPLAY_SUPPORT
3496 if (!Settings.NetPlay || !NetPlay.PendingWait4Sync ||
3497 WaitForSingleObject (GUI.ClientSemaphore, 100) != WAIT_TIMEOUT)
3498 {
3499 if (NetPlay.PendingWait4Sync)
3500 {
3501 NetPlay.PendingWait4Sync = FALSE;
3502 NetPlay.FrameCount++;
3503 S9xNPStepJoypadHistory ();
3504 }
3505 #endif
3506 if(watches[0].on)
3507 {
3508 // copy the memory used by each active watch
3509 for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++)
3510 {
3511 if(watches[i].on)
3512 {
3513 int address = watches[i].address - 0x7E0000;
3514 const uint8* source;
3515 if(address < 0x20000)
3516 source = Memory.RAM + address ;
3517 else if(address < 0x30000)
3518 source = Memory.SRAM + address - 0x20000;
3519 else
3520 source = Memory.FillRAM + address - 0x30000;
3521
3522 CopyMemory(Cheat.CWatchRAM + address, source, watches[i].size);
3523 }
3524 }
3525 }
3526 if(cheatSearchHWND)
3527 {
3528 if(timeGetTime() - lastTime >= 100)
3529 {
3530 SendMessage(cheatSearchHWND, WM_COMMAND, (WPARAM)(IDC_REFRESHLIST),(LPARAM)(NULL));
3531 lastTime = timeGetTime();
3532 }
3533 }
3534
3535 // the following is a hack to allow frametimes greater than 100ms,
3536 // without affecting the responsiveness of the GUI
3537 BOOL run_loop=false;
3538 do_frame_adjust=false;
3539 if (Settings.TurboMode || Settings.FrameAdvance || Settings.SkipFrames != AUTO_FRAMERATE
3540 #ifdef NETPLAY_SUPPORT
3541 || Settings.NetPlay
3542 #endif
3543 )
3544 {
3545 run_loop=true;
3546 }
3547 else
3548 {
3549 LONG prev;
3550 BOOL success;
3551 if ((success = ReleaseSemaphore (GUI.FrameTimerSemaphore, 1, &prev)) &&
3552 prev == 0)
3553 {
3554 WaitForSingleObject (GUI.FrameTimerSemaphore, 0);
3555 if (WaitForSingleObject (GUI.FrameTimerSemaphore, 100) == WAIT_OBJECT_0)
3556 {
3557 run_loop=true;
3558 }
3559 }
3560 else
3561 {
3562 if (success)
3563 WaitForSingleObject (GUI.FrameTimerSemaphore, 0);
3564 WaitForSingleObject (GUI.FrameTimerSemaphore, 0);
3565
3566 run_loop=true;
3567 do_frame_adjust=true;
3568 }
3569 }
3570
3571
3572 if(Settings.FrameAdvance)
3573 {
3574 if(GFX.InfoStringTimeout > 4)
3575 GFX.InfoStringTimeout = 4;
3576
3577 if(!GUI.FASkipsNonInput)
3578 Settings.FrameAdvance = false;
3579 }
3580 if(GUI.FrameAdvanceJustPressed)
3581 GUI.FrameAdvanceJustPressed--;
3582
3583 if(run_loop)
3584 {
3585 ProcessInput();
3586
3587 while(!S9xSyncSound()) {
3588 ResetEvent(GUI.SoundSyncEvent);
3589 if(WaitForSingleObject(GUI.SoundSyncEvent,1000) != WAIT_OBJECT_0)
3590 S9xClearSamples();
3591 }
3592
3593 if(GUI.rewindBufferSize
3594 #ifdef NETPLAY_SUPPORT
3595 &&!Settings.NetPlay
3596 #endif
3597 ) {
3598 if(GUI.rewinding) {
3599 GUI.rewinding = stateMan.pop();
3600 } else {
3601 if(IPPU.TotalEmulatedFrames % GUI.rewindGranularity == 0)
3602 stateMan.push();
3603 }
3604 }
3605
3606 S9xMainLoop();
3607 GUI.FrameCount++;
3608 }
3609
3610 #ifdef NETPLAY_SUPPORT
3611 }
3612 #endif
3613 if (CPU.Flags & DEBUG_MODE_FLAG)
3614 {
3615 Settings.Paused = TRUE;
3616 Settings.FrameAdvance = false;
3617 CPU.Flags &= ~DEBUG_MODE_FLAG;
3618 }
3619 if (GUI.CursorTimer)
3620 {
3621 if (--GUI.CursorTimer == 0)
3622 {
3623 if (GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_JUSTIFIER && GUI.ControllerOption != SNES_JUSTIFIER_2)
3624 SetCursor (NULL);
3625 }
3626 }
3627 }
3628
3629 loop_exit:
3630
3631 Settings.StopEmulation = TRUE;
3632
3633 // stop sound playback
3634 CloseSoundDevice();
3635
3636 if (GUI.hHotkeyTimer)
3637 timeKillEvent (GUI.hHotkeyTimer);
3638
3639 if( GUI.hFrameTimer)
3640 {
3641 timeKillEvent (GUI.hFrameTimer);
3642 timeEndPeriod (wSoundTimerRes);
3643 }
3644
3645 if (!Settings.StopEmulation)
3646 {
3647 Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR));
3648 S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
3649 }
3650 //if (!VOODOO_MODE && !GUI.FullScreen)
3651 // GetWindowRect (GUI.hWnd, &GUI.window_size);
3652
3653
3654 // this goes here, because the avi
3655 // recording might have messed with
3656 // the auto frame skip setting
3657 // (it needs to come before WinSave)
3658 DoAVIClose(0);
3659
3660 S9xMovieShutdown (); // must happen before saving config
3661
3662 WinUnlockConfigFile ();
3663 WinSaveConfigFile ();
3664 WinCleanupConfigData();
3665
3666 Memory.Deinit();
3667
3668 S9xGraphicsDeinit();
3669 S9xDeinitAPU();
3670 WinDeleteRecentGamesList ();
3671 DeinitS9x();
3672
3673 #ifdef CHECK_MEMORY_LEAKS
3674 _CrtDumpMemoryLeaks();
3675 #endif
3676 return msg.wParam;
3677 }
3678
FreezeUnfreeze(int slot,bool8 freeze)3679 void FreezeUnfreeze (int slot, bool8 freeze)
3680 {
3681 const char *filename;
3682 char ext [_MAX_EXT + 1];
3683
3684 #ifdef NETPLAY_SUPPORT
3685 if (!freeze && Settings.NetPlay && !Settings.NetPlayServer)
3686 {
3687 S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER,
3688 "Only the server is allowed to load freeze files.");
3689 return;
3690 }
3691 #endif
3692
3693 snprintf(ext, _MAX_EXT, ".%03d", slot);
3694 filename = S9xGetFilename(ext,SNAPSHOT_DIR);
3695
3696 S9xSetPause (PAUSE_FREEZE_FILE);
3697
3698 if (freeze)
3699 {
3700 // extern bool diagnostic_freezing;
3701 // if(GetAsyncKeyState('Q') && GetAsyncKeyState('W') && GetAsyncKeyState('E') && GetAsyncKeyState('R'))
3702 // {
3703 // diagnostic_freezing = true;
3704 // }
3705 S9xFreezeGame (filename);
3706 //
3707 // diagnostic_freezing = false;
3708 }
3709 else
3710 {
3711
3712 if (S9xUnfreezeGame (filename))
3713 {
3714 // S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, S9xBasename (filename));
3715 #ifdef NETPLAY_SUPPORT
3716 S9xNPServerQueueSendingFreezeFile (filename);
3717 #endif
3718 // UpdateBackBuffer();
3719 }
3720
3721 // fix next frame advance after loading non-skipping state from a skipping state
3722 skipNextFrameStop = true;
3723 }
3724
3725 S9xClearPause (PAUSE_FREEZE_FILE);
3726 }
3727
CheckDirectoryIsWritable(const char * filename)3728 void CheckDirectoryIsWritable (const char *filename)
3729 {
3730 FILE *fs = fopen (filename, "w+");
3731
3732 if (fs == NULL)
3733 MessageBox (GUI.hWnd, TEXT("The folder where Snes9X saves emulated save RAM files and\ngame save positions (freeze files) is currently set to a\nread-only folder.\n\nIf you do not change the game save folder, Snes9X will be\nunable to save your progress in this game. Change the folder\nfrom the Settings Dialog available from the Options menu.\n\nThe default save folder is called Saves, if no value is set.\n"),
3734 TEXT("Snes9X: Unable to save file warning"),
3735 MB_OK | MB_ICONINFORMATION);
3736 else
3737 {
3738 fclose (fs);
3739 remove (filename);
3740 }
3741 }
3742
CheckMenuStates()3743 static void CheckMenuStates ()
3744 {
3745 MENUITEMINFO mii;
3746 unsigned int i;
3747
3748 memset( &mii, 0, sizeof( mii));
3749 mii.cbSize = sizeof( mii);
3750 mii.fMask = MIIM_STATE;
3751
3752 mii.fState = (GUI.FullScreen||GUI.EmulatedFullscreen) ? MFS_CHECKED : MFS_UNCHECKED;
3753 SetMenuItemInfo (GUI.hMenu, ID_WINDOW_FULLSCREEN, FALSE, &mii);
3754
3755 mii.fState = GUI.Stretch ? MFS_CHECKED : MFS_UNCHECKED;
3756 SetMenuItemInfo (GUI.hMenu, ID_WINDOW_STRETCH, FALSE, &mii);
3757
3758 mii.fState = GUI.Stretch ? (GUI.AspectRatio ? MFS_CHECKED : MFS_UNCHECKED) : MFS_CHECKED|MFS_DISABLED;
3759 SetMenuItemInfo (GUI.hMenu, ID_WINDOW_ASPECTRATIO, FALSE, &mii);
3760
3761 mii.fState = GUI.BilinearFilter ? MFS_CHECKED : MFS_UNCHECKED;
3762 if(!GUI.Stretch)
3763 mii.fState |= MFS_DISABLED;
3764 SetMenuItemInfo (GUI.hMenu, ID_WINDOW_BILINEAR, FALSE, &mii);
3765
3766 mii.fState = Settings.DisplayFrameRate ? MFS_CHECKED : MFS_UNCHECKED;
3767 SetMenuItemInfo (GUI.hMenu, ID_VIDEO_SHOWFRAMERATE, FALSE, &mii);
3768
3769 mii.fState = (Settings.Paused && !Settings.StopEmulation) ? MFS_CHECKED : MFS_UNCHECKED;
3770 SetMenuItemInfo (GUI.hMenu, ID_FILE_PAUSE, FALSE, &mii);
3771
3772 mii.fState = (GUI.InactivePause) ? MFS_CHECKED : MFS_UNCHECKED;
3773 SetMenuItemInfo (GUI.hMenu, ID_EMULATION_PAUSEWHENINACTIVE, FALSE, &mii);
3774
3775 mii.fState = MFS_UNCHECKED;
3776 if (Settings.StopEmulation)
3777 mii.fState |= MFS_DISABLED;
3778 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE_SPC_DATA, FALSE, &mii);
3779 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE_SRAM_DATA, FALSE, &mii);
3780 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE1, FALSE, &mii);
3781 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE2, FALSE, &mii);
3782 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE3, FALSE, &mii);
3783 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE4, FALSE, &mii);
3784 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE5, FALSE, &mii);
3785 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE6, FALSE, &mii);
3786 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE7, FALSE, &mii);
3787 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE8, FALSE, &mii);
3788 SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE9, FALSE, &mii);
3789 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD1, FALSE, &mii);
3790 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD2, FALSE, &mii);
3791 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD3, FALSE, &mii);
3792 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD4, FALSE, &mii);
3793 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD5, FALSE, &mii);
3794 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD6, FALSE, &mii);
3795 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD7, FALSE, &mii);
3796 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD8, FALSE, &mii);
3797 SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD9, FALSE, &mii);
3798 SetMenuItemInfo (GUI.hMenu, ID_FILE_RESET, FALSE, &mii);
3799 SetMenuItemInfo (GUI.hMenu, ID_CHEAT_ENTER, FALSE, &mii);
3800 SetMenuItemInfo (GUI.hMenu, ID_CHEAT_SEARCH_MODAL, FALSE, &mii);
3801 SetMenuItemInfo (GUI.hMenu, IDM_ROM_INFO, FALSE, &mii);
3802
3803 if (GUI.FullScreen)
3804 mii.fState |= MFS_DISABLED;
3805 SetMenuItemInfo (GUI.hMenu, ID_CHEAT_SEARCH, FALSE, &mii);
3806
3807 #ifdef NETPLAY_SUPPORT
3808 if (Settings.NetPlay && !Settings.NetPlayServer)
3809 mii.fState = MFS_DISABLED;
3810 else
3811 mii.fState = Settings.NetPlayServer ? MFS_CHECKED : MFS_UNCHECKED;
3812 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SERVER, FALSE, &mii);
3813
3814 mii.fState = Settings.NetPlay && !Settings.NetPlayServer ? 0 : MFS_DISABLED;
3815 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_DISCONNECT, FALSE, &mii);
3816
3817 mii.fState = Settings.NetPlay || Settings.NetPlayServer ? MFS_DISABLED : 0;
3818 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_CONNECT, FALSE, &mii);
3819
3820 mii.fState = NPServer.SendROMImageOnConnect ? MFS_CHECKED : MFS_UNCHECKED;
3821 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SEND_ROM_ON_CONNECT, FALSE, &mii);
3822
3823 mii.fState = NPServer.SyncByReset ? MFS_CHECKED : MFS_UNCHECKED;
3824 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SYNC_BY_RESET, FALSE, &mii);
3825
3826 mii.fState = Settings.NetPlayServer ? 0 : MFS_DISABLED;
3827 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SYNC, FALSE, &mii);
3828 SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_ROM, FALSE, &mii);
3829 #endif
3830
3831 mii.fState = Settings.ApplyCheats ? MFS_CHECKED : MFS_UNCHECKED;
3832 if (Settings.StopEmulation)
3833 mii.fState |= MFS_DISABLED;
3834 SetMenuItemInfo( GUI.hMenu, ID_CHEAT_APPLY, FALSE, &mii);
3835
3836 mii.fState = MFS_UNCHECKED;
3837 if (GUI.AVIOut)
3838 mii.fState |= MFS_DISABLED;
3839 SetMenuItemInfo (GUI.hMenu, ID_SOUND_OPTIONS, FALSE, &mii);
3840
3841 SetMenuItemInfo (GUI.hMenu, ID_SOUND_NOSOUND, FALSE, &mii);
3842 for (i = 0; i < COUNT(SoundRates); i++)
3843 SetMenuItemInfo (GUI.hMenu, SoundRates[i].ident, FALSE, &mii);
3844
3845 if (Settings.SoundPlaybackRate == 0 || GUI.Mute)
3846 mii.fState |= MFS_DISABLED;
3847
3848 SetMenuItemInfo (GUI.hMenu, ID_SOUND_16BIT, FALSE, &mii);
3849 SetMenuItemInfo (GUI.hMenu, ID_SOUND_STEREO, FALSE, &mii);
3850 SetMenuItemInfo (GUI.hMenu, ID_SOUND_SYNC, FALSE, &mii);
3851 SetMenuItemInfo (GUI.hMenu, ID_SOUND_INTERPOLATED, FALSE, &mii);
3852
3853 SetMenuItemInfo (GUI.hMenu, ID_SOUND_16MS, FALSE, &mii);
3854 SetMenuItemInfo (GUI.hMenu, ID_SOUND_32MS, FALSE, &mii);
3855 SetMenuItemInfo (GUI.hMenu, ID_SOUND_48MS, FALSE, &mii);
3856 SetMenuItemInfo (GUI.hMenu, ID_SOUND_64MS, FALSE, &mii);
3857 SetMenuItemInfo (GUI.hMenu, ID_SOUND_80MS, FALSE, &mii);
3858 SetMenuItemInfo (GUI.hMenu, ID_SOUND_96MS, FALSE, &mii);
3859 SetMenuItemInfo (GUI.hMenu, ID_SOUND_112MS, FALSE, &mii);
3860 SetMenuItemInfo (GUI.hMenu, ID_SOUND_128MS, FALSE, &mii);
3861 SetMenuItemInfo (GUI.hMenu, ID_SOUND_144MS, FALSE, &mii);
3862 SetMenuItemInfo (GUI.hMenu, ID_SOUND_160MS, FALSE, &mii);
3863 SetMenuItemInfo (GUI.hMenu, ID_SOUND_176MS, FALSE, &mii);
3864 SetMenuItemInfo (GUI.hMenu, ID_SOUND_194MS, FALSE, &mii);
3865 SetMenuItemInfo (GUI.hMenu, ID_SOUND_210MS, FALSE, &mii);
3866
3867 if (!Settings.Stereo)
3868 mii.fState |= MFS_DISABLED;
3869
3870 SetMenuItemInfo (GUI.hMenu, ID_SOUND_REVERSE_STEREO, FALSE, &mii);
3871
3872 mii.fState = MFS_CHECKED;
3873 if (GUI.AVIOut)
3874 mii.fState |= MFS_DISABLED;
3875
3876 if (Settings.SoundPlaybackRate == 0 || GUI.Mute )
3877 SetMenuItemInfo (GUI.hMenu, ID_SOUND_NOSOUND, FALSE, &mii);
3878 else
3879 {
3880 for (i = 0; i < COUNT(SoundRates); i++)
3881 {
3882 if (SoundRates [i].rate == Settings.SoundPlaybackRate)
3883 {
3884 SetMenuItemInfo (GUI.hMenu, SoundRates[i].ident, FALSE, &mii);
3885 break;
3886 }
3887 }
3888 }
3889 if (Settings.SoundPlaybackRate == 0 || GUI.Mute)
3890 mii.fState |= MFS_DISABLED;
3891
3892 int id;
3893 switch (GUI.SoundBufferSize)
3894 {
3895 case 16: id = ID_SOUND_16MS; break;
3896 case 32: id = ID_SOUND_32MS; break;
3897 case 48: id = ID_SOUND_48MS; break;
3898 case 64: id = ID_SOUND_64MS; break;
3899 case 80: id = ID_SOUND_80MS; break;
3900 case 96: id = ID_SOUND_96MS; break;
3901 case 112: id = ID_SOUND_112MS; break;
3902 case 128: id = ID_SOUND_128MS; break;
3903 case 144: id = ID_SOUND_144MS; break;
3904 case 160: id = ID_SOUND_160MS; break;
3905 case 176: id = ID_SOUND_176MS; break;
3906 case 194: id = ID_SOUND_194MS; break;
3907 case 210: id = ID_SOUND_210MS; break;
3908 }
3909 SetMenuItemInfo (GUI.hMenu, id, FALSE, &mii);
3910
3911 if (Settings.SixteenBitSound)
3912 SetMenuItemInfo (GUI.hMenu, ID_SOUND_16BIT, FALSE, &mii);
3913 if (Settings.Stereo)
3914 SetMenuItemInfo (GUI.hMenu, ID_SOUND_STEREO, FALSE, &mii);
3915 if (Settings.SoundSync)
3916 SetMenuItemInfo (GUI.hMenu, ID_SOUND_SYNC, FALSE, &mii);
3917
3918 if (!Settings.Stereo)
3919 mii.fState |= MFS_DISABLED;
3920 if (Settings.ReverseStereo)
3921 SetMenuItemInfo (GUI.hMenu, ID_SOUND_REVERSE_STEREO, FALSE, &mii);
3922
3923 #ifdef DEBUGGER
3924 mii.fState = (CPU.Flags & TRACE_FLAG) ? MFS_CHECKED : MFS_UNCHECKED;
3925 SetMenuItemInfo (GUI.hMenu, ID_DEBUG_TRACE, FALSE, &mii);
3926 mii.fState = (spc_core->debug_is_enabled()) ? MFS_CHECKED : MFS_UNCHECKED;
3927 SetMenuItemInfo (GUI.hMenu, ID_DEBUG_APU_TRACE, FALSE, &mii);
3928 #endif
3929
3930 mii.fState = (!Settings.StopEmulation) ? MFS_ENABLED : MFS_DISABLED;
3931 SetMenuItemInfo (GUI.hMenu, ID_FILE_MOVIE_PLAY, FALSE, &mii);
3932 SetMenuItemInfo (GUI.hMenu, ID_FILE_MOVIE_RECORD, FALSE, &mii);
3933
3934 mii.fState = (S9xMovieActive () && !Settings.StopEmulation) ? MFS_ENABLED : MFS_DISABLED;
3935 SetMenuItemInfo (GUI.hMenu, ID_FILE_MOVIE_STOP, FALSE, &mii);
3936
3937 mii.fState = (GUI.SoundChannelEnable & (1 << 0)) ? MFS_CHECKED : MFS_UNCHECKED;
3938 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL1, FALSE, &mii);
3939 mii.fState = (GUI.SoundChannelEnable & (1 << 1)) ? MFS_CHECKED : MFS_UNCHECKED;
3940 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL2, FALSE, &mii);
3941 mii.fState = (GUI.SoundChannelEnable & (1 << 2)) ? MFS_CHECKED : MFS_UNCHECKED;
3942 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL3, FALSE, &mii);
3943 mii.fState = (GUI.SoundChannelEnable & (1 << 3)) ? MFS_CHECKED : MFS_UNCHECKED;
3944 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL4, FALSE, &mii);
3945 mii.fState = (GUI.SoundChannelEnable & (1 << 4)) ? MFS_CHECKED : MFS_UNCHECKED;
3946 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL5, FALSE, &mii);
3947 mii.fState = (GUI.SoundChannelEnable & (1 << 5)) ? MFS_CHECKED : MFS_UNCHECKED;
3948 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL6, FALSE, &mii);
3949 mii.fState = (GUI.SoundChannelEnable & (1 << 6)) ? MFS_CHECKED : MFS_UNCHECKED;
3950 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL7, FALSE, &mii);
3951 mii.fState = (GUI.SoundChannelEnable & (1 << 7)) ? MFS_CHECKED : MFS_UNCHECKED;
3952 SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL8, FALSE, &mii);
3953
3954 mii.fState = GUI.BackgroundInput ? MFS_CHECKED : MFS_UNCHECKED;
3955 SetMenuItemInfo (GUI.hMenu, ID_EMULATION_BACKGROUNDINPUT, FALSE, &mii);
3956
3957 UINT validFlag;
3958 ControllerOptionsFromControllers();
3959
3960 validFlag = (((1<<SNES_JOYPAD) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3961 mii.fState = validFlag | (GUI.ControllerOption == SNES_JOYPAD ? MFS_CHECKED : MFS_UNCHECKED);
3962 SetMenuItemInfo (GUI.hMenu, IDM_SNES_JOYPAD, FALSE, &mii);
3963
3964 validFlag = (((1<<SNES_MULTIPLAYER5) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3965 mii.fState = validFlag | (GUI.ControllerOption == SNES_MULTIPLAYER5 ? MFS_CHECKED : MFS_UNCHECKED);
3966 SetMenuItemInfo (GUI.hMenu, IDM_ENABLE_MULTITAP, FALSE, &mii);
3967
3968 validFlag = (((1<<SNES_MULTIPLAYER8) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3969 mii.fState = validFlag | (GUI.ControllerOption == SNES_MULTIPLAYER8 ? MFS_CHECKED : MFS_UNCHECKED);
3970 SetMenuItemInfo (GUI.hMenu, IDM_MULTITAP8, FALSE, &mii);
3971
3972 validFlag = (((1<<SNES_MOUSE) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3973 mii.fState = validFlag | (GUI.ControllerOption == SNES_MOUSE ? MFS_CHECKED : MFS_UNCHECKED);
3974 SetMenuItemInfo (GUI.hMenu, IDM_MOUSE_TOGGLE, FALSE, &mii);
3975
3976 validFlag = (((1<<SNES_MOUSE_SWAPPED) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3977 mii.fState = validFlag | (GUI.ControllerOption == SNES_MOUSE_SWAPPED ? MFS_CHECKED : MFS_UNCHECKED);
3978 SetMenuItemInfo (GUI.hMenu, IDM_MOUSE_SWAPPED, FALSE, &mii);
3979
3980 validFlag = (((1<<SNES_SUPERSCOPE) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3981 mii.fState = validFlag | (GUI.ControllerOption == SNES_SUPERSCOPE ? MFS_CHECKED : MFS_UNCHECKED);
3982 SetMenuItemInfo (GUI.hMenu, IDM_SCOPE_TOGGLE, FALSE, &mii);
3983
3984 validFlag = (((1<<SNES_JUSTIFIER) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3985 mii.fState = validFlag | (GUI.ControllerOption == SNES_JUSTIFIER ? MFS_CHECKED : MFS_UNCHECKED);
3986 SetMenuItemInfo (GUI.hMenu, IDM_JUSTIFIER, FALSE, &mii);
3987
3988 validFlag = (((1<<SNES_JUSTIFIER_2) & GUI.ValidControllerOptions) && (!S9xMovieActive() || !S9xMovieGetFrameCounter())) ? MFS_ENABLED : MFS_DISABLED;
3989 mii.fState = validFlag | (GUI.ControllerOption == SNES_JUSTIFIER_2 ? MFS_CHECKED : MFS_UNCHECKED);
3990 SetMenuItemInfo (GUI.hMenu, IDM_JUSTIFIERS, FALSE, &mii);
3991
3992 mii.fState = !Settings.StopEmulation ? MFS_ENABLED : MFS_DISABLED;
3993 SetMenuItemInfo (GUI.hMenu, ID_FILE_AVI_RECORDING, FALSE, &mii);
3994
3995 memset(&mii, 0, sizeof(mii));
3996 mii.cbSize = sizeof(mii);
3997 mii.fMask = MIIM_STRING;
3998
3999 mii.dwTypeData = !GUI.AVIOut ? TEXT("Start AVI Recording...") : TEXT("Stop AVI Recording");
4000 SetMenuItemInfo (GUI.hMenu, ID_FILE_AVI_RECORDING, FALSE, &mii);
4001 }
4002
ResetFrameTimer()4003 static void ResetFrameTimer ()
4004 {
4005 QueryPerformanceCounter((LARGE_INTEGER*)&PCStart);
4006 PCStartTicks = timeGetTime()*1000;
4007 if (Settings.FrameTime == Settings.FrameTimeNTSC) PCFrameTime = PCFrameTimeNTSC;
4008 else if (Settings.FrameTime == Settings.FrameTimePAL) PCFrameTime = PCFrameTimePAL;
4009 else PCFrameTime = (__int64)((double)(PCBase * Settings.FrameTime) * .000001);
4010
4011
4012 if (GUI.hFrameTimer)
4013 timeKillEvent (GUI.hFrameTimer);
4014
4015 GUI.hFrameTimer = timeSetEvent ((Settings.FrameTime+500)/1000, 0, (LPTIMECALLBACK)FrameTimer, 0, TIME_PERIODIC);
4016 }
4017
LoadROMPlain(const TCHAR * filename)4018 static bool LoadROMPlain(const TCHAR *filename)
4019 {
4020 if (!filename || !*filename)
4021 return (FALSE);
4022 SetCurrentDirectory(S9xGetDirectoryT(ROM_DIR));
4023 if (Memory.LoadROM (_tToChar(filename)))
4024 {
4025 S9xStartCheatSearch (&Cheat);
4026 ReInitSound();
4027 ResetFrameTimer ();
4028 return (TRUE);
4029 }
4030 return (FALSE);
4031 }
4032
LoadROM(const TCHAR * filename)4033 static bool LoadROM(const TCHAR *filename) {
4034
4035 #ifdef NETPLAY_SUPPORT
4036 if (Settings.NetPlay && !Settings.NetPlayServer)
4037 {
4038 S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER,
4039 WINPROC_DISCONNECT);
4040 return false;
4041 }
4042 #endif
4043
4044 if (!Settings.StopEmulation) {
4045 Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR));
4046 S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
4047 }
4048
4049 Settings.StopEmulation = !LoadROMPlain(filename);
4050
4051 if (!Settings.StopEmulation) {
4052 bool8 loadedSRAM = Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR));
4053 if(!loadedSRAM) // help migration from earlier Snes9x versions by checking ROM directory for savestates
4054 Memory.LoadSRAM (S9xGetFilename (".srm", ROMFILENAME_DIR));
4055 S9xAddToRecentGames (filename);
4056 CheckDirectoryIsWritable (S9xGetFilename (".---", SNAPSHOT_DIR));
4057
4058 #ifdef NETPLAY_SUPPORT
4059 if (NPServer.SendROMImageOnConnect)
4060 S9xNPServerQueueSendingROMImage ();
4061 else
4062 S9xNPServerQueueSendingLoadROMRequest (Memory.ROMName);
4063 #endif
4064 if(GUI.rewindBufferSize)
4065 {
4066 #if !_WIN64
4067 if (GUI.rewindBufferSize > 1024) GUI.rewindBufferSize = 1024;
4068 #endif
4069 stateMan.init(GUI.rewindBufferSize * 1024 * 1024);
4070 }
4071 }
4072
4073 if(GUI.ControllerOption == SNES_SUPERSCOPE)
4074 SetCursor (GUI.GunSight);
4075 else {
4076 SetCursor (GUI.Arrow);
4077 GUI.CursorTimer = 60;
4078 }
4079 Settings.Paused = false;
4080
4081 return !Settings.StopEmulation;
4082 }
4083
LoadMultiROM(const TCHAR * filename,const TCHAR * filename2)4084 static bool LoadMultiROM (const TCHAR *filename, const TCHAR *filename2)
4085 {
4086 SetCurrentDirectory(S9xGetDirectoryT(ROM_DIR));
4087 if (Memory.LoadMultiCart (_tToChar(filename), _tToChar(filename2)))
4088 {
4089 S9xStartCheatSearch (&Cheat);
4090 ReInitSound();
4091 ResetFrameTimer ();
4092 return (TRUE);
4093 }
4094 return (FALSE);
4095 }
4096
S9xLoadROMImage(const TCHAR * string)4097 bool8 S9xLoadROMImage (const TCHAR *string)
4098 {
4099 RestoreGUIDisplay ();
4100 TCHAR *buf = new TCHAR [200 + lstrlen (string)];
4101 _stprintf (buf, TEXT("The NetPlay server is requesting you load the following game:\n '%s'"),
4102 string);
4103
4104 MessageBox (GUI.hWnd, buf,
4105 SNES9X_INFO,
4106 MB_OK | MB_ICONINFORMATION);
4107
4108 delete buf;
4109
4110 TCHAR FileName [_MAX_PATH];
4111
4112 if(DoOpenRomDialog(FileName)) {
4113 return LoadROM(FileName);
4114 }
4115 else
4116 return (FALSE);
4117
4118 return (TRUE);
4119 }
4120
4121 /*****************************************************************************/
4122 #ifdef NETPLAY_SUPPORT
EnableServer(bool8 enable)4123 void EnableServer (bool8 enable)
4124 {
4125 if (enable != Settings.NetPlayServer)
4126 {
4127 if (Settings.NetPlay && !Settings.NetPlayServer)
4128 {
4129 Settings.NetPlay = FALSE;
4130 S9xNPDisconnect ();
4131 }
4132
4133 if (enable)
4134 {
4135 S9xSetPause (PAUSE_NETPLAY_CONNECT);
4136 Settings.NetPlayServer = S9xNPStartServer (Settings.Port);
4137 Sleep (1000);
4138
4139 if (!S9xNPConnectToServer ("127.0.0.1", Settings.Port,
4140 Memory.ROMName))
4141 {
4142 S9xClearPause (PAUSE_NETPLAY_CONNECT);
4143 }
4144 }
4145 else
4146 {
4147 Settings.NetPlayServer = FALSE;
4148 S9xNPStopServer ();
4149 }
4150 }
4151 }
4152 #endif
4153
S9xAddToRecentGames(const TCHAR * filename)4154 void S9xAddToRecentGames (const TCHAR *filename)
4155 {
4156 // Make sure its not in the list already
4157 int i;
4158 for(i = 0; i < MAX_RECENT_GAMES_LIST_SIZE; i++)
4159 if (!*GUI.RecentGames[i] || lstrcmp (filename, GUI.RecentGames[i]) == 0)
4160 break;
4161
4162 const bool underMax = (i < MAX_RECENT_GAMES_LIST_SIZE);
4163 if(underMax && *GUI.RecentGames[i])
4164 {
4165 // It is in the list, move it to the head of the list.
4166 TCHAR temp [MAX_PATH];
4167 lstrcpy(temp, GUI.RecentGames[i]);
4168 for(int j = i; j > 0; j--)
4169 lstrcpy(GUI.RecentGames[j], GUI.RecentGames[j-1]);
4170
4171 lstrcpy(GUI.RecentGames[0], temp);
4172 }
4173 else
4174 {
4175 // Not in the list, add it.
4176 if(underMax)
4177 // Extend the recent game list length by 1.
4178 memmove(&GUI.RecentGames[1], &GUI.RecentGames[0], MAX_PATH*i*sizeof(TCHAR));
4179 else
4180 // Throw the last item off the end of the list
4181 memmove(&GUI.RecentGames[1], &GUI.RecentGames[0], MAX_PATH*(i-1)*sizeof(TCHAR));
4182
4183 lstrcpy(GUI.RecentGames[0], filename);
4184
4185 WinSaveConfigFile();
4186 }
4187
4188 S9xSetRecentGames();
4189 }
4190
S9xRemoveFromRecentGames(int i)4191 void S9xRemoveFromRecentGames (int i)
4192 {
4193 if (*GUI.RecentGames [i])
4194 {
4195 for (int j = i; j < MAX_RECENT_GAMES_LIST_SIZE-1; j++)
4196 lstrcpy(GUI.RecentGames [j], GUI.RecentGames [j + 1]);
4197 *GUI.RecentGames [MAX_RECENT_GAMES_LIST_SIZE-1] = TEXT('\0');
4198
4199 S9xSetRecentGames ();
4200 }
4201 }
4202
4203 #ifdef UNICODE
4204
4205 /* OV2: We need dynamic binding to this function as it is not present in
4206 windows versions < vista. Since the jumplist is a win7 feature this
4207 is not a problem.
4208 */
4209 typedef HRESULT (STDAPICALLTYPE *SHCIFPN) (__in PCWSTR pszPath, __in_opt IBindCtx *pbc, __in REFIID riid, __deref_out void **ppv);
4210
Win7_JLSetRecentGames(ICustomDestinationList * pcdl,IObjectArray * poaRemoved,UINT maxSlots)4211 HRESULT Win7_JLSetRecentGames(ICustomDestinationList *pcdl, IObjectArray *poaRemoved, UINT maxSlots)
4212 {
4213 IObjectCollection *poc;
4214
4215 HMODULE S32dll = GetModuleHandle(TEXT("shell32.dll"));
4216 SHCIFPN SHCreateIFPN = (SHCIFPN)GetProcAddress(S32dll,"SHCreateItemFromParsingName");
4217 if(!SHCreateIFPN) {
4218 return S_FALSE;
4219 }
4220 HRESULT hr = CoCreateInstance
4221 (CLSID_EnumerableObjectCollection,
4222 NULL,
4223 CLSCTX_INPROC_SERVER,
4224 IID_PPV_ARGS(&poc));
4225 if (SUCCEEDED(hr)) {
4226 UINT max_list = MIN(maxSlots,GUI.MaxRecentGames);
4227 for (UINT i = 0; i < max_list && *GUI.RecentGames[i]; i++) {
4228 IShellItem *psi;
4229 if(SUCCEEDED(SHCreateIFPN(GUI.RecentGames[i],NULL,IID_PPV_ARGS(&psi)))) {
4230 hr = poc->AddObject(psi);
4231 psi->Release();
4232 }
4233 }
4234
4235 IObjectArray *poa;
4236 hr = poc->QueryInterface(IID_PPV_ARGS(&poa));
4237 if (SUCCEEDED(hr)) {
4238 hr = pcdl->AppendCategory(TEXT("ROMs"), poa);
4239 poa->Release();
4240 }
4241 poc->Release();
4242 }
4243 return hr;
4244 }
4245
Win7_CreateJumpList()4246 void Win7_CreateJumpList()
4247 {
4248 ICustomDestinationList *pcdl;
4249 HRESULT hr = CoCreateInstance(
4250 CLSID_DestinationList,
4251 NULL,
4252 CLSCTX_INPROC_SERVER,
4253 IID_PPV_ARGS(&pcdl));
4254 if (SUCCEEDED(hr)) {
4255 UINT maxSlots;
4256 IObjectArray *poaRemoved;
4257 hr = pcdl->BeginList(&maxSlots, IID_PPV_ARGS(&poaRemoved));
4258 if (SUCCEEDED(hr)) {
4259 hr = Win7_JLSetRecentGames(pcdl, poaRemoved,maxSlots);
4260 if (SUCCEEDED(hr)) {
4261 hr = pcdl->CommitList();
4262 }
4263 poaRemoved->Release();
4264 }
4265 pcdl->Release();
4266 }
4267 }
4268 #endif
4269
S9xSetRecentGames()4270 void S9xSetRecentGames ()
4271 {
4272 HMENU file = GetSubMenu (GUI.hMenu, 0);
4273 if (file)
4274 {
4275 HMENU recent = GetSubMenu (file, 1);
4276 if (recent)
4277 {
4278 MENUITEMINFO mii;
4279 TCHAR name [256 + 10];
4280 int i;
4281
4282 // Clear out the menu first
4283 for (i = GetMenuItemCount (recent) - 1; i >= 0; i--)
4284 RemoveMenu (recent, i, MF_BYPOSITION);
4285
4286 mii.cbSize = sizeof (mii);
4287 mii.fMask = MIIM_TYPE | MIIM_DATA | MIIM_STATE | MIIM_ID;
4288 mii.fType = MFT_STRING;
4289 mii.fState = MFS_UNCHECKED;
4290
4291 for (i = 0; i < MAX_RECENT_GAMES_LIST_SIZE && i < GUI.MaxRecentGames && *GUI.RecentGames [i]; i++)
4292 {
4293 // Build up a menu item string in the form:
4294 // 1. <basename of ROM image name>
4295
4296 _stprintf (name, TEXT("&%c. "), i < 9 ? '1' + i : 'A' + i - 9);
4297
4298 // append the game title to name, with formatting modifications as necessary
4299 {
4300 TCHAR baseName [256];
4301 lstrcpy (baseName, _tFromChar(S9xBasename (_tToChar(GUI.RecentGames [i]))));
4302 int pos = lstrlen (name), baseNameLen = lstrlen (baseName);
4303 for (int j = 0; j < baseNameLen ; j++)
4304 {
4305 TCHAR c = baseName [j];
4306 name [pos++] = c;
4307
4308 // & is a special character in Windows menus,
4309 // so we have to change & to && when copying over the game title
4310 // otherwise "Pocky & Rocky (U).smc" will show up as "Pocky _Rocky (U).smc", for example
4311 if(c == TEXT('&'))
4312 name [pos++] = TEXT('&');
4313 }
4314 name [pos] = TEXT('\0');
4315 }
4316
4317 mii.dwTypeData = name;
4318 mii.cch = lstrlen (name) + 1;
4319 mii.wID = 0xFF00 + i;
4320
4321 InsertMenuItem (recent, 0xFF00 + i, FALSE, &mii);
4322 }
4323 #ifdef UNICODE
4324 Win7_CreateJumpList();
4325 #endif
4326 }
4327 }
4328 }
4329
GetWindowMargins(HWND hwnd,UINT width)4330 RECT GetWindowMargins(HWND hwnd, UINT width)
4331 {
4332 RECT rcMargins = {0,0,0,0};
4333
4334 AdjustWindowRectEx(&rcMargins, GetWindowStyle(hwnd), !GUI.HideMenu, GetWindowExStyle(hwnd));
4335
4336 rcMargins.left = abs(rcMargins.left);
4337 rcMargins.top = abs(rcMargins.top);
4338
4339 if (!GUI.HideMenu) {
4340 RECT rcTemp = {0,0,width,0x7FFF}; // 0x7FFF="Infinite" height
4341 SendMessage(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rcTemp);
4342
4343 // Adjust our previous calculation to compensate for menu
4344 // wrapping.
4345 rcMargins.top = rcTemp.top;
4346 }
4347
4348 return rcMargins;
4349 }
4350
WinDeleteRecentGamesList()4351 void WinDeleteRecentGamesList ()
4352 {
4353 for(int i=0;i<MAX_RECENT_GAMES_LIST_SIZE;i++)
4354 GUI.RecentGames[i][0]=TEXT('\0');
4355 }
4356
CreateToolTip(int toolID,HWND hDlg,TCHAR * pText)4357 BOOL CreateToolTip(int toolID, HWND hDlg, TCHAR* pText)
4358 {
4359 // toolID: the resource ID of the control.
4360 // hDlg: the handle of the dialog box.
4361 // pText: the text that appears in the tooltip.
4362 // g_hInst: the global instance handle.
4363
4364 if (!toolID || !hDlg || !pText)
4365 {
4366 return FALSE;
4367 }
4368 // Get the window of the tool.
4369 HWND hwndTool = GetDlgItem(hDlg, toolID);
4370
4371 // Create the tooltip.
4372 HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
4373 WS_POPUP |TTS_ALWAYSTIP | TTS_BALLOON,
4374 CW_USEDEFAULT, CW_USEDEFAULT,
4375 CW_USEDEFAULT, CW_USEDEFAULT,
4376 hDlg, NULL,
4377 g_hInst, NULL);
4378
4379 if (!hwndTool || !hwndTip)
4380 {
4381 return FALSE;
4382 }
4383
4384 // Associate the tooltip with the tool.
4385 TOOLINFO toolInfo = { 0 };
4386 toolInfo.cbSize = sizeof(toolInfo);
4387 toolInfo.hwnd = hDlg;
4388 toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
4389 toolInfo.uId = (UINT_PTR)hwndTool;
4390 toolInfo.lpszText = pText;
4391 SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
4392
4393 return TRUE;
4394 }
4395
DlgSoundConf(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)4396 INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
4397 {
4398 HWND hTrackbar;
4399 TCHAR valTxt[10];
4400 switch(msg)
4401 {
4402 case WM_INITDIALOG:
4403 WinRefreshDisplay();
4404
4405 // FIXME: these strings should come from wlanguage.h
4406
4407 CreateToolTip(IDC_INRATEEDIT,hDlg,TEXT("For each 'Input rate' samples generated by the SNES, 'Playback rate' samples will produced. If you experience crackling you can try to lower this setting."));
4408 CreateToolTip(IDC_INRATE,hDlg,TEXT("For each 'Input rate' samples generated by the SNES, 'Playback rate' samples will produced. If you experience crackling you can try to lower this setting."));
4409
4410 int pos;
4411 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("Snes9x DirectSound"));
4412 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_SNES9X_DIRECT_SOUND_DRIVER);
4413 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("XAudio2"));
4414 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_XAUDIO2_SOUND_DRIVER);
4415 #ifdef FMOD_SUPPORT
4416 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("FMOD DirectSound"));
4417 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_FMOD_DIRECT_SOUND_DRIVER);
4418 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("FMOD Windows Multimedia"));
4419 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_FMOD_WAVE_SOUND_DRIVER);
4420 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("FMOD A3D"));
4421 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_FMOD_A3D_SOUND_DRIVER);
4422 #elif defined FMODEX_SUPPORT
4423 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("FMOD Ex Default"));
4424 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_FMODEX_DEFAULT_DRIVER);
4425 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("FMOD Ex ASIO"));
4426 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_FMODEX_ASIO_DRIVER);
4427 pos = SendDlgItemMessage(hDlg, IDC_DRIVER, CB_INSERTSTRING,-1,(LPARAM)TEXT("FMOD Ex OpenAL"));
4428 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_SETITEMDATA,pos,WIN_FMODEX_OPENAL_DRIVER);
4429 #endif
4430 SendDlgItemMessage(hDlg, IDC_DRIVER,CB_SETCURSEL,0,0);
4431 for(pos = 0;pos<SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETCOUNT,0,0);pos++) {
4432 if(SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETITEMDATA,pos,0)==GUI.SoundDriver) {
4433 SendDlgItemMessage(hDlg, IDC_DRIVER,CB_SETCURSEL,pos,0);
4434 break;
4435 }
4436 }
4437
4438 SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETRANGE,TRUE,MAKELONG(0,20));
4439 SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETPOS,TRUE,(Settings.SoundInputRate - 31100)/50);
4440 SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETTICFREQ,1,0);
4441 _sntprintf(valTxt,10,TEXT("%d"),Settings.SoundInputRate);
4442 Edit_SetText(GetDlgItem(hDlg, IDC_INRATEEDIT),valTxt);
4443
4444
4445 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,0,(LPARAM)TEXT("8 KHz"));
4446 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,1,(LPARAM)TEXT("11 KHz"));
4447 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,2,(LPARAM)TEXT("16 KHz"));
4448 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,3,(LPARAM)TEXT("22 KHz"));
4449 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,4,(LPARAM)TEXT("30 KHz"));
4450 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,5,(LPARAM)TEXT("32 KHz (SNES)"));
4451 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,6,(LPARAM)TEXT("35 KHz"));
4452 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,7,(LPARAM)TEXT("44 KHz"));
4453 SendDlgItemMessage(hDlg, IDC_RATE, CB_INSERTSTRING,8,(LPARAM)TEXT("48 KHz"));
4454
4455 int temp;
4456 switch(Settings.SoundPlaybackRate)
4457 {
4458 case 8000:temp=0;break;
4459 case 11025:temp=1;break;
4460 case 16000:temp=2;break;
4461 case 22050:temp=3;break;
4462 case 30000:temp=4;break;
4463 case 0:
4464 default:
4465 case 32000:temp=5;break;
4466 case 35000:temp=6;break;
4467 case 44000:
4468 case 44100:temp=7;break;
4469 case 48000:temp=8;break;
4470 }
4471 SendDlgItemMessage(hDlg,IDC_RATE,CB_SETCURSEL,temp,0);
4472
4473 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,0,(LPARAM)TEXT("16 ms"));
4474 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,1,(LPARAM)TEXT("32 ms"));
4475 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,2,(LPARAM)TEXT("48 ms"));
4476 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,3,(LPARAM)TEXT("64 ms"));
4477 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,4,(LPARAM)TEXT("80 ms"));
4478 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,5,(LPARAM)TEXT("96 ms"));
4479 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,6,(LPARAM)TEXT("112 ms"));
4480 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,7,(LPARAM)TEXT("128 ms"));
4481 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,8,(LPARAM)TEXT("144 ms"));
4482 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,9,(LPARAM)TEXT("160 ms"));
4483 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,10,(LPARAM)TEXT("176 ms"));
4484 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,11,(LPARAM)TEXT("194 ms"));
4485 SendDlgItemMessage(hDlg, IDC_BUFLEN, CB_INSERTSTRING,12,(LPARAM)TEXT("210 ms"));
4486
4487 SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,((GUI.SoundBufferSize/16)-1),0);
4488
4489 if(Settings.SixteenBitSound)
4490 SendDlgItemMessage(hDlg,IDC_16BIT,BM_SETCHECK,BST_CHECKED,0);
4491 if(Settings.Stereo)
4492 SendDlgItemMessage(hDlg,IDC_STEREO,BM_SETCHECK,BST_CHECKED,0);
4493 else EnableWindow(GetDlgItem(hDlg, IDC_REV_STEREO), FALSE);
4494 if(Settings.ReverseStereo)
4495 SendDlgItemMessage(hDlg,IDC_REV_STEREO,BM_SETCHECK,BST_CHECKED,0);
4496
4497 if(GUI.Mute)
4498 SendDlgItemMessage(hDlg,IDC_MUTE,BM_SETCHECK,BST_CHECKED,0);
4499 if(GUI.FAMute)
4500 SendDlgItemMessage(hDlg,IDC_FAMT,BM_SETCHECK,BST_CHECKED,0);
4501
4502 if(Settings.SoundSync)
4503 SendDlgItemMessage(hDlg,IDC_SYNC_TO_SOUND_CPU,BM_SETCHECK,BST_CHECKED,0);
4504
4505 return true;
4506 case WM_PAINT:
4507 {
4508 PAINTSTRUCT ps;
4509 BeginPaint (hDlg, &ps);
4510
4511 EndPaint (hDlg, &ps);
4512 }
4513 return true;
4514 case WM_HSCROLL:
4515 hTrackbar = GetDlgItem(hDlg, IDC_INRATE);
4516 if((HWND)lParam==hTrackbar) {
4517 int trackValue = 31100 + 50 * SendDlgItemMessage(hDlg,IDC_INRATE,TBM_GETPOS,0,0);
4518 _sntprintf(valTxt,10,TEXT("%d"),trackValue);
4519 Edit_SetText(GetDlgItem(hDlg, IDC_INRATEEDIT),valTxt);
4520 return true;
4521 }
4522 break;
4523 case WM_COMMAND:
4524 switch(LOWORD(wParam))
4525 {
4526 case IDOK:
4527 {
4528 GUI.SoundDriver=SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETITEMDATA,
4529 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETCURSEL, 0,0),0);
4530 Settings.SixteenBitSound=IsDlgButtonChecked(hDlg, IDC_16BIT);
4531 Settings.SoundSync=IsDlgButtonChecked(hDlg, IDC_SYNC_TO_SOUND_CPU);
4532 Settings.Stereo=IsDlgButtonChecked(hDlg, IDC_STEREO);
4533 Settings.ReverseStereo=IsDlgButtonChecked(hDlg, IDC_REV_STEREO);
4534 GUI.Mute=IsDlgButtonChecked(hDlg, IDC_MUTE);
4535 GUI.FAMute=IsDlgButtonChecked(hDlg, IDC_FAMT)!=0;
4536
4537
4538 switch(SendDlgItemMessage(hDlg, IDC_RATE,CB_GETCURSEL,0,0))
4539 {
4540 case 0: Settings.SoundPlaybackRate=8000; break;
4541 case 1: Settings.SoundPlaybackRate=11025; break;
4542 case 2: Settings.SoundPlaybackRate=16000; break;
4543 case 3: Settings.SoundPlaybackRate=22050; break;
4544 case 4: Settings.SoundPlaybackRate=30000; break;
4545 case 5: Settings.SoundPlaybackRate=32000; break;
4546 case 6: Settings.SoundPlaybackRate=35000; break;
4547 case 7: Settings.SoundPlaybackRate=44100; break;
4548 case 8: Settings.SoundPlaybackRate=48000; break;
4549 }
4550
4551 GUI.SoundBufferSize=(16*(1+(SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_GETCURSEL,0,0))));
4552
4553 Edit_GetText(GetDlgItem(hDlg,IDC_INRATEEDIT),valTxt,10);
4554 int sliderVal=_tstoi(valTxt);
4555 Settings.SoundInputRate = sliderVal>0?sliderVal:32000;
4556
4557 WinSaveConfigFile();
4558
4559 // already done in WinProc on return
4560 // ReInitSound();
4561
4562 } /* FALL THROUGH */
4563
4564 case IDCANCEL:
4565 EndDialog(hDlg, 1);
4566 return true;
4567
4568 case IDC_DRIVER:
4569 if(CBN_SELCHANGE==HIWORD(wParam))
4570 {
4571 int driver=SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETITEMDATA,
4572 SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETCURSEL, 0,0),0);
4573 switch(driver) {
4574 case WIN_SNES9X_DIRECT_SOUND_DRIVER:
4575 SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,3,0);
4576 break;
4577 case WIN_XAUDIO2_SOUND_DRIVER:
4578 SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,3,0);
4579 break;
4580 default:
4581 SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,7,0);
4582 break;
4583 }
4584 return true;
4585 }
4586 else return false;
4587 case IDC_STEREO:
4588 {
4589 if(BN_CLICKED==HIWORD(wParam)||BN_DBLCLK==HIWORD(wParam))
4590 {
4591 if(IsDlgButtonChecked(hDlg,IDC_STEREO))
4592 {
4593 EnableWindow(GetDlgItem(hDlg, IDC_REV_STEREO), TRUE);
4594 }
4595 else EnableWindow(GetDlgItem(hDlg, IDC_REV_STEREO), FALSE);
4596 return true;
4597
4598 }
4599 else return false;
4600 }
4601 case IDC_INRATEEDIT:
4602 if(HIWORD(wParam)==EN_UPDATE) {
4603 Edit_GetText(GetDlgItem(hDlg,IDC_INRATEEDIT),valTxt,10);
4604 int sliderVal=_tstoi(valTxt);
4605 SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETPOS,TRUE,(sliderVal - 31100)/50);
4606 }
4607 break;
4608 default: return false;
4609
4610
4611 }
4612 }
4613 return false;
4614 }
4615
4616 // SetSelProc
4617 // Callback procedure to set the initial selection of the (folder) browser.
SetSelProc(HWND hWnd,UINT uMsg,LPARAM lParam,LPARAM lpData)4618 int CALLBACK SetSelProc( HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
4619 {
4620 if (uMsg==BFFM_INITIALIZED) {
4621 ::SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData );
4622 }
4623 return 0;
4624 }
4625
StaticRAMBitSize()4626 const char *StaticRAMBitSize ()
4627 {
4628 static char tmp [20];
4629
4630 sprintf (tmp, " (%dKbit)", 8*(Memory.SRAMMask + 1) / 1024);
4631 return (tmp);
4632 }
4633
DlgInfoProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)4634 INT_PTR CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
4635 {
4636 switch(msg)
4637 {
4638 case WM_INITDIALOG:
4639 WinRefreshDisplay();
4640 {
4641 char temp[100];
4642 char romtext[4096];
4643 sprintf(romtext, "File: %s\r\nName: %s\r\n", Memory.ROMFilename, Memory.RawROMName);
4644 sprintf(temp, "Speed: %02X/%s\r\nROM Map: %s\r\nType: %02x\r\n", Memory.ROMSpeed, ((Memory.ROMSpeed&0x10)!=0)?"FastROM":"SlowROM",(Memory.HiROM)?"HiROM":"LoROM",Memory.ROMType);
4645 strcat(romtext, temp);
4646 strcat(romtext, "Kart contents: ");
4647 strcat(romtext, Memory.KartContents ());
4648 strcat(romtext, "\r\nHeader ROM Size: ");
4649 strcat(romtext, Memory.Size());
4650 sprintf(temp, "\r\nCalculated ROM Size: %d Mbits", Memory.CalculatedSize/0x20000);
4651 strcat(romtext, temp);
4652
4653 strcat(romtext, "\r\nSRAM size: ");
4654 strcat(romtext, Memory.StaticRAMSize ());
4655 strcat(romtext, StaticRAMBitSize());
4656 strcat(romtext, "\r\nActual Checksum: ");
4657 sprintf(temp, "%04X", Memory.CalculatedChecksum);
4658 strcat(romtext, temp);
4659 strcat(romtext, "\r\nHeader Checksum: ");
4660 sprintf(temp, "%04X", Memory.ROMChecksum);
4661 strcat(romtext, temp);
4662 strcat(romtext, "\r\nHeader Checksum Compliment: ");
4663 sprintf(temp, "%04X", Memory.ROMComplementChecksum);
4664 strcat(romtext, temp);
4665 strcat(romtext, "\r\nOutput: ");
4666 if(Memory.ROMRegion>12||Memory.ROMRegion<2)
4667 strcat(romtext, "NTSC 60Hz");
4668 else strcat(romtext, "PAL 50Hz");
4669
4670 sprintf(temp, "\r\nCRC32:\t%08X", Memory.ROMCRC32);
4671 strcat(romtext, temp);
4672
4673
4674 strcat(romtext, "\r\nLicensee: ");
4675
4676 int tmp=Memory.CompanyId;
4677 if(tmp==0)
4678 tmp=(Memory.HiROM)?Memory.ROM[0x0FFDA]:Memory.ROM[0x7FDA];
4679 switch(tmp)
4680 // switch(((Memory.ROMSpeed&0x0F)!=0)?Memory.ROM[0x0FFDA]:Memory.ROM[0x7FDA])
4681 // switch(atoi(Memory.CompanyId))
4682 // switch(((Memory.CompanyId[0]-'0')*16)+(Memory.CompanyId[1]-'0'))
4683 {
4684 case 0:strcat(romtext, "INVALID COMPANY");break;
4685 case 1:strcat(romtext, "Nintendo");break;
4686 case 2:strcat(romtext, "Ajinomoto");break;
4687 case 3:strcat(romtext, "Imagineer-Zoom");break;
4688 case 4:strcat(romtext, "Chris Gray Enterprises Inc.");break;
4689 case 5:strcat(romtext, "Zamuse");break;
4690 case 6:strcat(romtext, "Falcom");break;
4691 case 7:strcat(romtext, NOTKNOWN "7");break;
4692 case 8:strcat(romtext, "Capcom");break;
4693 case 9:strcat(romtext, "HOT-B");break;
4694 case 10:strcat(romtext, "Jaleco");break;
4695 case 11:strcat(romtext, "Coconuts");break;
4696 case 12:strcat(romtext, "Rage Software");break;
4697 case 13:strcat(romtext, "Micronet"); break; //Acc. ZFE
4698 case 14:strcat(romtext, "Technos");break;
4699 case 15:strcat(romtext, "Mebio Software");break;
4700 case 16:strcat(romtext, "SHOUEi System"); break; //Acc. ZFE
4701 case 17:strcat(romtext, "Starfish");break; //UCON 64
4702 case 18:strcat(romtext, "Gremlin Graphics");break;
4703 case 19:strcat(romtext, "Electronic Arts");break;
4704 case 20:strcat(romtext, "NCS / Masaya"); break; //Acc. ZFE
4705 case 21:strcat(romtext, "COBRA Team");break;
4706 case 22:strcat(romtext, "Human/Field");break;
4707 case 23:strcat(romtext, "KOEI");break;
4708 case 24:strcat(romtext, "Hudson Soft");break;
4709 case 25:strcat(romtext, "Game Village");break;//uCON64
4710 case 26:strcat(romtext, "Yanoman");break;
4711 case 27:strcat(romtext, NOTKNOWN "27");break;
4712 case 28:strcat(romtext, "Tecmo");break;
4713 case 29:strcat(romtext, NOTKNOWN "29");break;
4714 case 30:strcat(romtext, "Open System");break;
4715 case 31:strcat(romtext, "Virgin Games");break;
4716 case 32:strcat(romtext, "KSS");break;
4717 case 33:strcat(romtext, "Sunsoft");break;
4718 case 34:strcat(romtext, "POW");break;
4719 case 35:strcat(romtext, "Micro World");break;
4720 case 36:strcat(romtext, NOTKNOWN "36");break;
4721 case 37:strcat(romtext, NOTKNOWN "37");break;
4722 case 38:strcat(romtext, "Enix");break;
4723 case 39:strcat(romtext, "Loriciel/Electro Brain");break;//uCON64
4724 case 40:strcat(romtext, "Kemco");break;
4725 case 41:strcat(romtext, "Seta Co.,Ltd.");break;
4726 case 42:strcat(romtext, "Culture Brain"); break; //Acc. ZFE
4727 case 43:strcat(romtext, "Irem Japan");break;//Irem? Gun Force J
4728 case 44:strcat(romtext, "Pal Soft"); break; //Acc. ZFE
4729 case 45:strcat(romtext, "Visit Co.,Ltd.");break;
4730 case 46:strcat(romtext, "INTEC Inc."); break; //Acc. ZFE
4731 case 47:strcat(romtext, "System Sacom Corp."); break; //Acc. ZFE
4732 case 48:strcat(romtext, "Viacom New Media");break; //Zoop!
4733 case 49:strcat(romtext, "Carrozzeria");break;
4734 case 50:strcat(romtext, "Dynamic");break;
4735 case 51:strcat(romtext, "Nintendo");break;
4736 case 52:strcat(romtext, "Magifact");break;
4737 case 53:strcat(romtext, "Hect");break;
4738 case 54:strcat(romtext, NOTKNOWN "54");break;
4739 case 55:strcat(romtext, NOTKNOWN "55");break;
4740 case 56:strcat(romtext, "Capcom Europe");break;//Capcom? BOF2(E) MM7 (E)
4741 case 57:strcat(romtext, "Accolade Europe");break;//Accolade?Bubsy 2 (E)
4742 case 58:strcat(romtext, NOTKNOWN "58");break;
4743 case 59:strcat(romtext, "Arcade Zone");break;//uCON64
4744 case 60:strcat(romtext, "Empire Software");break;
4745 case 61:strcat(romtext, "Loriciel");break;
4746 case 62:strcat(romtext, "Gremlin Graphics"); break; //Acc. ZFE
4747 case 63:strcat(romtext, NOTKNOWN "63");break;
4748 case 64:strcat(romtext, "Seika Corp.");break;
4749 case 65:strcat(romtext, "UBI Soft");break;
4750 case 66:strcat(romtext, NOTKNOWN "66");break;
4751 case 67:strcat(romtext, NOTKNOWN "67");break;
4752 case 68:strcat(romtext, "LifeFitness Exertainment");break;//?? Exertainment Mountain Bike Rally (U).zip
4753 case 69:strcat(romtext, NOTKNOWN "69");break;
4754 case 70:strcat(romtext, "System 3");break;
4755 case 71:strcat(romtext, "Spectrum Holobyte");break;
4756 case 72:strcat(romtext, NOTKNOWN "72");break;
4757 case 73:strcat(romtext, "Irem");break;
4758 case 74:strcat(romtext, NOTKNOWN "74");break;
4759 case 75:strcat(romtext, "Raya Systems/Sculptured Software");break;
4760 case 76:strcat(romtext, "Renovation Products");break;
4761 case 77:strcat(romtext, "Malibu Games/Black Pearl");break;
4762 case 78:strcat(romtext, NOTKNOWN "78");break;
4763 case 79:strcat(romtext, "U.S. Gold");break;
4764 case 80:strcat(romtext, "Absolute Entertainment");break;
4765 case 81:strcat(romtext, "Acclaim");break;
4766 case 82:strcat(romtext, "Activision");break;
4767 case 83:strcat(romtext, "American Sammy");break;
4768 case 84:strcat(romtext, "GameTek");break;
4769 case 85:strcat(romtext, "Hi Tech Expressions");break;
4770 case 86:strcat(romtext, "LJN Toys");break;
4771 case 87:strcat(romtext, NOTKNOWN "87");break;
4772 case 88:strcat(romtext, NOTKNOWN "88");break;
4773 case 89:strcat(romtext, NOTKNOWN "89");break;
4774 case 90:strcat(romtext, "Mindscape");break;
4775 case 91:strcat(romtext, "Romstar, Inc."); break; //Acc. ZFE
4776 case 92:strcat(romtext, NOTKNOWN "92");break;
4777 case 93:strcat(romtext, "Tradewest");break;
4778 case 94:strcat(romtext, NOTKNOWN "94");break;
4779 case 95:strcat(romtext, "American Softworks Corp.");break;
4780 case 96:strcat(romtext, "Titus");break;
4781 case 97:strcat(romtext, "Virgin Interactive Entertainment");break;
4782 case 98:strcat(romtext, "Maxis");break;
4783 case 99:strcat(romtext, "Origin/FCI/Pony Canyon");break;//uCON64
4784 case 100:strcat(romtext, NOTKNOWN "100");break;
4785 case 101:strcat(romtext, NOTKNOWN "101");break;
4786 case 102:strcat(romtext, NOTKNOWN "102");break;
4787 case 103:strcat(romtext, "Ocean");break;
4788 case 104:strcat(romtext, NOTKNOWN "104");break;
4789 case 105:strcat(romtext, "Electronic Arts");break;
4790 case 106:strcat(romtext, NOTKNOWN "106");break;
4791 case 107:strcat(romtext, "Laser Beam");break;
4792 case 108:strcat(romtext, NOTKNOWN "108");break;
4793 case 109:strcat(romtext, NOTKNOWN "109");break;
4794 case 110:strcat(romtext, "Elite");break;
4795 case 111:strcat(romtext, "Electro Brain");break;
4796 case 112:strcat(romtext, "Infogrames");break;
4797 case 113:strcat(romtext, "Interplay");break;
4798 case 114:strcat(romtext, "LucasArts");break;
4799 case 115:strcat(romtext, "Parker Brothers");break;
4800 case 116:strcat(romtext, "Konami");break;//uCON64
4801 case 117:strcat(romtext, "STORM");break;
4802 case 118:strcat(romtext, NOTKNOWN "118");break;
4803 case 119:strcat(romtext, NOTKNOWN "119");break;
4804 case 120:strcat(romtext, "THQ Software");break;
4805 case 121:strcat(romtext, "Accolade Inc.");break;
4806 case 122:strcat(romtext, "Triffix Entertainment");break;
4807 case 123:strcat(romtext, NOTKNOWN "123");break;
4808 case 124:strcat(romtext, "Microprose");break;
4809 case 125:strcat(romtext, NOTKNOWN "125");break;
4810 case 126:strcat(romtext, NOTKNOWN "126");break;
4811 case 127:strcat(romtext, "Kemco");break;
4812 case 128:strcat(romtext, "Misawa");break;
4813 case 129:strcat(romtext, "Teichio");break;
4814 case 130:strcat(romtext, "Namco Ltd.");break;
4815 case 131:strcat(romtext, "Lozc");break;
4816 case 132:strcat(romtext, "Koei");break;
4817 case 133:strcat(romtext, NOTKNOWN "133");break;
4818 case 134:strcat(romtext, "Tokuma Shoten Intermedia");break;
4819 case 135:strcat(romtext, "Tsukuda Original"); break; //Acc. ZFE
4820 case 136:strcat(romtext, "DATAM-Polystar");break;
4821 case 137:strcat(romtext, NOTKNOWN "137");break;
4822 case 138:strcat(romtext, NOTKNOWN "138");break;
4823 case 139:strcat(romtext, "Bullet-Proof Software");break;
4824 case 140:strcat(romtext, "Vic Tokai");break;
4825 case 141:strcat(romtext, NOTKNOWN "141");break;
4826 case 142:strcat(romtext, "Character Soft");break;
4827 case 143:strcat(romtext, "I\'\'Max");break;
4828 case 144:strcat(romtext, "Takara");break;
4829 case 145:strcat(romtext, "CHUN Soft");break;
4830 case 146:strcat(romtext, "Video System Co., Ltd.");break;
4831 case 147:strcat(romtext, "BEC");break;
4832 case 148:strcat(romtext, NOTKNOWN "148");break;
4833 case 149:strcat(romtext, "Varie");break;
4834 case 150:strcat(romtext, "Yonezawa / S'Pal Corp."); break; //Acc. ZFE
4835 case 151:strcat(romtext, "Kaneco");break;
4836 case 152:strcat(romtext, NOTKNOWN "152");break;
4837 case 153:strcat(romtext, "Pack in Video");break;
4838 case 154:strcat(romtext, "Nichibutsu");break;
4839 case 155:strcat(romtext, "TECMO");break;
4840 case 156:strcat(romtext, "Imagineer Co.");break;
4841 case 157:strcat(romtext, NOTKNOWN "157");break;
4842 case 158:strcat(romtext, NOTKNOWN "158");break;
4843 case 159:strcat(romtext, NOTKNOWN "159");break;
4844 case 160:strcat(romtext, "Telenet");break;
4845 case 161:strcat(romtext, "Hori"); break; //Acc. uCON64
4846 case 162:strcat(romtext, NOTKNOWN "162");break;
4847 case 163:strcat(romtext, NOTKNOWN "163");break;
4848 case 164:strcat(romtext, "Konami");break;
4849 case 165:strcat(romtext, "K.Amusement Leasing Co.");break;
4850 case 166:strcat(romtext, NOTKNOWN "166");break;
4851 case 167:strcat(romtext, "Takara");break;
4852 case 168:strcat(romtext, NOTKNOWN "168");break;
4853 case 169:strcat(romtext, "Technos Jap.");break;
4854 case 170:strcat(romtext, "JVC");break;
4855 case 171:strcat(romtext, NOTKNOWN "171");break;
4856 case 172:strcat(romtext, "Toei Animation");break;
4857 case 173:strcat(romtext, "Toho");break;
4858 case 174:strcat(romtext, NOTKNOWN "174");break;
4859 case 175:strcat(romtext, "Namco Ltd.");break;
4860 case 176:strcat(romtext, "Media Rings Corp."); break; //Acc. ZFE
4861 case 177:strcat(romtext, "ASCII Co. Activison");break;
4862 case 178:strcat(romtext, "Bandai");break;
4863 case 179:strcat(romtext, NOTKNOWN "179");break;
4864 case 180:strcat(romtext, "Enix America");break;
4865 case 181:strcat(romtext, NOTKNOWN "181");break;
4866 case 182:strcat(romtext, "Halken");break;
4867 case 183:strcat(romtext, NOTKNOWN "183");break;
4868 case 184:strcat(romtext, NOTKNOWN "184");break;
4869 case 185:strcat(romtext, NOTKNOWN "185");break;
4870 case 186:strcat(romtext, "Culture Brain");break;
4871 case 187:strcat(romtext, "Sunsoft");break;
4872 case 188:strcat(romtext, "Toshiba EMI");break;
4873 case 189:strcat(romtext, "Sony Imagesoft");break;
4874 case 190:strcat(romtext, NOTKNOWN "190");break;
4875 case 191:strcat(romtext, "Sammy");break;
4876 case 192:strcat(romtext, "Taito");break;
4877 case 193:strcat(romtext, NOTKNOWN "193");break;
4878 case 194:strcat(romtext, "Kemco");break;
4879 case 195:strcat(romtext, "Square");break;
4880 case 196:strcat(romtext, "Tokuma Soft");break;
4881 case 197:strcat(romtext, "Data East");break;
4882 case 198:strcat(romtext, "Tonkin House");break;
4883 case 199:strcat(romtext, NOTKNOWN "199");break;
4884 case 200:strcat(romtext, "KOEI");break;
4885 case 201:strcat(romtext, NOTKNOWN "201");break;
4886 case 202:strcat(romtext, "Konami USA");break;
4887 case 203:strcat(romtext, "NTVIC");break;
4888 case 204:strcat(romtext, NOTKNOWN "204");break;
4889 case 205:strcat(romtext, "Meldac");break;
4890 case 206:strcat(romtext, "Pony Canyon");break;
4891 case 207:strcat(romtext, "Sotsu Agency/Sunrise");break;
4892 case 208:strcat(romtext, "Disco/Taito");break;
4893 case 209:strcat(romtext, "Sofel");break;
4894 case 210:strcat(romtext, "Quest Corp.");break;
4895 case 211:strcat(romtext, "Sigma");break;
4896 case 212:strcat(romtext, "Ask Kodansha Co., Ltd."); break; //Acc. ZFE
4897 case 213:strcat(romtext, NOTKNOWN "213");break;
4898 case 214:strcat(romtext, "Naxat");break;
4899 case 215:strcat(romtext, NOTKNOWN "215");break;
4900 case 216:strcat(romtext, "Capcom Co., Ltd.");break;
4901 case 217:strcat(romtext, "Banpresto");break;
4902 case 218:strcat(romtext, "Tomy");break;
4903 case 219:strcat(romtext, "Acclaim");break;
4904 case 220:strcat(romtext, NOTKNOWN "220");break;
4905 case 221:strcat(romtext, "NCS");break;
4906 case 222:strcat(romtext, "Human Entertainment");break;
4907 case 223:strcat(romtext, "Altron");break;
4908 case 224:strcat(romtext, "Jaleco");break;
4909 case 225:strcat(romtext, NOTKNOWN "225");break;
4910 case 226:strcat(romtext, "Yutaka");break;
4911 case 227:strcat(romtext, NOTKNOWN "227");break;
4912 case 228:strcat(romtext, "T&ESoft");break;
4913 case 229:strcat(romtext, "EPOCH Co.,Ltd.");break;
4914 case 230:strcat(romtext, NOTKNOWN "230");break;
4915 case 231:strcat(romtext, "Athena");break;
4916 case 232:strcat(romtext, "Asmik");break;
4917 case 233:strcat(romtext, "Natsume");break;
4918 case 234:strcat(romtext, "King Records");break;
4919 case 235:strcat(romtext, "Atlus");break;
4920 case 236:strcat(romtext, "Sony Music Entertainment");break;
4921 case 237:strcat(romtext, NOTKNOWN "237");break;
4922 case 238:strcat(romtext, "IGS");break;
4923 case 239:strcat(romtext, NOTKNOWN "239");break;
4924 case 240:strcat(romtext, NOTKNOWN "240");break;
4925 case 241:strcat(romtext, "Motown Software");break;
4926 case 242:strcat(romtext, "Left Field Entertainment");break;
4927 case 243:strcat(romtext, "Beam Software");break;
4928 case 244:strcat(romtext, "Tec Magik");break;
4929 case 245:strcat(romtext, NOTKNOWN "245");break;
4930 case 246:strcat(romtext, NOTKNOWN "246");break;
4931 case 247:strcat(romtext, NOTKNOWN "247");break;
4932 case 248:strcat(romtext, NOTKNOWN "248");break;
4933 case 249:strcat(romtext, "Cybersoft");break;
4934 case 250:strcat(romtext, NOTKNOWN "250");break;
4935 case 251:strcat(romtext, "Psygnosis"); break; //Acc. ZFE
4936 case 252:strcat(romtext, NOTKNOWN "252");break;
4937 case 253:strcat(romtext, NOTKNOWN "253");break;
4938 case 254:strcat(romtext, "Davidson"); break; //Acc. uCON64
4939 case 255:strcat(romtext, NOTKNOWN "255");break;
4940 default:strcat(romtext, NOTKNOWN);break;
4941 }
4942
4943 strcat(romtext, "\r\nROM Version: ");
4944 sprintf(temp, "1.%d", (Memory.HiROM)?Memory.ROM[0x0FFDB]:Memory.ROM[0x7FDB]);
4945 strcat(romtext, temp);
4946 strcat(romtext, "\r\nRegion: ");
4947 switch(Memory.ROMRegion)
4948 {
4949 case 0:
4950 strcat(romtext, "Japan");
4951 break;
4952 case 1:
4953 strcat(romtext, "USA/Canada");
4954 break;
4955 case 2:
4956 strcat(romtext, "Oceania, Europe, and Asia");
4957 break;
4958 case 3:
4959 strcat(romtext, "Sweden");
4960 break;
4961 case 4:
4962 strcat(romtext, "Finland");
4963 break;
4964 case 5:
4965 strcat(romtext, "Denmark");
4966 break;
4967 case 6:
4968 strcat(romtext, "France");
4969 break;
4970 case 7:
4971 strcat(romtext, "Holland");
4972 break;
4973 case 8:
4974 strcat(romtext, "Spain");
4975 break;
4976 case 9:
4977 strcat(romtext, "Germany, Austria, and Switzerland");
4978 break;
4979 case 10:
4980 strcat(romtext, "Italy");
4981 break;
4982 case 11:
4983 strcat(romtext, "Hong Kong and China");
4984 break;
4985 case 12:
4986 strcat(romtext, "Indonesia");
4987 break;
4988 case 13:
4989 strcat(romtext, "South Korea");
4990 break;
4991 case 14:strcat(romtext, "Unknown region 14");break;
4992 default:strcat(romtext, "Unknown region 15");break;
4993 }
4994 SendDlgItemMessage(hDlg, IDC_ROM_DATA, WM_SETTEXT, 0, (LPARAM)((TCHAR *)_tFromMS932(romtext)));
4995 break;
4996 }
4997 case WM_CTLCOLORSTATIC:
4998
4999 if(GetDlgCtrlID((HWND)lParam)==IDC_ROM_DATA && GUI.InfoColor!=WIN32_WHITE)
5000 {
5001 SetTextColor((HDC)wParam, GUI.InfoColor);
5002 SetBkColor((HDC)wParam, RGB(0,0,0));
5003 return (BOOL)GetStockObject( BLACK_BRUSH );
5004 }
5005 break;
5006 case WM_PAINT:
5007 break;
5008
5009 case WM_COMMAND:
5010 {
5011 switch(LOWORD(wParam))
5012 {
5013 case IDOK:
5014 case IDCANCEL:
5015 EndDialog(hDlg, 0);
5016 return true;
5017 break;
5018 default: break;
5019 }
5020 }
5021 default:
5022 break;
5023 }
5024 return FALSE;
5025 }
5026
DlgAboutProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)5027 INT_PTR CALLBACK DlgAboutProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
5028 {
5029
5030 switch(msg)
5031 {
5032 case WM_INITDIALOG:
5033 WinRefreshDisplay();
5034 {
5035 TCHAR buf[2048];//find better way of dealing.
5036 _stprintf(buf,DISCLAIMER_TEXT,TEXT(VERSION));
5037 SetDlgItemText(hDlg, IDC_DISCLAIMER, buf);
5038 SetWindowText(hDlg, ABOUT_DIALOG_TITLE APP_NAME);
5039 }
5040 return true;
5041 case WM_PAINT:
5042 {
5043 PAINTSTRUCT ps;
5044 BeginPaint (hDlg, &ps);
5045
5046 EndPaint (hDlg, &ps);
5047 }
5048 return true;
5049 case WM_COMMAND:
5050 {
5051 switch(LOWORD(wParam))
5052 {
5053 case IDOK:
5054 case IDCANCEL:
5055 EndDialog(hDlg, 0);
5056 return true;
5057 break;
5058 default: return false; break;
5059 }
5060 }
5061 default:return false;
5062 }
5063 }
DlgEmulatorProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)5064 INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
5065 {
5066 static TCHAR paths[8][MAX_PATH];
5067 static int which = 0;
5068 switch(msg)
5069 {
5070 case WM_INITDIALOG:
5071 WinRefreshDisplay();
5072 {
5073 SetWindowText(hDlg, EMUSET_TITLE);
5074 SetDlgItemText(hDlg, IDC_LABEL_FREEZE, EMUSET_LABEL_DIRECTORY);
5075 SetDlgItemText(hDlg, IDOK, BUTTON_OK);
5076 SetDlgItemText(hDlg, IDCANCEL, BUTTON_CANCEL);
5077 SetDlgItemText(hDlg, IDC_LABEL_ASRAM, EMUSET_LABEL_ASRAM);
5078 SetDlgItemText(hDlg, IDC_LABEL_ASRAM_TEXT, EMUSET_LABEL_ASRAM_TEXT);
5079 SetDlgItemText(hDlg, IDC_LABEL_SMAX, EMUSET_LABEL_SMAX);
5080 SetDlgItemText(hDlg, IDC_LABEL_SMAX_TEXT, EMUSET_LABEL_SMAX_TEXT);
5081 SetDlgItemText(hDlg, IDC_LABEL_STURBO_TEXT, EMUSET_LABEL_STURBO_TEXT);
5082 SetDlgItemText(hDlg, IDC_LABEL_STURBO, EMUSET_LABEL_STURBO);
5083 SetDlgItemText(hDlg, IDC_BROWSE, EMUSET_BROWSE);
5084 SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, GUI.FreezeFileDir);
5085 SetDlgItemText(hDlg, IDC_CONFIG_NAME_BOX, TEXT(S9X_CONF_FILE_NAME));
5086 SendDlgItemMessage(hDlg, IDC_SRAM_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)99, (short)0));
5087 SendDlgItemMessage(hDlg, IDC_SRAM_SPIN,UDM_SETPOS,0, Settings.AutoSaveDelay);
5088 SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP, UDM_SETRANGE, 0, MAKELPARAM((short)59, (short)0));
5089 SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP,UDM_SETPOS,0, Settings.AutoMaxSkipFrames);
5090 SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_SETRANGE, 0, MAKELPARAM((short)600, (short)0));
5091 SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP,UDM_SETPOS,0, Settings.TurboSkipFrames);
5092 SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)4000, (short)0));
5093 SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN,UDM_SETPOS,0, GUI.rewindBufferSize);
5094 SendDlgItemMessage(hDlg, IDC_REWIND_GRANULARITY_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)300, (short)1));
5095 SendDlgItemMessage(hDlg, IDC_REWIND_GRANULARITY_SPIN,UDM_SETPOS,0, GUI.rewindGranularity);
5096 CheckDlgButton(hDlg,IDC_INACTIVE_PAUSE,GUI.InactivePause ? BST_CHECKED : BST_UNCHECKED);
5097 CheckDlgButton(hDlg,IDC_CUSTOMROMOPEN,GUI.CustomRomOpen ? BST_CHECKED : BST_UNCHECKED);
5098 CheckDlgButton(hDlg,IDC_HIRESAVI,GUI.AVIHiRes ? BST_CHECKED : BST_UNCHECKED);
5099
5100 int inum = 0;
5101 lstrcpy(paths[inum++],GUI.RomDir);
5102 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_ROMS);
5103 lstrcpy(paths[inum++],GUI.ScreensDir);
5104 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SCREENS);
5105 lstrcpy(paths[inum++],GUI.MovieDir);
5106 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_MOVIES);
5107 lstrcpy(paths[inum++],GUI.SPCDir);
5108 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SPCS);
5109 lstrcpy(paths[inum++],GUI.FreezeFileDir);
5110 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SAVES);
5111 lstrcpy(paths[inum++],GUI.SRAMFileDir);
5112 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SRAM);
5113 lstrcpy(paths[inum++],GUI.PatchDir);
5114 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_PATCHESANDCHEATS);
5115 lstrcpy(paths[inum++],GUI.BiosDir);
5116 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_BIOS);
5117
5118 SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_SETCURSEL,(WPARAM)0,0);
5119 SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[0]);
5120 which = 0;
5121
5122 SetCurrentDirectory(S9xGetDirectoryT(DEFAULT_DIR));
5123 }
5124 case WM_PAINT:
5125 {
5126 PAINTSTRUCT ps;
5127 BeginPaint (hDlg, &ps);
5128
5129 EndPaint (hDlg, &ps);
5130 }
5131 return true;
5132 case WM_COMMAND:
5133 {
5134 switch(LOWORD(wParam))
5135 {
5136 case IDC_BROWSE:
5137 {
5138 LPMALLOC lpm=NULL;
5139 LPITEMIDLIST iidl=NULL;
5140 BROWSEINFO bi;
5141 memset(&bi, 0, sizeof(BROWSEINFO));
5142 TCHAR path[MAX_PATH];
5143 _tfullpath(path, paths[which], MAX_PATH);
5144 TCHAR title[]=SETTINGS_TITLE_SELECTFOLDER;
5145 bi.hwndOwner=hDlg;
5146 bi.pszDisplayName=path;
5147 bi.lpszTitle=title;
5148 bi.lpfn = SetSelProc;
5149 bi.lParam = (LPARAM)(LPCSTR) path;
5150 bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_EDITBOX;
5151 iidl=SHBrowseForFolder(&bi);
5152 if(iidl) SHGetPathFromIDList(iidl, path);
5153
5154 SHGetMalloc(&lpm);
5155 lpm->Free(iidl);
5156 absToRel(paths[which], path, S9xGetDirectoryT(DEFAULT_DIR));
5157 SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[which]);
5158 }
5159 break;
5160 case IDC_CUSTOM_FOLDER_FIELD:
5161 which = SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_GETCURSEL,0,0);
5162 GetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[which], MAX_PATH);
5163 break;
5164 case IDC_DIRCOMBO:
5165 which = SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_GETCURSEL,0,0);
5166 SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[which]);
5167 break;
5168 case IDOK:
5169 {
5170 int inum = 0;
5171 lstrcpy(GUI.RomDir,paths[inum++]);
5172 lstrcpy(GUI.ScreensDir,paths[inum++]);
5173 lstrcpy(GUI.MovieDir,paths[inum++]);
5174 lstrcpy(GUI.SPCDir,paths[inum++]);
5175 lstrcpy(GUI.FreezeFileDir,paths[inum++]);
5176 lstrcpy(GUI.SRAMFileDir,paths[inum++]);
5177 lstrcpy(GUI.PatchDir,paths[inum++]);
5178 lstrcpy(GUI.BiosDir,paths[inum++]);
5179
5180 GUI.InactivePause = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_INACTIVE_PAUSE));
5181 GUI.CustomRomOpen = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_CUSTOMROMOPEN));
5182 GUI.AVIHiRes = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_HIRESAVI));
5183
5184 Settings.TurboSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_GETPOS, 0,0);
5185 Settings.AutoMaxSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP, UDM_GETPOS, 0,0);
5186 Settings.AutoSaveDelay=SendDlgItemMessage(hDlg, IDC_SRAM_SPIN, UDM_GETPOS, 0,0);
5187 GUI.rewindGranularity = SendDlgItemMessage(hDlg, IDC_REWIND_GRANULARITY_SPIN, UDM_GETPOS, 0,0);
5188 if(GUI.rewindGranularity==0) GUI.rewindGranularity = 1;
5189 unsigned int newRewindBufSize = SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN, UDM_GETPOS, 0,0);
5190 if(GUI.rewindBufferSize != newRewindBufSize) {
5191 GUI.rewindBufferSize = newRewindBufSize;
5192 if(!Settings.StopEmulation) stateMan.init(GUI.rewindBufferSize * 1024 * 1024);
5193 }
5194
5195 WinSaveConfigFile();
5196 }
5197 /* fall through */
5198 case IDCANCEL:
5199 EndDialog(hDlg, 0);
5200 return true;
5201 break;
5202 default: return false; break;
5203 }
5204 }
5205 default:return false;
5206 }
5207 }
5208
5209 #define SKIP_FLOPPY
5210
ExtensionIsValid(const TCHAR * filename)5211 static bool ExtensionIsValid(const TCHAR * filename)
5212 {
5213 ExtList* curr=valid_ext;
5214 while(curr!=NULL)
5215 {
5216 if(curr->extension==NULL)
5217 {
5218 if(NULL==_tcsstr(filename, TEXT(".")))
5219 return true;
5220 }
5221 else if(filename[(lstrlen(filename)-1)-lstrlen(curr->extension)]=='.')
5222 {
5223 if(0==_tcsncicmp(&filename[(lstrlen(filename))-lstrlen(curr->extension)],
5224 curr->extension, lstrlen(curr->extension)))
5225 return true;
5226 }
5227 curr=curr->next;
5228 }
5229 return false;
5230 }
5231
IsCompressed(const TCHAR * filename)5232 bool IsCompressed(const TCHAR* filename)
5233 {
5234 ExtList* curr=valid_ext;
5235 while(curr!=NULL)
5236 {
5237 if(curr->extension==NULL)
5238 {
5239 if(NULL==_tcsstr(filename, TEXT(".")))
5240 return curr->compressed;
5241 }
5242 else if(filename[(lstrlen(filename)-1)-lstrlen(curr->extension)]=='.')
5243 {
5244 if(0==_tcsncicmp(&filename[(lstrlen(filename))-lstrlen(curr->extension)],
5245 curr->extension, lstrlen(curr->extension)))
5246 return curr->compressed;
5247 }
5248 curr=curr->next;
5249 }
5250 return false;
5251 }
5252
AllASCII(char * b,int size)5253 inline bool AllASCII(char *b, int size)
5254 {
5255 for (int i = 0; i < size; i++)
5256 {
5257 if (b[i] < 32 || b[i] > 126)
5258 {
5259 return(false);
5260 }
5261 }
5262 return(true);
5263 }
5264
InfoScore(char * Buffer)5265 inline int InfoScore(char *Buffer)
5266 {
5267 int score = 0;
5268 if (Buffer[28] + (Buffer[29] << 8) +
5269 Buffer[30] + (Buffer[31] << 8) == 0xFFFF)
5270 { score += 3; }
5271
5272 if (Buffer[26] == 0x33) { score += 2; }
5273 if ((Buffer[21] & 0xf) < 4) { score += 2; }
5274 if (!(Buffer[61] & 0x80)) { score -= 4; }
5275 if ((1 << (Buffer[23] - 7)) > 48) { score -= 1; }
5276 if (Buffer[25] < 14) { score += 1; }
5277 if (!AllASCII(Buffer, 20)) { score -= 1; }
5278
5279 return (score);
5280 }
5281
sum(unsigned char * array,unsigned int size=HEADER_SIZE)5282 inline unsigned short sum(unsigned char *array, unsigned int size = HEADER_SIZE)
5283 {
5284 register unsigned short theSum = 0;
5285 for (register unsigned int i = 0; i < size; i++)
5286 {
5287 theSum += array[i];
5288 }
5289 return(theSum);
5290 }
5291
rominfo(const TCHAR * filename,TCHAR * namebuffer,TCHAR * sizebuffer)5292 void rominfo(const TCHAR *filename, TCHAR *namebuffer, TCHAR *sizebuffer)
5293 {
5294 lstrcpy(namebuffer, ROM_ITEM_DESCNOTAVAILABLE);
5295 lstrcpy(sizebuffer, TEXT("? Mbits"));
5296
5297 #ifdef ZLIB
5298 if(IsCompressed(filename))
5299 {
5300 unzFile uf = unzOpen(_tToChar(filename));
5301 if(uf)
5302 {
5303 unz_file_info info;
5304 if(UNZ_OK == unzGetCurrentFileInfo(uf, &info, 0,0,0,0,0,0))
5305 {
5306 if (info.uncompressed_size < 0x8000) // Smaller than a block
5307 lstrcpy(namebuffer, ROM_ITEM_NOTAROM);
5308 else
5309 lstrcpy(namebuffer, ROM_ITEM_COMPRESSEDROMDESCRIPTION);
5310
5311 // should subtract header size, so this may be slightly off, but it's better than "? MBits"
5312 double MBitD = (double)(info.uncompressed_size - 0) / 0x100000 * 8;
5313 int MBitI = (int)MBitD;
5314 int sizeIndex;
5315 if(0!=(MBitI / 10))
5316 {
5317 sizebuffer[0] = MBitI / 10 + TEXT('0');
5318 sizeIndex = 1;
5319 }
5320 else
5321 sizeIndex = 0;
5322 sizebuffer[sizeIndex+0] = MBitI % 10 + TEXT('0');
5323 sizebuffer[sizeIndex+1] = TEXT('.');
5324 sizebuffer[sizeIndex+2] = (char)((MBitD - MBitI) * 10) + TEXT('0');
5325 sizebuffer[sizeIndex+3] = (char)((int)((MBitD - MBitI) * 100) % 10) + TEXT('0');
5326 sizebuffer[sizeIndex+4] = TEXT(' ');
5327 sizebuffer[sizeIndex+5] = TEXT('M');
5328 sizebuffer[sizeIndex+6] = TEXT('b');
5329 sizebuffer[sizeIndex+7] = TEXT('i');
5330 sizebuffer[sizeIndex+8] = TEXT('t');
5331 sizebuffer[sizeIndex+9] = TEXT('\0');
5332 }
5333 unzClose(uf);
5334 }
5335 return;
5336 }
5337 #endif
5338
5339 struct _stat filestats;
5340 _tstat(filename, &filestats);
5341
5342 int HeaderSize = 0;
5343
5344 if (filestats.st_size >= 0x8000)
5345 {
5346 ifstream ROMFile(filename, ios::in | ios::binary);
5347 if (ROMFile)
5348 {
5349 int HasHeadScore = 0, NoHeadScore = 0,
5350 HeadRemain = filestats.st_size & 0x7FFF;
5351
5352 switch(HeadRemain)
5353 {
5354 case 0:
5355 NoHeadScore += 3;
5356 break;
5357
5358 case HEADER_SIZE:
5359 HasHeadScore += 2;
5360 break;
5361 }
5362
5363 unsigned char HeaderBuffer[HEADER_SIZE];
5364 ROMFile.read((char *)HeaderBuffer, HEADER_SIZE);
5365
5366 if (sum(HeaderBuffer) < 2500) { HasHeadScore += 2; }
5367
5368 //SMC/SWC Header
5369 if (HeaderBuffer[8] == 0xAA &&
5370 HeaderBuffer[9] == 0xBB &&
5371 HeaderBuffer[10]== 4)
5372 { HasHeadScore += 3; }
5373 //FIG Header
5374 else if ((HeaderBuffer[4] == 0x77 && HeaderBuffer[5] == 0x83) ||
5375 (HeaderBuffer[4] == 0xDD && HeaderBuffer[5] == 0x82) ||
5376 (HeaderBuffer[4] == 0xDD && HeaderBuffer[5] == 2) ||
5377 (HeaderBuffer[4] == 0xF7 && HeaderBuffer[5] == 0x83) ||
5378 (HeaderBuffer[4] == 0xFD && HeaderBuffer[5] == 0x82) ||
5379 (HeaderBuffer[4] == 0x00 && HeaderBuffer[5] == 0x80) ||
5380 (HeaderBuffer[4] == 0x47 && HeaderBuffer[5] == 0x83) ||
5381 (HeaderBuffer[4] == 0x11 && HeaderBuffer[5] == 2))
5382 { HasHeadScore += 2; }
5383 else if (!strncmp("GAME DOCTOR SF 3", (char *)HeaderBuffer, 16))
5384 { HasHeadScore += 5; }
5385
5386 HeaderSize = HasHeadScore > NoHeadScore ? HEADER_SIZE : 0;
5387
5388 bool EHi = false;
5389 if (filestats.st_size - HeaderSize >= 0x500000)
5390 {
5391 ROMFile.seekg(0x40FFC0 + HeaderSize, ios::beg);
5392 ROMFile.read((char *)HeaderBuffer, INFO_LEN);
5393 if (InfoScore((char *)HeaderBuffer) > 1)
5394 {
5395 EHi = true;
5396 _tcsncpy(namebuffer, _tFromMS932((char *)HeaderBuffer), 21);
5397 }
5398 }
5399
5400 if (!EHi)
5401 {
5402 if (filestats.st_size - HeaderSize >= 0x10000)
5403 {
5404 char LoHead[INFO_LEN], HiHead[INFO_LEN];
5405
5406 ROMFile.seekg(0x7FC0 + HeaderSize, ios::beg);
5407 ROMFile.read(LoHead, INFO_LEN);
5408 int LoScore = InfoScore(LoHead);
5409
5410 ROMFile.seekg(0xFFC0 + HeaderSize, ios::beg);
5411 ROMFile.read(HiHead, INFO_LEN);
5412 int HiScore = InfoScore(HiHead);
5413
5414 _tcsncpy(namebuffer, _tFromMS932(LoScore > HiScore ? LoHead : HiHead), 21);
5415
5416 if (filestats.st_size - HeaderSize >= 0x20000)
5417 {
5418 ROMFile.seekg((filestats.st_size - HeaderSize) / 2 + 0x7FC0 + HeaderSize, ios::beg);
5419 ROMFile.read(LoHead, INFO_LEN);
5420 int IntLScore = InfoScore(LoHead) / 2;
5421
5422 if (IntLScore > LoScore && IntLScore > HiScore)
5423 {
5424 _tcsncpy(namebuffer, _tFromMS932(LoHead), 21);
5425 }
5426 }
5427 }
5428 else //ROM only has one block
5429 {
5430 char buf[21];
5431 ROMFile.seekg(0x7FC0 + HeaderSize, ios::beg);
5432 ROMFile.read(buf, 21);
5433 _tcsncpy(namebuffer,_tFromMS932(buf),21);
5434 }
5435 }
5436 ROMFile.close();
5437 }
5438 else //Couldn't open file
5439 {
5440 lstrcpy(namebuffer, ROM_ITEM_CANTOPEN);
5441 }
5442 }
5443 else //Smaller than a block
5444 {
5445 lstrcpy(namebuffer, ROM_ITEM_NOTAROM);
5446 }
5447
5448 double MBitD = (double)(filestats.st_size - HeaderSize) / 0x100000 * 8;
5449 int MBitI = (int)MBitD;
5450 int sizeIndex;
5451 if(0!=(MBitI / 10))
5452 {
5453 sizebuffer[0] = MBitI / 10 + TEXT('0');
5454 sizeIndex = 1;
5455 }
5456 else
5457 sizeIndex = 0;
5458 sizebuffer[sizeIndex+0] = MBitI % 10 + TEXT('0');
5459 sizebuffer[sizeIndex+1] = TEXT('.');
5460 sizebuffer[sizeIndex+2] = (char)((MBitD - MBitI) * 10) + TEXT('0');
5461 sizebuffer[sizeIndex+3] = (char)((int)((MBitD - MBitI) * 100) % 10) + TEXT('0');
5462 sizebuffer[sizeIndex+4] = TEXT(' ');
5463 sizebuffer[sizeIndex+5] = TEXT('M');
5464 sizebuffer[sizeIndex+6] = TEXT('b');
5465 sizebuffer[sizeIndex+7] = TEXT('i');
5466 sizebuffer[sizeIndex+8] = TEXT('t');
5467 sizebuffer[sizeIndex+9] = TEXT('\0');
5468 namebuffer[21] = TEXT('\0');
5469 }
5470
GetPathFromTree(HWND hDlg,UINT tree,TCHAR * selected,HTREEITEM hItem)5471 void GetPathFromTree( HWND hDlg, UINT tree, TCHAR* selected, HTREEITEM hItem)
5472 {
5473 TVITEM tv;
5474 TCHAR temp[MAX_PATH];
5475 temp[0]=('\0');
5476 memset(&tv, 0, sizeof(TVITEM));
5477 HTREEITEM hTreeTemp=hItem;
5478
5479 if(tv.iImage==7)
5480 {
5481 tv.mask=TVIF_HANDLE|TVIF_IMAGE;
5482 tv.hItem=hTreeTemp;
5483 tv.iImage=6;
5484 TreeView_SetItem(GetDlgItem(hDlg, tree),&tv);
5485 memset(&tv, 0, sizeof(TVITEM));
5486 }
5487
5488 tv.mask=TVIF_HANDLE|TVIF_TEXT;
5489 tv.hItem=hTreeTemp;
5490 tv.pszText=temp;
5491 tv.cchTextMax =MAX_PATH;
5492 TreeView_GetItem(GetDlgItem(hDlg, tree), &tv);
5493
5494 _stprintf(selected, TEXT("%s"), temp);
5495 while(TreeView_GetParent(GetDlgItem(hDlg, tree), hTreeTemp))
5496 {
5497 temp[0]=TEXT('\0');
5498 hTreeTemp=TreeView_GetParent(GetDlgItem(hDlg, tree), hTreeTemp);
5499 tv.mask=TVIF_HANDLE|TVIF_TEXT;
5500 tv.hItem=hTreeTemp;
5501 tv.pszText=temp;
5502 tv.cchTextMax =MAX_PATH;
5503 TreeView_GetItem(GetDlgItem(hDlg, tree), &tv);
5504 _stprintf(temp, TEXT("%s\\%s"),temp, selected);
5505 lstrcpy(selected, temp);
5506 }
5507 }
5508
5509 typedef struct RomDataCacheNode
5510 {
5511 TCHAR* fname;
5512 TCHAR* rname;
5513 TCHAR* rmbits;
5514 struct RomDataCacheNode* next;
5515 } RomDataList;
5516
ClearCacheList(RomDataList * rdl)5517 void ClearCacheList(RomDataList* rdl)
5518 {
5519 RomDataList* temp=rdl;
5520 RomDataList* temp2=NULL;
5521 if(rdl==NULL)
5522 return;
5523 do
5524 {
5525 temp2=temp->next;
5526 if(temp->fname)
5527 delete [] temp->fname;
5528 if(temp->rmbits)
5529 delete [] temp->rmbits;
5530 if(temp->rname)
5531 delete [] temp->rname;
5532 delete temp;
5533 temp=temp2;
5534 }
5535 while(temp!=NULL);
5536 }
5537
5538
ExpandDir(TCHAR * selected,HTREEITEM hParent,HWND hDlg)5539 void ExpandDir(TCHAR * selected, HTREEITEM hParent, HWND hDlg)
5540 {
5541 TCHAR temp[MAX_PATH];
5542 WIN32_FIND_DATA wfd;
5543 memset(&wfd, 0, sizeof(WIN32_FIND_DATA));
5544 lstrcat(selected, TEXT("\\*"));
5545 HANDLE hFind=FindFirstFile(selected,&wfd);
5546 selected[(lstrlen(selected)-1)]=TEXT('\0');
5547
5548 do
5549 {
5550 if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
5551 {
5552 if(lstrcmp(wfd.cFileName, TEXT("."))&&lstrcmp(wfd.cFileName, TEXT("..")))
5553 {
5554 //skip these, add the rest.
5555 TV_INSERTSTRUCT tvis;
5556 memset(&tvis, 0, sizeof(TV_INSERTSTRUCT));
5557 tvis.hParent=hParent;
5558 tvis.hInsertAfter=TVI_SORT;
5559 tvis.item.mask = TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
5560 tvis.item.pszText=wfd.cFileName;
5561 tvis.item.cchTextMax=MAX_PATH;
5562 const bool locked = (wfd.dwFileAttributes&(FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_ENCRYPTED|FILE_ATTRIBUTE_OFFLINE))!=0;
5563 const bool hidden = (wfd.dwFileAttributes&(FILE_ATTRIBUTE_HIDDEN))!=0;
5564 tvis.item.iImage=hidden?9:(locked?8:7);
5565 tvis.item.iSelectedImage=locked?8:6;
5566 HTREEITEM hNewTree=TreeView_InsertItem(GetDlgItem(hDlg, IDC_ROM_DIR),&tvis);
5567
5568 lstrcpy(temp, selected);
5569 lstrcat(temp, wfd.cFileName);
5570 lstrcat(temp, TEXT("\\*"));
5571
5572 bool subdir=false;
5573 WIN32_FIND_DATA wfd2;
5574 memset(&wfd2, 0, sizeof(WIN32_FIND_DATA));
5575 HANDLE hFind2=FindFirstFile(temp,&wfd2);
5576 do
5577 {
5578 if(wfd2.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
5579 {
5580 if(lstrcmp(wfd2.cFileName, TEXT("."))&&lstrcmp(wfd2.cFileName, TEXT("..")))
5581 {
5582 subdir=true;
5583 }
5584 }
5585 }
5586 while(FindNextFile(hFind2, &wfd2)&&!subdir);
5587
5588 if(subdir)
5589 {
5590 TV_INSERTSTRUCT tvis;
5591 memset(&tvis, 0, sizeof(TV_INSERTSTRUCT));
5592 tvis.hParent=hNewTree;
5593 tvis.hInsertAfter=TVI_SORT;
5594 TreeView_InsertItem(GetDlgItem(hDlg, IDC_ROM_DIR),&tvis);
5595
5596 }
5597 FindClose(hFind2);
5598
5599 }
5600 }
5601 }
5602 while(FindNextFile(hFind, &wfd));
5603
5604 FindClose(hFind);
5605 //scan for folders
5606 }
5607
5608
5609
ListFilesFromFolder(HWND hDlg,RomDataList ** prdl)5610 void ListFilesFromFolder(HWND hDlg, RomDataList** prdl)
5611 {
5612 RomDataList* rdl= *prdl;
5613 RomDataList* current=NULL;
5614 int count=0;
5615 TVITEM tv;
5616 TCHAR temp[MAX_PATH];
5617 TCHAR selected[MAX_PATH]; // directory path
5618 temp[0]='\0';
5619 memset(&tv, 0, sizeof(TVITEM));
5620 HTREEITEM hTreeItem=TreeView_GetSelection(GetDlgItem(hDlg, IDC_ROM_DIR));
5621
5622 GetPathFromTree(hDlg, IDC_ROM_DIR, selected, hTreeItem);
5623
5624 SendDlgItemMessage(hDlg, IDC_ROMLIST, WM_SETREDRAW, FALSE, 0);
5625 ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_ROMLIST));
5626 ClearCacheList(rdl);
5627 rdl=NULL;
5628 //Add items here.
5629
5630 WIN32_FIND_DATA wfd;
5631 memset(&wfd, 0, sizeof(WIN32_FIND_DATA));
5632
5633 lstrcat(selected, TEXT("\\*"));
5634
5635 HANDLE hFind=FindFirstFile(selected, &wfd);
5636 selected[(lstrlen(selected)-1)]=TEXT('\0');
5637 do
5638 {
5639 if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
5640 continue;
5641 if(ExtensionIsValid(wfd.cFileName))
5642 {
5643 RomDataList* newitem=new RomDataList;
5644 memset(newitem, 0, sizeof(RomDataList));
5645 newitem->fname=new TCHAR[1+lstrlen(wfd.cFileName)];
5646 lstrcpy(newitem->fname, wfd.cFileName);
5647
5648 // hide ntldr and no-name files
5649 if(!newitem->fname || !*newitem->fname || (!lstrcmp(newitem->fname, TEXT("ntldr")) && lstrlen(selected)<4))
5650 continue;
5651
5652 // too small to be a ROM
5653 if (wfd.nFileSizeLow < 0x8000 && !IsCompressed(wfd.cFileName))
5654 continue;
5655
5656 count++;
5657
5658 if(!rdl)
5659 rdl=newitem;
5660 else
5661 {
5662 if(0>_tcsicmp(newitem->fname,rdl->fname))
5663 {
5664 newitem->next=rdl;
5665 rdl=newitem;
5666 }
5667 else
5668 {
5669 RomDataList* trail=rdl;
5670 current=rdl->next;
5671 while(current!=NULL&&0<_tcsicmp(newitem->fname,current->fname))
5672 {
5673 trail=current;
5674 current=current->next;
5675 }
5676 newitem->next=current;
5677 trail->next=newitem;
5678 }
5679 }
5680 }
5681 }
5682 while(FindNextFile(hFind, &wfd));
5683
5684 FindClose(hFind);
5685
5686 SendDlgItemMessage(hDlg, IDC_ROMLIST, WM_SETREDRAW, TRUE, 0);
5687 *prdl=rdl;
5688 ListView_SetItemCountEx (GetDlgItem(hDlg, IDC_ROMLIST), count, 0);
5689 ListView_SetItemState (GetDlgItem(hDlg,IDC_ROMLIST), 0, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
5690 }
5691
5692 // load multicart rom dialog
DlgMultiROMProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)5693 INT_PTR CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
5694 {
5695 switch(msg)
5696 {
5697 case WM_INITDIALOG:{
5698 WinRefreshDisplay();
5699 TCHAR path[MAX_PATH];
5700 SetCurrentDirectory(S9xGetDirectoryT(BIOS_DIR));
5701 _tfullpath(path, TEXT("stbios.bin"), MAX_PATH);
5702 SetDlgItemText(hDlg, IDC_MULTICART_BIOSEDIT, path);
5703 FILE* ftemp = _tfopen(path, TEXT("rb"));
5704 if(ftemp)
5705 {
5706 fclose(ftemp);
5707 SetDlgItemText(hDlg, IDC_MULTICART_BIOSNOTFOUND, MULTICART_BIOS_FOUND);
5708 }
5709 else
5710 SetDlgItemText(hDlg, IDC_MULTICART_BIOSNOTFOUND, MULTICART_BIOS_NOT_FOUND);
5711 SetDlgItemText(hDlg, IDC_MULTICART_EDITA, multiRomA);
5712 SetDlgItemText(hDlg, IDC_MULTICART_EDITB, multiRomB);
5713 break;}
5714 case WM_COMMAND:
5715 {
5716 TCHAR rom1[MAX_PATH]={0}, rom2[MAX_PATH]={0};
5717 SetCurrentDirectory(S9xGetDirectoryT(ROM_DIR));
5718 switch(LOWORD(wParam))
5719 {
5720 case IDOK:
5721 GetDlgItemText(hDlg, IDC_MULTICART_EDITA, multiRomA, MAX_PATH);
5722 GetDlgItemText(hDlg, IDC_MULTICART_EDITB, multiRomB, MAX_PATH);
5723 EndDialog(hDlg, 1);
5724 return true;
5725 case IDCANCEL:
5726 EndDialog(hDlg, 0);
5727 return true;
5728 case IDC_MULTICART_SWAP:
5729 GetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom2, MAX_PATH);
5730 GetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom1, MAX_PATH);
5731 SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1);
5732 SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2);
5733 break;
5734 case IDC_MULTICART_BROWSEA:
5735 if(!DoOpenRomDialog(rom1, true))
5736 break;
5737 SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1);
5738 break;
5739 case IDC_MULTICART_BROWSEB:
5740 if(!DoOpenRomDialog(rom2, true))
5741 break;
5742 SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2);
5743 break;
5744 case IDC_MULTICART_CLEARA:
5745 rom1[0] = TEXT('\0');
5746 SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1);
5747 break;
5748 case IDC_MULTICART_CLEARB:
5749 rom1[1] = TEXT('\0');
5750 SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2);
5751 break;
5752 }
5753 }
5754 }
5755 return false;
5756 }
5757
DlgOpenROMProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)5758 INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
5759 {
5760 int rv=0;
5761 static HWND hSplit;
5762 static HIMAGELIST hIcons;
5763 static TCHAR *filename;
5764 static RomDataList* rdl;
5765 static int selectionMarkOverride = -1;
5766 static bool initDone = false;
5767 static RomDataList* nextInvalidatedROM = NULL;
5768 static int nextInvalidatedROMCounter = 0;
5769 static HWND romList = NULL;
5770 static HWND dirList = NULL;
5771 switch(msg)
5772 {
5773 case WM_INITDIALOG:
5774 WinRefreshDisplay();
5775 {
5776 initDone = false;
5777
5778 // suppress annoying "no disk in drive" errors
5779 SetErrorMode(SEM_FAILCRITICALERRORS);
5780
5781 romList = GetDlgItem(hDlg,IDC_ROMLIST);
5782 dirList = GetDlgItem(hDlg,IDC_ROM_DIR);
5783 filename=(TCHAR*)lParam;
5784 RECT treeRect;
5785 RECT listRect;
5786 WNDCLASSEX wcex;
5787 TCHAR tempclassname[]=TEXT("S9xSplitter");
5788 memset(&wcex, 0, sizeof(WNDCLASSEX));
5789 wcex.cbSize=sizeof(WNDCLASSEX);
5790 wcex.hInstance=g_hInst;
5791 wcex.lpfnWndProc=DlgChildSplitProc;
5792 wcex.lpszClassName=tempclassname;
5793 wcex.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
5794 wcex.hCursor=LoadCursor(NULL, IDC_SIZEWE);
5795 /// wcex.hCursor=LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE));
5796 /// ATOM aSplitter=RegisterClassEx(&wcex);
5797 GetWindowRect(dirList, &treeRect);
5798 GetWindowRect(romList, &listRect);
5799 POINT p;
5800
5801 ListView_SetExtendedListViewStyle(romList, LVS_EX_FULLROWSELECT);
5802
5803 p.x=treeRect.right;
5804 p.y=treeRect.top;
5805 ScreenToClient(hDlg, &p);
5806 hSplit=CreateWindow(TEXT("S9xSplitter"), TEXT(""),WS_CHILD|WS_VISIBLE , p.x, p.y, listRect.left-treeRect.right , listRect.bottom-listRect.top, hDlg,NULL, g_hInst,0);
5807
5808 LVCOLUMN col;
5809 static const LPTSTR temp1 = ROM_COLUMN_FILENAME;
5810 memset(&col, 0, sizeof(LVCOLUMN));
5811 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH;
5812 col.fmt=LVCFMT_LEFT;
5813 col.iOrder=0;
5814 col.cx=196;
5815 col.cchTextMax=5;
5816 col.pszText=temp1;
5817
5818 ListView_InsertColumn(romList, 0, &col);
5819
5820 static const LPTSTR temp2 = ROM_COLUMN_DESCRIPTION;
5821 memset(&col, 0, sizeof(LVCOLUMN));
5822 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
5823 col.fmt=LVCFMT_LEFT;
5824 col.iOrder=1;
5825 col.cx=112;
5826 col.cchTextMax=32;
5827 col.pszText=temp2;
5828 col.iSubItem=1;
5829
5830 ListView_InsertColumn(romList, 1, &col);
5831
5832
5833 static const LPTSTR temp3 = ROM_COLUMN_SIZE;
5834 memset(&col, 0, sizeof(LVCOLUMN));
5835 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
5836 col.fmt=LVCFMT_LEFT;
5837 col.iOrder=2;
5838 col.cx=67;
5839 col.cchTextMax=32;
5840 col.pszText=temp3;
5841 col.iSubItem=2;
5842
5843 ListView_InsertColumn(romList, 2, &col);
5844
5845
5846 SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_INSERTSTRING,0,(LPARAM)ROM_OPTION_AUTODETECT);
5847 SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_INSERTSTRING,1,(LPARAM)ROM_OPTION_FORCEHIROM);
5848 SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_INSERTSTRING,2,(LPARAM)ROM_OPTION_FORCELOROM);
5849 SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_SETCURSEL,0,0);
5850
5851 SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_INSERTSTRING,0,(LPARAM)ROM_OPTION_AUTODETECT);
5852 SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_INSERTSTRING,1,(LPARAM)ROM_OPTION_FORCEPAL);
5853 SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_INSERTSTRING,2,(LPARAM)ROM_OPTION_FORCENTSC);
5854 SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_SETCURSEL,0,0);
5855
5856 SendDlgItemMessage(hDlg, IDC_HEADER,CB_INSERTSTRING,0,(LPARAM)ROM_OPTION_AUTODETECT);
5857 SendDlgItemMessage(hDlg, IDC_HEADER,CB_INSERTSTRING,1,(LPARAM)ROM_OPTION_FORCEHEADER);
5858 SendDlgItemMessage(hDlg, IDC_HEADER,CB_INSERTSTRING,2,(LPARAM)ROM_OPTION_FORCENOHEADER);
5859 SendDlgItemMessage(hDlg, IDC_HEADER,CB_SETCURSEL,0,0);
5860
5861 SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,0,(LPARAM)ROM_OPTION_AUTODETECT);
5862 SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,1,(LPARAM)ROM_OPTION_NONINTERLEAVED);
5863 SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,2,(LPARAM)ROM_OPTION_MODE1);
5864 SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,3,(LPARAM)ROM_OPTION_MODE2);
5865 SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,4,(LPARAM)ROM_OPTION_GD24);
5866 SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_SETCURSEL,0,0);
5867
5868 hIcons=ImageList_Create(16,16,ILC_COLOR24,10,10);
5869
5870 HANDLE hBitmap;
5871
5872 #define ADD_IMAGE(IDB_NAME) \
5873 hBitmap=LoadImage(g_hInst, MAKEINTRESOURCE(IDB_NAME), IMAGE_BITMAP, 0,0, LR_DEFAULTCOLOR|LR_CREATEDIBSECTION); \
5874 ImageList_Add(hIcons, (HBITMAP)hBitmap, NULL); \
5875 DeleteObject(hBitmap);
5876
5877 ADD_IMAGE(IDB_HARDDRIVE); // 0
5878 ADD_IMAGE(IDB_CDDRIVE); // 1
5879 ADD_IMAGE(IDB_NETDRIVE); // 2
5880 ADD_IMAGE(IDB_REMOVABLE); // 3
5881 ADD_IMAGE(IDB_RAMDISK); // 4
5882 ADD_IMAGE(IDB_UNKNOWN); // 5
5883 ADD_IMAGE(IDB_OPENFOLDER); // 6
5884 ADD_IMAGE(IDB_CLOSEDFOLDER); // 7
5885 ADD_IMAGE(IDB_LOCKEDFOLDER); // 8
5886 ADD_IMAGE(IDB_HIDDENFOLDER); // 9
5887
5888 TreeView_SetImageList(dirList, hIcons, TVSIL_NORMAL);
5889
5890 // DWORD dw;
5891 TCHAR buffer[MAX_PATH];
5892 TCHAR blah[MAX_PATH];
5893 long result=ERROR_SUCCESS/*-1*/;
5894 HTREEITEM hTreeDrive=NULL;
5895
5896 TCHAR drive [_MAX_DRIVE + 1];
5897 lstrcpy (drive,TEXT("C:\\"));
5898
5899
5900 _tfullpath (buffer, S9xGetDirectoryT(ROM_DIR), MAX_PATH);
5901 _tsplitpath (buffer, drive, NULL, NULL, NULL);
5902
5903 DWORD driveMask=GetLogicalDrives();
5904
5905 #ifndef SKIP_FLOPPY
5906 for (int i=0;i<26;i++)
5907 #else
5908 for (int i=2;i<26;i++)
5909 #endif
5910 {
5911 if(driveMask&(1<<i))
5912 {
5913 TCHAR driveName[4];
5914 driveName[0]='A'+i;
5915 driveName[1]=':';
5916 driveName[2]='\\';
5917 driveName[3]='\0';
5918 UINT driveType=GetDriveType(driveName);
5919 driveName[2]='\0';
5920
5921 TVINSERTSTRUCT tvis;
5922 memset(&tvis, 0, sizeof(TVINSERTSTRUCT));
5923
5924 tvis.hParent=NULL;
5925 tvis.hInsertAfter=TVI_ROOT;
5926 tvis.item.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
5927
5928 switch(driveType)
5929 {
5930 case DRIVE_FIXED: tvis.item.iSelectedImage=tvis.item.iImage=0; break;
5931 case DRIVE_CDROM: tvis.item.iSelectedImage=tvis.item.iImage=1; break;
5932 case DRIVE_REMOTE: tvis.item.iSelectedImage=tvis.item.iImage=2; break;
5933 case DRIVE_REMOVABLE: tvis.item.iSelectedImage=tvis.item.iImage=3; break;
5934 case DRIVE_RAMDISK: tvis.item.iSelectedImage=tvis.item.iImage=4; break;
5935 default: tvis.item.iSelectedImage=tvis.item.iImage=5; break;
5936 }
5937
5938 tvis.item.pszText=driveName;
5939
5940 HTREEITEM hTwee=TreeView_InsertItem(dirList,&tvis);
5941
5942 if(result==ERROR_SUCCESS && !_tcsnicmp(drive, driveName, 2))
5943 hTreeDrive=hTwee;
5944
5945 TCHAR temp[10];
5946 lstrcpy(temp, driveName);
5947 lstrcat(temp, TEXT("\\*"));
5948 bool subdir=false;
5949
5950 if(driveType==DRIVE_REMOVABLE || driveType == DRIVE_CDROM || driveType == DRIVE_UNKNOWN)
5951 {
5952 TV_INSERTSTRUCT tvis;
5953 memset(&tvis, 0, sizeof(TV_INSERTSTRUCT));
5954 tvis.hParent=hTwee;
5955 tvis.hInsertAfter=TVI_SORT;
5956 TreeView_InsertItem(dirList,&tvis);
5957
5958 }
5959 else
5960 {
5961 WIN32_FIND_DATA wfd2;
5962 memset(&wfd2, 0, sizeof(WIN32_FIND_DATA));
5963 HANDLE hFind2=FindFirstFile(temp,&wfd2);
5964 do
5965 {
5966 if(wfd2.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
5967 {
5968 if(lstrcmp(wfd2.cFileName, TEXT("."))&&lstrcmp(wfd2.cFileName, TEXT("..")))
5969 {
5970 subdir=true;
5971 }
5972 }
5973 }
5974 while(FindNextFile(hFind2, &wfd2)&&!subdir);
5975
5976 if(subdir)
5977 {
5978 TV_INSERTSTRUCT tvis;
5979 memset(&tvis, 0, sizeof(TV_INSERTSTRUCT));
5980 tvis.hParent=hTwee;
5981 tvis.hInsertAfter=TVI_SORT;
5982 TreeView_InsertItem(dirList,&tvis);
5983 }
5984 FindClose(hFind2);
5985 }
5986 }
5987 }
5988
5989 SendDlgItemMessage(hDlg, IDC_ROM_DIR, WM_SETREDRAW, FALSE, 0);
5990
5991 if(result==ERROR_SUCCESS)
5992 {
5993 HTREEITEM hTreePrev;//,hTreeRoot;
5994 // hTreePrev=TreeView_GetRoot(dirList);
5995 // hTreeRoot=hTreeDrive;
5996 hTreePrev=hTreeDrive;
5997 HTREEITEM hTemp=hTreePrev;
5998 TCHAR* temp=buffer;
5999 TCHAR* temp2, * temp3;
6000
6001 do
6002 {
6003 temp2=_tcsstr(temp, TEXT("\\"));
6004 temp3=_tcsstr(temp, TEXT("/"));
6005 if(temp3 && temp3 < temp2)
6006 temp2 = temp3;
6007
6008 TVITEM tvi;
6009 memset(&tvi, 0, sizeof(TVITEM));
6010 tvi.mask=TVIF_TEXT;
6011 tvi.pszText=blah;
6012 tvi.cchTextMax=MAX_PATH;
6013 blah[0]=TEXT('\0');
6014
6015 if(temp2)
6016 *temp2=TEXT('\0');
6017
6018 tvi.hItem=hTemp;
6019 TreeView_GetItem(dirList, &tvi);
6020
6021 if(_tcsicmp(blah, temp) != 0)
6022 {
6023 do
6024 {
6025 tvi.mask=TVIF_TEXT;
6026 tvi.pszText=blah;
6027 tvi.cchTextMax=MAX_PATH;
6028 hTemp=TreeView_GetNextSibling(dirList, hTemp);
6029 tvi.hItem=hTemp;
6030 TreeView_GetItem(dirList, &tvi);
6031 }
6032 while((hTemp != NULL) && (_tcsicmp(blah, temp) != 0));
6033
6034 if(hTemp!=NULL)
6035 {
6036 hTreePrev=hTemp;
6037
6038 TreeView_SelectItem(dirList, hTreePrev);
6039 TreeView_EnsureVisible(dirList, hTreePrev);
6040 if(temp2)
6041 TreeView_Expand(dirList, hTreePrev, TVE_EXPAND);
6042
6043 hTemp=TreeView_GetChild(dirList, hTreePrev);
6044 }
6045 }
6046 else
6047 {
6048 TreeView_SelectItem(dirList, hTemp);
6049 TreeView_EnsureVisible(dirList, hTemp);
6050 if(temp2)
6051 TreeView_Expand(dirList, hTemp, TVE_EXPAND);
6052
6053 hTemp=TreeView_GetChild(dirList, hTemp);
6054 }
6055 if(temp2)
6056 temp=temp2+1;
6057 else
6058 temp=NULL;
6059 }
6060 while(temp);
6061
6062 if(Memory.ROMFilename[0]!='\0')
6063 {
6064 LVFINDINFO lvfi;
6065 memset(&lvfi, 0, sizeof(LVFINDINFO));
6066 TCHAR filename[_MAX_PATH];
6067 TCHAR *tmp, *tmp2;
6068 lstrcpy(filename,_tFromChar(Memory.ROMFilename));
6069 tmp = filename;
6070 while(tmp2=_tcsstr(tmp, TEXT("\\")))
6071 tmp=tmp2+sizeof(TCHAR);
6072
6073 lvfi.flags=LVFI_STRING;
6074 lvfi.psz=tmp2;
6075
6076 int idx=ListView_FindItem(romList, -1, &lvfi);
6077 ListView_SetSelectionMark(romList, idx);
6078 ListView_SetItemState(romList, idx, LVIS_SELECTED|LVIS_FOCUSED,LVIS_FOCUSED|LVIS_SELECTED);
6079 ListView_EnsureVisible(romList, idx, FALSE);
6080
6081 }
6082 SendDlgItemMessage(hDlg, IDC_ROM_DIR, WM_SETREDRAW, TRUE, 0);
6083 }
6084 initDone = true;
6085
6086 ListView_EnsureVisible (romList, (int)SendMessage(romList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED), FALSE);
6087
6088 // start up the WM_TIMER event
6089 nextInvalidatedROM = rdl;
6090 nextInvalidatedROMCounter = 0;
6091 SetTimer(hDlg,42,600,NULL);
6092
6093 return true; //true sets the keyboard focus, in case we need this elsewhere
6094 }
6095 case WM_TIMER:
6096 {
6097 if(!initDone || !nextInvalidatedROM || !rdl)
6098 return false;
6099
6100 // see if current selection needs filling in, and skip to that if so
6101 int selected = (int)SendMessage(romList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED);
6102 if(selected>=0)
6103 {
6104 RomDataList* curr=rdl;
6105 for(int i=0;i<selected;i++)
6106 if(curr) curr=curr->next;
6107 if(curr && !curr->rname)
6108 {
6109 nextInvalidatedROM = curr;
6110 nextInvalidatedROMCounter = selected;
6111 }
6112 }
6113
6114 LVHITTESTINFO lvhi;
6115 lvhi.flags = LVHT_ONITEM;
6116 lvhi.iItem = 0;
6117 lvhi.iSubItem = 0;
6118 lvhi.pt.x = 0;
6119 lvhi.pt.y = 0;
6120 ListView_HitTest(romList, &lvhi);
6121 int firstVisibleItem = lvhi.iItem+1;
6122 int lastVisibleItem = firstVisibleItem+20;
6123
6124 // skip up to 100 things that don't need updating
6125 bool enteredValid = false;
6126 if(nextInvalidatedROM->rname || nextInvalidatedROMCounter<firstVisibleItem || nextInvalidatedROMCounter>lastVisibleItem)
6127 for(int i = 0 ; i < 100 ; i++)
6128 if(nextInvalidatedROM->rname || (!enteredValid && (nextInvalidatedROMCounter<firstVisibleItem || nextInvalidatedROMCounter>lastVisibleItem)))
6129 {
6130 if(!enteredValid && nextInvalidatedROMCounter>=firstVisibleItem && nextInvalidatedROMCounter<lastVisibleItem)
6131 enteredValid = true;
6132 nextInvalidatedROM = nextInvalidatedROM->next;
6133 if(nextInvalidatedROM)
6134 nextInvalidatedROMCounter++;
6135 else
6136 {
6137 nextInvalidatedROM = rdl;
6138 nextInvalidatedROMCounter = 0;
6139 }
6140 }
6141
6142 // update 1 item, if it needs updating
6143 if(!nextInvalidatedROM->rname)
6144 {
6145 TCHAR path[MAX_PATH];
6146 TCHAR buffer[32];
6147 TCHAR buffer2[32];
6148 GetPathFromTree(hDlg, IDC_ROM_DIR, path, TreeView_GetSelection(dirList));
6149 lstrcat(path, TEXT("\\"));
6150 lstrcat(path, nextInvalidatedROM->fname);
6151 rominfo(path, buffer, buffer2);
6152 nextInvalidatedROM->rname=new TCHAR[lstrlen(buffer)+1];
6153 lstrcpy(nextInvalidatedROM->rname, buffer);
6154 nextInvalidatedROM->rmbits=new TCHAR[lstrlen(buffer2)+1];
6155 lstrcpy(nextInvalidatedROM->rmbits, buffer2);
6156
6157 ListView_RedrawItems(romList,nextInvalidatedROMCounter,nextInvalidatedROMCounter);
6158 }
6159
6160 // next timer
6161 nextInvalidatedROM = nextInvalidatedROM->next;
6162 if(nextInvalidatedROM)
6163 nextInvalidatedROMCounter++;
6164 else
6165 {
6166 nextInvalidatedROM = rdl;
6167 nextInvalidatedROMCounter = 0;
6168 }
6169 SetTimer(hDlg,42,600,NULL);
6170 return true;
6171 }
6172 case WM_PAINT:
6173 {
6174 PAINTSTRUCT ps;
6175 BeginPaint (hDlg, &ps);
6176
6177 EndPaint (hDlg, &ps);
6178 }
6179 return true;
6180
6181 case WM_COMMAND:
6182 {
6183 switch(LOWORD(wParam))
6184 {
6185 case IDOK:
6186 {
6187 LVITEM lvi;
6188 memset(&lvi, 0, sizeof(LVITEM));
6189 //get selections
6190 int list_index = selectionMarkOverride == -1 ? ListView_GetSelectionMark(romList) : selectionMarkOverride;
6191 if(list_index!=-1 && (int)SendMessage(romList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED)!=-1)
6192 {
6193 rv=1;
6194 TCHAR temp[MAX_PATH];
6195 temp[0]='\0';
6196 lvi.iItem=list_index;
6197 lvi.mask=LVIF_TEXT;
6198 lvi.pszText=filename;
6199 lvi.cchTextMax=MAX_PATH;
6200 ListView_GetItem(romList, &lvi);
6201
6202 lstrcpy(temp, filename);
6203
6204 HTREEITEM hTreeTemp=TreeView_GetSelection(dirList);
6205 TVITEM tv;
6206 memset(&tv, 0, sizeof(TVITEM));
6207
6208 tv.mask=TVIF_HANDLE|TVIF_TEXT;
6209 tv.hItem=hTreeTemp;
6210 tv.pszText=temp;
6211 tv.cchTextMax =MAX_PATH;
6212 TreeView_GetItem(dirList, &tv);
6213 _stprintf(temp, TEXT("%s\\%s"), temp, filename);
6214
6215 lstrcpy(filename, temp);
6216
6217 while(TreeView_GetParent(dirList, hTreeTemp)!=NULL)
6218 {
6219 temp[0]=TEXT('\0');
6220 hTreeTemp=TreeView_GetParent(dirList, hTreeTemp);
6221 tv.mask=TVIF_HANDLE|TVIF_TEXT;
6222 tv.hItem=hTreeTemp;
6223 tv.pszText=temp;
6224 tv.cchTextMax =MAX_PATH;
6225 TreeView_GetItem(dirList, &tv);
6226 _stprintf(temp, TEXT("%s\\%s"),temp, filename);
6227 lstrcpy(filename, temp);
6228 }
6229
6230 int iTemp=SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_GETCURSEL,0,0);
6231
6232 Settings.ForceHiROM=Settings.ForceLoROM=FALSE;
6233 if(iTemp==1)
6234 Settings.ForceHiROM=TRUE;
6235 else if(iTemp==2)
6236 Settings.ForceLoROM=TRUE;
6237
6238 iTemp=SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_GETCURSEL,0,0);
6239
6240 Settings.ForceNotInterleaved=Settings.ForceInterleaved=Settings.ForceInterleaved2=Settings.ForceInterleaveGD24=FALSE;
6241 if(iTemp==1)
6242 Settings.ForceNotInterleaved=TRUE;
6243 else if(iTemp==2)
6244 Settings.ForceInterleaved=TRUE;
6245 else if(iTemp==3)
6246 Settings.ForceInterleaved2=TRUE;
6247 else if(iTemp==4)
6248 Settings.ForceInterleaveGD24=TRUE;
6249
6250 iTemp=SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_GETCURSEL,0,0);
6251
6252 Settings.ForceNTSC=Settings.ForcePAL=FALSE;
6253 if(iTemp==1)
6254 Settings.ForcePAL=TRUE;
6255 else if(iTemp==2)
6256 Settings.ForceNTSC=TRUE;
6257
6258
6259 iTemp=SendDlgItemMessage(hDlg, IDC_HEADER,CB_GETCURSEL,0,0);
6260
6261 Settings.ForceNoHeader=Settings.ForceHeader=FALSE;
6262 if(iTemp==1)
6263 Settings.ForceHeader=TRUE;
6264 else if(iTemp==2)
6265 Settings.ForceNoHeader=TRUE;
6266
6267 lstrcpy(temp, filename);
6268 int i=lstrlen(temp);
6269 while(temp[i]!=TEXT('\\') && temp[i]!=TEXT('/'))
6270 {
6271 temp[i]=TEXT('\0');
6272 i--;
6273 }
6274 temp[i]=TEXT('\0');
6275
6276 if(!GUI.LockDirectories)
6277 absToRel(GUI.RomDir, temp, S9xGetDirectoryT(DEFAULT_DIR));
6278 }
6279 else
6280 {
6281 return false;
6282 }
6283 }
6284 case IDCANCEL:
6285 EndDialog(hDlg, rv);
6286 ClearCacheList(rdl);
6287 rdl=NULL;
6288 DestroyWindow(hSplit);
6289 UnregisterClass(TEXT("S9xSplitter"), g_hInst);
6290 TreeView_DeleteAllItems(dirList);
6291 ListView_DeleteAllItems(romList);
6292 return true;
6293 break;
6294 default: return false; break;
6295 }
6296 }
6297 case WM_NOTIFY:
6298 {
6299 if(lParam == 0)
6300 return false;
6301 NMHDR* pNmh=(NMHDR*)lParam;
6302 static int foundItemOverride = -1;
6303 switch(pNmh->idFrom)
6304 {
6305 case IDC_ROMLIST:
6306 {
6307 switch(pNmh->code)
6308 {
6309 // allow typing in a ROM filename (or part of it) to jump to it
6310 // necessary to implement ourselves because Windows doesn't provide
6311 // this functionality for virtual (owner data) lists such as this
6312 case LVN_ODFINDITEM:
6313 {
6314 LRESULT pResult;
6315
6316 // pNMHDR has information about the item we should find
6317 // In pResult we should save which item that should be selected
6318 NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)lParam;
6319
6320 /* pFindInfo->iStart is from which item we should search.
6321 We search to bottom, and then restart at top and will stop
6322 at pFindInfo->iStart, unless we find an item that match
6323 */
6324
6325 // Set the default return value to -1
6326 // That means we didn't find any match.
6327 pResult = -1;
6328
6329 //Is search NOT based on string?
6330 if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 )
6331 {
6332 //This will probably never happend...
6333 return pResult;
6334 }
6335
6336 //This is the string we search for
6337 LPCTSTR searchstr = pFindInfo->lvfi.psz;
6338
6339 int startPos = pFindInfo->iStart;
6340 //Is startPos outside the list (happens if last item is selected)
6341 if(startPos >= ListView_GetItemCount(romList))
6342 startPos = 0;
6343
6344 if(rdl==NULL)
6345 return pResult;
6346
6347 RomDataList* curr=rdl;
6348 for(int i=0;i<startPos;i++)
6349 curr=curr->next;
6350
6351 int currentPos=startPos;
6352 pResult=startPos;
6353
6354 bool looped = false;
6355
6356 // perform search
6357 do
6358 {
6359 // does this word begin with all characters in searchstr?
6360 if( _tcsnicmp(curr->fname, searchstr, lstrlen(searchstr)) == 0)
6361 {
6362 // select this item and stop search
6363 pResult = currentPos;
6364 break;
6365 }
6366 else if( _tcsnicmp(curr->fname, searchstr, lstrlen(searchstr)) > 0)
6367 {
6368 if(looped)
6369 {
6370 pResult = currentPos;
6371 break;
6372 }
6373
6374 // optimization: the items are ordered alphabetically, so go back to the top since we know it can't be anything further down
6375 curr=rdl;
6376 currentPos = 0;
6377 looped = true;
6378 continue;
6379 }
6380
6381 //Go to next item
6382 currentPos++;
6383 curr=curr->next;
6384
6385 //Need to restart at top?
6386 if(currentPos >= ListView_GetItemCount(romList))
6387 {
6388 currentPos = 0;
6389 curr = rdl;
6390 }
6391
6392 //Stop if back to start
6393 }while(currentPos != startPos);
6394
6395 foundItemOverride = pResult;
6396
6397 // in case previously-selected item is 0
6398 ListView_SetItemState (romList, 1, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
6399
6400 return pResult; // HACK: for some reason this selects the first item instead of what it's returning... current workaround is to manually re-select this return value upon the next changed event
6401 }
6402 break;
6403 case LVN_ITEMCHANGED:
6404 {
6405 // hack - see note directly above
6406 LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam;
6407 if(lpnmlv->uNewState & (LVIS_SELECTED|LVIS_FOCUSED))
6408 {
6409 if(foundItemOverride != -1 && lpnmlv->iItem == 0)
6410 {
6411 ListView_SetItemState (romList, foundItemOverride, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
6412 ListView_EnsureVisible (romList, foundItemOverride, FALSE);
6413 selectionMarkOverride = foundItemOverride;
6414 foundItemOverride = -1;
6415 }
6416 else
6417 {
6418 selectionMarkOverride = lpnmlv->iItem;
6419 }
6420 }
6421 }
6422 break;
6423 case LVN_GETDISPINFO:
6424 {
6425 if(!initDone)
6426 return false;
6427 int i, j;
6428 RomDataList* curr=rdl;
6429 if(rdl==NULL)
6430 return false;
6431 NMLVDISPINFO * nmlvdi=(NMLVDISPINFO*)lParam;
6432 j=nmlvdi->item.iItem;
6433 for(i=0;i<j;i++)
6434 if(curr) curr=curr->next;
6435 if(curr==NULL)
6436 return false;
6437 //if(curr->rname==NULL && j==(int)SendMessage(romList, LVM_GETNEXTITEM, -1, LVNI_SELECTED))
6438 //{
6439 // TCHAR path[MAX_PATH];
6440 // TCHAR buffer[32];
6441 // TCHAR buffer2[32];
6442 // GetPathFromTree(hDlg, IDC_ROM_DIR, path, TreeView_GetSelection(dirList));
6443 // strcat(path, "\\");
6444 // strcat(path, curr->fname);
6445 // rominfo(path, buffer, buffer2);
6446 // curr->rname=new char[strlen(buffer)+1];
6447 // strcpy(curr->rname, buffer);
6448 // curr->rmbits=new char[strlen(buffer2)+1];
6449 // strcpy(curr->rmbits, buffer2);
6450 //}
6451
6452 if(nmlvdi->item.iSubItem==0)
6453 {
6454 nmlvdi->item.pszText=curr->fname?curr->fname:TEXT("");
6455 nmlvdi->item.cchTextMax=MAX_PATH;
6456 }
6457 if(nmlvdi->item.iSubItem==1)
6458 {
6459 nmlvdi->item.pszText=curr->rname?curr->rname:TEXT("");
6460 nmlvdi->item.cchTextMax=24;
6461 }
6462
6463 if(nmlvdi->item.iSubItem==2)
6464 {
6465 nmlvdi->item.pszText=curr->rmbits?curr->rmbits:TEXT("");
6466 nmlvdi->item.cchTextMax=11;
6467 }
6468 // nmlvdi->item.mask=LVIF_TEXT; // This is bad as wine relies on this to not change.
6469 }
6470 break;
6471 case NM_DBLCLK:
6472 {
6473 PostMessage(hDlg, WM_COMMAND, (WPARAM)(IDOK),(LPARAM)(NULL));
6474 }
6475 default:break;
6476 }
6477 }
6478 break;
6479 case IDC_ROM_DIR:
6480 {
6481 switch(pNmh->code)
6482 {
6483 case TVN_ITEMEXPANDING:
6484 {
6485 TCHAR selected[MAX_PATH];
6486 NMTREEVIEW* nmTv=(NMTREEVIEW*)lParam;
6487
6488 while(TreeView_GetChild(dirList,nmTv->itemNew.hItem))
6489 {
6490 TreeView_DeleteItem(dirList, TreeView_GetChild(dirList,nmTv->itemNew.hItem));
6491 }
6492
6493 if(nmTv->action&TVE_EXPAND)
6494 {
6495
6496 GetPathFromTree(hDlg, IDC_ROM_DIR, selected,nmTv->itemNew.hItem);
6497 ExpandDir(selected, nmTv->itemNew.hItem, hDlg);
6498 }
6499 else
6500 {
6501 TVITEM tv;
6502 memset(&tv, 0, sizeof(TVITEM));
6503 HTREEITEM hTreeTemp=nmTv->itemNew.hItem;
6504
6505 if(tv.iImage==6)
6506 {
6507 tv.mask=TVIF_HANDLE|TVIF_IMAGE;
6508 tv.hItem=hTreeTemp;
6509 tv.iImage=7;
6510 TreeView_SetItem(dirList,&tv);
6511 }
6512
6513
6514 TV_INSERTSTRUCT tvis;
6515 memset(&tvis, 0, sizeof(TV_INSERTSTRUCT));
6516 tvis.hParent=nmTv->itemNew.hItem;
6517 tvis.hInsertAfter=TVI_SORT;
6518 TreeView_InsertItem(dirList,&tvis);
6519
6520 }
6521 }
6522 return false;
6523 break;
6524 case TVN_SELCHANGED:
6525 {
6526 ListFilesFromFolder(hDlg, &rdl);
6527 nextInvalidatedROM = rdl;
6528 nextInvalidatedROMCounter = 0;
6529 }
6530 default:return false;
6531 }
6532 }
6533 default:return false;
6534 }
6535 }
6536 default:return false;
6537 }
6538 }
DlgChildSplitProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)6539 LRESULT CALLBACK DlgChildSplitProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
6540 {
6541 static bool PaintSpecial;
6542 static short drag_x;
6543 short temp_x;
6544 switch(msg)
6545 {
6546 case WM_CREATE:
6547 return 0;
6548 case WM_SIZE:
6549 return 0;
6550 case WM_PAINT:
6551 PAINTSTRUCT ps;
6552 GetUpdateRect (hWnd, &ps.rcPaint, true);
6553 ps.hdc=GetDC(hWnd);
6554 ps.fErase=true;
6555 BeginPaint(hWnd, &ps);
6556 EndPaint(hWnd, &ps);
6557 ReleaseDC(hWnd, ps.hdc);
6558 return 0;
6559 case WM_LBUTTONDOWN:
6560 PaintSpecial=true;
6561 drag_x=GET_X_LPARAM(lParam);
6562 SetCapture(hWnd);
6563 return 0;
6564 case WM_LBUTTONUP:
6565 PaintSpecial=false;
6566 temp_x=(GET_X_LPARAM(lParam)-drag_x);
6567 HWND hDlg,hTree,hList;
6568 RECT treeRect;
6569 RECT listRect;
6570 hDlg=GetParent(hWnd);
6571 hTree=GetDlgItem(hDlg, IDC_ROM_DIR);
6572 hList=GetDlgItem(hDlg, IDC_ROMLIST);
6573 GetWindowRect(hTree, &treeRect);
6574
6575 POINT p;
6576 p.x=temp_x+treeRect.right;
6577 p.y=treeRect.top;
6578
6579 GetWindowRect(hList, &listRect);
6580
6581 if(p.x>(listRect.right-50))
6582 {
6583 temp_x-=(short)(p.x-(listRect.right-50));
6584 p.x=listRect.right-50;
6585 }
6586
6587
6588 ScreenToClient(hDlg, &p);
6589
6590 if(p.x<50)
6591 {
6592 temp_x+=(short)(50-p.x);
6593 p.x=50;
6594 }
6595
6596
6597 MoveWindow( hWnd, p.x, p.y, listRect.left-treeRect.right, listRect.bottom-listRect.top, FALSE);
6598 MoveWindow(hList, p.x+(listRect.left-treeRect.right), p.y,listRect.right-listRect.left-temp_x, listRect.bottom-listRect.top, TRUE);
6599 p.x=treeRect.left;
6600 p.y=treeRect.top;
6601 ScreenToClient(hDlg, &p);
6602 MoveWindow(hTree, p.x, p.y,treeRect.right-treeRect.left+temp_x,treeRect.bottom-treeRect.top, true);
6603 InvalidateRect(hWnd,NULL, true);
6604 ReleaseCapture();
6605 return 0;
6606 case WM_MOUSEMOVE:
6607 if (wParam & MK_LBUTTON)
6608 {
6609 //move paint location
6610 PaintSpecial=true;
6611 temp_x=(GET_X_LPARAM(lParam)-drag_x);
6612 hDlg=GetParent(hWnd);
6613 hTree=GetDlgItem(hDlg, IDC_ROM_DIR);
6614 hList=GetDlgItem(hDlg, IDC_ROMLIST);
6615 GetWindowRect(hTree, &treeRect);
6616
6617 p.x=temp_x+treeRect.right;
6618
6619 p.y=treeRect.top;
6620 GetWindowRect(hList, &listRect);
6621
6622 if(p.x>(listRect.right-50))
6623 {
6624 temp_x-=(short)(p.x-(listRect.right-50));
6625 p.x=listRect.right-50;
6626 }
6627
6628
6629 ScreenToClient(hDlg, &p);
6630
6631 if(p.x<50)
6632 {
6633 temp_x+=(short)(50-p.x);
6634 p.x=50;
6635 }
6636
6637 MoveWindow(hWnd, p.x, p.y, listRect.left-treeRect.right, listRect.bottom-listRect.top, FALSE);
6638 MoveWindow(hList, p.x+(listRect.left-treeRect.right), p.y,listRect.right-listRect.left-temp_x, listRect.bottom-listRect.top, TRUE);
6639 p.x=treeRect.left;
6640 p.y=treeRect.top;
6641 ScreenToClient(hDlg, &p);
6642 MoveWindow(hTree, p.x, p.y,treeRect.right-treeRect.left+temp_x,treeRect.bottom-treeRect.top, true);
6643 InvalidateRect(hWnd,NULL, true);
6644 }
6645 return 0;
6646 case WM_CAPTURECHANGED:
6647 PaintSpecial=false;
6648 ReleaseCapture();
6649 return 0;
6650 case WM_DESTROY:
6651 return 0;
6652 default:return DefWindowProc(hWnd, msg, wParam, lParam);
6653 }
6654 }
6655
6656
6657
6658
6659 #ifdef NETPLAY_SUPPORT
DlgNetConnect(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)6660 INT_PTR CALLBACK DlgNetConnect(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
6661 {
6662 // HKEY hKey;
6663 TCHAR defPort[5];
6664 TCHAR portTemp[5];
6665 TCHAR temp[100];
6666 // char temp2[5];
6667 static TCHAR* hostname;
6668 // unsigned long cbData;
6669 // static int i;
6670 if(Settings.Port==0)
6671 {
6672 _itot(1996,defPort,10);
6673 }
6674 else
6675 {
6676 _itot(Settings.Port,defPort,10);
6677 }
6678
6679 WORD chkLength;
6680 // if(RegCreateKeyEx(HKEY_CURRENT_USER,MY_REG_KEY "\\1.x\\NetPlayServerHistory",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS, NULL, &hKey,NULL) == ERROR_SUCCESS){}
6681
6682 switch (msg)
6683 {
6684 case WM_INITDIALOG:
6685 WinRefreshDisplay();
6686 SetWindowText(hDlg,NPCON_TITLE);
6687 SetDlgItemText(hDlg,IDC_LABEL_SERVERADDY,NPCON_LABEL_SERVERADDY);
6688 SetDlgItemText(hDlg,IDC_LABEL_PORTNUM,NPCON_LABEL_PORTNUM);
6689 SetDlgItemText(hDlg,IDC_CLEARHISTORY, NPCON_CLEARHISTORY);
6690 SetDlgItemText(hDlg,IDOK,BUTTON_OK);
6691 SetDlgItemText(hDlg,IDCANCEL,BUTTON_CANCEL);
6692 hostname = (TCHAR *)lParam;
6693 {
6694 for(int i=0; i<MAX_RECENT_HOSTS_LIST_SIZE && *GUI.RecentHostNames[i]; i++)
6695 SendDlgItemMessage(hDlg, IDC_HOSTNAME, CB_INSERTSTRING,i,(LPARAM)GUI.RecentHostNames[i]);
6696 }
6697
6698 SendDlgItemMessage(hDlg, IDC_PORTNUMBER, WM_SETTEXT, 0, (LPARAM)defPort);
6699
6700 SendDlgItemMessage(hDlg, IDC_HOSTNAME, WM_SETTEXT, 0, (LPARAM)NPCON_ENTERHOST);
6701
6702 return TRUE;
6703
6704 case WM_COMMAND:
6705 switch(LOWORD(wParam))
6706 {
6707 case IDC_CLEARHISTORY:
6708 {
6709 {
6710 SendDlgItemMessage(hDlg,IDC_HOSTNAME,CB_RESETCONTENT,0,0);
6711 SendDlgItemMessage(hDlg,IDC_HOSTNAME,CB_INSERTSTRING,0,(LPARAM)GUI.RecentHostNames[0]);
6712 for(int i=1; i<MAX_RECENT_HOSTS_LIST_SIZE; i++)
6713 *GUI.RecentHostNames[i] = TEXT('\0');
6714 }
6715 break;
6716 }
6717 case IDOK:
6718 {
6719
6720 chkLength = (WORD) SendDlgItemMessage(hDlg,IDC_PORTNUMBER,EM_LINELENGTH,0,0);
6721 *((LPWORD)portTemp) = chkLength;
6722 SendDlgItemMessage(hDlg,IDC_PORTNUMBER,EM_GETLINE,0,(LPARAM)(LPCTSTR)portTemp);
6723
6724 if(_ttoi(portTemp)>65535||_ttoi(portTemp)<1024)
6725 {
6726 MessageBox(hDlg,TEXT("Port Number needs to be between 1024 and 65535"),TEXT("Error"),MB_OK);
6727 break;
6728 }
6729 else
6730 {
6731 Settings.Port = _ttoi(portTemp);
6732 }
6733 //chkLength = (WORD) SendDlgItemMessage(hDlg,IDC_HOSTNAME,EM_LINELENGTH,0,0);
6734 //if(chkLength > 0)
6735 //{
6736 //SendDlgItemMessage(hDlg,IDC_HOSTNAME,EM_GETLINE,0,(LPARAM)hostname);
6737 SendDlgItemMessage(hDlg,IDC_HOSTNAME,WM_GETTEXT,100,(LPARAM)temp);
6738 if(!lstrcmp(temp, NPCON_ENTERHOST))
6739 {
6740 MessageBox(hDlg,NPCON_PLEASE_ENTERHOST,TEXT("Error"),MB_OK);
6741 break;
6742 }
6743 lstrcpy(hostname,temp);
6744 //MessageBox(hDlg,temp,"hola",MB_OK);
6745
6746 // save hostname in recent list
6747 {
6748 int i;
6749 for(i=0; i<MAX_RECENT_HOSTS_LIST_SIZE; i++)
6750 {
6751 if(!*GUI.RecentHostNames[i])
6752 {
6753 lstrcpy(GUI.RecentHostNames[i], hostname);
6754 break;
6755 }
6756 else if(!_tcsicmp(GUI.RecentHostNames[i], hostname))
6757 break;
6758 }
6759 if(i == MAX_RECENT_HOSTS_LIST_SIZE)
6760 lstrcpy(GUI.RecentHostNames[1+(rand()%(MAX_RECENT_HOSTS_LIST_SIZE-1))], hostname);
6761 }
6762
6763 unsigned long len;
6764 len = lstrlen(temp);
6765 if(len > 0)
6766 {
6767 EndDialog(hDlg,1);
6768 return TRUE;
6769 }
6770 else
6771 {
6772 EndDialog(hDlg,0);
6773 return TRUE;
6774 }
6775
6776 break;
6777 //}
6778 }
6779 case IDCANCEL:
6780 {
6781 EndDialog(hDlg, 0);
6782 return TRUE;
6783 }
6784 default:break;
6785 }
6786 }
6787 return FALSE;
6788 }
6789 #endif
SetInfoDlgColor(unsigned char r,unsigned char g,unsigned char b)6790 void SetInfoDlgColor(unsigned char r, unsigned char g, unsigned char b)
6791 {
6792 GUI.InfoColor=RGB(r,g,b);
6793 }
6794
6795 #define SNES9XWPROGID TEXT("Snes9x.Win32")
6796 #define SNES9XWPROGIDDESC TEXT("Snes9x ROM")
6797 #define SNES9XWAPPDESC TEXT("Snes9x is a portable, freeware Super Nintendo Entertainment System (SNES) emulator.")
6798 #define SNES9XWAPPNAME TEXT("Snes9x")
6799 #define REGCREATEKEY(key,subkey) \
6800 if(regResult=RegCreateKeyEx(key, subkey,\
6801 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE , NULL , &hKey, NULL ) != ERROR_SUCCESS){\
6802 return false;\
6803 }
6804 #define REGSETVALUE(key,name,type,data,size) \
6805 if(regResult=RegSetValueEx(key, name, NULL, type, (BYTE *)data, size) != ERROR_SUCCESS){\
6806 RegCloseKey(hKey);\
6807 return false;\
6808 }
6809
RegisterProgid()6810 bool RegisterProgid() {
6811 LONG regResult;
6812 TCHAR szRegKey[PATH_MAX];
6813 TCHAR szExePath[PATH_MAX];
6814 TCHAR *szExeName;
6815 HKEY hKey;
6816
6817 szRegKey[PATH_MAX-1]=TEXT('\0');
6818 GetModuleFileName(NULL, szExePath, PATH_MAX);
6819 szExeName = PathFindFileName(szExePath);
6820
6821 /* Register ProgID (for use in Default Programs)
6822 */
6823 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("Software\\Classes\\%s"),SNES9XWPROGID);
6824 REGCREATEKEY(HKEY_CURRENT_USER, szRegKey)
6825 REGSETVALUE(hKey,NULL,REG_SZ,SNES9XWPROGIDDESC,(lstrlen(SNES9XWPROGIDDESC) + 1) * sizeof(TCHAR))
6826 RegCloseKey(hKey);
6827
6828 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("Software\\Classes\\%s\\DefaultIcon"),SNES9XWPROGID);
6829 REGCREATEKEY(HKEY_CURRENT_USER,szRegKey)
6830 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("%s,0"),szExeName);
6831 REGSETVALUE(hKey,NULL,REG_SZ,szRegKey,(lstrlen(szRegKey) + 1) * sizeof(TCHAR))
6832 RegCloseKey(hKey);
6833
6834 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("Software\\Classes\\%s\\shell"),SNES9XWPROGID);
6835 REGCREATEKEY(HKEY_CURRENT_USER,szRegKey)
6836 REGSETVALUE(hKey,NULL,REG_SZ,TEXT("open"),5 * sizeof(TCHAR))
6837 RegCloseKey(hKey);
6838
6839 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("Software\\Classes\\%s\\shell\\open\\command"),SNES9XWPROGID);
6840 REGCREATEKEY(HKEY_CURRENT_USER,szRegKey)
6841 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("\"%s\" \"%%L\""),szExePath);
6842 REGSETVALUE(hKey,NULL,REG_SZ,szRegKey,(lstrlen(szRegKey) + 1) * sizeof(TCHAR))
6843 RegCloseKey(hKey);
6844
6845 /* Register Capabilities (for Default Programs)
6846 */
6847 REGCREATEKEY(HKEY_CURRENT_USER,TEXT("SOFTWARE\\Snes9x\\Capabilities"))
6848 REGSETVALUE(hKey,TEXT("ApplicationDescription"),REG_SZ,SNES9XWAPPDESC,(lstrlen(SNES9XWAPPDESC) + 1) * sizeof(TCHAR))
6849 REGSETVALUE(hKey,TEXT("ApplicationName"),REG_SZ,SNES9XWAPPNAME,(lstrlen(SNES9XWAPPNAME) + 1) * sizeof(TCHAR))
6850 RegCloseKey(hKey);
6851
6852 REGCREATEKEY(HKEY_CURRENT_USER,TEXT("SOFTWARE\\RegisteredApplications"))
6853 REGSETVALUE(hKey,TEXT("Snes9x"),REG_SZ,TEXT("SOFTWARE\\Snes9x\\Capabilities"),(lstrlen(TEXT("SOFTWARE\\Snes9x\\Capabilities")) + 1) * sizeof(TCHAR))
6854 RegCloseKey(hKey);
6855
6856 /* Register under Applications for use in OpenWithList
6857 */
6858 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("Software\\Classes\\Applications\\%s"),szExeName);
6859 REGCREATEKEY(HKEY_CURRENT_USER,szRegKey)
6860 RegCloseKey(hKey);
6861
6862 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("Software\\Classes\\Applications\\%s\\shell\\open\\command"),szExeName);
6863 REGCREATEKEY(HKEY_CURRENT_USER,szRegKey)
6864 _stprintf_s(szRegKey,PATH_MAX-1,TEXT("\"%s\" \"%%L\""),szExePath);
6865 REGSETVALUE(hKey,NULL,REG_SZ,szRegKey,(lstrlen(szRegKey) + 1) * sizeof(TCHAR))
6866 RegCloseKey(hKey);
6867
6868 return true;
6869 }
6870
RegisterExt(TCHAR * ext)6871 bool RegisterExt(TCHAR *ext) {
6872 LONG regResult;
6873 TCHAR szRegKey[PATH_MAX];
6874 TCHAR szExePath[PATH_MAX];
6875 TCHAR *szExeName;
6876 HKEY hKey;
6877
6878 if(!ext || ext==TEXT('\0'))
6879 return false;
6880
6881 GetModuleFileName(NULL, szExePath, PATH_MAX);
6882 szExeName = PathFindFileName(szExePath);
6883
6884 /* Register .ext as S9x capability (for Default Programs)
6885 */
6886 REGCREATEKEY(HKEY_CURRENT_USER,TEXT("SOFTWARE\\Snes9x\\Capabilities\\FileAssociations"))
6887 _stprintf_s(szRegKey,PATH_MAX-1,TEXT(".%s"),ext);
6888 REGSETVALUE(hKey,szRegKey,REG_SZ,SNES9XWPROGID,(lstrlen(SNES9XWPROGID) + 1) * sizeof(TCHAR))
6889 RegCloseKey(hKey);
6890
6891 /* Register in OpenWithList - will not be taken as default icon, necessary for Jump List
6892 */
6893 _stprintf(szRegKey,TEXT("Software\\Classes\\.%s\\OpenWithList\\%s"),ext,szExeName);
6894 REGCREATEKEY(HKEY_CURRENT_USER,szRegKey)
6895 RegCloseKey(hKey);
6896
6897 return true;
6898 }
6899
RegisterExts(void)6900 void RegisterExts(void) {
6901 ExtList *curr=valid_ext;
6902 while(curr->next!=NULL) {
6903 RegisterExt(curr->extension);
6904 curr=curr->next;
6905 }
6906 }
6907
ClearExts(void)6908 void ClearExts(void)
6909 {
6910 ExtList* temp;
6911 ExtList* curr=valid_ext;
6912 while(curr!=NULL)
6913 {
6914 temp=curr->next;
6915 if(curr->extension)
6916 delete [] curr->extension;
6917 delete curr;
6918 curr=temp;
6919 }
6920 valid_ext=NULL;
6921
6922 }
6923
LoadExts(void)6924 void LoadExts(void)
6925 {
6926 char buffer[MAX_PATH+2];
6927 if(valid_ext!=NULL)
6928 {
6929 ClearExts();
6930 }
6931 ExtList* curr;
6932 valid_ext=new ExtList;
6933 curr=valid_ext;
6934 memset(curr, 0, sizeof(ExtList));
6935 ifstream in;
6936
6937 #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__))
6938 in.open("Valid.Ext", ios::in);
6939 #else
6940 in.open("Valid.Ext", ios::in|ios::nocreate);
6941 #endif
6942 if (!in.is_open())
6943 {
6944 in.clear();
6945 MakeExtFile();
6946 #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__))
6947 in.open("Valid.Ext", ios::in);
6948 #else
6949 in.open("Valid.Ext", ios::in|ios::nocreate);
6950 #endif
6951 if(!in.is_open())
6952 {
6953 MessageBox(GUI.hWnd, TEXT("Fatal Error: The File \"Valid.Ext\" could not be found or created."), TEXT("Error"), MB_ICONERROR|MB_OK);
6954 PostQuitMessage(-1);
6955 }
6956 }
6957
6958 do
6959 {
6960 buffer[0]='\0';
6961 in.getline(buffer,MAX_PATH+2);
6962 if((*buffer)!='\0')
6963 {
6964 curr->next=new ExtList;
6965 curr=curr->next;
6966 memset(curr, 0, sizeof(ExtList));
6967 if(_strnicmp(buffer+strlen(buffer)-1, "Y", 1)==0)
6968 curr->compressed=true;
6969 if(strlen(buffer)>1)
6970 {
6971 curr->extension=new TCHAR[strlen(buffer)-1];
6972 _tcsncpy(curr->extension, _tFromChar(buffer), strlen(buffer)-1);
6973 curr->extension[strlen(buffer)-1]='\0';
6974 }
6975 else curr->extension=NULL;
6976 }
6977 }
6978 while(!in.eof());
6979 in.close();
6980 curr=valid_ext;
6981 valid_ext=valid_ext->next;
6982 delete curr;
6983 RegisterProgid();
6984 RegisterExts();
6985 }
6986
MakeExtFile(void)6987 void MakeExtFile(void)
6988 {
6989 ofstream out;
6990 out.open("Valid.Ext");
6991
6992 out<<"smcN"<<endl<<"zipY"<<endl<<"gzY" <<endl<<"swcN"<<endl<<"figN"<<endl;
6993 out<<"sfcN"<<endl;
6994 out<<"jmaY";
6995 out.close();
6996 SetFileAttributes(TEXT("Valid.Ext"), FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY);
6997 };
6998 #ifdef NETPLAY_SUPPORT
DlgNPOptions(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)6999 INT_PTR CALLBACK DlgNPOptions(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
7000 {
7001 TCHAR defPort[5];
7002 WORD chkLength;
7003 if(Settings.Port==0)
7004 {
7005 _itot(1996,defPort,10);
7006 }
7007 else
7008 {
7009 _itot(Settings.Port,defPort,10);
7010 }
7011
7012 switch (msg)
7013 {
7014 case WM_INITDIALOG:
7015 WinRefreshDisplay();
7016 SetWindowText(hDlg,NPOPT_TITLE);
7017 SetDlgItemText(hDlg,IDC_LABEL_PORTNUM,NPOPT_LABEL_PORTNUM);
7018 SetDlgItemText(hDlg,IDC_LABEL_PAUSEINTERVAL,NPOPT_LABEL_PAUSEINTERVAL);
7019 SetDlgItemText(hDlg,IDC_LABEL_PAUSEINTERVAL_TEXT,NPOPT_LABEL_PAUSEINTERVAL_TEXT);
7020 SetDlgItemText(hDlg,IDC_LABEL_MAXSKIP,NPOPT_LABEL_MAXSKIP);
7021 SetDlgItemText(hDlg,IDC_SYNCBYRESET,NPOPT_SYNCBYRESET);
7022 SetDlgItemText(hDlg,IDC_SENDROM,NPOPT_SENDROM);
7023 SetDlgItemText(hDlg,IDC_ACTASSERVER,NPOPT_ACTASSERVER);
7024 SetDlgItemText(hDlg,IDC_PORTNUMBLOCK,NPOPT_PORTNUMBLOCK);
7025 SetDlgItemText(hDlg,IDC_CLIENTSETTINGSBLOCK,NPOPT_CLIENTSETTINGSBLOCK);
7026 SetDlgItemText(hDlg,IDC_SERVERSETTINGSBLOCK,NPOPT_SERVERSETTINGSBLOCK);
7027 SetDlgItemText(hDlg,IDOK,BUTTON_OK);
7028 SetDlgItemText(hDlg,IDCANCEL,BUTTON_CANCEL);
7029
7030 SendDlgItemMessage(hDlg, IDC_PORTNUMBERA, WM_SETTEXT, 0, (LPARAM)defPort);
7031 if(Settings.NetPlayServer)
7032 {
7033 SendDlgItemMessage(hDlg, IDC_ACTASSERVER, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7034 }
7035 if(NPServer.SendROMImageOnConnect)
7036 {
7037 SendDlgItemMessage(hDlg, IDC_SENDROM, BM_SETCHECK, BST_CHECKED,0);
7038 }
7039
7040 if(NPServer.SyncByReset)
7041 {
7042 SendDlgItemMessage(hDlg, IDC_SYNCBYRESET, BM_SETCHECK, BST_CHECKED,0);
7043 }
7044 SendDlgItemMessage(hDlg, IDC_MAXSPIN, UDM_SETRANGE,0,MAKELPARAM((short)60,(short)0));
7045 SendDlgItemMessage(hDlg, IDC_MAXSPIN, UDM_SETPOS,0,MAKELONG(NetPlay.MaxFrameSkip,0));
7046 SendDlgItemMessage(hDlg, IDC_PAUSESPIN, UDM_SETRANGE,0,MAKELONG(30,0));
7047 SendDlgItemMessage(hDlg, IDC_PAUSESPIN, UDM_SETPOS,0,MAKELONG(NetPlay.MaxBehindFrameCount,0));
7048 return TRUE;
7049 case WM_PAINT:
7050 {
7051 PAINTSTRUCT ps;
7052 BeginPaint (hDlg, &ps);
7053
7054 EndPaint (hDlg, &ps);
7055 }
7056 return true;
7057
7058 case WM_COMMAND:
7059 switch(LOWORD(wParam))
7060 {
7061 case IDOK:
7062 {
7063 NetPlay.MaxFrameSkip=(uint32)SendDlgItemMessage(hDlg, IDC_MAXSPIN, UDM_GETPOS,0,0);
7064 NetPlay.MaxBehindFrameCount=(uint32)SendDlgItemMessage(hDlg, IDC_PAUSESPIN, UDM_GETPOS,0,0);
7065 chkLength=(WORD)SendDlgItemMessage(hDlg,IDC_PORTNUMBERA,EM_LINELENGTH,0,0);
7066 *((LPWORD)defPort) = chkLength;
7067 SendDlgItemMessage(hDlg,IDC_PORTNUMBERA,EM_GETLINE,0,(LPARAM)defPort);
7068 if(_ttoi(defPort)<1024||_ttoi(defPort)>65535)
7069 {
7070 MessageBox(hDlg,TEXT("Port Number needs to be betweeb 1024 and 65535"),TEXT("Error"),MB_OK);
7071 break;
7072 }
7073 else
7074 {
7075 Settings.Port = _ttoi(defPort);
7076 }
7077 //MessageBox(hDlg,defPort,defPort,MB_OK);
7078 Settings.NetPlayServer = IsDlgButtonChecked(hDlg,IDC_ACTASSERVER);
7079 NPServer.SendROMImageOnConnect = IsDlgButtonChecked(hDlg,IDC_SENDROM);
7080 NPServer.SyncByReset = IsDlgButtonChecked(hDlg,IDC_SYNCBYRESET);
7081
7082 EndDialog(hDlg,0);
7083 WinSaveConfigFile();
7084 return TRUE;
7085 }
7086 case IDCANCEL:
7087 {
7088 EndDialog(hDlg,0);
7089 return TRUE;
7090 }
7091 }
7092 }
7093 return FALSE;
7094 }
7095 #endif
7096
EnableDisableKeyFields(int index,HWND hDlg)7097 void EnableDisableKeyFields (int index, HWND hDlg)
7098 {
7099 bool enableUnTurboable;
7100 if(index < 5)
7101 {
7102 SetDlgItemText(hDlg,IDC_LABEL_RIGHT,INPUTCONFIG_LABEL_RIGHT);
7103 SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UPLEFT);
7104 SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UPRIGHT);
7105 SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT);
7106 SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_UP);
7107 SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_LEFT);
7108 SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_DOWN);
7109 SetDlgItemText(hDlg,IDC_LABEL_DOWNLEFT,INPUTCONFIG_LABEL_DOWNLEFT);
7110 enableUnTurboable = true;
7111 }
7112 else
7113 {
7114 SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_MAKE_TURBO);
7115 SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_MAKE_HELD);
7116 SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_MAKE_TURBO_HELD);
7117 SetDlgItemText(hDlg,IDC_LABEL_RIGHT,INPUTCONFIG_LABEL_CLEAR_TOGGLES_AND_TURBO);
7118 SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UNUSED);
7119 SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UNUSED);
7120 SetDlgItemText(hDlg,IDC_LABEL_DOWNLEFT,INPUTCONFIG_LABEL_UNUSED);
7121 SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_UNUSED);
7122 SetDlgItemText(hDlg,IDC_UPLEFT,INPUTCONFIG_LABEL_UNUSED);
7123 SetDlgItemText(hDlg,IDC_UPRIGHT,INPUTCONFIG_LABEL_UNUSED);
7124 SetDlgItemText(hDlg,IDC_DWNLEFT,INPUTCONFIG_LABEL_UNUSED);
7125 SetDlgItemText(hDlg,IDC_DWNRIGHT,INPUTCONFIG_LABEL_UNUSED);
7126 enableUnTurboable = false;
7127 }
7128
7129 EnableWindow(GetDlgItem(hDlg,IDC_UPLEFT), enableUnTurboable);
7130 EnableWindow(GetDlgItem(hDlg,IDC_UPRIGHT), enableUnTurboable);
7131 EnableWindow(GetDlgItem(hDlg,IDC_DWNRIGHT), enableUnTurboable);
7132 EnableWindow(GetDlgItem(hDlg,IDC_DWNLEFT), enableUnTurboable);
7133 }
7134
UpdateModeComboBox(HWND hComboBox)7135 void UpdateModeComboBox(HWND hComboBox)
7136 {
7137 TCHAR modeTxt[80];
7138 bool foundCurMode=false;
7139 dMode curMode;
7140
7141 dm.clear();
7142 ComboBox_ResetContent(hComboBox);
7143 WinEnumDisplayModes(&dm);
7144
7145 for(int i=0;i<dm.size();i++) {
7146 _stprintf( modeTxt, TEXT("%dx%d %dbit %dhz"), dm[i].width , dm[i].height, dm[i].depth ,dm[i].rate);
7147 ComboBox_AddString(hComboBox,modeTxt);
7148 if(GUI.FullscreenMode.width==dm[i].width&&GUI.FullscreenMode.height==dm[i].height&&GUI.FullscreenMode.rate==dm[i].rate&&GUI.FullscreenMode.depth==dm[i].depth) {
7149 ComboBox_SetCurSel(hComboBox,i);
7150 foundCurMode=true;
7151 }
7152 }
7153 if(!foundCurMode) {
7154 dm.push_back(GUI.FullscreenMode);
7155 _stprintf( modeTxt, TEXT("Unsupported mode selected"));
7156 ComboBox_AddString(hComboBox,modeTxt);
7157 ComboBox_SetCurSel(hComboBox,ComboBox_GetCount(hComboBox)-1);
7158 }
7159
7160 }
7161
7162 static WNDPROC lpfnOldWndProc;
7163
GroupBoxCheckBoxTitle(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)7164 LRESULT CALLBACK GroupBoxCheckBoxTitle(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
7165 {
7166 RECT checkBoxRect;
7167 if(message==WM_PAINT) {
7168 HWND checkHwnd=GetDlgItem(GetParent(hWnd),IDC_SHADER_ENABLED);
7169 GetClientRect(checkHwnd,&checkBoxRect);
7170 MapWindowPoints(checkHwnd,hWnd,(LPPOINT)&checkBoxRect,2);
7171 ValidateRect(hWnd,&checkBoxRect);
7172 }
7173 return CallWindowProc(lpfnOldWndProc, hWnd, message, wParam, lParam);
7174 }
7175
DlgFunky(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)7176 INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
7177 {
7178 int index;
7179 TCHAR s[80];
7180 char temp[80];
7181 TCHAR openFileName[MAX_PATH];
7182 OPENFILENAME ofn;
7183
7184 // temporary GUI state for restoring after previewing while selecting options
7185 static int prevScale, prevScaleHiRes, prevPPL;
7186 static bool prevStretch, prevAspectRatio, prevHeightExtend, prevAutoDisplayMessages, prevBilinearFilter, prevShaderEnabled, prevBlendHires;
7187 static int prevAspectWidth;
7188 static OutputMethod prevOutputMethod;
7189 static TCHAR prevD3DShaderFile[MAX_PATH],prevOGLShaderFile[MAX_PATH];
7190
7191 switch(msg)
7192 {
7193
7194 case WM_INITDIALOG:
7195 WinRefreshDisplay();
7196
7197 CreateToolTip(IDC_EMUFULLSCREEN,hDlg,TEXT("Emulate fullscreen by creating a window that spans the entire screen when going fullscreen"));
7198 CreateToolTip(IDC_AUTOFRAME,hDlg,TEXT("Try to achieve 50/60 fps by limiting the speed and skipping at most 'max skipped frames'"));
7199 CreateToolTip(IDC_MAXSKIP,hDlg,TEXT("Try to achieve 50/60 fps by limiting the speed and skipping at most 'max skipped frames'"));
7200 CreateToolTip(IDC_FIXEDSKIP,hDlg,TEXT("Always skip a fixed number of frames - no speed limit"));
7201 CreateToolTip(IDC_SKIPCOUNT,hDlg,TEXT("Always skip a fixed number of frames - no speed limit"));
7202 CreateToolTip(IDC_HIRES,hDlg,TEXT("Support the hi-res mode that a few games use, otherwise render them in low-res"));
7203 CreateToolTip(IDC_HEIGHT_EXTEND,hDlg,TEXT("Display an extra 15 pixels at the bottom, which few games use. Also increases AVI output size from 256x224 to 256x240"));
7204 CreateToolTip(IDC_MESSAGES_IN_IMAGE,hDlg,TEXT("Draw text inside the SNES image (will get into AVIs, screenshots, and filters)"));
7205
7206 prevOutputMethod = GUI.outputMethod;
7207 prevScale = GUI.Scale;
7208 prevScaleHiRes = GUI.ScaleHiRes;
7209 prevPPL = GFX.RealPPL;
7210 prevStretch = GUI.Stretch;
7211 prevBilinearFilter = GUI.BilinearFilter;
7212 prevAspectRatio = GUI.AspectRatio;
7213 prevAspectWidth = GUI.AspectWidth;
7214 prevHeightExtend = GUI.HeightExtend;
7215 prevAutoDisplayMessages = Settings.AutoDisplayMessages != 0;
7216 prevShaderEnabled = GUI.shaderEnabled;
7217 prevBlendHires = GUI.BlendHiRes;
7218 lstrcpy(prevD3DShaderFile,GUI.D3DshaderFileName);
7219 lstrcpy(prevOGLShaderFile,GUI.OGLshaderFileName);
7220
7221
7222 _stprintf(s,TEXT("Current: %dx%d %dbit %dHz"),GUI.FullscreenMode.width,GUI.FullscreenMode.height,GUI.FullscreenMode.depth,GUI.FullscreenMode.rate);
7223 SendDlgItemMessage(hDlg,IDC_CURRMODE,WM_SETTEXT,0,(LPARAM)s);
7224
7225 if(GUI.DoubleBuffered)
7226 SendDlgItemMessage(hDlg, IDC_DBLBUFFER, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7227 if(GUI.Vsync)
7228 SendDlgItemMessage(hDlg, IDC_VSYNC, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7229 SendDlgItemMessage(hDlg,IDC_FRAMERATESKIPSLIDER,TBM_SETRANGE,(WPARAM)true,(LPARAM)MAKELONG(0,9));
7230 if(Settings.SkipFrames!=AUTO_FRAMERATE)
7231 SendDlgItemMessage(hDlg,IDC_FRAMERATESKIPSLIDER,TBM_SETPOS,(WPARAM)true,(LPARAM)Settings.SkipFrames);
7232 EnableWindow(GetDlgItem(hDlg, IDC_TRANS), TRUE);
7233 if(Settings.Transparency)
7234 SendDlgItemMessage(hDlg, IDC_TRANS, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7235
7236 if(Settings.SupportHiRes)
7237 SendDlgItemMessage(hDlg, IDC_HIRES, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7238 if(GUI.BlendHiRes)
7239 SendDlgItemMessage(hDlg, IDC_HIRESBLEND, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7240 if(GUI.HeightExtend)
7241 SendDlgItemMessage(hDlg, IDC_HEIGHT_EXTEND, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7242 if(Settings.AutoDisplayMessages)
7243 SendDlgItemMessage(hDlg, IDC_MESSAGES_IN_IMAGE, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7244 if(Settings.SkipFrames==AUTO_FRAMERATE)
7245 SendDlgItemMessage(hDlg, IDC_AUTOFRAME, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7246 if(GUI.Stretch)
7247 {
7248 SendDlgItemMessage(hDlg, IDC_STRETCH, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7249 }
7250
7251 if(GUI.AspectRatio)
7252 SendDlgItemMessage(hDlg, IDC_ASPECT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7253 SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_ADDSTRING,0,(LPARAM)TEXT("8:7"));
7254 SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_ADDSTRING,0,(LPARAM)TEXT("4:3"));
7255 switch(GUI.AspectWidth) {
7256 case 256:
7257 SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_SETCURSEL,(WPARAM)0,0);
7258 break;
7259 case 299:
7260 SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_SETCURSEL,(WPARAM)1,0);
7261 break;
7262 default:
7263 SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_ADDSTRING,0,(LPARAM)TEXT("Custom"));
7264 SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_SETCURSEL,(WPARAM)2,0);
7265 break;
7266 }
7267
7268 if(GUI.FullScreen || GUI.EmulatedFullscreen)
7269 SendDlgItemMessage(hDlg, IDC_FULLSCREEN, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7270 if(GUI.EmulateFullscreen)
7271 SendDlgItemMessage(hDlg, IDC_EMUFULLSCREEN, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7272 if(GUI.BilinearFilter)
7273 SendDlgItemMessage(hDlg,IDC_BILINEAR, BM_SETCHECK, (WPARAM)BST_CHECKED,0);
7274 if(Settings.DisplayFrameRate)
7275 SendDlgItemMessage(hDlg, IDC_SHOWFPS, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7276
7277 if(Settings.SkipFrames==AUTO_FRAMERATE) {
7278 SendDlgItemMessage(hDlg, IDC_AUTOFRAME, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7279 EnableWindow(GetDlgItem(hDlg, IDC_SKIPCOUNT),FALSE);
7280 } else {
7281 SendDlgItemMessage(hDlg, IDC_FIXEDSKIP, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7282 EnableWindow(GetDlgItem(hDlg, IDC_MAXSKIP),FALSE);
7283 }
7284 SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP, UDM_SETRANGE, 0, MAKELPARAM((short)59, (short)0));
7285 SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP, UDM_SETPOS,0, Settings.AutoMaxSkipFrames);
7286 SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP_FIXED, UDM_SETRANGE, 0, MAKELPARAM((short)59, (short)0));
7287 SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP_FIXED, UDM_SETPOS,0, Settings.SkipFrames==AUTO_FRAMERATE?0:Settings.SkipFrames);
7288
7289 if(GUI.shaderEnabled) {
7290 SendDlgItemMessage(hDlg, IDC_SHADER_ENABLED, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7291 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_HLSL_FILE),TRUE);
7292 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_HLSL_BROWSE),TRUE);
7293 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_FILE),TRUE);
7294 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_BROWSE),TRUE);
7295 }
7296 SetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.D3DshaderFileName);
7297 SetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,GUI.OGLshaderFileName);
7298
7299 lpfnOldWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg,IDC_SHADER_GROUP),GWLP_WNDPROC,(LONG_PTR)GroupBoxCheckBoxTitle);
7300
7301 EnableWindow(GetDlgItem(hDlg, IDC_ASPECT), GUI.Stretch);
7302
7303 SendDlgItemMessage(hDlg,IDC_OUTPUTMETHOD,CB_ADDSTRING,0,(LPARAM)TEXT("DirectDraw"));
7304 SendDlgItemMessage(hDlg,IDC_OUTPUTMETHOD,CB_ADDSTRING,0,(LPARAM)TEXT("Direct3D"));
7305 SendDlgItemMessage(hDlg,IDC_OUTPUTMETHOD,CB_ADDSTRING,0,(LPARAM)TEXT("OpenGL"));
7306 SendDlgItemMessage(hDlg,IDC_OUTPUTMETHOD,CB_SETCURSEL,(WPARAM)GUI.outputMethod,0);
7307 // add all the GUI.Scale filters to the combo box
7308 for(int filter = 0 ; filter < (int)NUM_FILTERS ; filter++)
7309 {
7310 strcpy(temp,GetFilterName((RenderFilter)filter));
7311 SendDlgItemMessageA(hDlg,IDC_FILTERBOX,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)temp);
7312 }
7313 for(int filter = 0, hiResPos = 0 ; filter < (int)NUM_FILTERS ; filter++)
7314 {
7315 if(GetFilterHiResSupport((RenderFilter)filter))
7316 {
7317 strcpy(temp,GetFilterName((RenderFilter)filter));
7318 SendDlgItemMessageA(hDlg,IDC_FILTERBOX2,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)temp);
7319 if(GUI.ScaleHiRes==filter)
7320 SendDlgItemMessage(hDlg,IDC_FILTERBOX2,CB_SETCURSEL,(WPARAM)hiResPos,0);
7321 hiResPos++;
7322 }
7323 }
7324
7325 SendDlgItemMessage(hDlg,IDC_FILTERBOX,CB_SETCURSEL,(WPARAM)GUI.Scale,0);
7326
7327 UpdateModeComboBox(GetDlgItem(hDlg,IDC_RESOLUTION));
7328
7329 // have to start focus on something like this or Escape won't exit the dialog
7330 SetFocus(hDlg);
7331
7332 break;
7333 case WM_CLOSE:
7334 case WM_DESTROY:
7335 break;
7336 case WM_COMMAND:
7337
7338 switch(LOWORD(wParam))
7339 {
7340 case IDC_STRETCH:
7341 // for some reason this screws up the fullscreen mode clipper if it happens before the refresh
7342 if(IsDlgButtonChecked(hDlg, IDC_STRETCH)==BST_CHECKED)
7343 {
7344 EnableWindow(GetDlgItem(hDlg, IDC_ASPECT), TRUE);
7345 }
7346 else
7347 {
7348 EnableWindow(GetDlgItem(hDlg, IDC_ASPECT), FALSE);
7349 }
7350
7351 GUI.Stretch = (bool)(IsDlgButtonChecked(hDlg,IDC_STRETCH)==BST_CHECKED);
7352 // refresh screen, so the user can see the new mode
7353 // (assuming the dialog box isn't completely covering the game window)
7354 WinDisplayApplyChanges();
7355
7356 WinRefreshDisplay();
7357 break;
7358
7359 case IDC_BILINEAR:
7360
7361 GUI.BilinearFilter = (bool)(IsDlgButtonChecked(hDlg,IDC_BILINEAR)==BST_CHECKED);
7362
7363 //// refresh screen, so the user can see the new stretch mode
7364 WinDisplayApplyChanges();
7365
7366 WinRefreshDisplay();
7367 break;
7368
7369 case IDC_MESSAGES_IN_IMAGE:
7370 Settings.AutoDisplayMessages = (bool)(IsDlgButtonChecked(hDlg,IDC_MESSAGES_IN_IMAGE)==BST_CHECKED);
7371 if(Settings.AutoDisplayMessages)
7372 {
7373 if(!GFX.InfoString || !*GFX.InfoString){
7374 GFX.InfoString = "Test message!";
7375 GFX.InfoStringTimeout = 1;
7376 }
7377 S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1);
7378 }
7379 // refresh screen, so the user can see the new mode
7380 WinRefreshDisplay();
7381 break;
7382
7383 case IDC_ASPECT:
7384 GUI.AspectRatio = (bool)(IsDlgButtonChecked(hDlg,IDC_ASPECT)==BST_CHECKED);
7385 // refresh screen, so the user can see the new mode
7386 WinDisplayApplyChanges();
7387
7388 WinRefreshDisplay();
7389 break;
7390 case IDC_ASPECTDROP:
7391 if(HIWORD(wParam)==CBN_SELCHANGE) {
7392 int newsel = SendDlgItemMessage(hDlg,IDC_ASPECTDROP,CB_GETCURSEL,0,0);
7393 switch(newsel) {
7394 case 0:
7395 GUI.AspectWidth = 256;
7396 break;
7397 case 1:
7398 GUI.AspectWidth = 299;
7399 break;
7400 default:
7401 GUI.AspectWidth = prevAspectWidth;
7402 break;
7403 }
7404 WinDisplayApplyChanges();
7405 WinRefreshDisplay();
7406 }
7407 break;
7408
7409 case IDC_HEIGHT_EXTEND:
7410 GUI.HeightExtend = (bool)(IsDlgButtonChecked(hDlg,IDC_HEIGHT_EXTEND)==BST_CHECKED);
7411 // refresh screen, so the user can see the new mode
7412 WinDisplayApplyChanges();
7413
7414 WinRefreshDisplay();
7415 break;
7416
7417 case IDC_HIRESBLEND:
7418 GUI.BlendHiRes = (bool)(IsDlgButtonChecked(hDlg,IDC_HIRESBLEND)==BST_CHECKED);
7419 WinRefreshDisplay();
7420 break;
7421
7422 case IDC_AUTOFRAME:
7423 if(BN_CLICKED==HIWORD(wParam)||BN_DBLCLK==HIWORD(wParam))
7424 {
7425 EnableWindow(GetDlgItem(hDlg, IDC_MAXSKIP), TRUE);
7426 EnableWindow(GetDlgItem(hDlg, IDC_SKIPCOUNT), FALSE);
7427 return true;
7428
7429 }
7430 break;
7431 case IDC_FIXEDSKIP:
7432 if(BN_CLICKED==HIWORD(wParam)||BN_DBLCLK==HIWORD(wParam))
7433 {
7434 EnableWindow(GetDlgItem(hDlg, IDC_MAXSKIP), FALSE);
7435 EnableWindow(GetDlgItem(hDlg, IDC_SKIPCOUNT), TRUE);
7436 return true;
7437
7438 }
7439 break;
7440 case IDC_OUTPUTMETHOD:
7441 if(HIWORD(wParam)==CBN_SELCHANGE) {
7442 OutputMethod newOut = (OutputMethod)SendDlgItemMessage(hDlg,IDC_OUTPUTMETHOD,CB_GETCURSEL,0,0);
7443 if(GUI.outputMethod==newOut)
7444 break;
7445 if(GUI.FullScreen)
7446 ToggleFullScreen();
7447 GUI.outputMethod=newOut;
7448
7449 WinDisplayReset();
7450 UpdateModeComboBox(GetDlgItem(hDlg,IDC_RESOLUTION));
7451 WinRefreshDisplay();
7452 UpdateWindow(GUI.hWnd);
7453 }
7454 break;
7455 case IDC_SHADER_ENABLED:
7456 GUI.shaderEnabled = (bool)(IsDlgButtonChecked(hDlg,IDC_SHADER_ENABLED)==BST_CHECKED);
7457 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GROUP),GUI.shaderEnabled);
7458 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_HLSL_FILE),GUI.shaderEnabled);
7459 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_HLSL_BROWSE),GUI.shaderEnabled);
7460 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_FILE),GUI.shaderEnabled);
7461 EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_BROWSE),GUI.shaderEnabled);
7462
7463 GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.D3DshaderFileName,MAX_PATH);
7464 GetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,GUI.OGLshaderFileName,MAX_PATH);
7465 WinDisplayApplyChanges();
7466 WinRefreshDisplay();
7467 break;
7468 case IDC_SHADER_HLSL_BROWSE:
7469 GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,openFileName,MAX_PATH);
7470 memset((LPVOID)&ofn, 0, sizeof(OPENFILENAME));
7471
7472 ofn.lStructSize = sizeof(OPENFILENAME);
7473 ofn.hwndOwner = hDlg;
7474 ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp\0All Files\0*.*\0\0");
7475 ofn.lpstrFile = openFileName;
7476 ofn.lpstrTitle = TEXT("Select Shader");
7477 ofn.lpstrDefExt = TEXT("shader");
7478 ofn.nMaxFile = MAX_PATH;
7479 ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
7480 if(GetOpenFileName(&ofn)) {
7481 SetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,openFileName);
7482 lstrcpy(GUI.D3DshaderFileName,openFileName);
7483 WinDisplayApplyChanges();
7484 WinRefreshDisplay();
7485 }
7486 break;
7487 case IDC_SHADER_GLSL_BROWSE:
7488 GetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,openFileName,MAX_PATH);
7489 memset((LPVOID)&ofn, 0, sizeof(OPENFILENAME));
7490
7491 ofn.lStructSize = sizeof(OPENFILENAME);
7492 ofn.hwndOwner = hDlg;
7493 ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp\0All Files\0*.*\0\0");
7494 ofn.lpstrFile = openFileName;
7495 ofn.lpstrTitle = TEXT("Select Shader");
7496 ofn.lpstrDefExt = TEXT("shader");
7497 ofn.nMaxFile = MAX_PATH;
7498 ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
7499 if(GetOpenFileName(&ofn)) {
7500 SetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,openFileName);
7501 lstrcpy(GUI.OGLshaderFileName,openFileName);
7502 WinDisplayApplyChanges();
7503 WinRefreshDisplay();
7504 }
7505 break;
7506 case IDC_FILTERBOX:
7507 if(HIWORD(wParam)==CBN_SELCHANGE) {
7508 int scale = (int)SendDlgItemMessage(hDlg,IDC_FILTERBOX,CB_GETCURSEL,0,0);
7509 if(scale == GUI.Scale)
7510 break;
7511
7512 const int oldScaleScale = max(GetFilterScale(GUI.Scale), GetFilterScale(GUI.ScaleHiRes));
7513
7514 // UpdateScale(GUI.Scale, scale);
7515 GUI.Scale = (RenderFilter)scale;
7516
7517
7518 const int newScaleScale = max(GetFilterScale(GUI.Scale), GetFilterScale(GUI.ScaleHiRes));
7519
7520 if(oldScaleScale != newScaleScale)
7521 RestoreSNESDisplay();
7522
7523 // refresh screen, so the user can see the new filter
7524 // (assuming the dialog box isn't completely covering the game window)
7525 WinRefreshDisplay();
7526
7527 // set hi-res combo box to match the lo-res output filter as best as possible
7528 // if(GetFilterHiResSupport(GUI.Scale))
7529 checkUpdateFilterBox2:
7530 {
7531 char textOriginal [256];
7532 SendMessageA(GetDlgItem(hDlg, IDC_FILTERBOX), WM_GETTEXT, 256,(LPARAM)textOriginal);
7533 int count = SendDlgItemMessage(hDlg,IDC_FILTERBOX2,CB_GETCOUNT,0,0);
7534 // int scale = GUI.Scale;
7535 bool switched = false;
7536 for(int j=0; j<2 && !switched; j++){
7537 if(j){
7538 RenderFilter filter; // no match, set default for chosen scale
7539 switch(GetFilterScale(GUI.Scale)){
7540 case 1: filter = FILTER_SIMPLE1X; break;
7541 default: case 2: filter = FILTER_SIMPLE2X; break;
7542 case 3: filter = FILTER_SIMPLE3X; break;
7543 case 4: filter = FILTER_SIMPLE4X; break;
7544 case 5: case 6: filter = FILTER_SIMPLE4X; break;
7545 }
7546 strcpy(textOriginal, GetFilterName(filter));
7547 }
7548 for(int i=0; i<count && !switched; i++){
7549 int textLen = SendDlgItemMessageA(hDlg,IDC_FILTERBOX2,CB_GETLBTEXTLEN,(WPARAM)i,0);
7550 char* text = new char[textLen+1];
7551 SendDlgItemMessageA(hDlg,IDC_FILTERBOX2,CB_GETLBTEXT,(WPARAM)i,(LPARAM)text);
7552 if(!stricmp(textOriginal, text)){
7553 SendDlgItemMessageA(hDlg,IDC_FILTERBOX2,CB_SETCURSEL,(WPARAM)i,0);
7554 switched = true;
7555 }
7556 delete[] text;
7557 }
7558 }
7559 goto updateFilterBox2;
7560 }
7561 }
7562 break;
7563 case IDC_FILTERBOX2: // hi-res
7564 updateFilterBox2:
7565 {
7566 char text [256];
7567 text[0] = '\0';
7568 SendMessageA(GetDlgItem(hDlg, IDC_FILTERBOX2), WM_GETTEXT, 256,(LPARAM)text);
7569
7570 int scale = GUI.Scale;
7571 for(int i=0; i<NUM_FILTERS; i++)
7572 if(!stricmp(GetFilterName((RenderFilter)i), text))
7573 scale = i;
7574
7575 if(scale == GUI.ScaleHiRes)
7576 break;
7577
7578 const int oldScaleScale = max(GetFilterScale(GUI.Scale), GetFilterScale(GUI.ScaleHiRes));
7579
7580 // UpdateScale(GUI.Scale, scale);
7581 GUI.ScaleHiRes = (RenderFilter)scale;
7582
7583 const int newScaleScale = max(GetFilterScale(GUI.Scale), GetFilterScale(GUI.ScaleHiRes));
7584
7585 if(oldScaleScale != newScaleScale)
7586 RestoreSNESDisplay();
7587
7588 // refresh screen, so the user can see the new filter
7589 // (assuming the dialog box isn't completely covering the game window)
7590 WinRefreshDisplay();
7591 }
7592 break;
7593
7594 case IDOK:
7595 bool fullscreenWanted;
7596 Settings.Transparency = IsDlgButtonChecked(hDlg, IDC_TRANS);
7597 GUI.BilinearFilter = (bool)(IsDlgButtonChecked(hDlg,IDC_BILINEAR)==BST_CHECKED);
7598 if(!GUI.FullScreen || (GUI.FullscreenMode.width >= 512 && GUI.FullscreenMode.height >= 478) || GUI.Stretch)
7599 Settings.SupportHiRes = IsDlgButtonChecked(hDlg, IDC_HIRES);
7600 else
7601 Settings.SupportHiRes = false;
7602 GUI.HeightExtend = IsDlgButtonChecked(hDlg, IDC_HEIGHT_EXTEND)!=0;
7603 Settings.AutoDisplayMessages = IsDlgButtonChecked(hDlg, IDC_MESSAGES_IN_IMAGE);
7604 GUI.DoubleBuffered = (bool)(IsDlgButtonChecked(hDlg, IDC_DBLBUFFER)==BST_CHECKED);
7605 GUI.Vsync = (bool)(IsDlgButtonChecked(hDlg, IDC_VSYNC
7606
7607 )==BST_CHECKED);
7608 if(IsDlgButtonChecked(hDlg, IDC_AUTOFRAME))
7609 {
7610 Settings.SkipFrames=AUTO_FRAMERATE;
7611 Settings.AutoMaxSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP, UDM_GETPOS, 0,0);
7612 }
7613 else
7614 {
7615 Settings.SkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP_FIXED, UDM_GETPOS, 0,0);
7616 }
7617
7618
7619 GUI.Stretch = (bool)(IsDlgButtonChecked(hDlg, IDC_STRETCH)==BST_CHECKED);
7620 GUI.AspectRatio = (bool)(IsDlgButtonChecked(hDlg, IDC_ASPECT)==BST_CHECKED);
7621 fullscreenWanted = (bool)(IsDlgButtonChecked(hDlg, IDC_FULLSCREEN)==BST_CHECKED);
7622 GUI.EmulateFullscreen = (bool)(IsDlgButtonChecked(hDlg, IDC_EMUFULLSCREEN)==BST_CHECKED);
7623 Settings.DisplayFrameRate = IsDlgButtonChecked(hDlg, IDC_SHOWFPS);
7624 GUI.BlendHiRes = (bool)(IsDlgButtonChecked(hDlg, IDC_HIRESBLEND)==BST_CHECKED);
7625
7626 index = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
7627
7628 GUI.FullscreenMode = dm[index];
7629
7630 GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.D3DshaderFileName,MAX_PATH);
7631
7632
7633 // we might've changed the region that the game draws over
7634 // (by turning on "maintain aspect ratio", or turning on "extend height" when "maintain aspect ratio" is already on),
7635 // so we must invalidate the window to redraw black
7636 // behind the possibly-newly-revealed areas of the window
7637 RedrawWindow((HWND)GetParent(hDlg),NULL,NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_ERASENOW);
7638
7639 WinSaveConfigFile();
7640
7641 if(GUI.FullScreen && (GUI.FullscreenMode.width < 512 || GUI.FullscreenMode.height < 478))
7642 GUI.Scale = FILTER_NONE;
7643
7644 if(GUI.FullScreen && (GUI.FullscreenMode.width < 512 || GUI.FullscreenMode.height < 478))
7645 GUI.ScaleHiRes = FILTER_SIMPLE1X;
7646
7647 EndDialog(hDlg,0);
7648 WinDisplayApplyChanges();
7649
7650 // if we are emulating fullscreen and now want to change to regular fullscreen
7651 // we want to switch back to the last window size
7652 if(fullscreenWanted && GUI.EmulatedFullscreen && !GUI.EmulateFullscreen) {
7653 GUI.EmulateFullscreen = true;
7654 ToggleFullScreen();
7655 GUI.EmulateFullscreen = false;
7656 }
7657 if(fullscreenWanted != GUI.EmulatedFullscreen) {
7658 ToggleFullScreen();
7659 }
7660
7661
7662 return false;
7663
7664
7665
7666 case IDCANCEL:
7667 ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_OUTPUTMETHOD),prevOutputMethod);
7668 SendMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDC_OUTPUTMETHOD,CBN_SELCHANGE),0);
7669
7670 {
7671 //UpdateScale(GUI.Scale, prevScale);
7672 GUI.Scale = (RenderFilter)prevScale;
7673 GUI.ScaleHiRes = (RenderFilter)prevScaleHiRes;
7674 GFX.RealPPL = prevPPL;
7675 GUI.Stretch = prevStretch;
7676 Settings.AutoDisplayMessages = prevAutoDisplayMessages;
7677 GUI.BilinearFilter = prevBilinearFilter;
7678 GUI.AspectRatio = prevAspectRatio;
7679 GUI.AspectWidth = prevAspectWidth;
7680 GUI.HeightExtend = prevHeightExtend;
7681 GUI.shaderEnabled = prevShaderEnabled;
7682 GUI.BlendHiRes = prevBlendHires;
7683 lstrcpy(GUI.D3DshaderFileName,prevD3DShaderFile);
7684 lstrcpy(GUI.OGLshaderFileName,prevOGLShaderFile);
7685 }
7686
7687 EndDialog(hDlg,0);
7688
7689 return false;
7690 }
7691
7692
7693 }
7694
7695 return false;
7696 }
7697
set_buttoninfo(int index,HWND hDlg)7698 static void set_buttoninfo(int index, HWND hDlg)
7699 {
7700 SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
7701 SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
7702 SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
7703 SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
7704 SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
7705 SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
7706 SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
7707 SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
7708 SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
7709 SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
7710 SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
7711 SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
7712 if(index < 5)
7713 {
7714 SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
7715 SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
7716 SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
7717 SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
7718 }
7719 }
7720
7721 void TranslateKey(WORD keyz,char *out);
7722 //HWND funky;
7723 SJoyState JoystickF [16];
7724
7725
7726 #ifdef NETPLAY_SUPPORT
DlgNPProgress(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)7727 INT_PTR CALLBACK DlgNPProgress(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
7728 {
7729 SendDlgItemMessage(hDlg,IDC_NPPROGRESS,PBM_SETRANGE,0,(LPARAM)MAKELPARAM (0, 100));
7730 SendDlgItemMessage(hDlg,IDC_NPPROGRESS,PBM_SETPOS,(WPARAM)(int)NetPlay.PercentageComplete,0);
7731
7732 return false;
7733 }
7734 #endif
DlgInputConfig(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)7735 INT_PTR CALLBACK DlgInputConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
7736 {
7737 TCHAR temp[256];
7738 short C;
7739 int i, which;
7740 static int index=0;
7741
7742
7743 static SJoypad pads[10];
7744
7745
7746 //HBRUSH g_hbrBackground;
7747
7748 InitInputCustomControl();
7749 switch(msg)
7750 {
7751 case WM_PAINT:
7752 {
7753 PAINTSTRUCT ps;
7754 BeginPaint (hDlg, &ps);
7755
7756 EndPaint (hDlg, &ps);
7757 }
7758 return true;
7759 case WM_INITDIALOG:
7760 WinRefreshDisplay();
7761 SetWindowText(hDlg,INPUTCONFIG_TITLE);
7762 SetDlgItemText(hDlg,IDC_JPTOGGLE,INPUTCONFIG_JPTOGGLE);
7763 SetDlgItemText(hDlg,IDC_OK,BUTTON_OK);
7764 SetDlgItemText(hDlg,IDC_CANCEL,BUTTON_CANCEL);
7765 SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_UP);
7766 SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_DOWN);
7767 SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_LEFT);
7768 SetDlgItemText(hDlg,IDC_LABEL_A,INPUTCONFIG_LABEL_A);
7769 SetDlgItemText(hDlg,IDC_LABEL_B,INPUTCONFIG_LABEL_B);
7770 SetDlgItemText(hDlg,IDC_LABEL_X,INPUTCONFIG_LABEL_X);
7771 SetDlgItemText(hDlg,IDC_LABEL_Y,INPUTCONFIG_LABEL_Y);
7772 SetDlgItemText(hDlg,IDC_LABEL_L,INPUTCONFIG_LABEL_L);
7773 SetDlgItemText(hDlg,IDC_LABEL_R,INPUTCONFIG_LABEL_R);
7774 SetDlgItemText(hDlg,IDC_LABEL_START,INPUTCONFIG_LABEL_START);
7775 SetDlgItemText(hDlg,IDC_LABEL_SELECT,INPUTCONFIG_LABEL_SELECT);
7776 SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UPRIGHT);
7777 SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UPLEFT);
7778 SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT);
7779 SetDlgItemText(hDlg,IDC_LABEL_DOWNLEFT,INPUTCONFIG_LABEL_DOWNLEFT);
7780 SetDlgItemText(hDlg,IDC_LABEL_BLUE,INPUTCONFIG_LABEL_BLUE);
7781
7782 for(i=5;i<10;i++)
7783 Joypad[i].Left_Up = Joypad[i].Right_Up = Joypad[i].Left_Down = Joypad[i].Right_Down = 0;
7784
7785 memcpy(pads, Joypad, 10*sizeof(SJoypad));
7786
7787 for( i=0;i<256;i++)
7788 GetAsyncKeyState(i);
7789
7790 for( C = 0; C != 16; C ++)
7791 JoystickF[C].Attached = joyGetDevCaps( JOYSTICKID1+C, &JoystickF[C].Caps, sizeof( JOYCAPS)) == JOYERR_NOERROR;
7792
7793 for(i=1;i<6;i++)
7794 {
7795 _stprintf(temp,INPUTCONFIG_JPCOMBO,i);
7796 SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp);
7797 }
7798
7799 for(i=6;i<11;i++)
7800 {
7801 _stprintf(temp,INPUTCONFIG_JPCOMBO INPUTCONFIG_LABEL_CONTROLLER_TURBO_PANEL_MOD,i-5);
7802 SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp);
7803 }
7804
7805 SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)0,0);
7806
7807 SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK, Joypad[index].Enabled ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
7808 SendDlgItemMessage(hDlg,IDC_ALLOWLEFTRIGHT,BM_SETCHECK, Settings.UpAndDown ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
7809
7810 set_buttoninfo(index,hDlg);
7811
7812 EnableDisableKeyFields(index,hDlg);
7813
7814 PostMessage(hDlg,WM_COMMAND, CBN_SELCHANGE<<16, 0);
7815
7816 SetFocus(GetDlgItem(hDlg,IDC_JPCOMBO));
7817
7818 return true;
7819 break;
7820 case WM_CLOSE:
7821 EndDialog(hDlg, 0);
7822 return TRUE;
7823 case WM_USER+46:
7824 // refresh command, for clicking away from a selected field
7825 index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
7826 if(index > 4) index += 3; // skip controllers 6, 7, and 8 in the input dialog
7827 set_buttoninfo(index,hDlg);
7828 return TRUE;
7829 case WM_USER+43:
7830 //MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK);
7831 which = GetDlgCtrlID((HWND)lParam);
7832 switch(which)
7833 {
7834 case IDC_UP:
7835 Joypad[index].Up = wParam;
7836
7837 break;
7838 case IDC_DOWN:
7839 Joypad[index].Down = wParam;
7840
7841 break;
7842 case IDC_LEFT:
7843 Joypad[index].Left = wParam;
7844
7845 break;
7846 case IDC_RIGHT:
7847 Joypad[index].Right = wParam;
7848
7849 break;
7850 case IDC_A:
7851 Joypad[index].A = wParam;
7852
7853 break;
7854 case IDC_B:
7855 Joypad[index].B = wParam;
7856
7857 break;
7858 case IDC_X:
7859 Joypad[index].X = wParam;
7860
7861 break;
7862 case IDC_Y:
7863 Joypad[index].Y = wParam;
7864
7865 break;
7866 case IDC_L:
7867 Joypad[index].L = wParam;
7868 break;
7869
7870 case IDC_R:
7871 Joypad[index].R = wParam;
7872
7873 break;
7874 case IDC_SELECT:
7875 Joypad[index].Select = wParam;
7876
7877 break;
7878 case IDC_START:
7879 Joypad[index].Start = wParam;
7880
7881 break;
7882 case IDC_UPLEFT:
7883 Joypad[index].Left_Up = wParam;
7884
7885 break;
7886 case IDC_UPRIGHT:
7887 Joypad[index].Right_Up = wParam;
7888
7889 break;
7890 case IDC_DWNLEFT:
7891 Joypad[index].Left_Down = wParam;
7892
7893 break;
7894 case IDC_DWNRIGHT:
7895 Joypad[index].Right_Down = wParam;
7896
7897 break;
7898
7899 }
7900
7901 set_buttoninfo(index,hDlg);
7902
7903 PostMessage(hDlg,WM_NEXTDLGCTL,0,0);
7904 return true;
7905 case WM_COMMAND:
7906 switch(LOWORD(wParam))
7907 {
7908 case IDCANCEL:
7909 memcpy(Joypad, pads, 10*sizeof(SJoypad));
7910 EndDialog(hDlg,0);
7911 break;
7912
7913 case IDOK:
7914 Settings.UpAndDown = IsDlgButtonChecked(hDlg, IDC_ALLOWLEFTRIGHT);
7915 WinSaveConfigFile();
7916 EndDialog(hDlg,0);
7917 break;
7918
7919 case IDC_JPTOGGLE: // joypad Enable toggle
7920 index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
7921 if(index > 4) index += 3; // skip controllers 6, 7, and 8 in the input dialog
7922 Joypad[index].Enabled=IsDlgButtonChecked(hDlg,IDC_JPTOGGLE);
7923 set_buttoninfo(index, hDlg); // update display of conflicts
7924 break;
7925
7926 }
7927 switch(HIWORD(wParam))
7928 {
7929 case CBN_SELCHANGE:
7930 index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
7931 SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)index,0);
7932 if(index > 4) index += 3; // skip controllers 6, 7, and 8 in the input dialog
7933 if(index < 8)
7934 {
7935 SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK, Joypad[index].Enabled ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
7936 EnableWindow(GetDlgItem(hDlg,IDC_JPTOGGLE),TRUE);
7937 }
7938 else
7939 {
7940 SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK, Joypad[index-8].Enabled ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
7941 EnableWindow(GetDlgItem(hDlg,IDC_JPTOGGLE),FALSE);
7942 }
7943
7944 set_buttoninfo(index,hDlg);
7945
7946 EnableDisableKeyFields(index,hDlg);
7947
7948 break;
7949 }
7950 return FALSE;
7951
7952 }
7953
7954 return FALSE;
7955 }
7956
7957
set_hotkeyinfo(HWND hDlg)7958 static void set_hotkeyinfo(HWND hDlg)
7959 {
7960 int index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0);
7961
7962 switch(index)
7963 {
7964 case 0:
7965 // set page 1 fields
7966 SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.SpeedUp.key,CustomKeys.SpeedUp.modifiers);
7967 SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.SpeedDown.key,CustomKeys.SpeedDown.modifiers);
7968 SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.Pause.key,CustomKeys.Pause.modifiers);
7969 SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.FrameAdvance.key,CustomKeys.FrameAdvance.modifiers);
7970 SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.FastForward.key,CustomKeys.FastForward.modifiers);
7971 SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.SkipUp.key,CustomKeys.SkipUp.modifiers);
7972 SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.SkipDown.key,CustomKeys.SkipDown.modifiers);
7973 SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.ScopeTurbo.key,CustomKeys.ScopeTurbo.modifiers);
7974 SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.ScopePause.key,CustomKeys.ScopePause.modifiers);
7975 SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.ShowPressed.key,CustomKeys.ShowPressed.modifiers);
7976 SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.FrameCount.key,CustomKeys.FrameCount.modifiers);
7977 SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ReadOnly.key,CustomKeys.ReadOnly.modifiers);
7978 SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.SaveScreenShot.key,CustomKeys.SaveScreenShot.modifiers);
7979 break;
7980 case 1:
7981 SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.BGL1.key,CustomKeys.BGL1.modifiers);
7982 SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.BGL2.key,CustomKeys.BGL2.modifiers);
7983 SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.BGL3.key,CustomKeys.BGL3.modifiers);
7984 SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.BGL4.key,CustomKeys.BGL4.modifiers);
7985 SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.BGL5.key,CustomKeys.BGL5.modifiers);
7986 SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.ClippingWindows.key,CustomKeys.ClippingWindows.modifiers);
7987 SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.Transparency.key,CustomKeys.Transparency.modifiers);
7988 SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.FastForwardToggle.key,CustomKeys.FastForwardToggle.modifiers);
7989 SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.Rewind.key,CustomKeys.Rewind.modifiers);
7990 SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.SwitchControllers.key,CustomKeys.SwitchControllers.modifiers);
7991 SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.JoypadSwap.key,CustomKeys.JoypadSwap.modifiers);
7992 SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ResetGame.key,CustomKeys.ResetGame.modifiers);
7993 SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.ToggleCheats.key,CustomKeys.ToggleCheats.modifiers);
7994 break;
7995 case 2:
7996 SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.TurboA.key,CustomKeys.TurboA.modifiers);
7997 SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.TurboB.key,CustomKeys.TurboB.modifiers);
7998 SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.TurboY.key,CustomKeys.TurboY.modifiers);
7999 SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.TurboX.key,CustomKeys.TurboX.modifiers);
8000 SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.TurboL.key,CustomKeys.TurboL.modifiers);
8001 SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.TurboR.key,CustomKeys.TurboR.modifiers);
8002 SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.TurboStart.key,CustomKeys.TurboStart.modifiers);
8003 SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.TurboSelect.key,CustomKeys.TurboSelect.modifiers);
8004 SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.TurboLeft.key,CustomKeys.TurboLeft.modifiers);
8005 SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.TurboUp.key,CustomKeys.TurboUp.modifiers);
8006 SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.TurboRight.key,CustomKeys.TurboRight.modifiers);
8007 SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.TurboDown.key,CustomKeys.TurboDown.modifiers);
8008 SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,0,0);
8009 break;
8010 case 3:
8011 for(int i = 0 ; i < 10 ; i++)
8012 SendDlgItemMessage(hDlg,IDC_HOTKEY1+i,WM_USER+44,CustomKeys.SelectSave[i].key,CustomKeys.SelectSave[i].modifiers);
8013 SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,0,0);
8014 SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,0,0);
8015 SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.QuitS9X.key,CustomKeys.QuitS9X.modifiers);
8016 break;
8017 }
8018
8019 SendDlgItemMessage(hDlg,IDC_SLOTPLUS,WM_USER+44,CustomKeys.SlotPlus.key,CustomKeys.SlotPlus.modifiers);
8020 SendDlgItemMessage(hDlg,IDC_SLOTMINUS,WM_USER+44,CustomKeys.SlotMinus.key,CustomKeys.SlotMinus.modifiers);
8021 SendDlgItemMessage(hDlg,IDC_SLOTSAVE,WM_USER+44,CustomKeys.SlotSave.key,CustomKeys.SlotSave.modifiers);
8022 SendDlgItemMessage(hDlg,IDC_SLOTLOAD,WM_USER+44,CustomKeys.SlotLoad.key,CustomKeys.SlotLoad.modifiers);
8023 int i;
8024 for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE1+i,WM_USER+44,CustomKeys.Save[i].key,CustomKeys.Save[i].modifiers);
8025 for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE11+i,WM_USER+44,CustomKeys.Load[i].key,CustomKeys.Load[i].modifiers);
8026
8027 switch(index)
8028 {
8029 case 0:
8030 // set page 1 label text
8031 SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_1_1);
8032 SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_1_2);
8033 SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_1_3);
8034 SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_1_4);
8035 SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_1_5);
8036 SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_1_6);
8037 SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_1_7);
8038 SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_1_8);
8039 SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_1_9);
8040 SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_1_10);
8041 SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_1_11);
8042 SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_1_12);
8043 SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_1_13);
8044 break;
8045 case 1:
8046 SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_2_1);
8047 SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_2_2);
8048 SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_2_3);
8049 SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_2_4);
8050 SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_2_5);
8051 SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_2_6);
8052 SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_2_7);
8053 SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_2_8);
8054 SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_2_9);
8055 SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_2_10);
8056 SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_2_11);
8057 SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_2_12);
8058 SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_2_13);
8059 break;
8060 case 2:
8061 SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_3_1);
8062 SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_3_2);
8063 SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_3_3);
8064 SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_3_4);
8065 SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_3_5);
8066 SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_3_6);
8067 SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_3_7);
8068 SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_3_8);
8069 SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_3_9);
8070 SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_3_10);
8071 SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_3_11);
8072 SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_3_12);
8073 SetDlgItemText(hDlg,IDC_LABEL_HK13,INPUTCONFIG_LABEL_UNUSED);
8074
8075 break;
8076 case 3:
8077 for(int i = 0 ; i < 10 ; i++)
8078 {
8079 TCHAR temp [64];
8080 _stprintf(temp, TEXT("Select Slot %d"), i);
8081 SetDlgItemText(hDlg,IDC_LABEL_HK1+i,temp);
8082 }
8083 for(int i = 10 ; i < 12 ; i++)
8084 SetDlgItemText(hDlg,IDC_LABEL_HK1+i,INPUTCONFIG_LABEL_UNUSED);
8085 SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_4_13);
8086
8087 break;
8088 }
8089 }
8090
8091 // DlgHotkeyConfig
DlgHotkeyConfig(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)8092 INT_PTR CALLBACK DlgHotkeyConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
8093 {
8094 int i, which;
8095 static int index=0;
8096
8097
8098 static SCustomKeys keys;
8099
8100
8101 //HBRUSH g_hbrBackground;
8102 InitKeyCustomControl();
8103 switch(msg)
8104 {
8105 case WM_PAINT:
8106 {
8107 PAINTSTRUCT ps;
8108 BeginPaint (hDlg, &ps);
8109
8110 EndPaint (hDlg, &ps);
8111 }
8112 return true;
8113 case WM_INITDIALOG:
8114 WinRefreshDisplay();
8115 SetWindowText(hDlg,HOTKEYS_TITLE);
8116
8117 // insert hotkey page list items
8118 for(i=1 ; i <= 4 ; i++)
8119 {
8120 TCHAR temp[256];
8121 _stprintf(temp,HOTKEYS_HKCOMBO,i);
8122 SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp);
8123 }
8124
8125 SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_SETCURSEL,(WPARAM)0,0);
8126
8127 memcpy(&keys, &CustomKeys, sizeof(SCustomKeys));
8128 for( i=0;i<256;i++)
8129 {
8130 GetAsyncKeyState(i);
8131 }
8132
8133 SetDlgItemText(hDlg,IDC_LABEL_BLUE,HOTKEYS_LABEL_BLUE);
8134
8135 set_hotkeyinfo(hDlg);
8136
8137 PostMessage(hDlg,WM_COMMAND, CBN_SELCHANGE<<16, 0);
8138
8139 SetFocus(GetDlgItem(hDlg,IDC_HKCOMBO));
8140
8141
8142 return true;
8143 break;
8144 case WM_CLOSE:
8145 EndDialog(hDlg, 0);
8146 return TRUE;
8147 case WM_USER+46:
8148 // refresh command, for clicking away from a selected field
8149 index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0);
8150 set_hotkeyinfo(hDlg);
8151 return TRUE;
8152 case WM_USER+43:
8153 {
8154 //MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK);
8155 int modifiers = 0;
8156 if(GetAsyncKeyState(VK_MENU) || wParam == VK_MENU)
8157 modifiers |= CUSTKEY_ALT_MASK;
8158 if(GetAsyncKeyState(VK_CONTROL) || wParam == VK_CONTROL)
8159 modifiers |= CUSTKEY_CTRL_MASK;
8160 if(GetAsyncKeyState(VK_SHIFT) || wParam == VK_SHIFT)
8161 modifiers |= CUSTKEY_SHIFT_MASK;
8162
8163 int index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0);
8164
8165 which = GetDlgCtrlID((HWND)lParam);
8166
8167 switch(which)
8168 {
8169 case IDC_HOTKEY1:
8170 if(index == 0) CustomKeys.SpeedUp.key = wParam, CustomKeys.SpeedUp.modifiers = modifiers;
8171 if(index == 1) CustomKeys.BGL1.key = wParam, CustomKeys.BGL1.modifiers = modifiers;
8172 if(index == 2) CustomKeys.TurboA.key = wParam, CustomKeys.TurboA.modifiers = modifiers;
8173 if(index == 3) CustomKeys.SelectSave[0].key = wParam, CustomKeys.SelectSave[0].modifiers = modifiers;
8174 break;
8175 case IDC_HOTKEY2:
8176 if(index == 0) CustomKeys.SpeedDown.key = wParam, CustomKeys.SpeedDown.modifiers = modifiers;
8177 if(index == 1) CustomKeys.BGL2.key = wParam, CustomKeys.BGL2.modifiers = modifiers;
8178 if(index == 2) CustomKeys.TurboB.key = wParam, CustomKeys.TurboB.modifiers = modifiers;
8179 if(index == 3) CustomKeys.SelectSave[1].key = wParam, CustomKeys.SelectSave[1].modifiers = modifiers;
8180 break;
8181 case IDC_HOTKEY3:
8182 if(index == 0) CustomKeys.Pause.key = wParam, CustomKeys.Pause.modifiers = modifiers;
8183 if(index == 1) CustomKeys.BGL3.key = wParam, CustomKeys.BGL3.modifiers = modifiers;
8184 if(index == 2) CustomKeys.TurboY.key = wParam, CustomKeys.TurboY.modifiers = modifiers;
8185 if(index == 3) CustomKeys.SelectSave[2].key = wParam, CustomKeys.SelectSave[2].modifiers = modifiers;
8186 break;
8187 case IDC_HOTKEY4:
8188 if(index == 0) CustomKeys.FrameAdvance.key = wParam, CustomKeys.FrameAdvance.modifiers = modifiers;
8189 if(index == 1) CustomKeys.BGL4.key = wParam, CustomKeys.BGL4.modifiers = modifiers;
8190 if(index == 2) CustomKeys.TurboX.key = wParam, CustomKeys.TurboX.modifiers = modifiers;
8191 if(index == 3) CustomKeys.SelectSave[3].key = wParam, CustomKeys.SelectSave[3].modifiers = modifiers;
8192 break;
8193 case IDC_HOTKEY5:
8194 if(index == 0) CustomKeys.FastForward.key = wParam, CustomKeys.FastForward.modifiers = modifiers;
8195 if(index == 1) CustomKeys.BGL5.key = wParam, CustomKeys.BGL5.modifiers = modifiers;
8196 if(index == 2) CustomKeys.TurboL.key = wParam, CustomKeys.TurboL.modifiers = modifiers;
8197 if(index == 3) CustomKeys.SelectSave[4].key = wParam, CustomKeys.SelectSave[4].modifiers = modifiers;
8198 break;
8199 case IDC_HOTKEY6:
8200 if(index == 0) CustomKeys.SkipUp.key = wParam, CustomKeys.SkipUp.modifiers = modifiers;
8201 if(index == 1) CustomKeys.ClippingWindows.key = wParam, CustomKeys.ClippingWindows.modifiers = modifiers;
8202 if(index == 2) CustomKeys.TurboR.key = wParam, CustomKeys.TurboR.modifiers = modifiers;
8203 if(index == 3) CustomKeys.SelectSave[5].key = wParam, CustomKeys.SelectSave[5].modifiers = modifiers;
8204 break;
8205 case IDC_HOTKEY7:
8206 if(index == 0) CustomKeys.SkipDown.key = wParam, CustomKeys.SkipDown.modifiers = modifiers;
8207 if(index == 1) CustomKeys.Transparency.key = wParam, CustomKeys.Transparency.modifiers = modifiers;
8208 if(index == 2) CustomKeys.TurboStart.key = wParam, CustomKeys.TurboStart.modifiers = modifiers;
8209 if(index == 3) CustomKeys.SelectSave[6].key = wParam, CustomKeys.SelectSave[6].modifiers = modifiers;
8210 break;
8211 case IDC_HOTKEY8:
8212 if(index == 0) CustomKeys.ScopeTurbo.key = wParam, CustomKeys.ScopeTurbo.modifiers = modifiers;
8213 if(index == 1) CustomKeys.FastForwardToggle.key = wParam, CustomKeys.FastForwardToggle.modifiers = modifiers;
8214 if(index == 2) CustomKeys.TurboSelect.key = wParam, CustomKeys.TurboSelect.modifiers = modifiers;
8215 if(index == 3) CustomKeys.SelectSave[7].key = wParam, CustomKeys.SelectSave[7].modifiers = modifiers;
8216 break;
8217 case IDC_HOTKEY9:
8218 if(index == 0) CustomKeys.ScopePause.key = wParam, CustomKeys.ScopePause.modifiers = modifiers;
8219 if(index == 1) CustomKeys.Rewind.key = wParam, CustomKeys.Rewind.modifiers = modifiers;
8220 if(index == 2) CustomKeys.TurboLeft.key = wParam, CustomKeys.TurboLeft.modifiers = modifiers;
8221 if(index == 3) CustomKeys.SelectSave[8].key = wParam, CustomKeys.SelectSave[8].modifiers = modifiers;
8222 break;
8223 case IDC_HOTKEY10:
8224 if(index == 0) CustomKeys.ShowPressed.key = wParam, CustomKeys.ShowPressed.modifiers = modifiers;
8225 if(index == 1) CustomKeys.SwitchControllers.key = wParam, CustomKeys.SwitchControllers.modifiers = modifiers;
8226 if(index == 2) CustomKeys.TurboUp.key = wParam, CustomKeys.TurboUp.modifiers = modifiers;
8227 if(index == 3) CustomKeys.SelectSave[9].key = wParam, CustomKeys.SelectSave[9].modifiers = modifiers;
8228 break;
8229 case IDC_HOTKEY11:
8230 if(index == 0) CustomKeys.FrameCount.key = wParam, CustomKeys.FrameCount.modifiers = modifiers;
8231 if(index == 1) CustomKeys.JoypadSwap.key = wParam, CustomKeys.JoypadSwap.modifiers = modifiers;
8232 if(index == 2) CustomKeys.TurboRight.key = wParam, CustomKeys.TurboRight.modifiers = modifiers;
8233 break;
8234 case IDC_HOTKEY12:
8235 if(index == 0) CustomKeys.ReadOnly.key = wParam, CustomKeys.ReadOnly.modifiers = modifiers;
8236 if(index == 1) CustomKeys.ResetGame.key = wParam, CustomKeys.ResetGame.modifiers = modifiers;
8237 if(index == 2) CustomKeys.TurboDown.key = wParam, CustomKeys.TurboDown.modifiers = modifiers;
8238 // if(index == 3) CustomKeys.InterpMode7.key = wParam, CustomKeys.InterpMode7.modifiers = modifiers;
8239 break;
8240 case IDC_HOTKEY13:
8241 if(index == 0) CustomKeys.SaveScreenShot.key = wParam, CustomKeys.SaveScreenShot.modifiers = modifiers;
8242 if(index == 1) CustomKeys.ToggleCheats.key = wParam, CustomKeys.ToggleCheats.modifiers = modifiers;
8243 // if(index == 3) CustomKeys.BGLHack.key = wParam, CustomKeys.BGLHack.modifiers = modifiers;
8244 if(index == 3) CustomKeys.QuitS9X.key = wParam, CustomKeys.QuitS9X.modifiers = modifiers;
8245 break;
8246
8247 case IDC_SLOTPLUS:
8248 CustomKeys.SlotPlus.key = wParam;
8249 CustomKeys.SlotPlus.modifiers = modifiers;
8250 break;
8251
8252 case IDC_SLOTMINUS:
8253 CustomKeys.SlotMinus.key = wParam;
8254 CustomKeys.SlotMinus.modifiers = modifiers;
8255 break;
8256
8257 case IDC_SLOTLOAD:
8258 CustomKeys.SlotLoad.key = wParam;
8259 CustomKeys.SlotLoad.modifiers = modifiers;
8260 break;
8261
8262 case IDC_SLOTSAVE:
8263 CustomKeys.SlotSave.key = wParam;
8264 CustomKeys.SlotSave.modifiers = modifiers;
8265 break;
8266 }
8267
8268 if(which >= IDC_SAVE1 && which <= IDC_SAVE10)
8269 {
8270 CustomKeys.Save[which-IDC_SAVE1].key = wParam;
8271 CustomKeys.Save[which-IDC_SAVE1].modifiers = modifiers;
8272 }
8273 if(which >= IDC_SAVE11 && which <= IDC_SAVE20)
8274 {
8275 CustomKeys.Load[which-IDC_SAVE11].key = wParam;
8276 CustomKeys.Load[which-IDC_SAVE11].modifiers = modifiers;
8277 }
8278
8279 set_hotkeyinfo(hDlg);
8280 PostMessage(hDlg,WM_NEXTDLGCTL,0,0);
8281 // PostMessage(hDlg,WM_KILLFOCUS,0,0);
8282 }
8283 return true;
8284 case WM_COMMAND:
8285 switch(LOWORD(wParam))
8286 {
8287 case IDCANCEL:
8288 memcpy(&CustomKeys, &keys, sizeof(SCustomKeys));
8289 EndDialog(hDlg,0);
8290 break;
8291 case IDOK:
8292 WinSaveConfigFile();
8293 EndDialog(hDlg,0);
8294 break;
8295 }
8296 switch(HIWORD(wParam))
8297 {
8298 case CBN_SELCHANGE:
8299 index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0);
8300 SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_SETCURSEL,(WPARAM)index,0);
8301
8302 set_hotkeyinfo(hDlg);
8303
8304 SetFocus(GetDlgItem(hDlg,IDC_HKCOMBO));
8305
8306 break;
8307 }
8308 return FALSE;
8309
8310 }
8311
8312 return FALSE;
8313 }
8314
8315
8316 template<typename IntType>
ScanAddress(const TCHAR * str,IntType & value)8317 int ScanAddress(const TCHAR* str, IntType& value)
8318 {
8319 int ret = 0;
8320 if(_totlower(*str) == TEXT('s'))
8321 {
8322 ret = _stscanf(str+1, TEXT("%x"), &value);
8323 value += 0x7E0000 + 0x20000;
8324 }
8325 else if(_totlower(*str) == TEXT('i'))
8326 {
8327 ret = _stscanf(str+1, TEXT("%x"), &value);
8328 value += 0x7E0000 + 0x30000;
8329 }
8330 else
8331 {
8332 int plus = (*str == TEXT('0') && _totlower(str[1]) == TEXT('x')) ? 2 : 0;
8333 ret = _stscanf(str+plus, TEXT("%x"), &value);
8334 }
8335 return ret;
8336 }
8337
8338 enum CheatStatus{
8339 Untouched,
8340 Deleted,
8341 Modified
8342 };
8343 typedef struct{
8344 int* index;
8345 DWORD* state;
8346 }CheatTracker;
8347
8348 #define ITEM_QUERY(a, b, c, d, e) memset(&a, 0, sizeof(LV_ITEM)); \
8349 a.iItem= ListView_GetSelectionMark(GetDlgItem(hDlg, b)); \
8350 a.iSubItem=c; \
8351 a.mask=LVIF_TEXT; \
8352 a.pszText=d; \
8353 a.cchTextMax=e; \
8354 ListView_GetItem(GetDlgItem(hDlg, b), &a);
8355
DlgCheater(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)8356 INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
8357 {
8358 static bool internal_change;
8359 static bool has_sel;
8360 static int sel_idx;
8361 static uint8 new_sel;
8362 static CheatTracker ct;
8363 switch(msg)
8364 {
8365 case WM_INITDIALOG:
8366 WinRefreshDisplay();
8367
8368 ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_CHEAT_LIST), LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES);
8369
8370 SendDlgItemMessage(hDlg, IDC_CHEAT_CODE, EM_LIMITTEXT, 14, 0);
8371 SendDlgItemMessage(hDlg, IDC_CHEAT_DESCRIPTION, EM_LIMITTEXT, 22, 0);
8372 SendDlgItemMessage(hDlg, IDC_CHEAT_ADDRESS, EM_LIMITTEXT, 6, 0);
8373 SendDlgItemMessage(hDlg, IDC_CHEAT_BYTE, EM_LIMITTEXT, 3, 0);
8374
8375 LVCOLUMN col;
8376 TCHAR temp[32];
8377 lstrcpy(temp,SEARCH_COLUMN_ADDRESS);
8378 memset(&col, 0, sizeof(LVCOLUMN));
8379 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH;
8380 col.fmt=LVCFMT_LEFT;
8381 col.iOrder=0;
8382 col.cx=70;
8383 col.cchTextMax=7;
8384 col.pszText=temp;
8385
8386 ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 0, &col);
8387
8388 lstrcpy(temp,SEARCH_COLUMN_VALUE);
8389 memset(&col, 0, sizeof(LVCOLUMN));
8390 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
8391 col.fmt=LVCFMT_LEFT;
8392 col.iOrder=1;
8393 col.cx=43;
8394 col.cchTextMax=3;
8395 col.pszText=temp;
8396 col.iSubItem=1;
8397
8398 ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 1, &col);
8399
8400 lstrcpy(temp,SEARCH_COLUMN_DESCRIPTION);
8401 memset(&col, 0, sizeof(LVCOLUMN));
8402 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
8403 col.fmt=LVCFMT_LEFT;
8404 col.iOrder=2;
8405 col.cx=165;
8406 col.cchTextMax=32;
8407 col.pszText=temp;
8408 col.iSubItem=2;
8409
8410 ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 2, &col);
8411
8412 ct.index=new int[Cheat.num_cheats];
8413 ct.state=new DWORD[Cheat.num_cheats];
8414
8415 uint32 counter;
8416 for(counter=0; counter<Cheat.num_cheats; counter++)
8417 {
8418 TCHAR buffer[22];
8419 int curr_idx=-1;
8420 _stprintf(buffer, TEXT("%06X"), Cheat.c[counter].address);
8421 LVITEM lvi;
8422 memset(&lvi, 0, sizeof(LVITEM));
8423 lvi.mask=LVIF_TEXT;
8424 lvi.pszText=buffer;
8425 lvi.cchTextMax=7;
8426 lvi.iItem=counter;
8427 curr_idx=ListView_InsertItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi);
8428
8429 unsigned int k;
8430 for(k=0;k<counter;k++)
8431 {
8432 if(ct.index[k]>=curr_idx)
8433 ct.index[k]++;
8434 }
8435 ct.index[counter]=curr_idx;
8436 ct.state[counter]=Untouched;
8437
8438 _stprintf(buffer, TEXT("%02X"), Cheat.c[counter].byte);
8439 memset(&lvi, 0, sizeof(LVITEM));
8440 lvi.iItem=curr_idx;
8441 lvi.iSubItem=1;
8442 lvi.mask=LVIF_TEXT;
8443 lvi.pszText=buffer;
8444 lvi.cchTextMax=3;
8445 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8446
8447 lstrcpy(buffer,_tFromChar(Cheat.c[counter].name));
8448 memset(&lvi, 0, sizeof(LVITEM));
8449 lvi.iItem=curr_idx;
8450 lvi.iSubItem=2;
8451 lvi.mask=LVIF_TEXT;
8452 lvi.pszText=buffer;
8453 lvi.cchTextMax=23;
8454 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8455
8456 ListView_SetCheckState(GetDlgItem(hDlg,IDC_CHEAT_LIST), curr_idx, Cheat.c[counter].enabled);
8457
8458 }
8459 return true;
8460 case WM_PAINT:
8461 {
8462 PAINTSTRUCT ps;
8463 BeginPaint (hDlg, &ps);
8464
8465 EndPaint (hDlg, &ps);
8466 }
8467 return true;
8468 case WM_NOTIFY:
8469 {
8470 switch(LOWORD(wParam))
8471 {
8472 case IDC_CHEAT_LIST:
8473 if(0==ListView_GetSelectedCount(GetDlgItem(hDlg, IDC_CHEAT_LIST)))
8474 {
8475 EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), false);
8476 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
8477 has_sel=false;
8478 sel_idx=-1;
8479 }
8480 else
8481 {
8482 EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), true);
8483 if(!has_sel||sel_idx!=ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST)))
8484 {
8485 new_sel=3;
8486 //change
8487 TCHAR buf[25];
8488 LV_ITEM lvi;
8489
8490 ITEM_QUERY (lvi, IDC_CHEAT_LIST, 0, buf, 7);
8491
8492 SetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, lvi.pszText);
8493
8494 ITEM_QUERY (lvi, IDC_CHEAT_LIST, 1, &buf[lstrlen(buf)], 3);
8495
8496 SetDlgItemText(hDlg, IDC_CHEAT_CODE, buf);
8497 TCHAR temp[4];
8498 int q;
8499 _stscanf(lvi.pszText, TEXT("%02X"), &q);
8500 _stprintf(temp, TEXT("%d"), q);
8501 SetDlgItemText(hDlg, IDC_CHEAT_BYTE, temp);
8502
8503 ITEM_QUERY (lvi, IDC_CHEAT_LIST, 2, buf, 24);
8504
8505 internal_change=true;
8506 SetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, lvi.pszText);
8507
8508 }
8509 sel_idx=ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST));
8510 has_sel=true;
8511 }
8512
8513 return true;
8514 default: return false;
8515 }
8516 }
8517 case WM_COMMAND:
8518 {
8519 switch(LOWORD(wParam))
8520 {
8521 case IDC_CHEAT_DESCRIPTION:
8522 {
8523 switch(HIWORD(wParam))
8524 {
8525 case EN_CHANGE:
8526
8527 if(internal_change)
8528 {
8529 internal_change=!internal_change;
8530 return false;
8531 }
8532 if(!has_sel)
8533 return true;
8534 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true);
8535 return true;
8536 }
8537 break;
8538
8539 }
8540 case IDC_ADD_CHEAT:
8541 {
8542 char temp[24];
8543 TCHAR tempDesc[24];
8544 GetDlgItemTextA(hDlg, IDC_CHEAT_CODE, temp, 23);
8545 if(strcmp(temp, ""))
8546 {
8547 int j;
8548 bool skip=false;
8549 int count=1;
8550 uint32 addy;
8551 uint8 byte[3];
8552 //test game genie
8553 if (NULL==S9xGameGenieToRaw (temp, addy, byte[0]))
8554 skip=true;
8555 //test goldfinger
8556
8557 // if(!skip
8558
8559 //test PAR
8560
8561 if(!skip)
8562 {
8563 if(NULL==S9xProActionReplayToRaw(temp, addy, byte[0]))
8564 skip=true;
8565 }
8566
8567 if(!skip)
8568 return 0;
8569
8570 for(j=0; j<count; j++)
8571 {
8572 TCHAR buffer[7];
8573 int curr_idx=-1;
8574 _stprintf(buffer, TEXT("%06X"), addy);
8575 LVITEM lvi;
8576 memset(&lvi, 0, sizeof(LVITEM));
8577 lvi.mask=LVIF_TEXT;
8578 lvi.pszText=buffer;
8579 lvi.cchTextMax=6;
8580 lvi.iItem=ListView_GetItemCount(GetDlgItem(hDlg,IDC_CHEAT_LIST));
8581 curr_idx=ListView_InsertItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi);
8582
8583 unsigned int k;
8584 for(k=0;k<Cheat.num_cheats;k++)
8585 {
8586 if(ct.index[k]>=curr_idx)
8587 ct.index[k]++;
8588 }
8589
8590
8591 _stprintf(buffer, TEXT("%02X"), byte[j]);
8592 memset(&lvi, 0, sizeof(LVITEM));
8593 lvi.iItem=curr_idx;
8594 lvi.iSubItem=1;
8595 lvi.mask=LVIF_TEXT;
8596 lvi.pszText=buffer;
8597 lvi.cchTextMax=2;
8598 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8599
8600
8601 GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, tempDesc, 23);
8602
8603 memset(&lvi, 0, sizeof(LVITEM));
8604 lvi.iItem=curr_idx;
8605 lvi.iSubItem=2;
8606 lvi.mask=LVIF_TEXT;
8607 lvi.pszText=tempDesc;
8608 lvi.cchTextMax=23;
8609 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8610
8611 addy++;
8612
8613
8614 }
8615 }
8616 else
8617 {
8618 uint8 byte;
8619 TCHAR buffer[7];
8620 TCHAR buffer2[7];
8621
8622 GetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, buffer, 7);
8623 GetDlgItemText(hDlg, IDC_CHEAT_BYTE, buffer2, 7);
8624
8625 int curr_idx=-1;
8626 LVITEM lvi;
8627 memset(&lvi, 0, sizeof(LVITEM));
8628 lvi.mask=LVIF_TEXT;
8629 lvi.pszText=buffer;
8630 lvi.cchTextMax=6;
8631 lvi.iItem=0;
8632 curr_idx=ListView_InsertItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi);
8633
8634 int scanres;
8635 if(buffer2[0]=='$')
8636 _stscanf(buffer2,TEXT("$%2X"), (unsigned int*)&scanres);
8637 else _stscanf(buffer2,TEXT("%d"), &scanres);
8638 byte = (uint8)(scanres & 0xff);
8639
8640 _stprintf(buffer2, TEXT("%02X"), byte);
8641
8642 memset(&lvi, 0, sizeof(LVITEM));
8643 lvi.iItem=curr_idx;
8644 lvi.iSubItem=1;
8645 lvi.mask=LVIF_TEXT;
8646 lvi.pszText=buffer2;
8647 lvi.cchTextMax=2;
8648 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8649
8650 GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, tempDesc, 23);
8651
8652 memset(&lvi, 0, sizeof(LVITEM));
8653 lvi.iItem=curr_idx;
8654 lvi.iSubItem=2;
8655 lvi.mask=LVIF_TEXT;
8656 lvi.pszText=tempDesc;
8657 lvi.cchTextMax=23;
8658 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8659 }
8660 }
8661 break;
8662 case IDC_UPDATE_CHEAT:
8663 {
8664 TCHAR temp[24];
8665 char code[24];
8666 GetDlgItemText(hDlg, IDC_CHEAT_CODE, temp, 23);
8667 strcpy(code,_tToChar(temp));
8668 if(strcmp(code, ""))
8669 {
8670 int j;
8671 bool skip=false;
8672 int count=1;
8673 uint32 addy;
8674 uint8 byte[3];
8675 //test game genie
8676 if (NULL==S9xGameGenieToRaw (code, addy, byte[0]))
8677 skip=true;
8678 //test goldfinger
8679
8680 // if(!skip
8681
8682 //test PAR
8683
8684 if(!skip)
8685 {
8686 if(NULL==S9xProActionReplayToRaw(code, addy, byte[0]))
8687 skip=true;
8688 }
8689
8690 if(!skip)
8691 return 0;
8692
8693 for(j=0;j<(int)Cheat.num_cheats;j++)
8694 {
8695 if(ct.index[j]==sel_idx)
8696 ct.state[j]=Modified;
8697 }
8698
8699 for(j=0; j<count; j++)
8700 {
8701 TCHAR buffer[7];
8702 // int curr_idx=-1;
8703 _stprintf(buffer, TEXT("%06X"), addy);
8704 LVITEM lvi;
8705 memset(&lvi, 0, sizeof(LVITEM));
8706 lvi.mask=LVIF_TEXT;
8707 lvi.pszText=buffer;
8708 lvi.cchTextMax=6;
8709 lvi.iItem=sel_idx;
8710 ListView_SetItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi);
8711
8712 _stprintf(buffer, TEXT("%02X"), byte[j]);
8713 memset(&lvi, 0, sizeof(LVITEM));
8714 lvi.iItem=sel_idx;
8715 lvi.iSubItem=1;
8716 lvi.mask=LVIF_TEXT;
8717 lvi.pszText=buffer;
8718 lvi.cchTextMax=2;
8719 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8720
8721 GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, temp, 23);
8722
8723 memset(&lvi, 0, sizeof(LVITEM));
8724 lvi.iItem=sel_idx;
8725 lvi.iSubItem=2;
8726 lvi.mask=LVIF_TEXT;
8727 lvi.pszText=temp;
8728 lvi.cchTextMax=23;
8729 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8730
8731 addy++;
8732
8733
8734 }
8735 }
8736 else
8737 {
8738 uint8 byte;
8739 TCHAR buffer[7];
8740
8741 GetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, buffer, 7);
8742 int j;
8743 for(j=0;j<(int)Cheat.num_cheats;j++)
8744 {
8745 if(ct.index[j]==sel_idx)
8746 ct.state[j]=Modified;
8747 }
8748
8749 // int curr_idx=-1;
8750 LVITEM lvi;
8751 memset(&lvi, 0, sizeof(LVITEM));
8752 lvi.mask=LVIF_TEXT;
8753 lvi.pszText=buffer;
8754 lvi.cchTextMax=6;
8755 lvi.iItem=sel_idx;
8756 ListView_SetItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi);
8757
8758
8759 GetDlgItemText(hDlg, IDC_CHEAT_BYTE, buffer, 7);
8760
8761 int scanres;
8762 if(buffer[0]==TEXT('$'))
8763 _stscanf(buffer,TEXT("$%2X"), (unsigned int*)&scanres);
8764 else _stscanf(buffer,TEXT("%d"), &scanres);
8765 byte = (uint8)(scanres & 0xff);
8766
8767 _stprintf(buffer, TEXT("%02X"), byte);
8768
8769 memset(&lvi, 0, sizeof(LVITEM));
8770 lvi.iItem=sel_idx;
8771 lvi.iSubItem=1;
8772 lvi.mask=LVIF_TEXT;
8773 lvi.pszText=buffer;
8774 lvi.cchTextMax=2;
8775 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8776
8777 GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, temp, 23);
8778
8779 memset(&lvi, 0, sizeof(LVITEM));
8780 lvi.iItem=sel_idx;
8781 lvi.iSubItem=2;
8782 lvi.mask=LVIF_TEXT;
8783 lvi.pszText=temp;
8784 lvi.cchTextMax=23;
8785 SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi);
8786 }
8787 }
8788
8789 break;
8790 case IDC_DELETE_CHEAT:
8791 {
8792 unsigned int j;
8793 for(j=0;j<Cheat.num_cheats;j++)
8794 {
8795 if(ct.index[j]==sel_idx)
8796 ct.state[j]=Deleted;
8797 }
8798 for(j=0;j<Cheat.num_cheats;j++)
8799 {
8800 if(ct.index[j]>sel_idx)
8801 ct.index[j]--;
8802 }
8803 }
8804 ListView_DeleteItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), sel_idx);
8805
8806 break;
8807 case IDC_CLEAR_CHEATS:
8808 internal_change = true;
8809 SetDlgItemText(hDlg,IDC_CHEAT_CODE,TEXT(""));
8810 SetDlgItemText(hDlg,IDC_CHEAT_ADDRESS,TEXT(""));
8811 SetDlgItemText(hDlg,IDC_CHEAT_BYTE,TEXT(""));
8812 SetDlgItemText(hDlg,IDC_CHEAT_DESCRIPTION,TEXT(""));
8813 ListView_SetItemState(GetDlgItem(hDlg, IDC_CHEAT_LIST),sel_idx, 0, LVIS_SELECTED|LVIS_FOCUSED);
8814 ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST), -1);
8815 sel_idx=-1;
8816 has_sel=false;
8817 break;
8818 case IDC_CHEAT_CODE:
8819 {
8820 uint32 j, k;
8821 long index;
8822 char buffer[15];
8823 char buffer2[15];
8824 POINT point;
8825 switch(HIWORD(wParam))
8826 {
8827 case EN_CHANGE:
8828 if(internal_change)
8829 {
8830 internal_change=false;
8831 return true;
8832 }
8833 SendMessageA((HWND)lParam, WM_GETTEXT, 15,(LPARAM)buffer);
8834 GetCaretPos(&point);
8835
8836 index = SendMessageA((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16)));
8837
8838 k=0;
8839 for(j=0; j<strlen(buffer);j++)
8840 {
8841 if( (buffer[j]>='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F') || buffer[j]=='-' || buffer[j]=='X')
8842 {
8843 buffer2[k]=buffer[j];
8844 k++;
8845 }
8846 else index --;
8847 }
8848 buffer2[k]='\0';
8849
8850 if(has_sel&&!new_sel&&strlen(buffer2)!=0)
8851 {
8852 SetDlgItemTextA(hDlg, IDC_CHEAT_ADDRESS, "");
8853 SetDlgItemTextA(hDlg, IDC_CHEAT_BYTE, "");
8854
8855 }
8856
8857 if(new_sel!=0)
8858 new_sel--;
8859
8860 internal_change=true;
8861 SendMessageA((HWND)lParam, WM_SETTEXT, 0,(LPARAM)buffer2);
8862 SendMessageA((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index);
8863
8864 uint32 addy;
8865 uint8 val;
8866 bool8 sram;
8867 uint8 bytes[3];
8868 if(NULL==S9xGameGenieToRaw(buffer2, addy, val)||NULL==S9xProActionReplayToRaw(buffer2, addy, val)||NULL==S9xGoldFingerToRaw(buffer2, addy, sram, val, bytes))
8869 {
8870 if(has_sel)
8871 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true);
8872 else EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
8873 EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), true);
8874 }
8875 else
8876 {
8877 EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), false);
8878 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
8879 }
8880
8881 // SetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, "");
8882 // SetDlgItemText(hDlg, IDC_CHEAT_BYTE, "");
8883 break;
8884 }
8885 break;
8886 }
8887 case IDC_CHEAT_ADDRESS:
8888 {
8889 uint32 j, k;
8890 long index;
8891 char buffer[7];
8892 char buffer2[7];
8893 POINT point;
8894 switch(HIWORD(wParam))
8895 {
8896 case EN_CHANGE:
8897 if(internal_change)
8898 {
8899 internal_change=false;
8900 return true;
8901 }
8902 SendMessageA((HWND)lParam, WM_GETTEXT, 7,(LPARAM)buffer);
8903 GetCaretPos(&point);
8904
8905 index = SendMessageA((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16)));
8906
8907 k=0;
8908 for(j=0; j<strlen(buffer);j++)
8909 {
8910 if( (buffer[j]>='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F'))
8911 {
8912 buffer2[k]=buffer[j];
8913 k++;
8914 }
8915 else index --;
8916 }
8917 buffer2[k]='\0';
8918
8919
8920 internal_change=true;
8921 SendMessageA((HWND)lParam, WM_SETTEXT, 0,(LPARAM)buffer2);
8922 SendMessageA((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index);
8923
8924 SendMessageA(GetDlgItem(hDlg, IDC_CHEAT_BYTE), WM_GETTEXT, 4,(LPARAM)buffer);
8925
8926 if(has_sel&&!new_sel&&0!=strlen(buffer2))
8927 SetDlgItemTextA(hDlg, IDC_CHEAT_CODE, "");
8928
8929 if(new_sel!=0)
8930 new_sel--;
8931
8932 if(strlen(buffer2)!=0 && strlen(buffer) !=0)
8933 {
8934 if(has_sel)
8935 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true);
8936 else EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
8937 EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), true);
8938 }
8939 else
8940 {
8941 EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), false);
8942 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
8943 }
8944
8945 break;
8946 }
8947 break;
8948 }
8949 case IDC_CHEAT_BYTE:
8950 {
8951 uint32 j, k;
8952 long index;
8953 char buffer[4];
8954 char buffer2[4];
8955 POINT point;
8956 switch(HIWORD(wParam))
8957 {
8958 case EN_CHANGE:
8959 if(internal_change)
8960 {
8961 internal_change=false;
8962 return true;
8963 }
8964 SendMessageA((HWND)lParam, WM_GETTEXT, 4,(LPARAM)buffer);
8965 GetCaretPos(&point);
8966
8967 index = SendMessageA((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16)));
8968
8969 k=0;
8970 for(j=0; j<strlen(buffer);j++)
8971 {
8972 if( (buffer[j]>='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F') || buffer[j]=='$')
8973 {
8974 buffer2[k]=buffer[j];
8975 k++;
8976 }
8977 else index --;
8978 }
8979 buffer2[k]='\0';
8980
8981 if(has_sel&&!new_sel&&0!=strlen(buffer2))
8982 SetDlgItemTextA(hDlg, IDC_CHEAT_CODE, "");
8983
8984 if(new_sel!=0)
8985 new_sel--;
8986
8987 internal_change=true;
8988 SendMessageA((HWND)lParam, WM_SETTEXT, 0,(LPARAM)buffer2);
8989 SendMessageA((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index);
8990
8991 SendMessageA(GetDlgItem(hDlg, IDC_CHEAT_ADDRESS), WM_GETTEXT, 7,(LPARAM)buffer);
8992 if(strlen(buffer2)!=0 && strlen(buffer) !=0)
8993 {
8994 if(has_sel)
8995 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true);
8996 else EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
8997 EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), true);
8998 }
8999 else
9000 {
9001 EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), false);
9002 EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
9003 }
9004 //SetDlgItemText(hDlg, IDC_CHEAT_CODE, "");
9005 break;
9006 }
9007 break;
9008 }
9009 case IDOK:
9010 {
9011 int k,l;
9012 bool hit;
9013 unsigned int scanned;
9014 for(k=0;k<ListView_GetItemCount(GetDlgItem(hDlg, IDC_CHEAT_LIST)); k++)
9015 {
9016 hit=false;
9017 for(l=0;l<(int)Cheat.num_cheats;l++)
9018 {
9019 if(ct.index[l]==k)
9020 {
9021 hit=true;
9022 Cheat.c[l].enabled=ListView_GetCheckState(GetDlgItem(hDlg, IDC_CHEAT_LIST),l);
9023 if(ct.state[l]==Untouched)
9024 l=Cheat.num_cheats;
9025 else if(ct.state[l]==(unsigned long)Modified)
9026 {
9027 if(Cheat.c[l].enabled)
9028 S9xDisableCheat(l);
9029 //update me!
9030 //get these!
9031
9032 TCHAR buf[25];
9033 LV_ITEM lvi;
9034 memset(&lvi, 0, sizeof(LV_ITEM));
9035 lvi.iItem= k;
9036 lvi.mask=LVIF_TEXT;
9037 lvi.pszText=buf;
9038 lvi.cchTextMax=7;
9039
9040 ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
9041
9042 ScanAddress(lvi.pszText, scanned);
9043 Cheat.c[l].address = scanned;
9044
9045 memset(&lvi, 0, sizeof(LV_ITEM));
9046 lvi.iItem= k;
9047 lvi.iSubItem=1;
9048 lvi.mask=LVIF_TEXT;
9049 lvi.pszText=buf;
9050 lvi.cchTextMax=3;
9051
9052 ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
9053
9054 _stscanf(lvi.pszText, TEXT("%02X"), &scanned);
9055 Cheat.c[l].byte = (uint8)(scanned & 0xff);
9056
9057 memset(&lvi, 0, sizeof(LV_ITEM));
9058 lvi.iItem= k;
9059 lvi.iSubItem=2;
9060 lvi.mask=LVIF_TEXT;
9061 lvi.pszText=buf;
9062 lvi.cchTextMax=24;
9063
9064 ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
9065
9066 strcpy(Cheat.c[l].name,_tToChar(lvi.pszText));
9067
9068 Cheat.c[l].enabled=ListView_GetCheckState(GetDlgItem(hDlg, IDC_CHEAT_LIST),k);
9069
9070 if(Cheat.c[l].enabled)
9071 S9xEnableCheat(l);
9072 }
9073
9074 }
9075 }
9076 if(!hit)
9077 {
9078 uint32 address;
9079 uint8 byte;
9080 bool8 enabled;
9081 TCHAR buf[25];
9082 LV_ITEM lvi;
9083 memset(&lvi, 0, sizeof(LV_ITEM));
9084 lvi.iItem= k;
9085 lvi.mask=LVIF_TEXT;
9086 lvi.pszText=buf;
9087 lvi.cchTextMax=7;
9088
9089 ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
9090
9091 ScanAddress(lvi.pszText, scanned);
9092 address = scanned;
9093
9094 memset(&lvi, 0, sizeof(LV_ITEM));
9095 lvi.iItem= k;
9096 lvi.iSubItem=1;
9097 lvi.mask=LVIF_TEXT;
9098 lvi.pszText=buf;
9099 lvi.cchTextMax=3;
9100
9101 ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
9102
9103 _stscanf(lvi.pszText, TEXT("%02X"), &scanned);
9104 byte = (uint8)(scanned & 0xff);
9105
9106 enabled=ListView_GetCheckState(GetDlgItem(hDlg, IDC_CHEAT_LIST),k);
9107
9108 S9xAddCheat(enabled,true,address,byte);
9109
9110 memset(&lvi, 0, sizeof(LV_ITEM));
9111 lvi.iItem= k;
9112 lvi.iSubItem=2;
9113 lvi.mask=LVIF_TEXT;
9114 lvi.pszText=buf;
9115 lvi.cchTextMax=24;
9116
9117 ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
9118
9119 strcpy(Cheat.c[Cheat.num_cheats-1].name, _tToChar(lvi.pszText));
9120
9121
9122 }
9123 }
9124
9125 for(l=(int)Cheat.num_cheats-1;l>=0;l--)
9126 {
9127 if(ct.state[l]==Deleted)
9128 {
9129 S9xDeleteCheat(l);
9130 }
9131 }
9132 }
9133 case IDCANCEL:
9134 delete [] ct.index;
9135 delete [] ct.state;
9136 EndDialog(hDlg, 0);
9137 return true;
9138 default:return false;
9139 }
9140 }
9141 default: return false;
9142 }
9143 }
9144
9145
9146 #define TEST_BIT(a,v) \
9147 ((a)[(v) >> 5] & (1 << ((v) & 31)))
9148
CheatCount(int byteSub)9149 static inline int CheatCount(int byteSub)
9150 {
9151 int a, b=0;
9152 // for(a=0;a<0x32000-byteSub;a++)
9153 for(a=0;a<0x30000-byteSub;a++) // hide IRAM from cheat dialog (it seems not to be searhed correctly)
9154 {
9155 if(TEST_BIT(Cheat.ALL_BITS, a))
9156 b++;
9157 }
9158 return b;
9159 }
9160
9161
9162 struct ICheat
9163 {
9164 uint32 address;
9165 uint32 new_val;
9166 uint32 saved_val;
9167 int size;
9168 bool8 enabled;
9169 bool8 saved;
9170 char name [22];
9171 int format;
9172 };
9173
TestRange(int val_type,S9xCheatDataSize bytes,uint32 value)9174 bool TestRange(int val_type, S9xCheatDataSize bytes, uint32 value)
9175 {
9176 if(val_type!=2)
9177 {
9178 if(bytes==S9X_8_BITS)
9179 {
9180 if(value<256)
9181 return true;
9182 else return false;
9183 }
9184 if(bytes==S9X_16_BITS)
9185 {
9186 if(value<65536)
9187 return true;
9188 else return false;
9189 }
9190 if(bytes==S9X_24_BITS)
9191 {
9192 if(value<16777216)
9193 return true;
9194 else return false;
9195 }
9196 //if it reads in, it's a valid 32-bit unsigned!
9197 return true;
9198 }
9199 else
9200 {
9201 if(bytes==S9X_8_BITS)
9202 {
9203 if((int32)value<128 && (int32)value >= -128)
9204 return true;
9205 else return false;
9206 }
9207 if(bytes==S9X_16_BITS)
9208 {
9209 if((int32)value<32768 && (int32)value >= -32768)
9210 return true;
9211 else return false;
9212 }
9213 if(bytes==S9X_24_BITS)
9214 {
9215 if((int32)value<8388608 && (int32)value >= -8388608)
9216 return true;
9217 else return false;
9218 }
9219 //should be handled by sscanf
9220 return true;
9221 }
9222 }
9223
9224
DlgCheatSearch(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)9225 INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
9226 {
9227 static S9xCheatDataSize bytes;
9228 static int val_type;
9229 static int use_entered;
9230 static S9xCheatComparisonType comp_type;
9231 switch(msg)
9232 {
9233 case WM_INITDIALOG:
9234 {
9235 WinRefreshDisplay();
9236 if(val_type==0)
9237 val_type=1;
9238 ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_ADDYS), LVS_EX_FULLROWSELECT);
9239
9240 //defaults
9241 SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_CHECKED, 0);
9242 if(!use_entered)
9243 SendDlgItemMessage(hDlg, IDC_PREV, BM_SETCHECK, BST_CHECKED, 0);
9244 else if(use_entered==1)
9245 {
9246 SendDlgItemMessage(hDlg, IDC_ENTERED, BM_SETCHECK, BST_CHECKED, 0);
9247 EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true);
9248 EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true);
9249 }
9250 else if(use_entered==2)
9251 {
9252 SendDlgItemMessage(hDlg, IDC_ENTEREDADDRESS, BM_SETCHECK, BST_CHECKED, 0);
9253 EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true);
9254 EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true);
9255 }
9256 SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0);
9257 SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0);
9258
9259 if(comp_type==S9X_GREATER_THAN)
9260 {
9261 SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0);
9262 SendDlgItemMessage(hDlg, IDC_GREATER_THAN, BM_SETCHECK, BST_CHECKED, 0);
9263 }
9264 else if(comp_type==S9X_LESS_THAN_OR_EQUAL)
9265 {
9266 SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0);
9267 SendDlgItemMessage(hDlg, IDC_LESS_THAN_EQUAL, BM_SETCHECK, BST_CHECKED, 0);
9268
9269 }
9270 else if(comp_type==S9X_GREATER_THAN_OR_EQUAL)
9271 {
9272 SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0);
9273 SendDlgItemMessage(hDlg, IDC_GREATER_THAN_EQUAL, BM_SETCHECK, BST_CHECKED, 0);
9274
9275 }
9276 else if(comp_type==S9X_EQUAL)
9277 {
9278 SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0);
9279 SendDlgItemMessage(hDlg, IDC_EQUAL, BM_SETCHECK, BST_CHECKED, 0);
9280
9281 }
9282 else if(comp_type==S9X_NOT_EQUAL)
9283 {
9284 SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0);
9285 SendDlgItemMessage(hDlg, IDC_NOT_EQUAL, BM_SETCHECK, BST_CHECKED, 0);
9286
9287 }
9288
9289 if(val_type==2)
9290 {
9291 SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_UNCHECKED, 0);
9292 SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0);
9293
9294 }
9295 else if(val_type==3)
9296 {
9297 SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_UNCHECKED, 0);
9298 SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_CHECKED, 0);
9299 }
9300
9301 if(bytes==S9X_16_BITS)
9302 {
9303 SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_UNCHECKED, 0);
9304 SendDlgItemMessage(hDlg, IDC_2_BYTE, BM_SETCHECK, BST_CHECKED, 0);
9305 }
9306 else if(bytes==S9X_24_BITS)
9307 {
9308 SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_UNCHECKED, 0);
9309 SendDlgItemMessage(hDlg, IDC_3_BYTE, BM_SETCHECK, BST_CHECKED, 0);
9310 }
9311 else if(bytes==S9X_32_BITS)
9312 {
9313 SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_UNCHECKED, 0);
9314 SendDlgItemMessage(hDlg, IDC_4_BYTE, BM_SETCHECK, BST_CHECKED, 0);
9315 }
9316
9317 LVCOLUMN col;
9318 TCHAR temp[32];
9319 lstrcpy(temp,TEXT("Address"));
9320 memset(&col, 0, sizeof(LVCOLUMN));
9321 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH;
9322 col.fmt=LVCFMT_LEFT;
9323 col.iOrder=0;
9324 col.cx=70;
9325 col.cchTextMax=7;
9326 col.pszText=temp;
9327
9328 ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 0, &col);
9329
9330 lstrcpy(temp,TEXT("Curr. Value"));
9331 memset(&col, 0, sizeof(LVCOLUMN));
9332 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
9333 col.fmt=LVCFMT_LEFT;
9334 col.iOrder=1;
9335 col.cx=104;
9336 col.cchTextMax=3;
9337 col.pszText=temp;
9338 col.iSubItem=1;
9339
9340 ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 1, &col);
9341
9342 lstrcpy(temp,TEXT("Prev. Value"));
9343 memset(&col, 0, sizeof(LVCOLUMN));
9344 col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
9345 col.fmt=LVCFMT_LEFT;
9346 col.iOrder=2;
9347 col.cx=104;
9348 col.cchTextMax=32;
9349 col.pszText=temp;
9350 col.iSubItem=2;
9351
9352 ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 2, &col);
9353
9354 {
9355 int l = CheatCount(bytes);
9356 ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l);
9357 }
9358
9359 }
9360 return true;
9361
9362 case WM_DESTROY:
9363 {
9364 cheatSearchHWND = NULL;
9365 S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
9366 break;
9367 }
9368
9369 case WM_PAINT:
9370 {
9371 PAINTSTRUCT ps;
9372 BeginPaint (hDlg, &ps);
9373
9374 EndPaint (hDlg, &ps);
9375 }
9376 return true;
9377 case WM_NOTIFY:
9378 {
9379 static int selectionMarkOverride = -1;
9380 static int foundItemOverride = -1;
9381 if(wParam == IDC_ADDYS)
9382 {
9383 NMHDR * nmh=(NMHDR*)lParam;
9384 if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && nmh->code == LVN_GETDISPINFO)
9385 {
9386 static TCHAR buf[12]; // the following code assumes this variable is static
9387 int i, j;
9388 NMLVDISPINFO * nmlvdi=(NMLVDISPINFO*)lParam;
9389 j=nmlvdi->item.iItem;
9390 j++;
9391 for(i=0;i<(0x32000-bytes)&& j>0;i++)
9392 {
9393 if(TEST_BIT(Cheat.ALL_BITS, i))
9394 j--;
9395 }
9396 if (i>=0x32000 && j!=0)
9397 {
9398 return false;
9399 }
9400 i--;
9401 if(j=nmlvdi->item.iSubItem==0)
9402 {
9403 if(i < 0x20000)
9404 _stprintf(buf, TEXT("%06X"), i+0x7E0000);
9405 else if(i < 0x30000)
9406 _stprintf(buf, TEXT("s%05X"), i-0x20000);
9407 else
9408 _stprintf(buf, TEXT("i%05X"), i-0x30000);
9409 nmlvdi->item.pszText=buf;
9410 nmlvdi->item.cchTextMax=8;
9411 }
9412 if(j=nmlvdi->item.iSubItem==1)
9413 {
9414 int q=0, r=0;
9415 if(i < 0x20000)
9416 for(r=0;r<=bytes;r++)
9417 q+=(Cheat.RAM[i+r])<<(8*r);
9418 else if(i < 0x30000)
9419 for(r=0;r<=bytes;r++)
9420 q+=(Cheat.SRAM[(i-0x20000)+r])<<(8*r);
9421 else
9422 for(r=0;r<=bytes;r++)
9423 q+=(Cheat.FillRAM[(i-0x30000)+r])<<(8*r);
9424 //needs to account for size
9425 switch(val_type)
9426 {
9427 case 1:
9428 _stprintf(buf, TEXT("%u"), q);
9429 break;
9430 case 3:
9431 {
9432 switch(bytes)
9433 {
9434 default:
9435 case S9X_8_BITS: _stprintf(buf, TEXT("%02X"), q&0xFF);break;
9436 case S9X_16_BITS: _stprintf(buf, TEXT("%04X"), q&0xFFFF); break;
9437 case S9X_24_BITS: _stprintf(buf, TEXT("%06X"), q&0xFFFFFF);break;
9438 case S9X_32_BITS: _stprintf(buf, TEXT("%08X"), q);break;
9439 }
9440 }
9441 break;
9442 case 2:
9443 default:
9444 switch(bytes)
9445 {
9446 default:
9447 case S9X_8_BITS:
9448 if((q-128)<0)
9449 _stprintf(buf, TEXT("%d"), q&0xFF);
9450 else _stprintf(buf, TEXT("%d"), q-256);
9451 break;
9452 case S9X_16_BITS:
9453 if((q-32768)<0)
9454 _stprintf(buf, TEXT("%d"), q&0xFFFF);
9455 else _stprintf(buf, TEXT("%d"), q-65536);
9456 break;
9457 case S9X_24_BITS:
9458 if((q-0x800000)<0)
9459 _stprintf(buf, TEXT("%d"), q&0xFFFFFF);
9460 else _stprintf(buf, TEXT("%d"), q-0x1000000);
9461 break;
9462
9463 case S9X_32_BITS: _stprintf(buf, TEXT("%d"), q);break;
9464 }
9465 break;
9466 }
9467 nmlvdi->item.pszText=buf;
9468 nmlvdi->item.cchTextMax=4;
9469 }
9470 if(j=nmlvdi->item.iSubItem==2)
9471 {
9472 int q=0, r=0;
9473 if(i < 0x20000)
9474 for(r=0;r<=bytes;r++)
9475 q+=(Cheat.CWRAM[i+r])<<(8*r);
9476 else if(i < 0x30000)
9477 for(r=0;r<=bytes;r++)
9478 q+=(Cheat.CSRAM[(i-0x20000)+r])<<(8*r);
9479 else
9480 for(r=0;r<=bytes;r++)
9481 q+=(Cheat.CIRAM[(i-0x30000)+r])<<(8*r);
9482 //needs to account for size
9483 switch(val_type)
9484 {
9485 case 1:
9486 _stprintf(buf, TEXT("%u"), q);
9487 break;
9488 case 3:
9489 {
9490 switch(bytes)
9491 {
9492 default:
9493 case S9X_8_BITS:_stprintf(buf, TEXT("%02X"), q&0xFF);break;
9494 case S9X_16_BITS: _stprintf(buf, TEXT("%04X"), q&0xFFFF); break;
9495 case S9X_24_BITS: _stprintf(buf, TEXT("%06X"), q&0xFFFFFF);break;
9496 case S9X_32_BITS: _stprintf(buf, TEXT("%08X"), q);break;
9497 }
9498 break;
9499 }
9500 case 2:
9501 default:
9502 switch(bytes)
9503 {
9504 default:
9505 case S9X_8_BITS:
9506 if((q-128)<0)
9507 _stprintf(buf, TEXT("%d"), q&0xFF);
9508 else _stprintf(buf, TEXT("%d"), q-256);
9509 break;
9510 case S9X_16_BITS:
9511 if((q-32768)<0)
9512 _stprintf(buf, TEXT("%d"), q&0xFFFF);
9513 else _stprintf(buf, TEXT("%d"), q-65536);
9514 break;
9515 case S9X_24_BITS:
9516 if((q-0x800000)<0)
9517 _stprintf(buf, TEXT("%d"), q&0xFFFFFF);
9518 else _stprintf(buf, TEXT("%d"), q-0x1000000);
9519 break;
9520
9521 case S9X_32_BITS: _stprintf(buf, TEXT("%d"), q);break;
9522 }
9523 break;
9524 }
9525 nmlvdi->item.pszText=buf;
9526 nmlvdi->item.cchTextMax=4;
9527 }
9528 // nmlvdi->item.mask=LVIF_TEXT; // This is bad as wine relies on this to not change.
9529
9530 }
9531 else if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && (nmh->code == (UINT)LVN_ITEMACTIVATE||nmh->code == (UINT)NM_CLICK))
9532 {
9533 bool enable=true;
9534 if(-1==ListView_GetSelectionMark(nmh->hwndFrom))
9535 {
9536 enable=false;
9537 }
9538 EnableWindow(GetDlgItem(hDlg, IDC_C_ADD), enable);
9539 EnableWindow(GetDlgItem(hDlg, IDC_C_WATCH), enable);
9540 }
9541 // allow typing in an address to jump to it
9542 else if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && nmh->code == (UINT)LVN_ODFINDITEM)
9543 {
9544 LRESULT pResult;
9545
9546 // pNMHDR has information about the item we should find
9547 // In pResult we should save which item that should be selected
9548 NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)lParam;
9549
9550 /* pFindInfo->iStart is from which item we should search.
9551 We search to bottom, and then restart at top and will stop
9552 at pFindInfo->iStart, unless we find an item that match
9553 */
9554
9555 // Set the default return value to -1
9556 // That means we didn't find any match.
9557 pResult = -1;
9558
9559 //Is search NOT based on string?
9560 if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 )
9561 {
9562 //This will probably never happend...
9563 return pResult;
9564 }
9565
9566 //This is the string we search for
9567 const TCHAR *searchstr = pFindInfo->lvfi.psz;
9568
9569 int startPos = pFindInfo->iStart;
9570 //Is startPos outside the list (happens if last item is selected)
9571 if(startPos >= ListView_GetItemCount(GetDlgItem(hDlg,IDC_ADDYS)))
9572 startPos = 0;
9573
9574 int currentPos, addrPos;
9575 for(addrPos=0,currentPos=0;addrPos<(0x32000-bytes)&¤tPos<startPos;addrPos++)
9576 {
9577 if(TEST_BIT(Cheat.ALL_BITS, addrPos))
9578 currentPos++;
9579 }
9580
9581 pResult=currentPos;
9582
9583 if (addrPos>=0x32000 && addrPos!=0)
9584 break;
9585
9586 // ignore leading 0's
9587 while(searchstr[0] == '0' && searchstr[1] != '\0')
9588 searchstr++;
9589
9590 int searchNum = 0;
9591
9592 ScanAddress(searchstr, searchNum);
9593
9594
9595 // if (searchstr[0] != '7')
9596 // break; // all searchable addresses begin with a 7
9597
9598 bool looped = false;
9599
9600 // perform search
9601 do
9602 {
9603
9604 if(addrPos == searchNum)
9605 {
9606 // select this item and stop search
9607 pResult = currentPos;
9608 break;
9609 }
9610 else if(addrPos > searchNum)
9611 {
9612 if(looped)
9613 {
9614 pResult = currentPos;
9615 break;
9616 }
9617
9618 // optimization: the items are ordered alphabetically, so go back to the top since we know it can't be anything further down
9619 currentPos = 0;
9620 addrPos = 0;
9621 while(!TEST_BIT(Cheat.ALL_BITS, addrPos))
9622 addrPos++;
9623 looped = true;
9624 continue;
9625 }
9626
9627 //Go to next item
9628 addrPos++;
9629 while(!TEST_BIT(Cheat.ALL_BITS, addrPos))
9630 addrPos++;
9631 currentPos++;
9632
9633 //Need to restart at top?
9634 if(currentPos >= ListView_GetItemCount(GetDlgItem(hDlg,IDC_ADDYS)))
9635 {
9636 currentPos = 0;
9637 addrPos = 0;
9638 while(!TEST_BIT(Cheat.ALL_BITS, addrPos))
9639 addrPos++;
9640 }
9641
9642 //Stop if back to start
9643 }while(currentPos != startPos);
9644
9645 foundItemOverride = pResult;
9646
9647 // in case previously-selected item is 0
9648 ListView_SetItemState (GetDlgItem(hDlg,IDC_ADDYS), 1, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
9649
9650 return pResult; // HACK: for some reason this selects the first item instead of what it's returning... current workaround is to manually re-select this return value upon the next changed event
9651 }
9652 else if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && nmh->code == LVN_ITEMCHANGED)
9653 {
9654 // hack - see note directly above
9655 LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam;
9656 if(lpnmlv->uNewState & (LVIS_SELECTED|LVIS_FOCUSED))
9657 {
9658 if(foundItemOverride != -1 && lpnmlv->iItem == 0)
9659 {
9660 ListView_SetItemState (GetDlgItem(hDlg,IDC_ADDYS), foundItemOverride, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
9661 ListView_EnsureVisible (GetDlgItem(hDlg,IDC_ADDYS), foundItemOverride, FALSE);
9662 selectionMarkOverride = foundItemOverride;
9663 foundItemOverride = -1;
9664 }
9665 else
9666 {
9667 selectionMarkOverride = lpnmlv->iItem;
9668 }
9669 }
9670 }
9671 }
9672 }
9673 break;
9674 case WM_ACTIVATE:
9675 ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000);
9676 break;
9677 case WM_COMMAND:
9678 {
9679 switch(LOWORD(wParam))
9680 {
9681 case IDC_LESS_THAN:
9682 case IDC_GREATER_THAN:
9683 case IDC_LESS_THAN_EQUAL:
9684 case IDC_GREATER_THAN_EQUAL:
9685 case IDC_EQUAL:
9686 case IDC_NOT_EQUAL:
9687 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN))
9688 comp_type=S9X_LESS_THAN;
9689 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN))
9690 comp_type=S9X_GREATER_THAN;
9691 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN_EQUAL))
9692 comp_type=S9X_LESS_THAN_OR_EQUAL;
9693 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN_EQUAL))
9694 comp_type=S9X_GREATER_THAN_OR_EQUAL;
9695 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_EQUAL))
9696 comp_type=S9X_EQUAL;
9697 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_NOT_EQUAL))
9698 comp_type=S9X_NOT_EQUAL;
9699
9700 break;
9701 case IDC_1_BYTE:
9702 case IDC_2_BYTE:
9703 case IDC_3_BYTE:
9704 case IDC_4_BYTE:
9705 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_1_BYTE))
9706 bytes=S9X_8_BITS;
9707 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_2_BYTE))
9708 bytes=S9X_16_BITS;
9709 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_3_BYTE))
9710 bytes=S9X_24_BITS;
9711 else bytes=S9X_32_BITS;
9712 {
9713 int l = CheatCount(bytes);
9714 ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l);
9715 }
9716
9717 break;
9718
9719 case IDC_SIGNED:
9720 case IDC_UNSIGNED:
9721 case IDC_HEX:
9722 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_UNSIGNED))
9723 val_type=1;
9724 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_SIGNED))
9725 val_type=2;
9726 else val_type=3;
9727 ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000);
9728 break;
9729 case IDC_C_ADD:
9730 {
9731 // account for size
9732 struct ICheat cht;
9733 // int idx=-1;
9734 LVITEM lvi;
9735 static TCHAR buf[12]; // the following code assumes this variable is static, I think
9736 memset(&cht, 0, sizeof(struct SCheat));
9737
9738 //retrieve and convert to SCheat
9739
9740 if(bytes==S9X_8_BITS)
9741 cht.size=1;
9742 else if (bytes==S9X_16_BITS)
9743 cht.size=2;
9744 else if (bytes==S9X_24_BITS)
9745 cht.size=3;
9746 else if (bytes==S9X_32_BITS)
9747 cht.size=4;
9748
9749
9750 ITEM_QUERY(lvi, IDC_ADDYS, 0, buf, 7);
9751
9752
9753 ScanAddress(buf, cht.address);
9754
9755 memset(buf, 0, sizeof(TCHAR) * 7);
9756 if(val_type==1)
9757 {
9758 ITEM_QUERY(lvi, IDC_ADDYS, 1, buf, 12);
9759 _stscanf(buf, TEXT("%u"), &cht.new_val);
9760 memset(buf, 0, sizeof(TCHAR) * 7);
9761 ITEM_QUERY(lvi, IDC_ADDYS, 2, buf, 12);
9762 _stscanf(buf, TEXT("%u"), &cht.saved_val);
9763 }
9764 else if(val_type==3)
9765 {
9766 ITEM_QUERY(lvi, IDC_ADDYS, 1, buf, 12);
9767 _stscanf(buf, TEXT("%x"), &cht.new_val);
9768 memset(buf, 0, sizeof(TCHAR) * 7);
9769 ITEM_QUERY(lvi, IDC_ADDYS, 2, buf, 12);
9770 _stscanf(buf, TEXT("%x"), &cht.saved_val);
9771 }
9772 else
9773 {
9774 ITEM_QUERY(lvi, IDC_ADDYS, 1, buf, 12);
9775 _stscanf(buf, TEXT("%d"), &cht.new_val);
9776 memset(buf, 0, sizeof(TCHAR) * 7);
9777 ITEM_QUERY(lvi, IDC_ADDYS, 2, buf, 12);
9778 _stscanf(buf, TEXT("%d"), &cht.saved_val);
9779 }
9780 cht.format=val_type;
9781 //invoke dialog
9782 DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CHEAT_FROM_SEARCH), hDlg, DlgCheatSearchAdd, (LPARAM)&cht);
9783 }
9784 break;
9785 case IDC_C_RESET:
9786 S9xStartCheatSearch(&Cheat);
9787 {
9788 int l = CheatCount(bytes);
9789 ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l);
9790 }
9791 ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000);
9792 //val_type=1;
9793 //SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0);
9794 //SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_UNCHECKED, 0);
9795 //SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_UNCHECKED, 0);
9796
9797 //bytes=S9X_8_BITS;
9798 //SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0);
9799 //SendDlgItemMessage(hDlg, IDC_2_BYTE, BM_SETCHECK, BST_UNCHECKED, 0);
9800 //SendDlgItemMessage(hDlg, IDC_3_BYTE, BM_SETCHECK, BST_UNCHECKED, 0);
9801 //SendDlgItemMessage(hDlg, IDC_4_BYTE, BM_SETCHECK, BST_UNCHECKED, 0);
9802
9803
9804 //use_entered=0;
9805 //SendDlgItemMessage(hDlg, IDC_PREV, BM_SETCHECK, BST_CHECKED, 0);
9806 //SendDlgItemMessage(hDlg, IDC_ENTERED, BM_SETCHECK, BST_UNCHECKED, 0);
9807 //SendDlgItemMessage(hDlg, IDC_ENTEREDADDRESS, BM_SETCHECK, BST_UNCHECKED, 0);
9808 //EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), false);
9809 //EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), false);
9810
9811 //comp_type=S9X_LESS_THAN;
9812 //SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_CHECKED, 0);
9813 //SendDlgItemMessage(hDlg, IDC_GREATER_THAN, BM_SETCHECK, BST_UNCHECKED, 0);
9814 //SendDlgItemMessage(hDlg, IDC_LESS_THAN_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0);
9815 //SendDlgItemMessage(hDlg, IDC_GREATER_THAN_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0);
9816 //SendDlgItemMessage(hDlg, IDC_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0);
9817 //SendDlgItemMessage(hDlg, IDC_NOT_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0);
9818 return true;
9819 case IDC_C_WATCH:
9820 {
9821 uint32 address = (uint32)-1;
9822 TCHAR buf [12];
9823 LVITEM lvi;
9824 ITEM_QUERY(lvi, IDC_ADDYS, 0, buf, 7);
9825 ScanAddress(buf, address);
9826 {
9827 memset(buf, 0, sizeof(TCHAR) * 7);
9828
9829 unsigned int i;
9830 for(i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++)
9831 if(!watches[i].on || watches[i].address == address)
9832 break;
9833 if(i >= sizeof(watches)/sizeof(*watches))
9834 i = (unsigned int)(sizeof(watches)/sizeof(*watches)-1);
9835
9836 watches[i].on = true;
9837
9838 // account for size
9839 if(bytes==S9X_8_BITS)
9840 watches[i].size=1;
9841 else if (bytes==S9X_16_BITS)
9842 watches[i].size=2;
9843 else if (bytes==S9X_24_BITS)
9844 watches[i].size=3;
9845 else if (bytes==S9X_32_BITS)
9846 watches[i].size=4;
9847
9848 watches[i].format=val_type;
9849 watches[i].address=address;
9850 strncpy(watches[i].buf,_tToChar(buf),12);
9851 if(address < 0x7E0000 + 0x20000)
9852 sprintf(watches[i].desc, "%6X", address);
9853 else if(address < 0x7E0000 + 0x30000)
9854 sprintf(watches[i].desc, "s%05X", address - 0x7E0000 - 0x20000);
9855 else
9856 sprintf(watches[i].desc, "i%05X", address - 0x7E0000 - 0x30000);
9857 }
9858 {
9859 RECT rect;
9860 GetClientRect (GUI.hWnd, &rect);
9861 InvalidateRect (GUI.hWnd, &rect, true);
9862 }
9863 }
9864 break;
9865 case IDC_C_CLEARWATCH:
9866 {
9867 for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++)
9868 watches[i].on = false;
9869 {
9870 RECT rect;
9871 GetClientRect (GUI.hWnd, &rect);
9872 InvalidateRect (GUI.hWnd, &rect, true);
9873 }
9874 }
9875 break;
9876 case IDC_C_LOADWATCH:
9877 {
9878 OPENFILENAME ofn;
9879 TCHAR szFileName[MAX_PATH];
9880 TCHAR szPathName[MAX_PATH];
9881 lstrcpy(szFileName, TEXT("watches"));
9882 _tfullpath(szPathName, S9xGetDirectoryT(CHEAT_DIR), MAX_PATH);
9883
9884 memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) );
9885 ofn.lStructSize = sizeof(OPENFILENAME);
9886 ofn.hwndOwner = GUI.hWnd;
9887 ofn.lpstrFilter = FILE_INFO_TXT_FILE_TYPE TEXT("\0*.txt\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0");
9888 ofn.lpstrFile = szFileName;
9889 ofn.lpstrDefExt = TEXT("txt");
9890 ofn.nMaxFile = MAX_PATH;
9891 ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
9892 ofn.lpstrInitialDir = szPathName;
9893 if(GetOpenFileName( &ofn ))
9894 {
9895 FILE *file = _tfopen(szFileName, TEXT("r"));
9896 if(file)
9897 {
9898 unsigned int i;
9899 for(i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++)
9900 watches[i].on = false;
9901 for(i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++)
9902 {
9903 char nameStr [32];
9904 nameStr[0]='?'; nameStr[1]='\0';
9905 fscanf(file, " address = 0x%x, name = \"%31[^\"]\", size = %d, format = %d\n", &watches[i].address, nameStr, &watches[i].size, &watches[i].format);
9906 if(nameStr[0] == '\0' || nameStr[0] == '?')
9907 {
9908 if(watches[i].address < 0x7E0000 + 0x20000)
9909 sprintf(nameStr, "%06X", watches[i].address);
9910 else if(watches[i].address < 0x7E0000 + 0x30000)
9911 sprintf(nameStr, "s%05X", watches[i].address - 0x7E0000 - 0x20000);
9912 else
9913 sprintf(nameStr, "i%05X", watches[i].address - 0x7E0000 - 0x30000);
9914 }
9915 nameStr[31] = '\0';
9916 if(!ferror(file))
9917 {
9918 watches[i].on = true;
9919 watches[i].buf[0] = '\0';
9920 strncpy(watches[i].desc, nameStr, sizeof(watches[i].desc)); watches[i].desc[sizeof(watches[i].desc)-1]='\0';
9921 }
9922 if(ferror(file) || feof(file))
9923 break;
9924 }
9925 fclose(file);
9926 }
9927 }
9928 {
9929 RECT rect;
9930 GetClientRect (GUI.hWnd, &rect);
9931 InvalidateRect (GUI.hWnd, &rect, true);
9932 }
9933 }
9934 break;
9935 case IDC_C_SAVEWATCH:
9936 {
9937 OPENFILENAME ofn;
9938 TCHAR szFileName[MAX_PATH];
9939 TCHAR szPathName[MAX_PATH];
9940 lstrcpy(szFileName, TEXT("watches"));
9941 _tfullpath(szPathName, S9xGetDirectoryT(CHEAT_DIR), MAX_PATH);
9942
9943 memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) );
9944 ofn.lStructSize = sizeof(OPENFILENAME);
9945 ofn.hwndOwner = GUI.hWnd;
9946 ofn.lpstrFilter = FILE_INFO_TXT_FILE_TYPE TEXT("\0*.txt\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0");
9947 ofn.lpstrFile = szFileName;
9948 ofn.lpstrDefExt = TEXT("txt");
9949 ofn.nMaxFile = MAX_PATH;
9950 ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
9951 ofn.lpstrInitialDir = szPathName;
9952 if(GetSaveFileName( &ofn ))
9953 {
9954 FILE *file = _tfopen(szFileName, TEXT("w"));
9955 if(file)
9956 {
9957 for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++)
9958 if(watches[i].on)
9959 // fprintf(file, "address = 0x%x, name = \"%6X\", size = %d, format = %d\n", watches[i].address, watches[i].address, watches[i].size, watches[i].format);
9960 fprintf(file, "address = 0x%x, name = \"?\", size = %d, format = %d\n", watches[i].address, watches[i].size, watches[i].format);
9961 fclose(file);
9962 }
9963 }
9964 {
9965 RECT rect;
9966 GetClientRect (GUI.hWnd, &rect);
9967 InvalidateRect (GUI.hWnd, &rect, true);
9968 }
9969 }
9970 break;
9971
9972 case IDC_REFRESHLIST:
9973 ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000);
9974 break;
9975
9976 case IDC_ENTERED:
9977 case IDC_ENTEREDADDRESS:
9978 case IDC_PREV:
9979 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTERED))
9980 {
9981 use_entered=1;
9982 EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true);
9983 EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true);
9984 }
9985 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTEREDADDRESS))
9986 {
9987 use_entered=2;
9988 EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true);
9989 EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true);
9990 }
9991 else
9992 {
9993 use_entered=0;
9994 EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), false);
9995 EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), false);
9996 }
9997 return true;
9998 break;
9999 case IDC_C_SEARCH:
10000 {
10001 val_type=0;
10002
10003 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN))
10004 comp_type=S9X_LESS_THAN;
10005 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN))
10006 comp_type=S9X_GREATER_THAN;
10007 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN_EQUAL))
10008 comp_type=S9X_LESS_THAN_OR_EQUAL;
10009 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN_EQUAL))
10010 comp_type=S9X_GREATER_THAN_OR_EQUAL;
10011 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_EQUAL))
10012 comp_type=S9X_EQUAL;
10013 else comp_type=S9X_NOT_EQUAL;
10014
10015 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_UNSIGNED))
10016 val_type=1;
10017 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_SIGNED))
10018 val_type=2;
10019 else val_type=3;
10020
10021
10022
10023 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_1_BYTE))
10024 bytes=S9X_8_BITS;
10025 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_2_BYTE))
10026 bytes=S9X_16_BITS;
10027 else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_3_BYTE))
10028 bytes=S9X_24_BITS;
10029 else bytes=S9X_32_BITS;
10030
10031
10032 if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTERED) ||
10033 BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTEREDADDRESS))
10034 {
10035 TCHAR buf[20];
10036 GetDlgItemText(hDlg, IDC_VALUE_ENTER, buf, 20);
10037 uint32 value;
10038 int ret;
10039 if(use_entered==2)
10040 {
10041 ret = ScanAddress(buf, value);
10042 value -= 0x7E0000;
10043 S9xSearchForAddress (&Cheat, comp_type, bytes, value, FALSE);
10044 }
10045 else
10046 {
10047 if(val_type==1)
10048 ret=_stscanf(buf, TEXT("%ul"), &value);
10049 else if (val_type==2)
10050 ret=_stscanf(buf, TEXT("%d"), &value);
10051 else ret=_stscanf(buf, TEXT("%x"), &value);
10052
10053
10054 if(ret!=1||!TestRange(val_type, bytes, value))
10055 {
10056 MessageBox(hDlg, SEARCH_ERR_INVALIDSEARCHVALUE, SEARCH_TITLE_CHEATERROR, MB_OK);
10057 return true;
10058 }
10059
10060 S9xSearchForValue (&Cheat, comp_type,
10061 bytes, value,
10062 (val_type==2), FALSE);
10063 }
10064
10065 }
10066 else
10067 {
10068 S9xSearchForChange (&Cheat, comp_type,
10069 bytes, (val_type==2), FALSE);
10070 }
10071 int l = CheatCount(bytes);
10072 ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l);
10073 }
10074
10075 // if non-modal, update "Prev. Value" column after Search
10076 if(cheatSearchHWND)
10077 {
10078 CopyMemory(Cheat.CWRAM, Cheat.RAM, 0x20000);
10079 CopyMemory(Cheat.CSRAM, Cheat.SRAM, 0x10000);
10080 CopyMemory(Cheat.CIRAM, Cheat.FillRAM, 0x2000);
10081 }
10082
10083
10084 ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000);
10085 return true;
10086 break;
10087 case IDOK:
10088 CopyMemory(Cheat.CWRAM, Cheat.RAM, 0x20000);
10089 CopyMemory(Cheat.CSRAM, Cheat.SRAM, 0x10000);
10090 CopyMemory(Cheat.CIRAM, Cheat.FillRAM, 0x2000);
10091 /* fall through */
10092 case IDCANCEL:
10093 if(cheatSearchHWND)
10094 DestroyWindow(hDlg);
10095 else
10096 EndDialog(hDlg, 0);
10097 return true;
10098 default: break;
10099 }
10100 }
10101 default: return false;
10102 }
10103 return false;
10104 }
10105
DlgCheatSearchAdd(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)10106 INT_PTR CALLBACK DlgCheatSearchAdd(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
10107 {
10108 static struct ICheat* new_cheat;
10109 int ret=-1;
10110 switch(msg)
10111 {
10112 case WM_INITDIALOG:
10113 WinRefreshDisplay();
10114 {
10115 TCHAR buf [12];
10116 new_cheat=(struct ICheat*)lParam;
10117 _stprintf(buf, TEXT("%06X"), new_cheat->address);
10118 SetDlgItemText(hDlg, IDC_NC_ADDRESS, buf);
10119 switch(new_cheat->format)
10120 {
10121 default:
10122 case 1://UNSIGNED
10123 memset(buf,0,sizeof(TCHAR) * 12);
10124 _stprintf(buf, TEXT("%u"), new_cheat->new_val);
10125 SetDlgItemText(hDlg, IDC_NC_CURRVAL, buf);
10126 memset(buf,0,sizeof(TCHAR) * 12);
10127 _stprintf(buf, TEXT("%u"), new_cheat->saved_val);
10128 SetDlgItemText(hDlg, IDC_NC_PREVVAL, buf);
10129 SetWindowLongPtr(GetDlgItem(hDlg, IDC_NC_NEWVAL), GWL_STYLE, ES_NUMBER |GetWindowLongPtr(GetDlgItem(hDlg, IDC_NC_NEWVAL),GWL_STYLE));
10130 SetWindowLongPtr(GetDlgItem(hDlg, IDC_NC_CURRVAL), GWL_STYLE, ES_NUMBER |GetWindowLongPtr(GetDlgItem(hDlg, IDC_NC_CURRVAL),GWL_STYLE));
10131 SetWindowLongPtr(GetDlgItem(hDlg, IDC_NC_PREVVAL), GWL_STYLE, ES_NUMBER |GetWindowLongPtr(GetDlgItem(hDlg, IDC_NC_PREVVAL),GWL_STYLE));
10132 if(new_cheat->size==1)
10133 {
10134 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 3, 0);
10135 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 3, 0);
10136 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 3, 0);
10137
10138 }
10139 if(new_cheat->size==2)
10140 {
10141 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 5, 0);
10142 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 5, 0);
10143 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 5, 0);
10144
10145 }
10146 if(new_cheat->size==3)
10147 {
10148 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 8, 0);
10149 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 8, 0);
10150 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 8, 0);
10151
10152 }
10153 if(new_cheat->size==4)
10154 {
10155 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 10, 0);
10156 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 10, 0);
10157 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 10, 0);
10158
10159 }
10160 break;
10161 case 3:
10162 {
10163 TCHAR formatstring[10];
10164 _stprintf(formatstring, TEXT("%%%02dX"),new_cheat->size*2);
10165 memset(buf,0,sizeof(TCHAR) * 12);
10166 _stprintf(buf, formatstring, new_cheat->new_val);
10167 SetDlgItemText(hDlg, IDC_NC_CURRVAL, buf);
10168 memset(buf,0,sizeof(TCHAR) * 12);
10169 _stprintf(buf, formatstring, new_cheat->saved_val);
10170 SetDlgItemText(hDlg, IDC_NC_PREVVAL, buf);
10171 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, new_cheat->size*2, 0);
10172 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, new_cheat->size*2, 0);
10173 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, new_cheat->size*2, 0);
10174
10175 }
10176 break; //HEX
10177 case 2:
10178 memset(buf,0,sizeof(TCHAR) * 12);
10179 _stprintf(buf, TEXT("%d"), new_cheat->new_val);
10180 SetDlgItemText(hDlg, IDC_NC_CURRVAL, buf);
10181 memset(buf,0,sizeof(TCHAR) * 12);
10182 _stprintf(buf, TEXT("%d"), new_cheat->saved_val);
10183 SetDlgItemText(hDlg, IDC_NC_PREVVAL, buf);
10184 if(new_cheat->size==1)
10185 {
10186 //-128
10187 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 4, 0);
10188 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 4, 0);
10189 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 4, 0);
10190 }
10191 if(new_cheat->size==2)
10192 {
10193 //-32768
10194 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 6, 0);
10195 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 6, 0);
10196 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 6, 0);
10197 }
10198 if(new_cheat->size==3)
10199 {
10200 //-8388608
10201 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 8, 0);
10202 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 8, 0);
10203 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 8, 0);
10204 }
10205 if(new_cheat->size==4)
10206 {
10207 //-2147483648
10208 SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 11, 0);
10209 SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 11, 0);
10210 SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 11, 0);
10211 }
10212 break;
10213 }
10214 }
10215 return true;
10216 case WM_PAINT:
10217 {
10218 PAINTSTRUCT ps;
10219 BeginPaint (hDlg, &ps);
10220
10221 EndPaint (hDlg, &ps);
10222 }
10223 return true;
10224 case WM_COMMAND:
10225 {
10226 switch(LOWORD(wParam))
10227 {
10228 case IDOK:
10229 {
10230 int ret = 0;
10231 TCHAR buf[23];
10232 int temp=new_cheat->size;
10233 S9xCheatDataSize tmp = S9X_8_BITS;
10234 memset(new_cheat, 0, sizeof(struct SCheat));
10235 new_cheat->size=temp;
10236 GetDlgItemText(hDlg, IDC_NC_ADDRESS, buf, 7);
10237 ScanAddress(buf, new_cheat->address);
10238
10239 if(temp==1)
10240 tmp=S9X_8_BITS;
10241 if(temp==2)
10242 tmp=S9X_16_BITS;
10243 if(temp==3)
10244 tmp=S9X_24_BITS;
10245 if(temp==4)
10246 tmp=S9X_32_BITS;
10247
10248
10249 if(0!=GetDlgItemText(hDlg, IDC_NC_NEWVAL, buf, 12))
10250 {
10251 if(new_cheat->format==2)
10252 ret=_stscanf(buf, TEXT("%d"), &new_cheat->new_val);
10253 else if(new_cheat->format==1)
10254 ret=_stscanf(buf, TEXT("%u"), &new_cheat->new_val);
10255 else if(new_cheat->format==3)
10256 ret=_stscanf(buf, TEXT("%x"), &new_cheat->new_val);
10257
10258 if(ret!=1 || !TestRange(new_cheat->format, tmp, new_cheat->new_val))
10259 {
10260 MessageBox(hDlg, SEARCH_ERR_INVALIDNEWVALUE, SEARCH_TITLE_RANGEERROR, MB_OK);
10261 return true;
10262 }
10263
10264
10265 if(0==GetDlgItemText(hDlg, IDC_NC_CURRVAL, buf, 12))
10266 new_cheat->saved=FALSE;
10267 else
10268 {
10269 int i;
10270 if(new_cheat->format==2)
10271 ret=_stscanf(buf, TEXT("%d"), &i);
10272 else if(new_cheat->format==1)
10273 ret=_stscanf(buf, TEXT("%u"), &i);
10274 else if(new_cheat->format==3)
10275 ret=_stscanf(buf, TEXT("%x"), &i);
10276
10277 if(ret!=1 || !TestRange(new_cheat->format, tmp, i))
10278 {
10279 MessageBox(hDlg, SEARCH_ERR_INVALIDCURVALUE, SEARCH_TITLE_RANGEERROR, MB_OK);
10280 return true;
10281 }
10282
10283
10284 new_cheat->saved_val=i;
10285 new_cheat->saved=TRUE;
10286 }
10287 TCHAR tempBuf[22];
10288 GetDlgItemText(hDlg, IDC_NC_DESC, tempBuf, 22);
10289 strncpy(new_cheat->name,_tToChar(tempBuf),22);
10290
10291 new_cheat->enabled=TRUE;
10292 for(int byteIndex = 0; byteIndex < new_cheat->size; byteIndex++)
10293 {
10294 S9xAddCheat(new_cheat->enabled,new_cheat->saved_val,new_cheat->address+byteIndex,(new_cheat->new_val>>(8*byteIndex))&0xFF);
10295 strcpy(Cheat.c[Cheat.num_cheats-1].name,new_cheat->name);
10296 }
10297 ret=0;
10298 }
10299 }
10300
10301 case IDCANCEL:
10302 EndDialog(hDlg, ret);
10303 return true;
10304 default: break;
10305 }
10306 }
10307 default: return false;
10308 }
10309 }
10310
set_movieinfo(const TCHAR * path,HWND hDlg)10311 static void set_movieinfo(const TCHAR* path, HWND hDlg)
10312 {
10313 MovieInfo m;
10314 int i;
10315 int getInfoResult=FILE_NOT_FOUND;
10316
10317 if(lstrlen(path))
10318 getInfoResult = S9xMovieGetInfo(_tToChar(path), &m);
10319
10320 if(getInfoResult!=FILE_NOT_FOUND)
10321 {
10322 TCHAR* p;
10323 TCHAR tmpstr[128];
10324 lstrcpyn(tmpstr, _tctime(&m.TimeCreated), 127);
10325 tmpstr[127]=TEXT('\0');
10326 if((p=_tcsrchr(tmpstr, TEXT('\n'))))
10327 *p=TEXT('\0');
10328 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_DATE), tmpstr);
10329
10330 uint32 div = Memory.ROMFramesPerSecond;
10331 if(!div) div = 60;
10332 uint32 l=(m.LengthFrames+(div>>1))/div;
10333 uint32 seconds=l%60;
10334 l/=60;
10335 uint32 minutes=l%60;
10336 l/=60;
10337 uint32 hours=l%60;
10338 _stprintf(tmpstr, TEXT("%02d:%02d:%02d"), hours, minutes, seconds);
10339 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_LENGTH), tmpstr);
10340 _stprintf(tmpstr, TEXT("%u"), m.LengthFrames);
10341 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_FRAMES), tmpstr);
10342 _stprintf(tmpstr, TEXT("%u"), m.RerecordCount);
10343 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_RERECORD), tmpstr);
10344 }
10345 else
10346 {
10347 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_DATE), TEXT(""));
10348 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_LENGTH), TEXT(""));
10349 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_FRAMES), TEXT(""));
10350 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_RERECORD), TEXT(""));
10351 }
10352
10353 if(getInfoResult==SUCCESS)
10354 {
10355 // set author comment:
10356 {
10357 /// SetWindowTextW(GetDlgItem(hDlg, IDC_MOVIE_METADATA), m.Metadata); // won't work, because of & symbol
10358
10359 wchar_t metadata [MOVIE_MAX_METADATA];
10360 int j, pos = 0, len = wcslen(m.Metadata);
10361 for (j = 0; j < len ; j++)
10362 {
10363 wchar_t c = m.Metadata [j];
10364 metadata [pos++] = c;
10365
10366 // & is a special character in Windows fields,
10367 // so we have to change & to && when copying over the game title
10368 // otherwise "Pocky & Rocky" will show up as "Pocky Rocky", for example
10369 if(c == (wchar_t)'&')
10370 metadata [pos++] = (wchar_t)'&';
10371 }
10372 metadata [pos] = (wchar_t)'\0';
10373
10374 SetWindowTextW(GetDlgItem(hDlg, IDC_MOVIE_METADATA), metadata);
10375 }
10376 SetWindowText(GetDlgItem(hDlg, IDC_LABEL_MOVIEINFOBOX), MOVIE_LABEL_AUTHORINFO);
10377
10378 if(m.ReadOnly)
10379 {
10380 EnableWindow(GetDlgItem(hDlg, IDC_READONLY), FALSE);
10381 SendDlgItemMessage(hDlg,IDC_READONLY,BM_SETCHECK,BST_CHECKED,0);
10382 }
10383 else
10384 {
10385 EnableWindow(GetDlgItem(hDlg, IDC_READONLY), TRUE);
10386 /// SendDlgItemMessage(hDlg,IDC_READONLY,BM_SETCHECK,BST_UNCHECKED,0);
10387 }
10388 EnableWindow(GetDlgItem(hDlg, IDC_DISPLAY_INPUT), TRUE);
10389
10390 for(i=0; i<5; ++i)
10391 {
10392 SendDlgItemMessage(hDlg,IDC_JOY1+i,BM_SETCHECK,(m.ControllersMask & (1<<i)) ? BST_CHECKED : BST_UNCHECKED,0);
10393 }
10394
10395 if(m.Opts & MOVIE_OPT_FROM_RESET)
10396 {
10397 SendDlgItemMessage(hDlg,IDC_RECORD_NOW,BM_SETCHECK,BST_UNCHECKED,0);
10398 SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK,BST_CHECKED,0);
10399 }
10400 else
10401 {
10402 SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK,BST_UNCHECKED,0);
10403 SendDlgItemMessage(hDlg,IDC_RECORD_NOW,BM_SETCHECK,BST_CHECKED,0);
10404 }
10405
10406
10407 // if(m.SyncFlags & MOVIE_SYNC_DATA_EXISTS)
10408 {
10409 // SetWindowText(GetDlgItem(hDlg, IDC_LOADEDFROMMOVIE), _T(MOVIE_LABEL_SYNC_DATA_FROM_MOVIE));
10410 }
10411
10412 {
10413 TCHAR str [256];
10414
10415 if(m.SyncFlags & MOVIE_SYNC_HASROMINFO)
10416 {
10417 _stprintf(str, MOVIE_INFO_MOVIEROM MOVIE_INFO_ROMINFO, m.ROMCRC32, _tFromChar(m.ROMName));
10418 SetWindowText(GetDlgItem(hDlg, IDC_MOVIEROMINFO), str);
10419 }
10420 else
10421 {
10422 _stprintf(str, MOVIE_INFO_MOVIEROM MOVIE_INFO_ROMNOTSTORED);
10423 SetWindowText(GetDlgItem(hDlg, IDC_MOVIEROMINFO), str);
10424 }
10425
10426 bool mismatch = (m.SyncFlags & MOVIE_SYNC_HASROMINFO) && m.ROMCRC32 != Memory.ROMCRC32;
10427 _stprintf(str, MOVIE_INFO_CURRENTROM MOVIE_INFO_ROMINFO TEXT("%s"), Memory.ROMCRC32, _tFromChar(Memory.ROMName), mismatch?MOVIE_INFO_MISMATCH:TEXT(""));
10428 SetWindowText(GetDlgItem(hDlg, IDC_CURRENTROMINFO), str);
10429
10430 _stprintf(str, TEXT("%s"), mismatch?MOVIE_WARNING_MISMATCH:MOVIE_WARNING_OK);
10431 SetWindowText(GetDlgItem(hDlg, IDC_PLAYWARN), str);
10432 }
10433
10434 EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
10435 }
10436 else
10437 {
10438 // get the path of (where we think) the movie is
10439 TCHAR tempPathStr [512];
10440 lstrcpyn(tempPathStr, path, 512);
10441 tempPathStr[511] = TEXT('\0');
10442 TCHAR* slash = _tcsrchr(tempPathStr, TEXT('\\'));
10443 slash = max(slash, _tcsrchr(tempPathStr, TEXT('/')));
10444 if(slash) *slash = TEXT('\0');
10445 TCHAR tempDirStr [512];
10446 TCHAR dirStr [768];
10447 _tfullpath(tempDirStr, tempPathStr, 512);
10448 TCHAR* documeStr = _tcsstr(tempDirStr, TEXT("Documents and Settings"));
10449 if(documeStr) { // abbreviate
10450 lstrcpy(documeStr, documeStr+14);
10451 lstrcpyn(documeStr, TEXT("docume~1"), 8);
10452 }
10453 _stprintf(dirStr, MOVIE_INFO_DIRECTORY, tempDirStr);
10454
10455 switch(getInfoResult)
10456 {
10457 default:
10458 SetWindowText(GetDlgItem(hDlg, IDC_PLAYWARN), TEXT(""));
10459 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_METADATA), TEXT(""));
10460 break;
10461 case FILE_NOT_FOUND:
10462 SetWindowText(GetDlgItem(hDlg, IDC_PLAYWARN), MOVIE_ERR_NOT_FOUND_SHORT);
10463 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_METADATA), MOVIE_ERR_NOT_FOUND);
10464 break;
10465 case WRONG_FORMAT:
10466 SetWindowText(GetDlgItem(hDlg, IDC_PLAYWARN), MOVIE_ERR_WRONG_FORMAT_SHORT);
10467 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_METADATA), MOVIE_ERR_WRONG_FORMAT);
10468 break;
10469 case WRONG_VERSION:
10470 SetWindowText(GetDlgItem(hDlg, IDC_PLAYWARN), MOVIE_ERR_WRONG_VERSION_SHORT);
10471 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_METADATA), MOVIE_ERR_WRONG_VERSION);
10472 break;
10473 }
10474 SetWindowText(GetDlgItem(hDlg, IDC_LABEL_MOVIEINFOBOX), MOVIE_LABEL_ERRORINFO);
10475
10476 EnableWindow(GetDlgItem(hDlg, IDC_READONLY), FALSE);
10477 EnableWindow(GetDlgItem(hDlg, IDC_DISPLAY_INPUT), FALSE);
10478 SendDlgItemMessage(hDlg,IDC_READONLY,BM_SETCHECK,BST_UNCHECKED,0);
10479 SendDlgItemMessage(hDlg,IDC_DISPLAY_INPUT,BM_SETCHECK,BST_UNCHECKED,0);
10480
10481
10482 {
10483 SendDlgItemMessage(hDlg,IDC_ALLOWLEFTRIGHT,BM_SETCHECK, Settings.UpAndDown ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
10484 SendDlgItemMessage(hDlg,IDC_SYNC_TO_SOUND_CPU,BM_SETCHECK, Settings.SoundSync ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
10485 }
10486
10487 {
10488 TCHAR str [256];
10489
10490 // no movie loaded
10491 SetWindowText(GetDlgItem(hDlg, IDC_MOVIEROMINFO), dirStr);
10492
10493 _stprintf(str, MOVIE_INFO_CURRENTROM MOVIE_INFO_ROMINFO, Memory.ROMCRC32, _tFromChar(Memory.ROMName));
10494 SetWindowText(GetDlgItem(hDlg, IDC_CURRENTROMINFO), str);
10495 }
10496
10497 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
10498 }
10499
10500 }
10501
DlgOpenMovie(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)10502 INT_PTR CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
10503 {
10504 static OpenMovieParams* op=NULL;
10505 static TCHAR movieDirectory [MAX_PATH];
10506
10507 switch(msg)
10508 {
10509 case WM_INITDIALOG:
10510 WinRefreshDisplay();
10511 {
10512 SetCurrentDirectory(S9xGetDirectoryT(DEFAULT_DIR));
10513 _tfullpath (movieDirectory, GUI.MovieDir, MAX_PATH);
10514 _tmkdir(movieDirectory);
10515 SetCurrentDirectory(movieDirectory);
10516
10517 op=(OpenMovieParams*)lParam;
10518
10519 // get default filename
10520 if(Memory.ROMFilename[0]!='\0')
10521 {
10522 static TCHAR filename [_MAX_PATH + 1];
10523 TCHAR drive [_MAX_DRIVE + 1];
10524 TCHAR dir [_MAX_DIR + 1];
10525 TCHAR fname [_MAX_FNAME + 1];
10526 TCHAR ext [_MAX_EXT + 1];
10527 _tsplitpath (_tFromChar(Memory.ROMFilename), drive, dir, fname, ext);
10528 _tmakepath (filename, TEXT(""), TEXT(""), fname, TEXT("smv"));
10529 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), filename);
10530 set_movieinfo(filename, hDlg);
10531 }
10532 else
10533 {
10534 set_movieinfo(TEXT(""), hDlg);
10535 }
10536
10537 SendDlgItemMessage(hDlg,IDC_READONLY,BM_SETCHECK,GUI.MovieReadOnly ? BST_CHECKED : BST_UNCHECKED,0);
10538
10539 SetDlgItemText(hDlg,IDC_LABEL_STARTSETTINGS, MOVIE_LABEL_STARTSETTINGS);
10540 SetDlgItemText(hDlg,IDC_LABEL_CONTROLLERSETTINGS, MOVIE_LABEL_CONTSETTINGS);
10541 SetDlgItemText(hDlg,IDC_LABEL_SYNCSETTINGS, MOVIE_LABEL_SYNCSETTINGS);
10542 }
10543 return true;
10544
10545 case WM_COMMAND:
10546 {
10547 switch(LOWORD(wParam))
10548 {
10549 case IDC_BROWSE_MOVIE:
10550 {
10551 OPENFILENAME ofn;
10552 TCHAR szFileName[MAX_PATH];
10553
10554 szFileName[0] = TEXT('\0');
10555
10556 memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) );
10557 ofn.lStructSize = sizeof(OPENFILENAME);
10558 ofn.hwndOwner = hDlg;
10559 ofn.lpstrFilter = MOVIE_FILETYPE_DESCRIPTION TEXT("\0*.smv\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0");
10560 ofn.lpstrFile = szFileName;
10561 ofn.lpstrDefExt = TEXT("smv");
10562 ofn.nMaxFile = MAX_PATH;
10563 ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; // hide previously-ignored read-only checkbox (the real read-only box is in the open-movie dialog itself)
10564 ofn.lpstrInitialDir = movieDirectory;
10565 if(GetOpenFileName( &ofn ))
10566 {
10567 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), szFileName);
10568
10569 if(!GUI.LockDirectories)
10570 {
10571 TCHAR temp [256];
10572 GetCurrentDirectory(MAX_PATH, temp);
10573 absToRel(GUI.MovieDir, temp, S9xGetDirectoryT(DEFAULT_DIR));
10574 }
10575
10576 set_movieinfo(szFileName, hDlg);
10577 }
10578 SetCurrentDirectory(movieDirectory);
10579 }
10580 return true;
10581
10582 case IDC_MOVIE_PATH:
10583 {
10584 TCHAR szFileName[MAX_PATH];
10585 GetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), szFileName, MAX_PATH);
10586 set_movieinfo(szFileName, hDlg);
10587 }
10588 break;
10589
10590 case IDOK:
10591 {
10592 if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_READONLY, BM_GETCHECK,0,0))
10593 {
10594 op->ReadOnly=TRUE;
10595 GUI.MovieReadOnly=TRUE;
10596 }
10597 else
10598 GUI.MovieReadOnly=FALSE;
10599 if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_DISPLAY_INPUT, BM_GETCHECK,0,0))
10600 op->DisplayInput=TRUE;
10601 GetDlgItemText(hDlg, IDC_MOVIE_PATH, op->Path, MAX_PATH);
10602 SetCurrentDirectory(movieDirectory);
10603 }
10604 EndDialog(hDlg, 1);
10605 return true;
10606
10607 case IDCANCEL:
10608 EndDialog(hDlg, 0);
10609 return true;
10610
10611 default:
10612 break;
10613 }
10614 }
10615
10616 default:
10617 return false;
10618 }
10619 }
10620
10621 // checks if the currently loaded ROM has an SRAM file in the saves directory that we have write access to
existsSRAM()10622 static bool existsSRAM ()
10623 {
10624 return(!access(S9xGetFilename(".srm", SRAM_DIR), R_OK|W_OK));
10625 }
10626
DlgCreateMovie(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)10627 INT_PTR CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
10628 {
10629 static OpenMovieParams* op=NULL;
10630 static TCHAR movieDirectory [MAX_PATH];
10631
10632 switch(msg)
10633 {
10634 case WM_INITDIALOG:
10635 {
10636 WinRefreshDisplay();
10637 SetCurrentDirectory(S9xGetDirectoryT(DEFAULT_DIR));
10638 _tfullpath (movieDirectory, GUI.MovieDir, MAX_PATH);
10639 _tmkdir(movieDirectory);
10640 SetCurrentDirectory(movieDirectory);
10641
10642 // have to save here or the SRAM file might not exist when we check for it
10643 // (which would cause clear SRAM option to not work)
10644 Memory.SaveSRAM(S9xGetFilename (".srm", SRAM_DIR));
10645
10646
10647 op=(OpenMovieParams*)lParam;
10648
10649 SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK,BST_UNCHECKED,0);
10650
10651 int i;
10652 for(i=1; i<5; ++i)
10653 {
10654 SendDlgItemMessage(hDlg,IDC_JOY1+i,BM_SETCHECK,BST_UNCHECKED,0);
10655 }
10656 SendDlgItemMessage(hDlg,IDC_JOY1,BM_SETCHECK,BST_CHECKED,0);
10657
10658 // get default filename
10659 if(Memory.ROMFilename[0]!='\0')
10660 {
10661 static TCHAR filename [_MAX_PATH + 1];
10662 TCHAR drive [_MAX_DRIVE + 1];
10663 TCHAR dir [_MAX_DIR + 1];
10664 TCHAR fname [_MAX_FNAME + 1];
10665 TCHAR ext [_MAX_EXT + 1];
10666 _tsplitpath (_tFromChar(Memory.ROMFilename), drive, dir, fname, ext);
10667 _tmakepath (filename, TEXT(""), TEXT(""), fname, TEXT("smv"));
10668 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), filename);
10669 }
10670
10671 //EnableWindow(GetDlgItem(hDlg, IDC_SYNC_TO_SOUND_CPU), Settings.SoundDriver<1||Settings.SoundDriver>3); // can't sync sound to CPU unless using "Snes9x DirectSound" driver
10672
10673 SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK, (WPARAM)(GUI.MovieStartFromReset ? BST_CHECKED : BST_UNCHECKED), 0);
10674 SendDlgItemMessage(hDlg,IDC_RECORD_NOW,BM_SETCHECK, (WPARAM)(GUI.MovieStartFromReset ? BST_UNCHECKED : BST_CHECKED), 0);
10675 if(existsSRAM())
10676 {
10677 EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), GUI.MovieStartFromReset);
10678 SendDlgItemMessage(hDlg,IDC_CLEARSRAM,BM_SETCHECK, (WPARAM)(GUI.MovieClearSRAM ? BST_CHECKED : BST_UNCHECKED), 0);
10679 }
10680 else
10681 {
10682 EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), false);
10683 SendDlgItemMessage(hDlg,IDC_CLEARSRAM,BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
10684 }
10685
10686 SetDlgItemText(hDlg,IDC_LABEL_STARTSETTINGS, MOVIE_LABEL_STARTSETTINGS);
10687 SetDlgItemText(hDlg,IDC_LABEL_CONTROLLERSETTINGS, MOVIE_LABEL_CONTSETTINGS);
10688 SetDlgItemText(hDlg,IDC_LABEL_SYNCSETTINGS, MOVIE_LABEL_SYNCSETTINGS);
10689 }
10690 return true;
10691
10692 case WM_COMMAND:
10693 {
10694 switch(LOWORD(wParam))
10695 {
10696 case IDC_BROWSE_MOVIE:
10697 {
10698 OPENFILENAME ofn;
10699 TCHAR szFileName[MAX_PATH];
10700
10701 szFileName[0] = TEXT('\0');
10702
10703 memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) );
10704 ofn.lStructSize = sizeof(OPENFILENAME);
10705 ofn.hwndOwner = hDlg;
10706 ofn.lpstrFilter = MOVIE_FILETYPE_DESCRIPTION TEXT("\0*.smv\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0");
10707 ofn.lpstrFile = szFileName;
10708 ofn.lpstrDefExt = TEXT("smv");
10709 ofn.nMaxFile = MAX_PATH;
10710 ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
10711 ofn.lpstrInitialDir = movieDirectory;
10712 if(GetSaveFileName( &ofn ))
10713 {
10714 SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), szFileName);
10715
10716 if(!GUI.LockDirectories)
10717 {
10718 TCHAR temp [256];
10719 GetCurrentDirectory(MAX_PATH, temp);
10720 absToRel(GUI.MovieDir, temp, S9xGetDirectoryT(DEFAULT_DIR));
10721 }
10722 }
10723 SetCurrentDirectory(movieDirectory);
10724 }
10725 return true;
10726
10727 case IDOK:
10728 {
10729 GetDlgItemText(hDlg, IDC_MOVIE_PATH, op->Path, MAX_PATH);
10730 GetDlgItemTextW(hDlg, IDC_MOVIE_METADATA, op->Metadata, MOVIE_MAX_METADATA);
10731 int i;
10732 for(i=wcslen(op->Metadata); i<32; i++)
10733 wcscat(op->Metadata, L" ");
10734 op->ControllersMask=0;
10735 op->Opts=0;
10736 for(i=0; i<5; ++i) // TODO: should we even bother with 8-controller recording? right now there are only 5 controller buttons in the dialog, so...
10737 {
10738 if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_JOY1+i, BM_GETCHECK,0,0))
10739 op->ControllersMask |= (1<<i);
10740 }
10741 if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_RECORD_RESET, BM_GETCHECK,0,0))
10742 {
10743 op->Opts |= MOVIE_OPT_FROM_RESET;
10744 GUI.MovieStartFromReset = TRUE;
10745 }
10746 else
10747 GUI.MovieStartFromReset = FALSE;
10748
10749 op->SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO;
10750
10751 if(IsDlgButtonChecked(hDlg, IDC_CLEARSRAM) && IsDlgButtonChecked(hDlg, IDC_RECORD_RESET) && existsSRAM())
10752 {
10753 GUI.MovieClearSRAM = TRUE;
10754 remove(S9xGetFilename (".srm", SRAM_DIR)); // delete SRAM if it exists (maybe unnecessary?)
10755 remove(S9xGetFilename (".srm", ROMFILENAME_DIR));
10756 Memory.LoadSRAM(S9xGetFilename (".srm", SRAM_DIR)); // refresh memory (hard reset)
10757 }
10758 else if(!IsDlgButtonChecked(hDlg, IDC_CLEARSRAM) && IsDlgButtonChecked(hDlg, IDC_RECORD_RESET) && existsSRAM())
10759 {
10760 GUI.MovieClearSRAM = FALSE;
10761 }
10762 SetCurrentDirectory(movieDirectory);
10763 }
10764 EndDialog(hDlg, 1);
10765 return true;
10766
10767 case IDCANCEL:
10768 EndDialog(hDlg, 0);
10769 return true;
10770
10771 case IDC_RECORD_NOW:
10772 if(existsSRAM())
10773 {
10774 EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), false);
10775 }
10776 break;
10777
10778 case IDC_RECORD_RESET:
10779 if(existsSRAM())
10780 {
10781 EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), true);
10782 }
10783 break;
10784
10785 default:
10786 break;
10787 }
10788 }
10789
10790 default:
10791 return false;
10792 }
10793 }
10794
10795
10796
10797 // MYO
S9xHandlePortCommand(s9xcommand_t cmd,int16 data1,int16 data2)10798 void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2)
10799 {
10800 return;
10801 }
10802
10803 // NYI
S9xChooseFilename(bool8 read_only)10804 const char *S9xChooseFilename (bool8 read_only)
10805 {
10806 return NULL;
10807 }
10808
10809 // NYI
S9xChooseMovieFilename(bool8 read_only)10810 const char *S9xChooseMovieFilename (bool8 read_only)
10811 {
10812 return NULL;
10813 }
10814
10815
S9xStringInput(const char * msg)10816 const char * S9xStringInput(const char *msg)
10817 {
10818 return NULL;
10819 }
10820
S9xToggleSoundChannel(int c)10821 void S9xToggleSoundChannel (int c)
10822 {
10823 if (c == 8)
10824 GUI.SoundChannelEnable = 255;
10825 else
10826 GUI.SoundChannelEnable ^= 1 << c;
10827
10828 S9xSetSoundControl(GUI.SoundChannelEnable);
10829 }
10830
S9xPollButton(uint32 id,bool * pressed)10831 bool S9xPollButton(uint32 id, bool *pressed){
10832 if(S9xMoviePlaying())
10833 return false;
10834
10835 *pressed = false;
10836
10837 #define CHECK_KEY(controller, button) (!S9xGetState(Joypad[controller].button) || (ToggleJoypadStorage[controller].button && !TurboToggleJoypadStorage[controller].button) || (IPPU.TotalEmulatedFrames%2 == ToggleJoypadStorage[controller].button && TurboToggleJoypadStorage[controller].button))
10838
10839 extern bool S9xGetState (WORD KeyIdent);
10840 if (id & k_MO) // mouse
10841 {
10842 switch (id & 0xFF)
10843 {
10844 case 0: *pressed = GUI.MouseButtons & 1 /* Left */ || ((id & k_C1) && (CHECK_KEY(0,A) || CHECK_KEY(0,L))) || ((id & k_C2) && (CHECK_KEY(1,A) || CHECK_KEY(1,L))); break;
10845 case 1: *pressed = GUI.MouseButtons & 2 /* Right */ || ((id & k_C1) && (CHECK_KEY(0,B) || CHECK_KEY(0,R))) || ((id & k_C2) && (CHECK_KEY(1,B) || CHECK_KEY(1,R))); break;
10846 }
10847 }
10848 else
10849 if (id & k_SS) // superscope
10850 {
10851 switch (id & 0xFF)
10852 {
10853 case 0: *pressed = GUI.MouseX <= 0 || GUI.MouseY <= 0 || GUI.MouseX >= IPPU.RenderedScreenWidth || GUI.MouseY >= ((IPPU.RenderedScreenHeight> 256) ? SNES_HEIGHT_EXTENDED<<1 : SNES_HEIGHT_EXTENDED) || CHECK_KEY(1,X); break;
10854 case 2: *pressed = (GUI.MouseButtons & 2) /* Right */ || CHECK_KEY(1,B) || CHECK_KEY(1,R) ; break;
10855 case 3: *pressed = (GUI.MouseButtons & 4) /* Middle */ || GUI.superscope_turbo || CHECK_KEY(1,Y); GUI.superscope_turbo=0; GUI.MouseButtons &= ~4; break;
10856 case 4: *pressed = GUI.superscope_pause || CHECK_KEY(1,Start) || CHECK_KEY(1,Select); break;
10857 case 1: *pressed = (GUI.MouseButtons & 1) /* Left */ || CHECK_KEY(1,A) || CHECK_KEY(1,L); break;
10858 }
10859 }
10860 else
10861 if (id & k_LG) // justifier
10862 {
10863 if (id & k_C1)
10864 {
10865 switch (id & 0xFF)
10866 {
10867 case 0: *pressed = GUI.MouseX <= 0 || GUI.MouseY <= 0 || GUI.MouseX >= IPPU.RenderedScreenWidth || GUI.MouseY >= ((IPPU.RenderedScreenHeight> 256) ? SNES_HEIGHT_EXTENDED<<1 : SNES_HEIGHT_EXTENDED) || CHECK_KEY(0,X) || CHECK_KEY(0,Start); break;
10868 case 1: *pressed = GUI.MouseButtons & 1 /* Left */ || CHECK_KEY(0,A) || CHECK_KEY(0,L); break;
10869 case 2: *pressed = GUI.MouseButtons & 2 /* Right */ || CHECK_KEY(1,B) || CHECK_KEY(1,R); break;
10870 }
10871 }
10872 else
10873 {
10874 switch (id & 0xFF)
10875 {
10876 case 0: *pressed = CHECK_KEY(1,Start) /* 2p Start */ || CHECK_KEY(1,X); break;
10877 case 1: *pressed = CHECK_KEY(1,A) /* 2p A */ || CHECK_KEY(1,L); break;
10878 case 2: *pressed = CHECK_KEY(1,B) /* 2p B */ || CHECK_KEY(1,R); break;
10879 }
10880 }
10881 }
10882
10883 return (true);
10884 }
10885
10886 // ??? NYI
S9xPollAxis(uint32 id,int16 * value)10887 bool S9xPollAxis(uint32 id, int16 *value){
10888 return false;
10889 }
10890
S9xPollPointer(uint32 id,int16 * x,int16 * y)10891 bool S9xPollPointer(uint32 id, int16 *x, int16 *y){
10892 if(S9xMoviePlaying())
10893 return false;
10894
10895 if (id & k_PT)
10896 {
10897 *x = GUI.MouseX;
10898 *y = GUI.MouseY;
10899 }
10900 else
10901 *x = *y = 0;
10902 return (true);
10903 }
10904
10905 // adjusts settings based on ROM that was just loaded
S9xPostRomInit()10906 void S9xPostRomInit()
10907 {
10908 // "Cheats are on" message if cheats are on and active,
10909 // to make it less likely that someone will think there is some bug because of
10910 // a lingering cheat they don't realize is on
10911 if (Settings.ApplyCheats)
10912 {
10913 extern struct SCheatData Cheat;
10914 for (uint32 i = 0; i < Cheat.num_cheats; i++)
10915 {
10916 if (Cheat.c [i].enabled)
10917 {
10918 char String2 [1024];
10919 sprintf(String2, "(CHEATS ARE ON!) %s", String);
10920 strncpy(String, String2, 512);
10921 break;
10922 }
10923 }
10924 }
10925
10926 if(!S9xMovieActive() && !startingMovie)
10927 {
10928 // revert previously forced control
10929 if(GUI.ControlForced!=0xff) {
10930 GUI.ControllerOption = GUI.ControlForced;
10931 ChangeInputDevice();
10932 }
10933 int prevController = GUI.ControllerOption;
10934 GUI.ValidControllerOptions = 0xFFFF;
10935
10936 // NSRT controller settings
10937 if (!strncmp((const char *)Memory.NSRTHeader+24, "NSRT", 4))
10938 {
10939 switch(Memory.NSRTHeader[29])
10940 {
10941 default: // unknown or unsupported
10942 break;
10943 case 0x00: // Gamepad / Gamepad
10944 GUI.ControllerOption = SNES_JOYPAD;
10945 GUI.ValidControllerOptions = (1<<SNES_JOYPAD);
10946 break;
10947 case 0x10: // Mouse / Gamepad
10948 GUI.ControllerOption = SNES_MOUSE;
10949 GUI.ValidControllerOptions = (1<<SNES_MOUSE);
10950 break;
10951 case 0x20: // Mouse_or_Gamepad / Gamepad
10952 if(GUI.ControllerOption == SNES_MOUSE_SWAPPED)
10953 GUI.ControllerOption = SNES_MOUSE;
10954 if(GUI.ControllerOption != SNES_MOUSE)
10955 GUI.ControllerOption = SNES_JOYPAD;
10956 GUI.ValidControllerOptions = (1<<SNES_JOYPAD) | (1<<SNES_MOUSE);
10957 break;
10958 case 0x01: // Gamepad / Mouse
10959 GUI.ControllerOption = SNES_MOUSE_SWAPPED;
10960 GUI.ValidControllerOptions = (1<<SNES_MOUSE_SWAPPED);
10961 break;
10962 case 0x22: // Mouse_or_Gamepad / Mouse_or_Gamepad
10963 if(GUI.ControllerOption != SNES_MOUSE && GUI.ControllerOption != SNES_MOUSE_SWAPPED)
10964 GUI.ControllerOption = SNES_JOYPAD;
10965 GUI.ValidControllerOptions = (1<<SNES_JOYPAD) | (1<<SNES_MOUSE) | (1<<SNES_MOUSE_SWAPPED);
10966 break;
10967 case 0x03: // Gamepad / Superscope
10968 GUI.ControllerOption = SNES_SUPERSCOPE;
10969 GUI.ValidControllerOptions = (1<<SNES_SUPERSCOPE);
10970 break;
10971 case 0x04: // Gamepad / Gamepad_or_Superscope
10972 if(GUI.ControllerOption == SNES_JUSTIFIER || GUI.ControllerOption == SNES_JUSTIFIER_2)
10973 GUI.ControllerOption = SNES_SUPERSCOPE;
10974 if(GUI.ControllerOption != SNES_SUPERSCOPE)
10975 GUI.ControllerOption = SNES_JOYPAD;
10976 GUI.ValidControllerOptions = (1<<SNES_JOYPAD) | (1<<SNES_SUPERSCOPE);
10977 break;
10978 case 0x05: // Gamepad / Justifier
10979 if(GUI.ControllerOption != SNES_JUSTIFIER_2)
10980 GUI.ControllerOption = SNES_JUSTIFIER;
10981 GUI.ValidControllerOptions = (1<<SNES_JUSTIFIER) | (1<<SNES_JUSTIFIER_2);
10982 break;
10983 case 0x06: // Gamepad / Multitap_or_Gamepad
10984 GUI.ControllerOption = SNES_MULTIPLAYER5;
10985 GUI.ValidControllerOptions = (1<<SNES_MULTIPLAYER5) | (1<<SNES_JOYPAD);
10986 break;
10987 case 0x66: // Multitap_or_Gamepad / Multitap_or_Gamepad
10988 GUI.ControllerOption = SNES_MULTIPLAYER8;
10989 GUI.ValidControllerOptions = (1<<SNES_MULTIPLAYER8) | (1<<SNES_MULTIPLAYER5) | (1<<SNES_JOYPAD);
10990 break;
10991 case 0x24: // Gamepad_or_Mouse / Gamepad_or_Superscope
10992 if(GUI.ControllerOption == SNES_JUSTIFIER || GUI.ControllerOption == SNES_JUSTIFIER_2)
10993 GUI.ControllerOption = SNES_SUPERSCOPE;
10994 if(GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_MOUSE)
10995 GUI.ControllerOption = SNES_JOYPAD;
10996 GUI.ValidControllerOptions = (1<<SNES_JOYPAD) | (1<<SNES_MOUSE) | (1<<SNES_SUPERSCOPE);
10997 break;
10998 case 0x27: // Gamepad_or_Mouse / Gamepad_or_Mouse_or_Superscope
10999 if(GUI.ControllerOption == SNES_JUSTIFIER || GUI.ControllerOption == SNES_JUSTIFIER_2)
11000 GUI.ControllerOption = SNES_SUPERSCOPE;
11001 if(GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_MOUSE && GUI.ControllerOption != SNES_MOUSE_SWAPPED)
11002 GUI.ControllerOption = SNES_JOYPAD;
11003 GUI.ValidControllerOptions = (1<<SNES_JOYPAD) | (1<<SNES_MOUSE) | (1<<SNES_MOUSE_SWAPPED) | (1<<SNES_SUPERSCOPE);
11004 break;
11005 case 0x08: // Gamepad / Mouse_or_Multitap_or_Gamepad
11006 if(GUI.ControllerOption == SNES_MOUSE)
11007 GUI.ControllerOption = SNES_MOUSE_SWAPPED;
11008 if(GUI.ControllerOption == SNES_MULTIPLAYER8)
11009 GUI.ControllerOption = SNES_MULTIPLAYER5;
11010 if(GUI.ControllerOption != SNES_MULTIPLAYER5 && GUI.ControllerOption != SNES_MOUSE_SWAPPED)
11011 GUI.ControllerOption = SNES_JOYPAD;
11012 GUI.ValidControllerOptions = (1<<SNES_MOUSE_SWAPPED) | (1<<SNES_MULTIPLAYER5) | (1<<SNES_JOYPAD);
11013 break;
11014 }
11015 ChangeInputDevice();
11016 }
11017
11018 // update menu and remember what (if anything) the control was forced from
11019 GUI.ControlForced = prevController;
11020 }
11021
11022 // reset fast-forward and other input-related GUI state
11023 Settings.TurboMode = FALSE;
11024 GUI.superscope_turbo = 0;
11025 GUI.superscope_pause = 0;
11026 GUI.MouseButtons = 0;
11027 GUI.MouseX = 0;
11028 GUI.MouseY = 0;
11029 GUI.TurboMask = 0;
11030 GUI.FrameAdvanceJustPressed = 0;
11031
11032 // black out the screen
11033 for (uint32 y = 0; y < (uint32)IPPU.RenderedScreenHeight; y++)
11034 memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL*2);
11035 }
11036