src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 02 Sep 2002 16:02:17 +0000
changeset 486 8b1c1ae7af11
parent 468 0b0c2e63eb27
child 525 f55cdaec12b9
permissions -rw-r--r--
Fixed a typo in a previous patch
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <malloc.h>
    31 #include <windows.h>
    32 #include "directx.h"
    33 
    34 /* Not yet in the mingw32 cross-compile headers */
    35 #ifndef CDS_FULLSCREEN
    36 #define CDS_FULLSCREEN	4
    37 #endif
    38 
    39 #include "SDL_error.h"
    40 #include "SDL_timer.h"
    41 #include "SDL_events.h"
    42 #include "SDL_syswm.h"
    43 #include "SDL_sysvideo.h"
    44 #include "SDL_RLEaccel_c.h"
    45 #include "SDL_blit.h"
    46 #include "SDL_pixels_c.h"
    47 #include "SDL_dx5video.h"
    48 #include "SDL_syswm_c.h"
    49 #include "SDL_sysmouse_c.h"
    50 #include "SDL_dx5events_c.h"
    51 #include "SDL_dx5yuv_c.h"
    52 #include "SDL_wingl_c.h"
    53 
    54 #ifdef _WIN32_WCE
    55 #define NO_CHANGEDISPLAYSETTINGS
    56 #endif
    57 #ifndef WS_MAXIMIZE
    58 #define WS_MAXIMIZE		0
    59 #endif
    60 #ifndef SWP_NOCOPYBITS
    61 #define SWP_NOCOPYBITS	0
    62 #endif
    63 #ifndef PC_NOCOLLAPSE
    64 #define PC_NOCOLLAPSE	0
    65 #endif
    66 
    67 
    68 /* DirectX function pointers for video and events */
    69 HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
    70 HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter);
    71 
    72 /* This is the rect EnumModes2 uses */
    73 struct DX5EnumRect {
    74 	SDL_Rect r;
    75 	struct DX5EnumRect* next;
    76 };
    77 static struct DX5EnumRect *enumlists[NUM_MODELISTS];
    78 
    79 /*
    80  * Experimentally determined values for c_cfDI* constants used in DirectX 5.0
    81  */
    82 
    83 /* Keyboard */
    84 
    85 static DIOBJECTDATAFORMAT KBD_fmt[] = {
    86 	{ &GUID_Key, 0, 0x8000000C, 0x00000000 },
    87 	{ &GUID_Key, 1, 0x8000010C, 0x00000000 },
    88 	{ &GUID_Key, 2, 0x8000020C, 0x00000000 },
    89 	{ &GUID_Key, 3, 0x8000030C, 0x00000000 },
    90 	{ &GUID_Key, 4, 0x8000040C, 0x00000000 },
    91 	{ &GUID_Key, 5, 0x8000050C, 0x00000000 },
    92 	{ &GUID_Key, 6, 0x8000060C, 0x00000000 },
    93 	{ &GUID_Key, 7, 0x8000070C, 0x00000000 },
    94 	{ &GUID_Key, 8, 0x8000080C, 0x00000000 },
    95 	{ &GUID_Key, 9, 0x8000090C, 0x00000000 },
    96 	{ &GUID_Key, 10, 0x80000A0C, 0x00000000 },
    97 	{ &GUID_Key, 11, 0x80000B0C, 0x00000000 },
    98 	{ &GUID_Key, 12, 0x80000C0C, 0x00000000 },
    99 	{ &GUID_Key, 13, 0x80000D0C, 0x00000000 },
   100 	{ &GUID_Key, 14, 0x80000E0C, 0x00000000 },
   101 	{ &GUID_Key, 15, 0x80000F0C, 0x00000000 },
   102 	{ &GUID_Key, 16, 0x8000100C, 0x00000000 },
   103 	{ &GUID_Key, 17, 0x8000110C, 0x00000000 },
   104 	{ &GUID_Key, 18, 0x8000120C, 0x00000000 },
   105 	{ &GUID_Key, 19, 0x8000130C, 0x00000000 },
   106 	{ &GUID_Key, 20, 0x8000140C, 0x00000000 },
   107 	{ &GUID_Key, 21, 0x8000150C, 0x00000000 },
   108 	{ &GUID_Key, 22, 0x8000160C, 0x00000000 },
   109 	{ &GUID_Key, 23, 0x8000170C, 0x00000000 },
   110 	{ &GUID_Key, 24, 0x8000180C, 0x00000000 },
   111 	{ &GUID_Key, 25, 0x8000190C, 0x00000000 },
   112 	{ &GUID_Key, 26, 0x80001A0C, 0x00000000 },
   113 	{ &GUID_Key, 27, 0x80001B0C, 0x00000000 },
   114 	{ &GUID_Key, 28, 0x80001C0C, 0x00000000 },
   115 	{ &GUID_Key, 29, 0x80001D0C, 0x00000000 },
   116 	{ &GUID_Key, 30, 0x80001E0C, 0x00000000 },
   117 	{ &GUID_Key, 31, 0x80001F0C, 0x00000000 },
   118 	{ &GUID_Key, 32, 0x8000200C, 0x00000000 },
   119 	{ &GUID_Key, 33, 0x8000210C, 0x00000000 },
   120 	{ &GUID_Key, 34, 0x8000220C, 0x00000000 },
   121 	{ &GUID_Key, 35, 0x8000230C, 0x00000000 },
   122 	{ &GUID_Key, 36, 0x8000240C, 0x00000000 },
   123 	{ &GUID_Key, 37, 0x8000250C, 0x00000000 },
   124 	{ &GUID_Key, 38, 0x8000260C, 0x00000000 },
   125 	{ &GUID_Key, 39, 0x8000270C, 0x00000000 },
   126 	{ &GUID_Key, 40, 0x8000280C, 0x00000000 },
   127 	{ &GUID_Key, 41, 0x8000290C, 0x00000000 },
   128 	{ &GUID_Key, 42, 0x80002A0C, 0x00000000 },
   129 	{ &GUID_Key, 43, 0x80002B0C, 0x00000000 },
   130 	{ &GUID_Key, 44, 0x80002C0C, 0x00000000 },
   131 	{ &GUID_Key, 45, 0x80002D0C, 0x00000000 },
   132 	{ &GUID_Key, 46, 0x80002E0C, 0x00000000 },
   133 	{ &GUID_Key, 47, 0x80002F0C, 0x00000000 },
   134 	{ &GUID_Key, 48, 0x8000300C, 0x00000000 },
   135 	{ &GUID_Key, 49, 0x8000310C, 0x00000000 },
   136 	{ &GUID_Key, 50, 0x8000320C, 0x00000000 },
   137 	{ &GUID_Key, 51, 0x8000330C, 0x00000000 },
   138 	{ &GUID_Key, 52, 0x8000340C, 0x00000000 },
   139 	{ &GUID_Key, 53, 0x8000350C, 0x00000000 },
   140 	{ &GUID_Key, 54, 0x8000360C, 0x00000000 },
   141 	{ &GUID_Key, 55, 0x8000370C, 0x00000000 },
   142 	{ &GUID_Key, 56, 0x8000380C, 0x00000000 },
   143 	{ &GUID_Key, 57, 0x8000390C, 0x00000000 },
   144 	{ &GUID_Key, 58, 0x80003A0C, 0x00000000 },
   145 	{ &GUID_Key, 59, 0x80003B0C, 0x00000000 },
   146 	{ &GUID_Key, 60, 0x80003C0C, 0x00000000 },
   147 	{ &GUID_Key, 61, 0x80003D0C, 0x00000000 },
   148 	{ &GUID_Key, 62, 0x80003E0C, 0x00000000 },
   149 	{ &GUID_Key, 63, 0x80003F0C, 0x00000000 },
   150 	{ &GUID_Key, 64, 0x8000400C, 0x00000000 },
   151 	{ &GUID_Key, 65, 0x8000410C, 0x00000000 },
   152 	{ &GUID_Key, 66, 0x8000420C, 0x00000000 },
   153 	{ &GUID_Key, 67, 0x8000430C, 0x00000000 },
   154 	{ &GUID_Key, 68, 0x8000440C, 0x00000000 },
   155 	{ &GUID_Key, 69, 0x8000450C, 0x00000000 },
   156 	{ &GUID_Key, 70, 0x8000460C, 0x00000000 },
   157 	{ &GUID_Key, 71, 0x8000470C, 0x00000000 },
   158 	{ &GUID_Key, 72, 0x8000480C, 0x00000000 },
   159 	{ &GUID_Key, 73, 0x8000490C, 0x00000000 },
   160 	{ &GUID_Key, 74, 0x80004A0C, 0x00000000 },
   161 	{ &GUID_Key, 75, 0x80004B0C, 0x00000000 },
   162 	{ &GUID_Key, 76, 0x80004C0C, 0x00000000 },
   163 	{ &GUID_Key, 77, 0x80004D0C, 0x00000000 },
   164 	{ &GUID_Key, 78, 0x80004E0C, 0x00000000 },
   165 	{ &GUID_Key, 79, 0x80004F0C, 0x00000000 },
   166 	{ &GUID_Key, 80, 0x8000500C, 0x00000000 },
   167 	{ &GUID_Key, 81, 0x8000510C, 0x00000000 },
   168 	{ &GUID_Key, 82, 0x8000520C, 0x00000000 },
   169 	{ &GUID_Key, 83, 0x8000530C, 0x00000000 },
   170 	{ &GUID_Key, 84, 0x8000540C, 0x00000000 },
   171 	{ &GUID_Key, 85, 0x8000550C, 0x00000000 },
   172 	{ &GUID_Key, 86, 0x8000560C, 0x00000000 },
   173 	{ &GUID_Key, 87, 0x8000570C, 0x00000000 },
   174 	{ &GUID_Key, 88, 0x8000580C, 0x00000000 },
   175 	{ &GUID_Key, 89, 0x8000590C, 0x00000000 },
   176 	{ &GUID_Key, 90, 0x80005A0C, 0x00000000 },
   177 	{ &GUID_Key, 91, 0x80005B0C, 0x00000000 },
   178 	{ &GUID_Key, 92, 0x80005C0C, 0x00000000 },
   179 	{ &GUID_Key, 93, 0x80005D0C, 0x00000000 },
   180 	{ &GUID_Key, 94, 0x80005E0C, 0x00000000 },
   181 	{ &GUID_Key, 95, 0x80005F0C, 0x00000000 },
   182 	{ &GUID_Key, 96, 0x8000600C, 0x00000000 },
   183 	{ &GUID_Key, 97, 0x8000610C, 0x00000000 },
   184 	{ &GUID_Key, 98, 0x8000620C, 0x00000000 },
   185 	{ &GUID_Key, 99, 0x8000630C, 0x00000000 },
   186 	{ &GUID_Key, 100, 0x8000640C, 0x00000000 },
   187 	{ &GUID_Key, 101, 0x8000650C, 0x00000000 },
   188 	{ &GUID_Key, 102, 0x8000660C, 0x00000000 },
   189 	{ &GUID_Key, 103, 0x8000670C, 0x00000000 },
   190 	{ &GUID_Key, 104, 0x8000680C, 0x00000000 },
   191 	{ &GUID_Key, 105, 0x8000690C, 0x00000000 },
   192 	{ &GUID_Key, 106, 0x80006A0C, 0x00000000 },
   193 	{ &GUID_Key, 107, 0x80006B0C, 0x00000000 },
   194 	{ &GUID_Key, 108, 0x80006C0C, 0x00000000 },
   195 	{ &GUID_Key, 109, 0x80006D0C, 0x00000000 },
   196 	{ &GUID_Key, 110, 0x80006E0C, 0x00000000 },
   197 	{ &GUID_Key, 111, 0x80006F0C, 0x00000000 },
   198 	{ &GUID_Key, 112, 0x8000700C, 0x00000000 },
   199 	{ &GUID_Key, 113, 0x8000710C, 0x00000000 },
   200 	{ &GUID_Key, 114, 0x8000720C, 0x00000000 },
   201 	{ &GUID_Key, 115, 0x8000730C, 0x00000000 },
   202 	{ &GUID_Key, 116, 0x8000740C, 0x00000000 },
   203 	{ &GUID_Key, 117, 0x8000750C, 0x00000000 },
   204 	{ &GUID_Key, 118, 0x8000760C, 0x00000000 },
   205 	{ &GUID_Key, 119, 0x8000770C, 0x00000000 },
   206 	{ &GUID_Key, 120, 0x8000780C, 0x00000000 },
   207 	{ &GUID_Key, 121, 0x8000790C, 0x00000000 },
   208 	{ &GUID_Key, 122, 0x80007A0C, 0x00000000 },
   209 	{ &GUID_Key, 123, 0x80007B0C, 0x00000000 },
   210 	{ &GUID_Key, 124, 0x80007C0C, 0x00000000 },
   211 	{ &GUID_Key, 125, 0x80007D0C, 0x00000000 },
   212 	{ &GUID_Key, 126, 0x80007E0C, 0x00000000 },
   213 	{ &GUID_Key, 127, 0x80007F0C, 0x00000000 },
   214 	{ &GUID_Key, 128, 0x8000800C, 0x00000000 },
   215 	{ &GUID_Key, 129, 0x8000810C, 0x00000000 },
   216 	{ &GUID_Key, 130, 0x8000820C, 0x00000000 },
   217 	{ &GUID_Key, 131, 0x8000830C, 0x00000000 },
   218 	{ &GUID_Key, 132, 0x8000840C, 0x00000000 },
   219 	{ &GUID_Key, 133, 0x8000850C, 0x00000000 },
   220 	{ &GUID_Key, 134, 0x8000860C, 0x00000000 },
   221 	{ &GUID_Key, 135, 0x8000870C, 0x00000000 },
   222 	{ &GUID_Key, 136, 0x8000880C, 0x00000000 },
   223 	{ &GUID_Key, 137, 0x8000890C, 0x00000000 },
   224 	{ &GUID_Key, 138, 0x80008A0C, 0x00000000 },
   225 	{ &GUID_Key, 139, 0x80008B0C, 0x00000000 },
   226 	{ &GUID_Key, 140, 0x80008C0C, 0x00000000 },
   227 	{ &GUID_Key, 141, 0x80008D0C, 0x00000000 },
   228 	{ &GUID_Key, 142, 0x80008E0C, 0x00000000 },
   229 	{ &GUID_Key, 143, 0x80008F0C, 0x00000000 },
   230 	{ &GUID_Key, 144, 0x8000900C, 0x00000000 },
   231 	{ &GUID_Key, 145, 0x8000910C, 0x00000000 },
   232 	{ &GUID_Key, 146, 0x8000920C, 0x00000000 },
   233 	{ &GUID_Key, 147, 0x8000930C, 0x00000000 },
   234 	{ &GUID_Key, 148, 0x8000940C, 0x00000000 },
   235 	{ &GUID_Key, 149, 0x8000950C, 0x00000000 },
   236 	{ &GUID_Key, 150, 0x8000960C, 0x00000000 },
   237 	{ &GUID_Key, 151, 0x8000970C, 0x00000000 },
   238 	{ &GUID_Key, 152, 0x8000980C, 0x00000000 },
   239 	{ &GUID_Key, 153, 0x8000990C, 0x00000000 },
   240 	{ &GUID_Key, 154, 0x80009A0C, 0x00000000 },
   241 	{ &GUID_Key, 155, 0x80009B0C, 0x00000000 },
   242 	{ &GUID_Key, 156, 0x80009C0C, 0x00000000 },
   243 	{ &GUID_Key, 157, 0x80009D0C, 0x00000000 },
   244 	{ &GUID_Key, 158, 0x80009E0C, 0x00000000 },
   245 	{ &GUID_Key, 159, 0x80009F0C, 0x00000000 },
   246 	{ &GUID_Key, 160, 0x8000A00C, 0x00000000 },
   247 	{ &GUID_Key, 161, 0x8000A10C, 0x00000000 },
   248 	{ &GUID_Key, 162, 0x8000A20C, 0x00000000 },
   249 	{ &GUID_Key, 163, 0x8000A30C, 0x00000000 },
   250 	{ &GUID_Key, 164, 0x8000A40C, 0x00000000 },
   251 	{ &GUID_Key, 165, 0x8000A50C, 0x00000000 },
   252 	{ &GUID_Key, 166, 0x8000A60C, 0x00000000 },
   253 	{ &GUID_Key, 167, 0x8000A70C, 0x00000000 },
   254 	{ &GUID_Key, 168, 0x8000A80C, 0x00000000 },
   255 	{ &GUID_Key, 169, 0x8000A90C, 0x00000000 },
   256 	{ &GUID_Key, 170, 0x8000AA0C, 0x00000000 },
   257 	{ &GUID_Key, 171, 0x8000AB0C, 0x00000000 },
   258 	{ &GUID_Key, 172, 0x8000AC0C, 0x00000000 },
   259 	{ &GUID_Key, 173, 0x8000AD0C, 0x00000000 },
   260 	{ &GUID_Key, 174, 0x8000AE0C, 0x00000000 },
   261 	{ &GUID_Key, 175, 0x8000AF0C, 0x00000000 },
   262 	{ &GUID_Key, 176, 0x8000B00C, 0x00000000 },
   263 	{ &GUID_Key, 177, 0x8000B10C, 0x00000000 },
   264 	{ &GUID_Key, 178, 0x8000B20C, 0x00000000 },
   265 	{ &GUID_Key, 179, 0x8000B30C, 0x00000000 },
   266 	{ &GUID_Key, 180, 0x8000B40C, 0x00000000 },
   267 	{ &GUID_Key, 181, 0x8000B50C, 0x00000000 },
   268 	{ &GUID_Key, 182, 0x8000B60C, 0x00000000 },
   269 	{ &GUID_Key, 183, 0x8000B70C, 0x00000000 },
   270 	{ &GUID_Key, 184, 0x8000B80C, 0x00000000 },
   271 	{ &GUID_Key, 185, 0x8000B90C, 0x00000000 },
   272 	{ &GUID_Key, 186, 0x8000BA0C, 0x00000000 },
   273 	{ &GUID_Key, 187, 0x8000BB0C, 0x00000000 },
   274 	{ &GUID_Key, 188, 0x8000BC0C, 0x00000000 },
   275 	{ &GUID_Key, 189, 0x8000BD0C, 0x00000000 },
   276 	{ &GUID_Key, 190, 0x8000BE0C, 0x00000000 },
   277 	{ &GUID_Key, 191, 0x8000BF0C, 0x00000000 },
   278 	{ &GUID_Key, 192, 0x8000C00C, 0x00000000 },
   279 	{ &GUID_Key, 193, 0x8000C10C, 0x00000000 },
   280 	{ &GUID_Key, 194, 0x8000C20C, 0x00000000 },
   281 	{ &GUID_Key, 195, 0x8000C30C, 0x00000000 },
   282 	{ &GUID_Key, 196, 0x8000C40C, 0x00000000 },
   283 	{ &GUID_Key, 197, 0x8000C50C, 0x00000000 },
   284 	{ &GUID_Key, 198, 0x8000C60C, 0x00000000 },
   285 	{ &GUID_Key, 199, 0x8000C70C, 0x00000000 },
   286 	{ &GUID_Key, 200, 0x8000C80C, 0x00000000 },
   287 	{ &GUID_Key, 201, 0x8000C90C, 0x00000000 },
   288 	{ &GUID_Key, 202, 0x8000CA0C, 0x00000000 },
   289 	{ &GUID_Key, 203, 0x8000CB0C, 0x00000000 },
   290 	{ &GUID_Key, 204, 0x8000CC0C, 0x00000000 },
   291 	{ &GUID_Key, 205, 0x8000CD0C, 0x00000000 },
   292 	{ &GUID_Key, 206, 0x8000CE0C, 0x00000000 },
   293 	{ &GUID_Key, 207, 0x8000CF0C, 0x00000000 },
   294 	{ &GUID_Key, 208, 0x8000D00C, 0x00000000 },
   295 	{ &GUID_Key, 209, 0x8000D10C, 0x00000000 },
   296 	{ &GUID_Key, 210, 0x8000D20C, 0x00000000 },
   297 	{ &GUID_Key, 211, 0x8000D30C, 0x00000000 },
   298 	{ &GUID_Key, 212, 0x8000D40C, 0x00000000 },
   299 	{ &GUID_Key, 213, 0x8000D50C, 0x00000000 },
   300 	{ &GUID_Key, 214, 0x8000D60C, 0x00000000 },
   301 	{ &GUID_Key, 215, 0x8000D70C, 0x00000000 },
   302 	{ &GUID_Key, 216, 0x8000D80C, 0x00000000 },
   303 	{ &GUID_Key, 217, 0x8000D90C, 0x00000000 },
   304 	{ &GUID_Key, 218, 0x8000DA0C, 0x00000000 },
   305 	{ &GUID_Key, 219, 0x8000DB0C, 0x00000000 },
   306 	{ &GUID_Key, 220, 0x8000DC0C, 0x00000000 },
   307 	{ &GUID_Key, 221, 0x8000DD0C, 0x00000000 },
   308 	{ &GUID_Key, 222, 0x8000DE0C, 0x00000000 },
   309 	{ &GUID_Key, 223, 0x8000DF0C, 0x00000000 },
   310 	{ &GUID_Key, 224, 0x8000E00C, 0x00000000 },
   311 	{ &GUID_Key, 225, 0x8000E10C, 0x00000000 },
   312 	{ &GUID_Key, 226, 0x8000E20C, 0x00000000 },
   313 	{ &GUID_Key, 227, 0x8000E30C, 0x00000000 },
   314 	{ &GUID_Key, 228, 0x8000E40C, 0x00000000 },
   315 	{ &GUID_Key, 229, 0x8000E50C, 0x00000000 },
   316 	{ &GUID_Key, 230, 0x8000E60C, 0x00000000 },
   317 	{ &GUID_Key, 231, 0x8000E70C, 0x00000000 },
   318 	{ &GUID_Key, 232, 0x8000E80C, 0x00000000 },
   319 	{ &GUID_Key, 233, 0x8000E90C, 0x00000000 },
   320 	{ &GUID_Key, 234, 0x8000EA0C, 0x00000000 },
   321 	{ &GUID_Key, 235, 0x8000EB0C, 0x00000000 },
   322 	{ &GUID_Key, 236, 0x8000EC0C, 0x00000000 },
   323 	{ &GUID_Key, 237, 0x8000ED0C, 0x00000000 },
   324 	{ &GUID_Key, 238, 0x8000EE0C, 0x00000000 },
   325 	{ &GUID_Key, 239, 0x8000EF0C, 0x00000000 },
   326 	{ &GUID_Key, 240, 0x8000F00C, 0x00000000 },
   327 	{ &GUID_Key, 241, 0x8000F10C, 0x00000000 },
   328 	{ &GUID_Key, 242, 0x8000F20C, 0x00000000 },
   329 	{ &GUID_Key, 243, 0x8000F30C, 0x00000000 },
   330 	{ &GUID_Key, 244, 0x8000F40C, 0x00000000 },
   331 	{ &GUID_Key, 245, 0x8000F50C, 0x00000000 },
   332 	{ &GUID_Key, 246, 0x8000F60C, 0x00000000 },
   333 	{ &GUID_Key, 247, 0x8000F70C, 0x00000000 },
   334 	{ &GUID_Key, 248, 0x8000F80C, 0x00000000 },
   335 	{ &GUID_Key, 249, 0x8000F90C, 0x00000000 },
   336 	{ &GUID_Key, 250, 0x8000FA0C, 0x00000000 },
   337 	{ &GUID_Key, 251, 0x8000FB0C, 0x00000000 },
   338 	{ &GUID_Key, 252, 0x8000FC0C, 0x00000000 },
   339 	{ &GUID_Key, 253, 0x8000FD0C, 0x00000000 },
   340 	{ &GUID_Key, 254, 0x8000FE0C, 0x00000000 },
   341 	{ &GUID_Key, 255, 0x8000FF0C, 0x00000000 },
   342 };
   343 
   344 const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
   345 
   346 
   347 /* Mouse */
   348 
   349 static DIOBJECTDATAFORMAT PTR_fmt[] = {
   350 	{ &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 },
   351 	{ &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 },
   352 	{ &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 },
   353 	{ NULL, 12, 0x00FFFF0C, 0x00000000 },
   354 	{ NULL, 13, 0x00FFFF0C, 0x00000000 },
   355 	{ NULL, 14, 0x80FFFF0C, 0x00000000 },
   356 	{ NULL, 15, 0x80FFFF0C, 0x00000000 },
   357 };
   358 
   359 const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
   360 
   361 
   362 /* Joystick */
   363 
   364 static DIOBJECTDATAFORMAT JOY_fmt[] = {
   365 	{ &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 },
   366 	{ &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 },
   367 	{ &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 },
   368 	{ &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 },
   369 	{ &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 },
   370 	{ &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 },
   371 	{ &GUID_Slider, 24, 0x80FFFF03, 0x00000100 },
   372 	{ &GUID_Slider, 28, 0x80FFFF03, 0x00000100 },
   373 	{ &GUID_POV, 32, 0x80FFFF10, 0x00000000 },
   374 	{ &GUID_POV, 36, 0x80FFFF10, 0x00000000 },
   375 	{ &GUID_POV, 40, 0x80FFFF10, 0x00000000 },
   376 	{ &GUID_POV, 44, 0x80FFFF10, 0x00000000 },
   377 	{ NULL, 48, 0x80FFFF0C, 0x00000000 },
   378 	{ NULL, 49, 0x80FFFF0C, 0x00000000 },
   379 	{ NULL, 50, 0x80FFFF0C, 0x00000000 },
   380 	{ NULL, 51, 0x80FFFF0C, 0x00000000 },
   381 	{ NULL, 52, 0x80FFFF0C, 0x00000000 },
   382 	{ NULL, 53, 0x80FFFF0C, 0x00000000 },
   383 	{ NULL, 54, 0x80FFFF0C, 0x00000000 },
   384 	{ NULL, 55, 0x80FFFF0C, 0x00000000 },
   385 	{ NULL, 56, 0x80FFFF0C, 0x00000000 },
   386 	{ NULL, 57, 0x80FFFF0C, 0x00000000 },
   387 	{ NULL, 58, 0x80FFFF0C, 0x00000000 },
   388 	{ NULL, 59, 0x80FFFF0C, 0x00000000 },
   389 	{ NULL, 60, 0x80FFFF0C, 0x00000000 },
   390 	{ NULL, 61, 0x80FFFF0C, 0x00000000 },
   391 	{ NULL, 62, 0x80FFFF0C, 0x00000000 },
   392 	{ NULL, 63, 0x80FFFF0C, 0x00000000 },
   393 	{ NULL, 64, 0x80FFFF0C, 0x00000000 },
   394 	{ NULL, 65, 0x80FFFF0C, 0x00000000 },
   395 	{ NULL, 66, 0x80FFFF0C, 0x00000000 },
   396 	{ NULL, 67, 0x80FFFF0C, 0x00000000 },
   397 	{ NULL, 68, 0x80FFFF0C, 0x00000000 },
   398 	{ NULL, 69, 0x80FFFF0C, 0x00000000 },
   399 	{ NULL, 70, 0x80FFFF0C, 0x00000000 },
   400 	{ NULL, 71, 0x80FFFF0C, 0x00000000 },
   401 	{ NULL, 72, 0x80FFFF0C, 0x00000000 },
   402 	{ NULL, 73, 0x80FFFF0C, 0x00000000 },
   403 	{ NULL, 74, 0x80FFFF0C, 0x00000000 },
   404 	{ NULL, 75, 0x80FFFF0C, 0x00000000 },
   405 	{ NULL, 76, 0x80FFFF0C, 0x00000000 },
   406 	{ NULL, 77, 0x80FFFF0C, 0x00000000 },
   407 	{ NULL, 78, 0x80FFFF0C, 0x00000000 },
   408 	{ NULL, 79, 0x80FFFF0C, 0x00000000 },
   409 };
   410 
   411 const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
   412 
   413 
   414 /* Initialization/Query functions */
   415 static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat);
   416 static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
   417 static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
   418 static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
   419 			 SDL_Color *colors);
   420 static int DX5_SetGammaRamp(_THIS, Uint16 *ramp);
   421 static int DX5_GetGammaRamp(_THIS, Uint16 *ramp);
   422 static void DX5_VideoQuit(_THIS);
   423 
   424 /* Hardware surface functions */
   425 static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface);
   426 static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
   427 static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
   428 static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
   429 static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
   430 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface);
   431 static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface);
   432 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface);
   433 static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface);
   434 
   435 static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
   436 				LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
   437 
   438 /* Windows message handling functions */
   439 static void DX5_RealizePalette(_THIS);
   440 static void DX5_PaletteChanged(_THIS, HWND window);
   441 static void DX5_WinPAINT(_THIS, HDC hdc);
   442 
   443 /* WinDIB driver functions for manipulating gamma ramps */
   444 extern int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
   445 extern int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
   446 extern void DIB_QuitGamma(_THIS);
   447 
   448 /* DX5 driver bootstrap functions */
   449 
   450 static int DX5_Available(void)
   451 {
   452 	HINSTANCE DInputDLL;
   453 	HINSTANCE DDrawDLL;
   454 	int dinput_ok;
   455 	int ddraw_ok;
   456 
   457 	/* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
   458 	dinput_ok = 0;
   459 	DInputDLL = LoadLibrary(TEXT("DINPUT.DLL"));
   460 	if ( DInputDLL != NULL ) {
   461 		dinput_ok = 1;
   462 	  	FreeLibrary(DInputDLL);
   463 	}
   464 	ddraw_ok = 0;
   465 	DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL"));
   466 	if ( DDrawDLL != NULL ) {
   467 	  HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
   468 	  LPDIRECTDRAW DDraw;
   469 
   470 	  /* Try to create a valid DirectDraw object */
   471 	  DDrawCreate = (void *)GetProcAddress(DDrawDLL, TEXT("DirectDrawCreate"));
   472 	  if ( (DDrawCreate != NULL)
   473 			&& !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) {
   474 	    if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
   475 							NULL, DDSCL_NORMAL)) ) {
   476 	      DDSURFACEDESC desc;
   477 	      LPDIRECTDRAWSURFACE  DDrawSurf;
   478 	      LPDIRECTDRAWSURFACE3 DDrawSurf3;
   479 
   480 	      /* Try to create a DirectDrawSurface3 object */
   481 	      memset(&desc, 0, sizeof(desc));
   482 	      desc.dwSize = sizeof(desc);
   483 	      desc.dwFlags = DDSD_CAPS;
   484 	      desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
   485 	      if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc,
   486 							&DDrawSurf, NULL)) ) {
   487 	        if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf,
   488 			&IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) {
   489 	          /* Yay! */
   490 		  ddraw_ok = 1;
   491 
   492 	          /* Clean up.. */
   493 	          IDirectDrawSurface3_Release(DDrawSurf3);
   494 	        }
   495 	        IDirectDrawSurface_Release(DDrawSurf);
   496 	      }
   497 	    }
   498 	    IDirectDraw_Release(DDraw);
   499 	  }
   500 	  FreeLibrary(DDrawDLL);
   501 	}
   502 	return(dinput_ok && ddraw_ok);
   503 }
   504 
   505 /* Functions for loading the DirectX functions dynamically */
   506 static HINSTANCE DDrawDLL = NULL;
   507 static HINSTANCE DInputDLL = NULL;
   508 
   509 static void DX5_Unload(void)
   510 {
   511 	if ( DDrawDLL != NULL ) {
   512 		FreeLibrary(DDrawDLL);
   513 		DDrawCreate = NULL;
   514 		DDrawDLL = NULL;
   515 	}
   516 	if ( DInputDLL != NULL ) {
   517 		FreeLibrary(DInputDLL);
   518 		DInputCreate = NULL;
   519 		DInputDLL = NULL;
   520 	}
   521 }
   522 static int DX5_Load(void)
   523 {
   524 	int status;
   525 
   526 	DX5_Unload();
   527 	DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL"));
   528 	if ( DDrawDLL != NULL ) {
   529 		DDrawCreate = (void *)GetProcAddress(DDrawDLL,
   530 					TEXT("DirectDrawCreate"));
   531 	}
   532 	DInputDLL = LoadLibrary(TEXT("DINPUT.DLL"));
   533 	if ( DInputDLL != NULL ) {
   534 		DInputCreate = (void *)GetProcAddress(DInputDLL,
   535 					TEXT("DirectInputCreateA"));
   536 	}
   537 	if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) {
   538 		status = 0;
   539 	} else {
   540 		DX5_Unload();
   541 		status = -1;
   542 	}
   543 	return status;
   544 }
   545 
   546 static void DX5_DeleteDevice(SDL_VideoDevice *this)
   547 {
   548 	/* Free DirectDraw object */
   549 	if ( ddraw2 != NULL ) {
   550 		IDirectDraw2_Release(ddraw2);
   551 	}
   552 	DX5_Unload();
   553 	if ( this ) {
   554 		if ( this->hidden ) {
   555 			free(this->hidden);
   556 		}
   557 		if ( this->gl_data ) {
   558 			free(this->gl_data);
   559 		}
   560 		free(this);
   561 	}
   562 }
   563 
   564 static SDL_VideoDevice *DX5_CreateDevice(int devindex)
   565 {
   566 	SDL_VideoDevice *device;
   567 
   568 	/* Load DirectX */
   569 	if ( DX5_Load() < 0 ) {
   570 		return(NULL);
   571 	}
   572 
   573 	/* Initialize all variables that we clean on shutdown */
   574 	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   575 	if ( device ) {
   576 		memset(device, 0, (sizeof *device));
   577 		device->hidden = (struct SDL_PrivateVideoData *)
   578 				malloc((sizeof *device->hidden));
   579 		device->gl_data = (struct SDL_PrivateGLData *)
   580 				malloc((sizeof *device->gl_data));
   581 	}
   582 	if ( (device == NULL) || (device->hidden == NULL) ||
   583 		                 (device->gl_data == NULL) ) {
   584 		SDL_OutOfMemory();
   585 		DX5_DeleteDevice(device);
   586 		return(NULL);
   587 	}
   588 	memset(device->hidden, 0, (sizeof *device->hidden));
   589 	memset(device->gl_data, 0, (sizeof *device->gl_data));
   590 
   591 	/* Set the function pointers */
   592 	device->VideoInit = DX5_VideoInit;
   593 	device->ListModes = DX5_ListModes;
   594 	device->SetVideoMode = DX5_SetVideoMode;
   595 	device->UpdateMouse = WIN_UpdateMouse;
   596 	device->CreateYUVOverlay = DX5_CreateYUVOverlay;
   597 	device->SetColors = DX5_SetColors;
   598 	device->UpdateRects = NULL;
   599 	device->VideoQuit = DX5_VideoQuit;
   600 	device->AllocHWSurface = DX5_AllocHWSurface;
   601 	device->CheckHWBlit = DX5_CheckHWBlit;
   602 	device->FillHWRect = DX5_FillHWRect;
   603 	device->SetHWColorKey = DX5_SetHWColorKey;
   604 	device->SetHWAlpha = DX5_SetHWAlpha;
   605 	device->LockHWSurface = DX5_LockHWSurface;
   606 	device->UnlockHWSurface = DX5_UnlockHWSurface;
   607 	device->FlipHWSurface = DX5_FlipHWSurface;
   608 	device->FreeHWSurface = DX5_FreeHWSurface;
   609 	device->SetGammaRamp = DX5_SetGammaRamp;
   610 	device->GetGammaRamp = DX5_GetGammaRamp;
   611 #ifdef HAVE_OPENGL
   612 	device->GL_LoadLibrary = WIN_GL_LoadLibrary;
   613 	device->GL_GetProcAddress = WIN_GL_GetProcAddress;
   614 	device->GL_GetAttribute = WIN_GL_GetAttribute;
   615 	device->GL_MakeCurrent = WIN_GL_MakeCurrent;
   616 	device->GL_SwapBuffers = WIN_GL_SwapBuffers;
   617 #endif
   618 	device->SetCaption = WIN_SetWMCaption;
   619 	device->SetIcon = WIN_SetWMIcon;
   620 	device->IconifyWindow = WIN_IconifyWindow;
   621 	device->GrabInput = WIN_GrabInput;
   622 	device->GetWMInfo = WIN_GetWMInfo;
   623 	device->FreeWMCursor = WIN_FreeWMCursor;
   624 	device->CreateWMCursor = WIN_CreateWMCursor;
   625 	device->ShowWMCursor = WIN_ShowWMCursor;
   626 	device->WarpWMCursor = WIN_WarpWMCursor;
   627 	device->CheckMouseMode = WIN_CheckMouseMode;
   628 	device->InitOSKeymap = DX5_InitOSKeymap;
   629 	device->PumpEvents = DX5_PumpEvents;
   630 
   631 	/* Set up the windows message handling functions */
   632 	WIN_RealizePalette = DX5_RealizePalette;
   633 	WIN_PaletteChanged = DX5_PaletteChanged;
   634 	WIN_WinPAINT = DX5_WinPAINT;
   635 	HandleMessage = DX5_HandleMessage;
   636 
   637 	device->free = DX5_DeleteDevice;
   638 
   639 	/* We're finally ready */
   640 	return device;
   641 }
   642 
   643 VideoBootStrap DIRECTX_bootstrap = {
   644 	"directx", "Win95/98/2000 DirectX",
   645 	DX5_Available, DX5_CreateDevice
   646 };
   647 
   648 static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata)
   649 {
   650 	SDL_VideoDevice *this = (SDL_VideoDevice *)udata;
   651 	struct DX5EnumRect *enumrect;
   652 #if defined(NONAMELESSUNION)
   653 	int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
   654 #else
   655 	int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
   656 #endif
   657 
   658 	switch (bpp)  {
   659 		case 8:
   660 		case 16:
   661 		case 24:
   662 		case 32:
   663 			bpp /= 8; --bpp;
   664 			++SDL_nummodes[bpp];
   665 			enumrect = (struct DX5EnumRect*)malloc(sizeof(struct DX5EnumRect));
   666 			if ( !enumrect ) {
   667 				SDL_OutOfMemory();
   668 				return(DDENUMRET_CANCEL);
   669 			}
   670 			enumrect->r.x = 0;
   671 			enumrect->r.y = 0;
   672 			enumrect->r.w = (Uint16)desc->dwWidth;
   673 			enumrect->r.h = (Uint16)desc->dwHeight;
   674 			enumrect->next = enumlists[bpp];
   675 			enumlists[bpp] = enumrect;
   676 			break;
   677 	}
   678 
   679 
   680 	return(DDENUMRET_OK);
   681 }
   682 
   683 void SetDDerror(const char *function, int code)
   684 {
   685 	static char *error;
   686 	static char  errbuf[1024];
   687 
   688 	errbuf[0] = 0;
   689 	switch (code) {
   690 		case DDERR_GENERIC:
   691 			error = "Undefined error!";
   692 			break;
   693 		case DDERR_EXCEPTION:
   694 			error = "Exception encountered";
   695 			break;
   696 		case DDERR_INVALIDOBJECT:
   697 			error = "Invalid object";
   698 			break;
   699 		case DDERR_INVALIDPARAMS:
   700 			error = "Invalid parameters";
   701 			break;
   702 		case DDERR_NOTFOUND:
   703 			error = "Object not found";
   704 			break;
   705 		case DDERR_INVALIDRECT:
   706 			error = "Invalid rectangle";
   707 			break;
   708 		case DDERR_INVALIDCAPS:
   709 			error = "Invalid caps member";
   710 			break;
   711 		case DDERR_INVALIDPIXELFORMAT:
   712 			error = "Invalid pixel format";
   713 			break;
   714 		case DDERR_OUTOFMEMORY:
   715 			error = "Out of memory";
   716 			break;
   717 		case DDERR_OUTOFVIDEOMEMORY:
   718 			error = "Out of video memory";
   719 			break;
   720 		case DDERR_SURFACEBUSY:
   721 			error = "Surface busy";
   722 			break;
   723 		case DDERR_SURFACELOST:
   724 			error = "Surface was lost";
   725 			break;
   726 		case DDERR_WASSTILLDRAWING:
   727 			error = "DirectDraw is still drawing";
   728 			break;
   729 		case DDERR_INVALIDSURFACETYPE:
   730 			error = "Invalid surface type";
   731 			break;
   732 		case DDERR_NOEXCLUSIVEMODE:
   733 			error = "Not in exclusive access mode";
   734 			break;
   735 		case DDERR_NOPALETTEATTACHED:
   736 			error = "No palette attached";
   737 			break;
   738 		case DDERR_NOPALETTEHW:
   739 			error = "No palette hardware";
   740 			break;
   741 		case DDERR_NOT8BITCOLOR:
   742 			error = "Not 8-bit color";
   743 			break;
   744 		case DDERR_EXCLUSIVEMODEALREADYSET:
   745 			error = "Exclusive mode was already set";
   746 			break;
   747 		case DDERR_HWNDALREADYSET:
   748 			error = "Window handle already set";
   749 			break;
   750 		case DDERR_HWNDSUBCLASSED:
   751 			error = "Window handle is subclassed";
   752 			break;
   753 		case DDERR_NOBLTHW:
   754 			error = "No blit hardware";
   755 			break;
   756 		case DDERR_IMPLICITLYCREATED:
   757 			error = "Surface was implicitly created";
   758 			break;
   759 		case DDERR_INCOMPATIBLEPRIMARY:
   760 			error = "Incompatible primary surface";
   761 			break;
   762 		case DDERR_NOCOOPERATIVELEVELSET:
   763 			error = "No cooperative level set";
   764 			break;
   765 		case DDERR_NODIRECTDRAWHW:
   766 			error = "No DirectDraw hardware";
   767 			break;
   768 		case DDERR_NOEMULATION:
   769 			error = "No emulation available";
   770 			break;
   771 		case DDERR_NOFLIPHW:
   772 			error = "No flip hardware";
   773 			break;
   774 		case DDERR_NOTFLIPPABLE:
   775 			error = "Surface not flippable";
   776 			break;
   777 		case DDERR_PRIMARYSURFACEALREADYEXISTS:
   778 			error = "Primary surface already exists";
   779 			break;
   780 		case DDERR_UNSUPPORTEDMODE:
   781 			error = "Unsupported mode";
   782 			break;
   783 		case DDERR_WRONGMODE:
   784 			error = "Surface created in different mode";
   785 			break;
   786 		case DDERR_UNSUPPORTED:
   787 			error = "Operation not supported";
   788 			break;
   789 		case E_NOINTERFACE:
   790 			error = "Interface not present";
   791 			break;
   792 		default:
   793 			sprintf(errbuf, "%s: Unknown DirectDraw error: 0x%x",
   794 								function, code);
   795 			break;
   796 	}
   797 	if ( ! errbuf[0] ) {
   798 		sprintf(errbuf, "%s: %s", function, error);
   799 	}
   800 	SDL_SetError("%s", errbuf);
   801 	return;
   802 }
   803 
   804 
   805 static int DX5_UpdateVideoInfo(_THIS)
   806 {
   807 	/* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
   808 #if DIRECTDRAW_VERSION <= 0x300
   809 #error Your version of DirectX must be greater than or equal to 5.0
   810 #endif
   811 #ifndef IDirectDrawGammaControl_SetGammaRamp
   812 	/*if gamma is undefined then we really have directx <= 0x500*/
   813 	DDCAPS DDCaps;
   814 #else
   815 	DDCAPS_DX5 DDCaps;
   816 #endif
   817 	HRESULT result;
   818 
   819 	/* Fill in our hardware acceleration capabilities */
   820 	memset(&DDCaps, 0, sizeof(DDCaps));
   821 	DDCaps.dwSize = sizeof(DDCaps);
   822 	result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL);
   823 	if ( result != DD_OK ) {
   824 		SetDDerror("DirectDraw2::GetCaps", result);
   825 		return(-1);
   826 	}
   827 	this->info.hw_available = 1;
   828 	if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) {
   829 		this->info.blit_hw = 1;
   830 	}
   831 	if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
   832 	     ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
   833 		this->info.blit_hw_CC = 1;
   834 	}
   835 	if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
   836 		/* This is only for alpha channel, and DirectX 6
   837 		   doesn't support 2D alpha blits yet, so set it 0
   838 		 */
   839 		this->info.blit_hw_A = 0;
   840 	}
   841 	if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
   842 		this->info.blit_sw = 1;
   843 		/* This isn't necessarily true, but the HEL will cover us */
   844 		this->info.blit_sw_CC = this->info.blit_hw_CC;
   845 		this->info.blit_sw_A = this->info.blit_hw_A;
   846 	}
   847 	if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
   848 		this->info.blit_fill = 1;
   849 	}
   850 
   851 	/* Find out how much video memory is available */
   852 	{ DDSCAPS ddsCaps;
   853 	  DWORD total_mem;
   854 		ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
   855 		result = IDirectDraw2_GetAvailableVidMem(ddraw2,
   856 						&ddsCaps, &total_mem, NULL);
   857 		if ( result != DD_OK ) {
   858 			total_mem = DDCaps.dwVidMemTotal; 
   859 		}
   860 		this->info.video_mem = total_mem/1024;
   861 	}
   862 	return(0);
   863 }
   864 
   865 int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
   866 {
   867 	HRESULT result;
   868 	LPDIRECTDRAW ddraw;
   869 	int i, j;
   870 	HDC hdc;
   871 
   872 	/* Intialize everything */
   873 	ddraw2 = NULL;
   874 	SDL_primary = NULL;
   875 	SDL_clipper = NULL;
   876 	SDL_palette = NULL;
   877 	for ( i=0; i<NUM_MODELISTS; ++i ) {
   878 		SDL_nummodes[i] = 0;
   879 		SDL_modelist[i] = NULL;
   880 		SDL_modeindex[i] = 0;
   881 	}
   882 	colorchange_expected = 0;
   883 
   884 	/* Create the window */
   885 	if ( DX5_CreateWindow(this) < 0 ) {
   886 		return(-1);
   887 	}
   888 #ifndef DISABLE_AUDIO
   889 	DX5_SoundFocus(SDL_Window);
   890 #endif
   891 
   892 	/* Create the DirectDraw object */
   893 	result = DDrawCreate(NULL, &ddraw, NULL);
   894 	if ( result != DD_OK ) {
   895 		SetDDerror("DirectDrawCreate", result);
   896 		return(-1);
   897 	}
   898 	result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
   899 							(LPVOID *)&ddraw2);
   900 	IDirectDraw_Release(ddraw);
   901 	if ( result != DD_OK ) {
   902 		SetDDerror("DirectDraw::QueryInterface", result);
   903 		return(-1);
   904 	}
   905 
   906 	/* Determine the screen depth */
   907 	hdc = GetDC(SDL_Window);
   908 	vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
   909 					GetDeviceCaps(hdc,BITSPIXEL);
   910 	ReleaseDC(SDL_Window, hdc);
   911 
   912 	/* Enumerate the available fullscreen modes */
   913 	for ( i=0; i<NUM_MODELISTS; ++i )
   914 		enumlists[i] = NULL;
   915 
   916 	result = IDirectDraw2_EnumDisplayModes(ddraw2,0,NULL,this,EnumModes2);
   917 	if ( result != DD_OK ) {
   918 		SetDDerror("DirectDraw2::EnumDisplayModes", result);
   919 		return(-1);
   920 	}
   921 	for ( i=0; i<NUM_MODELISTS; ++i ) {
   922 		struct DX5EnumRect *rect;
   923 		SDL_modelist[i] = (SDL_Rect **)
   924 				malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
   925 		if ( SDL_modelist[i] == NULL ) {
   926 			SDL_OutOfMemory();
   927 			return(-1);
   928 		}
   929 		for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
   930 			SDL_modelist[i][j]=(SDL_Rect *)rect;
   931 		}
   932 		SDL_modelist[i][j] = NULL;
   933 	}
   934 	
   935 	/* Fill in some window manager capabilities */
   936 	this->info.wm_available = 1;
   937 
   938 	/* Fill in the video hardware capabilities */
   939 	DX5_UpdateVideoInfo(this);
   940 
   941 	return(0);
   942 }
   943 
   944 SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   945 {
   946 	int bpp;
   947 
   948 	bpp = format->BitsPerPixel;
   949 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   950 		/* FIXME:  No support for 1 bpp or 4 bpp formats */
   951 		switch (bpp) {  /* Does windows support other BPP? */
   952 			case 8:
   953 			case 16:
   954 			case 24:
   955 			case 32:
   956 				bpp = (bpp/8)-1;
   957 				if ( SDL_nummodes[bpp] > 0 )
   958 					return(SDL_modelist[bpp]);
   959 				/* Fall through */
   960 			default:
   961 				return((SDL_Rect **)0);
   962 		}
   963 	} else {
   964 		if ( this->screen->format->BitsPerPixel == bpp ) {
   965 			return((SDL_Rect **)-1);
   966 		} else {
   967 			return((SDL_Rect **)0);
   968 		}
   969 	}
   970 }
   971 
   972 /* Various screen update functions available */
   973 static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
   974 static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
   975 
   976 SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
   977 				int width, int height, int bpp, Uint32 flags)
   978 {
   979 	SDL_Surface *video;
   980 	HRESULT result;
   981 	DWORD sharemode;
   982 	DWORD style;
   983 	const DWORD directstyle =
   984 			(WS_POPUP);
   985 	const DWORD windowstyle = 
   986 			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
   987 	const DWORD resizestyle =
   988 			(WS_THICKFRAME|WS_MAXIMIZEBOX);
   989 	DDSURFACEDESC ddsd;
   990 	LPDIRECTDRAWSURFACE  dd_surface1;
   991 	LPDIRECTDRAWSURFACE3 dd_surface3;
   992 	BOOL was_visible;
   993 
   994 #ifdef DDRAW_DEBUG
   995  fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
   996 #endif
   997 	/* See whether or not we should center the window */
   998 	was_visible = IsWindowVisible(SDL_Window);
   999 
  1000 	/* Clean up any previous DirectDraw surfaces */
  1001 	if ( current->hwdata ) {
  1002 		this->FreeHWSurface(this, current);
  1003 		current->hwdata = NULL;
  1004 	}
  1005 	if ( SDL_primary != NULL ) {
  1006 		IDirectDrawSurface3_Release(SDL_primary);
  1007 		SDL_primary = NULL;
  1008 	}
  1009 
  1010 #ifndef NO_CHANGEDISPLAYSETTINGS
  1011 	/* Unset any previous OpenGL fullscreen mode */
  1012 	if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  1013 	                       (SDL_OPENGL|SDL_FULLSCREEN) ) {
  1014 		ChangeDisplaySettings(NULL, 0);
  1015 	}
  1016 #endif
  1017 
  1018 	/* Clean up any GL context that may be hanging around */
  1019 	if ( current->flags & SDL_OPENGL ) {
  1020 		WIN_GL_ShutDown(this);
  1021 	}
  1022 
  1023 	/* If we are setting a GL mode, use GDI, not DirectX (yuck) */
  1024 	if ( flags & SDL_OPENGL ) {
  1025 		RECT bounds;
  1026 		int x, y;
  1027 		Uint32 Rmask, Gmask, Bmask;
  1028 
  1029 		/* Recalculate the bitmasks if necessary */
  1030 		if ( bpp == current->format->BitsPerPixel ) {
  1031 			video = current;
  1032 		} else {
  1033 			switch (bpp) {
  1034 			    case 15:
  1035 			    case 16:
  1036 				if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
  1037 					/* 5-5-5 */
  1038 					Rmask = 0x00007c00;
  1039 					Gmask = 0x000003e0;
  1040 					Bmask = 0x0000001f;
  1041 				} else {
  1042 					/* 5-6-5 */
  1043 					Rmask = 0x0000f800;
  1044 					Gmask = 0x000007e0;
  1045 					Bmask = 0x0000001f;
  1046 				}
  1047 				break;
  1048 			    case 24:
  1049 			    case 32:
  1050 				/* GDI defined as 8-8-8 */
  1051 				Rmask = 0x00ff0000;
  1052 				Gmask = 0x0000ff00;
  1053 				Bmask = 0x000000ff;
  1054 				break;
  1055 			    default:
  1056 				Rmask = 0x00000000;
  1057 				Gmask = 0x00000000;
  1058 				Bmask = 0x00000000;
  1059 				break;
  1060 			}
  1061 			video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
  1062 			                             Rmask, Gmask, Bmask, 0);
  1063 			if ( video == NULL ) {
  1064 				SDL_OutOfMemory();
  1065 				return(NULL);
  1066 			}
  1067 		}
  1068 
  1069 		/* Fill in part of the video surface */
  1070 		video->flags = 0;	/* Clear flags */
  1071 		video->w = width;
  1072 		video->h = height;
  1073 		video->pitch = SDL_CalculatePitch(video);
  1074 
  1075 #ifndef NO_CHANGEDISPLAYSETTINGS
  1076 		/* Set fullscreen mode if appropriate.
  1077 		   Ugh, since our list of valid video modes comes from
  1078 		   the DirectX driver, we may not actually be able to
  1079 		   change to the desired resolution here.
  1080 		   FIXME: Should we do a closest match?
  1081 		 */
  1082 		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1083 			DEVMODE settings;
  1084 
  1085 			memset(&settings, 0, sizeof(DEVMODE));
  1086 			settings.dmSize = sizeof(DEVMODE);
  1087 			settings.dmBitsPerPel = video->format->BitsPerPixel;
  1088 			settings.dmPelsWidth = width;
  1089 			settings.dmPelsHeight = height;
  1090 			settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  1091 			if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
  1092 				video->flags |= SDL_FULLSCREEN;
  1093 				SDL_fullscreen_mode = settings;
  1094 			}
  1095 		}
  1096 #endif /* !NO_CHANGEDISPLAYSETTINGS */
  1097 
  1098 		style = GetWindowLong(SDL_Window, GWL_STYLE);
  1099 		style &= ~(resizestyle|WS_MAXIMIZE);
  1100 		if ( video->flags & SDL_FULLSCREEN ) {
  1101 			style &= ~windowstyle;
  1102 			style |= directstyle;
  1103 		} else {
  1104 			if ( flags & SDL_NOFRAME ) {
  1105 				style &= ~windowstyle;
  1106 				style |= directstyle;
  1107 				video->flags |= SDL_NOFRAME;
  1108 			} else {
  1109 				style &= ~directstyle;
  1110 				style |= windowstyle;
  1111 				if ( flags & SDL_RESIZABLE ) {
  1112 					style |= resizestyle;
  1113 					video->flags |= SDL_RESIZABLE;
  1114 				}
  1115 			}
  1116 #if WS_MAXIMIZE
  1117 			if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1118 #endif
  1119 		}
  1120 		SetWindowLong(SDL_Window, GWL_STYLE, style);
  1121 
  1122 		/* Resize the window (copied from SDL WinDIB driver) */
  1123 		if ( SDL_windowid == NULL ) {
  1124 			HWND top;
  1125 			UINT swp_flags;
  1126 
  1127 			SDL_resizing = 1;
  1128 			bounds.top    = 0;
  1129 			bounds.bottom = video->h;
  1130 			bounds.left   = 0;
  1131 			bounds.right  = video->w;
  1132 			AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
  1133 			width = bounds.right-bounds.left;
  1134 			height = bounds.bottom-bounds.top;
  1135 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1136 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1137 			if ( y < 0 ) { /* Cover up title bar for more client area */
  1138 				y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1139 			}
  1140 			swp_flags = (SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
  1141 			if ( was_visible && !(video->flags & SDL_FULLSCREEN) ) {
  1142 				swp_flags |= SWP_NOMOVE;
  1143 			}
  1144 			if ( video->flags & SDL_FULLSCREEN ) {
  1145 				top = HWND_TOPMOST;
  1146 			} else {
  1147 				top = HWND_NOTOPMOST;
  1148 			}
  1149 			SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
  1150 			SDL_resizing = 0;
  1151 			SetForegroundWindow(SDL_Window);
  1152 		}
  1153 
  1154 		/* Set up for OpenGL */
  1155 		if ( WIN_GL_SetupWindow(this) < 0 ) {
  1156 			return(NULL);
  1157 		}
  1158 		video->flags |= SDL_OPENGL;
  1159 		return(video);
  1160 	}
  1161 
  1162 	/* Set the appropriate window style */
  1163 	style = GetWindowLong(SDL_Window, GWL_STYLE);
  1164 	style &= ~(resizestyle|WS_MAXIMIZE);
  1165 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1166 		style &= ~windowstyle;
  1167 		style |= directstyle;
  1168 	} else {
  1169 		if ( flags & SDL_NOFRAME ) {
  1170 			style &= ~windowstyle;
  1171 			style |= directstyle;
  1172 		} else {
  1173 			style &= ~directstyle;
  1174 			style |= windowstyle;
  1175 			if ( flags & SDL_RESIZABLE ) {
  1176 				style |= resizestyle;
  1177 			}
  1178 		}
  1179 #if WS_MAXIMIZE
  1180 		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1181 #endif
  1182 	}
  1183 	SetWindowLong(SDL_Window, GWL_STYLE, style);
  1184 
  1185 	/* Set DirectDraw sharing mode.. exclusive when fullscreen */
  1186 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1187 		sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
  1188 	} else {
  1189 		sharemode = DDSCL_NORMAL;
  1190 	}
  1191 	result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
  1192 	if ( result != DD_OK ) {
  1193 		SetDDerror("DirectDraw2::SetCooperativeLevel", result);
  1194 		return(NULL);
  1195 	}
  1196 
  1197 	/* Set the display mode, if we are in fullscreen mode */
  1198 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1199 		/* Cover up desktop during mode change */
  1200 		SDL_resizing = 1;
  1201 		SetWindowPos(SDL_Window, NULL, 0, 0, 
  1202 			GetSystemMetrics(SM_CXSCREEN),
  1203 			GetSystemMetrics(SM_CYSCREEN),
  1204 			(SWP_NOCOPYBITS | SWP_NOZORDER));
  1205 		SDL_resizing = 0;
  1206 		ShowWindow(SDL_Window, SW_SHOW);
  1207 		while ( GetForegroundWindow() != SDL_Window ) {
  1208 			SetForegroundWindow(SDL_Window);
  1209 			SDL_Delay(100);
  1210 		}
  1211 		result = IDirectDraw2_SetDisplayMode(ddraw2, width, height,
  1212 								bpp, 0, 0);
  1213 		if ( result != DD_OK ) {
  1214 			/* We couldn't set fullscreen mode, try window */
  1215 			return(DX5_SetVideoMode(this, current,
  1216 				width, height, bpp, flags & ~SDL_FULLSCREEN)); 
  1217 		}
  1218 		DX5_DInputReset(this, 1);
  1219 	} else {
  1220 		DX5_DInputReset(this, 0);
  1221 	}
  1222 	DX5_UpdateVideoInfo(this);
  1223 
  1224 	/* Create a primary DirectDraw surface */
  1225 	memset(&ddsd, 0, sizeof(ddsd));
  1226 	ddsd.dwSize = sizeof(ddsd);
  1227 	ddsd.dwFlags = DDSD_CAPS;
  1228 	ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
  1229 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1230 		/* There's no windowed double-buffering */
  1231 		flags &= ~SDL_DOUBLEBUF;
  1232 	}
  1233 	if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1234 		ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
  1235 		ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1236 		ddsd.dwBackBufferCount = 1;
  1237 	}
  1238 	result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
  1239 	if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
  1240 		ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
  1241 		ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1242 		ddsd.dwBackBufferCount = 0;
  1243 		result = IDirectDraw2_CreateSurface(ddraw2,
  1244 						&ddsd, &dd_surface1, NULL); 
  1245 	}
  1246 	if ( result != DD_OK ) {
  1247 		SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
  1248 		return(NULL);
  1249 	}
  1250 	result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1251 			&IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
  1252 	if ( result != DD_OK ) {
  1253 		SetDDerror("DirectDrawSurface::QueryInterface", result);
  1254 		return(NULL);
  1255 	}
  1256 	result = IDirectDrawSurface_Release(dd_surface1);
  1257 	if ( result != DD_OK ) {
  1258 		SetDDerror("DirectDrawSurface::Release", result);
  1259 		return(NULL);
  1260 	}
  1261 
  1262 	/* Get the format of the primary DirectDraw surface */
  1263 	memset(&ddsd, 0, sizeof(ddsd));
  1264 	ddsd.dwSize = sizeof(ddsd);
  1265 	ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
  1266 	result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
  1267 	if ( result != DD_OK ) {
  1268 		SetDDerror("DirectDrawSurface::Release", result);
  1269 		return(NULL);
  1270 	}
  1271 	if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
  1272 		SDL_SetError("Primary DDRAW surface is not RGB format");
  1273 		return(NULL);
  1274 	}
  1275 
  1276 	/* Free old palette and create a new one if we're in 8-bit mode */
  1277 	if ( SDL_palette != NULL ) {
  1278 		IDirectDrawPalette_Release(SDL_palette);
  1279 		SDL_palette = NULL;
  1280 	}
  1281 #if defined(NONAMELESSUNION)
  1282 	if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
  1283 #else
  1284 	if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
  1285 #endif
  1286 		int i;
  1287 
  1288 		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1289 			/* We have access to the entire palette */
  1290 			for ( i=0; i<256; ++i ) {
  1291 				SDL_colors[i].peFlags =
  1292 						(PC_NOCOLLAPSE|PC_RESERVED);
  1293 				SDL_colors[i].peRed = 0;
  1294 				SDL_colors[i].peGreen = 0;
  1295 				SDL_colors[i].peBlue = 0;
  1296 			}
  1297 		} else {
  1298 			/* First 10 colors are reserved by Windows */
  1299 			for ( i=0; i<10; ++i ) {
  1300 				SDL_colors[i].peFlags = PC_EXPLICIT;
  1301 				SDL_colors[i].peRed = i;
  1302 				SDL_colors[i].peGreen = 0;
  1303 				SDL_colors[i].peBlue = 0;
  1304 			}
  1305 			for ( i=10; i<(10+236); ++i ) {
  1306 				SDL_colors[i].peFlags = PC_NOCOLLAPSE;
  1307 				SDL_colors[i].peRed = 0;
  1308 				SDL_colors[i].peGreen = 0;
  1309 				SDL_colors[i].peBlue = 0;
  1310 			}
  1311 			/* Last 10 colors are reserved by Windows */
  1312 			for ( i=246; i<256; ++i ) {
  1313 				SDL_colors[i].peFlags = PC_EXPLICIT;
  1314 				SDL_colors[i].peRed = i;
  1315 				SDL_colors[i].peGreen = 0;
  1316 				SDL_colors[i].peBlue = 0;
  1317 			}
  1318 		}
  1319 		result = IDirectDraw2_CreatePalette(ddraw2,
  1320 		     			(DDPCAPS_8BIT|DDPCAPS_ALLOW256),
  1321 						SDL_colors, &SDL_palette, NULL);
  1322 		if ( result != DD_OK ) {
  1323 			SetDDerror("DirectDraw2::CreatePalette", result);
  1324 			return(NULL);
  1325 		}
  1326 		result = IDirectDrawSurface3_SetPalette(SDL_primary,
  1327 								SDL_palette);
  1328 		if ( result != DD_OK ) {
  1329 			SetDDerror("DirectDrawSurface3::SetPalette", result);
  1330 			return(NULL);
  1331 		}
  1332 	}
  1333 
  1334 	/* Create our video surface using the same pixel format */
  1335 	video = current;
  1336 	if ( (width != video->w) || (height != video->h)
  1337 			|| (video->format->BitsPerPixel != 
  1338 #if defined(NONAMELESSUNION)
  1339 				ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
  1340 #else
  1341 				ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
  1342 #endif
  1343 		SDL_FreeSurface(video);
  1344 		video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
  1345 #if defined(NONAMELESSUNION)
  1346 				ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
  1347 					ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1348 					ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1349 					ddsd.ddpfPixelFormat.u4.dwBBitMask,
  1350 #else
  1351 				ddsd.ddpfPixelFormat.dwRGBBitCount,
  1352 					ddsd.ddpfPixelFormat.dwRBitMask,
  1353 					ddsd.ddpfPixelFormat.dwGBitMask,
  1354 					ddsd.ddpfPixelFormat.dwBBitMask,
  1355 #endif
  1356 								0);
  1357 		if ( video == NULL ) {
  1358 			SDL_OutOfMemory();
  1359 			return(NULL);
  1360 		}
  1361 		video->w = width;
  1362 		video->h = height;
  1363 		video->pitch = 0;
  1364 	}
  1365 	video->flags = 0;	/* Clear flags */
  1366 
  1367 	/* If not fullscreen, locking is possible, but it doesn't do what 
  1368 	   the caller really expects -- if the locked surface is written to,
  1369 	   the appropriate portion of the entire screen is modified, not 
  1370 	   the application window, as we would like.
  1371 	   Note that it is still possible to write directly to display
  1372 	   memory, but the application must respect the clip list of
  1373 	   the surface.  There might be some odd timing interactions
  1374 	   involving clip list updates and background refreshing as
  1375 	   Windows moves other windows across our window.
  1376 	   We currently don't support this, even though it might be a
  1377 	   good idea since BeOS has an implementation of BDirectWindow
  1378 	   that does the same thing.  This would be most useful for
  1379 	   applications that do complete screen updates every frame.
  1380 	    -- Fixme?
  1381 	*/
  1382 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1383 		/* Necessary if we're going from fullscreen to window */
  1384 		if ( video->pixels == NULL ) {
  1385 			video->pitch = (width*video->format->BytesPerPixel);
  1386 			/* Pitch needs to be QWORD (8-byte) aligned */
  1387 			video->pitch = (video->pitch + 7) & ~7;
  1388 			video->pixels = (void *)malloc(video->h*video->pitch);
  1389 			if ( video->pixels == NULL ) {
  1390 				if ( video != current ) {
  1391 					SDL_FreeSurface(video);
  1392 				}
  1393 				SDL_OutOfMemory();
  1394 				return(NULL);
  1395 			}
  1396 		}
  1397 		dd_surface3 = NULL;
  1398 #if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */
  1399 		if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1400 			video->flags |= SDL_HWSURFACE;
  1401 		} else {
  1402 			video->flags |= SDL_SWSURFACE;
  1403 		}
  1404 #else
  1405 		video->flags |= SDL_SWSURFACE;
  1406 #endif
  1407 		if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
  1408 			video->flags |= SDL_RESIZABLE;
  1409 		}
  1410 		if ( flags & SDL_NOFRAME ) {
  1411 			video->flags |= SDL_NOFRAME;
  1412 		}
  1413 	} else {
  1414 		/* Necessary if we're going from window to fullscreen */
  1415 		if ( video->pixels != NULL ) {
  1416 			free(video->pixels);
  1417 			video->pixels = NULL;
  1418 		}
  1419 		dd_surface3 = SDL_primary;
  1420 		video->flags |= SDL_HWSURFACE;
  1421 	}
  1422 
  1423 	/* See if the primary surface has double-buffering enabled */
  1424 	if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
  1425 		video->flags |= SDL_DOUBLEBUF;
  1426 	}
  1427 
  1428 	/* Allocate the SDL surface associated with the primary surface */
  1429 	if ( DX5_AllocDDSurface(this, video, dd_surface3,
  1430 	                        video->flags&SDL_HWSURFACE) < 0 ) {
  1431 		if ( video != current ) {
  1432 			SDL_FreeSurface(video);
  1433 		}
  1434 		return(NULL);
  1435 	}
  1436 
  1437 	/* Use the appropriate blitting function */
  1438 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1439 		video->flags |= SDL_FULLSCREEN;
  1440 		if ( video->format->palette != NULL ) {
  1441 			video->flags |= SDL_HWPALETTE;
  1442 		}
  1443 		this->UpdateRects = DX5_DirectUpdate;
  1444 	} else {
  1445 		this->UpdateRects = DX5_WindowUpdate;
  1446 	}
  1447 
  1448 	/* Make our window the proper size, set the clipper, then show it */
  1449 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1450 		RECT bounds;
  1451 		int  x, y;
  1452 		UINT swp_flags;
  1453 
  1454 		/* Create and set a clipper on our primary surface */
  1455 		if ( SDL_clipper == NULL ) {
  1456 			result = IDirectDraw2_CreateClipper(ddraw2,
  1457 							0, &SDL_clipper, NULL);
  1458 			if ( result != DD_OK ) {
  1459 				if ( video != current ) {
  1460 					SDL_FreeSurface(video);
  1461 				}
  1462 				SetDDerror("DirectDraw2::CreateClipper",result);
  1463 				return(NULL);
  1464 			}
  1465 		}
  1466 		result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
  1467 		if ( result != DD_OK ) {
  1468 			if ( video != current ) {
  1469 				SDL_FreeSurface(video);
  1470 			}
  1471 			SetDDerror("DirectDrawClipper::SetHWnd", result);
  1472 			return(NULL);
  1473 		}
  1474 		result = IDirectDrawSurface3_SetClipper(SDL_primary,
  1475 								SDL_clipper);
  1476 		if ( result != DD_OK ) {
  1477 			if ( video != current ) {
  1478 				SDL_FreeSurface(video);
  1479 			}
  1480 			SetDDerror("DirectDrawSurface3::SetClipper", result);
  1481 			return(NULL);
  1482 		}
  1483 
  1484 		/* Set the size of the window, centering and adjusting */
  1485 		SDL_resizing = 1;
  1486 		bounds.top    = 0;
  1487 		bounds.bottom = video->h;
  1488 		bounds.left   = 0;
  1489 		bounds.right  = video->w;
  1490 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
  1491 		width = bounds.right-bounds.left;
  1492 		height = bounds.bottom-bounds.top;
  1493 		x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1494 		y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1495 		if ( y < 0 ) { /* Cover up title bar for more client area */
  1496 			y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1497 		}
  1498 		swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER);
  1499 		if ( was_visible ) {
  1500 			swp_flags |= SWP_NOMOVE;
  1501 		}
  1502 		SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
  1503 		SDL_resizing = 0;
  1504 	}
  1505 	ShowWindow(SDL_Window, SW_SHOW);
  1506 	SetForegroundWindow(SDL_Window);
  1507 
  1508 	/* We're live! */
  1509 	return(video);
  1510 }
  1511 
  1512 struct private_hwdata {
  1513 	LPDIRECTDRAWSURFACE3 dd_surface;
  1514 	LPDIRECTDRAWSURFACE3 dd_writebuf;
  1515 };
  1516 
  1517 static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
  1518 				LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
  1519 {
  1520 	LPDIRECTDRAWSURFACE  dd_surface1;
  1521 	LPDIRECTDRAWSURFACE3 dd_surface3;
  1522 	DDSURFACEDESC ddsd;
  1523 	HRESULT result;
  1524 
  1525 	/* Clear the hardware flag, in case we fail */
  1526 	surface->flags &= ~flag;
  1527 
  1528 	/* Allocate the hardware acceleration data */
  1529 	surface->hwdata = (struct private_hwdata *)
  1530 					malloc(sizeof(*surface->hwdata));
  1531 	if ( surface->hwdata == NULL ) {
  1532 		SDL_OutOfMemory();
  1533 		return(-1);
  1534 	}
  1535 	dd_surface3 = NULL;
  1536 
  1537 	/* Set up the surface description */
  1538 	memset(&ddsd, 0, sizeof(ddsd));
  1539 	ddsd.dwSize = sizeof(ddsd);
  1540 	ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
  1541 					DDSD_PITCH|DDSD_PIXELFORMAT);
  1542 	ddsd.dwWidth = surface->w;
  1543 	ddsd.dwHeight= surface->h;
  1544 #if defined(NONAMELESSUNION)
  1545 	ddsd.u1.lPitch = surface->pitch;
  1546 #else
  1547 	ddsd.lPitch = surface->pitch;
  1548 #endif
  1549 	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1550 		ddsd.ddsCaps.dwCaps =
  1551 				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
  1552 	} else {
  1553 		ddsd.ddsCaps.dwCaps =
  1554 				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
  1555 	}
  1556 	ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  1557 	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  1558 	if ( surface->format->palette ) {
  1559 		ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  1560 	}
  1561 #if defined(NONAMELESSUNION)
  1562 	ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
  1563 	ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
  1564 	ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
  1565 	ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
  1566 #else
  1567 	ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
  1568 	ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
  1569 	ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
  1570 	ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
  1571 #endif
  1572 
  1573 	/* Create the DirectDraw video surface */
  1574 	if ( requested != NULL ) {
  1575 		dd_surface3 = requested;
  1576 	} else {
  1577 		result = IDirectDraw2_CreateSurface(ddraw2,
  1578 						&ddsd, &dd_surface1, NULL); 
  1579 		if ( result != DD_OK ) {
  1580 			SetDDerror("DirectDraw2::CreateSurface", result);
  1581 			goto error_end;
  1582 		}
  1583 		result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1584 			&IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
  1585 		IDirectDrawSurface_Release(dd_surface1);
  1586 		if ( result != DD_OK ) {
  1587 			SetDDerror("DirectDrawSurface::QueryInterface", result);
  1588 			goto error_end;
  1589 		}
  1590 	}
  1591 
  1592 	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1593 		/* Check to see whether the surface actually ended up
  1594 		   in video memory, and fail if not.  We expect the
  1595 		   surfaces we create here to actually be in hardware!
  1596 		*/
  1597 		result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
  1598 		if ( result != DD_OK ) {
  1599 			SetDDerror("DirectDrawSurface3::GetCaps", result);
  1600 			goto error_end;
  1601 		}
  1602 		if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
  1603 							DDSCAPS_VIDEOMEMORY ) {
  1604 			SDL_SetError("No room in video memory");
  1605 			goto error_end;
  1606 		}
  1607 	} else {
  1608 		/* Try to hook our surface memory */
  1609 		ddsd.dwFlags = DDSD_LPSURFACE;
  1610 		ddsd.lpSurface = surface->pixels;
  1611 		result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
  1612 								&ddsd, 0);
  1613 		if ( result != DD_OK ) {
  1614 			SetDDerror("DirectDraw2::SetSurfaceDesc", result);
  1615 			goto error_end;
  1616 		}
  1617 	
  1618 	}
  1619 
  1620 	/* Make sure the surface format was set properly */
  1621 	memset(&ddsd, 0, sizeof(ddsd));
  1622 	ddsd.dwSize = sizeof(ddsd);
  1623 	result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  1624 		&ddsd, (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1625 	if ( result != DD_OK ) {
  1626 		SetDDerror("DirectDrawSurface3::Lock", result);
  1627 		goto error_end;
  1628 	}
  1629 	IDirectDrawSurface3_Unlock(dd_surface3, NULL);
  1630 
  1631 	if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1632 		if ( ddsd.lpSurface != surface->pixels ) {
  1633 			SDL_SetError("DDraw didn't use SDL surface memory");
  1634 			goto error_end;
  1635 		}
  1636 		if (
  1637 #if defined(NONAMELESSUNION)
  1638 			ddsd.u1.lPitch
  1639 #else
  1640 			ddsd.lPitch
  1641 #endif
  1642 				 != (LONG)surface->pitch ) {
  1643 			SDL_SetError("DDraw created surface with wrong pitch");
  1644 			goto error_end;
  1645 		}
  1646 	} else {
  1647 #if defined(NONAMELESSUNION)
  1648 		surface->pitch = (Uint16)ddsd.u1.lPitch;
  1649 #else
  1650 		surface->pitch = (Uint16)ddsd.lPitch;
  1651 #endif
  1652 	}
  1653 #if defined(NONAMELESSUNION)
  1654 	if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
  1655 					surface->format->BitsPerPixel) ||
  1656 	     (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
  1657 	     (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
  1658 	     (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
  1659 #else
  1660 	if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
  1661 					surface->format->BitsPerPixel) ||
  1662 	     (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
  1663 	     (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
  1664 	     (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
  1665 #endif
  1666 		SDL_SetError("DDraw didn't use SDL surface description");
  1667 		goto error_end;
  1668 	}
  1669 	if ( (ddsd.dwWidth != (DWORD)surface->w) ||
  1670 		(ddsd.dwHeight != (DWORD)surface->h) ) {
  1671 		SDL_SetError("DDraw created surface with wrong size");
  1672 		goto error_end;
  1673 	}
  1674 
  1675 	/* Set the surface private data */
  1676 	surface->flags |= flag;
  1677 	surface->hwdata->dd_surface = dd_surface3;
  1678 	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1679 		LPDIRECTDRAWSURFACE3 dd_writebuf;
  1680 
  1681 		ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  1682 		result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
  1683 						&ddsd.ddsCaps, &dd_writebuf);
  1684 		if ( result != DD_OK ) {
  1685 			SetDDerror("DirectDrawSurface3::GetAttachedSurface",
  1686 								result);
  1687 		} else {
  1688 			dd_surface3 = dd_writebuf;
  1689 		}
  1690 	}
  1691 	surface->hwdata->dd_writebuf = dd_surface3;
  1692 
  1693 	/* We're ready to go! */
  1694 	return(0);
  1695 
  1696 	/* Okay, so goto's are cheesy, but there are so many possible
  1697 	   errors in this function, and the cleanup is the same in 
  1698 	   every single case.  Is there a better way, other than deeply
  1699 	   nesting the code?
  1700 	*/
  1701 error_end:
  1702 	if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
  1703 		IDirectDrawSurface_Release(dd_surface3);
  1704 	}
  1705 	free(surface->hwdata);
  1706 	surface->hwdata = NULL;
  1707 	return(-1);
  1708 }
  1709 
  1710 static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
  1711 {
  1712 	/* DDraw limitation -- you need to set cooperative level first */
  1713 	if ( SDL_primary == NULL ) {
  1714 		SDL_SetError("You must set a non-GL video mode first");
  1715 		return(-1);
  1716 	}
  1717 	return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
  1718 }
  1719 
  1720 #ifdef DDRAW_DEBUG
  1721 void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
  1722 {
  1723 	DDSURFACEDESC ddsd;
  1724 
  1725 	/* Lock and load! */
  1726 	memset(&ddsd, 0, sizeof(ddsd));
  1727 	ddsd.dwSize = sizeof(ddsd);
  1728 	if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
  1729 			(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
  1730 		return;
  1731 	}
  1732 	IDirectDrawSurface3_Unlock(surface, NULL);
  1733 	
  1734 	fprintf(stderr, "%s:\n", title);
  1735 	fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
  1736 		ddsd.dwWidth, ddsd.dwHeight,
  1737 		(flags & SDL_HWSURFACE) ? "hardware" : "software",
  1738 #if defined(NONAMELESSUNION)
  1739 		ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
  1740 #else
  1741 		ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
  1742 #endif
  1743 	fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
  1744 #if defined(NONAMELESSUNION)
  1745 	     		ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1746 	     		ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1747 	     		ddsd.ddpfPixelFormat.u4.dwBBitMask);
  1748 #else
  1749 	     		ddsd.ddpfPixelFormat.dwRBitMask,
  1750 	     		ddsd.ddpfPixelFormat.dwGBitMask,
  1751 	     		ddsd.ddpfPixelFormat.dwBBitMask);
  1752 #endif
  1753 }
  1754 #endif /* DDRAW_DEBUG */
  1755 
  1756 static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
  1757 					SDL_Surface *dst, SDL_Rect *dstrect)
  1758 {
  1759 	LPDIRECTDRAWSURFACE3 src_surface;
  1760 	LPDIRECTDRAWSURFACE3 dst_surface;
  1761 	DWORD flags;
  1762 	RECT rect;
  1763 	HRESULT result;
  1764 
  1765 	/* Set it up.. the desination must have a DDRAW surface */
  1766 	src_surface = src->hwdata->dd_writebuf;
  1767 	dst_surface = dst->hwdata->dd_writebuf;
  1768 	rect.top    = (LONG)srcrect->y;
  1769 	rect.bottom = (LONG)srcrect->y+srcrect->h;
  1770 	rect.left   = (LONG)srcrect->x;
  1771 	rect.right  = (LONG)srcrect->x+srcrect->w;
  1772 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
  1773 		flags = DDBLTFAST_SRCCOLORKEY;
  1774 	else
  1775 		flags = DDBLTFAST_NOCOLORKEY;
  1776 	/* FIXME:  We can remove this flag for _really_ fast blit queuing,
  1777 	           but it will affect the return values of locks and flips.
  1778 	 */
  1779 	flags |= DDBLTFAST_WAIT;
  1780 
  1781 	/* Do the blit! */
  1782 	result = IDirectDrawSurface3_BltFast(dst_surface,
  1783 			dstrect->x, dstrect->y, src_surface, &rect, flags);
  1784 	if ( result != DD_OK ) {
  1785 		if ( result == DDERR_SURFACELOST ) {
  1786 			result = IDirectDrawSurface3_Restore(src_surface);
  1787 			result = IDirectDrawSurface3_Restore(dst_surface);
  1788 			/* The surfaces need to be reloaded with artwork */
  1789 			SDL_SetError("Blit surfaces were lost, reload them");
  1790 			return(-2);
  1791 		}
  1792 		SetDDerror("IDirectDrawSurface3::BltFast", result);
  1793 #ifdef DDRAW_DEBUG
  1794  fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
  1795  fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
  1796 		(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
  1797 					dstrect->x, dstrect->y);
  1798   PrintSurface("SRC", src_surface, src->flags);
  1799   PrintSurface("DST", dst_surface, dst->flags);
  1800  fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
  1801 		rect.left, rect.top, rect.right, rect.bottom);
  1802 #endif
  1803 		/* Unexpected error, fall back to software blit */
  1804 		return(src->map->sw_blit(src, srcrect, dst, dstrect));
  1805 	}
  1806 	return(0);
  1807 }
  1808 
  1809 static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
  1810 {
  1811 	int accelerated;
  1812 
  1813 	/* We need to have a DDraw surface for HW blits */
  1814 	if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1815 		/* Allocate a DDraw surface for the blit */
  1816 		if ( src->hwdata == NULL ) {
  1817 			DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
  1818 		}
  1819 	}
  1820 	if ( src->hwdata == NULL ) {
  1821 		return(0);
  1822 	}
  1823 
  1824 	/* Set initial acceleration on */
  1825 	src->flags |= SDL_HWACCEL;
  1826 
  1827 	/* Set the surface attributes */
  1828 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  1829 		if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
  1830 			src->flags &= ~SDL_HWACCEL;
  1831 		}
  1832 	}
  1833 	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  1834 		if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
  1835 			src->flags &= ~SDL_HWACCEL;
  1836 		}
  1837 	}
  1838 
  1839 	/* Check to see if final surface blit is accelerated */
  1840 	accelerated = !!(src->flags & SDL_HWACCEL);
  1841 	if ( accelerated ) {
  1842 #ifdef DDRAW_DEBUG
  1843   fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
  1844 #endif
  1845 		src->map->hw_blit = DX5_HWAccelBlit;
  1846 	}
  1847 	return(accelerated);
  1848 }
  1849 
  1850 static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1851 {
  1852 	LPDIRECTDRAWSURFACE3 dst_surface;
  1853 	RECT area;
  1854 	DDBLTFX bltfx;
  1855 	HRESULT result;
  1856 
  1857 #ifdef DDRAW_DEBUG
  1858  fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
  1859 #endif
  1860 	dst_surface = dst->hwdata->dd_writebuf;
  1861 	area.top    = (LONG)dstrect->y;
  1862 	area.bottom = (LONG)dstrect->y+dstrect->h;
  1863 	area.left   = (LONG)dstrect->x;
  1864 	area.right  = (LONG)dstrect->x+dstrect->w;
  1865 	bltfx.dwSize = sizeof(bltfx);
  1866 #if defined(NONAMELESSUNION)
  1867 	bltfx.u5.dwFillColor = color;
  1868 #else
  1869 	bltfx.dwFillColor = color;
  1870 #endif
  1871 	result = IDirectDrawSurface3_Blt(dst_surface,
  1872 			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1873 	if ( result == DDERR_SURFACELOST ) {
  1874 		IDirectDrawSurface3_Restore(dst_surface);
  1875 		result = IDirectDrawSurface3_Blt(dst_surface,
  1876 			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1877 	}
  1878 	if ( result != DD_OK ) {
  1879 		SetDDerror("IDirectDrawSurface3::Blt", result);
  1880 		return(-1);
  1881 	}
  1882 	return(0);
  1883 }
  1884 
  1885 static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
  1886 {
  1887 	DDCOLORKEY colorkey;
  1888 	HRESULT result;
  1889 
  1890 	/* Set the surface colorkey */
  1891 	colorkey.dwColorSpaceLowValue = key;
  1892 	colorkey.dwColorSpaceHighValue = key;
  1893 	result = IDirectDrawSurface3_SetColorKey(
  1894 			surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
  1895 	if ( result != DD_OK ) {
  1896 		SetDDerror("IDirectDrawSurface3::SetColorKey", result);
  1897 		return(-1);
  1898 	}
  1899 	return(0);
  1900 }
  1901 static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
  1902 {
  1903 	return(-1);
  1904 }
  1905 
  1906 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
  1907 {
  1908 	HRESULT result;
  1909 	LPDIRECTDRAWSURFACE3 dd_surface;
  1910 	DDSURFACEDESC ddsd;
  1911 
  1912 	/* Lock and load! */
  1913 	dd_surface = surface->hwdata->dd_writebuf;
  1914 	memset(&ddsd, 0, sizeof(ddsd));
  1915 	ddsd.dwSize = sizeof(ddsd);
  1916 	result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  1917 					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1918 	if ( result == DDERR_SURFACELOST ) {
  1919 		result = IDirectDrawSurface3_Restore(
  1920 						surface->hwdata->dd_surface);
  1921 		result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
  1922 					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1923 	}
  1924 	if ( result != DD_OK ) {
  1925 		SetDDerror("DirectDrawSurface3::Lock", result);
  1926 		return(-1);
  1927 	}
  1928 	/* Pitch might have changed -- recalculate pitch and offset */
  1929 #if defined(NONAMELESSUNION)
  1930 	if ( surface->pitch != ddsd.u1.lPitch ) {
  1931 		surface->pitch = ddsd.u1.lPitch;
  1932 #else
  1933 	if ( surface->pitch != ddsd.lPitch ) {
  1934 		surface->pitch = (Uint16)ddsd.lPitch;
  1935 #endif
  1936 		surface->offset =
  1937 			((ddsd.dwHeight-surface->h)/2)*surface->pitch +
  1938 			((ddsd.dwWidth-surface->w)/2)*
  1939 					surface->format->BytesPerPixel;
  1940 	}
  1941 	surface->pixels = ddsd.lpSurface;
  1942 	return(0);
  1943 }
  1944 
  1945 static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
  1946 {
  1947 	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  1948 	surface->pixels = NULL;
  1949 }
  1950 
  1951 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
  1952 {
  1953 	HRESULT result;
  1954 	LPDIRECTDRAWSURFACE3 dd_surface;
  1955 
  1956 	dd_surface = surface->hwdata->dd_surface;
  1957 	result = IDirectDrawSurface3_Flip(dd_surface, NULL, 0);
  1958 	if ( result == DDERR_SURFACELOST ) {
  1959 		result = IDirectDrawSurface3_Restore(
  1960 						surface->hwdata->dd_surface);
  1961 		result = IDirectDrawSurface3_Flip(dd_surface, NULL, 0);
  1962 	}
  1963 	if ( result != DD_OK ) {
  1964 		SetDDerror("DirectDrawSurface3::Flip", result);
  1965 		return(-1);
  1966 	}
  1967 	return(0);
  1968 }
  1969 
  1970 static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
  1971 {
  1972 	if ( surface->hwdata ) {
  1973 		if ( surface->hwdata->dd_surface != SDL_primary ) {
  1974 			IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
  1975 		}
  1976 		free(surface->hwdata);
  1977 		surface->hwdata = NULL;
  1978 	}
  1979 }
  1980 
  1981 void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
  1982 {
  1983 	HRESULT result;
  1984 	int i;
  1985 	RECT src, dst;
  1986 
  1987 	for ( i=0; i<numrects; ++i ) {
  1988 		src.top    = (LONG)rects[i].y;
  1989 		src.bottom = (LONG)rects[i].y+rects[i].h;
  1990 		src.left   = (LONG)rects[i].x;
  1991 		src.right  = (LONG)rects[i].x+rects[i].w;
  1992 		dst.top    = SDL_bounds.top+src.top;
  1993 		dst.left   = SDL_bounds.left+src.left;
  1994 		dst.bottom = SDL_bounds.top+src.bottom;
  1995 		dst.right  = SDL_bounds.left+src.right;
  1996 		result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  1997 					this->screen->hwdata->dd_surface, &src,
  1998 							DDBLT_WAIT, NULL);
  1999 		/* Doh!  Check for lost surface and restore it */
  2000 		if ( result == DDERR_SURFACELOST ) {
  2001 			IDirectDrawSurface3_Restore(SDL_primary);
  2002 			IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  2003 					this->screen->hwdata->dd_surface, &src,
  2004 							DDBLT_WAIT, NULL);
  2005 		}
  2006 	}
  2007 }
  2008 
  2009 void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
  2010 {
  2011 }
  2012 
  2013 /* Compress a full palette into the limited number of colors given to us
  2014    by windows.
  2015 
  2016    The "best" way to do this is to sort the colors by diversity and place
  2017    the most diverse colors into the limited palette.  Unfortunately this
  2018    results in widely varying colors being displayed in the interval during
  2019    which the windows palette has been set, and the mapping of the shadow
  2020    surface to the new palette.  This is especially noticeable during fades.
  2021 
  2022    To deal with this problem, we can copy a predetermined portion of the
  2023    full palette, and use that as the limited palette.  This allows colors
  2024    to fade smoothly as the remapping is very similar on each palette change.
  2025    Unfortunately, this breaks applications which partition the palette into
  2026    distinct and widely varying areas, expecting all colors to be available.
  2027 
  2028    I'm making them both available, chosen at compile time.
  2029    If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
  2030    otherwise the sort-by-diversity algorithm will be used.
  2031 */
  2032 #define SIMPLE_COMPRESSION
  2033 #define CS_CS_DIST(A, B) ({						\
  2034 	int r = (A.r - B.r);						\
  2035 	int g = (A.g - B.g);						\
  2036 	int b = (A.b - B.b);						\
  2037 	(r*r + g*g + b*b);						\
  2038 })
  2039 static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
  2040 {
  2041 #ifdef SIMPLE_COMPRESSION
  2042 	int i, j;
  2043 #else
  2044 	static SDL_Color zero = { 0, 0, 0, 0 };
  2045 	int i, j;
  2046 	int max, dist;
  2047 	int prev, next;
  2048 	int *pool;
  2049 	int *seen, *order;
  2050 #endif
  2051 
  2052 	/* Does this happen? */
  2053 	if ( maxcolors > ncolors ) {
  2054 		maxcolors = ncolors;
  2055 	}
  2056 
  2057 #ifdef SIMPLE_COMPRESSION
  2058 	/* Just copy the first "maxcolors" colors */
  2059 	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  2060 		SDL_colors[j].peRed = colors[i].r;
  2061 		SDL_colors[j].peGreen = colors[i].g;
  2062 		SDL_colors[j].peBlue = colors[i].b;
  2063 	}
  2064 #else
  2065 	/* Allocate memory for the arrays we use */
  2066 	pool = (int *)alloca(2*ncolors*sizeof(int));
  2067 	if ( pool == NULL ) {
  2068 		/* No worries, just return */;
  2069 		return;
  2070 	}
  2071 	seen = pool;
  2072 	memset(seen, 0, ncolors*sizeof(int));
  2073 	order = pool+ncolors;
  2074 
  2075 	/* Start with the brightest color */
  2076 	max = 0;
  2077 	for ( i=0; i<ncolors; ++i ) {
  2078 		dist = CS_CS_DIST(zero, colors[i]);
  2079 		if ( dist >= max ) {
  2080 			max = dist;
  2081 			next = i;
  2082 		}
  2083 	}
  2084 	j = 0;
  2085 	order[j++] = next;
  2086 	seen[next] = 1;
  2087 	prev = next;
  2088 
  2089 	/* Keep going through all the colors */
  2090 	while ( j < maxcolors ) {
  2091 		max = 0;
  2092 		for ( i=0; i<ncolors; ++i ) {
  2093 			if ( seen[i] ) {
  2094 				continue;
  2095 			}
  2096 			dist = CS_CS_DIST(colors[i], colors[prev]);
  2097 			if ( dist >= max ) {
  2098 				max = dist;
  2099 				next = i;
  2100 			}
  2101 		}
  2102 		order[j++] = next;
  2103 		seen[next] = 1;
  2104 		prev = next;
  2105 	}
  2106 
  2107 	/* Compress the colors to the palette */
  2108 	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  2109 		SDL_colors[j].peRed = colors[order[i]].r;
  2110 		SDL_colors[j].peGreen = colors[order[i]].g;
  2111 		SDL_colors[j].peBlue = colors[order[i]].b;
  2112 	}
  2113 #endif /* SIMPLE_COMPRESSION */
  2114 }
  2115 
  2116 /* Set the system colormap in both fullscreen and windowed modes */
  2117 int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  2118 {
  2119 	int i;
  2120 	int alloct_all;
  2121 
  2122 	/* Copy palette colors into display palette */
  2123 	alloct_all = 0;
  2124 	if ( SDL_palette != NULL ) {
  2125 		if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  2126 			/* We can set all entries explicitly */
  2127 			for ( i=0; i< ncolors; ++i ) {
  2128 			        int j = firstcolor + i;
  2129 				SDL_colors[j].peRed = colors[i].r;
  2130 				SDL_colors[j].peGreen = colors[i].g;
  2131 				SDL_colors[j].peBlue = colors[i].b;
  2132 			}
  2133 			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2134 				firstcolor, ncolors, &SDL_colors[firstcolor]);
  2135 			alloct_all = 1;
  2136 		} else {
  2137 			/* Grab the 236 most diverse colors in the palette */
  2138 			DX5_CompressPalette(this, colors, ncolors, 236);
  2139 			/* This sends an WM_PALETTECHANGED message to us */
  2140 			colorchange_expected = 1;
  2141 			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2142 							0, 256, SDL_colors);
  2143 		}
  2144 	}
  2145 	return(alloct_all);
  2146 }
  2147 
  2148 /* Gamma code is only available on DirectX 7 and newer */
  2149 static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
  2150 {
  2151 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2152 	LPDIRECTDRAWGAMMACONTROL gamma;
  2153 	DDGAMMARAMP gamma_ramp;
  2154 	HRESULT result;
  2155 #endif
  2156 
  2157 	/* In windowed or OpenGL mode, use windib gamma code */
  2158 	if ( ! DDRAW_FULLSCREEN() ) {
  2159 		return DIB_SetGammaRamp(this, ramp);
  2160 	}
  2161 
  2162 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2163 	SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2164 	return -1;
  2165 #else
  2166 	/* Check for a video mode! */
  2167 	if ( ! SDL_primary ) {
  2168 		SDL_SetError("A video mode must be set for gamma correction");
  2169 		return(-1);
  2170 	}
  2171 
  2172 	/* Get the gamma control object */
  2173 	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2174 			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2175 	if ( result != DD_OK ) {
  2176 		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2177 		return(-1);
  2178 	}
  2179 
  2180 	/* Set up the gamma ramp */
  2181 	memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
  2182 	memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
  2183 	memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
  2184 	result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
  2185 	if ( result != DD_OK ) {
  2186 		SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
  2187 	}
  2188 
  2189 	/* Release the interface and return */
  2190 	IDirectDrawGammaControl_Release(gamma);
  2191 	return (result == DD_OK) ? 0 : -1;
  2192 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2193 }
  2194 
  2195 static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
  2196 {
  2197 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2198 	LPDIRECTDRAWGAMMACONTROL gamma;
  2199 	DDGAMMARAMP gamma_ramp;
  2200 	HRESULT result;
  2201 #endif
  2202 
  2203 	/* In windowed or OpenGL mode, use windib gamma code */
  2204 	if ( ! DDRAW_FULLSCREEN() ) {
  2205 		return DIB_GetGammaRamp(this, ramp);
  2206 	}
  2207 
  2208 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2209 	SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2210 	return -1;
  2211 #else
  2212 	/* Check for a video mode! */
  2213 	if ( ! SDL_primary ) {
  2214 		SDL_SetError("A video mode must be set for gamma correction");
  2215 		return(-1);
  2216 	}
  2217 
  2218 	/* Get the gamma control object */
  2219 	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2220 			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2221 	if ( result != DD_OK ) {
  2222 		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2223 		return(-1);
  2224 	}
  2225 
  2226 	/* Set up the gamma ramp */
  2227 	result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
  2228 	if ( result == DD_OK ) {
  2229 		memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
  2230 		memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
  2231 		memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
  2232 	} else {
  2233 		SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
  2234 	}
  2235 
  2236 	/* Release the interface and return */
  2237 	IDirectDrawGammaControl_Release(gamma);
  2238 	return (result == DD_OK) ? 0 : -1;
  2239 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2240 }
  2241 
  2242 static void FlushMessageQueue()
  2243 {
  2244 	MSG  msg;
  2245 	while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
  2246 		if ( msg.message == WM_QUIT ) break;
  2247 		TranslateMessage( &msg );
  2248 		DispatchMessage( &msg );
  2249 	}
  2250 }
  2251 
  2252 void DX5_VideoQuit(_THIS)
  2253 {
  2254 	int i, j;
  2255 
  2256 	/* If we're fullscreen GL, we need to reset the display */
  2257 	if ( this->screen != NULL ) {
  2258 #ifndef NO_CHANGEDISPLAYSETTINGS
  2259 		if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  2260 		                            (SDL_OPENGL|SDL_FULLSCREEN) ) {
  2261 			ChangeDisplaySettings(NULL, 0);
  2262 			ShowWindow(SDL_Window, SW_HIDE);
  2263 		}
  2264 #endif
  2265 		if ( this->screen->flags & SDL_OPENGL ) {
  2266 			WIN_GL_ShutDown(this);
  2267 		}
  2268 	}
  2269 
  2270 	/* Free any palettes we used */
  2271 	if ( SDL_palette != NULL ) {
  2272 		IDirectDrawPalette_Release(SDL_palette);
  2273 		SDL_palette = NULL;
  2274 	}
  2275 
  2276 	/* Allow the primary surface to be freed */
  2277 	if ( SDL_primary != NULL ) {
  2278 		SDL_primary = NULL;
  2279 	}
  2280 
  2281 	/* Free video mode lists */
  2282 	for ( i=0; i<NUM_MODELISTS; ++i ) {
  2283 		if ( SDL_modelist[i] != NULL ) {
  2284 			for ( j=0; SDL_modelist[i][j]; ++j )
  2285 				free(SDL_modelist[i][j]);
  2286 			free(SDL_modelist[i]);
  2287 			SDL_modelist[i] = NULL;
  2288 		}
  2289 	}
  2290 
  2291 	/* Free the window */
  2292 	DIB_QuitGamma(this);
  2293 	if ( SDL_Window ) {
  2294 		DX5_DestroyWindow(this);
  2295 		FlushMessageQueue();
  2296 	}
  2297 
  2298 	/* Free our window icon */
  2299 	if ( screen_icn ) {
  2300 		DestroyIcon(screen_icn);
  2301 		screen_icn = NULL;
  2302 	}
  2303 }
  2304 
  2305 /* Exported for the windows message loop only */
  2306 void DX5_RealizePalette(_THIS)
  2307 {
  2308 	if ( SDL_palette ) {
  2309 		IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  2310 	}
  2311 }
  2312 static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
  2313 {
  2314 	int row, col;
  2315 	Uint8 *pixels;
  2316 
  2317 	if ( surface->w && surface->h ) {
  2318 		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2319 			if ( this->LockHWSurface(this, surface) < 0 ) {
  2320 				return;
  2321 			}
  2322 		}
  2323 		for ( row=0; row<surface->h; ++row ) {
  2324 			pixels = (Uint8 *)surface->pixels+row*surface->pitch;
  2325 			for ( col=0; col<surface->w; ++col, ++pixels ) {
  2326 				*pixels = mapping[*pixels];
  2327 			}
  2328 		}
  2329 		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2330 			this->UnlockHWSurface(this, surface);
  2331 		}
  2332 		SDL_UpdateRect(surface, 0, 0, 0, 0);
  2333 	}
  2334 }
  2335 void DX5_PaletteChanged(_THIS, HWND window)
  2336 {
  2337 	SDL_Palette *palette;
  2338 	SDL_Color *saved = NULL;
  2339 	HDC hdc;
  2340 	int i;
  2341 	PALETTEENTRY *entries;
  2342 
  2343 	/* This is true when the window is closing */
  2344 	if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
  2345 		return;
  2346 
  2347 	/* We need to get the colors as they were set */
  2348 	palette = this->physpal;
  2349 	if(!palette)
  2350 	        palette = SDL_VideoSurface->format->palette;
  2351 	if ( palette == NULL ) { /* Sometimes we don't have a palette */
  2352 		return;
  2353 	}
  2354 	entries = (PALETTEENTRY *)alloca(palette->ncolors*sizeof(*entries));
  2355 	hdc = GetDC(window);
  2356 	GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
  2357 	ReleaseDC(window, hdc);
  2358 	if ( ! colorchange_expected ) {
  2359 		saved = (SDL_Color *)alloca(palette->ncolors*sizeof(SDL_Color));
  2360 		memcpy(saved, palette->colors, 
  2361 					palette->ncolors*sizeof(SDL_Color));
  2362 	}
  2363 	for ( i=0; i<palette->ncolors; ++i ) {
  2364 		palette->colors[i].r = entries[i].peRed;
  2365 		palette->colors[i].g = entries[i].peGreen;
  2366 		palette->colors[i].b = entries[i].peBlue;
  2367 	}
  2368 	if ( ! colorchange_expected ) {
  2369 		Uint8 mapping[256];
  2370 
  2371 		memset(mapping, 0, sizeof(mapping));
  2372 		for ( i=0; i<palette->ncolors; ++i ) {
  2373 			mapping[i] = SDL_FindColor(palette,
  2374 					saved[i].r, saved[i].g, saved[i].b);
  2375 		}
  2376 		DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
  2377 	}
  2378 	colorchange_expected = 0;
  2379 
  2380 	/* Notify all mapped surfaces of the change */
  2381 	SDL_FormatChanged(SDL_VideoSurface);
  2382 }
  2383 
  2384 /* Exported for the windows message loop only */
  2385 void DX5_WinPAINT(_THIS, HDC hdc)
  2386 {
  2387 	SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  2388 }