PCem
view src/win.c @ 145:34376c2f2d17
Disable keyboard input when main window out of focus - entry into dialogs no longer picked up by emulator.
Set RIDEV_NOHOTKEYS when registering raw input devices - Windows key and some other shortcuts no longer affect emulator.
| author | TomW |
|---|---|
| date | Sun Aug 17 15:23:26 2014 +0100 |
| parents | 24b744b9a632 |
| children | 82d7f693029b |
line source
1 #define _WIN32_WINNT 0x0501
2 #define BITMAP WINDOWS_BITMAP
3 #include <windows.h>
4 #include <windowsx.h>
5 #undef BITMAP
7 #include <commctrl.h>
8 #include <commdlg.h>
10 #include <process.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <stdlib.h>
16 #include "ibm.h"
17 #include "video.h"
18 #include "resources.h"
19 #include "cpu.h"
20 #include "ide.h"
21 #include "model.h"
22 #include "nvr.h"
23 #include "sound.h"
24 #include "thread.h"
26 #include "plat-midi.h"
27 #include "plat-keyboard.h"
29 #include "win.h"
30 #include "win-ddraw.h"
31 #include "win-ddraw-fs.h"
32 #include "win-d3d.h"
33 #include "win-d3d-fs.h"
34 //#include "win-opengl.h"
36 #ifndef MAPVK_VK_TO_VSC
37 #define MAPVK_VK_TO_VSC 0
38 #endif
40 uint64_t timer_freq;
42 static RAWINPUTDEVICE device;
43 static uint16_t scancode_map[65536];
45 static struct
46 {
47 void (*init)(HWND h);
48 void (*close)();
49 void (*resize)(int x, int y);
50 } vid_apis[2][2] =
51 {
52 {
53 ddraw_init, ddraw_close, NULL,
54 d3d_init, d3d_close, d3d_resize
55 },
56 {
57 ddraw_fs_init, ddraw_fs_close, NULL,
58 d3d_fs_init, d3d_fs_close, NULL
59 },
60 };
62 #define TIMER_1SEC 1
64 int winsizex=640,winsizey=480;
65 int gfx_present[GFX_MAX];
66 #undef cs
67 CRITICAL_SECTION cs;
69 HANDLE mainthreadh;
71 int infocus=1;
73 int drawits=0;
75 int romspresent[ROM_MAX];
76 int quited=0;
78 RECT oldclip;
79 int mousecapture=0;
81 /* Declare Windows procedure */
82 LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
83 LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
85 HWND ghwnd;
87 HINSTANCE hinstance;
89 HMENU menu;
91 extern int updatestatus;
93 int pause=0;
95 static int win_doresize = 0;
97 static int leave_fullscreen_flag = 0;
99 void updatewindowsize(int x, int y)
100 {
101 RECT r;
102 if (vid_resize) return;
104 winsizex=x; winsizey=y;
105 win_doresize = 1;
106 }
108 void releasemouse()
109 {
110 if (mousecapture)
111 {
112 ClipCursor(&oldclip);
113 ShowCursor(TRUE);
114 mousecapture = 0;
115 }
116 }
118 void startblit()
119 {
120 EnterCriticalSection(&cs);
121 }
123 void endblit()
124 {
125 LeaveCriticalSection(&cs);
126 }
128 void leave_fullscreen()
129 {
130 leave_fullscreen_flag = 1;
131 }
133 void mainthread(LPVOID param)
134 {
135 int t = 0;
136 int frames = 0;
137 DWORD old_time, new_time;
139 // Sleep(500);
140 drawits=0;
141 old_time = GetTickCount();
142 while (!quited)
143 {
144 if (updatestatus)
145 {
146 updatestatus = 0;
147 if (status_is_open)
148 SendMessage(status_hwnd, WM_USER, 0, 0);
149 }
150 new_time = GetTickCount();
151 drawits += new_time - old_time;
152 old_time = new_time;
153 if (drawits > 0 && !pause)
154 {
155 drawits-=10; if (drawits>50) drawits=0;
156 runpc();
157 frames++;
158 if (frames >= 200 && nvr_dosave)
159 {
160 frames = 0;
161 nvr_dosave = 0;
162 savenvr();
163 }
164 }
165 else
166 Sleep(1);
168 if (!video_fullscreen && win_doresize)
169 {
170 RECT r;
171 GetWindowRect(ghwnd, &r);
172 MoveWindow(ghwnd, r.left, r.top,
173 winsizex + (GetSystemMetrics(SM_CXFIXEDFRAME) * 2),
174 winsizey + (GetSystemMetrics(SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 1,
175 TRUE);
176 win_doresize = 0;
177 }
179 if (leave_fullscreen_flag)
180 {
181 leave_fullscreen_flag = 0;
182 SendMessage(ghwnd, WM_LEAVEFULLSCREEN, 0, 0);
183 }
184 }
185 }
187 void *thread_create(void (*thread_rout)(void *param), void *param)
188 {
189 return (void *)_beginthread(thread_rout, 0, param);
190 }
192 void thread_kill(void *handle)
193 {
194 TerminateThread(handle, 0);
195 }
197 void thread_sleep(int t)
198 {
199 Sleep(t);
200 }
202 typedef struct win_event_t
203 {
204 HANDLE handle;
205 } win_event_t;
207 event_t *thread_create_event()
208 {
209 win_event_t *event = malloc(sizeof(win_event_t));
211 event->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
213 return (event_t *)event;
214 }
216 void thread_set_event(event_t *_event)
217 {
218 win_event_t *event = (win_event_t *)_event;
220 SetEvent(event->handle);
221 }
223 void thread_reset_event(event_t *_event)
224 {
225 win_event_t *event = (win_event_t *)_event;
227 ResetEvent(event->handle);
228 }
230 int thread_wait_event(event_t *_event, int timeout)
231 {
232 win_event_t *event = (win_event_t *)_event;
234 if (timeout == -1)
235 timeout = INFINITE;
237 if (WaitForSingleObject(event->handle, timeout))
238 return 1;
239 return 0;
240 }
242 void thread_destroy_event(event_t *_event)
243 {
244 win_event_t *event = (win_event_t *)_event;
246 CloseHandle(event->handle);
248 free(event);
249 }
251 static void initmenu(void)
252 {
253 int c;
254 HMENU m;
255 char s[32];
256 m=GetSubMenu(menu,2); /*Settings*/
257 m=GetSubMenu(m,1); /*CD-ROM*/
259 /* Loop through each Windows drive letter and test to see if
260 it's a CDROM */
261 for (c='A';c<='Z';c++)
262 {
263 sprintf(s,"%c:\\",c);
264 if (GetDriveType(s)==DRIVE_CDROM)
265 {
266 sprintf(s, "Host CD/DVD Drive (%c:)", c);
267 AppendMenu(m,MF_STRING,IDM_CDROM_REAL+c,s);
268 }
269 }
270 }
272 void get_executable_name(char *s, int size)
273 {
274 GetModuleFileName(hinstance, s, size);
275 }
277 void set_window_title(char *s)
278 {
279 if (video_fullscreen)
280 return;
281 SetWindowText(ghwnd, s);
282 }
284 uint64_t timer_read()
285 {
286 LARGE_INTEGER qpc_time;
287 QueryPerformanceCounter(&qpc_time);
288 return qpc_time.QuadPart;
289 }
291 /* This is so we can disambiguate scan codes that would otherwise conflict and get
292 passed on incorrectly. */
293 UINT16 convert_scan_code(UINT16 scan_code)
294 {
295 switch (scan_code)
296 {
297 case 0xE001:
298 return 0xF001;
299 case 0xE002:
300 return 0xF002;
301 case 0xE005:
302 return 0xF005;
303 case 0xE006:
304 return 0xF006;
305 case 0xE007:
306 return 0xF007;
307 case 0xE071:
308 return 0xF008;
309 case 0xE072:
310 return 0xF009;
311 case 0xE07F:
312 return 0xF00A;
313 case 0xE0E1:
314 return 0xF00B;
315 case 0xE0EE:
316 return 0xF00C;
317 case 0xE0F1:
318 return 0xF00D;
319 case 0xE0FE:
320 return 0xF00E;
321 case 0xE0EF:
322 return 0xF00F;
324 default:
325 return scan_code;
326 }
327 }
329 void get_registry_key_map()
330 {
331 char *keyName = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout";
332 char *valueName = "Scancode Map";
333 char buf[32768];
334 DWORD bufSize;
335 HKEY hKey;
336 int j;
338 /* First, prepare the default scan code map list which is 1:1.
339 Remappings will be inserted directly into it.
340 65536 bytes so scan codes fit in easily and it's easy to find what each maps too,
341 since each array element is a scan code and provides for E0, etc. ones too. */
342 for (j = 0; j < 65536; j++)
343 scancode_map[j] = convert_scan_code(j);
345 bufSize = 32768;
346 pclog("Preparing scan code map list...\n");
347 /* Get the scan code remappings from:
348 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout */
349 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS)
350 {
351 if(RegQueryValueEx(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS)
352 {
353 UINT32 *bufEx2 = (UINT32 *) buf;
354 int scMapCount = bufEx2[2];
355 pclog("%lu scan code mappings found!\n", scMapCount);
356 if ((bufSize != 0) && (scMapCount != 0))
357 {
358 UINT16 *bufEx = (UINT16 *) (buf + 12);
359 pclog("More than zero scan code mappings found, processing...\n");
360 for (j = 0; j < scMapCount*2; j += 2)
361 {
362 /* Each scan code is 32-bit: 16 bits of remapped scan code,
363 and 16 bits of original scan code. */
364 int scancode_unmapped = bufEx[j + 1];
365 int scancode_mapped = bufEx[j];
367 scancode_mapped = convert_scan_code(scancode_mapped);
369 scancode_map[scancode_unmapped] = scancode_mapped;
370 pclog("Scan code mapping %u detected: %X -> %X\n", scancode_unmapped, scancode_mapped, scancode_map[scancode_unmapped]);
371 }
372 pclog("Done processing!\n");
373 }
374 }
375 RegCloseKey(hKey);
376 }
377 pclog("Done preparing!\n");
378 }
380 int WINAPI WinMain (HINSTANCE hThisInstance,
381 HINSTANCE hPrevInstance,
382 LPSTR lpszArgument,
383 int nFunsterStil)
385 {
386 HWND hwnd; /* This is the handle for our window */
387 MSG messages; /* Here messages to the application are saved */
388 WNDCLASSEX wincl; /* Data structure for the windowclass */
389 int c, d;
390 LARGE_INTEGER qpc_freq;
392 hinstance=hThisInstance;
393 /* The Window structure */
394 wincl.hInstance = hThisInstance;
395 wincl.lpszClassName = szClassName;
396 wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
397 wincl.style = CS_DBLCLKS; /* Catch double-clicks */
398 wincl.cbSize = sizeof (WNDCLASSEX);
400 /* Use default icon and mouse-pointer */
401 wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
402 wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
403 wincl.hCursor = NULL;//LoadCursor (NULL, IDC_ARROW);
404 wincl.lpszMenuName = NULL; /* No menu */
405 wincl.cbClsExtra = 0; /* No extra bytes after the window class */
406 wincl.cbWndExtra = 0; /* structure or the window instance */
407 /* Use Windows's default color as the background of the window */
408 wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
410 /* Register the window class, and if it fails quit the program */
411 if (!RegisterClassEx(&wincl))
412 return 0;
414 wincl.lpszClassName = szSubClassName;
415 wincl.lpfnWndProc = subWindowProcedure; /* This function is called by windows */
417 if (!RegisterClassEx(&wincl))
418 return 0;
420 menu = LoadMenu(hThisInstance, TEXT("MainMenu"));
421 initmenu();
423 /* The class is registered, let's create the program*/
424 hwnd = CreateWindowEx (
425 0, /* Extended possibilites for variation */
426 szClassName, /* Classname */
427 "PCem v8.1", /* Title Text */
428 WS_OVERLAPPEDWINDOW&~WS_SIZEBOX, /* default window */
429 CW_USEDEFAULT, /* Windows decides the position */
430 CW_USEDEFAULT, /* where the window ends up on the screen */
431 640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* The programs width */
432 480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */
433 HWND_DESKTOP, /* The window is a child-window to desktop */
434 menu, /* Menu */
435 hThisInstance, /* Program Instance handler */
436 NULL /* No Window Creation data */
437 );
439 /* Make the window visible on the screen */
440 ShowWindow (hwnd, nFunsterStil);
442 // win_set_window(hwnd);
444 memset(rawinputkey, 0, sizeof(rawinputkey));
445 device.usUsagePage = 0x01;
446 device.usUsage = 0x06;
447 device.dwFlags = RIDEV_NOHOTKEYS;
448 device.hwndTarget = hwnd;
450 if (RegisterRawInputDevices(&device, 1, sizeof(device)))
451 pclog("Raw input registered!\n");
452 else
453 pclog("Raw input registration failed!\n");
455 get_registry_key_map();
457 ghwnd=hwnd;
459 midi_init();
460 atexit(midi_close);
462 initpc();
464 vid_apis[0][vid_api].init(ghwnd);
466 if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE);
467 else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE);
469 if (!cdrom_enabled)
470 CheckMenuItem(menu, IDM_CDROM_DISABLED, MF_CHECKED);
471 else
472 CheckMenuItem(menu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
473 if (vid_resize) CheckMenuItem(menu, IDM_VID_RESIZE, MF_CHECKED);
474 CheckMenuItem(menu, IDM_VID_DDRAW + vid_api, MF_CHECKED);
475 CheckMenuItem(menu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED);
476 // set_display_switch_mode(SWITCH_BACKGROUND);
478 d=romset;
479 for (c=0;c<ROM_MAX;c++)
480 {
481 romset=c;
482 romspresent[c]=loadbios();
483 pclog("romset %i - %i\n", c, romspresent[c]);
484 }
486 for (c = 0; c < ROM_MAX; c++)
487 {
488 if (romspresent[c])
489 break;
490 }
491 if (c == ROM_MAX)
492 {
493 MessageBox(hwnd,"No ROMs present!\nYou must have at least one romset to use PCem.","PCem fatal error",MB_OK);
494 return 0;
495 }
497 romset=d;
498 c=loadbios();
500 if (!c)
501 {
502 if (romset!=-1) MessageBox(hwnd,"Configured romset not available.\nDefaulting to available romset.","PCem error",MB_OK);
503 for (c=0;c<ROM_MAX;c++)
504 {
505 if (romspresent[c])
506 {
507 romset = c;
508 model = model_getmodel(romset);
509 saveconfig();
510 resetpchard();
511 break;
512 }
513 }
514 }
517 for (c = 0; c < GFX_MAX; c++)
518 gfx_present[c] = video_card_available(video_old_to_new(c));
520 if (!video_card_available(video_old_to_new(gfxcard)))
521 {
522 if (romset!=-1) MessageBox(hwnd,"Configured video BIOS not available.\nDefaulting to available romset.","PCem error",MB_OK);
523 for (c = GFX_MAX-1; c >= 0; c--)
524 {
525 if (gfx_present[c])
526 {
527 gfxcard = c;
528 saveconfig();
529 resetpchard();
530 break;
531 }
532 }
533 }
535 loadbios();
537 timeBeginPeriod(1);
539 atexit(releasemouse);
541 // QueryPerformanceFrequency(&counter_base);
542 /// QueryPerformanceCounter(&counter_posold);
543 // counter_posold.QuadPart*=100;
545 InitializeCriticalSection(&cs);
546 mainthreadh=(HANDLE)_beginthread(mainthread,0,NULL);
547 SetThreadPriority(mainthreadh, THREAD_PRIORITY_HIGHEST);
550 updatewindowsize(640, 480);
552 QueryPerformanceFrequency(&qpc_freq);
553 timer_freq = qpc_freq.QuadPart;
555 // focus=1;
556 // setrefresh(100);
558 // ShowCursor(TRUE);
560 /* Run the message loop. It will run until GetMessage() returns 0 */
561 while (!quited)
562 {
563 /* if (infocus)
564 {
565 if (drawits)
566 {
567 drawits--;
568 if (drawits>10) drawits=0;
569 runpc();
570 }
571 //; else
572 // sleep(0);
573 if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END] && mousecapture)
574 {
575 ClipCursor(&oldclip);
576 mousecapture=0;
577 }
578 }*/
580 while (GetMessage(&messages,NULL,0,0) && !quited)
581 {
582 if (messages.message==WM_QUIT) quited=1;
583 TranslateMessage(&messages);
584 DispatchMessage(&messages);
585 if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END] && mousecapture)
586 {
587 ClipCursor(&oldclip);
588 ShowCursor(TRUE);
589 mousecapture=0;
590 }
591 }
593 quited=1;
594 // else
595 // sleep(10);
596 }
598 startblit();
599 // pclog("Sleep 1000\n");
600 Sleep(200);
601 // pclog("TerminateThread\n");
602 TerminateThread(mainthreadh,0);
603 // pclog("Quited? %i\n",quited);
604 // pclog("Closepc\n");
605 closepc();
606 // pclog("dumpregs\n");
608 vid_apis[video_fullscreen][vid_api].close();
610 timeEndPeriod(1);
611 // dumpregs();
612 if (mousecapture)
613 {
614 ClipCursor(&oldclip);
615 ShowCursor(TRUE);
616 }
618 UnregisterClass(szSubClassName, hinstance);
619 UnregisterClass(szClassName, hinstance);
621 // pclog("Ending! %i %i\n",messages.wParam,quited);
622 return messages.wParam;
623 }
625 char openfilestring[260];
626 int getfile(HWND hwnd, char *f, char *fn)
627 {
628 OPENFILENAME ofn; // common dialog box structure
629 BOOL r;
630 DWORD err;
632 // Initialize OPENFILENAME
633 ZeroMemory(&ofn, sizeof(ofn));
634 ofn.lStructSize = sizeof(ofn);
635 ofn.hwndOwner = hwnd;
636 ofn.lpstrFile = openfilestring;
637 //
638 // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
639 // use the contents of szFile to initialize itself.
640 //
641 // ofn.lpstrFile[0] = '\0';
642 strcpy(ofn.lpstrFile,fn);
643 ofn.nMaxFile = sizeof(openfilestring);
644 ofn.lpstrFilter = f;//"All\0*.*\0Text\0*.TXT\0";
645 ofn.nFilterIndex = 1;
646 ofn.lpstrFileTitle = NULL;
647 ofn.nMaxFileTitle = 0;
648 ofn.lpstrInitialDir = NULL;
649 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
651 // Display the Open dialog box.
653 pclog("GetOpenFileName - lpstrFile = %s\n", ofn.lpstrFile);
654 r = GetOpenFileName(&ofn);
655 if (r)
656 {
657 pclog("GetOpenFileName return true\n");
658 return 0;
659 }
660 pclog("GetOpenFileName return false\n");
661 err = CommDlgExtendedError();
662 pclog("CommDlgExtendedError return %04X\n", err);
663 return 1;
664 }
666 int getsfile(HWND hwnd, char *f, char *fn)
667 {
668 OPENFILENAME ofn; // common dialog box structure
669 BOOL r;
670 DWORD err;
672 // Initialize OPENFILENAME
673 ZeroMemory(&ofn, sizeof(ofn));
674 ofn.lStructSize = sizeof(ofn);
675 ofn.hwndOwner = hwnd;
676 ofn.lpstrFile = openfilestring;
677 //
678 // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
679 // use the contents of szFile to initialize itself.
680 //
681 // ofn.lpstrFile[0] = '\0';
682 strcpy(ofn.lpstrFile,fn);
683 ofn.nMaxFile = sizeof(openfilestring);
684 ofn.lpstrFilter = f;//"All\0*.*\0Text\0*.TXT\0";
685 ofn.nFilterIndex = 1;
686 ofn.lpstrFileTitle = NULL;
687 ofn.nMaxFileTitle = 0;
688 ofn.lpstrInitialDir = NULL;
689 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
691 // Display the Open dialog box.
693 pclog("GetSaveFileName - lpstrFile = %s\n", ofn.lpstrFile);
694 r = GetSaveFileName(&ofn);
695 if (r)
696 {
697 pclog("GetSaveFileName return true\n");
698 return 0;
699 }
700 pclog("GetSaveFileName return false\n");
701 err = CommDlgExtendedError();
702 pclog("CommDlgExtendedError return %04X\n", err);
703 return 1;
704 }
709 HHOOK hKeyboardHook;
711 LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
712 {
713 if (nCode < 0 || nCode != HC_ACTION || (!mousecapture && !video_fullscreen))
714 return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam);
716 KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
718 if (p->vkCode == VK_TAB && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab
719 if (p->vkCode == VK_SPACE && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab
720 if((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)) return 1;//disable windows keys
721 if (p->vkCode == VK_ESCAPE && p->flags & LLKHF_ALTDOWN) return 1;//disable alt-escape
722 BOOL bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);//checks ctrl key pressed
723 if (p->vkCode == VK_ESCAPE && bControlKeyDown) return 1; //disable ctrl-escape
725 return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam );
726 }
728 LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
729 {
730 HMENU hmenu;
731 RECT rect;
732 // pclog("Message %i %08X\n",message,message);
733 switch (message)
734 {
735 case WM_CREATE:
736 SetTimer(hwnd, TIMER_1SEC, 1000, NULL);
737 hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
738 break;
740 case WM_COMMAND:
741 // pclog("WM_COMMAND %i\n",LOWORD(wParam));
742 hmenu=GetMenu(hwnd);
743 switch (LOWORD(wParam))
744 {
745 case IDM_FILE_RESET:
746 pause=1;
747 Sleep(100);
748 resetpc();
749 pause=0;
750 break;
751 case IDM_FILE_HRESET:
752 pause=1;
753 Sleep(100);
754 resetpchard();
755 pause=0;
756 break;
757 case IDM_FILE_EXIT:
758 PostQuitMessage (0); /* send a WM_QUIT to the message queue */
759 break;
760 case IDM_DISC_A:
761 if (!getfile(hwnd,"Disc image (*.IMG;*.IMA)\0*.IMG;*.IMA\0All files (*.*)\0*.*\0",discfns[0]))
762 {
763 savedisc(0);
764 loaddisc(0,openfilestring);
765 saveconfig();
766 }
767 break;
768 case IDM_DISC_B:
769 if (!getfile(hwnd,"Disc image (*.IMG;*.IMA)\0*.IMG;*.IMA\0All files (*.*)\0*.*\0",discfns[1]))
770 {
771 savedisc(1);
772 loaddisc(1,openfilestring);
773 saveconfig();
774 }
775 break;
776 case IDM_EJECT_A:
777 savedisc(0);
778 ejectdisc(0);
779 saveconfig();
780 break;
781 case IDM_EJECT_B:
782 savedisc(1);
783 ejectdisc(1);
784 saveconfig();
785 break;
786 case IDM_HDCONF:
787 hdconf_open(hwnd);
788 break;
789 case IDM_CONFIG:
790 config_open(hwnd);
791 break;
792 case IDM_STATUS:
793 status_open(hwnd);
794 break;
796 case IDM_VID_RESIZE:
797 vid_resize=!vid_resize;
798 CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize)?MF_CHECKED:MF_UNCHECKED);
799 if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE);
800 else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE);
801 GetWindowRect(hwnd,&rect);
802 SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED);
803 saveconfig();
804 break;
806 case IDM_VID_DDRAW: case IDM_VID_D3D:
807 startblit();
808 CheckMenuItem(hmenu, IDM_VID_DDRAW + vid_api, MF_UNCHECKED);
809 vid_apis[0][vid_api].close();
810 vid_api = LOWORD(wParam) - IDM_VID_DDRAW;
811 CheckMenuItem(hmenu, IDM_VID_DDRAW + vid_api, MF_CHECKED);
812 vid_apis[0][vid_api].init(ghwnd);
813 endblit();
814 saveconfig();
815 device_force_redraw();
816 break;
818 case IDM_VID_FULLSCREEN:
819 if (video_fullscreen_first)
820 {
821 video_fullscreen_first = 0;
822 MessageBox(hwnd, "Use CTRL + ALT + PAGE DOWN to return to windowed mode", "PCem", MB_OK);
823 }
824 startblit();
825 mouse_close();
826 vid_apis[0][vid_api].close();
827 video_fullscreen = 1;
828 vid_apis[1][vid_api].init(ghwnd);
829 mouse_init();
830 endblit();
831 device_force_redraw();
832 break;
834 case IDM_VID_FS_FULL:
835 case IDM_VID_FS_43:
836 case IDM_VID_FS_SQ:
837 case IDM_VID_FS_INT:
838 CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_UNCHECKED);
839 video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL;
840 CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED);
841 saveconfig();
842 break;
844 case IDM_CDROM_DISABLED:
845 if (cdrom_enabled)
846 {
847 if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
848 break;
849 }
850 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
851 CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED);
852 CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_UNCHECKED);
853 if (cdrom_enabled)
854 {
855 cdrom_enabled = 0;
856 saveconfig();
857 resetpchard();
858 }
859 break;
861 case IDM_CDROM_EMPTY:
862 if (!cdrom_enabled)
863 {
864 if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
865 break;
866 }
867 atapi->exit();
868 ioctl_open(0);
869 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
870 CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
871 cdrom_drive=0;
872 CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED);
873 saveconfig();
874 if (!cdrom_enabled)
875 {
876 cdrom_enabled = 1;
877 saveconfig();
878 resetpchard();
879 }
880 break;
881 default:
882 if (LOWORD(wParam)>=IDM_CDROM_REAL && LOWORD(wParam)<(IDM_CDROM_REAL+100))
883 {
884 if (!cdrom_enabled)
885 {
886 if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
887 break;
888 }
889 atapi->exit();
890 ioctl_open(LOWORD(wParam)-IDM_CDROM_REAL);
891 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
892 CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
893 cdrom_drive = LOWORD(wParam) - IDM_CDROM_REAL;
894 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
895 saveconfig();
896 if (!cdrom_enabled)
897 {
898 cdrom_enabled = 1;
899 saveconfig();
900 resetpchard();
901 }
902 }
903 break;
904 }
905 return 0;
907 case WM_INPUT:
908 {
909 UINT size;
910 RAWINPUT *raw;
912 if (!infocus)
913 break;
915 GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
917 raw = malloc(size);
919 /* Here we read the raw input data for the keyboard */
920 GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER));
922 /* If the input is keyboard, we process it */
923 if (raw->header.dwType == RIM_TYPEKEYBOARD)
924 {
925 const RAWKEYBOARD rawKB = raw->data.keyboard;
926 USHORT scancode = rawKB.MakeCode;
928 // pclog("Keyboard input received: S:%X VK:%X F:%X\n", c, d, e);
930 if (rawKB.VKey == VK_NUMLOCK)
931 {
932 /* This is for proper handling of Pause/Break and Num Lock */
933 scancode = (MapVirtualKey(rawKB.VKey, MAPVK_VK_TO_VSC) | 0x100);
934 }
935 /* If it's not a scan code that starts with 0xE1 */
936 if (!(rawKB.Flags & RI_KEY_E1))
937 {
938 if (rawKB.Flags & RI_KEY_E0)
939 scancode |= (0xE0 << 8);
941 /* Remap it according to the list from the Registry */
942 scancode = scancode_map[scancode];
944 if ((scancode >> 8) == 0xF0)
945 scancode |= 0x100; /* Extended key code in disambiguated format */
946 else if ((scancode >> 8) == 0xE0)
947 scancode |= 0x80; /* Normal extended key code */
949 /* If it's not 0 (therefore not 0xE1, 0xE2, etc),
950 then pass it on to the rawinputkey array */
951 if (!(scancode & 0xf00))
952 rawinputkey[scancode & 0x1ff] = !(rawKB.Flags & RI_KEY_BREAK);
953 }
954 }
955 free(raw);
957 }
958 break;
960 case WM_SETFOCUS:
961 infocus=1;
962 // QueryPerformanceCounter(&counter_posold);
963 // pclog("Set focus!\n");
964 break;
965 case WM_KILLFOCUS:
966 infocus=0;
967 if (mousecapture)
968 {
969 ClipCursor(&oldclip);
970 ShowCursor(TRUE);
971 mousecapture=0;
972 }
973 // pclog("Lost focus!\n");
974 memset(rawinputkey, 0, sizeof(rawinputkey));
975 break;
977 case WM_LBUTTONUP:
978 if (!mousecapture && !video_fullscreen)
979 {
980 RECT pcclip;
982 GetClipCursor(&oldclip);
983 GetWindowRect(hwnd, &pcclip);
984 pcclip.left += GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
985 pcclip.right -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
986 pcclip.top += GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 10;
987 pcclip.bottom -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
988 ClipCursor(&pcclip);
989 mousecapture = 1;
990 ShowCursor(FALSE);
991 }
992 break;
994 case WM_MBUTTONUP:
995 releasemouse();
996 break;
998 case WM_ENTERMENULOOP:
999 // if (key[KEY_ALT] || key[KEY_ALTGR]) return 0;
1000 break;
1002 case WM_SIZE:
1003 winsizex=lParam&0xFFFF;
1004 winsizey=lParam>>16;
1006 if (vid_apis[video_fullscreen][vid_api].resize)
1007 {
1008 startblit();
1009 vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey);
1010 endblit();
1011 }
1013 if (mousecapture)
1014 {
1015 RECT pcclip;
1017 GetWindowRect(hwnd, &pcclip);
1018 pcclip.left += GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
1019 pcclip.right -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
1020 pcclip.top += GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 10;
1021 pcclip.bottom -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
1022 ClipCursor(&pcclip);
1023 }
1024 break;
1026 case WM_TIMER:
1027 if (wParam == TIMER_1SEC)
1028 onesec();
1029 break;
1031 case WM_RESETD3D:
1032 startblit();
1033 if (video_fullscreen)
1034 d3d_fs_reset();
1035 else
1036 d3d_reset();
1037 endblit();
1038 break;
1040 case WM_LEAVEFULLSCREEN:
1041 startblit();
1042 mouse_close();
1043 vid_apis[1][vid_api].close();
1044 video_fullscreen = 0;
1045 vid_apis[0][vid_api].init(ghwnd);
1046 mouse_init();
1047 endblit();
1048 device_force_redraw();
1049 break;
1051 case WM_KEYDOWN:
1052 case WM_SYSKEYDOWN:
1053 case WM_KEYUP:
1054 case WM_SYSKEYUP:
1055 // if (mousecapture)
1056 return 0;
1057 // return DefWindowProc (hwnd, message, wParam, lParam);
1060 case WM_DESTROY:
1061 UnhookWindowsHookEx( hKeyboardHook );
1062 KillTimer(hwnd, TIMER_1SEC);
1063 PostQuitMessage (0); /* send a WM_QUIT to the message queue */
1064 break;
1066 case WM_SYSCOMMAND:
1067 if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0 && (video_fullscreen || mousecapture))
1068 return 0; /*disable ALT key for menu*/
1070 default:
1071 // pclog("Def %08X %i\n",message,message);
1072 return DefWindowProc (hwnd, message, wParam, lParam);
1073 }
1074 return 0;
1075 }
1077 LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1078 {
1079 switch (message)
1080 {
1081 default:
1082 return DefWindowProc(hwnd, message, wParam, lParam);
1083 }
1084 return 0;
1085 }
