diff --git a/src/86box.h b/src/86box.h index 1b926a40b..69435018f 100644 --- a/src/86box.h +++ b/src/86box.h @@ -6,9 +6,9 @@ * * This file is part of the 86Box distribution. * - * Main emulator include file. + * Main include file for the application. * - * Version: @(#)86box.h 1.0.4 2017/10/16 + * Version: @(#)86box.h 1.0.6 2017/10/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -23,6 +23,19 @@ /* Configuration values. */ #define SERIAL_MAX 2 #define PARALLEL_MAX 1 +#define SCREEN_RES_X 640 +#define SCREEN_RES_Y 480 + +/* Version info. */ +#define EMU_NAME "86Box" +#define EMU_NAME_W L"86Box" +#define EMU_VERSION "2.00" +#define EMU_VERSION_W L"2.00" + +/* Filename and pathname info. */ +#define CONFIG_FILE_W L"86box.cfg" +#define NVR_PATH L"nvr" +#define SCREENSHOT_PATH L"screenshots" #if defined(ENABLE_BUSLOGIC_LOG) || \ @@ -38,57 +51,56 @@ # define ENABLE_LOG_COMMANDS 1 #endif -#define EMU_VERSION "2.00" -#define EMU_VERSION_W L"2.00" -#define EMU_NAME "86Box" -#define EMU_NAME_W L"86Box" - -#define CONFIG_FILE_W L"86box.cfg" - -#define NVR_PATH L"nvr" -#define SCREENSHOT_PATH L"screenshots" - - -/* Global variables. */ -#ifdef ENABLE_LOG_TOGGLES -extern int buslogic_do_log; -extern int cdrom_do_log; -extern int d86f_do_log; -extern int fdc_do_log; -extern int ide_do_log; -extern int serial_do_log; -extern int nic_do_log; -#endif - -extern int suppress_overscan; -extern int invert_display; -extern int scale; -extern int vid_api; -extern int vid_resize; -extern int winsizex,winsizey; - -extern wchar_t exe_path[1024]; -extern wchar_t cfg_path[1024]; - -extern uint64_t timer_freq; /* plat.h */ -extern int infocus; /* plat.h */ - -extern int dump_on_exit; -extern int start_in_fullscreen; -extern int window_w, window_h, window_x, window_y, window_remember; - - -/* Function prototypes. */ #ifdef __cplusplus extern "C" { #endif +/* Global variables. */ +extern int dump_on_exit; /* (O) dump regs on exit*/ +extern int start_in_fullscreen; /* (O) start in fullscreen */ + +extern int window_w, window_h, /* (C) window size and */ + window_x, window_y, /* position info */ + window_remember, + vid_resize, /* (C) allow resizing */ + invert_display, /* (C) invert the display */ + suppress_overscan; /* (C) suppress overscans */ +extern int scale; /* (C) screen scale factor */ +extern int vid_api; /* (C) video renderer */ +extern int vid_cga_contrast, /* (C) video */ + video_fullscreen, /* (C) video */ + video_fullscreen_first, /* (C) video */ + video_fullscreen_scale, /* (C) video */ + enable_overscan, /* (C) video */ + force_43, /* (C) video */ + video_speed; /* (C) video */ + + +#ifdef ENABLE_LOG_TOGGLES +extern int buslogic_do_log; +extern int cdrom_do_log; +extern int d86f_do_log; +extern int fdc_do_log; +extern int ide_do_log; +extern int serial_do_log; +extern int nic_do_log; +#endif + +extern wchar_t exe_path[1024]; /* path (dir) of executable */ +extern wchar_t cfg_path[1024]; /* path (dir) of user data */ +extern int scrnsz_x, /* current screen size, X */ + scrnsz_y; /* current screen size, Y */ + + +/* Function prototypes. */ extern void pclog(const char *format, ...); extern void fatal(const char *format, ...); +extern void set_screen_size(int x, int y); +extern void set_screen_size_natural(void); extern int pc_init_modules(void); extern int pc_init(int argc, wchar_t *argv[]); -extern void pc_close(void); +extern void pc_close(void *threadid); extern void pc_reset_hard_close(void); extern void pc_reset_hard_init(void); extern void pc_reset_hard(void); @@ -97,7 +109,9 @@ extern void pc_full_speed(void); extern void pc_speed_changed(void); extern void pc_send_cad(void); extern void pc_send_cae(void); -extern void pc_run(void); +extern void pc_thread(void *param); +extern void pc_start(void); +extern void pc_onesec(void); #ifdef __cplusplus } diff --git a/src/config.c b/src/config.c index 6476c7efd..8ba1cf5fa 100644 --- a/src/config.c +++ b/src/config.c @@ -8,7 +8,7 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.22 2017/10/16 + * Version: @(#)config.c 1.0.24 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -101,8 +101,31 @@ typedef struct { } +/* Commandline options. */ +int dump_on_exit = 0; /* (O) dump regs on exit */ +int start_in_fullscreen = 0; /* (O) start in fullscreen */ + +/* Configuration values. */ +int window_w, window_h, /* (C) window size and */ + window_x, window_y, /* position info */ + window_remember, + vid_resize, /* (C) allow resizing */ + invert_display, /* (C) invert the display */ + suppress_overscan = 0; /* (C) suppress overscans */ +int scale = 0; /* (C) screen scale factor */ +int vid_api = 0; /* (C) video renderer */ +int vid_cga_contrast = 0, /* (C) video */ + video_fullscreen = 0, /* (C) video */ + video_fullscreen_scale = 0, /* (C) video */ + video_fullscreen_first = 0, /* (C) video */ + enable_overscan = 0, /* (C) video */ + force_43 = 0, /* (C) video */ + video_speed = 0; /* (C) video */ + + wchar_t config_file_default[256]; + static list_t config_head; @@ -416,23 +439,8 @@ load_general(void) vid_resize = !!config_get_int(cat, "vid_resize", 0); memset(temp, '\0', sizeof(temp)); - p = config_get_string(cat, "vid_renderer", "d3d9"); - if (p != NULL) - strcpy(temp, p); - if (! strcmp(temp, "ddraw")) - vid_api = 0; - else if (! strcmp(temp, "d3d9")) - vid_api = 1; -#ifdef USE_VNC - else if (! strcmp(temp, "vnc")) - vid_api = 2; -#endif -#ifdef USE_RDP - else if (! strcmp(temp, "rdp")) - vid_api = 3; -#endif - else - vid_api = 1; /* default to d3d9 on invalid values */ + p = config_get_string(cat, "vid_renderer", "default"); + vid_api = plat_vidapi(p); config_delete_var(cat, "vid_api"); video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); diff --git a/src/config.h b/src/config.h index 257bdd1b7..2a6960b87 100644 --- a/src/config.h +++ b/src/config.h @@ -8,7 +8,7 @@ * * Configuration file handler header. * - * Version: @(#)config.h 1.0.4 2017/10/16 + * Version: @(#)config.h 1.0.5 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, diff --git a/src/ibm.h b/src/ibm.h index 185b20b05..2c7a2a9f7 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -567,8 +567,6 @@ uint32_t svga_color_transform(uint32_t color); extern "C" { #endif -extern void onesec(void); - extern int checkio(int port); extern void codegen_block_end(void); extern void codegen_reset(void); @@ -608,9 +606,4 @@ extern void x87_reset(void); #endif -/* Configuration values. */ -#define SERIAL_MAX 2 -#define PARALLEL_MAX 1 - - #endif /*EMU_IBM_H*/ diff --git a/src/machine/machine_at_scat.c b/src/machine/machine_at_scat.c index b06fad779..17f4797c6 100644 --- a/src/machine/machine_at_scat.c +++ b/src/machine/machine_at_scat.c @@ -10,7 +10,7 @@ * * Re-worked version based on the 82C235 datasheet and errata. * - * Version: @(#)at_scat.c 1.0.3 2017/10/16 + * Version: @(#)at_scat.c 1.0.4 2017/10/18 * * Authors: Original by GreatPsycho for PCem. * Fred N. van Kempen, @@ -30,7 +30,7 @@ #include "machine.h" -#define SCAT_DEBUG 2 +#define SCAT_DEBUG 1 #define SCAT_DMA_WS_CTL 0x01 #define SCAT_VERSION 0x40 @@ -177,12 +177,10 @@ set_xms_bound(uint8_t val) 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } else { -#if 0 for (i=0; i<6; i++) mem_mapping_disable(&scat_shadowram_mapping[i]); if (mem_size > 1024) mem_mapping_enable(&ram_high_mapping); -#endif if (scat_xms_bound > max_xms) scat_xms_bound = max_xms; @@ -280,10 +278,8 @@ ems_state(int state) } else { mem_mapping_set_exec(&scat_mapping[i], ram+base_addr); mem_mapping_disable(&scat_mapping[i]); -#if 0 if (i < 24) mem_mapping_enable(&scat_top_mapping[i]); -#endif } } } @@ -491,7 +487,6 @@ ics_write(uint8_t idx, uint8_t val) break; case SCAT_EMS_CTL: -pclog("SCAT: EMSctrl(%02x)\n", val); if (val & 0x40) { if (val & 1) { io_sethandler(0x0218, 3, @@ -527,24 +522,18 @@ pclog("SCAT: EMSctrl(%02x)\n", val); case SCAT_DRAM_CONFIG: if ((scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0) { -pclog("SCAT: 0\n"); if ((val & 0x0f) == 3) { -pclog("SCAT: 3\n"); if (mem_size > 1024) mem_mapping_disable(&ram_high_mapping); for (idx=0; idx<6; idx++) mem_mapping_enable(&scat_shadowram_mapping[idx]); } else { -pclog("SCAT: 0\n"); for (idx=0; idx<6; idx++) mem_mapping_disable(&scat_shadowram_mapping[idx]); -#if 0 if (mem_size > 1024) mem_mapping_enable(&ram_high_mapping); -#endif } } else { -pclog("SCAT: 1\n"); for (idx=0; idx<6; idx++) mem_mapping_disable(&scat_shadowram_mapping[idx]); if (mem_size > 1024) @@ -688,8 +677,6 @@ scat_init(void) */ pclog("SCAT: mem_size=%d\n", mem_size); - -#if 0 /* Create the 32 EMS page frame mappings for 256-640K. */ for (i=0; i<24; i++) { mem_mapping_add(&scat_top_mapping[i], @@ -698,12 +685,9 @@ scat_init(void) ems_pgwr, NULL, NULL, mem_size > 256+(i<<4) ? ram+0x40000+(i<<14) : NULL, MEM_MAPPING_INTERNAL, NULL); -// mem_mapping_enable(&scat_top_mapping[i]); - mem_mapping_disable(&scat_top_mapping[i]); + mem_mapping_enable(&scat_top_mapping[i]); } -#endif -#if 0 /* Re-map the 128K at A0000 (video BIOS) to above 16MB+top. */ mem_mapping_add(&scat_A000_mapping, 0xA0000, 0x20000, @@ -712,9 +696,7 @@ scat_init(void) ram+0xA0000, MEM_MAPPING_INTERNAL, NULL); mem_mapping_disable(&scat_A000_mapping); -#endif -#if 0 /* Create 32 page frames for EMS, each 16K. */ for (i=0; i<32; i++) { scat_ems[i].regs_2x8 = 0xff; @@ -727,9 +709,8 @@ scat_init(void) 0, &scat_ems[i]); mem_mapping_disable(&scat_mapping[i]); } -#endif -// for (i=4; i<10; i++) isram[i] = 0; + for (i=4; i<10; i++) isram[i] = 0; /* Re-map the BIOS ROM (C0000-FFFFF) area. */ for (i=12; i<16; i++) { @@ -741,7 +722,6 @@ scat_init(void) 0, NULL); } -#if 0 for (i=0; i<6; i++) { mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i<<16), 0x10000, @@ -750,7 +730,6 @@ scat_init(void) mem_size >= 1024 ? ram+get_addr(0x100000+(i<<16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); } -#endif set_xms_bound(0); shadow_state_update(); diff --git a/src/mouse.c b/src/mouse.c index 567fba71a..aee1dca46 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -8,7 +8,7 @@ * * Common driver module for MOUSE devices. * - * Version: @(#)mouse.c 1.0.9 2017/10/09 + * Version: @(#)mouse.c 1.0.10 2017/10/17 * * Authors: Sarah Walker, * Miran Grca, @@ -26,6 +26,7 @@ #include "device.h" #include "mouse.h" #include "machine/machine.h" +#include "plat_mouse.h" static mouse_t mouse_none = { @@ -81,6 +82,24 @@ mouse_emu_close(void) } +void +mouse_process(void) +{ + static int poll_delay = 2; + int x, y, z; + + if (--poll_delay) return; + + mouse_poll_host(); + + mouse_get_mickeys(&x, &y, &z); + + mouse_poll(x, y, z, mouse_buttons); + + poll_delay = 2; +} + + void mouse_poll(int x, int y, int z, int b) { diff --git a/src/pc.c b/src/pc.c index 5a88e5b49..f7e3fd3a5 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Emulation core dispatcher. * - * Version: @(#)pc.c 1.0.28 2017/10/16 + * Version: @(#)pc.c 1.0.29 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -77,30 +77,44 @@ #include "plat_mouse.h" -int window_w, window_h, window_x, window_y, window_remember; -int dump_on_exit = 0; -int start_in_fullscreen = 0; +/* Statistics. */ +extern int mmuflush, + readlnum, + writelnum; + + +/* Statistics. */ +int sndcount = 0; +int sreadlnum, + swritelnum, + segareads, + segawrites, + scycles_lost; +float mips, flops; +int cycles_lost = 0; // video +int insc = 0; // cpu +int emu_fps = 0, fps; // video +int framecount; + int CPUID; -int vid_resize, vid_api; int output; int atfullspeed; -int cycles_lost = 0; -int clockrate; -int insc = 0; -float mips, flops; -int framecount, fps; -int win_title_update = 0; -int status_update_needed = 0; -int pollmouse_delay = 2; -int mousecapture; -int suppress_overscan = 0; int cpuspeed2; -wchar_t exe_path[1024]; -wchar_t cfg_path[1024]; +int clockrate; + +int gfx_present[GFX_MAX]; // should not be here + +wchar_t exe_path[1024]; /* path (dir) of executable */ +wchar_t cfg_path[1024]; /* path (dir) of user data */ +int scrnsz_x = SCREEN_RES_X, /* current screen size, X */ + scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ +int title_update; +int mousecapture; +int64_t main_time; -extern int mmuflush; -extern int readlnum,writelnum; +static int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ + unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */ /* Log something to the logfile or stdout. */ @@ -149,6 +163,95 @@ fatal(const char *format, ...) } +void +set_screen_size(int x, int y) +{ + int owsx = scrnsz_x; + int owsy = scrnsz_y; + int temp_overscan_x = overscan_x; + int temp_overscan_y = overscan_y; + double dx, dy, dtx, dty; + int efscrnsz_y; + + /* Make sure we keep usable values. */ + pclog("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); + if (x < 320) x = 320; + if (y < 200) y = 200; + if (x > 2048) x = 2048; + if (y > 2048) y = 2048; + + /* Save the new values as "real" (unscaled) resolution. */ + unscaled_size_x = x; + efscrnsz_y = y; + + if (suppress_overscan) + temp_overscan_x = temp_overscan_y = 0; + + if (force_43) { + dx = (double)x; + dtx = (double)temp_overscan_x; + + dy = (double)y; + dty = (double)temp_overscan_y; + + /* Account for possible overscan. */ + if (temp_overscan_y == 16) { + /* CGA */ + dy = (((dx - dtx) / 4.0) * 3.0) + dty; + } else if (temp_overscan_y < 16) { + /* MDA/Hercules */ + dy = (x / 4.0) * 3.0; + } else { + if (enable_overscan) { + /* EGA/(S)VGA with overscan */ + dy = (((dx - dtx) / 4.0) * 3.0) + dty; + } else { + /* EGA/(S)VGA without overscan */ + dy = (x / 4.0) * 3.0; + } + } + unscaled_size_y = (int)dy; + } else { + unscaled_size_y = efscrnsz_y; + } + + switch(scale) { + case 0: /* 50% */ + scrnsz_x = (unscaled_size_x>>1); + scrnsz_y = (unscaled_size_y>>1); + break; + + case 1: /* 100% */ + scrnsz_x = unscaled_size_x; + scrnsz_y = unscaled_size_y; + break; + + case 2: /* 150% */ + scrnsz_x = ((unscaled_size_x*3)>>1); + scrnsz_y = ((unscaled_size_y*3)>>1); + break; + + case 3: /* 200% */ + scrnsz_x = (unscaled_size_x<<1); + scrnsz_y = (unscaled_size_y<<1); + break; + } + + /* If the resolution has changed, let the main thread handle it. */ + if ((owsx != scrnsz_x) || (owsy != scrnsz_y)) + doresize = 1; + else + doresize = 0; +} + + +void +set_screen_size_natural(void) +{ + set_screen_size(unscaled_size_x, unscaled_size_y); +} + + /* * Perform initial startup of the PC. * @@ -312,8 +415,7 @@ pc_init_modules(void) int c, i; pclog("Scanning for ROM images:\n"); - c = 0; - for (i=0; iexit(i); @@ -640,134 +767,216 @@ pc_close(void) /* - * Run the actual configured PC. + * The main thread runs the actual emulator code. + * + * We basically run until the upper layers terminate us, by + * setting the variable 'quited' there to 1. We get a pointer + * to that variable as our function argument. */ -int framecountx=0; -int sndcount=0; -int sreadlnum,swritelnum,segareads,segawrites, scycles_lost; -int serial_fifo_read, serial_fifo_write; -int emu_fps = 0; - -static wchar_t wmachine[2048]; -static wchar_t wcpu[2048]; - - -static void -pollmouse(void) -{ - int x, y, z; - - if (--pollmouse_delay) return; - - pollmouse_delay = 2; - - mouse_poll_host(); - - mouse_get_mickeys(&x, &y, &z); - - mouse_poll(x, y, z, mouse_buttons); -} - - void -pc_run(void) +pc_thread(void *param) { - wchar_t temp[200]; - int done = 0; + wchar_t temp[200], wcpu[2048]; + wchar_t wmachine[2048]; + uint64_t start_time, end_time; + uint32_t old_time, new_time; + int status_update_needed; + int done, drawits, frames; + int *quitp = (int *)param; + int framecountx; - startblit(); - clockrate = machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed; - - if (is386) { -#ifdef USE_DYNAREC - if (cpu_use_dynarec) - exec386_dynarec(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); - else + pclog("PC: starting main thread...\n"); + + main_time = 0; + framecountx = 0; + status_update_needed = title_update = 1; + old_time = plat_get_ticks(); + done = drawits = frames = 0; + while (! *quitp) { + /* Update the Stat(u)s window with the current info. */ + if (status_update_needed) { +#if 1 + pclog("Updating STATS window..\n"); +// ui_status_update(); #endif - exec386(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); - } else if (AT) { - exec386(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); - } else { - execx86(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); - } + status_update_needed = 0; + } - keyboard_process(); + /* See if it is time to run a frame of code. */ + new_time = plat_get_ticks(); + drawits += (new_time - old_time); + old_time = new_time; + if (drawits > 0 && !dopause) { + /* Yes, so do one frame now. */ + start_time = plat_timer_read(); + drawits -= 10; + if (drawits > 50) + drawits = 0; - pollmouse(); + /* Run a block of code. */ + startblit(); + clockrate = machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed; - if (joystick_type != 7) - joystick_poll(); + if (is386) { +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + exec386_dynarec(clockrate/100); + else +#endif + exec386(clockrate/100); + } else if (AT) { + exec386(clockrate/100); + } else { + execx86(clockrate/100); + } - endblit(); + keyboard_process(); - framecountx++; - framecount++; - if (framecountx >= 100) { - framecountx = 0; - mips = (float)insc/1000000.0f; - insc = 0; - flops = (float)fpucount/1000000.0f; - fpucount = 0; - sreadlnum = readlnum; - swritelnum = writelnum; - segareads = egareads; - segawrites = egawrites; - scycles_lost = cycles_lost; + mouse_process(); + + joystick_process(); + + endblit(); + + /* Done with this frame, update statistics. */ + framecount++; + if (++framecountx >= 100) { + framecountx = 0; + + /* FIXME: all this should go into a "stats" struct! */ + mips = (float)insc/1000000.0f; + insc = 0; + flops = (float)fpucount/1000000.0f; + fpucount = 0; + sreadlnum = readlnum; + swritelnum = writelnum; + segareads = egareads; + segawrites = egawrites; + scycles_lost = cycles_lost; #ifdef USE_DYNAREC - cpu_recomp_blocks_latched = cpu_recomp_blocks; - cpu_recomp_ins_latched = cpu_state.cpu_recomp_ins; - cpu_recomp_full_ins_latched = cpu_recomp_full_ins; - cpu_new_blocks_latched = cpu_new_blocks; - cpu_recomp_flushes_latched = cpu_recomp_flushes; - cpu_recomp_evicted_latched = cpu_recomp_evicted; - cpu_recomp_reuse_latched = cpu_recomp_reuse; - cpu_recomp_removed_latched = cpu_recomp_removed; - cpu_reps_latched = cpu_reps; - cpu_notreps_latched = cpu_notreps; + cpu_recomp_blocks_latched = cpu_recomp_blocks; + cpu_recomp_ins_latched = cpu_state.cpu_recomp_ins; + cpu_recomp_full_ins_latched = cpu_recomp_full_ins; + cpu_new_blocks_latched = cpu_new_blocks; + cpu_recomp_flushes_latched = cpu_recomp_flushes; + cpu_recomp_evicted_latched = cpu_recomp_evicted; + cpu_recomp_reuse_latched = cpu_recomp_reuse; + cpu_recomp_removed_latched = cpu_recomp_removed; + cpu_reps_latched = cpu_reps; + cpu_notreps_latched = cpu_notreps; - cpu_recomp_blocks = 0; - cpu_state.cpu_recomp_ins = 0; - cpu_recomp_full_ins = 0; - cpu_new_blocks = 0; - cpu_recomp_flushes = 0; - cpu_recomp_evicted = 0; - cpu_recomp_reuse = 0; - cpu_recomp_removed = 0; - cpu_reps = 0; - cpu_notreps = 0; + cpu_recomp_blocks = 0; + cpu_state.cpu_recomp_ins = 0; + cpu_recomp_full_ins = 0; + cpu_new_blocks = 0; + cpu_recomp_flushes = 0; + cpu_recomp_evicted = 0; + cpu_recomp_reuse = 0; + cpu_recomp_removed = 0; + cpu_reps = 0; + cpu_notreps = 0; #endif - status_update_needed = 1; - readlnum = writelnum = 0; - egareads = egawrites = 0; - cycles_lost = 0; - mmuflush = 0; - emu_fps = frames; - frames = 0; - } + readlnum = writelnum = 0; + egareads = egawrites = 0; + cycles_lost = 0; + mmuflush = 0; + emu_fps = frames; + frames = 0; - if (win_title_update) { - mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); - mbstowcs(wcpu, machines[machine].cpu[cpu_manufacturer].cpus[cpu].name, - strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu].name)+1); - swprintf(temp, sizeof_w(temp), L"%ls v%ls - %i%% - %ls - %ls - %ls", - EMU_NAME_W, EMU_VERSION_W, fps, wmachine, wcpu, - (!mousecapture) ? plat_get_string(IDS_2077) + /* We need a Status window update now. */ + status_update_needed = 1; + } + + if (title_update) { + mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); + mbstowcs(wcpu, machines[machine].cpu[cpu_manufacturer].cpus[cpu].name, + strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu].name)+1); + swprintf(temp, sizeof_w(temp), + L"%ls v%ls - %i%% - %ls - %ls - %ls", + EMU_NAME_W,EMU_VERSION_W,fps,wmachine,wcpu, + (!mousecapture) ? plat_get_string(IDS_2077) : ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079))); - ui_window_title(temp); - win_title_update = 0; + ui_window_title(temp); + + title_update = 0; + } + + /* One more frame done! */ + done++; + + /* Every 200 frames we save the machine status. */ + if (++frames >= 200 && nvr_dosave) { + nvr_save(); + nvr_dosave = 0; + frames = 0; + } + + end_time = plat_timer_read(); + main_time += (end_time - start_time); + } else { + /* Just so we dont overload the host OS. */ + plat_delay_ms(1); + } + + /* If needed, hand a screen resize. */ + if (!video_fullscreen && doresize && (scrnsz_x>0) && (scrnsz_y>0)) { +#if 1 + plat_resize(scrnsz_x, scrnsz_y); +#else + SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM)sb_borders); + GetWindowRect(hwndMain, &r); + MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE); + GetWindowRect(hwndRender, &r); + MoveWindow(hwndSBAR, + 0, r.bottom+GetSystemMetrics(SM_CYEDGE), + scrnsz_x, 17, TRUE); + GetWindowRect(hwndMain, &r); + + MoveWindow(hwndMain, r.left, r.top, + scrnsz_x+(GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2), + scrnsz_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); + + if (mousecapture) { + GetWindowRect(hwndRender, &r); + ClipCursor(&r); + } +#endif + + doresize = 0; + } + + /* If requested, leave full-screen mode. */ + if (leave_fullscreen_flag) { +#if 1 + pclog("Leaving full-screen mode..\n"); +// plat_fullscreen(0); +#else + SendMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); +#endif + leave_fullscreen_flag = 0; + } + +#if 0 + /* Do we really need this all the time? */ + if (video_fullscreen && infocus) + SetCursorPos(9999, 9999); +#endif } - done++; + pclog("PC: main thread done.\n"); } +/* Handler for the 1-second timer to refresh the window title. */ void -onesec(void) +pc_onesec(void) { fps = framecount; framecount = 0; - win_title_update = 1; + + title_update = 1; } diff --git a/src/plat.h b/src/plat.h index 9b9f27eb3..c62a9899c 100644 --- a/src/plat.h +++ b/src/plat.h @@ -8,7 +8,7 @@ * * Define the various platform support functions. * - * Version: @(#)plat.h 1.0.9 2017/10/16 + * Version: @(#)plat.h 1.0.11 2017/10/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -33,7 +33,14 @@ extern "C" { #endif /* Global variables residing in the platform module. */ -GLOBAL int dopause; +GLOBAL int dopause, /* system is paused */ + doresize, /* screen resize requested */ + quited, /* system exit requested */ + leave_fullscreen_flag; /* windowed-mode requested */ +GLOBAL uint64_t timer_freq; +//GLOBAL int efwinsizey; +GLOBAL int infocus; +GLOBAL int mousecapture; /* System-related functions. */ @@ -52,6 +59,10 @@ extern uint64_t plat_timer_read(void); extern uint32_t plat_get_ticks(void); extern void plat_delay_ms(uint32_t count); extern void plat_pause(int p); +extern int plat_vidapi(char *name); +extern int plat_setvid(int api); +extern void plat_setfullscreen(int on); +extern void plat_resize(int max_x, int max_y); /* Return the size (in wchar's) of a wchar_t array. */ @@ -71,7 +82,6 @@ extern wchar_t *plat_get_string_from_string(char *str); /* Platform-specific device support. */ extern uint8_t host_cdrom_drive_available[26]; extern uint8_t host_cdrom_drive_available_num; -extern uint32_t cdrom_capacity; extern void cdrom_init_host_drives(void); extern void cdrom_eject(uint8_t id); @@ -109,8 +119,6 @@ extern int thread_release_mutex(mutex_t *mutex); /* Other stuff. */ extern void startblit(void); extern void endblit(void); -extern void updatewindowsize(int x, int y); -extern void uws_natural(void); extern void leave_fullscreen(void); extern void take_screenshot(void); diff --git a/src/plat_joystick.h b/src/plat_joystick.h index aecb3537c..ecb80168e 100644 --- a/src/plat_joystick.h +++ b/src/plat_joystick.h @@ -4,66 +4,66 @@ #ifdef __cplusplus extern "C" { #endif - void joystick_init(); - void joystick_close(); - void joystick_poll(); - - typedef struct plat_joystick_t - { - char name[64]; - - int a[8]; - int b[32]; - int p[4]; - - struct - { - char name[32]; - int id; - } axis[8]; - - struct - { - char name[32]; - int id; - } button[32]; - - struct - { - char name[32]; - int id; - } pov[4]; - - int nr_axes; - int nr_buttons; - int nr_povs; - } plat_joystick_t; +extern void joystick_init(void); +extern void joystick_close(void); +extern void joystick_process(void); - #define MAX_PLAT_JOYSTICKS 8 +typedef struct plat_joystick_t +{ + char name[64]; - extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; - extern int joysticks_present; + int a[8]; + int b[32]; + int p[4]; - #define POV_X 0x80000000 - #define POV_Y 0x40000000 - - typedef struct joystick_t - { - int axis[8]; - int button[32]; - int pov[4]; - - int plat_joystick_nr; - int axis_mapping[8]; - int button_mapping[32]; - int pov_mapping[4][2]; - } joystick_t; + struct + { + char name[32]; + int id; + } axis[8]; - #define MAX_JOYSTICKS 4 - extern joystick_t joystick_state[MAX_JOYSTICKS]; + struct + { + char name[32]; + int id; + } button[32]; - #define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) + struct + { + char name[32]; + int id; + } pov[4]; + + int nr_axes; + int nr_buttons; + int nr_povs; +} plat_joystick_t; + +#define MAX_PLAT_JOYSTICKS 8 + +extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +extern int joysticks_present; + +#define POV_X 0x80000000 +#define POV_Y 0x40000000 + +typedef struct joystick_t +{ + int axis[8]; + int button[32]; + int pov[4]; + + int plat_joystick_nr; + int axis_mapping[8]; + int button_mapping[32]; + int pov_mapping[4][2]; +} joystick_t; + +#define MAX_JOYSTICKS 4 +extern joystick_t joystick_state[MAX_JOYSTICKS]; + +#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/src/plat_mouse.h b/src/plat_mouse.h index ff248f301..f5be1597c 100644 --- a/src/plat_mouse.h +++ b/src/plat_mouse.h @@ -1,16 +1,22 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ + + +extern int mousecapture; +extern int mouse_buttons; + + #ifdef __cplusplus extern "C" { #endif - void mouse_init(); - void mouse_close(); - extern int mouse_buttons; - void mouse_poll_host(); - void mouse_get_mickeys(int *x, int *y, int *z); - extern int mousecapture; +extern void mouse_init(void); +extern void mouse_close(void); +extern void mouse_process(void); +extern void mouse_poll_host(void); +extern void mouse_get_mickeys(int *x, int *y, int *z); + #ifdef __cplusplus } #endif diff --git a/src/rom.c b/src/rom.c index 4ab1ee82c..ad27f969f 100644 --- a/src/rom.c +++ b/src/rom.c @@ -13,7 +13,7 @@ * - c386sx16 BIOS fails checksum * - the loadfont() calls should be done elsewhere * - * Version: @(#)rom.c 1.0.13 2017/10/16 + * Version: @(#)rom.c 1.0.14 2017/10/17 * * Authors: Sarah Walker, * Miran Grca, @@ -565,7 +565,7 @@ rom_load_bios(int rom_id) return(1); case ROM_DESKPRO_386: - if (rom_load_interleaved( + if (! rom_load_interleaved( L"roms/machines/deskpro386/109592-005.U11.bin", L"roms/machines/deskpro386/109591-005.U13.bin", 0x000000, 32768, 0, rom)) break; diff --git a/src/ui.h b/src/ui.h index 52f675e7d..54823da29 100644 --- a/src/ui.h +++ b/src/ui.h @@ -8,7 +8,7 @@ * * Define the various UI functions. * - * Version: @(#)ui.h 1.0.4 2017/10/16 + * Version: @(#)ui.h 1.0.5 2017/10/16 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -41,6 +41,7 @@ extern "C" { extern int ui_msgbox(int type, void *arg); +extern void ui_check_menu_item(int id, int checked); /* Status Bar functions. */ #define SB_ICON_WIDTH 24 diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index e5cef155b..7f6ad068f 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.5 2017/10/16 + * Version: @(#)vid_cga.c 1.0.7 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -402,7 +402,7 @@ void cga_poll(void *p) ysize = cga->lastline - cga->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, (ysize << 1) + 16); + set_screen_size(xsize, (ysize << 1) + 16); } if (cga->composite) diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index cd220e702..fb3cdceba 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -8,7 +8,7 @@ * * Plantronics ColorPlus emulation. * - * Version: @(#)vid_colorplus.c 1.0.1 2017/10/16 + * Version: @(#)vid_colorplus.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -321,7 +321,7 @@ void colorplus_poll(void *p) ysize = colorplus->cga.lastline - colorplus->cga.firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, (ysize << 1) + 16); + set_screen_size(xsize, (ysize << 1) + 16); } if (colorplus->cga.composite) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index b5c2d1bdd..e3f494950 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.6 2017/10/16 + * Version: @(#)vid_ega.c 1.0.8 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -687,9 +687,9 @@ void ega_poll(void *p) } if (ega->vres) - updatewindowsize(xsize + x_add_ex, (ysize << 1) + y_add_ex); + set_screen_size(xsize + x_add_ex, (ysize << 1) + y_add_ex); else - updatewindowsize(xsize + x_add_ex, ysize + y_add_ex); + set_screen_size(xsize + x_add_ex, ysize + y_add_ex); } if (enable_overscan) diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index d06472887..20ab61790 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -8,7 +8,7 @@ * * MDSI Genius VHR emulation. * - * Version: @(#)vid_genius.c 1.0.1 2017/10/16 + * Version: @(#)vid_genius.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -557,7 +557,7 @@ void genius_poll(void *p) ysize = GENIUS_YSIZE; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize); + set_screen_size(xsize, ysize); } video_blit_memtoscreen_8(0, 0, xsize, ysize); diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index f072ff324..738a1c63f 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.2 2017/10/16 + * Version: @(#)vid_hercules.c 1.0.4 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -290,7 +290,7 @@ void hercules_poll(void *p) // printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]); if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize); + set_screen_size(xsize, ysize); } video_blit_memtoscreen_8(0, hercules->firstline, xsize, ysize); frames++; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index eff620f8e..a9bf93229 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_herculesplus.c 1.0.1 2017/10/16 + * Version: @(#)vid_herculesplus.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -639,7 +639,7 @@ void herculesplus_poll(void *p) ysize = herculesplus->lastline - herculesplus->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize); + set_screen_size(xsize, ysize); } video_blit_memtoscreen(0, herculesplus->firstline, 0, herculesplus->lastline - herculesplus->firstline, xsize, herculesplus->lastline - herculesplus->firstline); frames++; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 5ea18478b..18e8b7879 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.1 2017/10/16 + * Version: @(#)vid_incolor.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -986,7 +986,7 @@ void incolor_poll(void *p) ysize = incolor->lastline - incolor->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize); + set_screen_size(xsize, ysize); } video_blit_memtoscreen(0, incolor->firstline, 0, incolor->lastline - incolor->firstline, xsize, incolor->lastline - incolor->firstline); frames++; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index cd0be946a..dc350ff3b 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -8,7 +8,7 @@ * * MDA emulation. * - * Version: @(#)vid_mda.c 1.0.2 2017/10/16 + * Version: @(#)vid_mda.c 1.0.4 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -249,7 +249,7 @@ void mda_poll(void *p) ysize = mda->lastline - mda->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize); + set_screen_size(xsize, ysize); } video_blit_memtoscreen_8(0, mda->firstline, xsize, mda->lastline - mda->firstline); frames++; diff --git a/src/video/vid_olivetti_m24.c b/src/video/vid_olivetti_m24.c index 91d6e52b8..90398d7fc 100644 --- a/src/video/vid_olivetti_m24.c +++ b/src/video/vid_olivetti_m24.c @@ -8,7 +8,7 @@ * * Olivetti M24 video emulation- essentially double-res CGA. * - * Version: @(#)vid_olivetti_m24.c 1.0.1 2017/10/16 + * Version: @(#)vid_olivetti_m24.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -410,7 +410,7 @@ void m24_poll(void *p) ysize = m24->lastline - m24->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize + 16); + set_screen_size(xsize, ysize + 16); } video_blit_memtoscreen_8(0, m24->firstline - 8, xsize, (m24->lastline - m24->firstline) + 16); diff --git a/src/video/vid_pc1512.c b/src/video/vid_pc1512.c index 1e5a616da..ffb5c6fb4 100644 --- a/src/video/vid_pc1512.c +++ b/src/video/vid_pc1512.c @@ -15,7 +15,7 @@ * time as between 12 and 46 cycles. We currently always use * the lower number. * - * Version: @(#)vid_pc1512.c 1.0.1 2017/10/16 + * Version: @(#)vid_pc1512.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -419,7 +419,7 @@ static void pc1512_poll(void *p) ysize = pc1512->lastline - pc1512->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, (ysize << 1) + 16); + set_screen_size(xsize, (ysize << 1) + 16); } video_blit_memtoscreen_8(0, pc1512->firstline - 4, xsize, (pc1512->lastline - pc1512->firstline) + 8); diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index 43bcc580d..76be08f20 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -8,7 +8,7 @@ * * Video emulation for IBM PCjr. * - * Version: @(#)vid_pcjr.c 1.0.1 2017/10/16 + * Version: @(#)vid_pcjr.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -509,7 +509,7 @@ void pcjr_poll(void *p) ysize = pcjr->lastline - pcjr->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, (ysize << 1) + 16); + set_screen_size(xsize, (ysize << 1) + 16); } if (pcjr->composite) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 6d8da3ca8..f7b68a226 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.5 2017/10/16 + * Version: @(#)vid_svga.c 1.0.7 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -1617,30 +1617,13 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) return; } - if (((wx!=xsize) || ((wy + 1)!=ysize)) && !vid_resize) - { - xsize=wx; - ysize=wy+1; - if (xsize<64) xsize=640; - if (ysize<32) ysize=200; - - if ((xsize > 2032) || (ysize > 2032)) - { - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } - else - { - suppress_overscan = 0; - } - - updatewindowsize(xsize + x_add,ysize + y_add); - } - if (vid_resize) + if (((wx!=xsize) || ((wy+1)!=ysize))) { + /* Screen res has changed.. fix up, and let them know. */ xsize = wx; - ysize = wy + 1; + ysize = wy+1; + if (xsize<64) xsize = 640; + if (ysize<32) ysize = 200; if ((xsize > 2032) || (ysize > 2032)) { @@ -1652,6 +1635,8 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) { suppress_overscan = 0; } + + set_screen_size(xsize+x_add,ysize+y_add); } if (enable_overscan && !suppress_overscan) diff --git a/src/video/vid_tandy.c b/src/video/vid_tandy.c index f703efb43..1029665f3 100644 --- a/src/video/vid_tandy.c +++ b/src/video/vid_tandy.c @@ -8,7 +8,7 @@ * * Emulation of the Tandy Model 1000 video. * - * Version: @(#)vid_tandy.c 1.0.1 2017/10/16 + * Version: @(#)vid_tandy.c 1.0.2 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -546,7 +546,7 @@ void tandy_poll(void *p) ysize = tandy->lastline - tandy->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, (ysize << 1) + 16); + set_screen_size(xsize, (ysize << 1) + 16); } if (tandy->composite) diff --git a/src/video/vid_tandysl.c b/src/video/vid_tandysl.c index f09590ad1..354963472 100644 --- a/src/video/vid_tandysl.c +++ b/src/video/vid_tandysl.c @@ -8,7 +8,7 @@ * * Emulation of the Tandy Model 1000/SL video. * - * Version: @(#)vid_tandysl.c 1.0.1 2017/10/16 + * Version: @(#)vid_tandysl.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -615,7 +615,7 @@ static void tandysl_poll(void *p) ysize = tandy->lastline - tandy->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, (ysize << 1) + 16); + set_screen_size(xsize, (ysize << 1) + 16); } video_blit_memtoscreen_8(0, tandy->firstline-4, xsize, (tandy->lastline - tandy->firstline) + 8); diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index cbcf404b7..76724b3fd 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -8,7 +8,7 @@ * * Wyse-700 emulation. * - * Version: @(#)vid_wy700.c 1.0.1 2017/10/16 + * Version: @(#)vid_wy700.c 1.0.3 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -866,7 +866,7 @@ void wy700_poll(void *p) ysize = WY700_YSIZE; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; - updatewindowsize(xsize, ysize); + set_screen_size(xsize, ysize); } video_blit_memtoscreen_8(0, 0, xsize, ysize); diff --git a/src/video/video.c b/src/video/video.c index bf745f7b7..6081b660b 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.2 2017/10/13 + * Version: @(#)video.c 1.0.4 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -73,33 +73,35 @@ enum { }; -int vid_cga_contrast = 0; +BITMAP *screen = NULL; +BITMAP *buffer= NULL, + *buffer32= NULL; +uint8_t fontdat[256][8]; /* IBM CGA font */ +uint8_t fontdatm[256][16]; /* IBM MDA font */ +uint8_t fontdatw[512][32]; /* Wyse700 font */ +uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ +uint32_t pal_lookup[256]; +int xsize = 1, + ysize = 1; int cga_palette = 0; -int video_fullscreen = 0, - video_fullscreen_scale, - video_fullscreen_first; -uint32_t *video_6to8, - *video_15to32, - *video_16to32; -BITMAP *screen; +uint32_t *video_6to8 = NULL, + *video_15to32 = NULL, + *video_16to32 = NULL; int egareads = 0, egawrites = 0, changeframecount = 2; uint8_t rotatevga[8][256]; int frames = 0; -int fullchange; +int fullchange = 0; uint8_t edatlookup[4][4]; -int enable_overscan; -int overscan_x, - overscan_y; -int force_43; -int video_timing_b, - video_timing_w, - video_timing_l; -int video_res_x, - video_res_y, - video_bpp; -int video_speed = 0; +int overscan_x = 0, + overscan_y = 0; +int video_timing_b = 0, + video_timing_w = 0, + video_timing_l = 0; +int video_res_x = 0, + video_res_y = 0, + video_bpp = 0; int video_timing[6][4] = { { VIDEO_ISA, 8, 16, 32 }, { VIDEO_ISA, 6, 8, 16 }, @@ -108,14 +110,6 @@ int video_timing[6][4] = { { VIDEO_BUS, 4, 5, 10 }, { VIDEO_BUS, 3, 3, 4 } }; -BITMAP *buffer, - *buffer32; -uint8_t fontdat[256][8]; -uint8_t fontdatm[256][16]; -uint8_t fontdatw[512][32]; /* Wyse700 font */ -uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ -int xsize=1, - ysize=1; PALETTE cgapal = { {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, {0,0,0}, {0,42,42}, {42,0,42}, {42,42,42}, @@ -181,7 +175,6 @@ PALETTE cgapal_mono[6] = { {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, } }; -uint32_t pal_lookup[256]; static struct { @@ -193,11 +186,11 @@ static struct { event_t *wake_blit_thread; event_t *blit_complete; event_t *buffer_not_in_use; -} blit_data; +} blit_data; -static void (*memtoscreen_func)(int x, int y, int y1, int y2, int w, int h); -static void (*memtoscreen_8_func)(int x, int y, int w, int h); +static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); +static void (*blit8_func)(int x, int y, int w, int h); static @@ -208,9 +201,9 @@ void blit_thread(void *param) thread_reset_event(blit_data.wake_blit_thread); if (blit_data.blit8) - memtoscreen_8_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); + blit8_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); else - memtoscreen_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); + blit_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); blit_data.busy = 0; thread_set_event(blit_data.blit_complete); @@ -221,8 +214,8 @@ void blit_thread(void *param) void video_setblit(void(*blit8)(int,int,int,int),void(*blit)(int,int,int,int,int,int)) { - memtoscreen_func = blit; - memtoscreen_8_func = blit8; + blit_func = blit; + blit8_func = blit8; } @@ -297,6 +290,9 @@ cgapal_rebuild(void) { int c; + /* We cannot do this (yet) if we have not been enabled yet. */ + if (video_6to8 == NULL) return; + for (c=0; c<256; c++) { pal_lookup[c] = makecol(video_6to8[cgapal[c].r], video_6to8[cgapal[c].g], @@ -482,6 +478,8 @@ video_init(void) { int c, d, e; + pclog("VIDEO: initializing..\n"); + /* Account for overscan. */ buffer32 = create_bitmap(2048, 2048); @@ -583,7 +581,10 @@ loadfont(wchar_t *s, int format) int c,d; f = rom_fopen(s, L"rb"); - if (f == NULL) return; + if (f == NULL) { + pclog("VIDEO: cannot load font '%ls', fmt=%d\n", s, format); + return; + } switch (format) { case 0: /* MDA */ diff --git a/src/video/video.h b/src/video/video.h index 1aaf09e84..bbdb9f0eb 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -57,8 +57,6 @@ extern int video_res_x, video_res_y, video_bpp; extern int vid_resize; -extern int winsizex, - winsizey; extern int cga_palette; extern int vid_cga_contrast; extern int video_grayscale; diff --git a/src/win/win_vnc.c b/src/vnc.c similarity index 84% rename from src/win/win_vnc.c rename to src/vnc.c index a5e8f4413..a76544a80 100644 --- a/src/win/win_vnc.c +++ b/src/vnc.c @@ -6,9 +6,9 @@ * * This file is part of the 86Box distribution. * - * Implement the VNC renderer with LibVNCServer. + * Implement the VNC remote renderer with LibVNCServer. * - * Version: @(#)win_vnc.c 1.0.3 2017/10/16 + * Version: @(#)lnx_vnc.c 1.0.4 2017/10/18 * * Authors: Fred N. van Kempen, * Based on raw code by RichardG, @@ -17,17 +17,26 @@ */ #include #include -#include "../86box.h" -#include "../device.h" -#include "../video/video.h" -#include "../plat.h" -#include "../plat_keyboard.h" -#include "../ui.h" +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "video/video.h" +#include "plat.h" +#include "plat_keyboard.h" +#include "plat_mouse.h" +#include "ui.h" #define BITMAP MY_BITMAP #include #undef BITMAP -#include "win.h" -#include "win_vnc.h" +#include "vnc.h" + + +#define VNC_MIN_X 320 +#define VNC_MAX_X 2048 +#define VNC_MIN_Y 200 +#define VNC_MAX_Y 2048 static rfbScreenInfoPtr rfb = NULL; @@ -107,53 +116,6 @@ static int keysyms_ff[] = { }; -static void -vnc_clientgone(rfbClientPtr cl) -{ - pclog("VNC: client disconnected: %s\n", cl->host); - - if (clients > 0) - clients--; - if (clients == 0) { - /* No more clients, pause the emulator. */ - pclog("VNC: no clients, pausing..\n"); - plat_pause(1); - } -} - - -static enum rfbNewClientAction -vnc_newclient(rfbClientPtr cl) -{ - /* Hook the ClientGone function so we know when they're gone. */ - cl->clientGoneHook = vnc_clientgone; - - pclog("VNC: new client: %s\n", cl->host); - if (++clients == 1) { - /* We now have clients, un-pause the emulator. */ - pclog("VNC: unpausing..\n"); - plat_pause(0); - } - - return(RFB_CLIENT_ACCEPT); -} - - -static void -vnc_display(rfbClientPtr cl) -{ - /* Avoid race condition between resize and update. */ - if (!updatingSize && cl->newFBSizePending) { - updatingSize = 1; - } else if (updatingSize && !cl->newFBSizePending) { - updatingSize = 0; - - allowedX = rfb->width; - allowedY = rfb->height; - } -} - - static void vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) { @@ -177,18 +139,79 @@ vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) (will_press >> 8) & 0xff, will_press & 0xff); #endif - // first key + /* First key. */ key = (will_press >> 8) & 0xff; if (key > 0) recv_key[key] = down; - // second key + /* Second key. */ key = will_press & 0xff; if (key > 0) recv_key[key] = down; } +static void +vnc_ptrevent(int but, int x, int y, rfbClientPtr cl) +{ + if (x>=0 && x=0 && yhost); + + if (clients > 0) + clients--; + if (clients == 0) { + /* No more clients, pause the emulator. */ + pclog("VNC: no clients, pausing..\n"); + plat_pause(1); + } +} + + +static enum rfbNewClientAction +vnc_newclient(rfbClientPtr cl) +{ + /* Hook the ClientGone function so we know when they're gone. */ + cl->clientGoneHook = vnc_clientgone; + + pclog("VNC: new client: %s\n", cl->host); + if (++clients == 1) { + /* We now have clients, un-pause the emulator if needed. */ + pclog("VNC: unpausing..\n"); + plat_pause(0); + } + + /* For now, we always accept clients. */ + return(RFB_CLIENT_ACCEPT); +} + + +static void +vnc_display(rfbClientPtr cl) +{ + /* Avoid race condition between resize and update. */ + if (!updatingSize && cl->newFBSizePending) { + updatingSize = 1; + } else if (updatingSize && !cl->newFBSizePending) { + updatingSize = 0; + + allowedX = rfb->width; + allowedY = rfb->height; + } +} + + static void vnc_blit(int x, int y, int y1, int y2, int w, int h) { @@ -196,9 +219,9 @@ vnc_blit(int x, int y, int y1, int y2, int w, int h) int yy; for (yy=y1; yyframeBuffer)[yy*2048]); + p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*VNC_MAX_X]); - if ((y+yy) >= 0 && (y+yy) < 2048) + if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) memcpy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w*4); } @@ -216,7 +239,7 @@ vnc_blit8(int x, int y, int w, int h) int xx, yy; for (yy = 0; yy < h; yy++) { - p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*2048]); + p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*VNC_MAX_X]); if ((y+yy) >= 0 && (y+yy) < buffer->h) { for (xx=0; xxdesktopName = title; - rfb->frameBuffer = (char *)malloc(2048 * 2048 * 4); + rfb->frameBuffer = (char *)malloc(VNC_MAX_X*VNC_MAX_Y*4); rfb->serverFormat = rpf; rfb->alwaysShared = TRUE; rfb->displayHook = vnc_display; + rfb->ptrAddEvent = vnc_ptrevent; rfb->kbdAddEvent = vnc_kbdevent; rfb->newClientHook = vnc_newclient; + /* Set up our current resolution. */ + rfb->width = allowedX; + rfb->height = allowedY; + rfbInitServer(rfb); rfbRunEventLoop(rfb, -1, TRUE); @@ -271,10 +301,10 @@ vnc_init(HWND h) /* Set up our BLIT handlers. */ video_setblit(vnc_blit8, vnc_blit); - pclog("VNC: init complete.\n"); - clients = 0; + pclog("VNC: init complete.\n"); + return(1); } @@ -282,7 +312,13 @@ vnc_init(HWND h) void vnc_close(void) { - pclog("VNC: closed.\n"); + if (rfb != NULL) { + free(rfb->frameBuffer); + + rfbScreenCleanup(rfb); + + rfb = NULL; + } } @@ -294,6 +330,12 @@ vnc_resize(int x, int y) if (rfb == NULL) return; + /* TightVNC doesn't like certain sizes.. */ + if (x < VNC_MIN_X || x > VNC_MAX_X || y < VNC_MIN_Y || y > VNC_MAX_Y) { + pclog("VNC: invalid resoltion %dx%d requested!\n", x, y); + return; + } + if ((x != rfb->width || y != rfb->height) && x > 160 && y > 0) { pclog("VNC: updating resolution: %dx%d\n", x, y); @@ -313,6 +355,7 @@ vnc_resize(int x, int y) } +/* Tell them to pause if we have no clients. */ int vnc_pause(void) { diff --git a/src/win/win_vnc.h b/src/vnc.h similarity index 76% rename from src/win/win_vnc.h rename to src/vnc.h index ba3d793e9..96330284d 100644 --- a/src/win/win_vnc.h +++ b/src/vnc.h @@ -8,23 +8,31 @@ * * Definitions for the VNC renderer. * - * Version: @(#)win_vnc.h 1.0.1 2017/10/13 + * Version: @(#)vnc.h 1.0.3 2017/10/18 * * Authors: RichardG, * Fred N. van Kempen, * * Copyright 2017 Fred N. van Kempen. */ -#ifndef WIN_VNC_H -# define WIN_VNC_H +#ifndef EMU_VNC_H +# define EMU_VNC_H -extern int vnc_init(HWND h); +#ifdef __cplusplus +extern "C" { +#endif + +extern int vnc_init(void *); extern void vnc_close(void); extern void vnc_resize(int x, int y); extern int vnc_pause(void); extern void vnc_take_screenshot(wchar_t *fn); +#ifdef __cplusplus +} +#endif -#endif /*WIN_VNC_H*/ + +#endif /*EMU_VNC_H*/ diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 95a3c5beb..64ba39c6a 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.63 2017/10/14 +# Version: @(#)Makefile.mingw 1.0.64 2017/10/18 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -224,7 +224,7 @@ RFLAGS += -DUSE_VNC VNCLIB := -L$(VNC_PATH)\LIB endif VNCLIB += -lvncserver -VNCOBJ := win_vnc.o +VNCOBJ := vnc.o endif ifeq ($(RDP), y) @@ -235,7 +235,7 @@ RFLAGS += -DUSE_RDP RDPLIB := -L$(RDP_PATH)\LIB endif RDPLIB += -lrdp -RDPOBJ := win_rdp.o +RDPOBJ := rdp.o endif # Options for the DEV branch. @@ -276,7 +276,7 @@ endif MAINOBJ := pc.o config.o random.o timer.o io.o dma.o nmi.o pic.o \ pit.o ppi.o pci.o mca.o mcr.o mem.o memregs.o rom.o \ - device.o nvr.o nvr_at.o nvr_ps2.o \ + device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) \ intel.o intel_flash.o intel_sio.o CPUOBJ := cpu.o 386.o 386_dynarec.o 808x.o \ @@ -400,12 +400,11 @@ VIDOBJ := video.o \ PLATOBJ := win.o \ win_ddraw.o win_ddraw_fs.o win_d3d.o win_d3d_fs.o \ - $(VNCOBJ) $(RDPOBJ) \ - win_dynld.o win_thread.o $(WSERIAL) win_cdrom.o win_cdrom_ioctl.o \ - win_keyboard.o win_mouse.o win_joystick.o win_midi.o \ + win_dynld.o win_thread.o $(WSERIAL) win_video.o \ + win_cdrom.o win_cdrom_ioctl.o win_keyboard.o win_mouse.o \ + win_joystick.o win_midi.o \ win_dialog.o win_about.o win_status.o win_stbar.o \ - win_settings.o win_deviceconfig.o win_joystickconfig.o \ - $(OPENDIR) + win_settings.o win_deviceconfig.o win_joystickconfig.o OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(DEVOBJ) \ $(FDDOBJ) $(CDROMOBJ) $(HDDOBJ) \ @@ -513,7 +512,7 @@ ifneq ($(AUTODEP), y) depclean: @-rm -f $(DEPFILE) 2>NUL @echo Creating dependencies.. - @echo # Run "make depends" to re-create this file. $(DEPFILE) + @echo # Run "make depends" to re-create this file. >$(DEPFILE) depends: DEPOBJ=$(OBJ:%.o=%.d) depends: depclean $(OBJ:%.o=%.d) diff --git a/src/win/win.c b/src/win/win.c index c034c0e3f..15fafa5b7 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * The Emulator's Windows core. * - * Version: @(#)win.c 1.0.25 2017/10/16 + * Version: @(#)win.c 1.0.27 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -59,11 +59,7 @@ #include "../plat_midi.h" #include "../ui.h" #include "win.h" -#include "win_ddraw.h" #include "win_d3d.h" -#ifdef USE_VNC -# include "win_vnc.h" -#endif #define TIMER_1SEC 1 @@ -74,32 +70,18 @@ typedef struct { } rc_str_t; -extern int status_update_needed; - - -/* Public data, more or less non-specific to platform. */ -int scale = 0; -uint64_t timer_freq; -int winsizex = 640, - winsizey = 480; -int efwinsizey = 480; -int gfx_present[GFX_MAX]; -int drawits = 0; -int mousecapture = 0; -uint64_t main_time; - -/* Public data, specific to platform. */ -HWND hwndMain; -HMENU menuMain; +/* Platform Public data, specific (defined in lnx.h.) */ +HINSTANCE hinstance; /* application instance */ +HWND hwndMain, /* application main window */ + hwndRender; /* machine render window */ +HMENU menuMain; /* application main menu */ HANDLE ghMutex; -HINSTANCE hinstance; -HICON hIcon[512]; -RECT oldclip; -LCID dwLanguage; +HICON hIcon[512]; /* icon data loaded from resources */ +LCID lang_id; /* current language ID used */ +DWORD dwSubLangID; +RECT oldclip; /* mouse rect */ int infocus = 1; -int recv_key[272]; -uint32_t dwLangID, - dwSubLangID; +int recv_key[272]; /* keyboard input buffer */ char openfilestring[260]; WCHAR wopenfilestring[260]; @@ -107,19 +89,11 @@ WCHAR wopenfilestring[260]; /* Local data. */ static HANDLE thMain; -static HWND hwndRender; /* machine render window */ static wchar_t wTitle[512]; static RAWINPUTDEVICE device; static HHOOK hKeyboardHook; static int hook_enabled = 0; static int save_window_pos = 0; -static int doresize = 0; -static int quited; -static int leave_fullscreen_flag = 0; -static int unscaled_size_x = 0; -static int unscaled_size_y = 0; -static uint64_t start_time; -static uint64_t end_time; static wchar_t **argv; static int argc; static wchar_t *argbuf; @@ -132,42 +106,6 @@ static rc_str_t *lpRCstr2048, *lpRCstr5376, *lpRCstr5632, *lpRCstr6144; -static struct { - int local; - int (*init)(HWND h); - void (*close)(void); - void (*resize)(int x, int y); - int (*pause)(void); -} vid_apis[2][4] = { - { - { 1, ddraw_init, ddraw_close, NULL, ddraw_pause }, - { 1, d3d_init, d3d_close, d3d_resize, d3d_pause }, -#ifdef USE_VNC - { 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, -#else - { 0, NULL, NULL, NULL, NULL }, -#endif -#ifdef USE_RDP - { 0, rdp_init, rdp_close, rdp_resize, rdp_pause } -#else - { 0, NULL, NULL, NULL, NULL } -#endif - }, - { - { 1, ddraw_fs_init, ddraw_fs_close, NULL, ddraw_fs_pause }, - { 1, d3d_fs_init, d3d_fs_close, NULL, d3d_fs_pause }, -#ifdef USE_VNC - { 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, -#else - { 0, NULL, NULL, NULL, NULL }, -#endif -#ifdef USE_RDP - { 0, rdp_init, rdp_close, rdp_resize, rdp_pause } -#else - { 0, NULL, NULL, NULL, NULL } -#endif - } -}; HICON @@ -219,80 +157,6 @@ video_toggle_option(HMENU h, int *val, int id) } -/* The main thread runs the actual emulator code. */ -static void -MainThread(LPVOID param) -{ - int sb_borders[3]; - DWORD old_time, new_time; - int frames = 0; - RECT r; - - drawits = 0; - old_time = plat_get_ticks(); - while (! quited) { - if (status_update_needed) { - if (hwndStatus != NULL) - SendMessage(hwndStatus, WM_USER, 0, 0); - status_update_needed = 0; - } - - new_time = plat_get_ticks(); - drawits += new_time - old_time; - old_time = new_time; - if (drawits > 0 && !dopause) { - start_time = plat_timer_read(); - drawits -= 10; - if (drawits > 50) drawits = 0; - pc_run(); - - if (++frames >= 200 && nvr_dosave) { - frames = 0; - nvr_save(); - nvr_dosave = 0; - } - - end_time = plat_timer_read(); - main_time += end_time - start_time; - } else - plat_delay_ms(1); - - if (!video_fullscreen && vid_apis[0][vid_api].local && - doresize && (winsizex>0) && (winsizey>0)) { - SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders); - GetWindowRect(hwndMain, &r); - MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); - GetWindowRect(hwndRender, &r); - MoveWindow(hwndSBAR, - 0, r.bottom + GetSystemMetrics(SM_CYEDGE), - winsizex, 17, TRUE); - GetWindowRect(hwndMain, &r); - - MoveWindow(hwndMain, r.left, r.top, - winsizex + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2), - winsizey + (GetSystemMetrics(SM_CYEDGE) * 2) + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 17 + sb_borders[1] + 1, - TRUE); - - if (mousecapture) { - GetWindowRect(hwndRender, &r); - ClipCursor(&r); - } - - doresize = 0; - } - - if (leave_fullscreen_flag) { - leave_fullscreen_flag = 0; - - SendMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); - } - - if (video_fullscreen && infocus) - SetCursorPos(9999, 9999); - } -} - - static void ResetAllMenus(void) { @@ -399,7 +263,7 @@ static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { BOOL bControlKeyDown; - KBDLLHOOKSTRUCT* p; + KBDLLHOOKSTRUCT *p; if (nCode < 0 || nCode != HC_ACTION) return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)); @@ -528,42 +392,12 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) #ifdef USE_RDP case IDM_VID_RDP: #endif - startblit(); - video_wait_for_blit(); - CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_UNCHECKED); - vid_apis[0][vid_api].close(); - vid_api = LOWORD(wParam) - IDM_VID_DDRAW; - if (vid_apis[0][vid_api].local) - ShowWindow(hwndRender, SW_SHOW); - else - ShowWindow(hwndRender, SW_HIDE); - CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_CHECKED); - vid_apis[0][vid_api].init(hwndRender); - endblit(); - device_force_redraw(); - cgapal_rebuild(); + plat_setvid(LOWORD(wParam) - IDM_VID_DDRAW); config_save(); break; case IDM_VID_FULLSCREEN: - if (video_fullscreen == 1) break; - - if (video_fullscreen_first) { - video_fullscreen_first = 0; - ui_msgbox(MBX_INFO, (wchar_t *)IDS_2074); - } - - startblit(); - video_wait_for_blit(); - mouse_close(); - vid_apis[0][vid_api].close(); - video_fullscreen = 1; - vid_apis[1][vid_api].init(hwndMain); - mouse_init(); - leave_fullscreen_flag = 0; - endblit(); - device_force_redraw(); - cgapal_rebuild(); + plat_setfullscreen(1); config_save(); break; @@ -802,28 +636,17 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_SIZE: - winsizex = (lParam & 0xFFFF); - winsizey = (lParam >> 16) - (17 + 6); - if (winsizey < 0) - winsizey = 0; + scrnsz_x = (lParam & 0xFFFF); + scrnsz_y = (lParam >> 16) - (17 + 6); + if (scrnsz_y < 0) + scrnsz_y = 0; - MoveWindow(hwndSBAR, 0, winsizey + 6, winsizex, 17, TRUE); + plat_resize(scrnsz_x, scrnsz_y); - if (vid_apis[0][vid_api].local && (hwndRender != NULL)) { - MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); + if (mousecapture) { + GetWindowRect(hwndRender, &rect); - if (vid_apis[video_fullscreen][vid_api].resize) { - startblit(); - video_wait_for_blit(); - vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey); - endblit(); - } - - if (mousecapture) { - GetWindowRect(hwndRender, &rect); - - ClipCursor(&rect); - } + ClipCursor(&rect); } if (window_remember) { @@ -851,7 +674,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_TIMER: if (wParam == TIMER_1SEC) { - onesec(); + pc_onesec(); } break; @@ -865,15 +688,8 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_LEAVEFULLSCREEN: - startblit(); - mouse_close(); - vid_apis[1][vid_api].close(); - video_fullscreen = 0; + plat_setfullscreen(0); config_save(); - vid_apis[0][vid_api].init(hwndRender); - mouse_init(); - endblit(); - device_force_redraw(); cgapal_rebuild(); break; @@ -1080,7 +896,15 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) HWND hwnd; /* handle for our window */ HACCEL haccel; /* handle to accelerator table */ int bRet; - LARGE_INTEGER qpc_freq; + + /* We need this later. */ + hinstance = hInst; + + /* First, set our (default) language. */ + set_language(0x0409); + + /* Load common strings from the resource file. */ + LoadCommonStrings(); #ifdef USE_CONSOLE /* Create console window. */ @@ -1099,20 +923,14 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) return(1); } - /* We need this later. */ - hinstance = hInst; - - /* Load common strings from the resource file. */ - LoadCommonStrings(); - /* Create our main window's class and register it. */ - wincl.hInstance = hInst; + wincl.hInstance = hinstance; wincl.lpszClassName = CLASS_NAME; wincl.lpfnWndProc = MainWindowProcedure; wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof(WNDCLASSEX); - wincl.hIcon = LoadIcon(hInst, (LPCTSTR)100); - wincl.hIconSm = LoadIcon(hInst, (LPCTSTR)100); + wincl.hIcon = LoadIcon(hinstance, (LPCTSTR)100); + wincl.hIconSm = LoadIcon(hinstance, (LPCTSTR)100); wincl.hCursor = NULL; wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; @@ -1126,7 +944,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) return(2); /* Load the Window Menu(s) from the resources. */ - menuMain = LoadMenu(hInst, MENU_NAME); + menuMain = LoadMenu(hinstance, MENU_NAME); /* Set the initial title for the program's main window. */ _swprintf(title, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); @@ -1139,17 +957,17 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX) | DS_3DLOOK, CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where window ends up on the screen */ - 640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* width */ - 480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */ + 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 */ - hInst, /* Program Instance handler */ + hinstance, /* Program Instance handler */ NULL); /* no Window Creation data */ hwndMain = hwnd; ui_window_title(title); - /* Resize the window if needed. */ + /* Set up main window for resizing if configured. */ if (vid_resize) SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_MINIMIZEBOX)); @@ -1157,6 +975,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX&~WS_MINIMIZEBOX)); + /* Move to the last-saved position if needed. */ if (window_remember) MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); @@ -1167,7 +986,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) ShowWindow(hwnd, nFunsterStil); /* Load the accelerator table */ - haccel = LoadAccelerators(hInst, ACCEL_NAME); + haccel = LoadAccelerators(hinstance, ACCEL_NAME); if (haccel == NULL) { MessageBox(hwndMain, plat_get_string(IDS_2053), @@ -1192,7 +1011,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) get_registry_key_map(); /* Create the status bar window. */ - StatusBarCreate(hwndMain, IDC_STATUS, hInst); + StatusBarCreate(hwndMain, IDC_STATUS, hinstance); /* * Before we can create the Render window, we first have @@ -1203,24 +1022,18 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) /* Create the Machine Rendering window. */ hwndRender = CreateWindow(L"STATIC", NULL, WS_CHILD|SS_BITMAP, 0, 0, 1, 1, hwnd, NULL, hInst, NULL); - MoveWindow(hwndRender, 0, 0, winsizex, winsizey, TRUE); + MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE); - /* If this is a local renderer, enable it. */ - if (vid_apis[0][vid_api].local) - ShowWindow(hwndRender, SW_SHOW); - - /* Select the best system renderer available. */ - if (! vid_apis[0][vid_api].init(hwndRender)) { - vid_api ^= 1; - if (! vid_apis[0][vid_api].init(hwndRender)) { - MessageBox(hwnd, - plat_get_string(IDS_2095), - plat_get_string(IDS_2050), - MB_OK | MB_ICONERROR); - return(5); - } + /* 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); } +#if 0 /* Initialize the rendering window, or fullscreen. */ if (start_in_fullscreen) { startblit(); @@ -1231,11 +1044,10 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) endblit(); device_force_redraw(); } - if (vid_apis[video_fullscreen][vid_api].resize) { - startblit(); - vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey); - endblit(); - } +#endif + + /* Set up the current window size. */ + plat_resize(scrnsz_x, scrnsz_y); /* All done, fire up the actual emulated machine. */ if (! pc_init_modules()) { @@ -1253,23 +1065,18 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) /* Set the PAUSE mode depending on the renderer. */ plat_pause(0); + /* Initialize raw keyboard input buffer. */ + memset(recv_key, 0x00, sizeof(recv_key)); + /* * 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. */ - timeBeginPeriod(1); - QueryPerformanceFrequency(&qpc_freq); - timer_freq = qpc_freq.QuadPart; - - atexit(releasemouse); - - thMain = (HANDLE)_beginthread(MainThread, 0, NULL); - SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); + do_start(); /* Run the message loop. It will run until GetMessage() returns 0 */ - quited = 0; while (! quited) { bRet = GetMessage(&messages, NULL, 0, 0); if ((bRet == 0) || quited) break; @@ -1288,33 +1095,21 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) DispatchMessage(&messages); } - if (recv_key[0x58] && recv_key[0x42] && mousecapture) { + if (mousecapture && recv_key[0x58] && recv_key[0x42]) { ClipCursor(&oldclip); ShowCursor(TRUE); mousecapture = 0; } - if ((recv_key[0x1D] || recv_key[0x9D]) && + if (video_fullscreen && + (recv_key[0x1D] || recv_key[0x9D]) && (recv_key[0x38] || recv_key[0xB8]) && - (recv_key[0x51] || recv_key[0xD1]) && video_fullscreen) { - leave_fullscreen(); + (recv_key[0x51] || recv_key[0xD1])) { + /* Signal "exit fullscreen mode". */ + plat_setfullscreen(0); } } - /* Why start??? --FvK */ - startblit(); - - Sleep(200); - TerminateThread(thMain, 0); - - nvr_save(); - - config_save(); - - pc_close(); - - vid_apis[video_fullscreen][vid_api].close(); - timeEndPeriod(1); if (mousecapture) { @@ -1322,24 +1117,100 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nFunsterStil) ShowCursor(TRUE); } - UnregisterClass(SUB_CLASS_NAME, hInst); - UnregisterClass(CLASS_NAME, hInst); + UnregisterClass(SUB_CLASS_NAME, hinstance); + UnregisterClass(CLASS_NAME, hinstance); + + /* Close down the emulator. */ + do_stop(); return(messages.wParam); } -FILE * -plat_fopen(wchar_t *path, wchar_t *mode) +wchar_t * +ui_window_title(wchar_t *s) { - return(_wfopen(path, mode)); + if (! video_fullscreen) { + if (s != NULL) + wcscpy(wTitle, s); + else + s = wTitle; + + SetWindowText(hwndMain, s); + } + + return(s); +} + + +/* Set (or re-set) the language for the application. */ +void +set_language(int id) +{ + LCID lcidNew = MAKELCID(id, dwSubLangID); + + if (lang_id != lcidNew) { + /* Set our new language ID. */ + lang_id = lcidNew; + + SetThreadLocale(lang_id); + + /* Load the strings table for this ID. */ + LoadCommonStrings(); + +#if 0 + /* Update the menus for this ID. */ + MenuUpdate(); +#endif + } +} + + +/* + * We do this here since there is platform-specific stuff + * going on here, and we do it in a function separate from + * main() so we can call it from the UI module as well. + */ +void +do_start(void) +{ + LARGE_INTEGER qpc; + + /* We have not stopped yet. */ + quited = 0; + + /* Initialize the high-precision timer. */ + timeBeginPeriod(1); + QueryPerformanceFrequency(&qpc); + timer_freq = qpc.QuadPart; + pclog("Main timer precision: %llu\n", timer_freq); + + atexit(releasemouse); + + /* Start the emulator, really. */ + thMain = thread_create(pc_thread, &quited); + SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); +} + + +/* Cleanly stop the emulator. */ +void +do_stop(void) +{ + quited = 1; + + plat_delay_ms(100); + + pc_close(thMain); + + thMain = NULL; } void -plat_remove(wchar_t *path) +plat_get_exe_name(wchar_t *s, int size) { - _wremove(path); + GetModuleFileName(hinstance, s, size); } @@ -1359,10 +1230,17 @@ plat_chdir(wchar_t *path) } -void -plat_get_exe_name(wchar_t *s, int size) +FILE * +plat_fopen(wchar_t *path, wchar_t *mode) { - GetModuleFileName(hinstance, s, size); + return(_wfopen(path, mode)); +} + + +void +plat_remove(wchar_t *path) +{ + _wremove(path); } @@ -1417,22 +1295,6 @@ plat_put_backslash(wchar_t *s) } -wchar_t * -ui_window_title(wchar_t *s) -{ - if (! video_fullscreen) { - if (s != NULL) - wcscpy(wTitle, s); - else - s = wTitle; - - SetWindowText(hwndMain, s); - } - - return(s); -} - - int plat_dir_check(wchar_t *path) { @@ -1476,54 +1338,24 @@ plat_delay_ms(uint32_t count) /* We should have the language ID as a parameter. */ -void -win_set_language(void) -{ - SetThreadLocale(dwLanguage); -} - - -/* Update the global language used. This needs a parameter.. */ -void -win_language_update(void) -{ - win_set_language(); -#if 0 - MenuUpdate(); -#endif - LoadCommonStrings(); -} - - -void -win_language_check(void) -{ - LCID dwLanguageNew = MAKELCID(dwLangID, dwSubLangID); - - if (dwLanguageNew != dwLanguage) { - dwLanguage = dwLanguageNew; - - win_language_update(); - } -} - - void plat_pause(int p) { - static wchar_t oldtitle[512]; + static wchar_t oldtitle[128]; + wchar_t title[128]; /* If un-pausing, as the renderer if that's OK. */ if (p == 0) - p = vid_apis[video_fullscreen][vid_api].pause(); + p = get_vidpause(); /* If already so, done. */ if (dopause == p) return; if (p) { - wcscpy(oldtitle, wTitle); - wcscat(wTitle, L" - PAUSED -"); - ui_window_title(NULL); + wcscpy(oldtitle, ui_window_title(NULL)); + wcscpy(title, oldtitle); + wcscat(title, L" - PAUSED -"); + ui_window_title(title); } else { ui_window_title(oldtitle); } @@ -1531,7 +1363,8 @@ plat_pause(int p) dopause = p; /* Update the actual menu. */ - CheckMenuItem(menuMain, IDM_ACTION_PAUSE, (dopause)?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_ACTION_PAUSE, + (dopause) ? MF_CHECKED : MF_UNCHECKED); } @@ -1569,169 +1402,3 @@ plat_get_string_from_string(char *str) { return(plat_get_string(atoi(str))); } - - -void -take_screenshot(void) -{ - wchar_t path[1024], fn[128]; - struct tm *info; - time_t now; - - pclog("Screenshot: video API is: %i\n", vid_api); - if ((vid_api < 0) || (vid_api > 1)) return; - - memset(fn, 0, sizeof(fn)); - memset(path, 0, sizeof(path)); - - (void)time(&now); - info = localtime(&now); - - plat_append_filename(path, cfg_path, SCREENSHOT_PATH, sizeof(path)-2); - - if (! plat_dir_check(path)) - plat_dir_create(path); - -#ifdef WIN32 - wcscat(path, L"\\"); -#else - wcscat(path, L"/"); -#endif - - switch(vid_api) { - case 0: /* ddraw */ - wcsftime(path, 128, L"%Y%m%d_%H%M%S.bmp", info); - plat_append_filename(path, cfg_path, fn, 1024); - if (video_fullscreen) - ddraw_fs_take_screenshot(path); - else - ddraw_take_screenshot(path); - pclog("Screenshot: fn='%ls'\n", path); - break; - - case 1: /* d3d9 */ - wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); - plat_append_filename(path, cfg_path, fn, 1024); - if (video_fullscreen) - d3d_fs_take_screenshot(path); - else - d3d_take_screenshot(path); - pclog("Screenshot: fn='%ls'\n", path); - break; - -#ifdef USE_VNC - case 2: /* vnc */ - wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); - plat_append_filename(path, cfg_path, fn, 1024); - vnc_take_screenshot(path); - pclog("Screenshot: fn='%ls'\n", path); - break; -#endif - } -} - - -void -startblit(void) -{ - WaitForSingleObject(ghMutex, INFINITE); -} - - -void -endblit(void) -{ - ReleaseMutex(ghMutex); -} - - -void -updatewindowsize(int x, int y) -{ - int owsx = winsizex; - int owsy = winsizey; - int temp_overscan_x = overscan_x; - int temp_overscan_y = overscan_y; - double dx, dy, dtx, dty; - - if (vid_resize) return; - - if (x < 160) x = 160; - if (y < 100) y = 100; - if (x > 2048) x = 2048; - if (y > 2048) y = 2048; - - if (suppress_overscan) - temp_overscan_x = temp_overscan_y = 0; - - unscaled_size_x=x; efwinsizey=y; - - if (force_43) { - dx = (double) x; - dtx = (double) temp_overscan_x; - - dy = (double) y; - dty = (double) temp_overscan_y; - - /* Account for possible overscan. */ - if (temp_overscan_y == 16) { - /* CGA */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else if (temp_overscan_y < 16) { - /* MDA/Hercules */ - dy = (x / 4.0) * 3.0; - } else { - if (enable_overscan) { - /* EGA/(S)VGA with overscan */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else { - /* EGA/(S)VGA without overscan */ - dy = (x / 4.0) * 3.0; - } - } - unscaled_size_y = (int) dy; - } else { - unscaled_size_y = efwinsizey; - } - - switch(scale) { - case 0: - winsizex = unscaled_size_x >> 1; - winsizey = unscaled_size_y >> 1; - break; - - case 1: - winsizex = unscaled_size_x; - winsizey = unscaled_size_y; - break; - - case 2: - winsizex = (unscaled_size_x * 3) >> 1; - winsizey = (unscaled_size_y * 3) >> 1; - break; - - case 3: - winsizex = unscaled_size_x << 1; - winsizey = unscaled_size_y << 1; - break; - } - - if ((owsx != winsizex) || (owsy != winsizey)) - doresize = 1; - else - doresize = 0; -} - - -void -uws_natural(void) -{ - updatewindowsize(unscaled_size_x, efwinsizey); -} - - -void -leave_fullscreen(void) -{ - leave_fullscreen_flag = 1; -} diff --git a/src/win/win.h b/src/win/win.h index 916087de9..424646f15 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -6,11 +6,9 @@ * * This file is part of the 86Box distribution. * - * This file should contain things only used by the platform - * support modules for Windows. Generic definitions for UI and - * platform go into ../plat*.h. + * Platform support defintions for Win32. * - * Version: @(#)win.h 1.0.5 2017/10/13 + * Version: @(#)win.h 1.0.6 2017/10/18 * * Authors: Sarah Walker, * Miran Grca, @@ -20,12 +18,10 @@ * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. */ -#ifndef BOX_WIN_H -# define BOX_WIN_H +#ifndef PLAT_WIN_H +# define PLAT_WIN_H -# ifndef NO_UNICODE -# define UNICODE -# endif +# define UNICODE # define BITMAP WINDOWS_BITMAP # if 0 # ifdef _WIN32_WINNT @@ -52,13 +48,16 @@ #define WM_SAVESETTINGS 0x8888 +extern HINSTANCE hinstance; +extern HWND hwndMain, + hwndRender; +extern HANDLE ghMutex; +extern LCID lang_id; +extern HICON hIcon[512]; + extern int status_is_open; extern int mousecapture; -extern LCID dwLanguage; - -extern HINSTANCE hinstance; -extern HWND hwndMain; -extern HICON hIcon[512]; +extern int recv_key[272]; extern char openfilestring[260]; extern WCHAR wopenfilestring[260]; @@ -70,9 +69,13 @@ extern "C" { extern HICON LoadIconEx(PCTSTR pszIconName); -extern void win_language_set(void); -extern void win_language_update(void); -extern void win_language_check(void); +/* Emulator start/stop support functions. */ +extern void do_start(void); +extern void do_stop(void); + +/* Internal platform support functions. */ +extern void set_language(int id); +extern int get_vidpause(void); #ifdef EMU_DEVICE_H extern void deviceconfig_open(HWND hwnd, device_t *device); @@ -122,4 +125,4 @@ extern wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); #endif -#endif /*BOX_WIN_H*/ +#endif /*PLAT_WIN_H*/ diff --git a/src/win/win_joystick.cc b/src/win/win_joystick.cc index 695638ee8..56d2627e8 100644 --- a/src/win/win_joystick.cc +++ b/src/win/win_joystick.cc @@ -8,7 +8,7 @@ * * Joystick interface to host device. * - * Version: @(#)win_joystick.cc 1.0.4 2017/10/12 + * Version: @(#)win_joystick.cc 1.0.5 2017/10/17 * * Authors: Sarah Walker, * Miran Grca, @@ -220,10 +220,12 @@ static int joystick_get_axis(int joystick_nr, int mapping) return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; } -void joystick_poll() +void joystick_process(void) { int c, d; + if (joystick_type != 7) return; + for (c = 0; c < joysticks_present; c++) { DIJOYSTATE joystate; diff --git a/src/win/win_video.c b/src/win/win_video.c new file mode 100644 index 000000000..7696f37cc --- /dev/null +++ b/src/win/win_video.c @@ -0,0 +1,300 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Platform video API support for Win32. + * + * Version: @(#)win_video.c 1.0.1 2017/10/18 + * + * Author: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include +#include "../86box.h" +#include "../config.h" +#include "../device.h" +#include "../video/video.h" +#include "../plat.h" +#include "../plat_mouse.h" +#include "../ui.h" +#ifdef USE_VNC +# include "../vnc.h" +#endif +#ifdef USE_RDP +# include "../rdp.h" +#endif +#include "win.h" +#include "win_ddraw.h" +#include "win_d3d.h" + + +static struct { + char *name; + int local; + int (*init)(void *); + void (*close)(void); + void (*resize)(int x, int y); + int (*pause)(void); +} vid_apis[2][4] = { + { + { "DDraw", 1, (int(*)(void*))ddraw_init, ddraw_close, NULL, ddraw_pause }, + { "D3D", 1, (int(*)(void*))d3d_init, d3d_close, d3d_resize, d3d_pause }, +#ifdef USE_VNC + { "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, +#else + { NULL, 0, NULL, NULL, NULL, NULL }, +#endif +#ifdef USE_RDP + { "RDP", 0, rdp_init, rdp_close, rdp_resize, rdp_pause } +#else + { NULL, 0, NULL, NULL, NULL, NULL } +#endif + }, + { + { "DDraw", 1, (int(*)(void*))ddraw_fs_init, ddraw_fs_close, NULL, ddraw_fs_pause }, + { "D3D", 1, (int(*)(void*))d3d_fs_init, d3d_fs_close, NULL, d3d_fs_pause }, +#ifdef USE_VNC + { "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, +#else + { NULL, 0, NULL, NULL, NULL, NULL }, +#endif +#ifdef USE_RDP + { "RDP", 0, rdp_init, rdp_close, rdp_resize, rdp_pause } +#else + { NULL, 0, NULL, NULL, NULL, NULL } +#endif + }, +}; + + +#if 0 + /* Initialize the rendering window, or fullscreen. */ + if (start_in_fullscreen) { + startblit(); + vid_apis[0][vid_api].close(); + video_fullscreen = 1; + vid_apis[1][vid_api].init(hwndRender); + leave_fullscreen_flag = 0; + endblit(); + device_force_redraw(); + } +#endif + + +/* Return the VIDAPI number for the given name. */ +int +plat_vidapi(char *name) +{ + int i; + + if (!strcasecmp(name, "default") || !strcasecmp(name, "system")) return(0); + + for (i=0; i<4; i++) { + if (vid_apis[0][i].name && + !strcasecmp(vid_apis[0][i].name, name)) return(i); + } + + /* Default value. */ + return(0); +} + + +int +plat_setvid(int api) +{ + int i; + + pclog("Initializing VIDAPI: api=%d\n", api); + startblit(); + video_wait_for_blit(); + + /* Close the (old) API. */ + vid_apis[0][vid_api].close(); +#ifdef USE_WX + ui_check_menu_item(IDM_View_WX+vid_api, 0); +#endif + vid_api = api; + + if (vid_apis[0][vid_api].local) + ShowWindow(hwndRender, SW_SHOW); + else + ShowWindow(hwndRender, SW_HIDE); + + /* Initialize the (new) API. */ +#ifdef USE_WX + ui_check_menu_item(IDM_View_WX+vid_api, 1); +#endif + i = vid_apis[0][vid_api].init((void *)hwndRender); + endblit(); + if (! i) return(0); + + device_force_redraw(); + + return(1); +} + + +int +get_vidpause(void) +{ + return(vid_apis[video_fullscreen][vid_api].pause()); +} + + +void +plat_setfullscreen(int on) +{ + static int flag = 0; + + /* Want off and already off? */ + if (!on && !video_fullscreen) return; + + /* Want on and already on? */ + if (on && video_fullscreen) return; + + if (!on && !flag) { + /* We want to leave FS mode. */ + flag = 1; + + return; + } + + if (video_fullscreen_first) { + video_fullscreen_first = 0; + ui_msgbox(MBX_INFO, (wchar_t *)IDS_2074); + } + + /* OK, claim the video. */ + startblit(); + video_wait_for_blit(); + + mouse_close(); + + /* Close the current mode, and open the new one. */ + vid_apis[video_fullscreen][vid_api].close(); + video_fullscreen = on; + vid_apis[video_fullscreen][vid_api].init(NULL); + flag = 0; + + mouse_init(); + + /* Release video and make it redraw the screen. */ + endblit(); + device_force_redraw(); +} + + +void +take_screenshot(void) +{ + wchar_t path[1024], fn[128]; + struct tm *info; + time_t now; + + pclog("Screenshot: video API is: %i\n", vid_api); + if ((vid_api < 0) || (vid_api > 1)) return; + + memset(fn, 0, sizeof(fn)); + memset(path, 0, sizeof(path)); + + (void)time(&now); + info = localtime(&now); + + plat_append_filename(path, cfg_path, SCREENSHOT_PATH, sizeof(path)-2); + + if (! plat_dir_check(path)) + plat_dir_create(path); + +#ifdef WIN32 + wcscat(path, L"\\"); +#else + wcscat(path, L"/"); +#endif + + switch(vid_api) { + case 0: /* ddraw */ + wcsftime(path, 128, L"%Y%m%d_%H%M%S.bmp", info); + plat_append_filename(path, cfg_path, fn, 1024); + if (video_fullscreen) + ddraw_fs_take_screenshot(path); + else + ddraw_take_screenshot(path); + pclog("Screenshot: fn='%ls'\n", path); + break; + + case 1: /* d3d9 */ + wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); + plat_append_filename(path, cfg_path, fn, 1024); + if (video_fullscreen) + d3d_fs_take_screenshot(path); + else + d3d_take_screenshot(path); + pclog("Screenshot: fn='%ls'\n", path); + break; + +#ifdef USE_VNC + case 2: /* vnc */ + wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info); + plat_append_filename(path, cfg_path, fn, 1024); + vnc_take_screenshot(path); + pclog("Screenshot: fn='%ls'\n", path); + break; +#endif + } +} + + +void /* plat_ */ +startblit(void) +{ + WaitForSingleObject(ghMutex, INFINITE); +} + + +void /* plat_ */ +endblit(void) +{ + ReleaseMutex(ghMutex); +} + + +/* Tell the UI and/or renderers about a new screen resolution. */ +void +plat_resize(int x, int y) +{ +pclog("PLAT: VID[%d,%d] resizing to %dx%d\n", video_fullscreen, vid_api, x, y); + /* First, see if we should resize the UI window. */ + if (vid_resize) { + /* Move the main window. */ + + /* Move the status bar with it. */ + MoveWindow(hwndSBAR, 0, y+6, x, 17, TRUE); + + /* Move the render window if we have one. */ + if (vid_apis[0][vid_api].local && (hwndRender != NULL)) { + MoveWindow(hwndRender, 0, 0, x, y, TRUE); + } + } + + /* Now, tell the renderer about the new screen size we want. */ + if (vid_apis[video_fullscreen][vid_api].resize) { + startblit(); + vid_apis[video_fullscreen][vid_api].resize(x, y); + endblit(); + } +}