PCem

view src/win.c @ 149:82d7f693029b

Pause emulator before resetting emulator after changing CD-ROM type - fixes crash.
author TomW
date Fri Aug 22 19:58:17 2014 +0100
parents 34376c2f2d17
children 55564c65aa15
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 pause = 1;
856 Sleep(100);
857 cdrom_enabled = 0;
858 saveconfig();
859 resetpchard();
860 pause = 0;
861 }
862 break;
864 case IDM_CDROM_EMPTY:
865 if (!cdrom_enabled)
866 {
867 if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
868 break;
869 }
870 atapi->exit();
871 ioctl_open(0);
872 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
873 CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
874 cdrom_drive=0;
875 CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED);
876 saveconfig();
877 if (!cdrom_enabled)
878 {
879 pause = 1;
880 Sleep(100);
881 cdrom_enabled = 1;
882 saveconfig();
883 resetpchard();
884 pause = 0;
885 }
886 break;
887 default:
888 if (LOWORD(wParam)>=IDM_CDROM_REAL && LOWORD(wParam)<(IDM_CDROM_REAL+100))
889 {
890 if (!cdrom_enabled)
891 {
892 if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
893 break;
894 }
895 atapi->exit();
896 ioctl_open(LOWORD(wParam)-IDM_CDROM_REAL);
897 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
898 CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
899 cdrom_drive = LOWORD(wParam) - IDM_CDROM_REAL;
900 CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
901 saveconfig();
902 if (!cdrom_enabled)
903 {
904 pause = 1;
905 Sleep(100);
906 cdrom_enabled = 1;
907 saveconfig();
908 resetpchard();
909 pause = 0;
910 }
911 }
912 break;
913 }
914 return 0;
916 case WM_INPUT:
917 {
918 UINT size;
919 RAWINPUT *raw;
921 if (!infocus)
922 break;
924 GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
926 raw = malloc(size);
928 /* Here we read the raw input data for the keyboard */
929 GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER));
931 /* If the input is keyboard, we process it */
932 if (raw->header.dwType == RIM_TYPEKEYBOARD)
933 {
934 const RAWKEYBOARD rawKB = raw->data.keyboard;
935 USHORT scancode = rawKB.MakeCode;
937 // pclog("Keyboard input received: S:%X VK:%X F:%X\n", c, d, e);
939 if (rawKB.VKey == VK_NUMLOCK)
940 {
941 /* This is for proper handling of Pause/Break and Num Lock */
942 scancode = (MapVirtualKey(rawKB.VKey, MAPVK_VK_TO_VSC) | 0x100);
943 }
944 /* If it's not a scan code that starts with 0xE1 */
945 if (!(rawKB.Flags & RI_KEY_E1))
946 {
947 if (rawKB.Flags & RI_KEY_E0)
948 scancode |= (0xE0 << 8);
950 /* Remap it according to the list from the Registry */
951 scancode = scancode_map[scancode];
953 if ((scancode >> 8) == 0xF0)
954 scancode |= 0x100; /* Extended key code in disambiguated format */
955 else if ((scancode >> 8) == 0xE0)
956 scancode |= 0x80; /* Normal extended key code */
958 /* If it's not 0 (therefore not 0xE1, 0xE2, etc),
959 then pass it on to the rawinputkey array */
960 if (!(scancode & 0xf00))
961 rawinputkey[scancode & 0x1ff] = !(rawKB.Flags & RI_KEY_BREAK);
962 }
963 }
964 free(raw);
966 }
967 break;
969 case WM_SETFOCUS:
970 infocus=1;
971 // QueryPerformanceCounter(&counter_posold);
972 // pclog("Set focus!\n");
973 break;
974 case WM_KILLFOCUS:
975 infocus=0;
976 if (mousecapture)
977 {
978 ClipCursor(&oldclip);
979 ShowCursor(TRUE);
980 mousecapture=0;
981 }
982 // pclog("Lost focus!\n");
983 memset(rawinputkey, 0, sizeof(rawinputkey));
984 break;
986 case WM_LBUTTONUP:
987 if (!mousecapture && !video_fullscreen)
988 {
989 RECT pcclip;
991 GetClipCursor(&oldclip);
992 GetWindowRect(hwnd, &pcclip);
993 pcclip.left += GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
994 pcclip.right -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
995 pcclip.top += GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 10;
996 pcclip.bottom -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
997 ClipCursor(&pcclip);
998 mousecapture = 1;
999 ShowCursor(FALSE);
1001 break;
1003 case WM_MBUTTONUP:
1004 releasemouse();
1005 break;
1007 case WM_ENTERMENULOOP:
1008 // if (key[KEY_ALT] || key[KEY_ALTGR]) return 0;
1009 break;
1011 case WM_SIZE:
1012 winsizex=lParam&0xFFFF;
1013 winsizey=lParam>>16;
1015 if (vid_apis[video_fullscreen][vid_api].resize)
1017 startblit();
1018 vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey);
1019 endblit();
1022 if (mousecapture)
1024 RECT pcclip;
1026 GetWindowRect(hwnd, &pcclip);
1027 pcclip.left += GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
1028 pcclip.right -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
1029 pcclip.top += GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 10;
1030 pcclip.bottom -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10;
1031 ClipCursor(&pcclip);
1033 break;
1035 case WM_TIMER:
1036 if (wParam == TIMER_1SEC)
1037 onesec();
1038 break;
1040 case WM_RESETD3D:
1041 startblit();
1042 if (video_fullscreen)
1043 d3d_fs_reset();
1044 else
1045 d3d_reset();
1046 endblit();
1047 break;
1049 case WM_LEAVEFULLSCREEN:
1050 startblit();
1051 mouse_close();
1052 vid_apis[1][vid_api].close();
1053 video_fullscreen = 0;
1054 vid_apis[0][vid_api].init(ghwnd);
1055 mouse_init();
1056 endblit();
1057 device_force_redraw();
1058 break;
1060 case WM_KEYDOWN:
1061 case WM_SYSKEYDOWN:
1062 case WM_KEYUP:
1063 case WM_SYSKEYUP:
1064 // if (mousecapture)
1065 return 0;
1066 // return DefWindowProc (hwnd, message, wParam, lParam);
1069 case WM_DESTROY:
1070 UnhookWindowsHookEx( hKeyboardHook );
1071 KillTimer(hwnd, TIMER_1SEC);
1072 PostQuitMessage (0); /* send a WM_QUIT to the message queue */
1073 break;
1075 case WM_SYSCOMMAND:
1076 if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0 && (video_fullscreen || mousecapture))
1077 return 0; /*disable ALT key for menu*/
1079 default:
1080 // pclog("Def %08X %i\n",message,message);
1081 return DefWindowProc (hwnd, message, wParam, lParam);
1083 return 0;
1086 LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1088 switch (message)
1090 default:
1091 return DefWindowProc(hwnd, message, wParam, lParam);
1093 return 0;