src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 21 May 2006 16:47:41 +0000
changeset 1854 2280e314a978
parent 1771 8d3ca155c396
child 1855 5ff2c01e475e
permissions -rw-r--r--
Closed bug #74

Added DirectInput joystick code, contributed by Glenn Maynard.

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