src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 17 May 2006 08:18:28 +0000
branchSDL-1.3
changeset 1659 14717b52abc0
parent 1658 e49147870aac
child 1661 281d3f4870e5
permissions -rw-r--r--
Merge trunk-1.3-3
     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 int cmpmodes(const void *va, const void *vb)
   640 {
   641     SDL_Rect *a = *(SDL_Rect **)va;
   642     SDL_Rect *b = *(SDL_Rect **)vb;
   643     if ( a->w == b->w )
   644         return b->h - a->h;
   645     else
   646         return b->w - a->w;
   647 }
   648 
   649 static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata)
   650 {
   651 	SDL_VideoDevice *this = (SDL_VideoDevice *)udata;
   652 	struct DX5EnumRect *enumrect;
   653 #if defined(NONAMELESSUNION)
   654 	int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
   655 	int refreshRate = desc->u2.dwRefreshRate;
   656 #else
   657 	int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
   658 	int refreshRate = desc->dwRefreshRate;
   659 #endif
   660 	int maxRefreshRate;
   661 
   662 	if ( desc->dwWidth <= SDL_desktop_mode.dmPelsWidth &&
   663 	     desc->dwHeight <= SDL_desktop_mode.dmPelsHeight ) {
   664 		maxRefreshRate = SDL_desktop_mode.dmDisplayFrequency;
   665 	} else {
   666 		maxRefreshRate = 85;	/* safe value? */
   667 	}
   668 
   669 	switch (bpp)  {
   670 		case 8:
   671 		case 16:
   672 		case 24:
   673 		case 32:
   674 			bpp /= 8; --bpp;
   675 			if ( enumlists[bpp] &&
   676 			     enumlists[bpp]->r.w == (Uint16)desc->dwWidth &&
   677 			     enumlists[bpp]->r.h == (Uint16)desc->dwHeight ) {
   678 				if ( refreshRate > enumlists[bpp]->refreshRate &&
   679 				     refreshRate <= maxRefreshRate ) {
   680 					enumlists[bpp]->refreshRate = refreshRate;
   681 #ifdef DDRAW_DEBUG
   682  fprintf(stderr, "New refresh rate for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate);
   683 #endif
   684 				}
   685 				break;
   686 			}
   687 			++SDL_nummodes[bpp];
   688 			enumrect = (struct DX5EnumRect*)SDL_malloc(sizeof(struct DX5EnumRect));
   689 			if ( !enumrect ) {
   690 				SDL_OutOfMemory();
   691 				return(DDENUMRET_CANCEL);
   692 			}
   693 			enumrect->refreshRate = refreshRate;
   694 			enumrect->r.x = 0;
   695 			enumrect->r.y = 0;
   696 			enumrect->r.w = (Uint16)desc->dwWidth;
   697 			enumrect->r.h = (Uint16)desc->dwHeight;
   698 			enumrect->next = enumlists[bpp];
   699 			enumlists[bpp] = enumrect;
   700 #ifdef DDRAW_DEBUG
   701  fprintf(stderr, "New mode for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate);
   702 #endif
   703 			break;
   704 	}
   705 
   706 	return(DDENUMRET_OK);
   707 }
   708 
   709 void SetDDerror(const char *function, int code)
   710 {
   711 	static char *error;
   712 	static char  errbuf[1024];
   713 
   714 	errbuf[0] = 0;
   715 	switch (code) {
   716 		case DDERR_GENERIC:
   717 			error = "Undefined error!";
   718 			break;
   719 		case DDERR_EXCEPTION:
   720 			error = "Exception encountered";
   721 			break;
   722 		case DDERR_INVALIDOBJECT:
   723 			error = "Invalid object";
   724 			break;
   725 		case DDERR_INVALIDPARAMS:
   726 			error = "Invalid parameters";
   727 			break;
   728 		case DDERR_NOTFOUND:
   729 			error = "Object not found";
   730 			break;
   731 		case DDERR_INVALIDRECT:
   732 			error = "Invalid rectangle";
   733 			break;
   734 		case DDERR_INVALIDCAPS:
   735 			error = "Invalid caps member";
   736 			break;
   737 		case DDERR_INVALIDPIXELFORMAT:
   738 			error = "Invalid pixel format";
   739 			break;
   740 		case DDERR_OUTOFMEMORY:
   741 			error = "Out of memory";
   742 			break;
   743 		case DDERR_OUTOFVIDEOMEMORY:
   744 			error = "Out of video memory";
   745 			break;
   746 		case DDERR_SURFACEBUSY:
   747 			error = "Surface busy";
   748 			break;
   749 		case DDERR_SURFACELOST:
   750 			error = "Surface was lost";
   751 			break;
   752 		case DDERR_WASSTILLDRAWING:
   753 			error = "DirectDraw is still drawing";
   754 			break;
   755 		case DDERR_INVALIDSURFACETYPE:
   756 			error = "Invalid surface type";
   757 			break;
   758 		case DDERR_NOEXCLUSIVEMODE:
   759 			error = "Not in exclusive access mode";
   760 			break;
   761 		case DDERR_NOPALETTEATTACHED:
   762 			error = "No palette attached";
   763 			break;
   764 		case DDERR_NOPALETTEHW:
   765 			error = "No palette hardware";
   766 			break;
   767 		case DDERR_NOT8BITCOLOR:
   768 			error = "Not 8-bit color";
   769 			break;
   770 		case DDERR_EXCLUSIVEMODEALREADYSET:
   771 			error = "Exclusive mode was already set";
   772 			break;
   773 		case DDERR_HWNDALREADYSET:
   774 			error = "Window handle already set";
   775 			break;
   776 		case DDERR_HWNDSUBCLASSED:
   777 			error = "Window handle is subclassed";
   778 			break;
   779 		case DDERR_NOBLTHW:
   780 			error = "No blit hardware";
   781 			break;
   782 		case DDERR_IMPLICITLYCREATED:
   783 			error = "Surface was implicitly created";
   784 			break;
   785 		case DDERR_INCOMPATIBLEPRIMARY:
   786 			error = "Incompatible primary surface";
   787 			break;
   788 		case DDERR_NOCOOPERATIVELEVELSET:
   789 			error = "No cooperative level set";
   790 			break;
   791 		case DDERR_NODIRECTDRAWHW:
   792 			error = "No DirectDraw hardware";
   793 			break;
   794 		case DDERR_NOEMULATION:
   795 			error = "No emulation available";
   796 			break;
   797 		case DDERR_NOFLIPHW:
   798 			error = "No flip hardware";
   799 			break;
   800 		case DDERR_NOTFLIPPABLE:
   801 			error = "Surface not flippable";
   802 			break;
   803 		case DDERR_PRIMARYSURFACEALREADYEXISTS:
   804 			error = "Primary surface already exists";
   805 			break;
   806 		case DDERR_UNSUPPORTEDMODE:
   807 			error = "Unsupported mode";
   808 			break;
   809 		case DDERR_WRONGMODE:
   810 			error = "Surface created in different mode";
   811 			break;
   812 		case DDERR_UNSUPPORTED:
   813 			error = "Operation not supported";
   814 			break;
   815 		case E_NOINTERFACE:
   816 			error = "Interface not present";
   817 			break;
   818 		default:
   819 			SDL_snprintf(errbuf, SDL_arraysize(errbuf),
   820 			         "%s: Unknown DirectDraw error: 0x%x",
   821 								function, code);
   822 			break;
   823 	}
   824 	if ( ! errbuf[0] ) {
   825 		SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error);
   826 	}
   827 	SDL_SetError("%s", errbuf);
   828 	return;
   829 }
   830 
   831 
   832 static int DX5_UpdateVideoInfo(_THIS)
   833 {
   834 	/* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
   835 #if DIRECTDRAW_VERSION <= 0x300
   836 #error Your version of DirectX must be greater than or equal to 5.0
   837 #endif
   838 #ifndef IDirectDrawGammaControl_SetGammaRamp
   839 	/*if gamma is undefined then we really have directx <= 0x500*/
   840 	DDCAPS DDCaps;
   841 #else
   842 	DDCAPS_DX5 DDCaps;
   843 #endif
   844 	HRESULT result;
   845 
   846 	/* Fill in our hardware acceleration capabilities */
   847 	SDL_memset(&DDCaps, 0, sizeof(DDCaps));
   848 	DDCaps.dwSize = sizeof(DDCaps);
   849 	result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL);
   850 	if ( result != DD_OK ) {
   851 		SetDDerror("DirectDraw2::GetCaps", result);
   852 		return(-1);
   853 	}
   854 	this->info.hw_available = 1;
   855 	if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) {
   856 		this->info.blit_hw = 1;
   857 	}
   858 	if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
   859 	     ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
   860 		this->info.blit_hw_CC = 1;
   861 	}
   862 	if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
   863 		/* This is only for alpha channel, and DirectX 6
   864 		   doesn't support 2D alpha blits yet, so set it 0
   865 		 */
   866 		this->info.blit_hw_A = 0;
   867 	}
   868 	if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
   869 		this->info.blit_sw = 1;
   870 		/* This isn't necessarily true, but the HEL will cover us */
   871 		this->info.blit_sw_CC = this->info.blit_hw_CC;
   872 		this->info.blit_sw_A = this->info.blit_hw_A;
   873 	}
   874 	if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
   875 		this->info.blit_fill = 1;
   876 	}
   877 
   878 	/* Find out how much video memory is available */
   879 	{ DDSCAPS ddsCaps;
   880 	  DWORD total_mem;
   881 		ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
   882 		result = IDirectDraw2_GetAvailableVidMem(ddraw2,
   883 						&ddsCaps, &total_mem, NULL);
   884 		if ( result != DD_OK ) {
   885 			total_mem = DDCaps.dwVidMemTotal; 
   886 		}
   887 		this->info.video_mem = total_mem/1024;
   888 	}
   889 	return(0);
   890 }
   891 
   892 int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
   893 {
   894 	HRESULT result;
   895 	LPDIRECTDRAW ddraw;
   896 	int i, j;
   897 	HDC hdc;
   898 
   899 	/* Intialize everything */
   900 	ddraw2 = NULL;
   901 	SDL_primary = NULL;
   902 	SDL_clipper = NULL;
   903 	SDL_palette = NULL;
   904 	for ( i=0; i<NUM_MODELISTS; ++i ) {
   905 		SDL_nummodes[i] = 0;
   906 		SDL_modelist[i] = NULL;
   907 		SDL_modeindex[i] = 0;
   908 	}
   909 	colorchange_expected = 0;
   910 
   911 	/* Create the window */
   912 	if ( DX5_CreateWindow(this) < 0 ) {
   913 		return(-1);
   914 	}
   915 
   916 #if !SDL_AUDIO_DISABLED
   917 	DX5_SoundFocus(SDL_Window);
   918 #endif
   919 
   920 	/* Create the DirectDraw object */
   921 	result = DDrawCreate(NULL, &ddraw, NULL);
   922 	if ( result != DD_OK ) {
   923 		SetDDerror("DirectDrawCreate", result);
   924 		return(-1);
   925 	}
   926 	result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
   927 							(LPVOID *)&ddraw2);
   928 	IDirectDraw_Release(ddraw);
   929 	if ( result != DD_OK ) {
   930 		SetDDerror("DirectDraw::QueryInterface", result);
   931 		return(-1);
   932 	}
   933 
   934 	/* Determine the screen depth */
   935 	hdc = GetDC(SDL_Window);
   936 	vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
   937 					GetDeviceCaps(hdc,BITSPIXEL);
   938 	ReleaseDC(SDL_Window, hdc);
   939 
   940 #ifndef NO_CHANGEDISPLAYSETTINGS
   941 	/* Query for the desktop resolution */
   942 	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);
   943 	this->info.current_w = SDL_desktop_mode.dmPelsWidth;
   944 	this->info.current_h = SDL_desktop_mode.dmPelsHeight;
   945 #endif
   946 
   947 	/* Enumerate the available fullscreen modes */
   948 	for ( i=0; i<NUM_MODELISTS; ++i )
   949 		enumlists[i] = NULL;
   950 
   951 	result = IDirectDraw2_EnumDisplayModes(ddraw2,DDEDM_REFRESHRATES,NULL,this,EnumModes2);
   952 	if ( result != DD_OK ) {
   953 		SetDDerror("DirectDraw2::EnumDisplayModes", result);
   954 		return(-1);
   955 	}
   956 	for ( i=0; i<NUM_MODELISTS; ++i ) {
   957 		struct DX5EnumRect *rect;
   958 		SDL_modelist[i] = (SDL_Rect **)
   959 				SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
   960 		if ( SDL_modelist[i] == NULL ) {
   961 			SDL_OutOfMemory();
   962 			return(-1);
   963 		}
   964 		for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
   965 			SDL_modelist[i][j] = &rect->r;
   966 		}
   967 		SDL_modelist[i][j] = NULL;
   968 
   969 		if ( SDL_nummodes[i] > 0 ) {
   970 			SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes);
   971 		}
   972 	}
   973 	
   974 	/* Fill in some window manager capabilities */
   975 	this->info.wm_available = 1;
   976 
   977 	/* Fill in the video hardware capabilities */
   978 	DX5_UpdateVideoInfo(this);
   979 
   980 	return(0);
   981 }
   982 
   983 SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   984 {
   985 	int bpp;
   986 
   987 	bpp = format->BitsPerPixel;
   988 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   989 		/* FIXME:  No support for 1 bpp or 4 bpp formats */
   990 		switch (bpp) {  /* Does windows support other BPP? */
   991 			case 8:
   992 			case 16:
   993 			case 24:
   994 			case 32:
   995 				bpp = (bpp/8)-1;
   996 				if ( SDL_nummodes[bpp] > 0 )
   997 					return(SDL_modelist[bpp]);
   998 				/* Fall through */
   999 			default:
  1000 				return((SDL_Rect **)0);
  1001 		}
  1002 	} else {
  1003 		if ( this->screen->format->BitsPerPixel == bpp ) {
  1004 			return((SDL_Rect **)-1);
  1005 		} else {
  1006 			return((SDL_Rect **)0);
  1007 		}
  1008 	}
  1009 }
  1010 
  1011 /* Various screen update functions available */
  1012 static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
  1013 static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
  1014 
  1015 SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
  1016 				int width, int height, int bpp, Uint32 flags)
  1017 {
  1018 	SDL_Surface *video;
  1019 	HRESULT result;
  1020 	DWORD sharemode;
  1021 	DWORD style;
  1022 	const DWORD directstyle =
  1023 			(WS_POPUP);
  1024 	const DWORD windowstyle = 
  1025 			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
  1026 	const DWORD resizestyle =
  1027 			(WS_THICKFRAME|WS_MAXIMIZEBOX);
  1028 	DDSURFACEDESC ddsd;
  1029 	LPDIRECTDRAWSURFACE  dd_surface1;
  1030 	LPDIRECTDRAWSURFACE3 dd_surface3;
  1031 
  1032 	SDL_resizing = 1;
  1033 #ifdef DDRAW_DEBUG
  1034  fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
  1035 #endif
  1036 	/* Clean up any previous DirectDraw surfaces */
  1037 	if ( current->hwdata ) {
  1038 		this->FreeHWSurface(this, current);
  1039 		current->hwdata = NULL;
  1040 	}
  1041 	if ( SDL_primary != NULL ) {
  1042 		IDirectDrawSurface3_Release(SDL_primary);
  1043 		SDL_primary = NULL;
  1044 	}
  1045 
  1046 #ifndef NO_CHANGEDISPLAYSETTINGS
  1047 	/* Unset any previous OpenGL fullscreen mode */
  1048 	if ( (current->flags & (SDL_INTERNALOPENGL|SDL_FULLSCREEN)) ==
  1049 	                       (SDL_INTERNALOPENGL|SDL_FULLSCREEN) ) {
  1050 		ChangeDisplaySettings(NULL, 0);
  1051 	}
  1052 #endif
  1053 
  1054 	/* Clean up any GL context that may be hanging around */
  1055 	if ( current->flags & SDL_INTERNALOPENGL ) {
  1056 		WIN_GL_ShutDown(this);
  1057 	}
  1058 
  1059 	/* If we are setting a GL mode, use GDI, not DirectX (yuck) */
  1060 	if ( flags & SDL_INTERNALOPENGL ) {
  1061 		Uint32 Rmask, Gmask, Bmask;
  1062 
  1063 		/* Recalculate the bitmasks if necessary */
  1064 		if ( bpp == current->format->BitsPerPixel ) {
  1065 			video = current;
  1066 		} else {
  1067 			switch (bpp) {
  1068 			    case 15:
  1069 			    case 16:
  1070 				if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
  1071 					/* 5-5-5 */
  1072 					Rmask = 0x00007c00;
  1073 					Gmask = 0x000003e0;
  1074 					Bmask = 0x0000001f;
  1075 				} else {
  1076 					/* 5-6-5 */
  1077 					Rmask = 0x0000f800;
  1078 					Gmask = 0x000007e0;
  1079 					Bmask = 0x0000001f;
  1080 				}
  1081 				break;
  1082 			    case 24:
  1083 			    case 32:
  1084 				/* GDI defined as 8-8-8 */
  1085 				Rmask = 0x00ff0000;
  1086 				Gmask = 0x0000ff00;
  1087 				Bmask = 0x000000ff;
  1088 				break;
  1089 			    default:
  1090 				Rmask = 0x00000000;
  1091 				Gmask = 0x00000000;
  1092 				Bmask = 0x00000000;
  1093 				break;
  1094 			}
  1095 			video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
  1096 			                             Rmask, Gmask, Bmask, 0);
  1097 			if ( video == NULL ) {
  1098 				SDL_OutOfMemory();
  1099 				return(NULL);
  1100 			}
  1101 		}
  1102 
  1103 		/* Fill in part of the video surface */
  1104 		video->flags = 0;	/* Clear flags */
  1105 		video->w = width;
  1106 		video->h = height;
  1107 		video->pitch = SDL_CalculatePitch(video);
  1108 
  1109 #ifndef NO_CHANGEDISPLAYSETTINGS
  1110 		/* Set fullscreen mode if appropriate.
  1111 		   Ugh, since our list of valid video modes comes from
  1112 		   the DirectX driver, we may not actually be able to
  1113 		   change to the desired resolution here.
  1114 		   FIXME: Should we do a closest match?
  1115 		 */
  1116 		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1117 			DEVMODE settings;
  1118 			BOOL changed;
  1119 
  1120 			SDL_memset(&settings, 0, sizeof(DEVMODE));
  1121 			settings.dmSize = sizeof(DEVMODE);
  1122 			settings.dmBitsPerPel = video->format->BitsPerPixel;
  1123 			settings.dmPelsWidth = width;
  1124 			settings.dmPelsHeight = height;
  1125 			settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  1126 			if ( width <= (int)SDL_desktop_mode.dmPelsWidth &&
  1127 			     height <= (int)SDL_desktop_mode.dmPelsHeight ) {
  1128 				settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
  1129 				settings.dmFields |= DM_DISPLAYFREQUENCY;
  1130 			}
  1131 			changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
  1132 			if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) {
  1133 				settings.dmFields &= ~DM_DISPLAYFREQUENCY;
  1134 				changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
  1135 			}
  1136 			if ( changed ) {
  1137 				video->flags |= SDL_FULLSCREEN;
  1138 				SDL_fullscreen_mode = settings;
  1139 			}
  1140 		}
  1141 #endif /* !NO_CHANGEDISPLAYSETTINGS */
  1142 
  1143 		style = GetWindowLong(SDL_Window, GWL_STYLE);
  1144 		style &= ~(resizestyle|WS_MAXIMIZE);
  1145 		if ( video->flags & SDL_FULLSCREEN ) {
  1146 			style &= ~windowstyle;
  1147 			style |= directstyle;
  1148 		} else {
  1149 			if ( flags & SDL_NOFRAME ) {
  1150 				style &= ~windowstyle;
  1151 				style |= directstyle;
  1152 				video->flags |= SDL_NOFRAME;
  1153 			} else {
  1154 				style &= ~directstyle;
  1155 				style |= windowstyle;
  1156 				if ( flags & SDL_RESIZABLE ) {
  1157 					style |= resizestyle;
  1158 					video->flags |= SDL_RESIZABLE;
  1159 				}
  1160 			}
  1161 #if WS_MAXIMIZE
  1162 			if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1163 #endif
  1164 		}
  1165 
  1166 		/* DJM: Don't piss of anyone who has setup his own window */
  1167 		if ( !SDL_windowid )
  1168 			SetWindowLong(SDL_Window, GWL_STYLE, style);
  1169 
  1170 		/* Resize the window (copied from SDL WinDIB driver) */
  1171 		if ( !SDL_windowid && !IsZoomed(SDL_Window) ) {
  1172 			RECT bounds;
  1173 			int x, y;
  1174 			HWND top;
  1175 			UINT swp_flags;
  1176 			const char *window = NULL;
  1177 			const char *center = NULL;
  1178 
  1179 			if ( !SDL_windowX && !SDL_windowY ) {
  1180 				window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1181 				center = SDL_getenv("SDL_VIDEO_CENTERED");
  1182 				if ( window ) {
  1183 					if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) {
  1184 						SDL_windowX = x;
  1185 						SDL_windowY = y;
  1186 					}
  1187 					if ( SDL_strcmp(window, "center") == 0 ) {
  1188 						center = window;
  1189 					}
  1190 				}
  1191 			}
  1192 			swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
  1193 
  1194 			bounds.left = SDL_windowX;
  1195 			bounds.top = SDL_windowY;
  1196 			bounds.right = SDL_windowX+video->w;
  1197 			bounds.bottom = SDL_windowY+video->h;
  1198 			AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
  1199 			width = bounds.right-bounds.left;
  1200 			height = bounds.bottom-bounds.top;
  1201 			if ( (flags & SDL_FULLSCREEN) ) {
  1202 				x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1203 				y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1204 			} else if ( center ) {
  1205 				x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1206 				y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1207 			} else if ( SDL_windowX || SDL_windowY || window ) {
  1208 				x = bounds.left;
  1209 				y = bounds.top;
  1210 			} else {
  1211 				x = y = -1;
  1212 				swp_flags |= SWP_NOMOVE;
  1213 			}
  1214 			if ( flags & SDL_FULLSCREEN ) {
  1215 				top = HWND_TOPMOST;
  1216 			} else {
  1217 				top = HWND_NOTOPMOST;
  1218 			}
  1219 			SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
  1220 			if ( !(flags & SDL_FULLSCREEN) ) {
  1221 				SDL_windowX = SDL_bounds.left;
  1222 				SDL_windowY = SDL_bounds.top;
  1223 			}
  1224 			SetForegroundWindow(SDL_Window);
  1225 		}
  1226 		SDL_resizing = 0;
  1227 
  1228 		/* Set up for OpenGL */
  1229 		if ( WIN_GL_SetupWindow(this) < 0 ) {
  1230 			return(NULL);
  1231 		}
  1232 		video->flags |= SDL_INTERNALOPENGL;
  1233 		return(video);
  1234 	}
  1235 
  1236 	/* Set the appropriate window style */
  1237 	style = GetWindowLong(SDL_Window, GWL_STYLE);
  1238 	style &= ~(resizestyle|WS_MAXIMIZE);
  1239 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1240 		style &= ~windowstyle;
  1241 		style |= directstyle;
  1242 	} else {
  1243 		if ( flags & SDL_NOFRAME ) {
  1244 			style &= ~windowstyle;
  1245 			style |= directstyle;
  1246 		} else {
  1247 			style &= ~directstyle;
  1248 			style |= windowstyle;
  1249 			if ( flags & SDL_RESIZABLE ) {
  1250 				style |= resizestyle;
  1251 			}
  1252 		}
  1253 #if WS_MAXIMIZE
  1254 		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1255 #endif
  1256 	}
  1257 	/* DJM: Don't piss of anyone who has setup his own window */
  1258 	if ( !SDL_windowid )
  1259 		SetWindowLong(SDL_Window, GWL_STYLE, style);
  1260 
  1261 	/* Set DirectDraw sharing mode.. exclusive when fullscreen */
  1262 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1263 		sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
  1264 	} else {
  1265 		sharemode = DDSCL_NORMAL;
  1266 	}
  1267 	result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
  1268 	if ( result != DD_OK ) {
  1269 		SetDDerror("DirectDraw2::SetCooperativeLevel", result);
  1270 		return(NULL);
  1271 	}
  1272 
  1273 	/* Set the display mode, if we are in fullscreen mode */
  1274 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1275 		RECT bounds;
  1276 		struct DX5EnumRect *rect;
  1277 		int maxRefreshRate;
  1278 
  1279 		/* Cover up desktop during mode change */
  1280 		bounds.left = 0;
  1281 		bounds.top = 0;
  1282 		bounds.right = GetSystemMetrics(SM_CXSCREEN);
  1283 		bounds.bottom = GetSystemMetrics(SM_CYSCREEN);
  1284 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
  1285 		SetWindowPos(SDL_Window, HWND_TOPMOST,
  1286 			bounds.left, bounds.top, 
  1287 			bounds.right - bounds.left,
  1288 			bounds.bottom - bounds.top, SWP_NOCOPYBITS);
  1289 		ShowWindow(SDL_Window, SW_SHOW);
  1290 		while ( GetForegroundWindow() != SDL_Window ) {
  1291 			SetForegroundWindow(SDL_Window);
  1292 			SDL_Delay(100);
  1293 		}
  1294 
  1295 		/* find maximum monitor refresh rate for this resolution */
  1296 		/* Dmitry Yakimov ftech@tula.net */
  1297 		maxRefreshRate = 0; /* system default */
  1298 		for ( rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next ) {
  1299 			if ( (width == rect->r.w) && (height == rect->r.h) ) {
  1300 				maxRefreshRate = rect->refreshRate;
  1301 				break;
  1302 			}
  1303 		}
  1304 #ifdef DDRAW_DEBUG
  1305  fprintf(stderr, "refresh rate = %d Hz\n", maxRefreshRate);
  1306 #endif
  1307 
  1308 		result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, maxRefreshRate, 0);
  1309 		if ( result != DD_OK ) {
  1310 			result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0);
  1311 			if ( result != DD_OK ) {
  1312 				/* We couldn't set fullscreen mode, try window */
  1313 				return(DX5_SetVideoMode(this, current, width, height, bpp, flags & ~SDL_FULLSCREEN)); 
  1314 			}
  1315 		}
  1316 		DX5_DInputReset(this, 1);
  1317 	} else {
  1318 		DX5_DInputReset(this, 0);
  1319 	}
  1320 	DX5_UpdateVideoInfo(this);
  1321 
  1322 	/* Create a primary DirectDraw surface */
  1323 	SDL_memset(&ddsd, 0, sizeof(ddsd));
  1324 	ddsd.dwSize = sizeof(ddsd);
  1325 	ddsd.dwFlags = DDSD_CAPS;
  1326 	ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
  1327 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1328 		/* There's no windowed double-buffering */
  1329 		flags &= ~SDL_DOUBLEBUF;
  1330 	}
  1331 	if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1332 		ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
  1333 		ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1334 		ddsd.dwBackBufferCount = 1;
  1335 	}
  1336 	result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
  1337 	if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
  1338 		ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
  1339 		ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1340 		ddsd.dwBackBufferCount = 0;
  1341 		result = IDirectDraw2_CreateSurface(ddraw2,
  1342 						&ddsd, &dd_surface1, NULL); 
  1343 	}
  1344 	if ( result != DD_OK ) {
  1345 		SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
  1346 		return(NULL);
  1347 	}
  1348 	result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1349 			&IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
  1350 	if ( result != DD_OK ) {
  1351 		SetDDerror("DirectDrawSurface::QueryInterface", result);
  1352 		return(NULL);
  1353 	}
  1354 	IDirectDrawSurface_Release(dd_surface1);
  1355 
  1356 	/* Get the format of the primary DirectDraw surface */
  1357 	SDL_memset(&ddsd, 0, sizeof(ddsd));
  1358 	ddsd.dwSize = sizeof(ddsd);
  1359 	ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
  1360 	result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
  1361 	if ( result != DD_OK ) {
  1362 		SetDDerror("DirectDrawSurface::GetSurfaceDesc", result);
  1363 		return(NULL);
  1364 	}
  1365 	if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
  1366 		SDL_SetError("Primary DDRAW surface is not RGB format");
  1367 		return(NULL);
  1368 	}
  1369 
  1370 	/* Free old palette and create a new one if we're in 8-bit mode */
  1371 	if ( SDL_palette != NULL ) {
  1372 		IDirectDrawPalette_Release(SDL_palette);
  1373 		SDL_palette = NULL;
  1374 	}
  1375 #if defined(NONAMELESSUNION)
  1376 	if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
  1377 #else
  1378 	if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
  1379 #endif
  1380 		int i;
  1381 
  1382 		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1383 			/* We have access to the entire palette */
  1384 			for ( i=0; i<256; ++i ) {
  1385 				SDL_colors[i].peFlags =
  1386 						(PC_NOCOLLAPSE|PC_RESERVED);
  1387 				SDL_colors[i].peRed = 0;
  1388 				SDL_colors[i].peGreen = 0;
  1389 				SDL_colors[i].peBlue = 0;
  1390 			}
  1391 		} else {
  1392 			/* First 10 colors are reserved by Windows */
  1393 			for ( i=0; i<10; ++i ) {
  1394 				SDL_colors[i].peFlags = PC_EXPLICIT;
  1395 				SDL_colors[i].peRed = i;
  1396 				SDL_colors[i].peGreen = 0;
  1397 				SDL_colors[i].peBlue = 0;
  1398 			}
  1399 			for ( i=10; i<(10+236); ++i ) {
  1400 				SDL_colors[i].peFlags = PC_NOCOLLAPSE;
  1401 				SDL_colors[i].peRed = 0;
  1402 				SDL_colors[i].peGreen = 0;
  1403 				SDL_colors[i].peBlue = 0;
  1404 			}
  1405 			/* Last 10 colors are reserved by Windows */
  1406 			for ( i=246; i<256; ++i ) {
  1407 				SDL_colors[i].peFlags = PC_EXPLICIT;
  1408 				SDL_colors[i].peRed = i;
  1409 				SDL_colors[i].peGreen = 0;
  1410 				SDL_colors[i].peBlue = 0;
  1411 			}
  1412 		}
  1413 		result = IDirectDraw2_CreatePalette(ddraw2,
  1414 		     			(DDPCAPS_8BIT|DDPCAPS_ALLOW256),
  1415 						SDL_colors, &SDL_palette, NULL);
  1416 		if ( result != DD_OK ) {
  1417 			SetDDerror("DirectDraw2::CreatePalette", result);
  1418 			return(NULL);
  1419 		}
  1420 		result = IDirectDrawSurface3_SetPalette(SDL_primary,
  1421 								SDL_palette);
  1422 		if ( result != DD_OK ) {
  1423 			SetDDerror("DirectDrawSurface3::SetPalette", result);
  1424 			return(NULL);
  1425 		}
  1426 	}
  1427 
  1428 	/* Create our video surface using the same pixel format */
  1429 	video = current;
  1430 	if ( (width != video->w) || (height != video->h)
  1431 			|| (video->format->BitsPerPixel != 
  1432 #if defined(NONAMELESSUNION)
  1433 				ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
  1434 #else
  1435 				ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
  1436 #endif
  1437 		SDL_FreeSurface(video);
  1438 		video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
  1439 #if defined(NONAMELESSUNION)
  1440 				ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
  1441 					ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1442 					ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1443 					ddsd.ddpfPixelFormat.u4.dwBBitMask,
  1444 #else
  1445 				ddsd.ddpfPixelFormat.dwRGBBitCount,
  1446 					ddsd.ddpfPixelFormat.dwRBitMask,
  1447 					ddsd.ddpfPixelFormat.dwGBitMask,
  1448 					ddsd.ddpfPixelFormat.dwBBitMask,
  1449 #endif
  1450 								0);
  1451 		if ( video == NULL ) {
  1452 			SDL_OutOfMemory();
  1453 			return(NULL);
  1454 		}
  1455 		video->w = width;
  1456 		video->h = height;
  1457 		video->pitch = 0;
  1458 	}
  1459 	video->flags = 0;	/* Clear flags */
  1460 
  1461 	/* If not fullscreen, locking is possible, but it doesn't do what 
  1462 	   the caller really expects -- if the locked surface is written to,
  1463 	   the appropriate portion of the entire screen is modified, not 
  1464 	   the application window, as we would like.
  1465 	   Note that it is still possible to write directly to display
  1466 	   memory, but the application must respect the clip list of
  1467 	   the surface.  There might be some odd timing interactions
  1468 	   involving clip list updates and background refreshing as
  1469 	   Windows moves other windows across our window.
  1470 	   We currently don't support this, even though it might be a
  1471 	   good idea since BeOS has an implementation of BDirectWindow
  1472 	   that does the same thing.  This would be most useful for
  1473 	   applications that do complete screen updates every frame.
  1474 	    -- Fixme?
  1475 	*/
  1476 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1477 		/* Necessary if we're going from fullscreen to window */
  1478 		if ( video->pixels == NULL ) {
  1479 			video->pitch = (width*video->format->BytesPerPixel);
  1480 			/* Pitch needs to be QWORD (8-byte) aligned */
  1481 			video->pitch = (video->pitch + 7) & ~7;
  1482 			video->pixels = (void *)SDL_malloc(video->h*video->pitch);
  1483 			if ( video->pixels == NULL ) {
  1484 				if ( video != current ) {
  1485 					SDL_FreeSurface(video);
  1486 				}
  1487 				SDL_OutOfMemory();
  1488 				return(NULL);
  1489 			}
  1490 		}
  1491 		dd_surface3 = NULL;
  1492 #if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */
  1493 		if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1494 			video->flags |= SDL_HWSURFACE;
  1495 		} else {
  1496 			video->flags |= SDL_SWSURFACE;
  1497 		}
  1498 #else
  1499 		video->flags |= SDL_SWSURFACE;
  1500 #endif
  1501 		if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
  1502 			video->flags |= SDL_RESIZABLE;
  1503 		}
  1504 		if ( flags & SDL_NOFRAME ) {
  1505 			video->flags |= SDL_NOFRAME;
  1506 		}
  1507 	} else {
  1508 		/* Necessary if we're going from window to fullscreen */
  1509 		if ( video->pixels != NULL ) {
  1510 			SDL_free(video->pixels);
  1511 			video->pixels = NULL;
  1512 		}
  1513 		dd_surface3 = SDL_primary;
  1514 		video->flags |= SDL_HWSURFACE;
  1515 	}
  1516 
  1517 	/* See if the primary surface has double-buffering enabled */
  1518 	if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
  1519 		video->flags |= SDL_DOUBLEBUF;
  1520 	}
  1521 
  1522 	/* Allocate the SDL surface associated with the primary surface */
  1523 	if ( DX5_AllocDDSurface(this, video, dd_surface3,
  1524 	                        video->flags&SDL_HWSURFACE) < 0 ) {
  1525 		if ( video != current ) {
  1526 			SDL_FreeSurface(video);
  1527 		}
  1528 		return(NULL);
  1529 	}
  1530 
  1531 	/* Use the appropriate blitting function */
  1532 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1533 		video->flags |= SDL_FULLSCREEN;
  1534 		if ( video->format->palette != NULL ) {
  1535 			video->flags |= SDL_HWPALETTE;
  1536 		}
  1537 		this->UpdateRects = DX5_DirectUpdate;
  1538 	} else {
  1539 		this->UpdateRects = DX5_WindowUpdate;
  1540 	}
  1541 
  1542 	/* Make our window the proper size, set the clipper, then show it */
  1543 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1544 		/* Create and set a clipper on our primary surface */
  1545 		if ( SDL_clipper == NULL ) {
  1546 			result = IDirectDraw2_CreateClipper(ddraw2,
  1547 							0, &SDL_clipper, NULL);
  1548 			if ( result != DD_OK ) {
  1549 				if ( video != current ) {
  1550 					SDL_FreeSurface(video);
  1551 				}
  1552 				SetDDerror("DirectDraw2::CreateClipper",result);
  1553 				return(NULL);
  1554 			}
  1555 		}
  1556 		result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
  1557 		if ( result != DD_OK ) {
  1558 			if ( video != current ) {
  1559 				SDL_FreeSurface(video);
  1560 			}
  1561 			SetDDerror("DirectDrawClipper::SetHWnd", result);
  1562 			return(NULL);
  1563 		}
  1564 		result = IDirectDrawSurface3_SetClipper(SDL_primary,
  1565 								SDL_clipper);
  1566 		if ( result != DD_OK ) {
  1567 			if ( video != current ) {
  1568 				SDL_FreeSurface(video);
  1569 			}
  1570 			SetDDerror("DirectDrawSurface3::SetClipper", result);
  1571 			return(NULL);
  1572 		}
  1573 
  1574 		/* Resize the window (copied from SDL WinDIB driver) */
  1575 		if ( !SDL_windowid && !IsZoomed(SDL_Window) ) {
  1576 			RECT bounds;
  1577 			int  x, y;
  1578 			UINT swp_flags;
  1579 			const char *window = NULL;
  1580 			const char *center = NULL;
  1581 
  1582 			if ( !SDL_windowX && !SDL_windowY ) {
  1583 				window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1584 				center = SDL_getenv("SDL_VIDEO_CENTERED");
  1585 				if ( window ) {
  1586 					if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) {
  1587 						SDL_windowX = x;
  1588 						SDL_windowY = y;
  1589 					}
  1590 					if ( SDL_strcmp(window, "center") == 0 ) {
  1591 						center = window;
  1592 					}
  1593 				}
  1594 			}
  1595 			swp_flags = SWP_NOCOPYBITS;
  1596 
  1597 			bounds.left = SDL_windowX;
  1598 			bounds.top = SDL_windowY;
  1599 			bounds.right = SDL_windowX+video->w;
  1600 			bounds.bottom = SDL_windowY+video->h;
  1601 			AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
  1602 			width = bounds.right-bounds.left;
  1603 			height = bounds.bottom-bounds.top;
  1604 			if ( center ) {
  1605 				x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1606 				y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1607 			} else if ( SDL_windowX || SDL_windowY || window ) {
  1608 				x = bounds.left;
  1609 				y = bounds.top;
  1610 			} else {
  1611 				x = y = -1;
  1612 				swp_flags |= SWP_NOMOVE;
  1613 			}
  1614 			SetWindowPos(SDL_Window, HWND_NOTOPMOST, x, y, width, height, swp_flags);
  1615 			SDL_windowX = SDL_bounds.left;
  1616 			SDL_windowY = SDL_bounds.top;
  1617 		}
  1618 
  1619 	}
  1620 	ShowWindow(SDL_Window, SW_SHOW);
  1621 	SetForegroundWindow(SDL_Window);
  1622 	SDL_resizing = 0;
  1623 
  1624 	/* JC 14 Mar 2006
  1625 		Flush the message loop or this can cause big problems later
  1626 		Especially if the user decides to use dialog boxes or assert()!
  1627 	*/
  1628 	WIN_FlushMessageQueue();
  1629 
  1630 	/* We're live! */
  1631 	return(video);
  1632 }
  1633 
  1634 struct private_hwdata {
  1635 	LPDIRECTDRAWSURFACE3 dd_surface;
  1636 	LPDIRECTDRAWSURFACE3 dd_writebuf;
  1637 };
  1638 
  1639 static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
  1640 				LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
  1641 {
  1642 	LPDIRECTDRAWSURFACE  dd_surface1;
  1643 	LPDIRECTDRAWSURFACE3 dd_surface3;
  1644 	DDSURFACEDESC ddsd;
  1645 	HRESULT result;
  1646 
  1647 	/* Clear the hardware flag, in case we fail */
  1648 	surface->flags &= ~flag;
  1649 
  1650 	/* Allocate the hardware acceleration data */
  1651 	surface->hwdata = (struct private_hwdata *)
  1652 					SDL_malloc(sizeof(*surface->hwdata));
  1653 	if ( surface->hwdata == NULL ) {
  1654 		SDL_OutOfMemory();
  1655 		return(-1);
  1656 	}
  1657 	dd_surface3 = NULL;
  1658 
  1659 	/* Set up the surface description */
  1660 	SDL_memset(&ddsd, 0, sizeof(ddsd));
  1661 	ddsd.dwSize = sizeof(ddsd);
  1662 	ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
  1663 					DDSD_PITCH|DDSD_PIXELFORMAT);
  1664 	ddsd.dwWidth = surface->w;
  1665 	ddsd.dwHeight= surface->h;
  1666 #if defined(NONAMELESSUNION)
  1667 	ddsd.u1.lPitch = surface->pitch;
  1668 #else
  1669 	ddsd.lPitch = surface->pitch;
  1670 #endif
  1671 	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1672 		ddsd.ddsCaps.dwCaps =
  1673 				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
  1674 	} else {
  1675 		ddsd.ddsCaps.dwCaps =
  1676 				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
  1677 	}
  1678 	ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  1679 	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  1680 	if ( surface->format->palette ) {
  1681 		ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  1682 	}
  1683 #if defined(NONAMELESSUNION)
  1684 	ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
  1685 	ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
  1686 	ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
  1687 	ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
  1688 #else
  1689 	ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
  1690 	ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
  1691 	ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
  1692 	ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
  1693 #endif
  1694 
  1695 	/* Create the DirectDraw video surface */
  1696 	if ( requested != NULL ) {
  1697 		dd_surface3 = requested;
  1698 	} else {
  1699 		result = IDirectDraw2_CreateSurface(ddraw2,
  1700 						&ddsd, &dd_surface1, NULL); 
  1701 		if ( result != DD_OK ) {
  1702 			SetDDerror("DirectDraw2::CreateSurface", result);
  1703 			goto error_end;
  1704 		}
  1705 		result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1706 			&IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
  1707 		IDirectDrawSurface_Release(dd_surface1);
  1708 		if ( result != DD_OK ) {
  1709 			SetDDerror("DirectDrawSurface::QueryInterface", result);
  1710 			goto error_end;
  1711 		}
  1712 	}
  1713 
  1714 	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1715 		/* Check to see whether the surface actually ended up
  1716 		   in video memory, and fail if not.  We expect the
  1717 		   surfaces we create here to actually be in hardware!
  1718 		*/
  1719 		result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
  1720 		if ( result != DD_OK ) {
  1721 			SetDDerror("DirectDrawSurface3::GetCaps", result);
  1722 			goto error_end;
  1723 		}
  1724 		if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
  1725 							DDSCAPS_VIDEOMEMORY ) {
  1726 			SDL_SetError("No room in video memory");
  1727 			goto error_end;
  1728 		}
  1729 	} else {
  1730 		/* Try to hook our surface memory */
  1731 		ddsd.dwFlags = DDSD_LPSURFACE;
  1732 		ddsd.lpSurface = surface->pixels;
  1733 		result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
  1734 								&ddsd, 0);
  1735 		if ( result != DD_OK ) {
  1736 			SetDDerror("DirectDraw2::SetSurfaceDesc", result);
  1737 			goto error_end;
  1738 		}
  1739 	
  1740 	}
  1741 
  1742 	/* Make sure the surface format was set properly */
  1743 	SDL_memset(&ddsd, 0, sizeof(ddsd));
  1744 	ddsd.dwSize = sizeof(ddsd);
  1745 	result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  1746 		&ddsd, (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1747 	if ( result != DD_OK ) {
  1748 		SetDDerror("DirectDrawSurface3::Lock", result);
  1749 		goto error_end;
  1750 	}
  1751 	IDirectDrawSurface3_Unlock(dd_surface3, NULL);
  1752 
  1753 	if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1754 		if ( ddsd.lpSurface != surface->pixels ) {
  1755 			SDL_SetError("DDraw didn't use SDL surface memory");
  1756 			goto error_end;
  1757 		}
  1758 		if (
  1759 #if defined(NONAMELESSUNION)
  1760 			ddsd.u1.lPitch
  1761 #else
  1762 			ddsd.lPitch
  1763 #endif
  1764 				 != (LONG)surface->pitch ) {
  1765 			SDL_SetError("DDraw created surface with wrong pitch");
  1766 			goto error_end;
  1767 		}
  1768 	} else {
  1769 #if defined(NONAMELESSUNION)
  1770 		surface->pitch = (Uint16)ddsd.u1.lPitch;
  1771 #else
  1772 		surface->pitch = (Uint16)ddsd.lPitch;
  1773 #endif
  1774 	}
  1775 #if defined(NONAMELESSUNION)
  1776 	if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
  1777 					surface->format->BitsPerPixel) ||
  1778 	     (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
  1779 	     (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
  1780 	     (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
  1781 #else
  1782 	if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
  1783 					surface->format->BitsPerPixel) ||
  1784 	     (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
  1785 	     (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
  1786 	     (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
  1787 #endif
  1788 		SDL_SetError("DDraw didn't use SDL surface description");
  1789 		goto error_end;
  1790 	}
  1791 	if ( (ddsd.dwWidth != (DWORD)surface->w) ||
  1792 		(ddsd.dwHeight != (DWORD)surface->h) ) {
  1793 		SDL_SetError("DDraw created surface with wrong size");
  1794 		goto error_end;
  1795 	}
  1796 
  1797 	/* Set the surface private data */
  1798 	surface->flags |= flag;
  1799 	surface->hwdata->dd_surface = dd_surface3;
  1800 	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1801 		LPDIRECTDRAWSURFACE3 dd_writebuf;
  1802 
  1803 		ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  1804 		result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
  1805 						&ddsd.ddsCaps, &dd_writebuf);
  1806 		if ( result != DD_OK ) {
  1807 			SetDDerror("DirectDrawSurface3::GetAttachedSurface",
  1808 								result);
  1809 		} else {
  1810 			dd_surface3 = dd_writebuf;
  1811 		}
  1812 	}
  1813 	surface->hwdata->dd_writebuf = dd_surface3;
  1814 
  1815 	/* We're ready to go! */
  1816 	return(0);
  1817 
  1818 	/* Okay, so goto's are cheesy, but there are so many possible
  1819 	   errors in this function, and the cleanup is the same in 
  1820 	   every single case.  Is there a better way, other than deeply
  1821 	   nesting the code?
  1822 	*/
  1823 error_end:
  1824 	if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
  1825 		IDirectDrawSurface_Release(dd_surface3);
  1826 	}
  1827 	SDL_free(surface->hwdata);
  1828 	surface->hwdata = NULL;
  1829 	return(-1);
  1830 }
  1831 
  1832 static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
  1833 {
  1834 	/* DDraw limitation -- you need to set cooperative level first */
  1835 	if ( SDL_primary == NULL ) {
  1836 		SDL_SetError("You must set a non-GL video mode first");
  1837 		return(-1);
  1838 	}
  1839 	return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
  1840 }
  1841 
  1842 #ifdef DDRAW_DEBUG
  1843 void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
  1844 {
  1845 	DDSURFACEDESC ddsd;
  1846 
  1847 	/* Lock and load! */
  1848 	SDL_memset(&ddsd, 0, sizeof(ddsd));
  1849 	ddsd.dwSize = sizeof(ddsd);
  1850 	if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
  1851 			(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
  1852 		return;
  1853 	}
  1854 	IDirectDrawSurface3_Unlock(surface, NULL);
  1855 	
  1856 	fprintf(stderr, "%s:\n", title);
  1857 	fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
  1858 		ddsd.dwWidth, ddsd.dwHeight,
  1859 		(flags & SDL_HWSURFACE) ? "hardware" : "software",
  1860 #if defined(NONAMELESSUNION)
  1861 		ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
  1862 #else
  1863 		ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
  1864 #endif
  1865 	fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
  1866 #if defined(NONAMELESSUNION)
  1867 	     		ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1868 	     		ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1869 	     		ddsd.ddpfPixelFormat.u4.dwBBitMask);
  1870 #else
  1871 	     		ddsd.ddpfPixelFormat.dwRBitMask,
  1872 	     		ddsd.ddpfPixelFormat.dwGBitMask,
  1873 	     		ddsd.ddpfPixelFormat.dwBBitMask);
  1874 #endif
  1875 }
  1876 #endif /* DDRAW_DEBUG */
  1877 
  1878 static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
  1879 					SDL_Surface *dst, SDL_Rect *dstrect)
  1880 {
  1881 	LPDIRECTDRAWSURFACE3 src_surface;
  1882 	LPDIRECTDRAWSURFACE3 dst_surface;
  1883 	DWORD flags;
  1884 	RECT rect;
  1885 	HRESULT result;
  1886 
  1887 	/* Set it up.. the desination must have a DDRAW surface */
  1888 	src_surface = src->hwdata->dd_writebuf;
  1889 	dst_surface = dst->hwdata->dd_writebuf;
  1890 	rect.top    = (LONG)srcrect->y;
  1891 	rect.bottom = (LONG)srcrect->y+srcrect->h;
  1892 	rect.left   = (LONG)srcrect->x;
  1893 	rect.right  = (LONG)srcrect->x+srcrect->w;
  1894 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
  1895 		flags = DDBLTFAST_SRCCOLORKEY;
  1896 	else
  1897 		flags = DDBLTFAST_NOCOLORKEY;
  1898 	/* FIXME:  We can remove this flag for _really_ fast blit queuing,
  1899 	           but it will affect the return values of locks and flips.
  1900 	 */
  1901 	flags |= DDBLTFAST_WAIT;
  1902 
  1903 	/* Do the blit! */
  1904 	result = IDirectDrawSurface3_BltFast(dst_surface,
  1905 			dstrect->x, dstrect->y, src_surface, &rect, flags);
  1906 	if ( result != DD_OK ) {
  1907 		if ( result == DDERR_SURFACELOST ) {
  1908 			result = IDirectDrawSurface3_Restore(src_surface);
  1909 			result = IDirectDrawSurface3_Restore(dst_surface);
  1910 			/* The surfaces need to be reloaded with artwork */
  1911 			SDL_SetError("Blit surfaces were lost, reload them");
  1912 			return(-2);
  1913 		}
  1914 		SetDDerror("IDirectDrawSurface3::BltFast", result);
  1915 #ifdef DDRAW_DEBUG
  1916  fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
  1917  fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
  1918 		(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
  1919 					dstrect->x, dstrect->y);
  1920   PrintSurface("SRC", src_surface, src->flags);
  1921   PrintSurface("DST", dst_surface, dst->flags);
  1922  fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
  1923 		rect.left, rect.top, rect.right, rect.bottom);
  1924 #endif
  1925 		/* Unexpected error, fall back to software blit */
  1926 		return(src->map->sw_blit(src, srcrect, dst, dstrect));
  1927 	}
  1928 	return(0);
  1929 }
  1930 
  1931 static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
  1932 {
  1933 	int accelerated;
  1934 
  1935 	/* We need to have a DDraw surface for HW blits */
  1936 	if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1937 		/* Allocate a DDraw surface for the blit */
  1938 		if ( src->hwdata == NULL ) {
  1939 			DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
  1940 		}
  1941 	}
  1942 	if ( src->hwdata == NULL ) {
  1943 		return(0);
  1944 	}
  1945 
  1946 	/* Set initial acceleration on */
  1947 	src->flags |= SDL_HWACCEL;
  1948 
  1949 	/* Set the surface attributes */
  1950 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  1951 		if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
  1952 			src->flags &= ~SDL_HWACCEL;
  1953 		}
  1954 	}
  1955 	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  1956 		if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
  1957 			src->flags &= ~SDL_HWACCEL;
  1958 		}
  1959 	}
  1960 
  1961 	/* Check to see if final surface blit is accelerated */
  1962 	accelerated = !!(src->flags & SDL_HWACCEL);
  1963 	if ( accelerated ) {
  1964 #ifdef DDRAW_DEBUG
  1965   fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
  1966 #endif
  1967 		src->map->hw_blit = DX5_HWAccelBlit;
  1968 	}
  1969 	return(accelerated);
  1970 }
  1971 
  1972 static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1973 {
  1974 	LPDIRECTDRAWSURFACE3 dst_surface;
  1975 	RECT area;
  1976 	DDBLTFX bltfx;
  1977 	HRESULT result;
  1978 
  1979 #ifdef DDRAW_DEBUG
  1980  fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
  1981 #endif
  1982 	dst_surface = dst->hwdata->dd_writebuf;
  1983 	area.top    = (LONG)dstrect->y;
  1984 	area.bottom = (LONG)dstrect->y+dstrect->h;
  1985 	area.left   = (LONG)dstrect->x;
  1986 	area.right  = (LONG)dstrect->x+dstrect->w;
  1987 	bltfx.dwSize = sizeof(bltfx);
  1988 #if defined(NONAMELESSUNION)
  1989 	bltfx.u5.dwFillColor = color;
  1990 #else
  1991 	bltfx.dwFillColor = color;
  1992 #endif
  1993 	result = IDirectDrawSurface3_Blt(dst_surface,
  1994 			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1995 	if ( result == DDERR_SURFACELOST ) {
  1996 		IDirectDrawSurface3_Restore(dst_surface);
  1997 		result = IDirectDrawSurface3_Blt(dst_surface,
  1998 			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1999 	}
  2000 	if ( result != DD_OK ) {
  2001 		SetDDerror("IDirectDrawSurface3::Blt", result);
  2002 		return(-1);
  2003 	}
  2004 	return(0);
  2005 }
  2006 
  2007 static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
  2008 {
  2009 	DDCOLORKEY colorkey;
  2010 	HRESULT result;
  2011 
  2012 	/* Set the surface colorkey */
  2013 	colorkey.dwColorSpaceLowValue = key;
  2014 	colorkey.dwColorSpaceHighValue = key;
  2015 	result = IDirectDrawSurface3_SetColorKey(
  2016 			surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
  2017 	if ( result != DD_OK ) {
  2018 		SetDDerror("IDirectDrawSurface3::SetColorKey", result);
  2019 		return(-1);
  2020 	}
  2021 	return(0);
  2022 }
  2023 static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
  2024 {
  2025 	return(-1);
  2026 }
  2027 
  2028 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
  2029 {
  2030 	HRESULT result;
  2031 	LPDIRECTDRAWSURFACE3 dd_surface;
  2032 	DDSURFACEDESC ddsd;
  2033 
  2034 	/* Lock and load! */
  2035 	dd_surface = surface->hwdata->dd_writebuf;
  2036 	SDL_memset(&ddsd, 0, sizeof(ddsd));
  2037 	ddsd.dwSize = sizeof(ddsd);
  2038 	result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  2039 					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  2040 	if ( result == DDERR_SURFACELOST ) {
  2041 		result = IDirectDrawSurface3_Restore(
  2042 						surface->hwdata->dd_surface);
  2043 		result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
  2044 					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  2045 	}
  2046 	if ( result != DD_OK ) {
  2047 		SetDDerror("DirectDrawSurface3::Lock", result);
  2048 		return(-1);
  2049 	}
  2050 	/* Pitch might have changed -- recalculate pitch and offset */
  2051 #if defined(NONAMELESSUNION)
  2052 	if ( surface->pitch != ddsd.u1.lPitch ) {
  2053 		surface->pitch = ddsd.u1.lPitch;
  2054 #else
  2055 	if ( surface->pitch != ddsd.lPitch ) {
  2056 		surface->pitch = (Uint16)ddsd.lPitch;
  2057 #endif
  2058 		surface->offset =
  2059 			((ddsd.dwHeight-surface->h)/2)*surface->pitch +
  2060 			((ddsd.dwWidth-surface->w)/2)*
  2061 					surface->format->BytesPerPixel;
  2062 	}
  2063 	surface->pixels = ddsd.lpSurface;
  2064 	return(0);
  2065 }
  2066 
  2067 static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
  2068 {
  2069 	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  2070 	surface->pixels = NULL;
  2071 }
  2072 
  2073 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
  2074 {
  2075 	HRESULT result;
  2076 	LPDIRECTDRAWSURFACE3 dd_surface;
  2077 
  2078 	dd_surface = surface->hwdata->dd_surface;
  2079 
  2080 	/* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
  2081 	/* Dmitry Yakimov (ftech@tula.net) */
  2082 	while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
  2083 
  2084 	result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  2085 	if ( result == DDERR_SURFACELOST ) {
  2086 		result = IDirectDrawSurface3_Restore(
  2087 						surface->hwdata->dd_surface);
  2088 		while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
  2089 		result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  2090 	}
  2091 	if ( result != DD_OK ) {
  2092 		SetDDerror("DirectDrawSurface3::Flip", result);
  2093 		return(-1);
  2094 	}
  2095 	return(0);
  2096 }
  2097 
  2098 static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
  2099 {
  2100 	if ( surface->hwdata ) {
  2101 		if ( surface->hwdata->dd_surface != SDL_primary ) {
  2102 			IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
  2103 		}
  2104 		SDL_free(surface->hwdata);
  2105 		surface->hwdata = NULL;
  2106 	}
  2107 }
  2108 
  2109 void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
  2110 {
  2111 	HRESULT result;
  2112 	int i;
  2113 	RECT src, dst;
  2114 
  2115 	for ( i=0; i<numrects; ++i ) {
  2116 		src.top    = (LONG)rects[i].y;
  2117 		src.bottom = (LONG)rects[i].y+rects[i].h;
  2118 		src.left   = (LONG)rects[i].x;
  2119 		src.right  = (LONG)rects[i].x+rects[i].w;
  2120 		dst.top    = SDL_bounds.top+src.top;
  2121 		dst.left   = SDL_bounds.left+src.left;
  2122 		dst.bottom = SDL_bounds.top+src.bottom;
  2123 		dst.right  = SDL_bounds.left+src.right;
  2124 		result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  2125 					this->screen->hwdata->dd_surface, &src,
  2126 							DDBLT_WAIT, NULL);
  2127 		/* Doh!  Check for lost surface and restore it */
  2128 		if ( result == DDERR_SURFACELOST ) {
  2129 			IDirectDrawSurface3_Restore(SDL_primary);
  2130 			IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  2131 					this->screen->hwdata->dd_surface, &src,
  2132 							DDBLT_WAIT, NULL);
  2133 		}
  2134 	}
  2135 }
  2136 
  2137 void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
  2138 {
  2139 }
  2140 
  2141 /* Compress a full palette into the limited number of colors given to us
  2142    by windows.
  2143 
  2144    The "best" way to do this is to sort the colors by diversity and place
  2145    the most diverse colors into the limited palette.  Unfortunately this
  2146    results in widely varying colors being displayed in the interval during
  2147    which the windows palette has been set, and the mapping of the shadow
  2148    surface to the new palette.  This is especially noticeable during fades.
  2149 
  2150    To deal with this problem, we can copy a predetermined portion of the
  2151    full palette, and use that as the limited palette.  This allows colors
  2152    to fade smoothly as the remapping is very similar on each palette change.
  2153    Unfortunately, this breaks applications which partition the palette into
  2154    distinct and widely varying areas, expecting all colors to be available.
  2155 
  2156    I'm making them both available, chosen at compile time.
  2157    If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
  2158    otherwise the sort-by-diversity algorithm will be used.
  2159 */
  2160 #define SIMPLE_COMPRESSION
  2161 #define CS_CS_DIST(A, B) ({						\
  2162 	int r = (A.r - B.r);						\
  2163 	int g = (A.g - B.g);						\
  2164 	int b = (A.b - B.b);						\
  2165 	(r*r + g*g + b*b);						\
  2166 })
  2167 static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
  2168 {
  2169 #ifdef SIMPLE_COMPRESSION
  2170 	int i, j;
  2171 #else
  2172 	static SDL_Color zero = { 0, 0, 0, 0 };
  2173 	int i, j;
  2174 	int max, dist;
  2175 	int prev, next;
  2176 	int *pool;
  2177 	int *seen, *order;
  2178 #endif
  2179 
  2180 	/* Does this happen? */
  2181 	if ( maxcolors > ncolors ) {
  2182 		maxcolors = ncolors;
  2183 	}
  2184 
  2185 #ifdef SIMPLE_COMPRESSION
  2186 	/* Just copy the first "maxcolors" colors */
  2187 	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  2188 		SDL_colors[j].peRed = colors[i].r;
  2189 		SDL_colors[j].peGreen = colors[i].g;
  2190 		SDL_colors[j].peBlue = colors[i].b;
  2191 	}
  2192 #else
  2193 	/* Allocate memory for the arrays we use */
  2194 	pool = SDL_stack_alloc(int, 2*ncolors);
  2195 	if ( pool == NULL ) {
  2196 		/* No worries, just return */;
  2197 		return;
  2198 	}
  2199 	seen = pool;
  2200 	SDL_memset(seen, 0, ncolors*sizeof(int));
  2201 	order = pool+ncolors;
  2202 
  2203 	/* Start with the brightest color */
  2204 	max = 0;
  2205 	for ( i=0; i<ncolors; ++i ) {
  2206 		dist = CS_CS_DIST(zero, colors[i]);
  2207 		if ( dist >= max ) {
  2208 			max = dist;
  2209 			next = i;
  2210 		}
  2211 	}
  2212 	j = 0;
  2213 	order[j++] = next;
  2214 	seen[next] = 1;
  2215 	prev = next;
  2216 
  2217 	/* Keep going through all the colors */
  2218 	while ( j < maxcolors ) {
  2219 		max = 0;
  2220 		for ( i=0; i<ncolors; ++i ) {
  2221 			if ( seen[i] ) {
  2222 				continue;
  2223 			}
  2224 			dist = CS_CS_DIST(colors[i], colors[prev]);
  2225 			if ( dist >= max ) {
  2226 				max = dist;
  2227 				next = i;
  2228 			}
  2229 		}
  2230 		order[j++] = next;
  2231 		seen[next] = 1;
  2232 		prev = next;
  2233 	}
  2234 
  2235 	/* Compress the colors to the palette */
  2236 	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  2237 		SDL_colors[j].peRed = colors[order[i]].r;
  2238 		SDL_colors[j].peGreen = colors[order[i]].g;
  2239 		SDL_colors[j].peBlue = colors[order[i]].b;
  2240 	}
  2241 	SDL_stack_free(pool);
  2242 #endif /* SIMPLE_COMPRESSION */
  2243 }
  2244 
  2245 /* Set the system colormap in both fullscreen and windowed modes */
  2246 int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  2247 {
  2248 	int i;
  2249 	int alloct_all;
  2250 
  2251 	/* Copy palette colors into display palette */
  2252 	alloct_all = 0;
  2253 	if ( SDL_palette != NULL ) {
  2254 		if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  2255 			/* We can set all entries explicitly */
  2256 			for ( i=0; i< ncolors; ++i ) {
  2257 			        int j = firstcolor + i;
  2258 				SDL_colors[j].peRed = colors[i].r;
  2259 				SDL_colors[j].peGreen = colors[i].g;
  2260 				SDL_colors[j].peBlue = colors[i].b;
  2261 			}
  2262 			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2263 				firstcolor, ncolors, &SDL_colors[firstcolor]);
  2264 			alloct_all = 1;
  2265 		} else {
  2266 			/* Grab the 236 most diverse colors in the palette */
  2267 			DX5_CompressPalette(this, colors, ncolors, 236);
  2268 			/* This sends an WM_PALETTECHANGED message to us */
  2269 			colorchange_expected = 1;
  2270 			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2271 							0, 256, SDL_colors);
  2272 		}
  2273 	}
  2274 	return(alloct_all);
  2275 }
  2276 
  2277 /* Gamma code is only available on DirectX 7 and newer */
  2278 static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
  2279 {
  2280 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2281 	LPDIRECTDRAWGAMMACONTROL gamma;
  2282 	DDGAMMARAMP gamma_ramp;
  2283 	HRESULT result;
  2284 #endif
  2285 
  2286 	/* In windowed or OpenGL mode, use windib gamma code */
  2287 	if ( ! DDRAW_FULLSCREEN() ) {
  2288 		return DIB_SetGammaRamp(this, ramp);
  2289 	}
  2290 
  2291 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2292 	SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2293 	return -1;
  2294 #else
  2295 	/* Check for a video mode! */
  2296 	if ( ! SDL_primary ) {
  2297 		SDL_SetError("A video mode must be set for gamma correction");
  2298 		return(-1);
  2299 	}
  2300 
  2301 	/* Get the gamma control object */
  2302 	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2303 			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2304 	if ( result != DD_OK ) {
  2305 		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2306 		return(-1);
  2307 	}
  2308 
  2309 	/* Set up the gamma ramp */
  2310 	SDL_memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
  2311 	SDL_memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
  2312 	SDL_memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
  2313 	result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
  2314 	if ( result != DD_OK ) {
  2315 		SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
  2316 	}
  2317 
  2318 	/* Release the interface and return */
  2319 	IDirectDrawGammaControl_Release(gamma);
  2320 	return (result == DD_OK) ? 0 : -1;
  2321 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2322 }
  2323 
  2324 static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
  2325 {
  2326 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2327 	LPDIRECTDRAWGAMMACONTROL gamma;
  2328 	DDGAMMARAMP gamma_ramp;
  2329 	HRESULT result;
  2330 #endif
  2331 
  2332 	/* In windowed or OpenGL mode, use windib gamma code */
  2333 	if ( ! DDRAW_FULLSCREEN() ) {
  2334 		return DIB_GetGammaRamp(this, ramp);
  2335 	}
  2336 
  2337 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2338 	SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2339 	return -1;
  2340 #else
  2341 	/* Check for a video mode! */
  2342 	if ( ! SDL_primary ) {
  2343 		SDL_SetError("A video mode must be set for gamma correction");
  2344 		return(-1);
  2345 	}
  2346 
  2347 	/* Get the gamma control object */
  2348 	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2349 			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2350 	if ( result != DD_OK ) {
  2351 		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2352 		return(-1);
  2353 	}
  2354 
  2355 	/* Set up the gamma ramp */
  2356 	result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
  2357 	if ( result == DD_OK ) {
  2358 		SDL_memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
  2359 		SDL_memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
  2360 		SDL_memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
  2361 	} else {
  2362 		SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
  2363 	}
  2364 
  2365 	/* Release the interface and return */
  2366 	IDirectDrawGammaControl_Release(gamma);
  2367 	return (result == DD_OK) ? 0 : -1;
  2368 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2369 }
  2370 
  2371 void DX5_VideoQuit(_THIS)
  2372 {
  2373 	int i, j;
  2374 
  2375 	/* If we're fullscreen GL, we need to reset the display */
  2376 	if ( this->screen != NULL ) {
  2377 #ifndef NO_CHANGEDISPLAYSETTINGS
  2378 		if ( (this->screen->flags & (SDL_INTERNALOPENGL|SDL_FULLSCREEN)) ==
  2379 		                            (SDL_INTERNALOPENGL|SDL_FULLSCREEN) ) {
  2380 			ChangeDisplaySettings(NULL, 0);
  2381 			ShowWindow(SDL_Window, SW_HIDE);
  2382 		}
  2383 #endif
  2384 		if ( this->screen->flags & SDL_INTERNALOPENGL ) {
  2385 			WIN_GL_ShutDown(this);
  2386 		}
  2387 	}
  2388 
  2389 	/* Free any palettes we used */
  2390 	if ( SDL_palette != NULL ) {
  2391 		IDirectDrawPalette_Release(SDL_palette);
  2392 		SDL_palette = NULL;
  2393 	}
  2394 
  2395 	/* Allow the primary surface to be freed */
  2396 	if ( SDL_primary != NULL ) {
  2397 		SDL_primary = NULL;
  2398 	}
  2399 
  2400 	/* Free video mode lists */
  2401 	for ( i=0; i<NUM_MODELISTS; ++i ) {
  2402 		if ( SDL_modelist[i] != NULL ) {
  2403 			for ( j=0; SDL_modelist[i][j]; ++j )
  2404 				SDL_free(SDL_modelist[i][j]);
  2405 			SDL_free(SDL_modelist[i]);
  2406 			SDL_modelist[i] = NULL;
  2407 		}
  2408 	}
  2409 
  2410 	/* Free the window */
  2411 	DIB_QuitGamma(this);
  2412 	if ( SDL_Window ) {
  2413 		DX5_DestroyWindow(this);
  2414 	}
  2415 
  2416 	/* Free our window icon */
  2417 	if ( screen_icn ) {
  2418 		DestroyIcon(screen_icn);
  2419 		screen_icn = NULL;
  2420 	}
  2421 }
  2422 
  2423 /* Exported for the windows message loop only */
  2424 void DX5_RealizePalette(_THIS)
  2425 {
  2426 	if ( SDL_palette ) {
  2427 		IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  2428 	}
  2429 }
  2430 static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
  2431 {
  2432 	int row, col;
  2433 	Uint8 *pixels;
  2434 
  2435 	if ( surface->w && surface->h ) {
  2436 		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2437 			if ( this->LockHWSurface(this, surface) < 0 ) {
  2438 				return;
  2439 			}
  2440 		}
  2441 		for ( row=0; row<surface->h; ++row ) {
  2442 			pixels = (Uint8 *)surface->pixels+row*surface->pitch;
  2443 			for ( col=0; col<surface->w; ++col, ++pixels ) {
  2444 				*pixels = mapping[*pixels];
  2445 			}
  2446 		}
  2447 		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2448 			this->UnlockHWSurface(this, surface);
  2449 		}
  2450 		SDL_UpdateRect(surface, 0, 0, 0, 0);
  2451 	}
  2452 }
  2453 void DX5_PaletteChanged(_THIS, HWND window)
  2454 {
  2455 	SDL_Palette *palette;
  2456 	SDL_Color *saved = NULL;
  2457 	HDC hdc;
  2458 	int i;
  2459 	PALETTEENTRY *entries;
  2460 
  2461 	/* This is true when the window is closing */
  2462 	if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
  2463 		return;
  2464 
  2465 	/* We need to get the colors as they were set */
  2466 	palette = this->physpal;
  2467 	if(!palette)
  2468 	        palette = SDL_VideoSurface->format->palette;
  2469 	if ( palette == NULL ) { /* Sometimes we don't have a palette */
  2470 		return;
  2471 	}
  2472 	entries = SDL_stack_alloc(PALETTEENTRY, palette->ncolors);
  2473 	hdc = GetDC(window);
  2474 	GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
  2475 	ReleaseDC(window, hdc);
  2476 	if ( ! colorchange_expected ) {
  2477 		saved = SDL_stack_alloc(SDL_Color, palette->ncolors);
  2478 		SDL_memcpy(saved, palette->colors, 
  2479 					palette->ncolors*sizeof(SDL_Color));
  2480 	}
  2481 	for ( i=0; i<palette->ncolors; ++i ) {
  2482 		palette->colors[i].r = entries[i].peRed;
  2483 		palette->colors[i].g = entries[i].peGreen;
  2484 		palette->colors[i].b = entries[i].peBlue;
  2485 	}
  2486 	SDL_stack_free(entries);
  2487 	if ( ! colorchange_expected ) {
  2488 		Uint8 mapping[256];
  2489 
  2490 		SDL_memset(mapping, 0, sizeof(mapping));
  2491 		for ( i=0; i<palette->ncolors; ++i ) {
  2492 			mapping[i] = SDL_FindColor(palette,
  2493 					saved[i].r, saved[i].g, saved[i].b);
  2494 		}
  2495 		DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
  2496 		SDL_stack_free(saved);
  2497 	}
  2498 	colorchange_expected = 0;
  2499 
  2500 	/* Notify all mapped surfaces of the change */
  2501 	SDL_FormatChanged(SDL_VideoSurface);
  2502 }
  2503 
  2504 /* Exported for the windows message loop only */
  2505 void DX5_WinPAINT(_THIS, HDC hdc)
  2506 {
  2507 	SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  2508 }