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