PageRenderTime 258ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 1ms

/od-win32/win32.cpp

https://github.com/tonioni/WinUAE
C++ | 8048 lines | 7560 code | 354 blank | 134 comment | 1278 complexity | 49bd2430fa5b0cf46a57d05b9b623f71 MD5 | raw file
  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * Win32 interface
  5. *
  6. * Copyright 1997-1998 Mathias Ortmann
  7. * Copyright 1997-1999 Brian King
  8. */
  9. //#define MEMDEBUG
  10. #define MOUSECLIP_LOG 0
  11. #define MOUSECLIP_HIDE 1
  12. #define TOUCH_SUPPORT 1
  13. #define TOUCH_DEBUG 1
  14. #define KBHOOK 0
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <signal.h>
  18. #include "sysconfig.h"
  19. #define USETHREADCHARACTERICS 1
  20. #define _WIN32_WINNT 0x0A00
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include <commdlg.h>
  24. #include <shellapi.h>
  25. #include <zmouse.h>
  26. #include <ddraw.h>
  27. #include <dbt.h>
  28. #include <math.h>
  29. #include <mmsystem.h>
  30. #include <shobjidl.h>
  31. #include <shlobj.h>
  32. #include <shlwapi.h>
  33. #include <dbghelp.h>
  34. #include <float.h>
  35. #include <WtsApi32.h>
  36. #include <Avrt.h>
  37. #include <Cfgmgr32.h>
  38. #include <shellscalingapi.h>
  39. #include "resource.h"
  40. #include <wintab.h>
  41. #include "wintablet.h"
  42. #include <pktdef.h>
  43. #include "sysdeps.h"
  44. #include "options.h"
  45. #include "audio.h"
  46. #include "sound.h"
  47. #include "uae.h"
  48. #include "memory.h"
  49. #include "rommgr.h"
  50. #include "custom.h"
  51. #include "events.h"
  52. #include "newcpu.h"
  53. #include "traps.h"
  54. #include "xwin.h"
  55. #include "keyboard.h"
  56. #include "inputdevice.h"
  57. #include "keybuf.h"
  58. #include "drawing.h"
  59. #include "dxwrap.h"
  60. #include "picasso96_win.h"
  61. #include "bsdsocket.h"
  62. #include "win32.h"
  63. #include "win32gfx.h"
  64. #include "registry.h"
  65. #include "win32gui.h"
  66. #include "autoconf.h"
  67. #include "gui.h"
  68. #include "uae/mman.h"
  69. #include "avioutput.h"
  70. #include "ahidsound.h"
  71. #include "ahidsound_new.h"
  72. #include "zfile.h"
  73. #include "savestate.h"
  74. #include "ioport.h"
  75. #include "parser.h"
  76. #include "scsidev.h"
  77. #include "disk.h"
  78. #include "catweasel.h"
  79. #include "lcd.h"
  80. #include "uaeipc.h"
  81. #include "ar.h"
  82. #include "akiko.h"
  83. #include "cdtv.h"
  84. #include "direct3d.h"
  85. #include "clipboard_win32.h"
  86. #include "blkdev.h"
  87. #include "inputrecord.h"
  88. #include "gfxboard.h"
  89. #include "statusline.h"
  90. #include "devices.h"
  91. #ifdef RETROPLATFORM
  92. #include "rp.h"
  93. #include "cloanto/RetroPlatformIPC.h"
  94. #endif
  95. #include "uae/ppc.h"
  96. #include "fsdb.h"
  97. #include "uae/time.h"
  98. #include "specialmonitors.h"
  99. #include "debug.h"
  100. #include "disasm.h"
  101. const static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF,
  102. { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
  103. const static GUID GUID_DEVINTERFACE_KEYBOARD = { 0x884b96c3, 0x56ef, 0x11d1,
  104. { 0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd } };
  105. const static GUID GUID_DEVINTERFACE_MOUSE = { 0x378de44c, 0x56ef, 0x11d1,
  106. { 0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd } };
  107. extern int harddrive_dangerous, do_rdbdump;
  108. extern int no_rawinput, no_directinput, no_windowsmouse;
  109. extern int force_directsound;
  110. extern int log_a2065, a2065_promiscuous, log_ethernet;
  111. extern int rawinput_enabled_hid, rawinput_log;
  112. extern int log_filesys;
  113. extern int forcedframelatency;
  114. int log_scsi;
  115. int log_net;
  116. int log_vsync, debug_vsync_min_delay, debug_vsync_forced_delay;
  117. static int log_winmouse;
  118. int uaelib_debug;
  119. int pissoff_value = 15000 * CYCLE_UNIT;
  120. unsigned int fpucontrol;
  121. int extraframewait, extraframewait2;
  122. int busywait;
  123. static int noNtDelayExecution;
  124. extern FILE *debugfile;
  125. extern int console_logging;
  126. OSVERSIONINFO osVersion;
  127. static SYSTEM_INFO SystemInfo;
  128. static int logging_started;
  129. static MINIDUMP_TYPE minidumpmode = MiniDumpNormal;
  130. static int nocrashdump;
  131. static int doquit;
  132. static int console_started;
  133. void *globalipc;
  134. int cpu_mmx = 1;
  135. int D3DEX = 1;
  136. int shaderon = -1;
  137. int d3ddebug = 0;
  138. int max_uae_width;
  139. int max_uae_height;
  140. HINSTANCE hInst = NULL;
  141. HMODULE hUIDLL = NULL;
  142. HWND (WINAPI *pHtmlHelp)(HWND, LPCWSTR, UINT, LPDWORD);
  143. HWND hHiddenWnd, hGUIWnd;
  144. #if KBHOOK
  145. static HHOOK hhook;
  146. #endif
  147. static UINT TaskbarRestart;
  148. static HWND TaskbarRestartHWND;
  149. static int forceroms;
  150. static int start_data = 0;
  151. static void *tablet;
  152. HCURSOR normalcursor;
  153. static HWND hwndNextViewer;
  154. static bool clipboard_initialized;
  155. HANDLE AVTask;
  156. static int all_events_disabled;
  157. static int mainthreadid;
  158. TCHAR VersionStr[256];
  159. TCHAR BetaStr[64];
  160. extern pathtype path_type;
  161. int toggle_sound;
  162. int paraport_mask;
  163. HKEY hWinUAEKey = NULL;
  164. COLORREF g_dwBackgroundColor;
  165. HMODULE userdll;
  166. HMODULE kerneldll;
  167. int pause_emulation;
  168. static int sound_closed;
  169. static int recapture;
  170. static int focus;
  171. static int mouseinside;
  172. int mouseactive;
  173. int minimized;
  174. int monitor_off;
  175. static int mm_timerres;
  176. static int timermode, timeon;
  177. #define MAX_TIMEHANDLES 8
  178. static int timehandlecounter;
  179. static HANDLE timehandle[MAX_TIMEHANDLES];
  180. static bool timehandleinuse[MAX_TIMEHANDLES];
  181. static HANDLE cpu_wakeup_event;
  182. static volatile bool cpu_wakeup_event_triggered;
  183. int sleep_resolution;
  184. static CRITICAL_SECTION cs_time;
  185. TCHAR executable_path[MAX_DPATH];
  186. TCHAR start_path_data[MAX_DPATH];
  187. TCHAR start_path_exe[MAX_DPATH];
  188. TCHAR start_path_plugins[MAX_DPATH];
  189. TCHAR start_path_new1[MAX_DPATH]; /* AF2005 */
  190. TCHAR start_path_new2[MAX_DPATH]; /* AMIGAFOREVERDATA */
  191. TCHAR help_file[MAX_DPATH];
  192. TCHAR bootlogpath[MAX_DPATH];
  193. TCHAR logpath[MAX_DPATH];
  194. bool winuaelog_temporary_enable;
  195. int af_path_2005;
  196. int quickstart = 1, configurationcache = 1, relativepaths = 0, artcache = 0;
  197. int saveimageoriginalpath = 0;
  198. int recursiveromscan = 0;
  199. static TCHAR *inipath = NULL;
  200. static int guijoybutton[MAX_JPORTS];
  201. static int guijoyaxis[MAX_JPORTS][4];
  202. static bool guijoychange;
  203. typedef NTSTATUS(CALLBACK* NTDELAYEXECUTION)(BOOL, PLARGE_INTEGER);
  204. typedef NTSTATUS(CALLBACK* ZWSETTIMERRESOLUTION)(ULONG, BOOLEAN, PULONG);
  205. static NTDELAYEXECUTION pNtDelayExecution;
  206. static ZWSETTIMERRESOLUTION pZwSetTimerResolution;
  207. #if TOUCH_SUPPORT
  208. typedef BOOL (CALLBACK* REGISTERTOUCHWINDOW)(HWND, ULONG);
  209. typedef BOOL (CALLBACK* GETTOUCHINPUTINFO)(HTOUCHINPUT, UINT, PTOUCHINPUT, int);
  210. typedef BOOL (CALLBACK* CLOSETOUCHINPUTHANDLE)(HTOUCHINPUT);
  211. static GETTOUCHINPUTINFO pGetTouchInputInfo;
  212. static CLOSETOUCHINPUTHANDLE pCloseTouchInputHandle;
  213. #endif
  214. ADJUSTWINDOWRECTEXFORDPI pAdjustWindowRectExForDpi;
  215. typedef HRESULT(CALLBACK* GETDPIFORMONITOR)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*);
  216. static GETDPIFORMONITOR pGetDpiForMonitor;
  217. typedef UINT(CALLBACK* GETDPIFORWINDOW)(HWND);
  218. static GETDPIFORWINDOW pGetDpiForWindow;
  219. int getdpiformonitor(HMONITOR mon)
  220. {
  221. if (mon) {
  222. static HMODULE shcore;
  223. if (!shcore)
  224. shcore = LoadLibrary(_T("Shcore.dll"));
  225. if (shcore) {
  226. if (!pGetDpiForMonitor) {
  227. pGetDpiForMonitor = (GETDPIFORMONITOR)GetProcAddress(shcore, "GetDpiForMonitor");
  228. }
  229. if (pGetDpiForMonitor) {
  230. UINT x, y;
  231. if (SUCCEEDED(pGetDpiForMonitor(mon, MDT_EFFECTIVE_DPI, &x, &y)))
  232. return y;
  233. }
  234. }
  235. }
  236. HDC hdc = GetDC(NULL);
  237. int dpi = GetDeviceCaps(hdc, LOGPIXELSX);
  238. ReleaseDC(NULL, hdc);
  239. return dpi;
  240. }
  241. int getdpiforwindow(HWND hwnd)
  242. {
  243. if (!pGetDpiForWindow) {
  244. pGetDpiForWindow = (GETDPIFORWINDOW)GetProcAddress(userdll, "GetDpiForWindow");
  245. }
  246. if (pGetDpiForWindow)
  247. return pGetDpiForWindow(hwnd);
  248. HDC hdc = GetDC(NULL);
  249. int dpi = GetDeviceCaps(hdc, LOGPIXELSY);
  250. ReleaseDC(NULL, hdc);
  251. return dpi;
  252. }
  253. static ULONG ActualTimerResolution;
  254. int target_sleep_nanos(int nanos)
  255. {
  256. static bool init;
  257. if (!init && !noNtDelayExecution) {
  258. pNtDelayExecution = (NTDELAYEXECUTION)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtDelayExecution");
  259. pZwSetTimerResolution = (ZWSETTIMERRESOLUTION)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "ZwSetTimerResolution");
  260. if (pZwSetTimerResolution) {
  261. // 0.5ms
  262. NTSTATUS status = pZwSetTimerResolution((500 * 1000) / 100, TRUE, &ActualTimerResolution);
  263. if (!status) {
  264. LARGE_INTEGER interval;
  265. interval.QuadPart = -(int)ActualTimerResolution;
  266. status = pNtDelayExecution(false, &interval);
  267. if (!status) {
  268. write_log(_T("Using NtDelayExecution. ActualTimerResolution=%u\n"), ActualTimerResolution);
  269. } else {
  270. write_log(_T("NtDelayExecution returned %08x\n"), status);
  271. pNtDelayExecution = NULL;
  272. pZwSetTimerResolution = NULL;
  273. }
  274. } else {
  275. write_log(_T("NtDelayExecution not available\n"));
  276. pNtDelayExecution = NULL;
  277. pZwSetTimerResolution = NULL;
  278. }
  279. }
  280. init = true;
  281. }
  282. if (pNtDelayExecution) {
  283. if (nanos < 0)
  284. return 800;
  285. LARGE_INTEGER interval;
  286. int start = read_processor_time();
  287. nanos *= 10;
  288. if (nanos < ActualTimerResolution)
  289. nanos = ActualTimerResolution;
  290. interval.QuadPart = -nanos;
  291. pNtDelayExecution(false, &interval);
  292. idletime += read_processor_time() - start;
  293. } else {
  294. if (nanos < 0)
  295. return 1300;
  296. sleep_millis_main(1);
  297. }
  298. return 0;
  299. }
  300. uae_u64 spincount;
  301. extern bool calculated_scanline;
  302. void target_spin(int total)
  303. {
  304. if (!spincount || calculated_scanline)
  305. return;
  306. if (total > 10)
  307. total = 10;
  308. while (total-- >= 0) {
  309. uae_u64 v1 = __rdtsc();
  310. v1 += spincount;
  311. while (v1 > __rdtsc());
  312. }
  313. }
  314. extern int vsync_activeheight;
  315. void target_calibrate_spin(void)
  316. {
  317. struct amigadisplay *ad = &adisplays[0];
  318. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
  319. int vp;
  320. const int cntlines = 1;
  321. uae_u64 sc;
  322. spincount = 0;
  323. if (!ap->gfx_vsyncmode)
  324. return;
  325. if (busywait || calculated_scanline) {
  326. write_log(_T("target_calibrate_spin() skipped\n"));
  327. return;
  328. }
  329. write_log(_T("target_calibrate_spin() start\n"));
  330. sc = 0x800000000000;
  331. for (int i = 0; i < 50; i++) {
  332. for (;;) {
  333. vp = target_get_display_scanline(-1);
  334. if (vp <= -10)
  335. goto fail;
  336. if (vp >= 1 && vp < vsync_activeheight - 10)
  337. break;
  338. }
  339. uae_u64 v1;
  340. int vp2;
  341. for (;;) {
  342. v1 = __rdtsc();
  343. vp2 = target_get_display_scanline(-1);
  344. if (vp2 <= -10)
  345. goto fail;
  346. if (vp2 == vp + cntlines)
  347. break;
  348. if (vp2 < vp || vp2 > vp + cntlines)
  349. goto trynext;
  350. }
  351. for (;;) {
  352. int vp2 = target_get_display_scanline(-1);
  353. if (vp2 <= -10)
  354. goto fail;
  355. if (vp2 == vp + cntlines * 2) {
  356. uae_u64 scd = (__rdtsc() - v1) / cntlines;
  357. if (sc > scd)
  358. sc = scd;
  359. }
  360. if (vp2 < vp)
  361. break;
  362. if (vp2 > vp + cntlines * 2)
  363. break;
  364. }
  365. trynext:;
  366. }
  367. if (sc == 0x800000000000) {
  368. write_log(_T("Spincount calculation error, spinloop not used.\n"), sc);
  369. spincount = 0;
  370. } else {
  371. spincount = sc;
  372. write_log(_T("Spincount = %llu\n"), sc);
  373. }
  374. return;
  375. fail:
  376. write_log(_T("Scanline read failed: %d!\n"), vp);
  377. spincount = 0;
  378. }
  379. int timeend (void)
  380. {
  381. if (!timeon)
  382. return 1;
  383. timeon = 0;
  384. if (timeEndPeriod (mm_timerres) == TIMERR_NOERROR)
  385. return 1;
  386. write_log (_T("TimeEndPeriod() failed\n"));
  387. return 0;
  388. }
  389. int timebegin (void)
  390. {
  391. if (timeon) {
  392. timeend ();
  393. return timebegin ();
  394. }
  395. timeon = 0;
  396. if (timeBeginPeriod (mm_timerres) == TIMERR_NOERROR) {
  397. timeon = 1;
  398. return 1;
  399. }
  400. write_log (_T("TimeBeginPeriod() failed\n"));
  401. return 0;
  402. }
  403. static int init_mmtimer (void)
  404. {
  405. TIMECAPS tc;
  406. int i;
  407. mm_timerres = 0;
  408. if (timeGetDevCaps (&tc, sizeof (TIMECAPS)) != TIMERR_NOERROR)
  409. return 0;
  410. mm_timerres = min (max (tc.wPeriodMin, 1), tc.wPeriodMax);
  411. sleep_resolution = 1000 / mm_timerres;
  412. for (i = 0; i < MAX_TIMEHANDLES; i++)
  413. timehandle[i] = CreateEvent (NULL, TRUE, FALSE, NULL);
  414. cpu_wakeup_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  415. InitializeCriticalSection (&cs_time);
  416. timehandlecounter = 0;
  417. return 1;
  418. }
  419. void sleep_cpu_wakeup(void)
  420. {
  421. if (!cpu_wakeup_event_triggered) {
  422. cpu_wakeup_event_triggered = true;
  423. SetEvent(cpu_wakeup_event);
  424. }
  425. }
  426. HANDLE get_sound_event(void);
  427. extern HANDLE waitvblankevent;
  428. static int sleep_millis2 (int ms, bool main)
  429. {
  430. UINT TimerEvent;
  431. int start = 0;
  432. int cnt;
  433. HANDLE sound_event = get_sound_event();
  434. bool wasneg = ms < 0;
  435. bool pullcheck = false;
  436. int ret = 0;
  437. if (ms < 0)
  438. ms = -ms;
  439. if (main) {
  440. if (sound_event) {
  441. bool pullcheck = audio_is_event_frame_possible(ms);
  442. if (pullcheck) {
  443. if (WaitForSingleObject(sound_event, 0) == WAIT_OBJECT_0) {
  444. if (wasneg) {
  445. write_log(_T("efw %d imm abort\n"), ms);
  446. }
  447. return -1;
  448. }
  449. }
  450. }
  451. if (WaitForSingleObject(cpu_wakeup_event, 0) == WAIT_OBJECT_0) {
  452. return 0;
  453. }
  454. if (waitvblankevent && WaitForSingleObject(waitvblankevent, 0) == WAIT_OBJECT_0) {
  455. return 0;
  456. }
  457. start = read_processor_time ();
  458. }
  459. EnterCriticalSection (&cs_time);
  460. for (;;) {
  461. timehandlecounter++;
  462. if (timehandlecounter >= MAX_TIMEHANDLES)
  463. timehandlecounter = 0;
  464. if (timehandleinuse[timehandlecounter] == false) {
  465. cnt = timehandlecounter;
  466. timehandleinuse[cnt] = true;
  467. break;
  468. }
  469. }
  470. LeaveCriticalSection (&cs_time);
  471. TimerEvent = timeSetEvent (ms, 0, (LPTIMECALLBACK)timehandle[cnt], 0, TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
  472. if (main) {
  473. int c = 0;
  474. HANDLE evt[4];
  475. int sound_event_cnt = -1;
  476. int vblank_event_cnt = -1;
  477. evt[c++] = timehandle[cnt];
  478. evt[c++] = cpu_wakeup_event;
  479. if (waitvblankevent) {
  480. vblank_event_cnt = c;
  481. evt[c++] = waitvblankevent;
  482. }
  483. if (sound_event && pullcheck) {
  484. sound_event_cnt = c;
  485. evt[c++] = sound_event;
  486. }
  487. DWORD status = WaitForMultipleObjects(c, evt, FALSE, ms);
  488. if (sound_event_cnt >= 0 && status == WAIT_OBJECT_0 + sound_event_cnt)
  489. ret = -1;
  490. if (vblank_event_cnt >= 0 && status == WAIT_OBJECT_0 + vblank_event_cnt)
  491. ret = -1;
  492. if (wasneg) {
  493. if (sound_event_cnt >= 0 && status == WAIT_OBJECT_0 + sound_event_cnt) {
  494. write_log(_T("efw %d delayed abort\n"), ms);
  495. } else if (status == WAIT_TIMEOUT) {
  496. write_log(_T("efw %d full wait\n"), ms);
  497. }
  498. }
  499. cpu_wakeup_event_triggered = false;
  500. } else {
  501. WaitForSingleObject(timehandle[cnt], ms);
  502. }
  503. ResetEvent (timehandle[cnt]);
  504. timeKillEvent (TimerEvent);
  505. timehandleinuse[cnt] = false;
  506. if (main)
  507. idletime += read_processor_time () - start;
  508. return ret;
  509. }
  510. int sleep_millis_main (int ms)
  511. {
  512. return sleep_millis2 (ms, true);
  513. }
  514. int sleep_millis (int ms)
  515. {
  516. return sleep_millis2 (ms, false);
  517. }
  518. int sleep_millis_amiga(int ms)
  519. {
  520. int ret = sleep_millis_main(ms);
  521. return ret;
  522. }
  523. bool quit_ok(void)
  524. {
  525. if (isfullscreen() > 0)
  526. return true;
  527. if (!currprefs.win32_warn_exit)
  528. return true;
  529. if (quit_program == -UAE_QUIT)
  530. return true;
  531. TCHAR temp[MAX_DPATH];
  532. WIN32GUI_LoadUIString(IDS_QUIT_WARNING, temp, MAX_DPATH);
  533. int ret = gui_message_multibutton(1, temp);
  534. return ret == 1;
  535. }
  536. static void setcursor(struct AmigaMonitor *mon, int oldx, int oldy)
  537. {
  538. int dx = (mon->amigawinclip_rect.left - mon->amigawin_rect.left) + (mon->amigawinclip_rect.right - mon->amigawinclip_rect.left) / 2;
  539. int dy = (mon->amigawinclip_rect.top - mon->amigawin_rect.top) + (mon->amigawinclip_rect.bottom - mon->amigawinclip_rect.top) / 2;
  540. mon->mouseposx = oldx - dx;
  541. mon->mouseposy = oldy - dy;
  542. mon->windowmouse_max_w = (mon->amigawinclip_rect.right - mon->amigawinclip_rect.left) / 2 - 50;
  543. mon->windowmouse_max_h = (mon->amigawinclip_rect.bottom - mon->amigawinclip_rect.top) / 2 - 50;
  544. if (mon->windowmouse_max_w < 10)
  545. mon->windowmouse_max_w = 10;
  546. if (mon->windowmouse_max_h < 10)
  547. mon->windowmouse_max_h = 10;
  548. if ((currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC) && currprefs.input_tablet > 0 && mousehack_alive () && isfullscreen () <= 0) {
  549. mon->mouseposx = mon->mouseposy = 0;
  550. return;
  551. }
  552. #if MOUSECLIP_LOG
  553. write_log (_T("mon=%d %dx%d %dx%d %dx%d %dx%d (%dx%d %dx%d)\n"),
  554. mon->monitor_id,
  555. dx, dy,
  556. mon->mouseposx, mon->mouseposy,
  557. oldx, oldy,
  558. oldx + mon->amigawinclip_rect.left, oldy + mon->amigawinclip_rect.top,
  559. mon->amigawinclip_rect.left, mon->amigawinclip_rect.top,
  560. mon->amigawinclip_rect.right, mon->amigawinclip_rect.bottom);
  561. #endif
  562. if (oldx >= 30000 || oldy >= 30000 || oldx <= -30000 || oldy <= -30000) {
  563. oldx = oldy = 0;
  564. } else {
  565. if (abs(mon->mouseposx) < mon->windowmouse_max_w && abs(mon->mouseposy) < mon->windowmouse_max_h)
  566. return;
  567. }
  568. mon->mouseposx = mon->mouseposy = 0;
  569. if (oldx < 0 || oldy < 0 || oldx > mon->amigawin_rect.right - mon->amigawin_rect.left || oldy > mon->amigawin_rect.bottom - mon->amigawin_rect.top) {
  570. write_log (_T("Mouse out of range: mon=%d %dx%d (%dx%d %dx%d)\n"), mon->monitor_id, oldx, oldy,
  571. mon->amigawin_rect.left, mon->amigawin_rect.top, mon->amigawin_rect.right, mon->amigawin_rect.bottom);
  572. return;
  573. }
  574. int cx = (mon->amigawinclip_rect.right - mon->amigawinclip_rect.left) / 2 + mon->amigawin_rect.left + (mon->amigawinclip_rect.left - mon->amigawin_rect.left);
  575. int cy = (mon->amigawinclip_rect.bottom - mon->amigawinclip_rect.top) / 2 + mon->amigawin_rect.top + (mon->amigawinclip_rect.top - mon->amigawin_rect.top);
  576. #if MOUSECLIP_LOG
  577. write_log (_T("SetCursorPos(%d,%d) mon=%d\n"), cx, cy, mon->monitor_id);
  578. #endif
  579. SetCursorPos (cx, cy);
  580. }
  581. static int mon_cursorclipped;
  582. extern TCHAR config_filename[256];
  583. static void setmaintitle(int monid)
  584. {
  585. TCHAR txt[1000], txt2[500];
  586. HWND hwnd = AMonitors[monid].hMainWnd;
  587. #ifdef RETROPLATFORM
  588. if (rp_isactive ())
  589. return;
  590. #endif
  591. txt[0] = 0;
  592. if (!monid) {
  593. inprec_getstatus(txt);
  594. if (currprefs.config_window_title[0]) {
  595. _tcscat(txt, currprefs.config_window_title);
  596. _tcscat(txt, _T(" - "));
  597. } else if (config_filename[0]) {
  598. _tcscat(txt, _T("["));
  599. _tcscat(txt, config_filename);
  600. _tcscat(txt, _T("] - "));
  601. }
  602. } else {
  603. if (monid == currprefs.monitoremu_mon && currprefs.monitoremu >= 2) {
  604. _tcscat(txt, _T("["));
  605. _tcscat(txt, specialmonitorfriendlynames[currprefs.monitoremu - 2]);
  606. _tcscat(txt, _T("] - "));
  607. } else {
  608. for (int i = 0; i < MAX_RTG_BOARDS; i++) {
  609. if (monid == currprefs.rtgboards[i].monitor_id) {
  610. _tcscat(txt, _T("["));
  611. _tcscat(txt, gfxboard_get_name(currprefs.rtgboards[i].rtgmem_type));
  612. _tcscat(txt, _T("] - "));
  613. }
  614. }
  615. }
  616. }
  617. _tcscat (txt, _T("WinUAE"));
  618. txt2[0] = 0;
  619. if (!monid) {
  620. if (pause_emulation) {
  621. WIN32GUI_LoadUIString(IDS_WINUAETITLE_PAUSED, txt2, sizeof(txt2) / sizeof(TCHAR));
  622. } else if (mouseactive > 0) {
  623. WIN32GUI_LoadUIString((currprefs.input_mouse_untrap & MOUSEUNTRAP_MIDDLEBUTTON) ? IDS_WINUAETITLE_MMB : IDS_WINUAETITLE_NORMAL,
  624. txt2, sizeof(txt2) / sizeof(TCHAR));
  625. }
  626. if (_tcslen(WINUAEBETA) > 0) {
  627. _tcscat(txt, BetaStr);
  628. if (_tcslen(WINUAEEXTRA) > 0) {
  629. _tcscat(txt, _T(" "));
  630. _tcscat(txt, WINUAEEXTRA);
  631. }
  632. }
  633. }
  634. if (txt2[0]) {
  635. _tcscat (txt, _T(" - "));
  636. _tcscat (txt, txt2);
  637. }
  638. SetWindowText (hwnd, txt);
  639. }
  640. static int pausemouseactive;
  641. void resumesoundpaused (void)
  642. {
  643. resume_sound ();
  644. #ifdef AHI
  645. ahi_open_sound ();
  646. ahi2_pause_sound (0);
  647. #endif
  648. }
  649. void setsoundpaused (void)
  650. {
  651. pause_sound ();
  652. #ifdef AHI
  653. ahi_close_sound ();
  654. ahi2_pause_sound (1);
  655. #endif
  656. }
  657. bool resumepaused(int priority)
  658. {
  659. struct AmigaMonitor *mon = &AMonitors[0];
  660. //write_log (_T("resume %d (%d)\n"), priority, pause_emulation);
  661. if (pause_emulation > priority)
  662. return false;
  663. if (!pause_emulation)
  664. return false;
  665. devices_unpause();
  666. resumesoundpaused ();
  667. if (pausemouseactive) {
  668. pausemouseactive = 0;
  669. setmouseactive(mon->monitor_id, isfullscreen() > 0 ? 1 : -1);
  670. }
  671. pause_emulation = 0;
  672. setsystime ();
  673. setmaintitle(mon->monitor_id);
  674. wait_keyrelease();
  675. return true;
  676. }
  677. bool setpaused(int priority)
  678. {
  679. struct AmigaMonitor *mon = &AMonitors[0];
  680. //write_log (_T("pause %d (%d)\n"), priority, pause_emulation);
  681. if (pause_emulation > priority)
  682. return false;
  683. pause_emulation = priority;
  684. devices_pause();
  685. setsoundpaused ();
  686. pausemouseactive = 1;
  687. if (isfullscreen () <= 0) {
  688. pausemouseactive = mouseactive;
  689. setmouseactive(mon->monitor_id, 0);
  690. }
  691. setmaintitle(mon->monitor_id);
  692. return true;
  693. }
  694. void setminimized(int monid)
  695. {
  696. if (!minimized)
  697. minimized = 1;
  698. set_inhibit_frame(monid, IHF_WINDOWHIDDEN);
  699. if (isfullscreen() > 0 && D3D_resize) {
  700. write_log(_T("setminimized\n"));
  701. D3D_resize(monid, -1);
  702. }
  703. }
  704. void unsetminimized(int monid)
  705. {
  706. if (minimized < 0)
  707. WIN32GFX_DisplayChangeRequested(2);
  708. else if (minimized > 0)
  709. full_redraw_all();
  710. minimized = 0;
  711. clear_inhibit_frame(monid, IHF_WINDOWHIDDEN);
  712. }
  713. void refreshtitle(void)
  714. {
  715. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  716. struct AmigaMonitor *mon = &AMonitors[i];
  717. if (mon->hMainWnd && isfullscreen() == 0) {
  718. setmaintitle(mon->monitor_id);
  719. }
  720. }
  721. }
  722. #ifndef AVIOUTPUT
  723. static int avioutput_video = 0;
  724. #endif
  725. void setpriority (struct threadpriorities *pri)
  726. {
  727. int err;
  728. if (!AVTask) {
  729. DWORD opri = GetPriorityClass (GetCurrentProcess ());
  730. if (opri != IDLE_PRIORITY_CLASS && opri != NORMAL_PRIORITY_CLASS && opri != BELOW_NORMAL_PRIORITY_CLASS && opri != ABOVE_NORMAL_PRIORITY_CLASS)
  731. return;
  732. err = SetPriorityClass (GetCurrentProcess (), pri->classvalue);
  733. if (!err)
  734. write_log (_T("priority set failed, %08X\n"), GetLastError ());
  735. }
  736. }
  737. static void setcursorshape(int monid)
  738. {
  739. if (currprefs.input_tablet && (currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC) && currprefs.input_magic_mouse_cursor == MAGICMOUSE_NATIVE_ONLY) {
  740. if (GetCursor() != NULL)
  741. SetCursor(NULL);
  742. } else if (!picasso_setwincursor(monid)) {
  743. if (GetCursor() != normalcursor)
  744. SetCursor(normalcursor);
  745. }
  746. }
  747. void releasecapture(struct AmigaMonitor *mon)
  748. {
  749. //write_log(_T("releasecapture %d\n"), mon_cursorclipped);
  750. #if 0
  751. CURSORINFO pci;
  752. pci.cbSize = sizeof pci;
  753. GetCursorInfo(&pci);
  754. write_log(_T("PCI %08x %p %d %d\n"), pci.flags, pci.hCursor, pci.ptScreenPos.x, pci.ptScreenPos.y);
  755. #endif
  756. if (!mon_cursorclipped)
  757. return;
  758. if (!ClipCursor(NULL))
  759. write_log(_T("ClipCursor %08x\n"), GetLastError());
  760. if (!ReleaseCapture())
  761. write_log(_T("ReleaseCapture %08x\n"), GetLastError());
  762. int c = ShowCursor(TRUE);
  763. write_log(_T("ShowCursor %d\n"), c);
  764. mon_cursorclipped = 0;
  765. }
  766. void updatemouseclip(struct AmigaMonitor *mon)
  767. {
  768. if (mon_cursorclipped) {
  769. mon->amigawinclip_rect = mon->amigawin_rect;
  770. if (!isfullscreen()) {
  771. int idx = 0;
  772. reenumeratemonitors();
  773. while (Displays[idx].monitorname) {
  774. RECT out;
  775. struct MultiDisplay *md = &Displays[idx];
  776. idx++;
  777. if (md->rect.left == md->workrect.left && md->rect.right == md->workrect.right
  778. && md->rect.top == md->workrect.top && md->rect.bottom == md->workrect.bottom)
  779. continue;
  780. // not in this monitor?
  781. if (!IntersectRect(&out, &md->rect, &mon->amigawin_rect))
  782. continue;
  783. for (int e = 0; e < 4; e++) {
  784. int v1, v2, x, y;
  785. LONG *lp;
  786. switch (e)
  787. {
  788. case 0:
  789. default:
  790. v1 = md->rect.left;
  791. v2 = md->workrect.left;
  792. lp = &mon->amigawinclip_rect.left;
  793. x = v1 - 1;
  794. y = (md->rect.bottom - md->rect.top) / 2;
  795. break;
  796. case 1:
  797. v1 = md->rect.top;
  798. v2 = md->workrect.top;
  799. lp = &mon->amigawinclip_rect.top;
  800. x = (md->rect.right - md->rect.left) / 2;
  801. y = v1 - 1;
  802. break;
  803. case 2:
  804. v1 = md->rect.right;
  805. v2 = md->workrect.right;
  806. lp = &mon->amigawinclip_rect.right;
  807. x = v1 + 1;
  808. y = (md->rect.bottom - md->rect.top) / 2;
  809. break;
  810. case 3:
  811. v1 = md->rect.bottom;
  812. v2 = md->workrect.bottom;
  813. lp = &mon->amigawinclip_rect.bottom;
  814. x = (md->rect.right - md->rect.left) / 2;
  815. y = v1 + 1;
  816. break;
  817. }
  818. // is there another monitor sharing this edge?
  819. POINT pt;
  820. pt.x = x;
  821. pt.y = y;
  822. if (MonitorFromPoint(pt, MONITOR_DEFAULTTONULL))
  823. continue;
  824. // restrict mouse clip bounding box to this edge
  825. if (e >= 2) {
  826. if (*lp > v2) {
  827. *lp = v2;
  828. }
  829. } else {
  830. if (*lp < v2) {
  831. *lp = v2;
  832. }
  833. }
  834. }
  835. }
  836. // Too small or invalid?
  837. if (mon->amigawinclip_rect.right <= mon->amigawinclip_rect.left + 7 || mon->amigawinclip_rect.bottom <= mon->amigawinclip_rect.top + 7)
  838. mon->amigawinclip_rect = mon->amigawin_rect;
  839. }
  840. if (mon_cursorclipped == mon->monitor_id + 1) {
  841. #if MOUSECLIP_LOG
  842. write_log(_T("CLIP mon=%d %dx%d %dx%d %d\n"), mon->monitor_id, mon->amigawin_rect.left, mon->amigawin_rect.top, mon->amigawin_rect.right, mon->amigawin_rect.bottom, isfullscreen());
  843. #endif
  844. if (!ClipCursor(&mon->amigawinclip_rect))
  845. write_log(_T("ClipCursor error %d\n"), GetLastError());
  846. }
  847. }
  848. }
  849. void updatewinrect(struct AmigaMonitor *mon, bool allowfullscreen)
  850. {
  851. int f = isfullscreen ();
  852. if (!allowfullscreen && f > 0)
  853. return;
  854. GetWindowRect(mon->hAmigaWnd, &mon->amigawin_rect);
  855. GetWindowRect(mon->hAmigaWnd, &mon->amigawinclip_rect);
  856. #if MOUSECLIP_LOG
  857. write_log (_T("GetWindowRect mon=%d %dx%d %dx%d %d\n"), mon->monitor_id, mon->amigawin_rect.left, mon->amigawin_rect.top, mon->amigawin_rect.right, mon->amigawin_rect.bottom, f);
  858. #endif
  859. if (f == 0 && mon->monitor_id == 0) {
  860. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.x = mon->amigawin_rect.left;
  861. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.y = mon->amigawin_rect.top;
  862. currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.x = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.x;
  863. currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.y = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.y;
  864. }
  865. }
  866. #if KBHOOK
  867. static bool HasAltModifier(int flags)
  868. {
  869. return (flags & 0x20) == 0x20;
  870. }
  871. static LRESULT CALLBACK captureKey(int nCode, WPARAM wp, LPARAM lp)
  872. {
  873. if (nCode >= 0)
  874. {
  875. KBDLLHOOKSTRUCT *kbd = (KBDLLHOOKSTRUCT*)lp;
  876. DWORD vk = kbd->vkCode;
  877. DWORD flags = kbd->flags;
  878. // Disabling Windows keys
  879. if (vk == VK_RWIN || vk == VK_LWIN || (vk == VK_TAB && HasAltModifier(flags))) {
  880. return 1;
  881. }
  882. }
  883. return CallNextHookEx(hhook, nCode, wp, lp);
  884. }
  885. #endif
  886. static bool iswindowfocus(struct AmigaMonitor *mon)
  887. {
  888. bool donotfocus = false;
  889. HWND f = GetFocus ();
  890. HWND fw = GetForegroundWindow ();
  891. HWND w1 = mon->hAmigaWnd;
  892. HWND w2 = mon->hMainWnd;
  893. if (f != w1 && f != w2)
  894. donotfocus = true;
  895. //write_log(_T("f=%p fw=%p w1=%p w2=%p\n"), f, fw, w1, w2);
  896. #ifdef RETROPLATFORM
  897. if (rp_isactive()) {
  898. HWND hGuestParent = rp_getparent();
  899. DWORD dwHostProcessId;
  900. GetWindowThreadProcessId(hGuestParent, &dwHostProcessId);
  901. if (fw) {
  902. DWORD dwForegroundProcessId = 0;
  903. GetWindowThreadProcessId(fw, &dwForegroundProcessId);
  904. //write_log(_T("dwForegroundProcessId=%p dwHostProcessId=%p\n"), dwForegroundProcessId, dwHostProcessId);
  905. if (dwForegroundProcessId == dwHostProcessId) {
  906. donotfocus = false;
  907. }
  908. }
  909. }
  910. #endif
  911. if (isfullscreen () > 0)
  912. donotfocus = false;
  913. return donotfocus == false;
  914. }
  915. bool ismouseactive (void)
  916. {
  917. return mouseactive > 0;
  918. }
  919. void target_inputdevice_unacquire(void)
  920. {
  921. close_tablet(tablet);
  922. tablet = NULL;
  923. }
  924. void target_inputdevice_acquire(void)
  925. {
  926. struct AmigaMonitor *mon = &AMonitors[0];
  927. target_inputdevice_unacquire();
  928. tablet = open_tablet(mon->hAmigaWnd);
  929. }
  930. int getfocusedmonitor(void)
  931. {
  932. if (focus > 0) {
  933. return focus - 1;
  934. }
  935. return 0;
  936. }
  937. static void setmouseactive2(struct AmigaMonitor *mon, int active, bool allowpause)
  938. {
  939. #ifdef RETROPLATFORM
  940. bool isrp = rp_isactive () != 0;
  941. #else
  942. bool isrp = false;
  943. #endif
  944. //write_log (_T("setmouseactive %d->%d cursor=%d focus=%d recap=%d\n"), mouseactive, active, mon_cursorclipped, focus, recapture);
  945. if (active == 0)
  946. releasecapture (mon);
  947. if (mouseactive == active && active >= 0)
  948. return;
  949. if (!isrp && active == 1 && !(currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC)) {
  950. HANDLE c = GetCursor ();
  951. if (c != normalcursor)
  952. return;
  953. }
  954. if (active) {
  955. if (!isrp && !IsWindowVisible (mon->hAmigaWnd))
  956. return;
  957. }
  958. if (active < 0)
  959. active = 1;
  960. mouseactive = active ? mon->monitor_id + 1 : 0;
  961. mon->mouseposx = mon->mouseposy = 0;
  962. //write_log (_T("setmouseactive(%d)\n"), active);
  963. releasecapture (mon);
  964. recapture = 0;
  965. if (isfullscreen () <= 0 && (currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC) && currprefs.input_tablet > 0) {
  966. if (mousehack_alive ())
  967. return;
  968. SetCursor (normalcursor);
  969. }
  970. bool gotfocus = false;
  971. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  972. HWND h = GetFocus();
  973. if (h && (h == AMonitors[i].hAmigaWnd || h == AMonitors[i].hMainWnd)) {
  974. mon = &AMonitors[i];
  975. break;
  976. }
  977. }
  978. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  979. if (iswindowfocus(&AMonitors[i])) {
  980. gotfocus = true;
  981. break;
  982. }
  983. }
  984. if (!gotfocus) {
  985. write_log (_T("Tried to capture mouse but window didn't have focus! F=%d A=%d\n"), focus, mouseactive);
  986. focus = 0;
  987. mouseactive = 0;
  988. active = 0;
  989. }
  990. if (mouseactive > 0)
  991. focus = mon->monitor_id + 1;
  992. //write_log(_T("setcapture %d %d %d\n"), mouseactive, focus, mon_cursorclipped);
  993. if (mouseactive) {
  994. if (focus) {
  995. if (GetActiveWindow() != mon->hMainWnd && GetActiveWindow() != mon->hAmigaWnd)
  996. SetActiveWindow(mon->hMainWnd);
  997. if (!mon_cursorclipped) {
  998. //write_log(_T("setcapture\n"));
  999. #if MOUSECLIP_HIDE
  1000. ShowCursor (FALSE);
  1001. #endif
  1002. SetCapture (mon->hAmigaWnd);
  1003. updatewinrect(mon, false);
  1004. mon_cursorclipped = mon->monitor_id + 1;
  1005. updatemouseclip(mon);
  1006. }
  1007. setcursor(mon, -30000, -30000);
  1008. }
  1009. wait_keyrelease();
  1010. inputdevice_acquire(TRUE);
  1011. setpriority (&priorities[currprefs.win32_active_capture_priority]);
  1012. if (currprefs.win32_active_nocapture_pause) {
  1013. resumepaused(2);
  1014. } else if (currprefs.win32_active_nocapture_nosound && sound_closed < 0) {
  1015. resumesoundpaused();
  1016. }
  1017. setmaintitle(mon->monitor_id);
  1018. #if KBHOOK
  1019. if (!hhook) {
  1020. hhook = SetWindowsHookEx(WH_KEYBOARD_LL, captureKey, GetModuleHandle(NULL), 0);
  1021. }
  1022. #endif
  1023. } else {
  1024. #if KBHOOK
  1025. if (hhook) {
  1026. UnhookWindowsHookEx(hhook);
  1027. hhook = NULL;
  1028. }
  1029. #endif
  1030. inputdevice_acquire (FALSE);
  1031. inputdevice_releasebuttons();
  1032. }
  1033. if (!active && allowpause) {
  1034. if (currprefs.win32_active_nocapture_pause) {
  1035. setpaused (2);
  1036. } else if (currprefs.win32_active_nocapture_nosound) {
  1037. setsoundpaused ();
  1038. sound_closed = -1;
  1039. }
  1040. setmaintitle(mon->monitor_id);
  1041. }
  1042. #ifdef RETROPLATFORM
  1043. rp_mouse_capture(active);
  1044. rp_mouse_magic(magicmouse_alive());
  1045. #endif
  1046. }
  1047. void setmouseactive(int monid, int active)
  1048. {
  1049. struct AmigaMonitor *mon = &AMonitors[monid];
  1050. monitor_off = 0;
  1051. if (active > 1)
  1052. SetForegroundWindow(mon->hAmigaWnd);
  1053. setmouseactive2(mon, active, true);
  1054. }
  1055. static int hotkeys[] = { VK_VOLUME_UP, VK_VOLUME_DOWN, VK_VOLUME_MUTE, -1 };
  1056. static void winuae_active(struct AmigaMonitor *mon, HWND hwnd, int minimized)
  1057. {
  1058. struct threadpriorities *pri;
  1059. //write_log (_T("winuae_active(%p,%d)\n"), hwnd, minimized);
  1060. monitor_off = 0;
  1061. /* without this returning from hibernate-mode causes wrong timing
  1062. */
  1063. timeend ();
  1064. sleep_millis (2);
  1065. timebegin ();
  1066. focus = mon->monitor_id + 1;
  1067. pri = &priorities[currprefs.win32_inactive_priority];
  1068. if (!minimized)
  1069. pri = &priorities[currprefs.win32_active_capture_priority];
  1070. setpriority(pri);
  1071. if (sound_closed) {
  1072. if (sound_closed < 0) {
  1073. resumesoundpaused ();
  1074. } else {
  1075. if (currprefs.win32_active_nocapture_pause) {
  1076. if (mouseactive)
  1077. resumepaused (2);
  1078. } else if (currprefs.win32_iconified_pause && !currprefs.win32_inactive_pause)
  1079. resumepaused (1);
  1080. else if (currprefs.win32_inactive_pause)
  1081. resumepaused (2);
  1082. }
  1083. sound_closed = 0;
  1084. }
  1085. #if 0
  1086. RegisterHotKey (mon->hAmigaWnd, IDHOT_SNAPDESKTOP, 0, VK_SNAPSHOT);
  1087. for (int i = 0; hotkeys[i] >= 0; i++)
  1088. RegisterHotKey (mon->hAmigaWnd, hotkeys[i], 0, hotkeys[i]);
  1089. #endif
  1090. getcapslock ();
  1091. wait_keyrelease ();
  1092. inputdevice_acquire (TRUE);
  1093. if ((isfullscreen () > 0 || currprefs.win32_capture_always) && !gui_active)
  1094. setmouseactive(mon->monitor_id, 1);
  1095. #ifdef LOGITECHLCD
  1096. if (!minimized)
  1097. lcd_priority (1);
  1098. #endif
  1099. clipboard_active(mon->hAmigaWnd, 1);
  1100. #if USETHREADCHARACTERICS
  1101. if (os_vista && AVTask == NULL) {
  1102. typedef HANDLE(WINAPI* AVSETMMTHREADCHARACTERISTICS)(LPCTSTR, LPDWORD);
  1103. DWORD taskIndex = 0;
  1104. AVSETMMTHREADCHARACTERISTICS pAvSetMmThreadCharacteristics =
  1105. (AVSETMMTHREADCHARACTERISTICS)GetProcAddress(GetModuleHandle(_T("Avrt.dll")), "AvSetMmThreadCharacteristicsW");
  1106. if (pAvSetMmThreadCharacteristics) {
  1107. if (!(AVTask = pAvSetMmThreadCharacteristics(TEXT("Pro Audio"), &taskIndex))) {
  1108. write_log (_T("AvSetMmThreadCharacteristics failed: %d\n"), GetLastError ());
  1109. }
  1110. }
  1111. }
  1112. #endif
  1113. }
  1114. static void winuae_inactive(struct AmigaMonitor *mon, HWND hWnd, int minimized)
  1115. {
  1116. struct threadpriorities *pri;
  1117. int wasfocus = focus;
  1118. //write_log (_T("winuae_inactive(%d)\n"), minimized);
  1119. #if USETHREADCHARACTERICS
  1120. if (AVTask) {
  1121. typedef BOOL(WINAPI* AVREVERTMMTHREADCHARACTERISTICS)(HANDLE);
  1122. AVREVERTMMTHREADCHARACTERISTICS pAvRevertMmThreadCharacteristics =
  1123. (AVREVERTMMTHREADCHARACTERISTICS)GetProcAddress(GetModuleHandle(_T("Avrt.dll")), "AvRevertMmThreadCharacteristics");
  1124. if (pAvRevertMmThreadCharacteristics)
  1125. pAvRevertMmThreadCharacteristics(AVTask);
  1126. AVTask = NULL;
  1127. }
  1128. #endif
  1129. if (!currprefs.win32_powersavedisabled)
  1130. SetThreadExecutionState (ES_CONTINUOUS);
  1131. if (minimized)
  1132. exit_gui(0);
  1133. #if 0
  1134. for (int i = 0; hotkeys[i] >= 0; i++)
  1135. UnregisterHotKey (mon->hAmigaWnd, hotkeys[i]);
  1136. UnregisterHotKey (mon->hAmigaWnd, IDHOT_SNAPDESKTOP);
  1137. #endif
  1138. focus = 0;
  1139. recapture = 0;
  1140. wait_keyrelease ();
  1141. setmouseactive(mon->monitor_id, 0);
  1142. clipboard_active(mon->hAmigaWnd, 0);
  1143. pri = &priorities[currprefs.win32_inactive_priority];
  1144. if (!quit_program) {
  1145. if (minimized) {
  1146. pri = &priorities[currprefs.win32_iconified_priority];
  1147. if (currprefs.win32_iconified_pause) {
  1148. inputdevice_unacquire();
  1149. setpaused(1);
  1150. sound_closed = 1;
  1151. } else if (currprefs.win32_iconified_nosound) {
  1152. inputdevice_unacquire(true, currprefs.win32_iconified_input);
  1153. setsoundpaused();
  1154. sound_closed = -1;
  1155. } else {
  1156. inputdevice_unacquire(true, currprefs.win32_iconified_input);
  1157. }
  1158. } else if (mouseactive) {
  1159. inputdevice_unacquire();
  1160. if (currprefs.win32_active_nocapture_pause) {
  1161. setpaused (2);
  1162. sound_closed = 1;
  1163. } else if (currprefs.win32_active_nocapture_nosound) {
  1164. setsoundpaused ();
  1165. sound_closed = -1;
  1166. }
  1167. } else {
  1168. if (currprefs.win32_inactive_pause) {
  1169. inputdevice_unacquire();
  1170. setpaused(2);
  1171. sound_closed = 1;
  1172. } else if (currprefs.win32_inactive_nosound) {
  1173. inputdevice_unacquire(true, currprefs.win32_inactive_input);
  1174. setsoundpaused();
  1175. sound_closed = -1;
  1176. } else {
  1177. inputdevice_unacquire(true, currprefs.win32_inactive_input);
  1178. }
  1179. }
  1180. } else {
  1181. inputdevice_unacquire();
  1182. }
  1183. setpriority (pri);
  1184. #ifdef FILESYS
  1185. filesys_flush_cache ();
  1186. #endif
  1187. #ifdef LOGITECHLCD
  1188. lcd_priority (0);
  1189. #endif
  1190. }
  1191. void minimizewindow(int monid)
  1192. {
  1193. struct AmigaMonitor *mon = &AMonitors[monid];
  1194. if (mon->screen_is_initialized)
  1195. ShowWindow (mon->hMainWnd, SW_MINIMIZE);
  1196. }
  1197. void enablecapture(int monid)
  1198. {
  1199. if (pause_emulation > 2)
  1200. return;
  1201. //write_log(_T("enablecapture\n"));
  1202. setmouseactive(monid, 1);
  1203. if (sound_closed < 0) {
  1204. resumesoundpaused();
  1205. sound_closed = 0;
  1206. }
  1207. if (currprefs.win32_inactive_pause || currprefs.win32_active_nocapture_pause) {
  1208. resumepaused(2);
  1209. }
  1210. }
  1211. void disablecapture(void)
  1212. {
  1213. //write_log(_T("disablecapture\n"));
  1214. setmouseactive(0, 0);
  1215. focus = 0;
  1216. if (currprefs.win32_active_nocapture_pause && sound_closed == 0) {
  1217. setpaused (2);
  1218. sound_closed = 1;
  1219. } else if (currprefs.win32_active_nocapture_nosound && sound_closed == 0) {
  1220. setsoundpaused ();
  1221. sound_closed = -1;
  1222. }
  1223. }
  1224. void gui_gameport_button_change (int port, int button, int onoff)
  1225. {
  1226. //write_log (_T("%d %d %d\n"), port, button, onoff);
  1227. #ifdef RETROPLATFORM
  1228. int mask = 0;
  1229. if (button == JOYBUTTON_CD32_PLAY)
  1230. mask = RP_JOYSTICK_BUTTON5;
  1231. if (button == JOYBUTTON_CD32_RWD)
  1232. mask = RP_JOYSTICK_BUTTON6;
  1233. if (button == JOYBUTTON_CD32_FFW)
  1234. mask = RP_JOYSTICK_BUTTON7;
  1235. if (button == JOYBUTTON_CD32_GREEN)
  1236. mask = RP_JOYSTICK_BUTTON4;
  1237. if (button == JOYBUTTON_3 || button == JOYBUTTON_CD32_YELLOW)
  1238. mask = RP_JOYSTICK_BUTTON3;
  1239. if (button == JOYBUTTON_1 || button == JOYBUTTON_CD32_RED)
  1240. mask = RP_JOYSTICK_BUTTON1;
  1241. if (button == JOYBUTTON_2 || button == JOYBUTTON_CD32_BLUE)
  1242. mask = RP_JOYSTICK_BUTTON2;
  1243. rp_update_gameport (port, mask, onoff);
  1244. #endif
  1245. if (onoff)
  1246. guijoybutton[port] |= 1 << button;
  1247. else
  1248. guijoybutton[port] &= ~(1 << button);
  1249. guijoychange = true;
  1250. }
  1251. void gui_gameport_axis_change (int port, int axis, int state, int max)
  1252. {
  1253. int onoff = state ? 100 : 0;
  1254. if (axis < 0 || axis > 3)
  1255. return;
  1256. if (max < 0) {
  1257. if (guijoyaxis[port][axis] == 0)
  1258. return;
  1259. if (guijoyaxis[port][axis] > 0)
  1260. guijoyaxis[port][axis]--;
  1261. } else {
  1262. if (state > max)
  1263. state = max;
  1264. if (state < 0)
  1265. state = 0;
  1266. guijoyaxis[port][axis] = max ? state * 127 / max : onoff;
  1267. #ifdef RETROPLATFORM
  1268. if (axis == DIR_LEFT_BIT)
  1269. rp_update_gameport (port, RP_JOYSTICK_LEFT, onoff);
  1270. if (axis == DIR_RIGHT_BIT)
  1271. rp_update_gameport (port, RP_JOYSTICK_RIGHT, onoff);
  1272. if (axis == DIR_UP_BIT)
  1273. rp_update_gameport (port, RP_JOYSTICK_UP, onoff);
  1274. if (axis == DIR_DOWN_BIT)
  1275. rp_update_gameport (port, RP_JOYSTICK_DOWN, onoff);
  1276. #endif
  1277. }
  1278. guijoychange = true;
  1279. }
  1280. void setmouseactivexy(int monid, int x, int y, int dir)
  1281. {
  1282. struct AmigaMonitor *mon = &AMonitors[monid];
  1283. int diff = 8;
  1284. if (isfullscreen () > 0)
  1285. return;
  1286. x += mon->amigawin_rect.left;
  1287. y += mon->amigawin_rect.top;
  1288. if (dir & 1)
  1289. x = mon->amigawin_rect.left - diff;
  1290. if (dir & 2)
  1291. x = mon->amigawin_rect.right + diff;
  1292. if (dir & 4)
  1293. y = mon->amigawin_rect.top - diff;
  1294. if (dir & 8)
  1295. y = mon->amigawin_rect.bottom + diff;
  1296. if (!dir) {
  1297. x += (mon->amigawin_rect.right - mon->amigawin_rect.left) / 2;
  1298. y += (mon->amigawin_rect.bottom - mon->amigawin_rect.top) / 2;
  1299. }
  1300. if (isfullscreen () < 0) {
  1301. POINT pt;
  1302. pt.x = x;
  1303. pt.y = y;
  1304. if (MonitorFromPoint (pt, MONITOR_DEFAULTTONULL) == NULL)
  1305. return;
  1306. }
  1307. if (mouseactive) {
  1308. disablecapture ();
  1309. SetCursorPos (x, y);
  1310. if (dir) {
  1311. recapture = 1;
  1312. }
  1313. }
  1314. }
  1315. int isfocus(void)
  1316. {
  1317. if (isfullscreen () > 0) {
  1318. if (!minimized)
  1319. return 2;
  1320. return 0;
  1321. }
  1322. if (currprefs.input_tablet >= TABLET_MOUSEHACK && (currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC)) {
  1323. if (mouseinside)
  1324. return 2;
  1325. if (focus)
  1326. return 1;
  1327. return 0;
  1328. }
  1329. if (focus && mouseactive > 0)
  1330. return 2;
  1331. if (focus)
  1332. return -1;
  1333. return 0;
  1334. }
  1335. static void activationtoggle(int monid, bool inactiveonly)
  1336. {
  1337. if (mouseactive) {
  1338. if ((isfullscreen () > 0) || (isfullscreen () < 0 && currprefs.win32_minimize_inactive)) {
  1339. disablecapture();
  1340. minimizewindow(monid);
  1341. } else {
  1342. setmouseactive(monid, 0);
  1343. }
  1344. } else {
  1345. if (!inactiveonly)
  1346. setmouseactive(monid, 1);
  1347. }
  1348. }
  1349. static void handleXbutton (WPARAM wParam, int updown)
  1350. {
  1351. int b = GET_XBUTTON_WPARAM (wParam);
  1352. int num = (b & XBUTTON1) ? 3 : (b & XBUTTON2) ? 4 : -1;
  1353. if (num >= 0)
  1354. setmousebuttonstate (dinput_winmouse (), num, updown);
  1355. }
  1356. #define MEDIA_INSERT_QUEUE_SIZE 10
  1357. static TCHAR *media_insert_queue[MEDIA_INSERT_QUEUE_SIZE];
  1358. static int media_insert_queue_type[MEDIA_INSERT_QUEUE_SIZE];
  1359. static int media_change_timer;
  1360. static int device_change_timer;
  1361. static int is_in_media_queue(const TCHAR *drvname)
  1362. {
  1363. for (int i = 0; i < MEDIA_INSERT_QUEUE_SIZE; i++) {
  1364. if (media_insert_queue[i] != NULL) {
  1365. if (!_tcsicmp(drvname, media_insert_queue[i]))
  1366. return i;
  1367. }
  1368. }
  1369. return -1;
  1370. }
  1371. static void start_media_insert_timer(HWND hwnd)
  1372. {
  1373. if (!media_change_timer) {
  1374. media_change_timer = 1;
  1375. SetTimer(hwnd, 2, 1000, NULL);
  1376. }
  1377. }
  1378. static void add_media_insert_queue(HWND hwnd, const TCHAR *drvname, int retrycnt)
  1379. {
  1380. int idx = is_in_media_queue(drvname);
  1381. if (idx >= 0) {
  1382. if (retrycnt > media_insert_queue_type[idx])
  1383. media_insert_queue_type[idx] = retrycnt;
  1384. write_log(_T("%s already queued for insertion, cnt=%d.\n"), drvname, retrycnt);
  1385. start_media_insert_timer(hwnd);
  1386. return;
  1387. }
  1388. for (int i = 0; i < MEDIA_INSERT_QUEUE_SIZE; i++) {
  1389. if (media_insert_queue[i] == NULL) {
  1390. media_insert_queue[i] = my_strdup(drvname);
  1391. media_insert_queue_type[i] = retrycnt;
  1392. start_media_insert_timer(hwnd);
  1393. return;
  1394. }
  1395. }
  1396. }
  1397. #if TOUCH_SUPPORT
  1398. static int touch_touched;
  1399. static DWORD touch_time;
  1400. #define MAX_TOUCHES 10
  1401. struct touch_store
  1402. {
  1403. bool inuse;
  1404. DWORD id;
  1405. int port;
  1406. int button;
  1407. int axis;
  1408. };
  1409. static struct touch_store touches[MAX_TOUCHES];
  1410. static void touch_release(struct touch_store *ts, const RECT *rcontrol)
  1411. {
  1412. if (ts->port == 0) {
  1413. if (ts->button == 0)
  1414. inputdevice_uaelib(_T("JOY1_FIRE_BUTTON"), 0, 1, false);
  1415. if (ts->button == 1)
  1416. inputdevice_uaelib(_T("JOY1_2ND_BUTTON"), 0, 1, false);
  1417. } else if (ts->port == 1) {
  1418. if (ts->button == 0)
  1419. inputdevice_uaelib(_T("JOY2_FIRE_BUTTON"), 0, 1, false);
  1420. if (ts->button == 1)
  1421. inputdevice_uaelib(_T("JOY2_2ND_BUTTON"), 0, 1, false);
  1422. }
  1423. if (ts->axis >= 0) {
  1424. if (ts->port == 0) {
  1425. inputdevice_uaelib(_T("MOUSE1_HORIZ"), 0, -1, false);
  1426. inputdevice_uaelib(_T("MOUSE1_VERT"), 0, -1, false);
  1427. } else {
  1428. inputdevice_uaelib(_T("JOY2_HORIZ"), 0, 1, false);
  1429. inputdevice_uaelib(_T("JOY2_VERT"), 0, 1, false);
  1430. }
  1431. }
  1432. ts->button = -1;
  1433. ts->axis = -1;
  1434. }
  1435. static void tablet_touch(DWORD id, int pressrel, int x, int y, const RECT *rcontrol)
  1436. {
  1437. struct touch_store *ts = NULL;
  1438. int buttony = rcontrol->bottom - (rcontrol->bottom - rcontrol->top) / 4;
  1439. int new_slot = -1;
  1440. for (int i = 0; i < MAX_TOUCHES; i++) {
  1441. struct touch_store *tts = &touches[i];
  1442. if (!tts->inuse && new_slot < 0)
  1443. new_slot = i;
  1444. if (tts->inuse && tts->id == id) {
  1445. ts = tts;
  1446. #if TOUCH_DEBUG > 1
  1447. write_log(_T("touch_event: old touch event %d\n"), id);
  1448. #endif
  1449. break;
  1450. }
  1451. }
  1452. if (!ts) {
  1453. // do not allocate new if release
  1454. if (pressrel == 0)
  1455. return;
  1456. if (new_slot < 0)
  1457. return;
  1458. #if TOUCH_DEBUG > 1
  1459. write_log(_T("touch_event: new touch event %d\n"), id);
  1460. #endif
  1461. ts = &touches[new_slot];
  1462. ts->inuse = true;
  1463. ts->axis = -1;
  1464. ts->button = -1;
  1465. ts->id = id;
  1466. }
  1467. // Touch release? Release buttons, center stick/mouse.
  1468. if (ts->inuse && ts->id == id && pressrel < 0) {
  1469. touch_release(ts, rcontrol);
  1470. ts->inuse = false;
  1471. return;
  1472. }
  1473. // Check hit boxes if new touch.
  1474. for (int i = 0; i < 2; i++) {
  1475. const RECT *r = &rcontrol[i];
  1476. if (x >= r->left && x < r->right && y >= r->top && y < r->bottom) {
  1477. #if TOUCH_DEBUG > 1
  1478. write_log(_T("touch_event: press=%d rect=%d wm=%d\n"), pressrel, i, dinput_winmouse());
  1479. #endif
  1480. if (pressrel == 0) {
  1481. // move? port can't change, axis<>button not allowed
  1482. if (ts->port == i) {
  1483. if (y >= buttony && ts->button >= 0) {
  1484. int button = x > r->left + (r->right - r->left) / 2 ? 1 : 0;
  1485. if (button != ts->button) {
  1486. // button change, release old button
  1487. touch_release(ts, rcontrol);
  1488. ts->button = button;
  1489. pressrel = 1;
  1490. }
  1491. }
  1492. }
  1493. } else if (pressrel > 0) {
  1494. // new touch
  1495. ts->port = i;
  1496. if (ts->button < 0 && y >= buttony) {
  1497. ts->button = x > r->left + (r->right - r->left) / 2 ? 1 : 0;
  1498. } else if (ts->axis < 0 && y < buttony) {
  1499. ts->axis = 1;
  1500. }
  1501. }
  1502. }
  1503. }
  1504. // Directions hit?
  1505. if (ts->inuse && ts->id == id && ts->axis >= 0) {
  1506. const RECT *r = &rcontrol[ts->port];
  1507. int xdiff = (r->left + (r->right - r->left) / 2) - x;
  1508. int ydiff = (r->top + (buttony - r->top) / 2) - y;
  1509. #if TOUCH_DEBUG > 1
  1510. write_log(_T("touch_event: rect=%d xdiff %03d ydiff %03d\n"), ts->port, xdiff, ydiff);
  1511. #endif
  1512. xdiff = -xdiff;
  1513. ydiff = -ydiff;
  1514. if (ts->port == 0) {
  1515. int div = (r->bottom - r->top) / (2 * 5);
  1516. if (div <= 0)
  1517. div = 1;
  1518. int vx = xdiff / div;
  1519. int vy = ydiff / div;
  1520. #if TOUCH_DEBUG > 1
  1521. write_log(_T("touch_event: xdiff %03d ydiff %03d div %03d vx %03d vy %03d\n"), xdiff, ydiff, div, vx, vy);
  1522. #endif
  1523. inputdevice_uaelib(_T("MOUSE1_HORIZ"), vx, -1, false);
  1524. inputdevice_uaelib(_T("MOUSE1_VERT"), vy, -1, false);
  1525. } else {
  1526. int div = (r->bottom - r->top) / (2 * 3);
  1527. if (div <= 0)
  1528. div = 1;
  1529. if (xdiff <= -div)
  1530. inputdevice_uaelib(_T("JOY2_HORIZ"), -1, 1, false);
  1531. else if (xdiff >= div)
  1532. inputdevice_uaelib(_T("JOY2_HORIZ"), 1, 1, false);
  1533. else
  1534. inputdevice_uaelib(_T("JOY2_HORIZ"), 0, 1, false);
  1535. if (ydiff <= -div)
  1536. inputdevice_uaelib(_T("JOY2_VERT"), -1, 1, false);
  1537. else if (ydiff >= div)
  1538. inputdevice_uaelib(_T("JOY2_VERT"), 1, 1, false);
  1539. else
  1540. inputdevice_uaelib(_T("JOY2_VERT"), 0, 1, false);
  1541. }
  1542. }
  1543. // Buttons hit?
  1544. if (ts->inuse && ts->id == id && pressrel > 0) {
  1545. if (ts->port == 0) {
  1546. if (ts->button == 0)
  1547. inputdevice_uaelib(_T("JOY1_FIRE_BUTTON"), 1, 1, false);
  1548. if (ts->button == 1)
  1549. inputdevice_uaelib(_T("JOY1_2ND_BUTTON"), 1, 1, false);
  1550. } else if (ts->port == 1) {
  1551. if (ts->button == 0)
  1552. inputdevice_uaelib(_T("JOY2_FIRE_BUTTON"), 1, 1, false);
  1553. if (ts->button == 1)
  1554. inputdevice_uaelib(_T("JOY2_2ND_BUTTON"), 1, 1, false);
  1555. }
  1556. }
  1557. }
  1558. static void touch_event(DWORD id, int pressrel, int x, int y, const RECT *rcontrol)
  1559. {
  1560. if (is_touch_lightpen()) {
  1561. tablet_lightpen(x, y, -1, -1, pressrel, pressrel > 0, true, dinput_lightpen(), -1);
  1562. } else {
  1563. tablet_touch(id, pressrel, x, y, rcontrol);
  1564. }
  1565. }
  1566. static int touch_prev_x, touch_prev_y;
  1567. static DWORD touch_prev_flags;
  1568. static void processtouch(struct AmigaMonitor *mon, HWND hwnd, WPARAM wParam, LPARAM lParam)
  1569. {
  1570. RECT rgui, rcontrol[2];
  1571. int bottom;
  1572. if (currprefs.input_tablet && !is_touch_lightpen())
  1573. return;
  1574. if (isfullscreen()) {
  1575. rgui.left = mon->amigawin_rect.left;
  1576. rgui.top = mon->amigawin_rect.top;
  1577. rgui.right = mon->amigawin_rect.right;
  1578. rgui.bottom = mon->amigawin_rect.top + 30;
  1579. bottom = mon->amigawin_rect.bottom;
  1580. } else {
  1581. rgui.left = mon->mainwin_rect.left;
  1582. rgui.top = mon->mainwin_rect.top;
  1583. rgui.right = mon->mainwin_rect.right;
  1584. rgui.bottom = mon->amigawin_rect.top + GetSystemMetrics(SM_CYMENU) + 2;
  1585. bottom = mon->mainwin_rect.bottom;
  1586. }
  1587. int maxx = rgui.right - rgui.left;
  1588. int maxy = rgui.bottom - rgui.top;
  1589. int max = maxx > maxy ? maxx : maxy;
  1590. // left control region
  1591. rcontrol[0].left = rgui.left;
  1592. rcontrol[0].right = rcontrol[0].left + max / 2;
  1593. rcontrol[0].bottom = bottom;
  1594. rcontrol[0].top = bottom - max / 2;
  1595. // right control region
  1596. rcontrol[1].right = rgui.right;
  1597. rcontrol[1].left = rcontrol[1].right - max / 2;
  1598. rcontrol[1].bottom = bottom;
  1599. rcontrol[1].top = bottom - max / 2;
  1600. if (!pGetTouchInputInfo || !pCloseTouchInputHandle)
  1601. return;
  1602. UINT cInputs = LOWORD(wParam);
  1603. PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs];
  1604. if (NULL != pInputs) {
  1605. if (pGetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) {
  1606. for (int i = 0; i < cInputs; i++) {
  1607. PTOUCHINPUT ti = &pInputs[i];
  1608. int x = ti->x / 100;
  1609. int y = ti->y / 100;
  1610. if (x != touch_prev_x || y != touch_prev_y || ti->dwFlags != touch_prev_flags) {
  1611. touch_prev_x = x;
  1612. touch_prev_y = y;
  1613. touch_prev_flags = ti->dwFlags;
  1614. #if TOUCH_DEBUG
  1615. // write_log(_T("ID=%08x FLAGS=%08x MASK=%08x X=%d Y=%d \n"), ti->dwID, ti->dwFlags, ti->dwMask, x, y);
  1616. #endif
  1617. if (is_touch_lightpen() || (currprefs.input_tablet == TABLET_OFF && dinput_winmouse() < 0)) {
  1618. if (ti->dwFlags & TOUCHEVENTF_DOWN)
  1619. touch_event(ti->dwID, 1, x, y, rcontrol);
  1620. if (ti->dwFlags & TOUCHEVENTF_UP)
  1621. touch_event(ti->dwID, -1, x, y, rcontrol);
  1622. if (ti->dwFlags & TOUCHEVENTF_MOVE)
  1623. touch_event(ti->dwID, 0, x, y, rcontrol);
  1624. }
  1625. if (ti->dwFlags & TOUCHEVENTF_PRIMARY) {
  1626. if (x < rgui.left || x >= rgui.right || y < rgui.top || y >= rgui.bottom) {
  1627. touch_touched = 0;
  1628. } else {
  1629. if (ti->dwFlags & (TOUCHEVENTF_DOWN | TOUCHEVENTF_MOVE)) {
  1630. if (!touch_touched && (ti->dwFlags & TOUCHEVENTF_DOWN)) {
  1631. touch_touched = 1;
  1632. touch_time = ti->dwTime;
  1633. #if TOUCH_DEBUG
  1634. write_log(_T("TOUCHED %d\n"), touch_time);
  1635. #endif
  1636. }
  1637. } else if (ti->dwFlags & TOUCHEVENTF_UP) {
  1638. if (touch_touched && ti->dwTime >= touch_time + 2 * 1000) {
  1639. #if TOUCH_DEBUG
  1640. write_log(_T("TOUCHED GUI\n"), touch_time);
  1641. #endif
  1642. inputdevice_add_inputcode(AKS_ENTERGUI, 1, NULL);
  1643. }
  1644. #if TOUCH_DEBUG
  1645. write_log(_T("RELEASED\n"));
  1646. #endif
  1647. touch_touched = 0;
  1648. }
  1649. }
  1650. }
  1651. }
  1652. }
  1653. pCloseTouchInputHandle((HTOUCHINPUT)lParam);
  1654. }
  1655. delete [] pInputs;
  1656. }
  1657. }
  1658. #endif
  1659. static void resizing(struct AmigaMonitor *mon, int mode, RECT *r)
  1660. {
  1661. int nw = (r->right - r->left) + mon->ratio_adjust_x;
  1662. int nh = (r->bottom - r->top) + mon->ratio_adjust_y;
  1663. if (!mon->ratio_sizing || !mon->ratio_width || !mon->ratio_height)
  1664. return;
  1665. if (mode == WMSZ_BOTTOM || mode == WMSZ_TOP) {
  1666. int w = nh * mon->ratio_width / mon->ratio_height;
  1667. r->right = r->left + w - mon->ratio_adjust_x;
  1668. } else if (mode == WMSZ_LEFT || mode == WMSZ_RIGHT) {
  1669. int h = nw * mon->ratio_height / mon->ratio_width;
  1670. r->bottom = r->top + h - mon->ratio_adjust_y;
  1671. } else if (mode == WMSZ_BOTTOMRIGHT || mode == WMSZ_BOTTOMLEFT || mode == WMSZ_TOPLEFT || mode == WMSZ_TOPRIGHT) {
  1672. int w = r->right - r->left;
  1673. int h = r->bottom - r->top;
  1674. if (nw * mon->ratio_height > nh * mon->ratio_width) {
  1675. h = nw * mon->ratio_height / mon->ratio_width;
  1676. } else {
  1677. w = nh * mon->ratio_width / mon->ratio_height;
  1678. }
  1679. if (mode == WMSZ_BOTTOMRIGHT) {
  1680. r->bottom = r->top + h;
  1681. r->right = r->left + w;
  1682. } else if (mode == WMSZ_BOTTOMLEFT) {
  1683. r->bottom = r->top + h;
  1684. r->left = r->right - w;
  1685. } else if (mode == WMSZ_TOPLEFT) {
  1686. r->top = r->bottom - h;
  1687. r->left = r->right - w;
  1688. } else if (mode == WMSZ_TOPRIGHT) {
  1689. r->top = r->bottom - h;
  1690. r->right = r->left + w;
  1691. }
  1692. }
  1693. }
  1694. #define MSGDEBUG 1
  1695. static LRESULT CALLBACK AmigaWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1696. {
  1697. struct AmigaMonitor *mon = NULL;
  1698. HDC hDC;
  1699. int mx, my;
  1700. int istablet = (GetMessageExtraInfo() & 0xFFFFFF00) == 0xFF515700;
  1701. static int mm, recursive, ignoremousemove;
  1702. static bool ignorelbutton;
  1703. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  1704. if (hWnd == AMonitors[i].hAmigaWnd) {
  1705. mon = &AMonitors[i];
  1706. break;
  1707. }
  1708. if (hWnd == AMonitors[i].hMainWnd) {
  1709. mon = &AMonitors[i];
  1710. break;
  1711. }
  1712. }
  1713. if (!mon) {
  1714. mon = &AMonitors[0];
  1715. }
  1716. #if MSGDEBUG > 1
  1717. write_log (_T("AWP: %p %08x %08x %08x\n"), hWnd, message, wParam, lParam);
  1718. #endif
  1719. if (all_events_disabled)
  1720. return 0;
  1721. switch (message)
  1722. {
  1723. case WM_QUERYENDSESSION:
  1724. {
  1725. if (hWnd == mon->hMainWnd && currprefs.win32_shutdown_notification && !rp_isactive()) {
  1726. return FALSE;
  1727. }
  1728. return TRUE;
  1729. }
  1730. case WM_ENDSESSION:
  1731. return FALSE;
  1732. case WM_INPUT:
  1733. monitor_off = 0;
  1734. handle_rawinput (lParam);
  1735. DefWindowProc (hWnd, message, wParam, lParam);
  1736. return 0;
  1737. case WM_INPUT_DEVICE_CHANGE:
  1738. if (is_hid_rawinput()) {
  1739. if (handle_rawinput_change(lParam, wParam)) {
  1740. // wait 2 seconds before re-enumerating
  1741. if (device_change_timer)
  1742. KillTimer(hWnd, 4);
  1743. device_change_timer = 1;
  1744. SetTimer(hWnd, 4, 2000, NULL);
  1745. }
  1746. return 0;
  1747. }
  1748. return DefWindowProc(hWnd, message, wParam, lParam);
  1749. }
  1750. switch (message)
  1751. {
  1752. case WM_SETFOCUS:
  1753. //write_log(_T("WM_SETFOCUS\n"));
  1754. winuae_active(mon, hWnd, minimized);
  1755. unsetminimized(mon->monitor_id);
  1756. dx_check();
  1757. return 0;
  1758. case WM_EXITSIZEMOVE:
  1759. if (wParam == SC_MOVE) {
  1760. if (D3D_resize) {
  1761. if (isfullscreen() > 0 && wParam == SIZE_RESTORED) {
  1762. write_log(_T("WM_EXITSIZEMOVE restored\n"));
  1763. D3D_resize(0, 1);
  1764. }
  1765. write_log(_T("WM_EXITSIZEMOVE\n"));
  1766. D3D_resize(0, 0);
  1767. }
  1768. }
  1769. return 0;
  1770. case WM_SIZE:
  1771. if (mon->hStatusWnd)
  1772. SendMessage(mon->hStatusWnd, WM_SIZE, wParam, lParam);
  1773. if (wParam == SIZE_MINIMIZED && !minimized) {
  1774. write_log(_T("SIZE_MINIMIZED\n"));
  1775. setminimized(mon->monitor_id);
  1776. winuae_inactive(mon, hWnd, minimized);
  1777. }
  1778. return 0;
  1779. case WM_SIZING:
  1780. resizing(mon, wParam, (RECT*)lParam);
  1781. return TRUE;
  1782. case WM_ACTIVATE:
  1783. //write_log(_T("WM_ACTIVATE %p %x\n"), hWnd, wParam);
  1784. if (LOWORD(wParam) == WA_INACTIVE) {
  1785. //write_log(_T("WM_ACTIVATE %x\n"), wParam);
  1786. if (HIWORD(wParam))
  1787. setminimized(mon->monitor_id);
  1788. else
  1789. unsetminimized(mon->monitor_id);
  1790. winuae_inactive(mon, hWnd, minimized);
  1791. }
  1792. dx_check();
  1793. return 0;
  1794. case WM_MOUSEACTIVATE:
  1795. if (isfocus() == 0)
  1796. ignorelbutton = true;
  1797. break;
  1798. case WM_ACTIVATEAPP:
  1799. D3D_restore(0, false);
  1800. //write_log(_T("WM_ACTIVATEAPP %08x\n"), wParam);
  1801. if (!wParam && isfullscreen() > 0 && D3D_resize && !gui_active) {
  1802. write_log(_T("WM_ACTIVATEAPP inactive %p\n"), hWnd);
  1803. D3D_resize(0, -1);
  1804. } else if (wParam && isfullscreen() > 0 && D3D_resize && !gui_active) {
  1805. write_log(_T("WM_ACTIVATEAPP active %p\n"), hWnd);
  1806. D3D_resize(0, 1);
  1807. }
  1808. if (!wParam && isfullscreen() <= 0 && currprefs.win32_minimize_inactive && !gui_active) {
  1809. minimizewindow(mon->monitor_id);
  1810. }
  1811. #ifdef RETROPLATFORM
  1812. rp_activate(wParam, lParam);
  1813. #endif
  1814. dx_check();
  1815. return 0;
  1816. case WM_KEYDOWN:
  1817. if (dinput_wmkey((uae_u32)lParam))
  1818. inputdevice_add_inputcode(AKS_ENTERGUI, 1, NULL);
  1819. return 0;
  1820. case WM_LBUTTONUP:
  1821. if (!rp_mouseevent(-32768, -32768, 0, 1)) {
  1822. if (dinput_winmouse() >= 0 && isfocus()) {
  1823. if (log_winmouse)
  1824. write_log(_T("WM_LBUTTONUP\n"));
  1825. setmousebuttonstate(dinput_winmouse(), 0, 0);
  1826. }
  1827. }
  1828. return 0;
  1829. case WM_LBUTTONDOWN:
  1830. case WM_LBUTTONDBLCLK:
  1831. if (!rp_mouseevent(-32768, -32768, 1, 1)) {
  1832. if (!mouseactive && !gui_active && (!mousehack_alive() || currprefs.input_tablet != TABLET_MOUSEHACK || (currprefs.input_tablet == TABLET_MOUSEHACK && !(currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC)) || isfullscreen() > 0)) {
  1833. // borderless = do not capture with single-click
  1834. if (ignorelbutton) {
  1835. ignorelbutton = 0;
  1836. if (currprefs.win32_borderless)
  1837. return 0;
  1838. }
  1839. if (message == WM_LBUTTONDOWN && isfullscreen() == 0 && currprefs.win32_borderless && !rp_isactive()) {
  1840. // full-window drag
  1841. SendMessage(mon->hAmigaWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
  1842. return 0;
  1843. }
  1844. if (!pause_emulation || currprefs.win32_active_nocapture_pause)
  1845. setmouseactive(mon->monitor_id, (message == WM_LBUTTONDBLCLK || isfullscreen() > 0) ? 2 : 1);
  1846. } else if (dinput_winmouse() >= 0 && isfocus()) {
  1847. if (log_winmouse)
  1848. write_log(_T("WM_LBUTTONDOWN\n"));
  1849. setmousebuttonstate(dinput_winmouse(), 0, 1);
  1850. }
  1851. }
  1852. return 0;
  1853. case WM_RBUTTONUP:
  1854. if (!rp_mouseevent(-32768, -32768, 0, 2)) {
  1855. if (dinput_winmouse() >= 0 && isfocus()) {
  1856. if (log_winmouse)
  1857. write_log(_T("WM_RBUTTONUP\n"));
  1858. setmousebuttonstate(dinput_winmouse(), 1, 0);
  1859. }
  1860. }
  1861. return 0;
  1862. case WM_RBUTTONDOWN:
  1863. case WM_RBUTTONDBLCLK:
  1864. if (!rp_mouseevent(-32768, -32768, 2, 2)) {
  1865. if (dinput_winmouse() >= 0 && isfocus() > 0) {
  1866. if (log_winmouse)
  1867. write_log(_T("WM_RBUTTONDOWN\n"));
  1868. setmousebuttonstate(dinput_winmouse(), 1, 1);
  1869. }
  1870. }
  1871. return 0;
  1872. case WM_MBUTTONUP:
  1873. if (!rp_mouseevent(-32768, -32768, 0, 4)) {
  1874. if (!(currprefs.input_mouse_untrap & MOUSEUNTRAP_MIDDLEBUTTON)) {
  1875. if (log_winmouse)
  1876. write_log(_T("WM_MBUTTONUP\n"));
  1877. if (dinput_winmouse() >= 0 && isfocus())
  1878. setmousebuttonstate(dinput_winmouse(), 2, 0);
  1879. }
  1880. }
  1881. return 0;
  1882. case WM_MBUTTONDOWN:
  1883. case WM_MBUTTONDBLCLK:
  1884. if (!rp_mouseevent(-32768, -32768, 4, 4)) {
  1885. if (currprefs.input_mouse_untrap & MOUSEUNTRAP_MIDDLEBUTTON) {
  1886. activationtoggle(mon->monitor_id, true);
  1887. } else {
  1888. if (dinput_winmouse() >= 0 && isfocus() > 0) {
  1889. if (log_winmouse)
  1890. write_log(_T("WM_MBUTTONDOWN\n"));
  1891. setmousebuttonstate(dinput_winmouse(), 2, 1);
  1892. }
  1893. }
  1894. }
  1895. return 0;
  1896. case WM_XBUTTONUP:
  1897. if (!rp_ismouseevent() && dinput_winmouse() >= 0 && isfocus()) {
  1898. if (log_winmouse)
  1899. write_log(_T("WM_XBUTTONUP %08x\n"), wParam);
  1900. handleXbutton(wParam, 0);
  1901. return TRUE;
  1902. }
  1903. return 0;
  1904. case WM_XBUTTONDOWN:
  1905. case WM_XBUTTONDBLCLK:
  1906. if (!rp_ismouseevent() && dinput_winmouse() >= 0 && isfocus() > 0) {
  1907. if (log_winmouse)
  1908. write_log(_T("WM_XBUTTONDOWN %08x\n"), wParam);
  1909. handleXbutton(wParam, 1);
  1910. return TRUE;
  1911. }
  1912. return 0;
  1913. case WM_MOUSEWHEEL:
  1914. if (!rp_ismouseevent() && dinput_winmouse() >= 0 && isfocus() > 0) {
  1915. int val = ((short)HIWORD(wParam));
  1916. if (log_winmouse)
  1917. write_log(_T("WM_MOUSEWHEEL %08x\n"), wParam);
  1918. setmousestate(dinput_winmouse(), 2, val, 0);
  1919. if (val < 0)
  1920. setmousebuttonstate(dinput_winmouse(), dinput_wheelbuttonstart() + 0, -1);
  1921. else if (val > 0)
  1922. setmousebuttonstate(dinput_winmouse(), dinput_wheelbuttonstart() + 1, -1);
  1923. return TRUE;
  1924. }
  1925. return 0;
  1926. case WM_MOUSEHWHEEL:
  1927. if (!rp_ismouseevent() && dinput_winmouse() >= 0 && isfocus() > 0) {
  1928. int val = ((short)HIWORD(wParam));
  1929. if (log_winmouse)
  1930. write_log(_T("WM_MOUSEHWHEEL %08x\n"), wParam);
  1931. setmousestate(dinput_winmouse(), 3, val, 0);
  1932. if (val < 0)
  1933. setmousebuttonstate(dinput_winmouse(), dinput_wheelbuttonstart() + 2, -1);
  1934. else if (val > 0)
  1935. setmousebuttonstate(dinput_winmouse(), dinput_wheelbuttonstart() + 3, -1);
  1936. return TRUE;
  1937. }
  1938. return 0;
  1939. case WM_PAINT:
  1940. {
  1941. static int recursive = 0;
  1942. if (recursive == 0) {
  1943. PAINTSTRUCT ps;
  1944. recursive++;
  1945. notice_screen_contents_lost(mon->monitor_id);
  1946. hDC = BeginPaint(hWnd, &ps);
  1947. /* Check to see if this WM_PAINT is coming while we've got the GUI visible */
  1948. if (mon->manual_painting_needed)
  1949. updatedisplayarea(mon->monitor_id);
  1950. EndPaint(hWnd, &ps);
  1951. recursive--;
  1952. }
  1953. }
  1954. return 0;
  1955. case WM_DROPFILES:
  1956. dragdrop(hWnd, (HDROP)wParam, &changed_prefs, -2);
  1957. return 0;
  1958. case WM_TIMER:
  1959. if (wParam == 2) {
  1960. bool restart = false;
  1961. KillTimer(hWnd, 2);
  1962. media_change_timer = 0;
  1963. DWORD r = CMP_WaitNoPendingInstallEvents(0);
  1964. write_log(_T("filesys timer, CMP_WaitNoPendingInstallEvents=%d\n"), r);
  1965. if (r == WAIT_OBJECT_0) {
  1966. for (int i = 0; i < MEDIA_INSERT_QUEUE_SIZE; i++) {
  1967. if (media_insert_queue[i]) {
  1968. TCHAR *drvname = media_insert_queue[i];
  1969. int r = my_getvolumeinfo(drvname);
  1970. if (r < 0) {
  1971. if (media_insert_queue_type[i] > 0) {
  1972. write_log(_T("Mounting %s but drive is not ready, %d.. retrying %d..\n"), drvname, r, media_insert_queue_type[i]);
  1973. media_insert_queue_type[i]--;
  1974. restart = true;
  1975. continue;
  1976. } else {
  1977. write_log(_T("Mounting %s but drive is not ready, %d.. aborting..\n"), drvname, r);
  1978. }
  1979. } else {
  1980. int inserted = 1;
  1981. DWORD type = GetDriveType(drvname);
  1982. if (type == DRIVE_CDROM)
  1983. inserted = -1;
  1984. r = filesys_media_change(drvname, inserted, NULL);
  1985. if (r < 0) {
  1986. write_log(_T("Mounting %s but previous media change is still in progress..\n"), drvname);
  1987. restart = true;
  1988. break;
  1989. } else if (r > 0) {
  1990. write_log(_T("%s mounted\n"), drvname);
  1991. } else {
  1992. write_log(_T("%s mount failed\n"), drvname);
  1993. }
  1994. }
  1995. xfree(media_insert_queue[i]);
  1996. media_insert_queue[i] = NULL;
  1997. }
  1998. }
  1999. } else if (r == WAIT_TIMEOUT) {
  2000. restart = true;
  2001. }
  2002. if (restart)
  2003. start_media_insert_timer(hWnd);
  2004. } else if (wParam == 4) {
  2005. device_change_timer = 0;
  2006. KillTimer(hWnd, 4);
  2007. inputdevice_devicechange(&changed_prefs);
  2008. inputdevice_copyjports(&changed_prefs, &workprefs);
  2009. } else if (wParam == 1) {
  2010. #ifdef PARALLEL_PORT
  2011. finishjob();
  2012. #endif
  2013. }
  2014. return 0;
  2015. case WM_CREATE:
  2016. #ifdef RETROPLATFORM
  2017. rp_set_hwnd(hWnd);
  2018. #endif
  2019. DragAcceptFiles(hWnd, TRUE);
  2020. normalcursor = LoadCursor(NULL, IDC_ARROW);
  2021. if (!clipboard_initialized) {
  2022. clipboard_initialized = true;
  2023. hwndNextViewer = SetClipboardViewer(hWnd);
  2024. clipboard_init(hWnd);
  2025. }
  2026. return 0;
  2027. case WM_DESTROY:
  2028. clipboard_initialized = false;
  2029. if (device_change_timer)
  2030. KillTimer(hWnd, 4);
  2031. device_change_timer = 0;
  2032. wait_keyrelease();
  2033. inputdevice_unacquire();
  2034. dinput_window();
  2035. return 0;
  2036. case WM_CLOSE:
  2037. if (quit_ok())
  2038. uae_quit();
  2039. return 0;
  2040. case WM_WINDOWPOSCHANGED:
  2041. {
  2042. WINDOWPOS *wp = (WINDOWPOS*)lParam;
  2043. if (isfullscreen() <= 0) {
  2044. if (!IsIconic(hWnd) && hWnd == mon->hAmigaWnd) {
  2045. updatewinrect(mon, false);
  2046. updatemouseclip(mon);
  2047. }
  2048. }
  2049. }
  2050. break;
  2051. case WM_SETCURSOR:
  2052. {
  2053. if ((HWND)wParam == mon->hAmigaWnd && currprefs.input_tablet > 0 && (currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC) && isfullscreen() <= 0) {
  2054. if (mousehack_alive()) {
  2055. setcursorshape(mon->monitor_id);
  2056. return 1;
  2057. }
  2058. }
  2059. break;
  2060. }
  2061. case WM_KILLFOCUS:
  2062. //write_log(_T("killfocus\n"));
  2063. focus = 0;
  2064. return 0;
  2065. case WM_MOUSELEAVE:
  2066. mouseinside = false;
  2067. //write_log(_T("mouseoutside\n"));
  2068. return 0;
  2069. case WM_MOUSEMOVE:
  2070. {
  2071. int wm = dinput_winmouse();
  2072. monitor_off = 0;
  2073. if (!mouseinside) {
  2074. //write_log(_T("mouseinside\n"));
  2075. TRACKMOUSEEVENT tme = { 0 };
  2076. mouseinside = true;
  2077. tme.cbSize = sizeof tme;
  2078. tme.dwFlags = TME_LEAVE;
  2079. tme.hwndTrack = mon->hAmigaWnd;
  2080. TrackMouseEvent(&tme);
  2081. }
  2082. mx = (signed short)LOWORD(lParam);
  2083. my = (signed short)HIWORD(lParam);
  2084. if (log_winmouse)
  2085. write_log (_T("WM_MOUSEMOVE MON=%d NUM=%d ACT=%d FOCUS=%d CLIP=%d FS=%d %dx%d %dx%d\n"),
  2086. mon->monitor_id, wm, mouseactive, focus, mon_cursorclipped, isfullscreen (), mx, my, mon->mouseposx, mon->mouseposy);
  2087. if (rp_mouseevent(mx, my, -1, -1))
  2088. return 0;
  2089. mx -= mon->mouseposx;
  2090. my -= mon->mouseposy;
  2091. if (recapture && isfullscreen() <= 0) {
  2092. enablecapture(mon->monitor_id);
  2093. return 0;
  2094. }
  2095. if (wm < 0 && (istablet || currprefs.input_tablet >= TABLET_MOUSEHACK)) {
  2096. /* absolute */
  2097. setmousestate(0, 0, mx, 1);
  2098. setmousestate(0, 1, my, 1);
  2099. return 0;
  2100. }
  2101. if (wm >= 0) {
  2102. if (istablet || currprefs.input_tablet >= TABLET_MOUSEHACK) {
  2103. /* absolute */
  2104. setmousestate(dinput_winmouse(), 0, mx, 1);
  2105. setmousestate(dinput_winmouse(), 1, my, 1);
  2106. return 0;
  2107. }
  2108. if (!focus || !mouseactive)
  2109. return DefWindowProc(hWnd, message, wParam, lParam);
  2110. /* relative */
  2111. int mxx = (mon->amigawinclip_rect.left - mon->amigawin_rect.left) + (mon->amigawinclip_rect.right - mon->amigawinclip_rect.left) / 2;
  2112. int myy = (mon->amigawinclip_rect.top - mon->amigawin_rect.top) + (mon->amigawinclip_rect.bottom - mon->amigawinclip_rect.top) / 2;
  2113. mx = mx - mxx;
  2114. my = my - myy;
  2115. setmousestate(dinput_winmouse(), 0, mx, 0);
  2116. setmousestate(dinput_winmouse(), 1, my, 0);
  2117. } else if (isfocus() < 0 && (istablet || currprefs.input_tablet >= TABLET_MOUSEHACK)) {
  2118. setmousestate(0, 0, mx, 1);
  2119. setmousestate(0, 1, my, 1);
  2120. }
  2121. if (mon_cursorclipped || mouseactive)
  2122. setcursor(mon, LOWORD(lParam), HIWORD(lParam));
  2123. return 0;
  2124. }
  2125. break;
  2126. case WM_MOVING:
  2127. {
  2128. LRESULT lr = DefWindowProc(hWnd, message, wParam, lParam);
  2129. return lr;
  2130. }
  2131. case WM_MOVE:
  2132. return FALSE;
  2133. case WM_ENABLE:
  2134. rp_set_enabledisable(wParam ? 1 : 0);
  2135. return FALSE;
  2136. #ifdef FILESYS
  2137. case WM_USER + 2:
  2138. {
  2139. LONG lEvent;
  2140. PIDLIST_ABSOLUTE *ppidl;
  2141. HANDLE lock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent);
  2142. if (lock) {
  2143. if (lEvent == SHCNE_MEDIAINSERTED || lEvent == SHCNE_DRIVEADD || lEvent == SHCNE_MEDIAREMOVED || lEvent == SHCNE_DRIVEREMOVED) {
  2144. TCHAR drvpath[MAX_DPATH + 1];
  2145. if (SHGetPathFromIDList(ppidl[0], drvpath)) {
  2146. int inserted = (lEvent == SHCNE_MEDIAINSERTED || lEvent == SHCNE_DRIVEADD) ? 1 : 0;
  2147. write_log(_T("Shell Notification %d '%s'\n"), inserted, drvpath);
  2148. if (!win32_hardfile_media_change(drvpath, inserted)) {
  2149. if (inserted) {
  2150. add_media_insert_queue(hWnd, drvpath, 5);
  2151. } else {
  2152. if (is_in_media_queue(drvpath) >= 0) {
  2153. write_log(_T("Insertion queued, removal event dropped\n"));
  2154. } else {
  2155. filesys_media_change(drvpath, inserted, NULL);
  2156. }
  2157. }
  2158. }
  2159. }
  2160. }
  2161. SHChangeNotification_Unlock(lock);
  2162. }
  2163. }
  2164. return TRUE;
  2165. case WM_DEVICECHANGE:
  2166. {
  2167. extern bool win32_spti_media_change(TCHAR driveletter, int insert);
  2168. extern bool win32_ioctl_media_change(TCHAR driveletter, int insert);
  2169. DEV_BROADCAST_HDR *pBHdr = (DEV_BROADCAST_HDR *)lParam;
  2170. int devicechange = 0;
  2171. if (pBHdr && pBHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
  2172. bool ignore = false;
  2173. DEV_BROADCAST_DEVICEINTERFACE *dbd = (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
  2174. GUID *g = &dbd->dbcc_classguid;
  2175. const GUID *ghid = &GUID_DEVINTERFACE_HID;
  2176. // if HID and rawhid active: ignore this event
  2177. if (!memcmp(g, ghid, sizeof(GUID))) {
  2178. if (is_hid_rawinput())
  2179. ignore = true;
  2180. }
  2181. if (!ignore) {
  2182. if (wParam == DBT_DEVICEREMOVECOMPLETE)
  2183. devicechange = 1;
  2184. else if (wParam == DBT_DEVICEARRIVAL)
  2185. devicechange = 1;
  2186. }
  2187. } else if (pBHdr && pBHdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
  2188. DEV_BROADCAST_VOLUME *pBVol = (DEV_BROADCAST_VOLUME *)lParam;
  2189. if (wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) {
  2190. if (pBVol->dbcv_unitmask) {
  2191. int inserted, i;
  2192. TCHAR drive;
  2193. UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  2194. for (i = 0; i <= 'Z' - 'A'; i++) {
  2195. if (pBVol->dbcv_unitmask & (1 << i)) {
  2196. TCHAR drvname[10];
  2197. int type;
  2198. drive = 'A' + i;
  2199. _stprintf(drvname, _T("%c:\\"), drive);
  2200. type = GetDriveType(drvname);
  2201. if (wParam == DBT_DEVICEARRIVAL)
  2202. inserted = 1;
  2203. else
  2204. inserted = 0;
  2205. if (pBVol->dbcv_flags & DBTF_MEDIA) {
  2206. bool matched = false;
  2207. matched |= win32_spti_media_change(drive, inserted);
  2208. matched |= win32_ioctl_media_change(drive, inserted);
  2209. }
  2210. if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM || !inserted) {
  2211. write_log(_T("WM_DEVICECHANGE '%s' type=%d inserted=%d\n"), drvname, type, inserted);
  2212. if (!win32_hardfile_media_change(drvname, inserted)) {
  2213. if (inserted) {
  2214. add_media_insert_queue(hWnd, drvname, 0);
  2215. } else {
  2216. if (is_in_media_queue(drvname) >= 0) {
  2217. write_log(_T("Insertion queued, removal event dropped\n"));
  2218. } else {
  2219. filesys_media_change(drvname, inserted, NULL);
  2220. }
  2221. }
  2222. }
  2223. }
  2224. }
  2225. }
  2226. SetErrorMode(errormode);
  2227. }
  2228. }
  2229. }
  2230. if (devicechange) { // && !is_hid_rawinput()) {
  2231. if (device_change_timer)
  2232. KillTimer(hWnd, 4);
  2233. device_change_timer = 1;
  2234. SetTimer(hWnd, 4, 2000, NULL);
  2235. }
  2236. }
  2237. #endif
  2238. return TRUE;
  2239. case WM_MENUCHAR:
  2240. return MNC_CLOSE << 16;
  2241. case WM_SYSCOMMAND:
  2242. switch (wParam & 0xfff0) // Check System Calls
  2243. {
  2244. // SetThreadExecutionState handles this now
  2245. case SC_SCREENSAVE: // Screensaver Trying To Start?
  2246. break;
  2247. case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
  2248. write_log(_T("SC_MONITORPOWER=%d"), lParam);
  2249. if ((int)lParam < 0)
  2250. monitor_off = 0;
  2251. else if ((int)lParam > 0)
  2252. monitor_off = 1;
  2253. break;
  2254. case SC_KEYMENU:
  2255. if (HIWORD(lParam) <= 0 && isfocus() > 1)
  2256. return 0;
  2257. break;
  2258. default:
  2259. {
  2260. LRESULT lr;
  2261. if ((wParam & 0xfff0) == SC_CLOSE) {
  2262. #ifdef RETROPLATFORM
  2263. if (rp_close())
  2264. return 0;
  2265. #endif
  2266. if (!quit_ok())
  2267. return 0;
  2268. uae_quit();
  2269. }
  2270. lr = DefWindowProc(hWnd, message, wParam, lParam);
  2271. switch (wParam & 0xfff0)
  2272. {
  2273. case SC_MINIMIZE:
  2274. winuae_inactive(mon, hWnd, 1);
  2275. break;
  2276. case SC_RESTORE:
  2277. break;
  2278. case SC_CLOSE:
  2279. break;
  2280. }
  2281. return lr;
  2282. }
  2283. }
  2284. break;
  2285. case WM_SYSKEYDOWN:
  2286. if (currprefs.win32_ctrl_F11_is_quit && wParam == VK_F4)
  2287. return 0;
  2288. break;
  2289. case WM_NOTIFY:
  2290. {
  2291. LPNMHDR nm = (LPNMHDR)lParam;
  2292. if (nm->hwndFrom == mon->hStatusWnd) {
  2293. switch (nm->code)
  2294. {
  2295. /* status bar clicks */
  2296. case NM_CLICK:
  2297. case NM_RCLICK:
  2298. {
  2299. LPNMMOUSE lpnm = (LPNMMOUSE)lParam;
  2300. int num = (int)lpnm->dwItemSpec;
  2301. int df0 = 9;
  2302. if (num >= df0 && num <= df0 + 3) { // DF0-DF3
  2303. num -= df0;
  2304. if (nm->code == NM_RCLICK) {
  2305. disk_eject(num);
  2306. } else if (changed_prefs.floppyslots[num].dfxtype >= 0) {
  2307. DiskSelection(hWnd, IDC_DF0 + num, 0, &changed_prefs, NULL, NULL);
  2308. disk_insert(num, changed_prefs.floppyslots[num].df);
  2309. }
  2310. } else if (num == 5) {
  2311. if (nm->code == NM_CLICK) // POWER
  2312. inputdevice_add_inputcode(AKS_ENTERGUI, 1, NULL);
  2313. else
  2314. uae_reset(0, 1);
  2315. } else if (num == 4) {
  2316. if (pause_emulation) {
  2317. resumepaused(9);
  2318. setmouseactive(mon->monitor_id, 1);
  2319. }
  2320. }
  2321. return TRUE;
  2322. }
  2323. }
  2324. }
  2325. }
  2326. break;
  2327. case WM_CHANGECBCHAIN:
  2328. if (clipboard_initialized) {
  2329. if ((HWND)wParam == hwndNextViewer)
  2330. hwndNextViewer = (HWND)lParam;
  2331. else if (hwndNextViewer != NULL)
  2332. SendMessage(hwndNextViewer, message, wParam, lParam);
  2333. return 0;
  2334. }
  2335. break;
  2336. case WM_DRAWCLIPBOARD:
  2337. if (clipboard_initialized) {
  2338. clipboard_changed(hWnd);
  2339. if (hwndNextViewer)
  2340. SendMessage(hwndNextViewer, message, wParam, lParam);
  2341. return 0;
  2342. }
  2343. break;
  2344. case WM_WTSSESSION_CHANGE:
  2345. {
  2346. static int wasactive;
  2347. switch (wParam)
  2348. {
  2349. case WTS_CONSOLE_CONNECT:
  2350. case WTS_SESSION_UNLOCK:
  2351. if (wasactive)
  2352. winuae_active(mon, hWnd, 0);
  2353. wasactive = 0;
  2354. break;
  2355. case WTS_CONSOLE_DISCONNECT:
  2356. case WTS_SESSION_LOCK:
  2357. wasactive = mouseactive;
  2358. winuae_inactive(mon, hWnd, 0);
  2359. break;
  2360. }
  2361. break;
  2362. }
  2363. case WT_PROXIMITY:
  2364. {
  2365. send_tablet_proximity(LOWORD(lParam) ? 1 : 0);
  2366. return 0;
  2367. }
  2368. case WT_PACKET:
  2369. {
  2370. typedef BOOL(API* WTPACKET)(HCTX, UINT, LPVOID);
  2371. extern WTPACKET pWTPacket;
  2372. PACKET pkt;
  2373. if (inputdevice_is_tablet() <= 0 && !currprefs.tablet_library && !is_touch_lightpen()) {
  2374. close_tablet(tablet);
  2375. tablet = NULL;
  2376. return 0;
  2377. }
  2378. if (pWTPacket((HCTX)lParam, wParam, &pkt)) {
  2379. int x, y, z, pres, proxi;
  2380. DWORD buttons;
  2381. ORIENTATION ori;
  2382. ROTATION rot;
  2383. x = pkt.pkX;
  2384. y = pkt.pkY;
  2385. z = pkt.pkZ;
  2386. pres = pkt.pkNormalPressure;
  2387. ori = pkt.pkOrientation;
  2388. rot = pkt.pkRotation;
  2389. buttons = pkt.pkButtons;
  2390. proxi = pkt.pkStatus;
  2391. send_tablet(x, y, z, pres, buttons, proxi, ori.orAzimuth, ori.orAltitude, ori.orTwist, rot.roPitch, rot.roRoll, rot.roYaw, &mon->amigawin_rect);
  2392. }
  2393. return 0;
  2394. }
  2395. #if TOUCH_SUPPORT
  2396. case WM_TOUCH:
  2397. processtouch(mon, hWnd, wParam, lParam);
  2398. break;
  2399. #endif
  2400. default:
  2401. break;
  2402. }
  2403. return DefWindowProc (hWnd, message, wParam, lParam);
  2404. }
  2405. static int canstretch(struct AmigaMonitor *mon)
  2406. {
  2407. if (isfullscreen () != 0)
  2408. return 0;
  2409. if (!WIN32GFX_IsPicassoScreen(mon)) {
  2410. if (!currprefs.gfx_windowed_resize)
  2411. return 0;
  2412. if (currprefs.gf[APMODE_NATIVE].gfx_filter_autoscale == AUTOSCALE_RESIZE)
  2413. return 0;
  2414. return 1;
  2415. } else {
  2416. if (currprefs.win32_rtgallowscaling || currprefs.gf[APMODE_RTG].gfx_filter_autoscale)
  2417. return 1;
  2418. }
  2419. return 0;
  2420. }
  2421. static void plot (LPDRAWITEMSTRUCT lpDIS, int x, int y, int dx, int dy, int idx)
  2422. {
  2423. COLORREF rgb;
  2424. x += dx;
  2425. y += dy;
  2426. if (idx == 0)
  2427. rgb = RGB(0x00,0x00,0xff);
  2428. else if (idx == 1)
  2429. rgb = RGB(0xff,0x00,0x00);
  2430. else if (idx == 2)
  2431. rgb = RGB(0xff,0xff,0x00);
  2432. else if (idx == 3)
  2433. rgb = RGB(0x00,0xff,0x00);
  2434. else
  2435. rgb = RGB(0x00,0x00,0x00);
  2436. SetPixel (lpDIS->hDC, x, y, rgb);
  2437. SetPixel (lpDIS->hDC, x + 1, y, rgb);
  2438. SetPixel (lpDIS->hDC, x - 1, y, rgb);
  2439. SetPixel (lpDIS->hDC, x, y + 1, rgb);
  2440. SetPixel (lpDIS->hDC, x, y - 1, rgb);
  2441. }
  2442. static LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2443. {
  2444. static RECT myrect;
  2445. struct AmigaMonitor *mon = NULL;
  2446. PAINTSTRUCT ps;
  2447. RECT rc;
  2448. HDC hDC;
  2449. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  2450. if (hWnd == AMonitors[i].hMainWnd) {
  2451. mon = &AMonitors[i];
  2452. break;
  2453. }
  2454. }
  2455. if (!mon) {
  2456. mon = &AMonitors[0];
  2457. }
  2458. #if MSGDEBUG > 1
  2459. write_log (_T("MWP: %x %d\n"), hWnd, message);
  2460. #endif
  2461. if (all_events_disabled)
  2462. return 0;
  2463. switch (message)
  2464. {
  2465. case WM_SETCURSOR:
  2466. case WM_KILLFOCUS:
  2467. case WM_SETFOCUS:
  2468. case WM_MOUSEMOVE:
  2469. case WM_MOUSELEAVE:
  2470. case WM_MOUSEWHEEL:
  2471. case WM_MOUSEHWHEEL:
  2472. case WM_ACTIVATEAPP:
  2473. case WM_DROPFILES:
  2474. case WM_ACTIVATE:
  2475. case WM_MENUCHAR:
  2476. case WM_SYSCOMMAND:
  2477. case WM_KEYUP:
  2478. case WM_SYSKEYUP:
  2479. case WM_KEYDOWN:
  2480. case WM_SYSKEYDOWN:
  2481. case WM_LBUTTONDOWN:
  2482. case WM_LBUTTONUP:
  2483. case WM_LBUTTONDBLCLK:
  2484. case WM_MBUTTONDOWN:
  2485. case WM_MBUTTONUP:
  2486. case WM_MBUTTONDBLCLK:
  2487. case WM_RBUTTONDOWN:
  2488. case WM_RBUTTONUP:
  2489. case WM_RBUTTONDBLCLK:
  2490. case WM_MOVING:
  2491. case WM_MOVE:
  2492. case WM_SIZING:
  2493. case WM_SIZE:
  2494. case WM_DESTROY:
  2495. case WM_CLOSE:
  2496. case WM_HELP:
  2497. case WM_DEVICECHANGE:
  2498. case WM_INPUT:
  2499. case WM_INPUT_DEVICE_CHANGE:
  2500. case WM_USER + 1:
  2501. case WM_USER + 2:
  2502. case WM_COMMAND:
  2503. case WM_NOTIFY:
  2504. case WM_ENABLE:
  2505. case WT_PACKET:
  2506. case WM_WTSSESSION_CHANGE:
  2507. case WM_TIMER:
  2508. #if TOUCH_SUPPORT
  2509. case WM_TOUCH:
  2510. #endif
  2511. case WM_QUERYENDSESSION:
  2512. case WM_ENDSESSION:
  2513. return AmigaWindowProc (hWnd, message, wParam, lParam);
  2514. case WM_DWMCOMPOSITIONCHANGED:
  2515. case WM_THEMECHANGED:
  2516. case WM_DISPLAYCHANGE:
  2517. WIN32GFX_DisplayChangeRequested (-1);
  2518. return 0;
  2519. case WM_POWERBROADCAST:
  2520. write_log("POWERBROADCAST: %08x %08x %08x\n", message, lParam, wParam);
  2521. if (wParam == PBT_APMRESUMEAUTOMATIC) {
  2522. setsystime ();
  2523. return TRUE;
  2524. }
  2525. return 0;
  2526. case WM_DPICHANGED:
  2527. {
  2528. if (isfullscreen() == 0) {
  2529. RECT* const r = (RECT*)lParam;
  2530. SetWindowPos(hWnd, NULL, r->left, r->top, r->right - r->left, r->bottom - r->top, SWP_NOZORDER | SWP_NOACTIVATE);
  2531. return 0;
  2532. }
  2533. break;
  2534. }
  2535. case WM_GETMINMAXINFO:
  2536. {
  2537. LPMINMAXINFO lpmmi;
  2538. lpmmi = (LPMINMAXINFO)lParam;
  2539. lpmmi->ptMinTrackSize.x = 160 + mon->window_extra_width;
  2540. lpmmi->ptMinTrackSize.y = 128 + mon->window_extra_height;
  2541. lpmmi->ptMaxTrackSize.x = max_uae_width + mon->window_extra_width;
  2542. lpmmi->ptMaxTrackSize.y = max_uae_height + mon->window_extra_height;
  2543. }
  2544. return 0;
  2545. case WM_ENTERSIZEMOVE:
  2546. mon->in_sizemove++;
  2547. mon->ratio_width = mon->amigawin_rect.right - mon->amigawinclip_rect.left;
  2548. mon->ratio_height = mon->amigawin_rect.bottom - mon->amigawinclip_rect.top;
  2549. mon->ratio_adjust_x = mon->ratio_width - (mon->mainwin_rect.right - mon->mainwin_rect.left);
  2550. mon->ratio_adjust_y = mon->ratio_height - (mon->mainwin_rect.bottom - mon->mainwin_rect.top);
  2551. mon->ratio_sizing = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0;
  2552. break;
  2553. case WM_EXITSIZEMOVE:
  2554. mon->in_sizemove--;
  2555. /* fall through */
  2556. case WM_WINDOWPOSCHANGED:
  2557. {
  2558. if (isfullscreen () > 0)
  2559. break;
  2560. if (mon->in_sizemove > 0)
  2561. break;
  2562. int iconic = IsIconic (hWnd);
  2563. if (mon->hAmigaWnd && hWnd == mon->hMainWnd && !iconic) {
  2564. //write_log (_T("WM_WINDOWPOSCHANGED MAIN\n"));
  2565. GetWindowRect(mon->hMainWnd, &mon->mainwin_rect);
  2566. updatewinrect(mon, false);
  2567. updatemouseclip(mon);
  2568. if (minimized) {
  2569. unsetminimized(mon->monitor_id);
  2570. winuae_active(mon, mon->hAmigaWnd, minimized);
  2571. }
  2572. if (isfullscreen() == 0) {
  2573. static int store_xy;
  2574. RECT rc2;
  2575. if (GetWindowRect (mon->hMainWnd, &rc2)) {
  2576. DWORD left = rc2.left - mon->win_x_diff;
  2577. DWORD top = rc2.top - mon->win_y_diff;
  2578. DWORD width = rc2.right - rc2.left;
  2579. DWORD height = rc2.bottom - rc2.top;
  2580. if (store_xy++) {
  2581. if (!mon->monitor_id) {
  2582. regsetint(NULL, _T("MainPosX"), left);
  2583. regsetint(NULL, _T("MainPosY"), top);
  2584. } else {
  2585. TCHAR buf[100];
  2586. _stprintf(buf, _T("MainPosX_%d"), mon->monitor_id);
  2587. regsetint(NULL, buf, left);
  2588. _stprintf(buf, _T("MainPosY_%d"), mon->monitor_id);
  2589. regsetint(NULL, buf, top);
  2590. }
  2591. }
  2592. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.x = left;
  2593. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.y = top;
  2594. if (canstretch(mon)) {
  2595. int w = mon->mainwin_rect.right - mon->mainwin_rect.left;
  2596. int h = mon->mainwin_rect.bottom - mon->mainwin_rect.top;
  2597. if (w != changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.width + mon->window_extra_width ||
  2598. h != changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.height + mon->window_extra_height) {
  2599. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.width = w - mon->window_extra_width;
  2600. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.height = h - mon->window_extra_height;
  2601. set_config_changed();
  2602. }
  2603. }
  2604. }
  2605. if (mon->hStatusWnd)
  2606. SendMessage(mon->hStatusWnd, WM_SIZE, wParam, lParam);
  2607. return 0;
  2608. }
  2609. }
  2610. }
  2611. break;
  2612. case WM_WINDOWPOSCHANGING:
  2613. {
  2614. WINDOWPOS *wp = (WINDOWPOS*)lParam;
  2615. if (!canstretch(mon))
  2616. wp->flags |= SWP_NOSIZE;
  2617. break;
  2618. }
  2619. case WM_PAINT:
  2620. hDC = BeginPaint (hWnd, &ps);
  2621. GetClientRect (hWnd, &rc);
  2622. DrawEdge (hDC, &rc, EDGE_SUNKEN, BF_RECT);
  2623. EndPaint (hWnd, &ps);
  2624. return 0;
  2625. case WM_NCLBUTTONDBLCLK:
  2626. if (wParam == HTCAPTION) {
  2627. if (GetKeyState (VK_SHIFT)) {
  2628. toggle_fullscreen(0, 0);
  2629. return 0;
  2630. } else if (GetKeyState (VK_CONTROL)) {
  2631. toggle_fullscreen(0, 2);
  2632. return 0;
  2633. }
  2634. }
  2635. break;
  2636. case WM_DRAWITEM:
  2637. {
  2638. LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
  2639. if (lpDIS->hwndItem == mon->hStatusWnd) {
  2640. HBRUSH b = (HBRUSH)(COLOR_3DFACE + 1);
  2641. if (mon->hStatusBkgB == NULL) {
  2642. COLORREF c = GetPixel(lpDIS->hDC, lpDIS->rcItem.left + (lpDIS->rcItem.right - lpDIS->rcItem.left) / 2, lpDIS->rcItem.top + (lpDIS->rcItem.bottom - lpDIS->rcItem.top) / 2);
  2643. if (c != CLR_INVALID) {
  2644. mon->hStatusBkgB = CreateSolidBrush(c);
  2645. }
  2646. }
  2647. if (mon->hStatusBkgB != NULL) {
  2648. b = mon->hStatusBkgB;
  2649. }
  2650. if (lpDIS->itemID == window_led_msg_start) {
  2651. COLORREF oc;
  2652. int x = lpDIS->rcItem.left + 1;
  2653. int y = (lpDIS->rcItem.bottom - lpDIS->rcItem.top + 1) / 2 + lpDIS->rcItem.top - 1;
  2654. const TCHAR *txt = statusline_fetch();
  2655. int flags = DT_VCENTER | DT_SINGLELINE | DT_LEFT;
  2656. FillRect(lpDIS->hDC, &lpDIS->rcItem, mon->hStatusBkgB);
  2657. if (txt) {
  2658. SetBkMode(lpDIS->hDC, TRANSPARENT);
  2659. oc = SetTextColor(lpDIS->hDC, RGB(0x00, 0x00, 0x00));
  2660. DrawText(lpDIS->hDC, txt, _tcslen(txt), &lpDIS->rcItem, flags);
  2661. SetTextColor(lpDIS->hDC, oc);
  2662. }
  2663. } else if (lpDIS->itemID > 0 && lpDIS->itemID <= window_led_joy_start) {
  2664. int port = 1 - (lpDIS->itemID - (window_led_msg_start + 1));
  2665. int x = (lpDIS->rcItem.right - lpDIS->rcItem.left + 1) / 2 + lpDIS->rcItem.left - 1;
  2666. int y = (lpDIS->rcItem.bottom - lpDIS->rcItem.top + 1) / 2 + lpDIS->rcItem.top - 1;
  2667. RECT r = lpDIS->rcItem;
  2668. r.left++;
  2669. r.right--;
  2670. r.top++;
  2671. r.bottom--;
  2672. FillRect (lpDIS->hDC, &r, mon->hStatusBkgB);
  2673. for (int i = 0; i < 2; i++) {
  2674. int buttons = guijoybutton[port + i * 2];
  2675. int m = i == 0 ? 1 : 2;
  2676. bool got = false;
  2677. if (buttons & (1 << JOYBUTTON_CD32_BLUE)) {
  2678. plot(lpDIS, x - 1, y, 0, 0, 0);
  2679. got = true;
  2680. }
  2681. if (buttons & (1 << JOYBUTTON_CD32_RED)) {
  2682. plot(lpDIS, x + 1, y, 0, 0, 1);
  2683. got = true;
  2684. }
  2685. if (buttons & (1 << JOYBUTTON_CD32_YELLOW)) {
  2686. plot(lpDIS, x, y - 1, 0, 0, 2);
  2687. got = true;
  2688. }
  2689. if (buttons & (1 << JOYBUTTON_CD32_GREEN)) {
  2690. plot(lpDIS, x, y + 1, 0, 0, 3);
  2691. got = true;
  2692. }
  2693. if (!got) {
  2694. if (buttons & 1)
  2695. plot(lpDIS, x, y, 0, 0, 1);
  2696. if (buttons & 2)
  2697. plot(lpDIS, x, y, 0, 0, 0);
  2698. if (buttons & ~(1 | 2))
  2699. plot(lpDIS, x, y, 0, 0, -1);
  2700. }
  2701. for (int j = 0; j < 4; j++) {
  2702. int dx = 0, dy = 0;
  2703. int axis = guijoyaxis[port + i * 2][j];
  2704. if (j == DIR_LEFT_BIT)
  2705. dx = -1;
  2706. if (j == DIR_RIGHT_BIT)
  2707. dx = +1;
  2708. if (j == DIR_UP_BIT)
  2709. dy = -1;
  2710. if (j == DIR_DOWN_BIT)
  2711. dy = +1;
  2712. if (axis && (dx || dy)) {
  2713. dx *= axis * 8 / 127;
  2714. dy *= axis * 8 / 127;
  2715. plot(lpDIS, x, y, dx, dy, -1);
  2716. }
  2717. }
  2718. }
  2719. } else {
  2720. DWORD flags, tflags;
  2721. COLORREF oc;
  2722. TCHAR *txt = (TCHAR*)lpDIS->itemData;
  2723. tflags = txt[_tcslen (txt) + 1];
  2724. SetBkMode (lpDIS->hDC, TRANSPARENT);
  2725. if ((tflags & 2) == 0)
  2726. tflags &= ~(4 | 8 | 16 | 32);
  2727. if (tflags & 4) {
  2728. oc = SetTextColor (lpDIS->hDC, RGB(0xcc, 0x00, 0x00)); // writing
  2729. } else if (tflags & 8) {
  2730. oc = SetTextColor (lpDIS->hDC, RGB(0x00, 0xcc, 0x00)); // playing
  2731. } else {
  2732. oc = SetTextColor (lpDIS->hDC, GetSysColor ((tflags & 2) ? COLOR_BTNTEXT : COLOR_GRAYTEXT));
  2733. }
  2734. if (tflags & 32) {
  2735. ;
  2736. }
  2737. flags = DT_VCENTER | DT_SINGLELINE;
  2738. if (tflags & 1) {
  2739. flags |= DT_CENTER;
  2740. lpDIS->rcItem.left++;
  2741. lpDIS->rcItem.right -= 3;
  2742. } else {
  2743. flags |= DT_LEFT;
  2744. lpDIS->rcItem.right--;
  2745. lpDIS->rcItem.left += 2;
  2746. }
  2747. DrawText (lpDIS->hDC, txt, _tcslen (txt), &lpDIS->rcItem, flags);
  2748. SetTextColor (lpDIS->hDC, oc);
  2749. }
  2750. }
  2751. break;
  2752. }
  2753. default:
  2754. break;
  2755. }
  2756. return DefWindowProc (hWnd, message, wParam, lParam);
  2757. }
  2758. static LRESULT CALLBACK HiddenWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2759. {
  2760. struct AmigaMonitor *mon = &AMonitors[0];
  2761. switch (message)
  2762. {
  2763. case WM_USER + 1: /* Systray icon */
  2764. switch (lParam)
  2765. {
  2766. case WM_LBUTTONDOWN:
  2767. SetForegroundWindow (hGUIWnd ? hGUIWnd : mon->hMainWnd);
  2768. break;
  2769. case WM_LBUTTONDBLCLK:
  2770. case NIN_SELECT:
  2771. if (!gui_active)
  2772. inputdevice_add_inputcode (AKS_ENTERGUI, 1, NULL);
  2773. break;
  2774. case WM_RBUTTONDOWN:
  2775. case WM_CONTEXTMENU:
  2776. case NIN_KEYSELECT:
  2777. if (!gui_active)
  2778. systraymenu (hWnd);
  2779. else
  2780. SetForegroundWindow (hGUIWnd ? hGUIWnd : mon->hMainWnd);
  2781. break;
  2782. }
  2783. break;
  2784. case WM_COMMAND:
  2785. switch (wParam & 0xffff)
  2786. {
  2787. case ID_ST_CONFIGURATION:
  2788. inputdevice_add_inputcode (AKS_ENTERGUI, 1, NULL);
  2789. break;
  2790. case ID_ST_HELP:
  2791. HtmlHelp (NULL, help_file, 0, NULL);
  2792. break;
  2793. case ID_ST_QUIT:
  2794. uae_quit ();
  2795. break;
  2796. case ID_ST_RESET:
  2797. uae_reset (0, 1);
  2798. break;
  2799. case ID_ST_CDEJECTALL:
  2800. changed_prefs.cdslots[0].name[0] = 0;
  2801. changed_prefs.cdslots[0].inuse = false;
  2802. break;
  2803. case ID_ST_CD0:
  2804. DiskSelection (isfullscreen() > 0 ? NULL : hWnd, IDC_CD_SELECT, 17, &changed_prefs, NULL, NULL);
  2805. break;
  2806. case ID_ST_EJECTALL:
  2807. disk_eject (0);
  2808. disk_eject (1);
  2809. disk_eject (2);
  2810. disk_eject (3);
  2811. break;
  2812. case ID_ST_DF0:
  2813. DiskSelection (isfullscreen() > 0 ? NULL : hWnd, IDC_DF0, 0, &changed_prefs, NULL, NULL);
  2814. disk_insert (0, changed_prefs.floppyslots[0].df);
  2815. break;
  2816. case ID_ST_DF1:
  2817. DiskSelection (isfullscreen() > 0 ? NULL : hWnd, IDC_DF1, 0, &changed_prefs, NULL, NULL);
  2818. disk_insert (1, changed_prefs.floppyslots[0].df);
  2819. break;
  2820. case ID_ST_DF2:
  2821. DiskSelection (isfullscreen() > 0 ? NULL : hWnd, IDC_DF2, 0, &changed_prefs, NULL, NULL);
  2822. disk_insert (2, changed_prefs.floppyslots[0].df);
  2823. break;
  2824. case ID_ST_DF3:
  2825. DiskSelection (isfullscreen() > 0 ? NULL : hWnd, IDC_DF3, 0, &changed_prefs, NULL, NULL);
  2826. disk_insert (3, changed_prefs.floppyslots[0].df);
  2827. break;
  2828. }
  2829. break;
  2830. }
  2831. if (TaskbarRestart != 0 && TaskbarRestartHWND == hWnd && message == TaskbarRestart) {
  2832. //write_log (_T("notif: taskbarrestart\n"));
  2833. systray (TaskbarRestartHWND, FALSE);
  2834. }
  2835. return DefWindowProc (hWnd, message, wParam, lParam);
  2836. }
  2837. static LRESULT CALLBACK BlankWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2838. {
  2839. return DefWindowProc (hWnd, message, wParam, lParam);
  2840. }
  2841. int handle_msgpump (void)
  2842. {
  2843. int got = 0;
  2844. MSG msg;
  2845. while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
  2846. got = 1;
  2847. TranslateMessage (&msg);
  2848. DispatchMessage (&msg);
  2849. }
  2850. while (checkIPC (globalipc, &currprefs));
  2851. return got;
  2852. }
  2853. bool handle_events (void)
  2854. {
  2855. struct AmigaMonitor *mon = &AMonitors[0];
  2856. static int was_paused = 0;
  2857. static int cnt1, cnt2;
  2858. static int pausedelay;
  2859. if (mon->hStatusWnd && guijoychange && window_led_joy_start > 0) {
  2860. guijoychange = false;
  2861. for (int i = 0; i < window_led_joy_start; i++)
  2862. PostMessage(mon->hStatusWnd, SB_SETTEXT, (WPARAM)((i + 1) | SBT_OWNERDRAW), (LPARAM)_T(""));
  2863. }
  2864. pausedelay = 0;
  2865. if (pause_emulation) {
  2866. MSG msg;
  2867. if (was_paused == 0) {
  2868. timeend();
  2869. setpaused (pause_emulation);
  2870. was_paused = pause_emulation;
  2871. mon->manual_painting_needed++;
  2872. gui_fps (0, 0, 0);
  2873. gui_led (LED_SND, 0, -1);
  2874. // we got just paused, report it to caller.
  2875. return 1;
  2876. }
  2877. MsgWaitForMultipleObjects (0, NULL, FALSE, 100, QS_ALLINPUT);
  2878. while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
  2879. TranslateMessage (&msg);
  2880. DispatchMessage (&msg);
  2881. }
  2882. if (D3D_run) {
  2883. if (D3D_run(0)) {
  2884. full_redraw_all();
  2885. }
  2886. }
  2887. inputdevicefunc_keyboard.read ();
  2888. inputdevicefunc_mouse.read ();
  2889. inputdevicefunc_joystick.read ();
  2890. inputdevice_handle_inputcode ();
  2891. #ifdef RETROPLATFORM
  2892. rp_vsync ();
  2893. #endif
  2894. cnt1 = 0;
  2895. while (checkIPC (globalipc, &currprefs));
  2896. // if (quit_program)
  2897. // break;
  2898. cnt2--;
  2899. if (cnt2 <= 0) {
  2900. if (currprefs.win32_powersavedisabled)
  2901. SetThreadExecutionState (ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
  2902. cnt2 = 10;
  2903. }
  2904. }
  2905. if (was_paused && (!pause_emulation || quit_program)) {
  2906. updatedisplayarea(mon->monitor_id);
  2907. mon->manual_painting_needed--;
  2908. pause_emulation = was_paused;
  2909. resumepaused (was_paused);
  2910. sound_closed = 0;
  2911. was_paused = 0;
  2912. timebegin();
  2913. }
  2914. cnt1--;
  2915. if (cnt1 <= 0) {
  2916. uae_time_calibrate();
  2917. flush_log ();
  2918. cnt1 = 50 * 5;
  2919. cnt2--;
  2920. if (cnt2 <= 0) {
  2921. if (currprefs.win32_powersavedisabled)
  2922. SetThreadExecutionState (ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
  2923. cnt2 = 5;
  2924. }
  2925. }
  2926. if (D3D_run) {
  2927. if (D3D_run(0))
  2928. full_redraw_all();
  2929. }
  2930. return pause_emulation != 0;
  2931. }
  2932. /* We're not a console-app anymore! */
  2933. void setup_brkhandler (void)
  2934. {
  2935. }
  2936. void remove_brkhandler (void)
  2937. {
  2938. }
  2939. static void WIN32_UnregisterClasses (void)
  2940. {
  2941. systray (hHiddenWnd, TRUE);
  2942. DestroyWindow (hHiddenWnd);
  2943. }
  2944. static int WIN32_RegisterClasses (void)
  2945. {
  2946. WNDCLASS wc;
  2947. HDC hDC;
  2948. COLORREF black = RGB(0, 0, 0);
  2949. g_dwBackgroundColor = RGB(10, 0, 10);
  2950. hDC = GetDC (NULL);
  2951. if (GetDeviceCaps (hDC, NUMCOLORS) != -1)
  2952. g_dwBackgroundColor = RGB (255, 0, 255);
  2953. ReleaseDC (NULL, hDC);
  2954. wc.style = CS_DBLCLKS | CS_OWNDC;
  2955. wc.lpfnWndProc = AmigaWindowProc;
  2956. wc.cbClsExtra = 0;
  2957. wc.cbWndExtra = DLGWINDOWEXTRA;
  2958. wc.hInstance = hInst;
  2959. wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON));
  2960. wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  2961. wc.lpszMenuName = 0;
  2962. wc.lpszClassName = _T("AmigaPowah");
  2963. wc.hbrBackground = CreateSolidBrush (g_dwBackgroundColor);
  2964. if (!RegisterClass (&wc))
  2965. return 0;
  2966. wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  2967. wc.lpfnWndProc = MainWindowProc;
  2968. wc.cbClsExtra = 0;
  2969. wc.cbWndExtra = DLGWINDOWEXTRA;
  2970. wc.hInstance = hInst;
  2971. wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON));
  2972. wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  2973. wc.hbrBackground = CreateSolidBrush (black);
  2974. wc.lpszMenuName = 0;
  2975. wc.lpszClassName = _T("PCsuxRox");
  2976. if (!RegisterClass (&wc))
  2977. return 0;
  2978. wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  2979. wc.lpfnWndProc = BoxArtWindowProc;
  2980. wc.cbClsExtra = 0;
  2981. wc.cbWndExtra = DLGWINDOWEXTRA;
  2982. wc.hInstance = hInst;
  2983. wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_APPICON));
  2984. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  2985. wc.hbrBackground = CreateSolidBrush(g_dwBackgroundColor);
  2986. wc.lpszMenuName = 0;
  2987. wc.lpszClassName = _T("BoxArt");
  2988. if (!RegisterClass(&wc))
  2989. return 0;
  2990. wc.style = 0;
  2991. wc.lpfnWndProc = HiddenWindowProc;
  2992. wc.cbClsExtra = 0;
  2993. wc.cbWndExtra = DLGWINDOWEXTRA;
  2994. wc.hInstance = hInst;
  2995. wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON));
  2996. wc.hCursor = NULL;
  2997. wc.hbrBackground = CreateSolidBrush (g_dwBackgroundColor);
  2998. wc.lpszMenuName = 0;
  2999. wc.lpszClassName = _T("Useless");
  3000. if (!RegisterClass (&wc))
  3001. return 0;
  3002. wc.style = 0;
  3003. wc.lpfnWndProc = BlankWindowProc;
  3004. wc.cbClsExtra = 0;
  3005. wc.cbWndExtra = DLGWINDOWEXTRA;
  3006. wc.hInstance = hInst;
  3007. wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON));
  3008. wc.hCursor = NULL;
  3009. wc.hbrBackground = CreateSolidBrush (g_dwBackgroundColor);
  3010. wc.lpszMenuName = 0;
  3011. wc.lpszClassName = _T("Blank");
  3012. if (!RegisterClass (&wc))
  3013. return 0;
  3014. hHiddenWnd = CreateWindowEx (0,
  3015. _T("Useless"), _T("You don't see me"),
  3016. WS_POPUP,
  3017. 0, 0,
  3018. 1, 1,
  3019. NULL, NULL, 0, NULL);
  3020. if (!hHiddenWnd)
  3021. return 0;
  3022. return 1;
  3023. }
  3024. static HINSTANCE hRichEdit = NULL, hHtmlHelp = NULL;
  3025. int WIN32_CleanupLibraries (void)
  3026. {
  3027. if (hRichEdit)
  3028. FreeLibrary (hRichEdit);
  3029. if (hHtmlHelp)
  3030. FreeLibrary (hHtmlHelp);
  3031. if (hUIDLL)
  3032. FreeLibrary (hUIDLL);
  3033. CoUninitialize ();
  3034. return 1;
  3035. }
  3036. /* HtmlHelp Initialization - optional component */
  3037. int WIN32_InitHtmlHelp (void)
  3038. {
  3039. const TCHAR *chm = _T("WinUAE.chm");
  3040. int result = 0;
  3041. _stprintf(help_file, _T("%s%s"), start_path_data, chm);
  3042. if (!zfile_exists (help_file))
  3043. _stprintf(help_file, _T("%s%s"), start_path_exe, chm);
  3044. if (zfile_exists (help_file)) {
  3045. if (hHtmlHelp = LoadLibrary (_T("HHCTRL.OCX"))) {
  3046. pHtmlHelp = (HWND(WINAPI *)(HWND, LPCWSTR, UINT, LPDWORD))GetProcAddress (hHtmlHelp, "HtmlHelpW");
  3047. result = 1;
  3048. }
  3049. }
  3050. return result;
  3051. }
  3052. const struct winuae_lang langs[] =
  3053. {
  3054. { LANG_AFRIKAANS, _T("Afrikaans") },
  3055. { LANG_ARABIC, _T("Arabic") },
  3056. { LANG_ARMENIAN, _T("Armenian") },
  3057. { LANG_ASSAMESE, _T("Assamese") },
  3058. { LANG_AZERI, _T("Azeri") },
  3059. { LANG_BASQUE, _T("Basque") },
  3060. { LANG_BELARUSIAN, _T("Belarusian") },
  3061. { LANG_BENGALI, _T("Bengali") },
  3062. { LANG_BULGARIAN, _T("Bulgarian") },
  3063. { LANG_CATALAN, _T("Catalan") },
  3064. { LANG_CHINESE, _T("Chinese") },
  3065. { LANG_CROATIAN, _T("Croatian") },
  3066. { LANG_CZECH, _T("Czech") },
  3067. { LANG_DANISH, _T("Danish") },
  3068. { LANG_DUTCH, _T("Dutch") },
  3069. { LANG_ESTONIAN, _T("Estoanian") },
  3070. { LANG_FAEROESE, _T("Faeroese") },
  3071. { LANG_FARSI, _T("Farsi") },
  3072. { LANG_FINNISH, _T("Finnish") },
  3073. { LANG_FRENCH, _T("French") },
  3074. { LANG_GEORGIAN, _T("Georgian") },
  3075. { LANG_GERMAN, _T("German") },
  3076. { LANG_GREEK, _T("Greek") },
  3077. { LANG_GUJARATI, _T("Gujarati") },
  3078. { LANG_HEBREW, _T("Hebrew") },
  3079. { LANG_HINDI, _T("Hindi") },
  3080. { LANG_HUNGARIAN, _T("Hungarian") },
  3081. { LANG_ICELANDIC, _T("Icelandic") },
  3082. { LANG_INDONESIAN, _T("Indonesian") },
  3083. { LANG_ITALIAN, _T("Italian") },
  3084. { LANG_JAPANESE, _T("Japanese") },
  3085. { LANG_KANNADA, _T("Kannada") },
  3086. { LANG_KASHMIRI, _T("Kashmiri") },
  3087. { LANG_KAZAK, _T("Kazak") },
  3088. { LANG_KONKANI, _T("Konkani") },
  3089. { LANG_KOREAN, _T("Korean") },
  3090. { LANG_LATVIAN, _T("Latvian") },
  3091. { LANG_LITHUANIAN, _T("Lithuanian") },
  3092. { LANG_MACEDONIAN, _T("Macedonian") },
  3093. { LANG_MALAY, _T("Malay") },
  3094. { LANG_MALAYALAM, _T("Malayalam") },
  3095. { LANG_MANIPURI, _T("Manipuri") },
  3096. { LANG_MARATHI, _T("Marathi") },
  3097. { LANG_NEPALI, _T("Nepali") },
  3098. { LANG_NORWEGIAN, _T("Norwegian") },
  3099. { LANG_ORIYA, _T("Oriya") },
  3100. { LANG_POLISH, _T("Polish") },
  3101. { LANG_PORTUGUESE, _T("Portuguese") },
  3102. { LANG_PUNJABI, _T("Punjabi") },
  3103. { LANG_ROMANIAN, _T("Romanian") },
  3104. { LANG_RUSSIAN, _T("Russian") },
  3105. { LANG_SANSKRIT, _T("Sanskrit") },
  3106. { LANG_SINDHI, _T("Sindhi") },
  3107. { LANG_SLOVAK, _T("Slovak") },
  3108. { LANG_SLOVENIAN, _T("Slovenian") },
  3109. { LANG_SPANISH, _T("Spanish") },
  3110. { LANG_SWAHILI, _T("Swahili") },
  3111. { LANG_SWEDISH, _T("Swedish") },
  3112. { LANG_TAMIL, _T("Tamil") },
  3113. { LANG_TATAR, _T("Tatar") },
  3114. { LANG_TELUGU, _T("Telugu") },
  3115. { LANG_THAI, _T("Thai") },
  3116. { LANG_TURKISH, _T("Turkish") },
  3117. { LANG_UKRAINIAN, _T("Ukrainian") },
  3118. { LANG_UZBEK, _T("Uzbek") },
  3119. { LANG_VIETNAMESE, _T("Vietnamese") },
  3120. { LANG_ENGLISH, _T("default") },
  3121. { 0x400, _T("guidll.dll") },
  3122. { 0, NULL }
  3123. };
  3124. static const TCHAR *getlanguagename(DWORD id)
  3125. {
  3126. int i;
  3127. for (i = 0; langs[i].name; i++) {
  3128. if (langs[i].id == id)
  3129. return langs[i].name;
  3130. }
  3131. return NULL;
  3132. }
  3133. HMODULE language_load (WORD language)
  3134. {
  3135. HMODULE result = NULL;
  3136. if (language == 0xffff || language == 0) {
  3137. /* new user-specific Windows ME/2K/XP method to get UI language */
  3138. language = GetUserDefaultUILanguage ();
  3139. language &= 0x3ff; // low 9-bits form the primary-language ID
  3140. }
  3141. TCHAR kblname[KL_NAMELENGTH];
  3142. if (GetKeyboardLayoutName(kblname)) {
  3143. // This is so stupid, function that returns hex number as a string?
  3144. // GetKeyboardLayout() does not work. It seems to return locale, not keyboard layout.
  3145. TCHAR *endptr;
  3146. uae_u32 kbl = _tcstol(kblname, &endptr, 16);
  3147. uae_u32 kblid = kbl & 0x3ff;
  3148. if (kblid == LANG_GERMAN)
  3149. hrtmon_lang = 2;
  3150. if (kblid == LANG_FRENCH)
  3151. hrtmon_lang = 3;
  3152. }
  3153. #if LANG_DLL > 0
  3154. TCHAR dllbuf[MAX_DPATH];
  3155. const TCHAR *dllname;
  3156. dllname = getlanguagename (language);
  3157. if (dllname) {
  3158. DWORD dwVersionHandle, dwFileVersionInfoSize;
  3159. LPVOID lpFileVersionData = NULL;
  3160. BOOL success = FALSE;
  3161. int fail = 1;
  3162. if (language == 0x400)
  3163. _tcscpy (dllbuf, _T("guidll.dll"));
  3164. else
  3165. _stprintf (dllbuf, _T("WinUAE_%s.dll"), dllname);
  3166. result = WIN32_LoadLibrary (dllbuf);
  3167. if (result) {
  3168. dwFileVersionInfoSize = GetFileVersionInfoSize (dllbuf, &dwVersionHandle);
  3169. if (dwFileVersionInfoSize) {
  3170. if (lpFileVersionData = xcalloc (uae_u8, dwFileVersionInfoSize)) {
  3171. if (GetFileVersionInfo (dllbuf, dwVersionHandle, dwFileVersionInfoSize, lpFileVersionData)) {
  3172. VS_FIXEDFILEINFO *vsFileInfo = NULL;
  3173. UINT uLen;
  3174. fail = 0;
  3175. if (VerQueryValue (lpFileVersionData, TEXT("\\"), (void **)&vsFileInfo, &uLen)) {
  3176. if (vsFileInfo &&
  3177. HIWORD(vsFileInfo->dwProductVersionMS) == UAEMAJOR
  3178. && LOWORD(vsFileInfo->dwProductVersionMS) == UAEMINOR
  3179. && (!LANG_DLL_FULL_VERSION_MATCH || (HIWORD(vsFileInfo->dwProductVersionLS) == UAESUBREV))) {
  3180. success = TRUE;
  3181. write_log (_T("Translation DLL '%s' loaded and enabled\n"), dllbuf);
  3182. } else {
  3183. write_log (_T("Translation DLL '%s' version mismatch (%d.%d.%d)\n"), dllbuf,
  3184. HIWORD(vsFileInfo->dwProductVersionMS),
  3185. LOWORD(vsFileInfo->dwProductVersionMS),
  3186. HIWORD(vsFileInfo->dwProductVersionLS));
  3187. }
  3188. }
  3189. }
  3190. xfree (lpFileVersionData);
  3191. }
  3192. }
  3193. }
  3194. if (fail) {
  3195. DWORD err = GetLastError ();
  3196. if (err != ERROR_MOD_NOT_FOUND && err != ERROR_DLL_NOT_FOUND)
  3197. write_log (_T("Translation DLL '%s' failed to load, error %d\n"), dllbuf, GetLastError ());
  3198. }
  3199. if (result && !success) {
  3200. FreeLibrary (result);
  3201. result = NULL;
  3202. }
  3203. }
  3204. #endif
  3205. return result;
  3206. }
  3207. struct threadpriorities priorities[] = {
  3208. { NULL, THREAD_PRIORITY_ABOVE_NORMAL, ABOVE_NORMAL_PRIORITY_CLASS, IDS_PRI_ABOVENORMAL },
  3209. { NULL, THREAD_PRIORITY_NORMAL, NORMAL_PRIORITY_CLASS, IDS_PRI_NORMAL },
  3210. { NULL, THREAD_PRIORITY_BELOW_NORMAL, BELOW_NORMAL_PRIORITY_CLASS, IDS_PRI_BELOWNORMAL },
  3211. { NULL, THREAD_PRIORITY_LOWEST, IDLE_PRIORITY_CLASS, IDS_PRI_LOW },
  3212. { 0, 0, 0, 0 }
  3213. };
  3214. static void pritransla (void)
  3215. {
  3216. int i;
  3217. for (i = 0; priorities[i].id; i++) {
  3218. TCHAR tmp[MAX_DPATH];
  3219. WIN32GUI_LoadUIString (priorities[i].id, tmp, sizeof (tmp) / sizeof (TCHAR));
  3220. priorities[i].name = my_strdup (tmp);
  3221. }
  3222. }
  3223. static void WIN32_InitLang (void)
  3224. {
  3225. int lid;
  3226. WORD langid = 0xffff;
  3227. if (regqueryint (NULL, _T("Language"), &lid))
  3228. langid = (WORD)lid;
  3229. hUIDLL = language_load (langid);
  3230. pritransla ();
  3231. }
  3232. typedef HRESULT (CALLBACK* SETCURRENTPROCESSEXPLICITAPPUSERMODEIDD)(PCWSTR);
  3233. /* try to load COMDLG32 and DDRAW, initialize csDraw */
  3234. static int WIN32_InitLibraries (void)
  3235. {
  3236. LARGE_INTEGER freq;
  3237. SETCURRENTPROCESSEXPLICITAPPUSERMODEIDD pSetCurrentProcessExplicitAppUserModelID;
  3238. /* Determine our processor speed and capabilities */
  3239. if (!init_mmtimer ()) {
  3240. pre_gui_message (_T("MMTimer initialization failed, exiting.."));
  3241. return 0;
  3242. }
  3243. if (!QueryPerformanceCounter (&freq)) {
  3244. pre_gui_message (_T("No QueryPerformanceFrequency() supported, exiting..\n"));
  3245. return 0;
  3246. }
  3247. uae_time_init();
  3248. if (!timebegin ()) {
  3249. pre_gui_message (_T("MMTimer second initialization failed, exiting.."));
  3250. return 0;
  3251. }
  3252. pSetCurrentProcessExplicitAppUserModelID = (SETCURRENTPROCESSEXPLICITAPPUSERMODEIDD)GetProcAddress (
  3253. GetModuleHandle (_T("shell32.dll")), "SetCurrentProcessExplicitAppUserModelID");
  3254. if (pSetCurrentProcessExplicitAppUserModelID)
  3255. pSetCurrentProcessExplicitAppUserModelID (WINUAEAPPNAME);
  3256. hRichEdit = LoadLibrary (_T("RICHED32.DLL"));
  3257. return 1;
  3258. }
  3259. int debuggable (void)
  3260. {
  3261. return 0;
  3262. }
  3263. void toggle_mousegrab(void)
  3264. {
  3265. activationtoggle(0, false);
  3266. }
  3267. #define LOG_BOOT _T("winuaebootlog.txt")
  3268. #define LOG_NORMAL _T("winuaelog.txt")
  3269. static bool createbootlog = true;
  3270. static bool logging_disabled = false;
  3271. void logging_open (int bootlog, int append)
  3272. {
  3273. TCHAR *outpath;
  3274. TCHAR debugfilename[MAX_DPATH];
  3275. if (logging_disabled && !winuaelog_temporary_enable)
  3276. return;
  3277. outpath = logpath;
  3278. debugfilename[0] = 0;
  3279. #ifndef SINGLEFILE
  3280. if (currprefs.win32_logfile || winuaelog_temporary_enable) {
  3281. _stprintf (debugfilename, _T("%s%s"), start_path_data, LOG_NORMAL);
  3282. }
  3283. if (bootlog) {
  3284. _stprintf (debugfilename, _T("%s%s"), start_path_data, LOG_BOOT);
  3285. outpath = bootlogpath;
  3286. if (!createbootlog)
  3287. bootlog = -1;
  3288. }
  3289. if (debugfilename[0]) {
  3290. if (!debugfile)
  3291. debugfile = log_open (debugfilename, append, bootlog, outpath);
  3292. }
  3293. #endif
  3294. }
  3295. typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  3296. void logging_init (void)
  3297. {
  3298. #ifndef _WIN64
  3299. LPFN_ISWOW64PROCESS fnIsWow64Process;
  3300. #endif
  3301. int wow64 = 0;
  3302. static int started;
  3303. static int first;
  3304. TCHAR tmp[MAX_DPATH], filedate[256];
  3305. if (first > 1) {
  3306. write_log (_T("** RESTART **\n"));
  3307. return;
  3308. }
  3309. if (first == 1) {
  3310. write_log (_T("Log (%s): '%s%s'\n"), currprefs.win32_logfile || winuaelog_temporary_enable ? _T("enabled") : _T("disabled"),
  3311. start_path_data, LOG_NORMAL);
  3312. if (debugfile)
  3313. log_close (debugfile);
  3314. debugfile = 0;
  3315. }
  3316. logging_open (first ? 0 : 1, 0);
  3317. logging_started = 1;
  3318. first++;
  3319. #ifdef _WIN64
  3320. wow64 = 1;
  3321. #else
  3322. fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(kerneldll, "IsWow64Process");
  3323. if (fnIsWow64Process)
  3324. fnIsWow64Process (GetCurrentProcess (), &wow64);
  3325. #endif
  3326. _tcscpy (filedate, _T("?"));
  3327. if (GetModuleFileName (NULL, tmp, sizeof tmp / sizeof (TCHAR))) {
  3328. HANDLE h = CreateFile (tmp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  3329. if (h != INVALID_HANDLE_VALUE) {
  3330. FILETIME ft;
  3331. if (GetFileTime (h, &ft, NULL, NULL)) {
  3332. SYSTEMTIME st;
  3333. if (FileTimeToSystemTime(&ft, &st)) {
  3334. _stprintf (filedate, _T("%02d:%02d"), st.wHour, st.wMinute);
  3335. }
  3336. }
  3337. CloseHandle (h);
  3338. }
  3339. }
  3340. write_log (_T("\n%s (%d.%d.%d %s%s[%d])"), VersionStr,
  3341. osVersion.dwMajorVersion, osVersion.dwMinorVersion, osVersion.dwBuildNumber, osVersion.szCSDVersion,
  3342. _tcslen (osVersion.szCSDVersion) > 0 ? _T(" ") : _T(""), os_admin);
  3343. write_log (_T(" %d-bit %X.%X.%X %d %s %d"),
  3344. wow64 ? 64 : 32,
  3345. SystemInfo.wProcessorArchitecture, SystemInfo.wProcessorLevel, SystemInfo.wProcessorRevision,
  3346. SystemInfo.dwNumberOfProcessors, filedate, os_touch);
  3347. write_log (_T("\n(c) 1995-2001 Bernd Schmidt - Core UAE concept and implementation.")
  3348. _T("\n(c) 1998-2021 Toni Wilen - Win32 port, core code updates.")
  3349. _T("\n(c) 1996-2001 Brian King - Win32 port, Picasso96 RTG, and GUI.")
  3350. _T("\n(c) 1996-1999 Mathias Ortmann - Win32 port and bsdsocket support.")
  3351. _T("\n(c) 2000-2001 Bernd Meyer - JIT engine.")
  3352. _T("\n(c) 2000-2005 Bernd Roesch - MIDI input, many fixes.")
  3353. _T("\nPress F12 to show the Settings Dialog (GUI), Alt-F4 to quit.")
  3354. _T("\nEnd+F1 changes floppy 0, End+F2 changes floppy 1, etc.")
  3355. _T("\n"));
  3356. tmp[0] = 0;
  3357. GetModuleFileName (NULL, tmp, sizeof tmp / sizeof (TCHAR));
  3358. write_log (_T("'%s'\n"), tmp);
  3359. write_log (_T("EXE: '%s', DATA: '%s', PLUGIN: '%s'\n"), start_path_exe, start_path_data, start_path_plugins);
  3360. regstatus ();
  3361. }
  3362. void logging_cleanup (void)
  3363. {
  3364. if (debugfile)
  3365. fclose (debugfile);
  3366. debugfile = 0;
  3367. }
  3368. uae_u8 *save_log (int bootlog, int *len)
  3369. {
  3370. FILE *f;
  3371. uae_u8 *dst = NULL;
  3372. int size;
  3373. if (!logging_started)
  3374. return NULL;
  3375. f = _tfopen (bootlog ? LOG_BOOT : LOG_NORMAL, _T("rb"));
  3376. if (!f)
  3377. return NULL;
  3378. fseek (f, 0, SEEK_END);
  3379. size = ftell (f);
  3380. fseek (f, 0, SEEK_SET);
  3381. if (*len > 0 && size > *len)
  3382. size = *len;
  3383. if (size > 0) {
  3384. dst = xcalloc (uae_u8, size + 1);
  3385. if (dst)
  3386. fread (dst, 1, size, f);
  3387. fclose (f);
  3388. *len = size + 1;
  3389. }
  3390. return dst;
  3391. }
  3392. void stripslashes (TCHAR *p)
  3393. {
  3394. while (_tcslen (p) > 0 && (p[_tcslen (p) - 1] == '\\' || p[_tcslen (p) - 1] == '/'))
  3395. p[_tcslen (p) - 1] = 0;
  3396. }
  3397. void fixtrailing (TCHAR *p)
  3398. {
  3399. if (_tcslen(p) == 0)
  3400. return;
  3401. if (p[_tcslen(p) - 1] == '/' || p[_tcslen(p) - 1] == '\\')
  3402. return;
  3403. _tcscat(p, _T("\\"));
  3404. }
  3405. static void fixdriveletter(TCHAR *path)
  3406. {
  3407. if (_istalpha(path[0]) && path[1] == ':' && path[2] == '\\' && path[3] == '.' && path[4] == 0)
  3408. path[3] = 0;
  3409. if (_istalpha(path[0]) && path[1] == ':' && path[2] == '\\' && path[3] == '.' && path[4] == '.' && path[5] == 0)
  3410. path[3] = 0;
  3411. }
  3412. // convert path to absolute or relative
  3413. void fullpath(TCHAR *path, int size, bool userelative)
  3414. {
  3415. if (path[0] == 0 || (path[0] == '\\' && path[1] == '\\') || path[0] == ':')
  3416. return;
  3417. // has one or more environment variables? do nothing.
  3418. if (_tcschr(path, '%'))
  3419. return;
  3420. if (_tcslen(path) >= 2 && path[_tcslen(path) - 1] == '.')
  3421. return;
  3422. /* <drive letter>: is supposed to mean same as <drive letter>:\ */
  3423. if (_istalpha (path[0]) && path[1] == ':' && path[2] == 0)
  3424. _tcscat (path, _T("\\"));
  3425. if (userelative) {
  3426. TCHAR tmp1[MAX_DPATH], tmp2[MAX_DPATH];
  3427. tmp1[0] = 0;
  3428. GetCurrentDirectory (sizeof tmp1 / sizeof (TCHAR), tmp1);
  3429. fixtrailing (tmp1);
  3430. tmp2[0] = 0;
  3431. int ret = GetFullPathName (path, sizeof tmp2 / sizeof (TCHAR), tmp2, NULL);
  3432. if (ret == 0 || ret >= sizeof tmp2 / sizeof (TCHAR))
  3433. return;
  3434. if (_tcslen(tmp1) > 2 && _tcsnicmp(tmp1, tmp2, 3) == 0 && tmp1[1] == ':' && tmp1[2] == '\\') {
  3435. // same drive letter
  3436. path[0] = 0;
  3437. if (PathRelativePathTo(path, tmp1, FILE_ATTRIBUTE_DIRECTORY, tmp2, tmp2[_tcslen(tmp2) - 1] == '\\' ? FILE_ATTRIBUTE_DIRECTORY : 0)) {
  3438. if (path[0]) {
  3439. if (path[0] == '.' && path[1] == 0) {
  3440. _tcscpy(path, _T(".\\"));
  3441. } else if (path[0] == '\\') {
  3442. _tcscpy(tmp1, path + 1);
  3443. _stprintf(path, _T(".\\%s"), tmp1);
  3444. } else if (path[0] != '.') {
  3445. _tcscpy(tmp1, path);
  3446. _stprintf(path, _T(".\\%s"), tmp1);
  3447. }
  3448. } else {
  3449. _tcscpy (path, tmp2);
  3450. }
  3451. goto done;
  3452. }
  3453. }
  3454. if (_tcsnicmp (tmp1, tmp2, _tcslen (tmp1)) == 0) {
  3455. // tmp2 is inside tmp1
  3456. _tcscpy (path, _T(".\\"));
  3457. _tcscat (path, tmp2 + _tcslen (tmp1));
  3458. } else {
  3459. _tcscpy (path, tmp2);
  3460. }
  3461. done:;
  3462. } else {
  3463. TCHAR tmp[MAX_DPATH];
  3464. _tcscpy(tmp, path);
  3465. DWORD err = GetFullPathName (tmp, size, path, NULL);
  3466. }
  3467. }
  3468. void fullpath(TCHAR *path, int size)
  3469. {
  3470. fullpath(path, size, relativepaths);
  3471. }
  3472. bool samepath(const TCHAR *p1, const TCHAR *p2)
  3473. {
  3474. if (!_tcsicmp(p1, p2))
  3475. return true;
  3476. TCHAR path1[MAX_DPATH], path2[MAX_DPATH];
  3477. _tcscpy(path1, p1);
  3478. _tcscpy(path2, p2);
  3479. fixdriveletter(path1);
  3480. fixdriveletter(path2);
  3481. if (!_tcsicmp(path1, path2))
  3482. return true;
  3483. return false;
  3484. }
  3485. bool target_isrelativemode(void)
  3486. {
  3487. return relativepaths != 0;
  3488. }
  3489. void getpathpart (TCHAR *outpath, int size, const TCHAR *inpath)
  3490. {
  3491. _tcscpy (outpath, inpath);
  3492. TCHAR *p = _tcsrchr (outpath, '\\');
  3493. if (p)
  3494. p[0] = 0;
  3495. fixtrailing (outpath);
  3496. }
  3497. void getfilepart (TCHAR *out, int size, const TCHAR *path)
  3498. {
  3499. out[0] = 0;
  3500. const TCHAR *p = _tcsrchr (path, '\\');
  3501. if (p)
  3502. _tcscpy (out, p + 1);
  3503. else
  3504. _tcscpy (out, path);
  3505. }
  3506. typedef DWORD (STDAPICALLTYPE *PFN_GetKey)(LPVOID lpvBuffer, DWORD dwSize);
  3507. uae_u8 *target_load_keyfile (struct uae_prefs *p, const TCHAR *path, int *sizep, TCHAR *name)
  3508. {
  3509. uae_u8 *keybuf = NULL;
  3510. HMODULE h;
  3511. PFN_GetKey pfnGetKey;
  3512. int size;
  3513. const TCHAR *libname = _T("amigaforever.dll");
  3514. h = WIN32_LoadLibrary(libname);
  3515. if (!h) {
  3516. TCHAR path[MAX_DPATH];
  3517. _stprintf (path, _T("%s..\\Player\\%s"), start_path_exe, libname);
  3518. h = WIN32_LoadLibrary(path);
  3519. if (!h) {
  3520. TCHAR *afr = _wgetenv (_T("AMIGAFOREVERROOT"));
  3521. if (afr) {
  3522. TCHAR tmp[MAX_DPATH];
  3523. _tcscpy (tmp, afr);
  3524. fixtrailing (tmp);
  3525. _stprintf (path, _T("%sPlayer\\%s"), tmp, libname);
  3526. h = WIN32_LoadLibrary(path);
  3527. }
  3528. }
  3529. }
  3530. if (!h)
  3531. return NULL;
  3532. GetModuleFileName (h, name, MAX_DPATH);
  3533. //write_log (_T("keydll: %s'\n"), name);
  3534. pfnGetKey = (PFN_GetKey)GetProcAddress (h, "GetKey");
  3535. //write_log (_T("addr: %08x\n"), pfnGetKey);
  3536. if (pfnGetKey) {
  3537. size = pfnGetKey (NULL, 0);
  3538. *sizep = size;
  3539. //write_log (_T("size: %d\n"), size);
  3540. if (size > 0) {
  3541. int gotsize;
  3542. keybuf = xmalloc (uae_u8, size);
  3543. gotsize = pfnGetKey (keybuf, size);
  3544. //write_log (_T("gotsize: %d\n"), gotsize);
  3545. if (gotsize != size) {
  3546. xfree (keybuf);
  3547. keybuf = NULL;
  3548. }
  3549. }
  3550. }
  3551. FreeLibrary (h);
  3552. //write_log (_T("keybuf=%08x\n"), keybuf);
  3553. return keybuf;
  3554. }
  3555. /***
  3556. *static void parse_cmdline(cmdstart, argv, args, numargs, numchars)
  3557. *
  3558. *Purpose:
  3559. * Parses the command line and sets up the argv[] array.
  3560. * On entry, cmdstart should point to the command line,
  3561. * argv should point to memory for the argv array, args
  3562. * points to memory to place the text of the arguments.
  3563. * If these are NULL, then no storing (only counting)
  3564. * is done. On exit, *numargs has the number of
  3565. * arguments (plus one for a final NULL argument),
  3566. * and *numchars has the number of bytes used in the buffer
  3567. * pointed to by args.
  3568. *
  3569. *Entry:
  3570. * _TSCHAR *cmdstart - pointer to command line of the form
  3571. * <progname><nul><args><nul>
  3572. * _TSCHAR **argv - where to build argv array; NULL means don't
  3573. * build array
  3574. * _TSCHAR *args - where to place argument text; NULL means don't
  3575. * store text
  3576. *
  3577. *Exit:
  3578. * no return value
  3579. * int *numargs - returns number of argv entries created
  3580. * int *numchars - number of characters used in args buffer
  3581. *
  3582. *Exceptions:
  3583. *
  3584. *******************************************************************************/
  3585. #define NULCHAR _T('\0')
  3586. #define SPACECHAR _T(' ')
  3587. #define TABCHAR _T('\t')
  3588. #define DQUOTECHAR _T('\"')
  3589. #define SLASHCHAR _T('\\')
  3590. static void __cdecl wparse_cmdline (
  3591. const _TSCHAR *cmdstart,
  3592. _TSCHAR **argv,
  3593. _TSCHAR *args,
  3594. int *numargs,
  3595. int *numchars
  3596. )
  3597. {
  3598. const _TSCHAR *p;
  3599. _TUCHAR c;
  3600. int inquote; /* 1 = inside quotes */
  3601. int copychar; /* 1 = copy char to *args */
  3602. unsigned numslash; /* num of backslashes seen */
  3603. *numchars = 0;
  3604. *numargs = 1; /* the program name at least */
  3605. /* first scan the program name, copy it, and count the bytes */
  3606. p = cmdstart;
  3607. if (argv)
  3608. *argv++ = args;
  3609. #ifdef WILDCARD
  3610. /* To handle later wild card expansion, we prefix each entry by
  3611. it's first character before quote handling. This is done
  3612. so _[w]cwild() knows whether to expand an entry or not. */
  3613. if (args)
  3614. *args++ = *p;
  3615. ++*numchars;
  3616. #endif /* WILDCARD */
  3617. /* A quoted program name is handled here. The handling is much
  3618. simpler than for other arguments. Basically, whatever lies
  3619. between the leading double-quote and next one, or a terminal null
  3620. character is simply accepted. Fancier handling is not required
  3621. because the program name must be a legal NTFS/HPFS file name.
  3622. Note that the double-quote characters are not copied, nor do they
  3623. contribute to numchars. */
  3624. inquote = FALSE;
  3625. do {
  3626. if (*p == DQUOTECHAR )
  3627. {
  3628. inquote = !inquote;
  3629. c = (_TUCHAR) *p++;
  3630. continue;
  3631. }
  3632. ++*numchars;
  3633. if (args)
  3634. *args++ = *p;
  3635. c = (_TUCHAR) *p++;
  3636. #ifdef _MBCS
  3637. if (_ismbblead(c)) {
  3638. ++*numchars;
  3639. if (args)
  3640. *args++ = *p; /* copy 2nd byte too */
  3641. p++; /* skip over trail byte */
  3642. }
  3643. #endif /* _MBCS */
  3644. } while ( (c != NULCHAR && (inquote || (c != SPACECHAR && c != TABCHAR))) );
  3645. if ( c == NULCHAR ) {
  3646. p--;
  3647. } else {
  3648. if (args)
  3649. *(args-1) = NULCHAR;
  3650. }
  3651. inquote = 0;
  3652. /* loop on each argument */
  3653. for(;;) {
  3654. if ( *p ) {
  3655. while (*p == SPACECHAR || *p == TABCHAR)
  3656. ++p;
  3657. }
  3658. if (*p == NULCHAR)
  3659. break; /* end of args */
  3660. /* scan an argument */
  3661. if (argv)
  3662. *argv++ = args; /* store ptr to arg */
  3663. ++*numargs;
  3664. #ifdef WILDCARD
  3665. /* To handle later wild card expansion, we prefix each entry by
  3666. it's first character before quote handling. This is done
  3667. so _[w]cwild() knows whether to expand an entry or not. */
  3668. if (args)
  3669. *args++ = *p;
  3670. ++*numchars;
  3671. #endif /* WILDCARD */
  3672. /* loop through scanning one argument */
  3673. for (;;) {
  3674. copychar = 1;
  3675. /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
  3676. 2N+1 backslashes + " ==> N backslashes + literal "
  3677. N backslashes ==> N backslashes */
  3678. numslash = 0;
  3679. while (*p == SLASHCHAR) {
  3680. /* count number of backslashes for use below */
  3681. ++p;
  3682. ++numslash;
  3683. }
  3684. if (*p == DQUOTECHAR) {
  3685. /* if 2N backslashes before, start/end quote, otherwise
  3686. copy literally */
  3687. if (numslash % 2 == 0) {
  3688. if (inquote && p[1] == DQUOTECHAR) {
  3689. p++; /* Double quote inside quoted string */
  3690. } else { /* skip first quote char and copy second */
  3691. copychar = 0; /* don't copy quote */
  3692. inquote = !inquote;
  3693. }
  3694. }
  3695. numslash /= 2; /* divide numslash by two */
  3696. }
  3697. /* copy slashes */
  3698. while (numslash--) {
  3699. if (args)
  3700. *args++ = SLASHCHAR;
  3701. ++*numchars;
  3702. }
  3703. /* if at end of arg, break loop */
  3704. if (*p == NULCHAR || (!inquote && (*p == SPACECHAR || *p == TABCHAR)))
  3705. break;
  3706. /* copy character into argument */
  3707. #ifdef _MBCS
  3708. if (copychar) {
  3709. if (args) {
  3710. if (_ismbblead(*p)) {
  3711. *args++ = *p++;
  3712. ++*numchars;
  3713. }
  3714. *args++ = *p;
  3715. } else {
  3716. if (_ismbblead(*p)) {
  3717. ++p;
  3718. ++*numchars;
  3719. }
  3720. }
  3721. ++*numchars;
  3722. }
  3723. ++p;
  3724. #else /* _MBCS */
  3725. if (copychar) {
  3726. if (args)
  3727. *args++ = *p;
  3728. ++*numchars;
  3729. }
  3730. ++p;
  3731. #endif /* _MBCS */
  3732. }
  3733. /* null-terminate the argument */
  3734. if (args)
  3735. *args++ = NULCHAR; /* terminate string */
  3736. ++*numchars;
  3737. }
  3738. /* We put one last argument in -- a null ptr */
  3739. if (argv)
  3740. *argv++ = NULL;
  3741. ++*numargs;
  3742. }
  3743. #define MAX_ARGUMENTS 128
  3744. static TCHAR **parseargstring (const TCHAR *s)
  3745. {
  3746. TCHAR **p;
  3747. int numa, numc;
  3748. if (_tcslen (s) == 0)
  3749. return NULL;
  3750. wparse_cmdline (s, NULL, NULL, &numa, &numc);
  3751. numa++;
  3752. p = (TCHAR**)xcalloc (uae_u8, numa * sizeof (TCHAR*) + numc * sizeof (TCHAR));
  3753. wparse_cmdline (s, (wchar_t **)p, (wchar_t *)(((char *)p) + numa * sizeof(wchar_t *)), &numa, &numc);
  3754. if (numa > MAX_ARGUMENTS) {
  3755. p[MAX_ARGUMENTS] = NULL;
  3756. numa = MAX_ARGUMENTS;
  3757. }
  3758. TCHAR **dstp = xcalloc (TCHAR*, MAX_ARGUMENTS + 1);
  3759. for (int i = 0; p[i]; i++)
  3760. dstp[i] = my_strdup (p[i]);
  3761. xfree (p);
  3762. return dstp;
  3763. }
  3764. static void shellexecute (const TCHAR *command)
  3765. {
  3766. STARTUPINFO si = { 0 };
  3767. PROCESS_INFORMATION pi = { 0 };
  3768. TCHAR **arg;
  3769. int i, j, k, stop;
  3770. if (_tcslen (command) == 0)
  3771. return;
  3772. i = j = 0;
  3773. stop = 0;
  3774. arg = parseargstring (command);
  3775. while (!stop) {
  3776. TCHAR *cmd, *exec;
  3777. int len = 1;
  3778. j = i;
  3779. while (arg[i] && _tcscmp (arg[i], L";")) {
  3780. len += _tcslen (arg[i]) + 3;
  3781. i++;
  3782. }
  3783. exec = NULL;
  3784. cmd = xcalloc (TCHAR, len);
  3785. for (k = j; k < i; k++) {
  3786. int quote = 0;
  3787. if (_tcslen (cmd) > 0)
  3788. _tcscat (cmd, L" ");
  3789. if (_tcschr (arg[k], ' '))
  3790. quote = 1;
  3791. if (quote)
  3792. _tcscat (cmd, L"\"");
  3793. _tcscat (cmd, arg[k]);
  3794. if (quote)
  3795. _tcscat (cmd, _T("\""));
  3796. if (!exec && !_tcsicmp (cmd, _T("cmd.exe"))) {
  3797. int size;
  3798. size = GetEnvironmentVariable (_T("ComSpec"), NULL, 0);
  3799. if (size > 0) {
  3800. exec = xcalloc (TCHAR, size + 1);
  3801. GetEnvironmentVariable (_T("ComSpec"), exec, size);
  3802. }
  3803. cmd[0] = 0;
  3804. }
  3805. }
  3806. if (arg[i++] == 0)
  3807. stop = 1;
  3808. si.cb = sizeof si;
  3809. //si.wShowWindow = SW_HIDE;
  3810. //si.dwFlags = STARTF_USESHOWWINDOW;
  3811. if (CreateProcess (exec,
  3812. cmd,
  3813. NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
  3814. WaitForSingleObject (pi.hProcess, INFINITE);
  3815. CloseHandle (pi.hProcess);
  3816. CloseHandle (pi.hThread);
  3817. } else {
  3818. write_log (_T("CreateProcess('%s' '%s') failed, %d\n"),
  3819. exec, cmd, GetLastError ());
  3820. }
  3821. xfree (exec);
  3822. xfree (cmd);
  3823. }
  3824. for (i = 0; arg && arg[i]; i++)
  3825. xfree (arg[i]);
  3826. xfree (arg);
  3827. }
  3828. void target_run (void)
  3829. {
  3830. shellexecute (currprefs.win32_commandpathstart);
  3831. }
  3832. void target_quit (void)
  3833. {
  3834. shellexecute (currprefs.win32_commandpathend);
  3835. }
  3836. void target_fixup_options (struct uae_prefs *p)
  3837. {
  3838. if (p->win32_automount_cddrives && !p->scsi)
  3839. p->scsi = 1;
  3840. if (p->win32_uaescsimode > UAESCSI_LAST)
  3841. p->win32_uaescsimode = UAESCSI_SPTI;
  3842. bool paused = false;
  3843. bool nosound = false;
  3844. bool nojoy = true;
  3845. if (!paused) {
  3846. paused = p->win32_active_nocapture_pause;
  3847. nosound = p->win32_active_nocapture_nosound;
  3848. } else {
  3849. p->win32_active_nocapture_pause = p->win32_active_nocapture_nosound = true;
  3850. nosound = true;
  3851. nojoy = false;
  3852. }
  3853. if (!paused) {
  3854. paused = p->win32_inactive_pause;
  3855. nosound = p->win32_inactive_nosound;
  3856. nojoy = (p->win32_inactive_input & 4) == 0;
  3857. } else {
  3858. p->win32_inactive_pause = p->win32_inactive_nosound = true;
  3859. p->win32_inactive_input = 0;
  3860. nosound = true;
  3861. nojoy = true;
  3862. }
  3863. if (p->rtg_hardwaresprite && !p->gfx_api) {
  3864. error_log(_T("DirectDraw is not RTG hardware sprite compatible."));
  3865. p->rtg_hardwaresprite = false;
  3866. }
  3867. if (p->rtgboards[0].rtgmem_type >= GFXBOARD_HARDWARE) {
  3868. p->rtg_hardwareinterrupt = false;
  3869. p->rtg_hardwaresprite = false;
  3870. p->win32_rtgmatchdepth = false;
  3871. p->color_mode = 5;
  3872. if (p->ppc_model && !p->gfx_api) {
  3873. error_log(_T("Graphics board and PPC: Direct3D enabled."));
  3874. p->gfx_api = os_win7 ? 2 : 1;
  3875. }
  3876. }
  3877. struct MultiDisplay *md = getdisplay(p, 0);
  3878. for (int j = 0; j < MAX_AMIGADISPLAYS; j++) {
  3879. if (p->gfx_monitor[j].gfx_size_fs.special == WH_NATIVE) {
  3880. int i;
  3881. for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
  3882. if (md->DisplayModes[i].res.width == md->rect.right - md->rect.left &&
  3883. md->DisplayModes[i].res.height == md->rect.bottom - md->rect.top) {
  3884. p->gfx_monitor[j].gfx_size_fs.width = md->DisplayModes[i].res.width;
  3885. p->gfx_monitor[j].gfx_size_fs.height = md->DisplayModes[i].res.height;
  3886. write_log(_T("Native resolution: %dx%d\n"), p->gfx_monitor[j].gfx_size_fs.width, p->gfx_monitor[j].gfx_size_fs.height);
  3887. break;
  3888. }
  3889. }
  3890. if (md->DisplayModes[i].depth < 0) {
  3891. p->gfx_monitor[j].gfx_size_fs.special = 0;
  3892. write_log(_T("Native resolution not found.\n"));
  3893. }
  3894. }
  3895. }
  3896. /* switch from 32 to 16 or vice versa if mode does not exist */
  3897. if (1 || isfullscreen() > 0) {
  3898. int depth = p->color_mode == 5 ? 4 : 2;
  3899. for (int i = 0; md->DisplayModes[i].depth >= 0; i++) {
  3900. if (md->DisplayModes[i].depth == depth) {
  3901. depth = 0;
  3902. break;
  3903. }
  3904. }
  3905. if (depth) {
  3906. p->color_mode = p->color_mode == 5 ? 2 : 5;
  3907. }
  3908. }
  3909. if ((p->gfx_apmode[0].gfx_vsyncmode || p->gfx_apmode[1].gfx_vsyncmode) ) {
  3910. if (p->produce_sound && sound_devices[p->win32_soundcard]->type == SOUND_DEVICE_DS) {
  3911. p->win32_soundcard = 0;
  3912. }
  3913. }
  3914. d3d_select(p);
  3915. }
  3916. void target_default_options (struct uae_prefs *p, int type)
  3917. {
  3918. TCHAR buf[MAX_DPATH];
  3919. if (type == 2 || type == 0 || type == 3) {
  3920. p->win32_logfile = 0;
  3921. p->win32_active_nocapture_pause = 0;
  3922. p->win32_active_nocapture_nosound = 0;
  3923. p->win32_iconified_nosound = 1;
  3924. p->win32_iconified_pause = 1;
  3925. p->win32_iconified_input = 0;
  3926. p->win32_inactive_nosound = 0;
  3927. p->win32_inactive_pause = 0;
  3928. p->win32_inactive_input = 0;
  3929. p->win32_ctrl_F11_is_quit = 0;
  3930. p->win32_soundcard = 0;
  3931. p->win32_samplersoundcard = -1;
  3932. p->win32_minimize_inactive = 0;
  3933. p->win32_capture_always = false;
  3934. p->win32_start_minimized = false;
  3935. p->win32_start_uncaptured = false;
  3936. p->win32_active_capture_priority = 1;
  3937. //p->win32_active_nocapture_priority = 1;
  3938. p->win32_inactive_priority = 2;
  3939. p->win32_iconified_priority = 3;
  3940. p->win32_notaskbarbutton = false;
  3941. p->win32_nonotificationicon = false;
  3942. p->win32_main_alwaysontop = false;
  3943. p->win32_gui_alwaysontop = false;
  3944. p->win32_guikey = -1;
  3945. p->win32_automount_removable = 0;
  3946. p->win32_automount_drives = 0;
  3947. p->win32_automount_removabledrives = 0;
  3948. p->win32_automount_cddrives = 0;
  3949. p->win32_automount_netdrives = 0;
  3950. p->win32_kbledmode = 1;
  3951. p->win32_uaescsimode = UAESCSI_CDEMU;
  3952. p->win32_borderless = 0;
  3953. p->win32_blankmonitors = false;
  3954. p->win32_powersavedisabled = true;
  3955. p->sana2 = 0;
  3956. p->win32_rtgmatchdepth = 1;
  3957. p->gf[APMODE_RTG].gfx_filter_autoscale = RTG_MODE_SCALE;
  3958. p->win32_rtgallowscaling = 0;
  3959. p->win32_rtgscaleaspectratio = -1;
  3960. p->win32_rtgvblankrate = 0;
  3961. p->rtg_hardwaresprite = true;
  3962. p->win32_commandpathstart[0] = 0;
  3963. p->win32_commandpathend[0] = 0;
  3964. p->win32_statusbar = 1;
  3965. p->gfx_api = os_win7 ? 2 : (os_vista ? 1 : 0);
  3966. if (p->gfx_api > 1)
  3967. p->color_mode = 5;
  3968. if (p->gf[APMODE_NATIVE].gfx_filter == 0 && p->gfx_api)
  3969. p->gf[APMODE_NATIVE].gfx_filter = 1;
  3970. if (p->gf[APMODE_RTG].gfx_filter == 0 && p->gfx_api)
  3971. p->gf[APMODE_RTG].gfx_filter = 1;
  3972. WIN32GUI_LoadUIString (IDS_INPUT_CUSTOM, buf, sizeof buf / sizeof (TCHAR));
  3973. for (int i = 0; i < GAMEPORT_INPUT_SETTINGS; i++)
  3974. _stprintf (p->input_config_name[i], buf, i + 1);
  3975. p->aviout_xoffset = -1;
  3976. p->aviout_yoffset = -1;
  3977. }
  3978. if (type == 1 || type == 0 || type == 3) {
  3979. p->win32_uaescsimode = UAESCSI_CDEMU;
  3980. p->win32_midioutdev = -2;
  3981. p->win32_midiindev = 0;
  3982. p->win32_midirouter = false;
  3983. p->win32_automount_removable = 0;
  3984. p->win32_automount_drives = 0;
  3985. p->win32_automount_removabledrives = 0;
  3986. p->win32_automount_cddrives = 0;
  3987. p->win32_automount_netdrives = 0;
  3988. p->picasso96_modeflags = RGBFF_CLUT | RGBFF_R5G6B5PC | RGBFF_B8G8R8A8;
  3989. p->win32_filesystem_mangle_reserved_names = true;
  3990. }
  3991. }
  3992. static const TCHAR *scsimode[] = { _T("SCSIEMU"), _T("SPTI"), _T("SPTI+SCSISCAN"), NULL };
  3993. static const TCHAR *statusbarmode[] = { _T("none"), _T("normal"), _T("extended"), NULL };
  3994. static const TCHAR *configmult[] = { _T("1x"), _T("2x"), _T("3x"), _T("4x"), _T("5x"), _T("6x"), _T("7x"), _T("8x"), NULL };
  3995. static struct midiportinfo *getmidiport (struct midiportinfo **mi, int devid)
  3996. {
  3997. for (int i = 0; i < MAX_MIDI_PORTS; i++) {
  3998. if (mi[i] != NULL && mi[i]->devid == devid)
  3999. return mi[i];
  4000. }
  4001. return NULL;
  4002. }
  4003. extern int scsiromselected;
  4004. void target_save_options (struct zfile *f, struct uae_prefs *p)
  4005. {
  4006. struct midiportinfo *midp;
  4007. cfgfile_target_write_bool (f, _T("middle_mouse"), (p->input_mouse_untrap & MOUSEUNTRAP_MIDDLEBUTTON) != 0);
  4008. cfgfile_target_dwrite_bool (f, _T("logfile"), p->win32_logfile);
  4009. cfgfile_target_dwrite_bool (f, _T("map_drives"), p->win32_automount_drives);
  4010. cfgfile_target_dwrite_bool (f, _T("map_drives_auto"), p->win32_automount_removable);
  4011. cfgfile_target_dwrite_bool (f, _T("map_cd_drives"), p->win32_automount_cddrives);
  4012. cfgfile_target_dwrite_bool (f, _T("map_net_drives"), p->win32_automount_netdrives);
  4013. cfgfile_target_dwrite_bool (f, _T("map_removable_drives"), p->win32_automount_removabledrives);
  4014. serdevtoname (p->sername);
  4015. cfgfile_target_dwrite_str(f, _T("serial_port"), p->sername[0] ? p->sername : _T("none"));
  4016. sernametodev (p->sername);
  4017. cfgfile_target_dwrite_str_escape(f, _T("parallel_port"), p->prtname[0] ? p->prtname : _T("none"));
  4018. cfgfile_target_dwrite (f, _T("active_priority"), _T("%d"), priorities[p->win32_active_capture_priority].value);
  4019. #if 0
  4020. cfgfile_target_dwrite (f, _T("active_not_captured_priority"), _T("%d"), priorities[p->win32_active_nocapture_priority].value);
  4021. #endif
  4022. cfgfile_target_dwrite_bool(f, _T("active_not_captured_nosound"), p->win32_active_nocapture_nosound);
  4023. cfgfile_target_dwrite_bool(f, _T("active_not_captured_pause"), p->win32_active_nocapture_pause);
  4024. cfgfile_target_dwrite(f, _T("inactive_priority"), _T("%d"), priorities[p->win32_inactive_priority].value);
  4025. cfgfile_target_dwrite_bool(f, _T("inactive_nosound"), p->win32_inactive_nosound);
  4026. cfgfile_target_dwrite_bool(f, _T("inactive_pause"), p->win32_inactive_pause);
  4027. cfgfile_target_dwrite(f, _T("inactive_input"), _T("%d"), p->win32_inactive_input);
  4028. cfgfile_target_dwrite(f, _T("iconified_priority"), _T("%d"), priorities[p->win32_iconified_priority].value);
  4029. cfgfile_target_dwrite_bool(f, _T("iconified_nosound"), p->win32_iconified_nosound);
  4030. cfgfile_target_dwrite_bool(f, _T("iconified_pause"), p->win32_iconified_pause);
  4031. cfgfile_target_dwrite(f, _T("iconified_input"), _T("%d"), p->win32_iconified_input);
  4032. cfgfile_target_dwrite_bool(f, _T("inactive_iconify"), p->win32_minimize_inactive);
  4033. cfgfile_target_dwrite_bool(f, _T("active_capture_automatically"), p->win32_capture_always);
  4034. cfgfile_target_dwrite_bool(f, _T("start_iconified"), p->win32_start_minimized);
  4035. cfgfile_target_dwrite_bool(f, _T("start_not_captured"), p->win32_start_uncaptured);
  4036. cfgfile_target_dwrite_bool (f, _T("ctrl_f11_is_quit"), p->win32_ctrl_F11_is_quit);
  4037. cfgfile_target_dwrite (f, _T("midiout_device"), _T("%d"), p->win32_midioutdev);
  4038. cfgfile_target_dwrite (f, _T("midiin_device"), _T("%d"), p->win32_midiindev);
  4039. midp = getmidiport (midioutportinfo, p->win32_midioutdev);
  4040. if (p->win32_midioutdev < -1)
  4041. cfgfile_target_dwrite_str_escape(f, _T("midiout_device_name"), _T("none"));
  4042. else if (p->win32_midioutdev == -1 || midp == NULL)
  4043. cfgfile_target_dwrite_str_escape(f, _T("midiout_device_name"), _T("default"));
  4044. else
  4045. cfgfile_target_dwrite_str_escape(f, _T("midiout_device_name"), midp->name);
  4046. midp = getmidiport (midiinportinfo, p->win32_midiindev);
  4047. if (p->win32_midiindev < 0 || midp == NULL)
  4048. cfgfile_target_dwrite_str_escape(f, _T("midiin_device_name"), _T("none"));
  4049. else
  4050. cfgfile_target_dwrite_str_escape(f, _T("midiin_device_name"), midp->name);
  4051. cfgfile_target_dwrite_bool (f, _T("midirouter"), p->win32_midirouter);
  4052. cfgfile_target_dwrite_bool (f, _T("rtg_match_depth"), p->win32_rtgmatchdepth);
  4053. cfgfile_target_dwrite_bool(f, _T("rtg_scale_small"), p->gf[1].gfx_filter_autoscale == 1);
  4054. cfgfile_target_dwrite_bool(f, _T("rtg_scale_center"), p->gf[1].gfx_filter_autoscale == 2);
  4055. cfgfile_target_dwrite_bool (f, _T("rtg_scale_allow"), p->win32_rtgallowscaling);
  4056. cfgfile_target_dwrite (f, _T("rtg_scale_aspect_ratio"), _T("%d:%d"),
  4057. p->win32_rtgscaleaspectratio >= 0 ? (p->win32_rtgscaleaspectratio / ASPECTMULT) : -1,
  4058. p->win32_rtgscaleaspectratio >= 0 ? (p->win32_rtgscaleaspectratio & (ASPECTMULT - 1)) : -1);
  4059. if (p->win32_rtgvblankrate <= 0)
  4060. cfgfile_target_dwrite_str (f, _T("rtg_vblank"), p->win32_rtgvblankrate == -1 ? _T("real") : (p->win32_rtgvblankrate == -2 ? _T("disabled") : _T("chipset")));
  4061. else
  4062. cfgfile_target_dwrite (f, _T("rtg_vblank"), _T("%d"), p->win32_rtgvblankrate);
  4063. cfgfile_target_dwrite_bool (f, _T("borderless"), p->win32_borderless);
  4064. cfgfile_target_dwrite_bool (f, _T("blank_monitors"), p->win32_blankmonitors);
  4065. cfgfile_target_dwrite_str (f, _T("uaescsimode"), scsimode[p->win32_uaescsimode]);
  4066. cfgfile_target_dwrite_str (f, _T("statusbar"), statusbarmode[p->win32_statusbar]);
  4067. cfgfile_target_write (f, _T("soundcard"), _T("%d"), p->win32_soundcard);
  4068. if (p->win32_soundcard >= 0 && p->win32_soundcard < MAX_SOUND_DEVICES && sound_devices[p->win32_soundcard])
  4069. cfgfile_target_write_str (f, _T("soundcardname"), sound_devices[p->win32_soundcard]->cfgname);
  4070. if (p->win32_samplersoundcard >= 0 && p->win32_samplersoundcard < MAX_SOUND_DEVICES) {
  4071. cfgfile_target_write (f, _T("samplersoundcard"), _T("%d"), p->win32_samplersoundcard);
  4072. if (record_devices[p->win32_samplersoundcard])
  4073. cfgfile_target_write_str (f, _T("samplersoundcardname"), record_devices[p->win32_samplersoundcard]->cfgname);
  4074. }
  4075. cfgfile_target_dwrite (f, _T("cpu_idle"), _T("%d"), p->cpu_idle);
  4076. cfgfile_target_dwrite_bool (f, _T("notaskbarbutton"), p->win32_notaskbarbutton);
  4077. cfgfile_target_dwrite_bool (f, _T("nonotificationicon"), p->win32_nonotificationicon);
  4078. cfgfile_target_dwrite_bool (f, _T("always_on_top"), p->win32_main_alwaysontop);
  4079. cfgfile_target_dwrite_bool (f, _T("gui_always_on_top"), p->win32_gui_alwaysontop);
  4080. cfgfile_target_dwrite_bool (f, _T("no_recyclebin"), p->win32_norecyclebin);
  4081. if (p->win32_guikey >= 0)
  4082. cfgfile_target_dwrite (f, _T("guikey"), _T("0x%x"), p->win32_guikey);
  4083. cfgfile_target_dwrite (f, _T("kbledmode"), _T("%d"), p->win32_kbledmode);
  4084. cfgfile_target_dwrite_bool (f, _T("powersavedisabled"), p->win32_powersavedisabled);
  4085. cfgfile_target_dwrite_str (f, _T("exec_before"), p->win32_commandpathstart);
  4086. cfgfile_target_dwrite_str (f, _T("exec_after"), p->win32_commandpathend);
  4087. cfgfile_target_dwrite_str (f, _T("parjoyport0"), p->win32_parjoyport0);
  4088. cfgfile_target_dwrite_str (f, _T("parjoyport1"), p->win32_parjoyport1);
  4089. cfgfile_target_dwrite_str (f, _T("gui_page"), p->win32_guipage);
  4090. cfgfile_target_dwrite_str (f, _T("gui_active_page"), p->win32_guiactivepage);
  4091. cfgfile_target_dwrite_bool(f, _T("filesystem_mangle_reserved_names"), p->win32_filesystem_mangle_reserved_names);
  4092. cfgfile_target_dwrite_bool(f, _T("right_control_is_right_win"), p->right_control_is_right_win_key);
  4093. cfgfile_target_dwrite_bool(f, _T("windows_shutdown_notification"), p->win32_shutdown_notification);
  4094. cfgfile_target_dwrite_bool(f, _T("warn_exit"), p->win32_warn_exit);
  4095. cfgfile_target_dwrite(f, _T("extraframewait"), _T("%d"), extraframewait);
  4096. cfgfile_target_dwrite(f, _T("extraframewait_us"), _T("%d"), extraframewait2);
  4097. cfgfile_target_dwrite (f, _T("framelatency"), _T("%d"), forcedframelatency);
  4098. if (scsiromselected > 0)
  4099. cfgfile_target_write(f, _T("expansion_gui_page"), expansionroms[scsiromselected].name);
  4100. cfgfile_target_dwrite(f, _T("recording_width"), _T("%d"), p->aviout_width);
  4101. cfgfile_target_dwrite(f, _T("recording_height"), _T("%d"), p->aviout_height);
  4102. cfgfile_target_dwrite(f, _T("recording_x"), _T("%d"), p->aviout_xoffset);
  4103. cfgfile_target_dwrite(f, _T("recording_y"), _T("%d"), p->aviout_yoffset);
  4104. cfgfile_target_dwrite(f, _T("screenshot_width"), _T("%d"), p->screenshot_width);
  4105. cfgfile_target_dwrite(f, _T("screenshot_height"), _T("%d"), p->screenshot_height);
  4106. cfgfile_target_dwrite(f, _T("screenshot_x"), _T("%d"), p->screenshot_xoffset);
  4107. cfgfile_target_dwrite(f, _T("screenshot_y"), _T("%d"), p->screenshot_yoffset);
  4108. cfgfile_target_dwrite(f, _T("screenshot_min_width"), _T("%d"), p->screenshot_min_width);
  4109. cfgfile_target_dwrite(f, _T("screenshot_min_height"), _T("%d"), p->screenshot_min_height);
  4110. cfgfile_target_dwrite(f, _T("screenshot_max_width"), _T("%d"), p->screenshot_max_width);
  4111. cfgfile_target_dwrite(f, _T("screenshot_max_height"), _T("%d"), p->screenshot_max_height);
  4112. cfgfile_target_dwrite(f, _T("screenshot_output_width_limit"), _T("%d"), p->screenshot_output_width);
  4113. cfgfile_target_dwrite(f, _T("screenshot_output_height_limit"), _T("%d"), p->screenshot_output_height);
  4114. cfgfile_target_dwrite_str(f, _T("screenshot_mult_width"), configmult[p->screenshot_xmult]);
  4115. cfgfile_target_dwrite_str(f, _T("screenshot_mult_height"), configmult[p->screenshot_ymult]);
  4116. }
  4117. void target_restart (void)
  4118. {
  4119. gui_restart ();
  4120. }
  4121. static int fetchpri (int pri, int defpri)
  4122. {
  4123. int i = 0;
  4124. while (priorities[i].name) {
  4125. if (priorities[i].value == pri)
  4126. return i;
  4127. i++;
  4128. }
  4129. return defpri;
  4130. }
  4131. TCHAR *target_expand_environment (const TCHAR *path, TCHAR *out, int maxlen)
  4132. {
  4133. if (!path)
  4134. return NULL;
  4135. if (out == NULL) {
  4136. int len = ExpandEnvironmentStrings (path, NULL, 0);
  4137. if (len <= 0)
  4138. return my_strdup (path);
  4139. TCHAR *s = xmalloc (TCHAR, len + 1);
  4140. ExpandEnvironmentStrings (path, s, len);
  4141. return s;
  4142. } else {
  4143. if (ExpandEnvironmentStrings(path, out, maxlen) <= 0)
  4144. _tcscpy(out, path);
  4145. return out;
  4146. }
  4147. }
  4148. static const TCHAR *obsolete[] = {
  4149. _T("killwinkeys"), _T("sound_force_primary"), _T("iconified_highpriority"),
  4150. _T("sound_sync"), _T("sound_tweak"), _T("directx6"), _T("sound_style"),
  4151. _T("file_path"), _T("iconified_nospeed"), _T("activepriority"), _T("magic_mouse"),
  4152. _T("filesystem_codepage"), _T("aspi"), _T("no_overlay"), _T("soundcard_exclusive"),
  4153. _T("specialkey"), _T("sound_speed_tweak"), _T("sound_lag"),
  4154. 0
  4155. };
  4156. int target_parse_option (struct uae_prefs *p, const TCHAR *option, const TCHAR *value)
  4157. {
  4158. TCHAR tmpbuf[CONFIG_BLEN];
  4159. int i, v;
  4160. bool tbool;
  4161. if (cfgfile_yesno(option, value, _T("middle_mouse"), &tbool)) {
  4162. if (tbool)
  4163. p->input_mouse_untrap |= MOUSEUNTRAP_MIDDLEBUTTON;
  4164. else
  4165. p->input_mouse_untrap &= ~MOUSEUNTRAP_MIDDLEBUTTON;
  4166. return 1;
  4167. }
  4168. if (cfgfile_yesno(option, value, _T("map_drives"), &p->win32_automount_drives)
  4169. || cfgfile_yesno(option, value, _T("map_drives_auto"), &p->win32_automount_removable)
  4170. || cfgfile_yesno(option, value, _T("map_cd_drives"), &p->win32_automount_cddrives)
  4171. || cfgfile_yesno(option, value, _T("map_net_drives"), &p->win32_automount_netdrives)
  4172. || cfgfile_yesno(option, value, _T("map_removable_drives"), &p->win32_automount_removabledrives)
  4173. || cfgfile_yesno(option, value, _T("logfile"), &p->win32_logfile)
  4174. || cfgfile_yesno(option, value, _T("networking"), &p->socket_emu)
  4175. || cfgfile_yesno(option, value, _T("borderless"), &p->win32_borderless)
  4176. || cfgfile_yesno(option, value, _T("blank_monitors"), &p->win32_blankmonitors)
  4177. || cfgfile_yesno(option, value, _T("active_not_captured_pause"), &p->win32_active_nocapture_pause)
  4178. || cfgfile_yesno(option, value, _T("active_not_captured_nosound"), &p->win32_active_nocapture_nosound)
  4179. || cfgfile_yesno(option, value, _T("inactive_pause"), &p->win32_inactive_pause)
  4180. || cfgfile_yesno(option, value, _T("inactive_nosound"), &p->win32_inactive_nosound)
  4181. || cfgfile_intval(option, value, _T("inactive_input"), &p->win32_inactive_input, 1)
  4182. || cfgfile_yesno(option, value, _T("iconified_pause"), &p->win32_iconified_pause)
  4183. || cfgfile_yesno(option, value, _T("iconified_nosound"), &p->win32_iconified_nosound)
  4184. || cfgfile_intval(option, value, _T("iconified_input"), &p->win32_iconified_input, 1)
  4185. || cfgfile_yesno(option, value, _T("ctrl_f11_is_quit"), &p->win32_ctrl_F11_is_quit)
  4186. || cfgfile_yesno(option, value, _T("no_recyclebin"), &p->win32_norecyclebin)
  4187. || cfgfile_intval(option, value, _T("midi_device"), &p->win32_midioutdev, 1)
  4188. || cfgfile_intval(option, value, _T("midiout_device"), &p->win32_midioutdev, 1)
  4189. || cfgfile_intval(option, value, _T("midiin_device"), &p->win32_midiindev, 1)
  4190. || cfgfile_yesno(option, value, _T("midirouter"), &p->win32_midirouter)
  4191. || cfgfile_intval(option, value, _T("samplersoundcard"), &p->win32_samplersoundcard, 1)
  4192. || cfgfile_yesno(option, value, _T("notaskbarbutton"), &p->win32_notaskbarbutton)
  4193. || cfgfile_yesno(option, value, _T("nonotificationicon"), &p->win32_nonotificationicon)
  4194. || cfgfile_yesno(option, value, _T("always_on_top"), &p->win32_main_alwaysontop)
  4195. || cfgfile_yesno(option, value, _T("gui_always_on_top"), &p->win32_gui_alwaysontop)
  4196. || cfgfile_yesno(option, value, _T("powersavedisabled"), &p->win32_powersavedisabled)
  4197. || cfgfile_string(option, value, _T("exec_before"), p->win32_commandpathstart, sizeof p->win32_commandpathstart / sizeof (TCHAR))
  4198. || cfgfile_string(option, value, _T("exec_after"), p->win32_commandpathend, sizeof p->win32_commandpathend / sizeof (TCHAR))
  4199. || cfgfile_string(option, value, _T("parjoyport0"), p->win32_parjoyport0, sizeof p->win32_parjoyport0 / sizeof (TCHAR))
  4200. || cfgfile_string(option, value, _T("parjoyport1"), p->win32_parjoyport1, sizeof p->win32_parjoyport1 / sizeof (TCHAR))
  4201. || cfgfile_string(option, value, _T("gui_page"), p->win32_guipage, sizeof p->win32_guipage / sizeof (TCHAR))
  4202. || cfgfile_string(option, value, _T("gui_active_page"), p->win32_guiactivepage, sizeof p->win32_guiactivepage / sizeof (TCHAR))
  4203. || cfgfile_intval(option, value, _T("guikey"), &p->win32_guikey, 1)
  4204. || cfgfile_intval(option, value, _T("kbledmode"), &p->win32_kbledmode, 1)
  4205. || cfgfile_yesno(option, value, _T("filesystem_mangle_reserved_names"), &p->win32_filesystem_mangle_reserved_names)
  4206. || cfgfile_yesno(option, value, _T("right_control_is_right_win"), &p->right_control_is_right_win_key)
  4207. || cfgfile_yesno(option, value, _T("windows_shutdown_notification"), &p->win32_shutdown_notification)
  4208. || cfgfile_yesno(option, value, _T("warn_exit"), &p->win32_warn_exit)
  4209. || cfgfile_intval(option, value, _T("extraframewait"), &extraframewait, 1)
  4210. || cfgfile_intval(option, value, _T("extraframewait_us"), &extraframewait2, 1)
  4211. || cfgfile_intval(option, value, _T("framelatency"), &forcedframelatency, 1)
  4212. || cfgfile_intval(option, value, _T("cpu_idle"), &p->cpu_idle, 1))
  4213. return 1;
  4214. if (cfgfile_intval(option, value, _T("recording_width"), &p->aviout_width, 1)
  4215. || cfgfile_intval(option, value, _T("recording_height"), &p->aviout_height, 1)
  4216. || cfgfile_intval(option, value, _T("recording_x"), &p->aviout_xoffset, 1)
  4217. || cfgfile_intval(option, value, _T("recording_y"), &p->aviout_yoffset, 1)
  4218. || cfgfile_intval(option, value, _T("screenshot_width"), &p->screenshot_width, 1)
  4219. || cfgfile_intval(option, value, _T("screenshot_height"), &p->screenshot_height, 1)
  4220. || cfgfile_intval(option, value, _T("screenshot_x"), &p->screenshot_xoffset, 1)
  4221. || cfgfile_intval(option, value, _T("screenshot_y"), &p->screenshot_yoffset, 1)
  4222. || cfgfile_intval(option, value, _T("screenshot_min_width"), &p->screenshot_min_width, 1)
  4223. || cfgfile_intval(option, value, _T("screenshot_min_height"), &p->screenshot_min_height, 1)
  4224. || cfgfile_intval(option, value, _T("screenshot_max_width"), &p->screenshot_max_width, 1)
  4225. || cfgfile_intval(option, value, _T("screenshot_max_height"), &p->screenshot_max_height, 1)
  4226. || cfgfile_intval(option, value, _T("screenshot_output_width_limit"), &p->screenshot_output_width, 1)
  4227. || cfgfile_intval(option, value, _T("screenshot_output_height_limit"), &p->screenshot_output_height, 1))
  4228. return 1;
  4229. if (cfgfile_strval(option, value, _T("screenshot_mult_width"), &p->screenshot_xmult, configmult, 0))
  4230. return 1;
  4231. if (cfgfile_strval(option, value, _T("screenshot_mult_height"), &p->screenshot_ymult, configmult, 0))
  4232. return 1;
  4233. if (cfgfile_string(option, value, _T("expansion_gui_page"), tmpbuf, sizeof tmpbuf / sizeof(TCHAR))) {
  4234. TCHAR *p = _tcschr(tmpbuf, ',');
  4235. if (p != NULL)
  4236. *p = 0;
  4237. for (int i = 0; expansionroms[i].name; i++) {
  4238. if (!_tcsicmp(tmpbuf, expansionroms[i].name)) {
  4239. scsiromselected = i;
  4240. break;
  4241. }
  4242. }
  4243. return 1;
  4244. }
  4245. if (cfgfile_yesno (option, value, _T("rtg_match_depth"), &p->win32_rtgmatchdepth))
  4246. return 1;
  4247. if (cfgfile_yesno (option, value, _T("rtg_scale_small"), &tbool)) {
  4248. p->gf[1].gfx_filter_autoscale = tbool ? RTG_MODE_SCALE : 0;
  4249. return 1;
  4250. }
  4251. if (cfgfile_yesno (option, value, _T("rtg_scale_center"), &tbool)) {
  4252. if (tbool)
  4253. p->gf[1].gfx_filter_autoscale = RTG_MODE_CENTER;
  4254. return 1;
  4255. }
  4256. if (cfgfile_yesno (option, value, _T("rtg_scale_allow"), &p->win32_rtgallowscaling))
  4257. return 1;
  4258. if (cfgfile_intval (option, value, _T("soundcard"), &p->win32_soundcard, 1)) {
  4259. if (p->win32_soundcard < 0 || p->win32_soundcard >= MAX_SOUND_DEVICES || sound_devices[p->win32_soundcard] == NULL)
  4260. p->win32_soundcard = 0;
  4261. return 1;
  4262. }
  4263. if (cfgfile_string (option, value, _T("soundcardname"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
  4264. int i, num;
  4265. num = p->win32_soundcard;
  4266. p->win32_soundcard = -1;
  4267. for (i = 0; i < MAX_SOUND_DEVICES && sound_devices[i] ; i++) {
  4268. if (i < num)
  4269. continue;
  4270. if (!_tcscmp (sound_devices[i]->cfgname, tmpbuf)) {
  4271. p->win32_soundcard = i;
  4272. break;
  4273. }
  4274. }
  4275. if (p->win32_soundcard < 0) {
  4276. for (i = 0; i < MAX_SOUND_DEVICES && sound_devices[i]; i++) {
  4277. if (!_tcscmp (sound_devices[i]->cfgname, tmpbuf)) {
  4278. p->win32_soundcard = i;
  4279. break;
  4280. }
  4281. }
  4282. }
  4283. if (p->win32_soundcard < 0) {
  4284. for (i = 0; i < MAX_SOUND_DEVICES && sound_devices[i]; i++) {
  4285. if (!sound_devices[i]->prefix)
  4286. continue;
  4287. int prefixlen = _tcslen(sound_devices[i]->prefix);
  4288. int tmplen = _tcslen(tmpbuf);
  4289. if (prefixlen > 0 && tmplen >= prefixlen &&
  4290. !_tcsncmp(sound_devices[i]->prefix, tmpbuf, prefixlen) &&
  4291. ((tmplen > prefixlen && tmpbuf[prefixlen] == ':')
  4292. || tmplen == prefixlen)) {
  4293. p->win32_soundcard = i;
  4294. break;
  4295. }
  4296. }
  4297. }
  4298. if (p->win32_soundcard < 0)
  4299. p->win32_soundcard = num;
  4300. return 1;
  4301. }
  4302. if (cfgfile_string (option, value, _T("samplersoundcardname"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
  4303. int i, num;
  4304. num = p->win32_samplersoundcard;
  4305. p->win32_samplersoundcard = -1;
  4306. for (i = 0; i < MAX_SOUND_DEVICES && record_devices[i]; i++) {
  4307. if (i < num)
  4308. continue;
  4309. if (!_tcscmp (record_devices[i]->cfgname, tmpbuf)) {
  4310. p->win32_samplersoundcard = i;
  4311. break;
  4312. }
  4313. }
  4314. if (p->win32_samplersoundcard < 0) {
  4315. for (i = 0; i < MAX_SOUND_DEVICES && record_devices[i]; i++) {
  4316. if (!_tcscmp (record_devices[i]->cfgname, tmpbuf)) {
  4317. p->win32_samplersoundcard = i;
  4318. break;
  4319. }
  4320. }
  4321. }
  4322. return 1;
  4323. }
  4324. if (cfgfile_string (option, value, _T("rtg_vblank"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
  4325. if (!_tcscmp (tmpbuf, _T("real"))) {
  4326. p->win32_rtgvblankrate = -1;
  4327. return 1;
  4328. }
  4329. if (!_tcscmp (tmpbuf, _T("disabled"))) {
  4330. p->win32_rtgvblankrate = -2;
  4331. return 1;
  4332. }
  4333. if (!_tcscmp (tmpbuf, _T("chipset"))) {
  4334. p->win32_rtgvblankrate = 0;
  4335. return 1;
  4336. }
  4337. p->win32_rtgvblankrate = _tstol (tmpbuf);
  4338. return 1;
  4339. }
  4340. if (cfgfile_string (option, value, _T("rtg_scale_aspect_ratio"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
  4341. int v1, v2;
  4342. TCHAR *s;
  4343. p->win32_rtgscaleaspectratio = -1;
  4344. v1 = _tstol (tmpbuf);
  4345. s = _tcschr (tmpbuf, ':');
  4346. if (s) {
  4347. v2 = _tstol (s + 1);
  4348. if (v1 < 0 || v2 < 0)
  4349. p->win32_rtgscaleaspectratio = -1;
  4350. else if (v1 == 0 || v2 == 0)
  4351. p->win32_rtgscaleaspectratio = 0;
  4352. else
  4353. p->win32_rtgscaleaspectratio = v1 * ASPECTMULT + v2;
  4354. }
  4355. return 1;
  4356. }
  4357. if (cfgfile_strval (option, value, _T("uaescsimode"), &p->win32_uaescsimode, scsimode, 0)) {
  4358. // force SCSIEMU if pre 2.3 configuration
  4359. if (p->config_version < ((2 << 16) | (3 << 8)))
  4360. p->win32_uaescsimode = UAESCSI_CDEMU;
  4361. return 1;
  4362. }
  4363. if (cfgfile_strval (option, value, _T("statusbar"), &p->win32_statusbar, statusbarmode, 0))
  4364. return 1;
  4365. if (cfgfile_intval (option, value, _T("active_priority"), &v, 1) || cfgfile_intval (option, value, _T("activepriority"), &v, 1)) {
  4366. p->win32_active_capture_priority = fetchpri (v, 1);
  4367. p->win32_active_nocapture_pause = false;
  4368. p->win32_active_nocapture_nosound = false;
  4369. return 1;
  4370. }
  4371. #if 0
  4372. if (cfgfile_intval (option, value, _T("active_not_captured_priority"), &v, 1)) {
  4373. p->win32_active_nocapture_priority = fetchpri (v, 1);
  4374. return 1;
  4375. }
  4376. #endif
  4377. if (cfgfile_yesno(option, value, _T("active_capture_automatically"), &p->win32_capture_always))
  4378. return 1;
  4379. if (cfgfile_intval (option, value, _T("inactive_priority"), &v, 1)) {
  4380. p->win32_inactive_priority = fetchpri (v, 1);
  4381. return 1;
  4382. }
  4383. if (cfgfile_intval (option, value, _T("iconified_priority"), &v, 1)) {
  4384. p->win32_iconified_priority = fetchpri (v, 2);
  4385. return 1;
  4386. }
  4387. if (cfgfile_yesno (option, value, _T("inactive_iconify"), &p->win32_minimize_inactive))
  4388. return 1;
  4389. if (cfgfile_yesno (option, value, _T("start_iconified"), &p->win32_start_minimized))
  4390. return 1;
  4391. if (cfgfile_yesno (option, value, _T("start_not_captured"), &p->win32_start_uncaptured))
  4392. return 1;
  4393. if (cfgfile_string_escape(option, value, _T("serial_port"), &p->sername[0], 256)) {
  4394. sernametodev (p->sername);
  4395. if (p->sername[0])
  4396. p->use_serial = 1;
  4397. else
  4398. p->use_serial = 0;
  4399. return 1;
  4400. }
  4401. if (cfgfile_string_escape(option, value, _T("parallel_port"), &p->prtname[0], 256)) {
  4402. if (!_tcscmp (p->prtname, _T("none")))
  4403. p->prtname[0] = 0;
  4404. if (!_tcscmp (p->prtname, _T("default"))) {
  4405. p->prtname[0] = 0;
  4406. DWORD size = 256;
  4407. GetDefaultPrinter (p->prtname, &size);
  4408. }
  4409. return 1;
  4410. }
  4411. if (cfgfile_string_escape(option, value, _T("midiout_device_name"), tmpbuf, 256)) {
  4412. p->win32_midioutdev = -2;
  4413. if (!_tcsicmp (tmpbuf, _T("default")) || (midioutportinfo[0] && !_tcsicmp (tmpbuf, midioutportinfo[0]->name)))
  4414. p->win32_midioutdev = -1;
  4415. for (int i = 0; i < MAX_MIDI_PORTS && midioutportinfo[i]; i++) {
  4416. if (!_tcsicmp (midioutportinfo[i]->name, tmpbuf)) {
  4417. p->win32_midioutdev = midioutportinfo[i]->devid;
  4418. }
  4419. }
  4420. return 1;
  4421. }
  4422. if (cfgfile_string_escape(option, value, _T("midiin_device_name"), tmpbuf, 256)) {
  4423. p->win32_midiindev = -1;
  4424. for (int i = 0; i < MAX_MIDI_PORTS && midiinportinfo[i]; i++) {
  4425. if (!_tcsicmp (midiinportinfo[i]->name, tmpbuf)) {
  4426. p->win32_midiindev = midiinportinfo[i]->devid;
  4427. }
  4428. }
  4429. return 1;
  4430. }
  4431. i = 0;
  4432. while (obsolete[i]) {
  4433. if (!strcasecmp (obsolete[i], option)) {
  4434. write_log (_T("obsolete config entry '%s'\n"), option);
  4435. return 1;
  4436. }
  4437. i++;
  4438. }
  4439. return 0;
  4440. }
  4441. static void createdir (const TCHAR *path)
  4442. {
  4443. CreateDirectory (path, NULL);
  4444. }
  4445. void fetch_saveimagepath (TCHAR *out, int size, int dir)
  4446. {
  4447. fetch_path (_T("SaveimagePath"), out, size);
  4448. if (dir) {
  4449. out[_tcslen (out) - 1] = 0;
  4450. createdir (out);
  4451. fetch_path (_T("SaveimagePath"), out, size);
  4452. }
  4453. }
  4454. void fetch_configurationpath (TCHAR *out, int size)
  4455. {
  4456. fetch_path (_T("ConfigurationPath"), out, size);
  4457. }
  4458. void fetch_luapath (TCHAR *out, int size)
  4459. {
  4460. fetch_path (_T("LuaPath"), out, size);
  4461. }
  4462. void fetch_screenshotpath (TCHAR *out, int size)
  4463. {
  4464. fetch_path (_T("ScreenshotPath"), out, size);
  4465. }
  4466. void fetch_ripperpath (TCHAR *out, int size)
  4467. {
  4468. fetch_path (_T("RipperPath"), out, size);
  4469. }
  4470. void fetch_statefilepath (TCHAR *out, int size)
  4471. {
  4472. fetch_path (_T("StatefilePath"), out, size);
  4473. }
  4474. void fetch_inputfilepath (TCHAR *out, int size)
  4475. {
  4476. fetch_path (_T("InputPath"), out, size);
  4477. }
  4478. void fetch_datapath (TCHAR *out, int size)
  4479. {
  4480. fetch_path (NULL, out, size);
  4481. }
  4482. void fetch_rompath (TCHAR *out, int size)
  4483. {
  4484. fetch_path (_T("KickstartPath"), out, size);
  4485. }
  4486. static int isfilesindir (const TCHAR *p)
  4487. {
  4488. WIN32_FIND_DATA fd;
  4489. HANDLE h;
  4490. TCHAR path[MAX_DPATH];
  4491. int i = 0;
  4492. DWORD v;
  4493. v = GetFileAttributes (p);
  4494. if (v == INVALID_FILE_ATTRIBUTES || !(v & FILE_ATTRIBUTE_DIRECTORY))
  4495. return 0;
  4496. _tcscpy (path, p);
  4497. _tcscat (path, _T("\\*.*"));
  4498. h = FindFirstFile (path, &fd);
  4499. if (h != INVALID_HANDLE_VALUE) {
  4500. for (i = 0; i < 3; i++) {
  4501. if (!FindNextFile (h, &fd))
  4502. break;
  4503. }
  4504. FindClose (h);
  4505. }
  4506. if (i == 3)
  4507. return 1;
  4508. return 0;
  4509. }
  4510. void fetch_path (const TCHAR *name, TCHAR *out, int size)
  4511. {
  4512. int size2 = size;
  4513. _tcscpy (out, start_path_data);
  4514. if (!name) {
  4515. fullpath (out, size);
  4516. return;
  4517. }
  4518. if (!_tcscmp (name, _T("FloppyPath")))
  4519. _tcscat (out, _T("..\\shared\\adf\\"));
  4520. if (!_tcscmp (name, _T("CDPath")))
  4521. _tcscat (out, _T("..\\shared\\cd\\"));
  4522. if (!_tcscmp (name, _T("TapePath")))
  4523. _tcscat (out, _T("..\\shared\\tape\\"));
  4524. if (!_tcscmp (name, _T("hdfPath")))
  4525. _tcscat (out, _T("..\\shared\\hdf\\"));
  4526. if (!_tcscmp (name, _T("KickstartPath")))
  4527. _tcscat (out, _T("..\\shared\\rom\\"));
  4528. if (!_tcscmp (name, _T("ConfigurationPath")))
  4529. _tcscat (out, _T("Configurations\\"));
  4530. if (!_tcscmp (name, _T("LuaPath")))
  4531. _tcscat (out, _T("lua\\"));
  4532. if (!_tcscmp (name, _T("StatefilePath")))
  4533. _tcscat (out, _T("Savestates\\"));
  4534. if (!_tcscmp (name, _T("InputPath")))
  4535. _tcscat (out, _T("Inputrecordings\\"));
  4536. if (start_data >= 0)
  4537. regquerystr (NULL, name, out, &size);
  4538. if (GetFileAttributes (out) == INVALID_FILE_ATTRIBUTES)
  4539. _tcscpy (out, start_path_data);
  4540. #if 0
  4541. if (out[0] == '\\' && (_tcslen (out) >= 2 && out[1] != '\\')) { /* relative? */
  4542. _tcscpy (out, start_path_data);
  4543. if (start_data >= 0) {
  4544. size2 -= _tcslen (out);
  4545. regquerystr (NULL, name, out, &size2);
  4546. }
  4547. }
  4548. #endif
  4549. stripslashes (out);
  4550. if (!_tcscmp (name, _T("KickstartPath"))) {
  4551. DWORD v = GetFileAttributes (out);
  4552. if (v == INVALID_FILE_ATTRIBUTES || !(v & FILE_ATTRIBUTE_DIRECTORY))
  4553. _tcscpy (out, start_path_data);
  4554. }
  4555. fixtrailing (out);
  4556. fullpath (out, size2);
  4557. }
  4558. int get_rom_path (TCHAR *out, pathtype mode)
  4559. {
  4560. TCHAR tmp[MAX_DPATH];
  4561. tmp[0] = 0;
  4562. switch (mode)
  4563. {
  4564. case PATH_TYPE_DEFAULT:
  4565. {
  4566. if (!_tcscmp (start_path_data, start_path_exe))
  4567. _tcscpy (tmp, _T(".\\"));
  4568. else
  4569. _tcscpy (tmp, start_path_data);
  4570. if (GetFileAttributes (tmp) != INVALID_FILE_ATTRIBUTES) {
  4571. TCHAR tmp2[MAX_DPATH];
  4572. _tcscpy (tmp2, tmp);
  4573. _tcscat (tmp2, _T("rom"));
  4574. if (GetFileAttributes (tmp2) != INVALID_FILE_ATTRIBUTES) {
  4575. _tcscpy (tmp, tmp2);
  4576. } else {
  4577. _tcscpy (tmp2, tmp);
  4578. _tcscpy (tmp2, _T("roms"));
  4579. if (GetFileAttributes (tmp2) != INVALID_FILE_ATTRIBUTES) {
  4580. _tcscpy (tmp, tmp2);
  4581. } else {
  4582. if (!get_rom_path (tmp, PATH_TYPE_NEWAF)) {
  4583. if (!get_rom_path (tmp, PATH_TYPE_AMIGAFOREVERDATA)) {
  4584. _tcscpy (tmp, start_path_data);
  4585. }
  4586. }
  4587. }
  4588. }
  4589. }
  4590. }
  4591. break;
  4592. case PATH_TYPE_NEWAF:
  4593. {
  4594. TCHAR tmp2[MAX_DPATH];
  4595. _tcscpy (tmp2, start_path_new1);
  4596. _tcscat (tmp2, _T("..\\system\\rom"));
  4597. if (isfilesindir (tmp2)) {
  4598. _tcscpy (tmp, tmp2);
  4599. break;
  4600. }
  4601. _tcscpy (tmp2, start_path_new1);
  4602. _tcscat (tmp2, _T("..\\shared\\rom"));
  4603. if (isfilesindir (tmp2)) {
  4604. _tcscpy (tmp, tmp2);
  4605. break;
  4606. }
  4607. }
  4608. break;
  4609. case PATH_TYPE_AMIGAFOREVERDATA:
  4610. {
  4611. TCHAR tmp2[MAX_DPATH];
  4612. _tcscpy (tmp2, start_path_new2);
  4613. _tcscat (tmp2, _T("system\\rom"));
  4614. if (isfilesindir (tmp2)) {
  4615. _tcscpy (tmp, tmp2);
  4616. break;
  4617. }
  4618. _tcscpy (tmp2, start_path_new2);
  4619. _tcscat (tmp2, _T("shared\\rom"));
  4620. if (isfilesindir (tmp2)) {
  4621. _tcscpy (tmp, tmp2);
  4622. break;
  4623. }
  4624. }
  4625. break;
  4626. default:
  4627. return -1;
  4628. }
  4629. if (isfilesindir (tmp)) {
  4630. _tcscpy (out, tmp);
  4631. fixtrailing (out);
  4632. }
  4633. if (out[0]) {
  4634. fullpath (out, MAX_DPATH);
  4635. }
  4636. return out[0] ? 1 : 0;
  4637. }
  4638. void set_path (const TCHAR *name, TCHAR *path, pathtype mode)
  4639. {
  4640. TCHAR tmp[MAX_DPATH];
  4641. if (!path) {
  4642. if (!_tcscmp (start_path_data, start_path_exe))
  4643. _tcscpy (tmp, _T(".\\"));
  4644. else
  4645. _tcscpy (tmp, start_path_data);
  4646. if (!_tcscmp (name, _T("KickstartPath")))
  4647. _tcscat (tmp, _T("Roms"));
  4648. if (!_tcscmp (name, _T("ConfigurationPath")))
  4649. _tcscat (tmp, _T("Configurations"));
  4650. if (!_tcscmp (name, _T("LuaPath")))
  4651. _tcscat (tmp, _T("lua"));
  4652. if (!_tcscmp (name, _T("ScreenshotPath")))
  4653. _tcscat (tmp, _T("Screenshots"));
  4654. if (!_tcscmp (name, _T("StatefilePath")))
  4655. _tcscat (tmp, _T("Savestates"));
  4656. if (!_tcscmp (name, _T("SaveimagePath")))
  4657. _tcscat (tmp, _T("SaveImages"));
  4658. if (!_tcscmp (name, _T("InputPath")))
  4659. _tcscat (tmp, _T("Inputrecordings"));
  4660. } else {
  4661. _tcscpy (tmp, path);
  4662. }
  4663. stripslashes (tmp);
  4664. if (!_tcscmp (name, _T("KickstartPath"))) {
  4665. DWORD v = GetFileAttributes (tmp);
  4666. if (v == INVALID_FILE_ATTRIBUTES || !(v & FILE_ATTRIBUTE_DIRECTORY))
  4667. get_rom_path (tmp, PATH_TYPE_DEFAULT);
  4668. if (mode == PATH_TYPE_NEWAF) {
  4669. get_rom_path (tmp, PATH_TYPE_NEWAF);
  4670. } else if (mode == PATH_TYPE_AMIGAFOREVERDATA) {
  4671. get_rom_path (tmp, PATH_TYPE_AMIGAFOREVERDATA);
  4672. }
  4673. }
  4674. fixtrailing (tmp);
  4675. fullpath (tmp, sizeof tmp / sizeof (TCHAR));
  4676. regsetstr (NULL, name, tmp);
  4677. }
  4678. void set_path (const TCHAR *name, TCHAR *path)
  4679. {
  4680. set_path (name, path, PATH_TYPE_DEFAULT);
  4681. }
  4682. static void initpath (const TCHAR *name, TCHAR *path)
  4683. {
  4684. if (regexists (NULL, name))
  4685. return;
  4686. set_path (name, NULL);
  4687. }
  4688. static void romlist_add2 (const TCHAR *path, struct romdata *rd)
  4689. {
  4690. if (getregmode ()) {
  4691. int ok = 0;
  4692. TCHAR tmp[MAX_DPATH];
  4693. if (path[0] == '/' || path[0] == '\\')
  4694. ok = 1;
  4695. if (_tcslen (path) > 1 && path[1] == ':')
  4696. ok = 1;
  4697. if (!ok) {
  4698. _tcscpy (tmp, start_path_exe);
  4699. _tcscat (tmp, path);
  4700. romlist_add (tmp, rd);
  4701. return;
  4702. }
  4703. }
  4704. romlist_add (path, rd);
  4705. }
  4706. extern int scan_roms (HWND, int);
  4707. void read_rom_list (void)
  4708. {
  4709. TCHAR tmp2[1000];
  4710. int idx, idx2;
  4711. UAEREG *fkey;
  4712. TCHAR tmp[1000];
  4713. int size, size2, exists;
  4714. romlist_clear ();
  4715. exists = regexiststree (NULL, _T("DetectedROMs"));
  4716. fkey = regcreatetree (NULL, _T("DetectedROMs"));
  4717. if (fkey == NULL)
  4718. return;
  4719. if (!exists || forceroms) {
  4720. load_keyring (NULL, NULL);
  4721. scan_roms (NULL, forceroms ? 0 : 1);
  4722. }
  4723. forceroms = 0;
  4724. idx = 0;
  4725. for (;;) {
  4726. size = sizeof (tmp) / sizeof (TCHAR);
  4727. size2 = sizeof (tmp2) / sizeof (TCHAR);
  4728. if (!regenumstr (fkey, idx, tmp, &size, tmp2, &size2))
  4729. break;
  4730. if (_tcslen (tmp) == 7 || _tcslen (tmp) == 13) {
  4731. int group = 0;
  4732. int subitem = 0;
  4733. idx2 = _tstol (tmp + 4);
  4734. if (_tcslen (tmp) == 13) {
  4735. group = _tstol (tmp + 8);
  4736. subitem = _tstol (tmp + 11);
  4737. }
  4738. if (idx2 >= 0 && _tcslen (tmp2) > 0) {
  4739. struct romdata *rd = getromdatabyidgroup (idx2, group, subitem);
  4740. if (rd) {
  4741. TCHAR *s = _tcschr (tmp2, '\"');
  4742. if (s && _tcslen (s) > 1) {
  4743. TCHAR *s2 = my_strdup (s + 1);
  4744. s = _tcschr (s2, '\"');
  4745. if (s)
  4746. *s = 0;
  4747. romlist_add2 (s2, rd);
  4748. xfree (s2);
  4749. } else {
  4750. romlist_add2 (tmp2, rd);
  4751. }
  4752. }
  4753. }
  4754. }
  4755. idx++;
  4756. }
  4757. romlist_add (NULL, NULL);
  4758. regclosetree (fkey);
  4759. }
  4760. static int parseversion (TCHAR **vs)
  4761. {
  4762. TCHAR tmp[10];
  4763. int i;
  4764. i = 0;
  4765. while (**vs >= '0' && **vs <= '9') {
  4766. if (i >= sizeof (tmp) / sizeof (TCHAR))
  4767. return 0;
  4768. tmp[i++] = **vs;
  4769. (*vs)++;
  4770. }
  4771. if (**vs == '.')
  4772. (*vs)++;
  4773. tmp[i] = 0;
  4774. return _tstol (tmp);
  4775. }
  4776. static int checkversion (TCHAR *vs, int *verp)
  4777. {
  4778. int ver;
  4779. if (_tcslen (vs) < 10)
  4780. return 0;
  4781. if (_tcsncmp (vs, _T("WinUAE "), 7))
  4782. return 0;
  4783. vs += 7;
  4784. ver = parseversion (&vs) << 16;
  4785. ver |= parseversion (&vs) << 8;
  4786. ver |= parseversion (&vs);
  4787. if (verp)
  4788. *verp = ver;
  4789. if (ver >= ((UAEMAJOR << 16) | (UAEMINOR << 8) | UAESUBREV))
  4790. return 0;
  4791. return 1;
  4792. }
  4793. static int shell_deassociate (const TCHAR *extension)
  4794. {
  4795. HKEY rkey;
  4796. const TCHAR *progid = _T("WinUAE");
  4797. int def = !_tcscmp (extension, _T(".uae"));
  4798. TCHAR rpath1[MAX_DPATH], rpath2[MAX_DPATH], progid2[MAX_DPATH];
  4799. UAEREG *fkey;
  4800. if (extension == NULL || _tcslen (extension) < 1 || extension[0] != '.')
  4801. return 0;
  4802. _tcscpy (progid2, progid);
  4803. _tcscat (progid2, extension);
  4804. if (os_admin > 1)
  4805. rkey = HKEY_LOCAL_MACHINE;
  4806. else
  4807. rkey = HKEY_CURRENT_USER;
  4808. _tcscpy (rpath1, _T("Software\\Classes\\"));
  4809. _tcscpy (rpath2, rpath1);
  4810. _tcscat (rpath2, extension);
  4811. RegDeleteKey (rkey, rpath2);
  4812. _tcscpy (rpath2, rpath1);
  4813. _tcscat (rpath2, progid);
  4814. if (!def)
  4815. _tcscat (rpath2, extension);
  4816. SHDeleteKey (rkey, rpath2);
  4817. fkey = regcreatetree (NULL, _T("FileAssociations"));
  4818. regdelete (fkey, extension);
  4819. regclosetree (fkey);
  4820. return 1;
  4821. }
  4822. static int shell_associate_2 (const TCHAR *extension, const TCHAR *shellcommand, const TCHAR *command, struct contextcommand *cc, const TCHAR *perceivedtype,
  4823. const TCHAR *description, const TCHAR *ext2, int icon)
  4824. {
  4825. TCHAR rpath1[MAX_DPATH], rpath2[MAX_DPATH], progid2[MAX_DPATH];
  4826. HKEY rkey, key1, key2;
  4827. DWORD disposition;
  4828. const TCHAR *progid = _T("WinUAE");
  4829. int def = !_tcscmp (extension, _T(".uae"));
  4830. const TCHAR *defprogid;
  4831. UAEREG *fkey;
  4832. if (!icon)
  4833. icon = IDI_APPICON;
  4834. _tcscpy (progid2, progid);
  4835. _tcscat (progid2, ext2 ? ext2 : extension);
  4836. if (os_admin > 1)
  4837. rkey = HKEY_LOCAL_MACHINE;
  4838. else
  4839. rkey = HKEY_CURRENT_USER;
  4840. defprogid = def ? progid : progid2;
  4841. _tcscpy (rpath1, _T("Software\\Classes\\"));
  4842. _tcscpy (rpath2, rpath1);
  4843. _tcscat (rpath2, extension);
  4844. if (RegCreateKeyEx (rkey, rpath2, 0, NULL, REG_OPTION_NON_VOLATILE,
  4845. KEY_WRITE | KEY_READ, NULL, &key1, &disposition) == ERROR_SUCCESS) {
  4846. RegSetValueEx (key1, _T(""), 0, REG_SZ, (CONST BYTE *)defprogid, (_tcslen (defprogid) + 1) * sizeof (TCHAR));
  4847. if (perceivedtype)
  4848. RegSetValueEx (key1, _T("PerceivedType"), 0, REG_SZ, (CONST BYTE *)perceivedtype, (_tcslen (perceivedtype) + 1) * sizeof (TCHAR));
  4849. RegCloseKey (key1);
  4850. }
  4851. _tcscpy (rpath2, rpath1);
  4852. _tcscat (rpath2, progid);
  4853. if (!def)
  4854. _tcscat (rpath2, ext2 ? ext2 : extension);
  4855. if (description) {
  4856. if (RegCreateKeyEx (rkey, rpath2, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &key1, &disposition) == ERROR_SUCCESS) {
  4857. TCHAR tmp[MAX_DPATH];
  4858. RegSetValueEx (key1, _T(""), 0, REG_SZ, (CONST BYTE *)description, (_tcslen (description) + 1) * sizeof (TCHAR));
  4859. RegSetValueEx (key1, _T("AppUserModelID"), 0, REG_SZ, (CONST BYTE *)WINUAEAPPNAME, (_tcslen (WINUAEAPPNAME) + 1) * sizeof (TCHAR));
  4860. _tcscpy (tmp, rpath2);
  4861. _tcscat (tmp, _T("\\CurVer"));
  4862. if (RegCreateKeyEx (rkey, tmp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &key2, &disposition) == ERROR_SUCCESS) {
  4863. RegSetValueEx (key2, _T(""), 0, REG_SZ, (CONST BYTE *)defprogid, (_tcslen (defprogid) + 1) * sizeof (TCHAR));
  4864. RegCloseKey (key2);
  4865. }
  4866. if (icon) {
  4867. _tcscpy (tmp, rpath2);
  4868. _tcscat (tmp, _T("\\DefaultIcon"));
  4869. if (RegCreateKeyEx (rkey, tmp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &key2, &disposition) == ERROR_SUCCESS) {
  4870. _stprintf (tmp, _T("%s,%d"), executable_path, -icon);
  4871. RegSetValueEx (key2, _T(""), 0, REG_SZ, (CONST BYTE *)tmp, (_tcslen (tmp) + 1) * sizeof (TCHAR));
  4872. RegCloseKey (key2);
  4873. }
  4874. }
  4875. RegCloseKey (key1);
  4876. }
  4877. }
  4878. cc = NULL;
  4879. struct contextcommand ccs[2];
  4880. memset (ccs, 0, sizeof ccs);
  4881. if ((command || shellcommand)) {
  4882. ccs[0].command = command;
  4883. ccs[0].shellcommand = shellcommand;
  4884. ccs[0].icon = IDI_APPICON;
  4885. cc = &ccs[0];
  4886. }
  4887. if (cc) {
  4888. TCHAR path2[MAX_DPATH];
  4889. for (int i = 0; cc[i].command; i++) {
  4890. _tcscpy (path2, rpath2);
  4891. _tcscat (path2, _T("\\shell\\"));
  4892. if (cc[i].shellcommand)
  4893. _tcscat (path2, cc[i].shellcommand);
  4894. else
  4895. _tcscat (path2, _T("open"));
  4896. if (cc[i].icon) {
  4897. if (RegCreateKeyEx (rkey, path2, 0, NULL, REG_OPTION_NON_VOLATILE,
  4898. KEY_WRITE | KEY_READ, NULL, &key1, &disposition) == ERROR_SUCCESS) {
  4899. TCHAR tmp[MAX_DPATH];
  4900. _stprintf (tmp, _T("%s,%d"), executable_path, -cc[i].icon);
  4901. RegSetValueEx (key1, _T("Icon"), 0, REG_SZ, (CONST BYTE *)tmp, (_tcslen (tmp) + 1) * sizeof (TCHAR));
  4902. RegCloseKey (key1);
  4903. }
  4904. }
  4905. _tcscat (path2, _T("\\command"));
  4906. if (RegCreateKeyEx (rkey, path2, 0, NULL, REG_OPTION_NON_VOLATILE,
  4907. KEY_WRITE | KEY_READ, NULL, &key1, &disposition) == ERROR_SUCCESS) {
  4908. TCHAR path[MAX_DPATH];
  4909. _stprintf (path, _T("\"%sWinUAE.exe\" %s"), start_path_exe, cc[i].command);
  4910. RegSetValueEx (key1, _T(""), 0, REG_SZ, (CONST BYTE *)path, (_tcslen (path) + 1) * sizeof (TCHAR));
  4911. RegCloseKey (key1);
  4912. }
  4913. }
  4914. }
  4915. fkey = regcreatetree (NULL, _T("FileAssociations"));
  4916. regsetstr (fkey, extension, _T(""));
  4917. regclosetree (fkey);
  4918. return 1;
  4919. }
  4920. static int shell_associate (const TCHAR *extension, const TCHAR *command, struct contextcommand *cc, const TCHAR *perceivedtype, const TCHAR *description, const TCHAR *ext2, int icon)
  4921. {
  4922. int v = shell_associate_2 (extension, NULL, command, cc, perceivedtype, description, ext2, icon);
  4923. if (!_tcscmp (extension, _T(".uae")))
  4924. shell_associate_2 (extension, _T("edit"), _T("-f \"%1\" -s use_gui=yes"), NULL, _T("text"), description, NULL, icon);
  4925. return v;
  4926. }
  4927. static int shell_associate_is (const TCHAR *extension)
  4928. {
  4929. TCHAR rpath1[MAX_DPATH], rpath2[MAX_DPATH];
  4930. TCHAR progid2[MAX_DPATH], tmp[MAX_DPATH];
  4931. DWORD size;
  4932. HKEY rkey, key1;
  4933. const TCHAR *progid = _T("WinUAE");
  4934. int def = !_tcscmp (extension, _T(".uae"));
  4935. _tcscpy (progid2, progid);
  4936. _tcscat (progid2, extension);
  4937. if (os_admin > 1)
  4938. rkey = HKEY_LOCAL_MACHINE;
  4939. else
  4940. rkey = HKEY_CURRENT_USER;
  4941. _tcscpy (rpath1, _T("Software\\Classes\\"));
  4942. _tcscpy (rpath2, rpath1);
  4943. _tcscat (rpath2, extension);
  4944. size = sizeof tmp / sizeof (TCHAR);
  4945. if (RegOpenKeyEx (rkey, rpath2, 0, KEY_READ, &key1) == ERROR_SUCCESS) {
  4946. if (RegQueryValueEx (key1, NULL, NULL, NULL, (LPBYTE)tmp, &size) == ERROR_SUCCESS) {
  4947. if (_tcscmp (tmp, def ? progid : progid2)) {
  4948. RegCloseKey (key1);
  4949. return 0;
  4950. }
  4951. }
  4952. RegCloseKey (key1);
  4953. }
  4954. _tcscpy (rpath2, rpath1);
  4955. _tcscat (rpath2, progid);
  4956. if (!def)
  4957. _tcscat (rpath2, extension);
  4958. if (RegOpenKeyEx (rkey, rpath2, 0, KEY_READ, &key1) == ERROR_SUCCESS) {
  4959. RegCloseKey (key1);
  4960. return 1;
  4961. }
  4962. return 0;
  4963. }
  4964. static struct contextcommand cc_cd[] = {
  4965. { _T("CDTV"), _T("-cdimage=\"%1\" -s use_gui=no -cfgparam=quickstart=CDTV,0"), IDI_APPICON },
  4966. { _T("CD32"), _T("-cdimage=\"%1\" -s use_gui=no -cfgparam=quickstart=CD32,0"), IDI_APPICON },
  4967. { NULL }
  4968. };
  4969. static struct contextcommand cc_disk[] = {
  4970. { _T("A500"), _T("-0 \"%1\" -s use_gui=no -cfgparam=quickstart=A500,0"), IDI_DISKIMAGE },
  4971. { _T("A1200"), _T("-0 \"%1\" -s use_gui=no -cfgparam=quickstart=A1200,0"), IDI_DISKIMAGE },
  4972. { NULL }
  4973. };
  4974. struct assext exts[] = {
  4975. // { _T(".cue"), _T("-cdimage=\"%1\" -s use_gui=no"), _T("WinUAE CD image"), IDI_DISKIMAGE, cc_cd },
  4976. // { _T(".iso"), _T("-cdimage=\"%1\" -s use_gui=no"), _T("WinUAE CD image"), IDI_DISKIMAGE, cc_cd },
  4977. // { _T(".ccd"), _T("-cdimage=\"%1\" -s use_gui=no"), _T("WinUAE CD image"), IDI_DISKIMAGE, cc_cd },
  4978. { _T(".uae"), _T("-f \"%1\""), _T("WinUAE configuration file"), IDI_CONFIGFILE, NULL },
  4979. { _T(".adf"), _T("-0 \"%1\" -s use_gui=no"), _T("WinUAE floppy disk image"), IDI_DISKIMAGE, cc_disk },
  4980. { _T(".adz"), _T("-0 \"%1\" -s use_gui=no"), _T("WinUAE floppy disk image"), IDI_DISKIMAGE, cc_disk },
  4981. { _T(".dms"), _T("-0 \"%1\" -s use_gui=no"), _T("WinUAE floppy disk image"), IDI_DISKIMAGE, cc_disk },
  4982. { _T(".fdi"), _T("-0 \"%1\" -s use_gui=no"), _T("WinUAE floppy disk image"), IDI_DISKIMAGE, cc_disk },
  4983. { _T(".ipf"), _T("-0 \"%1\" -s use_gui=no"), _T("WinUAE floppy disk image"), IDI_DISKIMAGE, cc_disk },
  4984. { _T(".uss"), _T("-s statefile=\"%1\" -s use_gui=no"), _T("WinUAE statefile"), IDI_APPICON, NULL },
  4985. { NULL }
  4986. };
  4987. static void associate_init_extensions (void)
  4988. {
  4989. int i;
  4990. for (i = 0; exts[i].ext; i++) {
  4991. exts[i].enabled = 0;
  4992. if (shell_associate_is (exts[i].ext))
  4993. exts[i].enabled = 1;
  4994. }
  4995. if (rp_param || inipath)
  4996. return;
  4997. // associate .uae by default when running for the first time
  4998. if (!regexiststree (NULL, _T("FileAssociations"))) {
  4999. UAEREG *fkey;
  5000. if (exts[0].enabled == 0) {
  5001. shell_associate (exts[0].ext, exts[0].cmd, exts[0].cc, NULL, exts[0].desc, NULL, exts[0].icon);
  5002. exts[0].enabled = shell_associate_is (exts[0].ext);
  5003. }
  5004. fkey = regcreatetree (NULL, _T("FileAssociations"));
  5005. regsetstr (fkey, exts[0].ext, _T(""));
  5006. regclosetree (fkey);
  5007. }
  5008. if (os_admin > 1) {
  5009. DWORD disposition;
  5010. TCHAR rpath[MAX_DPATH];
  5011. HKEY rkey = HKEY_LOCAL_MACHINE;
  5012. HKEY key1;
  5013. bool setit = true;
  5014. _tcscpy (rpath, _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\winuae.exe"));
  5015. if (RegOpenKeyEx (rkey, rpath, 0, KEY_READ, &key1) == ERROR_SUCCESS) {
  5016. TCHAR tmp[MAX_DPATH];
  5017. DWORD size = sizeof tmp / sizeof (TCHAR);
  5018. if (RegQueryValueEx (key1, NULL, NULL, NULL, (LPBYTE)tmp, &size) == ERROR_SUCCESS) {
  5019. if (!_tcsicmp (tmp, executable_path))
  5020. setit = false;
  5021. }
  5022. RegCloseKey (key1);
  5023. }
  5024. if (setit) {
  5025. if (RegCreateKeyEx (rkey, rpath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &key1, &disposition) == ERROR_SUCCESS) {
  5026. DWORD val = 1;
  5027. RegSetValueEx (key1, _T(""), 0, REG_SZ, (CONST BYTE *)executable_path, (_tcslen (executable_path) + 1) * sizeof (TCHAR));
  5028. RegSetValueEx (key1, _T("UseUrl"), 0, REG_DWORD, (LPBYTE)&val, sizeof val);
  5029. _tcscpy (rpath, start_path_exe);
  5030. rpath[_tcslen (rpath) - 1] = 0;
  5031. RegSetValueEx (key1, _T("Path"), 0, REG_SZ, (CONST BYTE *)rpath, (_tcslen (rpath) + 1) * sizeof (TCHAR));
  5032. RegCloseKey (key1);
  5033. SHChangeNotify (SHCNE_ASSOCCHANGED, 0, 0, 0);
  5034. }
  5035. }
  5036. }
  5037. #if 0
  5038. UAEREG *fkey;
  5039. fkey = regcreatetree (NULL, _T("FileAssociations"));
  5040. if (fkey) {
  5041. int ok = 1;
  5042. TCHAR tmp[MAX_DPATH];
  5043. _tcscpy (tmp, _T("Following file associations:\n"));
  5044. for (i = 0; exts[i].ext; i++) {
  5045. TCHAR tmp2[10];
  5046. int size = sizeof tmp;
  5047. int is1 = exts[i].enabled;
  5048. int is2 = regquerystr (fkey, exts[i].ext, tmp2, &size);
  5049. if (is1 == 0 && is2 != 0) {
  5050. _tcscat (tmp, exts[i].ext);
  5051. _tcscat (tmp, _T("\n"));
  5052. ok = 0;
  5053. }
  5054. }
  5055. if (!ok) {
  5056. TCHAR szTitle[MAX_DPATH];
  5057. WIN32GUI_LoadUIString (IDS_ERRORTITLE, szTitle, MAX_DPATH);
  5058. _tcscat (szTitle, BetaStr);
  5059. if (MessageBox (NULL, tmp, szTitle, MB_YESNO | MB_TASKMODAL) == IDOK) {
  5060. for (i = 0; exts[i].ext; i++) {
  5061. TCHAR tmp2[10];
  5062. int size = sizeof tmp;
  5063. int is1 = exts[i].enabled;
  5064. int is2 = regquerystr (fkey, exts[i].ext, tmp2, &size);
  5065. if (is1 == 0 && is2 != 0) {
  5066. regdelete (fkey, exts[i].ext);
  5067. shell_associate (exts[i].ext, exts[i].cmd, NULL, exts[i].desc, NULL);
  5068. exts[i].enabled = shell_associate_is (exts[i].ext);
  5069. }
  5070. }
  5071. } else {
  5072. for (i = 0; exts[i].ext; i++) {
  5073. if (!exts[i].enabled)
  5074. regdelete (fkey, exts[i].ext);
  5075. }
  5076. }
  5077. }
  5078. }
  5079. #endif
  5080. }
  5081. void associate_file_extensions (void)
  5082. {
  5083. int i;
  5084. int modified = 0;
  5085. if (rp_param)
  5086. return;
  5087. for (i = 0; exts[i].ext; i++) {
  5088. int already = shell_associate_is (exts[i].ext);
  5089. if (exts[i].enabled == 0 && already) {
  5090. shell_deassociate (exts[i].ext);
  5091. exts[i].enabled = shell_associate_is (exts[i].ext);
  5092. if (exts[i].enabled) {
  5093. modified = 1;
  5094. shell_associate (exts[i].ext, exts[i].cmd, exts[i].cc, NULL, exts[i].desc, NULL, exts[i].icon);
  5095. }
  5096. } else if (exts[i].enabled) {
  5097. shell_associate (exts[i].ext, exts[i].cmd, exts[i].cc, NULL, exts[i].desc, NULL, exts[i].icon);
  5098. exts[i].enabled = shell_associate_is (exts[i].ext);
  5099. if (exts[i].enabled != already)
  5100. modified = 1;
  5101. }
  5102. }
  5103. if (modified)
  5104. SHChangeNotify (SHCNE_ASSOCCHANGED, 0, 0, 0);
  5105. }
  5106. static bool resetgui_pending;
  5107. static void resetgui(void)
  5108. {
  5109. regdelete(NULL, _T("GUIPosX"));
  5110. regdelete(NULL, _T("GUIPosY"));
  5111. regdelete(NULL, _T("GUIPosFWX"));
  5112. regdelete(NULL, _T("GUIPosFWY"));
  5113. regdelete(NULL, _T("GUIPosFSX"));
  5114. regdelete(NULL, _T("GUIPosFSY"));
  5115. regdelete(NULL, _T("GUISizeX"));
  5116. regdelete(NULL, _T("GUISizeY"));
  5117. regdelete(NULL, _T("GUISizeFWX"));
  5118. regdelete(NULL, _T("GUISizeFWY"));
  5119. regdelete(NULL, _T("GUISizeFSX"));
  5120. regdelete(NULL, _T("GUISizeFSY"));
  5121. regdelete(NULL, _T("GUIFont"));
  5122. regdelete(NULL, _T("GUIListFont"));
  5123. UAEREG *key = regcreatetree(NULL, _T("ListViews"));
  5124. if (key) {
  5125. for (int i = 1; i <= 10; i++) {
  5126. TCHAR buf[100];
  5127. _stprintf(buf, _T("LV_%d"), i);
  5128. regdelete(key, buf);
  5129. }
  5130. regclosetree(key);
  5131. }
  5132. resetgui_pending = false;
  5133. }
  5134. static void target_load_debugger_config(void)
  5135. {
  5136. int size;
  5137. disasm_flags = DISASM_FLAG_LC_MNEMO | DISASM_FLAG_LC_REG | DISASM_FLAG_LC_SIZE | DISASM_FLAG_LC_HEX | DISASM_FLAG_CC | DISASM_FLAG_EA | DISASM_FLAG_VAL | DISASM_FLAG_WORDS;
  5138. disasm_min_words = 5;
  5139. disasm_max_words = 16;
  5140. disasm_hexprefix[0] = '$';
  5141. disasm_hexprefix[1] = 0;
  5142. UAEREG *fkey = regcreatetree(NULL, _T("Debugger"));
  5143. if (fkey) {
  5144. regqueryint(fkey, _T("Disasm_flags"), &disasm_flags);
  5145. regqueryint(fkey, _T("Disasm_min_words"), &disasm_min_words);
  5146. regqueryint(fkey, _T("Disasm_max_words"), &disasm_max_words);
  5147. size = sizeof(disasm_hexprefix) / sizeof(TCHAR);
  5148. regquerystr(fkey, _T("Hex_prefix"), disasm_hexprefix, &size);
  5149. regclosetree(fkey);
  5150. }
  5151. }
  5152. static void target_save_debugger_config(void)
  5153. {
  5154. if (!debugger_used) {
  5155. return;
  5156. }
  5157. UAEREG *fkey = regcreatetree(NULL, _T("Debugger"));
  5158. if (fkey) {
  5159. regsetint(fkey, _T("Disasm_flags"), disasm_flags);
  5160. regsetint(fkey, _T("Disasm_min_words"), disasm_min_words);
  5161. regsetint(fkey, _T("Disasm_max_words"), disasm_max_words);
  5162. regsetstr(fkey, _T("Hex_prefix"), disasm_hexprefix);
  5163. regclosetree(fkey);
  5164. }
  5165. }
  5166. static void WIN32_HandleRegistryStuff (void)
  5167. {
  5168. RGBFTYPE colortype = RGBFB_NONE;
  5169. DWORD dwType = REG_DWORD;
  5170. DWORD dwDisplayInfoSize = sizeof (colortype);
  5171. int size;
  5172. TCHAR path[MAX_DPATH] = _T("");
  5173. TCHAR tmp[MAX_DPATH];
  5174. TCHAR version[100];
  5175. initpath (_T("FloppyPath"), start_path_data);
  5176. initpath (_T("KickstartPath"), start_path_data);
  5177. initpath (_T("hdfPath"), start_path_data);
  5178. initpath (_T("ConfigurationPath"), start_path_data);
  5179. initpath (_T("LuaPath"), start_path_data);
  5180. initpath (_T("ScreenshotPath"), start_path_data);
  5181. initpath (_T("StatefilePath"), start_path_data);
  5182. initpath (_T("SaveimagePath"), start_path_data);
  5183. initpath (_T("VideoPath"), start_path_data);
  5184. initpath (_T("InputPath"), start_path_data);
  5185. size = sizeof(version) / sizeof(TCHAR);
  5186. if (regquerystr(NULL, _T("Version"), version, &size)) {
  5187. int ver = 0;
  5188. if (checkversion(version, &ver)) {
  5189. regsetstr(NULL, _T("Version"), VersionStr);
  5190. // Reset GUI setting if pre-4.3.0
  5191. if (ver > 0x030000 && ver < 0x040300) {
  5192. resetgui_pending = true;
  5193. }
  5194. }
  5195. } else {
  5196. regsetstr(NULL, _T("Version"), VersionStr);
  5197. }
  5198. if (resetgui_pending) {
  5199. resetgui();
  5200. }
  5201. if (!regexists (NULL, _T("MainPosX")) || !regexists (NULL, _T("GUIPosX"))) {
  5202. int x = GetSystemMetrics (SM_CXSCREEN);
  5203. int y = GetSystemMetrics (SM_CYSCREEN);
  5204. int dpi = getdpiformonitor(NULL);
  5205. x = (x - (800 * dpi / 96)) / 2;
  5206. y = (y - (600 * dpi / 96)) / 2;
  5207. if (x < 10)
  5208. x = 10;
  5209. if (y < 10)
  5210. y = 10;
  5211. /* Create and initialize all our sub-keys to the default values */
  5212. regsetint (NULL, _T("MainPosX"), x);
  5213. regsetint (NULL, _T("MainPosY"), y);
  5214. regsetint (NULL, _T("GUIPosX"), x);
  5215. regsetint (NULL, _T("GUIPosY"), y);
  5216. }
  5217. size = sizeof (version) / sizeof (TCHAR);
  5218. if (regquerystr (NULL, _T("ROMCheckVersion"), version, &size)) {
  5219. if (checkversion (version, NULL)) {
  5220. if (regsetstr (NULL, _T("ROMCheckVersion"), VersionStr))
  5221. forceroms = 1;
  5222. }
  5223. } else {
  5224. if (regsetstr (NULL, _T("ROMCheckVersion"), VersionStr))
  5225. forceroms = 1;
  5226. }
  5227. regqueryint (NULL, _T("DirectDraw_Secondary"), &ddforceram);
  5228. if (regexists (NULL, _T("SoundDriverMask"))) {
  5229. regqueryint (NULL, _T("SoundDriverMask"), &sounddrivermask);
  5230. } else {
  5231. sounddrivermask = 3;
  5232. regsetint (NULL, _T("SoundDriverMask"), sounddrivermask);
  5233. }
  5234. if (regexists (NULL, _T("RecursiveROMScan")))
  5235. regqueryint (NULL, _T("RecursiveROMScan"), &recursiveromscan);
  5236. else
  5237. regsetint (NULL, _T("RecursiveROMScan"), recursiveromscan);
  5238. if (regexists (NULL, _T("ConfigurationCache")))
  5239. regqueryint (NULL, _T("ConfigurationCache"), &configurationcache);
  5240. else
  5241. regsetint (NULL, _T("ConfigurationCache"), configurationcache);
  5242. if (regexists(NULL, _T("ArtCache")))
  5243. regqueryint(NULL, _T("ArtCache"), &artcache);
  5244. else
  5245. regsetint(NULL, _T("ArtCache"), artcache);
  5246. if (regexists(NULL, _T("ArtImageCount")))
  5247. regqueryint(NULL, _T("ArtImageCount"), &max_visible_boxart_images);
  5248. else
  5249. regsetint(NULL, _T("ArtImageCount"), max_visible_boxart_images);
  5250. if (regexists(NULL, _T("ArtImageWidth")))
  5251. regqueryint(NULL, _T("ArtImageWidth"), &stored_boxart_window_width);
  5252. else
  5253. regsetint(NULL, _T("ArtImageWidth"), stored_boxart_window_width);
  5254. if (regexists(NULL, _T("ArtImageWidthFS")))
  5255. regqueryint(NULL, _T("ArtImageWidthFS"), &stored_boxart_window_width_fsgui);
  5256. else
  5257. regsetint(NULL, _T("ArtImageWidthFS"), stored_boxart_window_width_fsgui);
  5258. if (regexists (NULL, _T("SaveImageOriginalPath")))
  5259. regqueryint (NULL, _T("SaveImageOriginalPath"), &saveimageoriginalpath);
  5260. else
  5261. regsetint (NULL, _T("SaveImageOriginalPath"), saveimageoriginalpath);
  5262. if (regexists (NULL, _T("RelativePaths")))
  5263. regqueryint (NULL, _T("RelativePaths"), &relativepaths);
  5264. else
  5265. regsetint (NULL, _T("RelativePaths"), relativepaths);
  5266. if (!regqueryint (NULL, _T("QuickStartMode"), &quickstart))
  5267. quickstart = 1;
  5268. tmp[0] = 0;
  5269. size = sizeof(tmp) / sizeof(TCHAR);
  5270. if (regquerystr(NULL, _T("FloppyBridge"), tmp, &size)) {
  5271. char *c = ua(tmp);
  5272. floppybridge_set_config(c);
  5273. xfree(c);
  5274. }
  5275. reopen_console ();
  5276. fetch_path (_T("ConfigurationPath"), path, sizeof (path) / sizeof (TCHAR));
  5277. if (path[0])
  5278. path[_tcslen (path) - 1] = 0;
  5279. if (GetFileAttributes (path) == 0xffffffff) {
  5280. TCHAR path2[MAX_DPATH];
  5281. _tcscpy (path2, path);
  5282. createdir (path);
  5283. _tcscat (path, _T("\\Host"));
  5284. createdir (path);
  5285. _tcscpy (path, path2);
  5286. _tcscat (path, _T("\\Hardware"));
  5287. createdir (path);
  5288. }
  5289. fetch_path (_T("StatefilePath"), path, sizeof (path) / sizeof (TCHAR));
  5290. createdir (path);
  5291. _tcscat (path, _T("default.uss"));
  5292. _tcscpy (savestate_fname, path);
  5293. fetch_path (_T("InputPath"), path, sizeof (path) / sizeof (TCHAR));
  5294. createdir (path);
  5295. regclosetree (read_disk_history (HISTORY_FLOPPY));
  5296. regclosetree (read_disk_history (HISTORY_CD));
  5297. associate_init_extensions ();
  5298. read_rom_list ();
  5299. load_keyring (NULL, NULL);
  5300. target_load_debugger_config();
  5301. }
  5302. #if WINUAEPUBLICBETA > 0
  5303. static const TCHAR *BETAMESSAGE = {
  5304. _T("This is unstable beta software. Click cancel if you are not comfortable using software that is incomplete and can have serious programming errors.")
  5305. };
  5306. #endif
  5307. static int betamessage (void)
  5308. {
  5309. #if WINUAEPUBLICBETA > 0
  5310. int showmsg = TRUE;
  5311. HANDLE h = INVALID_HANDLE_VALUE;
  5312. ULONGLONG regft64;
  5313. ULARGE_INTEGER ft64;
  5314. ULARGE_INTEGER sft64;
  5315. struct tm *t;
  5316. __int64 ltime;
  5317. DWORD dwType, size;
  5318. #ifdef _WIN64
  5319. const TCHAR *tokenname = _T("BetaToken64");
  5320. #else
  5321. const TCHAR *tokenname = _T("BetaToken");
  5322. #endif
  5323. ft64.QuadPart = 0;
  5324. for (;;) {
  5325. FILETIME ft, sft;
  5326. SYSTEMTIME st;
  5327. TCHAR tmp1[MAX_DPATH];
  5328. if (!hWinUAEKey)
  5329. break;
  5330. if (GetModuleFileName (NULL, tmp1, sizeof tmp1 / sizeof (TCHAR)) == 0)
  5331. break;
  5332. h = CreateFile (tmp1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  5333. if (h == INVALID_HANDLE_VALUE)
  5334. break;
  5335. if (GetFileTime (h, &ft, NULL, NULL) == 0)
  5336. break;
  5337. ft64.LowPart = ft.dwLowDateTime;
  5338. ft64.HighPart = ft.dwHighDateTime;
  5339. dwType = REG_QWORD;
  5340. size = sizeof regft64;
  5341. if (!regquerylonglong (NULL, tokenname, &regft64))
  5342. break;
  5343. GetSystemTime(&st);
  5344. SystemTimeToFileTime(&st, &sft);
  5345. sft64.LowPart = sft.dwLowDateTime;
  5346. sft64.HighPart = sft.dwHighDateTime;
  5347. if (ft64.QuadPart == regft64)
  5348. showmsg = FALSE;
  5349. /* complain again in 7 days */
  5350. if (sft64.QuadPart > regft64 + (ULONGLONG)1000000000 * 60 * 60 * 24 * 7)
  5351. showmsg = TRUE;
  5352. break;
  5353. }
  5354. if (h != INVALID_HANDLE_VALUE)
  5355. CloseHandle (h);
  5356. if (showmsg) {
  5357. int r, data;
  5358. TCHAR title[MAX_DPATH];
  5359. dwType = REG_DWORD;
  5360. size = sizeof data;
  5361. if (regqueryint (NULL, _T("Beta_Just_Shut_Up"), &data)) {
  5362. if (data == 68000 + 10) {
  5363. write_log (_T("I was told to shut up :(\n"));
  5364. return 1;
  5365. }
  5366. }
  5367. _time64 (&ltime);
  5368. t = _gmtime64 (&ltime);
  5369. /* "expire" in 1 month */
  5370. if (MAKEBD(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday) > WINUAEDATE + 100)
  5371. pre_gui_message (_T("This beta build of WinUAE is obsolete.\nPlease download newer version."));
  5372. _tcscpy (title, _T("WinUAE Public Beta Disclaimer"));
  5373. _tcscat (title, BetaStr);
  5374. r = MessageBox (NULL, BETAMESSAGE, title, MB_OKCANCEL | MB_TASKMODAL | MB_SETFOREGROUND | MB_ICONWARNING | MB_DEFBUTTON2);
  5375. if (r == IDABORT || r == IDCANCEL)
  5376. return 0;
  5377. if (ft64.QuadPart > 0) {
  5378. regft64 = ft64.QuadPart;
  5379. regsetlonglong (NULL, tokenname, regft64);
  5380. }
  5381. }
  5382. #endif
  5383. return 1;
  5384. }
  5385. int os_admin, os_64bit, os_win7, os_win8, os_win10, os_vista, cpu_number, os_touch;
  5386. BOOL os_dwm_enabled;
  5387. BOOL dpi_aware_v2;
  5388. static int isadminpriv (void)
  5389. {
  5390. DWORD i, dwSize = 0, dwResult = 0;
  5391. HANDLE hToken;
  5392. PTOKEN_GROUPS pGroupInfo;
  5393. BYTE sidBuffer[100];
  5394. PSID pSID = (PSID)&sidBuffer;
  5395. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  5396. int isadmin = 0;
  5397. // Open a handle to the access token for the calling process.
  5398. if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &hToken)) {
  5399. write_log (_T("OpenProcessToken Error %u\n"), GetLastError ());
  5400. return FALSE;
  5401. }
  5402. // Call GetTokenInformation to get the buffer size.
  5403. if(!GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize)) {
  5404. dwResult = GetLastError ();
  5405. if(dwResult != ERROR_INSUFFICIENT_BUFFER) {
  5406. write_log (_T("GetTokenInformation Error %u\n"), dwResult);
  5407. return FALSE;
  5408. }
  5409. }
  5410. // Allocate the buffer.
  5411. pGroupInfo = (PTOKEN_GROUPS)GlobalAlloc (GPTR, dwSize);
  5412. // Call GetTokenInformation again to get the group information.
  5413. if (!GetTokenInformation (hToken, TokenGroups, pGroupInfo, dwSize, &dwSize)) {
  5414. write_log (_T("GetTokenInformation Error %u\n"), GetLastError ());
  5415. return FALSE;
  5416. }
  5417. // Create a SID for the BUILTIN\Administrators group.
  5418. if (!AllocateAndInitializeSid (&SIDAuth, 2,
  5419. SECURITY_BUILTIN_DOMAIN_RID,
  5420. DOMAIN_ALIAS_RID_ADMINS,
  5421. 0, 0, 0, 0, 0, 0,
  5422. &pSID)) {
  5423. write_log (_T("AllocateAndInitializeSid Error %u\n"), GetLastError ());
  5424. return FALSE;
  5425. }
  5426. // Loop through the group SIDs looking for the administrator SID.
  5427. for(i = 0; i < pGroupInfo->GroupCount; i++) {
  5428. if (EqualSid (pSID, pGroupInfo->Groups[i].Sid))
  5429. isadmin = 1;
  5430. }
  5431. if (pSID)
  5432. FreeSid (pSID);
  5433. if (pGroupInfo)
  5434. GlobalFree (pGroupInfo);
  5435. return isadmin;
  5436. }
  5437. typedef void (CALLBACK* PGETNATIVESYSTEMINFO)(LPSYSTEM_INFO);
  5438. typedef BOOL (CALLBACK* PISUSERANADMIN)(VOID);
  5439. static int osdetect (void)
  5440. {
  5441. PGETNATIVESYSTEMINFO pGetNativeSystemInfo;
  5442. PISUSERANADMIN pIsUserAnAdmin;
  5443. pGetNativeSystemInfo = (PGETNATIVESYSTEMINFO)GetProcAddress(kerneldll, "GetNativeSystemInfo");
  5444. pIsUserAnAdmin = (PISUSERANADMIN)GetProcAddress(
  5445. GetModuleHandle(_T("shell32.dll")), "IsUserAnAdmin");
  5446. GetSystemInfo (&SystemInfo);
  5447. if (pGetNativeSystemInfo)
  5448. pGetNativeSystemInfo (&SystemInfo);
  5449. osVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  5450. if (GetVersionEx (&osVersion)) {
  5451. if (osVersion.dwMajorVersion >= 6)
  5452. os_vista = 1;
  5453. if (osVersion.dwMajorVersion >= 7 || (osVersion.dwMajorVersion == 6 && osVersion.dwMinorVersion >= 1))
  5454. os_win7 = 1;
  5455. if (osVersion.dwMajorVersion >= 7 || (osVersion.dwMajorVersion == 6 && osVersion.dwMinorVersion >= 2))
  5456. os_win8 = 1;
  5457. if (osVersion.dwMajorVersion >= 7 || (osVersion.dwMajorVersion == 6 && osVersion.dwMinorVersion >= 3))
  5458. os_win8 = 2;
  5459. if (osVersion.dwMajorVersion >= 10)
  5460. os_win10 = 1;
  5461. if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
  5462. os_64bit = 1;
  5463. }
  5464. cpu_number = SystemInfo.dwNumberOfProcessors;
  5465. os_admin = isadminpriv ();
  5466. if (os_admin) {
  5467. if (pIsUserAnAdmin) {
  5468. if (pIsUserAnAdmin ())
  5469. os_admin++;
  5470. } else {
  5471. os_admin++;
  5472. }
  5473. }
  5474. if (os_win7) {
  5475. int v = GetSystemMetrics(SM_DIGITIZER);
  5476. if (v & NID_READY) {
  5477. if (v & (NID_INTEGRATED_TOUCH | NID_INTEGRATED_PEN | NID_EXTERNAL_TOUCH | NID_EXTERNAL_PEN))
  5478. os_touch = 1;
  5479. }
  5480. }
  5481. if (os_vista) {
  5482. typedef HRESULT(CALLBACK* DWMISCOMPOSITIONENABLED)(BOOL*);
  5483. HMODULE dwmapihandle;
  5484. DWMISCOMPOSITIONENABLED pDwmIsCompositionEnabled;
  5485. dwmapihandle = LoadLibrary(_T("dwmapi.dll"));
  5486. if (dwmapihandle) {
  5487. pDwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED)GetProcAddress(dwmapihandle, "DwmIsCompositionEnabled");
  5488. if (pDwmIsCompositionEnabled) {
  5489. pDwmIsCompositionEnabled(&os_dwm_enabled);
  5490. }
  5491. FreeLibrary(dwmapihandle);
  5492. }
  5493. }
  5494. return 1;
  5495. }
  5496. void create_afnewdir (int remove)
  5497. {
  5498. TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH];
  5499. if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, tmp))) {
  5500. fixtrailing (tmp);
  5501. _tcscpy (tmp2, tmp);
  5502. _tcscat (tmp2, _T("Amiga Files"));
  5503. _tcscpy (tmp, tmp2);
  5504. _tcscat (tmp, _T("\\WinUAE"));
  5505. if (remove) {
  5506. DWORD attrs = GetFileAttributes(tmp);
  5507. if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) && !(attrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
  5508. RemoveDirectory (tmp);
  5509. RemoveDirectory (tmp2);
  5510. }
  5511. } else {
  5512. CreateDirectory (tmp2, NULL);
  5513. CreateDirectory (tmp, NULL);
  5514. }
  5515. }
  5516. }
  5517. static bool isdir (const TCHAR *path)
  5518. {
  5519. DWORD a = GetFileAttributes (path);
  5520. if (a == INVALID_FILE_ATTRIBUTES)
  5521. return false;
  5522. if (a & FILE_ATTRIBUTE_DIRECTORY)
  5523. return true;
  5524. return false;
  5525. }
  5526. bool get_plugin_path (TCHAR *out, int len, const TCHAR *path)
  5527. {
  5528. TCHAR tmp[MAX_DPATH];
  5529. _tcscpy (tmp, start_path_plugins);
  5530. if (path != NULL)
  5531. _tcscat (tmp, path);
  5532. if (isdir (tmp)) {
  5533. _tcscpy (out, tmp);
  5534. fixtrailing (out);
  5535. return true;
  5536. }
  5537. if (!_tcsicmp (path, _T("floppysounds"))) {
  5538. _tcscpy (tmp, start_path_data);
  5539. _tcscpy (tmp, _T("uae_data"));
  5540. if (isdir (tmp)) {
  5541. _tcscpy (out, tmp);
  5542. fixtrailing (out);
  5543. return true;
  5544. }
  5545. _tcscpy (tmp, start_path_exe);
  5546. _tcscpy (tmp, _T("uae_data"));
  5547. if (isdir (tmp)) {
  5548. _tcscpy (out, tmp);
  5549. fixtrailing (out);
  5550. return true;
  5551. }
  5552. }
  5553. _tcscpy (tmp, start_path_data);
  5554. _tcscpy (tmp, WIN32_PLUGINDIR);
  5555. if (path != NULL)
  5556. _tcscat (tmp, path);
  5557. if (isdir (tmp)) {
  5558. _tcscpy (out, tmp);
  5559. fixtrailing (out);
  5560. return true;
  5561. }
  5562. _tcscpy (tmp, start_path_exe);
  5563. _tcscpy (tmp, WIN32_PLUGINDIR);
  5564. if (path != NULL)
  5565. _tcscat (tmp, path);
  5566. if (isdir (tmp)) {
  5567. _tcscpy (out, tmp);
  5568. fixtrailing (out);
  5569. return true;
  5570. }
  5571. _tcscpy (out, start_path_plugins);
  5572. if (path != NULL)
  5573. _tcscat (tmp, path);
  5574. fixtrailing (out);
  5575. return false;
  5576. }
  5577. void setpathmode (pathtype pt)
  5578. {
  5579. TCHAR pathmode[32] = { 0 };
  5580. if (pt == PATH_TYPE_WINUAE)
  5581. _tcscpy (pathmode, _T("WinUAE"));
  5582. if (pt == PATH_TYPE_NEWWINUAE)
  5583. _tcscpy (pathmode, _T("WinUAE_2"));
  5584. if (pt == PATH_TYPE_NEWAF)
  5585. _tcscpy (pathmode, _T("AmigaForever"));
  5586. if (pt == PATH_TYPE_AMIGAFOREVERDATA)
  5587. _tcscpy (pathmode, _T("AMIGAFOREVERDATA"));
  5588. regsetstr (NULL, _T("PathMode"), pathmode);
  5589. }
  5590. static void getstartpaths (void)
  5591. {
  5592. TCHAR *posn, *p;
  5593. TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH], prevpath[MAX_DPATH];
  5594. DWORD v;
  5595. UAEREG *key;
  5596. TCHAR xstart_path_uae[MAX_DPATH], xstart_path_old[MAX_DPATH];
  5597. TCHAR xstart_path_new1[MAX_DPATH], xstart_path_new2[MAX_DPATH];
  5598. path_type = PATH_TYPE_DEFAULT;
  5599. prevpath[0] = 0;
  5600. xstart_path_uae[0] = xstart_path_old[0] = xstart_path_new1[0] = xstart_path_new2[0] = 0;
  5601. key = regcreatetree (NULL, NULL);
  5602. if (key) {
  5603. int size = sizeof (prevpath) / sizeof (TCHAR);
  5604. if (!regquerystr (key, _T("PathMode"), prevpath, &size))
  5605. prevpath[0] = 0;
  5606. regclosetree (key);
  5607. }
  5608. if (!_tcscmp (prevpath, _T("WinUAE")))
  5609. path_type = PATH_TYPE_WINUAE;
  5610. if (!_tcscmp (prevpath, _T("WinUAE_2")))
  5611. path_type = PATH_TYPE_NEWWINUAE;
  5612. if (!_tcscmp (prevpath, _T("AF2005")) || !_tcscmp (prevpath, _T("AmigaForever")))
  5613. path_type = PATH_TYPE_NEWAF;
  5614. if (!_tcscmp (prevpath, _T("AMIGAFOREVERDATA")))
  5615. path_type = PATH_TYPE_AMIGAFOREVERDATA;
  5616. _tcscpy(start_path_exe, executable_path);
  5617. if((posn = _tcsrchr (start_path_exe, '\\')))
  5618. posn[1] = 0;
  5619. if (path_type == PATH_TYPE_DEFAULT && inipath) {
  5620. path_type = PATH_TYPE_WINUAE;
  5621. _tcscpy (xstart_path_uae, start_path_exe);
  5622. relativepaths = 1;
  5623. } else if (path_type == PATH_TYPE_DEFAULT && start_data == 0 && key) {
  5624. bool ispath = false;
  5625. _tcscpy (tmp2, start_path_exe);
  5626. _tcscat (tmp2, _T("configurations\\configuration.cache"));
  5627. v = GetFileAttributes (tmp2);
  5628. if (v != INVALID_FILE_ATTRIBUTES && !(v & FILE_ATTRIBUTE_DIRECTORY))
  5629. ispath = true;
  5630. _tcscpy (tmp2, start_path_exe);
  5631. _tcscat (tmp2, _T("roms"));
  5632. v = GetFileAttributes (tmp2);
  5633. if (v != INVALID_FILE_ATTRIBUTES && (v & FILE_ATTRIBUTE_DIRECTORY))
  5634. ispath = true;
  5635. if (!ispath) {
  5636. if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, tmp))) {
  5637. GetFullPathName (tmp, sizeof tmp / sizeof (TCHAR), tmp2, NULL);
  5638. // installed in Program Files?
  5639. if (_tcsnicmp (tmp, tmp2, _tcslen (tmp)) == 0) {
  5640. if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, tmp))) {
  5641. fixtrailing (tmp);
  5642. _tcscpy (tmp2, tmp);
  5643. _tcscat (tmp2, _T("Amiga Files"));
  5644. CreateDirectory (tmp2, NULL);
  5645. _tcscat (tmp2, _T("\\WinUAE"));
  5646. CreateDirectory (tmp2, NULL);
  5647. v = GetFileAttributes (tmp2);
  5648. if (v != INVALID_FILE_ATTRIBUTES && (v & FILE_ATTRIBUTE_DIRECTORY)) {
  5649. _tcscat (tmp2, _T("\\"));
  5650. path_type = PATH_TYPE_NEWWINUAE;
  5651. _tcscpy (tmp, tmp2);
  5652. _tcscat (tmp, _T("Configurations"));
  5653. CreateDirectory (tmp, NULL);
  5654. _tcscpy (tmp, tmp2);
  5655. _tcscat (tmp, _T("Screenshots"));
  5656. CreateDirectory (tmp, NULL);
  5657. _tcscpy (tmp, tmp2);
  5658. _tcscat (tmp, _T("Savestates"));
  5659. CreateDirectory (tmp, NULL);
  5660. _tcscpy (tmp, tmp2);
  5661. _tcscat (tmp, _T("Screenshots"));
  5662. CreateDirectory (tmp, NULL);
  5663. }
  5664. }
  5665. }
  5666. }
  5667. }
  5668. }
  5669. _tcscpy (tmp, start_path_exe);
  5670. _tcscat (tmp, _T("roms"));
  5671. if (isfilesindir (tmp)) {
  5672. _tcscpy (xstart_path_uae, start_path_exe);
  5673. }
  5674. _tcscpy (tmp, start_path_exe);
  5675. _tcscat (tmp, _T("configurations"));
  5676. if (isfilesindir (tmp)) {
  5677. _tcscpy (xstart_path_uae, start_path_exe);
  5678. }
  5679. p = _wgetenv (_T("AMIGAFOREVERDATA"));
  5680. if (p) {
  5681. _tcscpy (tmp, p);
  5682. fixtrailing (tmp);
  5683. _tcscpy (start_path_new2, p);
  5684. v = GetFileAttributes (tmp);
  5685. if (v != INVALID_FILE_ATTRIBUTES && (v & FILE_ATTRIBUTE_DIRECTORY)) {
  5686. _tcscpy (xstart_path_new2, start_path_new2);
  5687. _tcscpy (xstart_path_new2, _T("WinUAE\\"));
  5688. af_path_2005 |= 2;
  5689. }
  5690. }
  5691. if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, tmp))) {
  5692. fixtrailing (tmp);
  5693. _tcscpy (tmp2, tmp);
  5694. _tcscat (tmp2, _T("Amiga Files\\"));
  5695. _tcscpy (tmp, tmp2);
  5696. _tcscat (tmp, _T("WinUAE"));
  5697. v = GetFileAttributes (tmp);
  5698. if (v != INVALID_FILE_ATTRIBUTES && (v & FILE_ATTRIBUTE_DIRECTORY)) {
  5699. TCHAR *p;
  5700. _tcscpy (xstart_path_new1, tmp2);
  5701. _tcscat (xstart_path_new1, _T("WinUAE\\"));
  5702. _tcscpy (xstart_path_uae, start_path_exe);
  5703. _tcscpy (start_path_new1, xstart_path_new1);
  5704. p = tmp2 + _tcslen (tmp2);
  5705. _tcscpy (p, _T("System"));
  5706. if (isfilesindir (tmp2)) {
  5707. af_path_2005 |= 1;
  5708. } else {
  5709. _tcscpy (p, _T("Shared"));
  5710. if (isfilesindir (tmp2)) {
  5711. af_path_2005 |= 1;
  5712. }
  5713. }
  5714. }
  5715. }
  5716. if (start_data == 0) {
  5717. start_data = 1;
  5718. if (path_type == PATH_TYPE_WINUAE && xstart_path_uae[0]) {
  5719. _tcscpy (start_path_data, xstart_path_uae);
  5720. } else if (path_type == PATH_TYPE_NEWWINUAE && xstart_path_new1[0]) {
  5721. _tcscpy (start_path_data, xstart_path_new1);
  5722. create_afnewdir (0);
  5723. } else if (path_type == PATH_TYPE_NEWAF && (af_path_2005 & 1) && xstart_path_new1[0]) {
  5724. _tcscpy (start_path_data, xstart_path_new1);
  5725. create_afnewdir (0);
  5726. } else if (path_type == PATH_TYPE_AMIGAFOREVERDATA && (af_path_2005 & 2) && xstart_path_new2[0]) {
  5727. _tcscpy (start_path_data, xstart_path_new2);
  5728. } else if (path_type == PATH_TYPE_DEFAULT) {
  5729. _tcscpy (start_path_data, xstart_path_uae);
  5730. if (af_path_2005 & 1) {
  5731. path_type = PATH_TYPE_NEWAF;
  5732. create_afnewdir (1);
  5733. _tcscpy (start_path_data, xstart_path_new1);
  5734. }
  5735. if (af_path_2005 & 2) {
  5736. _tcscpy (tmp, xstart_path_new2);
  5737. _tcscat (tmp, _T("system\\rom"));
  5738. if (isfilesindir (tmp)) {
  5739. path_type = PATH_TYPE_AMIGAFOREVERDATA;
  5740. } else {
  5741. _tcscpy (tmp, xstart_path_new2);
  5742. _tcscat (tmp, _T("shared\\rom"));
  5743. if (isfilesindir (tmp)) {
  5744. path_type = PATH_TYPE_AMIGAFOREVERDATA;
  5745. } else {
  5746. path_type = PATH_TYPE_NEWWINUAE;
  5747. }
  5748. }
  5749. _tcscpy (start_path_data, xstart_path_new2);
  5750. }
  5751. }
  5752. }
  5753. v = GetFileAttributes (start_path_data);
  5754. if (v == INVALID_FILE_ATTRIBUTES || !(v & FILE_ATTRIBUTE_DIRECTORY) || start_data == 0 || start_data == -2) {
  5755. _tcscpy (start_path_data, start_path_exe);
  5756. }
  5757. fixtrailing (start_path_data);
  5758. fullpath (start_path_data, sizeof start_path_data / sizeof (TCHAR));
  5759. SetCurrentDirectory (start_path_data);
  5760. // use path via command line?
  5761. if (!start_path_plugins[0]) {
  5762. // default path
  5763. _tcscpy (start_path_plugins, start_path_data);
  5764. _tcscat (start_path_plugins, WIN32_PLUGINDIR);
  5765. }
  5766. v = GetFileAttributes (start_path_plugins);
  5767. if (!start_path_plugins[0] || v == INVALID_FILE_ATTRIBUTES || !(v & FILE_ATTRIBUTE_DIRECTORY)) {
  5768. // not found, exe path?
  5769. _tcscpy (start_path_plugins, start_path_exe);
  5770. _tcscat (start_path_plugins, WIN32_PLUGINDIR);
  5771. v = GetFileAttributes (start_path_plugins);
  5772. if (v == INVALID_FILE_ATTRIBUTES || !(v & FILE_ATTRIBUTE_DIRECTORY))
  5773. _tcscpy (start_path_plugins, start_path_data); // not found, very default path
  5774. }
  5775. fixtrailing (start_path_plugins);
  5776. fullpath (start_path_plugins, sizeof start_path_plugins / sizeof (TCHAR));
  5777. setpathmode (path_type);
  5778. }
  5779. extern void test (void);
  5780. extern int screenshotmode, postscript_print_debugging, sound_debug, log_uaeserial, clipboard_debug;
  5781. extern int force_direct_catweasel, sound_mode_skip, maxmem;
  5782. extern int pngprint, log_sercon, midi_inbuflen;
  5783. extern int debug_rtg_blitter;
  5784. extern int log_bsd;
  5785. extern int inputdevice_logging;
  5786. extern int vsync_modechangetimeout;
  5787. extern int tablet_log;
  5788. extern int log_blitter;
  5789. extern int slirp_debug;
  5790. extern int fakemodewaitms;
  5791. extern float sound_sync_multiplier;
  5792. extern int log_cd32;
  5793. extern int log_ld;
  5794. extern int logitech_lcd;
  5795. extern uae_s64 max_avi_size;
  5796. extern int floppy_writemode;
  5797. extern DWORD_PTR cpu_affinity, cpu_paffinity;
  5798. static DWORD_PTR original_affinity = -1;
  5799. static int getval (const TCHAR *s)
  5800. {
  5801. int base = 10;
  5802. int v;
  5803. TCHAR *endptr;
  5804. if (s[0] == '0' && _totupper(s[1]) == 'X')
  5805. s += 2, base = 16;
  5806. v = _tcstol (s, &endptr, base);
  5807. if (*endptr != '\0' || *s == '\0')
  5808. return 0;
  5809. return v;
  5810. }
  5811. static uae_s64 getval64(const TCHAR *s)
  5812. {
  5813. int base = 10;
  5814. uae_s64 v;
  5815. TCHAR *endptr;
  5816. if (s[0] == '0' && _totupper(s[1]) == 'X')
  5817. s += 2, base = 16;
  5818. v = _wcstoui64(s, &endptr, base);
  5819. if (*endptr != '\0' || *s == '\0')
  5820. return 0;
  5821. return v;
  5822. }
  5823. #if 0
  5824. static float getvalf (const TCHAR *s)
  5825. {
  5826. TCHAR *endptr;
  5827. double v;
  5828. v = _tcstof (s, &endptr);
  5829. if (*endptr != '\0' || *s == '\0')
  5830. return 0;
  5831. return v;
  5832. }
  5833. #endif
  5834. static void makeverstr (TCHAR *s)
  5835. {
  5836. if (_tcslen (WINUAEBETA) > 0) {
  5837. _stprintf (BetaStr, _T(" (%sBeta %s, %d.%02d.%02d)"), WINUAEPUBLICBETA > 0 ? _T("Public ") : _T(""), WINUAEBETA,
  5838. GETBDY(WINUAEDATE), GETBDM(WINUAEDATE), GETBDD(WINUAEDATE));
  5839. #ifdef _WIN64
  5840. _tcscat (BetaStr, _T(" 64-bit"));
  5841. #endif
  5842. _stprintf (s, _T("WinUAE %d.%d.%d%s%s"),
  5843. UAEMAJOR, UAEMINOR, UAESUBREV, WINUAEREV, BetaStr);
  5844. } else {
  5845. _stprintf (s, _T("WinUAE %d.%d.%d%s (%d.%02d.%02d)"),
  5846. UAEMAJOR, UAEMINOR, UAESUBREV, WINUAEREV, GETBDY(WINUAEDATE), GETBDM(WINUAEDATE), GETBDD(WINUAEDATE));
  5847. #ifdef _WIN64
  5848. _tcscat (s, _T(" 64-bit"));
  5849. #endif
  5850. }
  5851. if (_tcslen (WINUAEEXTRA) > 0) {
  5852. _tcscat (s, _T(" "));
  5853. _tcscat (s, WINUAEEXTRA);
  5854. }
  5855. }
  5856. static TCHAR *getdefaultini (int *tempfile)
  5857. {
  5858. FILE *f;
  5859. TCHAR path[MAX_DPATH], orgpath[MAX_DPATH];
  5860. *tempfile = 0;
  5861. path[0] = 0;
  5862. if (!GetFullPathName (executable_path, sizeof path / sizeof (TCHAR), path, NULL))
  5863. _tcscpy (path, executable_path);
  5864. TCHAR *posn;
  5865. if((posn = _tcsrchr (path, '\\')))
  5866. posn[1] = 0;
  5867. _tcscat (path, _T("winuae.ini"));
  5868. _tcscpy (orgpath, path);
  5869. #if 1
  5870. f = _tfopen (path, _T("r+"));
  5871. if (f) {
  5872. fclose (f);
  5873. return my_strdup (path);
  5874. }
  5875. f = _tfopen (path, _T("w"));
  5876. if (f) {
  5877. fclose (f);
  5878. return my_strdup (path);
  5879. }
  5880. #endif
  5881. *tempfile = 1;
  5882. int v = GetTempPath (sizeof path / sizeof (TCHAR), path);
  5883. if (v == 0 || v > sizeof path / sizeof (TCHAR))
  5884. return my_strdup (orgpath);
  5885. _tcsncat (path, _T("winuae.ini"), sizeof path / sizeof (TCHAR) - _tcslen(path));
  5886. f = _tfopen (path, _T("w"));
  5887. if (f) {
  5888. fclose (f);
  5889. return my_strdup (path);
  5890. }
  5891. return my_strdup (orgpath);
  5892. }
  5893. static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2)
  5894. {
  5895. const TCHAR *arg = argx + 1;
  5896. if (argx[0] != '-' && argx[0] != '/')
  5897. return 0;
  5898. if (!_tcscmp(arg, _T("convert")) && np && np2) {
  5899. zfile_convertimage(np, np2);
  5900. return -1;
  5901. }
  5902. if (!_tcscmp(arg, _T("console"))) {
  5903. console_started = 1;
  5904. return 1;
  5905. }
  5906. if (!_tcscmp(arg, _T("cli"))) {
  5907. console_emulation = 1;
  5908. return 1;
  5909. }
  5910. if (!_tcscmp(arg, _T("log"))) {
  5911. console_logging = 1;
  5912. return 1;
  5913. }
  5914. if (!_tcscmp(arg, _T("logfile"))) {
  5915. winuaelog_temporary_enable = true;
  5916. return 1;
  5917. }
  5918. #ifdef FILESYS
  5919. if (!_tcscmp(arg, _T("rdbdump"))) {
  5920. do_rdbdump = 1;
  5921. return 1;
  5922. }
  5923. if (!_tcscmp(arg, _T("hddump"))) {
  5924. do_rdbdump = 2;
  5925. return 1;
  5926. }
  5927. if (!_tcscmp(arg, _T("disableharddrivesafetycheck"))) {
  5928. //harddrive_dangerous = 0x1234dead;
  5929. return 1;
  5930. }
  5931. if (!_tcscmp(arg, _T("noaspifiltering"))) {
  5932. //aspi_allow_all = 1;
  5933. return 1;
  5934. }
  5935. #endif
  5936. if (!_tcscmp(arg, _T("pngprint"))) {
  5937. pngprint = 1;
  5938. return 1;
  5939. }
  5940. if (!_tcscmp(arg, _T("norawinput"))) {
  5941. no_rawinput |= 4;
  5942. return 1;
  5943. }
  5944. if (!_tcscmp(arg, _T("norawinput_all"))) {
  5945. no_rawinput = 7;
  5946. return 1;
  5947. }
  5948. if (!_tcscmp(arg, _T("norawinput_keyboard"))) {
  5949. no_rawinput |= 1;
  5950. return 1;
  5951. }
  5952. if (!_tcscmp(arg, _T("norawinput_mouse"))) {
  5953. no_rawinput |= 2;
  5954. return 1;
  5955. }
  5956. if (!_tcscmp(arg, _T("nodirectinput"))) {
  5957. no_directinput = 1;
  5958. return 1;
  5959. }
  5960. if (!_tcscmp(arg, _T("nowindowsmouse"))) {
  5961. no_windowsmouse = 1;
  5962. return 1;
  5963. }
  5964. if (!_tcscmp(arg, _T("rawhid"))) {
  5965. rawinput_enabled_hid = 1;
  5966. return 1;
  5967. }
  5968. if (!_tcscmp(arg, _T("norawhid"))) {
  5969. rawinput_enabled_hid = 0;
  5970. return 1;
  5971. }
  5972. if (!_tcscmp(arg, _T("rawkeyboard"))) {
  5973. // obsolete
  5974. return 1;
  5975. }
  5976. if (!_tcscmp(arg, _T("winmouselog"))) {
  5977. log_winmouse = 1;
  5978. return 1;
  5979. }
  5980. if (!_tcscmp(arg, _T("directsound"))) {
  5981. force_directsound = 1;
  5982. return 1;
  5983. }
  5984. if (!_tcscmp(arg, _T("scsilog"))) {
  5985. log_scsi = 1;
  5986. return 1;
  5987. }
  5988. if (!_tcscmp(arg, _T("scsiemulog"))) {
  5989. extern int log_scsiemu;
  5990. log_scsiemu = 1;
  5991. return 1;
  5992. }
  5993. if (!_tcscmp(arg, _T("ds_partition_hdf"))) {
  5994. extern int enable_ds_partition_hdf;
  5995. enable_ds_partition_hdf = 1;
  5996. return 1;
  5997. }
  5998. if (!_tcscmp(arg, _T("filesyslog"))) {
  5999. log_filesys = 1;
  6000. return 1;
  6001. }
  6002. if (!_tcscmp(arg, _T("filesyslog2"))) {
  6003. log_filesys = 2;
  6004. return 1;
  6005. }
  6006. if (!_tcscmp(arg, _T("netlog"))) {
  6007. log_net = 1;
  6008. return 1;
  6009. }
  6010. if (!_tcscmp(arg, _T("serlog"))) {
  6011. log_sercon = 1;
  6012. return 1;
  6013. }
  6014. if (!_tcscmp(arg, _T("serlog2"))) {
  6015. log_sercon = 2;
  6016. return 1;
  6017. }
  6018. if (!_tcscmp(arg, _T("serlog3"))) {
  6019. log_sercon = 3;
  6020. return 1;
  6021. }
  6022. if (!_tcscmp(arg, _T("a2065log"))) {
  6023. log_a2065 = 1;
  6024. return 1;
  6025. }
  6026. if (!_tcscmp(arg, _T("a2065log2"))) {
  6027. log_a2065 = 2;
  6028. return 1;
  6029. }
  6030. if (!_tcscmp(arg, _T("a2065log3"))) {
  6031. log_a2065 = 3;
  6032. return 1;
  6033. }
  6034. if (!_tcscmp(arg, _T("a2065_promiscuous"))) {
  6035. a2065_promiscuous = 1;
  6036. return 1;
  6037. }
  6038. if (!_tcscmp(arg, _T("seriallog"))) {
  6039. log_uaeserial = 1;
  6040. return 1;
  6041. }
  6042. if (!_tcscmp(arg, _T("vsynclog")) || !_tcscmp(arg, _T("vsynclog1"))) {
  6043. log_vsync |= 1;
  6044. return 1;
  6045. }
  6046. if (!_tcscmp(arg, _T("vsynclog2"))) {
  6047. log_vsync |= 2;
  6048. return 1;
  6049. }
  6050. if (!_tcscmp(arg, _T("bsdlog"))) {
  6051. log_bsd = 1;
  6052. return 1;
  6053. }
  6054. if (!_tcscmp(arg, _T("clipboarddebug"))) {
  6055. clipboard_debug = 1;
  6056. return 1;
  6057. }
  6058. if (!_tcscmp(arg, _T("rplog"))) {
  6059. log_rp = 3;
  6060. return 1;
  6061. }
  6062. if (!_tcscmp(arg, _T("nomultidisplay"))) {
  6063. return 1;
  6064. }
  6065. if (!_tcscmp(arg, _T("legacypaths"))) {
  6066. start_data = -2;
  6067. return 1;
  6068. }
  6069. if (!_tcscmp(arg, _T("screenshotbmp"))) {
  6070. screenshotmode = 0;
  6071. return 1;
  6072. }
  6073. if (!_tcscmp(arg, _T("psprintdebug"))) {
  6074. postscript_print_debugging = 1;
  6075. return 1;
  6076. }
  6077. if (!_tcscmp(arg, _T("sounddebug"))) {
  6078. sound_debug = 1;
  6079. return 1;
  6080. }
  6081. if (!_tcscmp(arg, _T("directcatweasel"))) {
  6082. force_direct_catweasel = 1;
  6083. if (np) {
  6084. force_direct_catweasel = getval(np);
  6085. return 2;
  6086. }
  6087. return 1;
  6088. }
  6089. if (!_tcscmp(arg, _T("forcerdtsc"))) {
  6090. uae_time_use_rdtsc(true);
  6091. return 1;
  6092. }
  6093. if (!_tcscmp(arg, _T("ddsoftwarecolorkey"))) {
  6094. // obsolete
  6095. return 1;
  6096. }
  6097. if (!_tcscmp(arg, _T("nod3d9ex"))) {
  6098. D3DEX = 0;
  6099. return 1;
  6100. }
  6101. if (!_tcscmp(arg, _T("nod3d9shader"))) {
  6102. shaderon = 0;
  6103. return 1;
  6104. }
  6105. if (!_tcscmp(arg, _T("d3ddebug"))) {
  6106. d3ddebug = 1;
  6107. return 1;
  6108. }
  6109. if (!_tcscmp(arg, _T("logflush"))) {
  6110. extern int always_flush_log;
  6111. always_flush_log = 1;
  6112. return 1;
  6113. }
  6114. if (!_tcscmp(arg, _T("ahidebug"))) {
  6115. extern int ahi_debug;
  6116. ahi_debug = 2;
  6117. return 1;
  6118. }
  6119. if (!_tcscmp(arg, _T("ahidebug2"))) {
  6120. extern int ahi_debug;
  6121. ahi_debug = 3;
  6122. return 1;
  6123. }
  6124. if (!_tcscmp(arg, _T("quittogui"))) {
  6125. quit_to_gui = 1;
  6126. return 1;
  6127. }
  6128. if (!_tcscmp(arg, _T("ini")) && np) {
  6129. inipath = my_strdup(np);
  6130. return 2;
  6131. }
  6132. if (!_tcscmp(arg, _T("portable"))) {
  6133. int temp;
  6134. inipath = getdefaultini(&temp);
  6135. createbootlog = false;
  6136. return 1;
  6137. }
  6138. if (!_tcscmp(arg, _T("bootlog"))) {
  6139. createbootlog = true;
  6140. return 1;
  6141. }
  6142. if (!_tcscmp(arg, _T("nobootlog"))) {
  6143. createbootlog = false;
  6144. return 1;
  6145. }
  6146. if (!_tcscmp(arg, _T("cd32log"))) {
  6147. if (log_cd32 < 1)
  6148. log_cd32 = 1;
  6149. return 1;
  6150. }
  6151. if (!_tcscmp(arg, _T("cd32log2"))) {
  6152. if (log_cd32 < 2)
  6153. log_cd32 = 2;
  6154. return 1;
  6155. }
  6156. if (!_tcscmp(arg, _T("nolcd"))) {
  6157. logitech_lcd = 0;
  6158. return 1;
  6159. }
  6160. if (!_tcscmp(arg, _T("romlist"))) {
  6161. void dumpromlist(void);
  6162. dumpromlist();
  6163. return -1;
  6164. }
  6165. if (!_tcscmp(arg, _T("rawextadf"))) {
  6166. floppy_writemode = -1;
  6167. return 1;
  6168. }
  6169. if (!_tcscmp(arg, _T("busywait"))) {
  6170. busywait = 1;
  6171. return 1;
  6172. }
  6173. if (!_tcscmp(arg, _T("nontdelayexecution"))) {
  6174. noNtDelayExecution = 1;
  6175. return 1;
  6176. }
  6177. if (!_tcscmp(arg, _T("resetgui"))) {
  6178. resetgui_pending = true;
  6179. return 1;
  6180. }
  6181. if (!_tcscmp(arg, _T("nocrashdump"))) {
  6182. nocrashdump = 1;
  6183. return 1;
  6184. }
  6185. if (!np)
  6186. return 0;
  6187. #if 0
  6188. if (!_tcscmp (arg, _T("sound_adjust"))) {
  6189. sound_sync_multiplier = getvalf (np);
  6190. return 2;
  6191. }
  6192. #endif
  6193. if (!_tcscmp(arg, _T("max_avi_size"))) {
  6194. max_avi_size = getval64(np);
  6195. return 2;
  6196. }
  6197. if (!_tcscmp(arg, _T("ethlog"))) {
  6198. log_ethernet = getval(np);
  6199. return 2;
  6200. }
  6201. if (!_tcscmp (arg, _T("vsync_modechangetimeout"))) {
  6202. vsync_modechangetimeout = getval (np);
  6203. return 2;
  6204. }
  6205. if (!_tcscmp (arg, _T("rtg_blitter"))) {
  6206. debug_rtg_blitter = getval (np);
  6207. return 2;
  6208. }
  6209. if (!_tcscmp (arg, _T("vsync_min_delay"))) {
  6210. debug_vsync_min_delay = getval (np);
  6211. return 2;
  6212. }
  6213. if (!_tcscmp (arg, _T("vsync_forced_delay"))) {
  6214. debug_vsync_forced_delay = getval (np);
  6215. return 2;
  6216. }
  6217. if (!_tcscmp (arg, _T("threadedd3d"))) {
  6218. fakemodewaitms = getval (np);
  6219. return 2;
  6220. }
  6221. if (!_tcscmp (arg, _T("tabletlog"))) {
  6222. tablet_log = getval (np);
  6223. return 2;
  6224. }
  6225. if (!_tcscmp (arg, _T("blitterdebug"))) {
  6226. log_blitter = getval (np);
  6227. return 2;
  6228. }
  6229. if (!_tcscmp (arg, _T("inputlog"))) {
  6230. rawinput_log = getval (np);
  6231. return 2;
  6232. }
  6233. if (!_tcscmp (arg, _T("inputdevicelog"))) {
  6234. inputdevice_logging = getval (np);
  6235. return 2;
  6236. }
  6237. if (!_tcscmp (arg, _T("slirplog"))) {
  6238. slirp_debug = getval (np);
  6239. return 2;
  6240. }
  6241. if (!_tcscmp (arg, _T("ldlog"))) {
  6242. log_ld = getval (np);
  6243. return 2;
  6244. }
  6245. if (!_tcscmp (arg, _T("midiinbuffer"))) {
  6246. midi_inbuflen = getval (np);
  6247. if (midi_inbuflen < 16000)
  6248. midi_inbuflen = 16000;
  6249. return 2;
  6250. }
  6251. if (!_tcscmp (arg, _T("ddforcemode"))) {
  6252. extern int ddforceram;
  6253. ddforceram = getval (np);
  6254. if (ddforceram < 0 || ddforceram > 3)
  6255. ddforceram = 0;
  6256. return 2;
  6257. }
  6258. if (!_tcscmp (arg, _T("affinity"))) {
  6259. cpu_affinity = getval (np);
  6260. if (cpu_affinity == 0)
  6261. cpu_affinity = original_affinity;
  6262. SetThreadAffinityMask (GetCurrentThread (), cpu_affinity);
  6263. return 2;
  6264. }
  6265. if (!_tcscmp (arg, _T("paffinity"))) {
  6266. cpu_paffinity = getval (np);
  6267. if (cpu_paffinity == 0)
  6268. cpu_paffinity = original_affinity;
  6269. SetProcessAffinityMask (GetCurrentProcess (), cpu_paffinity);
  6270. return 2;
  6271. }
  6272. if (!_tcscmp (arg, _T("datapath"))) {
  6273. ExpandEnvironmentStrings (np, start_path_data, sizeof start_path_data / sizeof (TCHAR));
  6274. start_data = -1;
  6275. return 2;
  6276. }
  6277. if (!_tcscmp (arg, _T("pluginpath"))) {
  6278. ExpandEnvironmentStrings (np, start_path_plugins, sizeof start_path_plugins / sizeof (TCHAR));
  6279. return 2;
  6280. }
  6281. if (!_tcscmp (arg, _T("maxmem"))) {
  6282. maxmem = getval (np);
  6283. return 2;
  6284. }
  6285. if (!_tcscmp (arg, _T("soundmodeskip"))) {
  6286. sound_mode_skip = getval (np);
  6287. return 2;
  6288. }
  6289. if (!_tcscmp (arg, _T("p96skipmode"))) {
  6290. extern int p96skipmode;
  6291. p96skipmode = getval (np);
  6292. return 2;
  6293. }
  6294. if (!_tcscmp (arg, _T("minidumpmode"))) {
  6295. minidumpmode = (MINIDUMP_TYPE)getval (np);
  6296. return 2;
  6297. }
  6298. if (!_tcscmp (arg, _T("jitevent"))) {
  6299. pissoff_value = getval (np) * CYCLE_UNIT;
  6300. return 2;
  6301. }
  6302. if (!_tcscmp (arg, _T("inputrecorddebug"))) {
  6303. inputrecord_debug = getval (np);
  6304. return 2;
  6305. }
  6306. if (!_tcscmp(arg, _T("extraframewait"))) {
  6307. extraframewait = getval(np);
  6308. return 2;
  6309. }
  6310. if (!_tcscmp(arg, _T("extraframewait_us"))) {
  6311. extraframewait2 = getval(np);
  6312. return 2;
  6313. }
  6314. if (!_tcscmp (arg, _T("framelatency"))) {
  6315. forcedframelatency = getval (np);
  6316. return 2;
  6317. }
  6318. #ifdef RETROPLATFORM
  6319. if (!_tcscmp (arg, _T("rphost"))) {
  6320. rp_param = my_strdup (np);
  6321. return 2;
  6322. }
  6323. if (!_tcscmp (arg, _T("rpescapekey"))) {
  6324. rp_rpescapekey = getval (np);
  6325. return 2;
  6326. }
  6327. if (!_tcscmp (arg, _T("rpescapeholdtime"))) {
  6328. rp_rpescapeholdtime = getval (np);
  6329. return 2;
  6330. }
  6331. if (!_tcscmp (arg, _T("rpscreenmode"))) {
  6332. rp_screenmode = getval (np);
  6333. return 2;
  6334. }
  6335. if (!_tcscmp(arg, _T("rpinputmode"))) {
  6336. rp_inputmode = getval(np);
  6337. return 2;
  6338. }
  6339. if (!_tcscmp(arg, _T("hrtmon_keyboard"))) {
  6340. hrtmon_lang = getval(np);
  6341. return 2;
  6342. }
  6343. #endif
  6344. return 0;
  6345. }
  6346. static TCHAR **parseargstrings (TCHAR *s, TCHAR **xargv)
  6347. {
  6348. int cnt, i, xargc;
  6349. TCHAR **args;
  6350. args = parseargstring (s);
  6351. for (cnt = 0; args[cnt]; cnt++);
  6352. for (xargc = 0; xargv[xargc]; xargc++);
  6353. for (i = 0; i < cnt; i++) {
  6354. TCHAR *arg = args[i];
  6355. TCHAR *next = i + 1 < cnt ? args[i + 1] : NULL;
  6356. TCHAR *next2 = i + 2 < cnt ? args[i + 2] : NULL;
  6357. int v = parseargs (arg, next, next2);
  6358. if (!v) {
  6359. xargv[xargc++] = my_strdup (arg);
  6360. } else if (v == 2) {
  6361. i++;
  6362. } else if (v < 0) {
  6363. doquit = 1;
  6364. return NULL;
  6365. }
  6366. }
  6367. return args;
  6368. }
  6369. static int process_arg (TCHAR *cmdline, TCHAR **xargv, TCHAR ***xargv3)
  6370. {
  6371. int i, xargc;
  6372. TCHAR **argv;
  6373. TCHAR tmp[MAX_DPATH];
  6374. int fd, ok, added;
  6375. *xargv3 = NULL;
  6376. argv = parseargstring (cmdline);
  6377. if (argv == NULL)
  6378. return 0;
  6379. added = 0;
  6380. xargc = 0;
  6381. xargv[xargc++] = my_strdup (executable_path);
  6382. fd = 0;
  6383. for (i = 0; argv[i]; i++) {
  6384. // resolve .lnk paths
  6385. const TCHAR *arg = argv[i];
  6386. if (_tcslen(arg) > 4 && !_tcsicmp(arg + _tcslen(arg) - 4, _T(".lnk"))) {
  6387. if (my_existsfile(arg)) {
  6388. TCHAR s[MAX_DPATH];
  6389. _tcscpy(s, arg);
  6390. if (my_resolveshortcut(s, MAX_DPATH)) {
  6391. xfree(argv[i]);
  6392. argv[i] = my_strdup(s);
  6393. }
  6394. }
  6395. }
  6396. }
  6397. for (i = 0; argv[i]; i++) {
  6398. TCHAR *f = argv[i];
  6399. ok = 0;
  6400. if (f[0] != '-' && f[0] != '/') {
  6401. int type = -1;
  6402. struct zfile *z = zfile_fopen (f, _T("rb"), ZFD_NORMAL);
  6403. if (z) {
  6404. type = zfile_gettype (z);
  6405. zfile_fclose (z);
  6406. }
  6407. tmp[0] = 0;
  6408. switch (type)
  6409. {
  6410. case ZFILE_CONFIGURATION:
  6411. _stprintf (tmp, _T("-config=%s"), f);
  6412. break;
  6413. case ZFILE_STATEFILE:
  6414. _stprintf (tmp, _T("-statefile=%s"), f);
  6415. break;
  6416. case ZFILE_CDIMAGE:
  6417. _stprintf (tmp, _T("-cdimage=%s"), f);
  6418. break;
  6419. case ZFILE_DISKIMAGE:
  6420. if (fd < 4)
  6421. _stprintf (tmp, _T("-cfgparam=floppy%d=%s"), fd++, f);
  6422. break;
  6423. }
  6424. if (tmp[0]) {
  6425. xfree (argv[i]);
  6426. argv[i] = my_strdup (tmp);
  6427. ok = 1;
  6428. added = 1;
  6429. }
  6430. }
  6431. if (!ok)
  6432. break;
  6433. }
  6434. if (added) {
  6435. for (i = 0; argv[i]; i++);
  6436. argv[i++] = my_strdup (_T("-s"));
  6437. argv[i++] = my_strdup (_T("use_gui=no"));
  6438. argv[i] = NULL;
  6439. }
  6440. for (i = 0; argv[i]; i++) {
  6441. TCHAR *arg = argv[i];
  6442. TCHAR *next = argv[i + 1];
  6443. TCHAR *next2 = next != NULL ? argv[i + 2] : NULL;
  6444. int v = parseargs (arg, next, next2);
  6445. if (!v) {
  6446. xargv[xargc++] = my_strdup (arg);
  6447. } else if (v == 2) {
  6448. i++;
  6449. } else if (v < 0) {
  6450. doquit = 1;
  6451. return 0;
  6452. }
  6453. }
  6454. #if 0
  6455. argv = 0;
  6456. argv[0] = 0;
  6457. #endif
  6458. *xargv3 = argv;
  6459. return xargc;
  6460. }
  6461. static TCHAR **WIN32_InitRegistry (TCHAR **argv)
  6462. {
  6463. DWORD disposition;
  6464. TCHAR tmp[MAX_DPATH];
  6465. int size = sizeof tmp / sizeof (TCHAR);
  6466. reginitializeinit (&inipath);
  6467. hWinUAEKey = NULL;
  6468. if (getregmode () == NULL || WINUAEPUBLICBETA > 0) {
  6469. /* Create/Open the hWinUAEKey which points our config-info */
  6470. RegCreateKeyEx (HKEY_CURRENT_USER, _T("Software\\Arabuusimiehet\\WinUAE"), 0, _T(""), REG_OPTION_NON_VOLATILE,
  6471. KEY_WRITE | KEY_READ, NULL, &hWinUAEKey, &disposition);
  6472. if (hWinUAEKey == NULL) {
  6473. FILE *f;
  6474. TCHAR *path;
  6475. int tempfile;
  6476. path = getdefaultini (&tempfile);
  6477. f = _tfopen (path, _T("r"));
  6478. if (!f)
  6479. f = _tfopen (path, _T("w"));
  6480. if (f) {
  6481. fclose (f);
  6482. reginitializeinit (&path);
  6483. }
  6484. xfree (path);
  6485. }
  6486. }
  6487. if (regquerystr (NULL, _T("Commandline"), tmp, &size))
  6488. return parseargstrings (tmp, argv);
  6489. return NULL;
  6490. }
  6491. bool switchreginimode(void)
  6492. {
  6493. TCHAR *path;
  6494. const TCHAR *inipath = getregmode();
  6495. if (inipath == NULL) {
  6496. // reg -> ini
  6497. FILE *f;
  6498. int tempfile;
  6499. path = getdefaultini(&tempfile);
  6500. if (tempfile)
  6501. return false;
  6502. f = _tfopen (path, _T("w"));
  6503. if (f) {
  6504. fclose(f);
  6505. return reginitializeinit(&path) != 0;
  6506. }
  6507. } else {
  6508. // ini -> reg
  6509. DeleteFile(inipath);
  6510. path = NULL;
  6511. reginitializeinit(&path);
  6512. return true;
  6513. }
  6514. return false;
  6515. }
  6516. static const TCHAR *pipename = _T("\\\\.\\pipe\\WinUAE");
  6517. static bool singleprocess (void)
  6518. {
  6519. DWORD mode, ret, avail;
  6520. bool ok = false;
  6521. TCHAR buf[1000];
  6522. HANDLE p = CreateFile(
  6523. pipename,
  6524. GENERIC_READ | GENERIC_WRITE,
  6525. 0,
  6526. NULL,
  6527. OPEN_EXISTING,
  6528. 0,
  6529. NULL);
  6530. if (p == INVALID_HANDLE_VALUE)
  6531. return false;
  6532. mode = PIPE_READMODE_MESSAGE;
  6533. if (!SetNamedPipeHandleState(p, &mode, NULL, NULL))
  6534. goto end;
  6535. buf[0] = 0xfeff;
  6536. _tcscpy (buf + 1, _T("IPC_QUIT"));
  6537. if (!WriteFile(p, (void*)buf, (_tcslen (buf) + 1) * sizeof (TCHAR), &ret, NULL))
  6538. goto end;
  6539. if (!PeekNamedPipe(p, NULL, 0, NULL, &avail, NULL))
  6540. goto end;
  6541. if (!ReadFile(p, buf, sizeof buf, &ret, NULL))
  6542. goto end;
  6543. ok = true;
  6544. end:
  6545. CloseHandle(p);
  6546. return ok;
  6547. }
  6548. static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
  6549. {
  6550. HANDLE hMutex;
  6551. TCHAR **argv = NULL, **argv2 = NULL, **argv3;
  6552. int argc, i;
  6553. if (!osdetect ())
  6554. return 0;
  6555. if (os_vista) {
  6556. max_uae_width = 8192;
  6557. max_uae_height = 8192;
  6558. } else {
  6559. max_uae_width = 3072;
  6560. max_uae_height = 2048;
  6561. }
  6562. hInst = hInstance;
  6563. hMutex = CreateMutex (NULL, FALSE, _T("WinUAE Instantiated")); // To tell the installer we're running
  6564. //singleprocess ();
  6565. argv = xcalloc (TCHAR*, MAX_ARGUMENTS);
  6566. argv3 = NULL;
  6567. argc = process_arg (lpCmdLine, argv, &argv3);
  6568. if (doquit)
  6569. return 0;
  6570. argv2 = WIN32_InitRegistry (argv);
  6571. if (regqueryint (NULL, _T("log_disabled"), &i)) {
  6572. if (i)
  6573. logging_disabled = true;
  6574. }
  6575. getstartpaths ();
  6576. makeverstr (VersionStr);
  6577. logging_init ();
  6578. if (_tcslen (lpCmdLine) > 0)
  6579. write_log (_T("'%s'\n"), lpCmdLine);
  6580. if (argv3 && argv3[0]) {
  6581. write_log (_T("params:\n"));
  6582. for (i = 0; argv3[i]; i++)
  6583. write_log (_T("%d: '%s'\n"), i + 1, argv3[i]);
  6584. }
  6585. if (argv2) {
  6586. write_log (_T("extra params:\n"));
  6587. for (i = 0; argv2[i]; i++)
  6588. write_log (_T("%d: '%s'\n"), i + 1, argv2[i]);
  6589. }
  6590. if (preinit_shm () && WIN32_RegisterClasses () && WIN32_InitLibraries ()) {
  6591. DWORD i;
  6592. #ifdef RETROPLATFORM
  6593. if (rp_param != NULL) {
  6594. if (FAILED (rp_init ()))
  6595. goto end;
  6596. }
  6597. #endif
  6598. WIN32_HandleRegistryStuff ();
  6599. write_log (_T("Enumerating display devices.. \n"));
  6600. enumeratedisplays ();
  6601. write_log (_T("Sorting devices and modes..\n"));
  6602. sortdisplays ();
  6603. enumerate_sound_devices ();
  6604. for (i = 0; i < MAX_SOUND_DEVICES && sound_devices[i]; i++) {
  6605. int type = sound_devices[i]->type;
  6606. write_log (_T("%d:%s: %s\n"), i, type == SOUND_DEVICE_XAUDIO2 ? _T("XA") : (type == SOUND_DEVICE_DS ? _T("DS") : (type == SOUND_DEVICE_AL ? _T("AL") : (type == SOUND_DEVICE_WASAPI ? _T("WA") : (type == SOUND_DEVICE_WASAPI_EXCLUSIVE ? _T("WX") : _T("PA"))))), sound_devices[i]->name);
  6607. }
  6608. write_log (_T("Enumerating recording devices:\n"));
  6609. for (i = 0; i < MAX_SOUND_DEVICES && record_devices[i]; i++) {
  6610. int type = record_devices[i]->type;
  6611. write_log (_T("%d:%s: %s\n"), i, type == SOUND_DEVICE_XAUDIO2 ? _T("XA") : (type == SOUND_DEVICE_DS ? _T("DS") : (type == SOUND_DEVICE_AL ? _T("AL") : (type == SOUND_DEVICE_WASAPI ? _T("WA") : (type == SOUND_DEVICE_WASAPI_EXCLUSIVE ? _T("WX") : _T("PA"))))), record_devices[i]->name);
  6612. }
  6613. write_log (_T("done\n"));
  6614. #if 0
  6615. DEVMODE devmode;
  6616. memset (&devmode, 0, sizeof (devmode));
  6617. devmode.dmSize = sizeof (DEVMODE);
  6618. if (EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &devmode)) {
  6619. default_freq = devmode.dmDisplayFrequency;
  6620. if (default_freq >= 70)
  6621. default_freq = 70;
  6622. else
  6623. default_freq = 60;
  6624. }
  6625. #endif
  6626. WIN32_InitLang ();
  6627. WIN32_InitHtmlHelp ();
  6628. DirectDraw_Release ();
  6629. unicode_init ();
  6630. can_D3D11(false);
  6631. if (betamessage ()) {
  6632. keyboard_settrans ();
  6633. #ifdef CATWEASEL
  6634. catweasel_init ();
  6635. #endif
  6636. #ifdef PARALLEL_PORT
  6637. paraport_mask = paraport_init ();
  6638. #endif
  6639. globalipc = createIPC (_T("WinUAE"), 0);
  6640. shmem_serial_create();
  6641. enumserialports ();
  6642. enummidiports ();
  6643. real_main (argc, argv);
  6644. }
  6645. }
  6646. end:
  6647. closeIPC (globalipc);
  6648. shmem_serial_delete();
  6649. write_disk_history ();
  6650. target_save_debugger_config();
  6651. timeend ();
  6652. #ifdef AVIOUTPUT
  6653. AVIOutput_Release ();
  6654. #endif
  6655. #ifdef AHI
  6656. ahi_close_sound ();
  6657. #endif
  6658. #ifdef PARALLEL_PORT
  6659. paraport_free ();
  6660. closeprinter ();
  6661. #endif
  6662. create_afnewdir (1);
  6663. #ifdef RETROPLATFORM
  6664. rp_free ();
  6665. #endif
  6666. CloseHandle (hMutex);
  6667. WIN32_CleanupLibraries ();
  6668. WIN32_UnregisterClasses ();
  6669. #ifdef _DEBUG
  6670. // show memory leaks
  6671. //_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  6672. #endif
  6673. close_console();
  6674. regclosetree(NULL);
  6675. if (hWinUAEKey)
  6676. RegCloseKey(hWinUAEKey);
  6677. _fcloseall();
  6678. for (i = 0; i < argc; i++)
  6679. xfree (argv[i]);
  6680. xfree (argv);
  6681. if (argv2) {
  6682. for (i = 0; argv2[i]; i++)
  6683. xfree (argv2[i]);
  6684. xfree (argv2);
  6685. }
  6686. for (i = 0; argv3 && argv3[i]; i++)
  6687. xfree (argv3[i]);
  6688. xfree (argv3);
  6689. return FALSE;
  6690. }
  6691. #if 0
  6692. int execute_command (TCHAR *cmd)
  6693. {
  6694. STARTUPINFO si;
  6695. PROCESS_INFORMATION pi;
  6696. memset (&si, 0, sizeof (si));
  6697. si.cb = sizeof (si);
  6698. si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  6699. si.wShowWindow = SW_HIDE;
  6700. if(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
  6701. WaitForSingleObject(pi.hProcess, INFINITE);
  6702. return 1;
  6703. }
  6704. return 0;
  6705. }
  6706. #endif
  6707. #include "driveclick.h"
  6708. static const int drvsampleres[] = {
  6709. IDR_DRIVE_CLICK_A500_1, DS_CLICK,
  6710. IDR_DRIVE_SPIN_A500_1, DS_SPIN,
  6711. IDR_DRIVE_SPINND_A500_1, DS_SPINND,
  6712. IDR_DRIVE_STARTUP_A500_1, DS_START,
  6713. IDR_DRIVE_SNATCH_A500_1, DS_SNATCH,
  6714. -1
  6715. };
  6716. int driveclick_loadresource (struct drvsample *sp, int drivetype)
  6717. {
  6718. int i, ok;
  6719. ok = 1;
  6720. for (i = 0; drvsampleres[i] >= 0; i += 2) {
  6721. struct drvsample *s = sp + drvsampleres[i + 1];
  6722. HRSRC res = FindResource (NULL, MAKEINTRESOURCE (drvsampleres[i + 0]), _T("WAVE"));
  6723. if (res != 0) {
  6724. HANDLE h = LoadResource (NULL, res);
  6725. int len = SizeofResource (NULL, res);
  6726. uae_u8 *p = (uae_u8*)LockResource (h);
  6727. s->p = decodewav (p, &len);
  6728. s->len = len;
  6729. } else {
  6730. ok = 0;
  6731. }
  6732. }
  6733. return ok;
  6734. }
  6735. typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
  6736. CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  6737. CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  6738. CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
  6739. static void savedump (MINIDUMPWRITEDUMP dump, HANDLE f, struct _EXCEPTION_POINTERS *pExceptionPointers)
  6740. {
  6741. MINIDUMP_EXCEPTION_INFORMATION exinfo;
  6742. MINIDUMP_USER_STREAM_INFORMATION musi, *musip;
  6743. MINIDUMP_USER_STREAM mus[3], *musp;
  6744. uae_u8 *log;
  6745. int len;
  6746. musip = NULL;
  6747. musi.UserStreamArray = mus;
  6748. musi.UserStreamCount = 0;
  6749. len = 30000;
  6750. log = save_log (TRUE, &len);
  6751. if (log) {
  6752. musp = &mus[musi.UserStreamCount];
  6753. musi.UserStreamCount++;
  6754. musp->Type = LastReservedStream + musi.UserStreamCount;
  6755. musp->Buffer = log;
  6756. musp->BufferSize = len;
  6757. len = 30000;
  6758. log = save_log (FALSE, &len);
  6759. if (log) {
  6760. musp = &mus[musi.UserStreamCount];
  6761. musi.UserStreamCount++;
  6762. musp->Type = LastReservedStream + musi.UserStreamCount;
  6763. musp->Buffer = log;
  6764. musp->BufferSize = len;
  6765. }
  6766. }
  6767. const TCHAR *config = cfgfile_getconfigdata(&len);
  6768. if (config && len > 0) {
  6769. musp = &mus[musi.UserStreamCount];
  6770. musi.UserStreamCount++;
  6771. musp->Type = LastReservedStream + musi.UserStreamCount;
  6772. musp->Buffer = (void*)config;
  6773. musp->BufferSize = len;
  6774. }
  6775. if (musi.UserStreamCount > 0)
  6776. musip = &musi;
  6777. exinfo.ThreadId = GetCurrentThreadId ();
  6778. exinfo.ExceptionPointers = pExceptionPointers;
  6779. exinfo.ClientPointers = 0;
  6780. dump (GetCurrentProcess (), GetCurrentProcessId (), f, minidumpmode, &exinfo, musip, NULL);
  6781. }
  6782. static void create_dump (struct _EXCEPTION_POINTERS *pExceptionPointers)
  6783. {
  6784. TCHAR path[MAX_DPATH];
  6785. TCHAR path2[MAX_DPATH];
  6786. TCHAR msg[1024];
  6787. TCHAR *p;
  6788. HMODULE dll = NULL;
  6789. struct tm when;
  6790. __time64_t now;
  6791. if (GetModuleFileName (NULL, path, MAX_DPATH)) {
  6792. TCHAR dumpfilename[100];
  6793. TCHAR beta[100];
  6794. TCHAR path3[MAX_DPATH];
  6795. TCHAR *slash = _tcsrchr (path, '\\');
  6796. _time64 (&now);
  6797. when = *_localtime64 (&now);
  6798. _tcscpy (path2, path);
  6799. if (slash) {
  6800. _tcscpy (slash + 1, _T("DBGHELP.DLL"));
  6801. dll = WIN32_LoadLibrary (path);
  6802. }
  6803. slash = _tcsrchr (path2, '\\');
  6804. if (slash)
  6805. p = slash + 1;
  6806. else
  6807. p = path2;
  6808. p[0] = 0;
  6809. beta[0] = 0;
  6810. if (WINUAEPUBLICBETA > 0)
  6811. _stprintf (beta, _T("b%s"), WINUAEBETA);
  6812. _stprintf (dumpfilename, _T("winuae%s_%d.%d.%d_%s_%d.%02d.%02d_%02d.%02d.%02d.dmp"),
  6813. #ifdef _WIN64
  6814. _T("_x64"),
  6815. #else
  6816. _T(""),
  6817. #endif
  6818. UAEMAJOR, UAEMINOR, UAESUBREV, beta[0] ? beta : _T("R"),
  6819. when.tm_year + 1900, when.tm_mon + 1, when.tm_mday, when.tm_hour, when.tm_min, when.tm_sec);
  6820. if (dll == NULL)
  6821. dll = WIN32_LoadLibrary (_T("DBGHELP.DLL"));
  6822. if (dll) {
  6823. all_events_disabled = 1;
  6824. MINIDUMPWRITEDUMP dump = (MINIDUMPWRITEDUMP)GetProcAddress (dll, "MiniDumpWriteDump");
  6825. if (dump) {
  6826. _tcscpy (path3, path2);
  6827. _tcscat (path3, dumpfilename);
  6828. HANDLE f = CreateFile (path3, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  6829. if (f == INVALID_HANDLE_VALUE) {
  6830. _tcscpy (path3, start_path_data);
  6831. _tcscat (path3, dumpfilename);
  6832. f = CreateFile (path3, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  6833. }
  6834. if (f == INVALID_HANDLE_VALUE) {
  6835. if (GetTempPath (MAX_DPATH, path3) > 0) {
  6836. _tcscat (path3, dumpfilename);
  6837. f = CreateFile (path3, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  6838. }
  6839. }
  6840. if (f != INVALID_HANDLE_VALUE) {
  6841. flush_log ();
  6842. savedump (dump, f, pExceptionPointers);
  6843. CloseHandle (f);
  6844. ClipCursor(NULL);
  6845. ReleaseCapture();
  6846. ShowCursor(TRUE);
  6847. if (debugfile)
  6848. log_close(debugfile);
  6849. if (isfullscreen () <= 0) {
  6850. _stprintf (msg, _T("Crash detected. MiniDump saved as:\n%s\n"), path3);
  6851. MessageBox (NULL, msg, _T("Crash"), MB_OK | MB_ICONWARNING | MB_TASKMODAL | MB_SETFOREGROUND);
  6852. }
  6853. ExitProcess(0);
  6854. }
  6855. }
  6856. all_events_disabled = 0;
  6857. }
  6858. }
  6859. }
  6860. #if defined(_WIN64)
  6861. LONG WINAPI WIN32_ExceptionFilter (struct _EXCEPTION_POINTERS * pExceptionPointers, DWORD ec)
  6862. {
  6863. if (nocrashdump || isfullscreen() > 0)
  6864. EXCEPTION_CONTINUE_SEARCH;
  6865. write_log (_T("EVALEXCEPTION %08x!\n"), ec);
  6866. create_dump (pExceptionPointers);
  6867. return EXCEPTION_CONTINUE_SEARCH;
  6868. }
  6869. #else
  6870. #if 0
  6871. #include <errorrep.h>
  6872. #endif
  6873. /* Gah, don't look at this crap, please.. */
  6874. static void efix (DWORD *regp, void *p, void *ps, int *got)
  6875. {
  6876. DWORD reg = *regp;
  6877. if (p >= (void*)reg && p < (void*)(reg + 32)) {
  6878. *regp = (DWORD)ps;
  6879. *got = 1;
  6880. }
  6881. }
  6882. LONG WINAPI WIN32_ExceptionFilter (struct _EXCEPTION_POINTERS *pExceptionPointers, DWORD ec)
  6883. {
  6884. if (nocrashdump)
  6885. EXCEPTION_CONTINUE_SEARCH;
  6886. static uae_u8 *prevpc;
  6887. LONG lRet = EXCEPTION_CONTINUE_SEARCH;
  6888. PEXCEPTION_RECORD er = pExceptionPointers->ExceptionRecord;
  6889. PCONTEXT ctx = pExceptionPointers->ContextRecord;
  6890. #if 0
  6891. if (ec >= EXCEPTION_FLT_DENORMAL_OPERAND && ec <= EXCEPTION_FLT_UNDERFLOW) {
  6892. extern void fpp_setexcept (uae_u16);
  6893. if (ec == EXCEPTION_FLT_INEXACT_RESULT)
  6894. fpp_setexcept (0x0100 | 0x0200);
  6895. else if (ec == EXCEPTION_FLT_OVERFLOW)
  6896. fpp_setexcept (0x1000);
  6897. else if (ec == EXCEPTION_FLT_UNDERFLOW)
  6898. fpp_setexcept (0x0800);
  6899. else if (ec == EXCEPTION_FLT_DIVIDE_BY_ZERO)
  6900. fpp_setexcept (0x0400);
  6901. return EXCEPTION_CONTINUE_EXECUTION;
  6902. }
  6903. #endif
  6904. /* Check possible access violation in 68010+/compatible mode disabled if PC points to non-existing memory */
  6905. #if 1
  6906. if (ec == EXCEPTION_ACCESS_VIOLATION && !er->ExceptionFlags &&
  6907. er->NumberParameters >= 2 && !er->ExceptionInformation[0] && regs.pc_p) {
  6908. void *p = (void*)er->ExceptionInformation[1];
  6909. write_log (_T("ExceptionFilter Trap: %p %p %p\n"), p, regs.pc_p, prevpc);
  6910. if ((p >= (void*)regs.pc_p && p < (void*)(regs.pc_p + 32))
  6911. || (p >= (void*)prevpc && p < (void*)(prevpc + 32))) {
  6912. int got = 0;
  6913. uaecptr opc = m68k_getpc ();
  6914. void *ps = get_real_address (0);
  6915. m68k_dumpstate(NULL, 0xffffffff);
  6916. efix (&ctx->Eax, p, ps, &got);
  6917. efix (&ctx->Ebx, p, ps, &got);
  6918. efix (&ctx->Ecx, p, ps, &got);
  6919. efix (&ctx->Edx, p, ps, &got);
  6920. efix (&ctx->Esi, p, ps, &got);
  6921. efix (&ctx->Edi, p, ps, &got);
  6922. write_log (_T("Access violation! (68KPC=%08X HOSTADDR=%p)\n"), M68K_GETPC, p);
  6923. if (got == 0) {
  6924. write_log (_T("failed to find and fix the problem (%p). crashing..\n"), p);
  6925. } else {
  6926. void *ppc = regs.pc_p;
  6927. m68k_setpc (0);
  6928. if (ppc != regs.pc_p) {
  6929. prevpc = (uae_u8*)ppc;
  6930. }
  6931. m68k_setpc ((uaecptr)p);
  6932. hardware_exception2(opc, 0, er->ExceptionInformation[0] == 0, true, 4);
  6933. lRet = EXCEPTION_CONTINUE_EXECUTION;
  6934. }
  6935. }
  6936. }
  6937. #endif
  6938. #ifndef _DEBUG
  6939. if (lRet == EXCEPTION_CONTINUE_SEARCH)
  6940. create_dump (pExceptionPointers);
  6941. #endif
  6942. #if 0
  6943. HMODULE hFaultRepDll = LoadLibrary (_T("FaultRep.dll")) ;
  6944. if (hFaultRepDll) {
  6945. pfn_REPORTFAULT pfn = (pfn_REPORTFAULT)GetProcAddress (hFaultRepDll, _T("ReportFault"));
  6946. if (pfn) {
  6947. EFaultRepRetVal rc = pfn (pExceptionPointers, 0);
  6948. lRet = EXCEPTION_EXECUTE_HANDLER;
  6949. }
  6950. FreeLibrary (hFaultRepDll );
  6951. }
  6952. #endif
  6953. return lRet ;
  6954. }
  6955. #endif
  6956. void addnotifications (HWND hwnd, int remove, int isgui)
  6957. {
  6958. static ULONG ret;
  6959. static HDEVNOTIFY hdn1, hdn2, hdn3;
  6960. static int wtson;
  6961. if (remove) {
  6962. if (ret > 0)
  6963. SHChangeNotifyDeregister (ret);
  6964. ret = 0;
  6965. if (hdn1)
  6966. UnregisterDeviceNotification (hdn1);
  6967. if (hdn2)
  6968. UnregisterDeviceNotification (hdn2);
  6969. if (hdn3)
  6970. UnregisterDeviceNotification (hdn3);
  6971. hdn1 = 0;
  6972. hdn2 = 0;
  6973. hdn3 = 0;
  6974. if (wtson && !isgui)
  6975. WTSUnRegisterSessionNotification (hwnd);
  6976. wtson = 0;
  6977. } else {
  6978. DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
  6979. SHChangeNotifyEntry shCNE = { 0 };
  6980. shCNE.pidl = NULL;
  6981. shCNE.fRecursive = TRUE;
  6982. ret = SHChangeNotifyRegister (hwnd, SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_NewDelivery,
  6983. SHCNE_MEDIAREMOVED | SHCNE_MEDIAINSERTED | SHCNE_DRIVEREMOVED | SHCNE_DRIVEADD,
  6984. WM_USER + 2, 1, &shCNE);
  6985. NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  6986. NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  6987. NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_KEYBOARD;
  6988. hdn1 = RegisterDeviceNotification (hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  6989. NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_MOUSE;
  6990. hdn2 = RegisterDeviceNotification (hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  6991. NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
  6992. hdn3 = RegisterDeviceNotification (hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  6993. if (!isgui)
  6994. wtson = WTSRegisterSessionNotification (hwnd, NOTIFY_FOR_THIS_SESSION);
  6995. }
  6996. }
  6997. void registertouch(HWND hwnd)
  6998. {
  6999. #if TOUCH_SUPPORT
  7000. REGISTERTOUCHWINDOW pRegisterTouchWindow;
  7001. if (!os_touch)
  7002. return;
  7003. pRegisterTouchWindow = (REGISTERTOUCHWINDOW)GetProcAddress(userdll, "RegisterTouchWindow");
  7004. pGetTouchInputInfo = (GETTOUCHINPUTINFO)GetProcAddress(userdll, "GetTouchInputInfo");
  7005. pCloseTouchInputHandle = (CLOSETOUCHINPUTHANDLE)GetProcAddress(userdll, "CloseTouchInputHandle");
  7006. if (!pRegisterTouchWindow || !pGetTouchInputInfo || !pCloseTouchInputHandle)
  7007. return;
  7008. if (!pRegisterTouchWindow(hwnd, 0)) {
  7009. write_log(_T("RegisterTouchWindow error: %d\n"), GetLastError());
  7010. }
  7011. #endif
  7012. }
  7013. void systray (HWND hwnd, int remove)
  7014. {
  7015. static const GUID iconguid = { 0x6974bfc1, 0x898b, 0x4157, { 0xa4, 0x30, 0x43, 0x6b, 0xa0, 0xdd, 0x5d, 0xf2 } };
  7016. NOTIFYICONDATA nid;
  7017. BOOL v;
  7018. static bool noguid;
  7019. if (!remove && currprefs.win32_nonotificationicon)
  7020. return;
  7021. #ifdef RETROPLATFORM
  7022. if (rp_isactive ())
  7023. return;
  7024. #endif
  7025. bool canguid = !noguid && os_win7;
  7026. //write_log (_T("notif: systray(%x,%d)\n"), hwnd, remove);
  7027. if (!remove) {
  7028. if (!TaskbarRestart)
  7029. TaskbarRestart = RegisterWindowMessage (_T("TaskbarCreated"));
  7030. TaskbarRestartHWND = hwnd;
  7031. //write_log (_T("notif: taskbarrestart = %d\n"), TaskbarRestart);
  7032. } else {
  7033. TaskbarRestart = 0;
  7034. hwnd = TaskbarRestartHWND;
  7035. }
  7036. if (!hwnd)
  7037. return;
  7038. memset (&nid, 0, sizeof (nid));
  7039. nid.cbSize = sizeof (nid);
  7040. nid.hWnd = hwnd;
  7041. nid.hIcon = LoadIcon (hInst, (LPCWSTR)MAKEINTRESOURCE (IDI_APPICON));
  7042. nid.uFlags = NIF_ICON | NIF_MESSAGE | (canguid ? NIF_GUID : 0);
  7043. nid.uCallbackMessage = WM_USER + 1;
  7044. nid.uVersion = os_win7 ? NOTIFYICON_VERSION_4 : NOTIFYICON_VERSION;
  7045. nid.dwInfoFlags = NIIF_USER;
  7046. _tcscpy(nid.szInfo, _T("WinUAE"));
  7047. _tcscpy(nid.szInfoTitle, _T("WinUAE"));
  7048. nid.hBalloonIcon = nid.hIcon;
  7049. if (canguid) {
  7050. nid.guidItem = iconguid;
  7051. if (!remove) {
  7052. // if guid identifier: always remove first.
  7053. // old icon may not have been removed due to crash etc
  7054. v = Shell_NotifyIcon(NIM_DELETE, &nid);
  7055. }
  7056. }
  7057. v = Shell_NotifyIcon (remove ? NIM_DELETE : NIM_ADD, &nid);
  7058. if (!remove && !v && !noguid) {
  7059. noguid = true;
  7060. write_log(_T("Notify error2 = %x %d\n"), GetLastError(), remove);
  7061. return systray(hwnd, remove);
  7062. }
  7063. //write_log (_T("notif: Shell_NotifyIcon returned %d\n"), v);
  7064. if (v) {
  7065. if (remove) {
  7066. TaskbarRestartHWND = NULL;
  7067. } else {
  7068. v = Shell_NotifyIcon(NIM_SETVERSION, &nid);
  7069. }
  7070. } else {
  7071. write_log (_T("Notify error = %x %d\n"), GetLastError(), remove);
  7072. }
  7073. }
  7074. static void systraymenu (HWND hwnd)
  7075. {
  7076. POINT pt;
  7077. HMENU menu, menu2, drvmenu, cdmenu;
  7078. int drvs[] = { ID_ST_DF0, ID_ST_DF1, ID_ST_DF2, ID_ST_DF3, -1 };
  7079. int i;
  7080. TCHAR text[100], text2[100];
  7081. WIN32GUI_LoadUIString (IDS_STMENUNOFLOPPY, text, sizeof (text) / sizeof (TCHAR));
  7082. WIN32GUI_LoadUIString (IDS_STMENUNOCD, text2, sizeof (text2) / sizeof (TCHAR));
  7083. GetCursorPos (&pt);
  7084. menu = LoadMenu (hUIDLL ? hUIDLL : hInst, MAKEINTRESOURCE (IDM_SYSTRAY));
  7085. if (!menu)
  7086. return;
  7087. menu2 = GetSubMenu (menu, 0);
  7088. drvmenu = GetSubMenu (menu2, 1);
  7089. cdmenu = GetSubMenu (menu2, 2);
  7090. EnableMenuItem (menu2, ID_ST_HELP, pHtmlHelp ? MF_ENABLED : MF_GRAYED);
  7091. i = 0;
  7092. while (drvs[i] >= 0) {
  7093. TCHAR s[MAX_DPATH];
  7094. if (currprefs.floppyslots[i].df[0])
  7095. _stprintf (s, _T("DF%d: [%s]"), i, currprefs.floppyslots[i].df);
  7096. else
  7097. _stprintf (s, _T("DF%d: [%s]"), i, text);
  7098. ModifyMenu (drvmenu, drvs[i], MF_BYCOMMAND | MF_STRING, drvs[i], s);
  7099. EnableMenuItem (menu2, drvs[i], currprefs.floppyslots[i].dfxtype < 0 ? MF_GRAYED : MF_ENABLED);
  7100. i++;
  7101. }
  7102. {
  7103. TCHAR s[MAX_DPATH];
  7104. if (currprefs.cdslots[0].inuse && currprefs.cdslots[0].name[0])
  7105. _stprintf (s, _T("CD: [%s]"), currprefs.cdslots[0].name);
  7106. else
  7107. _stprintf (s, _T("CD: [%s]"), text2);
  7108. ModifyMenu (cdmenu, ID_ST_CD0, MF_BYCOMMAND | MF_STRING, ID_ST_CD0, s);
  7109. int open = 0;
  7110. struct device_info di;
  7111. if (sys_command_info (0, &di, 1) && di.open)
  7112. open = 1;
  7113. EnableMenuItem (menu2, ID_ST_CD0, open == 0 ? MF_GRAYED : MF_ENABLED);
  7114. }
  7115. if (isfullscreen () <= 0)
  7116. SetForegroundWindow (hwnd);
  7117. TrackPopupMenu (menu2, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
  7118. pt.x, pt.y, 0, hwnd, NULL);
  7119. PostMessage (hwnd, WM_NULL, 0, 0);
  7120. DestroyMenu (menu);
  7121. }
  7122. static void LLError (HMODULE m, const TCHAR *s)
  7123. {
  7124. DWORD err;
  7125. if (m) {
  7126. // write_log (_T("'%s' opened\n"), s);
  7127. return;
  7128. }
  7129. err = GetLastError ();
  7130. if (err == ERROR_MOD_NOT_FOUND || err == ERROR_DLL_NOT_FOUND)
  7131. return;
  7132. write_log (_T("%s failed to open %d\n"), s, err);
  7133. }
  7134. HMODULE WIN32_LoadLibrary_2 (const TCHAR *name, int expand)
  7135. {
  7136. HMODULE m = NULL;
  7137. TCHAR *newname;
  7138. DWORD err = -1;
  7139. int round;
  7140. newname = xmalloc (TCHAR, _tcslen (name) + 1 + 10);
  7141. if (!newname)
  7142. return NULL;
  7143. for (round = 0; round < 6; round++) {
  7144. TCHAR s[MAX_DPATH], dir[MAX_DPATH], dir2[MAX_DPATH];
  7145. _tcscpy (newname, name);
  7146. #ifdef CPU_64_BIT
  7147. TCHAR *p = NULL;
  7148. switch(round)
  7149. {
  7150. case 0:
  7151. p = _tcsstr (newname, _T("32"));
  7152. if (p) {
  7153. p[0] = '6';
  7154. p[1] = '4';
  7155. }
  7156. break;
  7157. case 1:
  7158. p = _tcschr (newname, '.');
  7159. if (p) {
  7160. _tcscpy(p, _T("_x64"));
  7161. _tcscat(p, _tcschr(name, '.'));
  7162. }
  7163. break;
  7164. case 2:
  7165. p = _tcschr (newname, '.');
  7166. if (p) {
  7167. _tcscpy(p, _T("x64"));
  7168. _tcscat(p, _tcschr(name, '.'));
  7169. }
  7170. break;
  7171. case 3:
  7172. p = _tcschr (newname, '.');
  7173. if (p) {
  7174. _tcscpy(p, _T("_64"));
  7175. _tcscat(p, _tcschr(name, '.'));
  7176. }
  7177. break;
  7178. case 4:
  7179. p = _tcschr (newname, '.');
  7180. if (p) {
  7181. _tcscpy(p, _T("64"));
  7182. _tcscat(p, _tcschr(name, '.'));
  7183. }
  7184. break;
  7185. case 5:
  7186. p = newname;
  7187. break;
  7188. }
  7189. if (!p)
  7190. continue;
  7191. #endif
  7192. get_plugin_path (s, sizeof s / sizeof (TCHAR), NULL);
  7193. _tcscat (s, newname);
  7194. GetDllDirectory(sizeof(dir2) / sizeof TCHAR, dir2);
  7195. getpathpart(dir, sizeof(dir) / sizeof TCHAR, s);
  7196. stripslashes(dir);
  7197. if (dir[0])
  7198. SetDllDirectory(dir);
  7199. m = LoadLibrary (s);
  7200. LLError (m ,s);
  7201. if (m) {
  7202. if (dir2[0])
  7203. SetDllDirectory(dir2);
  7204. goto end;
  7205. }
  7206. m = LoadLibrary (newname);
  7207. LLError (m, newname);
  7208. if (dir2[0])
  7209. SetDllDirectory(dir2);
  7210. if (m)
  7211. goto end;
  7212. #ifndef CPU_64_BIT
  7213. break;
  7214. #endif
  7215. }
  7216. end:
  7217. xfree (newname);
  7218. return m;
  7219. }
  7220. HMODULE WIN32_LoadLibrary (const TCHAR *name)
  7221. {
  7222. return WIN32_LoadLibrary_2 (name, TRUE);
  7223. }
  7224. int isdllversion (const TCHAR *name, int version, int revision, int subver, int subrev)
  7225. {
  7226. DWORD dwVersionHandle, dwFileVersionInfoSize;
  7227. LPVOID lpFileVersionData = NULL;
  7228. int ok = 0;
  7229. dwFileVersionInfoSize = GetFileVersionInfoSize (name, &dwVersionHandle);
  7230. if (dwFileVersionInfoSize) {
  7231. if (lpFileVersionData = xcalloc (uae_u8, dwFileVersionInfoSize)) {
  7232. if (GetFileVersionInfo (name, dwVersionHandle, dwFileVersionInfoSize, lpFileVersionData)) {
  7233. VS_FIXEDFILEINFO *vsFileInfo = NULL;
  7234. UINT uLen;
  7235. if (VerQueryValue (lpFileVersionData, TEXT("\\"), (void **)&vsFileInfo, &uLen)) {
  7236. if (vsFileInfo) {
  7237. uae_u64 v1 = ((uae_u64)vsFileInfo->dwProductVersionMS << 32) | vsFileInfo->dwProductVersionLS;
  7238. uae_u64 v2 = ((uae_u64)version << 48) | ((uae_u64)revision << 32) | (subver << 16) | (subrev << 0);
  7239. write_log (_T("%s %d.%d.%d.%d\n"), name,
  7240. HIWORD (vsFileInfo->dwProductVersionMS), LOWORD (vsFileInfo->dwProductVersionMS),
  7241. HIWORD (vsFileInfo->dwProductVersionLS), LOWORD (vsFileInfo->dwProductVersionLS));
  7242. if (v1 >= v2)
  7243. ok = 1;
  7244. }
  7245. }
  7246. }
  7247. xfree (lpFileVersionData);
  7248. }
  7249. }
  7250. return ok;
  7251. }
  7252. int get_guid_target (uae_u8 *out)
  7253. {
  7254. GUID guid;
  7255. if (CoCreateGuid (&guid) != S_OK)
  7256. return 0;
  7257. out[0] = guid.Data1 >> 24;
  7258. out[1] = (uae_u8)(guid.Data1 >> 16);
  7259. out[2] = (uae_u8)(guid.Data1 >> 8);
  7260. out[3] = (uae_u8)(guid.Data1 >> 0);
  7261. out[4] = guid.Data2 >> 8;
  7262. out[5] = guid.Data2 >> 0;
  7263. out[6] = guid.Data3 >> 8;
  7264. out[7] = guid.Data3 >> 0;
  7265. memcpy (out + 8, guid.Data4, 8);
  7266. return 1;
  7267. }
  7268. typedef HRESULT (CALLBACK* SHCREATEITEMFROMPARSINGNAME)
  7269. (PCWSTR,IBindCtx*,REFIID,void**); // Vista+ only
  7270. void target_getdate(int *y, int *m, int *d)
  7271. {
  7272. *y = GETBDY(WINUAEDATE);
  7273. *m = GETBDM(WINUAEDATE);
  7274. *d = GETBDD(WINUAEDATE);
  7275. }
  7276. void target_addtorecent (const TCHAR *name, int t)
  7277. {
  7278. TCHAR tmp[MAX_DPATH];
  7279. if (name == NULL || name[0] == 0)
  7280. return;
  7281. tmp[0] = 0;
  7282. GetFullPathName (name, sizeof tmp / sizeof (TCHAR), tmp, NULL);
  7283. if (os_win7) {
  7284. SHCREATEITEMFROMPARSINGNAME pSHCreateItemFromParsingName;
  7285. SHARDAPPIDINFO shard;
  7286. pSHCreateItemFromParsingName = (SHCREATEITEMFROMPARSINGNAME)GetProcAddress (
  7287. GetModuleHandle (_T("shell32.dll")), "SHCreateItemFromParsingName");
  7288. if (!pSHCreateItemFromParsingName)
  7289. return;
  7290. shard.pszAppID = WINUAEAPPNAME;
  7291. if (SUCCEEDED (pSHCreateItemFromParsingName (tmp, NULL, IID_IShellItem, (void**)&shard.psi))) {
  7292. SHAddToRecentDocs (SHARD_APPIDINFO, &shard);
  7293. shard.psi->Release();
  7294. }
  7295. } else {
  7296. SHAddToRecentDocs (SHARD_PATH, tmp);
  7297. }
  7298. }
  7299. void target_reset (void)
  7300. {
  7301. clipboard_reset ();
  7302. }
  7303. uae_u32 emulib_target_getcpurate (uae_u32 v, uae_u32 *low)
  7304. {
  7305. *low = 0;
  7306. if (v == 1) {
  7307. LARGE_INTEGER pf;
  7308. pf.QuadPart = 0;
  7309. QueryPerformanceFrequency (&pf);
  7310. *low = pf.LowPart;
  7311. return pf.HighPart;
  7312. } else if (v == 2) {
  7313. LARGE_INTEGER pf;
  7314. pf.QuadPart = 0;
  7315. QueryPerformanceCounter (&pf);
  7316. *low = pf.LowPart;
  7317. return pf.HighPart;
  7318. }
  7319. return 0;
  7320. }
  7321. bool target_can_autoswitchdevice(void)
  7322. {
  7323. #ifdef RETROPLATFORM
  7324. if (rp_isactive ())
  7325. return false;
  7326. #endif
  7327. if (!ismouseactive())
  7328. return false;
  7329. return true;
  7330. }
  7331. void fpux_save (int *v)
  7332. {
  7333. #ifndef _WIN64
  7334. *v = _controlfp (0, 0);
  7335. _controlfp (fpucontrol, _MCW_IC | _MCW_RC | _MCW_PC);
  7336. #endif
  7337. }
  7338. void fpux_restore (int *v)
  7339. {
  7340. #ifndef _WIN64
  7341. if (v)
  7342. _controlfp (*v, _MCW_IC | _MCW_RC | _MCW_PC);
  7343. #endif
  7344. }
  7345. struct winuae //this struct is put in a6 if you call
  7346. //execute native function
  7347. {
  7348. HWND amigawnd; //address of amiga Window Windows Handle
  7349. unsigned int changenum; //number to detect screen close/open
  7350. unsigned int z3offset; //the offset to add to acsess Z3 mem from Dll side
  7351. };
  7352. void *uaenative_get_uaevar (void)
  7353. {
  7354. struct AmigaMonitor *mon = &AMonitors[0];
  7355. static struct winuae uaevar;
  7356. #ifdef _WIN32
  7357. uaevar.amigawnd = mon->hAmigaWnd;
  7358. #endif
  7359. uaevar.z3offset = (uae_u32)get_real_address (z3fastmem_bank[0].start) - z3fastmem_bank[0].start;
  7360. return &uaevar;
  7361. }
  7362. const TCHAR **uaenative_get_library_dirs (void)
  7363. {
  7364. static const TCHAR **nats;
  7365. static TCHAR *path;
  7366. if (nats == NULL)
  7367. nats = xcalloc (const TCHAR*, 3);
  7368. if (path == NULL) {
  7369. path = xcalloc (TCHAR, MAX_DPATH);
  7370. _tcscpy (path, start_path_data);
  7371. _tcscat (path, _T("plugins"));
  7372. }
  7373. nats[0] = start_path_data;
  7374. nats[1] = path;
  7375. return nats;
  7376. }
  7377. bool is_mainthread(void)
  7378. {
  7379. return GetCurrentThreadId() == mainthreadid;
  7380. }
  7381. typedef BOOL (CALLBACK* CHANGEWINDOWMESSAGEFILTER)(UINT, DWORD);
  7382. typedef DPI_AWARENESS_CONTEXT (CALLBACK* GETTHREADDPIAWARENESSCONTEXT)(void);
  7383. typedef DPI_AWARENESS (CALLBACK* GETAWARENESSFROMDPIAWARENESSCONTEXT)(DPI_AWARENESS_CONTEXT);
  7384. #ifndef NDEBUG
  7385. typedef BOOL(WINAPI* SETPROCESSMITIGATIONPOLICY)(DWORD, PVOID, SIZE_T);
  7386. static SETPROCESSMITIGATIONPOLICY pSetProcessMitigationPolicy;
  7387. #endif
  7388. int PASCAL wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
  7389. {
  7390. DWORD_PTR sys_aff;
  7391. HANDLE thread;
  7392. #if 0
  7393. #ifdef _DEBUG
  7394. {
  7395. int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  7396. //tmp &= 0xffff;
  7397. tmp |= _CRTDBG_CHECK_ALWAYS_DF;
  7398. tmp |= _CRTDBG_CHECK_CRT_DF;
  7399. #ifdef MEMDEBUG
  7400. tmp |=_CRTDBG_CHECK_EVERY_16_DF;
  7401. tmp |= _CRTDBG_DELAY_FREE_MEM_DF;
  7402. #endif
  7403. _CrtSetDbgFlag(tmp);
  7404. }
  7405. #endif
  7406. #endif
  7407. userdll = GetModuleHandle(_T("user32.dll"));
  7408. kerneldll = GetModuleHandle(_T("kernel32.dll"));
  7409. if (!userdll || !kerneldll)
  7410. return 0;
  7411. #ifndef NDEBUG
  7412. PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY p = { 0 };
  7413. p.HandleExceptionsPermanentlyEnabled = 1;
  7414. p.RaiseExceptionOnInvalidHandleReference = 1;
  7415. //ProcessStrictHandleCheckPolicy = 3
  7416. pSetProcessMitigationPolicy = (SETPROCESSMITIGATIONPOLICY)GetProcAddress(kerneldll, "SetProcessMitigationPolicy");
  7417. pSetProcessMitigationPolicy(3, &p, sizeof p);
  7418. #endif
  7419. executable_path[0] = 0;
  7420. GetModuleFileName(NULL, executable_path, sizeof executable_path / sizeof(TCHAR));
  7421. SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  7422. currprefs.win32_filesystem_mangle_reserved_names = true;
  7423. SetDllDirectory (_T(""));
  7424. /* Make sure we do an InitCommonControls() to get some advanced controls */
  7425. CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  7426. GETTHREADDPIAWARENESSCONTEXT pGetThreadDpiAwarenessContext = (GETTHREADDPIAWARENESSCONTEXT)GetProcAddress(userdll, "GetThreadDpiAwarenessContext");
  7427. if (pGetThreadDpiAwarenessContext) {
  7428. DPI_AWARENESS_CONTEXT dpiawactx = pGetThreadDpiAwarenessContext();
  7429. if (dpiawactx) {
  7430. GETAWARENESSFROMDPIAWARENESSCONTEXT pGetAwarenessFromDpiAwarenessContext = (GETAWARENESSFROMDPIAWARENESSCONTEXT)GetProcAddress(userdll, "GetAwarenessFromDpiAwarenessContext");
  7431. if (pGetAwarenessFromDpiAwarenessContext) {
  7432. DPI_AWARENESS dpiawa = pGetAwarenessFromDpiAwarenessContext(dpiawactx);
  7433. if (dpiawa == DPI_AWARENESS_PER_MONITOR_AWARE)
  7434. dpi_aware_v2 = true;
  7435. }
  7436. }
  7437. }
  7438. pAdjustWindowRectExForDpi = (ADJUSTWINDOWRECTEXFORDPI)GetProcAddress(userdll, "AdjustWindowRectExForDpi");
  7439. InitCommonControls ();
  7440. original_affinity = 1;
  7441. GetProcessAffinityMask (GetCurrentProcess (), &original_affinity, &sys_aff);
  7442. thread = GetCurrentThread ();
  7443. mainthreadid = GetCurrentThreadId();
  7444. //original_affinity = SetThreadAffinityMask(thread, 1);
  7445. fpucontrol = _controlfp (0, 0) & (_MCW_IC | _MCW_RC | _MCW_PC);
  7446. _tzset ();
  7447. #if 0
  7448. #define MSGFLT_ADD 1
  7449. CHANGEWINDOWMESSAGEFILTER pChangeWindowMessageFilter;
  7450. pChangeWindowMessageFilter = (CHANGEWINDOWMESSAGEFILTER)GetProcAddress(
  7451. userdll, "ChangeWindowMessageFilter");
  7452. if (pChangeWindowMessageFilter)
  7453. pChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
  7454. #endif
  7455. log_open (NULL, 0, -1, NULL);
  7456. #ifdef NDEBUG
  7457. __try {
  7458. #endif
  7459. WinMain2 (hInstance, hPrevInstance, lpCmdLine, nCmdShow);
  7460. #ifdef NDEBUG
  7461. } __except(WIN32_ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) {
  7462. }
  7463. #endif
  7464. //SetThreadAffinityMask (thread, original_affinity);
  7465. return FALSE;
  7466. }