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