From c6227d1fc69048a150ec358074d8161981d5cd06 Mon Sep 17 00:00:00 2001 From: TomW Date: Sat, 7 Dec 2013 13:43:06 +0000 Subject: [PATCH] Added fullscreen mode. Some code tidying. --- src/Makefile.mingw | 2 +- src/ibm.h | 1 - src/pc.c | 7 +- src/pc.rc | 9 + src/plat-mouse.h | 2 +- src/resources.h | 38 ++-- src/video.c | 1 + src/video.h | 10 + src/win-d3d-fs.cc | 484 ++++++++++++++++++++++++++++++++++++++++++++ src/win-d3d-fs.h | 10 + src/win-ddraw-fs.cc | 324 +++++++++++++++++++++++++++++ src/win-ddraw-fs.h | 8 + src/win-ddraw.cc | 26 +-- src/win-ddraw.h | 3 - src/win-keyboard.cc | 8 + src/win-mouse.cc | 6 +- src/win.c | 224 +++++++++++++------- src/win.h | 13 ++ 18 files changed, 1060 insertions(+), 116 deletions(-) create mode 100644 src/win-d3d-fs.cc create mode 100644 src/win-d3d-fs.h create mode 100644 src/win-ddraw-fs.cc create mode 100644 src/win-ddraw-fs.h diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 61558bd..afa24e3 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -18,7 +18,7 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o \ vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \ vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \ - vid_voodoo.o video.o wd76c10.o win.o win-d3d.o win-ddraw.o win-keyboard.o win-midi.o \ + vid_voodoo.o video.o wd76c10.o win.o win-d3d.o win-d3d-fs.o win-ddraw.o win-ddraw-fs.o win-keyboard.o win-midi.o \ win-mouse.o win-timer.o win-video.o x86seg.o x87.o xtide.o pc.res FMOBJ = fmopl.o ymf262.o diff --git a/src/ibm.h b/src/ibm.h index 203a0c2..93e4c57 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -443,7 +443,6 @@ PcemHDC hdc[2]; /*Keyboard*/ int keybsenddelay; -extern int kb_win; /*CD-ROM*/ diff --git a/src/pc.c b/src/pc.c index 4868e4f..fd72143 100644 --- a/src/pc.c +++ b/src/pc.c @@ -34,7 +34,6 @@ int frame = 0; int cdrom_enabled; int CPUID; -int kb_win; int vid_resize, vid_api; int cycles_lost = 0; @@ -461,9 +460,10 @@ void loadconfig() cache = get_config_int(NULL, "cache", 3); cga_comp = get_config_int(NULL, "cga_composite", 0); - kb_win = get_config_int(NULL, "kb_win", 0); vid_resize = get_config_int(NULL, "vid_resize", 0); vid_api = get_config_int(NULL, "vid_api", 0); + video_fullscreen_scale = get_config_int(NULL, "video_fullscreen_scale", 0); + video_fullscreen_first = get_config_int(NULL, "video_fullscreen_first", 1); hdc[0].spt = get_config_int(NULL, "hdc_sectors", 0); hdc[0].hpc = get_config_int(NULL, "hdc_heads", 0); @@ -502,9 +502,10 @@ void saveconfig() set_config_int(NULL, "mem_size", mem_size); set_config_int(NULL, "cdrom_drive", cdrom_drive); set_config_int(NULL, "cdrom_enabled", cdrom_enabled); - set_config_int(NULL, "kb_win", kb_win); set_config_int(NULL, "vid_resize", vid_resize); set_config_int(NULL, "vid_api", vid_api); + set_config_int(NULL, "video_fullscreen_scale", video_fullscreen_scale); + set_config_int(NULL, "video_fullscreen_first", video_fullscreen_first); set_config_int(NULL, "hdc_sectors", hdc[0].spt); set_config_int(NULL, "hdc_heads", hdc[0].hpc); diff --git a/src/pc.rc b/src/pc.rc index cb08eef..b0db6f8 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -30,6 +30,15 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&DirectDraw", IDM_VID_DDRAW MENUITEM "Direct&3D", IDM_VID_D3D + MENUITEM SEPARATOR + MENUITEM "&Fullscreen", IDM_VID_FULLSCREEN + POPUP "Fullscreen &stretch mode" + BEGIN + MENUITEM "&Full screen stretch", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Square pixels", IDM_VID_FS_SQ + MENUITEM "&Integer scale", IDM_VID_FS_INT + END END END POPUP "&Misc" diff --git a/src/plat-mouse.h b/src/plat-mouse.h index ff020ea..b96d707 100644 --- a/src/plat-mouse.h +++ b/src/plat-mouse.h @@ -2,7 +2,7 @@ extern "C" { #endif void mouse_init(); - void mouse_remove(); + void mouse_close(); extern int mouse_b; void poll_mouse(); void position_mouse(int x, int y); diff --git a/src/resources.h b/src/resources.h index a48dea5..f9bc464 100644 --- a/src/resources.h +++ b/src/resources.h @@ -1,20 +1,23 @@ -#define IDM_FILE_RESET 40000 -#define IDM_FILE_HRESET 40001 -#define IDM_FILE_EXIT 40002 -#define IDM_DISC_A 40010 -#define IDM_DISC_B 40011 -#define IDM_EJECT_A 40012 -#define IDM_EJECT_B 40013 -#define IDM_HDCONF 40014 -#define IDM_CONFIG 40020 -#define IDM_STATUS 40030 -#define IDM_KEY_ALLEGRO 40040 -#define IDM_KEY_WINDOWS 40041 -#define IDM_VID_RESIZE 40050 -#define IDM_VID_DDRAW 40060 -#define IDM_VID_D3D 40061 -#define IDM_CDROM_EMPTY 40100 -#define IDM_CDROM_REAL 40100 +#define IDM_FILE_RESET 40000 +#define IDM_FILE_HRESET 40001 +#define IDM_FILE_EXIT 40002 +#define IDM_DISC_A 40010 +#define IDM_DISC_B 40011 +#define IDM_EJECT_A 40012 +#define IDM_EJECT_B 40013 +#define IDM_HDCONF 40014 +#define IDM_CONFIG 40020 +#define IDM_STATUS 40030 +#define IDM_VID_RESIZE 40050 +#define IDM_VID_DDRAW 40060 +#define IDM_VID_D3D 40061 +#define IDM_VID_FULLSCREEN 40070 +#define IDM_VID_FS_FULL 40071 +#define IDM_VID_FS_43 40072 +#define IDM_VID_FS_SQ 40073 +#define IDM_VID_FS_INT 40074 +#define IDM_CDROM_EMPTY 40100 +#define IDM_CDROM_REAL 40100 #define IDM_CDROM_DISABLED 40200 #define IDC_COMBO1 1000 @@ -61,3 +64,4 @@ #define IDC_STEXT_DEVICE 1108 #define WM_RESETD3D WM_USER +#define WM_LEAVEFULLSCREEN WM_USER + 1 diff --git a/src/video.c b/src/video.c index ea1406d..a397010 100644 --- a/src/video.c +++ b/src/video.c @@ -108,6 +108,7 @@ int video_new_to_old(int card) return video_cards[card].legacy_id; } +int video_fullscreen = 0, video_fullscreen_scale, video_fullscreen_first; uint32_t *video_15to32, *video_16to32; int egareads=0,egawrites=0; diff --git a/src/video.h b/src/video.h index f0c8304..1883ad8 100644 --- a/src/video.h +++ b/src/video.h @@ -4,6 +4,16 @@ int video_card_getid(char *s); int video_old_to_new(int card); int video_new_to_old(int card); +extern int video_fullscreen, video_fullscreen_scale, video_fullscreen_first; + +enum +{ + FULLSCR_SCALE_FULL = 0, + FULLSCR_SCALE_43, + FULLSCR_SCALE_SQ, + FULLSCR_SCALE_INT +}; + extern int egareads,egawrites; extern int fullchange; diff --git a/src/win-d3d-fs.cc b/src/win-d3d-fs.cc new file mode 100644 index 0000000..1804763 --- /dev/null +++ b/src/win-d3d-fs.cc @@ -0,0 +1,484 @@ +#include +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP +#include "resources.h" +#include "video.h" +#include "win-d3d-fs.h" +#include "win.h" + +extern "C" void fatal(const char *format, ...); +extern "C" void pclog(const char *format, ...); + +extern "C" void device_force_redraw(); + +static void d3d_fs_init_objects(); +static void d3d_fs_close_objects(); +static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h); + +static LPDIRECT3D9 d3d = NULL; +static LPDIRECT3DDEVICE9 d3ddev = NULL; +static LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL; +static LPDIRECT3DTEXTURE9 d3dTexture = NULL; +static D3DPRESENT_PARAMETERS d3dpp; + +static HWND d3d_hwnd; +static HWND d3d_device_window; + +static int d3d_fs_w, d3d_fs_h; + +struct CUSTOMVERTEX +{ + FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag + FLOAT tu, tv; +}; + +static 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}, + {0,0,0},{21,63,21},{63,21,21},{63,63,21}, + {0,0,0},{21,63,63},{63,21,63},{63,63,63}, + + {0,0,0},{0,0,42},{0,42,0},{0,42,42}, + {42,0,0},{42,0,42},{42,21,00},{42,42,42}, + {21,21,21},{21,21,63},{21,63,21},{21,63,63}, + {63,21,21},{63,21,63},{63,63,21},{63,63,63}, + + {0,0,0},{0,21,0},{0,0,42},{0,42,42}, + {42,0,21},{21,10,21},{42,0,42},{42,0,63}, + {21,21,21},{21,63,21},{42,21,42},{21,63,63}, + {63,0,0},{42,42,0},{63,21,42},{41,41,41}, + + {0,0,0},{0,42,42},{42,0,0},{42,42,42}, + {0,0,0},{0,42,42},{42,0,0},{42,42,42}, + {0,0,0},{0,63,63},{63,0,0},{63,63,63}, + {0,0,0},{0,63,63},{63,0,0},{63,63,63}, +}; + +static uint32_t pal_lookup[256]; + +static CUSTOMVERTEX d3d_verts[] = +{ + { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f}, + {2048.0f, 2048.0f, 1.0f, 1.0f, 1.0f, 1.0f}, + { 0.0f, 2048.0f, 1.0f, 1.0f, 0.0f, 1.0f}, + + { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f}, + {2048.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f}, + {2048.0f, 2048.0f, 1.0f, 1.0f, 1.0f, 1.0f}, +}; + +void d3d_fs_init(HWND h) +{ + int c; + HRESULT hr; + + d3d_fs_w = GetSystemMetrics(SM_CXSCREEN); + d3d_fs_h = GetSystemMetrics(SM_CYSCREEN); + + for (c = 0; c < 256; c++) + pal_lookup[c] = makecol(cgapal[c].r << 2, cgapal[c].g << 2, cgapal[c].b << 2); + + d3d_hwnd = h; + + d3d_device_window = CreateWindowEx ( + 0, + szSubClassName, + "PCem v0.7", + WS_POPUP, + CW_USEDEFAULT, + CW_USEDEFAULT, + 640, + 480, + HWND_DESKTOP, + NULL, + NULL, + NULL + ); + + d3d = Direct3DCreate9(D3D_SDK_VERSION); + + memset(&d3dpp, 0, sizeof(d3dpp)); + + d3dpp.Flags = 0; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.hDeviceWindow = d3d_device_window; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; + d3dpp.MultiSampleQuality = 0; + d3dpp.EnableAutoDepthStencil = false; + d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + d3dpp.Windowed = false; + d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; + d3dpp.BackBufferWidth = d3d_fs_w; + d3dpp.BackBufferHeight = d3d_fs_h; + + hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, h, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); + + d3d_fs_init_objects(); + + video_blit_memtoscreen = d3d_fs_blit_memtoscreen; + video_blit_memtoscreen_8 = d3d_fs_blit_memtoscreen_8; +} + +static void d3d_fs_close_objects() +{ + if (d3dTexture) + { + d3dTexture->Release(); + d3dTexture = NULL; + } + if (v_buffer) + { + v_buffer->Release(); + v_buffer = NULL; + } +} + +static void d3d_fs_init_objects() +{ + HRESULT hr; + D3DLOCKED_RECT dr; + int y; + RECT r; + + hr = d3ddev->CreateVertexBuffer(6*sizeof(CUSTOMVERTEX), + 0, + D3DFVF_XYZRHW | D3DFVF_TEX1, + D3DPOOL_MANAGED, + &v_buffer, + NULL); + + d3ddev->CreateTexture(2048, 2048, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &d3dTexture, NULL); + + r.top = r.left = 0; + r.bottom = r.right = 2047; + + if (FAILED(d3dTexture->LockRect(0, &dr, &r, 0))) + fatal("LockRect failed\n"); + + for (y = 0; y < 2048; y++) + { + uint32_t *p = (uint32_t *)(dr.pBits + (y * dr.Pitch)); + memset(p, 0, 2048 * 4); + } + + d3dTexture->UnlockRect(0); + + d3ddev->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1); + d3ddev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddev->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + d3ddev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); +} + +/*void d3d_resize(int x, int y) +{ + HRESULT hr; + + d3dpp.BackBufferWidth = x; + d3dpp.BackBufferHeight = y; + + d3d_reset(); +}*/ + +void d3d_fs_reset() +{ + HRESULT hr; + + memset(&d3dpp, 0, sizeof(d3dpp)); + + d3dpp.Flags = 0; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.hDeviceWindow = d3d_device_window; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; + d3dpp.MultiSampleQuality = 0; + d3dpp.EnableAutoDepthStencil = false; + d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + d3dpp.Windowed = false; + d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; + d3dpp.BackBufferWidth = d3d_fs_w; + d3dpp.BackBufferHeight = d3d_fs_h; + + hr = d3ddev->Reset(&d3dpp); + + if (hr == D3DERR_DEVICELOST) + return; + + d3ddev->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1); + d3ddev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddev->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + d3ddev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + + device_force_redraw(); +} + +void d3d_fs_close() +{ + if (d3dTexture) + { + d3dTexture->Release(); + d3dTexture = NULL; + } + if (v_buffer) + { + v_buffer->Release(); + v_buffer = NULL; + } + if (d3ddev) + { + d3ddev->Release(); + d3ddev = NULL; + } + if (d3d) + { + d3d->Release(); + d3d = NULL; + } + DestroyWindow(d3d_device_window); +} + +static void d3d_fs_size(RECT window_rect, double *l, double *t, double *r, double *b, int w, int h) +{ + int ratio_w, ratio_h; + switch (video_fullscreen_scale) + { + case FULLSCR_SCALE_FULL: + *l = -0.5; + *t = -0.5; + *r = (window_rect.right - window_rect.left) - 0.5; + *b = (window_rect.bottom - window_rect.top) - 0.5; + break; + case FULLSCR_SCALE_43: + *t = -0.5; + *b = (window_rect.bottom - window_rect.top) - 0.5; + *l = ((window_rect.right - window_rect.left) / 2) - (((window_rect.bottom - window_rect.top) * 4) / (3 * 2)) - 0.5; + *r = ((window_rect.right - window_rect.left) / 2) + (((window_rect.bottom - window_rect.top) * 4) / (3 * 2)) - 0.5; + if (*l < -0.5) + { + *l = -0.5; + *r = (window_rect.right - window_rect.left) - 0.5; + *t = ((window_rect.bottom - window_rect.top) / 2) - (((window_rect.right - window_rect.left) * 3) / (4 * 2)) - 0.5; + *b = ((window_rect.bottom - window_rect.top) / 2) + (((window_rect.right - window_rect.left) * 3) / (4 * 2)) - 0.5; + } + break; + case FULLSCR_SCALE_SQ: + *t = -0.5; + *b = (window_rect.bottom - window_rect.top) - 0.5; + *l = ((window_rect.right - window_rect.left) / 2) - (((window_rect.bottom - window_rect.top) * w) / (h * 2)) - 0.5; + *r = ((window_rect.right - window_rect.left) / 2) + (((window_rect.bottom - window_rect.top) * w) / (h * 2)) - 0.5; + if (*l < -0.5) + { + *l = -0.5; + *r = (window_rect.right - window_rect.left) - 0.5; + *t = ((window_rect.bottom - window_rect.top) / 2) - (((window_rect.right - window_rect.left) * h) / (w * 2)) - 0.5; + *b = ((window_rect.bottom - window_rect.top) / 2) + (((window_rect.right - window_rect.left) * h) / (w * 2)) - 0.5; + } + break; + case FULLSCR_SCALE_INT: + ratio_w = (window_rect.right - window_rect.left) / w; + ratio_h = (window_rect.bottom - window_rect.top) / h; + if (ratio_h < ratio_w) + ratio_w = ratio_h; + *l = ((window_rect.right - window_rect.left) / 2) - ((w * ratio_w) / 2) - 0.5; + *r = ((window_rect.right - window_rect.left) / 2) + ((w * ratio_w) / 2) - 0.5; + *t = ((window_rect.bottom - window_rect.top) / 2) - ((h * ratio_w) / 2) - 0.5; + *b = ((window_rect.bottom - window_rect.top) / 2) + ((h * ratio_w) / 2) - 0.5; + break; + } +} + +static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +{ + HRESULT hr = D3D_OK; + VOID* pVoid; + D3DLOCKED_RECT dr; + RECT window_rect; + uint32_t *p, *src; + int yy; + double l, t, r, b; + + d3d_verts[0].tu = d3d_verts[2].tu = d3d_verts[3].tu = 0; + d3d_verts[0].tv = d3d_verts[3].tv = d3d_verts[4].tv = 0; + d3d_verts[1].tu = d3d_verts[4].tu = d3d_verts[5].tu = (float)w / 2048.0; + d3d_verts[1].tv = d3d_verts[2].tv = d3d_verts[5].tv = (float)h / 2048.0; + + GetClientRect(d3d_device_window, &window_rect); + d3d_fs_size(window_rect, &l, &t, &r, &b, w, h); + + d3d_verts[0].x = l; + d3d_verts[0].y = t; + d3d_verts[1].x = r; + d3d_verts[1].y = b; + d3d_verts[2].x = l; + d3d_verts[2].y = b; + d3d_verts[3].x = l; + d3d_verts[3].y = t; + d3d_verts[4].x = r; + d3d_verts[4].y = t; + d3d_verts[5].x = r; + d3d_verts[5].y = b; + + if (hr == D3D_OK) + hr = v_buffer->Lock(0, 0, (void**)&pVoid, 0); + if (hr == D3D_OK) + memcpy(pVoid, d3d_verts, sizeof(d3d_verts)); + if (hr == D3D_OK) + hr = v_buffer->Unlock(); + + if (hr == D3D_OK && !(y1 == 0 && y2 == 0)) + { + RECT lock_rect; + + lock_rect.top = y1; + lock_rect.left = 0; + lock_rect.bottom = y2; + lock_rect.right = 2047; + + if (FAILED(d3dTexture->LockRect(0, &dr, &lock_rect, 0))) + fatal("LockRect failed\n"); + + for (yy = y1; yy < y2; yy++) + memcpy(dr.pBits + ((yy - y1) * dr.Pitch), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + + d3dTexture->UnlockRect(0); + } + + if (hr == D3D_OK) + hr = d3ddev->BeginScene(); + + if (hr == D3D_OK) + { + if (hr == D3D_OK) + d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0); + + if (hr == D3D_OK) + hr = d3ddev->SetTexture(0, d3dTexture); + + if (hr == D3D_OK) + hr = d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + if (hr == D3D_OK) + hr = d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX)); + + if (hr == D3D_OK) + hr = d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); + + if (hr == D3D_OK) + hr = d3ddev->SetTexture(0, NULL); + + if (hr == D3D_OK) + hr = d3ddev->EndScene(); + } + + if (hr == D3D_OK) + hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL); + + if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) + PostMessage(ghwnd, WM_RESETD3D, 0, 0); +} + +static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h) +{ + HRESULT hr = D3D_OK; + VOID* pVoid; + D3DLOCKED_RECT dr; + RECT window_rect; + uint32_t *p, *src; + int xx, yy; + double l, t, r, b; + + d3d_verts[0].tu = d3d_verts[2].tu = d3d_verts[3].tu = 0; + d3d_verts[0].tv = d3d_verts[3].tv = d3d_verts[4].tv = 0; + d3d_verts[1].tu = d3d_verts[4].tu = d3d_verts[5].tu = (float)w / 2048.0; + d3d_verts[1].tv = d3d_verts[2].tv = d3d_verts[5].tv = (float)h / 2048.0; + + GetClientRect(d3d_device_window, &window_rect); + d3d_fs_size(window_rect, &l, &t, &r, &b, w, h); + + d3d_verts[0].x = l; + d3d_verts[0].y = t; + d3d_verts[1].x = r; + d3d_verts[1].y = b; + d3d_verts[2].x = l; + d3d_verts[2].y = b; + d3d_verts[3].x = l; + d3d_verts[3].y = t; + d3d_verts[4].x = r; + d3d_verts[4].y = t; + d3d_verts[5].x = r; + d3d_verts[5].y = b; + + if (hr == D3D_OK) + hr = v_buffer->Lock(0, 0, (void**)&pVoid, 0); + if (hr == D3D_OK) + memcpy(pVoid, d3d_verts, sizeof(d3d_verts)); + if (hr == D3D_OK) + hr = v_buffer->Unlock(); + + if (hr == D3D_OK) + { + RECT lock_rect; + + lock_rect.top = 0; + lock_rect.left = 0; + lock_rect.bottom = 2047; + lock_rect.right = 2047; + + if (FAILED(d3dTexture->LockRect(0, &dr, &lock_rect, 0))) + fatal("LockRect failed\n"); + + for (yy = 0; yy < h; yy++) + { + uint32_t *p = (uint32_t *)(dr.pBits + (yy * dr.Pitch)); + if ((y + yy) >= 0 && (y + yy) < buffer->h) + { + for (xx = 0; xx < w; xx++) + p[xx] = pal_lookup[buffer->line[y + yy][x + xx]]; + } + } + + d3dTexture->UnlockRect(0); + } + + if (hr == D3D_OK) + hr = d3ddev->BeginScene(); + + if (hr == D3D_OK) + { + if (hr == D3D_OK) + d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0); + + if (hr == D3D_OK) + hr = d3ddev->SetTexture(0, d3dTexture); + + if (hr == D3D_OK) + hr = d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + if (hr == D3D_OK) + hr = d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX)); + + if (hr == D3D_OK) + hr = d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); + + if (hr == D3D_OK) + hr = d3ddev->SetTexture(0, NULL); + + if (hr == D3D_OK) + hr = d3ddev->EndScene(); + } + + if (hr == D3D_OK) + hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL); + + if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) + PostMessage(ghwnd, WM_RESETD3D, 0, 0); +} diff --git a/src/win-d3d-fs.h b/src/win-d3d-fs.h new file mode 100644 index 0000000..821537d --- /dev/null +++ b/src/win-d3d-fs.h @@ -0,0 +1,10 @@ +#ifdef __cplusplus +extern "C" { +#endif + void d3d_fs_init(HWND h); + void d3d_fs_close(); + void d3d_fs_reset(); + void d3d_fs_resize(int x, int y); +#ifdef __cplusplus +} +#endif diff --git a/src/win-ddraw-fs.cc b/src/win-ddraw-fs.cc new file mode 100644 index 0000000..4919dd7 --- /dev/null +++ b/src/win-ddraw-fs.cc @@ -0,0 +1,324 @@ +#include +#define BITMAP WINDOWS_BITMAP +#include +#undef BITMAP +#include "win-ddraw-fs.h" +#include "video.h" + +extern "C" void fatal(const char *format, ...); +extern "C" void pclog(const char *format, ...); + +extern "C" void device_force_redraw(); + +extern "C" void ddraw_fs_init(HWND h); +extern "C" void ddraw_fs_close(); + +static void ddraw_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +static void ddraw_fs_blit_memtoscreen_8(int x, int y, int w, int h); + +static LPDIRECTDRAW lpdd = NULL; +static LPDIRECTDRAW4 lpdd4 = NULL; +static LPDIRECTDRAWSURFACE4 lpdds_pri = NULL; +static LPDIRECTDRAWSURFACE4 lpdds_back = NULL; +static LPDIRECTDRAWSURFACE4 lpdds_back2 = NULL; +static LPDIRECTDRAWCLIPPER lpdd_clipper = NULL; +static DDSURFACEDESC2 ddsd; + +static HWND ddraw_hwnd; +static int ddraw_w, ddraw_h; + +static 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}, + {0,0,0},{21,63,21},{63,21,21},{63,63,21}, + {0,0,0},{21,63,63},{63,21,63},{63,63,63}, + + {0,0,0},{0,0,42},{0,42,0},{0,42,42}, + {42,0,0},{42,0,42},{42,21,00},{42,42,42}, + {21,21,21},{21,21,63},{21,63,21},{21,63,63}, + {63,21,21},{63,21,63},{63,63,21},{63,63,63}, + + {0,0,0},{0,21,0},{0,0,42},{0,42,42}, + {42,0,21},{21,10,21},{42,0,42},{42,0,63}, + {21,21,21},{21,63,21},{42,21,42},{21,63,63}, + {63,0,0},{42,42,0},{63,21,42},{41,41,41}, + + {0,0,0},{0,42,42},{42,0,0},{42,42,42}, + {0,0,0},{0,42,42},{42,0,0},{42,42,42}, + {0,0,0},{0,63,63},{63,0,0},{63,63,63}, + {0,0,0},{0,63,63},{63,0,0},{63,63,63}, +}; + +static uint32_t pal_lookup[256]; + +void ddraw_fs_init(HWND h) +{ + int c; + + ddraw_w = GetSystemMetrics(SM_CXSCREEN); + ddraw_h = GetSystemMetrics(SM_CYSCREEN); + + for (c = 0; c < 256; c++) + pal_lookup[c] = makecol(cgapal[c].r << 2, cgapal[c].g << 2, cgapal[c].b << 2); + + if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL))) + fatal("DirectDrawCreate failed\n"); + + if (FAILED(lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4))) + fatal("QueryInterface failed\n"); + + lpdd->Release(); + lpdd = NULL; + + atexit(ddraw_fs_close); + + if (FAILED(lpdd4->SetCooperativeLevel(h, DDSCL_SETFOCUSWINDOW | + DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT))) + fatal("SetCooperativeLevel failed\n"); + + if (FAILED(lpdd4->SetDisplayMode(ddraw_w, ddraw_h, 32, 0 ,0))) + fatal("SetDisplayMode failed\n"); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.dwBackBufferCount = 1; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; + if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL))) + fatal("CreateSurface failed\n"); + + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + if (FAILED(lpdds_pri->GetAttachedSurface(&ddsd.ddsCaps, &lpdds_back2))) + fatal("CreateSurface back failed\n"); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 2048; + ddsd.dwHeight = 2048; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL))) + fatal("CreateSurface back failed\n"); + + pclog("DDRAW_INIT complete\n"); + ddraw_hwnd = h; + video_blit_memtoscreen = ddraw_fs_blit_memtoscreen; + video_blit_memtoscreen_8 = ddraw_fs_blit_memtoscreen_8; +} + +void ddraw_fs_close() +{ + if (lpdds_back2) + { + lpdds_back2->Release(); + lpdds_back2 = NULL; + } + if (lpdds_back) + { + lpdds_back->Release(); + lpdds_back = NULL; + } + if (lpdds_pri) + { + lpdds_pri->Release(); + lpdds_pri = NULL; + } + if (lpdd_clipper) + { + lpdd_clipper->Release(); + lpdd_clipper = NULL; + } + if (lpdd4) + { + lpdd4->Release(); + lpdd4 = NULL; + } +} + +static void ddraw_fs_size(RECT window_rect, RECT *r_dest, int w, int h) +{ + int ratio_w, ratio_h; + switch (video_fullscreen_scale) + { + case FULLSCR_SCALE_FULL: + r_dest->left = 0; + r_dest->top = 0; + r_dest->right = (window_rect.right - window_rect.left) - 1; + r_dest->bottom = (window_rect.bottom - window_rect.top) - 1; + break; + case FULLSCR_SCALE_43: + r_dest->top = 0; + r_dest->bottom = (window_rect.bottom - window_rect.top) - 1; + r_dest->left = ((window_rect.right - window_rect.left) / 2) - (((window_rect.bottom - window_rect.top) * 4) / (3 * 2)); + r_dest->right = ((window_rect.right - window_rect.left) / 2) + (((window_rect.bottom - window_rect.top) * 4) / (3 * 2)) - 1; + if (r_dest->left < 0) + { + r_dest->left = 0; + r_dest->right = (window_rect.right - window_rect.left) - 1; + r_dest->top = ((window_rect.bottom - window_rect.top) / 2) - (((window_rect.right - window_rect.left) * 3) / (4 * 2)); + r_dest->bottom = ((window_rect.bottom - window_rect.top) / 2) + (((window_rect.right - window_rect.left) * 3) / (4 * 2)) - 1; + } + break; + case FULLSCR_SCALE_SQ: + r_dest->top = 0; + r_dest->bottom = (window_rect.bottom - window_rect.top) - 1; + r_dest->left = ((window_rect.right - window_rect.left) / 2) - (((window_rect.bottom - window_rect.top) * w) / (h * 2)); + r_dest->right = ((window_rect.right - window_rect.left) / 2) + (((window_rect.bottom - window_rect.top) * w) / (h * 2)) - 1; + if (r_dest->left < 0) + { + r_dest->left = 0; + r_dest->right = (window_rect.right - window_rect.left) - 1; + r_dest->top = ((window_rect.bottom - window_rect.top) / 2) - (((window_rect.right - window_rect.left) * h) / (w * 2)); + r_dest->bottom = ((window_rect.bottom - window_rect.top) / 2) + (((window_rect.right - window_rect.left) * h) / (w * 2)) - 1; + } + break; + case FULLSCR_SCALE_INT: + ratio_w = (window_rect.right - window_rect.left) / w; + ratio_h = (window_rect.bottom - window_rect.top) / h; + if (ratio_h < ratio_w) + ratio_w = ratio_h; + r_dest->left = ((window_rect.right - window_rect.left) / 2) - ((w * ratio_w) / 2); + r_dest->right = ((window_rect.right - window_rect.left) / 2) + ((w * ratio_w) / 2) - 1; + r_dest->top = ((window_rect.bottom - window_rect.top) / 2) - ((h * ratio_w) / 2); + r_dest->bottom = ((window_rect.bottom - window_rect.top) / 2) + ((h * ratio_w) / 2) - 1; + break; + } +} + +static void ddraw_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +{ + RECT r_src; + RECT r_dest; + RECT window_rect; + int yy; + HRESULT hr; + DDBLTFX ddbltfx; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) + { + lpdds_back->Restore(); + lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + device_force_redraw(); + } + if (!ddsd.lpSurface) return; + for (yy = y1; yy < y2; yy++) + memcpy(ddsd.lpSurface + (yy * ddsd.lPitch), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + lpdds_back->Unlock(NULL); + + window_rect.left = 0; + window_rect.top = 0; + window_rect.right = ddraw_w; + window_rect.bottom = ddraw_h; + ddraw_fs_size(window_rect, &r_dest, w, h); + + r_src.left = 0; + r_src.top = 0; + r_src.right = w; + r_src.bottom = h; + + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = 0; + + lpdds_back2->Blt(&window_rect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); + + hr = lpdds_back2->Blt(&r_dest, lpdds_back, &r_src, DDBLT_WAIT, NULL); + if (hr == DDERR_SURFACELOST) + { + lpdds_back2->Restore(); + lpdds_back2->Blt(&r_dest, lpdds_back, &r_src, DDBLT_WAIT, NULL); + } + + if (readflash) + { + RECT r; + r.left = window_rect.right - 40; + r.right = window_rect.right - 8; + r.top = 8; + r.bottom = 14; + ddbltfx.dwFillColor = 0xffffff; + lpdds_back2->Blt(&r, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); + } + + hr = lpdds_pri->Flip(NULL, DDFLIP_NOVSYNC); + if (hr == DDERR_SURFACELOST) + { + lpdds_pri->Restore(); + lpdds_pri->Flip(NULL, DDFLIP_NOVSYNC); + } +} + +static void ddraw_fs_blit_memtoscreen_8(int x, int y, int w, int h) +{ + RECT r_src; + RECT r_dest; + RECT window_rect; + int xx, yy; + HRESULT hr; + DDBLTFX ddbltfx; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + + if (hr == DDERR_SURFACELOST) + { + lpdds_back->Restore(); + lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + device_force_redraw(); + } + if (!ddsd.lpSurface) return; + for (yy = 0; yy < h; yy++) + { + if ((y + yy) >= 0 && (y + yy) < buffer->h) + { + uint32_t *p = (uint32_t *)(ddsd.lpSurface + (yy * ddsd.lPitch)); + for (xx = 0; xx < w; xx++) + p[xx] = pal_lookup[buffer->line[y + yy][x + xx]]; + } + } + lpdds_back->Unlock(NULL); + + window_rect.left = 0; + window_rect.top = 0; + window_rect.right = ddraw_w; + window_rect.bottom = ddraw_h; + ddraw_fs_size(window_rect, &r_dest, w, h); + + r_src.left = 0; + r_src.top = 0; + r_src.right = w; + r_src.bottom = h; + + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = 0; + + lpdds_back2->Blt(&window_rect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); + + hr = lpdds_back2->Blt(&r_dest, lpdds_back, &r_src, DDBLT_WAIT, NULL); + if (hr == DDERR_SURFACELOST) + { + lpdds_back2->Restore(); + lpdds_back2->Blt(&r_dest, lpdds_back, &r_src, DDBLT_WAIT, NULL); + } + + if (readflash) + { + RECT r; + r.left = window_rect.right - 40; + r.right = window_rect.right - 8; + r.top = 8; + r.bottom = 14; + ddbltfx.dwFillColor = 0xffffff; + lpdds_back2->Blt(&r, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); + } + + lpdds_pri->Flip(NULL, DDFLIP_NOVSYNC); +} diff --git a/src/win-ddraw-fs.h b/src/win-ddraw-fs.h new file mode 100644 index 0000000..122b98d --- /dev/null +++ b/src/win-ddraw-fs.h @@ -0,0 +1,8 @@ +#ifdef __cplusplus +extern "C" { +#endif + void ddraw_fs_init(HWND h); + void ddraw_fs_close(); +#ifdef __cplusplus +} +#endif diff --git a/src/win-ddraw.cc b/src/win-ddraw.cc index 7719100..90ed957 100644 --- a/src/win-ddraw.cc +++ b/src/win-ddraw.cc @@ -12,17 +12,19 @@ extern "C" void device_force_redraw(); extern "C" void ddraw_init(HWND h); extern "C" void ddraw_close(); -extern "C" void ddraw_draw(); -LPDIRECTDRAW lpdd = NULL; -LPDIRECTDRAW4 lpdd4 = NULL; -LPDIRECTDRAWSURFACE4 lpdds_pri = NULL; -LPDIRECTDRAWSURFACE4 lpdds_back = NULL; -LPDIRECTDRAWSURFACE4 lpdds_back2 = NULL; -LPDIRECTDRAWCLIPPER lpdd_clipper = NULL; -DDSURFACEDESC2 ddsd; +static void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +static void ddraw_blit_memtoscreen_8(int x, int y, int w, int h); -HWND ddraw_hwnd; +static LPDIRECTDRAW lpdd = NULL; +static LPDIRECTDRAW4 lpdd4 = NULL; +static LPDIRECTDRAWSURFACE4 lpdds_pri = NULL; +static LPDIRECTDRAWSURFACE4 lpdds_back = NULL; +static LPDIRECTDRAWSURFACE4 lpdds_back2 = NULL; +static LPDIRECTDRAWCLIPPER lpdd_clipper = NULL; +static DDSURFACEDESC2 ddsd; + +static HWND ddraw_hwnd; static PALETTE cgapal= { @@ -140,7 +142,7 @@ void ddraw_close() } } -void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +static void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { RECT r_src; RECT r_dest; @@ -171,7 +173,7 @@ void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) ClientToScreen(ddraw_hwnd, &po); GetClientRect(ddraw_hwnd, &r_dest); OffsetRect(&r_dest, po.x, po.y); - + r_src.left = 0; r_src.top = 0; r_src.right = w; @@ -213,7 +215,7 @@ void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) } } -void ddraw_blit_memtoscreen_8(int x, int y, int w, int h) +static void ddraw_blit_memtoscreen_8(int x, int y, int w, int h) { RECT r_src; RECT r_dest; diff --git a/src/win-ddraw.h b/src/win-ddraw.h index 22a8c13..7561cca 100644 --- a/src/win-ddraw.h +++ b/src/win-ddraw.h @@ -3,9 +3,6 @@ extern "C" { #endif void ddraw_init(HWND h); void ddraw_close(); - - void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); - void ddraw_blit_memtoscreen_8(int x, int y, int w, int h); #ifdef __cplusplus } #endif diff --git a/src/win-keyboard.cc b/src/win-keyboard.cc index e7963a8..0b4a814 100644 --- a/src/win-keyboard.cc +++ b/src/win-keyboard.cc @@ -2,9 +2,12 @@ #include #include #define DIRECTINPUT_VERSION 0x0700 +#define BITMAP WINDOWS_BITMAP #include +#undef BITMAP #include "plat-keyboard.h" #include "win.h" +#include "video.h" extern "C" int key[256]; uint8_t dinput_key[256]; @@ -106,4 +109,9 @@ void keyboard_poll_host() // if (key[c]) pclog("Key down %i %02X %i %02X\n", c, c, keyboard_lookup[c], keyboard_lookup[c]); } } + if (((dinput_key[DIK_LCONTROL] | dinput_key[DIK_RCONTROL]) & 0x80) && + ((dinput_key[DIK_LMENU] | dinput_key[DIK_RMENU]) & 0x80) && + (dinput_key[DIK_NEXT] & 0x80) && + video_fullscreen) + leave_fullscreen(); } diff --git a/src/win-mouse.cc b/src/win-mouse.cc index 08f493f..7823f4b 100644 --- a/src/win-mouse.cc +++ b/src/win-mouse.cc @@ -3,6 +3,8 @@ #include "plat-dinput.h" #include "win.h" +extern "C" int video_fullscreen; + extern "C" void fatal(const char *format, ...); extern "C" void pclog(const char *format, ...); @@ -23,7 +25,7 @@ void mouse_init() if (FAILED(lpdi->CreateDevice(GUID_SysMouse, &lpdi_mouse, NULL))) fatal("mouse_init : CreateDevice failed\n"); - if (FAILED(lpdi_mouse->SetCooperativeLevel(ghwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) + if (FAILED(lpdi_mouse->SetCooperativeLevel(ghwnd, DISCL_FOREGROUND | (video_fullscreen ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE)))) fatal("mouse_init : SetCooperativeLevel failed\n"); if (FAILED(lpdi_mouse->SetDataFormat(&c_dfDIMouse))) fatal("mouse_init : SetDataFormat failed\n"); @@ -56,7 +58,7 @@ void poll_mouse() mouse_b |= 4; mouse_x += mousestate.lX; mouse_y += mousestate.lY; - if (!mousecapture) + if (!mousecapture && !video_fullscreen) mouse_x = mouse_y = mouse_b = 0; } diff --git a/src/win.c b/src/win.c index f19a4ba..0513216 100644 --- a/src/win.c +++ b/src/win.c @@ -21,8 +21,11 @@ #include "plat-midi.h" #include "plat-keyboard.h" +#include "win.h" #include "win-ddraw.h" +#include "win-ddraw-fs.h" #include "win-d3d.h" +#include "win-d3d-fs.h" //#include "win-opengl.h" static struct @@ -30,10 +33,16 @@ static struct void (*init)(HWND h); void (*close)(); void (*resize)(int x, int y); -} vid_apis[] = +} vid_apis[2][2] = { - ddraw_init, ddraw_close, NULL, - d3d_init, d3d_close, d3d_resize + { + ddraw_init, ddraw_close, NULL, + d3d_init, d3d_close, d3d_resize + }, + { + ddraw_fs_init, ddraw_fs_close, NULL, + d3d_fs_init, d3d_fs_close, NULL + }, }; #define TIMER_1SEC 1 @@ -80,10 +89,8 @@ RECT oldclip; int mousecapture=0; int drawit; /* Declare Windows procedure */ -LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); - -/* Make the class name into a global variable */ -char szClassName[ ] = "WindowsApp"; +LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); HWND ghwnd; static int win_doresize = 0; @@ -130,6 +137,12 @@ void endblit() LeaveCriticalSection(&cs); } +static int leave_fullscreen_flag = 0; +void leave_fullscreen() +{ + leave_fullscreen_flag = 1; +} + int mainthreadon=0; /*static HANDLE blitobject; @@ -189,20 +202,24 @@ void mainthread(LPVOID param) } } else - { Sleep(1); - } - if (win_doresize) + if (!video_fullscreen && win_doresize) { RECT r; GetWindowRect(ghwnd, &r); MoveWindow(ghwnd, r.left, r.top, - winsizex + (GetSystemMetrics(SM_CXFIXEDFRAME) * 2), - winsizey + (GetSystemMetrics(SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 1, - TRUE); + winsizex + (GetSystemMetrics(SM_CXFIXEDFRAME) * 2), + winsizey + (GetSystemMetrics(SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 1, + TRUE); win_doresize = 0; } + + if (leave_fullscreen_flag) + { + leave_fullscreen_flag = 0; + SendMessage(ghwnd, WM_LEAVEFULLSCREEN, 0, 0); + } } mainthreadon=0; } @@ -239,6 +256,8 @@ void get_executable_name(char *s, int size) void set_window_title(char *s) { + if (video_fullscreen) + return; SetWindowText(ghwnd, s); } @@ -248,51 +267,57 @@ int WINAPI WinMain (HINSTANCE hThisInstance, int nFunsterStil) { - HWND hwnd; /* This is the handle for our window */ - MSG messages; /* Here messages to the application are saved */ - WNDCLASSEX wincl; /* Data structure for the windowclass */ - int c, d; + HWND hwnd; /* This is the handle for our window */ + MSG messages; /* Here messages to the application are saved */ + WNDCLASSEX wincl; /* Data structure for the windowclass */ + int c, d; hinstance=hThisInstance; - /* The Window structure */ - wincl.hInstance = hThisInstance; - wincl.lpszClassName = szClassName; - wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ - wincl.style = CS_DBLCLKS; /* Catch double-clicks */ - wincl.cbSize = sizeof (WNDCLASSEX); + /* The Window structure */ + wincl.hInstance = hThisInstance; + wincl.lpszClassName = szClassName; + wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ + wincl.style = CS_DBLCLKS; /* Catch double-clicks */ + wincl.cbSize = sizeof (WNDCLASSEX); - /* Use default icon and mouse-pointer */ - wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); - wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); - wincl.hCursor = NULL;//LoadCursor (NULL, IDC_ARROW); - wincl.lpszMenuName = NULL; /* No menu */ - wincl.cbClsExtra = 0; /* No extra bytes after the window class */ - wincl.cbWndExtra = 0; /* structure or the window instance */ - /* Use Windows's default color as the background of the window */ - wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; + /* Use default icon and mouse-pointer */ + wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); + wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); + wincl.hCursor = NULL;//LoadCursor (NULL, IDC_ARROW); + wincl.lpszMenuName = NULL; /* No menu */ + wincl.cbClsExtra = 0; /* No extra bytes after the window class */ + wincl.cbWndExtra = 0; /* structure or the window instance */ + /* Use Windows's default color as the background of the window */ + wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; - /* Register the window class, and if it fails quit the program */ - if (!RegisterClassEx (&wincl)) - return 0; + /* Register the window class, and if it fails quit the program */ + if (!RegisterClassEx(&wincl)) + return 0; - menu=LoadMenu(hThisInstance,TEXT("MainMenu")); + wincl.lpszClassName = szSubClassName; + wincl.lpfnWndProc = subWindowProcedure; /* This function is called by windows */ + + if (!RegisterClassEx(&wincl)) + return 0; + + menu = LoadMenu(hThisInstance, TEXT("MainMenu")); initmenu(); - /* The class is registered, let's create the program*/ - hwnd = CreateWindowEx ( - 0, /* Extended possibilites for variation */ - szClassName, /* Classname */ - "PCem v0.7", /* Title Text */ - WS_OVERLAPPEDWINDOW&~WS_SIZEBOX, /* default window */ - CW_USEDEFAULT, /* Windows decides the position */ - CW_USEDEFAULT, /* where the window ends up on the screen */ - 640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* The programs width */ - 480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */ - HWND_DESKTOP, /* The window is a child-window to desktop */ - menu, /* Menu */ - hThisInstance, /* Program Instance handler */ - NULL /* No Window Creation data */ - ); + /* The class is registered, let's create the program*/ + hwnd = CreateWindowEx ( + 0, /* Extended possibilites for variation */ + szClassName, /* Classname */ + "PCem v0.7", /* Title Text */ + WS_OVERLAPPEDWINDOW&~WS_SIZEBOX, /* default window */ + CW_USEDEFAULT, /* Windows decides the position */ + CW_USEDEFAULT, /* where the window ends up on the screen */ + 640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* The programs width */ + 480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */ + HWND_DESKTOP, /* The window is a child-window to desktop */ + menu, /* Menu */ + hThisInstance, /* Program Instance handler */ + NULL /* No Window Creation data */ + ); /* Make the window visible on the screen */ ShowWindow (hwnd, nFunsterStil); @@ -306,7 +331,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, initpc(); - vid_apis[vid_api].init(ghwnd); + vid_apis[0][vid_api].init(ghwnd); if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE); else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE); @@ -315,9 +340,9 @@ int WINAPI WinMain (HINSTANCE hThisInstance, CheckMenuItem(menu, IDM_CDROM_DISABLED, MF_CHECKED); else CheckMenuItem(menu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED); - CheckMenuItem(menu, IDM_KEY_ALLEGRO + kb_win, MF_CHECKED); if (vid_resize) CheckMenuItem(menu, IDM_VID_RESIZE, MF_CHECKED); - CheckMenuItem(menu, IDM_VID_DDRAW + vid_api, MF_CHECKED); + CheckMenuItem(menu, IDM_VID_DDRAW + vid_api, MF_CHECKED); + CheckMenuItem(menu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED); // set_display_switch_mode(SWITCH_BACKGROUND); d=romset; @@ -439,12 +464,12 @@ InitializeCriticalSection(&cs); if (messages.message==WM_QUIT) quited=1; TranslateMessage(&messages); DispatchMessage(&messages); - if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END] && mousecapture) - { - ClipCursor(&oldclip); - ShowCursor(TRUE); - mousecapture=0; - } + if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END] && mousecapture) + { + ClipCursor(&oldclip); + ShowCursor(TRUE); + mousecapture=0; + } } quited=1; @@ -463,7 +488,7 @@ InitializeCriticalSection(&cs); closepc(); // pclog("dumpregs\n"); - vid_apis[vid_api].close(); + vid_apis[video_fullscreen][vid_api].close(); timeEndPeriod(1); // endsoundthread(); @@ -473,6 +498,10 @@ InitializeCriticalSection(&cs); ClipCursor(&oldclip); ShowCursor(TRUE); } + + UnregisterClass(szSubClassName, hinstance); + UnregisterClass(szClassName, hinstance); + // pclog("Ending! %i %i\n",messages.wParam,quited); return messages.wParam; } @@ -1398,12 +1427,13 @@ HHOOK hKeyboardHook; LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) { - if (nCode < 0 || nCode != HC_ACTION || !mousecapture) return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam); + if (nCode < 0 || nCode != HC_ACTION || (!mousecapture && !video_fullscreen)) + return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam); KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam; - if(p->vkCode==VK_TAB && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab - if(p->vkCode==VK_SPACE && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab + if (p->vkCode == VK_TAB && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab + if (p->vkCode == VK_SPACE && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab if((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)) return 1;//disable windows keys if (p->vkCode == VK_ESCAPE && p->flags & LLKHF_ALTDOWN) return 1;//disable alt-escape BOOL bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);//checks ctrl key pressed @@ -1496,21 +1526,39 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM case IDM_VID_DDRAW: case IDM_VID_D3D: startblit(); CheckMenuItem(hmenu, IDM_VID_DDRAW + vid_api, MF_UNCHECKED); - vid_apis[vid_api].close(); + vid_apis[0][vid_api].close(); vid_api = LOWORD(wParam) - IDM_VID_DDRAW; CheckMenuItem(hmenu, IDM_VID_DDRAW + vid_api, MF_CHECKED); - vid_apis[vid_api].init(ghwnd); + vid_apis[0][vid_api].init(ghwnd); endblit(); saveconfig(); device_force_redraw(); break; - case IDM_KEY_ALLEGRO: case IDM_KEY_WINDOWS: - CheckMenuItem(hmenu,LOWORD(wParam),MF_CHECKED); - CheckMenuItem(hmenu,LOWORD(wParam)^1,MF_UNCHECKED); -// if (kb_win && LOWORD(wParam)==IDM_KEY_ALLEGRO) install_keyboard(); -// if (!kb_win && LOWORD(wParam)==IDM_KEY_WINDOWS) remove_keyboard(); - kb_win=LOWORD(wParam)-IDM_KEY_ALLEGRO; + case IDM_VID_FULLSCREEN: + if (video_fullscreen_first) + { + video_fullscreen_first = 0; + MessageBox(hwnd, "Use CTRL + ALT + PAGE DOWN to return to windowed mode", "PCem", MB_OK); + } + startblit(); + mouse_close(); + vid_apis[0][vid_api].close(); + video_fullscreen = 1; + vid_apis[1][vid_api].init(ghwnd); + mouse_init(); + endblit(); + device_force_redraw(); + break; + + case IDM_VID_FS_FULL: + case IDM_VID_FS_43: + case IDM_VID_FS_SQ: + case IDM_VID_FS_INT: + 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); + saveconfig(); break; case IDM_CDROM_DISABLED: @@ -1597,7 +1645,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM break; case WM_LBUTTONUP: - if (!mousecapture) + if (!mousecapture && !video_fullscreen) { RECT pcclip; @@ -1621,10 +1669,10 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM winsizex=lParam&0xFFFF; winsizey=lParam>>16; - if (vid_apis[vid_api].resize) + if (vid_apis[video_fullscreen][vid_api].resize) { startblit(); - vid_apis[vid_api].resize(winsizex, winsizey); + vid_apis[video_fullscreen][vid_api].resize(winsizex, winsizey); endblit(); } @@ -1648,9 +1696,23 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM case WM_RESETD3D: startblit(); - d3d_reset(); + if (video_fullscreen) + d3d_fs_reset(); + else + d3d_reset(); endblit(); break; + + case WM_LEAVEFULLSCREEN: + startblit(); + mouse_close(); + vid_apis[1][vid_api].close(); + video_fullscreen = 0; + vid_apis[0][vid_api].init(ghwnd); + mouse_init(); + endblit(); + device_force_redraw(); + break; case WM_KEYDOWN: case WM_SYSKEYDOWN: @@ -1671,3 +1733,13 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM } return 0; } + +LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } + return 0; +} diff --git a/src/win.h b/src/win.h index 4506d16..fe69f01 100644 --- a/src/win.h +++ b/src/win.h @@ -1,3 +1,16 @@ extern HINSTANCE hinstance; extern HWND ghwnd; extern int mousecapture; + +#ifdef __cplusplus +extern "C" { +#endif + +#define szClassName "PCemMainWnd" +#define szSubClassName "PCemSubWnd" + +void leave_fullscreen(); + +#ifdef __cplusplus +} +#endif