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