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