1 // Windows video functions.
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <windows.h>
7 #include <wtypes.h>
8 #include <ddraw.h>
9 #ifdef __GCC__
10 #include <Windows32/Errors.h>
11 #endif
12 #include "gr.h"
13 #include "grdef.h"
14 #include "palette.h"
15 #include "u_mem.h"
16 #include "error.h"
17 #include "vers_id.h"
18 
19 #include "gamefont.h"
20 
21 //added 10/05/98 by Matt Mueller - make fullscreen mode optional
22 #include "args.h"
23 
24 //removed 07/11/99 by adb - now option
25 ////added 02/20/99 by adb - put descent in a window, sort of. Needed for debugging
26 ////(needs a 256 color mode to be useful)
27 //#ifndef NDEBUG
28 //#define DD_NOT_EXCL
29 //#endif
30 //end remove - adb
31 
32 char *backbuffer = NULL;
33 
34 int gr_installed = 0;
35 
36 // Min without sideeffects.
37 #ifdef _MSC_VER
38 #define inline __inline
39 #endif
40 
41 #undef min
min(int x,int y)42 inline static int min(int x, int y) { return x < y ? x : y; }
43 
44 // Windows specific
45 HINSTANCE hInst;
46 HWND g_hWnd;
47 LPDIRECTDRAW            lpDD;
48 LPDIRECTDRAWSURFACE     lpDDSPrimary;
49 LPDIRECTDRAWSURFACE     lpDDSOne;
50 LPDIRECTDRAWPALETTE     lpDDPal;
51 PALETTEENTRY pe[256];
52 
53 //added 02/20/99 by adb - put descent in a window, sort of. Needed for debugging
54 //(needs a 256 color mode to be useful)
55 //#define DD_NOT_EXCL
56 
57 void gr_palette_clear(); // Function prototype for gr_init;
58 
59 
DDerror(int code)60 static char *DDerror(int code)
61 {
62 	static char *error;
63 	switch (code) {
64 /*                case DDERR_GENERIC:
65 			error = "Undefined error!";
66                         break;*/
67 		case DDERR_EXCEPTION:
68 			error = "Exception encountered";
69 			break;
70 		case DDERR_INVALIDOBJECT:
71 			error = "Invalid object";
72 			break;
73 /*                case DDERR_INVALIDPARAMS:
74 			error = "Invalid parameters";
75                         break;*/
76 		case DDERR_NOTFOUND:
77 			error = "Object not found";
78 			break;
79 		case DDERR_INVALIDRECT:
80 			error = "Invalid rectangle";
81 			break;
82 		case DDERR_INVALIDCAPS:
83 			error = "Invalid caps member";
84 			break;
85 		case DDERR_INVALIDPIXELFORMAT:
86 			error = "Invalid pixel format";
87 			break;
88 /*                case DDERR_OUTOFMEMORY:
89 			error = "Out of memory";
90                         break;*/
91 		case DDERR_OUTOFVIDEOMEMORY:
92 			error = "Out of video memory";
93 			break;
94 		case DDERR_SURFACEBUSY:
95 			error = "Surface busy";
96 			break;
97 		case DDERR_SURFACELOST:
98 			error = "Surface was lost";
99 			break;
100 		case DDERR_WASSTILLDRAWING:
101 			error = "DirectDraw is still drawing";
102 			break;
103 		case DDERR_INVALIDSURFACETYPE:
104 			error = "Invalid surface type";
105 			break;
106 		case DDERR_NOEXCLUSIVEMODE:
107 			error = "Not in exclusive access mode";
108 			break;
109 		case DDERR_NOPALETTEATTACHED:
110 			error = "No palette attached";
111 			break;
112 		case DDERR_NOPALETTEHW:
113 			error = "No palette hardware";
114 			break;
115 		case DDERR_NOT8BITCOLOR:
116 			error = "Not 8-bit color";
117 			break;
118 		case DDERR_EXCLUSIVEMODEALREADYSET:
119 			error = "Exclusive mode was already set";
120 			break;
121 		case DDERR_HWNDALREADYSET:
122 			error = "Window handle already set";
123 			break;
124 		case DDERR_HWNDSUBCLASSED:
125 			error = "Window handle is subclassed";
126 			break;
127 		case DDERR_NOBLTHW:
128 			error = "No blit hardware";
129 			break;
130 		case DDERR_IMPLICITLYCREATED:
131 			error = "Surface was implicitly created";
132 			break;
133 		case DDERR_INCOMPATIBLEPRIMARY:
134 			error = "Incompatible primary surface";
135 			break;
136 		case DDERR_NOCOOPERATIVELEVELSET:
137 			error = "No cooperative level set";
138 			break;
139 		case DDERR_NODIRECTDRAWHW:
140 			error = "No DirectDraw hardware";
141 			break;
142 		case DDERR_NOEMULATION:
143 			error = "No emulation available";
144 			break;
145 		case DDERR_NOFLIPHW:
146 			error = "No flip hardware";
147 			break;
148 		case DDERR_NOTFLIPPABLE:
149 			error = "Surface not flippable";
150 			break;
151 		case DDERR_PRIMARYSURFACEALREADYEXISTS:
152 			error = "Primary surface already exists";
153 			break;
154 		case DDERR_UNSUPPORTEDMODE:
155 			error = "Unsupported mode";
156 			break;
157 		case DDERR_WRONGMODE:
158 			error = "Surface created in different mode";
159 			break;
160 /*                case DDERR_UNSUPPORTED:
161 			error = "Operation not supported";
162                         break;*/
163 		default:
164                 error = "unknown";
165 			break;
166 	}
167 	return error;
168 }
169 
170 
gr_update()171 void gr_update()
172 {
173   DDSURFACEDESC       ddsd;
174   HRESULT             ddrval;
175   int i;
176   int w, h;
177   char *j;
178   char *k;
179 
180   ddsd.dwSize=sizeof(ddsd);
181   ddrval=IDirectDrawSurface_Lock(lpDDSPrimary,NULL,&ddsd,0,NULL);
182   if (ddrval!=DD_OK) {
183    printf("lock failed, %s\n", DDerror(ddrval));
184    Assert(ddrval==DD_OK);
185   }
186 
187   j=backbuffer; k=ddsd.lpSurface;
188   h=grd_curscreen->sc_canvas.cv_bitmap.bm_h;
189   w=grd_curscreen->sc_canvas.cv_bitmap.bm_w;
190   for (i=0; i<h; i++) {
191     memcpy(k, j, w);
192   j+=grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize;
193   //j+=ddsd.dwWidth;
194 #ifdef NONAMELESSUNION
195   k+=ddsd.u1.lPitch;
196 #else
197   k+=ddsd.lPitch;
198 #endif
199   }
200   IDirectDrawSurface_Unlock(lpDDSPrimary,NULL);
201 /*   while (1)
202  {
203    ddrval=IDirectDrawSurface_Flip(lpDDSPrimary,NULL,0);
204    if (ddrval == DD_OK)
205    {
206      printf("Flip was successful\n");
207      break;
208    }
209    if (ddrval == DDERR_SURFACELOST)
210    {
211       printf("surface was lost\n");
212      ddrval=IDirectDrawSurface_Restore(lpDDSPrimary);
213      if (ddrval != DD_OK)
214      {
215        printf("restore failed\n");
216        break;
217      }
218    }
219    if (ddrval == DDERR_WASSTILLDRAWING )
220    {
221      printf("was still drawing\n");
222      break;
223    }
224  }*/
225 }
226 
227 
228 
gr_set_mode(u_int32_t mode)229 int gr_set_mode(u_int32_t mode)
230 {
231         DDSURFACEDESC       ddsd;
232 //        DDSURFACEDESC       DDSDesc;
233 //        DDSCAPS             ddcaps;
234         HRESULT             ddrval;
235 	unsigned int w,h;
236 
237 	if (mode<=0)
238 		return 0;
239 
240 	w=SM_W(mode);
241 	h=SM_H(mode);
242 
243         if(lpDDSPrimary!=NULL)
244         {
245             IDirectDrawSurface_Release(lpDDSPrimary);
246             lpDDSPrimary=NULL;
247         }
248 
249         if (backbuffer) free(backbuffer);
250 
251 
252 	//changed 07/11/99 by adb - nonfullscreen mode now option
253 	if (!FindArg("-semiwin"))
254 	{
255         ddrval=IDirectDraw_SetDisplayMode(lpDD,w,h,8);
256 
257         if (ddrval!=DD_OK)
258         {
259           fprintf(stderr, "Hmmm... I had a problem changing screen modes... is %ix%ix8 supported? If so, try again... :-( %s\n",w,h, DDerror(ddrval));
260           return -3; // This is **not** good...
261         }
262 	}
263 	//end changes - adb
264        ddsd.dwSize=sizeof(ddsd);
265        ddsd.dwFlags=DDSD_CAPS /*| DDSD_BACKBUFFERCOUNT*/;
266        ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE /*| DDSCAPS_FLIP | DDSCAPS_COMPLEX*/;
267        //ddsd.dwBackBufferCount=1;
268 
269        ddrval=IDirectDraw_CreateSurface(lpDD,&ddsd,&lpDDSPrimary,NULL);
270        if(ddrval!=DD_OK)
271        {
272         return -4;
273        }
274 
275 #if 0
276        memset(&ddcaps,0,sizeof(ddcaps));
277 //       ddcaps.dwSize=sizeof(ddcaps);
278        ddcaps.dwCaps=DDSCAPS_BACKBUFFER;
279 
280        ddrval=IDirectDrawSurface_GetAttachedSurface(lpDDSPrimary,&ddcaps,&lpDDSOne);
281        Assert(ddrval==DD_OK);
282        if(lpDDSOne==NULL)
283        {
284          return -5;
285        }
286 #endif
287 
288        ddrval=IDirectDraw_CreatePalette(lpDD,DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,pe,&lpDDPal,NULL);
289        Assert(ddrval==DD_OK);
290        if(ddrval!=DD_OK)
291        {
292          return FALSE;
293        }
294 
295        IDirectDrawSurface_SetPalette(lpDDSPrimary,lpDDPal);
296 //       IDirectDrawSurface_SetPalette(lpDDSOne,lpDDPal);
297 
298        gr_palette_clear();
299 
300        memset( grd_curscreen, 0, sizeof(grs_screen));
301        grd_curscreen->sc_mode = mode;
302        grd_curscreen->sc_w = w;
303        grd_curscreen->sc_h = h;
304        grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
305        grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
306        grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
307        grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
308        grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
309        grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR;
310 
311        backbuffer = malloc(w*h);
312        memset(backbuffer, 0, w*h);
313        grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)backbuffer;
314 
315        ddsd.dwSize=sizeof(ddsd);
316        ddrval=IDirectDrawSurface_Lock(lpDDSPrimary,NULL,&ddsd,0,NULL);
317        if(ddrval!=DD_OK)
318        {
319         return -6;
320        }
321 
322        // bm_rowsize is for backbuffer, so always w -- adb
323        grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w;
324        //grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = (short)ddsd.lPitch;
325 
326        memset(ddsd.lpSurface,0,w*h); // Black the canvas out to stop nasty kludgy display
327        IDirectDrawSurface_Unlock(lpDDSPrimary,NULL);
328 
329        gr_set_current_canvas(NULL);
330 
331 	   gamefont_choose_game_font(w,h);
332 
333        printf("Successfully completed set_mode\n");
334        return 0;
335 }
336 
337 
338 
Win32_DoSetPalette(PALETTEENTRY * rgpe)339 void Win32_DoSetPalette (PALETTEENTRY *rgpe)
340 {
341 	IDirectDraw_WaitForVerticalBlank(lpDD,DDWAITVB_BLOCKBEGIN,NULL);
342 	IDirectDrawPalette_SetEntries(lpDDPal,0,0,256,rgpe);
343 }
344 
Win32_DoGetPalette(PALETTEENTRY * rgpe)345 void Win32_DoGetPalette (PALETTEENTRY *rgpe)
346 {
347 	IDirectDrawPalette_GetEntries(lpDDPal,0,0,256,rgpe);
348 }
349 
350 //added 07/11/99 by adb for d3d
Win32_MakePalVisible(void)351 void Win32_MakePalVisible(void)
352 {
353 }
354 //end additions - adb
355 
356 void gr_close(void);
357 
gr_init(int mode)358 int gr_init(int mode)
359 {
360  int retcode;
361  	// Only do this function once!
362 	if (gr_installed==1)
363 		return -1;
364 	MALLOC( grd_curscreen,grs_screen,1 );
365 	memset( grd_curscreen, 0, sizeof(grs_screen));
366 
367 	// Set the mode.
368 	if ((retcode=gr_set_mode(mode)))
369 	{
370 		return retcode;
371 	}
372 	grd_curscreen->sc_canvas.cv_color = 0;
373 	grd_curscreen->sc_canvas.cv_drawmode = 0;
374 	grd_curscreen->sc_canvas.cv_font = NULL;
375 	grd_curscreen->sc_canvas.cv_font_fg_color = 0;
376 	grd_curscreen->sc_canvas.cv_font_bg_color = 0;
377 	gr_set_current_canvas( &grd_curscreen->sc_canvas );
378 
379 	gr_installed = 1;
380 	// added on 980913 by adb to add cleanup
381 	atexit(gr_close);
382 	// end changes by adb
383 
384 	return 0;
385 }
386 
gr_close(void)387 void gr_close(void)
388 {
389 	if (gr_installed==1)
390 	{
391 		gr_installed = 0;
392 		free(grd_curscreen);
393 		free(backbuffer);
394 	}
395 }
396 
397 
398