]> icculus.org git repositories - btb/d2x.git/blob - main/gamerend.c
comments/formatting
[btb/d2x.git] / main / gamerend.c
1 /* $Id: gamerend.c,v 1.11 2003-10-10 09:36:35 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Stuff for rendering the HUD
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #ifdef RCS
26 static char rcsid[] = "$Id: gamerend.c,v 1.11 2003-10-10 09:36:35 btb Exp $";
27 #endif
28
29 #ifdef WINDOWS
30 #include "desw.h"
31 #include "winapp.h"
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37
38 #include "pstypes.h"
39 #include "console.h"
40 #include "pa_enabl.h"                   //$$POLY_ACC
41 #include "inferno.h"
42 #include "error.h"
43 #include "mono.h"
44 #include "gr.h"
45 #include "palette.h"
46 #include "ibitblt.h"
47 #include "bm.h"
48 #include "player.h"
49 #include "render.h"
50 #include "menu.h"
51 #include "newmenu.h"
52 #include "screens.h"
53 #include "fix.h"
54 #include "robot.h"
55 #include "game.h"
56 #include "gauges.h"
57 #include "gamefont.h"
58 #include "newdemo.h"
59 #include "text.h"
60 #include "multi.h"
61 #include "endlevel.h"
62 #include "cntrlcen.h"
63 #include "powerup.h"
64 #include "laser.h"
65 #include "playsave.h"
66 #include "automap.h"
67 #include "mission.h"
68 #include "gameseq.h"
69
70 #if defined(POLY_ACC)
71 #include "poly_acc.h"
72 #endif
73
74 #ifdef OGL
75 #include "ogl_init.h"
76 #endif
77
78 extern fix Cruise_speed;
79 extern int LinearSVGABuffer;
80 extern int Current_display_mode;
81 extern cvar_t r_framerate;
82
83
84 #ifdef WINDOWS
85 cockpit_span_line win_cockpit_mask[480];
86 void win_do_emul_ibitblt(dd_grs_canvas *csrc, dd_grs_canvas *cdest);
87 #endif
88
89
90 #ifndef NDEBUG
91 extern int Debug_pause;                         //John's debugging pause system
92 #endif
93
94 #ifndef RELEASE
95 extern int Saving_movie_frames;
96 #else
97 #define Saving_movie_frames 0
98 #endif
99
100 // Returns the length of the first 'n' characters of a string.
101 int string_width( char * s, int n )
102 {
103         int w,h,aw;
104         char p;
105         p = s[n];
106         s[n] = 0;
107         gr_get_string_size( s, &w, &h, &aw );
108         s[n] = p;
109         return w;
110 }
111
112 // Draw string 's' centered on a canvas... if wider than
113 // canvas, then wrap it.
114 void draw_centered_text( int y, char * s )
115 {
116         int i, l;
117         char p;
118
119         l = strlen(s);
120
121         if ( string_width( s, l ) < grd_curcanv->cv_bitmap.bm_w )       {
122                 gr_string( 0x8000, y, s );
123                 return;
124         }
125
126         for (i=0; i<l; i++ )    {
127                 if ( string_width(s,i) > (grd_curcanv->cv_bitmap.bm_w - 16) )   {
128                         p = s[i];
129                         s[i] = 0;
130                         gr_string( 0x8000, y, s );
131                         s[i] = p;
132                         gr_string( 0x8000, y+grd_curcanv->cv_font->ft_h+1, &s[i] );
133                         return;
134                 }
135         }
136 }
137
138 extern ubyte DefiningMarkerMessage;
139 extern char Marker_input[];
140
141 #define MAX_MARKER_MESSAGE_LEN 120
142 void game_draw_marker_message()
143 {
144         char temp_string[MAX_MARKER_MESSAGE_LEN+25];
145
146         if ( DefiningMarkerMessage)
147           {
148                 gr_set_curfont( GAME_FONT );    //GAME_FONT 
149                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
150                 sprintf( temp_string, "Marker: %s_", Marker_input );
151                 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
152           }
153
154 }
155
156 #ifdef NETWORK
157 void game_draw_multi_message()
158 {
159         char temp_string[MAX_MULTI_MESSAGE_LEN+25];
160
161         if ( (Game_mode&GM_MULTI) && (multi_sending_message))   {
162                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
163                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
164                 sprintf( temp_string, "%s: %s_", TXT_MESSAGE, Network_message );
165                 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
166
167         }
168
169         if ( (Game_mode&GM_MULTI) && (multi_defining_message))  {
170                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
171                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
172                 sprintf( temp_string, "%s #%d: %s_", TXT_MACRO, multi_defining_message, Network_message );
173                 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
174         }
175 }
176 #endif
177
178 //these should be in gr.h 
179 #define cv_w  cv_bitmap.bm_w
180 #define cv_h  cv_bitmap.bm_h
181
182 fix frame_time_list[8] = {0,0,0,0,0,0,0,0};
183 fix frame_time_total=0;
184 int frame_time_cntr=0;
185
186 void ftoa(char *string, fix f)
187 {
188         int decimal, fractional;
189         
190         decimal = f2i(f);
191         fractional = ((f & 0xffff)*100)/65536;
192         if (fractional < 0 )
193                 fractional *= -1;
194         if (fractional > 99 ) fractional = 99;
195         sprintf( string, "%d.%02d", decimal, fractional );
196 }
197
198 void show_framerate()
199 {
200         char temp[50];
201    //static int q;
202
203         fix rate;
204         int x = 8, y = 5; // position measured from lower right corner
205
206         frame_time_total += RealFrameTime - frame_time_list[frame_time_cntr];
207         frame_time_list[frame_time_cntr] = RealFrameTime;
208         frame_time_cntr = (frame_time_cntr+1)%8;
209
210         rate = fixdiv(f1_0*8,frame_time_total);
211
212         gr_set_curfont( GAME_FONT );    
213         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
214
215         ftoa( temp, rate );     // Convert fixed to string
216         if (Game_mode & GM_MULTI)
217                 y = 7;
218         gr_printf(grd_curcanv->cv_w-(x*GAME_FONT->ft_w),grd_curcanv->cv_h-y*(GAME_FONT->ft_h+GAME_FONT->ft_h/4),"FPS: %s ", temp );
219 //   if ( !( q++ % 30 ) )
220 //      mprintf( (0,"fps: %s\n", temp ) );
221 }
222
223 #ifndef NDEBUG
224
225 fix Show_view_text_timer = -1;
226
227 void draw_window_label()
228 {
229         if ( Show_view_text_timer > 0 )
230         {
231                 char *viewer_name,*control_name;
232                 char    *viewer_id;
233                 Show_view_text_timer -= FrameTime;
234                 gr_set_curfont( GAME_FONT );
235
236                 viewer_id = "";
237                 switch( Viewer->type )
238                 {
239                         case OBJ_FIREBALL:      viewer_name = "Fireball"; break;
240                         case OBJ_ROBOT:         viewer_name = "Robot";
241 #ifdef EDITOR
242                                                                                 viewer_id = Robot_names[Viewer->id];
243 #endif
244                                 break;
245                         case OBJ_HOSTAGE:               viewer_name = "Hostage"; break;
246                         case OBJ_PLAYER:                viewer_name = "Player"; break;
247                         case OBJ_WEAPON:                viewer_name = "Weapon"; break;
248                         case OBJ_CAMERA:                viewer_name = "Camera"; break;
249                         case OBJ_POWERUP:               viewer_name = "Powerup";
250 #ifdef EDITOR
251                                                                                 viewer_id = Powerup_names[Viewer->id];
252 #endif
253                                 break;
254                         case OBJ_DEBRIS:                viewer_name = "Debris"; break;
255                         case OBJ_CNTRLCEN:      viewer_name = "Reactor"; break;
256                         default:                                        viewer_name = "Unknown"; break;
257                 }
258
259                 switch ( Viewer->control_type) {
260                         case CT_NONE:                   control_name = "Stopped"; break;
261                         case CT_AI:                             control_name = "AI"; break;
262                         case CT_FLYING:         control_name = "Flying"; break;
263                         case CT_SLEW:                   control_name = "Slew"; break;
264                         case CT_FLYTHROUGH:     control_name = "Flythrough"; break;
265                         case CT_MORPH:                  control_name = "Morphing"; break;
266                         default:                                        control_name = "Unknown"; break;
267                 }
268
269                 gr_set_fontcolor( gr_getcolor(31, 0, 0), -1 );
270                 gr_printf( 0x8000, 45, "%i: %s [%s] View - %s",Viewer-Objects, viewer_name, viewer_id, control_name );
271
272         }
273 }
274 #endif
275
276 extern int Game_window_x;
277 extern int Game_window_y;
278 extern int Game_window_w;
279 extern int Game_window_h;
280 extern int max_window_w;
281 extern int max_window_h;
282
283 void render_countdown_gauge()
284 {
285         if (!Endlevel_sequence && Control_center_destroyed  && (Countdown_seconds_left>-1)) { // && (Countdown_seconds_left<127))       {
286                 int     y;
287
288                 #if !defined(D2_OEM) && !defined(SHAREWARE)             // no countdown on registered only
289                 //      On last level, we don't want a countdown.
290                 if ((Current_mission_num == Builtin_mission_num) && (Current_level_num == Last_level))
291             {           
292              if (!(Game_mode & GM_MULTI))
293                    return;
294                   if (Game_mode & GM_MULTI_ROBOTS)
295                         return;
296             }    
297                 #endif
298
299                 gr_set_curfont( SMALL_FONT );
300                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
301                 y = SMALL_FONT->ft_h*4;
302                 if (Cockpit_mode == CM_FULL_SCREEN)
303                         y += SMALL_FONT->ft_h*2;
304
305                 if (Player_is_dead)
306                         y += SMALL_FONT->ft_h*2;
307
308                 //if (!((Cockpit_mode == CM_STATUS_BAR) && (Game_window_y >= 19)))
309                 //      y += 5;
310                 gr_printf(0x8000, y, "T-%d s", Countdown_seconds_left );
311         }
312 }
313
314 void game_draw_hud_stuff()
315 {
316 #ifdef MACINTOSH
317         int odisplay_mode = Current_display_mode;
318         if (Scanline_double) {
319                 FontHires = 0;
320                 Current_display_mode = 0;
321         }
322 #endif
323
324
325         //mprintf ((0,"Linear is %d!\n",LinearSVGABuffer));
326         
327         #ifndef NDEBUG
328         if (Debug_pause) {
329                 gr_set_curfont( MEDIUM1_FONT );
330                 gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 ); // gr_getcolor(31,0,0));
331                 gr_ustring( 0x8000, 85/2, "Debug Pause - Press P to exit" );
332         }
333         #endif
334
335         #ifndef NDEBUG
336         draw_window_label();
337         #endif
338
339 #ifdef NETWORK
340         game_draw_multi_message();
341 #endif
342
343    game_draw_marker_message();
344
345 //   if (Game_mode & GM_MULTI)
346 //    {
347 //     if (Netgame.PlayTimeAllowed)
348 //       game_draw_time_left ();
349 //  }
350
351         if ((Newdemo_state == ND_STATE_PLAYBACK) || (Newdemo_state == ND_STATE_RECORDING)) {
352                 char message[128];
353                 int h,w,aw;
354
355                 if (Newdemo_state == ND_STATE_PLAYBACK) {
356                         if (Newdemo_vcr_state != ND_STATE_PRINTSCREEN) {
357                                 sprintf(message, "%s (%d%%%% %s)", TXT_DEMO_PLAYBACK, newdemo_get_percent_done(), TXT_DONE);
358                         } else {
359                                 sprintf (message, " ");
360                         }
361                 } else 
362                         sprintf (message, TXT_DEMO_RECORDING);
363
364                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
365                 gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
366
367                 gr_get_string_size(message, &w, &h, &aw );
368                 #ifdef MACINTOSH
369                 if (Scanline_double)            // double height if scanline doubling since we have the correct
370                         h += h;                                 // font for printing, but the wrong height.
371                 #endif
372                 if (Cockpit_mode == CM_FULL_COCKPIT) {
373                         if (grd_curcanv->cv_bitmap.bm_h > 240)
374                                 h += 40;
375                         else
376                                 h += 15;
377                 } else if ( Cockpit_mode == CM_LETTERBOX )
378                         h += 7;
379                 if (Cockpit_mode != CM_REAR_VIEW && !Saving_movie_frames)
380                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, grd_curcanv->cv_bitmap.bm_h - h - 2, message );
381         }
382
383         render_countdown_gauge();
384
385         if ( Player_num > -1 && Viewer->type==OBJ_PLAYER && Viewer->id==Player_num )    {
386                 int     x = 3;
387                 int     y = grd_curcanv->cv_bitmap.bm_h;
388
389                 gr_set_curfont( GAME_FONT );
390                 gr_set_fontcolor( gr_getcolor(0, 31, 0), -1 );
391                 if (Cruise_speed > 0) {
392                         int line_spacing = GAME_FONT->ft_h + GAME_FONT->ft_h/4;
393
394 mprintf((0,"line_spacing=%d ",line_spacing));
395
396                         if (Cockpit_mode==CM_FULL_SCREEN) {
397                                 if (Game_mode & GM_MULTI)
398                                         y -= line_spacing * 11; //64
399                                 else
400                                         y -= line_spacing * 6;  //32
401                         } else if (Cockpit_mode == CM_STATUS_BAR) {
402                                 if (Game_mode & GM_MULTI)
403                                         y -= line_spacing * 8;  //48
404                                 else
405                                         y -= line_spacing * 4;  //24
406                         } else {
407                                 y = line_spacing * 2;   //12
408                                 x = 20+2;
409                         }
410
411                         gr_printf( x, y, "%s %2d%%", TXT_CRUISE, f2i(Cruise_speed) );
412                 }
413         }
414
415         if (r_framerate.value)
416                 show_framerate();
417
418         if ( (Newdemo_state == ND_STATE_PLAYBACK) )
419                 Game_mode = Newdemo_game_mode;
420
421         draw_hud();
422
423         if ( (Newdemo_state == ND_STATE_PLAYBACK) )
424                 Game_mode = GM_NORMAL;
425
426         if ( Player_is_dead )
427                 player_dead_message();
428
429 #ifdef MACINTOSH
430         if (Scanline_double) {
431                 FontHires = 1;
432                 Current_display_mode = odisplay_mode;
433         }
434 #endif
435 }
436
437 extern int gr_bitblt_dest_step_shift;
438 extern int gr_wait_for_retrace;
439 extern int gr_bitblt_double;
440
441 #if 0
442 void expand_row(ubyte * dest, ubyte * src, int num_src_pixels );
443 #pragma aux expand_row parm [edi] [esi] [ecx] modify exact [ecx esi edi eax ebx] = \
444         "add    esi, ecx"                       \
445         "dec    esi"                                    \
446         "add    edi, ecx"                       \
447         "add    edi, ecx"                       \
448         "dec    edi"                                    \
449         "dec    edi"                                    \
450 "nextpixel:"                                    \
451         "mov    al,[esi]"                       \
452         "mov    ah, al"                         \
453         "dec    esi"                                    \
454         "mov    [edi], ax"                      \
455         "dec    edi"                                    \
456         "dec    edi"                                    \
457         "dec    ecx"                                    \
458         "jnz    nextpixel"                      \
459 "done:"
460 #else
461 void expand_row(ubyte * dest, ubyte * src, int num_src_pixels )
462 {
463         int i;
464         
465         for (i = 0; i < num_src_pixels; i++) {
466                 *dest++ = *src;
467                 *dest++ = *src++;
468         }
469 }
470 #endif
471
472 // doubles the size in x or y of a bitmap in place.
473 void game_expand_bitmap( grs_bitmap * bmp, uint flags )
474 {
475         int i;
476         ubyte * dptr, * sptr;
477
478         switch(flags & 3)       {
479         case 2: // expand x
480                 Assert( bmp->bm_rowsize == bmp->bm_w*2 );
481                 dptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
482                 for (i=bmp->bm_h-1; i>=0; i-- ) {
483                         expand_row( dptr, dptr, bmp->bm_w );    
484                         dptr -= bmp->bm_rowsize;
485                 }
486                 bmp->bm_w *= 2;
487                 break;
488         case 1: // expand y
489                 dptr = &bmp->bm_data[(2*(bmp->bm_h-1)+1)*bmp->bm_rowsize];
490                 sptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
491                 for (i=bmp->bm_h-1; i>=0; i-- ) {
492                         memcpy( dptr, sptr, bmp->bm_w );        
493                         dptr -= bmp->bm_rowsize;
494                         memcpy( dptr, sptr, bmp->bm_w );        
495                         dptr -= bmp->bm_rowsize;
496                         sptr -= bmp->bm_rowsize;
497                 }
498                 bmp->bm_h *= 2;
499                 break;
500         case 3: // expand x & y
501                 Assert( bmp->bm_rowsize == bmp->bm_w*2 );
502                 dptr = &bmp->bm_data[(2*(bmp->bm_h-1)+1)*bmp->bm_rowsize];
503                 sptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
504                 for (i=bmp->bm_h-1; i>=0; i-- ) {
505                         expand_row( dptr, sptr, bmp->bm_w );    
506                         dptr -= bmp->bm_rowsize;
507                         expand_row( dptr, sptr, bmp->bm_w );    
508                         dptr -= bmp->bm_rowsize;
509                         sptr -= bmp->bm_rowsize;
510                 }
511                 bmp->bm_w *= 2;
512                 bmp->bm_h *= 2;
513                 break;
514         }
515 }
516
517 extern int SW_drawn[2], SW_x[2], SW_y[2], SW_w[2], SW_h[2];
518
519 extern int Guided_in_big_window;
520
521 #if 0
522 //render a frame for the game in stereo
523 void game_render_frame_stereo()
524 {
525         int dw,dh,sw,sh;
526         fix save_aspect;
527         fix actual_eye_width;
528         int actual_eye_offset;
529         grs_canvas RenderCanvas[2];
530         int no_draw_hud=0;
531
532         save_aspect = grd_curscreen->sc_aspect;
533         grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio
534
535         sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
536         sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
537
538         if (VR_low_res & 1)     {
539                 sh /= 2;                                
540                 grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio                                
541         }
542         if (VR_low_res & 2)     {
543                 sw /= 2;                                
544                 grd_curscreen->sc_aspect /= 2;  //Muck with aspect ratio                                
545         }
546
547         gr_init_sub_canvas( &RenderCanvas[0], &VR_render_buffer[0], 0, 0, sw, sh );
548         gr_init_sub_canvas( &RenderCanvas[1], &VR_render_buffer[1], 0, 0, sw, sh );
549
550         // Draw the left eye's view
551         if (VR_eye_switch)      {
552                 actual_eye_width = -VR_eye_width;
553                 actual_eye_offset = -VR_eye_offset;
554         } else {
555                 actual_eye_width = VR_eye_width;
556                 actual_eye_offset = VR_eye_offset;
557         }
558
559         if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && Guided_in_big_window)
560                 actual_eye_offset = 0;
561
562         gr_set_current_canvas(&RenderCanvas[0]);
563
564         if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && Guided_in_big_window) {
565                 char *msg = "Guided Missile View";
566                 object *viewer_save = Viewer;
567                 int w,h,aw;
568
569                 Viewer = Guided_missile[Player_num];
570
571                 WIN(DDGRLOCK(dd_grd_curcanv));  // Must lock DD canvas!!!
572                 {
573                         #ifdef MACINTOSH
574                         if (Scanline_double)
575                                 FontHires = 0;
576                         #endif
577                         update_rendered_data(0, Viewer, 0, 0);
578                         render_frame(0, 0);
579 #if defined(POLY_ACC) && !defined(MACINTOSH)    // dma stuff not support on mac via RAVE
580                         pa_dma_poll();
581 #endif
582   
583                         wake_up_rendered_objects(Viewer, 0);
584                         Viewer = viewer_save;
585
586                         gr_set_curfont( GAME_FONT );    //GAME_FONT );
587                         gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
588                         gr_get_string_size(msg, &w, &h, &aw );
589
590                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
591
592                         draw_guided_crosshair();
593                 }
594                 WIN(DDGRUNLOCK(dd_grd_curcanv));
595
596                         HUD_render_message_frame();
597                         #ifdef MACINTOSH
598                         if (Scanline_double)
599                                 FontHires = 1;
600                         #endif
601
602                 no_draw_hud=1;
603         }
604         else if (Rear_view)
605                 render_frame(actual_eye_width, 0);      // switch eye positions for rear view
606         else
607                 render_frame(-actual_eye_width, 0);             // Left eye
608
609         if ( VR_low_res )
610                 game_expand_bitmap( &RenderCanvas[0].cv_bitmap, VR_low_res );
611
612         {       //render small window into left eye's canvas
613                 grs_canvas *save=grd_curcanv;
614                 fix save_aspect2 = grd_curscreen->sc_aspect;
615                 grd_curscreen->sc_aspect = save_aspect*2;
616                 SW_drawn[0] = SW_drawn[1] = 0;
617                 show_extra_views();
618                 gr_set_current_canvas(save);
619                 grd_curscreen->sc_aspect = save_aspect2;
620         }
621
622 //NEWVR
623         if (actual_eye_offset > 0 ) {
624                 gr_setcolor( gr_getcolor(0,0,0) );
625                 gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(actual_eye_offset)*2, 0, 
626                grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
627         } else if (actual_eye_offset < 0 ) {
628                 gr_setcolor( gr_getcolor(0,0,0) );
629                 gr_rect( 0, 0, labs(actual_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
630         }
631
632         if ( VR_show_hud && !no_draw_hud )      {
633                 grs_canvas tmp;
634                 if (actual_eye_offset < 0 ) {
635                         gr_init_sub_canvas( &tmp, grd_curcanv, labs(actual_eye_offset*2), 0, grd_curcanv->cv_bitmap.bm_w-(labs(actual_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
636                 } else {
637                         gr_init_sub_canvas( &tmp, grd_curcanv, 0, 0, grd_curcanv->cv_bitmap.bm_w-(labs(actual_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
638                 }
639                 gr_set_current_canvas( &tmp );
640                 game_draw_hud_stuff();
641         }
642
643
644         // Draw the right eye's view
645         gr_set_current_canvas(&RenderCanvas[1]);
646
647         if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && Guided_in_big_window)
648                 gr_bitmap(0,0,&RenderCanvas[0].cv_bitmap);
649         else {
650                 if (Rear_view)
651                         render_frame(-actual_eye_width, 0);     // switch eye positions for rear view
652                 else
653                         render_frame(actual_eye_width, 0);              // Right eye
654
655                 if ( VR_low_res )
656                         game_expand_bitmap( &RenderCanvas[1].cv_bitmap, VR_low_res );
657         }
658
659
660         {       //copy small window from left eye
661                 grs_canvas temp;
662                 int w;
663                 for (w=0;w<2;w++) {
664                         if (SW_drawn[w]) {
665                                 gr_init_sub_canvas(&temp,&RenderCanvas[0],SW_x[w],SW_y[w],SW_w[w],SW_h[w]);
666                                 gr_bitmap(SW_x[w]+actual_eye_offset*2,SW_y[w],&temp.cv_bitmap);
667                         }
668                 }
669         }
670
671 //NEWVR
672         if (actual_eye_offset>0) {
673                 gr_setcolor( gr_getcolor(0,0,0) );
674                 gr_rect( 0, 0, labs(actual_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
675         } else if ( actual_eye_offset < 0 )     {
676                 gr_setcolor( gr_getcolor(0,0,0) );
677                 gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(actual_eye_offset)*2, 0, 
678                grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
679         }
680
681 //NEWVR (Add the next 2 lines)
682         if ( VR_show_hud && !no_draw_hud )      {
683                 grs_canvas tmp;
684                 if (actual_eye_offset > 0 ) {
685                         gr_init_sub_canvas( &tmp, grd_curcanv, labs(actual_eye_offset*2), 0, grd_curcanv->cv_bitmap.bm_w-(labs(actual_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
686                 } else {
687                         gr_init_sub_canvas( &tmp, grd_curcanv, 0, 0, grd_curcanv->cv_bitmap.bm_w-(labs(actual_eye_offset)*2), grd_curcanv->cv_bitmap.bm_h );
688                 }
689                 gr_set_current_canvas( &tmp );
690                 game_draw_hud_stuff();
691         }
692
693
694         // Draws white and black registration encoding lines
695         // and Accounts for pixel-shift adjustment in upcoming bitblts
696         if (VR_use_reg_code)    {
697                 int width, height, quarter;
698
699                 width = RenderCanvas[0].cv_bitmap.bm_w;
700                 height = RenderCanvas[0].cv_bitmap.bm_h;
701                 quarter = width / 4;
702
703                 // black out left-hand side of left page
704
705                 // draw registration code for left eye
706                 if ( VR_eye_switch )
707                         gr_set_current_canvas( &RenderCanvas[1] );
708                 else
709                         gr_set_current_canvas( &RenderCanvas[0] );
710                 gr_setcolor( VR_WHITE_INDEX );
711                 gr_scanline( 0, quarter, height-1 );
712                 gr_setcolor( VR_BLACK_INDEX );
713                 gr_scanline( quarter, width-1, height-1 );
714
715                 if ( VR_eye_switch )
716                         gr_set_current_canvas( &RenderCanvas[0] );
717                 else
718                         gr_set_current_canvas( &RenderCanvas[1] );
719                 gr_setcolor( VR_WHITE_INDEX );
720                 gr_scanline( 0, quarter*3, height-1 );
721                 gr_setcolor( VR_BLACK_INDEX );
722                 gr_scanline( quarter*3, width-1, height-1 );
723    }
724
725                 // Copy left eye, then right eye
726         if ( VR_screen_flags&VRF_USE_PAGING )
727                 VR_current_page = !VR_current_page;
728         else 
729                 VR_current_page = 0;
730         gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
731
732 //NEWVR
733
734         if ( VR_eye_offset_changed > 0 )        {
735                 VR_eye_offset_changed--;
736                 gr_clear_canvas(0);
737         }
738
739         sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
740         sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
741
742         // Copy left eye, then right eye
743         gr_bitblt_dest_step_shift = 1;          // Skip every other scanline.
744
745         if (VR_render_mode == VR_INTERLACED )   {
746                 if ( actual_eye_offset > 0 )    {
747                         int xoff = labs(actual_eye_offset);
748                         gr_bm_ubitblt( dw-xoff, dh, xoff, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
749                         gr_bm_ubitblt( dw-xoff, dh, 0, 1, xoff, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
750                 } else if ( actual_eye_offset < 0 )     {
751                         int xoff = labs(actual_eye_offset);
752                         gr_bm_ubitblt( dw-xoff, dh, 0, 0, xoff, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
753                         gr_bm_ubitblt( dw-xoff, dh, xoff, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
754                 } else {
755                         gr_bm_ubitblt( dw, dh, 0, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
756                         gr_bm_ubitblt( dw, dh, 0, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
757                 }
758         } else if (VR_render_mode == VR_AREA_DET) {
759                 // VFX copy
760                 gr_bm_ubitblt( dw, dh, 0,  VR_current_page, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
761                 gr_bm_ubitblt( dw, dh, dw, VR_current_page, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
762         } else {
763                 Int3();         // Huh?
764         }
765
766         gr_bitblt_dest_step_shift = 0;
767
768         //if ( Game_vfx_flag )
769         //      vfx_set_page(VR_current_page);          // 0 or 1
770         //else 
771                 if ( VR_screen_flags&VRF_USE_PAGING )   {
772                         gr_wait_for_retrace = 0;
773
774 //      Added by Samir from John's code
775                 if ( (VR_screen_pages[VR_current_page].cv_bitmap.bm_type == BM_MODEX) && (Game_3dmax_flag==3) ) {
776                         int old_x, old_y, new_x;
777                         old_x = VR_screen_pages[VR_current_page].cv_bitmap.bm_x;
778                         old_y = VR_screen_pages[VR_current_page].cv_bitmap.bm_y;
779                         new_x = old_y*VR_screen_pages[VR_current_page].cv_bitmap.bm_rowsize;
780                         new_x += old_x/4;
781                         VR_screen_pages[VR_current_page].cv_bitmap.bm_x = new_x;
782                         VR_screen_pages[VR_current_page].cv_bitmap.bm_y = 0;
783                         VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_SVGA;
784                         gr_show_canvas( &VR_screen_pages[VR_current_page] );
785                         VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_MODEX;
786                         VR_screen_pages[VR_current_page].cv_bitmap.bm_x = old_x;
787                         VR_screen_pages[VR_current_page].cv_bitmap.bm_y = old_y;
788                 } else {
789                         gr_show_canvas( &VR_screen_pages[VR_current_page] );
790                 }
791                 gr_wait_for_retrace = 1;
792         }
793         grd_curscreen->sc_aspect=save_aspect;
794 }
795 #endif
796 ubyte RenderingType=0;
797 ubyte DemoDoingRight=0,DemoDoingLeft=0;
798 extern ubyte DemoDoRight,DemoDoLeft;
799 extern object DemoRightExtra,DemoLeftExtra;
800
801 char DemoWBUType[]={0,WBU_MISSILE,WBU_MISSILE,WBU_REAR,WBU_ESCORT,WBU_MARKER,WBU_MISSILE};
802 char DemoRearCheck[]={0,0,0,1,0,0,0};
803 char *DemoExtraMessage[]={"PLAYER","GUIDED","MISSILE","REAR","GUIDE-BOT","MARKER","SHIP"};
804
805 extern char guidebot_name[];
806
807 void show_extra_views()
808 {
809         int did_missile_view=0;
810         int save_newdemo_state = Newdemo_state;
811         int w;
812
813    if (Newdemo_state==ND_STATE_PLAYBACK)
814     {
815      if (DemoDoLeft)
816       { 
817                  DemoDoingLeft=DemoDoLeft;
818                 
819        if (DemoDoLeft==3)
820                         do_cockpit_window_view(0,ConsoleObject,1,WBU_REAR,"REAR");
821        else
822               do_cockpit_window_view(0,&DemoLeftExtra,DemoRearCheck[DemoDoLeft],DemoWBUType[DemoDoLeft],DemoExtraMessage[DemoDoLeft]);
823                 }
824      else
825                 do_cockpit_window_view(0,NULL,0,WBU_WEAPON,NULL);
826
827           if (DemoDoRight)
828                 {
829                  DemoDoingRight=DemoDoRight;
830                 
831        if (DemoDoRight==3)
832                         do_cockpit_window_view(1,ConsoleObject,1,WBU_REAR,"REAR");
833        else
834            do_cockpit_window_view(1,&DemoRightExtra,DemoRearCheck[DemoDoRight],DemoWBUType[DemoDoRight],DemoExtraMessage[DemoDoRight]);
835                 } 
836      else
837         do_cockpit_window_view(1,NULL,0,WBU_WEAPON,NULL);
838           
839       DemoDoLeft=DemoDoRight=0;
840                 DemoDoingLeft=DemoDoingRight=0;
841     
842         return;
843     } 
844
845         if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) {
846                 if (Guided_in_big_window)
847                  {
848                         RenderingType=6+(1<<4);
849                         do_cockpit_window_view(1,Viewer,0,WBU_MISSILE,"SHIP");
850                  }
851                 else
852                  {
853                         RenderingType=1+(1<<4);
854                         do_cockpit_window_view(1,Guided_missile[Player_num],0,WBU_GUIDED,"GUIDED");
855             }
856                         
857                 did_missile_view=1;
858         }
859         else {
860
861                 if (Guided_missile[Player_num]) {               //used to be active
862                         if (!Guided_in_big_window)
863                                 do_cockpit_window_view(1,NULL,0,WBU_STATIC,NULL);
864                         Guided_missile[Player_num] = NULL;
865                 }
866
867                 if (Missile_viewer) {           //do missile view
868                         static int mv_sig=-1;
869                         if (mv_sig == -1)
870                                 mv_sig = Missile_viewer->signature;
871                         if (Missile_view_enabled && Missile_viewer->type!=OBJ_NONE && Missile_viewer->signature == mv_sig) {
872                                 RenderingType=2+(1<<4);
873                                 do_cockpit_window_view(1,Missile_viewer,0,WBU_MISSILE,"MISSILE");
874                                 did_missile_view=1;
875                         }
876                         else {
877                                 Missile_viewer = NULL;
878                                 mv_sig = -1;
879                                 RenderingType=255;
880                                 do_cockpit_window_view(1,NULL,0,WBU_STATIC,NULL);
881                         }
882                 }
883         }
884
885         for (w=0;w<2;w++) {
886
887                 if (w==1 && did_missile_view)
888                         continue;               //if showing missile view in right window, can't show anything else
889
890                 //show special views if selected
891                 switch (Cockpit_3d_view[w]) {
892                         case CV_NONE:
893                                 RenderingType=255;
894                                 do_cockpit_window_view(w,NULL,0,WBU_WEAPON,NULL);
895                                 break;
896                         case CV_REAR:
897                                 if (Rear_view) {                //if big window is rear view, show front here
898                                         RenderingType=3+(w<<4);                         
899                                         do_cockpit_window_view(w,ConsoleObject,0,WBU_REAR,"FRONT");
900                                 }
901                                 else {                                  //show normal rear view
902                                         RenderingType=3+(w<<4);                         
903                                         do_cockpit_window_view(w,ConsoleObject,1,WBU_REAR,"REAR");
904                                 }
905                                 break;
906                         case CV_ESCORT: {
907                                 object *buddy;
908                                 buddy = find_escort();
909                                 if (buddy == NULL) {
910                                         do_cockpit_window_view(w,NULL,0,WBU_WEAPON,NULL);
911                                         Cockpit_3d_view[w] = CV_NONE;
912                                 }
913                                 else {
914                                         RenderingType=4+(w<<4);
915                                         do_cockpit_window_view(w,buddy,0,WBU_ESCORT,guidebot_name);
916                                 }
917                                 break;
918                         }
919 #ifdef NETWORK
920                         case CV_COOP: {
921                                 int player = Coop_view_player[w];
922
923                  RenderingType=255; // don't handle coop stuff                  
924                                 
925                                 if (player!=-1 && Players[player].connected && ((Game_mode & GM_MULTI_COOP) || ((Game_mode & GM_TEAM) && (get_team(player) == get_team(Player_num)))))
926                                         do_cockpit_window_view(w,&Objects[Players[Coop_view_player[w]].objnum],0,WBU_COOP,Players[Coop_view_player[w]].callsign);
927                                 else {
928                                         do_cockpit_window_view(w,NULL,0,WBU_WEAPON,NULL);
929                                         Cockpit_3d_view[w] = CV_NONE;
930                                 }
931                                 break;
932                         }
933 #endif
934                         case CV_MARKER: {
935                                 char label[10];
936                                 RenderingType=5+(w<<4);
937                                 if (Marker_viewer_num[w] == -1 || MarkerObject[Marker_viewer_num[w]] == -1) {
938                                         Cockpit_3d_view[w] = CV_NONE;
939                                         break;
940                                 }
941                                 sprintf(label,"Marker %d",Marker_viewer_num[w]+1);
942                                 do_cockpit_window_view(w,&Objects[MarkerObject[Marker_viewer_num[w]]],0,WBU_MARKER,label);
943                                 break;
944                         }
945                         default:
946                                 Int3();         //invalid window type
947                 }
948         }
949         RenderingType=0;
950         Newdemo_state = save_newdemo_state;
951 }
952
953 int BigWindowSwitch=0;
954 extern int force_cockpit_redraw;
955 #ifndef MACINTOSH
956 extern ubyte * Game_cockpit_copy_code;
957 #else
958 extern ubyte Game_cockpit_copy_code;
959 #endif
960
961 void draw_guided_crosshair(void);
962
963 #ifdef MACINTOSH
964 // special code to render a frame w/hw acceleration
965
966 // next routine is called as a callback from the current hardware engine being used.  The
967 // routine is called once all of the accelerated drawing is done.  We now overlay the
968 // backbuffer with hud stuff.
969
970 void pa_mac_render_extras( void )
971 {
972         grs_canvas Screen_3d_window;
973
974         gr_init_sub_canvas( &Screen_3d_window, &VR_screen_pages[0], 
975                 VR_render_sub_buffer[0].cv_bitmap.bm_x, 
976                 VR_render_sub_buffer[0].cv_bitmap.bm_y, 
977                 VR_render_sub_buffer[0].cv_bitmap.bm_w, 
978                 VR_render_sub_buffer[0].cv_bitmap.bm_h);
979
980         gr_set_current_canvas( &Screen_3d_window );             // set to current screen
981         
982         if (Guided_missile[Player_num] &&
983                 Guided_missile[Player_num]->type==OBJ_WEAPON &&
984                 Guided_missile[Player_num]->id==GUIDEDMISS_ID &&
985                 Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] &&
986                 Guided_in_big_window)
987         {
988                 char *msg = "Guided Missile View";
989                 int w,h,aw;
990
991                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
992                 gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
993                 gr_get_string_size(msg, &w, &h, &aw );
994
995                 gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
996
997                 draw_guided_crosshair();
998
999                 HUD_render_message_frame();
1000         } 
1001         else
1002         {
1003                 game_draw_hud_stuff();          // draw hud stuff when not doing missle view in big window
1004         }
1005
1006         if (Game_paused) {              //render pause message over off-screen 3d (to minimize flicker)
1007                 extern char *Pause_msg;
1008                 ubyte *save_data = VR_screen_pages[VR_current_page].cv_bitmap.bm_data;
1009
1010                 WIN(Int3());                    // Not supported yet.
1011                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=VR_render_buffer[VR_current_page].cv_bitmap.bm_data;
1012                 show_boxed_message(Pause_msg);
1013                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=save_data;
1014         }
1015
1016
1017 }
1018
1019 void pa_mac_game_render_frame( void )
1020 {       
1021         Assert ( !Scanline_double );
1022         Assert ( PAEnabled );
1023         
1024         gr_set_current_canvas(&VR_render_sub_buffer[0]);        // set up the right canvas so rendering is done to correct size
1025
1026         pa_render_start();
1027         
1028         if (Guided_missile[Player_num] &&
1029                 Guided_missile[Player_num]->type==OBJ_WEAPON &&
1030                 Guided_missile[Player_num]->id==GUIDEDMISS_ID &&
1031                 Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] &&
1032                 Guided_in_big_window)
1033         {
1034                 char *msg = "Guided Missile View";
1035                 object *viewer_save = Viewer;
1036                 int w,h,aw;
1037
1038                 if (Cockpit_mode==CM_FULL_COCKPIT) {
1039                         BigWindowSwitch=1;
1040                         force_cockpit_redraw=1;
1041                         Cockpit_mode=CM_STATUS_BAR;
1042                         pa_render_end();
1043                         return;
1044                 }
1045   
1046                 Viewer = Guided_missile[Player_num];
1047                 update_rendered_data(0, Viewer, 0, 0);
1048                 render_frame(0, 0);
1049                 wake_up_rendered_objects(Viewer, 0);
1050                 Viewer = viewer_save;
1051         }
1052         else
1053         {       
1054                 if (BigWindowSwitch)
1055                 {
1056                         force_cockpit_redraw=1;
1057                         Cockpit_mode=CM_FULL_COCKPIT;
1058                         BigWindowSwitch=0;
1059                         pa_render_end();
1060                         return;
1061                 }
1062
1063                 update_rendered_data(0, Viewer, Rear_view, 0);
1064                 render_frame(0, 0);
1065          }
1066
1067         if (Cockpit_mode == CM_FULL_SCREEN)
1068         {
1069                 show_extra_views();
1070         }
1071
1072
1073         pa_render_end();
1074
1075         // NOTE:  Hud stuff is drawn using a RAVE call back which draws onto the back buffer
1076         // after rendering finishes but before the page flip
1077
1078         if (Cockpit_mode != CM_FULL_SCREEN)
1079         {
1080                 show_extra_views();             //missile view, buddy bot, etc.
1081         }
1082         
1083         // Draw Gauges straight to screen
1084         if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR)
1085         {
1086
1087                 if ( (Newdemo_state == ND_STATE_PLAYBACK) )
1088                 {
1089                         Game_mode = Newdemo_game_mode;
1090                 }
1091                 
1092                 Current_display_mode = 1;
1093                         render_gauges();
1094                 Current_display_mode = -1;
1095
1096                 if ( (Newdemo_state == ND_STATE_PLAYBACK) )
1097                 {
1098                         Game_mode = GM_NORMAL;
1099                 }
1100         }
1101 }
1102 #endif // MACINTOSH
1103
1104
1105 //render a frame for the game
1106 //              WINDOWS:
1107 //                      will render everything to dd_VR_render_sub_buffer
1108 //                      which all leads to the dd_VR_offscreen_buffer
1109 void game_render_frame_mono(void)
1110 {
1111         WINDOS (
1112                 dd_grs_canvas Screen_3d_window,
1113                 grs_canvas Screen_3d_window
1114         );
1115         int no_draw_hud=0;
1116
1117         #if defined(MACINTOSH)
1118         if ( PAEnabled ) {
1119                 pa_mac_game_render_frame();
1120                 return;
1121         }
1122         #endif
1123         
1124
1125         WINDOS (
1126                 dd_gr_init_sub_canvas(&Screen_3d_window, &dd_VR_screen_pages[0],
1127                         dd_VR_render_sub_buffer[0].canvas.cv_bitmap.bm_x, 
1128                         dd_VR_render_sub_buffer[0].canvas.cv_bitmap.bm_y, 
1129                         dd_VR_render_sub_buffer[0].canvas.cv_bitmap.bm_w, 
1130                         dd_VR_render_sub_buffer[0].canvas.cv_bitmap.bm_h),
1131                 gr_init_sub_canvas( &Screen_3d_window, &VR_screen_pages[0], 
1132                         VR_render_sub_buffer[0].cv_bitmap.bm_x, 
1133                         VR_render_sub_buffer[0].cv_bitmap.bm_y, 
1134                         VR_render_sub_buffer[0].cv_bitmap.bm_w, 
1135                         VR_render_sub_buffer[0].cv_bitmap.bm_h)
1136         );
1137
1138         if ( Game_double_buffer ) {     
1139                 WINDOS(
1140                         dd_gr_set_current_canvas(&dd_VR_render_sub_buffer[0]),
1141                         gr_set_current_canvas(&VR_render_sub_buffer[0])
1142                 );
1143         }
1144         else    {
1145                 WINDOS(
1146                         dd_gr_set_current_canvas(&Screen_3d_window),
1147                         gr_set_current_canvas(&Screen_3d_window)
1148                 );
1149         }
1150         
1151 #if defined(POLY_ACC) && !defined(MACINTOSH)  // begin s3 relocation of cockpit drawing.
1152
1153     pa_flush();
1154
1155     if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && Guided_in_big_window)
1156         no_draw_hud = 1;
1157
1158     if (!no_draw_hud)   {
1159                 WIN(DDGRLOCK(dd_grd_curcanv));
1160                 game_draw_hud_stuff();
1161                 WIN(DDGRUNLOCK(dd_grd_curcanv));
1162         }
1163
1164         show_extra_views();             //missile view, buddy bot, etc.
1165         pa_dma_poll();
1166
1167         if (Game_paused) {              //render pause message over off-screen 3d (to minimize flicker)
1168                 extern char *Pause_msg;
1169                 ubyte *save_data = VR_screen_pages[VR_current_page].cv_bitmap.bm_data;
1170
1171                 WIN(Int3());                    // Not supported yet.
1172                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=VR_render_buffer[VR_current_page].cv_bitmap.bm_data;
1173                 show_boxed_message(Pause_msg);
1174                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=save_data;
1175         }
1176
1177         if ( Game_double_buffer ) {             //copy to visible screen
1178                 if ( !Game_cockpit_copy_code )  {
1179                         if ( VR_screen_flags&VRF_USE_PAGING )   {
1180                                 VR_current_page = !VR_current_page;
1181                     gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
1182                                         gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w, VR_render_sub_buffer[0].cv_h, VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y, 0, 0, &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
1183                                         gr_wait_for_retrace = 0;
1184                                         gr_show_canvas( &VR_screen_pages[VR_current_page] );
1185                                         gr_wait_for_retrace = 1;
1186             } else {
1187 #ifdef  POLY_ACC        //$$
1188                                         pa_about_to_flip();
1189 #endif
1190                 gr_bm_ubitblt(
1191                     VR_render_sub_buffer[0].cv_w, VR_render_sub_buffer[0].cv_h,
1192                     VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y,
1193                     VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y,
1194                     &VR_render_sub_buffer[0].cv_bitmap,  &VR_screen_pages[0].cv_bitmap
1195                 );
1196             }
1197                 } else  {
1198 #ifdef  POLY_ACC        //$$
1199         pa_about_to_flip();
1200 #endif
1201                 gr_ibitblt( &VR_render_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap, Game_cockpit_copy_code );
1202         }
1203         }
1204
1205         if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR) {
1206
1207                 if ( (Newdemo_state == ND_STATE_PLAYBACK) )
1208                         Game_mode = Newdemo_game_mode;
1209
1210                 render_gauges();
1211
1212                 if ( (Newdemo_state == ND_STATE_PLAYBACK) )
1213                         Game_mode = GM_NORMAL;
1214         }
1215
1216     // restore current canvas.
1217     if ( Game_double_buffer ) {
1218                 WINDOS(
1219                         dd_gr_set_current_canvas(&dd_VR_render_sub_buffer[0]),
1220                         gr_set_current_canvas(&VR_render_sub_buffer[0])
1221                 );
1222         }
1223         else    {
1224                 WINDOS(
1225                         dd_gr_set_current_canvas(&Screen_3d_window),
1226                         gr_set_current_canvas(&Screen_3d_window)
1227                 );
1228         }
1229         
1230 #endif      // end s3 relocation of cockpit drawing.
1231
1232         if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && Guided_in_big_window) {
1233                 char *msg = "Guided Missile View";
1234                 object *viewer_save = Viewer;
1235                 int w,h,aw;
1236
1237       if (Cockpit_mode==CM_FULL_COCKPIT)
1238                         {
1239                          BigWindowSwitch=1;
1240                          force_cockpit_redraw=1;
1241                          Cockpit_mode=CM_STATUS_BAR;
1242                          return;
1243                    }
1244   
1245                 Viewer = Guided_missile[Player_num];
1246
1247                 WIN(DDGRLOCK(dd_grd_curcanv));  // Must lock DD canvas!!!
1248                 {
1249                         #ifdef MACINTOSH
1250                         if (Scanline_double)
1251                                 FontHires = 0;
1252                         #endif
1253                         update_rendered_data(0, Viewer, 0, 0);
1254                         render_frame(0, 0);
1255   
1256                         wake_up_rendered_objects(Viewer, 0);
1257                         Viewer = viewer_save;
1258
1259                         gr_set_curfont( GAME_FONT );    //GAME_FONT );
1260                         gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
1261                         gr_get_string_size(msg, &w, &h, &aw );
1262
1263                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
1264
1265                         draw_guided_crosshair();
1266                 }
1267                 WIN(DDGRUNLOCK(dd_grd_curcanv));
1268
1269                         HUD_render_message_frame();
1270                         #ifdef MACINTOSH
1271                         if (Scanline_double)
1272                                 FontHires = 1;
1273                         #endif
1274
1275                 no_draw_hud=1;
1276         }
1277         else
1278          {      
1279                 if (BigWindowSwitch)
1280                  {
1281                    force_cockpit_redraw=1;
1282                         Cockpit_mode=CM_FULL_COCKPIT;
1283                    BigWindowSwitch=0;
1284                         return;
1285                  }
1286                 WIN(DDGRLOCK(dd_grd_curcanv));  // Must lock DD canvas!!!
1287                 update_rendered_data(0, Viewer, Rear_view, 0);
1288                 render_frame(0, 0);
1289 #if defined(POLY_ACC) && !defined(MACINTOSH)    // dma stuff not supported on mac via RAVE
1290                 pa_dma_poll();
1291 #endif
1292                 WIN(DDGRUNLOCK(dd_grd_curcanv));
1293          }
1294
1295         if ( Game_double_buffer ) {     
1296                 WINDOS(
1297                         dd_gr_set_current_canvas(&dd_VR_render_sub_buffer[0]),
1298                         gr_set_current_canvas(&VR_render_sub_buffer[0])
1299                 );
1300         }
1301         else    {
1302                 WINDOS(
1303                         dd_gr_set_current_canvas(&Screen_3d_window),
1304                         gr_set_current_canvas(&Screen_3d_window)
1305                 );
1306         }
1307
1308 #if !defined(POLY_ACC) || defined(MACINTOSH)
1309
1310         if (!no_draw_hud)       {
1311                 WIN(DDGRLOCK(dd_grd_curcanv));
1312                 game_draw_hud_stuff();
1313                 WIN(DDGRUNLOCK(dd_grd_curcanv));
1314         }
1315
1316         show_extra_views();             //missile view, buddy bot, etc.
1317
1318 #ifdef WINDOWS
1319         if (Game_paused) {              //render pause message over off-screen 3d (to minimize flicker)
1320                 extern char *Pause_msg;
1321 //              LPDIRECTDRAWSURFACE save_dds = dd_VR_screen_pages[VR_current_page].lpdds;
1322
1323 //              dd_VR_screen_pages[VR_current_page].lpdds = dd_VR_render_buffer[VR_current_page].lpdds;
1324                 show_boxed_message(Pause_msg);
1325 //              dd_VR_screen_pages[VR_current_page].lpdds = save_dds;
1326         }
1327 #else
1328         if (Game_paused) {              //render pause message over off-screen 3d (to minimize flicker)
1329                 extern char *Pause_msg;
1330                 ubyte *save_data = VR_screen_pages[VR_current_page].cv_bitmap.bm_data;
1331
1332                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=VR_render_buffer[VR_current_page].cv_bitmap.bm_data;
1333                 show_boxed_message(Pause_msg);
1334                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=save_data;
1335         }
1336 #endif
1337
1338         if ( Game_double_buffer ) {             //copy to visible screen
1339                 if ( !Game_cockpit_copy_code )  {
1340                         if ( VR_screen_flags&VRF_USE_PAGING )   {       
1341                                 VR_current_page = !VR_current_page;
1342                                 #ifdef WINDOWS
1343                                         dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]);
1344                                         dd_gr_flip();
1345                                 #else
1346                                         gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
1347                                         gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w, VR_render_sub_buffer[0].cv_h, VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y, 0, 0, &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
1348                                         gr_wait_for_retrace = 0;
1349                                         gr_show_canvas( &VR_screen_pages[VR_current_page] );
1350                                         gr_wait_for_retrace = 1;
1351                                 #endif
1352                         } else {
1353                         #ifdef MACINTOSH
1354                                 if (Scanline_double)
1355                                         gr_bm_ubitblt_double( VR_render_sub_buffer[0].cv_w, VR_render_sub_buffer[0].cv_h, VR_render_sub_buffer[0].cv_bitmap.bm_x, VR_render_sub_buffer[0].cv_bitmap.bm_y, 0, 0, &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap );
1356                                 else
1357                         #endif // NOTE LINK TO ABOVE IF
1358                         #ifdef WINDOWS    
1359                                 if (GRMODEINFO(emul) || GRMODEINFO(modex) || GRMODEINFO(dbuf))
1360                                         // From render buffer to screen buffer.
1361                                         dd_gr_blt_notrans(&dd_VR_render_sub_buffer[0],
1362                                                 0,0,
1363                                                 dd_VR_render_sub_buffer[0].canvas.cv_w,
1364                                                 dd_VR_render_sub_buffer[0].canvas.cv_h,
1365                                                 dd_grd_screencanv,
1366                                                 dd_VR_render_sub_buffer[0].xoff, 
1367                                                 dd_VR_render_sub_buffer[0].yoff, 
1368                                                 dd_VR_render_sub_buffer[0].canvas.cv_w,
1369                                                 dd_VR_render_sub_buffer[0].canvas.cv_h);
1370
1371                                         DDGRRESTORE;
1372                         // Puts back canvas to front canvas by blt or flip
1373                                 if (GRMODEINFO(modex)) {
1374                                         //@@VR_current_page = !VR_current_page;
1375                                         //@@dd_gr_flip();
1376                                         win_flip = 1;
1377                                 }
1378                         #else
1379                                 gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w, 
1380                                                 VR_render_sub_buffer[0].cv_h, 
1381                                                 VR_render_sub_buffer[0].cv_bitmap.bm_x, 
1382                                                 VR_render_sub_buffer[0].cv_bitmap.bm_y, 
1383                                                 0, 0, 
1384                                                 &VR_render_sub_buffer[0].cv_bitmap, 
1385                                                 &VR_screen_pages[0].cv_bitmap );
1386                         #endif
1387
1388          #ifdef _3DFX
1389          _3dfx_BufferSwap();
1390          #endif
1391
1392                         }
1393                 } else  {
1394                         #if 1 //def MACINTOSH
1395                                 gr_ibitblt( &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap, Scanline_double );
1396                         #else
1397                         #ifndef WINDOWS
1398                                 gr_ibitblt( &VR_render_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap, Game_cockpit_copy_code );
1399                         #else
1400                                 win_do_emul_ibitblt( &dd_VR_render_sub_buffer[0], dd_grd_screencanv);
1401                                 DDGRRESTORE;
1402                                 if (GRMODEINFO(modex)) {
1403                                         //@@VR_current_page = !VR_current_page;
1404                                         //@@dd_gr_flip();
1405                                         win_flip = 1;
1406                                 }
1407                         #endif
1408                         #endif
1409                 }
1410         }
1411
1412         if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR) {
1413
1414                 if ( (Newdemo_state == ND_STATE_PLAYBACK) )
1415                         Game_mode = Newdemo_game_mode;
1416
1417                 render_gauges();
1418
1419                 if ( (Newdemo_state == ND_STATE_PLAYBACK) )
1420                         Game_mode = GM_NORMAL;
1421         }
1422
1423 #ifdef WINDOWS
1424         if (win_flip) {
1425                 VR_current_page = !VR_current_page;
1426                 dd_gr_flip();
1427         }
1428 #endif
1429
1430 #endif
1431
1432         con_update();
1433
1434         gr_update();
1435 #ifdef OGL
1436         ogl_swap_buffers();
1437 #endif
1438 }
1439
1440 void toggle_cockpit()
1441 {
1442         int new_mode;
1443
1444         switch (Cockpit_mode) {
1445
1446                 case CM_FULL_COCKPIT: {
1447                         int max_h = grd_curscreen->sc_h - GameBitmaps[cockpit_bitmap[CM_STATUS_BAR+(Current_display_mode?(Num_cockpits/2):0)].index].bm_h;
1448                         if (Game_window_h > max_h)              //too big for statusbar
1449                                 new_mode = CM_FULL_SCREEN;
1450                         else
1451                                 new_mode = CM_STATUS_BAR;
1452                         break;
1453                 }
1454
1455                 case CM_STATUS_BAR:
1456                 case CM_FULL_SCREEN:
1457                         if (Rear_view)
1458                                 return;
1459                         new_mode = CM_FULL_COCKPIT;
1460                         break;
1461
1462                 case CM_REAR_VIEW:
1463                 case CM_LETTERBOX:
1464                 default:
1465                         return;                 //do nothing
1466                         break;
1467
1468         }
1469
1470         select_cockpit(new_mode);
1471         HUD_clear_messages();
1472         write_player_file();
1473 }
1474
1475 #ifndef MACINTOSH
1476 #define WINDOW_W_DELTA  ((max_window_w / 16)&~1)        //24    //20
1477 #define WINDOW_H_DELTA  ((max_window_h / 16)&~1)        //12    //10
1478
1479 #define WINDOW_MIN_W            ((max_window_w * 10) / 22)      //160
1480 #define WINDOW_MIN_H            ((max_window_h * 10) / 22)
1481 #else
1482 //#define WINDOW_W_DELTA        32
1483 //#define WINDOW_H_DELTA        16
1484
1485 #define WINDOW_W_DELTA  ((max_window_w / 16) & ~15)             // double word aligned
1486 #define WINDOW_H_DELTA  ((max_window_h / 16) & ~15)             // double word aligned
1487
1488 #define WINDOW_MIN_W            (max_window_w-(WINDOW_W_DELTA*11))
1489 #define WINDOW_MIN_H            (max_window_h-(WINDOW_H_DELTA*11))
1490 #endif
1491
1492 void grow_window()
1493 {
1494         if (Cockpit_mode == CM_FULL_COCKPIT) {
1495                 Game_window_h = max_window_h;
1496                 Game_window_w = max_window_w;
1497                 toggle_cockpit();
1498                 HUD_init_message("Press F3 to return to Cockpit mode");
1499                 return;
1500         }
1501
1502         if (Cockpit_mode != CM_STATUS_BAR && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1503                 return;
1504
1505         if (Game_window_h>=max_window_h || Game_window_w>=max_window_w) {
1506                 //Game_window_w = max_window_w;
1507                 //Game_window_h = max_window_h;
1508                 select_cockpit(CM_FULL_SCREEN);
1509         } else {
1510                 //int x,y;
1511
1512                 Game_window_w += WINDOW_W_DELTA;
1513                 Game_window_h += WINDOW_H_DELTA;
1514
1515                 #ifdef MACINTOSH                // horrible hack to ensure that height is even to satisfy pixel doubling blitter
1516                 if ( Scanline_double && (Game_window_h & 1) )
1517                         Game_window_h--;
1518                 #endif
1519
1520                 if (Game_window_h > max_window_h)
1521                         Game_window_h = max_window_h;
1522
1523                 if (Game_window_w > max_window_w)
1524                         Game_window_w = max_window_w;
1525
1526                 Game_window_x = (max_window_w - Game_window_w)/2;
1527                 Game_window_y = (max_window_h - Game_window_h)/2;
1528
1529                 game_init_render_sub_buffers( Game_window_x, Game_window_y, Game_window_w, Game_window_h );
1530         }
1531
1532         HUD_clear_messages();   //      @mk, 11/11/94
1533
1534         write_player_file();
1535 }
1536
1537 // grs_bitmap background_bitmap;        already declared in line 434 (samir 4/10/94)
1538
1539 extern grs_bitmap background_bitmap;
1540
1541 void copy_background_rect(int left,int top,int right,int bot)
1542 {
1543         grs_bitmap *bm = &background_bitmap;
1544         int x,y;
1545         int tile_left,tile_right,tile_top,tile_bot;
1546         int ofs_x,ofs_y;
1547         int dest_x,dest_y;
1548
1549         if (right < left || bot < top)
1550                 return;
1551
1552         tile_left = left / bm->bm_w;
1553         tile_right = right / bm->bm_w;
1554         tile_top = top / bm->bm_h;
1555         tile_bot = bot / bm->bm_h;
1556
1557         ofs_y = top % bm->bm_h;
1558         dest_y = top;
1559
1560 WIN(DDGRLOCK(dd_grd_curcanv))
1561 {
1562         for (y=tile_top;y<=tile_bot;y++) {
1563                 int w,h;
1564
1565                 ofs_x = left % bm->bm_w;
1566                 dest_x = left;
1567
1568                 //h = (bot < dest_y+bm->bm_h)?(bot-dest_y+1):(bm->bm_h-ofs_y);
1569                 h = min(bot-dest_y+1,bm->bm_h-ofs_y);
1570
1571                 for (x=tile_left;x<=tile_right;x++) {
1572
1573                         //w = (right < dest_x+bm->bm_w)?(right-dest_x+1):(bm->bm_w-ofs_x);
1574                         w = min(right-dest_x+1,bm->bm_w-ofs_x);
1575                 
1576                         gr_bm_ubitblt(w,h,dest_x,dest_y,ofs_x,ofs_y,
1577                                         &background_bitmap,&grd_curcanv->cv_bitmap);
1578
1579                         ofs_x = 0;
1580                         dest_x += w;
1581                 }
1582
1583                 ofs_y = 0;
1584                 dest_y += h;
1585         }
1586
1587 WIN(DDGRUNLOCK(dd_grd_curcanv));
1588
1589 }
1590
1591 #ifdef WINDOWS
1592 int force_background_fill=0;
1593 #endif
1594
1595 //fills int the background surrounding the 3d window
1596 void fill_background()
1597 {
1598         int x,y,w,h,dx,dy;
1599
1600         x = Game_window_x;
1601         y = Game_window_y;
1602         w = Game_window_w;
1603         h = Game_window_h;
1604
1605         dx = x;
1606         dy = y;
1607
1608         WINDOS( dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]),
1609                                 gr_set_current_canvas(&VR_screen_pages[VR_current_page])
1610         );
1611         copy_background_rect(x-dx,y-dy,x-1,y+h+dy-1);
1612         copy_background_rect(x+w,y-dy,grd_curcanv->cv_w-1,y+h+dy-1);
1613         copy_background_rect(x,y-dy,x+w-1,y-1);
1614         copy_background_rect(x,y+h,x+w-1,y+h+dy-1);
1615
1616 #ifdef WINDOWS
1617         if (GRMODEINFO(modex)) {
1618                 copy_background_rect(x-dx,y-dy,x-1,y+h+dy-1);
1619                 copy_background_rect(x+w,y-dy,grd_curcanv->cv_w-1,y+h+dy-1);
1620                 copy_background_rect(x,y-dy,x+w-1,y-1);
1621                 copy_background_rect(x,y+h,x+w-1,y+h+dy-1);
1622         }
1623 #endif
1624
1625         if (VR_screen_flags & VRF_USE_PAGING) {
1626                 WINDOS( dd_gr_set_current_canvas(&dd_VR_screen_pages[!VR_current_page]),
1627                                         gr_set_current_canvas(&VR_screen_pages[!VR_current_page])
1628                 );
1629                 copy_background_rect(x-dx,y-dy,x-1,y+h+dy-1);
1630                 copy_background_rect(x+w,y-dy,x+w+dx-1,y+h+dy-1);
1631                 copy_background_rect(x,y-dy,x+w-1,y-1);
1632                 copy_background_rect(x,y+h,x+w-1,y+h+dy-1);
1633         }
1634
1635         #ifdef WINDOWS
1636         if (GRMODEINFO(modex) && force_background_fill==0)              //double-buffered
1637                 force_background_fill=2;
1638         #endif
1639 }
1640
1641 void shrink_window()
1642 {
1643         #ifdef WINDOWS
1644         //When you shrink the window twice in two frames, the background doens't
1645         //restore properly.  So this hack keeps you from shrinking the window
1646         //before two frames have been drawn
1647         static int last_shrink_framecount=-1;
1648         if (FrameCount - last_shrink_framecount < 2)
1649                 return;
1650         last_shrink_framecount = FrameCount;
1651         #endif
1652         
1653         mprintf((0,"%d ",FrameCount));
1654
1655 //  mprintf ((0,"W=%d H=%d\n",Game_window_w,Game_window_h));
1656  
1657         if (Cockpit_mode == CM_FULL_COCKPIT && (VR_screen_flags & VRF_ALLOW_COCKPIT)) {
1658                 Game_window_h = max_window_h;
1659                 Game_window_w = max_window_w;
1660                 //!!toggle_cockpit();
1661                 select_cockpit(CM_STATUS_BAR);
1662 //              shrink_window();
1663 //              shrink_window();
1664                 HUD_init_message("Press F3 to return to Cockpit mode");
1665                 write_player_file();
1666                 return;
1667         }
1668
1669         if (Cockpit_mode == CM_FULL_SCREEN && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1670         {
1671                 //Game_window_w = max_window_w;
1672                 //Game_window_h = max_window_h;
1673                 select_cockpit(CM_STATUS_BAR);
1674                 write_player_file();
1675                 return;
1676         }
1677
1678         if (Cockpit_mode != CM_STATUS_BAR && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1679                 return;
1680
1681    mprintf ((0,"Cockpit mode=%d\n",Cockpit_mode));
1682
1683         if (Game_window_w > WINDOW_MIN_W) {
1684                 //int x,y;
1685
1686       Game_window_w -= WINDOW_W_DELTA;
1687                 Game_window_h -= WINDOW_H_DELTA;
1688
1689
1690   mprintf ((0,"NewW=%d NewH=%d VW=%d maxH=%d\n",Game_window_w,Game_window_h,max_window_w,max_window_h));
1691                   
1692                 if ( Game_window_w < WINDOW_MIN_W )
1693                         Game_window_w = WINDOW_MIN_W;
1694
1695                 if ( Game_window_h < WINDOW_MIN_H )
1696                         Game_window_h = WINDOW_MIN_H;
1697                         
1698                 #ifdef MACINTOSH                // horrible hack to ensure that height is even to satisfy pixel doubling blitter
1699                 if ( Scanline_double && (Game_window_h & 1) )
1700                         Game_window_h--;
1701                 #endif
1702
1703                 Game_window_x = (max_window_w - Game_window_w)/2;
1704                 Game_window_y = (max_window_h - Game_window_h)/2;
1705
1706                 fill_background();
1707
1708                 game_init_render_sub_buffers( Game_window_x, Game_window_y, Game_window_w, Game_window_h );
1709                 HUD_clear_messages();
1710                 write_player_file();
1711         }
1712
1713 }
1714
1715 int last_drawn_cockpit[2] = { -1, -1 };
1716
1717 // This actually renders the new cockpit onto the screen.
1718 void update_cockpits(int force_redraw)
1719 {
1720         //int x, y, w, h;
1721
1722         if (Cockpit_mode != last_drawn_cockpit[VR_current_page] || force_redraw )
1723                 last_drawn_cockpit[VR_current_page] = Cockpit_mode;
1724         else
1725                 return;
1726
1727         //Redraw the on-screen cockpit bitmaps
1728         if (VR_render_mode != VR_NONE ) return;
1729
1730         switch( Cockpit_mode )  {
1731         case CM_FULL_COCKPIT:
1732         case CM_REAR_VIEW:
1733         WINDOS(
1734                 dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]),
1735                 gr_set_current_canvas(&VR_screen_pages[VR_current_page])
1736         );
1737                 PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode+(Current_display_mode?(Num_cockpits/2):0)]);
1738
1739         WIN(DDGRLOCK(dd_grd_curcanv));
1740                 gr_ubitmapm(0,0, &GameBitmaps[cockpit_bitmap[Cockpit_mode+(Current_display_mode?(Num_cockpits/2):0)].index]);   
1741         WIN(DDGRUNLOCK(dd_grd_curcanv));
1742                 break;
1743
1744         case CM_FULL_SCREEN:
1745                 Game_window_x = (max_window_w - Game_window_w)/2;
1746                 Game_window_y = (max_window_h - Game_window_h)/2;
1747                 fill_background();
1748                 break;
1749
1750         case CM_STATUS_BAR:
1751
1752                         WINDOS (        dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]),
1753                                                 gr_set_current_canvas(&VR_screen_pages[VR_current_page])
1754                         );
1755
1756                         PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode+(Current_display_mode?(Num_cockpits/2):0)]);
1757                         
1758                         WIN(DDGRLOCK(dd_grd_curcanv));
1759                                 gr_ubitmapm(0,max_window_h,&GameBitmaps[cockpit_bitmap[Cockpit_mode+(Current_display_mode?(Num_cockpits/2):0)].index]);
1760                         WIN(DDGRUNLOCK(dd_grd_curcanv));
1761         
1762                 #ifdef MACINTOSH                // hideously horrible hack to put grey line 1 scanline above because of pixel doubling "oddness"
1763                         if (Scanline_double)
1764                         {
1765                                 gr_setcolor(BM_XRGB(13,13,13));         // color of top of status bar
1766                                 gr_uscanline( 0, grd_curcanv->cv_w, max_window_h-1 );
1767                         }
1768                 #endif
1769
1770                 Game_window_x = (max_window_w - Game_window_w)/2;
1771                 Game_window_y = (max_window_h - Game_window_h)/2;
1772                 fill_background();
1773                 break;
1774
1775         case CM_LETTERBOX:
1776                 WINDOS( dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]),
1777                                         gr_set_current_canvas(&VR_screen_pages[VR_current_page])
1778                 );
1779                 WINDOS ( dd_gr_clear_canvas( BM_XRGB(0,0,0) ),
1780                                         gr_clear_canvas( BM_XRGB(0,0,0) ) );
1781
1782                 // In a modex mode, clear the other buffer.
1783                 if (grd_curcanv->cv_bitmap.bm_type == BM_MODEX) {
1784                         gr_set_current_canvas(&VR_screen_pages[VR_current_page^1]);
1785                         gr_clear_canvas( BM_XRGB(0,0,0) );
1786                         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1787                 }
1788                 break;
1789
1790         }
1791
1792         WINDOS (        dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]),
1793                                 gr_set_current_canvas(&VR_screen_pages[VR_current_page])
1794         );
1795
1796         if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR)
1797                 init_gauges();
1798
1799 }
1800
1801
1802 void game_render_frame()
1803 {
1804         set_screen_mode( SCREEN_GAME );
1805
1806         update_cockpits(0);
1807
1808         #ifdef WINDOWS
1809         if (force_background_fill) {
1810                 fill_background();
1811                 force_background_fill--;
1812         }
1813         #endif
1814
1815         play_homing_warning();
1816
1817         if (VR_render_mode == VR_NONE )
1818                 game_render_frame_mono();        
1819 /*      else
1820                 game_render_frame_stereo();      
1821                 */
1822
1823         // Make sure palette is faded in
1824         stop_time();
1825         gr_palette_fade_in( gr_palette, 32, 0 );
1826         start_time();
1827
1828         FrameCount++;
1829 }
1830
1831 extern int Color_0_31_0;
1832
1833 //draw a crosshair for the guided missile
1834 void draw_guided_crosshair(void)
1835 {
1836         int x,y,w,h;
1837
1838         gr_setcolor(Color_0_31_0);
1839
1840         w = grd_curcanv->cv_w>>5;
1841         if (w < 5)
1842                 w = 5;
1843
1844         h = i2f(w) / grd_curscreen->sc_aspect;
1845
1846         x = grd_curcanv->cv_w / 2;
1847         y = grd_curcanv->cv_h / 2;
1848
1849         gr_scanline(x-w/2,x+w/2,y);
1850         gr_uline(i2f(x),i2f(y-h/2),i2f(x),i2f(y+h/2));
1851
1852 }
1853
1854 typedef struct bkg {
1855         short x, y, w, h;                       // The location of the menu.
1856         grs_bitmap * bmp;                       // The background under the menu.
1857 } bkg;
1858
1859 bkg bg = {0,0,0,0,NULL};
1860
1861 #define BOX_BORDER (MenuHires?60:30)
1862
1863 //show a message in a nice little box
1864 void show_boxed_message(char *msg)
1865 {       
1866         int w,h,aw;
1867         int x,y;
1868
1869         WINDOS(
1870                 dd_gr_set_current_canvas(&dd_VR_screen_pages[VR_current_page]),
1871                 gr_set_current_canvas(&VR_screen_pages[VR_current_page])
1872         );
1873         gr_set_curfont( MEDIUM1_FONT );
1874
1875         gr_get_string_size(msg,&w,&h,&aw);
1876
1877         x = (grd_curscreen->sc_w-w)/2;
1878         y = (grd_curscreen->sc_h-h)/2;
1879
1880         if (bg.bmp) {
1881                 gr_free_bitmap(bg.bmp);
1882                 bg.bmp = NULL;
1883         }
1884
1885         // Save the background of the display
1886         bg.x=x; bg.y=y; bg.w=w; bg.h=h;
1887
1888 #if defined(POLY_ACC)
1889     bg.bmp = gr_create_bitmap2( w+BOX_BORDER, h+BOX_BORDER, grd_curcanv->cv_bitmap.bm_type, NULL );
1890 #else
1891         bg.bmp = gr_create_bitmap( w+BOX_BORDER, h+BOX_BORDER );
1892 #endif
1893
1894         WIN( DDGRLOCK(dd_grd_curcanv));
1895                 gr_bm_ubitblt(w+BOX_BORDER, h+BOX_BORDER, 0, 0, x-BOX_BORDER/2, y-BOX_BORDER/2, &(grd_curcanv->cv_bitmap), bg.bmp );
1896         WIN( DDGRUNLOCK(dd_grd_curcanv));
1897
1898                 nm_draw_background(x-BOX_BORDER/2,y-BOX_BORDER/2,x+w+BOX_BORDER/2-1,y+h+BOX_BORDER/2-1);
1899
1900                 gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 );
1901
1902         WIN( DDGRLOCK(dd_grd_curcanv));
1903                 gr_ustring( 0x8000, y, msg );
1904         WIN( DDGRUNLOCK(dd_grd_curcanv));
1905         WIN( DDGRRESTORE);
1906 }
1907
1908 void clear_boxed_message()
1909 {
1910
1911         if (bg.bmp) {
1912
1913                 WIN(DDGRLOCK(dd_grd_curcanv));
1914                         gr_bitmap(bg.x-BOX_BORDER/2, bg.y-BOX_BORDER/2, bg.bmp);
1915                 WIN(DDGRUNLOCK(dd_grd_curcanv));
1916                 WIN(DDGRRESTORE);
1917         
1918                 gr_free_bitmap(bg.bmp);
1919                 bg.bmp = NULL;
1920         }
1921 }
1922
1923
1924 #ifdef WINDOWS
1925 void win_do_emul_ibitblt(dd_grs_canvas *csrc, dd_grs_canvas *cdest)
1926 {
1927         ubyte *src_data;
1928         ubyte *dest_data;
1929         int line, span;
1930
1931
1932         WIN(DDGRLOCK(csrc));
1933         WIN(DDGRLOCK(cdest));
1934                 src_data = csrc->canvas.cv_bitmap.bm_data;
1935                 dest_data = cdest->canvas.cv_bitmap.bm_data; 
1936
1937 //              mprintf((0, "Render Ptr: %x;  Dest Ptr: %x;\n",src_data, dest_data));
1938
1939                 for (line = 0; line < 480; line++, 
1940                                                 dest_data += cdest->canvas.cv_bitmap.bm_rowsize)
1941                 {
1942                         cockpit_span_line *sline;
1943
1944                         sline = &win_cockpit_mask[line];
1945
1946                         if (!sline->num) continue;
1947                         if (sline->num == 255) break;
1948                         for (span = 0; span < sline->num; span++)
1949                         {
1950                                 if ((sline->span[span].xmax-sline->span[span].xmin+1) < 10) {
1951                                         gr_winckpit_blt_span(sline->span[span].xmin,
1952                                                                                 sline->span[span].xmax,
1953                                                                                 src_data, dest_data);
1954                                 }
1955                                 else {
1956                                         gr_winckpit_blt_span_long(sline->span[span].xmin,
1957                                                                                 sline->span[span].xmax,
1958                                                                                 src_data, dest_data);
1959                                 }
1960                         }
1961                         src_data += csrc->canvas.cv_bitmap.bm_rowsize;
1962                 }
1963         WIN(DDGRUNLOCK(cdest));
1964         WIN(DDGRUNLOCK(csrc));
1965 }
1966
1967
1968 //@@void win_do_emul_ibitblt(dd_grs_canvas *csrc, dd_grs_canvas *cdest)
1969 //@@{
1970 //@@    HRESULT res;
1971 //@@    DDBLTFX bltfx;
1972 //@@    RECT srect, drect;
1973 //@@
1974 //@@//  Do Render Blt to Mask Surface (dest blt 1-255)
1975 //@@    bltfx.dwSize = sizeof(bltfx);
1976 //@@    bltfx.ddckDestColorkey.dwColorSpaceLowValue = 1;
1977 //@@    bltfx.ddckDestColorkey.dwColorSpaceHighValue = 255;
1978 //@@    SetRect(&srect, 0,0,    csrc->canvas.cv_w, csrc->canvas.cv_h);
1979 //@@    SetRect(&drect, 0,0,    csrc->canvas.cv_w, csrc->canvas.cv_h);
1980 //@@
1981 //@@    res = IDirectDrawSurface_Blt(_lpDDSMask, &drect, csrc->lpdds, &srect,
1982 //@@                                                                            DDBLT_WAIT | DDBLT_KEYDESTOVERRIDE,
1983 //@@                                                                            &bltfx);
1984 //@@    if (res != DD_OK) 
1985 //@@            Error("win_ibitblt: ddraw blt to mask err: %x.\n", res);
1986 //@@
1987 //@@//  Do Mask Blt to Screen (src blt !0)
1988 //@@    bltfx.dwSize = sizeof(bltfx);
1989 //@@    bltfx.ddckSrcColorkey.dwColorSpaceLowValue = 0;
1990 //@@    bltfx.ddckSrcColorkey.dwColorSpaceHighValue = 0;
1991 //@@
1992 //@@    res = IDirectDrawSurface_Blt(cdest->lpdds, &drect, _lpDDSMask, &srect,
1993 //@@                                                                            DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE,
1994 //@@                                                                            NULL);
1995 //@@    if (res != DD_OK) 
1996 //@@            Error("win_ibitblt: ddraw blt to screen err: %x.\n", res);
1997 //@@}
1998 #endif
1999