]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/techmenu.cpp
Freespace 1 support
[taylor/freespace2.git] / src / menuui / techmenu.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/MenuUI/TechMenu.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module that contains functions to drive the Tech Menu user interface
16  *
17  * $Log$
18  * Revision 1.6  2003/05/25 02:30:42  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.5  2002/06/17 06:33:09  relnev
22  * ryan's struct patch for gcc 2.95
23  *
24  * Revision 1.4  2002/06/09 04:41:22  relnev
25  * added copyright header
26  *
27  * Revision 1.3  2002/06/02 04:26:34  relnev
28  * warning cleanup
29  *
30  * Revision 1.2  2002/05/07 03:16:46  theoddone33
31  * The Great Newline Fix
32  *
33  * Revision 1.1.1.1  2002/05/03 03:28:09  root
34  * Initial import.
35  *
36  * 
37  * 43    11/02/99 3:22p Jefff
38  * translate ship names in tech room
39  * 
40  * 42    10/25/99 5:47p Jefff
41  * reassigned some xstr ids
42  * 
43  * 41    10/12/99 4:50p Jefff
44  * 
45  * 40    9/08/99 11:09a Dave
46  * Use stills for intel and weapon stuff in the techroom if animations
47  * aren't avaliable.
48  * 
49  * 39    9/05/99 11:19p Dave
50  * Made d3d texture cache much more safe. Fixed training scoring bug where
51  * it would backout scores without ever having applied them in the first
52  * place.
53  * 
54  * 38    9/03/99 11:19a Jefff
55  * fixed double render of intel descriptions
56  * 
57  * 37    9/03/99 1:32a Dave
58  * CD checking by act. Added support to play 2 cutscenes in a row
59  * seamlessly. Fixed super low level cfile bug related to files in the
60  * root directory of a CD. Added cheat code to set campaign mission # in
61  * main hall.
62  * 
63  * 36    9/01/99 5:12p Jefff
64  * Fixed bad scroll bug
65  * 
66  * 35    8/25/99 3:03p Jefff
67  * 'more' indicator, lotsa coord changes for new background,  disabling of
68  * buttons in trackball mode, list follows selected item when prev/next
69  * buttons used.
70  * 
71  * 34    8/24/99 8:55p Dave
72  * Make sure nondimming pixels work properly in tech menu.
73  * 
74  * 33    8/24/99 10:47a Jefff
75  * tech room weapon anims.  added tech anim field to weapons.tbl
76  * 
77  * 32    8/10/99 5:29p Jefff
78  * use new tech_title field in weapons array
79  * 
80  * 31    8/10/99 3:45p Jefff
81  * Put the smack down on the tech room.  Its all new, but tastefully done.
82  * 
83  * 30    8/09/99 5:53p Jefff
84  * 
85  * 29    8/02/99 10:27a Jefff
86  * removed a warning for the time being
87  * 
88  * 28    8/02/99 10:13a Jefff
89  * started scrubbing, waiting till after demo to continue
90  * 
91  * 27    7/28/99 1:02p Jefff
92  * Changed "Species" to "Intelligence" -- also changed in strings.tbl.
93  * 
94  * 26    7/26/99 4:33p Jordonr
95  * Don't need techroom palette
96  * 
97  * 25    7/20/99 1:49p Dave
98  * Peter Drake build. Fixed some release build warnings.
99  * 
100  * 24    7/19/99 2:13p Dave
101  * Added some new strings for Heiko.
102  * 
103  * 23    7/14/99 9:42a Dave
104  * Put in clear_color debug function. Put in base for 3dnow stuff / P3
105  * stuff
106  * 
107  * 22    6/16/99 4:06p Dave
108  * New pilot info popup. Added new draw-bitmap-as-poly function.
109  * 
110  * 21    5/09/99 8:57p Dave
111  * Final E3 build preparations.
112  * 
113  * 20    5/09/99 6:00p Dave
114  * Lots of cool new effects. E3 build tweaks.
115  * 
116  * 19    4/29/99 2:16p Neilk
117  * added a 2nd callback for slider so its model is not loaded on mouselock
118  * until mouse button is released
119  * 
120  * 18    4/26/99 5:05p Neilk
121  * updated to new artwork, added slider support
122  * 
123  * 17    4/25/99 3:02p Dave
124  * Build defines for the E3 build.
125  * 
126  * 16    4/23/99 12:01p Johnson
127  * Added SIF_HUGE_SHIP
128  * 
129  * 15    4/12/99 10:07p Dave
130  * Made network startup more forgiving. Added checkmarks to dogfight
131  * screen for players who hit commit.
132  * 
133  * 14    4/08/99 2:10a Dave
134  * Numerous bug fixes for the beta. Added builtin mission info for the
135  * beta.
136  * 
137  * 13    2/19/99 11:42a Dave
138  * Put in model rendering autocentering.
139  * 
140  * 12    2/01/99 5:55p Dave
141  * Removed the idea of explicit bitmaps for buttons. Fixed text
142  * highlighting for disabled gadgets.
143  * 
144  * 11    1/30/99 5:08p Dave
145  * More new hi-res stuff.Support for nice D3D textures.
146  * 
147  * 10    1/29/99 3:56p Neilk
148  * Converted tech_infos screens to multiresolution
149  * 
150  * 9     1/29/99 3:54p Neilk
151  * 
152  * 8     1/29/99 12:47a Dave
153  * Put in sounds for beam weapon. A bunch of interface screens (tech
154  * database stuff).
155  * 
156  * 7     11/30/98 1:07p Dave
157  * 16 bit conversion, first run.
158  * 
159  * 6     10/23/98 3:51p Dave
160  * Full support for tstrings.tbl and foreign languages. All that remains
161  * is to make it active in Fred.
162  * 
163  * 5     10/16/98 9:40a Andsager
164  * Remove ".h" files from model.h
165  * 
166  * 4     10/13/98 2:47p Andsager
167  * Remove reference to Tech_shivan_species_avail
168  * 
169  * 3     10/13/98 9:28a Dave
170  * Started neatening up freespace.h. Many variables renamed and
171  * reorganized. Added AlphaColors.[h,cpp]
172  * 
173  * 2     10/07/98 10:53a Dave
174  * Initial checkin.
175  * 
176  * 1     10/07/98 10:49a Dave
177  * 
178  * 67    9/21/98 10:02p Dave
179  * Last minute changes to techroom weapon/ship/species stuff.
180  * 
181  * 66    9/07/98 2:49p Dan
182  * Removed spurious Assert
183  * 
184  * 65    7/06/98 2:42p Hoffoss
185  * Fixed bug with weapons shown in tech database.
186  * 
187  * 64    6/10/98 11:48a Lawrance
188  * fix bug with trying to free NULL anims
189  * 
190  * 63    6/05/98 9:54a Lawrance
191  * OEM changes
192  * 
193  * 62    6/01/98 11:43a John
194  * JAS & MK:  Classified all strings for localization.
195  * 
196  * 61    5/26/98 11:10a Lawrance
197  * Fix bug where window controls get disabled when F1 pressed twice
198  * 
199  * 60    5/23/98 10:38p Lawrance
200  * Avoid doing a cfile refresh when running debug
201  * 
202  * 59    5/23/98 6:49p Lawrance
203  * Fix problems with refreshing the file list when a CD is inserted
204  * 
205  * 58    5/22/98 11:15a Lawrance
206  * Tweak how CD gets asked for
207  * 
208  * 57    5/22/98 1:06a Hoffoss
209  * Made Fred not use OLE.
210  * 
211  * 56    5/21/98 6:57p Lawrance
212  * Only ask for the CD once
213  * 
214  * 55    5/21/98 12:46a Hoffoss
215  * Made text offset reset when new description is loaded.
216  * 
217  * 54    5/20/98 9:46p John
218  * added code so the places in code that change half the palette don't
219  * have to clear the screen.
220  * 
221  * 53    5/20/98 3:28p Sandeep
222  * Fixed bug where in multi only discovered weapons show up, and in single
223  * all weapons showed up (backwards).
224  * 
225  * 52    5/20/98 2:11p Hoffoss
226  * Fixed some species description problems.
227  * 
228  * 51    5/18/98 6:45p Hoffoss
229  * Added species descriptions to species database in techroom.
230  * 
231  * 50    5/17/98 6:13p Hoffoss
232  * Fixed scrolling of info text area. 
233  *
234  * $NoKeywords: $
235  *
236  */
237
238 #include "gamesequence.h"
239 #include "techmenu.h"
240 #include "2d.h"
241 #include "3d.h"
242 #include "snazzyui.h"
243 #include "managepilot.h"
244 #include "key.h"
245 #include "bmpman.h"
246 #include "timer.h"
247 #include "missioncampaign.h"
248 #include "missionshipchoice.h"
249 #include "freespace.h"
250 #include "mainhallmenu.h"
251 #include "missionscreencommon.h"
252 #include "gamesnd.h"
253 #include "font.h"
254 #include "vecmat.h"
255 #include "mouse.h"
256 #include "uidefs.h"
257 #include "contexthelp.h"
258 #include "alphacolors.h"
259 #include "animplay.h"
260 #include "localize.h"
261 #include "lighting.h"
262
263 #define REVOLUTION_RATE 5.2f
264
265 #ifdef MAKE_FS1
266         #define NUM_BUTTONS 18
267 #else
268         #define NUM_BUTTONS     16
269 #endif
270 #define NUM_TABS                3
271 #define LIST_BUTTONS_MAX        41
272
273 #define SHIPS_DATA_MODE         (1<<0)
274 #define WEAPONS_DATA_MODE       (1<<1)
275 #define SPECIES_DATA_MODE       (1<<2)
276 #define WEAPONS_SPECIES_DATA_MODE       (WEAPONS_DATA_MODE | SPECIES_DATA_MODE)
277
278 #define SHIPS_DATA_TAB                                  0
279 #define WEAPONS_DATA_TAB                                1
280 #define INTEL_DATA_TAB                                  2
281 #define TECH_DATABASE_TAB                               3
282 #define SIMULATOR_TAB                                   4
283 #define CUTSCENES_TAB                                   5
284 #define CREDITS_TAB                                             6
285
286 #define SCROLL_LIST_UP                                  7
287 #define SCROLL_LIST_DOWN                                8
288 #define SCROLL_INFO_UP                                  9
289 #define SCROLL_INFO_DOWN                                10
290
291 #define PREV_ENTRY_BUTTON                               11
292 #define NEXT_ENTRY_BUTTON                               12
293
294 #define HELP_BUTTON                                             13
295 #define OPTIONS_BUTTON                                  14
296 #define EXIT_BUTTON                                             15
297
298 #ifdef MAKE_FS1
299 #define PREV_ENTRY_BUTTON2                              16
300 #define NEXT_ENTRY_BUTTON2                              17
301 #endif
302
303
304 #define REPEAT                                          (1<<0)
305 #define NO_MOUSE_OVER_SOUND     (1<<1)
306
307 // indicies for coords
308 #define SHIP_X_COORD 0 
309 #define SHIP_Y_COORD 1
310 #define SHIP_W_COORD 2
311 #define SHIP_H_COORD 3
312
313 // background filename for species
314 // note weapon filename is now same as ship filename
315 char *Tech_background_filename[GR_NUM_RESOLUTIONS] = {
316         "TechShipData",
317         "2_TechShipData"
318 };
319 char *Tech_mask_filename[GR_NUM_RESOLUTIONS] = {
320         "TechShipData-M",
321         "2_TechShipData-M"
322 };
323 #ifndef MAKE_FS1
324 char *Tech_slider_filename[GR_NUM_RESOLUTIONS] = {
325         "slider",
326         "2_slider"
327 };
328 #endif
329
330 #ifdef MAKE_FS1
331 // need the second background for FS1
332 char *Tech_data_background_filename = {
333         "TechData"
334 };
335 char *Tech_data_mask_filename = {
336         "TechData-M"
337 };
338 #endif
339
340 int Tech_list_coords[GR_NUM_RESOLUTIONS][4] = {
341         { // GR_640
342 #ifdef MAKE_FS1
343                 35, 131, 178, 198
344 #else
345                 27, 98, 161, 234
346 #endif
347         },
348         { // GR_1024
349                 43, 157, 253, 374
350         }
351 };
352
353 int Tech_ship_display_coords[GR_NUM_RESOLUTIONS][4] = {
354         { // GR_640
355 #ifdef MAKE_FS1
356                 234, 115, 390, 229
357 #else
358                 239, 98, 393, 222
359 #endif
360         },
361         { // GR_1024
362                 382, 158, 629, 355
363         }
364 };
365
366 int Tech_desc_coords[GR_NUM_RESOLUTIONS][4] = {
367         { // GR_640
368 #ifdef MAKE_FS1
369                 22, 362, 382, 64
370 #else
371                 29, 347, 365, 125
372 #endif
373         },
374         { // GR_1024
375                 47, 555, 584, 200
376         }
377 };
378
379 int Tech_ani_coords[GR_NUM_RESOLUTIONS][2] = {
380         { // GR_640
381 #ifdef MAKE_FS1
382                 424, 140
383 #else
384                 196, 115
385 #endif
386         },
387         { // GR_1024
388                 449, 245
389         }
390 };
391
392 #ifdef MAKE_FS1
393 int Tech_data_desc_coords[GR_NUM_RESOLUTIONS][4] = {
394         { // GR_640
395                 24, 139, 376, 281
396         },
397         { // GR_1024
398                 24, 182, 638, 528
399         }
400 };
401 #endif
402
403 #ifndef MAKE_FS1
404 int Tech_slider_coords[GR_NUM_RESOLUTIONS][4] = {
405         { // GR_640
406                 2, 118, 20, 194
407         },
408         { // GR_1024
409                 3, 190, 32, 310
410         }
411 };
412 #endif
413
414 // detail backup
415 int Tech_detail_backup;
416 int Tech_texture_backup;
417
418 #define MAX_TEXT_LINES          100
419 #define MAX_TEXT_LINE_LEN       256
420
421 struct techroom_buttons {
422         char *filename;
423         int x, y, xt, yt;
424         int hotspot;
425         int tab;
426         int flags;
427         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
428
429         techroom_buttons(char *name, int x1, int y1, int xt1, int yt1, int h, int t, int f = 0) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h), tab(t), flags(f) {}
430 };
431
432 static techroom_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
433         {       // GR_640
434 #ifdef MAKE_FS1
435                 techroom_buttons("TDB_04",      20,             429,    -1,     -1,     4,      -1),                                                    // ship data tab
436                 techroom_buttons("TDB_05",      70,             429,    -1,     -1,     5,      -1),                                                    // weapons data tab
437                 techroom_buttons("TDB_06",      147,    429,    -1,     -1,     6,      -1),                                                    // species data tab
438                 techroom_buttons("TDB_00",      0,              0,              -1,     -1,     0,      -1),                                                    // technical database tab
439                 techroom_buttons("TDB_01",      0,              19,             -1,     -1,     1,      -1),                                                    // mission simulator tab
440                 techroom_buttons("TDB_02",      0,              35,             -1,     -1,     2,      -1),                                                    // cutscenes tab
441                 techroom_buttons("TDB_03",      0,              56,             -1,     -1,     3,      -1),                                                    // credits tab
442                 techroom_buttons("TSB_16",      0,              206,    -1,     -1,     16,     SHIPS_DATA_MODE),                               // list up
443                 techroom_buttons("TSB_17",      0,              254,    -1,     -1,     17,     SHIPS_DATA_MODE),                               // list down
444                 techroom_buttons("TSB_18",      411,    351,    -1,     -1,     18,     SHIPS_DATA_MODE),                               // description up
445                 techroom_buttons("TSB_19",      411,    397,    -1,     -1,     19,     SHIPS_DATA_MODE),                               // description down
446 //              techroom_buttons("TDB_11",      558,    272,    -1,     -1,     11, WEAPONS_SPECIES_DATA_MODE),         // prev data entry
447 //              techroom_buttons("TDB_12",      606,    272,    -1,     -1,     12, WEAPONS_SPECIES_DATA_MODE),         // next data entry
448                 techroom_buttons("TSB_22",      477,    338,    -1,     -1,     22, SHIPS_DATA_MODE),                           // prev data entry
449                 techroom_buttons("TSB_23",      524,    338,    -1,     -1,     23, SHIPS_DATA_MODE),                           // next data entry
450                 techroom_buttons("TDB_13",  469,        425,    -1,     -1,     13, -1),                                                        // help
451                 techroom_buttons("TDB_14",  448,        452,    -1,     -1,     14, -1),                                                        // options
452                 techroom_buttons("TDB_15",      552,    411,    -1,     -1,     15, -1),                                                        // exit
453                 techroom_buttons("TDB_11",      477,    291,    -1,     -1,     11, WEAPONS_SPECIES_DATA_MODE),         // prev data entry
454                 techroom_buttons("TDB_12",      524,    291,    -1,     -1,     12, WEAPONS_SPECIES_DATA_MODE),         // next data entry
455 #else
456                 techroom_buttons("TDB_04",      406,    384,    447,    393,    4,      -1),                                                                                    // ship data tab
457                 techroom_buttons("TDB_05",      404,    418,    447,    429,    5,      -1),                                                                                    // weapons data tab
458                 techroom_buttons("TDB_06",      404,    447,    447,    461,    6,      -1),                                                                                    // species data tab
459                 techroom_buttons("TDB_00",      7,              3,              37,     7,              0,      -1),                                                                                    // technical database tab
460                 techroom_buttons("TDB_01",      7,              18,     37,     23,     1,      -1),                                                                                    // mission simulator tab
461                 techroom_buttons("TDB_02",      7,              34,     37,     38,     2,      -1),                                                                                    // cutscenes tab
462                 techroom_buttons("TDB_03",      7,              49,     37,     54,     3,      -1),                                                                                    // credits tab
463                 techroom_buttons("TDB_07",      1,              86,     -1,     -1,     7,      SHIPS_DATA_MODE, REPEAT),                               // prev data entry
464                 techroom_buttons("TDB_08",      1,              317,    -1,     -1,     8,      SHIPS_DATA_MODE, REPEAT),                               // next data entry
465                 techroom_buttons("TDB_09",      1,              406,    -1,     -1,     9,      SHIPS_DATA_MODE, REPEAT),                               // prev data entry
466                 techroom_buttons("TDB_10",      1,              447,    -1,     -1,     10,     SHIPS_DATA_MODE, REPEAT),                       // next data entry
467                 //techroom_buttons("TDB_11",    558,    272,    -1,     -1,     11,     WEAPONS_SPECIES_DATA_MODE),             // prev data entry
468                 //techroom_buttons("TDB_12",    606,    272,    -1,     -1,     12,     WEAPONS_SPECIES_DATA_MODE),             // next data entry
469                 techroom_buttons("TDB_11a",559, 323,    -1,     -1,     11,     SHIPS_DATA_MODE, REPEAT),                       // prev data entry
470                 techroom_buttons("TDB_12a",609, 323,    -1,     -1,     12,     SHIPS_DATA_MODE, REPEAT),                       // next data entry
471                 techroom_buttons("TDB_13",      533,    425,    500,    440,    13,     -1),                                                                            // help
472                 techroom_buttons("TDB_14",      533,    455,    479,    464,    14,     -1),                                                                            // options
473                 techroom_buttons("TDB_15a",571, 425,    588,    413,    15,     -1),                                                                            // exit         
474 #endif
475         }, 
476         {       // GR_1024
477                 techroom_buttons("2_TDB_04",    649,    614,    717,    630,    4,      -1),                                                                            // ship data tab
478                 techroom_buttons("2_TDB_05",    646,    669,    717,    687,    5,      -1),                                                                            // weapons data tab
479                 techroom_buttons("2_TDB_06",    646,    716,    717,    739,    6,      -1),                                                                            // species data tab
480                 techroom_buttons("2_TDB_00",    12,     5,              59,     12,     0,      -1),                                                                            // technical database tab
481                 techroom_buttons("2_TDB_01",    12,     31,     59,     37,     1,      -1),                                                                            // mission simulator tab
482                 techroom_buttons("2_TDB_02",    12,     56,     59,     62,     2,      -1),                                                                            // cutscenes tab
483                 techroom_buttons("2_TDB_03",    12,     81,     59,     88,     3,      -1),                                                                            // credits tab
484                 techroom_buttons("2_TDB_07",    1,              138,    -1,     -1,     7,      SHIPS_DATA_MODE, REPEAT),                       // prev data entry
485                 techroom_buttons("2_TDB_08",    1,              507,    -1,     -1,     8,      SHIPS_DATA_MODE, REPEAT),                       // next data entry
486                 techroom_buttons("2_TDB_09",    1,              649,    -1,     -1,     9,      SHIPS_DATA_MODE, REPEAT),                       // prev data entry
487                 techroom_buttons("2_TDB_10",    1,              716,    -1,     -1,     10,     SHIPS_DATA_MODE, REPEAT),               // next data entry
488 #ifdef MAKE_FS1
489                 // filler
490                 techroom_buttons("2_TDB_11",    893,    436,    -1,     -1,     11,     WEAPONS_SPECIES_DATA_MODE),     // prev data entry
491                 techroom_buttons("2_TDB_12",    970,    436,    -1,     -1,     12,     WEAPONS_SPECIES_DATA_MODE),     // next data entry
492 #endif
493                 techroom_buttons("2_TDB_11a",   895,    518,    -1,     -1,     11,     SHIPS_DATA_MODE, REPEAT),               // prev data entry
494                 techroom_buttons("2_TDB_12a",   974,    518,    -1,     -1,     12,     SHIPS_DATA_MODE, REPEAT),               // next data entry
495                 techroom_buttons("2_TDB_13",    854,    681,    800,    704,    13,     -1),                                                                    // help
496                 techroom_buttons("2_TDB_14",    854,    728,    780,    743,    14,     -1),                                                                    // options
497                 techroom_buttons("2_TDB_15a",   914,    681,    930,    660,    15,     -1),                                                                    // exit         
498         }, 
499 };
500
501 static UI_WINDOW Ui_window;
502 static UI_BUTTON View_window;
503 //static int Background_bitmap;
504 #ifdef MAKE_FS1
505 static int Tech_data_background_bitmap;
506 #endif
507 static int Tech_background_bitmap;
508 static int Tab = 0;
509 // static int List_size;
510 static int List_offset;
511 static int Select_tease_line;
512 static int Trackball_mode = 1;
513 static int Trackball_active = 0;
514 static matrix Techroom_ship_orient = IDENTITY_MATRIX;
515 // static int Tech_room_ask_for_cd;
516
517 static int Text_size;
518 static int Text_offset;
519 static int Text_line_size[MAX_TEXT_LINES];
520 static char *Text_lines[MAX_TEXT_LINES];
521
522 static int Cur_entry;                           // this is the current entry selected, using entry indexing
523 static int Cur_entry_index;             // this is the current entry selected, using master list indexing
524 static int Techroom_ship_modelnum;
525 static float Techroom_ship_rot;
526 static UI_BUTTON List_buttons[LIST_BUTTONS_MAX];  // buttons for each line of text in list
527 static int Anim_playing_id = -1;
528 static anim_instance *Cur_anim_instance = NULL;
529 //static int Palette_bmp;
530 #ifdef MAKE_FS1
531 static int ShipWin01;
532 static int ShipWin02;
533 static int ShipWin03;
534 static int ShipWin04;
535 #endif
536 static ubyte Palette[768];
537 static char Palette_name[128];
538
539 static int Ships_loaded = 0;
540 static int Weapons_loaded = 0;
541 static int Intel_loaded = 0;
542
543 // out entry data struct & vars
544 typedef struct {
545         int     index;          // index into the master table that its in (ie Ship_info[])
546         char* name;                     // ptr to name string
547         char* desc;                     // ptr to description string
548         anim* animation;        // ptr to the animation
549         int     bitmap;         // bitmap handle
550         int     has_anim;       // flag to indicate the presence of an animation for this item
551 } tech_list_entry;
552
553 static tech_list_entry Ship_list[MAX_SHIP_TYPES];
554 static int Ship_list_size = 0;
555 static tech_list_entry Weapon_list[MAX_WEAPON_TYPES];
556 static int Weapon_list_size = 0;
557 static tech_list_entry Intel_list[MAX_INTEL_ENTRIES];
558 static int Intel_list_size = 0;
559 static tech_list_entry *Current_list;                                                           // points to currently valid display list
560 static int Current_list_size = 0;
561
562 #ifndef MAKE_FS1
563 // slider stuff
564 static UI_SLIDER2 Tech_slider;
565 #endif
566
567 //XSTR:OFF
568 #ifdef MAKE_FS1
569 static char *Intel_anim_filenames[MAX_INTEL_ENTRIES] = {
570         "tech_tpilot.ani",
571         "tech_vasudan.ani",
572         "tech_shivan.ani",
573 };
574 #endif
575 //XSTR:ON
576
577 // Intelligence master data structs (these get inited @ game startup from species.tbl)
578 intel_data Intel_info[MAX_INTEL_ENTRIES];
579 int Intel_info_size = 0;
580
581 // some prototypes to make you happy
582 int techroom_load_ani(anim **animpp, char *name);
583 void tech_common_render();
584 void techroom_start_anim();
585 void tech_scroll_list_up();
586 void tech_scroll_list_down();
587 #ifdef MAKE_FS1
588 void techroom_data_init();
589 void techroom_tab_setup(int set_palette);
590 #endif
591
592
593
594
595 ////////////////////////////////////////////////////
596 // like, functions and stuff
597
598 void techroom_init_desc(char *src, int w)
599 {
600         Text_size = Text_offset = 0;
601         if (!src) {
602                 return;
603         }
604
605         Text_size = split_str(src, w, Text_line_size, Text_lines, MAX_TEXT_LINES);
606         Assert(Text_size >= 0 && Text_size < MAX_TEXT_LINES);
607 }
608
609 void techroom_select_new_entry()
610 {
611         Assert(Current_list != NULL);
612         if (Current_list == NULL) return;
613
614         Cur_entry_index = Current_list[Cur_entry].index;
615
616         // if we are in the ships tab, load the ship model
617         if (Tab == SHIPS_DATA_TAB) {
618                 ship_info *sip = &Ship_info[Cur_entry_index];
619
620 #ifdef MULTIPLAYER_BETA_BUILD
621                 // don't load supercaps in the beta
622                 if((sip->flags & SIF_SUPERCAP) || (sip->flags & SIF_DRYDOCK)){
623                         Techroom_ship_modelnum = -1;
624                 } else {
625                         Techroom_ship_modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
626                 }
627
628                 // page in ship textures properly (takes care of nondimming pixels)
629                 model_page_in_textures(Techroom_ship_modelnum, Cur_entry_index);
630 #else
631                 Techroom_ship_modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
632
633                 // page in ship textures properly (takes care of nondimming pixels)
634                 model_page_in_textures(Techroom_ship_modelnum, Cur_entry_index);
635 #endif
636         } else {
637                 Techroom_ship_modelnum = -1;
638                 Trackball_mode = 0;
639         }
640
641 //      Techroom_ship_rot = PI;
642
643 #ifdef MAKE_FS1
644         if (Tab == (WEAPONS_DATA_TAB || INTEL_DATA_TAB)){
645                 techroom_init_desc(Current_list[Cur_entry].desc, Tech_data_desc_coords[gr_screen.res][SHIP_W_COORD]);
646         } else {
647                 techroom_init_desc(Current_list[Cur_entry].desc, Tech_desc_coords[gr_screen.res][SHIP_W_COORD]);
648         }
649 #else
650         techroom_init_desc(Current_list[Cur_entry].desc, Tech_desc_coords[gr_screen.res][SHIP_W_COORD]);
651 #endif
652         techroom_start_anim();
653 }
654
655 // write out the current description in the bottom window
656 void techroom_render_desc(int xo, int yo, int h)
657 {
658         int y, z, len, font_height;
659         char line[MAX_TEXT_LINE_LEN + 1];
660
661         font_height = gr_get_font_height();
662
663         y = 0;
664         z = Text_offset;
665         while (y + font_height <= h) {
666                 if (z >= Text_size){
667                         break;
668                 }
669
670                 len = Text_line_size[z];
671                 if (len > MAX_TEXT_LINE_LEN){
672                         len = MAX_TEXT_LINE_LEN;
673                 }
674
675                 strncpy(line, Text_lines[z], len);
676                 line[len] = 0;
677                 gr_string(xo, yo + y, line);
678
679                 y += font_height;
680                 z++;
681         }
682
683         // maybe output 'more' indicator
684 #ifndef MAKE_FS1   // not used in original
685         if ( z < Text_size ) {
686                 // can be scrolled down
687                 int more_txt_x = Tech_desc_coords[gr_screen.res][0] + (Tech_desc_coords[gr_screen.res][2]/2) - 10;      // FIXME should move these to constants since they dont move
688                 int more_txt_y = Tech_desc_coords[gr_screen.res][1] + Tech_desc_coords[gr_screen.res][3];                               // located below brief text, centered
689                 int w, h;
690                 gr_get_string_size(&w, &h, XSTR("more", 1469), strlen(XSTR("more", 1469)));
691                 gr_set_color_fast(&Color_black);
692                 gr_rect(more_txt_x-2, more_txt_y, w+3, h);
693                 gr_set_color_fast(&Color_red);
694                 gr_string(more_txt_x, more_txt_y, XSTR("more", 1469));  // base location on the input x and y?
695         }
696 #endif
697
698 }
699
700 // new version of weapons
701 void techroom_weapons_render2(float frametime)
702 {
703         // render common stuff
704 #ifndef MAKE_FS1
705         tech_common_render();
706 #else
707         // render description in its box
708         gr_set_color_fast(&Color_text_normal);
709         techroom_render_desc(Tech_data_desc_coords[gr_screen.res][SHIP_X_COORD], Tech_data_desc_coords[gr_screen.res][SHIP_Y_COORD], Tech_data_desc_coords[gr_screen.res][SHIP_H_COORD]);
710 #endif
711
712         // render the animation
713         {
714                 // JAS: This code is hacked to allow the animation to use all 256 colors
715                 extern int Palman_allow_any_color;
716                 Palman_allow_any_color = 1;
717                 anim_render_all(0, frametime);
718                 Palman_allow_any_color = 0;
719         }
720
721         // if our active item has a bitmap instead of an animation, draw it
722         if((Cur_entry > 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
723                 gr_set_bitmap(Current_list[Cur_entry].bitmap);
724                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
725         }
726 }
727
728 // renders the stuff common to all 3 tech room tabs
729 void tech_common_render()
730 {
731         char buf[256];
732         int y, z, font_height;
733
734         // render description in its box
735         gr_set_color_fast(&Color_text_normal);
736         techroom_render_desc(Tech_desc_coords[gr_screen.res][SHIP_X_COORD], Tech_desc_coords[gr_screen.res][SHIP_Y_COORD], Tech_desc_coords[gr_screen.res][SHIP_H_COORD]);
737
738         font_height = gr_get_font_height();
739
740         // draw the list of entries
741         y = 0;
742         z = List_offset;
743         while (y + font_height <= Tech_list_coords[gr_screen.res][SHIP_H_COORD]) {
744                 if (z >= Current_list_size) {
745                         break;
746                 }
747
748                 if (z == Cur_entry) {
749                         gr_set_color_fast(&Color_text_selected);
750                 } else if (z == Select_tease_line) {
751                         gr_set_color_fast(&Color_text_subselected);
752                 } else {
753                         gr_set_color_fast(&Color_text_normal);
754                 }
755
756                 strcpy(buf, Current_list[z].name);
757                 if (Lcl_gr) {
758                         lcl_translate_ship_name(buf);
759                 }
760
761                 gr_force_fit_string(buf, 255, Tech_list_coords[gr_screen.res][SHIP_W_COORD]);
762                 gr_string(Tech_list_coords[gr_screen.res][SHIP_X_COORD], Tech_list_coords[gr_screen.res][SHIP_Y_COORD] + y, buf);
763
764                 List_buttons[z - List_offset].update_dimensions(Tech_list_coords[gr_screen.res][SHIP_X_COORD], Tech_list_coords[gr_screen.res][SHIP_Y_COORD] + y, Tech_list_coords[gr_screen.res][SHIP_W_COORD], font_height);
765                 List_buttons[z - List_offset].enable(1);
766
767                 y += font_height;
768                 z++;
769         }
770
771         // disable the rest of the list buttons
772         z -= List_offset;
773         while (z < LIST_BUTTONS_MAX) {
774                 List_buttons[z++].disable();
775         }
776 }
777
778 void techroom_ships_render(float frametime)
779 {
780         // render all the common stuff
781         tech_common_render();
782
783         // now render the trackball ship, which is unique to the ships tab
784         float rev_rate;
785         angles rot_angles, view_angles;
786         int z;
787         ship_info *sip = &Ship_info[Cur_entry_index];
788
789         // get correct revolution rate
790         rev_rate = REVOLUTION_RATE;
791         z = sip->flags;
792         if (z & SIF_BIG_SHIP) {
793                 rev_rate *= 1.7f;
794         }
795         if (z & SIF_HUGE_SHIP) {
796                 rev_rate *= 3.0f;
797         }
798
799         // rotate the ship as much as required for this frame
800         Techroom_ship_rot += PI2 * frametime / rev_rate;
801         while (Techroom_ship_rot > PI2){
802                 Techroom_ship_rot -= PI2;       
803         }
804
805         // turn off fogging
806         gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
807
808         //      reorient ship
809         if (Trackball_active) {
810                 int dx, dy;
811                 matrix mat1, mat2;
812
813                 if (Trackball_active) {
814                         mouse_get_delta(&dx, &dy);
815                         if (dx || dy) {
816                                 vm_trackball(-dx, -dy, &mat1);
817                                 vm_matrix_x_matrix(&mat2, &mat1, &Techroom_ship_orient);
818                                 Techroom_ship_orient = mat2;
819                         }
820                 }
821
822         } else {
823                 // setup stuff needed to render the ship
824                 view_angles.p = -0.6f;
825                 view_angles.b = 0.0f;
826                 view_angles.h = 0.0f;
827                 vm_angles_2_matrix(&Techroom_ship_orient, &view_angles);
828
829                 rot_angles.p = 0.0f;
830                 rot_angles.b = 0.0f;
831                 rot_angles.h = Techroom_ship_rot;
832                 vm_rotate_matrix_by_angles(&Techroom_ship_orient, &rot_angles);
833         }
834
835         gr_set_clip(Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD]);        
836
837         // render the ship
838 #ifdef MULTIPLAYER_BETA_BUILD
839         if((sip->flags & SIF_SUPERCAP) || (sip->flags & SIF_DRYDOCK)) {
840                 gr_set_color_fast(&Color_bright);
841                 gr_string(Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD] + 50, NOX("No soup for you!"));
842         } else {
843                 g3_start_frame(1);
844
845                 g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
846
847                 // lighting for techroom
848                 light_reset();
849                 vector light_dir = vmd_zero_vector;
850                 light_dir.y = 1.0f;     
851                 light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
852                 // light_filter_reset();
853                 light_rotate_all();
854                 // lighting for techroom
855
856                 model_clear_instance(Techroom_ship_modelnum);
857                 model_set_detail_level(0);
858                 model_render(Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER);
859
860                 g3_end_frame();
861         }
862 #else
863         g3_start_frame(1);
864
865         g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
866
867         // lighting for techroom
868         light_reset();
869         vector light_dir = vmd_zero_vector;
870         light_dir.xyz.y = 1.0f;
871         light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
872         // light_filter_reset();
873         light_rotate_all();
874         // lighting for techroom
875
876         model_clear_instance(Techroom_ship_modelnum);
877         model_set_detail_level(0);
878         model_render(Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector, MR_LOCK_DETAIL | MR_AUTOCENTER);
879
880         g3_end_frame();
881 #endif
882
883         gr_reset_clip();
884 }
885
886 // select previous entry in current list
887 void tech_prev_entry()
888 {
889         Cur_entry--;
890         if (Cur_entry < 0) {
891                 Cur_entry = Current_list_size - 1;
892
893                 // scroll to end of list
894                 List_offset = Cur_entry - Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() + 1;
895                 if (List_offset < 0) {
896                         // this happens when there are not enough items to scroll
897                         List_offset = 0;
898                 }
899 #ifndef MAKE_FS1
900                 Tech_slider.force_currentItem(Tech_slider.get_numberItems());
901 #endif
902         } else {
903                 // maybe adjust list position by 1
904                 if (List_offset > Cur_entry) {
905                         tech_scroll_list_up();
906 #ifndef MAKE_FS1
907                         Tech_slider.forceUp();
908 #endif
909                 }
910         }
911
912         techroom_select_new_entry();
913         gamesnd_play_iface(SND_SCROLL);
914 }
915
916 // select next entry in current list
917 void tech_next_entry()
918 {
919         Cur_entry++;
920         if (Cur_entry >= Current_list_size) {
921                 Cur_entry = 0;
922
923                 // scroll to beginning of list
924                 List_offset = 0;
925 #ifndef MAKE_FS1
926                 Tech_slider.force_currentItem(Cur_entry);
927 #endif
928         } else {
929                 // maybe adjust list position by 1
930                 if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() <= Cur_entry) {
931                         tech_scroll_list_down();
932 #ifndef MAKE_FS1
933                         Tech_slider.forceDown();
934 #endif
935                 }
936         }
937
938         techroom_select_new_entry();
939         gamesnd_play_iface(SND_SCROLL);
940 }
941
942 void tech_scroll_info_up()
943 {
944         if (Text_offset) {
945                 Text_offset--;
946                 gamesnd_play_iface(SND_SCROLL);
947         } else {
948                 gamesnd_play_iface(SND_GENERAL_FAIL);
949         }
950 }
951
952 void tech_scroll_info_down()
953 {
954         int h;
955
956         if (Tab == SHIPS_DATA_TAB){
957                 h = Tech_desc_coords[gr_screen.res][SHIP_H_COORD];
958         } else {
959                 h = Tech_desc_coords[gr_screen.res][3];
960         }
961
962         if (Text_offset + h / gr_get_font_height() < Text_size) {
963                 Text_offset++;
964                 gamesnd_play_iface(SND_SCROLL);
965         } else {
966                 gamesnd_play_iface(SND_GENERAL_FAIL);
967         }
968 }
969
970 void tech_scroll_list_up()
971 {
972         //int last;
973
974         if (List_offset > 0) {
975                 List_offset--;
976                 //last = List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() - 1;
977                 gamesnd_play_iface(SND_SCROLL);
978         } else {
979                 gamesnd_play_iface(SND_GENERAL_FAIL);
980         }
981 }
982
983 void tech_scroll_list_down()
984 {
985         if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() < Current_list_size) {
986                 List_offset++;
987                 gamesnd_play_iface(SND_SCROLL);
988         } else {
989                 gamesnd_play_iface(SND_GENERAL_FAIL);
990         }
991 }
992
993 // this doesnt do a damn thing...
994 void tech_ship_scroll_capture()
995 {
996         techroom_select_new_entry();
997 }
998
999
1000 // this is obsolete - see techroom_weapons_render2(...)
1001 void techroom_weapons_render(float frametime)
1002 {
1003         gr_set_color_fast(&Color_text_normal);
1004         techroom_render_desc(Tech_desc_coords[gr_screen.res][0], Tech_desc_coords[gr_screen.res][1], Tech_desc_coords[gr_screen.res][3]);
1005
1006         {
1007                 // JAS: This code is hacked to allow the animation to use all 256 colors
1008                 extern int Palman_allow_any_color;
1009                 Palman_allow_any_color = 1;
1010                 anim_render_all(0, frametime);
1011                 Palman_allow_any_color = 0;
1012         }
1013
1014         // if our active item has a bitmap instead of an animation, draw it
1015         if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
1016                 gr_set_bitmap(Current_list[Cur_entry].bitmap);
1017                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1018         }
1019 }
1020
1021 void techroom_intel_render(float frametime)
1022 {
1023 #ifndef MAKE_FS1
1024         tech_common_render();
1025 #else
1026         // render description in its box
1027         gr_set_color_fast(&Color_text_normal);
1028         techroom_render_desc(Tech_data_desc_coords[gr_screen.res][SHIP_X_COORD], Tech_data_desc_coords[gr_screen.res][SHIP_Y_COORD], Tech_data_desc_coords[gr_screen.res][SHIP_H_COORD]);
1029 #endif
1030
1031         {
1032                 // JAS: This code is hacked to allow the animation to use all 256 colors
1033                 extern int Palman_allow_any_color;
1034                 Palman_allow_any_color = 1;
1035                 anim_render_all(0, frametime);
1036                 Palman_allow_any_color = 0;
1037         }
1038
1039         // if our active item has a bitmap instead of an animation, draw it
1040         if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
1041                 gr_set_bitmap(Current_list[Cur_entry].bitmap);
1042                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1043         }
1044 }
1045
1046 void techroom_stop_anim(int id)
1047 {
1048         if (Cur_anim_instance && (id != Anim_playing_id)) {
1049                 anim_stop_playing(Cur_anim_instance);
1050                 Cur_anim_instance = NULL;
1051         }
1052 }
1053
1054 void techroom_start_anim()
1055 {
1056         int id;
1057         anim *animp;
1058         anim_play_struct aps;
1059
1060         if (Cur_entry < 0) {
1061                 techroom_stop_anim(-1);
1062                 Anim_playing_id = -1;
1063         }
1064
1065         if (Tab == WEAPONS_DATA_TAB) {
1066                 id = Cur_entry;
1067         } else {
1068                 id = Cur_entry + 2000;                                          // this offset is arbitrary?
1069         }
1070
1071         techroom_stop_anim(id);
1072
1073         // if we actually have an animation
1074         if(Current_list[Cur_entry].animation != NULL){
1075                 animp = Current_list[Cur_entry].animation;      
1076
1077                 if (id != Anim_playing_id) {
1078                         Anim_playing_id = -1;
1079                         if (animp) {
1080                                 anim_play_init(&aps, animp, Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1081                                 aps.looped = 1;
1082                                 Cur_anim_instance = anim_play(&aps);
1083                                 Anim_playing_id = id;
1084                         }
1085
1086                         if (animp) {
1087                                 memcpy(Palette, animp->palette, 384);
1088                                 gr_set_palette(animp->name, Palette, 1);
1089                         }
1090                 }
1091         }
1092 }
1093
1094
1095 void techroom_change_tab(int num)
1096 {
1097         int i, multi = 0, mask, font_height, max_num_entries_viewable;  
1098
1099         Tab = num;
1100         // Assert(Current_list_size >= 0);
1101         List_offset = 0;
1102         Cur_entry = 0;
1103         multi = Player->flags & PLAYER_FLAGS_IS_MULTI;
1104
1105         for (i=0; i<LIST_BUTTONS_MAX; i++){
1106                 List_buttons[i].disable();
1107         }
1108
1109         // disable some stuff in multiplayer
1110         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1111                 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1112                 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1113         }
1114
1115         switch (Tab) {
1116                 case SHIPS_DATA_TAB:
1117                         mask = multi ? SIF_IN_TECH_DATABASE_M : SIF_IN_TECH_DATABASE;
1118                         
1119                         // load ship info if necessary
1120                         if (Ships_loaded == 0) {
1121                                 Ship_list_size = 0;
1122                                 for (i=0; i<Num_ship_types; i++) {
1123 #ifndef MAKE_FS1
1124                                         if (Ship_info[i].flags & mask) {
1125 #else
1126                                         // make sure it has a description before displaying
1127                                         if ((Ship_info[i].flags && mask) && (Ship_info[i].tech_desc)) {
1128 #endif
1129                                                 // this ship should be displayed, fill out the entry struct
1130                                                 Ship_list[Ship_list_size].bitmap = -1;
1131                                                 Ship_list[Ship_list_size].index = i;
1132                                                 Ship_list[Ship_list_size].animation = NULL;                     // no anim for ships
1133                                                 Ship_list[Ship_list_size].has_anim = 0;                         // no anim for ships
1134                                                 Ship_list[Ship_list_size].name = Ship_info[i].name;
1135                                                 Ship_list[Ship_list_size].desc = Ship_info[i].tech_desc;
1136                                                 Ship_list_size++;
1137                                         }                               
1138                                 }
1139                                 Ships_loaded = 1;
1140                         }
1141
1142                         Current_list = Ship_list;
1143                         Current_list_size = Ship_list_size;
1144
1145                         font_height = gr_get_font_height();
1146                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1147 #ifndef MAKE_FS1
1148                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1149 #endif
1150
1151                         // no anim to start here
1152                         break;
1153
1154                 case WEAPONS_DATA_TAB:
1155 #ifdef MAKE_FS1
1156                         techroom_data_init();
1157 #endif
1158                         // load weapon info & anims if necessary
1159                         if (Weapons_loaded == 0) {
1160                                 Weapon_list_size = 0;
1161                                 mask = multi ? WIF_PLAYER_ALLOWED : WIF_IN_TECH_DATABASE;
1162
1163                                 for (i=0; i<MAX_WEAPON_TYPES; i++) {
1164                                         if (Weapon_info[i].wi_flags & mask) { 
1165 #ifndef MAKE_FS1
1166                                                 // note: hack here to exclude dogfight weapons -- dont put weapon in if it has same description as pvs weapon
1167                                                 if ((Weapon_list_size > 0) && (!strcmp(Weapon_info[i].tech_desc, Weapon_list[Weapon_list_size-1].desc))) {
1168 #else
1169                                                 // exclude entries with no description, basically the same as above but helps get rid of special cases as well
1170                                                 if ((Weapon_list_size > 0) && (!Weapon_info[i].tech_desc)) {
1171 #endif
1172                                                         continue;
1173                                                 }
1174
1175                                                 // we have a weapon that should be in the tech db, so fill out the entry struct
1176                                                 Weapon_list[Weapon_list_size].index = i;
1177                                                 Weapon_list[Weapon_list_size].desc = Weapon_info[i].tech_desc;
1178                                                 Weapon_list[Weapon_list_size].has_anim = 1;
1179                                                 Weapon_list[Weapon_list_size].name = Weapon_info[i].tech_title;
1180                                                 Weapon_list[Weapon_list_size].bitmap = -1;
1181                                                 if (Weapon_list[Weapon_list_size].name[0] == 0) {
1182                                                         Weapon_list[Weapon_list_size].name = Weapon_info[i].name;
1183                                                 }
1184
1185 #ifdef MAKE_FS1
1186                                                 // figure out the animation based on weapon name
1187                                                 if (!strcmp(Weapon_info[i].name, "ML-16 Laser")) {
1188                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_ML16.ani", NAME_LENGTH);
1189                                                 } else if (!strcmp(Weapon_info[i].name, "Disruptor")) {
1190                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Disruptor.ani", NAME_LENGTH);
1191                                                 } else if (!strcmp(Weapon_info[i].name, "D-Advanced")) {
1192                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_DAdvanced.ani", NAME_LENGTH);
1193                                                 } else if (!strcmp(Weapon_info[i].name, "Avenger")) {
1194                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Avenger.ani", NAME_LENGTH);
1195                                                 } else if (!strcmp(Weapon_info[i].name, "Flail")) {
1196                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Flail.ani", NAME_LENGTH);
1197                                                 } else if (!strcmp(Weapon_info[i].name, "Prometheus")) {
1198                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Prometheus.ani", NAME_LENGTH);
1199                                                 } else if (!strcmp(Weapon_info[i].name, "Banshee")) {
1200                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Banshee.ani", NAME_LENGTH);
1201                                                 } else if (!strcmp(Weapon_info[i].name, "MX-50")) {
1202                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_MX50.ani", NAME_LENGTH);
1203                                                 } else if (!strcmp(Weapon_info[i].name, "D-Missile")) {
1204                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_DisruptorMissile.ani", NAME_LENGTH);
1205                                                 } else if (!strcmp(Weapon_info[i].name, "Fury")) {
1206                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Fury.ani", NAME_LENGTH);
1207                                                 } else if (!strcmp(Weapon_info[i].name, "Hornet")) {
1208                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Hornet.ani", NAME_LENGTH);
1209                                                 } else if (!strcmp(Weapon_info[i].name, "Interceptor")) {
1210                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Interceptor.ani", NAME_LENGTH);
1211                                                 } else if (!strcmp(Weapon_info[i].name, "Phoenix V")) {
1212                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Phoenix.ani", NAME_LENGTH);
1213                                                 } else if (!strcmp(Weapon_info[i].name, "Synaptic")) {
1214                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Synaptic.ani", NAME_LENGTH);
1215                                                 } else if (!strcmp(Weapon_info[i].name, "Stiletto")) {
1216                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Stiletto.ani", NAME_LENGTH);
1217                                                 } else if (!strcmp(Weapon_info[i].name, "Tsunami")) {
1218                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Tsunami.ani", NAME_LENGTH);
1219                                                 } else if (!strcmp(Weapon_info[i].name, "Harbinger")) {
1220                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_Harbinger.ani", NAME_LENGTH);
1221                                                 } else if (!strcmp(Weapon_info[i].name, "Leech Cannon")) {
1222                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_leech.ani", NAME_LENGTH);
1223                                                 } else if (!strcmp(Weapon_info[i].name, "EM Pulse")) {
1224                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_empulse.ani", NAME_LENGTH);
1225                                                 } else if (!strcmp(Weapon_info[i].name, "S-Breaker")) {
1226                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_sbreaker.ani", NAME_LENGTH);
1227                                                 } else if (!strcmp(Weapon_info[i].name, "Cluster Bomb")) {
1228                                                         strncpy(Weapon_info[i].tech_anim_filename, "CB_cluster.ani", NAME_LENGTH);
1229                                                 }
1230 #endif
1231
1232                                                 // load the weapon animation
1233                                                 if(!techroom_load_ani(&Weapon_list[Weapon_list_size].animation, Weapon_info[i].tech_anim_filename)){
1234                                                         Weapon_list[Weapon_list_size].has_anim = 0;
1235                                                         Weapon_list[Weapon_list_size].animation = NULL;
1236
1237                                                         // hmm. try a bitmap instead
1238                                                         Weapon_list[Weapon_list_size].bitmap = bm_load(Weapon_info[i].tech_anim_filename);
1239                                                 }                                               
1240
1241                                                 Weapon_list_size++;
1242                                         }                               
1243                                 }
1244
1245                                 Weapons_loaded = 1;
1246                         }
1247
1248                         Current_list = Weapon_list;
1249                         Current_list_size = Weapon_list_size;
1250
1251                         font_height = gr_get_font_height();
1252                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1253 #ifndef MAKE_FS1
1254                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1255 #endif
1256
1257                         techroom_start_anim();
1258                         break;
1259
1260                 case INTEL_DATA_TAB:
1261
1262 #ifdef MAKE_FS1
1263                         techroom_data_init();
1264 #endif
1265                         // load intel if necessary
1266                         if ( Intel_loaded == 0 ) {
1267                                 // now populate the entry structs
1268                                 Intel_list_size = 0;
1269                                 for (i=0; i<Intel_info_size; i++) {
1270
1271                                         if (Intel_info[i].in_tech_db != 0) {
1272                                                 // leave option for no animation if string == "none"
1273                                                 if (!strcmp(Intel_info[i].anim_filename, "none")) {
1274                                                         Intel_list[Intel_list_size].has_anim = 0;
1275                                                         Intel_list[Intel_list_size].animation = NULL;
1276                                                 } else {
1277                                                         // try and load as an animation
1278                                                         Intel_list[Intel_list_size].has_anim = 0;
1279                                                         Intel_list[Intel_list_size].bitmap = -1;
1280                                                         if(techroom_load_ani(&Intel_list[Intel_list_size].animation, Intel_info[i].anim_filename)){
1281                                                                 Intel_list[Intel_list_size].has_anim = 1;                                                       
1282                                                         } else {
1283                                                                 Intel_list[Intel_list_size].bitmap = bm_load(Intel_info[i].anim_filename);
1284                                                         }
1285                                                 }
1286
1287                                                 Intel_list[Intel_list_size].desc = Intel_info[i].desc;
1288                                                 Intel_list[Intel_list_size].index = i;
1289                                                 Intel_list[Intel_list_size].name = Intel_info[i].name;
1290                                                 Intel_list_size++;
1291                                         }
1292                                 }       
1293                                 Intel_loaded = 1;
1294                         }
1295
1296                         // index lookup on intel is a pretty pointless, but it keeps everything 
1297                         // consistent and doesnt really hurt anything
1298                         Current_list = Intel_list;
1299                         Current_list_size = Intel_list_size;
1300
1301                         font_height = gr_get_font_height();
1302                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1303 #ifndef MAKE_FS1
1304                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1305 #endif
1306
1307                         techroom_start_anim();
1308                         break;
1309         }
1310
1311         // reset the entry
1312         Cur_entry = 0;
1313         techroom_select_new_entry();
1314
1315 #ifdef MAKE_FS1
1316         techroom_tab_setup(1);
1317 #endif
1318 }
1319
1320 int techroom_button_pressed(int num)
1321 {
1322         switch (num) {
1323                 case SHIPS_DATA_TAB:
1324                 case WEAPONS_DATA_TAB:
1325                 case INTEL_DATA_TAB:
1326                         techroom_change_tab(num);
1327                         break;
1328
1329                 case SIMULATOR_TAB:
1330 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1331                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1332                         gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
1333                         return 1;
1334 #else
1335                         return 0;
1336 #endif
1337
1338                 case CUTSCENES_TAB:
1339 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1340                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1341                         gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
1342                         return 1;
1343 #else
1344                         return 0;
1345 #endif
1346
1347                 case CREDITS_TAB:
1348 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1349                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1350                         gameseq_post_event(GS_EVENT_CREDITS);
1351                         return 1;
1352 #else 
1353                         return 0;
1354 #endif
1355
1356                 case PREV_ENTRY_BUTTON:
1357                         tech_prev_entry();
1358                         break;
1359
1360                 case NEXT_ENTRY_BUTTON:
1361                         tech_next_entry();
1362                         break;
1363
1364 #ifdef MAKE_FS1
1365                 case PREV_ENTRY_BUTTON2:
1366                         tech_prev_entry();
1367                         break;
1368
1369                 case NEXT_ENTRY_BUTTON2:
1370                         tech_next_entry();
1371                         break;
1372 #endif
1373
1374                 case SCROLL_LIST_UP:
1375                         tech_scroll_list_up();
1376 #ifndef MAKE_FS1
1377                         Tech_slider.forceUp();
1378 #endif
1379                         break;
1380
1381                 case SCROLL_LIST_DOWN:
1382                         tech_scroll_list_down();
1383 #ifndef MAKE_FS1
1384                         Tech_slider.forceDown();
1385 #endif
1386                         break;
1387
1388                 case SCROLL_INFO_UP:
1389                         tech_scroll_info_up();
1390                         break;
1391
1392                 case SCROLL_INFO_DOWN:
1393                         tech_scroll_info_down();
1394                         break;
1395
1396                 case HELP_BUTTON:
1397                         launch_context_help();
1398                         gamesnd_play_iface(SND_HELP_PRESSED);
1399                         break;
1400
1401                 case OPTIONS_BUTTON:
1402                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1403                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1404                         break;
1405
1406                 case EXIT_BUTTON:
1407                         gamesnd_play_iface(SND_COMMIT_PRESSED);
1408                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1409                         break;
1410         }
1411
1412         return 0;
1413 }
1414
1415 int techroom_load_ani(anim **animpp, char *name)
1416 {
1417         int load_attempts = 0;
1418         char anim_filename[64] = "2_";
1419
1420         // hi-res support
1421         // (i dont think there are any hi-res anims for these tho)
1422         if (gr_screen.res == GR_1024) {
1423                 strcat(anim_filename, name);
1424         } else {
1425                 strcpy(anim_filename, name);
1426         }
1427
1428         while(1) {
1429                 if ( load_attempts++ > 5 ) {
1430                         // Tech_room_ask_for_cd = 0;
1431                         return 0;
1432                 }
1433
1434                 *animpp = anim_load(anim_filename, 1);
1435                 if ( *animpp ) {
1436                         return 1;
1437                 } else if (gr_screen.res == GR_1024) {
1438                         // try to load low-res version if hi-res failed
1439                         *animpp = anim_load(name, 1);
1440                         if (*animpp) {
1441                                 return 1;
1442                         }
1443                 }
1444
1445                 // couldn't load animation, ask user to insert CD (if necessary)
1446                 // if ( Tech_room_ask_for_cd ) {
1447                         // if ( game_do_cd_check() == 0 ) {
1448                                 // Tech_room_ask_for_cd = 0;
1449                                 // break;
1450                         // }
1451                 // }
1452         }
1453
1454         // bogus
1455         return 0;
1456 }
1457
1458
1459 void techroom_intel_init()
1460 {
1461         int rval;
1462         static int inited = 0;
1463
1464         // open localization
1465         lcl_ext_open();
1466
1467         if (!inited) {
1468                 if ((rval = setjmp(parse_abort)) != 0) {
1469                         // close localization
1470                         lcl_ext_close();
1471
1472                         return;
1473                 } else {
1474                         read_file_text("species.tbl");
1475                         reset_parse();
1476
1477                         Intel_info_size = 0;
1478
1479 #ifndef MAKE_FS1
1480                         while (optional_string("$Entry:")) {
1481                                 Assert(Intel_info_size < MAX_INTEL_ENTRIES);
1482                                 if (Intel_info_size >= MAX_INTEL_ENTRIES) break;
1483
1484                                 required_string("$Name:");
1485                                 stuff_string(Intel_info[Intel_info_size].name, F_NAME, NULL, 32);
1486                                 required_string("$Anim:");
1487                                 stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NULL, 32);
1488                                 required_string("$AlwaysInTechRoom:");
1489                                 stuff_int(&Intel_info[Intel_info_size].in_tech_db);
1490                                 required_string("$Description:");
1491                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1492
1493
1494                                 Intel_info_size++;
1495                         }
1496 #else
1497                         if (optional_string("$Terran Tech Description:")) {
1498                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1499                                 strcpy(Intel_info[Intel_info_size].name, "Terran");
1500                                 strcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[0]);
1501                                 Intel_info[Intel_info_size].in_tech_db = 1;
1502
1503                                 Intel_info_size++;
1504                         }
1505                         
1506                         if (optional_string("$Vasudan Tech Description:")) {
1507
1508                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1509                                 strcpy(Intel_info[Intel_info_size].name, "Vasudan");
1510                                 strcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[1]);
1511                                 Intel_info[Intel_info_size].in_tech_db = 1;
1512
1513                                 Intel_info_size++;
1514                         }
1515                         
1516                         if (optional_string("$Shivan Tech Description:")) {
1517
1518                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1519                                 strcpy(Intel_info[Intel_info_size].name, "Shivan");
1520                                 strcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[2]);
1521                                 // FIXME: shouldn't always be in the intel database but no choice at this point
1522                                 // there are only about 4 missions before they show up anyway so it may not be worth it
1523                                 Intel_info[Intel_info_size].in_tech_db = 1;
1524
1525                                 Intel_info_size++;
1526                         }
1527 #endif
1528                         inited = 1;
1529                 }
1530         }
1531
1532         // close localization
1533         lcl_ext_close();
1534 }
1535
1536 void techroom_init()
1537 {
1538         int i, idx;
1539         techroom_buttons *b;
1540
1541         gr_reset_clip();
1542         gr_clear();
1543         Mouse_hidden++;
1544         gr_flip();
1545         Mouse_hidden--;
1546
1547         Ships_loaded = 0;
1548         Weapons_loaded = 0;
1549         Intel_loaded = 0;
1550
1551         // Tech_room_ask_for_cd = 1;
1552
1553         // backup and bash detail level stuff
1554         Tech_detail_backup = Detail.detail_distance;
1555         Detail.detail_distance = MAX_DETAIL_LEVEL;
1556         Tech_texture_backup = Detail.hardware_textures;
1557         Detail.hardware_textures = MAX_DETAIL_LEVEL;
1558
1559         /*
1560         Palette_bmp = bm_load("TechDataPalette");
1561         Assert(Palette_bmp);
1562         bm_get_palette(Palette_bmp, Palette, Palette_name);  // get the palette for this bitmap
1563         gr_set_palette(Palette_name, Palette, 1);
1564         */
1565
1566 #ifdef MAKE_FS1
1567         common_set_interface_palette("TechDataPalette");
1568 #endif
1569
1570         // unflag fullneb 
1571         The_mission.flags &= ~MISSION_FLAG_FULLNEB;
1572
1573         // set up UI stuff
1574         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1575 #ifndef MAKE_FS1  // do this with techroom_tab_setup()
1576         Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1577 #endif
1578
1579         Tech_background_bitmap = bm_load(Tech_background_filename[gr_screen.res]);
1580         if (Tech_background_bitmap < 0) {
1581                 // failed to load bitmap, not a good thing
1582                 Int3();
1583         }
1584
1585 #ifdef MAKE_FS1 // for weapons/species tab
1586         Tech_data_background_bitmap = bm_load(Tech_data_background_filename);
1587         if (Tech_data_background_bitmap < 0) {
1588                 // failed to load bitmap, not a good thing
1589                 Int3();
1590         }
1591
1592         techroom_tab_setup(0);
1593
1594         // don't draw buttons that are only on other tabs
1595         for (i=0; i<PREV_ENTRY_BUTTON2; i++) {
1596 #else
1597         for (i=0; i<NUM_BUTTONS; i++) {
1598 #endif
1599                 b = &Buttons[gr_screen.res][i];
1600
1601                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1602                 // set up callback for when a mouse first goes over a button
1603                 if (b->filename) {
1604                         b->button.set_bmaps(b->filename);
1605 //                      if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1606                                 b->button.set_highlight_action(common_play_highlight_sound);
1607 //                      }
1608
1609                 } else {
1610                         b->button.hide();
1611                 }
1612
1613                 b->button.link_hotspot(b->hotspot);
1614         }
1615         
1616 #ifndef MAKE_FS1
1617         // common tab button text
1618         Ui_window.add_XSTR("Technical Database", 1055, Buttons[gr_screen.res][TECH_DATABASE_TAB].xt,  Buttons[gr_screen.res][TECH_DATABASE_TAB].yt, &Buttons[gr_screen.res][TECH_DATABASE_TAB].button, UI_XSTR_COLOR_GREEN);
1619         Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[gr_screen.res][SIMULATOR_TAB].xt,  Buttons[gr_screen.res][SIMULATOR_TAB].yt, &Buttons[gr_screen.res][SIMULATOR_TAB].button, UI_XSTR_COLOR_GREEN);
1620         Ui_window.add_XSTR("Cutscenes", 1057, Buttons[gr_screen.res][CUTSCENES_TAB].xt,  Buttons[gr_screen.res][CUTSCENES_TAB].yt, &Buttons[gr_screen.res][CUTSCENES_TAB].button, UI_XSTR_COLOR_GREEN);
1621         Ui_window.add_XSTR("Credits", 1058, Buttons[gr_screen.res][CREDITS_TAB].xt,  Buttons[gr_screen.res][CREDITS_TAB].yt, &Buttons[gr_screen.res][CREDITS_TAB].button, UI_XSTR_COLOR_GREEN);
1622
1623         // common ship/weapon/intel text
1624         Ui_window.add_XSTR("Ships", 293, Buttons[gr_screen.res][SHIPS_DATA_TAB].xt,  Buttons[gr_screen.res][SHIPS_DATA_TAB].yt, &Buttons[gr_screen.res][SHIPS_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
1625         Ui_window.add_XSTR("Weapons", 1553, Buttons[gr_screen.res][WEAPONS_DATA_TAB].xt,  Buttons[gr_screen.res][WEAPONS_DATA_TAB].yt, &Buttons[gr_screen.res][WEAPONS_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
1626         Ui_window.add_XSTR("Intelligence", 1066, Buttons[gr_screen.res][INTEL_DATA_TAB].xt,  Buttons[gr_screen.res][INTEL_DATA_TAB].yt, &Buttons[gr_screen.res][INTEL_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
1627
1628         // common help/options/commit text
1629
1630         // NK: removed these two text labels on Tech screen update 4/26/99
1631 //      Ui_window.add_XSTR("Help", 928, Buttons[gr_screen.res][HELP_BUTTON].xt,  Buttons[gr_screen.res][HELP_BUTTON].yt, &Buttons[gr_screen.res][HELP_BUTTON].button, UI_XSTR_COLOR_GREEN);
1632 //      Ui_window.add_XSTR("Options", 1036, Buttons[gr_screen.res][OPTIONS_BUTTON].xt,  Buttons[gr_screen.res][OPTIONS_BUTTON].yt, &Buttons[gr_screen.res][OPTIONS_BUTTON].button, UI_XSTR_COLOR_GREEN);                
1633         Ui_window.add_XSTR("Exit", 1418, Buttons[gr_screen.res][EXIT_BUTTON].xt,  Buttons[gr_screen.res][EXIT_BUTTON].yt, &Buttons[gr_screen.res][EXIT_BUTTON].button, UI_XSTR_COLOR_PINK);             
1634 #endif
1635
1636         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1637                 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1638                 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1639         }
1640
1641         // set some hotkeys
1642         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.set_hotkey(KEY_LEFT);
1643         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.set_hotkey(KEY_RIGHT);
1644 #ifndef MAKE_FS1 // set per tab
1645         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(KEY_UP);
1646         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(KEY_DOWN);
1647 #endif
1648
1649
1650         for (i=0; i<LIST_BUTTONS_MAX; i++) {
1651                 List_buttons[i].create(&Ui_window, "", 0, 0, 60, 30, 0, 1);
1652                 List_buttons[i].hide();
1653                 List_buttons[i].disable();
1654         }
1655
1656         View_window.create(&Ui_window, "", Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD], 1, 1);
1657         View_window.hide();
1658
1659 #ifdef MAKE_FS1
1660         ShipWin01 = bm_load(NOX("ShipWin01"));
1661         ShipWin02 = bm_load(NOX("ShipWin02"));
1662         ShipWin03 = bm_load(NOX("ShipWin03"));
1663         ShipWin04 = bm_load(NOX("ShipWin04"));
1664 #endif
1665
1666         Buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(KEY_F1);
1667         Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
1668         Buttons[gr_screen.res][SCROLL_LIST_UP].button.set_hotkey(KEY_PAGEUP);
1669         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.set_hotkey(KEY_PAGEDOWN);
1670
1671         // init help overlay states
1672         help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1673
1674         // setup slider
1675 #ifndef MAKE_FS1
1676         Tech_slider.create(&Ui_window, Tech_slider_coords[gr_screen.res][SHIP_X_COORD], Tech_slider_coords[gr_screen.res][SHIP_Y_COORD], Tech_slider_coords[gr_screen.res][SHIP_W_COORD], Tech_slider_coords[gr_screen.res][SHIP_H_COORD], Num_ship_types, Tech_slider_filename[gr_screen.res], &tech_scroll_list_up, &tech_scroll_list_down, &tech_ship_scroll_capture);
1677 #endif
1678
1679         Cur_anim_instance = NULL;
1680
1681         // zero weapon and intel anim/bitmap stuff
1682         for(idx=0; idx<MAX_WEAPON_TYPES; idx++){
1683                 Weapon_list[idx].animation = NULL;
1684                 Weapon_list[idx].bitmap = -1;
1685         }
1686         for(idx=0; idx<MAX_INTEL_ENTRIES; idx++){
1687                 Intel_list[idx].animation = NULL;
1688                 Intel_list[idx].bitmap = -1;
1689         }
1690
1691         Anim_playing_id = -1;
1692         techroom_change_tab(Tab);
1693 }
1694
1695 void techroom_close()
1696 {
1697         int i;
1698
1699         techroom_stop_anim(-1);
1700         for (i=0; i<MAX_WEAPON_TYPES; i++) {
1701                 if ( Weapon_list[i].animation ) {
1702                         anim_free(Weapon_list[i].animation);
1703                         Weapon_list[i].animation = NULL;
1704                 }
1705                 if( Weapon_list[i].bitmap >= 0 ){
1706                         bm_unload(Weapon_list[i].bitmap);
1707                         Weapon_list[i].bitmap = -1;
1708                 }
1709         }
1710
1711         for (i=0; i<MAX_INTEL_ENTRIES; i++){
1712                 if (Intel_list[i].animation != NULL) {
1713                         anim_free(Intel_list[i].animation);
1714                         Intel_list[i].animation = NULL;
1715                 }
1716                 if( Intel_list[i].bitmap >= 0 ){
1717                         bm_unload(Intel_list[i].bitmap);
1718                         Intel_list[i].bitmap = -1;
1719                 }
1720         }
1721
1722         Ships_loaded = 0;
1723         Weapons_loaded = 0;
1724         Intel_loaded = 0;
1725
1726 #ifdef MAKE_FS1
1727         if (ShipWin01){
1728                 bm_unload(ShipWin01);
1729         }
1730         if (ShipWin02){
1731                 bm_unload(ShipWin02);
1732         }
1733         if (ShipWin03){
1734                 bm_unload(ShipWin03);
1735         }
1736         if (ShipWin04){
1737                 bm_unload(ShipWin04);
1738         }
1739
1740         if (Tech_data_background_bitmap) {
1741                 bm_unload(Tech_data_background_bitmap);
1742         }
1743 #endif
1744
1745         if (Tech_background_bitmap) {
1746                 bm_unload(Tech_background_bitmap);
1747         }
1748
1749         Ui_window.destroy();
1750         common_free_interface_palette();                // restore game palette
1751         /*
1752         if (Palette_bmp){
1753                 bm_unload(Palette_bmp);
1754         }
1755         */
1756
1757         // restore detail settings
1758         Detail.detail_distance = Tech_detail_backup;
1759         Detail.hardware_textures = Tech_texture_backup;
1760 }
1761
1762 #ifdef MAKE_FS1
1763 void techroom_data_init()
1764 {
1765         int i;
1766         techroom_buttons *b;
1767
1768         for (i=PREV_ENTRY_BUTTON2; i<NUM_BUTTONS; i++) {
1769                 b = &Buttons[gr_screen.res][i];
1770
1771                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1772                 // set up callback for when a mouse first goes over a button
1773                 if (b->filename) {
1774                         b->button.set_bmaps(b->filename);
1775                         b->button.set_highlight_action(common_play_highlight_sound);
1776                 } else {
1777                         b->button.hide();
1778                 }
1779
1780                 b->button.link_hotspot(b->hotspot);
1781         }
1782 }
1783
1784 void techroom_tab_setup(int set_palette)
1785 {
1786         // char *pal;
1787         int i;
1788         int flags[256];
1789
1790         for (i=0; i<256; i++){
1791                 flags[i] = 0;
1792         }
1793
1794         // activate, deactivate any necessary controls
1795         for (i=0; i<NUM_BUTTONS; i++) {
1796                 Buttons[gr_screen.res][i].button.enable();
1797                 if (Buttons[gr_screen.res][i].filename)
1798                         Buttons[gr_screen.res][i].button.unhide();
1799         }
1800
1801         // do other special processing
1802         switch (Tab) {
1803                 case SHIPS_DATA_TAB:
1804                         // set the mask for this tab
1805                         Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1806
1807                         // setup hotkeys to scroll list
1808                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(KEY_UP);
1809                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(KEY_DOWN);
1810
1811                         // hide extra buttons
1812                         Buttons[gr_screen.res][PREV_ENTRY_BUTTON2].button.hide();
1813                         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON2].button.hide();
1814                         break;
1815
1816                 case WEAPONS_DATA_TAB:
1817                         // set the mask for this tab
1818                         Ui_window.set_mask_bmap(Tech_data_mask_filename);
1819
1820                         // the list isn't supposed to scroll so clear the hotkeys
1821                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(-1);
1822                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(-1);
1823
1824                         // hide extra buttons
1825                         Buttons[gr_screen.res][SCROLL_LIST_UP].button.hide();
1826                         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.hide();
1827                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.hide();
1828                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.hide();
1829                         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.hide();
1830                         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.hide();
1831                         break;
1832
1833                 case INTEL_DATA_TAB:
1834                         // set the mask for this tab
1835                         Ui_window.set_mask_bmap(Tech_data_mask_filename);
1836
1837                         // the list isn't supposed to scroll so clear the hotkeys
1838                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(-1);
1839                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(-1);
1840
1841                         // hide extra buttons
1842                         Buttons[gr_screen.res][SCROLL_LIST_UP].button.hide();
1843                         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.hide();
1844                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.hide();
1845                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.hide();
1846                         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.hide();
1847                         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.hide();
1848                         break;
1849         }
1850 }
1851 #endif
1852
1853 void techroom_do_frame(float frametime)
1854 {
1855         int i, k;       
1856
1857         // turn off controls when overlay is on
1858         if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1859                 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
1860                 Ui_window.set_ignore_gadgets(1);
1861         }
1862
1863         // turn off controls in trackball mode
1864         if (Trackball_active) {
1865                 Ui_window.set_ignore_gadgets(1);
1866         } else {
1867                 Ui_window.set_ignore_gadgets(0);
1868         }
1869
1870         k = Ui_window.process() & ~KEY_DEBUGGED;
1871
1872         if ( (k > 0) || B1_JUST_RELEASED ) {
1873                 if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1874                         help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1875                         Ui_window.set_ignore_gadgets(0);
1876                         k = 0;
1877                 }
1878         }
1879
1880         if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
1881                 Ui_window.set_ignore_gadgets(0);
1882         }
1883
1884         switch (k) {
1885                 case KEY_SHIFTED | KEY_TAB:  // activate previous tab
1886                         i = Tab - 1;
1887                         if (i < 0) {
1888                                 i = NUM_TABS - 1;
1889                         }
1890
1891                         techroom_change_tab(i);
1892                         break;
1893
1894                 case KEY_TAB:  // activate next tab
1895                         i = Tab + 1;
1896                         if (i >= NUM_TABS) {
1897                                 i = 0;
1898                         }
1899
1900                         techroom_change_tab(i);
1901                         break;
1902
1903                 case KEY_CTRLED | KEY_DOWN:
1904                         if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
1905                                 techroom_button_pressed(SIMULATOR_TAB);
1906                                 break;
1907                         }
1908                         // fall through
1909
1910                 case KEY_CTRLED | KEY_UP:
1911                         techroom_button_pressed(CREDITS_TAB);
1912                         break;
1913 /*
1914                 case KEY_UP:
1915                         tech_prev_entry();
1916                         break;
1917
1918                 case KEY_DOWN:
1919                         tech_next_entry();
1920                         break;
1921 */
1922                 case KEY_CTRLED | KEY_ENTER:
1923                 case KEY_ESC:
1924                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1925                         break;
1926         }       
1927
1928         // check ship model window for activity
1929         if (View_window.pressed()) {
1930                 Trackball_active = 1;
1931                 Trackball_mode = 1;
1932         }
1933         if (B1_RELEASED) {
1934                 Trackball_active = 0;
1935         }
1936
1937         // check all da buttons
1938         for (i=0; i<NUM_BUTTONS; i++) {
1939                 if (Buttons[gr_screen.res][i].button.pressed()) {
1940                         if (techroom_button_pressed(i)) {
1941                                 return;
1942                         }
1943                 }
1944         }
1945
1946         // check for mouseovers/clicks on the selection list
1947         Select_tease_line = -1;
1948         for (i=0; i<LIST_BUTTONS_MAX; i++) {
1949                 if (List_buttons[i].is_mouse_on()) {
1950                         Select_tease_line = i + List_offset;
1951                 }
1952         
1953                 if (List_buttons[i].pressed()) {
1954                         Cur_entry = i + List_offset;
1955                         gamesnd_play_iface(SND_USER_SELECT);
1956                         techroom_select_new_entry();
1957                 }
1958         }
1959
1960 #ifndef MAKE_FS1  // do this per tab instead
1961         // clear & draw bg bitmap
1962         GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
1963         if (Tech_background_bitmap >= 0) {
1964                 gr_set_bitmap(Tech_background_bitmap);
1965                 gr_bitmap(0, 0);
1966         }
1967 #endif
1968
1969         // render
1970         switch (Tab) {
1971                 case SHIPS_DATA_TAB:
1972 #ifdef MAKE_FS1
1973                         // clear & draw bg bitmap
1974                         GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
1975                         if (Tech_background_bitmap >= 0) {
1976                                 gr_set_bitmap(Tech_background_bitmap);
1977                                 gr_bitmap(0, 0);
1978                         }
1979 #endif
1980                         techroom_ships_render(frametime);
1981
1982 #ifdef MAKE_FS1
1983                         if (ShipWin01) {
1984                                 gr_set_bitmap(ShipWin01);
1985                                 gr_bitmap(223, 104);
1986                         }
1987
1988                         if (ShipWin02) {
1989                                 gr_set_bitmap(ShipWin02);
1990                                 gr_bitmap(621, 124);
1991                         }
1992
1993                         if (ShipWin03) {
1994                                 gr_set_bitmap(ShipWin03);
1995                                 gr_bitmap(223, 338);
1996                         }
1997
1998                         if (ShipWin04) {
1999                                 gr_set_bitmap(ShipWin04);
2000                                 gr_bitmap(218, 124);
2001                         }
2002 #endif
2003
2004                         break;
2005
2006                 case WEAPONS_DATA_TAB:
2007 #ifdef MAKE_FS1
2008                         // clear & draw bg bitmap
2009                         GR_MAYBE_CLEAR_RES(Tech_data_background_bitmap);
2010                         if (Tech_data_background_bitmap >= 0) {
2011                                 gr_set_bitmap(Tech_data_background_bitmap);
2012                                 gr_bitmap(0, 0);
2013                         }
2014 #endif
2015                         techroom_weapons_render2(frametime);
2016
2017                         break;
2018
2019                 case INTEL_DATA_TAB:
2020 #ifdef MAKE_FS1
2021                         // clear & draw bg bitmap
2022                         GR_MAYBE_CLEAR_RES(Tech_data_background_bitmap);
2023                         if (Tech_data_background_bitmap >= 0) {
2024                                 gr_set_bitmap(Tech_data_background_bitmap);
2025                                 gr_bitmap(0, 0);
2026                         }
2027 #endif
2028                         techroom_intel_render(frametime);
2029
2030                         break;
2031         }
2032
2033         Ui_window.draw();
2034
2035         for (i=TECH_DATABASE_TAB; i<=CREDITS_TAB; i++) {
2036                 if (Buttons[gr_screen.res][i].button.button_down()) {
2037                         break;
2038                 }
2039         }
2040         if (i > CREDITS_TAB) {
2041                 Buttons[gr_screen.res][TECH_DATABASE_TAB].button.draw_forced(2);
2042         }
2043
2044         for (i=0; i<NUM_TABS; i++){
2045                 if (Buttons[gr_screen.res][i].button.button_down()){
2046                         break;
2047                 }
2048         }
2049         if (i == NUM_TABS){
2050                 Buttons[gr_screen.res][Tab].button.draw_forced(2);
2051         }
2052
2053         // blit help overlay if active
2054         help_overlay_maybe_blit(TECH_ROOM_OVERLAY);
2055
2056         gr_flip();
2057 }
2058