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