]> icculus.org git repositories - btb/d2x.git/blob - main/gauges.c
remove DirectDraw use and Windows mouse stuff made redundant by SDL (lots of WINDOWS...
[btb/d2x.git] / main / gauges.c
1 /* $Id: gauges.c,v 1.20 2005-08-02 06:13:56 chris Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Inferno gauge drivers
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29
30 #include "hudmsg.h"
31
32 #include "inferno.h"
33 #include "game.h"
34 #include "screens.h"
35 #include "gauges.h"
36 #include "physics.h"
37 #include "error.h"
38
39 #include "menu.h"                       // For the font.
40 #include "mono.h"
41 #include "collide.h"
42 #include "newdemo.h"
43 #include "player.h"
44 #include "gamefont.h"
45 #include "bm.h"
46 #include "text.h"
47 #include "powerup.h"
48 #include "sounds.h"
49 #ifdef NETWORK
50 #include "multi.h"
51 #include "network.h"
52 #endif
53 #include "endlevel.h"
54 #include "cntrlcen.h"
55 #include "controls.h"
56
57 #include "wall.h"
58 #include "text.h"
59 #include "render.h"
60 #include "piggy.h"
61 #include "laser.h"
62
63 #ifdef OGL
64 #include "ogl_init.h"
65 #endif
66
67 void draw_ammo_info(int x,int y,int ammo_count,int primary);
68 extern void draw_guided_crosshair(void);
69
70 bitmap_index Gauges[MAX_GAUGE_BMS];   // Array of all gauge bitmaps.
71 bitmap_index Gauges_hires[MAX_GAUGE_BMS];   // hires gauges
72
73 grs_canvas *Canv_LeftEnergyGauge;
74 grs_canvas *Canv_AfterburnerGauge;
75 grs_canvas *Canv_SBEnergyGauge;
76 grs_canvas *Canv_SBAfterburnerGauge;
77 grs_canvas *Canv_RightEnergyGauge;
78 grs_canvas *Canv_NumericalGauge;
79
80 //Flags for gauges/hud stuff
81 ubyte Reticle_on=1;
82
83 //bitmap numbers for gauges
84
85 #define GAUGE_SHIELDS                   0               //0..9, in decreasing order (100%,90%...0%)
86
87 #define GAUGE_INVULNERABLE              10              //10..19
88 #define N_INVULNERABLE_FRAMES   10
89
90 #define GAUGE_AFTERBURNER       20
91 #define GAUGE_ENERGY_LEFT               21
92 #define GAUGE_ENERGY_RIGHT              22
93 #define GAUGE_NUMERICAL                 23
94
95 #define GAUGE_BLUE_KEY                  24
96 #define GAUGE_GOLD_KEY                  25
97 #define GAUGE_RED_KEY                   26
98 #define GAUGE_BLUE_KEY_OFF              27
99 #define GAUGE_GOLD_KEY_OFF              28
100 #define GAUGE_RED_KEY_OFF               29
101
102 #define SB_GAUGE_BLUE_KEY               30
103 #define SB_GAUGE_GOLD_KEY               31
104 #define SB_GAUGE_RED_KEY                32
105 #define SB_GAUGE_BLUE_KEY_OFF   33
106 #define SB_GAUGE_GOLD_KEY_OFF   34
107 #define SB_GAUGE_RED_KEY_OFF    35
108
109 #define SB_GAUGE_ENERGY                 36
110
111 #define GAUGE_LIVES                             37      
112
113 #define GAUGE_SHIPS                             38
114 #define GAUGE_SHIPS_LAST                45
115
116 #define RETICLE_CROSS                   46
117 #define RETICLE_PRIMARY                 48
118 #define RETICLE_SECONDARY               51
119 #define RETICLE_LAST                            55
120
121 #define GAUGE_HOMING_WARNING_ON 56
122 #define GAUGE_HOMING_WARNING_OFF        57
123
124 #define SML_RETICLE_CROSS               58
125 #define SML_RETICLE_PRIMARY     60
126 #define SML_RETICLE_SECONDARY   63
127 #define SML_RETICLE_LAST                67
128
129 #define KEY_ICON_BLUE                   68
130 #define KEY_ICON_YELLOW                 69
131 #define KEY_ICON_RED                            70
132
133 #define SB_GAUGE_AFTERBURNER    71
134
135 #define FLAG_ICON_RED                   72
136 #define FLAG_ICON_BLUE                  73
137
138
139 /* Use static inline function under GCC to avoid CR/LF issues */
140 #ifdef __GNUC__
141 #define PAGE_IN_GAUGE(x) _page_in_gauge(x)
142 static inline void _page_in_gauge(int x)
143 {
144     if (FontHires) {
145         PIGGY_PAGE_IN(Gauges_hires[x]);
146     } else {
147         PIGGY_PAGE_IN(Gauges[x]);
148     }
149 }
150
151 #else
152 #define PAGE_IN_GAUGE(x) \
153         do {                                                                                                    \
154                 if (FontHires) {                                \
155                         PIGGY_PAGE_IN(Gauges_hires[x]);         \
156                 } else {                                                                                        \
157                         PIGGY_PAGE_IN(Gauges[x]);                               \
158                 }                                                                                                       \
159         } while (0)
160
161 #endif
162
163 #define GET_GAUGE_INDEX(x)      (FontHires?Gauges_hires[x].index:Gauges[x].index)
164
165 //change MAX_GAUGE_BMS when adding gauges
166
167 //Coordinats for gauges
168
169 extern int Current_display_mode;
170
171 // cockpit keys
172
173 #define GAUGE_BLUE_KEY_X_L              272
174 #define GAUGE_BLUE_KEY_Y_L              152
175 #define GAUGE_BLUE_KEY_X_H              535
176 #define GAUGE_BLUE_KEY_Y_H              374
177 #define GAUGE_BLUE_KEY_X                (Current_display_mode?GAUGE_BLUE_KEY_X_H:GAUGE_BLUE_KEY_X_L)
178 #define GAUGE_BLUE_KEY_Y                (Current_display_mode?GAUGE_BLUE_KEY_Y_H:GAUGE_BLUE_KEY_Y_L)
179
180 #define GAUGE_GOLD_KEY_X_L              273
181 #define GAUGE_GOLD_KEY_Y_L              162
182 #define GAUGE_GOLD_KEY_X_H              537
183 #define GAUGE_GOLD_KEY_Y_H              395
184 #define GAUGE_GOLD_KEY_X                (Current_display_mode?GAUGE_GOLD_KEY_X_H:GAUGE_GOLD_KEY_X_L)
185 #define GAUGE_GOLD_KEY_Y                (Current_display_mode?GAUGE_GOLD_KEY_Y_H:GAUGE_GOLD_KEY_Y_L)
186
187 #define GAUGE_RED_KEY_X_L               274
188 #define GAUGE_RED_KEY_Y_L               172
189 #define GAUGE_RED_KEY_X_H               539
190 #define GAUGE_RED_KEY_Y_H               416
191 #define GAUGE_RED_KEY_X                 (Current_display_mode?GAUGE_RED_KEY_X_H:GAUGE_RED_KEY_X_L)
192 #define GAUGE_RED_KEY_Y                 (Current_display_mode?GAUGE_RED_KEY_Y_H:GAUGE_RED_KEY_Y_L)
193
194 // status bar keys
195
196 #define SB_GAUGE_KEYS_X_L          11
197 #define SB_GAUGE_KEYS_X_H               26
198 #define SB_GAUGE_KEYS_X                 (Current_display_mode?SB_GAUGE_KEYS_X_H:SB_GAUGE_KEYS_X_L)
199
200 #define SB_GAUGE_BLUE_KEY_Y_L           153
201 #define SB_GAUGE_GOLD_KEY_Y_L           169
202 #define SB_GAUGE_RED_KEY_Y_L            185
203
204 #define SB_GAUGE_BLUE_KEY_Y_H           390
205 #define SB_GAUGE_GOLD_KEY_Y_H           422
206 #define SB_GAUGE_RED_KEY_Y_H            454
207
208 #define SB_GAUGE_BLUE_KEY_Y     (Current_display_mode?SB_GAUGE_BLUE_KEY_Y_H:SB_GAUGE_BLUE_KEY_Y_L)
209 #define SB_GAUGE_GOLD_KEY_Y     (Current_display_mode?SB_GAUGE_GOLD_KEY_Y_H:SB_GAUGE_GOLD_KEY_Y_L)
210 #define SB_GAUGE_RED_KEY_Y              (Current_display_mode?SB_GAUGE_RED_KEY_Y_H:SB_GAUGE_RED_KEY_Y_L)
211
212 // cockpit enery gauges
213
214 #define LEFT_ENERGY_GAUGE_X_L   70
215 #define LEFT_ENERGY_GAUGE_Y_L   131
216 #define LEFT_ENERGY_GAUGE_W_L   64
217 #define LEFT_ENERGY_GAUGE_H_L   8
218
219 #define LEFT_ENERGY_GAUGE_X_H   137
220 #define LEFT_ENERGY_GAUGE_Y_H   314
221 #define LEFT_ENERGY_GAUGE_W_H   133
222 #define LEFT_ENERGY_GAUGE_H_H   21
223
224 #define LEFT_ENERGY_GAUGE_X     (Current_display_mode?LEFT_ENERGY_GAUGE_X_H:LEFT_ENERGY_GAUGE_X_L)
225 #define LEFT_ENERGY_GAUGE_Y     (Current_display_mode?LEFT_ENERGY_GAUGE_Y_H:LEFT_ENERGY_GAUGE_Y_L)
226 #define LEFT_ENERGY_GAUGE_W     (Current_display_mode?LEFT_ENERGY_GAUGE_W_H:LEFT_ENERGY_GAUGE_W_L)
227 #define LEFT_ENERGY_GAUGE_H     (Current_display_mode?LEFT_ENERGY_GAUGE_H_H:LEFT_ENERGY_GAUGE_H_L)
228
229 #define RIGHT_ENERGY_GAUGE_X    (Current_display_mode?380:190)
230 #define RIGHT_ENERGY_GAUGE_Y    (Current_display_mode?314:131)
231 #define RIGHT_ENERGY_GAUGE_W    (Current_display_mode?133:64)
232 #define RIGHT_ENERGY_GAUGE_H    (Current_display_mode?21:8)
233
234 // cockpit afterburner gauge
235
236 #define AFTERBURNER_GAUGE_X_L   45-1
237 #define AFTERBURNER_GAUGE_Y_L   158
238 #define AFTERBURNER_GAUGE_W_L   12
239 #define AFTERBURNER_GAUGE_H_L   32
240
241 #define AFTERBURNER_GAUGE_X_H   88
242 #define AFTERBURNER_GAUGE_Y_H   377
243 #define AFTERBURNER_GAUGE_W_H   21
244 #define AFTERBURNER_GAUGE_H_H   65
245
246 #define AFTERBURNER_GAUGE_X     (Current_display_mode?AFTERBURNER_GAUGE_X_H:AFTERBURNER_GAUGE_X_L)
247 #define AFTERBURNER_GAUGE_Y     (Current_display_mode?AFTERBURNER_GAUGE_Y_H:AFTERBURNER_GAUGE_Y_L)
248 #define AFTERBURNER_GAUGE_W     (Current_display_mode?AFTERBURNER_GAUGE_W_H:AFTERBURNER_GAUGE_W_L)
249 #define AFTERBURNER_GAUGE_H     (Current_display_mode?AFTERBURNER_GAUGE_H_H:AFTERBURNER_GAUGE_H_L)
250
251 // sb energy gauge
252
253 #define SB_ENERGY_GAUGE_X               (Current_display_mode?196:98)
254 #define SB_ENERGY_GAUGE_Y               (Current_display_mode?382:(155-2))
255 #define SB_ENERGY_GAUGE_W               (Current_display_mode?32:16)
256 #define SB_ENERGY_GAUGE_H               (Current_display_mode?60:29)
257
258 // sb afterburner gauge
259
260 #define SB_AFTERBURNER_GAUGE_X          (Current_display_mode?196:98)
261 #define SB_AFTERBURNER_GAUGE_Y          (Current_display_mode?446:184)
262 #define SB_AFTERBURNER_GAUGE_W          (Current_display_mode?33:16)
263 #define SB_AFTERBURNER_GAUGE_H          (Current_display_mode?29:13)
264
265 #define SB_ENERGY_NUM_X                 (SB_ENERGY_GAUGE_X+(Current_display_mode?4:2))
266 #define SB_ENERGY_NUM_Y                 (Current_display_mode?457:175)
267
268 #define SHIELD_GAUGE_X                  (Current_display_mode?292:146)
269 #define SHIELD_GAUGE_Y                  (Current_display_mode?374:155)
270 #define SHIELD_GAUGE_W                  (Current_display_mode?70:35)
271 #define SHIELD_GAUGE_H                  (Current_display_mode?77:32)
272
273 #define SHIP_GAUGE_X                    (SHIELD_GAUGE_X+(Current_display_mode?11:5))
274 #define SHIP_GAUGE_Y                            (SHIELD_GAUGE_Y+(Current_display_mode?10:5))
275
276 #define SB_SHIELD_GAUGE_X               (Current_display_mode?247:123)          //139
277 #define SB_SHIELD_GAUGE_Y               (Current_display_mode?395:163)
278
279 #define SB_SHIP_GAUGE_X                 (SB_SHIELD_GAUGE_X+(Current_display_mode?11:5))
280 #define SB_SHIP_GAUGE_Y                 (SB_SHIELD_GAUGE_Y+(Current_display_mode?10:5))
281
282 #define SB_SHIELD_NUM_X                 (SB_SHIELD_GAUGE_X+(Current_display_mode?21:12))        //151
283 #define SB_SHIELD_NUM_Y                 (SB_SHIELD_GAUGE_Y-(Current_display_mode?16:8))                 //156 -- MWA used to be hard coded to 156
284
285 #define NUMERICAL_GAUGE_X               (Current_display_mode?308:154)
286 #define NUMERICAL_GAUGE_Y               (Current_display_mode?316:130)
287 #define NUMERICAL_GAUGE_W               (Current_display_mode?38:19)
288 #define NUMERICAL_GAUGE_H               (Current_display_mode?55:22)
289
290 #define PRIMARY_W_PIC_X                 (Current_display_mode?(135-10):64)
291 #define PRIMARY_W_PIC_Y                 (Current_display_mode?370:154)
292 #define PRIMARY_W_TEXT_X                (Current_display_mode?182:87)
293 #define PRIMARY_W_TEXT_Y                (Current_display_mode?400:157)
294 #define PRIMARY_AMMO_X                  (Current_display_mode?186:(96-3))
295 #define PRIMARY_AMMO_Y                  (Current_display_mode?420:171)
296
297 #define SECONDARY_W_PIC_X               (Current_display_mode?466:234)
298 #define SECONDARY_W_PIC_Y               (Current_display_mode?374:154)
299 #define SECONDARY_W_TEXT_X              (Current_display_mode?413:207)
300 #define SECONDARY_W_TEXT_Y              (Current_display_mode?378:157)
301 #define SECONDARY_AMMO_X                (Current_display_mode?428:213)
302 #define SECONDARY_AMMO_Y                (Current_display_mode?407:171)
303
304 #define SB_LIVES_X                              (Current_display_mode?(550-10-3):266)
305 #define SB_LIVES_Y                              (Current_display_mode?450-3:185)
306 #define SB_LIVES_LABEL_X                (Current_display_mode?475:237)
307 #define SB_LIVES_LABEL_Y                (SB_LIVES_Y+1)
308
309 #define SB_SCORE_RIGHT_L                301
310 #define SB_SCORE_RIGHT_H                (605+8)
311 #define SB_SCORE_RIGHT                  (Current_display_mode?SB_SCORE_RIGHT_H:SB_SCORE_RIGHT_L)
312
313 #define SB_SCORE_Y                              (Current_display_mode?398:158)
314 #define SB_SCORE_LABEL_X                (Current_display_mode?475:237)
315
316 #define SB_SCORE_ADDED_RIGHT    (Current_display_mode?SB_SCORE_RIGHT_H:SB_SCORE_RIGHT_L)
317 #define SB_SCORE_ADDED_Y                (Current_display_mode?413:165)
318
319 #define HOMING_WARNING_X                (Current_display_mode?14:7)
320 #define HOMING_WARNING_Y                (Current_display_mode?415:171)
321
322 #define BOMB_COUNT_X                    (Current_display_mode?546:275)
323 #define BOMB_COUNT_Y                    (Current_display_mode?445:186)
324
325 #define SB_BOMB_COUNT_X                 (Current_display_mode?342:171)
326 #define SB_BOMB_COUNT_Y                 (Current_display_mode?458:191)
327
328 #define LHX(x)          ((x)*(MenuHires?2:1))
329 #define LHY(y)          ((y)*(MenuHires?2.4:1))
330
331 static int score_display[2];
332 static fix score_time;
333
334 static int old_score[2]                         = { -1, -1 };
335 static int old_energy[2]                        = { -1, -1 };
336 static int old_shields[2]                       = { -1, -1 };
337 static int old_flags[2]                         = { -1, -1 };
338 static int old_weapon[2][2]             = {{ -1, -1 },{-1,-1}};
339 static int old_ammo_count[2][2] = {{ -1, -1 },{-1,-1}};
340 static int Old_Omega_charge[2]  = { -1, -1 };
341 static int old_laser_level[2]           = { -1, -1 };
342 static int old_cloak[2]                         = { 0, 0 };
343 static int old_lives[2]                         = { -1, -1 };
344 static fix old_afterburner[2]           = { -1, -1 };
345 static int old_bombcount[2]             = { 0, 0 };
346
347 static int invulnerable_frame = 0;
348
349 static int cloak_fade_state;            //0=steady, -1 fading out, 1 fading in 
350
351 #define WS_SET                          0               //in correct state
352 #define WS_FADING_OUT   1
353 #define WS_FADING_IN            2
354
355 int weapon_box_user[2]={WBU_WEAPON,WBU_WEAPON};         //see WBU_ constants in gauges.h
356 int weapon_box_states[2] = {WS_SET, WS_SET};
357 fix weapon_box_fade_values[2];
358
359 #define FADE_SCALE      (2*i2f(GR_FADE_LEVELS)/REARM_TIME)              // fade out and back in REARM_TIME, in fade levels per seconds (int)
360
361 typedef struct span {
362         sbyte l,r;
363 } span;
364
365 //store delta x values from left of box
366 span weapon_window_left[] = {           //first span 67,151
367                 {8,51},
368                 {6,53},
369                 {5,54},
370                 {4-1,53+2},
371                 {4-1,53+3},
372                 {4-1,53+3},
373                 {4-2,53+3},
374                 {4-2,53+3},
375                 {3-1,53+3},
376                 {3-1,53+3},
377                 {3-1,53+3},
378                 {3-1,53+3},
379                 {3-1,53+3},
380                 {3-1,53+3},
381                 {3-1,53+3},
382                 {3-2,53+3},
383                 {2-1,53+3},
384                 {2-1,53+3},
385                 {2-1,53+3},
386                 {2-1,53+3},
387                 {2-1,53+3},
388                 {2-1,53+3},
389                 {2-1,53+3},
390                 {2-1,53+3},
391                 {1-1,53+3},
392                 {1-1,53+2},
393                 {1-1,53+2},
394                 {1-1,53+2},
395                 {1-1,53+2},
396                 {1-1,53+2},
397                 {1-1,53+2},
398                 {1-1,53+2},
399                 {0,53+2},
400                 {0,53+2},
401                 {0,53+2},
402                 {0,53+2},
403                 {0,52+3},
404                 {1-1,52+2},
405                 {2-2,51+3},
406                 {3-2,51+2},
407                 {4-2,50+2},
408                 {5-2,50},
409                 {5-2+2,50-2},
410         };
411
412
413 //store delta x values from left of box
414 span weapon_window_right[] = {          //first span 207,154
415                 {208-202,255-202},
416                 {206-202,257-202},
417                 {205-202,258-202},
418                 {204-202,259-202},
419                 {203-202,260-202},
420                 {203-202,260-202},
421                 {203-202,260-202},
422                 {203-202,260-202},
423                 {203-202,260-202},
424                 {203-202,261-202},
425                 {203-202,261-202},
426                 {203-202,261-202},
427                 {203-202,261-202},
428                 {203-202,261-202},
429                 {203-202,261-202},
430                 {203-202,261-202},
431                 {203-202,261-202},
432                 {203-202,261-202},
433                 {203-202,262-202},
434                 {203-202,262-202},
435                 {203-202,262-202},
436                 {203-202,262-202},
437                 {203-202,262-202},
438                 {203-202,262-202},
439                 {203-202,262-202},
440                 {203-202,262-202},
441                 {204-202,263-202},
442                 {204-202,263-202},
443                 {204-202,263-202},
444                 {204-202,263-202},
445                 {204-202,263-202},
446                 {204-202,263-202},
447                 {204-202,263-202},
448                 {204-202,263-202},
449                 {204-202,263-202},
450                 {204-202,263-202},
451                 {204-202,263-202},
452                 {204-202,263-202},
453                 {205-202,263-202},
454                 {206-202,262-202},
455                 {207-202,261-202},
456                 {208-202,260-202},
457                 {211-202,255-202},
458         };
459
460 //store delta x values from left of box
461 span weapon_window_left_hires[] = {             //first span 67,154
462         {20,110},
463         {18,113},
464         {16,114},
465         {15,116},
466         {14,117},
467         {13,118},
468         {12,119},
469         {11,119},
470         {10,120},
471         {10,120},
472         {9,121},
473         {8,121},
474         {8,121},
475         {8,122},
476         {7,122},
477         {7,122},
478         {7,122},
479         {7,122},
480         {7,122},
481         {6,122},
482         {6,122},
483         {6,122},
484         {6,122},
485         {6,122},
486         {6,122},
487         {6,122},
488         {6,122},
489         {6,122},
490         {6,122},
491         {5,122},
492         {5,122},
493         {5,122},
494         {5,122},
495         {5,121},
496         {5,121},
497         {5,121},
498         {5,121},
499         {5,121},
500         {5,121},
501         {4,121},
502         {4,121},
503         {4,121},
504         {4,121},
505         {4,121},
506         {4,121},
507         {4,121},
508         {4,121},
509         {4,121},
510         {4,121},
511         {3,121},
512         {3,121},
513         {3,120},
514         {3,120},
515         {3,120},
516         {3,120},
517         {3,120},
518         {3,120},
519         {3,120},
520         {3,120},
521         {3,120},
522         {2,120},
523         {2,120},
524         {2,120},
525         {2,120},
526         {2,120},
527         {2,120},
528         {2,120},
529         {2,120},
530         {2,120},
531         {2,120},
532         {2,120},
533         {2,120},
534         {1,120},
535         {1,120},
536         {1,119},
537         {1,119},
538         {1,119},
539         {1,119},
540         {1,119},
541         {1,119},
542         {1,119},
543         {1,119},
544         {0,119},
545         {0,119},
546         {0,119},
547         {0,119},
548         {0,119},
549         {0,119},
550         {0,119},
551         {0,118},
552         {0,118},
553         {0,118},
554         {0,117},
555         {0,117},
556         {0,117},
557         {1,116},
558         {1,116},
559         {2,115},
560         {2,114},
561         {3,113},
562         {4,112},
563         {5,111},
564         {5,110},
565         {7,109},
566         {9,107},
567         {10,105},
568         {12,102},
569 };
570
571
572 //store delta x values from left of box
573 span weapon_window_right_hires[] = {            //first span 207,154
574         {12,105},
575         {9,107},
576         {8,109},
577         {6,110},
578         {5,111},
579         {4,112},
580         {3,113},
581         {3,114},
582         {2,115},
583         {2,115},
584         {1,116},
585         {1,117},
586         {1,117},
587         {0,117},
588         {0,118},
589         {0,118},
590         {0,118},
591         {0,118},
592         {0,118},
593         {0,119},
594         {0,119},
595         {0,119},
596         {0,119},
597         {0,119},
598         {0,119},
599         {0,119},
600         {0,119},
601         {0,119},
602         {0,119},
603         {0,120},
604         {0,120},
605         {0,120},
606         {0,120},
607         {1,120},
608         {1,120},
609         {1,120},
610         {1,120},
611         {1,120},
612         {1,120},
613         {1,121},
614         {1,121},
615         {1,121},
616         {1,121},
617         {1,121},
618         {1,121},
619         {1,121},
620         {1,121},
621         {1,121},
622         {1,121},
623         {1,122},
624         {1,122},
625         {2,122},
626         {2,122},
627         {2,122},
628         {2,122},
629         {2,122},
630         {2,122},
631         {2,122},
632         {2,122},
633         {2,123},
634         {2,123},
635         {2,123},
636         {2,123},
637         {2,123},
638         {2,123},
639         {2,123},
640         {2,123},
641         {2,123},
642         {2,123},
643         {2,123},
644         {2,123},
645         {2,123},
646         {2,124},
647         {2,124},
648         {3,124},
649         {3,124},
650         {3,124},
651         {3,124},
652         {3,124},
653         {3,124},
654         {3,124},
655         {3,125},
656         {3,125},
657         {3,125},
658         {3,125},
659         {3,125},
660         {3,125},
661         {3,125},
662         {3,125},
663         {4,125},
664         {4,125},
665         {4,125},
666         {5,125},
667         {5,125},
668         {5,125},
669         {6,125},
670         {6,124},
671         {7,123},
672         {8,123},
673         {9,122},
674         {10,121},
675         {11,120},
676         {12,120},
677         {13,118},
678         {15,117},
679         {18,115},
680         {20,114},
681 };
682
683                                                                                         
684 #define N_LEFT_WINDOW_SPANS  (sizeof(weapon_window_left)/sizeof(*weapon_window_left))
685 #define N_RIGHT_WINDOW_SPANS (sizeof(weapon_window_right)/sizeof(*weapon_window_right))
686
687 #define N_LEFT_WINDOW_SPANS_H  (sizeof(weapon_window_left_hires)/sizeof(*weapon_window_left_hires))
688 #define N_RIGHT_WINDOW_SPANS_H (sizeof(weapon_window_right_hires)/sizeof(*weapon_window_right_hires))
689
690 // defining box boundries for weapon pictures
691
692 #define PRIMARY_W_BOX_LEFT_L            63
693 #define PRIMARY_W_BOX_TOP_L             151             //154
694 #define PRIMARY_W_BOX_RIGHT_L           (PRIMARY_W_BOX_LEFT_L+58)
695 #define PRIMARY_W_BOX_BOT_L             (PRIMARY_W_BOX_TOP_L+N_LEFT_WINDOW_SPANS-1)
696                                                                                         
697 #define PRIMARY_W_BOX_LEFT_H            121
698 #define PRIMARY_W_BOX_TOP_H             364
699 #define PRIMARY_W_BOX_RIGHT_H           242
700 #define PRIMARY_W_BOX_BOT_H             (PRIMARY_W_BOX_TOP_H+N_LEFT_WINDOW_SPANS_H-1)           //470
701                                                                                         
702 #define PRIMARY_W_BOX_LEFT              (Current_display_mode?PRIMARY_W_BOX_LEFT_H:PRIMARY_W_BOX_LEFT_L)
703 #define PRIMARY_W_BOX_TOP               (Current_display_mode?PRIMARY_W_BOX_TOP_H:PRIMARY_W_BOX_TOP_L)
704 #define PRIMARY_W_BOX_RIGHT     (Current_display_mode?PRIMARY_W_BOX_RIGHT_H:PRIMARY_W_BOX_RIGHT_L)
705 #define PRIMARY_W_BOX_BOT               (Current_display_mode?PRIMARY_W_BOX_BOT_H:PRIMARY_W_BOX_BOT_L)
706
707 #define SECONDARY_W_BOX_LEFT_L  202     //207
708 #define SECONDARY_W_BOX_TOP_L           151
709 #define SECONDARY_W_BOX_RIGHT_L 263     //(SECONDARY_W_BOX_LEFT+54)
710 #define SECONDARY_W_BOX_BOT_L           (SECONDARY_W_BOX_TOP_L+N_RIGHT_WINDOW_SPANS-1)
711
712 #define SECONDARY_W_BOX_LEFT_H  404
713 #define SECONDARY_W_BOX_TOP_H           363
714 #define SECONDARY_W_BOX_RIGHT_H 529
715 #define SECONDARY_W_BOX_BOT_H           (SECONDARY_W_BOX_TOP_H+N_RIGHT_WINDOW_SPANS_H-1)                //470
716
717 #define SECONDARY_W_BOX_LEFT    (Current_display_mode?SECONDARY_W_BOX_LEFT_H:SECONDARY_W_BOX_LEFT_L)
718 #define SECONDARY_W_BOX_TOP     (Current_display_mode?SECONDARY_W_BOX_TOP_H:SECONDARY_W_BOX_TOP_L)
719 #define SECONDARY_W_BOX_RIGHT   (Current_display_mode?SECONDARY_W_BOX_RIGHT_H:SECONDARY_W_BOX_RIGHT_L)
720 #define SECONDARY_W_BOX_BOT     (Current_display_mode?SECONDARY_W_BOX_BOT_H:SECONDARY_W_BOX_BOT_L)
721
722 #define SB_PRIMARY_W_BOX_LEFT_L         34              //50
723 #define SB_PRIMARY_W_BOX_TOP_L          153
724 #define SB_PRIMARY_W_BOX_RIGHT_L                (SB_PRIMARY_W_BOX_LEFT_L+53+2)
725 #define SB_PRIMARY_W_BOX_BOT_L          (195+1)
726                                                                                         
727 #define SB_PRIMARY_W_BOX_LEFT_H         68
728 #define SB_PRIMARY_W_BOX_TOP_H          381
729 #define SB_PRIMARY_W_BOX_RIGHT_H                179
730 #define SB_PRIMARY_W_BOX_BOT_H          473
731                                                                                         
732 #define SB_PRIMARY_W_BOX_LEFT           (Current_display_mode?SB_PRIMARY_W_BOX_LEFT_H:SB_PRIMARY_W_BOX_LEFT_L)
733 #define SB_PRIMARY_W_BOX_TOP            (Current_display_mode?SB_PRIMARY_W_BOX_TOP_H:SB_PRIMARY_W_BOX_TOP_L)
734 #define SB_PRIMARY_W_BOX_RIGHT  (Current_display_mode?SB_PRIMARY_W_BOX_RIGHT_H:SB_PRIMARY_W_BOX_RIGHT_L)
735 #define SB_PRIMARY_W_BOX_BOT            (Current_display_mode?SB_PRIMARY_W_BOX_BOT_H:SB_PRIMARY_W_BOX_BOT_L)
736                                                                                         
737 #define SB_SECONDARY_W_BOX_LEFT_L       169
738 #define SB_SECONDARY_W_BOX_TOP_L                153
739 #define SB_SECONDARY_W_BOX_RIGHT_L      (SB_SECONDARY_W_BOX_LEFT_L+54+1)
740 #define SB_SECONDARY_W_BOX_BOT_L                (153+43)
741
742 #define SB_SECONDARY_W_BOX_LEFT_H       338
743 #define SB_SECONDARY_W_BOX_TOP_H                381
744 #define SB_SECONDARY_W_BOX_RIGHT_H      449
745 #define SB_SECONDARY_W_BOX_BOT_H                473
746
747 #define SB_SECONDARY_W_BOX_LEFT (Current_display_mode?SB_SECONDARY_W_BOX_LEFT_H:SB_SECONDARY_W_BOX_LEFT_L)      //210
748 #define SB_SECONDARY_W_BOX_TOP  (Current_display_mode?SB_SECONDARY_W_BOX_TOP_H:SB_SECONDARY_W_BOX_TOP_L)
749 #define SB_SECONDARY_W_BOX_RIGHT        (Current_display_mode?SB_SECONDARY_W_BOX_RIGHT_H:SB_SECONDARY_W_BOX_RIGHT_L)
750 #define SB_SECONDARY_W_BOX_BOT  (Current_display_mode?SB_SECONDARY_W_BOX_BOT_H:SB_SECONDARY_W_BOX_BOT_L)
751
752 #define SB_PRIMARY_W_PIC_X                      (SB_PRIMARY_W_BOX_LEFT+1)       //51
753 #define SB_PRIMARY_W_PIC_Y                      (Current_display_mode?382:154)
754 #define SB_PRIMARY_W_TEXT_X             (SB_PRIMARY_W_BOX_LEFT+(Current_display_mode?50:24))    //(51+23)
755 #define SB_PRIMARY_W_TEXT_Y             (Current_display_mode?390:157)
756 #define SB_PRIMARY_AMMO_X                       (SB_PRIMARY_W_BOX_LEFT+(Current_display_mode?(38+20):30))       //((SB_PRIMARY_W_BOX_LEFT+33)-3)        //(51+32)
757 #define SB_PRIMARY_AMMO_Y                       (Current_display_mode?410:171)
758
759 #define SB_SECONDARY_W_PIC_X            (Current_display_mode?385:(SB_SECONDARY_W_BOX_LEFT+29)) //(212+27)
760 #define SB_SECONDARY_W_PIC_Y            (Current_display_mode?382:154)
761 #define SB_SECONDARY_W_TEXT_X           (SB_SECONDARY_W_BOX_LEFT+2)     //212
762 #define SB_SECONDARY_W_TEXT_Y           (Current_display_mode?389:157)
763 #define SB_SECONDARY_AMMO_X             (SB_SECONDARY_W_BOX_LEFT+(Current_display_mode?(14-4):11))      //(212+9)
764 #define SB_SECONDARY_AMMO_Y             (Current_display_mode?414:171)
765
766 typedef struct gauge_box {
767         int left,top;
768         int right,bot;          //maximal box
769         span *spanlist; //list of left,right spans for copy
770 } gauge_box;
771
772 gauge_box gauge_boxes[] = {
773
774 // primary left/right low res
775                 {PRIMARY_W_BOX_LEFT_L,PRIMARY_W_BOX_TOP_L,PRIMARY_W_BOX_RIGHT_L,PRIMARY_W_BOX_BOT_L,weapon_window_left},
776                 {SECONDARY_W_BOX_LEFT_L,SECONDARY_W_BOX_TOP_L,SECONDARY_W_BOX_RIGHT_L,SECONDARY_W_BOX_BOT_L,weapon_window_right},
777
778 //sb left/right low res
779                 {SB_PRIMARY_W_BOX_LEFT_L,SB_PRIMARY_W_BOX_TOP_L,SB_PRIMARY_W_BOX_RIGHT_L,SB_PRIMARY_W_BOX_BOT_L,NULL},
780                 {SB_SECONDARY_W_BOX_LEFT_L,SB_SECONDARY_W_BOX_TOP_L,SB_SECONDARY_W_BOX_RIGHT_L,SB_SECONDARY_W_BOX_BOT_L,NULL},
781
782 // primary left/right hires
783                 {PRIMARY_W_BOX_LEFT_H,PRIMARY_W_BOX_TOP_H,PRIMARY_W_BOX_RIGHT_H,PRIMARY_W_BOX_BOT_H,weapon_window_left_hires},
784                 {SECONDARY_W_BOX_LEFT_H,SECONDARY_W_BOX_TOP_H,SECONDARY_W_BOX_RIGHT_H,SECONDARY_W_BOX_BOT_H,weapon_window_right_hires},
785
786 // sb left/right hires
787                 {SB_PRIMARY_W_BOX_LEFT_H,SB_PRIMARY_W_BOX_TOP_H,SB_PRIMARY_W_BOX_RIGHT_H,SB_PRIMARY_W_BOX_BOT_H,NULL},
788                 {SB_SECONDARY_W_BOX_LEFT_H,SB_SECONDARY_W_BOX_TOP_H,SB_SECONDARY_W_BOX_RIGHT_H,SB_SECONDARY_W_BOX_BOT_H,NULL},
789         };
790
791 // these macros refer to arrays above
792
793 #define COCKPIT_PRIMARY_BOX             (!Current_display_mode?0:4)
794 #define COCKPIT_SECONDARY_BOX           (!Current_display_mode?1:5)
795 #define SB_PRIMARY_BOX                          (!Current_display_mode?2:6)
796 #define SB_SECONDARY_BOX                        (!Current_display_mode?3:7)
797
798 int     Color_0_31_0 = -1;
799
800 //copy a box from the off-screen buffer to the visible page
801 void copy_gauge_box(gauge_box *box,grs_bitmap *bm)
802 {
803         if (box->spanlist) {
804                 int n_spans = box->bot-box->top+1;
805                 int cnt,y;
806
807 //gr_setcolor(BM_XRGB(31,0,0));
808
809                 for (cnt=0,y=box->top;cnt<n_spans;cnt++,y++) {
810                         gr_bm_ubitblt(box->spanlist[cnt].r-box->spanlist[cnt].l+1,1,
811                                                 box->left+box->spanlist[cnt].l,y,box->left+box->spanlist[cnt].l,y,bm,&grd_curcanv->cv_bitmap);
812
813                         //gr_scanline(box->left+box->spanlist[cnt].l,box->left+box->spanlist[cnt].r,y);
814                 }
815         }
816         else
817          {
818                 gr_bm_ubitblt(box->right-box->left+1,box->bot-box->top+1,
819                                                 box->left,box->top,box->left,box->top,
820                                                 bm,&grd_curcanv->cv_bitmap);
821          }
822 }
823
824 //fills in the coords of the hostage video window
825 void get_hostage_window_coords(int *x,int *y,int *w,int *h)
826 {
827         if (Cockpit_mode == CM_STATUS_BAR) {
828                 *x = SB_SECONDARY_W_BOX_LEFT;
829                 *y = SB_SECONDARY_W_BOX_TOP;
830                 *w = SB_SECONDARY_W_BOX_RIGHT - SB_SECONDARY_W_BOX_LEFT + 1;
831                 *h = SB_SECONDARY_W_BOX_BOT - SB_SECONDARY_W_BOX_TOP + 1;
832         }
833         else {
834                 *x = SECONDARY_W_BOX_LEFT;
835                 *y = SECONDARY_W_BOX_TOP;
836                 *w = SECONDARY_W_BOX_RIGHT - SECONDARY_W_BOX_LEFT + 1;
837                 *h = SECONDARY_W_BOX_BOT - SECONDARY_W_BOX_TOP + 1;
838         }
839
840 }
841
842 //these should be in gr.h 
843 #define cv_w  cv_bitmap.bm_w
844 #define cv_h  cv_bitmap.bm_h
845
846 extern int HUD_nmessages, hud_first; // From hud.c
847 extern char HUD_messages[HUD_MAX_NUM][HUD_MESSAGE_LENGTH+5]; 
848 extern fix ThisLevelTime;
849 extern fix Omega_charge;
850
851 void hud_show_score()
852 {
853         char    score_str[20];
854         int     w, h, aw;
855
856         if ((HUD_nmessages > 0) && (strlen(HUD_messages[hud_first]) > 38))
857                 return;
858
859         gr_set_curfont( GAME_FONT );
860
861         if ( ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) ) {
862                 sprintf(score_str, "%s: %5d", TXT_KILLS, Players[Player_num].net_kills_total);
863         } else {
864                 sprintf(score_str, "%s: %5d", TXT_SCORE, Players[Player_num].score);
865         }
866
867         gr_get_string_size(score_str, &w, &h, &aw );
868
869         if (Color_0_31_0 == -1)
870                 Color_0_31_0 = gr_getcolor(0,31,0);
871         gr_set_fontcolor(Color_0_31_0, -1);
872
873         gr_printf(grd_curcanv->cv_w-w-LHX(2), 3, score_str);
874  }
875
876 void hud_show_timer_count()
877  {
878 #ifdef NETWORK
879         char    score_str[20];
880         int     w, h, aw,i;
881         fix timevar=0;
882 #endif
883
884         if ((HUD_nmessages > 0) && (strlen(HUD_messages[hud_first]) > 38))
885                 return;
886
887 #ifdef NETWORK
888    if ((Game_mode & GM_NETWORK) && Netgame.PlayTimeAllowed)
889     {
890      timevar=i2f (Netgame.PlayTimeAllowed*5*60);
891      i=f2i(timevar-ThisLevelTime);
892      i++;
893     
894      sprintf(score_str, "T - %5d", i);
895                                                                                                                                                                                                  
896      gr_get_string_size(score_str, &w, &h, &aw );
897
898      if (Color_0_31_0 == -1)
899                 Color_0_31_0 = gr_getcolor(0,31,0);
900      gr_set_fontcolor(Color_0_31_0, -1);
901
902      if (i>-1 && !Control_center_destroyed)
903              gr_printf(grd_curcanv->cv_w-w-LHX(10), LHX(11), score_str);
904     }
905 #endif
906  }
907
908
909 //y offset between lines on HUD
910 int Line_spacing;
911
912 void hud_show_score_added()
913 {
914         int     color;
915         int     w, h, aw;
916         char    score_str[20];
917
918         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
919                 return;
920
921         if (score_display[0] == 0)
922                 return;
923
924         gr_set_curfont( GAME_FONT );
925
926         score_time -= FrameTime;
927         if (score_time > 0) {
928                 color = f2i(score_time * 20) + 12;
929
930                 if (color < 10) color = 12;
931                 if (color > 31) color = 30;
932
933                 color = color - (color % 4);    //      Only allowing colors 12,16,20,24,28 speeds up gr_getcolor, improves caching
934
935                 if (Cheats_enabled)
936                         sprintf(score_str, "%s", TXT_CHEATER);
937                 else
938                         sprintf(score_str, "%5d", score_display[0]);
939
940                 gr_get_string_size(score_str, &w, &h, &aw );
941                 gr_set_fontcolor(gr_getcolor(0, color, 0),-1 );
942                 gr_printf(grd_curcanv->cv_w-w-LHX(2+10), Line_spacing+4, score_str);
943         } else {
944                 score_time = 0;
945                 score_display[0] = 0;
946         }
947         
948 }
949
950 void sb_show_score()
951 {                                                                                                                                                                                                                                                                    
952         char    score_str[20];
953         int x,y;
954         int     w, h, aw;
955         static int last_x[4]={SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_H,SB_SCORE_RIGHT_H};
956         int redraw_score;
957
958         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
959                 redraw_score = -99;
960         else
961                 redraw_score = -1;
962
963         //if (old_score[VR_current_page] == redraw_score)
964         {
965                 gr_set_curfont( GAME_FONT );
966                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
967
968                 if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
969                         {
970                          gr_printf(SB_SCORE_LABEL_X,SB_SCORE_Y,"%s:", TXT_KILLS);
971                         }
972                 else
973                   {
974                         gr_printf(SB_SCORE_LABEL_X,SB_SCORE_Y,"%s:", TXT_SCORE);
975                   }
976         }
977
978         gr_set_curfont( GAME_FONT );
979         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
980                 sprintf(score_str, "%5d", Players[Player_num].net_kills_total);
981         else
982                 sprintf(score_str, "%5d", Players[Player_num].score);
983         gr_get_string_size(score_str, &w, &h, &aw );
984
985         x = SB_SCORE_RIGHT-w-LHX(2);
986         y = SB_SCORE_Y;
987         
988         //erase old score
989         gr_setcolor(BM_XRGB(0,0,0));
990         gr_rect(last_x[(Current_display_mode?2:0)+VR_current_page],y,SB_SCORE_RIGHT,y+GAME_FONT->ft_h);
991
992         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
993                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
994         else
995                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );      
996  
997         gr_printf(x,y,score_str);
998
999         last_x[(Current_display_mode?2:0)+VR_current_page] = x;
1000 }
1001
1002 void sb_show_score_added()
1003 {
1004         int     color;
1005         int w, h, aw;
1006         char    score_str[32];
1007         int x;
1008         static int last_x[4]={SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_H,SB_SCORE_RIGHT_H};
1009         static  int last_score_display[2] = { -1, -1};
1010         
1011         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
1012                 return;
1013
1014         if (score_display[VR_current_page] == 0)
1015                 return;
1016
1017         gr_set_curfont( GAME_FONT );
1018
1019         score_time -= FrameTime;
1020         if (score_time > 0) {
1021                 if (score_display[VR_current_page] != last_score_display[VR_current_page])
1022                 {
1023                         gr_setcolor(BM_XRGB(0,0,0));
1024                         gr_rect(last_x[(Current_display_mode?2:0)+VR_current_page],SB_SCORE_ADDED_Y,SB_SCORE_ADDED_RIGHT,SB_SCORE_ADDED_Y+GAME_FONT->ft_h);
1025
1026                         last_score_display[VR_current_page] = score_display[VR_current_page];
1027                 }
1028
1029                 color = f2i(score_time * 20) + 10;
1030
1031                 if (color < 10) color = 10;
1032                 if (color > 31) color = 31;
1033
1034                 if (Cheats_enabled)
1035                         sprintf(score_str, "%s", TXT_CHEATER);
1036                 else
1037                         sprintf(score_str, "%5d", score_display[VR_current_page]);
1038
1039                 gr_get_string_size(score_str, &w, &h, &aw );
1040
1041                 x = SB_SCORE_ADDED_RIGHT-w-LHX(2);
1042
1043                 gr_set_fontcolor(gr_getcolor(0, color, 0),-1 );
1044
1045                 gr_printf(x, SB_SCORE_ADDED_Y, score_str);
1046
1047
1048                 last_x[(Current_display_mode?2:0)+VR_current_page] = x;
1049
1050         } else {
1051                 //erase old score
1052                 gr_setcolor(BM_XRGB(0,0,0));
1053                 gr_rect(last_x[(Current_display_mode?2:0)+VR_current_page],SB_SCORE_ADDED_Y,SB_SCORE_ADDED_RIGHT,SB_SCORE_ADDED_Y+GAME_FONT->ft_h);
1054
1055                 score_time = 0;
1056                 score_display[VR_current_page] = 0;
1057
1058         }
1059 }
1060
1061 fix     Last_warning_beep_time[2] = {0,0};              //      Time we last played homing missile warning beep.
1062
1063 //      -----------------------------------------------------------------------------
1064 void play_homing_warning(void)
1065 {
1066         fix     beep_delay;
1067
1068         if (Endlevel_sequence || Player_is_dead)
1069                 return;
1070
1071         if (Players[Player_num].homing_object_dist >= 0) {
1072                 beep_delay = Players[Player_num].homing_object_dist/128;
1073                 if (beep_delay > F1_0)
1074                         beep_delay = F1_0;
1075                 else if (beep_delay < F1_0/8)
1076                         beep_delay = F1_0/8;
1077
1078                 if (Last_warning_beep_time[VR_current_page] > GameTime)
1079                         Last_warning_beep_time[VR_current_page] = 0;
1080
1081                 if (GameTime - Last_warning_beep_time[VR_current_page] > beep_delay/2) {
1082                         digi_play_sample( SOUND_HOMING_WARNING, F1_0 );
1083                         Last_warning_beep_time[VR_current_page] = GameTime;
1084                 }
1085         }
1086 }
1087
1088 int     Last_homing_warning_shown[2]={-1,-1};
1089
1090 //      -----------------------------------------------------------------------------
1091 void show_homing_warning(void)
1092 {
1093         if ((Cockpit_mode == CM_STATUS_BAR) || (Endlevel_sequence)) {
1094                 if (Last_homing_warning_shown[VR_current_page] == 1) {
1095                         PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_OFF );
1096
1097                         gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_OFF) ] );
1098
1099                         Last_homing_warning_shown[VR_current_page] = 0;
1100                 }
1101                 return;
1102         }
1103
1104         gr_set_current_canvas( get_current_game_screen() );
1105
1106
1107         if (Players[Player_num].homing_object_dist >= 0) {
1108
1109                 if (GameTime & 0x4000) {
1110                         if (Last_homing_warning_shown[VR_current_page] != 1) {
1111                                 PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_ON );
1112                                 gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_ON) ] );
1113                                 Last_homing_warning_shown[VR_current_page] = 1;
1114                         }
1115                 } else {
1116                         if (Last_homing_warning_shown[VR_current_page] != 0) {
1117                                 PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_OFF );
1118                                 gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_OFF) ] );
1119                                 Last_homing_warning_shown[VR_current_page] = 0;
1120                         }
1121                 }
1122         } else if (Last_homing_warning_shown[VR_current_page] != 0) {
1123                 PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_OFF );
1124                 gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_OFF) ] );
1125                 Last_homing_warning_shown[VR_current_page] = 0;
1126         }
1127 }
1128
1129 #define MAX_SHOWN_LIVES 4
1130
1131 extern int Game_window_y;
1132 extern int SW_y[2];
1133
1134 void hud_show_homing_warning(void)
1135 {
1136         if (Players[Player_num].homing_object_dist >= 0) {
1137                 if (GameTime & 0x4000) {
1138                         int x=0x8000, y=grd_curcanv->cv_h-Line_spacing;
1139
1140                         if (weapon_box_user[0] != WBU_WEAPON || weapon_box_user[1] != WBU_WEAPON) {
1141                                 int wy = (weapon_box_user[0] != WBU_WEAPON)?SW_y[0]:SW_y[1];
1142                                 y = min(y,(wy - Line_spacing - Game_window_y));
1143                         }
1144
1145                         gr_set_curfont( GAME_FONT );
1146                         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1147                         gr_printf(x,y,TXT_LOCK);
1148                 }
1149         }
1150 }
1151
1152 void hud_show_keys(void)
1153 {
1154         int y = 3*Line_spacing;
1155         int dx = GAME_FONT->ft_w+GAME_FONT->ft_w/2;
1156
1157         if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) {
1158                 PAGE_IN_GAUGE( KEY_ICON_BLUE );
1159                 gr_ubitmapm(2,y,&GameBitmaps[ GET_GAUGE_INDEX(KEY_ICON_BLUE) ] );
1160
1161         }
1162
1163         if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) {
1164                 PAGE_IN_GAUGE( KEY_ICON_YELLOW );
1165                 gr_ubitmapm(2+dx,y,&GameBitmaps[ GET_GAUGE_INDEX(KEY_ICON_YELLOW) ] );
1166         }
1167
1168         if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) {
1169                 PAGE_IN_GAUGE( KEY_ICON_RED );
1170                 gr_ubitmapm(2+2*dx,y,&GameBitmaps[ GET_GAUGE_INDEX(KEY_ICON_RED) ] );
1171         }
1172
1173 }
1174
1175 #ifdef NETWORK
1176 extern grs_bitmap Orb_icons[2];
1177
1178 void hud_show_orbs (void)
1179 {
1180         if (Game_mode & GM_HOARD) {
1181                 int x,y;
1182                 grs_bitmap *bm;
1183
1184                 x=y=0;
1185
1186                 if (Cockpit_mode == CM_FULL_COCKPIT) {
1187                         y = 2*Line_spacing;
1188                         x = 4*GAME_FONT->ft_w;
1189                 }
1190                 else if (Cockpit_mode == CM_STATUS_BAR) {
1191                         y = Line_spacing;
1192                         x = GAME_FONT->ft_w;
1193                 }
1194                 else if (Cockpit_mode == CM_FULL_SCREEN) {
1195                         y = 5*Line_spacing;
1196                         x = GAME_FONT->ft_w;
1197                         if (FontHires)
1198                                 y += Line_spacing;
1199                 }
1200                 else
1201                         Int3();         //what sort of cockpit?
1202
1203                 bm = &Orb_icons[FontHires];
1204                 gr_ubitmapm(x,y,bm);
1205
1206                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1207                 gr_printf(x+bm->bm_w+bm->bm_w/2, y+(FontHires?2:1), "x %d", Players[Player_num].secondary_ammo[PROXIMITY_INDEX]);
1208
1209         }
1210 }
1211
1212 void hud_show_flag(void)
1213 {
1214         if ((Game_mode & GM_CAPTURE) && (Players[Player_num].flags & PLAYER_FLAGS_FLAG)) {
1215                 int x,y,icon;
1216
1217                 x=y=0;
1218
1219                 if (Cockpit_mode == CM_FULL_COCKPIT) {
1220                         y = 2*Line_spacing;
1221                         x = 4*GAME_FONT->ft_w;
1222                 }
1223                 else if (Cockpit_mode == CM_STATUS_BAR) {
1224                         y = Line_spacing;
1225                         x = GAME_FONT->ft_w;
1226                 }
1227                 else if (Cockpit_mode == CM_FULL_SCREEN) {
1228                         y = 5*Line_spacing;
1229                         x = GAME_FONT->ft_w;
1230                         if (FontHires)
1231                                 y += Line_spacing;
1232                 }
1233                 else
1234                         Int3();         //what sort of cockpit?
1235
1236
1237                 icon = (get_team(Player_num) == TEAM_BLUE)?FLAG_ICON_RED:FLAG_ICON_BLUE;
1238
1239                 PAGE_IN_GAUGE( icon );
1240                 gr_ubitmapm(x,y,&GameBitmaps[ GET_GAUGE_INDEX(icon) ] );
1241
1242         }
1243 }
1244 #endif
1245
1246 void hud_show_energy(void)
1247 {
1248         //gr_set_current_canvas(&VR_render_sub_buffer[0]);      //render off-screen
1249         gr_set_curfont( GAME_FONT );
1250         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1251         if (Game_mode & GM_MULTI)
1252                 gr_printf(2, grd_curcanv->cv_h-5*Line_spacing,"%s: %i", TXT_ENERGY, f2ir(Players[Player_num].energy));
1253         else
1254                 gr_printf(2, grd_curcanv->cv_h-Line_spacing,"%s: %i", TXT_ENERGY, f2ir(Players[Player_num].energy));
1255
1256         if (Newdemo_state==ND_STATE_RECORDING ) {
1257                 int energy = f2ir(Players[Player_num].energy);
1258
1259                 if (energy != old_energy[VR_current_page]) {
1260                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
1261                         old_energy[VR_current_page] = energy;
1262                 }
1263         }
1264 }
1265
1266 void hud_show_afterburner(void)
1267 {
1268         int y;
1269
1270         if (! (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER))
1271                 return;         //don't draw if don't have
1272
1273         gr_set_curfont( GAME_FONT );
1274         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1275
1276         y = (Game_mode & GM_MULTI)?(-8*Line_spacing):(-3*Line_spacing);
1277
1278         gr_printf(2, grd_curcanv->cv_h+y, "burn: %d%%" , fixmul(Afterburner_charge,100));
1279
1280         if (Newdemo_state==ND_STATE_RECORDING ) {
1281
1282                 if (Afterburner_charge != old_afterburner[VR_current_page]) {
1283                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
1284                         old_afterburner[VR_current_page] = Afterburner_charge;
1285                 }
1286         }
1287 }
1288
1289 char *d2_very_short_secondary_weapon_names[] =
1290                 {"Flash","Guided","SmrtMine","Mercury","Shaker"};
1291
1292 #define SECONDARY_WEAPON_NAMES_VERY_SHORT(weapon_num)                                   \
1293         ((weapon_num <= MEGA_INDEX)?(*(&TXT_CONCUSSION + (weapon_num))):        \
1294         d2_very_short_secondary_weapon_names[weapon_num-SMISSILE1_INDEX])
1295
1296 //return which bomb will be dropped next time the bomb key is pressed
1297 extern int which_bomb();
1298
1299 void show_bomb_count(int x,int y,int bg_color,int always_show)
1300 {
1301         int bomb,count,countx;
1302         char txt[5],*t;
1303
1304         bomb = which_bomb();
1305         count = Players[Player_num].secondary_ammo[bomb];
1306
1307         #ifndef RELEASE
1308         count = min(count,99);  //only have room for 2 digits - cheating give 200
1309         #endif
1310
1311         countx = (bomb==PROXIMITY_INDEX)?count:-count;
1312
1313         if (always_show && count == 0)          //no bombs, draw nothing on HUD
1314                 return;
1315
1316         //if (!always_show && countx == old_bombcount[VR_current_page])
1317         //      return;
1318
1319 // I hate doing this off of hard coded coords!!!!
1320
1321         if (Cockpit_mode == CM_STATUS_BAR) {            //draw background
1322                 gr_setcolor(bg_color);
1323                 if (!Current_display_mode) {
1324                         gr_rect(169,189,189,196);
1325                         gr_setcolor(gr_find_closest_color(10,10,10));
1326                         gr_scanline(168,189,189);
1327                 } else {
1328                         gr_rect(338,453,378,470);
1329
1330                         gr_setcolor(gr_find_closest_color(10,10,10));
1331                         gr_scanline(336,378,453);
1332                 }
1333         }
1334
1335         if (count)
1336                 gr_set_fontcolor((bomb==PROXIMITY_INDEX)?gr_find_closest_color(55,0,0):gr_getcolor(59,50,21),bg_color);
1337         else
1338                 gr_set_fontcolor(bg_color,bg_color);    //erase by drawing in background color
1339
1340         sprintf(txt,"B:%02d",count);
1341
1342         while ((t=strchr(txt,'1')) != NULL)
1343                 *t = '\x84';    //convert to wide '1'
1344
1345         gr_string(x,y,txt);
1346
1347         old_bombcount[VR_current_page] = countx;
1348 }
1349
1350 void draw_primary_ammo_info(int ammo_count)
1351 {
1352         if (Cockpit_mode == CM_STATUS_BAR)
1353                 draw_ammo_info(SB_PRIMARY_AMMO_X,SB_PRIMARY_AMMO_Y,ammo_count,1);
1354         else
1355                 draw_ammo_info(PRIMARY_AMMO_X,PRIMARY_AMMO_Y,ammo_count,1);
1356 }
1357
1358 //convert '1' characters to special wide ones
1359 #define convert_1s(s) do {char *p=s; while ((p=strchr(p,'1')) != NULL) *p=132;} while(0)
1360
1361 void hud_show_weapons(void)
1362 {
1363         int     w, h, aw;
1364         int     y;
1365         char    *weapon_name;
1366         char    weapon_str[32];
1367
1368 //      gr_set_current_canvas(&VR_render_sub_buffer[0]);        //render off-screen
1369         gr_set_curfont( GAME_FONT );
1370         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1371
1372         y = grd_curcanv->cv_h;
1373
1374         if (Game_mode & GM_MULTI)
1375                 y -= 4*Line_spacing;
1376
1377         weapon_name = PRIMARY_WEAPON_NAMES_SHORT(Primary_weapon);
1378
1379         switch (Primary_weapon) {
1380                 case LASER_INDEX:
1381                         if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS)
1382                                 sprintf(weapon_str, "%s %s %i", TXT_QUAD, weapon_name, Players[Player_num].laser_level+1);
1383                         else
1384                                 sprintf(weapon_str, "%s %i", weapon_name, Players[Player_num].laser_level+1);
1385                         break;
1386
1387                 case SUPER_LASER_INDEX: Int3(); break;  //no such thing as super laser
1388
1389                 case VULCAN_INDEX:              
1390                 case GAUSS_INDEX:                       
1391                         sprintf(weapon_str, "%s: %i", weapon_name, f2i((unsigned) Players[Player_num].primary_ammo[VULCAN_INDEX] * (unsigned) VULCAN_AMMO_SCALE)); 
1392                         convert_1s(weapon_str);
1393                         break;
1394
1395                 case SPREADFIRE_INDEX:
1396                 case PLASMA_INDEX:
1397                 case FUSION_INDEX:
1398                 case HELIX_INDEX:
1399                 case PHOENIX_INDEX:
1400                         strcpy(weapon_str, weapon_name);
1401                         break;
1402                 case OMEGA_INDEX:
1403                         sprintf(weapon_str, "%s: %03i", weapon_name, Omega_charge * 100/MAX_OMEGA_CHARGE);
1404                         convert_1s(weapon_str);
1405                         break;
1406
1407                 default:                                                Int3(); weapon_str[0] = 0;      break;
1408         }
1409
1410         gr_get_string_size(weapon_str, &w, &h, &aw );
1411         gr_printf(grd_curcanv->cv_bitmap.bm_w-5-w, y-2*Line_spacing, weapon_str);
1412
1413         if (Primary_weapon == VULCAN_INDEX) {
1414                 if (Players[Player_num].primary_ammo[Primary_weapon] != old_ammo_count[0][VR_current_page]) {
1415                         if (Newdemo_state == ND_STATE_RECORDING)
1416                                 newdemo_record_primary_ammo(old_ammo_count[0][VR_current_page], Players[Player_num].primary_ammo[Primary_weapon]);
1417                         old_ammo_count[0][VR_current_page] = Players[Player_num].primary_ammo[Primary_weapon];
1418                 }
1419         }
1420
1421         if (Primary_weapon == OMEGA_INDEX) {
1422                 if (Omega_charge != Old_Omega_charge[VR_current_page]) {
1423                         if (Newdemo_state == ND_STATE_RECORDING)
1424                                 newdemo_record_primary_ammo(Old_Omega_charge[VR_current_page], Omega_charge);
1425                         Old_Omega_charge[VR_current_page] = Omega_charge;
1426                 }
1427         }
1428
1429         weapon_name = SECONDARY_WEAPON_NAMES_VERY_SHORT(Secondary_weapon);
1430
1431         sprintf(weapon_str, "%s %d",weapon_name,Players[Player_num].secondary_ammo[Secondary_weapon]);
1432         gr_get_string_size(weapon_str, &w, &h, &aw );
1433         gr_printf(grd_curcanv->cv_bitmap.bm_w-5-w, y-Line_spacing, weapon_str);
1434
1435         if (Players[Player_num].secondary_ammo[Secondary_weapon] != old_ammo_count[1][VR_current_page]) {
1436                 if (Newdemo_state == ND_STATE_RECORDING)
1437                         newdemo_record_secondary_ammo(old_ammo_count[1][VR_current_page], Players[Player_num].secondary_ammo[Secondary_weapon]);
1438                 old_ammo_count[1][VR_current_page] = Players[Player_num].secondary_ammo[Secondary_weapon];
1439         }
1440
1441         show_bomb_count(grd_curcanv->cv_bitmap.bm_w-(3*GAME_FONT->ft_w+(FontHires?0:2)), y-3*Line_spacing,-1,1);
1442 }
1443
1444 void hud_show_cloak_invuln(void)
1445 {
1446         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1447
1448         if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
1449                 int     y = grd_curcanv->cv_h;
1450
1451                 if (Game_mode & GM_MULTI)
1452                         y -= 7*Line_spacing;
1453                 else
1454                         y -= 4*Line_spacing;
1455
1456                 if ((Players[Player_num].cloak_time+CLOAK_TIME_MAX - GameTime > F1_0*3 ) || (GameTime & 0x8000))
1457                         gr_printf(2, y, "%s", TXT_CLOAKED);
1458         }
1459
1460         if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
1461                 int     y = grd_curcanv->cv_h;
1462
1463                 if (Game_mode & GM_MULTI)
1464                         y -= 10*Line_spacing;
1465                 else
1466                         y -= 5*Line_spacing;
1467
1468                 if (((Players[Player_num].invulnerable_time + INVULNERABLE_TIME_MAX - GameTime) > F1_0*4) || (GameTime & 0x8000))
1469                         gr_printf(2, y, "%s", TXT_INVULNERABLE);
1470         }
1471
1472 }
1473
1474 void hud_show_shield(void)
1475 {
1476 //      gr_set_current_canvas(&VR_render_sub_buffer[0]);        //render off-screen
1477         gr_set_curfont( GAME_FONT );
1478         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1479
1480         if ( Players[Player_num].shields >= 0 ) {
1481                 if (Game_mode & GM_MULTI)
1482                         gr_printf(2, grd_curcanv->cv_h-6*Line_spacing,"%s: %i", TXT_SHIELD, f2ir(Players[Player_num].shields));
1483                 else
1484                         gr_printf(2, grd_curcanv->cv_h-2*Line_spacing,"%s: %i", TXT_SHIELD, f2ir(Players[Player_num].shields));
1485         } else {
1486                 if (Game_mode & GM_MULTI)
1487                         gr_printf(2, grd_curcanv->cv_h-6*Line_spacing,"%s: 0", TXT_SHIELD );
1488                 else
1489                         gr_printf(2, grd_curcanv->cv_h-2*Line_spacing,"%s: 0", TXT_SHIELD );
1490         }
1491
1492         if (Newdemo_state==ND_STATE_RECORDING ) {
1493                 int shields = f2ir(Players[Player_num].shields);
1494
1495                 if (shields != old_shields[VR_current_page]) {          // Draw the shield gauge
1496                         newdemo_record_player_shields(old_shields[VR_current_page], shields);
1497                         old_shields[VR_current_page] = shields;
1498                 }
1499         }
1500 }
1501
1502 //draw the icons for number of lives
1503 void hud_show_lives()
1504 {
1505         if ((HUD_nmessages > 0) && (strlen(HUD_messages[hud_first]) > 38))
1506                 return;
1507
1508         if (Game_mode & GM_MULTI) {
1509                 gr_set_curfont( GAME_FONT );
1510                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1511                 gr_printf(10, 3, "%s: %d", TXT_DEATHS, Players[Player_num].net_killed_total);
1512         } 
1513         else if (Players[Player_num].lives > 1)  {
1514                 grs_bitmap *bm;
1515                 gr_set_curfont( GAME_FONT );
1516                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
1517                 PAGE_IN_GAUGE( GAUGE_LIVES );
1518                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_LIVES) ];
1519                 gr_ubitmapm(10,3,bm);
1520                 gr_printf(10+bm->bm_w+bm->bm_w/2, 4, "x %d", Players[Player_num].lives-1);
1521         }
1522
1523 }
1524
1525 void sb_show_lives()
1526 {
1527         int x,y;
1528         grs_bitmap * bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_LIVES) ];
1529         x = SB_LIVES_X;
1530         y = SB_LIVES_Y;
1531   
1532         //if (old_lives[VR_current_page] == -1)
1533         {
1534                 gr_set_curfont( GAME_FONT );
1535                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
1536                 if (Game_mode & GM_MULTI)
1537                         gr_printf(SB_LIVES_LABEL_X,SB_LIVES_LABEL_Y,"%s:", TXT_DEATHS);
1538                 else
1539                         gr_printf(SB_LIVES_LABEL_X,SB_LIVES_LABEL_Y,"%s:", TXT_LIVES);
1540
1541         }
1542
1543         if (Game_mode & GM_MULTI)
1544         {
1545                 char killed_str[20];
1546                 int w, h, aw;
1547                 static int last_x[4] = {SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_H,SB_SCORE_RIGHT_H};
1548                 int x;
1549
1550                 sprintf(killed_str, "%5d", Players[Player_num].net_killed_total);
1551                 gr_get_string_size(killed_str, &w, &h, &aw);
1552                 gr_setcolor(BM_XRGB(0,0,0));
1553                 gr_rect(last_x[(Current_display_mode?2:0)+VR_current_page], y+1, SB_SCORE_RIGHT, y+GAME_FONT->ft_h);
1554                 gr_set_fontcolor(gr_getcolor(0,20,0),-1);
1555                 x = SB_SCORE_RIGHT-w-2;         
1556                 gr_printf(x, y+1, killed_str);
1557                 last_x[(Current_display_mode?2:0)+VR_current_page] = x;
1558                 return;
1559         }
1560
1561         //if (old_lives[VR_current_page]==-1 || Players[Player_num].lives != old_lives[VR_current_page])
1562         {
1563
1564                 //erase old icons
1565
1566                 gr_setcolor(BM_XRGB(0,0,0));
1567       
1568            gr_rect(x, y, SB_SCORE_RIGHT, y+bm->bm_h);
1569
1570                 if (Players[Player_num].lives-1 > 0) {
1571                         gr_set_curfont( GAME_FONT );
1572                         gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
1573                         PAGE_IN_GAUGE( GAUGE_LIVES );
1574
1575                         gr_ubitmapm(x, y,bm);
1576                         gr_printf(x+bm->bm_w+GAME_FONT->ft_w, y, "x %d", Players[Player_num].lives-1);
1577
1578 //                      gr_printf(x+12, y, "x %d", Players[Player_num].lives-1);
1579                 }
1580         }
1581
1582 //      for (i=0;i<draw_count;i++,x+=bm->bm_w+2)
1583 //              gr_ubitmapm(x,y,bm);
1584
1585 }
1586
1587 #ifndef RELEASE
1588
1589 #ifdef PIGGY_USE_PAGING
1590 extern int Piggy_bitmap_cache_next;
1591 #endif
1592
1593 void show_time()
1594 {
1595         int secs = f2i(Players[Player_num].time_level) % 60;
1596         int mins = f2i(Players[Player_num].time_level) / 60;
1597
1598         gr_set_curfont( GAME_FONT );
1599
1600         if (Color_0_31_0 == -1)
1601                 Color_0_31_0 = gr_getcolor(0,31,0);
1602         gr_set_fontcolor(Color_0_31_0, -1 );
1603
1604         gr_printf(grd_curcanv->cv_w-4*GAME_FONT->ft_w,grd_curcanv->cv_h-4*Line_spacing,"%d:%02d", mins, secs);
1605
1606 //@@#ifdef PIGGY_USE_PAGING
1607 //@@    {
1608 //@@            char text[25];
1609 //@@            int w,h,aw;
1610 //@@            sprintf( text, "%d KB", Piggy_bitmap_cache_next/1024 );
1611 //@@            gr_get_string_size( text, &w, &h, &aw );        
1612 //@@            gr_printf(grd_curcanv->cv_w-10-w,grd_curcanv->cv_h/2, text );
1613 //@@    }
1614 //@@#endif
1615
1616 }
1617 #endif
1618
1619 #define EXTRA_SHIP_SCORE        50000           //get new ship every this many points
1620
1621 void add_points_to_score(int points) 
1622 {
1623         int prev_score;
1624
1625         score_time += f1_0*2;
1626         score_display[0] += points;
1627         score_display[1] += points;
1628         if (score_time > f1_0*4) score_time = f1_0*4;
1629
1630         if (points == 0 || Cheats_enabled)
1631                 return;
1632
1633         if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
1634                 return;
1635
1636         prev_score=Players[Player_num].score;
1637
1638         Players[Player_num].score += points;
1639
1640         if (Newdemo_state == ND_STATE_RECORDING)
1641                 newdemo_record_player_score(points);
1642
1643 #ifdef NETWORK
1644         if (Game_mode & GM_MULTI_COOP)
1645                 multi_send_score();
1646
1647         if (Game_mode & GM_MULTI)
1648                 return;
1649 #endif
1650
1651         if (Players[Player_num].score/EXTRA_SHIP_SCORE != prev_score/EXTRA_SHIP_SCORE) {
1652                 int snd;
1653                 Players[Player_num].lives += Players[Player_num].score/EXTRA_SHIP_SCORE - prev_score/EXTRA_SHIP_SCORE;
1654                 powerup_basic(20, 20, 20, 0, TXT_EXTRA_LIFE);
1655                 if ((snd=Powerup_info[POW_EXTRA_LIFE].hit_sound) > -1 )
1656                         digi_play_sample( snd, F1_0 );
1657         }
1658 }
1659
1660 void add_bonus_points_to_score(int points) 
1661 {
1662         int prev_score;
1663
1664         if (points == 0 || Cheats_enabled)
1665                 return;
1666
1667         prev_score=Players[Player_num].score;
1668
1669         Players[Player_num].score += points;
1670
1671
1672         if (Newdemo_state == ND_STATE_RECORDING)
1673                 newdemo_record_player_score(points);
1674
1675         if (Game_mode & GM_MULTI)
1676                 return;
1677
1678         if (Players[Player_num].score/EXTRA_SHIP_SCORE != prev_score/EXTRA_SHIP_SCORE) {
1679                 int snd;
1680                 Players[Player_num].lives += Players[Player_num].score/EXTRA_SHIP_SCORE - prev_score/EXTRA_SHIP_SCORE;
1681                 if ((snd=Powerup_info[POW_EXTRA_LIFE].hit_sound) > -1 )
1682                         digi_play_sample( snd, F1_0 );
1683         }
1684 }
1685
1686 #include "key.h"
1687
1688 void init_gauge_canvases()
1689 {
1690         PAGE_IN_GAUGE( SB_GAUGE_ENERGY );
1691         PAGE_IN_GAUGE( GAUGE_AFTERBURNER );
1692
1693         Canv_LeftEnergyGauge = gr_create_canvas( LEFT_ENERGY_GAUGE_W, LEFT_ENERGY_GAUGE_H );
1694         Canv_SBEnergyGauge = gr_create_canvas( SB_ENERGY_GAUGE_W, SB_ENERGY_GAUGE_H );
1695         Canv_SBAfterburnerGauge = gr_create_canvas( SB_AFTERBURNER_GAUGE_W, SB_AFTERBURNER_GAUGE_H );
1696         Canv_RightEnergyGauge = gr_create_canvas( RIGHT_ENERGY_GAUGE_W, RIGHT_ENERGY_GAUGE_H );
1697         Canv_NumericalGauge = gr_create_canvas( NUMERICAL_GAUGE_W, NUMERICAL_GAUGE_H );
1698         Canv_AfterburnerGauge = gr_create_canvas( AFTERBURNER_GAUGE_W, AFTERBURNER_GAUGE_H );
1699
1700 }
1701
1702 void close_gauge_canvases()
1703 {
1704         gr_free_canvas( Canv_LeftEnergyGauge );
1705         gr_free_canvas( Canv_SBEnergyGauge );
1706         gr_free_canvas( Canv_SBAfterburnerGauge );
1707         gr_free_canvas( Canv_RightEnergyGauge );
1708         gr_free_canvas( Canv_NumericalGauge );
1709         gr_free_canvas( Canv_AfterburnerGauge );
1710 }
1711
1712 void init_gauges()
1713 {
1714         int i;
1715
1716         //draw_gauges_on        = 1;
1717
1718         for (i=0; i<2; i++ )    {
1719                 if ( ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) || ((Newdemo_state == ND_STATE_PLAYBACK) && (Newdemo_game_mode & GM_MULTI) && !(Newdemo_game_mode & GM_MULTI_COOP)) ) 
1720                         old_score[i] = -99;
1721                 else
1722                         old_score[i]                    = -1;
1723                 old_energy[i]                   = -1;
1724                 old_shields[i]                  = -1;
1725                 old_flags[i]                    = -1;
1726                 old_cloak[i]                    = -1;
1727                 old_lives[i]                    = -1;
1728                 old_afterburner[i]      = -1;
1729                 old_bombcount[i]                = 0;
1730                 old_laser_level[i]      = 0;
1731         
1732                 old_weapon[0][i] = old_weapon[1][i] = -1;
1733                 old_ammo_count[0][i] = old_ammo_count[1][i] = -1;
1734                 Old_Omega_charge[i] = -1;
1735         }
1736
1737         cloak_fade_state = 0;
1738
1739         weapon_box_user[0] = weapon_box_user[1] = WBU_WEAPON;
1740 }
1741
1742 void draw_energy_bar(int energy)
1743 {
1744         int not_energy;
1745         int x1, x2, y;
1746
1747         // Draw left energy bar
1748         gr_set_current_canvas( Canv_LeftEnergyGauge );
1749         PAGE_IN_GAUGE( GAUGE_ENERGY_LEFT );
1750         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_ENERGY_LEFT)] );
1751         gr_setcolor( BM_XRGB(0,0,0) );
1752
1753         if ( !Current_display_mode )
1754                 not_energy = 61 - (energy*61)/100;
1755         else
1756                 not_energy = 125 - (energy*125)/100;
1757
1758         if (energy < 100)
1759                 for (y=0; y < LEFT_ENERGY_GAUGE_H; y++) {
1760                         x1 = LEFT_ENERGY_GAUGE_H - 1 - y;
1761                         x2 = LEFT_ENERGY_GAUGE_H - 1 - y + not_energy;
1762         
1763                         if ( y>=0 && y<(LEFT_ENERGY_GAUGE_H/4) ) if (x2 > LEFT_ENERGY_GAUGE_W - 1) x2 = LEFT_ENERGY_GAUGE_W - 1;
1764                         if ( y>=(LEFT_ENERGY_GAUGE_H/4) && y<((LEFT_ENERGY_GAUGE_H*3)/4) ) if (x2 > LEFT_ENERGY_GAUGE_W - 2) x2 = LEFT_ENERGY_GAUGE_W - 2;
1765                         if ( y>=((LEFT_ENERGY_GAUGE_H*3)/4) ) if (x2 > LEFT_ENERGY_GAUGE_W - 3) x2 = LEFT_ENERGY_GAUGE_W - 3;
1766                         
1767                         if (x2 > x1) gr_uscanline( x1, x2, y ); 
1768                 }
1769         
1770         gr_set_current_canvas( get_current_game_screen() );
1771         gr_ubitmapm( LEFT_ENERGY_GAUGE_X, LEFT_ENERGY_GAUGE_Y, &Canv_LeftEnergyGauge->cv_bitmap );
1772
1773         // Draw right energy bar
1774         gr_set_current_canvas( Canv_RightEnergyGauge );
1775         PAGE_IN_GAUGE( GAUGE_ENERGY_RIGHT );
1776         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_ENERGY_RIGHT) ] );
1777         gr_setcolor( BM_XRGB(0,0,0) );
1778
1779         if (energy < 100)
1780                 for (y=0; y < RIGHT_ENERGY_GAUGE_H; y++) {
1781                         x1 = RIGHT_ENERGY_GAUGE_W - RIGHT_ENERGY_GAUGE_H + y - not_energy;
1782                         x2 = RIGHT_ENERGY_GAUGE_W - RIGHT_ENERGY_GAUGE_H + y;
1783         
1784                         if ( y>=0 && y<(RIGHT_ENERGY_GAUGE_H/4) ) if (x1 < 0) x1 = 0;
1785                         if ( y>=(RIGHT_ENERGY_GAUGE_H/4) && y<((RIGHT_ENERGY_GAUGE_H*3)/4) ) if (x1 < 1) x1 = 1;
1786                         if ( y>=((RIGHT_ENERGY_GAUGE_H*3)/4) ) if (x1 < 2) x1 = 2;
1787                         
1788                         if (x2 > x1) gr_uscanline( x1, x2, y ); 
1789                 }
1790
1791         gr_set_current_canvas( get_current_game_screen() );
1792         gr_ubitmapm( RIGHT_ENERGY_GAUGE_X, RIGHT_ENERGY_GAUGE_Y, &Canv_RightEnergyGauge->cv_bitmap );
1793 }
1794
1795 ubyte afterburner_bar_table[AFTERBURNER_GAUGE_H_L*2] = {
1796                         3,11,
1797                         3,11,
1798                         3,11,
1799                         3,11,
1800                         3,11,
1801                         3,11,
1802                         2,11,
1803                         2,10,
1804                         2,10,
1805                         2,10,
1806                         2,10,
1807                         2,10,
1808                         2,10,
1809                         1,10,
1810                         1,10,
1811                         1,10,
1812                         1,9,
1813                         1,9,
1814                         1,9,
1815                         1,9,
1816                         0,9,
1817                         0,9,
1818                         0,8,
1819                         0,8,
1820                         0,8,
1821                         0,8,
1822                         1,8,
1823                         2,8,
1824                         3,8,
1825                         4,8,
1826                         5,8,
1827                         6,7,
1828 };
1829
1830 ubyte afterburner_bar_table_hires[AFTERBURNER_GAUGE_H_H*2] = {
1831         5,20,
1832         5,20,
1833         5,19,
1834         5,19,
1835         5,19,
1836         5,19,
1837         4,19,
1838         4,19,
1839         4,19,
1840         4,19,
1841
1842         4,19,
1843         4,18,
1844         4,18,
1845         4,18,
1846         4,18,
1847         3,18,
1848         3,18,
1849         3,18,
1850         3,18,
1851         3,18,
1852
1853         3,18,
1854         3,17,
1855         3,17,
1856         2,17,
1857         2,17,
1858         2,17,
1859         2,17,
1860         2,17,
1861         2,17,
1862         2,17,
1863
1864         2,17,
1865         2,16,
1866         2,16,
1867         1,16,
1868         1,16,
1869         1,16,
1870         1,16,
1871         1,16,
1872         1,16,
1873         1,16,
1874
1875         1,16,
1876         1,15,
1877         1,15,
1878         1,15,
1879         0,15,
1880         0,15,
1881         0,15,
1882         0,15,
1883         0,15,
1884         0,15,
1885
1886         0,14,
1887         0,14,
1888         0,14,
1889         1,14,
1890         2,14,
1891         3,14,
1892         4,14,
1893         5,14,
1894         6,13,
1895         7,13,
1896
1897         8,13,
1898         9,13,
1899         10,13,
1900         11,13,
1901         12,13
1902 };
1903
1904
1905 void draw_afterburner_bar(int afterburner)
1906 {
1907         int not_afterburner;
1908         int y;
1909
1910         // Draw afterburner bar
1911         gr_set_current_canvas( Canv_AfterburnerGauge );
1912         PAGE_IN_GAUGE( GAUGE_AFTERBURNER );
1913         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_AFTERBURNER) ] );
1914         gr_setcolor( BM_XRGB(0,0,0) );
1915
1916         not_afterburner = fixmul(f1_0 - afterburner,AFTERBURNER_GAUGE_H);
1917
1918         for (y=0;y<not_afterburner;y++) {
1919
1920                 gr_uscanline( (Current_display_mode?afterburner_bar_table_hires[y*2]:afterburner_bar_table[y*2]),
1921                                                 (Current_display_mode?afterburner_bar_table_hires[y*2+1]:afterburner_bar_table[y*2+1]), y ); 
1922         }
1923
1924         gr_set_current_canvas( get_current_game_screen() );
1925         gr_ubitmapm( AFTERBURNER_GAUGE_X, AFTERBURNER_GAUGE_Y, &Canv_AfterburnerGauge->cv_bitmap );
1926 }
1927
1928 void draw_shield_bar(int shield)
1929 {
1930         int bm_num = shield>=100?9:(shield / 10);
1931
1932         PAGE_IN_GAUGE( GAUGE_SHIELDS+9-bm_num   );
1933         gr_ubitmapm( SHIELD_GAUGE_X, SHIELD_GAUGE_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIELDS+9-bm_num) ] );
1934 }
1935
1936 #define CLOAK_FADE_WAIT_TIME  0x400
1937
1938 void draw_player_ship(int cloak_state,int old_cloak_state,int x, int y)
1939 {
1940         static fix cloak_fade_timer=0;
1941         static int cloak_fade_value=GR_FADE_LEVELS-1;
1942         static int refade = 0;
1943         grs_bitmap *bm = NULL;
1944
1945         if (Game_mode & GM_TEAM)        {
1946                 #ifdef NETWORK
1947                 PAGE_IN_GAUGE( GAUGE_SHIPS+get_team(Player_num) );
1948                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIPS+get_team(Player_num)) ];
1949                 #endif
1950         } else {
1951                 PAGE_IN_GAUGE( GAUGE_SHIPS+Player_num );
1952                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIPS+Player_num) ];
1953         }
1954         
1955
1956         if (old_cloak_state==-1 && cloak_state)
1957                         cloak_fade_value=0;
1958
1959 //      mprintf((0, "cloak/oldcloak %d/%d", cloak_state, old_cloak_state));
1960
1961         if (!cloak_state) {
1962                 cloak_fade_value=GR_FADE_LEVELS-1;
1963                 cloak_fade_state = 0;
1964         }
1965
1966         if (cloak_state==1 && old_cloak_state==0)
1967                 cloak_fade_state = -1;
1968         //else if (cloak_state==0 && old_cloak_state==1)
1969         //      cloak_fade_state = 1;
1970
1971         if (cloak_state && GameTime > Players[Player_num].cloak_time + CLOAK_TIME_MAX - i2f(3))         //doing "about-to-uncloak" effect
1972                 if (cloak_fade_state==0)
1973                         cloak_fade_state = 2;
1974         
1975
1976         if (cloak_fade_state)
1977                 cloak_fade_timer -= FrameTime;
1978
1979         while (cloak_fade_state && cloak_fade_timer < 0) {
1980
1981                 cloak_fade_timer += CLOAK_FADE_WAIT_TIME;
1982
1983                 cloak_fade_value += cloak_fade_state;
1984
1985                 if (cloak_fade_value >= GR_FADE_LEVELS-1) {
1986                         cloak_fade_value = GR_FADE_LEVELS-1;
1987                         if (cloak_fade_state == 2 && cloak_state)
1988                                 cloak_fade_state = -2;
1989                         else
1990                                 cloak_fade_state = 0;
1991                 }
1992                 else if (cloak_fade_value <= 0) {
1993                         cloak_fade_value = 0;
1994                         if (cloak_fade_state == -2)
1995                                 cloak_fade_state = 2;
1996                         else
1997                                 cloak_fade_state = 0;
1998                 }
1999         }
2000
2001 //      To fade out both pages in a paged mode.
2002         if (refade) refade = 0;
2003         else if (cloak_state && old_cloak_state && !cloak_fade_state && !refade) {
2004                 cloak_fade_state = -1;
2005                 refade = 1;
2006         }
2007
2008         gr_set_current_canvas(&VR_render_buffer[0]);
2009
2010         gr_ubitmap( x, y, bm);
2011
2012         Gr_scanline_darkening_level = cloak_fade_value;
2013         gr_rect(x, y, x+bm->bm_w-1, y+bm->bm_h-1);
2014         Gr_scanline_darkening_level = GR_FADE_LEVELS;
2015
2016         gr_set_current_canvas( get_current_game_screen() );
2017
2018         gr_bm_ubitbltm( bm->bm_w, bm->bm_h, x, y, x, y, &VR_render_buffer[0].cv_bitmap, &grd_curcanv->cv_bitmap);
2019 }
2020
2021 #define INV_FRAME_TIME  (f1_0/10)               //how long for each frame
2022
2023 void draw_numerical_display(int shield, int energy)
2024 {
2025         gr_set_current_canvas( Canv_NumericalGauge );
2026         gr_set_curfont( GAME_FONT );
2027         PAGE_IN_GAUGE( GAUGE_NUMERICAL );
2028         gr_ubitmap( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_NUMERICAL) ] );
2029
2030         gr_set_fontcolor(gr_getcolor(14,14,23),-1 );
2031
2032         if (!Current_display_mode) {
2033                 gr_printf((shield>99)?3:((shield>9)?5:7),15,"%d",shield);
2034                 gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2035                 gr_printf((energy>99)?3:((energy>9)?5:7),2,"%d",energy);
2036         } else {
2037                 gr_printf((shield>99)?7:((shield>9)?11:15),33,"%d",shield);
2038                 gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2039                 gr_printf((energy>99)?7:((energy>9)?11:15),4,"%d",energy);
2040         }
2041         
2042         gr_set_current_canvas( get_current_game_screen() );
2043         gr_ubitmapm( NUMERICAL_GAUGE_X, NUMERICAL_GAUGE_Y, &Canv_NumericalGauge->cv_bitmap );
2044 }
2045
2046
2047 void draw_keys()
2048 {
2049         gr_set_current_canvas( get_current_game_screen() );
2050
2051         if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY ) {
2052                 PAGE_IN_GAUGE( GAUGE_BLUE_KEY );
2053                 gr_ubitmapm( GAUGE_BLUE_KEY_X, GAUGE_BLUE_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_BLUE_KEY) ] );
2054         } else {
2055                 PAGE_IN_GAUGE( GAUGE_BLUE_KEY_OFF );
2056                 gr_ubitmapm( GAUGE_BLUE_KEY_X, GAUGE_BLUE_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_BLUE_KEY_OFF) ] );
2057         }
2058
2059         if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY)  {
2060                 PAGE_IN_GAUGE( GAUGE_GOLD_KEY );
2061                 gr_ubitmapm( GAUGE_GOLD_KEY_X, GAUGE_GOLD_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_GOLD_KEY) ] );
2062         } else {
2063                 PAGE_IN_GAUGE( GAUGE_GOLD_KEY_OFF );
2064                 gr_ubitmapm( GAUGE_GOLD_KEY_X, GAUGE_GOLD_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_GOLD_KEY_OFF) ] );
2065         }
2066
2067         if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY)   {
2068                 PAGE_IN_GAUGE( GAUGE_RED_KEY );
2069                 gr_ubitmapm( GAUGE_RED_KEY_X,  GAUGE_RED_KEY_Y,  &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_RED_KEY) ] );
2070         } else {
2071                 PAGE_IN_GAUGE( GAUGE_RED_KEY_OFF );
2072                 gr_ubitmapm( GAUGE_RED_KEY_X,  GAUGE_RED_KEY_Y,  &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_RED_KEY_OFF) ] );
2073         }
2074 }
2075
2076
2077 void draw_weapon_info_sub(int info_index,gauge_box *box,int pic_x,int pic_y,char *name,int text_x,int text_y)
2078 {
2079         grs_bitmap *bm;
2080         char *p;
2081
2082         //clear the window
2083         gr_setcolor(BM_XRGB(0,0,0));
2084         
2085    gr_rect(box->left,box->top,box->right,box->bot);
2086
2087         if (Piggy_hamfile_version >= 3 // !SHAREWARE
2088                 && Current_display_mode)
2089         {
2090                 bm=&GameBitmaps[Weapon_info[info_index].hires_picture.index];
2091                 PIGGY_PAGE_IN( Weapon_info[info_index].hires_picture );
2092         } else {
2093                 bm=&GameBitmaps[Weapon_info[info_index].picture.index];
2094                 PIGGY_PAGE_IN( Weapon_info[info_index].picture );
2095         }
2096
2097         Assert(bm != NULL);
2098
2099         gr_ubitmapm(pic_x,pic_y,bm);
2100         
2101         gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
2102
2103         if ((p=strchr(name,'\n'))!=NULL) {
2104                 *p=0;
2105                 gr_printf(text_x,text_y,name);
2106                 gr_printf(text_x,text_y+grd_curcanv->cv_font->ft_h+1,p+1);
2107                 *p='\n';
2108         } else
2109                 gr_printf(text_x,text_y,name);
2110
2111         //      For laser, show level and quadness
2112         if (info_index == LASER_ID || info_index == SUPER_LASER_ID) {
2113                 char    temp_str[7];
2114
2115                 sprintf(temp_str, "%s: 0", TXT_LVL);
2116
2117                 temp_str[5] = Players[Player_num].laser_level+1 + '0';
2118
2119                 gr_printf(text_x,text_y+Line_spacing, temp_str);
2120
2121                 if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS) {
2122                         strcpy(temp_str, TXT_QUAD);
2123                         gr_printf(text_x,text_y+2*Line_spacing, temp_str);
2124
2125                 }
2126
2127         }
2128 }
2129
2130
2131 void draw_weapon_info(int weapon_type,int weapon_num,int laser_level)
2132 {
2133         int info_index;
2134
2135         if (weapon_type == 0) {
2136                 info_index = Primary_weapon_to_weapon_info[weapon_num];
2137
2138                 if (info_index == LASER_ID && laser_level > MAX_LASER_LEVEL)
2139                         info_index = SUPER_LASER_ID;
2140
2141                 if (Cockpit_mode == CM_STATUS_BAR)
2142                         draw_weapon_info_sub(info_index,
2143                                 &gauge_boxes[SB_PRIMARY_BOX],
2144                                 SB_PRIMARY_W_PIC_X,SB_PRIMARY_W_PIC_Y,
2145                                 PRIMARY_WEAPON_NAMES_SHORT(weapon_num),
2146                                 SB_PRIMARY_W_TEXT_X,SB_PRIMARY_W_TEXT_Y);
2147                 else
2148                         draw_weapon_info_sub(info_index,
2149                                 &gauge_boxes[COCKPIT_PRIMARY_BOX],
2150                                 PRIMARY_W_PIC_X,PRIMARY_W_PIC_Y,
2151                                 PRIMARY_WEAPON_NAMES_SHORT(weapon_num),
2152                                 PRIMARY_W_TEXT_X,PRIMARY_W_TEXT_Y);
2153
2154         }
2155         else {
2156                 info_index = Secondary_weapon_to_weapon_info[weapon_num];
2157
2158                 if (Cockpit_mode == CM_STATUS_BAR)
2159                         draw_weapon_info_sub(info_index,
2160                                 &gauge_boxes[SB_SECONDARY_BOX],
2161                                 SB_SECONDARY_W_PIC_X,SB_SECONDARY_W_PIC_Y,
2162                                 SECONDARY_WEAPON_NAMES_SHORT(weapon_num),
2163                                 SB_SECONDARY_W_TEXT_X,SB_SECONDARY_W_TEXT_Y);
2164                 else
2165                         draw_weapon_info_sub(info_index,
2166                                 &gauge_boxes[COCKPIT_SECONDARY_BOX],
2167                                 SECONDARY_W_PIC_X,SECONDARY_W_PIC_Y,
2168                                 SECONDARY_WEAPON_NAMES_SHORT(weapon_num),
2169                                 SECONDARY_W_TEXT_X,SECONDARY_W_TEXT_Y);
2170         }
2171 }
2172
2173 void draw_ammo_info(int x,int y,int ammo_count,int primary)
2174 {
2175         int w;
2176         char str[16];
2177
2178         if (primary)
2179                 w = (grd_curcanv->cv_font->ft_w*7)/2;
2180         else
2181                 w = (grd_curcanv->cv_font->ft_w*5)/2;
2182
2183         gr_setcolor(BM_XRGB(0,0,0));
2184         gr_rect(x,y,x+w,y+grd_curcanv->cv_font->ft_h);
2185         gr_set_fontcolor(gr_getcolor(20,0,0),-1 );
2186         sprintf(str,"%03d",ammo_count);
2187         convert_1s(str);
2188         gr_printf(x,y,str);
2189 }
2190
2191 void draw_secondary_ammo_info(int ammo_count)
2192 {
2193         if (Cockpit_mode == CM_STATUS_BAR)
2194                 draw_ammo_info(SB_SECONDARY_AMMO_X,SB_SECONDARY_AMMO_Y,ammo_count,0);
2195         else
2196                 draw_ammo_info(SECONDARY_AMMO_X,SECONDARY_AMMO_Y,ammo_count,0);
2197 }
2198
2199 //returns true if drew picture
2200 int draw_weapon_box(int weapon_type,int weapon_num)
2201 {
2202         int drew_flag=0;
2203         int laser_level_changed;
2204
2205         gr_set_current_canvas(&VR_render_buffer[0]);
2206
2207         gr_set_curfont( GAME_FONT );
2208
2209         laser_level_changed = (weapon_type==0 && weapon_num==LASER_INDEX && (Players[Player_num].laser_level != old_laser_level[VR_current_page]));
2210
2211         if ((weapon_num != old_weapon[weapon_type][VR_current_page] || laser_level_changed) && weapon_box_states[weapon_type] == WS_SET && (old_weapon[weapon_type][VR_current_page] != -1))
2212         {
2213                 weapon_box_states[weapon_type] = WS_FADING_OUT;
2214                 weapon_box_fade_values[weapon_type]=i2f(GR_FADE_LEVELS-1);
2215         }
2216                 
2217         if (weapon_box_states[weapon_type] == WS_FADING_OUT) {
2218                 draw_weapon_info(weapon_type,old_weapon[weapon_type][VR_current_page],old_laser_level[VR_current_page]);
2219                 old_ammo_count[weapon_type][VR_current_page]=-1;
2220                 Old_Omega_charge[VR_current_page]=-1;
2221                 drew_flag=1;
2222                 weapon_box_fade_values[weapon_type] -= FrameTime * FADE_SCALE;
2223                 if (weapon_box_fade_values[weapon_type] <= 0) {
2224                         weapon_box_states[weapon_type] = WS_FADING_IN;
2225                         old_weapon[weapon_type][VR_current_page] = weapon_num;
2226                         old_weapon[weapon_type][!VR_current_page] = weapon_num;
2227                         old_laser_level[VR_current_page] = Players[Player_num].laser_level;
2228                         old_laser_level[!VR_current_page] = Players[Player_num].laser_level;
2229                         weapon_box_fade_values[weapon_type] = 0;
2230                 }
2231         }
2232         else if (weapon_box_states[weapon_type] == WS_FADING_IN) {
2233                 if (weapon_num != old_weapon[weapon_type][VR_current_page]) {
2234                         weapon_box_states[weapon_type] = WS_FADING_OUT;
2235                 }
2236                 else {
2237                         draw_weapon_info(weapon_type,weapon_num,Players[Player_num].laser_level);
2238                         old_ammo_count[weapon_type][VR_current_page]=-1;
2239                         Old_Omega_charge[VR_current_page]=-1;
2240                         drew_flag=1;
2241                         weapon_box_fade_values[weapon_type] += FrameTime * FADE_SCALE;
2242                         if (weapon_box_fade_values[weapon_type] >= i2f(GR_FADE_LEVELS-1)) {
2243                                 weapon_box_states[weapon_type] = WS_SET;
2244                                 old_weapon[weapon_type][!VR_current_page] = -1;         //force redraw (at full fade-in) of other page
2245                         }
2246                 }
2247         } else
2248         //      if (old_weapon[weapon_type][VR_current_page] == -1)
2249                         {
2250                         //@@if (laser_level_changed)
2251                         //@@    old_weapon[weapon_type][VR_current_page] = LASER_INDEX;
2252                         //@@else 
2253                         {
2254                                 draw_weapon_info(weapon_type, weapon_num, Players[Player_num].laser_level);
2255                                 old_weapon[weapon_type][VR_current_page] = weapon_num;
2256                                 old_ammo_count[weapon_type][VR_current_page] = -1;
2257                                 Old_Omega_charge[VR_current_page] = -1;
2258                                 old_laser_level[VR_current_page] = Players[Player_num].laser_level;
2259                                 drew_flag = 1;
2260                         }
2261                 }
2262
2263         if (weapon_box_states[weapon_type] != WS_SET) {         //fade gauge
2264                 int fade_value = f2i(weapon_box_fade_values[weapon_type]);
2265                 int boxofs = (Cockpit_mode==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2266                 
2267                 Gr_scanline_darkening_level = fade_value;
2268                 gr_rect(gauge_boxes[boxofs+weapon_type].left,gauge_boxes[boxofs+weapon_type].top,gauge_boxes[boxofs+weapon_type].right,gauge_boxes[boxofs+weapon_type].bot);
2269
2270                 Gr_scanline_darkening_level = GR_FADE_LEVELS;
2271         }
2272
2273         gr_set_current_canvas(get_current_game_screen());
2274         return drew_flag;
2275 }
2276
2277 fix static_time[2];
2278
2279 void draw_static(int win)
2280 {
2281         vclip *vc = &Vclip[VCLIP_MONITOR_STATIC];
2282         grs_bitmap *bmp;
2283         int framenum;
2284         int boxofs = (Cockpit_mode==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2285         int x,y;
2286
2287         static_time[win] += FrameTime;
2288         if (static_time[win] >= vc->play_time) {
2289                 weapon_box_user[win] = WBU_WEAPON;
2290                 return;
2291         }
2292
2293         framenum = static_time[win] * vc->num_frames / vc->play_time;
2294
2295         PIGGY_PAGE_IN(vc->frames[framenum]);
2296
2297         bmp = &GameBitmaps[vc->frames[framenum].index];
2298
2299         gr_set_current_canvas(&VR_render_buffer[0]);
2300    
2301         for (x=gauge_boxes[boxofs+win].left;x<gauge_boxes[boxofs+win].right;x+=bmp->bm_w)
2302                 for (y=gauge_boxes[boxofs+win].top;y<gauge_boxes[boxofs+win].bot;y+=bmp->bm_h)
2303                         gr_bitmap(x,y,bmp);
2304
2305         gr_set_current_canvas(get_current_game_screen());
2306
2307         copy_gauge_box(&gauge_boxes[boxofs+win],&VR_render_buffer[0].cv_bitmap);
2308 }
2309
2310 void draw_weapon_boxes()
2311 {
2312         int boxofs = (Cockpit_mode==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2313         int drew;
2314
2315         if (weapon_box_user[0] == WBU_WEAPON) {
2316                 drew = draw_weapon_box(0,Primary_weapon);
2317                 if (drew) 
2318                         copy_gauge_box(&gauge_boxes[boxofs+0],&VR_render_buffer[0].cv_bitmap);
2319
2320                 if (weapon_box_states[0] == WS_SET) {
2321                         if ((Primary_weapon == VULCAN_INDEX) || (Primary_weapon == GAUSS_INDEX))
2322                         {
2323                                 if (Newdemo_state == ND_STATE_RECORDING &&
2324                 Players[Player_num].primary_ammo[VULCAN_INDEX] != old_ammo_count[0][VR_current_page])
2325                                         newdemo_record_primary_ammo(old_ammo_count[0][VR_current_page], Players[Player_num].primary_ammo[VULCAN_INDEX]);
2326                                 draw_primary_ammo_info(f2i((unsigned) VULCAN_AMMO_SCALE * (unsigned) Players[Player_num].primary_ammo[VULCAN_INDEX]));
2327                                 old_ammo_count[0][VR_current_page] = Players[Player_num].primary_ammo[VULCAN_INDEX];
2328                         }
2329
2330                         if (Primary_weapon == OMEGA_INDEX)
2331                         {
2332                                 if (Newdemo_state == ND_STATE_RECORDING &&
2333                 Omega_charge != Old_Omega_charge[VR_current_page])
2334                                         newdemo_record_primary_ammo(Old_Omega_charge[VR_current_page], Omega_charge);
2335                                 draw_primary_ammo_info(Omega_charge * 100/MAX_OMEGA_CHARGE);
2336                                 Old_Omega_charge[VR_current_page] = Omega_charge;
2337                         }
2338                 }
2339         }
2340         else if (weapon_box_user[0] == WBU_STATIC)
2341                 draw_static(0);
2342
2343         if (weapon_box_user[1] == WBU_WEAPON) {
2344                 drew = draw_weapon_box(1,Secondary_weapon);
2345                 if (drew)
2346                         copy_gauge_box(&gauge_boxes[boxofs+1],&VR_render_buffer[0].cv_bitmap);
2347
2348                 if (weapon_box_states[1] == WS_SET)
2349                 {
2350                         old_bombcount[VR_current_page] = 0x7fff;        //force redraw
2351                         if (Newdemo_state == ND_STATE_RECORDING &&
2352         Players[Player_num].secondary_ammo[Secondary_weapon] != old_ammo_count[1][VR_current_page])
2353                                 newdemo_record_secondary_ammo(old_ammo_count[1][VR_current_page], Players[Player_num].secondary_ammo[Secondary_weapon]);
2354                         draw_secondary_ammo_info(Players[Player_num].secondary_ammo[Secondary_weapon]);
2355                         old_ammo_count[1][VR_current_page] = Players[Player_num].secondary_ammo[Secondary_weapon];
2356
2357                         if (Secondary_weapon != which_bomb())   // don't draw two bomb counts
2358                         {
2359                                 if (Cockpit_mode == CM_STATUS_BAR)
2360                                         show_bomb_count(SB_BOMB_COUNT_X, SB_BOMB_COUNT_Y, gr_find_closest_color(0, 0, 0), 0);
2361                                 else
2362                                         show_bomb_count(BOMB_COUNT_X, BOMB_COUNT_Y, gr_find_closest_color(0, 0, 0), 0);
2363                         }
2364                 }
2365         }
2366         else if (weapon_box_user[1] == WBU_STATIC)
2367                 draw_static(1);
2368 }
2369
2370
2371 void sb_draw_energy_bar(energy)
2372 {
2373         int erase_height, w, h, aw;
2374         char energy_str[20];
2375
2376         //gr_set_current_canvas( Canv_SBEnergyGauge );
2377
2378         gr_set_current_canvas(get_current_game_screen());
2379
2380         PAGE_IN_GAUGE( SB_GAUGE_ENERGY );
2381         gr_ubitmapm(SB_ENERGY_GAUGE_X, SB_ENERGY_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(SB_GAUGE_ENERGY)]);
2382
2383         erase_height = (100 - energy) * SB_ENERGY_GAUGE_H / 100;
2384
2385         if (erase_height > 0) {
2386                 gr_setcolor( BM_XRGB(0,0,0) );
2387                 gr_rect(SB_ENERGY_GAUGE_X, SB_ENERGY_GAUGE_Y, SB_ENERGY_GAUGE_X + SB_ENERGY_GAUGE_W - 1, SB_ENERGY_GAUGE_Y + erase_height - 1);
2388         }
2389
2390         //gr_ubitmapm( SB_ENERGY_GAUGE_X, SB_ENERGY_GAUGE_Y, &Canv_SBEnergyGauge->cv_bitmap );
2391
2392         //draw numbers
2393         sprintf(energy_str, "%d", energy);
2394         gr_get_string_size(energy_str, &w, &h, &aw );
2395         gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2396         gr_printf(SB_ENERGY_GAUGE_X + ((SB_ENERGY_GAUGE_W - w)/2), SB_ENERGY_GAUGE_Y + SB_ENERGY_GAUGE_H - GAME_FONT->ft_h - (GAME_FONT->ft_h / 4), "%d", energy);
2397 }
2398
2399 void sb_draw_afterburner()
2400 {
2401         int erase_height, w, h, aw;
2402         char ab_str[3] = "AB";
2403
2404         //gr_set_current_canvas( Canv_SBAfterburnerGauge );
2405         gr_set_current_canvas(get_current_game_screen());
2406         PAGE_IN_GAUGE( SB_GAUGE_AFTERBURNER );
2407         gr_ubitmapm(SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(SB_GAUGE_AFTERBURNER)]);
2408
2409         erase_height = fixmul((f1_0 - Afterburner_charge),SB_AFTERBURNER_GAUGE_H);
2410
2411         if (erase_height > 0) {
2412                 gr_setcolor( BM_XRGB(0,0,0) );
2413                 gr_rect(SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y, SB_AFTERBURNER_GAUGE_X + SB_AFTERBURNER_GAUGE_W - 1, SB_AFTERBURNER_GAUGE_Y + erase_height - 1);
2414         }
2415
2416         //gr_ubitmapm( SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y, &Canv_SBAfterburnerGauge->cv_bitmap );
2417
2418         //draw legend
2419         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
2420                 gr_set_fontcolor(gr_getcolor(45,0,0),-1 );
2421         else 
2422                 gr_set_fontcolor(gr_getcolor(12,12,12),-1 );
2423
2424         gr_get_string_size(ab_str, &w, &h, &aw );
2425         gr_printf(SB_AFTERBURNER_GAUGE_X + ((SB_AFTERBURNER_GAUGE_W - w)/2),SB_AFTERBURNER_GAUGE_Y+SB_AFTERBURNER_GAUGE_H-GAME_FONT->ft_h - (GAME_FONT->ft_h / 4),"AB");
2426 }
2427
2428 void sb_draw_shield_num(int shield)
2429 {
2430         //draw numbers
2431
2432         gr_set_curfont( GAME_FONT );
2433         gr_set_fontcolor(gr_getcolor(14,14,23),-1 );
2434
2435         //erase old one
2436 //      PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode + (Current_display_mode ? (Num_cockpits/2) : 0)]);
2437
2438 //      gr_setcolor(gr_gpixel(&grd_curcanv->cv_bitmap, SB_SHIELD_NUM_X - 1, SB_SHIELD_NUM_Y - 1));
2439
2440 //      gr_rect(SB_SHIELD_NUM_X, SB_SHIELD_NUM_Y, SB_SHIELD_NUM_X + (Current_display_mode ? 27 : 13), SB_SHIELD_NUM_Y + GAME_FONT->ft_h);
2441         gr_printf((shield>99)?SB_SHIELD_NUM_X:((shield>9)?SB_SHIELD_NUM_X+2:SB_SHIELD_NUM_X+4),SB_SHIELD_NUM_Y,"%d",shield);
2442 }
2443
2444 void sb_draw_shield_bar(int shield)
2445 {
2446         int bm_num = shield>=100?9:(shield / 10);
2447
2448         gr_set_current_canvas(get_current_game_screen());
2449         PAGE_IN_GAUGE( GAUGE_SHIELDS+9-bm_num );
2450         gr_ubitmapm( SB_SHIELD_GAUGE_X, SB_SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_SHIELDS+9-bm_num) ] );
2451 }
2452
2453 void sb_draw_keys()
2454 {
2455         grs_bitmap * bm;
2456         int flags = Players[Player_num].flags;
2457
2458         gr_set_current_canvas(get_current_game_screen());
2459         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_BLUE_KEY)?SB_GAUGE_BLUE_KEY:SB_GAUGE_BLUE_KEY_OFF) ];
2460         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_BLUE_KEY)?SB_GAUGE_BLUE_KEY:SB_GAUGE_BLUE_KEY_OFF );
2461         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_BLUE_KEY_Y, bm );
2462         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_GOLD_KEY)?SB_GAUGE_GOLD_KEY:SB_GAUGE_GOLD_KEY_OFF) ];
2463         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_GOLD_KEY)?SB_GAUGE_GOLD_KEY:SB_GAUGE_GOLD_KEY_OFF );
2464         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_GOLD_KEY_Y, bm );
2465         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_RED_KEY)?SB_GAUGE_RED_KEY:SB_GAUGE_RED_KEY_OFF) ];
2466         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_RED_KEY)?SB_GAUGE_RED_KEY:SB_GAUGE_RED_KEY_OFF );
2467         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_RED_KEY_Y, bm  );
2468 }
2469
2470 //      Draws invulnerable ship, or maybe the flashing ship, depending on invulnerability time left.
2471 void draw_invulnerable_ship()
2472 {
2473         static fix time=0;
2474
2475         gr_set_current_canvas(get_current_game_screen());
2476
2477         if (((Players[Player_num].invulnerable_time + INVULNERABLE_TIME_MAX - GameTime) > F1_0*4) || (GameTime & 0x8000)) {
2478
2479                 if (Cockpit_mode == CM_STATUS_BAR)      {
2480                         PAGE_IN_GAUGE( GAUGE_INVULNERABLE+invulnerable_frame );
2481                         gr_ubitmapm( SB_SHIELD_GAUGE_X, SB_SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_INVULNERABLE+invulnerable_frame) ] );
2482                 } else {
2483                         PAGE_IN_GAUGE( GAUGE_INVULNERABLE+invulnerable_frame );
2484                         gr_ubitmapm( SHIELD_GAUGE_X, SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_INVULNERABLE+invulnerable_frame)] );
2485                 }
2486
2487                 time += FrameTime;
2488
2489                 while (time > INV_FRAME_TIME) {
2490                         time -= INV_FRAME_TIME;
2491                         if (++invulnerable_frame == N_INVULNERABLE_FRAMES)
2492                                 invulnerable_frame=0;
2493                 }
2494         } else if (Cockpit_mode == CM_STATUS_BAR)
2495                 sb_draw_shield_bar(f2ir(Players[Player_num].shields));
2496         else
2497                 draw_shield_bar(f2ir(Players[Player_num].shields));
2498 }
2499
2500 extern int Missile_gun;
2501 extern int allowed_to_fire_laser(void);
2502 extern int allowed_to_fire_missile(void);
2503
2504 rgb player_rgb[] = {
2505                                                         {15,15,23},
2506                                                         {27,0,0},
2507                                                         {0,23,0},
2508                                                         {30,11,31},
2509                                                         {31,16,0},
2510                                                         {24,17,6},
2511                                                         {14,21,12},
2512                                                         {29,29,0},
2513                                                 };
2514
2515 extern ubyte Newdemo_flying_guided;
2516 extern int max_window_w;
2517
2518 typedef struct {
2519         sbyte x, y;
2520 } xy;
2521
2522 //offsets for reticle parts: high-big  high-sml  low-big  low-sml
2523 xy cross_offsets[4] =           { {-8,-5},      {-4,-2},        {-4,-2}, {-2,-1} };
2524 xy primary_offsets[4] =         { {-30,14}, {-16,6},    {-15,6}, {-8, 2} };
2525 xy secondary_offsets[4] =       { {-24,2},      {-12,0}, {-12,1}, {-6,-2} };
2526
2527 //draw the reticle
2528 void show_reticle(int force_big_one)
2529 {
2530         int x,y;
2531         int laser_ready,missile_ready,laser_ammo,missile_ammo;
2532         int cross_bm_num,primary_bm_num,secondary_bm_num;
2533         int use_hires_reticle,small_reticle,ofs,gauge_index;
2534
2535         if (Newdemo_state==ND_STATE_PLAYBACK && Newdemo_flying_guided)
2536         {
2537                  draw_guided_crosshair();
2538                  return;
2539         }
2540
2541         x = grd_curcanv->cv_w/2;
2542         y = grd_curcanv->cv_h/2;
2543
2544         laser_ready = allowed_to_fire_laser();
2545         missile_ready = allowed_to_fire_missile();
2546
2547         laser_ammo = player_has_weapon(Primary_weapon,0);
2548         missile_ammo = player_has_weapon(Secondary_weapon,1);
2549
2550         primary_bm_num = (laser_ready && laser_ammo==HAS_ALL);
2551         secondary_bm_num = (missile_ready && missile_ammo==HAS_ALL);
2552
2553         if (primary_bm_num && Primary_weapon==LASER_INDEX && (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS))
2554                 primary_bm_num++;
2555
2556         if (Secondary_weapon_to_gun_num[Secondary_weapon]==7)
2557                 secondary_bm_num += 3;          //now value is 0,1 or 3,4
2558         else if (secondary_bm_num && !(Missile_gun&1))
2559                         secondary_bm_num++;
2560
2561         cross_bm_num = ((primary_bm_num > 0) || (secondary_bm_num > 0));
2562
2563         Assert(primary_bm_num <= 2);
2564         Assert(secondary_bm_num <= 4);
2565         Assert(cross_bm_num <= 1);
2566 #ifdef OGL
2567         if (gl_reticle==2 || (gl_reticle && grd_curcanv->cv_bitmap.bm_w > 320))
2568         {
2569                 ogl_draw_reticle(cross_bm_num,primary_bm_num,secondary_bm_num);
2570         }
2571         else
2572         {
2573 #endif
2574
2575
2576                 use_hires_reticle = (FontHires != 0);
2577
2578         small_reticle = !(grd_curcanv->cv_bitmap.bm_w*3 > max_window_w*2 || force_big_one);
2579         ofs = (use_hires_reticle?0:2) + small_reticle;
2580
2581         gauge_index = (small_reticle?SML_RETICLE_CROSS:RETICLE_CROSS) + cross_bm_num;
2582         PAGE_IN_GAUGE( gauge_index );
2583         gr_ubitmapm(x+cross_offsets[ofs].x,y+cross_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2584
2585         gauge_index = (small_reticle?SML_RETICLE_PRIMARY:RETICLE_PRIMARY) + primary_bm_num;
2586         PAGE_IN_GAUGE( gauge_index );
2587         gr_ubitmapm(x+primary_offsets[ofs].x,y+primary_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2588
2589         gauge_index = (small_reticle?SML_RETICLE_SECONDARY:RETICLE_SECONDARY) + secondary_bm_num;
2590         PAGE_IN_GAUGE( gauge_index );
2591         gr_ubitmapm(x+secondary_offsets[ofs].x,y+secondary_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2592
2593 #ifdef OGL
2594         }
2595 #endif
2596 }
2597
2598 #ifdef NETWORK
2599 void hud_show_kill_list()
2600 {
2601         int n_players,player_list[MAX_NUM_NET_PLAYERS];
2602         int n_left,i,x0,x1,y,save_y,fth;
2603
2604 // ugly hack since placement of netgame players and kills is based off of
2605 // menuhires (which is always 1 for mac).  This throws off placement of
2606 // players in pixel double mode.
2607
2608         if (Show_kill_list_timer > 0)
2609         {
2610                 Show_kill_list_timer -= FrameTime;
2611                 if (Show_kill_list_timer < 0)
2612                         Show_kill_list = 0;
2613         }
2614         
2615         gr_set_curfont( GAME_FONT );
2616
2617         n_players = multi_get_kill_list(player_list);
2618
2619         if (Show_kill_list == 3)
2620                 n_players = 2;
2621
2622         if (n_players <= 4)
2623                 n_left = n_players;
2624         else
2625                 n_left = (n_players+1)/2;
2626
2627         //If font size changes, this code might not work right anymore 
2628         //Assert(GAME_FONT->ft_h==5 && GAME_FONT->ft_w==7);
2629
2630         fth = GAME_FONT->ft_h;
2631
2632         x0 = LHX(1); x1 = LHX(43);
2633
2634         if (Game_mode & GM_MULTI_COOP)
2635                 x1 = LHX(31);
2636
2637         save_y = y = grd_curcanv->cv_h - n_left*(fth+1);
2638
2639         if (Cockpit_mode == CM_FULL_COCKPIT) {
2640                 save_y = y -= LHX(6);
2641                 if (Game_mode & GM_MULTI_COOP)
2642                         x1 = LHX(33);
2643                 else
2644                         x1 = LHX(43);
2645         }
2646
2647         for (i=0;i<n_players;i++) {
2648                 int player_num;
2649                 char name[9];
2650                 int sw,sh,aw;
2651
2652                 if (i>=n_left) {
2653                         if (Cockpit_mode == CM_FULL_COCKPIT)
2654                                 x0 = grd_curcanv->cv_w - LHX(53);
2655                         else
2656                                 x0 = grd_curcanv->cv_w - LHX(60);
2657                         if (Game_mode & GM_MULTI_COOP)
2658                                 x1 = grd_curcanv->cv_w - LHX(27);
2659                         else
2660                                 x1 = grd_curcanv->cv_w - LHX(15);  // Right edge of name, change this for width problems
2661                         if (i==n_left)
2662                                 y = save_y;
2663
2664         if (Netgame.KillGoal || Netgame.PlayTimeAllowed)
2665            {
2666              x1-=LHX(18);
2667             // x0-=LHX(18);
2668            }
2669                 }
2670      else  if (Netgame.KillGoal || Netgame.PlayTimeAllowed)
2671            {
2672                                  x1 = LHX(43);
2673              x1-=LHX(18);
2674             // x0-=LHX(18);
2675            }
2676
2677         
2678                 if (Show_kill_list == 3)
2679                         player_num = i;
2680                 else
2681                         player_num = player_list[i];
2682
2683                 if (Show_kill_list == 1 || Show_kill_list==2)
2684                 {
2685                         int color;
2686
2687                         if (Players[player_num].connected != 1)
2688                                 gr_set_fontcolor(gr_getcolor(12, 12, 12), -1);
2689                         else if (Game_mode & GM_TEAM) {
2690                                 color = get_team(player_num);
2691                                 gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b),-1 );
2692                         }
2693                         else {
2694                                 color = player_num;
2695                                 gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b),-1 );
2696                         }
2697                 }       
2698
2699                 else 
2700                 {
2701                         gr_set_fontcolor(gr_getcolor(player_rgb[player_num].r,player_rgb[player_num].g,player_rgb[player_num].b),-1 );
2702                 }
2703
2704                 if (Show_kill_list == 3)
2705                         strcpy(name, Netgame.team_name[i]);
2706                 else
2707                         strcpy(name,Players[player_num].callsign);      // Note link to above if!!
2708                 gr_get_string_size(name,&sw,&sh,&aw);
2709                 while (sw > (x1-x0-LHX(2))) {
2710                         name[strlen(name)-1]=0;
2711                         gr_get_string_size(name,&sw,&sh,&aw);
2712                 }
2713                 gr_printf(x0,y,"%s",name);
2714
2715                 if (Show_kill_list==2)
2716                  {
2717                   if (Players[player_num].net_killed_total+Players[player_num].net_kills_total==0)
2718                         gr_printf (x1,y,"NA");
2719                   else
2720                    gr_printf (x1,y,"%d%%",(int)((float)((float)Players[player_num].net_kills_total/((float)Players[player_num].net_killed_total+(float)Players[player_num].net_kills_total))*100.0));           
2721                  }
2722                 else if (Show_kill_list == 3)   
2723                         gr_printf(x1,y,"%3d",team_kills[i]);
2724                 else if (Game_mode & GM_MULTI_COOP)
2725                         gr_printf(x1,y,"%-6d",Players[player_num].score);
2726       else if (Netgame.PlayTimeAllowed || Netgame.KillGoal)
2727          gr_printf(x1,y,"%3d(%d)",Players[player_num].net_kills_total,Players[player_num].KillGoalCount);
2728       else
2729                         gr_printf(x1,y,"%3d",Players[player_num].net_kills_total);
2730                         
2731                 y += fth+1;
2732
2733         }
2734
2735 #ifdef MACINTOSH
2736         MenuHires = 1;
2737 #endif
2738 }
2739 #endif
2740
2741 #ifndef RELEASE
2742 extern int Saving_movie_frames;
2743 #else
2744 #define Saving_movie_frames 0
2745 #endif
2746
2747 //returns true if viewer can see object
2748 int see_object(int objnum)
2749 {
2750         fvi_query fq;
2751         int hit_type;
2752         fvi_info hit_data;
2753
2754         //see if we can see this player
2755
2756         fq.p0                                   = &Viewer->pos;
2757         fq.p1                                   = &Objects[objnum].pos;
2758         fq.rad                                  = 0;
2759         fq.thisobjnum                   = Viewer - Objects;
2760         fq.flags                                = FQ_TRANSWALL | FQ_CHECK_OBJS;
2761         fq.startseg                             = Viewer->segnum;
2762         fq.ignore_obj_list      = NULL;
2763
2764         hit_type = find_vector_intersection(&fq, &hit_data);
2765
2766         return (hit_type == HIT_OBJECT && hit_data.hit_object == objnum);
2767 }
2768
2769 #ifdef NETWORK
2770 //show names of teammates & players carrying flags
2771 void show_HUD_names()
2772 {
2773         int show_team_names,show_all_names,show_flags,player_team;
2774         int p;
2775
2776         show_all_names = ((Newdemo_state == ND_STATE_PLAYBACK) || (Netgame.ShowAllNames && Show_reticle_name));
2777         show_team_names = (((Game_mode & GM_MULTI_COOP) || (Game_mode & GM_TEAM)) && Show_reticle_name);
2778         show_flags = (Game_mode & GM_CAPTURE) | (Game_mode & GM_HOARD);
2779
2780         if (! (show_all_names || show_team_names || show_flags))
2781                 return;
2782
2783         player_team = get_team(Player_num);
2784
2785         for (p=0;p<N_players;p++) {     //check all players
2786                 int objnum;
2787                 int show_name,has_flag;
2788
2789                 show_name = ((show_all_names && !(Players[p].flags & PLAYER_FLAGS_CLOAKED)) || (show_team_names && get_team(p)==player_team));
2790                 has_flag = (Players[p].connected && Players[p].flags & PLAYER_FLAGS_FLAG);
2791
2792                 if (Newdemo_state == ND_STATE_PLAYBACK) {
2793                         //if this is a demo, the objnum in the player struct is wrong,
2794                         //so we search the object list for the objnum
2795
2796                         for (objnum=0;objnum<=Highest_object_index;objnum++)
2797                                 if (Objects[objnum].type==OBJ_PLAYER && Objects[objnum].id == p)
2798                                         break;
2799                         if (objnum > Highest_object_index)              //not in list, thus not visible
2800                                 show_name = has_flag = 0;                               //..so don't show name
2801                 }
2802                 else
2803                         objnum = Players[p].objnum;
2804
2805                 if ((show_name || has_flag) && see_object(objnum)) {
2806                         g3s_point player_point;
2807
2808                         g3_rotate_point(&player_point,&Objects[objnum].pos);
2809
2810                         if (player_point.p3_codes == 0) {       //on screen
2811
2812                                 g3_project_point(&player_point);
2813
2814                                 if (! (player_point.p3_flags & PF_OVERFLOW)) {
2815                                         fix x,y;
2816                         
2817                                         x = player_point.p3_sx;
2818                                         y = player_point.p3_sy;
2819                         
2820                                         if (show_name) {                                // Draw callsign on HUD
2821                                                 char s[CALLSIGN_LEN+1];
2822                                                 int w, h, aw;
2823                                                 int x1, y1;
2824                                                 int color_num;
2825                         
2826                                                 color_num = (Game_mode & GM_TEAM)?get_team(p):p;
2827
2828                                                 sprintf(s, "%s", Players[p].callsign);
2829                                                 gr_get_string_size(s, &w, &h, &aw);
2830                                                 gr_set_fontcolor(gr_getcolor(player_rgb[color_num].r,player_rgb[color_num].g,player_rgb[color_num].b),-1 );
2831                                                 x1 = f2i(x)-w/2;
2832                                                 y1 = f2i(y)-h/2;
2833                                                 gr_string (x1, y1, s);
2834                                         }
2835                 
2836                                         if (has_flag) {                         // Draw box on HUD
2837                                                 fix dx,dy,w,h;
2838                         
2839                                                 dy = -fixmuldiv(fixmul(Objects[objnum].size,Matrix_scale.y),i2f(grd_curcanv->cv_h)/2,player_point.p3_z);
2840                                                 dx = fixmul(dy,grd_curscreen->sc_aspect);
2841         
2842                                                 w = dx/4;
2843                                                 h = dy/4;
2844         
2845                                                 if (Game_mode & GM_CAPTURE)
2846                                                         gr_setcolor((get_team(p) == TEAM_BLUE)?BM_XRGB(31,0,0):BM_XRGB(0,0,31));
2847                                                 else if (Game_mode & GM_HOARD)
2848                                                 {
2849                                                         if (Game_mode & GM_TEAM)
2850                                                                 gr_setcolor((get_team(p) == TEAM_RED)?BM_XRGB(31,0,0):BM_XRGB(0,0,31));
2851                                                         else
2852                                                                 gr_setcolor(BM_XRGB(0,31,0));
2853                                                 }
2854
2855                                                 gr_line(x+dx-w,y-dy,x+dx,y-dy);
2856                                                 gr_line(x+dx,y-dy,x+dx,y-dy+h);
2857         
2858                                                 gr_line(x-dx,y-dy,x-dx+w,y-dy);
2859                                                 gr_line(x-dx,y-dy,x-dx,y-dy+h);
2860         
2861                                                 gr_line(x+dx-w,y+dy,x+dx,y+dy);
2862                                                 gr_line(x+dx,y+dy,x+dx,y+dy-h);
2863         
2864                                                 gr_line(x-dx,y+dy,x-dx+w,y+dy);
2865                                                 gr_line(x-dx,y+dy,x-dx,y+dy-h);
2866                                         }
2867                                 }
2868                         }
2869                 }
2870         }
2871 }
2872 #endif
2873
2874
2875 extern int last_drawn_cockpit[2];
2876
2877 //draw all the things on the HUD
2878 void draw_hud()
2879 {
2880
2881 #if 0 //def OGL
2882         if (Cockpit_mode==CM_STATUS_BAR){
2883                 //ogl needs to redraw every frame, at least currently.
2884                 //              init_cockpit();
2885                         last_drawn_cockpit[0]=-1;
2886                         last_drawn_cockpit[1]=-1;
2887                                   init_gauges();
2888                 
2889                                //              vr_reset_display();
2890         }
2891 #endif
2892                                           
2893
2894         Line_spacing = GAME_FONT->ft_h + GAME_FONT->ft_h/4;
2895
2896         //      Show score so long as not in rearview
2897         if ( !Rear_view && Cockpit_mode!=CM_REAR_VIEW && Cockpit_mode!=CM_STATUS_BAR && !Saving_movie_frames) {
2898                 hud_show_score();
2899                 if (score_time)
2900                         hud_show_score_added();
2901         }
2902
2903         if ( !Rear_view && Cockpit_mode!=CM_REAR_VIEW && !Saving_movie_frames) 
2904          hud_show_timer_count();
2905
2906         //      Show other stuff if not in rearview or letterbox.
2907         if (!Rear_view && Cockpit_mode!=CM_REAR_VIEW) { // && Cockpit_mode!=CM_LETTERBOX) {
2908                 if (Cockpit_mode==CM_STATUS_BAR || Cockpit_mode==CM_FULL_SCREEN)
2909                         hud_show_homing_warning();
2910
2911                 if (Cockpit_mode==CM_FULL_SCREEN) {
2912                         hud_show_energy();
2913                         hud_show_shield();
2914                         hud_show_afterburner();
2915                         hud_show_weapons();
2916                         if (!Saving_movie_frames)
2917                                 hud_show_keys();
2918                         hud_show_cloak_invuln();
2919
2920                         if ( ( Newdemo_state==ND_STATE_RECORDING ) && ( Players[Player_num].flags != old_flags[VR_current_page] )) {
2921                                 newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
2922                                 old_flags[VR_current_page] = Players[Player_num].flags;
2923                         }
2924                 }
2925
2926                 #ifdef NETWORK
2927                 #ifndef RELEASE
2928                 if (!(Game_mode&GM_MULTI && Show_kill_list) && !Saving_movie_frames)
2929                         show_time();
2930                 #endif
2931                 #endif
2932                 if (Reticle_on && Cockpit_mode != CM_LETTERBOX && (!Use_player_head_angles))
2933                         show_reticle(0);
2934
2935 #ifdef NETWORK
2936                 show_HUD_names();
2937
2938                 if (Cockpit_mode != CM_LETTERBOX && Cockpit_mode != CM_REAR_VIEW)
2939                         hud_show_flag();
2940
2941                 if (Cockpit_mode != CM_LETTERBOX && Cockpit_mode != CM_REAR_VIEW)
2942                         hud_show_orbs();
2943
2944 #endif
2945                 if (!Saving_movie_frames)
2946                         HUD_render_message_frame();
2947
2948                 if (Cockpit_mode!=CM_STATUS_BAR && !Saving_movie_frames)
2949                         hud_show_lives();
2950
2951                 #ifdef NETWORK
2952                 if (Game_mode&GM_MULTI && Show_kill_list)
2953                         hud_show_kill_list();
2954                 #endif
2955         }
2956
2957         if (Rear_view && Cockpit_mode!=CM_REAR_VIEW) {
2958                 HUD_render_message_frame();
2959                 gr_set_curfont( GAME_FONT );
2960                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
2961                 if (Newdemo_state == ND_STATE_PLAYBACK)
2962                         gr_printf(0x8000,grd_curcanv->cv_h-14,TXT_REAR_VIEW);
2963                 else
2964                         gr_printf(0x8000,grd_curcanv->cv_h-10,TXT_REAR_VIEW);
2965         }
2966 }
2967
2968 extern short *BackBuffer;
2969
2970 //print out some player statistics
2971 void render_gauges()
2972 {
2973 #ifndef MACINTOSH
2974         static int old_display_mode = 0;
2975 #else
2976         static int old_display_mode = 1;
2977 #endif
2978         int energy = f2ir(Players[Player_num].energy);
2979         int shields = f2ir(Players[Player_num].shields);
2980         int cloak = ((Players[Player_num].flags&PLAYER_FLAGS_CLOAKED) != 0);
2981  
2982         Assert(Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR);
2983
2984 // check to see if our display mode has changed since last render time --
2985 // if so, then we need to make new gauge canvases.
2986
2987   
2988         if (old_display_mode != Current_display_mode) {
2989                 close_gauge_canvases();
2990                 init_gauge_canvases();
2991                 old_display_mode = Current_display_mode;
2992         }
2993
2994         if (shields < 0 ) shields = 0;
2995
2996         gr_set_current_canvas(get_current_game_screen());
2997         gr_set_curfont( GAME_FONT );
2998
2999         if (Newdemo_state == ND_STATE_RECORDING)
3000                 if (Players[Player_num].homing_object_dist >= 0)
3001                         newdemo_record_homing_distance(Players[Player_num].homing_object_dist);
3002
3003         if (Cockpit_mode == CM_FULL_COCKPIT)
3004                 draw_player_ship(cloak, old_cloak[VR_current_page], SHIP_GAUGE_X, SHIP_GAUGE_Y);
3005         else
3006                 draw_player_ship(cloak, old_cloak[VR_current_page], SB_SHIP_GAUGE_X, SB_SHIP_GAUGE_Y);
3007
3008         old_cloak[VR_current_page] = cloak;
3009
3010         if (Cockpit_mode == CM_FULL_COCKPIT) {
3011                 if (Newdemo_state == ND_STATE_RECORDING && (energy != old_energy[VR_current_page]))
3012                 {
3013                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
3014                         old_energy[VR_current_page] = energy;
3015                 }
3016                 draw_energy_bar(energy);
3017                 draw_numerical_display(shields, energy);
3018
3019                 if (Newdemo_state == ND_STATE_RECORDING && (Afterburner_charge != old_afterburner[VR_current_page]))
3020                 {
3021                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
3022                         old_afterburner[VR_current_page] = Afterburner_charge;
3023                 }
3024                 draw_afterburner_bar(Afterburner_charge);
3025
3026                 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
3027                         draw_invulnerable_ship();
3028                         old_shields[VR_current_page] = shields ^ 1;
3029                 } else {                // Draw the shield gauge
3030                         if (Newdemo_state == ND_STATE_RECORDING && (shields != old_shields[VR_current_page]))
3031                         {
3032                                 newdemo_record_player_shields(old_shields[VR_current_page], shields);
3033                                 old_shields[VR_current_page] = shields;
3034                         }
3035                         draw_shield_bar(shields);
3036                 }
3037                 draw_numerical_display(shields, energy);
3038         
3039                 if (Newdemo_state == ND_STATE_RECORDING && (Players[Player_num].flags != old_flags[VR_current_page]))
3040                 {
3041                         newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
3042                         old_flags[VR_current_page] = Players[Player_num].flags;
3043                 }
3044                 draw_keys();
3045
3046                 show_homing_warning();
3047
3048         } else if (Cockpit_mode == CM_STATUS_BAR) {
3049
3050                 if (Newdemo_state == ND_STATE_RECORDING && (energy != old_energy[VR_current_page]))
3051                 {
3052                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
3053                         old_energy[VR_current_page] = energy;
3054                 }
3055                 sb_draw_energy_bar(energy);
3056
3057                 if (Newdemo_state == ND_STATE_RECORDING && (Afterburner_charge != old_afterburner[VR_current_page]))
3058                 {
3059                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
3060                         old_afterburner[VR_current_page] = Afterburner_charge;
3061                 }
3062                 sb_draw_afterburner();
3063
3064                 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)
3065                 {
3066                         draw_invulnerable_ship();
3067                         old_shields[VR_current_page] = shields ^ 1;
3068                 } 
3069                 else
3070                 {               // Draw the shield gauge
3071                         if (Newdemo_state == ND_STATE_RECORDING && (shields != old_shields[VR_current_page]))
3072                         {
3073                                 newdemo_record_player_shields(old_shields[VR_current_page], shields);
3074                                 old_shields[VR_current_page] = shields;
3075                         }
3076                         sb_draw_shield_bar(shields);
3077                 }
3078                 sb_draw_shield_num(shields);
3079
3080                 if (Newdemo_state == ND_STATE_RECORDING && (Players[Player_num].flags != old_flags[VR_current_page]))
3081                 {
3082                         newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
3083                         old_flags[VR_current_page] = Players[Player_num].flags;
3084                 }
3085                 sb_draw_keys();
3086         
3087
3088                 // May want to record this in a demo...
3089                 if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
3090                 {
3091                         sb_show_lives();
3092                         old_lives[VR_current_page] = Players[Player_num].net_killed_total;
3093                 }
3094                 else
3095                 {
3096                         sb_show_lives();
3097                         old_lives[VR_current_page] = Players[Player_num].lives;
3098                 }
3099
3100                 if ((Game_mode&GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
3101                 {
3102                         sb_show_score();
3103                         old_score[VR_current_page] = Players[Player_num].net_kills_total;
3104                 }
3105                 else
3106                 {
3107                         sb_show_score();
3108                         old_score[VR_current_page] = Players[Player_num].score;
3109
3110                         //if (score_time)
3111                                 sb_show_score_added();
3112                 }
3113         }
3114
3115
3116         draw_weapon_boxes();
3117
3118 }
3119
3120 //      ---------------------------------------------------------------------------------------------------------
3121 //      Call when picked up a laser powerup.
3122 //      If laser is active, set old_weapon[0] to -1 to force redraw.
3123 void update_laser_weapon_info(void)
3124 {
3125         if (old_weapon[0][VR_current_page] == 0)
3126                 if (! (Players[Player_num].laser_level > MAX_LASER_LEVEL && old_laser_level[VR_current_page] <= MAX_LASER_LEVEL))
3127                         old_weapon[0][VR_current_page] = -1;
3128 }
3129
3130 extern int Game_window_y;
3131 void fill_background(void);
3132
3133 int SW_drawn[2], SW_x[2], SW_y[2], SW_w[2], SW_h[2];
3134
3135 //draws a 3d view into one of the cockpit windows.  win is 0 for left,
3136 //1 for right.  viewer is object.  NULL object means give up window
3137 //user is one of the WBU_ constants.  If rear_view_flag is set, show a
3138 //rear view.  If label is non-NULL, print the label at the top of the
3139 //window.
3140 void do_cockpit_window_view(int win,object *viewer,int rear_view_flag,int user,char *label)
3141 {
3142         grs_canvas window_canv;
3143         static grs_canvas overlap_canv;
3144         object *viewer_save = Viewer;
3145         static int overlap_dirty[2]={0,0};
3146         int boxnum;
3147         static int window_x,window_y;
3148         gauge_box *box;
3149         int rear_view_save = Rear_view;
3150         int w,h,dx;
3151
3152         box = NULL;
3153
3154         if (viewer == NULL) {                                                           //this user is done
3155
3156                 Assert(user == WBU_WEAPON || user == WBU_STATIC);
3157
3158                 if (user == WBU_STATIC && weapon_box_user[win] != WBU_STATIC)
3159                         static_time[win] = 0;
3160
3161                 if (weapon_box_user[win] == WBU_WEAPON || weapon_box_user[win] == WBU_STATIC)
3162                         return;         //already set
3163
3164                 weapon_box_user[win] = user;
3165
3166                 if (overlap_dirty[win]) {
3167                         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
3168                         fill_background();
3169                         overlap_dirty[win] = 0;
3170                 }
3171
3172                 return;
3173         }
3174
3175         update_rendered_data(win+1, viewer, rear_view_flag, user);
3176
3177         weapon_box_user[win] = user;                                            //say who's using window
3178                 
3179         Viewer = viewer;
3180         Rear_view = rear_view_flag;
3181
3182         if (Cockpit_mode == CM_FULL_SCREEN)
3183         {
3184
3185                 w = VR_render_buffer[0].cv_bitmap.bm_w/6;                       // hmm.  I could probably do the sub_buffer assigment for all macines, but I aint gonna chance it
3186
3187                 h = i2f(w) / grd_curscreen->sc_aspect;
3188
3189                 dx = (win==0)?-(w+(w/10)):(w/10);
3190
3191                 window_x = VR_render_buffer[0].cv_bitmap.bm_w/2+dx;
3192                 window_y = VR_render_buffer[0].cv_bitmap.bm_h-h-(h/10);
3193
3194                 //copy these vars so stereo code can get at them
3195                 SW_drawn[win]=1; SW_x[win] = window_x; SW_y[win] = window_y; SW_w[win] = w; SW_h[win] = h; 
3196
3197                 gr_init_sub_canvas(&window_canv,&VR_render_buffer[0],window_x,window_y,w,h);
3198         }
3199         else {
3200                 if (Cockpit_mode == CM_FULL_COCKPIT)
3201                         boxnum = (COCKPIT_PRIMARY_BOX)+win;
3202                 else if (Cockpit_mode == CM_STATUS_BAR)
3203                         boxnum = (SB_PRIMARY_BOX)+win;
3204                 else
3205                         goto abort;
3206
3207                 box = &gauge_boxes[boxnum];
3208
3209                 gr_init_sub_canvas(&window_canv,&VR_render_buffer[0],box->left,box->top,box->right-box->left+1,box->bot-box->top+1);
3210         }
3211
3212         gr_set_current_canvas(&window_canv);
3213         
3214         render_frame(0, win+1);
3215                 
3216         //      HACK! If guided missile, wake up robots as necessary.
3217         if (viewer->type == OBJ_WEAPON) {
3218                 // -- Used to require to be GUIDED -- if (viewer->id == GUIDEDMISS_ID)
3219                 wake_up_rendered_objects(viewer, win+1);
3220         }
3221
3222         if (label) {
3223                 gr_set_curfont( GAME_FONT );
3224                 if (Color_0_31_0 == -1)
3225                         Color_0_31_0 = gr_getcolor(0,31,0);
3226                 gr_set_fontcolor(Color_0_31_0, -1);
3227                 gr_printf(0x8000,2,label);
3228         }
3229
3230         if (user == WBU_GUIDED)
3231                 draw_guided_crosshair();
3232
3233         if (Cockpit_mode == CM_FULL_SCREEN) {
3234                 int small_window_bottom,big_window_bottom,extra_part_h;
3235                 
3236                 {
3237                         gr_setcolor(BM_XRGB(0,0,32));
3238                         gr_ubox(0,0,grd_curcanv->cv_bitmap.bm_w-1,grd_curcanv->cv_bitmap.bm_h-1);
3239                 }
3240
3241                 //if the window only partially overlaps the big 3d window, copy
3242                 //the extra part to the visible screen
3243
3244                 big_window_bottom = Game_window_y + Game_window_h - 1;
3245
3246                 if (window_y > big_window_bottom) {
3247
3248                         //the small window is completely outside the big 3d window, so
3249                         //copy it to the visible screen
3250
3251                         if (VR_screen_flags & VRF_USE_PAGING)
3252                                 gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
3253                         else
3254                                 gr_set_current_canvas(get_current_game_screen());
3255
3256                         gr_bitmap(window_x,window_y,&window_canv.cv_bitmap);
3257
3258                         overlap_dirty[win] = 1;
3259                 }
3260                 else {
3261
3262                         small_window_bottom = window_y + window_canv.cv_bitmap.bm_h - 1;
3263                         
3264                         extra_part_h = small_window_bottom - big_window_bottom;
3265
3266                         if (extra_part_h > 0) {
3267                         
3268                                 gr_init_sub_canvas(&overlap_canv,&window_canv,0,window_canv.cv_bitmap.bm_h-extra_part_h,window_canv.cv_bitmap.bm_w,extra_part_h);
3269
3270                                 if (VR_screen_flags & VRF_USE_PAGING)
3271                                         gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
3272                                 else
3273                                         gr_set_current_canvas(get_current_game_screen());
3274
3275                                 gr_bitmap(window_x,big_window_bottom+1,&overlap_canv.cv_bitmap);
3276                                 
3277                                 overlap_dirty[win] = 1;
3278                         }
3279                 }
3280         }
3281         else {
3282         
3283                 gr_set_current_canvas(get_current_game_screen());
3284                 copy_gauge_box(box,&VR_render_buffer[0].cv_bitmap);
3285         }
3286
3287         //force redraw when done
3288         old_weapon[win][VR_current_page] = old_ammo_count[win][VR_current_page] = -1;
3289
3290 abort:;
3291
3292         Viewer = viewer_save;
3293
3294         Rear_view = rear_view_save;
3295 }
3296
3297 #ifdef MACINTOSH
3298         void calculate_sub_view_window_bounds(int inSubWindowNum, TQARect* outBoundsRect)
3299         {
3300                 int             boxNumber               = 0;
3301                 gauge_box*      currentGaugeBox = NULL;
3302                 int w   = 0;
3303                 int h   = 0;
3304                 int dx  = 0;
3305                 int window_x = 0;
3306                 int window_y = 0;
3307
3308                 Assert(outBoundsRect);
3309                 Assert((inSubWindowNum == 0) || (inSubWindowNum == 1));
3310                 
3311                 switch (Cockpit_mode)
3312                 {
3313                         case CM_FULL_SCREEN:
3314                                 // note: this calculation is taken from do_cockpit_window_view for the full
3315                                 // screen mode case
3316                 
3317                                 w = (VR_render_buffer[0].cv_bitmap.bm_w) / 6;
3318                                 h = (i2f(w)) / (grd_curscreen->sc_aspect);
3319                 
3320                                 dx = (inSubWindowNum==0)?-(w+(w/10)):(w/10);
3321                 
3322                                 window_x = ((VR_render_buffer[0].cv_bitmap.bm_w) / 2) + dx;
3323                                 window_y = (VR_render_buffer[0].cv_bitmap.bm_h) - h - (h/10);
3324                                 
3325                                 outBoundsRect->top              = window_x;
3326                                 outBoundsRect->left             = window_y;
3327                                 outBoundsRect->bottom   = window_x + w;
3328                                 outBoundsRect->right    = window_y + h;
3329                                 break;
3330         
3331                         case CM_FULL_COCKPIT:
3332                         case CM_STATUS_BAR:
3333                                 if (inSubWindowNum == 0)
3334                                 {
3335                                         boxNumber = SB_PRIMARY_BOX;
3336                                 }
3337                                 else
3338                                 {
3339                                         boxNumber = SB_SECONDARY_BOX;
3340                                 }
3341                                 
3342                                 //boxNumber = (Current_display_mode * 4) + (Cockpit_mode * 2) + inSubWindowNum;
3343                                 currentGaugeBox = &gauge_boxes[boxNumber];
3344                                 Assert(currentGaugeBox);
3345                                 
3346                                 outBoundsRect->top              = currentGaugeBox->top;
3347                                 outBoundsRect->left             = currentGaugeBox->left;
3348                                 outBoundsRect->bottom   = currentGaugeBox->bot + 1;
3349                                 outBoundsRect->right    = currentGaugeBox->right + 1;
3350                                 
3351                                 break;
3352         
3353                         default:
3354                                 Int3();
3355                                 return;
3356                 }
3357         }
3358
3359 #endif
3360
3361