src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 14 Mar 2006 04:00:03 +0000
changeset 1523 21b1fbb53f4a
parent 1480 0a2bd6507477
child 1545 8d9bb0cf2c2a
permissions -rw-r--r--
(patch tweaked a bit)

Date: Tue, 14 Mar 2006 03:30:11 +0000
From: Peter Mulholland
Subject: [SDL] Windows MessageBox() strangeness fixes

Hello all,

I *think* this should fix the issues that people were seeing with
MessageBox() not working and therefore assert() on mingw/msvc. Forgive
me if i've screwed up making the diff file - I'm a total newb when it
comes to things like CVS and diff.

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