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