added UDP support for win32
[btb/d2x.git] / arch / win32 / gr.c
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
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
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
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
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
339 void Win32_DoSetPalette (PALETTEENTRY *rgpe)
340 {
341         IDirectDraw_WaitForVerticalBlank(lpDD,DDWAITVB_BLOCKBEGIN,NULL);
342         IDirectDrawPalette_SetEntries(lpDDPal,0,0,256,rgpe);
343 }
344
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
351 void Win32_MakePalVisible(void)
352 {
353 }
354 //end additions - adb
355
356 void gr_close(void);
357
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
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