]> icculus.org git repositories - btb/d2x.git/blob - main/gamerend.c
get rid of dependencies on predefined display modes
[btb/d2x.git] / main / gamerend.c
1 /* $Id: gamerend.c,v 1.22 2006-11-26 01:05:24 chris 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.22 2006-11-26 01:05:24 chris Exp $";
27 #endif
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32
33 #include "pstypes.h"
34 #include "console.h"
35 #include "inferno.h"
36 #include "error.h"
37 #include "mono.h"
38 #include "gr.h"
39 #include "palette.h"
40 #include "ibitblt.h"
41 #include "bm.h"
42 #include "player.h"
43 #include "render.h"
44 #include "menu.h"
45 #include "newmenu.h"
46 #include "screens.h"
47 #include "fix.h"
48 #include "robot.h"
49 #include "game.h"
50 #include "gauges.h"
51 #include "gamefont.h"
52 #include "newdemo.h"
53 #include "text.h"
54 #include "multi.h"
55 #include "endlevel.h"
56 #include "cntrlcen.h"
57 #include "powerup.h"
58 #include "laser.h"
59 #include "playsave.h"
60 #include "automap.h"
61 #include "mission.h"
62 #include "gameseq.h"
63
64 #ifdef OGL
65 #include "ogl_init.h"
66 #endif
67
68 extern fix Cruise_speed;
69 extern int LinearSVGABuffer;
70 extern cvar_t r_framerate;
71
72
73 #ifndef NDEBUG
74 extern int Debug_pause;                         //John's debugging pause system
75 #endif
76
77 #ifndef RELEASE
78 extern int Saving_movie_frames;
79 #else
80 #define Saving_movie_frames 0
81 #endif
82
83 // Returns the length of the first 'n' characters of a string.
84 int string_width( char * s, int n )
85 {
86         int w,h,aw;
87         char p;
88         p = s[n];
89         s[n] = 0;
90         gr_get_string_size( s, &w, &h, &aw );
91         s[n] = p;
92         return w;
93 }
94
95 // Draw string 's' centered on a canvas... if wider than
96 // canvas, then wrap it.
97 void draw_centered_text( int y, char * s )
98 {
99         int i, l;
100         char p;
101
102         l = strlen(s);
103
104         if ( string_width( s, l ) < grd_curcanv->cv_bitmap.bm_w )       {
105                 gr_string( 0x8000, y, s );
106                 return;
107         }
108
109         for (i=0; i<l; i++ )    {
110                 if ( string_width(s,i) > (grd_curcanv->cv_bitmap.bm_w - 16) )   {
111                         p = s[i];
112                         s[i] = 0;
113                         gr_string( 0x8000, y, s );
114                         s[i] = p;
115                         gr_string( 0x8000, y+grd_curcanv->cv_font->ft_h+1, &s[i] );
116                         return;
117                 }
118         }
119 }
120
121 extern ubyte DefiningMarkerMessage;
122 extern char Marker_input[];
123
124 #define MAX_MARKER_MESSAGE_LEN 120
125 void game_draw_marker_message()
126 {
127         char temp_string[MAX_MARKER_MESSAGE_LEN+25];
128
129         if ( DefiningMarkerMessage)
130           {
131                 gr_set_curfont( GAME_FONT );    //GAME_FONT 
132                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
133                 sprintf( temp_string, "Marker: %s_", Marker_input );
134                 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
135           }
136
137 }
138
139 #ifdef NETWORK
140 void game_draw_multi_message()
141 {
142         char temp_string[MAX_MULTI_MESSAGE_LEN+25];
143
144         if ( (Game_mode&GM_MULTI) && (multi_sending_message))   {
145                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
146                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
147                 sprintf( temp_string, "%s: %s_", TXT_MESSAGE, Network_message );
148                 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
149
150         }
151
152         if ( (Game_mode&GM_MULTI) && (multi_defining_message))  {
153                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
154                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
155                 sprintf( temp_string, "%s #%d: %s_", TXT_MACRO, multi_defining_message, Network_message );
156                 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
157         }
158 }
159 #endif
160
161 //these should be in gr.h 
162 #define cv_w  cv_bitmap.bm_w
163 #define cv_h  cv_bitmap.bm_h
164
165 fix frame_time_list[8] = {0,0,0,0,0,0,0,0};
166 fix frame_time_total=0;
167 int frame_time_cntr=0;
168
169 void ftoa(char *string, fix f)
170 {
171         int decimal, fractional;
172         
173         decimal = f2i(f);
174         fractional = ((f & 0xffff)*100)/65536;
175         if (fractional < 0 )
176                 fractional *= -1;
177         if (fractional > 99 ) fractional = 99;
178         sprintf( string, "%d.%02d", decimal, fractional );
179 }
180
181 void show_framerate()
182 {
183         char temp[50];
184    //static int q;
185
186         fix rate;
187         int x = 8, y = 5; // position measured from lower right corner
188
189         frame_time_total += RealFrameTime - frame_time_list[frame_time_cntr];
190         frame_time_list[frame_time_cntr] = RealFrameTime;
191         frame_time_cntr = (frame_time_cntr+1)%8;
192
193         rate = fixdiv(f1_0*8,frame_time_total);
194
195         gr_set_curfont( GAME_FONT );    
196         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
197
198         ftoa( temp, rate );     // Convert fixed to string
199         if (Game_mode & GM_MULTI)
200                 y = 7;
201         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 );
202 //   if ( !( q++ % 30 ) )
203 //      mprintf( (0,"fps: %s\n", temp ) );
204 }
205
206 #ifndef NDEBUG
207
208 fix Show_view_text_timer = -1;
209
210 void draw_window_label()
211 {
212         if ( Show_view_text_timer > 0 )
213         {
214                 char *viewer_name,*control_name;
215                 char    *viewer_id;
216                 Show_view_text_timer -= FrameTime;
217                 gr_set_curfont( GAME_FONT );
218
219                 viewer_id = "";
220                 switch( Viewer->type )
221                 {
222                         case OBJ_FIREBALL:      viewer_name = "Fireball"; break;
223                         case OBJ_ROBOT:         viewer_name = "Robot";
224 #ifdef EDITOR
225                                                                                 viewer_id = Robot_names[Viewer->id];
226 #endif
227                                 break;
228                         case OBJ_HOSTAGE:               viewer_name = "Hostage"; break;
229                         case OBJ_PLAYER:                viewer_name = "Player"; break;
230                         case OBJ_WEAPON:                viewer_name = "Weapon"; break;
231                         case OBJ_CAMERA:                viewer_name = "Camera"; break;
232                         case OBJ_POWERUP:               viewer_name = "Powerup";
233 #ifdef EDITOR
234                                                                                 viewer_id = Powerup_names[Viewer->id];
235 #endif
236                                 break;
237                         case OBJ_DEBRIS:                viewer_name = "Debris"; break;
238                         case OBJ_CNTRLCEN:      viewer_name = "Reactor"; break;
239                         default:                                        viewer_name = "Unknown"; break;
240                 }
241
242                 switch ( Viewer->control_type) {
243                         case CT_NONE:                   control_name = "Stopped"; break;
244                         case CT_AI:                             control_name = "AI"; break;
245                         case CT_FLYING:         control_name = "Flying"; break;
246                         case CT_SLEW:                   control_name = "Slew"; break;
247                         case CT_FLYTHROUGH:     control_name = "Flythrough"; break;
248                         case CT_MORPH:                  control_name = "Morphing"; break;
249                         default:                                        control_name = "Unknown"; break;
250                 }
251
252                 gr_set_fontcolor( gr_getcolor(31, 0, 0), -1 );
253                 gr_printf( 0x8000, 45, "%i: %s [%s] View - %s", OBJECT_NUMBER(Viewer), viewer_name, viewer_id, control_name );
254
255         }
256 }
257 #endif
258
259 extern int Game_window_x;
260 extern int Game_window_y;
261 extern int Game_window_w;
262 extern int Game_window_h;
263 extern int max_window_w;
264 extern int max_window_h;
265
266 void render_countdown_gauge()
267 {
268         if (!Endlevel_sequence && Control_center_destroyed  && (Countdown_seconds_left>-1)) { // && (Countdown_seconds_left<127))       {
269                 int     y;
270
271                 if (!is_D2_OEM && !is_MAC_SHARE && !is_SHAREWARE)    // no countdown on registered only
272                 {
273                         //      On last level, we don't want a countdown.
274                         if (PLAYING_BUILTIN_MISSION && Current_level_num == Last_level)
275                         {
276                                 if (!(Game_mode & GM_MULTI))
277                                         return;
278                                 if (Game_mode & GM_MULTI_ROBOTS)
279                                         return;
280                         }
281                 }
282
283                 gr_set_curfont( SMALL_FONT );
284                 gr_set_fontcolor(gr_getcolor(0,63,0), -1 );
285                 y = SMALL_FONT->ft_h*4;
286                 if (Cockpit_mode == CM_FULL_SCREEN)
287                         y += SMALL_FONT->ft_h*2;
288
289                 if (Player_is_dead)
290                         y += SMALL_FONT->ft_h*2;
291
292                 //if (!((Cockpit_mode == CM_STATUS_BAR) && (Game_window_y >= 19)))
293                 //      y += 5;
294                 gr_printf(0x8000, y, "T-%d s", Countdown_seconds_left );
295         }
296 }
297
298 void game_draw_hud_stuff()
299 {
300         //mprintf ((0,"Linear is %d!\n",LinearSVGABuffer));
301         
302         #ifndef NDEBUG
303         if (Debug_pause) {
304                 gr_set_curfont( MEDIUM1_FONT );
305                 gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 ); // gr_getcolor(31,0,0));
306                 gr_ustring( 0x8000, 85/2, "Debug Pause - Press P to exit" );
307         }
308         #endif
309
310         #ifndef NDEBUG
311         draw_window_label();
312         #endif
313
314 #ifdef NETWORK
315         game_draw_multi_message();
316 #endif
317
318    game_draw_marker_message();
319
320 //   if (Game_mode & GM_MULTI)
321 //    {
322 //     if (Netgame.PlayTimeAllowed)
323 //       game_draw_time_left ();
324 //  }
325
326         if ((Newdemo_state == ND_STATE_PLAYBACK) || (Newdemo_state == ND_STATE_RECORDING)) {
327                 char message[128];
328                 int h,w,aw;
329
330                 if (Newdemo_state == ND_STATE_PLAYBACK) {
331                         if (Newdemo_vcr_state != ND_STATE_PRINTSCREEN) {
332                                 sprintf(message, "%s (%d%%%% %s)", TXT_DEMO_PLAYBACK, newdemo_get_percent_done(), TXT_DONE);
333                         } else {
334                                 sprintf (message, " ");
335                         }
336                 } else 
337                         sprintf (message, "%s", TXT_DEMO_RECORDING);
338
339                 gr_set_curfont( GAME_FONT );    //GAME_FONT );
340                 gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
341
342                 gr_get_string_size(message, &w, &h, &aw );
343                 if (Cockpit_mode == CM_FULL_COCKPIT) {
344                         if (grd_curcanv->cv_bitmap.bm_h > 240)
345                                 h += 40;
346                         else
347                                 h += 15;
348                 } else if ( Cockpit_mode == CM_LETTERBOX )
349                         h += 7;
350                 if (Cockpit_mode != CM_REAR_VIEW && !Saving_movie_frames)
351                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, grd_curcanv->cv_bitmap.bm_h - h - 2, message );
352         }
353
354         render_countdown_gauge();
355
356         if ( Player_num > -1 && Viewer->type==OBJ_PLAYER && Viewer->id==Player_num )    {
357                 int     x = 3;
358                 int     y = grd_curcanv->cv_bitmap.bm_h;
359
360                 gr_set_curfont( GAME_FONT );
361                 gr_set_fontcolor( gr_getcolor(0, 31, 0), -1 );
362                 if (Cruise_speed > 0) {
363                         int line_spacing = GAME_FONT->ft_h + GAME_FONT->ft_h/4;
364
365 mprintf((0,"line_spacing=%d ",line_spacing));
366
367                         if (Cockpit_mode==CM_FULL_SCREEN) {
368                                 if (Game_mode & GM_MULTI)
369                                         y -= line_spacing * 11; //64
370                                 else
371                                         y -= line_spacing * 6;  //32
372                         } else if (Cockpit_mode == CM_STATUS_BAR) {
373                                 if (Game_mode & GM_MULTI)
374                                         y -= line_spacing * 8;  //48
375                                 else
376                                         y -= line_spacing * 4;  //24
377                         } else {
378                                 y = line_spacing * 2;   //12
379                                 x = 20+2;
380                         }
381
382                         gr_printf( x, y, "%s %2d%%", TXT_CRUISE, f2i(Cruise_speed) );
383                 }
384         }
385
386         if (r_framerate.value)
387                 show_framerate();
388
389         if ( Newdemo_state == ND_STATE_PLAYBACK )
390                 Game_mode = Newdemo_game_mode;
391
392         draw_hud();
393
394         if ( Newdemo_state == ND_STATE_PLAYBACK )
395                 Game_mode = GM_NORMAL;
396
397         if ( Player_is_dead )
398                 player_dead_message();
399 }
400
401 extern int gr_bitblt_dest_step_shift;
402 extern int gr_wait_for_retrace;
403 extern int gr_bitblt_double;
404
405 #if 0
406 void expand_row(ubyte * dest, ubyte * src, int num_src_pixels );
407 #pragma aux expand_row parm [edi] [esi] [ecx] modify exact [ecx esi edi eax ebx] = \
408         "add    esi, ecx"                       \
409         "dec    esi"                                    \
410         "add    edi, ecx"                       \
411         "add    edi, ecx"                       \
412         "dec    edi"                                    \
413         "dec    edi"                                    \
414 "nextpixel:"                                    \
415         "mov    al,[esi]"                       \
416         "mov    ah, al"                         \
417         "dec    esi"                                    \
418         "mov    [edi], ax"                      \
419         "dec    edi"                                    \
420         "dec    edi"                                    \
421         "dec    ecx"                                    \
422         "jnz    nextpixel"                      \
423 "done:"
424 #else
425 void expand_row(ubyte * dest, ubyte * src, int num_src_pixels )
426 {
427         int i;
428         
429         for (i = 0; i < num_src_pixels; i++) {
430                 *dest++ = *src;
431                 *dest++ = *src++;
432         }
433 }
434 #endif
435
436 // doubles the size in x or y of a bitmap in place.
437 void game_expand_bitmap( grs_bitmap * bmp, uint flags )
438 {
439         int i;
440         ubyte * dptr, * sptr;
441
442         switch(flags & 3)       {
443         case 2: // expand x
444                 Assert( bmp->bm_rowsize == bmp->bm_w*2 );
445                 dptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
446                 for (i=bmp->bm_h-1; i>=0; i-- ) {
447                         expand_row( dptr, dptr, bmp->bm_w );    
448                         dptr -= bmp->bm_rowsize;
449                 }
450                 bmp->bm_w *= 2;
451                 break;
452         case 1: // expand y
453                 dptr = &bmp->bm_data[(2*(bmp->bm_h-1)+1)*bmp->bm_rowsize];
454                 sptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
455                 for (i=bmp->bm_h-1; i>=0; i-- ) {
456                         memcpy( dptr, sptr, bmp->bm_w );        
457                         dptr -= bmp->bm_rowsize;
458                         memcpy( dptr, sptr, bmp->bm_w );        
459                         dptr -= bmp->bm_rowsize;
460                         sptr -= bmp->bm_rowsize;
461                 }
462                 bmp->bm_h *= 2;
463                 break;
464         case 3: // expand x & y
465                 Assert( bmp->bm_rowsize == bmp->bm_w*2 );
466                 dptr = &bmp->bm_data[(2*(bmp->bm_h-1)+1)*bmp->bm_rowsize];
467                 sptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
468                 for (i=bmp->bm_h-1; i>=0; i-- ) {
469                         expand_row( dptr, sptr, bmp->bm_w );    
470                         dptr -= bmp->bm_rowsize;
471                         expand_row( dptr, sptr, bmp->bm_w );    
472                         dptr -= bmp->bm_rowsize;
473                         sptr -= bmp->bm_rowsize;
474                 }
475                 bmp->bm_w *= 2;
476                 bmp->bm_h *= 2;
477                 break;
478         }
479 }
480
481 extern int SW_drawn[2], SW_x[2], SW_y[2], SW_w[2], SW_h[2];
482
483 extern int Guided_in_big_window;
484
485 #if 0
486 //render a frame for the game in stereo
487 void game_render_frame_stereo()
488 {
489         int dw,dh,sw,sh;
490         fix save_aspect;
491         fix actual_eye_width;
492         int actual_eye_offset;
493         grs_canvas RenderCanvas[2];
494         int no_draw_hud=0;
495
496         save_aspect = grd_curscreen->sc_aspect;
497         grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio
498
499         sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
500         sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
501
502         if (VR_low_res & 1)     {
503                 sh /= 2;                                
504                 grd_curscreen->sc_aspect *= 2;  //Muck with aspect ratio                                
505         }
506         if (VR_low_res & 2)     {
507                 sw /= 2;                                
508                 grd_curscreen->sc_aspect /= 2;  //Muck with aspect ratio                                
509         }
510
511         gr_init_sub_canvas( &RenderCanvas[0], &VR_render_buffer[0], 0, 0, sw, sh );
512         gr_init_sub_canvas( &RenderCanvas[1], &VR_render_buffer[1], 0, 0, sw, sh );
513
514         // Draw the left eye's view
515         if (VR_eye_switch)      {
516                 actual_eye_width = -VR_eye_width;
517                 actual_eye_offset = -VR_eye_offset;
518         } else {
519                 actual_eye_width = VR_eye_width;
520                 actual_eye_offset = VR_eye_offset;
521         }
522
523         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)
524                 actual_eye_offset = 0;
525
526         gr_set_current_canvas(&RenderCanvas[0]);
527
528         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) {
529                 char *msg = "Guided Missile View";
530                 object *viewer_save = Viewer;
531                 int w,h,aw;
532
533                 Viewer = Guided_missile[Player_num];
534
535                 {
536                         update_rendered_data(0, Viewer, 0, 0);
537                         render_frame(0, 0);
538   
539                         wake_up_rendered_objects(Viewer, 0);
540                         Viewer = viewer_save;
541
542                         gr_set_curfont( GAME_FONT );    //GAME_FONT );
543                         gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
544                         gr_get_string_size(msg, &w, &h, &aw );
545
546                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
547
548                         draw_guided_crosshair();
549                 }
550
551                 HUD_render_message_frame();
552
553                 no_draw_hud=1;
554         }
555         else if (Rear_view)
556                 render_frame(actual_eye_width, 0);      // switch eye positions for rear view
557         else
558                 render_frame(-actual_eye_width, 0);             // Left eye
559
560         if ( VR_low_res )
561                 game_expand_bitmap( &RenderCanvas[0].cv_bitmap, VR_low_res );
562
563         {       //render small window into left eye's canvas
564                 grs_canvas *save=grd_curcanv;
565                 fix save_aspect2 = grd_curscreen->sc_aspect;
566                 grd_curscreen->sc_aspect = save_aspect*2;
567                 SW_drawn[0] = SW_drawn[1] = 0;
568                 show_extra_views();
569                 gr_set_current_canvas(save);
570                 grd_curscreen->sc_aspect = save_aspect2;
571         }
572
573 //NEWVR
574         if (actual_eye_offset > 0 ) {
575                 gr_setcolor( gr_getcolor(0,0,0) );
576                 gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(actual_eye_offset)*2, 0, 
577                grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
578         } else if (actual_eye_offset < 0 ) {
579                 gr_setcolor( gr_getcolor(0,0,0) );
580                 gr_rect( 0, 0, labs(actual_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
581         }
582
583         if ( VR_show_hud && !no_draw_hud )      {
584                 grs_canvas tmp;
585                 if (actual_eye_offset < 0 ) {
586                         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 );
587                 } else {
588                         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 );
589                 }
590                 gr_set_current_canvas( &tmp );
591                 game_draw_hud_stuff();
592         }
593
594
595         // Draw the right eye's view
596         gr_set_current_canvas(&RenderCanvas[1]);
597
598         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)
599                 gr_bitmap(0,0,&RenderCanvas[0].cv_bitmap);
600         else {
601                 if (Rear_view)
602                         render_frame(-actual_eye_width, 0);     // switch eye positions for rear view
603                 else
604                         render_frame(actual_eye_width, 0);              // Right eye
605
606                 if ( VR_low_res )
607                         game_expand_bitmap( &RenderCanvas[1].cv_bitmap, VR_low_res );
608         }
609
610
611         {       //copy small window from left eye
612                 grs_canvas temp;
613                 int w;
614                 for (w=0;w<2;w++) {
615                         if (SW_drawn[w]) {
616                                 gr_init_sub_canvas(&temp,&RenderCanvas[0],SW_x[w],SW_y[w],SW_w[w],SW_h[w]);
617                                 gr_bitmap(SW_x[w]+actual_eye_offset*2,SW_y[w],&temp.cv_bitmap);
618                         }
619                 }
620         }
621
622 //NEWVR
623         if (actual_eye_offset>0) {
624                 gr_setcolor( gr_getcolor(0,0,0) );
625                 gr_rect( 0, 0, labs(actual_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
626         } else if ( actual_eye_offset < 0 )     {
627                 gr_setcolor( gr_getcolor(0,0,0) );
628                 gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(actual_eye_offset)*2, 0, 
629                grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
630         }
631
632 //NEWVR (Add the next 2 lines)
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         // Draws white and black registration encoding lines
646         // and Accounts for pixel-shift adjustment in upcoming bitblts
647         if (VR_use_reg_code)    {
648                 int width, height, quarter;
649
650                 width = RenderCanvas[0].cv_bitmap.bm_w;
651                 height = RenderCanvas[0].cv_bitmap.bm_h;
652                 quarter = width / 4;
653
654                 // black out left-hand side of left page
655
656                 // draw registration code for left eye
657                 if ( VR_eye_switch )
658                         gr_set_current_canvas( &RenderCanvas[1] );
659                 else
660                         gr_set_current_canvas( &RenderCanvas[0] );
661                 gr_setcolor( VR_WHITE_INDEX );
662                 gr_scanline( 0, quarter, height-1 );
663                 gr_setcolor( VR_BLACK_INDEX );
664                 gr_scanline( quarter, width-1, height-1 );
665
666                 if ( VR_eye_switch )
667                         gr_set_current_canvas( &RenderCanvas[0] );
668                 else
669                         gr_set_current_canvas( &RenderCanvas[1] );
670                 gr_setcolor( VR_WHITE_INDEX );
671                 gr_scanline( 0, quarter*3, height-1 );
672                 gr_setcolor( VR_BLACK_INDEX );
673                 gr_scanline( quarter*3, width-1, height-1 );
674    }
675
676                 // Copy left eye, then right eye
677         if ( VR_screen_flags&VRF_USE_PAGING )
678                 VR_current_page = !VR_current_page;
679         else 
680                 VR_current_page = 0;
681         gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
682
683 //NEWVR
684
685         if ( VR_eye_offset_changed > 0 )        {
686                 VR_eye_offset_changed--;
687                 gr_clear_canvas(0);
688         }
689
690         sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
691         sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
692
693         // Copy left eye, then right eye
694         gr_bitblt_dest_step_shift = 1;          // Skip every other scanline.
695
696         if (VR_render_mode == VR_INTERLACED )   {
697                 if ( actual_eye_offset > 0 )    {
698                         int xoff = labs(actual_eye_offset);
699                         gr_bm_ubitblt( dw-xoff, dh, xoff, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
700                         gr_bm_ubitblt( dw-xoff, dh, 0, 1, xoff, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
701                 } else if ( actual_eye_offset < 0 )     {
702                         int xoff = labs(actual_eye_offset);
703                         gr_bm_ubitblt( dw-xoff, dh, 0, 0, xoff, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
704                         gr_bm_ubitblt( dw-xoff, dh, xoff, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
705                 } else {
706                         gr_bm_ubitblt( dw, dh, 0, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
707                         gr_bm_ubitblt( dw, dh, 0, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap);
708                 }
709         } else if (VR_render_mode == VR_AREA_DET) {
710                 // VFX copy
711                 gr_bm_ubitblt( dw, dh, 0,  VR_current_page, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
712                 gr_bm_ubitblt( dw, dh, dw, VR_current_page, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[0].cv_bitmap);
713         } else {
714                 Int3();         // Huh?
715         }
716
717         gr_bitblt_dest_step_shift = 0;
718
719         //if ( Game_vfx_flag )
720         //      vfx_set_page(VR_current_page);          // 0 or 1
721         //else 
722                 if ( VR_screen_flags&VRF_USE_PAGING )   {
723                         gr_wait_for_retrace = 0;
724
725 //      Added by Samir from John's code
726                 if ( (VR_screen_pages[VR_current_page].cv_bitmap.bm_type == BM_MODEX) && (Game_3dmax_flag==3) ) {
727                         int old_x, old_y, new_x;
728                         old_x = VR_screen_pages[VR_current_page].cv_bitmap.bm_x;
729                         old_y = VR_screen_pages[VR_current_page].cv_bitmap.bm_y;
730                         new_x = old_y*VR_screen_pages[VR_current_page].cv_bitmap.bm_rowsize;
731                         new_x += old_x/4;
732                         VR_screen_pages[VR_current_page].cv_bitmap.bm_x = new_x;
733                         VR_screen_pages[VR_current_page].cv_bitmap.bm_y = 0;
734                         VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_SVGA;
735                         gr_show_canvas( &VR_screen_pages[VR_current_page] );
736                         VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_MODEX;
737                         VR_screen_pages[VR_current_page].cv_bitmap.bm_x = old_x;
738                         VR_screen_pages[VR_current_page].cv_bitmap.bm_y = old_y;
739                 } else {
740                         gr_show_canvas( &VR_screen_pages[VR_current_page] );
741                 }
742                 gr_wait_for_retrace = 1;
743         }
744         grd_curscreen->sc_aspect=save_aspect;
745 }
746 #endif
747 ubyte RenderingType=0;
748 ubyte DemoDoingRight=0,DemoDoingLeft=0;
749 extern ubyte DemoDoRight,DemoDoLeft;
750 extern object DemoRightExtra,DemoLeftExtra;
751
752 char DemoWBUType[]={0,WBU_MISSILE,WBU_MISSILE,WBU_REAR,WBU_ESCORT,WBU_MARKER,WBU_MISSILE};
753 char DemoRearCheck[]={0,0,0,1,0,0,0};
754 char *DemoExtraMessage[]={"PLAYER","GUIDED","MISSILE","REAR","GUIDE-BOT","MARKER","SHIP"};
755
756 extern char guidebot_name[];
757
758 void show_extra_views()
759 {
760         int did_missile_view=0;
761         int save_newdemo_state = Newdemo_state;
762         int w;
763
764    if (Newdemo_state==ND_STATE_PLAYBACK)
765     {
766      if (DemoDoLeft)
767       { 
768                  DemoDoingLeft=DemoDoLeft;
769                 
770        if (DemoDoLeft==3)
771                         do_cockpit_window_view(0,ConsoleObject,1,WBU_REAR,"REAR");
772        else
773               do_cockpit_window_view(0,&DemoLeftExtra,DemoRearCheck[DemoDoLeft],DemoWBUType[DemoDoLeft],DemoExtraMessage[DemoDoLeft]);
774                 }
775      else
776                 do_cockpit_window_view(0,NULL,0,WBU_WEAPON,NULL);
777
778           if (DemoDoRight)
779                 {
780                  DemoDoingRight=DemoDoRight;
781                 
782        if (DemoDoRight==3)
783                         do_cockpit_window_view(1,ConsoleObject,1,WBU_REAR,"REAR");
784        else
785            do_cockpit_window_view(1,&DemoRightExtra,DemoRearCheck[DemoDoRight],DemoWBUType[DemoDoRight],DemoExtraMessage[DemoDoRight]);
786                 } 
787      else
788         do_cockpit_window_view(1,NULL,0,WBU_WEAPON,NULL);
789           
790       DemoDoLeft=DemoDoRight=0;
791                 DemoDoingLeft=DemoDoingRight=0;
792     
793         return;
794     } 
795
796         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]) {
797                 if (Guided_in_big_window)
798                  {
799                         RenderingType=6+(1<<4);
800                         do_cockpit_window_view(1,Viewer,0,WBU_MISSILE,"SHIP");
801                  }
802                 else
803                  {
804                         RenderingType=1+(1<<4);
805                         do_cockpit_window_view(1,Guided_missile[Player_num],0,WBU_GUIDED,"GUIDED");
806             }
807                         
808                 did_missile_view=1;
809         }
810         else {
811
812                 if (Guided_missile[Player_num]) {               //used to be active
813                         if (!Guided_in_big_window)
814                                 do_cockpit_window_view(1,NULL,0,WBU_STATIC,NULL);
815                         Guided_missile[Player_num] = NULL;
816                 }
817
818                 if (Missile_viewer) {           //do missile view
819                         static int mv_sig=-1;
820                         if (mv_sig == -1)
821                                 mv_sig = Missile_viewer->signature;
822                         if (Missile_view_enabled && Missile_viewer->type!=OBJ_NONE && Missile_viewer->signature == mv_sig) {
823                                 RenderingType=2+(1<<4);
824                                 do_cockpit_window_view(1,Missile_viewer,0,WBU_MISSILE,"MISSILE");
825                                 did_missile_view=1;
826                         }
827                         else {
828                                 Missile_viewer = NULL;
829                                 mv_sig = -1;
830                                 RenderingType=255;
831                                 do_cockpit_window_view(1,NULL,0,WBU_STATIC,NULL);
832                         }
833                 }
834         }
835
836         for (w=0;w<2;w++) {
837
838                 if (w==1 && did_missile_view)
839                         continue;               //if showing missile view in right window, can't show anything else
840
841                 //show special views if selected
842                 switch (Cockpit_3d_view[w]) {
843                         case CV_NONE:
844                                 RenderingType=255;
845                                 do_cockpit_window_view(w,NULL,0,WBU_WEAPON,NULL);
846                                 break;
847                         case CV_REAR:
848                                 if (Rear_view) {                //if big window is rear view, show front here
849                                         RenderingType=3+(w<<4);                         
850                                         do_cockpit_window_view(w,ConsoleObject,0,WBU_REAR,"FRONT");
851                                 }
852                                 else {                                  //show normal rear view
853                                         RenderingType=3+(w<<4);                         
854                                         do_cockpit_window_view(w,ConsoleObject,1,WBU_REAR,"REAR");
855                                 }
856                                 break;
857                         case CV_ESCORT: {
858                                 object *buddy;
859                                 buddy = find_escort();
860                                 if (buddy == NULL) {
861                                         do_cockpit_window_view(w,NULL,0,WBU_WEAPON,NULL);
862                                         Cockpit_3d_view[w] = CV_NONE;
863                                 }
864                                 else {
865                                         RenderingType=4+(w<<4);
866                                         do_cockpit_window_view(w,buddy,0,WBU_ESCORT,guidebot_name);
867                                 }
868                                 break;
869                         }
870 #ifdef NETWORK
871                         case CV_COOP: {
872                                 int player = Coop_view_player[w];
873
874                  RenderingType=255; // don't handle coop stuff                  
875                                 
876                                 if (player!=-1 && Players[player].connected && ((Game_mode & GM_MULTI_COOP) || ((Game_mode & GM_TEAM) && (get_team(player) == get_team(Player_num)))))
877                                         do_cockpit_window_view(w,&Objects[Players[Coop_view_player[w]].objnum],0,WBU_COOP,Players[Coop_view_player[w]].callsign);
878                                 else {
879                                         do_cockpit_window_view(w,NULL,0,WBU_WEAPON,NULL);
880                                         Cockpit_3d_view[w] = CV_NONE;
881                                 }
882                                 break;
883                         }
884 #endif
885                         case CV_MARKER: {
886                                 char label[10];
887                                 RenderingType=5+(w<<4);
888                                 if (Marker_viewer_num[w] == -1 || MarkerObject[Marker_viewer_num[w]] == -1) {
889                                         Cockpit_3d_view[w] = CV_NONE;
890                                         break;
891                                 }
892                                 sprintf(label,"Marker %d",Marker_viewer_num[w]+1);
893                                 do_cockpit_window_view(w,&Objects[MarkerObject[Marker_viewer_num[w]]],0,WBU_MARKER,label);
894                                 break;
895                         }
896                         default:
897                                 Int3();         //invalid window type
898                 }
899         }
900         RenderingType=0;
901         Newdemo_state = save_newdemo_state;
902 }
903
904 int BigWindowSwitch=0;
905 extern int force_cockpit_redraw;
906
907 void draw_guided_crosshair(void);
908 void update_cockpits(int force_redraw);
909
910
911 //render a frame for the game
912 void game_render_frame_mono(void)
913 {
914         grs_canvas Screen_3d_window;
915         int no_draw_hud=0;
916         
917
918         gr_init_sub_canvas( &Screen_3d_window, &VR_screen_pages[0], 
919                 VR_render_sub_buffer[0].cv_bitmap.bm_x, 
920                 VR_render_sub_buffer[0].cv_bitmap.bm_y, 
921                 VR_render_sub_buffer[0].cv_bitmap.bm_w, 
922                 VR_render_sub_buffer[0].cv_bitmap.bm_h);
923
924         if ( Game_double_buffer )
925                 gr_set_current_canvas(&VR_render_sub_buffer[0]);
926         else
927                 gr_set_current_canvas(&Screen_3d_window);
928         
929         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) {
930                 char *msg = "Guided Missile View";
931                 object *viewer_save = Viewer;
932                 int w,h,aw;
933
934       if (Cockpit_mode==CM_FULL_COCKPIT)
935                         {
936                          BigWindowSwitch=1;
937                          force_cockpit_redraw=1;
938                          Cockpit_mode=CM_STATUS_BAR;
939                          return;
940                    }
941   
942                 Viewer = Guided_missile[Player_num];
943
944                 {
945                         update_rendered_data(0, Viewer, 0, 0);
946                         render_frame(0, 0);
947   
948                         wake_up_rendered_objects(Viewer, 0);
949                         Viewer = viewer_save;
950
951                         gr_set_curfont( GAME_FONT );    //GAME_FONT );
952                         gr_set_fontcolor(gr_getcolor(27,0,0), -1 );
953                         gr_get_string_size(msg, &w, &h, &aw );
954
955                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
956
957                         draw_guided_crosshair();
958                 }
959
960                 HUD_render_message_frame();
961
962                 no_draw_hud=1;
963         }
964         else
965          {      
966                 if (BigWindowSwitch)
967                  {
968                    force_cockpit_redraw=1;
969                         Cockpit_mode=CM_FULL_COCKPIT;
970                    BigWindowSwitch=0;
971                         return;
972                  }
973                 update_rendered_data(0, Viewer, Rear_view, 0);
974                 render_frame(0, 0);
975          }
976
977         if ( Game_double_buffer )
978                 gr_set_current_canvas(&VR_render_sub_buffer[0]);
979         else
980                 gr_set_current_canvas(&Screen_3d_window);
981
982         if (!no_draw_hud)
983                 game_draw_hud_stuff();
984
985         if (Game_paused) {              //render pause message over off-screen 3d (to minimize flicker)
986                 extern char *Pause_msg;
987                 ubyte *save_data = VR_screen_pages[VR_current_page].cv_bitmap.bm_data;
988
989                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=VR_render_buffer[VR_current_page].cv_bitmap.bm_data;
990                 show_boxed_message(Pause_msg);
991                 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=save_data;
992         }
993
994         if ( Game_double_buffer ) {             //copy to visible screen
995 //              if ( !Game_cockpit_copy_code )  {
996                         if ( VR_screen_flags&VRF_USE_PAGING )   {       
997                                 VR_current_page = !VR_current_page;
998                                 gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
999                                 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 );
1000                                 gr_wait_for_retrace = 0;
1001                                 gr_show_canvas( &VR_screen_pages[VR_current_page] );
1002                                 gr_wait_for_retrace = 1;
1003                         } else {
1004                                 gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w, 
1005                                                 VR_render_sub_buffer[0].cv_h, 
1006                                                 VR_render_sub_buffer[0].cv_bitmap.bm_x, 
1007                                                 VR_render_sub_buffer[0].cv_bitmap.bm_y, 
1008                                                 0, 0, 
1009                                                 &VR_render_sub_buffer[0].cv_bitmap, 
1010                                                 &VR_screen_pages[0].cv_bitmap );
1011                         }
1012 //              }
1013 #if 0
1014                 else    {
1015                         #ifdef __MSDOS__
1016                                 gr_ibitblt( &VR_render_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap, Game_cockpit_copy_code );
1017                         #else //def MACINTOSH
1018                                 gr_ibitblt( &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap );
1019                         #endif
1020                 }
1021 #endif
1022         }
1023
1024         update_cockpits(0);
1025
1026         show_extra_views();             //missile view, buddy bot, etc.
1027
1028         if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR) {
1029
1030                 if ( Newdemo_state == ND_STATE_PLAYBACK )
1031                         Game_mode = Newdemo_game_mode;
1032
1033                 render_gauges();
1034
1035                 if ( Newdemo_state == ND_STATE_PLAYBACK )
1036                         Game_mode = GM_NORMAL;
1037         }
1038
1039         CON_DrawConsole();
1040
1041         gr_update();
1042 #ifdef OGL
1043         ogl_swap_buffers();
1044 #endif
1045 }
1046
1047 void toggle_cockpit()
1048 {
1049         int new_mode;
1050
1051         switch (Cockpit_mode) {
1052
1053                 case CM_FULL_COCKPIT: {
1054                         int max_h = grd_curscreen->sc_h - GameBitmaps[cockpit_bitmap[CM_STATUS_BAR + (SM_HIRES?(Num_cockpits/2):0)].index].bm_h;
1055                         if (Game_window_h > max_h)              //too big for statusbar
1056                                 new_mode = CM_FULL_SCREEN;
1057                         else
1058                                 new_mode = CM_STATUS_BAR;
1059                         break;
1060                 }
1061
1062                 case CM_STATUS_BAR:
1063                 case CM_FULL_SCREEN:
1064                         if (Rear_view)
1065                                 return;
1066                         new_mode = CM_FULL_COCKPIT;
1067                         break;
1068
1069                 case CM_REAR_VIEW:
1070                 case CM_LETTERBOX:
1071                 default:
1072                         return;                 //do nothing
1073                         break;
1074
1075         }
1076
1077         select_cockpit(new_mode);
1078         HUD_clear_messages();
1079         write_player_file();
1080 }
1081
1082 #ifndef MACINTOSH
1083 #define WINDOW_W_DELTA  ((max_window_w / 16)&~1)        //24    //20
1084 #define WINDOW_H_DELTA  ((max_window_h / 16)&~1)        //12    //10
1085
1086 #define WINDOW_MIN_W            ((max_window_w * 10) / 22)      //160
1087 #define WINDOW_MIN_H            ((max_window_h * 10) / 22)
1088 #else
1089 //#define WINDOW_W_DELTA        32
1090 //#define WINDOW_H_DELTA        16
1091
1092 #define WINDOW_W_DELTA  ((max_window_w / 16) & ~15)             // double word aligned
1093 #define WINDOW_H_DELTA  ((max_window_h / 16) & ~15)             // double word aligned
1094
1095 #define WINDOW_MIN_W            (max_window_w-(WINDOW_W_DELTA*11))
1096 #define WINDOW_MIN_H            (max_window_h-(WINDOW_H_DELTA*11))
1097 #endif
1098
1099 void grow_window()
1100 {
1101         if (Cockpit_mode == CM_FULL_COCKPIT) {
1102                 Game_window_h = max_window_h;
1103                 Game_window_w = max_window_w;
1104                 toggle_cockpit();
1105                 HUD_init_message("Press F3 to return to Cockpit mode");
1106                 return;
1107         }
1108
1109         if (Cockpit_mode != CM_STATUS_BAR && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1110                 return;
1111
1112         if (Game_window_h>=max_window_h || Game_window_w>=max_window_w) {
1113                 //Game_window_w = max_window_w;
1114                 //Game_window_h = max_window_h;
1115                 select_cockpit(CM_FULL_SCREEN);
1116         } else {
1117                 //int x,y;
1118
1119                 Game_window_w += WINDOW_W_DELTA;
1120                 Game_window_h += WINDOW_H_DELTA;
1121
1122                 if (Game_window_h > max_window_h)
1123                         Game_window_h = max_window_h;
1124
1125                 if (Game_window_w > max_window_w)
1126                         Game_window_w = max_window_w;
1127
1128                 Game_window_x = (max_window_w - Game_window_w)/2;
1129                 Game_window_y = (max_window_h - Game_window_h)/2;
1130
1131                 game_init_render_sub_buffers( Game_window_x, Game_window_y, Game_window_w, Game_window_h );
1132         }
1133
1134         HUD_clear_messages();   //      @mk, 11/11/94
1135
1136         write_player_file();
1137 }
1138
1139 // grs_bitmap background_bitmap;        already declared in line 434 (samir 4/10/94)
1140
1141 extern grs_bitmap background_bitmap;
1142
1143 void copy_background_rect(int left,int top,int right,int bot)
1144 {
1145         grs_bitmap *bm = &background_bitmap;
1146         int x,y;
1147         int tile_left,tile_right,tile_top,tile_bot;
1148         int ofs_x,ofs_y;
1149         int dest_x,dest_y;
1150
1151         if (right < left || bot < top)
1152                 return;
1153
1154         tile_left = left / bm->bm_w;
1155         tile_right = right / bm->bm_w;
1156         tile_top = top / bm->bm_h;
1157         tile_bot = bot / bm->bm_h;
1158
1159         ofs_y = top % bm->bm_h;
1160         dest_y = top;
1161
1162         for (y=tile_top;y<=tile_bot;y++) {
1163                 int w,h;
1164
1165                 ofs_x = left % bm->bm_w;
1166                 dest_x = left;
1167
1168                 //h = (bot < dest_y+bm->bm_h)?(bot-dest_y+1):(bm->bm_h-ofs_y);
1169                 h = min(bot-dest_y+1,bm->bm_h-ofs_y);
1170
1171                 for (x=tile_left;x<=tile_right;x++) {
1172
1173                         //w = (right < dest_x+bm->bm_w)?(right-dest_x+1):(bm->bm_w-ofs_x);
1174                         w = min(right-dest_x+1,bm->bm_w-ofs_x);
1175                 
1176                         gr_bm_ubitblt(w,h,dest_x,dest_y,ofs_x,ofs_y,
1177                                         &background_bitmap,&grd_curcanv->cv_bitmap);
1178
1179                         ofs_x = 0;
1180                         dest_x += w;
1181                 }
1182
1183                 ofs_y = 0;
1184                 dest_y += h;
1185         }
1186 }
1187
1188 //fills int the background surrounding the 3d window
1189 void fill_background()
1190 {
1191         int x,y,w,h,dx,dy;
1192
1193         x = Game_window_x;
1194         y = Game_window_y;
1195         w = Game_window_w;
1196         h = Game_window_h;
1197
1198         dx = x;
1199         dy = y;
1200
1201         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1202         copy_background_rect(x-dx,y-dy,x-1,y+h+dy-1);
1203         copy_background_rect(x+w,y-dy,grd_curcanv->cv_w-1,y+h+dy-1);
1204         copy_background_rect(x,y-dy,x+w-1,y-1);
1205         copy_background_rect(x,y+h,x+w-1,y+h+dy-1);
1206
1207         if (VR_screen_flags & VRF_USE_PAGING) {
1208                 gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
1209                 copy_background_rect(x-dx,y-dy,x-1,y+h+dy-1);
1210                 copy_background_rect(x+w,y-dy,x+w+dx-1,y+h+dy-1);
1211                 copy_background_rect(x,y-dy,x+w-1,y-1);
1212                 copy_background_rect(x,y+h,x+w-1,y+h+dy-1);
1213         }
1214 }
1215
1216 void shrink_window()
1217 {
1218         mprintf((0,"%d ",FrameCount));
1219
1220 //  mprintf ((0,"W=%d H=%d\n",Game_window_w,Game_window_h));
1221  
1222         if (Cockpit_mode == CM_FULL_COCKPIT && (VR_screen_flags & VRF_ALLOW_COCKPIT)) {
1223                 Game_window_h = max_window_h;
1224                 Game_window_w = max_window_w;
1225                 //!!toggle_cockpit();
1226                 select_cockpit(CM_STATUS_BAR);
1227 //              shrink_window();
1228 //              shrink_window();
1229                 HUD_init_message("Press F3 to return to Cockpit mode");
1230                 write_player_file();
1231                 return;
1232         }
1233
1234         if (Cockpit_mode == CM_FULL_SCREEN && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1235         {
1236                 //Game_window_w = max_window_w;
1237                 //Game_window_h = max_window_h;
1238                 select_cockpit(CM_STATUS_BAR);
1239                 write_player_file();
1240                 return;
1241         }
1242
1243         if (Cockpit_mode != CM_STATUS_BAR && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1244                 return;
1245
1246    mprintf ((0,"Cockpit mode=%d\n",Cockpit_mode));
1247
1248         if (Game_window_w > WINDOW_MIN_W) {
1249                 //int x,y;
1250
1251       Game_window_w -= WINDOW_W_DELTA;
1252                 Game_window_h -= WINDOW_H_DELTA;
1253
1254
1255   mprintf ((0,"NewW=%d NewH=%d VW=%d maxH=%d\n",Game_window_w,Game_window_h,max_window_w,max_window_h));
1256                   
1257                 if ( Game_window_w < WINDOW_MIN_W )
1258                         Game_window_w = WINDOW_MIN_W;
1259
1260                 if ( Game_window_h < WINDOW_MIN_H )
1261                         Game_window_h = WINDOW_MIN_H;
1262                         
1263                 Game_window_x = (max_window_w - Game_window_w)/2;
1264                 Game_window_y = (max_window_h - Game_window_h)/2;
1265
1266                 fill_background();
1267
1268                 game_init_render_sub_buffers( Game_window_x, Game_window_y, Game_window_w, Game_window_h );
1269                 HUD_clear_messages();
1270                 write_player_file();
1271         }
1272
1273 }
1274
1275 int last_drawn_cockpit[2] = { -1, -1 };
1276 extern void ogl_loadbmtexture(grs_bitmap *bm); 
1277
1278 // This actually renders the new cockpit onto the screen.
1279 void update_cockpits(int force_redraw)
1280 {
1281         //int x, y, w, h;
1282
1283         //Redraw the on-screen cockpit bitmaps
1284         if (VR_render_mode != VR_NONE ) return;
1285
1286         switch( Cockpit_mode )  {
1287         case CM_FULL_COCKPIT:
1288         case CM_REAR_VIEW:
1289                 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1290                 PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode + (SM_HIRES?(Num_cockpits/2):0)]);
1291                 gr_ubitmapm(0,0, &GameBitmaps[cockpit_bitmap[Cockpit_mode + (SM_HIRES?(Num_cockpits/2):0)].index]);
1292                 break;
1293
1294         case CM_FULL_SCREEN:
1295                 Game_window_x = (max_window_w - Game_window_w)/2;
1296                 Game_window_y = (max_window_h - Game_window_h)/2;
1297                 fill_background();
1298                 break;
1299
1300         case CM_STATUS_BAR:
1301
1302                 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1303
1304                 PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode + (SM_HIRES?(Num_cockpits/2):0)]);
1305                 gr_ubitmapm(0,max_window_h,&GameBitmaps[cockpit_bitmap[Cockpit_mode + (SM_HIRES?(Num_cockpits/2):0)].index]);
1306         
1307                 Game_window_x = (max_window_w - Game_window_w)/2;
1308                 Game_window_y = (max_window_h - Game_window_h)/2;
1309                 fill_background();
1310                 break;
1311
1312         case CM_LETTERBOX:
1313                 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1314
1315                 // Clear the top and bottom of the screen
1316                 gr_setcolor(BM_XRGB(0,0,0));
1317                 gr_rect(0,
1318                         VR_render_sub_buffer[VR_current_page].cv_bitmap.bm_y + VR_render_sub_buffer[VR_current_page].cv_bitmap.bm_h,
1319                         GWIDTH-1,GHEIGHT-1);
1320                 gr_rect(0,0,GWIDTH-1,VR_render_sub_buffer[VR_current_page].cv_bitmap.bm_y);
1321
1322                 // In a modex mode, clear the other buffer.
1323                 if (grd_curcanv->cv_bitmap.bm_type == BM_MODEX) {
1324                         gr_set_current_canvas(&VR_screen_pages[VR_current_page^1]);
1325                         gr_clear_canvas( BM_XRGB(0,0,0) );
1326                         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1327                 }
1328                 break;
1329
1330         }
1331
1332         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1333
1334         if (Cockpit_mode != last_drawn_cockpit[VR_current_page] || force_redraw )
1335                 last_drawn_cockpit[VR_current_page] = Cockpit_mode;
1336         else
1337                 return;
1338
1339         if (Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR)
1340                 init_gauges();
1341
1342 }
1343
1344
1345 void game_render_frame()
1346 {
1347         set_screen_mode( SCREEN_GAME );
1348
1349 //      update_cockpits(0);
1350
1351         play_homing_warning();
1352
1353         if (VR_render_mode == VR_NONE )
1354                 game_render_frame_mono();        
1355 /*      else
1356                 game_render_frame_stereo();      
1357                 */
1358
1359         // Make sure palette is faded in
1360         stop_time();
1361         gr_palette_fade_in( gr_palette, 32, 0 );
1362         start_time();
1363
1364         FrameCount++;
1365 }
1366
1367 extern int Color_0_31_0;
1368
1369 //draw a crosshair for the guided missile
1370 void draw_guided_crosshair(void)
1371 {
1372         int x,y,w,h;
1373
1374         gr_setcolor(Color_0_31_0);
1375
1376         w = grd_curcanv->cv_w>>5;
1377         if (w < 5)
1378                 w = 5;
1379
1380         h = i2f(w) / grd_curscreen->sc_aspect;
1381
1382         x = grd_curcanv->cv_w / 2;
1383         y = grd_curcanv->cv_h / 2;
1384
1385         gr_scanline(x-w/2,x+w/2,y);
1386         gr_uline(i2f(x),i2f(y-h/2),i2f(x),i2f(y+h/2));
1387
1388 }
1389
1390 typedef struct bkg {
1391         short x, y, w, h;                       // The location of the menu.
1392         grs_bitmap * bmp;                       // The background under the menu.
1393 } bkg;
1394
1395 bkg bg = {0,0,0,0,NULL};
1396
1397 #define BOX_BORDER (MenuHires?60:30)
1398
1399 //show a message in a nice little box
1400 void show_boxed_message(char *msg)
1401 {       
1402         int w,h,aw;
1403         int x,y;
1404
1405         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1406         gr_set_curfont( MEDIUM1_FONT );
1407
1408         gr_get_string_size(msg,&w,&h,&aw);
1409
1410         x = (grd_curscreen->sc_w-w)/2;
1411         y = (grd_curscreen->sc_h-h)/2;
1412
1413         if (bg.bmp) {
1414                 gr_free_bitmap(bg.bmp);
1415                 bg.bmp = NULL;
1416         }
1417
1418         // Save the background of the display
1419         bg.x=x; bg.y=y; bg.w=w; bg.h=h;
1420
1421         bg.bmp = gr_create_bitmap( w+BOX_BORDER, h+BOX_BORDER );
1422
1423         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 );
1424
1425         nm_draw_background(x-BOX_BORDER/2,y-BOX_BORDER/2,x+w+BOX_BORDER/2-1,y+h+BOX_BORDER/2-1);
1426
1427         gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 );
1428
1429         gr_ustring( 0x8000, y, msg );
1430 }
1431
1432 void clear_boxed_message()
1433 {
1434
1435         if (bg.bmp) {
1436
1437                 gr_bitmap(bg.x-BOX_BORDER/2, bg.y-BOX_BORDER/2, bg.bmp);
1438         
1439                 gr_free_bitmap(bg.bmp);
1440                 bg.bmp = NULL;
1441         }
1442 }