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