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