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