src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 29 Jan 2006 09:13:36 +0000
changeset 1288 ea3888b472bf
parent 1280 f61f045343d3
child 1290 c4a5a772c5d9
permissions -rw-r--r--
Cleaned up the app registration stuff a bit
     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 )
  1137 			SetWindowLong(SDL_Window, GWL_STYLE, style);
  1138 
  1139 		/* Resize the window (copied from SDL WinDIB driver) */
  1140 		if ( !SDL_windowid ) {
  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 ( center ) {
  1172 				x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1173 				y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1174 			} else if ( SDL_windowX || SDL_windowY || window ) {
  1175 				x = bounds.left;
  1176 				y = bounds.top;
  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 )
  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 	IDirectDrawSurface_Release(dd_surface1);
  1327 
  1328 	/* Get the format of the primary DirectDraw surface */
  1329 	memset(&ddsd, 0, sizeof(ddsd));
  1330 	ddsd.dwSize = sizeof(ddsd);
  1331 	ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
  1332 	result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
  1333 	if ( result != DD_OK ) {
  1334 		SetDDerror("DirectDrawSurface::GetSurfaceDesc", result);
  1335 		return(NULL);
  1336 	}
  1337 	if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
  1338 		SDL_SetError("Primary DDRAW surface is not RGB format");
  1339 		return(NULL);
  1340 	}
  1341 
  1342 	/* Free old palette and create a new one if we're in 8-bit mode */
  1343 	if ( SDL_palette != NULL ) {
  1344 		IDirectDrawPalette_Release(SDL_palette);
  1345 		SDL_palette = NULL;
  1346 	}
  1347 #if defined(NONAMELESSUNION)
  1348 	if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
  1349 #else
  1350 	if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
  1351 #endif
  1352 		int i;
  1353 
  1354 		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1355 			/* We have access to the entire palette */
  1356 			for ( i=0; i<256; ++i ) {
  1357 				SDL_colors[i].peFlags =
  1358 						(PC_NOCOLLAPSE|PC_RESERVED);
  1359 				SDL_colors[i].peRed = 0;
  1360 				SDL_colors[i].peGreen = 0;
  1361 				SDL_colors[i].peBlue = 0;
  1362 			}
  1363 		} else {
  1364 			/* First 10 colors are reserved by Windows */
  1365 			for ( i=0; i<10; ++i ) {
  1366 				SDL_colors[i].peFlags = PC_EXPLICIT;
  1367 				SDL_colors[i].peRed = i;
  1368 				SDL_colors[i].peGreen = 0;
  1369 				SDL_colors[i].peBlue = 0;
  1370 			}
  1371 			for ( i=10; i<(10+236); ++i ) {
  1372 				SDL_colors[i].peFlags = PC_NOCOLLAPSE;
  1373 				SDL_colors[i].peRed = 0;
  1374 				SDL_colors[i].peGreen = 0;
  1375 				SDL_colors[i].peBlue = 0;
  1376 			}
  1377 			/* Last 10 colors are reserved by Windows */
  1378 			for ( i=246; i<256; ++i ) {
  1379 				SDL_colors[i].peFlags = PC_EXPLICIT;
  1380 				SDL_colors[i].peRed = i;
  1381 				SDL_colors[i].peGreen = 0;
  1382 				SDL_colors[i].peBlue = 0;
  1383 			}
  1384 		}
  1385 		result = IDirectDraw2_CreatePalette(ddraw2,
  1386 		     			(DDPCAPS_8BIT|DDPCAPS_ALLOW256),
  1387 						SDL_colors, &SDL_palette, NULL);
  1388 		if ( result != DD_OK ) {
  1389 			SetDDerror("DirectDraw2::CreatePalette", result);
  1390 			return(NULL);
  1391 		}
  1392 		result = IDirectDrawSurface3_SetPalette(SDL_primary,
  1393 								SDL_palette);
  1394 		if ( result != DD_OK ) {
  1395 			SetDDerror("DirectDrawSurface3::SetPalette", result);
  1396 			return(NULL);
  1397 		}
  1398 	}
  1399 
  1400 	/* Create our video surface using the same pixel format */
  1401 	video = current;
  1402 	if ( (width != video->w) || (height != video->h)
  1403 			|| (video->format->BitsPerPixel != 
  1404 #if defined(NONAMELESSUNION)
  1405 				ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
  1406 #else
  1407 				ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
  1408 #endif
  1409 		SDL_FreeSurface(video);
  1410 		video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
  1411 #if defined(NONAMELESSUNION)
  1412 				ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
  1413 					ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1414 					ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1415 					ddsd.ddpfPixelFormat.u4.dwBBitMask,
  1416 #else
  1417 				ddsd.ddpfPixelFormat.dwRGBBitCount,
  1418 					ddsd.ddpfPixelFormat.dwRBitMask,
  1419 					ddsd.ddpfPixelFormat.dwGBitMask,
  1420 					ddsd.ddpfPixelFormat.dwBBitMask,
  1421 #endif
  1422 								0);
  1423 		if ( video == NULL ) {
  1424 			SDL_OutOfMemory();
  1425 			return(NULL);
  1426 		}
  1427 		video->w = width;
  1428 		video->h = height;
  1429 		video->pitch = 0;
  1430 	}
  1431 	video->flags = 0;	/* Clear flags */
  1432 
  1433 	/* If not fullscreen, locking is possible, but it doesn't do what 
  1434 	   the caller really expects -- if the locked surface is written to,
  1435 	   the appropriate portion of the entire screen is modified, not 
  1436 	   the application window, as we would like.
  1437 	   Note that it is still possible to write directly to display
  1438 	   memory, but the application must respect the clip list of
  1439 	   the surface.  There might be some odd timing interactions
  1440 	   involving clip list updates and background refreshing as
  1441 	   Windows moves other windows across our window.
  1442 	   We currently don't support this, even though it might be a
  1443 	   good idea since BeOS has an implementation of BDirectWindow
  1444 	   that does the same thing.  This would be most useful for
  1445 	   applications that do complete screen updates every frame.
  1446 	    -- Fixme?
  1447 	*/
  1448 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1449 		/* Necessary if we're going from fullscreen to window */
  1450 		if ( video->pixels == NULL ) {
  1451 			video->pitch = (width*video->format->BytesPerPixel);
  1452 			/* Pitch needs to be QWORD (8-byte) aligned */
  1453 			video->pitch = (video->pitch + 7) & ~7;
  1454 			video->pixels = (void *)malloc(video->h*video->pitch);
  1455 			if ( video->pixels == NULL ) {
  1456 				if ( video != current ) {
  1457 					SDL_FreeSurface(video);
  1458 				}
  1459 				SDL_OutOfMemory();
  1460 				return(NULL);
  1461 			}
  1462 		}
  1463 		dd_surface3 = NULL;
  1464 #if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */
  1465 		if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1466 			video->flags |= SDL_HWSURFACE;
  1467 		} else {
  1468 			video->flags |= SDL_SWSURFACE;
  1469 		}
  1470 #else
  1471 		video->flags |= SDL_SWSURFACE;
  1472 #endif
  1473 		if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
  1474 			video->flags |= SDL_RESIZABLE;
  1475 		}
  1476 		if ( flags & SDL_NOFRAME ) {
  1477 			video->flags |= SDL_NOFRAME;
  1478 		}
  1479 	} else {
  1480 		/* Necessary if we're going from window to fullscreen */
  1481 		if ( video->pixels != NULL ) {
  1482 			free(video->pixels);
  1483 			video->pixels = NULL;
  1484 		}
  1485 		dd_surface3 = SDL_primary;
  1486 		video->flags |= SDL_HWSURFACE;
  1487 	}
  1488 
  1489 	/* See if the primary surface has double-buffering enabled */
  1490 	if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
  1491 		video->flags |= SDL_DOUBLEBUF;
  1492 	}
  1493 
  1494 	/* Allocate the SDL surface associated with the primary surface */
  1495 	if ( DX5_AllocDDSurface(this, video, dd_surface3,
  1496 	                        video->flags&SDL_HWSURFACE) < 0 ) {
  1497 		if ( video != current ) {
  1498 			SDL_FreeSurface(video);
  1499 		}
  1500 		return(NULL);
  1501 	}
  1502 
  1503 	/* Use the appropriate blitting function */
  1504 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1505 		video->flags |= SDL_FULLSCREEN;
  1506 		if ( video->format->palette != NULL ) {
  1507 			video->flags |= SDL_HWPALETTE;
  1508 		}
  1509 		this->UpdateRects = DX5_DirectUpdate;
  1510 	} else {
  1511 		this->UpdateRects = DX5_WindowUpdate;
  1512 	}
  1513 
  1514 	/* Make our window the proper size, set the clipper, then show it */
  1515 	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1516 		RECT bounds;
  1517 		int  x, y;
  1518 		UINT swp_flags;
  1519 		const char *window = getenv("SDL_VIDEO_WINDOW_POS");
  1520 		const char *center = getenv("SDL_VIDEO_CENTERED");
  1521 
  1522 		/* Create and set a clipper on our primary surface */
  1523 		if ( SDL_clipper == NULL ) {
  1524 			result = IDirectDraw2_CreateClipper(ddraw2,
  1525 							0, &SDL_clipper, NULL);
  1526 			if ( result != DD_OK ) {
  1527 				if ( video != current ) {
  1528 					SDL_FreeSurface(video);
  1529 				}
  1530 				SetDDerror("DirectDraw2::CreateClipper",result);
  1531 				return(NULL);
  1532 			}
  1533 		}
  1534 		result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
  1535 		if ( result != DD_OK ) {
  1536 			if ( video != current ) {
  1537 				SDL_FreeSurface(video);
  1538 			}
  1539 			SetDDerror("DirectDrawClipper::SetHWnd", result);
  1540 			return(NULL);
  1541 		}
  1542 		result = IDirectDrawSurface3_SetClipper(SDL_primary,
  1543 								SDL_clipper);
  1544 		if ( result != DD_OK ) {
  1545 			if ( video != current ) {
  1546 				SDL_FreeSurface(video);
  1547 			}
  1548 			SetDDerror("DirectDrawSurface3::SetClipper", result);
  1549 			return(NULL);
  1550 		}
  1551 
  1552 		if ( !SDL_windowX && !SDL_windowY ) {
  1553 			if ( window ) {
  1554 				if ( sscanf(window, "%d,%d", &x, &y) == 2 ) {
  1555 					SDL_windowX = x;
  1556 					SDL_windowY = y;
  1557 				}
  1558 				if ( strcmp(window, "center") == 0 ) {
  1559 					center = window;
  1560 					window = NULL;
  1561 				}
  1562 			}
  1563 		}
  1564 		swp_flags = SWP_NOCOPYBITS;
  1565 
  1566 		SDL_resizing = 1;
  1567 		bounds.left = SDL_windowX;
  1568 		bounds.top = SDL_windowY;
  1569 		bounds.right = SDL_windowX+video->w;
  1570 		bounds.bottom = SDL_windowY+video->h;
  1571 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
  1572 		width = bounds.right-bounds.left;
  1573 		height = bounds.bottom-bounds.top;
  1574 		if ( (flags & SDL_FULLSCREEN) ) {
  1575 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1576 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1577 		} else if ( center ) {
  1578 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1579 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1580 		} else if ( SDL_windowX || SDL_windowY || window ) {
  1581 			x = bounds.left;
  1582 			y = bounds.top;
  1583 		} else {
  1584 			x = y = -1;
  1585 			swp_flags |= SWP_NOMOVE;
  1586 		}
  1587 		if ( y < 0 ) { /* Cover up title bar for more client area */
  1588 			y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1589 		}
  1590 		SetWindowPos(SDL_Window, HWND_NOTOPMOST, x, y, width, height, swp_flags);
  1591 		SDL_resizing = 0;
  1592 
  1593 	}
  1594 	ShowWindow(SDL_Window, SW_SHOW);
  1595 	SetForegroundWindow(SDL_Window);
  1596 
  1597 	/* We're live! */
  1598 	return(video);
  1599 }
  1600 
  1601 struct private_hwdata {
  1602 	LPDIRECTDRAWSURFACE3 dd_surface;
  1603 	LPDIRECTDRAWSURFACE3 dd_writebuf;
  1604 };
  1605 
  1606 static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
  1607 				LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
  1608 {
  1609 	LPDIRECTDRAWSURFACE  dd_surface1;
  1610 	LPDIRECTDRAWSURFACE3 dd_surface3;
  1611 	DDSURFACEDESC ddsd;
  1612 	HRESULT result;
  1613 
  1614 	/* Clear the hardware flag, in case we fail */
  1615 	surface->flags &= ~flag;
  1616 
  1617 	/* Allocate the hardware acceleration data */
  1618 	surface->hwdata = (struct private_hwdata *)
  1619 					malloc(sizeof(*surface->hwdata));
  1620 	if ( surface->hwdata == NULL ) {
  1621 		SDL_OutOfMemory();
  1622 		return(-1);
  1623 	}
  1624 	dd_surface3 = NULL;
  1625 
  1626 	/* Set up the surface description */
  1627 	memset(&ddsd, 0, sizeof(ddsd));
  1628 	ddsd.dwSize = sizeof(ddsd);
  1629 	ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
  1630 					DDSD_PITCH|DDSD_PIXELFORMAT);
  1631 	ddsd.dwWidth = surface->w;
  1632 	ddsd.dwHeight= surface->h;
  1633 #if defined(NONAMELESSUNION)
  1634 	ddsd.u1.lPitch = surface->pitch;
  1635 #else
  1636 	ddsd.lPitch = surface->pitch;
  1637 #endif
  1638 	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1639 		ddsd.ddsCaps.dwCaps =
  1640 				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
  1641 	} else {
  1642 		ddsd.ddsCaps.dwCaps =
  1643 				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
  1644 	}
  1645 	ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  1646 	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  1647 	if ( surface->format->palette ) {
  1648 		ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  1649 	}
  1650 #if defined(NONAMELESSUNION)
  1651 	ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
  1652 	ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
  1653 	ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
  1654 	ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
  1655 #else
  1656 	ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
  1657 	ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
  1658 	ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
  1659 	ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
  1660 #endif
  1661 
  1662 	/* Create the DirectDraw video surface */
  1663 	if ( requested != NULL ) {
  1664 		dd_surface3 = requested;
  1665 	} else {
  1666 		result = IDirectDraw2_CreateSurface(ddraw2,
  1667 						&ddsd, &dd_surface1, NULL); 
  1668 		if ( result != DD_OK ) {
  1669 			SetDDerror("DirectDraw2::CreateSurface", result);
  1670 			goto error_end;
  1671 		}
  1672 		result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1673 			&IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
  1674 		IDirectDrawSurface_Release(dd_surface1);
  1675 		if ( result != DD_OK ) {
  1676 			SetDDerror("DirectDrawSurface::QueryInterface", result);
  1677 			goto error_end;
  1678 		}
  1679 	}
  1680 
  1681 	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1682 		/* Check to see whether the surface actually ended up
  1683 		   in video memory, and fail if not.  We expect the
  1684 		   surfaces we create here to actually be in hardware!
  1685 		*/
  1686 		result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
  1687 		if ( result != DD_OK ) {
  1688 			SetDDerror("DirectDrawSurface3::GetCaps", result);
  1689 			goto error_end;
  1690 		}
  1691 		if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
  1692 							DDSCAPS_VIDEOMEMORY ) {
  1693 			SDL_SetError("No room in video memory");
  1694 			goto error_end;
  1695 		}
  1696 	} else {
  1697 		/* Try to hook our surface memory */
  1698 		ddsd.dwFlags = DDSD_LPSURFACE;
  1699 		ddsd.lpSurface = surface->pixels;
  1700 		result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
  1701 								&ddsd, 0);
  1702 		if ( result != DD_OK ) {
  1703 			SetDDerror("DirectDraw2::SetSurfaceDesc", result);
  1704 			goto error_end;
  1705 		}
  1706 	
  1707 	}
  1708 
  1709 	/* Make sure the surface format was set properly */
  1710 	memset(&ddsd, 0, sizeof(ddsd));
  1711 	ddsd.dwSize = sizeof(ddsd);
  1712 	result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  1713 		&ddsd, (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1714 	if ( result != DD_OK ) {
  1715 		SetDDerror("DirectDrawSurface3::Lock", result);
  1716 		goto error_end;
  1717 	}
  1718 	IDirectDrawSurface3_Unlock(dd_surface3, NULL);
  1719 
  1720 	if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1721 		if ( ddsd.lpSurface != surface->pixels ) {
  1722 			SDL_SetError("DDraw didn't use SDL surface memory");
  1723 			goto error_end;
  1724 		}
  1725 		if (
  1726 #if defined(NONAMELESSUNION)
  1727 			ddsd.u1.lPitch
  1728 #else
  1729 			ddsd.lPitch
  1730 #endif
  1731 				 != (LONG)surface->pitch ) {
  1732 			SDL_SetError("DDraw created surface with wrong pitch");
  1733 			goto error_end;
  1734 		}
  1735 	} else {
  1736 #if defined(NONAMELESSUNION)
  1737 		surface->pitch = (Uint16)ddsd.u1.lPitch;
  1738 #else
  1739 		surface->pitch = (Uint16)ddsd.lPitch;
  1740 #endif
  1741 	}
  1742 #if defined(NONAMELESSUNION)
  1743 	if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
  1744 					surface->format->BitsPerPixel) ||
  1745 	     (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
  1746 	     (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
  1747 	     (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
  1748 #else
  1749 	if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
  1750 					surface->format->BitsPerPixel) ||
  1751 	     (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
  1752 	     (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
  1753 	     (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
  1754 #endif
  1755 		SDL_SetError("DDraw didn't use SDL surface description");
  1756 		goto error_end;
  1757 	}
  1758 	if ( (ddsd.dwWidth != (DWORD)surface->w) ||
  1759 		(ddsd.dwHeight != (DWORD)surface->h) ) {
  1760 		SDL_SetError("DDraw created surface with wrong size");
  1761 		goto error_end;
  1762 	}
  1763 
  1764 	/* Set the surface private data */
  1765 	surface->flags |= flag;
  1766 	surface->hwdata->dd_surface = dd_surface3;
  1767 	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1768 		LPDIRECTDRAWSURFACE3 dd_writebuf;
  1769 
  1770 		ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  1771 		result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
  1772 						&ddsd.ddsCaps, &dd_writebuf);
  1773 		if ( result != DD_OK ) {
  1774 			SetDDerror("DirectDrawSurface3::GetAttachedSurface",
  1775 								result);
  1776 		} else {
  1777 			dd_surface3 = dd_writebuf;
  1778 		}
  1779 	}
  1780 	surface->hwdata->dd_writebuf = dd_surface3;
  1781 
  1782 	/* We're ready to go! */
  1783 	return(0);
  1784 
  1785 	/* Okay, so goto's are cheesy, but there are so many possible
  1786 	   errors in this function, and the cleanup is the same in 
  1787 	   every single case.  Is there a better way, other than deeply
  1788 	   nesting the code?
  1789 	*/
  1790 error_end:
  1791 	if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
  1792 		IDirectDrawSurface_Release(dd_surface3);
  1793 	}
  1794 	free(surface->hwdata);
  1795 	surface->hwdata = NULL;
  1796 	return(-1);
  1797 }
  1798 
  1799 static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
  1800 {
  1801 	/* DDraw limitation -- you need to set cooperative level first */
  1802 	if ( SDL_primary == NULL ) {
  1803 		SDL_SetError("You must set a non-GL video mode first");
  1804 		return(-1);
  1805 	}
  1806 	return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
  1807 }
  1808 
  1809 #ifdef DDRAW_DEBUG
  1810 void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
  1811 {
  1812 	DDSURFACEDESC ddsd;
  1813 
  1814 	/* Lock and load! */
  1815 	memset(&ddsd, 0, sizeof(ddsd));
  1816 	ddsd.dwSize = sizeof(ddsd);
  1817 	if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
  1818 			(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
  1819 		return;
  1820 	}
  1821 	IDirectDrawSurface3_Unlock(surface, NULL);
  1822 	
  1823 	fprintf(stderr, "%s:\n", title);
  1824 	fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
  1825 		ddsd.dwWidth, ddsd.dwHeight,
  1826 		(flags & SDL_HWSURFACE) ? "hardware" : "software",
  1827 #if defined(NONAMELESSUNION)
  1828 		ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
  1829 #else
  1830 		ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
  1831 #endif
  1832 	fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
  1833 #if defined(NONAMELESSUNION)
  1834 	     		ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1835 	     		ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1836 	     		ddsd.ddpfPixelFormat.u4.dwBBitMask);
  1837 #else
  1838 	     		ddsd.ddpfPixelFormat.dwRBitMask,
  1839 	     		ddsd.ddpfPixelFormat.dwGBitMask,
  1840 	     		ddsd.ddpfPixelFormat.dwBBitMask);
  1841 #endif
  1842 }
  1843 #endif /* DDRAW_DEBUG */
  1844 
  1845 static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
  1846 					SDL_Surface *dst, SDL_Rect *dstrect)
  1847 {
  1848 	LPDIRECTDRAWSURFACE3 src_surface;
  1849 	LPDIRECTDRAWSURFACE3 dst_surface;
  1850 	DWORD flags;
  1851 	RECT rect;
  1852 	HRESULT result;
  1853 
  1854 	/* Set it up.. the desination must have a DDRAW surface */
  1855 	src_surface = src->hwdata->dd_writebuf;
  1856 	dst_surface = dst->hwdata->dd_writebuf;
  1857 	rect.top    = (LONG)srcrect->y;
  1858 	rect.bottom = (LONG)srcrect->y+srcrect->h;
  1859 	rect.left   = (LONG)srcrect->x;
  1860 	rect.right  = (LONG)srcrect->x+srcrect->w;
  1861 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
  1862 		flags = DDBLTFAST_SRCCOLORKEY;
  1863 	else
  1864 		flags = DDBLTFAST_NOCOLORKEY;
  1865 	/* FIXME:  We can remove this flag for _really_ fast blit queuing,
  1866 	           but it will affect the return values of locks and flips.
  1867 	 */
  1868 	flags |= DDBLTFAST_WAIT;
  1869 
  1870 	/* Do the blit! */
  1871 	result = IDirectDrawSurface3_BltFast(dst_surface,
  1872 			dstrect->x, dstrect->y, src_surface, &rect, flags);
  1873 	if ( result != DD_OK ) {
  1874 		if ( result == DDERR_SURFACELOST ) {
  1875 			result = IDirectDrawSurface3_Restore(src_surface);
  1876 			result = IDirectDrawSurface3_Restore(dst_surface);
  1877 			/* The surfaces need to be reloaded with artwork */
  1878 			SDL_SetError("Blit surfaces were lost, reload them");
  1879 			return(-2);
  1880 		}
  1881 		SetDDerror("IDirectDrawSurface3::BltFast", result);
  1882 #ifdef DDRAW_DEBUG
  1883  fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
  1884  fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
  1885 		(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
  1886 					dstrect->x, dstrect->y);
  1887   PrintSurface("SRC", src_surface, src->flags);
  1888   PrintSurface("DST", dst_surface, dst->flags);
  1889  fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
  1890 		rect.left, rect.top, rect.right, rect.bottom);
  1891 #endif
  1892 		/* Unexpected error, fall back to software blit */
  1893 		return(src->map->sw_blit(src, srcrect, dst, dstrect));
  1894 	}
  1895 	return(0);
  1896 }
  1897 
  1898 static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
  1899 {
  1900 	int accelerated;
  1901 
  1902 	/* We need to have a DDraw surface for HW blits */
  1903 	if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1904 		/* Allocate a DDraw surface for the blit */
  1905 		if ( src->hwdata == NULL ) {
  1906 			DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
  1907 		}
  1908 	}
  1909 	if ( src->hwdata == NULL ) {
  1910 		return(0);
  1911 	}
  1912 
  1913 	/* Set initial acceleration on */
  1914 	src->flags |= SDL_HWACCEL;
  1915 
  1916 	/* Set the surface attributes */
  1917 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  1918 		if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
  1919 			src->flags &= ~SDL_HWACCEL;
  1920 		}
  1921 	}
  1922 	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  1923 		if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
  1924 			src->flags &= ~SDL_HWACCEL;
  1925 		}
  1926 	}
  1927 
  1928 	/* Check to see if final surface blit is accelerated */
  1929 	accelerated = !!(src->flags & SDL_HWACCEL);
  1930 	if ( accelerated ) {
  1931 #ifdef DDRAW_DEBUG
  1932   fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
  1933 #endif
  1934 		src->map->hw_blit = DX5_HWAccelBlit;
  1935 	}
  1936 	return(accelerated);
  1937 }
  1938 
  1939 static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1940 {
  1941 	LPDIRECTDRAWSURFACE3 dst_surface;
  1942 	RECT area;
  1943 	DDBLTFX bltfx;
  1944 	HRESULT result;
  1945 
  1946 #ifdef DDRAW_DEBUG
  1947  fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
  1948 #endif
  1949 	dst_surface = dst->hwdata->dd_writebuf;
  1950 	area.top    = (LONG)dstrect->y;
  1951 	area.bottom = (LONG)dstrect->y+dstrect->h;
  1952 	area.left   = (LONG)dstrect->x;
  1953 	area.right  = (LONG)dstrect->x+dstrect->w;
  1954 	bltfx.dwSize = sizeof(bltfx);
  1955 #if defined(NONAMELESSUNION)
  1956 	bltfx.u5.dwFillColor = color;
  1957 #else
  1958 	bltfx.dwFillColor = color;
  1959 #endif
  1960 	result = IDirectDrawSurface3_Blt(dst_surface,
  1961 			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1962 	if ( result == DDERR_SURFACELOST ) {
  1963 		IDirectDrawSurface3_Restore(dst_surface);
  1964 		result = IDirectDrawSurface3_Blt(dst_surface,
  1965 			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1966 	}
  1967 	if ( result != DD_OK ) {
  1968 		SetDDerror("IDirectDrawSurface3::Blt", result);
  1969 		return(-1);
  1970 	}
  1971 	return(0);
  1972 }
  1973 
  1974 static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
  1975 {
  1976 	DDCOLORKEY colorkey;
  1977 	HRESULT result;
  1978 
  1979 	/* Set the surface colorkey */
  1980 	colorkey.dwColorSpaceLowValue = key;
  1981 	colorkey.dwColorSpaceHighValue = key;
  1982 	result = IDirectDrawSurface3_SetColorKey(
  1983 			surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
  1984 	if ( result != DD_OK ) {
  1985 		SetDDerror("IDirectDrawSurface3::SetColorKey", result);
  1986 		return(-1);
  1987 	}
  1988 	return(0);
  1989 }
  1990 static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
  1991 {
  1992 	return(-1);
  1993 }
  1994 
  1995 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
  1996 {
  1997 	HRESULT result;
  1998 	LPDIRECTDRAWSURFACE3 dd_surface;
  1999 	DDSURFACEDESC ddsd;
  2000 
  2001 	/* Lock and load! */
  2002 	dd_surface = surface->hwdata->dd_writebuf;
  2003 	memset(&ddsd, 0, sizeof(ddsd));
  2004 	ddsd.dwSize = sizeof(ddsd);
  2005 	result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  2006 					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  2007 	if ( result == DDERR_SURFACELOST ) {
  2008 		result = IDirectDrawSurface3_Restore(
  2009 						surface->hwdata->dd_surface);
  2010 		result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
  2011 					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  2012 	}
  2013 	if ( result != DD_OK ) {
  2014 		SetDDerror("DirectDrawSurface3::Lock", result);
  2015 		return(-1);
  2016 	}
  2017 	/* Pitch might have changed -- recalculate pitch and offset */
  2018 #if defined(NONAMELESSUNION)
  2019 	if ( surface->pitch != ddsd.u1.lPitch ) {
  2020 		surface->pitch = ddsd.u1.lPitch;
  2021 #else
  2022 	if ( surface->pitch != ddsd.lPitch ) {
  2023 		surface->pitch = (Uint16)ddsd.lPitch;
  2024 #endif
  2025 		surface->offset =
  2026 			((ddsd.dwHeight-surface->h)/2)*surface->pitch +
  2027 			((ddsd.dwWidth-surface->w)/2)*
  2028 					surface->format->BytesPerPixel;
  2029 	}
  2030 	surface->pixels = ddsd.lpSurface;
  2031 	return(0);
  2032 }
  2033 
  2034 static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
  2035 {
  2036 	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  2037 	surface->pixels = NULL;
  2038 }
  2039 
  2040 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
  2041 {
  2042 	HRESULT result;
  2043 	LPDIRECTDRAWSURFACE3 dd_surface;
  2044 
  2045 	dd_surface = surface->hwdata->dd_surface;
  2046 
  2047 	/* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
  2048 	/* Dmitry Yakimov (ftech@tula.net) */
  2049 	while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
  2050 
  2051 	result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  2052 	if ( result == DDERR_SURFACELOST ) {
  2053 		result = IDirectDrawSurface3_Restore(
  2054 						surface->hwdata->dd_surface);
  2055 		while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
  2056 		result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  2057 	}
  2058 	if ( result != DD_OK ) {
  2059 		SetDDerror("DirectDrawSurface3::Flip", result);
  2060 		return(-1);
  2061 	}
  2062 	return(0);
  2063 }
  2064 
  2065 static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
  2066 {
  2067 	if ( surface->hwdata ) {
  2068 		if ( surface->hwdata->dd_surface != SDL_primary ) {
  2069 			IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
  2070 		}
  2071 		free(surface->hwdata);
  2072 		surface->hwdata = NULL;
  2073 	}
  2074 }
  2075 
  2076 void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
  2077 {
  2078 	HRESULT result;
  2079 	int i;
  2080 	RECT src, dst;
  2081 
  2082 	for ( i=0; i<numrects; ++i ) {
  2083 		src.top    = (LONG)rects[i].y;
  2084 		src.bottom = (LONG)rects[i].y+rects[i].h;
  2085 		src.left   = (LONG)rects[i].x;
  2086 		src.right  = (LONG)rects[i].x+rects[i].w;
  2087 		dst.top    = SDL_bounds.top+src.top;
  2088 		dst.left   = SDL_bounds.left+src.left;
  2089 		dst.bottom = SDL_bounds.top+src.bottom;
  2090 		dst.right  = SDL_bounds.left+src.right;
  2091 		result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  2092 					this->screen->hwdata->dd_surface, &src,
  2093 							DDBLT_WAIT, NULL);
  2094 		/* Doh!  Check for lost surface and restore it */
  2095 		if ( result == DDERR_SURFACELOST ) {
  2096 			IDirectDrawSurface3_Restore(SDL_primary);
  2097 			IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  2098 					this->screen->hwdata->dd_surface, &src,
  2099 							DDBLT_WAIT, NULL);
  2100 		}
  2101 	}
  2102 }
  2103 
  2104 void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
  2105 {
  2106 }
  2107 
  2108 /* Compress a full palette into the limited number of colors given to us
  2109    by windows.
  2110 
  2111    The "best" way to do this is to sort the colors by diversity and place
  2112    the most diverse colors into the limited palette.  Unfortunately this
  2113    results in widely varying colors being displayed in the interval during
  2114    which the windows palette has been set, and the mapping of the shadow
  2115    surface to the new palette.  This is especially noticeable during fades.
  2116 
  2117    To deal with this problem, we can copy a predetermined portion of the
  2118    full palette, and use that as the limited palette.  This allows colors
  2119    to fade smoothly as the remapping is very similar on each palette change.
  2120    Unfortunately, this breaks applications which partition the palette into
  2121    distinct and widely varying areas, expecting all colors to be available.
  2122 
  2123    I'm making them both available, chosen at compile time.
  2124    If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
  2125    otherwise the sort-by-diversity algorithm will be used.
  2126 */
  2127 #define SIMPLE_COMPRESSION
  2128 #define CS_CS_DIST(A, B) ({						\
  2129 	int r = (A.r - B.r);						\
  2130 	int g = (A.g - B.g);						\
  2131 	int b = (A.b - B.b);						\
  2132 	(r*r + g*g + b*b);						\
  2133 })
  2134 static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
  2135 {
  2136 #ifdef SIMPLE_COMPRESSION
  2137 	int i, j;
  2138 #else
  2139 	static SDL_Color zero = { 0, 0, 0, 0 };
  2140 	int i, j;
  2141 	int max, dist;
  2142 	int prev, next;
  2143 	int *pool;
  2144 	int *seen, *order;
  2145 #endif
  2146 
  2147 	/* Does this happen? */
  2148 	if ( maxcolors > ncolors ) {
  2149 		maxcolors = ncolors;
  2150 	}
  2151 
  2152 #ifdef SIMPLE_COMPRESSION
  2153 	/* Just copy the first "maxcolors" colors */
  2154 	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  2155 		SDL_colors[j].peRed = colors[i].r;
  2156 		SDL_colors[j].peGreen = colors[i].g;
  2157 		SDL_colors[j].peBlue = colors[i].b;
  2158 	}
  2159 #else
  2160 	/* Allocate memory for the arrays we use */
  2161 	pool = (int *)alloca(2*ncolors*sizeof(int));
  2162 	if ( pool == NULL ) {
  2163 		/* No worries, just return */;
  2164 		return;
  2165 	}
  2166 	seen = pool;
  2167 	memset(seen, 0, ncolors*sizeof(int));
  2168 	order = pool+ncolors;
  2169 
  2170 	/* Start with the brightest color */
  2171 	max = 0;
  2172 	for ( i=0; i<ncolors; ++i ) {
  2173 		dist = CS_CS_DIST(zero, colors[i]);
  2174 		if ( dist >= max ) {
  2175 			max = dist;
  2176 			next = i;
  2177 		}
  2178 	}
  2179 	j = 0;
  2180 	order[j++] = next;
  2181 	seen[next] = 1;
  2182 	prev = next;
  2183 
  2184 	/* Keep going through all the colors */
  2185 	while ( j < maxcolors ) {
  2186 		max = 0;
  2187 		for ( i=0; i<ncolors; ++i ) {
  2188 			if ( seen[i] ) {
  2189 				continue;
  2190 			}
  2191 			dist = CS_CS_DIST(colors[i], colors[prev]);
  2192 			if ( dist >= max ) {
  2193 				max = dist;
  2194 				next = i;
  2195 			}
  2196 		}
  2197 		order[j++] = next;
  2198 		seen[next] = 1;
  2199 		prev = next;
  2200 	}
  2201 
  2202 	/* Compress the colors to the palette */
  2203 	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  2204 		SDL_colors[j].peRed = colors[order[i]].r;
  2205 		SDL_colors[j].peGreen = colors[order[i]].g;
  2206 		SDL_colors[j].peBlue = colors[order[i]].b;
  2207 	}
  2208 #endif /* SIMPLE_COMPRESSION */
  2209 }
  2210 
  2211 /* Set the system colormap in both fullscreen and windowed modes */
  2212 int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  2213 {
  2214 	int i;
  2215 	int alloct_all;
  2216 
  2217 	/* Copy palette colors into display palette */
  2218 	alloct_all = 0;
  2219 	if ( SDL_palette != NULL ) {
  2220 		if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  2221 			/* We can set all entries explicitly */
  2222 			for ( i=0; i< ncolors; ++i ) {
  2223 			        int j = firstcolor + i;
  2224 				SDL_colors[j].peRed = colors[i].r;
  2225 				SDL_colors[j].peGreen = colors[i].g;
  2226 				SDL_colors[j].peBlue = colors[i].b;
  2227 			}
  2228 			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2229 				firstcolor, ncolors, &SDL_colors[firstcolor]);
  2230 			alloct_all = 1;
  2231 		} else {
  2232 			/* Grab the 236 most diverse colors in the palette */
  2233 			DX5_CompressPalette(this, colors, ncolors, 236);
  2234 			/* This sends an WM_PALETTECHANGED message to us */
  2235 			colorchange_expected = 1;
  2236 			IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2237 							0, 256, SDL_colors);
  2238 		}
  2239 	}
  2240 	return(alloct_all);
  2241 }
  2242 
  2243 /* Gamma code is only available on DirectX 7 and newer */
  2244 static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
  2245 {
  2246 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2247 	LPDIRECTDRAWGAMMACONTROL gamma;
  2248 	DDGAMMARAMP gamma_ramp;
  2249 	HRESULT result;
  2250 #endif
  2251 
  2252 	/* In windowed or OpenGL mode, use windib gamma code */
  2253 	if ( ! DDRAW_FULLSCREEN() ) {
  2254 		return DIB_SetGammaRamp(this, ramp);
  2255 	}
  2256 
  2257 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2258 	SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2259 	return -1;
  2260 #else
  2261 	/* Check for a video mode! */
  2262 	if ( ! SDL_primary ) {
  2263 		SDL_SetError("A video mode must be set for gamma correction");
  2264 		return(-1);
  2265 	}
  2266 
  2267 	/* Get the gamma control object */
  2268 	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2269 			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2270 	if ( result != DD_OK ) {
  2271 		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2272 		return(-1);
  2273 	}
  2274 
  2275 	/* Set up the gamma ramp */
  2276 	memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
  2277 	memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
  2278 	memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
  2279 	result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
  2280 	if ( result != DD_OK ) {
  2281 		SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
  2282 	}
  2283 
  2284 	/* Release the interface and return */
  2285 	IDirectDrawGammaControl_Release(gamma);
  2286 	return (result == DD_OK) ? 0 : -1;
  2287 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2288 }
  2289 
  2290 static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
  2291 {
  2292 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2293 	LPDIRECTDRAWGAMMACONTROL gamma;
  2294 	DDGAMMARAMP gamma_ramp;
  2295 	HRESULT result;
  2296 #endif
  2297 
  2298 	/* In windowed or OpenGL mode, use windib gamma code */
  2299 	if ( ! DDRAW_FULLSCREEN() ) {
  2300 		return DIB_GetGammaRamp(this, ramp);
  2301 	}
  2302 
  2303 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2304 	SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2305 	return -1;
  2306 #else
  2307 	/* Check for a video mode! */
  2308 	if ( ! SDL_primary ) {
  2309 		SDL_SetError("A video mode must be set for gamma correction");
  2310 		return(-1);
  2311 	}
  2312 
  2313 	/* Get the gamma control object */
  2314 	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2315 			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2316 	if ( result != DD_OK ) {
  2317 		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2318 		return(-1);
  2319 	}
  2320 
  2321 	/* Set up the gamma ramp */
  2322 	result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
  2323 	if ( result == DD_OK ) {
  2324 		memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
  2325 		memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
  2326 		memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
  2327 	} else {
  2328 		SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
  2329 	}
  2330 
  2331 	/* Release the interface and return */
  2332 	IDirectDrawGammaControl_Release(gamma);
  2333 	return (result == DD_OK) ? 0 : -1;
  2334 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2335 }
  2336 
  2337 static void FlushMessageQueue()
  2338 {
  2339 	MSG  msg;
  2340 	while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
  2341 		if ( msg.message == WM_QUIT ) break;
  2342 		TranslateMessage( &msg );
  2343 		DispatchMessage( &msg );
  2344 	}
  2345 }
  2346 
  2347 void DX5_VideoQuit(_THIS)
  2348 {
  2349 	int i, j;
  2350 
  2351 	/* If we're fullscreen GL, we need to reset the display */
  2352 	if ( this->screen != NULL ) {
  2353 #ifndef NO_CHANGEDISPLAYSETTINGS
  2354 		if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  2355 		                            (SDL_OPENGL|SDL_FULLSCREEN) ) {
  2356 			ChangeDisplaySettings(NULL, 0);
  2357 			ShowWindow(SDL_Window, SW_HIDE);
  2358 		}
  2359 #endif
  2360 		if ( this->screen->flags & SDL_OPENGL ) {
  2361 			WIN_GL_ShutDown(this);
  2362 		}
  2363 	}
  2364 
  2365 	/* Free any palettes we used */
  2366 	if ( SDL_palette != NULL ) {
  2367 		IDirectDrawPalette_Release(SDL_palette);
  2368 		SDL_palette = NULL;
  2369 	}
  2370 
  2371 	/* Allow the primary surface to be freed */
  2372 	if ( SDL_primary != NULL ) {
  2373 		SDL_primary = NULL;
  2374 	}
  2375 
  2376 	/* Free video mode lists */
  2377 	for ( i=0; i<NUM_MODELISTS; ++i ) {
  2378 		if ( SDL_modelist[i] != NULL ) {
  2379 			for ( j=0; SDL_modelist[i][j]; ++j )
  2380 				free(SDL_modelist[i][j]);
  2381 			free(SDL_modelist[i]);
  2382 			SDL_modelist[i] = NULL;
  2383 		}
  2384 	}
  2385 
  2386 	/* Free the window */
  2387 	DIB_QuitGamma(this);
  2388 	if ( SDL_Window ) {
  2389 		DX5_DestroyWindow(this);
  2390 		FlushMessageQueue();
  2391 	}
  2392 
  2393 	/* Free our window icon */
  2394 	if ( screen_icn ) {
  2395 		DestroyIcon(screen_icn);
  2396 		screen_icn = NULL;
  2397 	}
  2398 }
  2399 
  2400 /* Exported for the windows message loop only */
  2401 void DX5_RealizePalette(_THIS)
  2402 {
  2403 	if ( SDL_palette ) {
  2404 		IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  2405 	}
  2406 }
  2407 static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
  2408 {
  2409 	int row, col;
  2410 	Uint8 *pixels;
  2411 
  2412 	if ( surface->w && surface->h ) {
  2413 		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2414 			if ( this->LockHWSurface(this, surface) < 0 ) {
  2415 				return;
  2416 			}
  2417 		}
  2418 		for ( row=0; row<surface->h; ++row ) {
  2419 			pixels = (Uint8 *)surface->pixels+row*surface->pitch;
  2420 			for ( col=0; col<surface->w; ++col, ++pixels ) {
  2421 				*pixels = mapping[*pixels];
  2422 			}
  2423 		}
  2424 		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2425 			this->UnlockHWSurface(this, surface);
  2426 		}
  2427 		SDL_UpdateRect(surface, 0, 0, 0, 0);
  2428 	}
  2429 }
  2430 void DX5_PaletteChanged(_THIS, HWND window)
  2431 {
  2432 	SDL_Palette *palette;
  2433 	SDL_Color *saved = NULL;
  2434 	HDC hdc;
  2435 	int i;
  2436 	PALETTEENTRY *entries;
  2437 
  2438 	/* This is true when the window is closing */
  2439 	if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
  2440 		return;
  2441 
  2442 	/* We need to get the colors as they were set */
  2443 	palette = this->physpal;
  2444 	if(!palette)
  2445 	        palette = SDL_VideoSurface->format->palette;
  2446 	if ( palette == NULL ) { /* Sometimes we don't have a palette */
  2447 		return;
  2448 	}
  2449 	entries = (PALETTEENTRY *)alloca(palette->ncolors*sizeof(*entries));
  2450 	hdc = GetDC(window);
  2451 	GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
  2452 	ReleaseDC(window, hdc);
  2453 	if ( ! colorchange_expected ) {
  2454 		saved = (SDL_Color *)alloca(palette->ncolors*sizeof(SDL_Color));
  2455 		memcpy(saved, palette->colors, 
  2456 					palette->ncolors*sizeof(SDL_Color));
  2457 	}
  2458 	for ( i=0; i<palette->ncolors; ++i ) {
  2459 		palette->colors[i].r = entries[i].peRed;
  2460 		palette->colors[i].g = entries[i].peGreen;
  2461 		palette->colors[i].b = entries[i].peBlue;
  2462 	}
  2463 	if ( ! colorchange_expected ) {
  2464 		Uint8 mapping[256];
  2465 
  2466 		memset(mapping, 0, sizeof(mapping));
  2467 		for ( i=0; i<palette->ncolors; ++i ) {
  2468 			mapping[i] = SDL_FindColor(palette,
  2469 					saved[i].r, saved[i].g, saved[i].b);
  2470 		}
  2471 		DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
  2472 	}
  2473 	colorchange_expected = 0;
  2474 
  2475 	/* Notify all mapped surfaces of the change */
  2476 	SDL_FormatChanged(SDL_VideoSurface);
  2477 }
  2478 
  2479 /* Exported for the windows message loop only */
  2480 void DX5_WinPAINT(_THIS, HDC hdc)
  2481 {
  2482 	SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  2483 }