Several cleanups and fixes here and there. Updated (Windows) UI to properly handle resets and changes in Settings. Updated to no longer scan for roms at startup.
1109 lines
29 KiB
C
1109 lines
29 KiB
C
/*
|
|
* VARCem Virtual Archaelogical Computer EMulator.
|
|
* An emulator of (mostly) x86-based PC systems and devices,
|
|
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
|
* spanning the era between 1981 and 1995.
|
|
*
|
|
* This file is part of the VARCem Project.
|
|
*
|
|
* Implement the user Interface module.
|
|
*
|
|
* Version: @(#)win_ui.c 1.0.3 2018/03/02
|
|
*
|
|
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
|
* Miran Grca, <mgrca8@gmail.com>
|
|
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
|
*
|
|
* Copyright 2017,2018 Fred N. van Kempen.
|
|
* Copyright 2016-2018 Miran Grca.
|
|
* Copyright 2008-2018 Sarah Walker.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the:
|
|
*
|
|
* Free Software Foundation, Inc.
|
|
* 59 Temple Place - Suite 330
|
|
* Boston, MA 02111-1307
|
|
* USA.
|
|
*/
|
|
#define UNICODE
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <wchar.h>
|
|
#include "../emu.h"
|
|
#include "../config.h"
|
|
#include "../device.h"
|
|
#include "../keyboard.h"
|
|
#include "../mouse.h"
|
|
#include "../video/video.h"
|
|
#include "../video/vid_ega.h" // for update_overscan
|
|
#include "../plat.h"
|
|
#include "../plat_midi.h"
|
|
#include "../ui.h"
|
|
#include "win.h"
|
|
#include "win_d3d.h"
|
|
|
|
|
|
#define TIMER_1SEC 1 /* ID of the one-second timer */
|
|
|
|
|
|
/* Platform Public data, specific. */
|
|
HWND hwndMain, /* application main window */
|
|
hwndRender; /* machine render window */
|
|
HMENU menuMain; /* application main menu */
|
|
HICON hIcon[512]; /* icon data loaded from resources */
|
|
RECT oldclip; /* mouse rect */
|
|
int infocus = 1;
|
|
int rctrl_is_lalt = 0;
|
|
|
|
char openfilestring[260];
|
|
WCHAR wopenfilestring[260];
|
|
|
|
|
|
/* Local data. */
|
|
static wchar_t wTitle[512];
|
|
static RAWINPUTDEVICE device;
|
|
static HHOOK hKeyboardHook;
|
|
static int hook_enabled = 0;
|
|
static int save_window_pos = 0;
|
|
|
|
|
|
static int vis = -1;
|
|
|
|
/* Set host cursor visible or not. */
|
|
void
|
|
show_cursor(int val)
|
|
{
|
|
if (val == vis)
|
|
return;
|
|
|
|
if (val == 0) {
|
|
while (1) {
|
|
if (ShowCursor(FALSE) < 0) break;
|
|
}
|
|
} else {
|
|
ShowCursor(TRUE);
|
|
}
|
|
|
|
vis = val;
|
|
}
|
|
|
|
|
|
HICON
|
|
LoadIconEx(PCTSTR pszIconName)
|
|
{
|
|
return((HICON)LoadImage(hinstance, pszIconName, IMAGE_ICON,
|
|
16, 16, LR_SHARED));
|
|
}
|
|
|
|
|
|
#if 0
|
|
static void
|
|
win_menu_update(void)
|
|
{
|
|
menuMain = LoadMenu(hinstance, L"MainMenu"));
|
|
|
|
menuSBAR = LoadMenu(hinstance, L"StatusBarMenu");
|
|
|
|
initmenu();
|
|
|
|
SetMenu(hwndMain, menu);
|
|
|
|
win_title_update = 1;
|
|
}
|
|
#endif
|
|
|
|
|
|
static void
|
|
video_toggle_option(HMENU h, int *val, int id)
|
|
{
|
|
startblit();
|
|
video_wait_for_blit();
|
|
*val ^= 1;
|
|
CheckMenuItem(h, id, *val ? MF_CHECKED : MF_UNCHECKED);
|
|
endblit();
|
|
config_save();
|
|
device_force_redraw();
|
|
}
|
|
|
|
|
|
static void
|
|
ResetAllMenus(void)
|
|
{
|
|
#ifndef DEV_BRANCH
|
|
/* FIXME: until we fix these.. --FvK */
|
|
EnableMenuItem(menuMain, IDM_CONFIG_LOAD, MF_DISABLED);
|
|
EnableMenuItem(menuMain, IDM_CONFIG_SAVE, MF_DISABLED);
|
|
#endif
|
|
|
|
CheckMenuItem(menuMain, IDM_ACTION_RCTRL_IS_LALT, MF_UNCHECKED);
|
|
|
|
CheckMenuItem(menuMain, IDM_UPDATE_ICONS, MF_UNCHECKED);
|
|
|
|
#ifdef ENABLE_LOG_TOGGLES
|
|
# ifdef ENABLE_BUSLOGIC_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_BUSLOGIC, MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_CDROM_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_CDROM, MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_D86F_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_D86F, MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_FDC_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_FDC, MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_IDE_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_IDE, MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_SERIAL_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_SERIAL, MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_NIC_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_NIC, MF_UNCHECKED);
|
|
# endif
|
|
#endif
|
|
|
|
CheckMenuItem(menuMain, IDM_VID_FORCE43, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_OVERSCAN, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_INVERT, MF_UNCHECKED);
|
|
|
|
CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_DDRAW+0, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_DDRAW+1, MF_UNCHECKED);
|
|
#ifdef USE_VNC
|
|
CheckMenuItem(menuMain, IDM_VID_DDRAW+2, MF_UNCHECKED);
|
|
#endif
|
|
#ifdef USE_VNC
|
|
CheckMenuItem(menuMain, IDM_VID_DDRAW+3, MF_UNCHECKED);
|
|
#endif
|
|
CheckMenuItem(menuMain, IDM_VID_FS_FULL+0, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_FS_FULL+1, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_FS_FULL+2, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_FS_FULL+3, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_FS_FULL+4, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_REMEMBER, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_SCALE_1X+0, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_SCALE_1X+1, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_SCALE_1X+2, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_SCALE_1X+3, MF_UNCHECKED);
|
|
|
|
CheckMenuItem(menuMain, IDM_VID_CGACON, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+0, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+1, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+2, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+0, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+1, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+2, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+3, MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+4, MF_UNCHECKED);
|
|
|
|
CheckMenuItem(menuMain, IDM_ACTION_RCTRL_IS_LALT, rctrl_is_lalt ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
CheckMenuItem(menuMain, IDM_UPDATE_ICONS, update_icons ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
#ifdef ENABLE_LOG_TOGGLES
|
|
# ifdef ENABLE_BUSLOGIC_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_BUSLOGIC, buslogic_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_CDROM_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_CDROM, cdrom_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_D86F_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_D86F, d86f_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_FDC_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_FDC, fdc_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_IDE_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_IDE, ide_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_SERIAL_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_SERIAL, serial_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
# ifdef ENABLE_NIC_LOG
|
|
CheckMenuItem(menuMain, IDM_LOG_NIC, nic_do_log?MF_CHECKED:MF_UNCHECKED);
|
|
# endif
|
|
#endif
|
|
|
|
CheckMenuItem(menuMain, IDM_VID_FORCE43, force_43?MF_CHECKED:MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_OVERSCAN, enable_overscan?MF_CHECKED:MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_INVERT, invert_display ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
if (vid_resize)
|
|
CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_CHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_DDRAW+vid_api, MF_CHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_REMEMBER, window_remember?MF_CHECKED:MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_SCALE_1X+scale, MF_CHECKED);
|
|
|
|
CheckMenuItem(menuMain, IDM_VID_CGACON, vid_cga_contrast?MF_CHECKED:MF_UNCHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+video_graytype, MF_CHECKED);
|
|
CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+video_grayscale, MF_CHECKED);
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL bControlKeyDown;
|
|
KBDLLHOOKSTRUCT *p;
|
|
|
|
if (nCode < 0 || nCode != HC_ACTION)
|
|
return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam));
|
|
|
|
p = (KBDLLHOOKSTRUCT*)lParam;
|
|
|
|
/* disable alt-tab */
|
|
if (p->vkCode == VK_TAB && p->flags & LLKHF_ALTDOWN) return(1);
|
|
|
|
/* disable alt-space */
|
|
if (p->vkCode == VK_SPACE && p->flags & LLKHF_ALTDOWN) return(1);
|
|
|
|
/* disable alt-escape */
|
|
if (p->vkCode == VK_ESCAPE && p->flags & LLKHF_ALTDOWN) return(1);
|
|
|
|
/* disable windows keys */
|
|
if((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)) return(1);
|
|
|
|
/* checks ctrl key pressed */
|
|
bControlKeyDown = GetAsyncKeyState(VK_CONTROL)>>((sizeof(SHORT)*8)-1);
|
|
|
|
/* disable ctrl-escape */
|
|
if (p->vkCode == VK_ESCAPE && bControlKeyDown) return(1);
|
|
|
|
return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam));
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HMENU hmenu;
|
|
RECT rect;
|
|
int sb_borders[3];
|
|
int temp_x, temp_y;
|
|
|
|
switch (message) {
|
|
case WM_CREATE:
|
|
SetTimer(hwnd, TIMER_1SEC, 1000, NULL);
|
|
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
|
|
LowLevelKeyboardProc,
|
|
GetModuleHandle(NULL), 0);
|
|
hook_enabled = 1;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
hmenu = GetMenu(hwnd);
|
|
switch (LOWORD(wParam)) {
|
|
case IDM_ACTION_SCREENSHOT:
|
|
take_screenshot();
|
|
break;
|
|
|
|
case IDM_ACTION_HRESET:
|
|
pc_reset(1);
|
|
break;
|
|
|
|
case IDM_ACTION_RESET_CAD:
|
|
pc_reset(0);
|
|
break;
|
|
|
|
case IDM_ACTION_EXIT:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case IDM_ACTION_CTRL_ALT_ESC:
|
|
keyboard_send_cae();
|
|
break;
|
|
|
|
case IDM_ACTION_RCTRL_IS_LALT:
|
|
rctrl_is_lalt ^= 1;
|
|
CheckMenuItem(hmenu, IDM_ACTION_RCTRL_IS_LALT, rctrl_is_lalt ? MF_CHECKED : MF_UNCHECKED);
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_ACTION_PAUSE:
|
|
plat_pause(dopause ^ 1);
|
|
CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
|
|
case IDM_CONFIG:
|
|
plat_pause(1);
|
|
if (win_settings_open(hwnd, 1) == 2)
|
|
pc_reset_hard_init();
|
|
plat_pause(0);
|
|
break;
|
|
|
|
case IDM_ABOUT:
|
|
AboutDialogCreate(hwnd);
|
|
break;
|
|
|
|
case IDM_STATUS:
|
|
StatusWindowCreate(hwnd);
|
|
break;
|
|
|
|
case IDM_UPDATE_ICONS:
|
|
update_icons ^= 1;
|
|
CheckMenuItem(hmenu, IDM_UPDATE_ICONS, update_icons ? MF_CHECKED : MF_UNCHECKED);
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_RESIZE:
|
|
vid_resize = !vid_resize;
|
|
CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize)? MF_CHECKED : MF_UNCHECKED);
|
|
GetWindowRect(hwnd, &rect);
|
|
|
|
if (vid_resize)
|
|
SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW) | WS_VISIBLE);
|
|
else
|
|
SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX) | WS_VISIBLE);
|
|
|
|
SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders);
|
|
|
|
/* Main Window. */
|
|
MoveWindow(hwnd, rect.left, rect.top,
|
|
unscaled_size_x + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2),
|
|
unscaled_size_y + (GetSystemMetrics(SM_CYEDGE) * 2) + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 17 + sb_borders[1] + 1,
|
|
TRUE);
|
|
|
|
/* Render window. */
|
|
MoveWindow(hwndRender, 0, 0, unscaled_size_x, unscaled_size_y, TRUE);
|
|
GetWindowRect(hwndRender, &rect);
|
|
|
|
/* Status bar. */
|
|
MoveWindow(hwndSBAR,
|
|
0, rect.bottom + GetSystemMetrics(SM_CYEDGE),
|
|
unscaled_size_x, 17, TRUE);
|
|
|
|
if (mouse_capture) {
|
|
GetWindowRect(hwndRender, &rect);
|
|
|
|
ClipCursor(&rect);
|
|
}
|
|
|
|
if (vid_resize) {
|
|
CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED);
|
|
CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED);
|
|
scale = 1;
|
|
}
|
|
EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED);
|
|
EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED);
|
|
EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED);
|
|
EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED);
|
|
doresize = 1;
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_REMEMBER:
|
|
window_remember = !window_remember;
|
|
CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED);
|
|
GetWindowRect(hwnd, &rect);
|
|
if (window_remember) {
|
|
window_x = rect.left;
|
|
window_y = rect.top;
|
|
window_w = rect.right - rect.left;
|
|
window_h = rect.bottom - rect.top;
|
|
}
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_DDRAW:
|
|
case IDM_VID_D3D:
|
|
#ifdef USE_VNC
|
|
case IDM_VID_VNC:
|
|
#endif
|
|
#ifdef USE_RDP
|
|
case IDM_VID_RDP:
|
|
#endif
|
|
CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_UNCHECKED);
|
|
plat_setvid(LOWORD(wParam) - IDM_VID_DDRAW);
|
|
CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_CHECKED);
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_FULLSCREEN:
|
|
/* pclog("enter full screen though menu\n"); */
|
|
plat_setfullscreen(1);
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_FS_FULL:
|
|
case IDM_VID_FS_43:
|
|
case IDM_VID_FS_SQ:
|
|
case IDM_VID_FS_INT:
|
|
case IDM_VID_FS_KEEPRATIO:
|
|
CheckMenuItem(hmenu, IDM_VID_FS_FULL+video_fullscreen_scale, MF_UNCHECKED);
|
|
video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL;
|
|
CheckMenuItem(hmenu, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED);
|
|
device_force_redraw();
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_SCALE_1X:
|
|
case IDM_VID_SCALE_2X:
|
|
case IDM_VID_SCALE_3X:
|
|
case IDM_VID_SCALE_4X:
|
|
CheckMenuItem(hmenu, IDM_VID_SCALE_1X+scale, MF_UNCHECKED);
|
|
scale = LOWORD(wParam) - IDM_VID_SCALE_1X;
|
|
CheckMenuItem(hmenu, IDM_VID_SCALE_1X+scale, MF_CHECKED);
|
|
device_force_redraw();
|
|
video_force_resize_set(1);
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_FORCE43:
|
|
video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43);
|
|
video_force_resize_set(1);
|
|
break;
|
|
|
|
case IDM_VID_INVERT:
|
|
video_toggle_option(hmenu, &invert_display, IDM_VID_INVERT);
|
|
break;
|
|
|
|
case IDM_VID_OVERSCAN:
|
|
update_overscan = 1;
|
|
video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN);
|
|
video_force_resize_set(1);
|
|
break;
|
|
|
|
case IDM_VID_CGACON:
|
|
vid_cga_contrast ^= 1;
|
|
CheckMenuItem(hmenu, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED);
|
|
cgapal_rebuild();
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_GRAYCT_601:
|
|
case IDM_VID_GRAYCT_709:
|
|
case IDM_VID_GRAYCT_AVE:
|
|
CheckMenuItem(hmenu, IDM_VID_GRAYCT_601+video_graytype, MF_UNCHECKED);
|
|
video_graytype = LOWORD(wParam) - IDM_VID_GRAYCT_601;
|
|
CheckMenuItem(hmenu, IDM_VID_GRAYCT_601+video_graytype, MF_CHECKED);
|
|
device_force_redraw();
|
|
config_save();
|
|
break;
|
|
|
|
case IDM_VID_GRAY_RGB:
|
|
case IDM_VID_GRAY_MONO:
|
|
case IDM_VID_GRAY_AMBER:
|
|
case IDM_VID_GRAY_GREEN:
|
|
case IDM_VID_GRAY_WHITE:
|
|
CheckMenuItem(hmenu, IDM_VID_GRAY_RGB+video_grayscale, MF_UNCHECKED);
|
|
video_grayscale = LOWORD(wParam) - IDM_VID_GRAY_RGB;
|
|
CheckMenuItem(hmenu, IDM_VID_GRAY_RGB+video_grayscale, MF_CHECKED);
|
|
device_force_redraw();
|
|
config_save();
|
|
break;
|
|
|
|
#ifdef ENABLE_LOG_TOGGLES
|
|
# ifdef ENABLE_BUSLOGIC_LOG
|
|
case IDM_LOG_BUSLOGIC:
|
|
buslogic_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_BUSLOGIC, buslogic_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
|
|
# ifdef ENABLE_CDROM_LOG
|
|
case IDM_LOG_CDROM:
|
|
cdrom_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_CDROM, cdrom_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
|
|
# ifdef ENABLE_D86F_LOG
|
|
case IDM_LOG_D86F:
|
|
d86f_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_D86F, d86f_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
|
|
# ifdef ENABLE_FDC_LOG
|
|
case IDM_LOG_FDC:
|
|
fdc_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_FDC, fdc_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
|
|
# ifdef ENABLE_IDE_LOG
|
|
case IDM_LOG_IDE:
|
|
ide_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_IDE, ide_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
|
|
# ifdef ENABLE_SERIAL_LOG
|
|
case IDM_LOG_SERIAL:
|
|
serial_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_SERIAL, serial_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
|
|
# ifdef ENABLE_NIC_LOG
|
|
case IDM_LOG_NIC:
|
|
nic_do_log ^= 1;
|
|
CheckMenuItem(hmenu, IDM_LOG_NIC, nic_do_log ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef ENABLE_LOG_BREAKPOINT
|
|
case IDM_LOG_BREAKPOINT:
|
|
pclog("---- LOG BREAKPOINT ----\n");
|
|
break;
|
|
#endif
|
|
|
|
#ifdef ENABLE_VRAM_DUMP
|
|
case IDM_DUMP_VRAM:
|
|
svga_dump_vram();
|
|
break;
|
|
#endif
|
|
|
|
case IDM_CONFIG_LOAD:
|
|
plat_pause(1);
|
|
if (!file_dlg_st(hwnd, IDS_2160, "", 0) &&
|
|
(ui_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051) == IDYES)) {
|
|
pc_reload(wopenfilestring);
|
|
ResetAllMenus();
|
|
}
|
|
plat_pause(0);
|
|
break;
|
|
|
|
case IDM_CONFIG_SAVE:
|
|
plat_pause(1);
|
|
if (! file_dlg_st(hwnd, IDS_2160, "", 1)) {
|
|
config_write(wopenfilestring);
|
|
}
|
|
plat_pause(0);
|
|
break;
|
|
}
|
|
return(0);
|
|
|
|
case WM_INPUT:
|
|
keyboard_handle(lParam, infocus);
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
infocus = 1;
|
|
if (! hook_enabled) {
|
|
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
|
|
LowLevelKeyboardProc,
|
|
GetModuleHandle(NULL),
|
|
0);
|
|
hook_enabled = 1;
|
|
}
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
infocus = 0;
|
|
plat_mouse_capture(0);
|
|
if (hook_enabled) {
|
|
UnhookWindowsHookEx(hKeyboardHook);
|
|
hook_enabled = 0;
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
if (! video_fullscreen)
|
|
plat_mouse_capture(1);
|
|
break;
|
|
|
|
case WM_MBUTTONUP:
|
|
if (mouse_get_buttons() < 3)
|
|
plat_mouse_capture(0);
|
|
break;
|
|
|
|
case WM_ENTERMENULOOP:
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders);
|
|
|
|
temp_x = (lParam & 0xFFFF);
|
|
temp_y = (lParam >> 16) - (21 + sb_borders[1]);
|
|
if (temp_x < 1)
|
|
temp_x = 1;
|
|
if (temp_y < 1)
|
|
temp_y = 1;
|
|
|
|
if ((temp_x != scrnsz_x) || (temp_y != scrnsz_y))
|
|
doresize = 1;
|
|
|
|
scrnsz_x = temp_x;
|
|
scrnsz_y = temp_y;
|
|
|
|
MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE);
|
|
|
|
GetWindowRect(hwndRender, &rect);
|
|
|
|
/* Status bar. */
|
|
MoveWindow(hwndSBAR,
|
|
0, rect.bottom + GetSystemMetrics(SM_CYEDGE),
|
|
scrnsz_x, 17, TRUE);
|
|
|
|
plat_vidsize(scrnsz_x, scrnsz_y);
|
|
|
|
MoveWindow(hwndSBAR, 0, scrnsz_y + 6, scrnsz_x, 17, TRUE);
|
|
|
|
if (mouse_capture) {
|
|
GetWindowRect(hwndRender, &rect);
|
|
|
|
ClipCursor(&rect);
|
|
}
|
|
|
|
if (window_remember) {
|
|
GetWindowRect(hwnd, &rect);
|
|
window_x = rect.left;
|
|
window_y = rect.top;
|
|
window_w = rect.right - rect.left;
|
|
window_h = rect.bottom - rect.top;
|
|
save_window_pos = 1;
|
|
}
|
|
|
|
config_save();
|
|
break;
|
|
|
|
case WM_MOVE:
|
|
/* If window is not resizable, then tell the main thread to
|
|
resize it, as sometimes, moves can mess up the window size. */
|
|
if (!vid_resize)
|
|
doresize = 1;
|
|
|
|
if (window_remember) {
|
|
GetWindowRect(hwnd, &rect);
|
|
window_x = rect.left;
|
|
window_y = rect.top;
|
|
window_w = rect.right - rect.left;
|
|
window_h = rect.bottom - rect.top;
|
|
save_window_pos = 1;
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
if (wParam == TIMER_1SEC) {
|
|
pc_onesec();
|
|
}
|
|
break;
|
|
|
|
case WM_RESETD3D:
|
|
startblit();
|
|
if (video_fullscreen)
|
|
d3d_reset_fs();
|
|
else
|
|
d3d_reset();
|
|
endblit();
|
|
break;
|
|
|
|
case WM_LEAVEFULLSCREEN:
|
|
/* pclog("leave full screen on window message\n"); */
|
|
plat_setfullscreen(0);
|
|
config_save();
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
case WM_KEYUP:
|
|
case WM_SYSKEYDOWN:
|
|
case WM_SYSKEYUP:
|
|
return(0);
|
|
|
|
case WM_DESTROY:
|
|
UnhookWindowsHookEx(hKeyboardHook);
|
|
KillTimer(hwnd, TIMER_1SEC);
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_SHOWSETTINGS:
|
|
plat_pause(1);
|
|
if (win_settings_open(hwnd, 1) == 2)
|
|
pc_reset_hard_init();
|
|
plat_pause(0);
|
|
break;
|
|
|
|
case WM_PAUSE:
|
|
plat_pause(dopause ^ 1);
|
|
CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED);
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
/*
|
|
* Disable ALT key *ALWAYS*,
|
|
* I don't think there's any use for
|
|
* reaching the menu that way.
|
|
*/
|
|
if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0) {
|
|
return 0; /*disable ALT key for menu*/
|
|
}
|
|
|
|
default:
|
|
return(DefWindowProc(hwnd, message, wParam, lParam));
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
SubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return(DefWindowProc(hwnd, message, wParam, lParam));
|
|
}
|
|
|
|
|
|
int
|
|
ui_init(int nCmdShow)
|
|
{
|
|
WCHAR title[200];
|
|
WNDCLASSEX wincl; /* buffer for main window's class */
|
|
MSG messages; /* received-messages buffer */
|
|
HWND hwnd = 0; /* handle for our window */
|
|
HACCEL haccel; /* handle to accelerator table */
|
|
int ret;
|
|
|
|
#if 0
|
|
/* We should have an application-wide at_exit catcher. */
|
|
atexit(plat_mouse_capture);
|
|
#endif
|
|
|
|
if (settings_only) {
|
|
if (! pc_init_modules()) {
|
|
/* Dang, no ROMs found at all! */
|
|
MessageBox(hwnd,
|
|
plat_get_string(IDS_2056),
|
|
plat_get_string(IDS_2050),
|
|
MB_OK | MB_ICONERROR);
|
|
return(6);
|
|
}
|
|
|
|
win_settings_open(NULL, 0);
|
|
return(0);
|
|
}
|
|
|
|
/* Create our main window's class and register it. */
|
|
wincl.hInstance = hinstance;
|
|
wincl.lpszClassName = CLASS_NAME;
|
|
wincl.lpfnWndProc = MainWindowProcedure;
|
|
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
|
|
wincl.cbSize = sizeof(WNDCLASSEX);
|
|
wincl.hIcon = LoadIcon(hinstance, (LPCTSTR)100);
|
|
wincl.hIconSm = LoadIcon(hinstance, (LPCTSTR)100);
|
|
wincl.hCursor = NULL;
|
|
wincl.lpszMenuName = NULL;
|
|
wincl.cbClsExtra = 0;
|
|
wincl.cbWndExtra = 0;
|
|
wincl.hbrBackground = CreateSolidBrush(RGB(0,0,0));
|
|
if (! RegisterClassEx(&wincl))
|
|
return(2);
|
|
wincl.lpszClassName = SUB_CLASS_NAME;
|
|
wincl.lpfnWndProc = SubWindowProcedure;
|
|
if (! RegisterClassEx(&wincl))
|
|
return(2);
|
|
|
|
/* Load the Window Menu(s) from the resources. */
|
|
menuMain = LoadMenu(hinstance, MENU_NAME);
|
|
|
|
/* Now create our main window. */
|
|
mbstowcs(title, emu_version, sizeof_w(title));
|
|
hwnd = CreateWindowEx (
|
|
0, /* no extended possibilites */
|
|
CLASS_NAME, /* class name */
|
|
title, /* Title Text */
|
|
(WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX) | DS_3DLOOK,
|
|
CW_USEDEFAULT, /* Windows decides the position */
|
|
CW_USEDEFAULT, /* where window ends up on the screen */
|
|
scrnsz_x+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* width */
|
|
scrnsz_y+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */
|
|
HWND_DESKTOP, /* window is a child to desktop */
|
|
menuMain, /* menu */
|
|
hinstance, /* Program Instance handler */
|
|
NULL); /* no Window Creation data */
|
|
hwndMain = hwnd;
|
|
|
|
ui_window_title(title);
|
|
|
|
/* Set up main window for resizing if configured. */
|
|
if (vid_resize)
|
|
SetWindowLongPtr(hwnd, GWL_STYLE,
|
|
(WS_OVERLAPPEDWINDOW));
|
|
else
|
|
SetWindowLongPtr(hwnd, GWL_STYLE,
|
|
(WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX));
|
|
|
|
/* Move to the last-saved position if needed. */
|
|
if (window_remember)
|
|
MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE);
|
|
|
|
/* Reset all menus to their defaults. */
|
|
ResetAllMenus();
|
|
|
|
/* Make the window visible on the screen. */
|
|
ShowWindow(hwnd, nCmdShow);
|
|
|
|
/* Load the accelerator table */
|
|
haccel = LoadAccelerators(hinstance, ACCEL_NAME);
|
|
if (haccel == NULL) {
|
|
MessageBox(hwndMain,
|
|
plat_get_string(IDS_2153),
|
|
plat_get_string(IDS_2050),
|
|
MB_OK | MB_ICONERROR);
|
|
return(3);
|
|
}
|
|
|
|
/* Initialize the input (keyboard, mouse, game) module. */
|
|
device.usUsagePage = 0x01;
|
|
device.usUsage = 0x06;
|
|
device.dwFlags = RIDEV_NOHOTKEYS;
|
|
device.hwndTarget = hwnd;
|
|
if (! RegisterRawInputDevices(&device, 1, sizeof(device))) {
|
|
MessageBox(hwndMain,
|
|
plat_get_string(IDS_2154),
|
|
plat_get_string(IDS_2050),
|
|
MB_OK | MB_ICONERROR);
|
|
return(4);
|
|
}
|
|
keyboard_getkeymap();
|
|
|
|
/* Initialize the mouse module. */
|
|
win_mouse_init();
|
|
|
|
/* Create the status bar window. */
|
|
StatusBarCreate(hwndMain, IDC_STATUS, hinstance);
|
|
|
|
/*
|
|
* Before we can create the Render window, we first have
|
|
* to prepare some other things that it depends on.
|
|
*/
|
|
ghMutex = CreateMutex(NULL, FALSE, L"VARCem.BlitMutex");
|
|
|
|
/* Create the Machine Rendering window. */
|
|
hwndRender = CreateWindow(L"STATIC", NULL, WS_CHILD|SS_BITMAP,
|
|
0, 0, 1, 1, hwnd, NULL, hinstance, NULL);
|
|
MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE);
|
|
|
|
/* That looks good, now continue setting up the machine. */
|
|
switch (pc_init_modules()) {
|
|
case -1: /* General failure during init, give up. */
|
|
return(6);
|
|
|
|
case 0: /* Configuration error, user wants to exit. */
|
|
return(0);
|
|
|
|
case 1: /* All good. */
|
|
break;
|
|
|
|
case 2: /* Configuration error, user wants to re-config. */
|
|
if (win_settings_open(NULL, 0)) {
|
|
/* Save the new configuration to file. */
|
|
config_save();
|
|
|
|
/* Remind them to restart. */
|
|
ui_msgbox(MBX_INFO, (wchar_t *)IDS_2062);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/* Initialize the configured Video API. */
|
|
if (! plat_setvid(vid_api)) {
|
|
MessageBox(hwnd,
|
|
plat_get_string(IDS_2095),
|
|
plat_get_string(IDS_2050),
|
|
MB_OK | MB_ICONERROR);
|
|
return(5);
|
|
}
|
|
|
|
/* Initialize the rendering window, or fullscreen. */
|
|
if (start_in_fullscreen)
|
|
plat_setfullscreen(1);
|
|
|
|
/* Set up the current window size. */
|
|
plat_resize(scrnsz_x, scrnsz_y);
|
|
|
|
/* Fire up the machine. */
|
|
pc_reset_hard();
|
|
|
|
/* Set the PAUSE mode depending on the renderer. */
|
|
plat_pause(0);
|
|
|
|
/* If so requested via the command line, inform the
|
|
* application that started us of our HWND, using the
|
|
* the hWnd and unique ID the application has given
|
|
* us. */
|
|
if (source_hwnd)
|
|
SendMessage((HWND) (uintptr_t) source_hwnd, WM_SENDHWND, (WPARAM) unique_id, (LPARAM) hwndMain);
|
|
|
|
/*
|
|
* Everything has been configured, and all seems to work,
|
|
* so now it is time to start the main thread to do some
|
|
* real work, and we will hang in here, dealing with the
|
|
* UI until we're done.
|
|
*/
|
|
do_start();
|
|
|
|
/* Run the message loop. It will run until GetMessage() returns 0 */
|
|
while (! quited) {
|
|
ret = GetMessage(&messages, NULL, 0, 0);
|
|
if ((ret == 0) || quited) break;
|
|
|
|
if (ret == -1) {
|
|
fatal("ret is -1\n");
|
|
}
|
|
|
|
if (messages.message == WM_QUIT) {
|
|
quited = 1;
|
|
break;
|
|
}
|
|
|
|
if (! TranslateAccelerator(hwnd, haccel, &messages)) {
|
|
TranslateMessage(&messages);
|
|
DispatchMessage(&messages);
|
|
}
|
|
|
|
if (mouse_capture && keyboard_ismsexit()) {
|
|
/* Release the in-app mouse. */
|
|
plat_mouse_capture(0);
|
|
}
|
|
|
|
if (video_fullscreen && keyboard_isfsexit()) {
|
|
/* Signal "exit fullscreen mode". */
|
|
/* pclog("leave full screen though key combination\n"); */
|
|
plat_setfullscreen(0);
|
|
}
|
|
}
|
|
|
|
timeEndPeriod(1);
|
|
|
|
if (mouse_capture)
|
|
plat_mouse_capture(0);
|
|
|
|
/* Close down the emulator. */
|
|
do_stop();
|
|
|
|
UnregisterClass(SUB_CLASS_NAME, hinstance);
|
|
UnregisterClass(CLASS_NAME, hinstance);
|
|
|
|
win_mouse_close();
|
|
|
|
return(messages.wParam);
|
|
}
|
|
|
|
|
|
wchar_t *
|
|
ui_window_title(wchar_t *s)
|
|
{
|
|
if (! video_fullscreen) {
|
|
if (s != NULL)
|
|
wcscpy(wTitle, s);
|
|
else
|
|
s = wTitle;
|
|
|
|
SetWindowText(hwndMain, s);
|
|
} else {
|
|
if (s == NULL)
|
|
s = wTitle;
|
|
}
|
|
|
|
return(s);
|
|
}
|
|
|
|
|
|
/* We should have the language ID as a parameter. */
|
|
void
|
|
plat_pause(int p)
|
|
{
|
|
static wchar_t oldtitle[512];
|
|
wchar_t title[512];
|
|
|
|
/* If un-pausing, as the renderer if that's OK. */
|
|
if (p == 0)
|
|
p = get_vidpause();
|
|
|
|
/* If already so, done. */
|
|
if (dopause == p) return;
|
|
|
|
if (p) {
|
|
wcscpy(oldtitle, ui_window_title(NULL));
|
|
wcscpy(title, oldtitle);
|
|
wcscat(title, L" - PAUSED -");
|
|
ui_window_title(title);
|
|
} else {
|
|
ui_window_title(oldtitle);
|
|
}
|
|
|
|
dopause = p;
|
|
|
|
/* Update the actual menu. */
|
|
CheckMenuItem(menuMain, IDM_ACTION_PAUSE,
|
|
(dopause) ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
|
|
|
|
/* Tell the UI about a new screen resolution. */
|
|
void
|
|
plat_resize(int x, int y)
|
|
{
|
|
int sb_borders[3];
|
|
RECT r;
|
|
|
|
#if 0
|
|
pclog("PLAT: VID[%d,%d] resizing to %dx%d\n", video_fullscreen, vid_api, x, y);
|
|
#endif
|
|
/* First, see if we should resize the UI window. */
|
|
if (!vid_resize) {
|
|
video_wait_for_blit();
|
|
SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders);
|
|
GetWindowRect(hwndMain, &r);
|
|
MoveWindow(hwndRender, 0, 0, x, y, TRUE);
|
|
|
|
GetWindowRect(hwndMain, &r);
|
|
MoveWindow(hwndMain, r.left, r.top,
|
|
x + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2),
|
|
y + (GetSystemMetrics(SM_CYEDGE) * 2) + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 17 + sb_borders[1] + 1,
|
|
TRUE);
|
|
GetWindowRect(hwndMain, &r);
|
|
|
|
MoveWindow(hwndRender, 0, 0, x, y, TRUE);
|
|
|
|
if (mouse_capture) {
|
|
GetWindowRect(hwndRender, &r);
|
|
ClipCursor(&r);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
plat_mouse_capture(int on)
|
|
{
|
|
RECT rect;
|
|
|
|
if (on && !mouse_capture) {
|
|
/* Enable the in-app mouse. */
|
|
GetClipCursor(&oldclip);
|
|
GetWindowRect(hwndRender, &rect);
|
|
ClipCursor(&rect);
|
|
/* pclog("mouse capture off, hide cursor\n"); */
|
|
show_cursor(0);
|
|
mouse_capture = 1;
|
|
} else if (!on && mouse_capture) {
|
|
/* Disable the in-app mouse. */
|
|
ClipCursor(&oldclip);
|
|
/* pclog("mouse capture on, show cursor\n"); */
|
|
show_cursor(-1);
|
|
|
|
mouse_capture = 0;
|
|
}
|
|
}
|