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