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