src/video/windx5/SDL_dx5video.c
changeset 0 74212992fb08
child 1 cf2af46e9e2a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/windx5/SDL_dx5video.c	Thu Apr 26 16:45:43 2001 +0000
     1.3 @@ -0,0 +1,2323 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@devolution.com
    1.24 +*/
    1.25 +
    1.26 +#ifdef SAVE_RCSID
    1.27 +static char rcsid =
    1.28 + "@(#) $Id$";
    1.29 +#endif
    1.30 +
    1.31 +#include <stdio.h>
    1.32 +#include <stdlib.h>
    1.33 +#include <malloc.h>
    1.34 +#include <windows.h>
    1.35 +#include "directx.h"
    1.36 +
    1.37 +/* Not yet in the mingw32 cross-compile headers */
    1.38 +#ifndef CDS_FULLSCREEN
    1.39 +#define CDS_FULLSCREEN	4
    1.40 +#endif
    1.41 +
    1.42 +#include "SDL_error.h"
    1.43 +#include "SDL_timer.h"
    1.44 +#include "SDL_events.h"
    1.45 +#include "SDL_syswm.h"
    1.46 +#include "SDL_sysvideo.h"
    1.47 +#include "SDL_RLEaccel_c.h"
    1.48 +#include "SDL_blit.h"
    1.49 +#include "SDL_pixels_c.h"
    1.50 +#include "SDL_dx5video.h"
    1.51 +#include "SDL_syswm_c.h"
    1.52 +#include "SDL_sysmouse_c.h"
    1.53 +#include "SDL_dx5events_c.h"
    1.54 +#include "SDL_dx5yuv_c.h"
    1.55 +#include "SDL_wingl_c.h"
    1.56 +
    1.57 +/* Function called to create a GL video mode - use the GDI driver, not DirectX */
    1.58 +extern SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
    1.59 +				int width, int height, int bpp, Uint32 flags);
    1.60 +
    1.61 +/* DirectX function pointers for video and events */
    1.62 +HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
    1.63 +HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
    1.64 +
    1.65 +/* This is the rect EnumModes2 uses */
    1.66 +struct DX5EnumRect {
    1.67 +	SDL_Rect r;
    1.68 +	struct DX5EnumRect* next;
    1.69 +};
    1.70 +static struct DX5EnumRect *enumlists[NUM_MODELISTS];
    1.71 +
    1.72 +/*
    1.73 + * Experimentally determined values for c_cfDI* constants used in DirectX 5.0
    1.74 + */
    1.75 +
    1.76 +/* Keyboard */
    1.77 +
    1.78 +static DIOBJECTDATAFORMAT KBD_fmt[] = {
    1.79 +	{ &GUID_Key, 0, 0x8000000C, 0x00000000 },
    1.80 +	{ &GUID_Key, 1, 0x8000010C, 0x00000000 },
    1.81 +	{ &GUID_Key, 2, 0x8000020C, 0x00000000 },
    1.82 +	{ &GUID_Key, 3, 0x8000030C, 0x00000000 },
    1.83 +	{ &GUID_Key, 4, 0x8000040C, 0x00000000 },
    1.84 +	{ &GUID_Key, 5, 0x8000050C, 0x00000000 },
    1.85 +	{ &GUID_Key, 6, 0x8000060C, 0x00000000 },
    1.86 +	{ &GUID_Key, 7, 0x8000070C, 0x00000000 },
    1.87 +	{ &GUID_Key, 8, 0x8000080C, 0x00000000 },
    1.88 +	{ &GUID_Key, 9, 0x8000090C, 0x00000000 },
    1.89 +	{ &GUID_Key, 10, 0x80000A0C, 0x00000000 },
    1.90 +	{ &GUID_Key, 11, 0x80000B0C, 0x00000000 },
    1.91 +	{ &GUID_Key, 12, 0x80000C0C, 0x00000000 },
    1.92 +	{ &GUID_Key, 13, 0x80000D0C, 0x00000000 },
    1.93 +	{ &GUID_Key, 14, 0x80000E0C, 0x00000000 },
    1.94 +	{ &GUID_Key, 15, 0x80000F0C, 0x00000000 },
    1.95 +	{ &GUID_Key, 16, 0x8000100C, 0x00000000 },
    1.96 +	{ &GUID_Key, 17, 0x8000110C, 0x00000000 },
    1.97 +	{ &GUID_Key, 18, 0x8000120C, 0x00000000 },
    1.98 +	{ &GUID_Key, 19, 0x8000130C, 0x00000000 },
    1.99 +	{ &GUID_Key, 20, 0x8000140C, 0x00000000 },
   1.100 +	{ &GUID_Key, 21, 0x8000150C, 0x00000000 },
   1.101 +	{ &GUID_Key, 22, 0x8000160C, 0x00000000 },
   1.102 +	{ &GUID_Key, 23, 0x8000170C, 0x00000000 },
   1.103 +	{ &GUID_Key, 24, 0x8000180C, 0x00000000 },
   1.104 +	{ &GUID_Key, 25, 0x8000190C, 0x00000000 },
   1.105 +	{ &GUID_Key, 26, 0x80001A0C, 0x00000000 },
   1.106 +	{ &GUID_Key, 27, 0x80001B0C, 0x00000000 },
   1.107 +	{ &GUID_Key, 28, 0x80001C0C, 0x00000000 },
   1.108 +	{ &GUID_Key, 29, 0x80001D0C, 0x00000000 },
   1.109 +	{ &GUID_Key, 30, 0x80001E0C, 0x00000000 },
   1.110 +	{ &GUID_Key, 31, 0x80001F0C, 0x00000000 },
   1.111 +	{ &GUID_Key, 32, 0x8000200C, 0x00000000 },
   1.112 +	{ &GUID_Key, 33, 0x8000210C, 0x00000000 },
   1.113 +	{ &GUID_Key, 34, 0x8000220C, 0x00000000 },
   1.114 +	{ &GUID_Key, 35, 0x8000230C, 0x00000000 },
   1.115 +	{ &GUID_Key, 36, 0x8000240C, 0x00000000 },
   1.116 +	{ &GUID_Key, 37, 0x8000250C, 0x00000000 },
   1.117 +	{ &GUID_Key, 38, 0x8000260C, 0x00000000 },
   1.118 +	{ &GUID_Key, 39, 0x8000270C, 0x00000000 },
   1.119 +	{ &GUID_Key, 40, 0x8000280C, 0x00000000 },
   1.120 +	{ &GUID_Key, 41, 0x8000290C, 0x00000000 },
   1.121 +	{ &GUID_Key, 42, 0x80002A0C, 0x00000000 },
   1.122 +	{ &GUID_Key, 43, 0x80002B0C, 0x00000000 },
   1.123 +	{ &GUID_Key, 44, 0x80002C0C, 0x00000000 },
   1.124 +	{ &GUID_Key, 45, 0x80002D0C, 0x00000000 },
   1.125 +	{ &GUID_Key, 46, 0x80002E0C, 0x00000000 },
   1.126 +	{ &GUID_Key, 47, 0x80002F0C, 0x00000000 },
   1.127 +	{ &GUID_Key, 48, 0x8000300C, 0x00000000 },
   1.128 +	{ &GUID_Key, 49, 0x8000310C, 0x00000000 },
   1.129 +	{ &GUID_Key, 50, 0x8000320C, 0x00000000 },
   1.130 +	{ &GUID_Key, 51, 0x8000330C, 0x00000000 },
   1.131 +	{ &GUID_Key, 52, 0x8000340C, 0x00000000 },
   1.132 +	{ &GUID_Key, 53, 0x8000350C, 0x00000000 },
   1.133 +	{ &GUID_Key, 54, 0x8000360C, 0x00000000 },
   1.134 +	{ &GUID_Key, 55, 0x8000370C, 0x00000000 },
   1.135 +	{ &GUID_Key, 56, 0x8000380C, 0x00000000 },
   1.136 +	{ &GUID_Key, 57, 0x8000390C, 0x00000000 },
   1.137 +	{ &GUID_Key, 58, 0x80003A0C, 0x00000000 },
   1.138 +	{ &GUID_Key, 59, 0x80003B0C, 0x00000000 },
   1.139 +	{ &GUID_Key, 60, 0x80003C0C, 0x00000000 },
   1.140 +	{ &GUID_Key, 61, 0x80003D0C, 0x00000000 },
   1.141 +	{ &GUID_Key, 62, 0x80003E0C, 0x00000000 },
   1.142 +	{ &GUID_Key, 63, 0x80003F0C, 0x00000000 },
   1.143 +	{ &GUID_Key, 64, 0x8000400C, 0x00000000 },
   1.144 +	{ &GUID_Key, 65, 0x8000410C, 0x00000000 },
   1.145 +	{ &GUID_Key, 66, 0x8000420C, 0x00000000 },
   1.146 +	{ &GUID_Key, 67, 0x8000430C, 0x00000000 },
   1.147 +	{ &GUID_Key, 68, 0x8000440C, 0x00000000 },
   1.148 +	{ &GUID_Key, 69, 0x8000450C, 0x00000000 },
   1.149 +	{ &GUID_Key, 70, 0x8000460C, 0x00000000 },
   1.150 +	{ &GUID_Key, 71, 0x8000470C, 0x00000000 },
   1.151 +	{ &GUID_Key, 72, 0x8000480C, 0x00000000 },
   1.152 +	{ &GUID_Key, 73, 0x8000490C, 0x00000000 },
   1.153 +	{ &GUID_Key, 74, 0x80004A0C, 0x00000000 },
   1.154 +	{ &GUID_Key, 75, 0x80004B0C, 0x00000000 },
   1.155 +	{ &GUID_Key, 76, 0x80004C0C, 0x00000000 },
   1.156 +	{ &GUID_Key, 77, 0x80004D0C, 0x00000000 },
   1.157 +	{ &GUID_Key, 78, 0x80004E0C, 0x00000000 },
   1.158 +	{ &GUID_Key, 79, 0x80004F0C, 0x00000000 },
   1.159 +	{ &GUID_Key, 80, 0x8000500C, 0x00000000 },
   1.160 +	{ &GUID_Key, 81, 0x8000510C, 0x00000000 },
   1.161 +	{ &GUID_Key, 82, 0x8000520C, 0x00000000 },
   1.162 +	{ &GUID_Key, 83, 0x8000530C, 0x00000000 },
   1.163 +	{ &GUID_Key, 84, 0x8000540C, 0x00000000 },
   1.164 +	{ &GUID_Key, 85, 0x8000550C, 0x00000000 },
   1.165 +	{ &GUID_Key, 86, 0x8000560C, 0x00000000 },
   1.166 +	{ &GUID_Key, 87, 0x8000570C, 0x00000000 },
   1.167 +	{ &GUID_Key, 88, 0x8000580C, 0x00000000 },
   1.168 +	{ &GUID_Key, 89, 0x8000590C, 0x00000000 },
   1.169 +	{ &GUID_Key, 90, 0x80005A0C, 0x00000000 },
   1.170 +	{ &GUID_Key, 91, 0x80005B0C, 0x00000000 },
   1.171 +	{ &GUID_Key, 92, 0x80005C0C, 0x00000000 },
   1.172 +	{ &GUID_Key, 93, 0x80005D0C, 0x00000000 },
   1.173 +	{ &GUID_Key, 94, 0x80005E0C, 0x00000000 },
   1.174 +	{ &GUID_Key, 95, 0x80005F0C, 0x00000000 },
   1.175 +	{ &GUID_Key, 96, 0x8000600C, 0x00000000 },
   1.176 +	{ &GUID_Key, 97, 0x8000610C, 0x00000000 },
   1.177 +	{ &GUID_Key, 98, 0x8000620C, 0x00000000 },
   1.178 +	{ &GUID_Key, 99, 0x8000630C, 0x00000000 },
   1.179 +	{ &GUID_Key, 100, 0x8000640C, 0x00000000 },
   1.180 +	{ &GUID_Key, 101, 0x8000650C, 0x00000000 },
   1.181 +	{ &GUID_Key, 102, 0x8000660C, 0x00000000 },
   1.182 +	{ &GUID_Key, 103, 0x8000670C, 0x00000000 },
   1.183 +	{ &GUID_Key, 104, 0x8000680C, 0x00000000 },
   1.184 +	{ &GUID_Key, 105, 0x8000690C, 0x00000000 },
   1.185 +	{ &GUID_Key, 106, 0x80006A0C, 0x00000000 },
   1.186 +	{ &GUID_Key, 107, 0x80006B0C, 0x00000000 },
   1.187 +	{ &GUID_Key, 108, 0x80006C0C, 0x00000000 },
   1.188 +	{ &GUID_Key, 109, 0x80006D0C, 0x00000000 },
   1.189 +	{ &GUID_Key, 110, 0x80006E0C, 0x00000000 },
   1.190 +	{ &GUID_Key, 111, 0x80006F0C, 0x00000000 },
   1.191 +	{ &GUID_Key, 112, 0x8000700C, 0x00000000 },
   1.192 +	{ &GUID_Key, 113, 0x8000710C, 0x00000000 },
   1.193 +	{ &GUID_Key, 114, 0x8000720C, 0x00000000 },
   1.194 +	{ &GUID_Key, 115, 0x8000730C, 0x00000000 },
   1.195 +	{ &GUID_Key, 116, 0x8000740C, 0x00000000 },
   1.196 +	{ &GUID_Key, 117, 0x8000750C, 0x00000000 },
   1.197 +	{ &GUID_Key, 118, 0x8000760C, 0x00000000 },
   1.198 +	{ &GUID_Key, 119, 0x8000770C, 0x00000000 },
   1.199 +	{ &GUID_Key, 120, 0x8000780C, 0x00000000 },
   1.200 +	{ &GUID_Key, 121, 0x8000790C, 0x00000000 },
   1.201 +	{ &GUID_Key, 122, 0x80007A0C, 0x00000000 },
   1.202 +	{ &GUID_Key, 123, 0x80007B0C, 0x00000000 },
   1.203 +	{ &GUID_Key, 124, 0x80007C0C, 0x00000000 },
   1.204 +	{ &GUID_Key, 125, 0x80007D0C, 0x00000000 },
   1.205 +	{ &GUID_Key, 126, 0x80007E0C, 0x00000000 },
   1.206 +	{ &GUID_Key, 127, 0x80007F0C, 0x00000000 },
   1.207 +	{ &GUID_Key, 128, 0x8000800C, 0x00000000 },
   1.208 +	{ &GUID_Key, 129, 0x8000810C, 0x00000000 },
   1.209 +	{ &GUID_Key, 130, 0x8000820C, 0x00000000 },
   1.210 +	{ &GUID_Key, 131, 0x8000830C, 0x00000000 },
   1.211 +	{ &GUID_Key, 132, 0x8000840C, 0x00000000 },
   1.212 +	{ &GUID_Key, 133, 0x8000850C, 0x00000000 },
   1.213 +	{ &GUID_Key, 134, 0x8000860C, 0x00000000 },
   1.214 +	{ &GUID_Key, 135, 0x8000870C, 0x00000000 },
   1.215 +	{ &GUID_Key, 136, 0x8000880C, 0x00000000 },
   1.216 +	{ &GUID_Key, 137, 0x8000890C, 0x00000000 },
   1.217 +	{ &GUID_Key, 138, 0x80008A0C, 0x00000000 },
   1.218 +	{ &GUID_Key, 139, 0x80008B0C, 0x00000000 },
   1.219 +	{ &GUID_Key, 140, 0x80008C0C, 0x00000000 },
   1.220 +	{ &GUID_Key, 141, 0x80008D0C, 0x00000000 },
   1.221 +	{ &GUID_Key, 142, 0x80008E0C, 0x00000000 },
   1.222 +	{ &GUID_Key, 143, 0x80008F0C, 0x00000000 },
   1.223 +	{ &GUID_Key, 144, 0x8000900C, 0x00000000 },
   1.224 +	{ &GUID_Key, 145, 0x8000910C, 0x00000000 },
   1.225 +	{ &GUID_Key, 146, 0x8000920C, 0x00000000 },
   1.226 +	{ &GUID_Key, 147, 0x8000930C, 0x00000000 },
   1.227 +	{ &GUID_Key, 148, 0x8000940C, 0x00000000 },
   1.228 +	{ &GUID_Key, 149, 0x8000950C, 0x00000000 },
   1.229 +	{ &GUID_Key, 150, 0x8000960C, 0x00000000 },
   1.230 +	{ &GUID_Key, 151, 0x8000970C, 0x00000000 },
   1.231 +	{ &GUID_Key, 152, 0x8000980C, 0x00000000 },
   1.232 +	{ &GUID_Key, 153, 0x8000990C, 0x00000000 },
   1.233 +	{ &GUID_Key, 154, 0x80009A0C, 0x00000000 },
   1.234 +	{ &GUID_Key, 155, 0x80009B0C, 0x00000000 },
   1.235 +	{ &GUID_Key, 156, 0x80009C0C, 0x00000000 },
   1.236 +	{ &GUID_Key, 157, 0x80009D0C, 0x00000000 },
   1.237 +	{ &GUID_Key, 158, 0x80009E0C, 0x00000000 },
   1.238 +	{ &GUID_Key, 159, 0x80009F0C, 0x00000000 },
   1.239 +	{ &GUID_Key, 160, 0x8000A00C, 0x00000000 },
   1.240 +	{ &GUID_Key, 161, 0x8000A10C, 0x00000000 },
   1.241 +	{ &GUID_Key, 162, 0x8000A20C, 0x00000000 },
   1.242 +	{ &GUID_Key, 163, 0x8000A30C, 0x00000000 },
   1.243 +	{ &GUID_Key, 164, 0x8000A40C, 0x00000000 },
   1.244 +	{ &GUID_Key, 165, 0x8000A50C, 0x00000000 },
   1.245 +	{ &GUID_Key, 166, 0x8000A60C, 0x00000000 },
   1.246 +	{ &GUID_Key, 167, 0x8000A70C, 0x00000000 },
   1.247 +	{ &GUID_Key, 168, 0x8000A80C, 0x00000000 },
   1.248 +	{ &GUID_Key, 169, 0x8000A90C, 0x00000000 },
   1.249 +	{ &GUID_Key, 170, 0x8000AA0C, 0x00000000 },
   1.250 +	{ &GUID_Key, 171, 0x8000AB0C, 0x00000000 },
   1.251 +	{ &GUID_Key, 172, 0x8000AC0C, 0x00000000 },
   1.252 +	{ &GUID_Key, 173, 0x8000AD0C, 0x00000000 },
   1.253 +	{ &GUID_Key, 174, 0x8000AE0C, 0x00000000 },
   1.254 +	{ &GUID_Key, 175, 0x8000AF0C, 0x00000000 },
   1.255 +	{ &GUID_Key, 176, 0x8000B00C, 0x00000000 },
   1.256 +	{ &GUID_Key, 177, 0x8000B10C, 0x00000000 },
   1.257 +	{ &GUID_Key, 178, 0x8000B20C, 0x00000000 },
   1.258 +	{ &GUID_Key, 179, 0x8000B30C, 0x00000000 },
   1.259 +	{ &GUID_Key, 180, 0x8000B40C, 0x00000000 },
   1.260 +	{ &GUID_Key, 181, 0x8000B50C, 0x00000000 },
   1.261 +	{ &GUID_Key, 182, 0x8000B60C, 0x00000000 },
   1.262 +	{ &GUID_Key, 183, 0x8000B70C, 0x00000000 },
   1.263 +	{ &GUID_Key, 184, 0x8000B80C, 0x00000000 },
   1.264 +	{ &GUID_Key, 185, 0x8000B90C, 0x00000000 },
   1.265 +	{ &GUID_Key, 186, 0x8000BA0C, 0x00000000 },
   1.266 +	{ &GUID_Key, 187, 0x8000BB0C, 0x00000000 },
   1.267 +	{ &GUID_Key, 188, 0x8000BC0C, 0x00000000 },
   1.268 +	{ &GUID_Key, 189, 0x8000BD0C, 0x00000000 },
   1.269 +	{ &GUID_Key, 190, 0x8000BE0C, 0x00000000 },
   1.270 +	{ &GUID_Key, 191, 0x8000BF0C, 0x00000000 },
   1.271 +	{ &GUID_Key, 192, 0x8000C00C, 0x00000000 },
   1.272 +	{ &GUID_Key, 193, 0x8000C10C, 0x00000000 },
   1.273 +	{ &GUID_Key, 194, 0x8000C20C, 0x00000000 },
   1.274 +	{ &GUID_Key, 195, 0x8000C30C, 0x00000000 },
   1.275 +	{ &GUID_Key, 196, 0x8000C40C, 0x00000000 },
   1.276 +	{ &GUID_Key, 197, 0x8000C50C, 0x00000000 },
   1.277 +	{ &GUID_Key, 198, 0x8000C60C, 0x00000000 },
   1.278 +	{ &GUID_Key, 199, 0x8000C70C, 0x00000000 },
   1.279 +	{ &GUID_Key, 200, 0x8000C80C, 0x00000000 },
   1.280 +	{ &GUID_Key, 201, 0x8000C90C, 0x00000000 },
   1.281 +	{ &GUID_Key, 202, 0x8000CA0C, 0x00000000 },
   1.282 +	{ &GUID_Key, 203, 0x8000CB0C, 0x00000000 },
   1.283 +	{ &GUID_Key, 204, 0x8000CC0C, 0x00000000 },
   1.284 +	{ &GUID_Key, 205, 0x8000CD0C, 0x00000000 },
   1.285 +	{ &GUID_Key, 206, 0x8000CE0C, 0x00000000 },
   1.286 +	{ &GUID_Key, 207, 0x8000CF0C, 0x00000000 },
   1.287 +	{ &GUID_Key, 208, 0x8000D00C, 0x00000000 },
   1.288 +	{ &GUID_Key, 209, 0x8000D10C, 0x00000000 },
   1.289 +	{ &GUID_Key, 210, 0x8000D20C, 0x00000000 },
   1.290 +	{ &GUID_Key, 211, 0x8000D30C, 0x00000000 },
   1.291 +	{ &GUID_Key, 212, 0x8000D40C, 0x00000000 },
   1.292 +	{ &GUID_Key, 213, 0x8000D50C, 0x00000000 },
   1.293 +	{ &GUID_Key, 214, 0x8000D60C, 0x00000000 },
   1.294 +	{ &GUID_Key, 215, 0x8000D70C, 0x00000000 },
   1.295 +	{ &GUID_Key, 216, 0x8000D80C, 0x00000000 },
   1.296 +	{ &GUID_Key, 217, 0x8000D90C, 0x00000000 },
   1.297 +	{ &GUID_Key, 218, 0x8000DA0C, 0x00000000 },
   1.298 +	{ &GUID_Key, 219, 0x8000DB0C, 0x00000000 },
   1.299 +	{ &GUID_Key, 220, 0x8000DC0C, 0x00000000 },
   1.300 +	{ &GUID_Key, 221, 0x8000DD0C, 0x00000000 },
   1.301 +	{ &GUID_Key, 222, 0x8000DE0C, 0x00000000 },
   1.302 +	{ &GUID_Key, 223, 0x8000DF0C, 0x00000000 },
   1.303 +	{ &GUID_Key, 224, 0x8000E00C, 0x00000000 },
   1.304 +	{ &GUID_Key, 225, 0x8000E10C, 0x00000000 },
   1.305 +	{ &GUID_Key, 226, 0x8000E20C, 0x00000000 },
   1.306 +	{ &GUID_Key, 227, 0x8000E30C, 0x00000000 },
   1.307 +	{ &GUID_Key, 228, 0x8000E40C, 0x00000000 },
   1.308 +	{ &GUID_Key, 229, 0x8000E50C, 0x00000000 },
   1.309 +	{ &GUID_Key, 230, 0x8000E60C, 0x00000000 },
   1.310 +	{ &GUID_Key, 231, 0x8000E70C, 0x00000000 },
   1.311 +	{ &GUID_Key, 232, 0x8000E80C, 0x00000000 },
   1.312 +	{ &GUID_Key, 233, 0x8000E90C, 0x00000000 },
   1.313 +	{ &GUID_Key, 234, 0x8000EA0C, 0x00000000 },
   1.314 +	{ &GUID_Key, 235, 0x8000EB0C, 0x00000000 },
   1.315 +	{ &GUID_Key, 236, 0x8000EC0C, 0x00000000 },
   1.316 +	{ &GUID_Key, 237, 0x8000ED0C, 0x00000000 },
   1.317 +	{ &GUID_Key, 238, 0x8000EE0C, 0x00000000 },
   1.318 +	{ &GUID_Key, 239, 0x8000EF0C, 0x00000000 },
   1.319 +	{ &GUID_Key, 240, 0x8000F00C, 0x00000000 },
   1.320 +	{ &GUID_Key, 241, 0x8000F10C, 0x00000000 },
   1.321 +	{ &GUID_Key, 242, 0x8000F20C, 0x00000000 },
   1.322 +	{ &GUID_Key, 243, 0x8000F30C, 0x00000000 },
   1.323 +	{ &GUID_Key, 244, 0x8000F40C, 0x00000000 },
   1.324 +	{ &GUID_Key, 245, 0x8000F50C, 0x00000000 },
   1.325 +	{ &GUID_Key, 246, 0x8000F60C, 0x00000000 },
   1.326 +	{ &GUID_Key, 247, 0x8000F70C, 0x00000000 },
   1.327 +	{ &GUID_Key, 248, 0x8000F80C, 0x00000000 },
   1.328 +	{ &GUID_Key, 249, 0x8000F90C, 0x00000000 },
   1.329 +	{ &GUID_Key, 250, 0x8000FA0C, 0x00000000 },
   1.330 +	{ &GUID_Key, 251, 0x8000FB0C, 0x00000000 },
   1.331 +	{ &GUID_Key, 252, 0x8000FC0C, 0x00000000 },
   1.332 +	{ &GUID_Key, 253, 0x8000FD0C, 0x00000000 },
   1.333 +	{ &GUID_Key, 254, 0x8000FE0C, 0x00000000 },
   1.334 +	{ &GUID_Key, 255, 0x8000FF0C, 0x00000000 },
   1.335 +};
   1.336 +
   1.337 +const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
   1.338 +
   1.339 +
   1.340 +/* Mouse */
   1.341 +
   1.342 +static DIOBJECTDATAFORMAT PTR_fmt[] = {
   1.343 +	{ &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 },
   1.344 +	{ &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 },
   1.345 +	{ &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 },
   1.346 +	{ NULL, 12, 0x00FFFF0C, 0x00000000 },
   1.347 +	{ NULL, 13, 0x00FFFF0C, 0x00000000 },
   1.348 +	{ NULL, 14, 0x80FFFF0C, 0x00000000 },
   1.349 +	{ NULL, 15, 0x80FFFF0C, 0x00000000 },
   1.350 +};
   1.351 +
   1.352 +const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
   1.353 +
   1.354 +
   1.355 +/* Joystick */
   1.356 +
   1.357 +static DIOBJECTDATAFORMAT JOY_fmt[] = {
   1.358 +	{ &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 },
   1.359 +	{ &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 },
   1.360 +	{ &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 },
   1.361 +	{ &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 },
   1.362 +	{ &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 },
   1.363 +	{ &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 },
   1.364 +	{ &GUID_Slider, 24, 0x80FFFF03, 0x00000100 },
   1.365 +	{ &GUID_Slider, 28, 0x80FFFF03, 0x00000100 },
   1.366 +	{ &GUID_POV, 32, 0x80FFFF10, 0x00000000 },
   1.367 +	{ &GUID_POV, 36, 0x80FFFF10, 0x00000000 },
   1.368 +	{ &GUID_POV, 40, 0x80FFFF10, 0x00000000 },
   1.369 +	{ &GUID_POV, 44, 0x80FFFF10, 0x00000000 },
   1.370 +	{ NULL, 48, 0x80FFFF0C, 0x00000000 },
   1.371 +	{ NULL, 49, 0x80FFFF0C, 0x00000000 },
   1.372 +	{ NULL, 50, 0x80FFFF0C, 0x00000000 },
   1.373 +	{ NULL, 51, 0x80FFFF0C, 0x00000000 },
   1.374 +	{ NULL, 52, 0x80FFFF0C, 0x00000000 },
   1.375 +	{ NULL, 53, 0x80FFFF0C, 0x00000000 },
   1.376 +	{ NULL, 54, 0x80FFFF0C, 0x00000000 },
   1.377 +	{ NULL, 55, 0x80FFFF0C, 0x00000000 },
   1.378 +	{ NULL, 56, 0x80FFFF0C, 0x00000000 },
   1.379 +	{ NULL, 57, 0x80FFFF0C, 0x00000000 },
   1.380 +	{ NULL, 58, 0x80FFFF0C, 0x00000000 },
   1.381 +	{ NULL, 59, 0x80FFFF0C, 0x00000000 },
   1.382 +	{ NULL, 60, 0x80FFFF0C, 0x00000000 },
   1.383 +	{ NULL, 61, 0x80FFFF0C, 0x00000000 },
   1.384 +	{ NULL, 62, 0x80FFFF0C, 0x00000000 },
   1.385 +	{ NULL, 63, 0x80FFFF0C, 0x00000000 },
   1.386 +	{ NULL, 64, 0x80FFFF0C, 0x00000000 },
   1.387 +	{ NULL, 65, 0x80FFFF0C, 0x00000000 },
   1.388 +	{ NULL, 66, 0x80FFFF0C, 0x00000000 },
   1.389 +	{ NULL, 67, 0x80FFFF0C, 0x00000000 },
   1.390 +	{ NULL, 68, 0x80FFFF0C, 0x00000000 },
   1.391 +	{ NULL, 69, 0x80FFFF0C, 0x00000000 },
   1.392 +	{ NULL, 70, 0x80FFFF0C, 0x00000000 },
   1.393 +	{ NULL, 71, 0x80FFFF0C, 0x00000000 },
   1.394 +	{ NULL, 72, 0x80FFFF0C, 0x00000000 },
   1.395 +	{ NULL, 73, 0x80FFFF0C, 0x00000000 },
   1.396 +	{ NULL, 74, 0x80FFFF0C, 0x00000000 },
   1.397 +	{ NULL, 75, 0x80FFFF0C, 0x00000000 },
   1.398 +	{ NULL, 76, 0x80FFFF0C, 0x00000000 },
   1.399 +	{ NULL, 77, 0x80FFFF0C, 0x00000000 },
   1.400 +	{ NULL, 78, 0x80FFFF0C, 0x00000000 },
   1.401 +	{ NULL, 79, 0x80FFFF0C, 0x00000000 },
   1.402 +};
   1.403 +
   1.404 +const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
   1.405 +
   1.406 +
   1.407 +/* Initialization/Query functions */
   1.408 +static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat);
   1.409 +static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
   1.410 +static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
   1.411 +static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
   1.412 +			 SDL_Color *colors);
   1.413 +static void DX5_SwapGamma(_THIS);
   1.414 +#ifdef IID_IDirectDrawGammaControl
   1.415 +static int DX5_SetGammaRamp(_THIS, Uint16 *ramp);
   1.416 +static int DX5_GetGammaRamp(_THIS, Uint16 *ramp);
   1.417 +#endif
   1.418 +static void DX5_VideoQuit(_THIS);
   1.419 +
   1.420 +/* Hardware surface functions */
   1.421 +static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface);
   1.422 +static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
   1.423 +static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
   1.424 +static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
   1.425 +static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
   1.426 +static int DX5_LockHWSurface(_THIS, SDL_Surface *surface);
   1.427 +static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface);
   1.428 +static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface);
   1.429 +static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface);
   1.430 +
   1.431 +static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
   1.432 +				LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
   1.433 +
   1.434 +/* Windows message handling functions */
   1.435 +static void DX5_RealizePalette(_THIS);
   1.436 +static void DX5_PaletteChanged(_THIS, HWND window);
   1.437 +static void DX5_WinPAINT(_THIS, HDC hdc);
   1.438 +
   1.439 +/* DX5 driver bootstrap functions */
   1.440 +
   1.441 +static int DX5_Available(void)
   1.442 +{
   1.443 +	HINSTANCE DInputDLL;
   1.444 +	HINSTANCE DDrawDLL;
   1.445 +	int dinput_ok;
   1.446 +	int ddraw_ok;
   1.447 +
   1.448 +	/* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
   1.449 +	dinput_ok = 0;
   1.450 +	DInputDLL = LoadLibrary("DINPUT.DLL");
   1.451 +	if ( DInputDLL != NULL ) {
   1.452 +		dinput_ok = 1;
   1.453 +	  	FreeLibrary(DInputDLL);
   1.454 +	}
   1.455 +	ddraw_ok = 0;
   1.456 +	DDrawDLL = LoadLibrary("DDRAW.DLL");
   1.457 +	if ( DDrawDLL != NULL ) {
   1.458 +	  HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
   1.459 +	  LPDIRECTDRAW DDraw;
   1.460 +
   1.461 +	  /* Try to create a valid DirectDraw object */
   1.462 +	  DDrawCreate = (void *)GetProcAddress(DDrawDLL, "DirectDrawCreate");
   1.463 +	  if ( (DDrawCreate != NULL)
   1.464 +			&& !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) {
   1.465 +	    if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
   1.466 +							NULL, DDSCL_NORMAL)) ) {
   1.467 +	      DDSURFACEDESC desc;
   1.468 +	      LPDIRECTDRAWSURFACE  DDrawSurf;
   1.469 +	      LPDIRECTDRAWSURFACE3 DDrawSurf3;
   1.470 +
   1.471 +	      /* Try to create a DirectDrawSurface3 object */
   1.472 +	      memset(&desc, 0, sizeof(desc));
   1.473 +	      desc.dwSize = sizeof(desc);
   1.474 +	      desc.dwFlags = DDSD_CAPS;
   1.475 +	      desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
   1.476 +	      if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc,
   1.477 +							&DDrawSurf, NULL)) ) {
   1.478 +	        if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf,
   1.479 +			&IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) {
   1.480 +	          /* Yay! */
   1.481 +		  ddraw_ok = 1;
   1.482 +
   1.483 +	          /* Clean up.. */
   1.484 +	          IDirectDrawSurface3_Release(DDrawSurf3);
   1.485 +	        }
   1.486 +	        IDirectDrawSurface_Release(DDrawSurf);
   1.487 +	      }
   1.488 +	    }
   1.489 +	    IDirectDraw_Release(DDraw);
   1.490 +	  }
   1.491 +	  FreeLibrary(DDrawDLL);
   1.492 +	}
   1.493 +	return(dinput_ok && ddraw_ok);
   1.494 +}
   1.495 +
   1.496 +/* Functions for loading the DirectX functions dynamically */
   1.497 +static HINSTANCE DDrawDLL = NULL;
   1.498 +static HINSTANCE DInputDLL = NULL;
   1.499 +
   1.500 +static void DX5_Unload(void)
   1.501 +{
   1.502 +	if ( DDrawDLL != NULL ) {
   1.503 +		FreeLibrary(DDrawDLL);
   1.504 +		DDrawCreate = NULL;
   1.505 +		DDrawDLL = NULL;
   1.506 +	}
   1.507 +	if ( DInputDLL != NULL ) {
   1.508 +		FreeLibrary(DInputDLL);
   1.509 +		DInputCreate = NULL;
   1.510 +		DInputDLL = NULL;
   1.511 +	}
   1.512 +}
   1.513 +static int DX5_Load(void)
   1.514 +{
   1.515 +	int status;
   1.516 +
   1.517 +	DX5_Unload();
   1.518 +	DDrawDLL = LoadLibrary("DDRAW.DLL");
   1.519 +	if ( DDrawDLL != NULL ) {
   1.520 +		DDrawCreate = (void *)GetProcAddress(DDrawDLL,
   1.521 +					"DirectDrawCreate");
   1.522 +	}
   1.523 +	DInputDLL = LoadLibrary("DINPUT.DLL");
   1.524 +	if ( DInputDLL != NULL ) {
   1.525 +		DInputCreate = (void *)GetProcAddress(DInputDLL,
   1.526 +					"DirectInputCreateA");
   1.527 +	}
   1.528 +	if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) {
   1.529 +		status = 0;
   1.530 +	} else {
   1.531 +		DX5_Unload();
   1.532 +		status = -1;
   1.533 +	}
   1.534 +	return status;
   1.535 +}
   1.536 +
   1.537 +static void DX5_DeleteDevice(SDL_VideoDevice *this)
   1.538 +{
   1.539 +	/* Free DirectDraw object */
   1.540 +	if ( ddraw2 != NULL ) {
   1.541 +		IDirectDraw2_Release(ddraw2);
   1.542 +	}
   1.543 +	DX5_Unload();
   1.544 +	if ( this ) {
   1.545 +		if ( this->hidden ) {
   1.546 +			free(this->hidden);
   1.547 +		}
   1.548 +		if ( this->gl_data ) {
   1.549 +			free(this->gl_data);
   1.550 +		}
   1.551 +		free(this);
   1.552 +	}
   1.553 +}
   1.554 +
   1.555 +static SDL_VideoDevice *DX5_CreateDevice(int devindex)
   1.556 +{
   1.557 +	SDL_VideoDevice *device;
   1.558 +
   1.559 +	/* Load DirectX */
   1.560 +	if ( DX5_Load() < 0 ) {
   1.561 +		return(NULL);
   1.562 +	}
   1.563 +
   1.564 +	/* Initialize all variables that we clean on shutdown */
   1.565 +	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   1.566 +	if ( device ) {
   1.567 +		memset(device, 0, (sizeof *device));
   1.568 +		device->hidden = (struct SDL_PrivateVideoData *)
   1.569 +				malloc((sizeof *device->hidden));
   1.570 +		device->gl_data = (struct SDL_PrivateGLData *)
   1.571 +				malloc((sizeof *device->gl_data));
   1.572 +	}
   1.573 +	if ( (device == NULL) || (device->hidden == NULL) ||
   1.574 +		                 (device->gl_data == NULL) ) {
   1.575 +		SDL_OutOfMemory();
   1.576 +		DX5_DeleteDevice(device);
   1.577 +		return(NULL);
   1.578 +	}
   1.579 +	memset(device->hidden, 0, (sizeof *device->hidden));
   1.580 +	memset(device->gl_data, 0, (sizeof *device->gl_data));
   1.581 +
   1.582 +	/* Set the function pointers */
   1.583 +	device->VideoInit = DX5_VideoInit;
   1.584 +	device->ListModes = DX5_ListModes;
   1.585 +	device->SetVideoMode = DX5_SetVideoMode;
   1.586 +	device->UpdateMouse = WIN_UpdateMouse;
   1.587 +	device->CreateYUVOverlay = DX5_CreateYUVOverlay;
   1.588 +	device->SetColors = DX5_SetColors;
   1.589 +	device->UpdateRects = NULL;
   1.590 +	device->VideoQuit = DX5_VideoQuit;
   1.591 +	device->AllocHWSurface = DX5_AllocHWSurface;
   1.592 +	device->CheckHWBlit = DX5_CheckHWBlit;
   1.593 +	device->FillHWRect = DX5_FillHWRect;
   1.594 +	device->SetHWColorKey = DX5_SetHWColorKey;
   1.595 +	device->SetHWAlpha = DX5_SetHWAlpha;
   1.596 +	device->LockHWSurface = DX5_LockHWSurface;
   1.597 +	device->UnlockHWSurface = DX5_UnlockHWSurface;
   1.598 +	device->FlipHWSurface = DX5_FlipHWSurface;
   1.599 +	device->FreeHWSurface = DX5_FreeHWSurface;
   1.600 +#ifdef IID_IDirectDrawGammaControl
   1.601 +	device->SetGammaRamp = DX5_SetGammaRamp;
   1.602 +	device->GetGammaRamp = DX5_GetGammaRamp;
   1.603 +#endif
   1.604 +#ifdef HAVE_OPENGL
   1.605 +        device->GL_LoadLibrary = WIN_GL_LoadLibrary;
   1.606 +        device->GL_GetProcAddress = WIN_GL_GetProcAddress;
   1.607 +        device->GL_GetAttribute = WIN_GL_GetAttribute;
   1.608 +        device->GL_MakeCurrent = WIN_GL_MakeCurrent;
   1.609 +        device->GL_SwapBuffers = WIN_GL_SwapBuffers;
   1.610 +#endif
   1.611 +	device->SetCaption = WIN_SetWMCaption;
   1.612 +	device->SetIcon = WIN_SetWMIcon;
   1.613 +	device->IconifyWindow = WIN_IconifyWindow;
   1.614 +	device->GrabInput = WIN_GrabInput;
   1.615 +	device->GetWMInfo = WIN_GetWMInfo;
   1.616 +	device->FreeWMCursor = WIN_FreeWMCursor;
   1.617 +	device->CreateWMCursor = WIN_CreateWMCursor;
   1.618 +	device->ShowWMCursor = WIN_ShowWMCursor;
   1.619 +	device->WarpWMCursor = WIN_WarpWMCursor;
   1.620 +	device->CheckMouseMode = WIN_CheckMouseMode;
   1.621 +	device->InitOSKeymap = DX5_InitOSKeymap;
   1.622 +	device->PumpEvents = DX5_PumpEvents;
   1.623 +
   1.624 +	/* Set up the windows message handling functions */
   1.625 +	WIN_RealizePalette = DX5_RealizePalette;
   1.626 +	WIN_PaletteChanged = DX5_PaletteChanged;
   1.627 +	WIN_SwapGamma = DX5_SwapGamma;
   1.628 +	WIN_WinPAINT = DX5_WinPAINT;
   1.629 +	HandleMessage = DX5_HandleMessage;
   1.630 +
   1.631 +	device->free = DX5_DeleteDevice;
   1.632 +
   1.633 +	/* We're finally ready */
   1.634 +	return device;
   1.635 +}
   1.636 +
   1.637 +VideoBootStrap DIRECTX_bootstrap = {
   1.638 +	"directx", "Win95/98/2000 DirectX",
   1.639 +	DX5_Available, DX5_CreateDevice
   1.640 +};
   1.641 +
   1.642 +static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata)
   1.643 +{
   1.644 +	SDL_VideoDevice *this = (SDL_VideoDevice *)udata;
   1.645 +	struct DX5EnumRect *enumrect;
   1.646 +#if defined(NONAMELESSUNION)
   1.647 +	int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
   1.648 +#else
   1.649 +	int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
   1.650 +#endif
   1.651 +
   1.652 +	switch (bpp)  {
   1.653 +		case 8:
   1.654 +		case 16:
   1.655 +		case 24:
   1.656 +		case 32:
   1.657 +			bpp /= 8; --bpp;
   1.658 +			++SDL_nummodes[bpp];
   1.659 +			enumrect = (struct DX5EnumRect*)malloc(sizeof(struct DX5EnumRect));
   1.660 +			if ( !enumrect ) {
   1.661 +				SDL_OutOfMemory();
   1.662 +				return(DDENUMRET_CANCEL);
   1.663 +			}
   1.664 +			enumrect->r.x = 0;
   1.665 +			enumrect->r.y = 0;
   1.666 +			enumrect->r.w = (Uint16)desc->dwWidth;
   1.667 +			enumrect->r.h = (Uint16)desc->dwHeight;
   1.668 +			enumrect->next = enumlists[bpp];
   1.669 +			enumlists[bpp] = enumrect;
   1.670 +			break;
   1.671 +	}
   1.672 +
   1.673 +
   1.674 +	return(DDENUMRET_OK);
   1.675 +}
   1.676 +
   1.677 +void SetDDerror(const char *function, int code)
   1.678 +{
   1.679 +	static char *error;
   1.680 +	static char  errbuf[BUFSIZ];
   1.681 +
   1.682 +	errbuf[0] = 0;
   1.683 +	switch (code) {
   1.684 +		case DDERR_GENERIC:
   1.685 +			error = "Undefined error!";
   1.686 +			break;
   1.687 +		case DDERR_EXCEPTION:
   1.688 +			error = "Exception encountered";
   1.689 +			break;
   1.690 +		case DDERR_INVALIDOBJECT:
   1.691 +			error = "Invalid object";
   1.692 +			break;
   1.693 +		case DDERR_INVALIDPARAMS:
   1.694 +			error = "Invalid parameters";
   1.695 +			break;
   1.696 +		case DDERR_NOTFOUND:
   1.697 +			error = "Object not found";
   1.698 +			break;
   1.699 +		case DDERR_INVALIDRECT:
   1.700 +			error = "Invalid rectangle";
   1.701 +			break;
   1.702 +		case DDERR_INVALIDCAPS:
   1.703 +			error = "Invalid caps member";
   1.704 +			break;
   1.705 +		case DDERR_INVALIDPIXELFORMAT:
   1.706 +			error = "Invalid pixel format";
   1.707 +			break;
   1.708 +		case DDERR_OUTOFMEMORY:
   1.709 +			error = "Out of memory";
   1.710 +			break;
   1.711 +		case DDERR_OUTOFVIDEOMEMORY:
   1.712 +			error = "Out of video memory";
   1.713 +			break;
   1.714 +		case DDERR_SURFACEBUSY:
   1.715 +			error = "Surface busy";
   1.716 +			break;
   1.717 +		case DDERR_SURFACELOST:
   1.718 +			error = "Surface was lost";
   1.719 +			break;
   1.720 +		case DDERR_WASSTILLDRAWING:
   1.721 +			error = "DirectDraw is still drawing";
   1.722 +			break;
   1.723 +		case DDERR_INVALIDSURFACETYPE:
   1.724 +			error = "Invalid surface type";
   1.725 +			break;
   1.726 +		case DDERR_NOEXCLUSIVEMODE:
   1.727 +			error = "Not in exclusive access mode";
   1.728 +			break;
   1.729 +		case DDERR_NOPALETTEATTACHED:
   1.730 +			error = "No palette attached";
   1.731 +			break;
   1.732 +		case DDERR_NOPALETTEHW:
   1.733 +			error = "No palette hardware";
   1.734 +			break;
   1.735 +		case DDERR_NOT8BITCOLOR:
   1.736 +			error = "Not 8-bit color";
   1.737 +			break;
   1.738 +		case DDERR_EXCLUSIVEMODEALREADYSET:
   1.739 +			error = "Exclusive mode was already set";
   1.740 +			break;
   1.741 +		case DDERR_HWNDALREADYSET:
   1.742 +			error = "Window handle already set";
   1.743 +			break;
   1.744 +		case DDERR_HWNDSUBCLASSED:
   1.745 +			error = "Window handle is subclassed";
   1.746 +			break;
   1.747 +		case DDERR_NOBLTHW:
   1.748 +			error = "No blit hardware";
   1.749 +			break;
   1.750 +		case DDERR_IMPLICITLYCREATED:
   1.751 +			error = "Surface was implicitly created";
   1.752 +			break;
   1.753 +		case DDERR_INCOMPATIBLEPRIMARY:
   1.754 +			error = "Incompatible primary surface";
   1.755 +			break;
   1.756 +		case DDERR_NOCOOPERATIVELEVELSET:
   1.757 +			error = "No cooperative level set";
   1.758 +			break;
   1.759 +		case DDERR_NODIRECTDRAWHW:
   1.760 +			error = "No DirectDraw hardware";
   1.761 +			break;
   1.762 +		case DDERR_NOEMULATION:
   1.763 +			error = "No emulation available";
   1.764 +			break;
   1.765 +		case DDERR_NOFLIPHW:
   1.766 +			error = "No flip hardware";
   1.767 +			break;
   1.768 +		case DDERR_NOTFLIPPABLE:
   1.769 +			error = "Surface not flippable";
   1.770 +			break;
   1.771 +		case DDERR_PRIMARYSURFACEALREADYEXISTS:
   1.772 +			error = "Primary surface already exists";
   1.773 +			break;
   1.774 +		case DDERR_UNSUPPORTEDMODE:
   1.775 +			error = "Unsupported mode";
   1.776 +			break;
   1.777 +		case DDERR_WRONGMODE:
   1.778 +			error = "Surface created in different mode";
   1.779 +			break;
   1.780 +		case DDERR_UNSUPPORTED:
   1.781 +			error = "Operation not supported";
   1.782 +			break;
   1.783 +		case E_NOINTERFACE:
   1.784 +			error = "Interface not present";
   1.785 +			break;
   1.786 +		default:
   1.787 +			sprintf(errbuf, "%s: Unknown DirectDraw error: 0x%x",
   1.788 +								function, code);
   1.789 +			break;
   1.790 +	}
   1.791 +	if ( ! errbuf[0] ) {
   1.792 +		sprintf(errbuf, "%s: %s", function, error);
   1.793 +	}
   1.794 +	SDL_SetError("%s", errbuf);
   1.795 +	return;
   1.796 +}
   1.797 +
   1.798 +
   1.799 +static int DX5_UpdateVideoInfo(_THIS)
   1.800 +{
   1.801 +	/* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
   1.802 +#if DIRECTDRAW_VERSION <= 0x300
   1.803 +#error Your version of DirectX must be greater than or equal to 5.0
   1.804 +#endif
   1.805 +#ifndef IID_IDirectDrawGammaControl
   1.806 +	/*if gamma is undefined then we really have directx <= 0x500*/
   1.807 +	DDCAPS DDCaps;
   1.808 +#else
   1.809 +	DDCAPS_DX5 DDCaps;
   1.810 +#endif
   1.811 +	HRESULT result;
   1.812 +
   1.813 +	/* Fill in our hardware acceleration capabilities */
   1.814 +	memset(&DDCaps, 0, sizeof(DDCaps));
   1.815 +	DDCaps.dwSize = sizeof(DDCaps);
   1.816 +	result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL);
   1.817 +	if ( result != DD_OK ) {
   1.818 +		SetDDerror("DirectDraw2::GetCaps", result);
   1.819 +		return(-1);
   1.820 +	}
   1.821 +	this->info.hw_available = 1;
   1.822 +	if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) {
   1.823 +		this->info.blit_hw = 1;
   1.824 +	}
   1.825 +	if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
   1.826 +	     ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
   1.827 +		this->info.blit_hw_CC = 1;
   1.828 +	}
   1.829 +	if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
   1.830 +		/* This is only for alpha channel, and DirectX 6
   1.831 +		   doesn't support 2D alpha blits yet, so set it 0
   1.832 +		 */
   1.833 +		this->info.blit_hw_A = 0;
   1.834 +	}
   1.835 +	if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
   1.836 +		this->info.blit_sw = 1;
   1.837 +		/* This isn't necessarily true, but the HEL will cover us */
   1.838 +		this->info.blit_sw_CC = this->info.blit_hw_CC;
   1.839 +		this->info.blit_sw_A = this->info.blit_hw_A;
   1.840 +	}
   1.841 +	if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
   1.842 +		this->info.blit_fill = 1;
   1.843 +	}
   1.844 +
   1.845 +	/* Find out how much video memory is available */
   1.846 +	{ DDSCAPS ddsCaps;
   1.847 +	  DWORD total_mem;
   1.848 +		ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
   1.849 +		result = IDirectDraw2_GetAvailableVidMem(ddraw2,
   1.850 +						&ddsCaps, &total_mem, NULL);
   1.851 +		if ( result != DD_OK ) {
   1.852 +			total_mem = DDCaps.dwVidMemTotal; 
   1.853 +		}
   1.854 +		this->info.video_mem = total_mem/1024;
   1.855 +	}
   1.856 +	return(0);
   1.857 +}
   1.858 +
   1.859 +int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
   1.860 +{
   1.861 +	HRESULT result;
   1.862 +	LPDIRECTDRAW ddraw;
   1.863 +	int i, j;
   1.864 +	HDC hdc;
   1.865 +
   1.866 +	/* Intialize everything */
   1.867 +	ddraw2 = NULL;
   1.868 +	SDL_primary = NULL;
   1.869 +	SDL_clipper = NULL;
   1.870 +	SDL_palette = NULL;
   1.871 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1.872 +		SDL_nummodes[i] = 0;
   1.873 +		SDL_modelist[i] = NULL;
   1.874 +		SDL_modeindex[i] = 0;
   1.875 +	}
   1.876 +	colorchange_expected = 0;
   1.877 +
   1.878 +	/* Create the window */
   1.879 +	if ( DX5_CreateWindow(this) < 0 ) {
   1.880 +		return(-1);
   1.881 +	}
   1.882 +	DX5_SoundFocus(SDL_Window);
   1.883 +
   1.884 +	/* Create the DirectDraw object */
   1.885 +	result = DDrawCreate(NULL, &ddraw, NULL);
   1.886 +	if ( result != DD_OK ) {
   1.887 +		SetDDerror("DirectDrawCreate", result);
   1.888 +		return(-1);
   1.889 +	}
   1.890 +	result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
   1.891 +							(LPVOID *)&ddraw2);
   1.892 +	IDirectDraw_Release(ddraw);
   1.893 +	if ( result != DD_OK ) {
   1.894 +		SetDDerror("DirectDraw::QueryInterface", result);
   1.895 +		return(-1);
   1.896 +	}
   1.897 +
   1.898 +	/* Determine the screen depth */
   1.899 +	hdc = GetDC(SDL_Window);
   1.900 +	vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
   1.901 +					GetDeviceCaps(hdc,BITSPIXEL);
   1.902 +	ReleaseDC(SDL_Window, hdc);
   1.903 +
   1.904 +	/* Enumerate the available fullscreen modes */
   1.905 +	for ( i=0; i<NUM_MODELISTS; ++i )
   1.906 +		enumlists[i] = NULL;
   1.907 +
   1.908 +	result = IDirectDraw2_EnumDisplayModes(ddraw2,0,NULL,this,EnumModes2);
   1.909 +	if ( result != DD_OK ) {
   1.910 +		SetDDerror("DirectDraw2::EnumDisplayModes", result);
   1.911 +		return(-1);
   1.912 +	}
   1.913 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1.914 +		struct DX5EnumRect *rect;
   1.915 +		SDL_modelist[i] = (SDL_Rect **)
   1.916 +				malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
   1.917 +		if ( SDL_modelist[i] == NULL ) {
   1.918 +			SDL_OutOfMemory();
   1.919 +			return(-1);
   1.920 +		}
   1.921 +		for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
   1.922 +			SDL_modelist[i][j]=(SDL_Rect *)rect;
   1.923 +		}
   1.924 +		SDL_modelist[i][j] = NULL;
   1.925 +	}
   1.926 +	
   1.927 +	/* Fill in some window manager capabilities */
   1.928 +	this->info.wm_available = 1;
   1.929 +
   1.930 +	/* Fill in the video hardware capabilities */
   1.931 +	DX5_UpdateVideoInfo(this);
   1.932 +
   1.933 +	return(0);
   1.934 +}
   1.935 +
   1.936 +SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   1.937 +{
   1.938 +	int bpp;
   1.939 +
   1.940 +	bpp = format->BitsPerPixel;
   1.941 +	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   1.942 +		/* FIXME:  No support for 1 bpp or 4 bpp formats */
   1.943 +		switch (bpp) {  /* Does windows support other BPP? */
   1.944 +			case 8:
   1.945 +			case 16:
   1.946 +			case 24:
   1.947 +			case 32:
   1.948 +				bpp = (bpp/8)-1;
   1.949 +				if ( SDL_nummodes[bpp] > 0 )
   1.950 +					return(SDL_modelist[bpp]);
   1.951 +				/* Fall through */
   1.952 +			default:
   1.953 +				return((SDL_Rect **)0);
   1.954 +		}
   1.955 +	} else {
   1.956 +		if ( this->screen->format->BitsPerPixel == bpp ) {
   1.957 +			return((SDL_Rect **)-1);
   1.958 +		} else {
   1.959 +			return((SDL_Rect **)0);
   1.960 +		}
   1.961 +	}
   1.962 +}
   1.963 +
   1.964 +/* Various screen update functions available */
   1.965 +static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
   1.966 +static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
   1.967 +
   1.968 +SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
   1.969 +				int width, int height, int bpp, Uint32 flags)
   1.970 +{
   1.971 +	SDL_Surface *video;
   1.972 +	HRESULT result;
   1.973 +	DWORD sharemode;
   1.974 +	DWORD style;
   1.975 +	const DWORD directstyle =
   1.976 +			(WS_POPUP);
   1.977 +	const DWORD windowstyle = 
   1.978 +			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
   1.979 +	const DWORD resizestyle =
   1.980 +			(WS_THICKFRAME|WS_MAXIMIZEBOX);
   1.981 +	DDSURFACEDESC ddsd;
   1.982 +	LPDIRECTDRAWSURFACE  dd_surface1;
   1.983 +	LPDIRECTDRAWSURFACE3 dd_surface3;
   1.984 +	BOOL was_visible;
   1.985 +
   1.986 +#ifdef DDRAW_DEBUG
   1.987 + fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
   1.988 +#endif
   1.989 +	/* See whether or not we should center the window */
   1.990 +	was_visible = IsWindowVisible(SDL_Window);
   1.991 +
   1.992 +	/* Clean up any previous DirectDraw surfaces */
   1.993 +	if ( current->hwdata ) {
   1.994 +		this->FreeHWSurface(this, current);
   1.995 +		current->hwdata = NULL;
   1.996 +	}
   1.997 +	if ( SDL_primary != NULL ) {
   1.998 +		IDirectDrawSurface3_Release(SDL_primary);
   1.999 +		SDL_primary = NULL;
  1.1000 +	}
  1.1001 +
  1.1002 +	/* Unset any previous OpenGL fullscreen mode */
  1.1003 +	if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  1.1004 +	                       (SDL_OPENGL|SDL_FULLSCREEN) ) {
  1.1005 +		ChangeDisplaySettings(NULL, 0);
  1.1006 +	}
  1.1007 +
  1.1008 +	/* Clean up any GL context that may be hanging around */
  1.1009 +	if ( current->flags & SDL_OPENGL ) {
  1.1010 +		WIN_GL_ShutDown(this);
  1.1011 +	}
  1.1012 +
  1.1013 +	/* If we are setting a GL mode, use GDI, not DirectX (yuck) */
  1.1014 +	if ( flags & SDL_OPENGL ) {
  1.1015 +		RECT bounds;
  1.1016 +		int x, y;
  1.1017 +		Uint32 Rmask, Gmask, Bmask;
  1.1018 +
  1.1019 +		/* Recalculate the bitmasks if necessary */
  1.1020 +		if ( bpp == current->format->BitsPerPixel ) {
  1.1021 +			video = current;
  1.1022 +		} else {
  1.1023 +			switch (bpp) {
  1.1024 +			    case 15:
  1.1025 +			    case 16:
  1.1026 +				if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
  1.1027 +					/* 5-5-5 */
  1.1028 +					Rmask = 0x00007c00;
  1.1029 +					Gmask = 0x000003e0;
  1.1030 +					Bmask = 0x0000001f;
  1.1031 +				} else {
  1.1032 +					/* 5-6-5 */
  1.1033 +					Rmask = 0x0000f800;
  1.1034 +					Gmask = 0x000007e0;
  1.1035 +					Bmask = 0x0000001f;
  1.1036 +				}
  1.1037 +				break;
  1.1038 +			    case 24:
  1.1039 +			    case 32:
  1.1040 +				/* GDI defined as 8-8-8 */
  1.1041 +				Rmask = 0x00ff0000;
  1.1042 +				Gmask = 0x0000ff00;
  1.1043 +				Bmask = 0x000000ff;
  1.1044 +				break;
  1.1045 +			    default:
  1.1046 +				Rmask = 0x00000000;
  1.1047 +				Gmask = 0x00000000;
  1.1048 +				Bmask = 0x00000000;
  1.1049 +				break;
  1.1050 +			}
  1.1051 +			video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
  1.1052 +			                             Rmask, Gmask, Bmask, 0);
  1.1053 +			if ( video == NULL ) {
  1.1054 +				SDL_OutOfMemory();
  1.1055 +				return(NULL);
  1.1056 +			}
  1.1057 +		}
  1.1058 +
  1.1059 +		/* Fill in part of the video surface */
  1.1060 +		video->flags = 0;	/* Clear flags */
  1.1061 +		video->w = width;
  1.1062 +		video->h = height;
  1.1063 +		video->pitch = SDL_CalculatePitch(video);
  1.1064 +
  1.1065 +		/* Set fullscreen mode if appropriate.
  1.1066 +		   Ugh, since our list of valid video modes comes from
  1.1067 +		   the DirectX driver, we may not actually be able to
  1.1068 +		   change to the desired resolution here.
  1.1069 +		   FIXME: Should we do a closest match?
  1.1070 +		 */
  1.1071 +		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1072 +			DEVMODE settings;
  1.1073 +
  1.1074 +			memset(&settings, 0, sizeof(DEVMODE));
  1.1075 +			settings.dmSize = sizeof(DEVMODE);
  1.1076 +			settings.dmBitsPerPel = video->format->BitsPerPixel;
  1.1077 +			settings.dmPelsWidth = width;
  1.1078 +			settings.dmPelsHeight = height;
  1.1079 +			settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  1.1080 +			if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
  1.1081 +				video->flags |= SDL_FULLSCREEN;
  1.1082 +			}
  1.1083 +		}
  1.1084 +
  1.1085 +		style = GetWindowLong(SDL_Window, GWL_STYLE);
  1.1086 +		style &= ~(resizestyle|WS_MAXIMIZE);
  1.1087 +		if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1088 +			style &= ~windowstyle;
  1.1089 +			style |= directstyle;
  1.1090 +		} else {
  1.1091 +			if ( flags & SDL_NOFRAME ) {
  1.1092 +				style &= ~windowstyle;
  1.1093 +				style |= directstyle;
  1.1094 +				video->flags |= SDL_NOFRAME;
  1.1095 +			} else {
  1.1096 +				style &= ~directstyle;
  1.1097 +				style |= windowstyle;
  1.1098 +				if ( flags & SDL_RESIZABLE ) {
  1.1099 +					style |= resizestyle;
  1.1100 +					video->flags |= SDL_RESIZABLE;
  1.1101 +				}
  1.1102 +			}
  1.1103 +			if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1.1104 +		}
  1.1105 +		SetWindowLong(SDL_Window, GWL_STYLE, style);
  1.1106 +
  1.1107 +		/* Resize the window (copied from SDL WinDIB driver) */
  1.1108 +		if ( SDL_windowid == NULL ) {
  1.1109 +			UINT swp_flags;
  1.1110 +
  1.1111 +			SDL_resizing = 1;
  1.1112 +			bounds.left = 0;
  1.1113 +			bounds.top = 0;
  1.1114 +			bounds.right = video->w;
  1.1115 +			bounds.bottom = video->h;
  1.1116 +			AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE);
  1.1117 +			width = bounds.right-bounds.left;
  1.1118 +			height = bounds.bottom-bounds.top;
  1.1119 +			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1.1120 +			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1.1121 +			if ( y < 0 ) { /* Cover up title bar for more client area */
  1.1122 +				y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1.1123 +			}
  1.1124 +			swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW);
  1.1125 +			if ( was_visible && !(flags & SDL_FULLSCREEN) ) {
  1.1126 +				swp_flags |= SWP_NOMOVE;
  1.1127 +			}
  1.1128 +			SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
  1.1129 +			SDL_resizing = 0;
  1.1130 +			SetForegroundWindow(SDL_Window);
  1.1131 +		}
  1.1132 +
  1.1133 +		/* Set up for OpenGL */
  1.1134 +		if ( WIN_GL_SetupWindow(this) < 0 ) {
  1.1135 +			return(NULL);
  1.1136 +		}
  1.1137 +		video->flags |= SDL_OPENGL;
  1.1138 +		return(video);
  1.1139 +	}
  1.1140 +
  1.1141 +	/* Set the appropriate window style */
  1.1142 +	style = GetWindowLong(SDL_Window, GWL_STYLE);
  1.1143 +	style &= ~(resizestyle|WS_MAXIMIZE);
  1.1144 +	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1145 +		style &= ~windowstyle;
  1.1146 +		style |= directstyle;
  1.1147 +	} else {
  1.1148 +		if ( flags & SDL_NOFRAME ) {
  1.1149 +			style &= ~windowstyle;
  1.1150 +			style |= directstyle;
  1.1151 +		} else {
  1.1152 +			style &= ~directstyle;
  1.1153 +			style |= windowstyle;
  1.1154 +			if ( flags & SDL_RESIZABLE ) {
  1.1155 +				style |= resizestyle;
  1.1156 +			}
  1.1157 +		}
  1.1158 +		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1.1159 +	}
  1.1160 +	SetWindowLong(SDL_Window, GWL_STYLE, style);
  1.1161 +
  1.1162 +	/* Set DirectDraw sharing mode.. exclusive when fullscreen */
  1.1163 +	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1164 +		sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
  1.1165 +	} else {
  1.1166 +		sharemode = DDSCL_NORMAL;
  1.1167 +	}
  1.1168 +	result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
  1.1169 +	if ( result != DD_OK ) {
  1.1170 +		SetDDerror("DirectDraw2::SetCooperativeLevel", result);
  1.1171 +		return(NULL);
  1.1172 +	}
  1.1173 +
  1.1174 +	/* Set the display mode, if we are in fullscreen mode */
  1.1175 +	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1176 +		/* Cover up desktop during mode change */
  1.1177 +		SDL_resizing = 1;
  1.1178 +		SetWindowPos(SDL_Window, NULL, 0, 0, 
  1.1179 +			GetSystemMetrics(SM_CXSCREEN),
  1.1180 +			GetSystemMetrics(SM_CYSCREEN),
  1.1181 +			(SWP_NOCOPYBITS | SWP_NOZORDER));
  1.1182 +		SDL_resizing = 0;
  1.1183 +		ShowWindow(SDL_Window, SW_SHOW);
  1.1184 +		while ( GetForegroundWindow() != SDL_Window ) {
  1.1185 +			SetForegroundWindow(SDL_Window);
  1.1186 +			SDL_Delay(100);
  1.1187 +		}
  1.1188 +		result = IDirectDraw2_SetDisplayMode(ddraw2, width, height,
  1.1189 +								bpp, 0, 0);
  1.1190 +		if ( result != DD_OK ) {
  1.1191 +			/* We couldn't set fullscreen mode, try window */
  1.1192 +			return(DX5_SetVideoMode(this, current,
  1.1193 +				width, height, bpp, flags & ~SDL_FULLSCREEN)); 
  1.1194 +		}
  1.1195 +		DX5_DInputReset(this, 1);
  1.1196 +	} else {
  1.1197 +		DX5_DInputReset(this, 0);
  1.1198 +	}
  1.1199 +	DX5_UpdateVideoInfo(this);
  1.1200 +
  1.1201 +	/* Create a primary DirectDraw surface */
  1.1202 +	memset(&ddsd, 0, sizeof(ddsd));
  1.1203 +	ddsd.dwSize = sizeof(ddsd);
  1.1204 +	ddsd.dwFlags = DDSD_CAPS;
  1.1205 +	ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
  1.1206 +	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1.1207 +		/* There's no windowed double-buffering */
  1.1208 +		flags &= ~SDL_DOUBLEBUF;
  1.1209 +	}
  1.1210 +	if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1.1211 +		ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
  1.1212 +		ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1.1213 +		ddsd.dwBackBufferCount = 1;
  1.1214 +	}
  1.1215 +	result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
  1.1216 +	if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
  1.1217 +		ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
  1.1218 +		ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1.1219 +		ddsd.dwBackBufferCount = 0;
  1.1220 +		result = IDirectDraw2_CreateSurface(ddraw2,
  1.1221 +						&ddsd, &dd_surface1, NULL); 
  1.1222 +	}
  1.1223 +	if ( result != DD_OK ) {
  1.1224 +		SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
  1.1225 +		return(NULL);
  1.1226 +	}
  1.1227 +	result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1.1228 +			&IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
  1.1229 +	if ( result != DD_OK ) {
  1.1230 +		SetDDerror("DirectDrawSurface::QueryInterface", result);
  1.1231 +		return(NULL);
  1.1232 +	}
  1.1233 +	result = IDirectDrawSurface_Release(dd_surface1);
  1.1234 +	if ( result != DD_OK ) {
  1.1235 +		SetDDerror("DirectDrawSurface::Release", result);
  1.1236 +		return(NULL);
  1.1237 +	}
  1.1238 +
  1.1239 +	/* Get the format of the primary DirectDraw surface */
  1.1240 +	memset(&ddsd, 0, sizeof(ddsd));
  1.1241 +	ddsd.dwSize = sizeof(ddsd);
  1.1242 +	ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
  1.1243 +	result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
  1.1244 +	if ( result != DD_OK ) {
  1.1245 +		SetDDerror("DirectDrawSurface::Release", result);
  1.1246 +		return(NULL);
  1.1247 +	}
  1.1248 +	if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
  1.1249 +		SDL_SetError("Primary DDRAW surface is not RGB format");
  1.1250 +		return(NULL);
  1.1251 +	}
  1.1252 +
  1.1253 +	/* Free old palette and create a new one if we're in 8-bit mode */
  1.1254 +	if ( SDL_palette != NULL ) {
  1.1255 +		IDirectDrawPalette_Release(SDL_palette);
  1.1256 +		SDL_palette = NULL;
  1.1257 +	}
  1.1258 +#if defined(NONAMELESSUNION)
  1.1259 +	if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
  1.1260 +#else
  1.1261 +	if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
  1.1262 +#endif
  1.1263 +		int i;
  1.1264 +
  1.1265 +		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1266 +			/* We have access to the entire palette */
  1.1267 +			for ( i=0; i<256; ++i ) {
  1.1268 +				SDL_colors[i].peFlags =
  1.1269 +						(PC_NOCOLLAPSE|PC_RESERVED);
  1.1270 +				SDL_colors[i].peRed = 0;
  1.1271 +				SDL_colors[i].peGreen = 0;
  1.1272 +				SDL_colors[i].peBlue = 0;
  1.1273 +			}
  1.1274 +		} else {
  1.1275 +			/* First 10 colors are reserved by Windows */
  1.1276 +			for ( i=0; i<10; ++i ) {
  1.1277 +				SDL_colors[i].peFlags = PC_EXPLICIT;
  1.1278 +				SDL_colors[i].peRed = i;
  1.1279 +				SDL_colors[i].peGreen = 0;
  1.1280 +				SDL_colors[i].peBlue = 0;
  1.1281 +			}
  1.1282 +			for ( i=10; i<(10+236); ++i ) {
  1.1283 +				SDL_colors[i].peFlags = PC_NOCOLLAPSE;
  1.1284 +				SDL_colors[i].peRed = 0;
  1.1285 +				SDL_colors[i].peGreen = 0;
  1.1286 +				SDL_colors[i].peBlue = 0;
  1.1287 +			}
  1.1288 +			/* Last 10 colors are reserved by Windows */
  1.1289 +			for ( i=246; i<256; ++i ) {
  1.1290 +				SDL_colors[i].peFlags = PC_EXPLICIT;
  1.1291 +				SDL_colors[i].peRed = i;
  1.1292 +				SDL_colors[i].peGreen = 0;
  1.1293 +				SDL_colors[i].peBlue = 0;
  1.1294 +			}
  1.1295 +		}
  1.1296 +		result = IDirectDraw2_CreatePalette(ddraw2,
  1.1297 +		     			(DDPCAPS_8BIT|DDPCAPS_ALLOW256),
  1.1298 +						SDL_colors, &SDL_palette, NULL);
  1.1299 +		if ( result != DD_OK ) {
  1.1300 +			SetDDerror("DirectDraw2::CreatePalette", result);
  1.1301 +			return(NULL);
  1.1302 +		}
  1.1303 +		result = IDirectDrawSurface3_SetPalette(SDL_primary,
  1.1304 +								SDL_palette);
  1.1305 +		if ( result != DD_OK ) {
  1.1306 +			SetDDerror("DirectDrawSurface3::SetPalette", result);
  1.1307 +			return(NULL);
  1.1308 +		}
  1.1309 +	}
  1.1310 +
  1.1311 +	/* Create our video surface using the same pixel format */
  1.1312 +	video = current;
  1.1313 +	if ( (width != video->w) || (height != video->h)
  1.1314 +			|| (video->format->BitsPerPixel != 
  1.1315 +#if defined(NONAMELESSUNION)
  1.1316 +				ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
  1.1317 +#else
  1.1318 +				ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
  1.1319 +#endif
  1.1320 +		SDL_FreeSurface(video);
  1.1321 +		video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
  1.1322 +#if defined(NONAMELESSUNION)
  1.1323 +				ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
  1.1324 +					ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1.1325 +					ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1.1326 +					ddsd.ddpfPixelFormat.u4.dwBBitMask,
  1.1327 +#else
  1.1328 +				ddsd.ddpfPixelFormat.dwRGBBitCount,
  1.1329 +					ddsd.ddpfPixelFormat.dwRBitMask,
  1.1330 +					ddsd.ddpfPixelFormat.dwGBitMask,
  1.1331 +					ddsd.ddpfPixelFormat.dwBBitMask,
  1.1332 +#endif
  1.1333 +								0);
  1.1334 +		if ( video == NULL ) {
  1.1335 +			SDL_OutOfMemory();
  1.1336 +			return(NULL);
  1.1337 +		}
  1.1338 +		video->w = width;
  1.1339 +		video->h = height;
  1.1340 +		video->pitch = 0;
  1.1341 +	}
  1.1342 +	video->flags = 0;	/* Clear flags */
  1.1343 +
  1.1344 +	/* If not fullscreen, locking is possible, but it doesn't do what 
  1.1345 +	   the caller really expects -- if the locked surface is written to,
  1.1346 +	   the appropriate portion of the entire screen is modified, not 
  1.1347 +	   the application window, as we would like.
  1.1348 +	   Note that it is still possible to write directly to display
  1.1349 +	   memory, but the application must respect the clip list of
  1.1350 +	   the surface.  There might be some odd timing interactions
  1.1351 +	   involving clip list updates and background refreshing as
  1.1352 +	   Windows moves other windows across our window.
  1.1353 +	   We currently don't support this, even though it might be a
  1.1354 +	   good idea since BeOS has an implementation of BDirectWindow
  1.1355 +	   that does the same thing.  This would be most useful for
  1.1356 +	   applications that do complete screen updates every frame.
  1.1357 +	    -- Fixme?
  1.1358 +	*/
  1.1359 +	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1.1360 +		/* Necessary if we're going from fullscreen to window */
  1.1361 +		if ( video->pixels == NULL ) {
  1.1362 +			video->pitch = (width*video->format->BytesPerPixel);
  1.1363 +			/* Pitch needs to be QWORD (8-byte) aligned */
  1.1364 +			video->pitch = (video->pitch + 7) & ~7;
  1.1365 +			video->pixels = (void *)malloc(video->h*video->pitch);
  1.1366 +			if ( video->pixels == NULL ) {
  1.1367 +				if ( video != current ) {
  1.1368 +					SDL_FreeSurface(video);
  1.1369 +				}
  1.1370 +				SDL_OutOfMemory();
  1.1371 +				return(NULL);
  1.1372 +			}
  1.1373 +		}
  1.1374 +		dd_surface3 = NULL;
  1.1375 +		video->flags |= SDL_SWSURFACE;
  1.1376 +		if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
  1.1377 +			video->flags |= SDL_RESIZABLE;
  1.1378 +		}
  1.1379 +		if ( flags & SDL_NOFRAME ) {
  1.1380 +			video->flags |= SDL_NOFRAME;
  1.1381 +		}
  1.1382 +	} else {
  1.1383 +		/* Necessary if we're going from window to fullscreen */
  1.1384 +		if ( video->pixels != NULL ) {
  1.1385 +			free(video->pixels);
  1.1386 +			video->pixels = NULL;
  1.1387 +		}
  1.1388 +		dd_surface3 = SDL_primary;
  1.1389 +		video->flags |= SDL_HWSURFACE;
  1.1390 +	}
  1.1391 +
  1.1392 +	/* See if the primary surface has double-buffering enabled */
  1.1393 +	if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
  1.1394 +		video->flags |= SDL_DOUBLEBUF;
  1.1395 +	}
  1.1396 +
  1.1397 +	/* Allocate the SDL surface associated with the primary surface */
  1.1398 +	if ( DX5_AllocDDSurface(this, video, dd_surface3,
  1.1399 +	                        video->flags&SDL_HWSURFACE) < 0 ) {
  1.1400 +		if ( video != current ) {
  1.1401 +			SDL_FreeSurface(video);
  1.1402 +		}
  1.1403 +		return(NULL);
  1.1404 +	}
  1.1405 +
  1.1406 +	/* Use the appropriate blitting function */
  1.1407 +	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.1408 +		video->flags |= SDL_FULLSCREEN;
  1.1409 +		if ( video->format->palette != NULL ) {
  1.1410 +			video->flags |= SDL_HWPALETTE;
  1.1411 +		}
  1.1412 +		this->UpdateRects = DX5_DirectUpdate;
  1.1413 +	} else {
  1.1414 +		this->UpdateRects = DX5_WindowUpdate;
  1.1415 +	}
  1.1416 +
  1.1417 +	/* Make our window the proper size, set the clipper, then show it */
  1.1418 +	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1.1419 +		RECT bounds;
  1.1420 +		int  x, y;
  1.1421 +		UINT swp_flags;
  1.1422 +
  1.1423 +		/* Create and set a clipper on our primary surface */
  1.1424 +		if ( SDL_clipper == NULL ) {
  1.1425 +			result = IDirectDraw2_CreateClipper(ddraw2,
  1.1426 +							0, &SDL_clipper, NULL);
  1.1427 +			if ( result != DD_OK ) {
  1.1428 +				if ( video != current ) {
  1.1429 +					SDL_FreeSurface(video);
  1.1430 +				}
  1.1431 +				SetDDerror("DirectDraw2::CreateClipper",result);
  1.1432 +				return(NULL);
  1.1433 +			}
  1.1434 +		}
  1.1435 +		result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
  1.1436 +		if ( result != DD_OK ) {
  1.1437 +			if ( video != current ) {
  1.1438 +				SDL_FreeSurface(video);
  1.1439 +			}
  1.1440 +			SetDDerror("DirectDrawClipper::SetHWnd", result);
  1.1441 +			return(NULL);
  1.1442 +		}
  1.1443 +		result = IDirectDrawSurface3_SetClipper(SDL_primary,
  1.1444 +								SDL_clipper);
  1.1445 +		if ( result != DD_OK ) {
  1.1446 +			if ( video != current ) {
  1.1447 +				SDL_FreeSurface(video);
  1.1448 +			}
  1.1449 +			SetDDerror("DirectDrawSurface3::SetClipper", result);
  1.1450 +			return(NULL);
  1.1451 +		}
  1.1452 +
  1.1453 +		/* Set the size of the window, centering and adjusting */
  1.1454 +		SDL_resizing = 1;
  1.1455 +		bounds.left = 0;
  1.1456 +		bounds.top = 0;
  1.1457 +		bounds.right = video->w;
  1.1458 +		bounds.bottom = video->h;
  1.1459 +		AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
  1.1460 +									FALSE);
  1.1461 +		width = bounds.right-bounds.left;
  1.1462 +		height = bounds.bottom-bounds.top;
  1.1463 +		x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1.1464 +		y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1.1465 +		if ( y < 0 ) { /* Cover up title bar for more client area */
  1.1466 +			y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1.1467 +		}
  1.1468 +		swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER);
  1.1469 +		if ( was_visible ) {
  1.1470 +			swp_flags |= SWP_NOMOVE;
  1.1471 +		}
  1.1472 +		SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
  1.1473 +		SDL_resizing = 0;
  1.1474 +	}
  1.1475 +	ShowWindow(SDL_Window, SW_SHOW);
  1.1476 +	SetForegroundWindow(SDL_Window);
  1.1477 +
  1.1478 +	/* We're live! */
  1.1479 +	return(video);
  1.1480 +}
  1.1481 +
  1.1482 +struct private_hwdata {
  1.1483 +	LPDIRECTDRAWSURFACE3 dd_surface;
  1.1484 +	LPDIRECTDRAWSURFACE3 dd_writebuf;
  1.1485 +};
  1.1486 +
  1.1487 +static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
  1.1488 +				LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
  1.1489 +{
  1.1490 +	LPDIRECTDRAWSURFACE  dd_surface1;
  1.1491 +	LPDIRECTDRAWSURFACE3 dd_surface3;
  1.1492 +	DDSURFACEDESC ddsd;
  1.1493 +	HRESULT result;
  1.1494 +
  1.1495 +	/* Clear the hardware flag, in case we fail */
  1.1496 +	surface->flags &= ~flag;
  1.1497 +
  1.1498 +	/* Allocate the hardware acceleration data */
  1.1499 +	surface->hwdata = (struct private_hwdata *)
  1.1500 +					malloc(sizeof(*surface->hwdata));
  1.1501 +	if ( surface->hwdata == NULL ) {
  1.1502 +		SDL_OutOfMemory();
  1.1503 +		return(-1);
  1.1504 +	}
  1.1505 +	dd_surface3 = NULL;
  1.1506 +
  1.1507 +	/* Set up the surface description */
  1.1508 +	memset(&ddsd, 0, sizeof(ddsd));
  1.1509 +	ddsd.dwSize = sizeof(ddsd);
  1.1510 +	ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
  1.1511 +					DDSD_PITCH|DDSD_PIXELFORMAT);
  1.1512 +	ddsd.dwWidth = surface->w;
  1.1513 +	ddsd.dwHeight= surface->h;
  1.1514 +#if defined(NONAMELESSUNION)
  1.1515 +	ddsd.u1.lPitch = surface->pitch;
  1.1516 +#else
  1.1517 +	ddsd.lPitch = surface->pitch;
  1.1518 +#endif
  1.1519 +	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1.1520 +		ddsd.ddsCaps.dwCaps =
  1.1521 +				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
  1.1522 +	} else {
  1.1523 +		ddsd.ddsCaps.dwCaps =
  1.1524 +				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
  1.1525 +	}
  1.1526 +	ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  1.1527 +	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  1.1528 +	if ( surface->format->palette ) {
  1.1529 +		ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  1.1530 +	}
  1.1531 +#if defined(NONAMELESSUNION)
  1.1532 +	ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
  1.1533 +	ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
  1.1534 +	ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
  1.1535 +	ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
  1.1536 +#else
  1.1537 +	ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
  1.1538 +	ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
  1.1539 +	ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
  1.1540 +	ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
  1.1541 +#endif
  1.1542 +
  1.1543 +	/* Create the DirectDraw video surface */
  1.1544 +	if ( requested != NULL ) {
  1.1545 +		dd_surface3 = requested;
  1.1546 +	} else {
  1.1547 +		result = IDirectDraw2_CreateSurface(ddraw2,
  1.1548 +						&ddsd, &dd_surface1, NULL); 
  1.1549 +		if ( result != DD_OK ) {
  1.1550 +			SetDDerror("DirectDraw2::CreateSurface", result);
  1.1551 +			goto error_end;
  1.1552 +		}
  1.1553 +		result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1.1554 +			&IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
  1.1555 +		IDirectDrawSurface_Release(dd_surface1);
  1.1556 +		if ( result != DD_OK ) {
  1.1557 +			SetDDerror("DirectDrawSurface::QueryInterface", result);
  1.1558 +			goto error_end;
  1.1559 +		}
  1.1560 +	}
  1.1561 +
  1.1562 +	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1.1563 +		/* Check to see whether the surface actually ended up
  1.1564 +		   in video memory, and fail if not.  We expect the
  1.1565 +		   surfaces we create here to actually be in hardware!
  1.1566 +		*/
  1.1567 +		result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
  1.1568 +		if ( result != DD_OK ) {
  1.1569 +			SetDDerror("DirectDrawSurface3::GetCaps", result);
  1.1570 +			goto error_end;
  1.1571 +		}
  1.1572 +		if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
  1.1573 +							DDSCAPS_VIDEOMEMORY ) {
  1.1574 +			SDL_SetError("No room in video memory");
  1.1575 +			goto error_end;
  1.1576 +		}
  1.1577 +	} else {
  1.1578 +		/* Try to hook our surface memory */
  1.1579 +		ddsd.dwFlags = DDSD_LPSURFACE;
  1.1580 +		ddsd.lpSurface = surface->pixels;
  1.1581 +		result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
  1.1582 +								&ddsd, 0);
  1.1583 +		if ( result != DD_OK ) {
  1.1584 +			SetDDerror("DirectDraw2::SetSurfaceDesc", result);
  1.1585 +			goto error_end;
  1.1586 +		}
  1.1587 +	
  1.1588 +	}
  1.1589 +
  1.1590 +	/* Make sure the surface format was set properly */
  1.1591 +	memset(&ddsd, 0, sizeof(ddsd));
  1.1592 +	ddsd.dwSize = sizeof(ddsd);
  1.1593 +	result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  1.1594 +					&ddsd, DDLOCK_NOSYSLOCK, NULL);
  1.1595 +	if ( result != DD_OK ) {
  1.1596 +		SetDDerror("DirectDrawSurface3::Lock", result);
  1.1597 +		goto error_end;
  1.1598 +	}
  1.1599 +	IDirectDrawSurface3_Unlock(dd_surface3, NULL);
  1.1600 +
  1.1601 +	if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1.1602 +		if ( ddsd.lpSurface != surface->pixels ) {
  1.1603 +			SDL_SetError("DDraw didn't use SDL surface memory");
  1.1604 +			goto error_end;
  1.1605 +		}
  1.1606 +		if (
  1.1607 +#if defined(NONAMELESSUNION)
  1.1608 +			ddsd.u1.lPitch
  1.1609 +#else
  1.1610 +			ddsd.lPitch
  1.1611 +#endif
  1.1612 +				 != (LONG)surface->pitch ) {
  1.1613 +			SDL_SetError("DDraw created surface with wrong pitch");
  1.1614 +			goto error_end;
  1.1615 +		}
  1.1616 +	} else {
  1.1617 +#if defined(NONAMELESSUNION)
  1.1618 +		surface->pitch = (Uint16)ddsd.u1.lPitch;
  1.1619 +#else
  1.1620 +		surface->pitch = (Uint16)ddsd.lPitch;
  1.1621 +#endif
  1.1622 +	}
  1.1623 +#if defined(NONAMELESSUNION)
  1.1624 +	if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
  1.1625 +					surface->format->BitsPerPixel) ||
  1.1626 +	     (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
  1.1627 +	     (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
  1.1628 +	     (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
  1.1629 +#else
  1.1630 +	if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
  1.1631 +					surface->format->BitsPerPixel) ||
  1.1632 +	     (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
  1.1633 +	     (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
  1.1634 +	     (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
  1.1635 +#endif
  1.1636 +		SDL_SetError("DDraw didn't use SDL surface description");
  1.1637 +		goto error_end;
  1.1638 +	}
  1.1639 +	if ( (ddsd.dwWidth != (DWORD)surface->w) ||
  1.1640 +		(ddsd.dwHeight != (DWORD)surface->h) ) {
  1.1641 +		SDL_SetError("DDraw created surface with wrong size");
  1.1642 +		goto error_end;
  1.1643 +	}
  1.1644 +
  1.1645 +	/* Set the surface private data */
  1.1646 +	surface->flags |= flag;
  1.1647 +	surface->hwdata->dd_surface = dd_surface3;
  1.1648 +	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1.1649 +		LPDIRECTDRAWSURFACE3 dd_writebuf;
  1.1650 +
  1.1651 +		ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  1.1652 +		result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
  1.1653 +						&ddsd.ddsCaps, &dd_writebuf);
  1.1654 +		if ( result != DD_OK ) {
  1.1655 +			SetDDerror("DirectDrawSurface3::GetAttachedSurface",
  1.1656 +								result);
  1.1657 +		} else {
  1.1658 +			dd_surface3 = dd_writebuf;
  1.1659 +		}
  1.1660 +	}
  1.1661 +	surface->hwdata->dd_writebuf = dd_surface3;
  1.1662 +
  1.1663 +	/* We're ready to go! */
  1.1664 +	return(0);
  1.1665 +
  1.1666 +	/* Okay, so goto's are cheesy, but there are so many possible
  1.1667 +	   errors in this function, and the cleanup is the same in 
  1.1668 +	   every single case.  Is there a better way, other than deeply
  1.1669 +	   nesting the code?
  1.1670 +	*/
  1.1671 +error_end:
  1.1672 +	if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
  1.1673 +		IDirectDrawSurface_Release(dd_surface3);
  1.1674 +	}
  1.1675 +	free(surface->hwdata);
  1.1676 +	surface->hwdata = NULL;
  1.1677 +	return(-1);
  1.1678 +}
  1.1679 +
  1.1680 +static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
  1.1681 +{
  1.1682 +	/* DDraw limitation -- you need to set cooperative level first */
  1.1683 +	if ( SDL_primary == NULL ) {
  1.1684 +		SDL_SetError("You must set a non-GL video mode first");
  1.1685 +		return(-1);
  1.1686 +	}
  1.1687 +	return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
  1.1688 +}
  1.1689 +
  1.1690 +void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
  1.1691 +{
  1.1692 +	DDSURFACEDESC ddsd;
  1.1693 +
  1.1694 +	/* Lock and load! */
  1.1695 +	memset(&ddsd, 0, sizeof(ddsd));
  1.1696 +	ddsd.dwSize = sizeof(ddsd);
  1.1697 +	if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
  1.1698 +			(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
  1.1699 +		return;
  1.1700 +	}
  1.1701 +	IDirectDrawSurface3_Unlock(surface, NULL);
  1.1702 +	
  1.1703 +	fprintf(stderr, "%s:\n", title);
  1.1704 +	fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
  1.1705 +		ddsd.dwWidth, ddsd.dwHeight,
  1.1706 +		(flags & SDL_HWSURFACE) ? "hardware" : "software",
  1.1707 +#if defined(NONAMELESSUNION)
  1.1708 +		ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
  1.1709 +#else
  1.1710 +		ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
  1.1711 +#endif
  1.1712 +	fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
  1.1713 +#if defined(NONAMELESSUNION)
  1.1714 +	     		ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1.1715 +	     		ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1.1716 +	     		ddsd.ddpfPixelFormat.u4.dwBBitMask);
  1.1717 +#else
  1.1718 +	     		ddsd.ddpfPixelFormat.dwRBitMask,
  1.1719 +	     		ddsd.ddpfPixelFormat.dwGBitMask,
  1.1720 +	     		ddsd.ddpfPixelFormat.dwBBitMask);
  1.1721 +#endif
  1.1722 +}
  1.1723 +
  1.1724 +static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
  1.1725 +					SDL_Surface *dst, SDL_Rect *dstrect)
  1.1726 +{
  1.1727 +	LPDIRECTDRAWSURFACE3 src_surface;
  1.1728 +	LPDIRECTDRAWSURFACE3 dst_surface;
  1.1729 +	DWORD flags;
  1.1730 +	RECT rect;
  1.1731 +	HRESULT result;
  1.1732 +
  1.1733 +	/* Set it up.. the desination must have a DDRAW surface */
  1.1734 +	src_surface = src->hwdata->dd_writebuf;
  1.1735 +	dst_surface = dst->hwdata->dd_writebuf;
  1.1736 +	rect.top    = srcrect->y;
  1.1737 +	rect.bottom = srcrect->y+srcrect->h;
  1.1738 +	rect.left   = srcrect->x;
  1.1739 +	rect.right  = srcrect->x+srcrect->w;
  1.1740 +	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
  1.1741 +		flags = DDBLTFAST_SRCCOLORKEY;
  1.1742 +	else
  1.1743 +		flags = DDBLTFAST_NOCOLORKEY;
  1.1744 +	/* FIXME:  We can remove this flag for _really_ fast blit queuing,
  1.1745 +	           but it will affect the return values of locks and flips.
  1.1746 +	 */
  1.1747 +	flags |= DDBLTFAST_WAIT;
  1.1748 +
  1.1749 +	/* Do the blit! */
  1.1750 +	result = IDirectDrawSurface3_BltFast(dst_surface,
  1.1751 +			dstrect->x, dstrect->y, src_surface, &rect, flags);
  1.1752 +	if ( result != DD_OK ) {
  1.1753 +		if ( result == DDERR_SURFACELOST ) {
  1.1754 +			result = IDirectDrawSurface3_Restore(src_surface);
  1.1755 +			result = IDirectDrawSurface3_Restore(dst_surface);
  1.1756 +			/* The surfaces need to be reloaded with artwork */
  1.1757 +			SDL_SetError("Blit surfaces were lost, reload them");
  1.1758 +			return(-2);
  1.1759 +		}
  1.1760 +		SetDDerror("IDirectDrawSurface3::BltFast", result);
  1.1761 +#ifdef DDRAW_DEBUG
  1.1762 + fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
  1.1763 + fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
  1.1764 +		(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
  1.1765 +					dstrect->x, dstrect->y);
  1.1766 +  PrintSurface("SRC", src_surface, src->flags);
  1.1767 +  PrintSurface("DST", dst_surface, dst->flags);
  1.1768 + fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
  1.1769 +		rect.left, rect.top, rect.right, rect.bottom);
  1.1770 +#endif
  1.1771 +		/* Unexpected error, fall back to software blit */
  1.1772 +		return(src->map->sw_blit(src, srcrect, dst, dstrect));
  1.1773 +	}
  1.1774 +	return(0);
  1.1775 +}
  1.1776 +
  1.1777 +static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
  1.1778 +{
  1.1779 +	int accelerated;
  1.1780 +
  1.1781 +	/* We need to have a DDraw surface for HW blits */
  1.1782 +	if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1.1783 +		/* Allocate a DDraw surface for the blit */
  1.1784 +		if ( src->hwdata == NULL ) {
  1.1785 +			DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
  1.1786 +		}
  1.1787 +	}
  1.1788 +	if ( src->hwdata == NULL ) {
  1.1789 +		return(0);
  1.1790 +	}
  1.1791 +
  1.1792 +	/* Set initial acceleration on */
  1.1793 +	src->flags |= SDL_HWACCEL;
  1.1794 +
  1.1795 +	/* Set the surface attributes */
  1.1796 +	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  1.1797 +		if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
  1.1798 +			src->flags &= ~SDL_HWACCEL;
  1.1799 +		}
  1.1800 +	}
  1.1801 +	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  1.1802 +		if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
  1.1803 +			src->flags &= ~SDL_HWACCEL;
  1.1804 +		}
  1.1805 +	}
  1.1806 +
  1.1807 +	/* Check to see if final surface blit is accelerated */
  1.1808 +	accelerated = !!(src->flags & SDL_HWACCEL);
  1.1809 +	if ( accelerated ) {
  1.1810 +#ifdef DDRAW_DEBUG
  1.1811 +  fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
  1.1812 +#endif
  1.1813 +		src->map->hw_blit = DX5_HWAccelBlit;
  1.1814 +	}
  1.1815 +	return(accelerated);
  1.1816 +}
  1.1817 +
  1.1818 +static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1.1819 +{
  1.1820 +	LPDIRECTDRAWSURFACE3 dst_surface;
  1.1821 +	RECT area;
  1.1822 +	DDBLTFX bltfx;
  1.1823 +	HRESULT result;
  1.1824 +
  1.1825 +#ifdef DDRAW_DEBUG
  1.1826 + fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
  1.1827 +#endif
  1.1828 +	dst_surface = dst->hwdata->dd_writebuf;
  1.1829 +	area.top = dstrect->y;
  1.1830 +	area.bottom = dstrect->y+dstrect->h;
  1.1831 +	area.left = dstrect->x;
  1.1832 +	area.right = dstrect->x+dstrect->w;
  1.1833 +	bltfx.dwSize = sizeof(bltfx);
  1.1834 +#if defined(NONAMELESSUNION)
  1.1835 +	bltfx.u5.dwFillColor = color;
  1.1836 +#else
  1.1837 +	bltfx.dwFillColor = color;
  1.1838 +#endif
  1.1839 +	result = IDirectDrawSurface3_Blt(dst_surface,
  1.1840 +			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1.1841 +	if ( result == DDERR_SURFACELOST ) {
  1.1842 +		IDirectDrawSurface3_Restore(dst_surface);
  1.1843 +		result = IDirectDrawSurface3_Blt(dst_surface,
  1.1844 +			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1.1845 +	}
  1.1846 +	if ( result != DD_OK ) {
  1.1847 +		SetDDerror("IDirectDrawSurface3::Blt", result);
  1.1848 +		return(-1);
  1.1849 +	}
  1.1850 +	return(0);
  1.1851 +}
  1.1852 +
  1.1853 +static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
  1.1854 +{
  1.1855 +	DDCOLORKEY colorkey;
  1.1856 +	HRESULT result;
  1.1857 +
  1.1858 +	/* Set the surface colorkey */
  1.1859 +	colorkey.dwColorSpaceLowValue = key;
  1.1860 +	colorkey.dwColorSpaceHighValue = key;
  1.1861 +	result = IDirectDrawSurface3_SetColorKey(
  1.1862 +			surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
  1.1863 +	if ( result != DD_OK ) {
  1.1864 +		SetDDerror("IDirectDrawSurface3::SetColorKey", result);
  1.1865 +		return(-1);
  1.1866 +	}
  1.1867 +	return(0);
  1.1868 +}
  1.1869 +static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
  1.1870 +{
  1.1871 +	return(-1);
  1.1872 +}
  1.1873 +
  1.1874 +static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
  1.1875 +{
  1.1876 +	HRESULT result;
  1.1877 +	LPDIRECTDRAWSURFACE3 dd_surface;
  1.1878 +	DDSURFACEDESC ddsd;
  1.1879 +
  1.1880 +	/* Lock and load! */
  1.1881 +	dd_surface = surface->hwdata->dd_writebuf;
  1.1882 +	memset(&ddsd, 0, sizeof(ddsd));
  1.1883 +	ddsd.dwSize = sizeof(ddsd);
  1.1884 +	result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  1.1885 +					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1.1886 +	if ( result == DDERR_SURFACELOST ) {
  1.1887 +		result = IDirectDrawSurface3_Restore(
  1.1888 +						surface->hwdata->dd_surface);
  1.1889 +		result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
  1.1890 +					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1.1891 +	}
  1.1892 +	if ( result != DD_OK ) {
  1.1893 +		SetDDerror("DirectDrawSurface3::Lock", result);
  1.1894 +		return(-1);
  1.1895 +	}
  1.1896 +	/* Pitch might have changed -- recalculate pitch and offset */
  1.1897 +#if defined(NONAMELESSUNION)
  1.1898 +	if ( surface->pitch != ddsd.u1.lPitch ) {
  1.1899 +		surface->pitch = ddsd.u1.lPitch;
  1.1900 +#else
  1.1901 +	if ( surface->pitch != ddsd.lPitch ) {
  1.1902 +		surface->pitch = (Uint16)ddsd.lPitch;
  1.1903 +#endif
  1.1904 +		surface->offset =
  1.1905 +			((ddsd.dwHeight-surface->h)/2)*surface->pitch +
  1.1906 +			((ddsd.dwWidth-surface->w)/2)*
  1.1907 +					surface->format->BytesPerPixel;
  1.1908 +	}
  1.1909 +	surface->pixels = ddsd.lpSurface;
  1.1910 +	return(0);
  1.1911 +}
  1.1912 +
  1.1913 +static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
  1.1914 +{
  1.1915 +	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  1.1916 +	surface->pixels = NULL;
  1.1917 +}
  1.1918 +
  1.1919 +static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
  1.1920 +{
  1.1921 +	HRESULT result;
  1.1922 +	LPDIRECTDRAWSURFACE3 dd_surface;
  1.1923 +
  1.1924 +	dd_surface = surface->hwdata->dd_surface;
  1.1925 +	result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  1.1926 +	if ( result == DDERR_SURFACELOST ) {
  1.1927 +		result = IDirectDrawSurface3_Restore(
  1.1928 +						surface->hwdata->dd_surface);
  1.1929 +		result = IDirectDrawSurface3_Flip(dd_surface,NULL,DDFLIP_WAIT);
  1.1930 +	}
  1.1931 +	if ( result != DD_OK ) {
  1.1932 +		SetDDerror("DirectDrawSurface3::Flip", result);
  1.1933 +		return(-1);
  1.1934 +	}
  1.1935 +	return(0);
  1.1936 +}
  1.1937 +
  1.1938 +static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
  1.1939 +{
  1.1940 +	if ( surface->hwdata ) {
  1.1941 +		if ( surface->hwdata->dd_surface != SDL_primary ) {
  1.1942 +			IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
  1.1943 +		}
  1.1944 +		free(surface->hwdata);
  1.1945 +		surface->hwdata = NULL;
  1.1946 +	}
  1.1947 +}
  1.1948 +
  1.1949 +void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
  1.1950 +{
  1.1951 +	HRESULT result;
  1.1952 +	int i;
  1.1953 +	RECT src, dst;
  1.1954 +
  1.1955 +	for ( i=0; i<numrects; ++i ) {
  1.1956 +		src.top = rects[i].y;
  1.1957 +		src.bottom = rects[i].y+rects[i].h;
  1.1958 +		src.left = rects[i].x;
  1.1959 +		src.right = rects[i].x+rects[i].w;
  1.1960 +		dst.top = SDL_bounds.top+src.top;
  1.1961 +		dst.left = SDL_bounds.left+src.left;
  1.1962 +		dst.bottom = SDL_bounds.top+src.bottom;
  1.1963 +		dst.right = SDL_bounds.left+src.right;
  1.1964 +		result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  1.1965 +					this->screen->hwdata->dd_surface, &src,
  1.1966 +							DDBLT_WAIT, NULL);
  1.1967 +		/* Doh!  Check for lost surface and restore it */
  1.1968 +		if ( result == DDERR_SURFACELOST ) {
  1.1969 +			IDirectDrawSurface3_Restore(SDL_primary);
  1.1970 +			IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  1.1971 +					this->screen->hwdata->dd_surface, &src,
  1.1972 +							DDBLT_WAIT, NULL);
  1.1973 +		}
  1.1974 +	}
  1.1975 +}
  1.1976 +
  1.1977 +void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
  1.1978 +{
  1.1979 +}
  1.1980 +
  1.1981 +/* Compress a full palette into the limited number of colors given to us
  1.1982 +   by windows.
  1.1983 +
  1.1984 +   The "best" way to do this is to sort the colors by diversity and place
  1.1985 +   the most diverse colors into the limited palette.  Unfortunately this
  1.1986 +   results in widely varying colors being displayed in the interval during
  1.1987 +   which the windows palette has been set, and the mapping of the shadow
  1.1988 +   surface to the new palette.  This is especially noticeable during fades.
  1.1989 +
  1.1990 +   To deal with this problem, we can copy a predetermined portion of the
  1.1991 +   full palette, and use that as the limited palette.  This allows colors
  1.1992 +   to fade smoothly as the remapping is very similar on each palette change.
  1.1993 +   Unfortunately, this breaks applications which partition the palette into
  1.1994 +   distinct and widely varying areas, expecting all colors to be available.
  1.1995 +
  1.1996 +   I'm making them both available, chosen at compile time.
  1.1997 +   If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
  1.1998 +   otherwise the sort-by-diversity algorithm will be used.
  1.1999 +*/
  1.2000 +#define SIMPLE_COMPRESSION
  1.2001 +#define CS_CS_DIST(A, B) ({						\
  1.2002 +	int r = (A.r - B.r);						\
  1.2003 +	int g = (A.g - B.g);						\
  1.2004 +	int b = (A.b - B.b);						\
  1.2005 +	(r*r + g*g + b*b);						\
  1.2006 +})
  1.2007 +static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
  1.2008 +{
  1.2009 +#ifdef SIMPLE_COMPRESSION
  1.2010 +	int i, j;
  1.2011 +#else
  1.2012 +	static SDL_Color zero = { 0, 0, 0, 0 };
  1.2013 +	int i, j;
  1.2014 +	int max, dist;
  1.2015 +	int prev, next;
  1.2016 +	int *pool;
  1.2017 +	int *seen, *order;
  1.2018 +#endif
  1.2019 +
  1.2020 +	/* Does this happen? */
  1.2021 +	if ( maxcolors > ncolors ) {
  1.2022 +		maxcolors = ncolors;
  1.2023 +	}
  1.2024 +
  1.2025 +#ifdef SIMPLE_COMPRESSION
  1.2026 +	/* Just copy the first "maxcolors" colors */
  1.2027 +	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  1.2028 +		SDL_colors[j].peRed = colors[i].r;
  1.2029 +		SDL_colors[j].peGreen = colors[i].g;
  1.2030 +		SDL_colors[j].peBlue = colors[i].b;
  1.2031 +	}
  1.2032 +#else
  1.2033 +	/* Allocate memory for the arrays we use */
  1.2034 +	pool = (int *)alloca(2*ncolors*sizeof(int));
  1.2035 +	if ( pool == NULL ) {
  1.2036 +		/* No worries, just return */;
  1.2037 +		return;
  1.2038 +	}
  1.2039 +	seen = pool;
  1.2040 +	memset(seen, 0, ncolors*sizeof(int));
  1.2041 +	order = pool+ncolors;
  1.2042 +
  1.2043 +	/* Start with the brightest color */
  1.2044 +	max = 0;
  1.2045 +	for ( i=0; i<ncolors; ++i ) {
  1.2046 +		dist = CS_CS_DIST(zero, colors[i]);
  1.2047 +		if ( dist >= max ) {
  1.2048 +			max = dist;
  1.2049 +			next = i;
  1.2050 +		}
  1.2051 +	}
  1.2052 +	j = 0;
  1.2053 +	order[j++] = next;
  1.2054 +	seen[next] = 1;
  1.2055 +	prev = next;
  1.2056 +
  1.2057 +	/* Keep going through all the colors */
  1.2058 +	while ( j < maxcolors ) {
  1.2059 +		max = 0;
  1.2060 +		for ( i=0; i<ncolors; ++i ) {
  1.2061 +			if ( seen[i] ) {
  1.2062 +				continue;
  1.2063 +			}
  1.2064 +			dist = CS_CS_DIST(colors[i], colors[prev]);
  1.2065 +			if ( dist >= max ) {
  1.2066 +				max = dist;
  1.2067 +				next = i;
  1.2068 +			}
  1.2069 +		}
  1.2070 +		order[j++] = next;
  1.2071 +		seen[next] = 1;
  1.2072 +		prev = next;
  1.2073 +	}
  1.2074 +
  1.2075 +	/* Compress the colors to the palette */
  1.2076 +	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  1.2077 +		SDL_colors[j].peRed = colors[order[i]].r;
  1.2078 +		SDL_colors[j].peGreen = colors[order[i]].g;
  1.2079 +		SDL_colors[j].peBlue = colors[order[i]].b;
  1.2080 +	}
  1.2081 +#endif /* SIMPLE_COMPRESSION */
  1.2082 +}
  1.2083 +
  1.2084 +/* Set the system colormap in both fullscreen and windowed modes */
  1.2085 +int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  1.2086 +{
  1.2087 +	int i;
  1.2088 +	int alloct_all;
  1.2089 +
  1.2090 +	/* Copy palette colors into display palette */
  1.2091 +	alloct_all = 0;
  1.2092 +	if ( SDL_palette != NULL ) {
  1.2093 +		if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1.2094 +			/* We can set all entries explicitly */
  1.2095 +			for ( i=0; i< ncolors; ++i ) {
  1.2096 +			        int j = firstcolor + i;
  1.2097 +				SDL_colors[j].peRed = colors[i].r;
  1.2098 +				SDL_colors[j].peGreen = colors[i].g;
  1.2099 +				SDL_colors[j].peBlue = colors[i].b;
  1.2100 +			}
  1.2101 +			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  1.2102 +				firstcolor, ncolors, &SDL_colors[firstcolor]);
  1.2103 +			alloct_all = 1;
  1.2104 +		} else {
  1.2105 +			/* Grab the 236 most diverse colors in the palette */
  1.2106 +			DX5_CompressPalette(this, colors, ncolors, 236);
  1.2107 +			/* This sends an WM_PALETTECHANGED message to us */
  1.2108 +			colorchange_expected = 1;
  1.2109 +			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  1.2110 +							0, 256, SDL_colors);
  1.2111 +		}
  1.2112 +	}
  1.2113 +	return(alloct_all);
  1.2114 +}
  1.2115 +
  1.2116 +static void DX5_SwapGamma(_THIS)
  1.2117 +{
  1.2118 +	return;
  1.2119 +}
  1.2120 +
  1.2121 +/* Gamma code is only available on DirectX 7 and newer */
  1.2122 +#ifdef IID_IDirectDrawGammaControl
  1.2123 +
  1.2124 +static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
  1.2125 +{
  1.2126 +	LPDIRECTDRAWGAMMACONTROL gamma;
  1.2127 +	DDGAMMARAMP gamma_ramp;
  1.2128 +	HRESULT result;
  1.2129 +
  1.2130 +	/* Check for a video mode! */
  1.2131 +	if ( ! SDL_primary ) {
  1.2132 +		SDL_SetError("A video mode must be set for gamma correction");
  1.2133 +		return(-1);
  1.2134 +	}
  1.2135 +
  1.2136 +	/* Get the gamma control object */
  1.2137 +	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  1.2138 +			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  1.2139 +	if ( result != DD_OK ) {
  1.2140 +		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  1.2141 +		return(-1);
  1.2142 +	}
  1.2143 +
  1.2144 +	/* Set up the gamma ramp */
  1.2145 +	memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
  1.2146 +	memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
  1.2147 +	memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
  1.2148 +	result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
  1.2149 +	if ( result != DD_OK ) {
  1.2150 +		SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
  1.2151 +	}
  1.2152 +
  1.2153 +	/* Release the interface and return */
  1.2154 +	IDirectDrawGammaControl_Release(gamma);
  1.2155 +	return (result == DD_OK) ? 0 : -1;
  1.2156 +}
  1.2157 +
  1.2158 +static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
  1.2159 +{
  1.2160 +	LPDIRECTDRAWGAMMACONTROL gamma;
  1.2161 +	DDGAMMARAMP gamma_ramp;
  1.2162 +	HRESULT result;
  1.2163 +
  1.2164 +	/* Check for a video mode! */
  1.2165 +	if ( ! SDL_primary ) {
  1.2166 +		SDL_SetError("A video mode must be set for gamma correction");
  1.2167 +		return(-1);
  1.2168 +	}
  1.2169 +
  1.2170 +	/* Get the gamma control object */
  1.2171 +	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  1.2172 +			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  1.2173 +	if ( result != DD_OK ) {
  1.2174 +		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  1.2175 +		return(-1);
  1.2176 +	}
  1.2177 +
  1.2178 +	/* Set up the gamma ramp */
  1.2179 +	result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
  1.2180 +	if ( result == DD_OK ) {
  1.2181 +		memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
  1.2182 +		memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
  1.2183 +		memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
  1.2184 +	} else {
  1.2185 +		SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
  1.2186 +	}
  1.2187 +
  1.2188 +	/* Release the interface and return */
  1.2189 +	IDirectDrawGammaControl_Release(gamma);
  1.2190 +	return (result == DD_OK) ? 0 : -1;
  1.2191 +}
  1.2192 +
  1.2193 +#endif /* IID_IDirectDrawGammaControl */
  1.2194 +
  1.2195 +void DX5_VideoQuit(_THIS)
  1.2196 +{
  1.2197 +	int i, j;
  1.2198 +
  1.2199 +	/* If we're fullscreen GL, we need to reset the display */
  1.2200 +	if ( this->screen != NULL ) {
  1.2201 +		if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  1.2202 +		                            (SDL_OPENGL|SDL_FULLSCREEN) ) {
  1.2203 +			ChangeDisplaySettings(NULL, 0);
  1.2204 +		}
  1.2205 +		if ( this->screen->flags & SDL_OPENGL ) {
  1.2206 +			WIN_GL_ShutDown(this);
  1.2207 +		}
  1.2208 +	}
  1.2209 +
  1.2210 +	/* Free any palettes we used */
  1.2211 +	if ( SDL_palette != NULL ) {
  1.2212 +		IDirectDrawPalette_Release(SDL_palette);
  1.2213 +		SDL_palette = NULL;
  1.2214 +	}
  1.2215 +
  1.2216 +	/* Allow the primary surface to be freed */
  1.2217 +	if ( SDL_primary != NULL ) {
  1.2218 +		SDL_primary = NULL;
  1.2219 +	}
  1.2220 +
  1.2221 +	/* Free video mode lists */
  1.2222 +	for ( i=0; i<NUM_MODELISTS; ++i ) {
  1.2223 +		if ( SDL_modelist[i] != NULL ) {
  1.2224 +			for ( j=0; SDL_modelist[i][j]; ++j )
  1.2225 +				free(SDL_modelist[i][j]);
  1.2226 +			free(SDL_modelist[i]);
  1.2227 +			SDL_modelist[i] = NULL;
  1.2228 +		}
  1.2229 +	}
  1.2230 +
  1.2231 +	/* Free the window */
  1.2232 +	if ( SDL_Window ) {
  1.2233 +		DX5_DestroyWindow(this);
  1.2234 +	}
  1.2235 +
  1.2236 +	/* Free our window icon */
  1.2237 +	if ( screen_icn ) {
  1.2238 +		DestroyIcon(screen_icn);
  1.2239 +		screen_icn = NULL;
  1.2240 +	}
  1.2241 +}
  1.2242 +
  1.2243 +/* Exported for the windows message loop only */
  1.2244 +void DX5_RealizePalette(_THIS)
  1.2245 +{
  1.2246 +	if ( SDL_palette ) {
  1.2247 +		IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  1.2248 +	}
  1.2249 +}
  1.2250 +static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
  1.2251 +{
  1.2252 +	int row, col;
  1.2253 +	Uint8 *pixels;
  1.2254 +
  1.2255 +	if ( surface->w && surface->h ) {
  1.2256 +		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1.2257 +			if ( this->LockHWSurface(this, surface) < 0 ) {
  1.2258 +				return;
  1.2259 +			}
  1.2260 +		}
  1.2261 +		for ( row=0; row<surface->h; ++row ) {
  1.2262 +			pixels = (Uint8 *)surface->pixels+row*surface->pitch;
  1.2263 +			for ( col=0; col<surface->w; ++col, ++pixels ) {
  1.2264 +				*pixels = mapping[*pixels];
  1.2265 +			}
  1.2266 +		}
  1.2267 +		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1.2268 +			this->UnlockHWSurface(this, surface);
  1.2269 +		}
  1.2270 +		SDL_UpdateRect(surface, 0, 0, 0, 0);
  1.2271 +	}
  1.2272 +}
  1.2273 +void DX5_PaletteChanged(_THIS, HWND window)
  1.2274 +{
  1.2275 +	SDL_Palette *palette;
  1.2276 +	SDL_Color *saved = NULL;
  1.2277 +	HDC hdc;
  1.2278 +	int i;
  1.2279 +	PALETTEENTRY *entries;
  1.2280 +
  1.2281 +	/* This is true when the window is closing */
  1.2282 +	if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
  1.2283 +		return;
  1.2284 +
  1.2285 +	/* We need to get the colors as they were set */
  1.2286 +	palette = this->physpal;
  1.2287 +	if(!palette)
  1.2288 +	        palette = SDL_VideoSurface->format->palette;
  1.2289 +	if ( palette == NULL ) { /* Sometimes we don't have a palette */
  1.2290 +		return;
  1.2291 +	}
  1.2292 +	entries = (PALETTEENTRY *)alloca(palette->ncolors*sizeof(*entries));
  1.2293 +	hdc = GetDC(window);
  1.2294 +	GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
  1.2295 +	ReleaseDC(window, hdc);
  1.2296 +	if ( ! colorchange_expected ) {
  1.2297 +		saved = (SDL_Color *)alloca(palette->ncolors*sizeof(SDL_Color));
  1.2298 +		memcpy(saved, palette->colors, 
  1.2299 +					palette->ncolors*sizeof(SDL_Color));
  1.2300 +	}
  1.2301 +	for ( i=0; i<palette->ncolors; ++i ) {
  1.2302 +		palette->colors[i].r = entries[i].peRed;
  1.2303 +		palette->colors[i].g = entries[i].peGreen;
  1.2304 +		palette->colors[i].b = entries[i].peBlue;
  1.2305 +	}
  1.2306 +	if ( ! colorchange_expected ) {
  1.2307 +		Uint8 mapping[256];
  1.2308 +
  1.2309 +		memset(mapping, 0, sizeof(mapping));
  1.2310 +		for ( i=0; i<palette->ncolors; ++i ) {
  1.2311 +			mapping[i] = SDL_FindColor(palette,
  1.2312 +					saved[i].r, saved[i].g, saved[i].b);
  1.2313 +		}
  1.2314 +		DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
  1.2315 +	}
  1.2316 +	colorchange_expected = 0;
  1.2317 +
  1.2318 +	/* Notify all mapped surfaces of the change */
  1.2319 +	SDL_FormatChanged(SDL_VideoSurface);
  1.2320 +}
  1.2321 +
  1.2322 +/* Exported for the windows message loop only */
  1.2323 +void DX5_WinPAINT(_THIS, HDC hdc)
  1.2324 +{
  1.2325 +	SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  1.2326 +}