diff src/video/windx5/SDL_dx5events.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children 994ed1d668e7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/windx5/SDL_dx5events.c	Thu Apr 26 16:45:43 2001 +0000
@@ -0,0 +1,780 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* CAUTION!!!!  If you modify this file, check ../windib/SDL_sysevents.c */
+
+#include "directx.h"
+
+#include <stdio.h>
+#include "SDL_events.h"
+#include "SDL_video.h"
+#include "SDL_error.h"
+#include "SDL_syswm.h"
+#include "SDL_sysevents.h"
+#include "SDL_events_c.h"
+#include "SDL_lowvideo.h"
+#include "SDL_dx5video.h"
+
+#ifndef WM_APP
+#define WM_APP	0x8000
+#endif
+
+/* The keyboard and mouse device input */
+#define MAX_INPUTS	16		/* Maximum of 16-1 input devices */
+#define INPUT_QSIZE	32		/* Buffer up to 32 input messages */
+
+static LPDIRECTINPUT dinput = NULL;
+static LPDIRECTINPUTDEVICE2 SDL_DIdev[MAX_INPUTS];
+static HANDLE               SDL_DIevt[MAX_INPUTS];
+static void (*SDL_DIfun[MAX_INPUTS])(const int, DIDEVICEOBJECTDATA *);
+static int SDL_DIndev = 0;
+static int mouse_lost;
+static int mouse_pressed;
+
+/* The translation table from a DirectInput scancode to an SDL keysym */
+static SDLKey DIK_keymap[256];
+static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed);
+
+/* Convert a DirectInput return code to a text message */
+static void SetDIerror(char *function, int code)
+{
+	static char *error;
+	static char  errbuf[BUFSIZ];
+
+	errbuf[0] = 0;
+	switch (code) {
+                case DIERR_GENERIC:
+                        error = "Undefined error!";
+                        break;
+		case DIERR_OLDDIRECTINPUTVERSION:
+			error = "Your version of DirectInput needs upgrading";
+			break;
+		case DIERR_INVALIDPARAM:
+                        error = "Invalid parameters";
+                        break;
+                case DIERR_OUTOFMEMORY:
+                        error = "Out of memory";
+                        break;
+		case DIERR_DEVICENOTREG:
+			error = "Device not registered";
+			break;
+		case DIERR_NOINTERFACE:
+			error = "Interface not supported";
+			break;
+		case DIERR_NOTINITIALIZED:
+			error = "Device not initialized";
+			break;
+		default:
+			sprintf(errbuf, "%s: Unknown DirectInput error: 0x%x",
+								function, code);
+			break;
+	}
+	if ( ! errbuf[0] ) {
+		sprintf(errbuf, "%s: %s", function, error);
+	}
+	SDL_SetError("%s", errbuf);
+	return;
+}
+
+/* Initialize DirectInput
+   Note:  If NONEXCLUSIVE access is requested for the devices, normal 
+          windows input messages will continue to be generated for that
+          input device, in addition to DirectInput messages.
+ */
+static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *events);
+static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *events);
+struct {
+	char *name;
+	REFGUID guid;
+	LPCDIDATAFORMAT format;
+	DWORD win_level;
+	DWORD raw_level;
+	void (*fun)(const int numevents, DIDEVICEOBJECTDATA *events);
+} inputs[] = {
+	{ "keyboard",
+		&GUID_SysKeyboard, &c_dfDIKeyboard,
+		(DISCL_FOREGROUND|DISCL_NONEXCLUSIVE),
+		(DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard },
+	{ "mouse",
+		&GUID_SysMouse, &c_dfDIMouse,
+		(DISCL_FOREGROUND|DISCL_NONEXCLUSIVE),
+		(DISCL_FOREGROUND|DISCL_EXCLUSIVE), handle_mouse },
+	{ NULL, NULL, NULL, 0, 0, NULL }
+};
+	
+static int DX5_DInputInit(_THIS)
+{
+	int         i;
+	LPDIRECTINPUTDEVICE device;
+	HRESULT     result;
+	DIPROPDWORD dipdw;
+
+	/* Create the DirectInput object */
+	result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION,
+							&dinput, NULL);
+	if ( result != DI_OK ) {
+		SetDIerror("DirectInputCreate", result);
+		return(-1);
+	}
+
+	/* Create all of our registered input devices */
+	SDL_DIndev = 0;
+	for ( i=0; inputs[i].name; ++i ) {
+		/* Create the DirectInput device */
+		result = IDirectInput_CreateDevice(dinput, inputs[i].guid,
+								&device, NULL);
+		if ( result != DI_OK ) {
+			SetDIerror("DirectInput::CreateDevice", result);
+			return(-1);
+		}
+		result = IDirectInputDevice_QueryInterface(device,
+			&IID_IDirectInputDevice2, (LPVOID *)&SDL_DIdev[i]);
+		IDirectInputDevice_Release(device);
+		if ( result != DI_OK ) {
+			SetDIerror("DirectInputDevice::QueryInterface", result);
+			return(-1);
+		}
+		result = IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i],
+					SDL_Window, inputs[i].win_level);
+		if ( result != DI_OK ) {
+			SetDIerror("DirectInputDevice::SetCooperativeLevel",
+									result);
+			return(-1);
+		}
+		result = IDirectInputDevice2_SetDataFormat(SDL_DIdev[i],
+							inputs[i].format);
+		if ( result != DI_OK ) {
+			SetDIerror("DirectInputDevice::SetDataFormat", result);
+			return(-1);
+		}
+
+		/* Set buffered input -- we aren't polling */
+		memset(&dipdw, 0, sizeof(dipdw));
+		dipdw.diph.dwSize = sizeof(dipdw);
+		dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
+		dipdw.diph.dwObj = 0;
+		dipdw.diph.dwHow = DIPH_DEVICE;
+		dipdw.dwData = INPUT_QSIZE;
+		result = IDirectInputDevice2_SetProperty(SDL_DIdev[i],
+						DIPROP_BUFFERSIZE, &dipdw.diph);
+		if ( result != DI_OK ) {
+			SetDIerror("DirectInputDevice::SetProperty", result);
+			return(-1);
+		}
+
+		/* Create an event to be signaled when input is ready */
+		SDL_DIevt[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
+		if ( SDL_DIevt[i] == NULL ) {
+			SDL_SetError("Couldn't create DirectInput event");
+			return(-1);
+		}
+		result = IDirectInputDevice2_SetEventNotification(SDL_DIdev[i],
+								SDL_DIevt[i]);
+		if ( result != DI_OK ) {
+			SetDIerror("DirectInputDevice::SetEventNotification",
+									result);
+			return(-1);
+		}
+		SDL_DIfun[i] = inputs[i].fun;
+
+		/* Acquire the device for input */
+		IDirectInputDevice2_Acquire(SDL_DIdev[i]);
+
+		/* Increment the number of devices we have */
+		++SDL_DIndev;
+	}
+	mouse_pressed = 0;
+
+	/* DirectInput is ready! */
+	return(0);
+}
+
+/* Change cooperative level based on whether or not we are fullscreen */
+void DX5_DInputReset(_THIS, int fullscreen)
+{
+	DWORD level;
+	int i;
+	HRESULT result;
+
+	for ( i=0; i<MAX_INPUTS; ++i ) {
+		if ( SDL_DIdev[i] != NULL ) {
+			if ( fullscreen ) {
+				level = inputs[i].raw_level;
+			} else {
+				level = inputs[i].win_level;
+			}
+			IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
+			result = IDirectInputDevice2_SetCooperativeLevel(
+					SDL_DIdev[i], SDL_Window, level);
+			IDirectInputDevice2_Acquire(SDL_DIdev[i]);
+			if ( result != DI_OK ) {
+				SetDIerror(
+			"DirectInputDevice::SetCooperativeLevel", result);
+			}
+		}
+	}
+	mouse_lost = 1;
+}
+
+/* Clean up DirectInput */
+static void DX5_DInputQuit(_THIS)
+{
+	int i;
+
+	if ( dinput != NULL ) {
+		/* Close and release all DirectInput devices */
+		for ( i=0; i<MAX_INPUTS; ++i ) {
+			if ( SDL_DIdev[i] != NULL ) {
+				IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
+				IDirectInputDevice2_SetEventNotification(
+							SDL_DIdev[i], NULL);
+				if ( SDL_DIevt[i] != NULL ) {
+					CloseHandle(SDL_DIevt[i]);
+					SDL_DIevt[i] = NULL;
+				}
+				IDirectInputDevice2_Release(SDL_DIdev[i]);
+				SDL_DIdev[i] = NULL;
+			}
+		}
+		/* Release DirectInput */
+		IDirectInput_Release(dinput);
+		dinput = NULL;
+	}
+}
+
+/* Flag to tell SDL whether or not we queued an event */
+static int posted = 0;
+
+/* Input event handler functions */
+static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *keybuf)
+{
+	int i;
+	SDL_keysym keysym;
+
+	/* Translate keyboard messages */
+	for ( i=0; i<numevents; ++i ) {
+		if ( keybuf[i].dwData & 0x80 ) {
+			posted = SDL_PrivateKeyboard(SDL_PRESSED,
+				    TranslateKey(keybuf[i].dwOfs, &keysym, 1));
+		} else {
+			posted = SDL_PrivateKeyboard(SDL_RELEASED,
+				    TranslateKey(keybuf[i].dwOfs, &keysym, 0));
+		}
+	}
+}
+static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf)
+{
+	int i;
+	Sint16 xrel, yrel;
+	Uint8 state;
+	Uint8 button;
+
+	/* If we are in windowed mode, Windows is taking care of the mouse */
+	if ( ! (SDL_PublicSurface->flags & SDL_FULLSCREEN) ) {
+		return;
+	}
+
+	/* If the mouse was lost, regain some sense of mouse state */
+	if ( mouse_lost ) {
+		POINT mouse_pos;
+		Uint8 old_state;
+		Uint8 new_state;
+
+		/* Set ourselves up with the current cursor position */
+		GetCursorPos(&mouse_pos);
+		ScreenToClient(SDL_Window, &mouse_pos);
+		posted = SDL_PrivateMouseMotion(0, 0,
+				(Sint16)mouse_pos.x, (Sint16)mouse_pos.y);
+
+		/* Check for mouse button changes */
+		old_state = SDL_GetMouseState(NULL, NULL);
+		new_state = 0;
+		{ /* Get the new DirectInput button state for the mouse */
+			DIMOUSESTATE distate;
+			HRESULT result;
+
+			result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1],
+						sizeof(distate), &distate);
+			if ( result != DI_OK ) {
+				/* Try again next time */
+				SetDIerror(
+				"IDirectInputDevice2::GetDeviceState", result);
+				return;
+			}
+			for ( i=3; i>=0; --i ) {
+				if ( (distate.rgbButtons[i]&0x80) == 0x80 ) {
+					new_state |= 0x01;
+				}
+				new_state <<= 1;
+			}
+		}
+		for ( i=0; i<8; ++i ) {
+			if ( (old_state&0x01) != (new_state&0x01) ) {
+				button = (Uint8)(i+1);
+				/* Button #2 on two button mice is button 3
+				   (the middle button is button 2)
+				 */
+				if ( button == 2 ) {
+					button = 3;
+				} else
+				if ( button == 3 ) {
+					button = 2;
+				}
+				if ( new_state & 0x01 ) {
+					/* Grab mouse so we get mouse-up */
+					if ( ++mouse_pressed > 0 ) {
+						SetCapture(SDL_Window);
+					}
+					state = SDL_PRESSED;
+				} else {
+					/* Release mouse after all mouse-ups */
+					if ( --mouse_pressed <= 0 ) {
+						ReleaseCapture();
+						mouse_pressed = 0;
+					}
+					state = SDL_RELEASED;
+				}
+				posted = SDL_PrivateMouseButton(state, button,
+									0, 0);
+			}
+			old_state >>= 1;
+			new_state >>= 1;
+		}
+		mouse_lost = 0;
+		return;
+	}
+
+	/* Translate mouse messages */
+	xrel = 0;
+	yrel = 0;
+	for ( i=0; i<(int)numevents; ++i ) {
+		switch (ptrbuf[i].dwOfs) {
+			case DIMOFS_X:
+				xrel += (Sint16)ptrbuf[i].dwData;
+				break;
+			case DIMOFS_Y:
+				yrel += (Sint16)ptrbuf[i].dwData;
+				break;
+			case DIMOFS_BUTTON0:
+			case DIMOFS_BUTTON1:
+			case DIMOFS_BUTTON2:
+			case DIMOFS_BUTTON3:
+				if ( xrel || yrel ) {
+					posted = SDL_PrivateMouseMotion(
+							0, 1, xrel, yrel);
+					xrel = 0;
+					yrel = 0;
+				}
+				button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1;
+				/* Button #2 on two button mice is button 3
+				   (the middle button is button 2)
+				 */
+				if ( button == 2 ) {
+					button = 3;
+				} else
+				if ( button == 3 ) {
+					button = 2;
+				}
+				if ( ptrbuf[i].dwData & 0x80 ) {
+					/* Grab mouse so we get mouse-up */
+					if ( ++mouse_pressed > 0 ) {
+						SetCapture(SDL_Window);
+					}
+					state = SDL_PRESSED;
+				} else {
+					/* Release mouse after all mouse-ups */
+					if ( --mouse_pressed <= 0 ) {
+						ReleaseCapture();
+						mouse_pressed = 0;
+					}
+					state = SDL_RELEASED;
+				}
+				posted = SDL_PrivateMouseButton(state, button,
+									0, 0);
+				break;
+		}
+	}
+	if ( xrel || yrel ) {
+		posted = SDL_PrivateMouseMotion( 0, 1, xrel, yrel);
+	}
+}
+
+/* The main Win32 event handler */
+LONG
+ DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	switch (msg) {
+		case WM_ACTIVATEAPP: {
+			int i, active;
+
+			active = (wParam && (GetForegroundWindow() == hwnd));
+			if ( active ) {
+				for ( i=0; SDL_DIdev[i]; ++i ) {
+					IDirectInputDevice2_Acquire(
+								SDL_DIdev[i]);
+				}
+			} else {
+				for ( i=0; SDL_DIdev[i]; ++i ) {
+					IDirectInputDevice2_Unacquire(
+								SDL_DIdev[i]);
+				}
+				mouse_lost = 1;
+			}
+		}
+		break;
+
+		case WM_DISPLAYCHANGE: {
+			WORD BitsPerPixel;
+			WORD SizeX, SizeY;
+
+			/* Ack!  The display changed size and/or depth! */
+			SizeX = LOWORD(lParam);
+			SizeY = HIWORD(lParam);
+			BitsPerPixel = wParam;
+			/* We cause this message when we go fullscreen */
+		}
+		break;
+
+		/* The keyboard is handled via DirectInput */
+		case WM_SYSKEYUP:
+		case WM_SYSKEYDOWN:
+		case WM_KEYUP:
+		case WM_KEYDOWN: {
+			/* Ignore windows keyboard messages */;
+		}
+		return(0);
+
+		/* Don't allow screen savers or monitor power downs.
+		   This is because they quietly clear DirectX surfaces.
+		   It would be better to allow the application to
+		   decide whether or not to blow these off, but the
+		   semantics of SDL_PrivateSysWMEvent() don't allow
+		   the application that choice.
+		 */
+		case WM_SYSCOMMAND: {
+			if ((wParam&0xFFF0)==SC_SCREENSAVE || 
+			    (wParam&0xFFF0)==SC_MONITORPOWER)
+				return(0);
+		}
+		goto custom_processing;
+		break;
+
+		default: {
+		custom_processing:
+			/* Only post the event if we're watching for it */
+			if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
+			        SDL_SysWMmsg wmmsg;
+
+				SDL_VERSION(&wmmsg.version);
+				wmmsg.hwnd = hwnd;
+				wmmsg.msg = msg;
+				wmmsg.wParam = wParam;
+				wmmsg.lParam = lParam;
+				posted = SDL_PrivateSysWMEvent(&wmmsg);
+			}
+		}
+		break;
+	}
+	return(DefWindowProc(hwnd, msg, wParam, lParam));
+}
+
+/* This function checks the windows message queue and DirectInput and returns
+   1 if there was input, 0 if there was no input, or -1 if the application has
+   posted a quit message.
+*/
+static int DX5_CheckInput(_THIS, int timeout)
+{
+	MSG msg;
+	int      i;
+	HRESULT  result;
+	DWORD    event;
+
+	/* Check the normal windows queue (highest preference) */
+	posted = 0;
+	while ( ! posted &&
+	        PeekMessage(&msg, NULL, 0, (WM_APP-1), PM_NOREMOVE) ) {
+		if ( GetMessage(&msg, NULL, 0, (WM_APP-1)) > 0 ) {
+			DispatchMessage(&msg);
+		} else {
+			return(-1);
+		}
+	}
+	if ( posted ) {
+		return(1);
+	}
+
+	/* Pump the DirectInput flow */
+	if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
+		for ( i=0; i<SDL_DIndev; ++i ) {
+			result = IDirectInputDevice2_Poll(SDL_DIdev[i]);
+			if ( (result == DIERR_INPUTLOST) ||
+					(result == DIERR_NOTACQUIRED) ) {
+				if ( strcmp(inputs[i].name, "mouse") == 0 ) {
+					mouse_lost = 1;
+				}
+				IDirectInputDevice2_Acquire(SDL_DIdev[i]);
+				IDirectInputDevice2_Poll(SDL_DIdev[i]);
+			}
+		}
+	}
+
+	/* Wait for messages and input events */
+	event = MsgWaitForMultipleObjects(SDL_DIndev, SDL_DIevt, FALSE,
+							timeout, QS_ALLEVENTS);
+	if ((event >= WAIT_OBJECT_0) && (event < (WAIT_OBJECT_0+SDL_DIndev))) {
+		DWORD numevents;
+		DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
+
+		event -= WAIT_OBJECT_0;
+		numevents = INPUT_QSIZE;
+		result = IDirectInputDevice2_GetDeviceData(
+				SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA),
+							evtbuf, &numevents, 0);
+		if ( (result == DIERR_INPUTLOST) ||
+					(result == DIERR_NOTACQUIRED) ) {
+			if ( strcmp(inputs[event].name, "mouse") == 0 ) {
+				mouse_lost = 1;
+			}
+			IDirectInputDevice2_Acquire(SDL_DIdev[event]);
+			result = IDirectInputDevice2_GetDeviceData(
+				SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA),
+							evtbuf, &numevents, 0);
+		}
+		/* Handle the events */
+		if ( result == DI_OK ) {
+			/* Note: This can post multiple events to event queue
+			 */
+			(*SDL_DIfun[event])((int)numevents, evtbuf);
+			return(1);
+		}
+	}
+	if ( event != WAIT_TIMEOUT ) {
+		/* Maybe there was a windows message? */
+		if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
+			if ( GetMessage(&msg, NULL, 0, 0) > 0 ) {
+				DispatchMessage(&msg);
+			} else {
+				return(-1);
+			}
+			return(1);
+		}
+	}
+	return(0);
+}
+
+void DX5_PumpEvents(_THIS)
+{
+	/* Wait for messages and DirectInput */
+	while ( DX5_CheckInput(this, 0) > 0 ) {
+		/* Loop and check again */;
+	}
+}
+
+void DX5_InitOSKeymap(_THIS)
+{
+	int i;
+
+	/* Map the DIK scancodes to SDL keysyms */
+	for ( i=0; i<SDL_TABLESIZE(DIK_keymap); ++i )
+		DIK_keymap[i] = 0;
+
+	/* Defined DIK_* constants */
+	DIK_keymap[DIK_ESCAPE] = SDLK_ESCAPE;
+	DIK_keymap[DIK_1] = SDLK_1;
+	DIK_keymap[DIK_2] = SDLK_2;
+	DIK_keymap[DIK_3] = SDLK_3;
+	DIK_keymap[DIK_4] = SDLK_4;
+	DIK_keymap[DIK_5] = SDLK_5;
+	DIK_keymap[DIK_6] = SDLK_6;
+	DIK_keymap[DIK_7] = SDLK_7;
+	DIK_keymap[DIK_8] = SDLK_8;
+	DIK_keymap[DIK_9] = SDLK_9;
+	DIK_keymap[DIK_0] = SDLK_0;
+	DIK_keymap[DIK_MINUS] = SDLK_MINUS;
+	DIK_keymap[DIK_EQUALS] = SDLK_EQUALS;
+	DIK_keymap[DIK_BACK] = SDLK_BACKSPACE;
+	DIK_keymap[DIK_TAB] = SDLK_TAB;
+	DIK_keymap[DIK_Q] = SDLK_q;
+	DIK_keymap[DIK_W] = SDLK_w;
+	DIK_keymap[DIK_E] = SDLK_e;
+	DIK_keymap[DIK_R] = SDLK_r;
+	DIK_keymap[DIK_T] = SDLK_t;
+	DIK_keymap[DIK_Y] = SDLK_y;
+	DIK_keymap[DIK_U] = SDLK_u;
+	DIK_keymap[DIK_I] = SDLK_i;
+	DIK_keymap[DIK_O] = SDLK_o;
+	DIK_keymap[DIK_P] = SDLK_p;
+	DIK_keymap[DIK_LBRACKET] = SDLK_LEFTBRACKET;
+	DIK_keymap[DIK_RBRACKET] = SDLK_RIGHTBRACKET;
+	DIK_keymap[DIK_RETURN] = SDLK_RETURN;
+	DIK_keymap[DIK_LCONTROL] = SDLK_LCTRL;
+	DIK_keymap[DIK_A] = SDLK_a;
+	DIK_keymap[DIK_S] = SDLK_s;
+	DIK_keymap[DIK_D] = SDLK_d;
+	DIK_keymap[DIK_F] = SDLK_f;
+	DIK_keymap[DIK_G] = SDLK_g;
+	DIK_keymap[DIK_H] = SDLK_h;
+	DIK_keymap[DIK_J] = SDLK_j;
+	DIK_keymap[DIK_K] = SDLK_k;
+	DIK_keymap[DIK_L] = SDLK_l;
+	DIK_keymap[DIK_SEMICOLON] = SDLK_SEMICOLON;
+	DIK_keymap[DIK_APOSTROPHE] = SDLK_QUOTE;
+	DIK_keymap[DIK_GRAVE] = SDLK_BACKQUOTE;
+	DIK_keymap[DIK_LSHIFT] = SDLK_LSHIFT;
+	DIK_keymap[DIK_BACKSLASH] = SDLK_BACKSLASH;
+	DIK_keymap[DIK_Z] = SDLK_z;
+	DIK_keymap[DIK_X] = SDLK_x;
+	DIK_keymap[DIK_C] = SDLK_c;
+	DIK_keymap[DIK_V] = SDLK_v;
+	DIK_keymap[DIK_B] = SDLK_b;
+	DIK_keymap[DIK_N] = SDLK_n;
+	DIK_keymap[DIK_M] = SDLK_m;
+	DIK_keymap[DIK_COMMA] = SDLK_COMMA;
+	DIK_keymap[DIK_PERIOD] = SDLK_PERIOD;
+	DIK_keymap[DIK_SLASH] = SDLK_SLASH;
+	DIK_keymap[DIK_RSHIFT] = SDLK_RSHIFT;
+	DIK_keymap[DIK_MULTIPLY] = SDLK_KP_MULTIPLY;
+	DIK_keymap[DIK_LMENU] = SDLK_LALT;
+	DIK_keymap[DIK_SPACE] = SDLK_SPACE;
+	DIK_keymap[DIK_CAPITAL] = SDLK_CAPSLOCK;
+	DIK_keymap[DIK_F1] = SDLK_F1;
+	DIK_keymap[DIK_F2] = SDLK_F2;
+	DIK_keymap[DIK_F3] = SDLK_F3;
+	DIK_keymap[DIK_F4] = SDLK_F4;
+	DIK_keymap[DIK_F5] = SDLK_F5;
+	DIK_keymap[DIK_F6] = SDLK_F6;
+	DIK_keymap[DIK_F7] = SDLK_F7;
+	DIK_keymap[DIK_F8] = SDLK_F8;
+	DIK_keymap[DIK_F9] = SDLK_F9;
+	DIK_keymap[DIK_F10] = SDLK_F10;
+	DIK_keymap[DIK_NUMLOCK] = SDLK_NUMLOCK;
+	DIK_keymap[DIK_SCROLL] = SDLK_SCROLLOCK;
+	DIK_keymap[DIK_NUMPAD7] = SDLK_KP7;
+	DIK_keymap[DIK_NUMPAD8] = SDLK_KP8;
+	DIK_keymap[DIK_NUMPAD9] = SDLK_KP9;
+	DIK_keymap[DIK_SUBTRACT] = SDLK_KP_MINUS;
+	DIK_keymap[DIK_NUMPAD4] = SDLK_KP4;
+	DIK_keymap[DIK_NUMPAD5] = SDLK_KP5;
+	DIK_keymap[DIK_NUMPAD6] = SDLK_KP6;
+	DIK_keymap[DIK_ADD] = SDLK_KP_PLUS;
+	DIK_keymap[DIK_NUMPAD1] = SDLK_KP1;
+	DIK_keymap[DIK_NUMPAD2] = SDLK_KP2;
+	DIK_keymap[DIK_NUMPAD3] = SDLK_KP3;
+	DIK_keymap[DIK_NUMPAD0] = SDLK_KP0;
+	DIK_keymap[DIK_DECIMAL] = SDLK_KP_PERIOD;
+	DIK_keymap[DIK_F11] = SDLK_F11;
+	DIK_keymap[DIK_F12] = SDLK_F12;
+
+	DIK_keymap[DIK_F13] = SDLK_F13;
+	DIK_keymap[DIK_F14] = SDLK_F14;
+	DIK_keymap[DIK_F15] = SDLK_F15;
+
+	DIK_keymap[DIK_NUMPADEQUALS] = SDLK_KP_EQUALS;
+	DIK_keymap[DIK_NUMPADENTER] = SDLK_KP_ENTER;
+	DIK_keymap[DIK_RCONTROL] = SDLK_RCTRL;
+	DIK_keymap[DIK_DIVIDE] = SDLK_KP_DIVIDE;
+	DIK_keymap[DIK_SYSRQ] = SDLK_SYSREQ;
+	DIK_keymap[DIK_RMENU] = SDLK_RALT;
+	DIK_keymap[DIK_HOME] = SDLK_HOME;
+	DIK_keymap[DIK_UP] = SDLK_UP;
+	DIK_keymap[DIK_PRIOR] = SDLK_PAGEUP;
+	DIK_keymap[DIK_LEFT] = SDLK_LEFT;
+	DIK_keymap[DIK_RIGHT] = SDLK_RIGHT;
+	DIK_keymap[DIK_END] = SDLK_END;
+	DIK_keymap[DIK_DOWN] = SDLK_DOWN;
+	DIK_keymap[DIK_NEXT] = SDLK_PAGEDOWN;
+	DIK_keymap[DIK_INSERT] = SDLK_INSERT;
+	DIK_keymap[DIK_DELETE] = SDLK_DELETE;
+	DIK_keymap[DIK_LWIN] = SDLK_LMETA;
+	DIK_keymap[DIK_RWIN] = SDLK_RMETA;
+	DIK_keymap[DIK_APPS] = SDLK_MENU;
+}
+
+static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed)
+{
+	/* Set the keysym information */
+	keysym->scancode = (unsigned char)scancode;
+	keysym->sym = DIK_keymap[scancode];
+	keysym->mod = KMOD_NONE;
+	keysym->unicode = 0;
+	if ( pressed && SDL_TranslateUNICODE ) { /* Someday use ToUnicode() */
+		UINT vkey;
+		BYTE keystate[256];
+		BYTE chars[2];
+
+		vkey = MapVirtualKey(scancode, 1);
+		GetKeyboardState(keystate);
+		if ( ToAscii(vkey,scancode,keystate,(WORD *)chars,0) == 1 ) {
+			keysym->unicode = chars[0];
+		}
+	}
+	return(keysym);
+}
+
+int DX5_CreateWindow(_THIS)
+{
+	int i;
+
+	/* Clear out DirectInput variables in case we fail */
+	for ( i=0; i<MAX_INPUTS; ++i ) {
+		SDL_DIdev[i] = NULL;
+		SDL_DIevt[i] = NULL;
+		SDL_DIfun[i] = NULL;
+	}
+
+	/* Create the SDL window */
+	SDL_RegisterApp("SDL_app", CS_BYTEALIGNCLIENT, 0);
+	if ( SDL_windowid ) {
+		SDL_Window = (HWND)strtol(SDL_windowid, NULL, 0);
+	} else {
+		SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
+                        (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),
+                                 0, 0, 0, 0, NULL, NULL, SDL_Instance, NULL);
+		if ( SDL_Window == NULL ) {
+			SDL_SetError("Couldn't create window");
+			return(-1);
+		}
+		ShowWindow(SDL_Window, SW_HIDE);
+	}
+
+	/* Initialize DirectInput */
+	if ( DX5_DInputInit(this) < 0 ) {
+		return(-1);
+	}
+
+	/* Ready to roll */
+	return(0);
+}
+
+void DX5_DestroyWindow(_THIS)
+{
+	/* Close down DirectInput */
+	DX5_DInputQuit(this);
+
+	/* Destroy our window */
+	DestroyWindow(SDL_Window);
+}