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