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