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