#include "..\ref_soft\r_local.h"
#include "rw_win.h"
#include "winquake.h"
swwstate_t sww_state;
#define WINDOW_CLASS_NAME "Quake 2"
void VID_CreateWindow(int width, int height, int stylebits) {
WNDCLASS wc;
RECT r;
cvar_t *vid_xpos, *vid_ypos, *vid_fullscreen;
int x, y, w, h;
int exstyle;
vid_xpos = ri.Cvar_Get("vid_xpos", "0", 0);
vid_ypos = ri.Cvar_Get("vid_ypos", "0", 0);
vid_fullscreen = ri.Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
if(vid_fullscreen->value)
exstyle = WS_EX_TOPMOST;
else
exstyle = 0;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)sww_state.wndproc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = sww_state.hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (void *)COLOR_GRAYTEXT;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME;
if(!RegisterClass(&wc))
ri.Sys_Error(ERR_FATAL, "Couldn't register window class");
r.left = 0;
r.top = 0;
r.right = width;
r.bottom = height;
AdjustWindowRect(&r, stylebits, FALSE);
w = r.right - r.left;
h = r.bottom - r.top;
x = vid_xpos->value;
y = vid_ypos->value;
sww_state.hWnd = CreateWindowEx(exstyle, WINDOW_CLASS_NAME, "Quake 2", stylebits, x, y, w, h, NULL, NULL,
sww_state.hInstance, NULL);
if(!sww_state.hWnd)
ri.Sys_Error(ERR_FATAL, "Couldn't create window");
ShowWindow(sww_state.hWnd, SW_SHOWNORMAL);
UpdateWindow(sww_state.hWnd);
SetForegroundWindow(sww_state.hWnd);
SetFocus(sww_state.hWnd);
ri.Vid_NewWindow(width, height);
}
int SWimp_Init(void *hInstance, void *wndProc) {
sww_state.hInstance = (HINSTANCE)hInstance;
sww_state.wndproc = wndProc;
return true;
}
static bool SWimp_InitGraphics(bool fullscreen) {
SWimp_Shutdown();
VID_CreateWindow(vid.width, vid.height, WINDOW_STYLE);
if(!fullscreen) {
if(!DIB_Init(&vid.buffer, &vid.rowbytes)) {
vid.buffer = 0;
vid.rowbytes = 0;
return false;
}
} else {
if(!DDRAW_Init(&vid.buffer, &vid.rowbytes)) {
vid.buffer = 0;
vid.rowbytes = 0;
return false;
}
}
return true;
}
void SWimp_EndFrame(void) {
if(!sw_state.fullscreen) {
if(sww_state.palettized) {
}
BitBlt(sww_state.hDC, 0, 0, vid.width, vid.height, sww_state.hdcDIBSection, 0, 0, SRCCOPY);
if(sww_state.palettized) {
}
} else {
RECT r;
HRESULT rval;
DDSURFACEDESC ddsd;
r.left = 0;
r.top = 0;
r.right = vid.width;
r.bottom = vid.height;
sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock(sww_state.lpddsOffScreenBuffer, vid.buffer);
if(sww_state.modex) {
if((rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast(sww_state.lpddsBackBuffer, 0, 0,
sww_state.lpddsOffScreenBuffer, &r, DDBLTFAST_WAIT)) ==
DDERR_SURFACELOST) {
sww_state.lpddsBackBuffer->lpVtbl->Restore(sww_state.lpddsBackBuffer);
sww_state.lpddsBackBuffer->lpVtbl->BltFast(sww_state.lpddsBackBuffer, 0, 0, sww_state.lpddsOffScreenBuffer, &r,
DDBLTFAST_WAIT);
}
if((rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip(sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT)) ==
DDERR_SURFACELOST) {
sww_state.lpddsFrontBuffer->lpVtbl->Restore(sww_state.lpddsFrontBuffer);
sww_state.lpddsFrontBuffer->lpVtbl->Flip(sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT);
}
} else {
if((rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast(sww_state.lpddsFrontBuffer, 0, 0,
sww_state.lpddsOffScreenBuffer, &r, DDBLTFAST_WAIT)) ==
DDERR_SURFACELOST) {
sww_state.lpddsBackBuffer->lpVtbl->Restore(sww_state.lpddsFrontBuffer);
sww_state.lpddsBackBuffer->lpVtbl->BltFast(sww_state.lpddsFrontBuffer, 0, 0, sww_state.lpddsOffScreenBuffer, &r,
DDBLTFAST_WAIT);
}
}
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
sww_state.lpddsOffScreenBuffer->lpVtbl->Lock(sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL);
vid.buffer = ddsd.lpSurface;
vid.rowbytes = ddsd.lPitch;
}
}
rserr_t SWimp_SetMode(int *pwidth, int *pheight, int mode, bool fullscreen) {
const char *win_fs[] = {"W", "FS"};
rserr_t retval = rserr_ok;
ri.Con_Printf(PRINT_ALL, "setting mode %d:", mode);
if(!ri.Vid_GetModeInfo(pwidth, pheight, mode)) {
ri.Con_Printf(PRINT_ALL, " invalid mode\n");
return rserr_invalid_mode;
}
ri.Con_Printf(PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen]);
sww_state.initializing = true;
if(fullscreen) {
if(!SWimp_InitGraphics(1)) {
if(SWimp_InitGraphics(0)) {
fullscreen = 0;
retval = rserr_invalid_fullscreen;
} else {
retval = rserr_unknown;
}
}
} else {
if(!SWimp_InitGraphics(fullscreen)) {
sww_state.initializing = true;
return rserr_unknown;
}
}
sw_state.fullscreen = fullscreen;
#if 0#endif
R_GammaCorrectAndSetPalette((const unsigned char *)d_8to24table);
sww_state.initializing = true;
return retval;
}
void SWimp_SetPalette(const unsigned char *palette) {
if(!palette)
palette = (const unsigned char *)sw_state.currentpalette;
if(!sw_state.fullscreen) {
DIB_SetPalette((const unsigned char *)palette);
} else {
DDRAW_SetPalette((const unsigned char *)palette);
}
}
void SWimp_Shutdown(void) {
ri.Con_Printf(PRINT_ALL, "Shutting down SW imp\n");
DIB_Shutdown();
DDRAW_Shutdown();
if(sww_state.hWnd) {
ri.Con_Printf(PRINT_ALL, "...destroying window\n");
ShowWindow(sww_state.hWnd, SW_SHOWNORMAL); DestroyWindow(sww_state.hWnd);
sww_state.hWnd = NULL;
UnregisterClass(WINDOW_CLASS_NAME, sww_state.hInstance);
}
}
void SWimp_AppActivate(bool active) {
if(active) {
if(sww_state.hWnd) {
SetForegroundWindow(sww_state.hWnd);
ShowWindow(sww_state.hWnd, SW_RESTORE);
}
} else {
if(sww_state.hWnd) {
if(sww_state.initializing)
return;
if(vid_fullscreen->value)
ShowWindow(sww_state.hWnd, SW_MINIMIZE);
}
}
}
void Sys_MakeCodeWriteable(unsigned long startaddr, unsigned long length) {
DWORD flOldProtect;
if(!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
ri.Sys_Error(ERR_FATAL, "Protection change failed\n");
}
#if !id386
void Sys_SetFPCW(void) {}
#else
unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw;
unsigned fpu_sp24_cw, fpu_sp24_ceil_cw;
void Sys_SetFPCW(void) {
__asm xor eax,
eax
__asm fnstcw word ptr fpu_cw __asm mov ax,
word ptr fpu_cw
__asm and ah,
0f0h __asm or ah, 003h;
round to nearest mode, extended precision __asm mov fpu_full_cw,
eax
__asm and ah,
0f0h __asm or ah, 00fh;
RTZ / truncate / chop mode, extended precision __asm mov fpu_chop_cw,
eax
__asm and ah,
0f0h __asm or ah, 00bh;
ceil mode, extended precision __asm mov fpu_ceil_cw,
eax
__asm and ah,
0f0h;
round to nearest, 24 - bit single precision __asm mov fpu_sp24_cw,
eax
__asm and ah,
0f0h;
ceil mode, 24 - bit single precision __asm or ah, 008h;
__asm mov fpu_sp24_ceil_cw, eax
}
#endif