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.
16 * Stuff for rendering the HUD
39 extern fix Cruise_speed;
40 extern int LinearSVGABuffer;
41 extern cvar_t r_framerate;
45 extern int Debug_pause; // John's debugging pause system
49 extern int Saving_movie_frames;
51 #define Saving_movie_frames 0
55 // Returns the length of the first 'n' characters of a string.
56 int string_width( char *s, int n )
63 gr_get_string_size( s, &w, &h, &aw );
69 // Draw string 's' centered on a canvas... if wider than
70 // canvas, then wrap it.
71 void draw_centered_text( int y, char *s )
78 if ( string_width( s, l ) < grd_curcanv->cv_bitmap.bm_w )
80 gr_string( 0x8000, y, s );
84 for ( i = 0; i < l; i++ )
86 if ( string_width(s, i) > (grd_curcanv->cv_bitmap.bm_w - 16) )
90 gr_string( 0x8000, y, s );
92 gr_string( 0x8000, y+grd_curcanv->cv_font->ft_h+1, &s[i] );
99 extern ubyte DefiningMarkerMessage;
100 extern char Marker_input[];
102 #define MAX_MARKER_MESSAGE_LEN 120
103 void game_draw_marker_message(void)
105 char temp_string[MAX_MARKER_MESSAGE_LEN+25];
107 if ( DefiningMarkerMessage)
109 gr_set_curfont( GAME_FONT ); //GAME_FONT
110 gr_set_fontcolor( gr_getcolor(0,63,0), -1 );
111 sprintf( temp_string, "Marker: %s_", Marker_input );
112 draw_centered_text(grd_curcanv->cv_bitmap.bm_h/2 - 16, temp_string );
118 void game_draw_multi_message(void)
120 char temp_string[MAX_MULTI_MESSAGE_LEN+25];
122 if ( (Game_mode&GM_MULTI) && multi_sending_message )
124 gr_set_curfont( GAME_FONT );
125 gr_set_fontcolor( gr_getcolor(0,63,0), -1 );
126 sprintf( temp_string, "%s: %s_", TXT_MESSAGE, Network_message );
127 draw_centered_text( grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
130 if ( (Game_mode&GM_MULTI) && multi_defining_message )
132 gr_set_curfont( GAME_FONT );
133 gr_set_fontcolor( gr_getcolor(0,63,0), -1 );
134 sprintf( temp_string, "%s #%d: %s_", TXT_MACRO, multi_defining_message, Network_message );
135 draw_centered_text( grd_curcanv->cv_bitmap.bm_h/2-16, temp_string );
141 //these should be in gr.h
142 #define cv_w cv_bitmap.bm_w
143 #define cv_h cv_bitmap.bm_h
145 fix frame_time_list[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
146 fix frame_time_total = 0;
147 int frame_time_cntr = 0;
150 void ftoa(char *string, fix f)
152 int decimal, fractional;
155 fractional = ((f & 0xffff)*100)/65536;
158 if (fractional > 99 )
160 sprintf( string, "%d.%02d", decimal, fractional );
164 void show_framerate(void)
169 int x = 8, y = 5; // position measured from lower right corner
171 frame_time_total += RealFrameTime - frame_time_list[frame_time_cntr];
172 frame_time_list[frame_time_cntr] = RealFrameTime;
173 frame_time_cntr = (frame_time_cntr+1) % 8;
175 rate = fixdiv(f1_0*8, frame_time_total);
177 gr_set_curfont( GAME_FONT );
178 gr_set_fontcolor( gr_getcolor(0,31,0), -1 );
180 ftoa( temp, rate ); // Convert fixed to string
181 if (Game_mode & GM_MULTI)
183 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 );
184 // if ( !( q++ % 30 ) )
185 // mprintf(( 0, "fps: %s\n", temp ));
190 fix Show_view_text_timer = -1;
192 void draw_window_label(void)
194 if ( Show_view_text_timer > 0 )
196 char *viewer_name, *control_name;
198 Show_view_text_timer -= FrameTime;
199 gr_set_curfont( GAME_FONT );
202 switch( Viewer->type )
204 case OBJ_FIREBALL: viewer_name = "Fireball"; break;
205 case OBJ_ROBOT: viewer_name = "Robot";
206 viewer_id = Robot_names[Viewer->id];
208 case OBJ_HOSTAGE: viewer_name = "Hostage"; break;
209 case OBJ_PLAYER: viewer_name = "Player"; break;
210 case OBJ_WEAPON: viewer_name = "Weapon"; break;
211 case OBJ_CAMERA: viewer_name = "Camera"; break;
212 case OBJ_POWERUP: viewer_name = "Powerup";
213 viewer_id = Powerup_names[Viewer->id];
215 case OBJ_DEBRIS: viewer_name = "Debris"; break;
216 case OBJ_CNTRLCEN: viewer_name = "Reactor"; break;
217 default: viewer_name = "Unknown"; break;
220 switch ( Viewer->control_type)
222 case CT_NONE: control_name = "Stopped"; break;
223 case CT_AI: control_name = "AI"; break;
224 case CT_FLYING: control_name = "Flying"; break;
225 case CT_SLEW: control_name = "Slew"; break;
226 case CT_FLYTHROUGH: control_name = "Flythrough"; break;
227 case CT_MORPH: control_name = "Morphing"; break;
228 default: control_name = "Unknown"; break;
231 gr_set_fontcolor( gr_getcolor(31, 0, 0), -1 );
232 gr_printf( 0x8000, 45, "%i: %s [%s] View - %s", OBJECT_NUMBER(Viewer), viewer_name, viewer_id, control_name );
239 extern int Game_window_x;
240 extern int Game_window_y;
241 extern int max_window_w;
242 extern int max_window_h;
245 void render_countdown_gauge(void)
247 if ( !Endlevel_sequence && Control_center_destroyed && (Countdown_seconds_left>-1)) // && (Countdown_seconds_left<127))
251 if (!is_D2_OEM && !is_MAC_SHARE && !is_SHAREWARE) // no countdown on registered only
253 // On last level, we don't want a countdown.
254 if (PLAYING_BUILTIN_MISSION && Current_level_num == Last_level)
256 if (!(Game_mode & GM_MULTI))
258 if (Game_mode & GM_MULTI_ROBOTS)
263 gr_set_curfont( SMALL_FONT );
264 gr_set_fontcolor( gr_getcolor(0,63,0), -1 );
265 y = SMALL_FONT->ft_h*4;
266 if (Cockpit_mode.intval == CM_FULL_SCREEN)
267 y += SMALL_FONT->ft_h*2;
270 y += SMALL_FONT->ft_h*2;
272 //if (!((Cockpit_mode.intval == CM_STATUS_BAR) && (Game_window_y >= 19)))
274 gr_printf( 0x8000, y, "T-%d s", Countdown_seconds_left );
279 void game_draw_hud_stuff(void)
281 //mprintf((0, "Linear is %d!\n", LinearSVGABuffer));
286 gr_set_curfont( MEDIUM1_FONT );
287 gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 ); //gr_getcolor(31,0,0));
288 gr_ustring( 0x8000, 85/2, "Debug Pause - Press P to exit" );
295 game_draw_multi_message();
298 game_draw_marker_message();
300 // if (Game_mode & GM_MULTI)
302 // if (Netgame.PlayTimeAllowed)
303 // game_draw_time_left ();
306 if ( (Newdemo_state == ND_STATE_PLAYBACK) || (Newdemo_state == ND_STATE_RECORDING) )
311 if (Newdemo_state == ND_STATE_PLAYBACK)
313 if (Newdemo_vcr_state != ND_STATE_PRINTSCREEN)
314 sprintf(message, "%s (%d%%%% %s)", TXT_DEMO_PLAYBACK, newdemo_get_percent_done(), TXT_DONE);
316 sprintf(message, " ");
319 sprintf(message, "%s", TXT_DEMO_RECORDING);
321 gr_set_curfont( GAME_FONT );
322 gr_set_fontcolor( gr_getcolor(27,0,0), -1 );
324 gr_get_string_size( message, &w, &h, &aw );
325 if (Cockpit_mode.intval == CM_FULL_COCKPIT)
327 if (grd_curcanv->cv_bitmap.bm_h > 240)
332 else if ( Cockpit_mode.intval == CM_LETTERBOX )
334 if (Cockpit_mode.intval != CM_REAR_VIEW && !Saving_movie_frames)
335 gr_printf( (grd_curcanv->cv_bitmap.bm_w-w)/2, grd_curcanv->cv_bitmap.bm_h - h - 2, message );
338 render_countdown_gauge();
340 if ( Player_num > -1 && Viewer->type==OBJ_PLAYER && Viewer->id==Player_num )
343 int y = grd_curcanv->cv_bitmap.bm_h;
345 gr_set_curfont( GAME_FONT );
346 gr_set_fontcolor( gr_getcolor(0, 31, 0), -1 );
347 if (Cruise_speed > 0)
349 int line_spacing = GAME_FONT->ft_h + GAME_FONT->ft_h/4;
351 mprintf((0, "line_spacing=%d ", line_spacing));
353 if (Cockpit_mode.intval == CM_FULL_SCREEN)
355 if (Game_mode & GM_MULTI)
356 y -= line_spacing * 11; //64
358 y -= line_spacing * 6; //32
360 else if (Cockpit_mode.intval == CM_STATUS_BAR)
362 if (Game_mode & GM_MULTI)
363 y -= line_spacing * 8; //48
365 y -= line_spacing * 4; //24
369 y = line_spacing * 2; //12
373 gr_printf( x, y, "%s %2d%%", TXT_CRUISE, f2i(Cruise_speed) );
377 if (r_framerate.intval)
380 if ( Newdemo_state == ND_STATE_PLAYBACK )
381 Game_mode = Newdemo_game_mode;
385 if ( Newdemo_state == ND_STATE_PLAYBACK )
386 Game_mode = GM_NORMAL;
388 if ( Player_is_dead )
389 player_dead_message();
393 extern int gr_bitblt_dest_step_shift;
394 extern int gr_wait_for_retrace;
395 extern int gr_bitblt_double;
399 void expand_row(ubyte *dest, ubyte *src, int num_src_pixels );
400 #pragma aux expand_row parm [edi] [esi] [ecx] modify exact [ecx esi edi eax ebx] = \
418 void expand_row( ubyte *dest, ubyte *src, int num_src_pixels )
422 for (i = 0; i < num_src_pixels; i++)
431 // doubles the size in x or y of a bitmap in place.
432 void game_expand_bitmap( grs_bitmap *bmp, uint flags )
440 Assert( bmp->bm_rowsize == bmp->bm_w*2 );
441 dptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
442 for ( i = bmp->bm_h-1; i >= 0; i-- )
444 expand_row( dptr, dptr, bmp->bm_w );
445 dptr -= bmp->bm_rowsize;
450 dptr = &bmp->bm_data[(2*(bmp->bm_h-1)+1)*bmp->bm_rowsize];
451 sptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
452 for ( i = bmp->bm_h-1; i >= 0; i-- )
454 memcpy( dptr, sptr, bmp->bm_w );
455 dptr -= bmp->bm_rowsize;
456 memcpy( dptr, sptr, bmp->bm_w );
457 dptr -= bmp->bm_rowsize;
458 sptr -= bmp->bm_rowsize;
462 case 3: // expand x & y
463 Assert( bmp->bm_rowsize == bmp->bm_w*2 );
464 dptr = &bmp->bm_data[(2*(bmp->bm_h-1)+1)*bmp->bm_rowsize];
465 sptr = &bmp->bm_data[(bmp->bm_h-1)*bmp->bm_rowsize];
466 for ( i = bmp->bm_h-1; i >= 0; i-- )
468 expand_row( dptr, sptr, bmp->bm_w );
469 dptr -= bmp->bm_rowsize;
470 expand_row( dptr, sptr, bmp->bm_w );
471 dptr -= bmp->bm_rowsize;
472 sptr -= bmp->bm_rowsize;
481 extern int SW_drawn[2], SW_x[2], SW_y[2], SW_w[2], SW_h[2];
485 //render a frame for the game in stereo
486 void game_render_frame_stereo(void)
490 fix actual_eye_width;
491 int actual_eye_offset;
492 grs_canvas RenderCanvas[2];
495 save_aspect = grd_curscreen->sc_aspect;
496 grd_curscreen->sc_aspect *= 2; // Muck with aspect ratio
498 sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
499 sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
504 grd_curscreen->sc_aspect *= 2; // Muck with aspect ratio
509 grd_curscreen->sc_aspect /= 2; // Muck with aspect ratio
512 gr_init_sub_canvas( &RenderCanvas[0], &VR_render_buffer[0], 0, 0, sw, sh );
513 gr_init_sub_canvas( &RenderCanvas[1], &VR_render_buffer[1], 0, 0, sw, sh );
515 // Draw the left eye's view
518 actual_eye_width = -VR_eye_width;
519 actual_eye_offset = -VR_eye_offset;
523 actual_eye_width = VR_eye_width;
524 actual_eye_offset = VR_eye_offset;
527 if (Guided_missile[Player_num] &&
528 Guided_missile[Player_num]->type == OBJ_WEAPON &&
529 Guided_missile[Player_num]->id == GUIDEDMISS_ID &&
530 Guided_missile[Player_num]->signature == Guided_missile_sig[Player_num] &&
531 Guided_in_big_window.intval)
532 actual_eye_offset = 0;
534 gr_set_current_canvas(&RenderCanvas[0]);
536 if (Guided_missile[Player_num] &&
537 Guided_missile[Player_num]->type == OBJ_WEAPON &&
538 Guided_missile[Player_num]->id == GUIDEDMISS_ID &&
539 Guided_missile[Player_num]->signature == Guided_missile_sig[Player_num] &&
540 Guided_in_big_window.intval)
542 char *msg = "Guided Missile View";
543 object *viewer_save = Viewer;
546 Viewer = Guided_missile[Player_num];
549 update_rendered_data(0, Viewer, 0, 0);
552 wake_up_rendered_objects(Viewer, 0);
553 Viewer = viewer_save;
555 gr_set_curfont( GAME_FONT );
556 gr_set_fontcolor( gr_getcolor(27,0,0), -1 );
557 gr_get_string_size( msg, &w, &h, &aw );
559 gr_printf( (grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
561 draw_guided_crosshair();
564 HUD_render_message_frame();
569 render_frame(actual_eye_width, 0); // switch eye positions for rear view
571 render_frame(-actual_eye_width, 0); // Left eye
574 game_expand_bitmap( &RenderCanvas[0].cv_bitmap, VR_low_res );
576 { // render small window into left eye's canvas
577 grs_canvas *save = grd_curcanv;
578 fix save_aspect2 = grd_curscreen->sc_aspect;
580 grd_curscreen->sc_aspect = save_aspect*2;
581 SW_drawn[0] = SW_drawn[1] = 0;
583 gr_set_current_canvas(save);
584 grd_curscreen->sc_aspect = save_aspect2;
588 if (actual_eye_offset > 0 )
590 gr_setcolor( gr_getcolor(0,0,0) );
591 gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(actual_eye_offset)*2, 0, grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
593 else if (actual_eye_offset < 0 )
595 gr_setcolor( gr_getcolor(0,0,0) );
596 gr_rect( 0, 0, labs(actual_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
599 if ( VR_show_hud && !no_draw_hud )
603 if (actual_eye_offset < 0 )
605 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 );
609 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 );
611 gr_set_current_canvas( &tmp );
612 game_draw_hud_stuff();
615 // Draw the right eye's view
616 gr_set_current_canvas(&RenderCanvas[1]);
618 if (Guided_missile[Player_num] &&
619 Guided_missile[Player_num]->type == OBJ_WEAPON &&
620 Guided_missile[Player_num]->id == GUIDEDMISS_ID &&
621 Guided_missile[Player_num]->signature == Guided_missile_sig[Player_num] &&
622 Guided_in_big_window.intval)
623 gr_bitmap(0, 0, &RenderCanvas[0].cv_bitmap);
627 render_frame(-actual_eye_width, 0); // switch eye positions for rear view
629 render_frame(actual_eye_width, 0); // Right eye
632 game_expand_bitmap( &RenderCanvas[1].cv_bitmap, VR_low_res );
635 { // copy small window from left eye
639 for (w = 0; w < 2; w++)
643 gr_init_sub_canvas(&temp, &RenderCanvas[0], SW_x[w], SW_y[w], SW_w[w], SW_h[w]);
644 gr_bitmap(SW_x[w]+actual_eye_offset*2, SW_y[w], &temp.cv_bitmap);
650 if (actual_eye_offset > 0)
652 gr_setcolor( gr_getcolor(0,0,0) );
653 gr_rect( 0, 0, labs(actual_eye_offset)*2-1, grd_curcanv->cv_bitmap.bm_h );
655 else if ( actual_eye_offset < 0 )
657 gr_setcolor( gr_getcolor(0,0,0) );
658 gr_rect( grd_curcanv->cv_bitmap.bm_w-labs(actual_eye_offset)*2, 0, grd_curcanv->cv_bitmap.bm_w-1, grd_curcanv->cv_bitmap.bm_h );
661 // NEWVR (Add the next 2 lines)
662 if ( VR_show_hud && !no_draw_hud )
666 if ( actual_eye_offset > 0 )
668 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 );
672 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 );
674 gr_set_current_canvas( &tmp );
675 game_draw_hud_stuff();
678 // Draws white and black registration encoding lines
679 // and Accounts for pixel-shift adjustment in upcoming bitblts
682 int width, height, quarter;
684 width = RenderCanvas[0].cv_bitmap.bm_w;
685 height = RenderCanvas[0].cv_bitmap.bm_h;
688 // black out left-hand side of left page
690 // draw registration code for left eye
692 gr_set_current_canvas( &RenderCanvas[1] );
694 gr_set_current_canvas( &RenderCanvas[0] );
695 gr_setcolor( VR_WHITE_INDEX );
696 gr_scanline( 0, quarter, height-1 );
697 gr_setcolor( VR_BLACK_INDEX );
698 gr_scanline( quarter, width-1, height-1 );
701 gr_set_current_canvas( &RenderCanvas[0] );
703 gr_set_current_canvas( &RenderCanvas[1] );
704 gr_setcolor( VR_WHITE_INDEX );
705 gr_scanline( 0, quarter*3, height-1 );
706 gr_setcolor( VR_BLACK_INDEX );
707 gr_scanline( quarter*3, width-1, height-1 );
710 // Copy left eye, then right eye
711 if ( VR_screen_flags&VRF_USE_PAGING )
712 VR_current_page = !VR_current_page;
715 gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
719 if ( VR_eye_offset_changed > 0 )
721 VR_eye_offset_changed--;
725 sw = dw = VR_render_buffer[0].cv_bitmap.bm_w;
726 sh = dh = VR_render_buffer[0].cv_bitmap.bm_h;
728 // Copy left eye, then right eye
729 gr_bitblt_dest_step_shift = 1; // Skip every other scanline.
731 if ( VR_render_mode == VR_INTERLACED )
733 if ( actual_eye_offset > 0 )
735 int xoff = labs(actual_eye_offset);
736 gr_bm_ubitblt( dw-xoff, dh, xoff, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
737 gr_bm_ubitblt( dw-xoff, dh, 0, 1, xoff, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
739 else if ( actual_eye_offset < 0 )
741 int xoff = labs(actual_eye_offset);
743 gr_bm_ubitblt( dw-xoff, dh, 0, 0, xoff, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
744 gr_bm_ubitblt( dw-xoff, dh, xoff, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
748 gr_bm_ubitblt( dw, dh, 0, 0, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
749 gr_bm_ubitblt( dw, dh, 0, 1, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[VR_current_page].cv_bitmap );
752 else if (VR_render_mode == VR_AREA_DET)
755 gr_bm_ubitblt( dw, dh, 0, VR_current_page, 0, 0, &RenderCanvas[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap );
756 gr_bm_ubitblt( dw, dh, dw, VR_current_page, 0, 0, &RenderCanvas[1].cv_bitmap, &VR_screen_pages[0].cv_bitmap );
763 gr_bitblt_dest_step_shift = 0;
765 // if ( Game_vfx_flag )
766 // vfx_set_page(VR_current_page); // 0 or 1
768 if ( VR_screen_flags&VRF_USE_PAGING )
770 gr_wait_for_retrace = 0;
772 // Added by Samir from John's code
773 if ( (VR_screen_pages[VR_current_page].cv_bitmap.bm_type == BM_MODEX) && (Game_3dmax_flag == 3) )
775 int old_x, old_y, new_x;
777 old_x = VR_screen_pages[VR_current_page].cv_bitmap.bm_x;
778 old_y = VR_screen_pages[VR_current_page].cv_bitmap.bm_y;
779 new_x = old_y*VR_screen_pages[VR_current_page].cv_bitmap.bm_rowsize;
781 VR_screen_pages[VR_current_page].cv_bitmap.bm_x = new_x;
782 VR_screen_pages[VR_current_page].cv_bitmap.bm_y = 0;
783 VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_SVGA;
784 gr_show_canvas( &VR_screen_pages[VR_current_page] );
785 VR_screen_pages[VR_current_page].cv_bitmap.bm_type = BM_MODEX;
786 VR_screen_pages[VR_current_page].cv_bitmap.bm_x = old_x;
787 VR_screen_pages[VR_current_page].cv_bitmap.bm_y = old_y;
790 gr_show_canvas( &VR_screen_pages[VR_current_page] );
791 gr_wait_for_retrace = 1;
793 grd_curscreen->sc_aspect = save_aspect;
798 ubyte RenderingType = 0;
799 ubyte DemoDoingRight = 0, DemoDoingLeft = 0;
800 extern ubyte DemoDoRight, DemoDoLeft;
801 extern object DemoRightExtra, DemoLeftExtra;
803 char DemoWBUType[] = { 0, WBU_MISSILE, WBU_MISSILE, WBU_REAR, WBU_ESCORT, WBU_MARKER, WBU_MISSILE };
804 char DemoRearCheck[] = { 0, 0, 0, 1, 0, 0, 0 };
805 static const char *const DemoExtraMessage[] = { "PLAYER", "GUIDED", "MISSILE", "REAR", "GUIDE-BOT", "MARKER", "SHIP" };
807 extern char guidebot_name[];
809 void show_extra_views()
811 int did_missile_view = 0;
812 int save_newdemo_state = Newdemo_state;
815 if (Newdemo_state == ND_STATE_PLAYBACK)
819 DemoDoingLeft = DemoDoLeft;
822 do_cockpit_window_view(0, ConsoleObject, 1, WBU_REAR, "REAR");
824 do_cockpit_window_view(0, &DemoLeftExtra, DemoRearCheck[DemoDoLeft], DemoWBUType[DemoDoLeft], DemoExtraMessage[DemoDoLeft]);
827 do_cockpit_window_view(0, NULL, 0, WBU_WEAPON, NULL);
831 DemoDoingRight = DemoDoRight;
833 if (DemoDoRight == 3)
834 do_cockpit_window_view(1, ConsoleObject, 1, WBU_REAR, "REAR");
836 do_cockpit_window_view(1, &DemoRightExtra, DemoRearCheck[DemoDoRight], DemoWBUType[DemoDoRight], DemoExtraMessage[DemoDoRight]);
839 do_cockpit_window_view(1, NULL, 0, WBU_WEAPON, NULL);
841 DemoDoLeft = DemoDoRight = 0;
842 DemoDoingLeft = DemoDoingRight = 0;
847 if (Guided_missile[Player_num] &&
848 Guided_missile[Player_num]->type == OBJ_WEAPON &&
849 Guided_missile[Player_num]->id == GUIDEDMISS_ID &&
850 Guided_missile[Player_num]->signature == Guided_missile_sig[Player_num])
852 if (Guided_in_big_window.intval)
854 RenderingType = 6 + (1<<4);
855 do_cockpit_window_view(1, Viewer, 0, WBU_MISSILE, "SHIP");
859 RenderingType = 1 + (1<<4);
860 do_cockpit_window_view(1, Guided_missile[Player_num], 0, WBU_GUIDED, "GUIDED");
863 did_missile_view = 1;
867 if (Guided_missile[Player_num]) // used to be active
869 if (!Guided_in_big_window.intval)
870 do_cockpit_window_view(1, NULL, 0, WBU_STATIC, NULL);
871 Guided_missile[Player_num] = NULL;
874 if (Missile_viewer) // do missile view
876 static int mv_sig = -1;
879 mv_sig = Missile_viewer->signature;
880 if (Missile_view_enabled.intval &&
881 Missile_viewer->type != OBJ_NONE &&
882 Missile_viewer->signature == mv_sig)
884 RenderingType = 2 + (1<<4);
885 do_cockpit_window_view(1, Missile_viewer, 0, WBU_MISSILE, "MISSILE");
886 did_missile_view = 1;
890 Missile_viewer = NULL;
893 do_cockpit_window_view(1, NULL, 0, WBU_STATIC, NULL);
898 for (w = 0; w < 2; w++)
900 if ( w == 1 && did_missile_view )
901 continue; // if showing missile view in right window, can't show anything else
903 // show special views if selected
904 switch (Cockpit_3d_view[w].intval)
908 do_cockpit_window_view(w, NULL, 0, WBU_WEAPON, NULL);
911 if (Rear_view) // if big window is rear view, show front here
913 RenderingType = 3 + (w<<4);
914 do_cockpit_window_view(w, ConsoleObject, 0, WBU_REAR, "FRONT");
916 else // show normal rear view
918 RenderingType = 3 + (w<<4);
919 do_cockpit_window_view(w, ConsoleObject, 1, WBU_REAR, "REAR");
925 buddy = find_escort();
928 do_cockpit_window_view(w, NULL, 0, WBU_WEAPON, NULL);
929 cvar_setint(&Cockpit_3d_view[w], CV_NONE);
933 RenderingType = 4 + (w<<4);
934 do_cockpit_window_view(w, buddy, 0, WBU_ESCORT, guidebot_name);
941 int player = Coop_view_player[w];
943 RenderingType = 255; // don't handle coop stuff
946 Players[player].connected &&
947 ((Game_mode & GM_MULTI_COOP) || ((Game_mode & GM_TEAM) && (get_team(player) == get_team(Player_num)))))
948 do_cockpit_window_view(w, &Objects[Players[Coop_view_player[w]].objnum], 0, WBU_COOP, Players[Coop_view_player[w]].callsign);
951 do_cockpit_window_view(w, NULL, 0, WBU_WEAPON, NULL);
952 cvar_setint(&Cockpit_3d_view[w], CV_NONE);
961 RenderingType = 5 + (w<<4);
962 if ( Marker_viewer_num[w] == -1 || MarkerObject[Marker_viewer_num[w]] == -1 )
964 cvar_setint(&Cockpit_3d_view[w], CV_NONE);
967 snprintf(label, sizeof(label)-1, "Marker %d", Marker_viewer_num[w] + 1);
968 do_cockpit_window_view(w, &Objects[MarkerObject[Marker_viewer_num[w]]], 0, WBU_MARKER, label);
972 Int3(); // invalid window type
976 Newdemo_state = save_newdemo_state;
980 int BigWindowSwitch = 0;
981 extern int force_cockpit_redraw;
983 void draw_guided_crosshair(void);
984 void update_cockpits(int force_redraw);
987 // render a frame for the game
988 void game_render_frame_mono(void)
990 grs_canvas Screen_3d_window;
993 gr_init_sub_canvas( &Screen_3d_window, &VR_screen_pages[0],
994 VR_render_sub_buffer[0].cv_bitmap.bm_x,
995 VR_render_sub_buffer[0].cv_bitmap.bm_y,
996 VR_render_sub_buffer[0].cv_bitmap.bm_w,
997 VR_render_sub_buffer[0].cv_bitmap.bm_h);
999 if ( Game_double_buffer )
1000 gr_set_current_canvas(&VR_render_sub_buffer[0]);
1002 gr_set_current_canvas(&Screen_3d_window);
1004 if (Guided_missile[Player_num] &&
1005 Guided_missile[Player_num]->type == OBJ_WEAPON &&
1006 Guided_missile[Player_num]->id == GUIDEDMISS_ID &&
1007 Guided_missile[Player_num]->signature == Guided_missile_sig[Player_num] &&
1008 Guided_in_big_window.intval)
1010 char *msg = "Guided Missile View";
1011 object *viewer_save = Viewer;
1014 if (Cockpit_mode.intval == CM_FULL_COCKPIT)
1016 BigWindowSwitch = 1;
1017 force_cockpit_redraw = 1;
1018 cvar_setint(&Cockpit_mode, CM_STATUS_BAR);
1022 Viewer = Guided_missile[Player_num];
1025 update_rendered_data(0, Viewer, 0, 0);
1028 wake_up_rendered_objects(Viewer, 0);
1029 Viewer = viewer_save;
1031 gr_set_curfont( GAME_FONT ); //GAME_FONT );
1032 gr_set_fontcolor( gr_getcolor(27,0,0), -1 );
1033 gr_get_string_size( msg, &w, &h, &aw );
1035 gr_printf( (grd_curcanv->cv_bitmap.bm_w-w)/2, 3, msg );
1037 draw_guided_crosshair();
1040 HUD_render_message_frame();
1046 if (BigWindowSwitch)
1048 force_cockpit_redraw = 1;
1049 cvar_setint(&Cockpit_mode, CM_FULL_COCKPIT);
1050 BigWindowSwitch = 0;
1053 update_rendered_data(0, Viewer, Rear_view, 0);
1057 if ( Game_double_buffer )
1058 gr_set_current_canvas(&VR_render_sub_buffer[0]);
1060 gr_set_current_canvas(&Screen_3d_window);
1063 game_draw_hud_stuff();
1065 if (Game_paused) // render pause message over off-screen 3d (to minimize flicker)
1067 extern char *Pause_msg;
1068 ubyte *save_data = VR_screen_pages[VR_current_page].cv_bitmap.bm_data;
1070 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=VR_render_buffer[VR_current_page].cv_bitmap.bm_data;
1071 show_boxed_message(Pause_msg);
1072 VR_screen_pages[VR_current_page].cv_bitmap.bm_data=save_data;
1075 if ( Game_double_buffer ) // copy to visible screen
1077 // if ( !Game_cockpit_copy_code )
1079 if ( VR_screen_flags&VRF_USE_PAGING )
1081 VR_current_page = !VR_current_page;
1082 gr_set_current_canvas( &VR_screen_pages[VR_current_page] );
1083 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 );
1084 gr_wait_for_retrace = 0;
1085 gr_show_canvas( &VR_screen_pages[VR_current_page] );
1086 gr_wait_for_retrace = 1;
1090 gr_bm_ubitblt( VR_render_sub_buffer[0].cv_w,
1091 VR_render_sub_buffer[0].cv_h,
1092 VR_render_sub_buffer[0].cv_bitmap.bm_x,
1093 VR_render_sub_buffer[0].cv_bitmap.bm_y,
1095 &VR_render_sub_buffer[0].cv_bitmap,
1096 &VR_screen_pages[0].cv_bitmap );
1103 gr_ibitblt( &VR_render_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap, Game_cockpit_copy_code );
1104 #else //def MACINTOSH
1105 gr_ibitblt( &VR_render_sub_buffer[0].cv_bitmap, &VR_screen_pages[0].cv_bitmap );
1113 show_extra_views(); // missile view, buddy bot, etc.
1115 if ( Cockpit_mode.intval == CM_FULL_COCKPIT || Cockpit_mode.intval == CM_STATUS_BAR )
1117 if ( Newdemo_state == ND_STATE_PLAYBACK )
1118 Game_mode = Newdemo_game_mode;
1122 if ( Newdemo_state == ND_STATE_PLAYBACK )
1123 Game_mode = GM_NORMAL;
1135 void toggle_cockpit(void)
1139 switch (Cockpit_mode.intval)
1141 case CM_FULL_COCKPIT:
1143 int max_h = grd_curscreen->sc_h - GameBitmaps[cockpit_bitmap[CM_STATUS_BAR + (SM_HIRES?(Num_cockpits/2):0)].index].bm_h;
1145 if (Game_window_h.intval > max_h) //too big for statusbar
1146 new_mode = CM_FULL_SCREEN;
1148 new_mode = CM_STATUS_BAR;
1153 case CM_FULL_SCREEN:
1156 new_mode = CM_FULL_COCKPIT;
1162 return; // do nothing
1167 select_cockpit(new_mode);
1168 HUD_clear_messages();
1174 #define WINDOW_W_DELTA ((max_window_w / 16)&~1) //24 //20
1175 #define WINDOW_H_DELTA ((max_window_h / 16)&~1) //12 //10
1177 #define WINDOW_MIN_W ((max_window_w * 10) / 22) //160
1178 #define WINDOW_MIN_H ((max_window_h * 10) / 22)
1180 //#define WINDOW_W_DELTA 32
1181 //#define WINDOW_H_DELTA 16
1183 #define WINDOW_W_DELTA ((max_window_w / 16) & ~15) // double word aligned
1184 #define WINDOW_H_DELTA ((max_window_h / 16) & ~15) // double word aligned
1186 #define WINDOW_MIN_W (max_window_w-(WINDOW_W_DELTA*11))
1187 #define WINDOW_MIN_H (max_window_h-(WINDOW_H_DELTA*11))
1191 void grow_window(void)
1193 if (Cockpit_mode.intval == CM_FULL_COCKPIT)
1195 cvar_setint(&Game_window_h, max_window_h);
1196 cvar_setint(&Game_window_w, max_window_w);
1198 HUD_init_message("Press F3 to return to Cockpit mode");
1202 if (Cockpit_mode.intval != CM_STATUS_BAR && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1205 if (Game_window_h.intval >= max_window_h || Game_window_w.intval >= max_window_w)
1207 //cvar_setint(&Game_window_w, max_window_w);
1208 //cvar_setint(&Game_window_h, max_window_h);
1209 select_cockpit(CM_FULL_SCREEN);
1215 cvar_setint(&Game_window_w, Game_window_w.intval + WINDOW_W_DELTA);
1216 cvar_setint(&Game_window_h, Game_window_h.intval + WINDOW_H_DELTA);
1218 if (Game_window_h.intval > max_window_h)
1219 cvar_setint(&Game_window_h, max_window_h);
1221 if (Game_window_w.intval > max_window_w)
1222 cvar_setint(&Game_window_w, max_window_w);
1224 Game_window_x = (max_window_w - Game_window_w.intval) / 2;
1225 Game_window_y = (max_window_h - Game_window_h.intval) / 2;
1227 game_init_render_sub_buffers( Game_window_x, Game_window_y, Game_window_w.intval, Game_window_h.intval );
1230 HUD_clear_messages(); // @mk, 11/11/94
1236 extern grs_bitmap background_bitmap;
1238 void copy_background_rect(int left,int top,int right,int bot)
1240 grs_bitmap *bm = &background_bitmap;
1242 int tile_left, tile_right, tile_top, tile_bot;
1246 if (right < left || bot < top)
1249 tile_left = left / bm->bm_w;
1250 tile_right = right / bm->bm_w;
1251 tile_top = top / bm->bm_h;
1252 tile_bot = bot / bm->bm_h;
1254 ofs_y = top % bm->bm_h;
1257 for (y = tile_top; y <= tile_bot; y++)
1261 ofs_x = left % bm->bm_w;
1264 //h = (bot < dest_y+bm->bm_h)?(bot-dest_y+1):(bm->bm_h-ofs_y);
1265 h = min(bot-dest_y+1,bm->bm_h-ofs_y);
1267 for (x = tile_left; x <= tile_right; x++)
1269 //w = (right < dest_x+bm->bm_w)?(right-dest_x+1):(bm->bm_w-ofs_x);
1270 w = min(right-dest_x+1, bm->bm_w-ofs_x);
1272 gr_bm_ubitblt(w, h, dest_x, dest_y, ofs_x, ofs_y, &background_bitmap, &grd_curcanv->cv_bitmap);
1284 // fills int the background surrounding the 3d window
1285 void fill_background(void)
1287 int x, y, w, h, dx, dy;
1291 w = Game_window_w.intval;
1292 h = Game_window_h.intval;
1297 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1298 copy_background_rect(x-dx, y-dy, x-1, y+h+dy-1);
1299 copy_background_rect(x+w, y-dy, grd_curcanv->cv_w-1, y+h+dy-1);
1300 copy_background_rect(x, y-dy, x+w-1, y-1);
1301 copy_background_rect(x, y+h, x+w-1, y+h+dy-1);
1303 if (VR_screen_flags & VRF_USE_PAGING)
1305 gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
1306 copy_background_rect(x-dx, y-dy, x-1, y+h+dy-1);
1307 copy_background_rect(x+w, y-dy, x+w+dx-1, y+h+dy-1);
1308 copy_background_rect(x, y-dy, x+w-1, y-1);
1309 copy_background_rect(x, y+h, x+w-1, y+h+dy-1);
1314 void shrink_window(void)
1316 mprintf((0, "%d ", FrameCount));
1318 // mprintf((0, "W=%d H=%d\n", Game_window_w.intval, Game_window_h.intval));
1320 if ( Cockpit_mode.intval == CM_FULL_COCKPIT && (VR_screen_flags & VRF_ALLOW_COCKPIT) )
1322 cvar_setint(&Game_window_h, max_window_h);
1323 cvar_setint(&Game_window_w, max_window_w);
1324 //!!toggle_cockpit();
1325 select_cockpit(CM_STATUS_BAR);
1328 HUD_init_message("Press F3 to return to Cockpit mode");
1333 if (Cockpit_mode.intval == CM_FULL_SCREEN && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1335 //cvar_setint(&Game_window_w, max_window_w);
1336 //cvar_setint(&Game_window_h, max_window_h);
1337 select_cockpit(CM_STATUS_BAR);
1342 if (Cockpit_mode.intval != CM_STATUS_BAR && (VR_screen_flags & VRF_ALLOW_COCKPIT))
1345 mprintf((0, "Cockpit mode=%d\n", Cockpit_mode.intval));
1347 if (Game_window_w.intval > WINDOW_MIN_W) {
1350 cvar_setint(&Game_window_w, Game_window_w.intval - WINDOW_W_DELTA);
1351 cvar_setint(&Game_window_h, Game_window_h.intval - WINDOW_H_DELTA);
1353 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));
1355 if ( Game_window_w.intval < WINDOW_MIN_W )
1356 cvar_setint(&Game_window_w, WINDOW_MIN_W);
1358 if ( Game_window_h.intval < WINDOW_MIN_H )
1359 cvar_setint(&Game_window_h, WINDOW_MIN_H);
1361 Game_window_x = (max_window_w - Game_window_w.intval) / 2;
1362 Game_window_y = (max_window_h - Game_window_h.intval) / 2;
1366 game_init_render_sub_buffers( Game_window_x, Game_window_y, Game_window_w.intval, Game_window_h.intval );
1367 HUD_clear_messages();
1373 int last_drawn_cockpit[2] = { -1, -1 };
1374 extern void ogl_loadbmtexture(grs_bitmap *bm);
1376 // This actually renders the new cockpit onto the screen.
1377 void update_cockpits(int force_redraw)
1381 // Redraw the on-screen cockpit bitmaps
1382 if (VR_render_mode != VR_NONE )
1385 switch( Cockpit_mode.intval )
1387 case CM_FULL_COCKPIT:
1389 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1390 PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode.intval + (SM_HIRES?(Num_cockpits/2):0)]);
1391 gr_ubitmapm(0, 0, &GameBitmaps[cockpit_bitmap[Cockpit_mode.intval + (SM_HIRES?(Num_cockpits/2):0)].index]);
1394 case CM_FULL_SCREEN:
1395 Game_window_x = (max_window_w - Game_window_w.intval) / 2;
1396 Game_window_y = (max_window_h - Game_window_h.intval) / 2;
1402 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1404 PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode.intval + (SM_HIRES?(Num_cockpits/2):0)]);
1405 gr_ubitmapm(0, max_window_h, &GameBitmaps[cockpit_bitmap[Cockpit_mode.intval + (SM_HIRES?(Num_cockpits/2):0)].index]);
1407 Game_window_x = (max_window_w - Game_window_w.intval) / 2;
1408 Game_window_y = (max_window_h - Game_window_h.intval) / 2;
1413 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1415 // Clear the top and bottom of the screen
1416 gr_setcolor(BM_XRGB(0,0,0));
1418 VR_render_sub_buffer[VR_current_page].cv_bitmap.bm_y + VR_render_sub_buffer[VR_current_page].cv_bitmap.bm_h,
1419 GWIDTH-1,GHEIGHT-1);
1420 gr_rect(0, 0, GWIDTH-1, VR_render_sub_buffer[VR_current_page].cv_bitmap.bm_y);
1422 // In a modex mode, clear the other buffer.
1423 if (grd_curcanv->cv_bitmap.bm_type == BM_MODEX)
1425 gr_set_current_canvas(&VR_screen_pages[VR_current_page^1]);
1426 gr_clear_canvas( BM_XRGB(0,0,0) );
1427 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1433 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1435 if (Cockpit_mode.intval != last_drawn_cockpit[VR_current_page] || force_redraw )
1436 last_drawn_cockpit[VR_current_page] = Cockpit_mode.intval;
1440 if ( Cockpit_mode.intval == CM_FULL_COCKPIT || Cockpit_mode.intval == CM_STATUS_BAR )
1445 void game_render_frame(void)
1447 set_screen_mode( SCREEN_GAME );
1449 // update_cockpits(0);
1451 play_homing_warning();
1453 if (VR_render_mode == VR_NONE )
1454 game_render_frame_mono();
1456 game_render_frame_stereo();
1459 // Make sure palette is faded in
1461 gr_palette_fade_in( gr_palette, 32, 0 );
1468 extern int Color_0_31_0;
1471 // draw a crosshair for the guided missile
1472 void draw_guided_crosshair(void)
1476 gr_setcolor(Color_0_31_0);
1478 w = grd_curcanv->cv_w>>5;
1482 h = i2f(w) / grd_curscreen->sc_aspect;
1484 x = grd_curcanv->cv_w / 2;
1485 y = grd_curcanv->cv_h / 2;
1487 gr_scanline(x-w/2, x+w/2, y);
1488 gr_uline(i2f(x), i2f(y-h/2), i2f(x), i2f(y+h/2));
1493 typedef struct bkg {
1494 short x, y, w, h; // The location of the menu.
1495 grs_bitmap * bmp; // The background under the menu.
1498 bkg bg = { 0, 0, 0, 0, NULL };
1500 #define BOX_BORDER (MenuHires?60:30)
1503 // show a message in a nice little box
1504 void show_boxed_message(char *msg)
1509 gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
1510 gr_set_curfont( MEDIUM1_FONT );
1512 gr_get_string_size(msg, &w, &h, &aw);
1514 x = (grd_curscreen->sc_w-w)/2;
1515 y = (grd_curscreen->sc_h-h)/2;
1519 gr_free_bitmap(bg.bmp);
1523 // Save the background of the display
1524 bg.x=x; bg.y=y; bg.w=w; bg.h=h;
1526 bg.bmp = gr_create_bitmap( w+BOX_BORDER, h+BOX_BORDER );
1528 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 );
1530 nm_draw_background(x-BOX_BORDER/2, y-BOX_BORDER/2, x+w+BOX_BORDER/2-1, y+h+BOX_BORDER/2-1);
1532 gr_set_fontcolor( gr_getcolor(31, 31, 31), -1 );
1534 gr_ustring( 0x8000, y, msg );
1538 void clear_boxed_message(void)
1542 gr_bitmap(bg.x-BOX_BORDER/2, bg.y-BOX_BORDER/2, bg.bmp);
1544 gr_free_bitmap(bg.bmp);