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