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