]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/techmenu.cpp
remove support for memory-mapped files
[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 || 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 w, h;
706                 gr_get_string_size(&w, &h, XSTR("more", 1469), strlen(XSTR("more", 1469)));
707                 gr_set_color_fast(&Color_black);
708                 gr_rect(more_txt_x-2, more_txt_y, w+3, h);
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, sizeof(buf));
773                 if (Lcl_gr) {
774                         lcl_translate_ship_name(buf, sizeof(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                 Cur_entry = Current_list_size - 1;
908
909                 // scroll to end of list
910                 List_offset = Cur_entry - Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() + 1;
911                 if (List_offset < 0) {
912                         // this happens when there are not enough items to scroll
913                         List_offset = 0;
914                 }
915 #ifndef MAKE_FS1
916                 Tech_slider.force_currentItem(Tech_slider.get_numberItems());
917 #endif
918         } else {
919                 // maybe adjust list position by 1
920                 if (List_offset > Cur_entry) {
921                         tech_scroll_list_up();
922 #ifndef MAKE_FS1
923                         Tech_slider.forceUp();
924 #endif
925                 }
926         }
927
928         techroom_select_new_entry();
929         gamesnd_play_iface(SND_SCROLL);
930 }
931
932 // select next entry in current list
933 void tech_next_entry()
934 {
935         Cur_entry++;
936         if (Cur_entry >= Current_list_size) {
937                 Cur_entry = 0;
938
939                 // scroll to beginning of list
940                 List_offset = 0;
941 #ifndef MAKE_FS1
942                 Tech_slider.force_currentItem(Cur_entry);
943 #endif
944         } else {
945                 // maybe adjust list position by 1
946                 if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() <= Cur_entry) {
947                         tech_scroll_list_down();
948 #ifndef MAKE_FS1
949                         Tech_slider.forceDown();
950 #endif
951                 }
952         }
953
954         techroom_select_new_entry();
955         gamesnd_play_iface(SND_SCROLL);
956 }
957
958 void tech_scroll_info_up()
959 {
960         if (Text_offset) {
961                 Text_offset--;
962                 gamesnd_play_iface(SND_SCROLL);
963         } else {
964                 gamesnd_play_iface(SND_GENERAL_FAIL);
965         }
966 }
967
968 void tech_scroll_info_down()
969 {
970         int h;
971
972         if (Tab == SHIPS_DATA_TAB){
973                 h = Tech_desc_coords[gr_screen.res][SHIP_H_COORD];
974         } else {
975                 h = Tech_desc_coords[gr_screen.res][3];
976         }
977
978         if (Text_offset + h / gr_get_font_height() < Text_size) {
979                 Text_offset++;
980                 gamesnd_play_iface(SND_SCROLL);
981         } else {
982                 gamesnd_play_iface(SND_GENERAL_FAIL);
983         }
984 }
985
986 void tech_scroll_list_up()
987 {
988         //int last;
989
990         if (List_offset > 0) {
991                 List_offset--;
992                 //last = List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() - 1;
993
994 #ifdef MAKE_FS1
995                 if ( (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() - 1) < Cur_entry ) {
996                         Cur_entry--;
997                         techroom_select_new_entry();
998                 }
999 #endif
1000                 gamesnd_play_iface(SND_SCROLL);
1001         } else {
1002                 gamesnd_play_iface(SND_GENERAL_FAIL);
1003         }
1004 }
1005
1006 void tech_scroll_list_down()
1007 {
1008         if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() < Current_list_size) {
1009                 List_offset++;
1010
1011 #ifdef MAKE_FS1
1012                 if ( (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height()) > Cur_entry ) {
1013                         Cur_entry++;
1014                         techroom_select_new_entry();
1015                 }
1016 #endif
1017                 gamesnd_play_iface(SND_SCROLL);
1018         } else {
1019                 gamesnd_play_iface(SND_GENERAL_FAIL);
1020         }
1021 }
1022
1023 // this doesnt do a damn thing...
1024 void tech_ship_scroll_capture()
1025 {
1026         techroom_select_new_entry();
1027 }
1028
1029
1030 // this is obsolete - see techroom_weapons_render2(...)
1031 void techroom_weapons_render(float frametime)
1032 {
1033         gr_set_color_fast(&Color_text_normal);
1034         techroom_render_desc(Tech_desc_coords[gr_screen.res][0], Tech_desc_coords[gr_screen.res][1], Tech_desc_coords[gr_screen.res][3]);
1035
1036         {
1037                 // JAS: This code is hacked to allow the animation to use all 256 colors
1038                 extern int Palman_allow_any_color;
1039                 Palman_allow_any_color = 1;
1040                 anim_render_all(0, frametime);
1041                 Palman_allow_any_color = 0;
1042         }
1043
1044         // if our active item has a bitmap instead of an animation, draw it
1045         if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
1046                 gr_set_bitmap(Current_list[Cur_entry].bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1047                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1048         }
1049 }
1050
1051 void techroom_intel_render(float frametime)
1052 {
1053 #ifndef MAKE_FS1
1054         tech_common_render();
1055 #else
1056         // render description in its box
1057         gr_set_color_fast(&Color_text_normal);
1058         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]);
1059 #endif
1060
1061         {
1062                 // JAS: This code is hacked to allow the animation to use all 256 colors
1063                 extern int Palman_allow_any_color;
1064                 Palman_allow_any_color = 1;
1065                 anim_render_all(0, frametime);
1066                 Palman_allow_any_color = 0;
1067         }
1068
1069         // if our active item has a bitmap instead of an animation, draw it
1070         if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
1071                 gr_set_bitmap(Current_list[Cur_entry].bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1072                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1073         }
1074 }
1075
1076 void techroom_stop_anim(int id)
1077 {
1078         if (Cur_anim_instance && (id != Anim_playing_id)) {
1079                 anim_stop_playing(Cur_anim_instance);
1080                 Cur_anim_instance = NULL;
1081         }
1082 }
1083
1084 void techroom_start_anim()
1085 {
1086         int id;
1087         anim *animp;
1088         anim_play_struct aps;
1089
1090         if (Cur_entry < 0) {
1091                 techroom_stop_anim(-1);
1092                 Anim_playing_id = -1;
1093         }
1094
1095         if (Tab == WEAPONS_DATA_TAB) {
1096                 id = Cur_entry;
1097         } else {
1098                 id = Cur_entry + 2000;                                          // this offset is arbitrary?
1099         }
1100
1101         techroom_stop_anim(id);
1102
1103         // if we actually have an animation
1104         if(Current_list[Cur_entry].animation != NULL){
1105                 animp = Current_list[Cur_entry].animation;      
1106
1107                 if (id != Anim_playing_id) {
1108                         Anim_playing_id = -1;
1109                         if (animp) {
1110                                 anim_play_init(&aps, animp, Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1111                                 aps.looped = 1;
1112                                 Cur_anim_instance = anim_play(&aps);
1113                                 Anim_playing_id = id;
1114                         }
1115
1116                         if (animp) {
1117                                 memcpy(Palette, animp->palette, 384);
1118                                 gr_set_palette(animp->name, Palette, 1);
1119                         }
1120                 }
1121         }
1122 }
1123
1124
1125 void techroom_change_tab(int num)
1126 {
1127         int i, multi = 0, mask, font_height, max_num_entries_viewable;  
1128
1129         Tab = num;
1130         // SDL_assert(Current_list_size >= 0);
1131         List_offset = 0;
1132         Cur_entry = 0;
1133         multi = Player->flags & PLAYER_FLAGS_IS_MULTI;
1134
1135         for (i=0; i<LIST_BUTTONS_MAX; i++){
1136                 List_buttons[i].disable();
1137         }
1138
1139         // disable some stuff in multiplayer
1140         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1141                 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1142                 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1143         }
1144
1145         switch (Tab) {
1146                 case SHIPS_DATA_TAB:
1147                         mask = multi ? SIF_IN_TECH_DATABASE_M : SIF_IN_TECH_DATABASE;
1148                         
1149                         // load ship info if necessary
1150                         if (Ships_loaded == 0) {
1151                                 Ship_list_size = 0;
1152                                 for (i=0; i<Num_ship_types; i++) {
1153 #ifndef MAKE_FS1
1154                                         if (Ship_info[i].flags & mask) {
1155 #else
1156                                         // make sure it has a description before displaying
1157                                         if ((Ship_info[i].flags & mask) && (Ship_info[i].tech_desc)) {
1158 #endif
1159                                                 // this ship should be displayed, fill out the entry struct
1160                                                 Ship_list[Ship_list_size].bitmap = -1;
1161                                                 Ship_list[Ship_list_size].index = i;
1162                                                 Ship_list[Ship_list_size].animation = NULL;                     // no anim for ships
1163                                                 Ship_list[Ship_list_size].has_anim = 0;                         // no anim for ships
1164                                                 Ship_list[Ship_list_size].name = Ship_info[i].name;
1165                                                 Ship_list[Ship_list_size].desc = Ship_info[i].tech_desc;
1166                                                 Ship_list_size++;
1167                                         }                               
1168                                 }
1169                                 Ships_loaded = 1;
1170                         }
1171
1172                         Current_list = Ship_list;
1173                         Current_list_size = Ship_list_size;
1174
1175                         font_height = gr_get_font_height();
1176                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1177 #ifndef MAKE_FS1
1178                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1179 #endif
1180
1181                         // no anim to start here
1182                         break;
1183
1184                 case WEAPONS_DATA_TAB:
1185 #ifdef MAKE_FS1
1186                         techroom_data_init();
1187 #endif
1188                         // load weapon info & anims if necessary
1189                         if (Weapons_loaded == 0) {
1190                                 Weapon_list_size = 0;
1191                                 mask = multi ? WIF_PLAYER_ALLOWED : WIF_IN_TECH_DATABASE;
1192
1193                                 for (i=0; i<MAX_WEAPON_TYPES; i++) {
1194                                         if (Weapon_info[i].wi_flags & mask) { 
1195 #ifndef MAKE_FS1
1196                                                 // note: hack here to exclude dogfight weapons -- dont put weapon in if it has same description as pvs weapon
1197                                                 if ((Weapon_list_size > 0) && (!strcmp(Weapon_info[i].tech_desc, Weapon_list[Weapon_list_size-1].desc))) {
1198 #else
1199                                                 // exclude entries with no description, basically the same as above but helps get rid of special cases as well
1200                                                 if ((Weapon_list_size > 0) && (!Weapon_info[i].tech_desc)) {
1201 #endif
1202                                                         continue;
1203                                                 }
1204
1205                                                 // we have a weapon that should be in the tech db, so fill out the entry struct
1206                                                 Weapon_list[Weapon_list_size].index = i;
1207                                                 Weapon_list[Weapon_list_size].desc = Weapon_info[i].tech_desc;
1208                                                 Weapon_list[Weapon_list_size].has_anim = 1;
1209                                                 Weapon_list[Weapon_list_size].name = Weapon_info[i].tech_title;
1210                                                 Weapon_list[Weapon_list_size].bitmap = -1;
1211                                                 if (Weapon_list[Weapon_list_size].name[0] == 0) {
1212                                                         Weapon_list[Weapon_list_size].name = Weapon_info[i].name;
1213                                                 }
1214
1215 #ifdef MAKE_FS1
1216                                                 // figure out the animation based on weapon name
1217                                                 if (!strcmp(Weapon_info[i].name, "ML-16 Laser")) {
1218                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_ML16.ani", NAME_LENGTH);
1219                                                 } else if (!strcmp(Weapon_info[i].name, "Disruptor")) {
1220                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Disruptor.ani", NAME_LENGTH);
1221                                                 } else if (!strcmp(Weapon_info[i].name, "D-Advanced")) {
1222                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_DAdvanced.ani", NAME_LENGTH);
1223                                                 } else if (!strcmp(Weapon_info[i].name, "Avenger")) {
1224                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Avenger.ani", NAME_LENGTH);
1225                                                 } else if (!strcmp(Weapon_info[i].name, "Flail")) {
1226                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Flail.ani", NAME_LENGTH);
1227                                                 } else if (!strcmp(Weapon_info[i].name, "Prometheus")) {
1228                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Prometheus.ani", NAME_LENGTH);
1229                                                 } else if (!strcmp(Weapon_info[i].name, "Banshee")) {
1230                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Banshee.ani", NAME_LENGTH);
1231                                                 } else if (!strcmp(Weapon_info[i].name, "MX-50")) {
1232                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_MX50.ani", NAME_LENGTH);
1233                                                 } else if (!strcmp(Weapon_info[i].name, "D-Missile")) {
1234                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_DisruptorMissile.ani", NAME_LENGTH);
1235                                                 } else if (!strcmp(Weapon_info[i].name, "Fury")) {
1236                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Fury.ani", NAME_LENGTH);
1237                                                 } else if (!strcmp(Weapon_info[i].name, "Hornet")) {
1238                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Hornet.ani", NAME_LENGTH);
1239                                                 } else if (!strcmp(Weapon_info[i].name, "Interceptor")) {
1240                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Interceptor.ani", NAME_LENGTH);
1241                                                 } else if (!strcmp(Weapon_info[i].name, "Phoenix V")) {
1242                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Phoenix.ani", NAME_LENGTH);
1243                                                 } else if (!strcmp(Weapon_info[i].name, "Synaptic")) {
1244                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Synaptic.ani", NAME_LENGTH);
1245                                                 } else if (!strcmp(Weapon_info[i].name, "Stiletto")) {
1246                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Stiletto.ani", NAME_LENGTH);
1247                                                 } else if (!strcmp(Weapon_info[i].name, "Tsunami")) {
1248                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Tsunami.ani", NAME_LENGTH);
1249                                                 } else if (!strcmp(Weapon_info[i].name, "Harbinger")) {
1250                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Harbinger.ani", NAME_LENGTH);
1251                                                 } else if (!strcmp(Weapon_info[i].name, "Leech Cannon")) {
1252                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_leech.ani", NAME_LENGTH);
1253                                                 } else if (!strcmp(Weapon_info[i].name, "EM Pulse")) {
1254                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_empulse.ani", NAME_LENGTH);
1255                                                 } else if (!strcmp(Weapon_info[i].name, "S-Breaker")) {
1256                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_sbreaker.ani", NAME_LENGTH);
1257                                                 } else if (!strcmp(Weapon_info[i].name, "Cluster Bomb")) {
1258                                                         SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_cluster.ani", NAME_LENGTH);
1259                                                 }
1260 #endif
1261
1262                                                 // load the weapon animation
1263                                                 if(!techroom_load_ani(&Weapon_list[Weapon_list_size].animation, Weapon_info[i].tech_anim_filename)){
1264                                                         Weapon_list[Weapon_list_size].has_anim = 0;
1265                                                         Weapon_list[Weapon_list_size].animation = NULL;
1266
1267                                                         // hmm. try a bitmap instead
1268                                                         Weapon_list[Weapon_list_size].bitmap = bm_load(Weapon_info[i].tech_anim_filename);
1269                                                 }                                               
1270
1271                                                 Weapon_list_size++;
1272                                         }                               
1273                                 }
1274
1275                                 Weapons_loaded = 1;
1276                         }
1277
1278                         Current_list = Weapon_list;
1279                         Current_list_size = Weapon_list_size;
1280
1281                         font_height = gr_get_font_height();
1282                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1283 #ifndef MAKE_FS1
1284                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1285 #endif
1286
1287                         techroom_start_anim();
1288                         break;
1289
1290                 case INTEL_DATA_TAB:
1291
1292 #ifdef MAKE_FS1
1293                         techroom_data_init();
1294 #endif
1295                         // load intel if necessary
1296                         if ( Intel_loaded == 0 ) {
1297                                 // now populate the entry structs
1298                                 Intel_list_size = 0;
1299                                 for (i=0; i<Intel_info_size; i++) {
1300
1301                                         if (Intel_info[i].in_tech_db != 0) {
1302                                                 // leave option for no animation if string == "none"
1303                                                 if (!strcmp(Intel_info[i].anim_filename, "none")) {
1304                                                         Intel_list[Intel_list_size].has_anim = 0;
1305                                                         Intel_list[Intel_list_size].animation = NULL;
1306                                                 } else {
1307                                                         // try and load as an animation
1308                                                         Intel_list[Intel_list_size].has_anim = 0;
1309                                                         Intel_list[Intel_list_size].bitmap = -1;
1310                                                         if(techroom_load_ani(&Intel_list[Intel_list_size].animation, Intel_info[i].anim_filename)){
1311                                                                 Intel_list[Intel_list_size].has_anim = 1;                                                       
1312                                                         } else {
1313                                                                 Intel_list[Intel_list_size].bitmap = bm_load(Intel_info[i].anim_filename);
1314                                                         }
1315                                                 }
1316
1317                                                 Intel_list[Intel_list_size].desc = Intel_info[i].desc;
1318                                                 Intel_list[Intel_list_size].index = i;
1319                                                 Intel_list[Intel_list_size].name = Intel_info[i].name;
1320                                                 Intel_list_size++;
1321                                         }
1322                                 }       
1323                                 Intel_loaded = 1;
1324                         }
1325
1326                         // index lookup on intel is a pretty pointless, but it keeps everything 
1327                         // consistent and doesnt really hurt anything
1328                         Current_list = Intel_list;
1329                         Current_list_size = Intel_list_size;
1330
1331                         font_height = gr_get_font_height();
1332                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1333 #ifndef MAKE_FS1
1334                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1335 #endif
1336
1337                         techroom_start_anim();
1338                         break;
1339         }
1340
1341         // reset the entry
1342         Cur_entry = 0;
1343         techroom_select_new_entry();
1344
1345 #ifdef MAKE_FS1
1346         techroom_tab_setup(1);
1347 #endif
1348 }
1349
1350 int techroom_button_pressed(int num)
1351 {
1352         switch (num) {
1353                 case SHIPS_DATA_TAB:
1354                 case WEAPONS_DATA_TAB:
1355                 case INTEL_DATA_TAB:
1356                         techroom_change_tab(num);
1357                         break;
1358
1359                 case SIMULATOR_TAB:
1360 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1361                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1362                         gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
1363                         return 1;
1364 #else
1365                         return 0;
1366 #endif
1367
1368                 case CUTSCENES_TAB:
1369 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1370                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1371                         gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
1372                         return 1;
1373 #else
1374                         return 0;
1375 #endif
1376
1377                 case CREDITS_TAB:
1378 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1379                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1380                         gameseq_post_event(GS_EVENT_CREDITS);
1381                         return 1;
1382 #else 
1383                         return 0;
1384 #endif
1385
1386                 case PREV_ENTRY_BUTTON:
1387                         tech_prev_entry();
1388                         break;
1389
1390                 case NEXT_ENTRY_BUTTON:
1391                         tech_next_entry();
1392                         break;
1393
1394 #ifdef MAKE_FS1
1395                 case PREV_ENTRY_BUTTON2:
1396                         tech_prev_entry();
1397                         break;
1398
1399                 case NEXT_ENTRY_BUTTON2:
1400                         tech_next_entry();
1401                         break;
1402 #endif
1403
1404                 case SCROLL_LIST_UP:
1405                         tech_scroll_list_up();
1406 #ifndef MAKE_FS1
1407                         Tech_slider.forceUp();
1408 #endif
1409                         break;
1410
1411                 case SCROLL_LIST_DOWN:
1412                         tech_scroll_list_down();
1413 #ifndef MAKE_FS1
1414                         Tech_slider.forceDown();
1415 #endif
1416                         break;
1417
1418                 case SCROLL_INFO_UP:
1419                         tech_scroll_info_up();
1420                         break;
1421
1422                 case SCROLL_INFO_DOWN:
1423                         tech_scroll_info_down();
1424                         break;
1425
1426                 case HELP_BUTTON:
1427                         launch_context_help();
1428                         gamesnd_play_iface(SND_HELP_PRESSED);
1429                         break;
1430
1431                 case OPTIONS_BUTTON:
1432                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1433                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1434                         break;
1435
1436                 case EXIT_BUTTON:
1437                         gamesnd_play_iface(SND_COMMIT_PRESSED);
1438                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1439                         break;
1440         }
1441
1442         return 0;
1443 }
1444
1445 int techroom_load_ani(anim **animpp, char *name)
1446 {
1447         int load_attempts = 0;
1448         char anim_filename[64] = "2_";
1449
1450         // hi-res support
1451         // (i dont think there are any hi-res anims for these tho)
1452         if (gr_screen.res == GR_1024) {
1453                 SDL_strlcat(anim_filename, name, sizeof(anim_filename));
1454         } else {
1455                 SDL_strlcpy(anim_filename, name, sizeof(anim_filename));
1456         }
1457
1458         while(1) {
1459                 if ( load_attempts++ > 5 ) {
1460                         // Tech_room_ask_for_cd = 0;
1461                         return 0;
1462                 }
1463
1464                 *animpp = anim_load(anim_filename);
1465                 if ( *animpp ) {
1466                         return 1;
1467                 } else if (gr_screen.res == GR_1024) {
1468                         // try to load low-res version if hi-res failed
1469                         *animpp = anim_load(name);
1470                         if (*animpp) {
1471                                 return 1;
1472                         }
1473                 }
1474
1475                 // couldn't load animation, ask user to insert CD (if necessary)
1476                 // if ( Tech_room_ask_for_cd ) {
1477                         // if ( game_do_cd_check() == 0 ) {
1478                                 // Tech_room_ask_for_cd = 0;
1479                                 // break;
1480                         // }
1481                 // }
1482         }
1483
1484         // bogus
1485         return 0;
1486 }
1487
1488
1489 void techroom_intel_init()
1490 {
1491         int rval;
1492         static int inited = 0;
1493
1494         // open localization
1495         lcl_ext_open();
1496
1497         if (!inited) {
1498                 if ((rval = setjmp(parse_abort)) != 0) {
1499                         // close localization
1500                         lcl_ext_close();
1501
1502                         return;
1503                 } else {
1504                         read_file_text("species.tbl");
1505                         reset_parse();
1506
1507                         Intel_info_size = 0;
1508
1509 #ifndef MAKE_FS1
1510                         while (optional_string("$Entry:")) {
1511                                 SDL_assert(Intel_info_size < MAX_INTEL_ENTRIES);
1512                                 if (Intel_info_size >= MAX_INTEL_ENTRIES) break;
1513
1514                                 required_string("$Name:");
1515                                 stuff_string(Intel_info[Intel_info_size].name, F_NAME, NULL, 32);
1516                                 required_string("$Anim:");
1517                                 stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NULL, 32);
1518                                 required_string("$AlwaysInTechRoom:");
1519                                 stuff_int(&Intel_info[Intel_info_size].in_tech_db);
1520                                 required_string("$Description:");
1521                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1522
1523
1524                                 Intel_info_size++;
1525                         }
1526 #else
1527                         if (optional_string("$Terran Tech Description:")) {
1528                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1529                                 SDL_strlcpy(Intel_info[Intel_info_size].name, "Terran", sizeof(Intel_info[0].name));
1530                                 SDL_strlcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[0], sizeof(Intel_info[0].anim_filename));
1531                                 Intel_info[Intel_info_size].in_tech_db = 1;
1532
1533                                 Intel_info_size++;
1534                         }
1535                         
1536                         if (optional_string("$Vasudan Tech Description:")) {
1537
1538                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1539                                 SDL_strlcpy(Intel_info[Intel_info_size].name, "Vasudan", sizeof(Intel_info[0].name));
1540                                 SDL_strlcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[1], sizeof(Intel_info[0].anim_filename));
1541                                 Intel_info[Intel_info_size].in_tech_db = 1;
1542
1543                                 Intel_info_size++;
1544                         }
1545                         
1546                         if (optional_string("$Shivan Tech Description:")) {
1547
1548                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1549                                 SDL_strlcpy(Intel_info[Intel_info_size].name, "Shivan", sizeof(Intel_info[0].name));
1550                                 SDL_strlcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[2], sizeof(Intel_info[0].anim_filename));
1551                                 // FIXME: shouldn't always be in the intel database but no choice at this point
1552                                 // there are only about 4 missions before they show up anyway so it may not be worth it
1553                                 Intel_info[Intel_info_size].in_tech_db = 1;
1554
1555                                 Intel_info_size++;
1556                         }
1557 #endif
1558                         inited = 1;
1559                 }
1560         }
1561
1562         // close localization
1563         lcl_ext_close();
1564 }
1565
1566 void techroom_init()
1567 {
1568         int i, idx;
1569         techroom_buttons *b;
1570
1571         gr_reset_clip();
1572         gr_clear();
1573         Mouse_hidden++;
1574         gr_flip();
1575         Mouse_hidden--;
1576
1577         Ships_loaded = 0;
1578         Weapons_loaded = 0;
1579         Intel_loaded = 0;
1580
1581         // Tech_room_ask_for_cd = 1;
1582
1583         // backup and bash detail level stuff
1584         Tech_detail_backup = Detail.detail_distance;
1585         Detail.detail_distance = MAX_DETAIL_LEVEL;
1586         Tech_texture_backup = Detail.hardware_textures;
1587         Detail.hardware_textures = MAX_DETAIL_LEVEL;
1588
1589         /*
1590         Palette_bmp = bm_load("TechDataPalette");
1591         SDL_assert(Palette_bmp);
1592         bm_get_palette(Palette_bmp, Palette, Palette_name);  // get the palette for this bitmap
1593         gr_set_palette(Palette_name, Palette, 1);
1594         */
1595
1596 #ifdef MAKE_FS1
1597         common_set_interface_palette("TechDataPalette");
1598 #endif
1599
1600         // unflag fullneb 
1601         The_mission.flags &= ~MISSION_FLAG_FULLNEB;
1602
1603         // set up UI stuff
1604         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1605 #ifndef MAKE_FS1  // do this with techroom_tab_setup()
1606         Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1607 #endif
1608
1609         Tech_background_bitmap = bm_load(Tech_background_filename[gr_screen.res]);
1610         if (Tech_background_bitmap < 0) {
1611                 // failed to load bitmap, not a good thing
1612                 Int3();
1613         }
1614
1615 #ifdef MAKE_FS1 // for weapons/species tab
1616         Tech_data_background_bitmap = bm_load(Tech_data_background_filename);
1617         if (Tech_data_background_bitmap < 0) {
1618                 // failed to load bitmap, not a good thing
1619                 Int3();
1620         }
1621
1622         techroom_tab_setup(0);
1623
1624         // don't draw buttons that are only on other tabs
1625         for (i=0; i<PREV_ENTRY_BUTTON2; i++) {
1626 #else
1627         for (i=0; i<NUM_BUTTONS; i++) {
1628 #endif
1629                 b = &Buttons[gr_screen.res][i];
1630
1631                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1632                 // set up callback for when a mouse first goes over a button
1633                 if (b->filename) {
1634                         b->button.set_bmaps(b->filename);
1635 //                      if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1636                                 b->button.set_highlight_action(common_play_highlight_sound);
1637 //                      }
1638
1639                 } else {
1640                         b->button.hide();
1641                 }
1642
1643                 b->button.link_hotspot(b->hotspot);
1644         }
1645         
1646 #ifndef MAKE_FS1
1647         // common tab button text
1648         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);
1649         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);
1650         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);
1651         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);
1652
1653         // common ship/weapon/intel text
1654         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);
1655         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);
1656         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);
1657
1658         // common help/options/commit text
1659
1660         // NK: removed these two text labels on Tech screen update 4/26/99
1661 //      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);
1662 //      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);                
1663         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);             
1664 #endif
1665
1666         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1667                 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1668                 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1669         }
1670
1671         // set some hotkeys
1672         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.set_hotkey(SDLK_LEFT);
1673         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.set_hotkey(SDLK_RIGHT);
1674 #ifndef MAKE_FS1 // set per tab
1675         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(SDLK_UP);
1676         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(SDLK_DOWN);
1677 #endif
1678
1679
1680         for (i=0; i<LIST_BUTTONS_MAX; i++) {
1681                 List_buttons[i].create(&Ui_window, "", 0, 0, 60, 30, 0, 1);
1682                 List_buttons[i].hide();
1683                 List_buttons[i].disable();
1684         }
1685
1686         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);
1687         View_window.hide();
1688
1689 #ifdef MAKE_FS1
1690         ShipWin01 = bm_load(NOX("ShipWin01"));
1691         ShipWin02 = bm_load(NOX("ShipWin02"));
1692         ShipWin03 = bm_load(NOX("ShipWin03"));
1693         ShipWin04 = bm_load(NOX("ShipWin04"));
1694 #endif
1695
1696         Buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(SDLK_F1);
1697         Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | SDLK_RETURN);
1698         Buttons[gr_screen.res][SCROLL_LIST_UP].button.set_hotkey(SDLK_PAGEUP);
1699         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.set_hotkey(SDLK_PAGEDOWN);
1700
1701         // init help overlay states
1702         help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1703
1704         // setup slider
1705 #ifndef MAKE_FS1
1706         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);
1707 #endif
1708
1709         Cur_anim_instance = NULL;
1710
1711         // zero weapon and intel anim/bitmap stuff
1712         for(idx=0; idx<MAX_WEAPON_TYPES; idx++){
1713                 Weapon_list[idx].animation = NULL;
1714                 Weapon_list[idx].bitmap = -1;
1715         }
1716         for(idx=0; idx<MAX_INTEL_ENTRIES; idx++){
1717                 Intel_list[idx].animation = NULL;
1718                 Intel_list[idx].bitmap = -1;
1719         }
1720
1721         Anim_playing_id = -1;
1722         techroom_change_tab(Tab);
1723 }
1724
1725 void techroom_close()
1726 {
1727         int i;
1728
1729         techroom_stop_anim(-1);
1730         for (i=0; i<MAX_WEAPON_TYPES; i++) {
1731                 if ( Weapon_list[i].animation ) {
1732                         anim_free(Weapon_list[i].animation);
1733                         Weapon_list[i].animation = NULL;
1734                 }
1735                 if( Weapon_list[i].bitmap >= 0 ){
1736                         bm_unload(Weapon_list[i].bitmap);
1737                         Weapon_list[i].bitmap = -1;
1738                 }
1739         }
1740
1741         for (i=0; i<MAX_INTEL_ENTRIES; i++){
1742                 if (Intel_list[i].animation != NULL) {
1743                         anim_free(Intel_list[i].animation);
1744                         Intel_list[i].animation = NULL;
1745                 }
1746                 if( Intel_list[i].bitmap >= 0 ){
1747                         bm_unload(Intel_list[i].bitmap);
1748                         Intel_list[i].bitmap = -1;
1749                 }
1750         }
1751
1752         Ships_loaded = 0;
1753         Weapons_loaded = 0;
1754         Intel_loaded = 0;
1755
1756 #ifdef MAKE_FS1
1757         if (ShipWin01){
1758                 bm_unload(ShipWin01);
1759         }
1760         if (ShipWin02){
1761                 bm_unload(ShipWin02);
1762         }
1763         if (ShipWin03){
1764                 bm_unload(ShipWin03);
1765         }
1766         if (ShipWin04){
1767                 bm_unload(ShipWin04);
1768         }
1769
1770         if (Tech_data_background_bitmap) {
1771                 bm_unload(Tech_data_background_bitmap);
1772         }
1773 #endif
1774
1775         if (Tech_background_bitmap) {
1776                 bm_unload(Tech_background_bitmap);
1777         }
1778
1779         Ui_window.destroy();
1780         common_free_interface_palette();                // restore game palette
1781         /*
1782         if (Palette_bmp){
1783                 bm_unload(Palette_bmp);
1784         }
1785         */
1786
1787         // restore detail settings
1788         Detail.detail_distance = Tech_detail_backup;
1789         Detail.hardware_textures = Tech_texture_backup;
1790 }
1791
1792 #ifdef MAKE_FS1
1793 void techroom_data_init()
1794 {
1795         int i;
1796         techroom_buttons *b;
1797
1798         for (i=PREV_ENTRY_BUTTON2; i<NUM_BUTTONS; i++) {
1799                 b = &Buttons[gr_screen.res][i];
1800
1801                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1802                 // set up callback for when a mouse first goes over a button
1803                 if (b->filename) {
1804                         b->button.set_bmaps(b->filename);
1805                         b->button.set_highlight_action(common_play_highlight_sound);
1806                 } else {
1807                         b->button.hide();
1808                 }
1809
1810                 b->button.link_hotspot(b->hotspot);
1811         }
1812 }
1813
1814 void techroom_tab_setup(int set_palette)
1815 {
1816         // char *pal;
1817         int i;
1818         int flags[256];
1819
1820         for (i=0; i<256; i++){
1821                 flags[i] = 0;
1822         }
1823
1824         // activate, deactivate any necessary controls
1825         for (i=0; i<NUM_BUTTONS; i++) {
1826                 Buttons[gr_screen.res][i].button.enable();
1827                 if (Buttons[gr_screen.res][i].filename)
1828                         Buttons[gr_screen.res][i].button.unhide();
1829         }
1830
1831         // do other special processing
1832         switch (Tab) {
1833                 case SHIPS_DATA_TAB:
1834                         // set the mask for this tab
1835                         Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1836
1837                         // setup hotkeys to scroll list
1838                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(SDLK_UP);
1839                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(SDLK_DOWN);
1840
1841                         // hide extra buttons
1842                         Buttons[gr_screen.res][PREV_ENTRY_BUTTON2].button.hide();
1843                         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON2].button.hide();
1844                         break;
1845
1846                 case WEAPONS_DATA_TAB:
1847                         // set the mask for this tab
1848                         Ui_window.set_mask_bmap(Tech_data_mask_filename);
1849
1850                         // the list isn't supposed to scroll so clear the hotkeys
1851                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(-1);
1852                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(-1);
1853
1854                         // hide extra buttons
1855                         Buttons[gr_screen.res][SCROLL_LIST_UP].button.hide();
1856                         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.hide();
1857                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.hide();
1858                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.hide();
1859                         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.hide();
1860                         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.hide();
1861                         break;
1862
1863                 case INTEL_DATA_TAB:
1864                         // set the mask for this tab
1865                         Ui_window.set_mask_bmap(Tech_data_mask_filename);
1866
1867                         // the list isn't supposed to scroll so clear the hotkeys
1868                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(-1);
1869                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(-1);
1870
1871                         // hide extra buttons
1872                         Buttons[gr_screen.res][SCROLL_LIST_UP].button.hide();
1873                         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.hide();
1874                         Buttons[gr_screen.res][SCROLL_INFO_UP].button.hide();
1875                         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.hide();
1876                         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.hide();
1877                         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.hide();
1878                         break;
1879         }
1880 }
1881 #endif
1882
1883 void techroom_do_frame(float frametime)
1884 {
1885         int i, k;       
1886
1887         // turn off controls when overlay is on
1888         if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1889                 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
1890                 Ui_window.set_ignore_gadgets(1);
1891         }
1892
1893         // turn off controls in trackball mode
1894         if (Trackball_active) {
1895                 Ui_window.set_ignore_gadgets(1);
1896         } else {
1897                 Ui_window.set_ignore_gadgets(0);
1898         }
1899
1900         k = Ui_window.process() & ~KEY_DEBUGGED;
1901
1902         if ( (k > 0) || B1_JUST_RELEASED ) {
1903                 if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1904                         help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1905                         Ui_window.set_ignore_gadgets(0);
1906                         k = 0;
1907                 }
1908         }
1909
1910         if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
1911                 Ui_window.set_ignore_gadgets(0);
1912         }
1913
1914         switch (k) {
1915                 case KEY_SHIFTED | SDLK_TAB:  // activate previous tab
1916                         i = Tab - 1;
1917                         if (i < 0) {
1918                                 i = NUM_TABS - 1;
1919                         }
1920
1921                         techroom_change_tab(i);
1922                         break;
1923
1924                 case SDLK_TAB:  // activate next tab
1925                         i = Tab + 1;
1926                         if (i >= NUM_TABS) {
1927                                 i = 0;
1928                         }
1929
1930                         techroom_change_tab(i);
1931                         break;
1932
1933                 case KEY_CTRLED | SDLK_DOWN:
1934                         if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
1935                                 techroom_button_pressed(SIMULATOR_TAB);
1936                                 break;
1937                         }
1938                         // fall through
1939
1940                 case KEY_CTRLED | SDLK_UP:
1941                         techroom_button_pressed(CREDITS_TAB);
1942                         break;
1943 /*
1944                 case SDLK_UP:
1945                         tech_prev_entry();
1946                         break;
1947
1948                 case SDLK_DOWN:
1949                         tech_next_entry();
1950                         break;
1951 */
1952                 case KEY_CTRLED | SDLK_RETURN:
1953                 case SDLK_ESCAPE:
1954                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1955                         break;
1956         }       
1957
1958         // check ship model window for activity
1959         if (View_window.pressed()) {
1960                 Trackball_active = 1;
1961                 Trackball_mode = 1;
1962         }
1963         if (B1_RELEASED) {
1964                 Trackball_active = 0;
1965         }
1966
1967         // check all da buttons
1968         for (i=0; i<NUM_BUTTONS; i++) {
1969                 if (Buttons[gr_screen.res][i].button.pressed()) {
1970                         if (techroom_button_pressed(i)) {
1971                                 return;
1972                         }
1973                 }
1974         }
1975
1976         // check for mouseovers/clicks on the selection list
1977         Select_tease_line = -1;
1978         for (i=0; i<LIST_BUTTONS_MAX; i++) {
1979                 if (List_buttons[i].is_mouse_on()) {
1980                         Select_tease_line = i + List_offset;
1981                 }
1982         
1983                 if (List_buttons[i].pressed()) {
1984                         Cur_entry = i + List_offset;
1985                         gamesnd_play_iface(SND_USER_SELECT);
1986                         techroom_select_new_entry();
1987                 }
1988         }
1989
1990 #ifndef MAKE_FS1  // do this per tab instead
1991         // clear & draw bg bitmap
1992         GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
1993         if (Tech_background_bitmap >= 0) {
1994                 gr_set_bitmap(Tech_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1995                 gr_bitmap(0, 0);
1996         }
1997 #endif
1998
1999         // render
2000         switch (Tab) {
2001                 case SHIPS_DATA_TAB:
2002 #ifdef MAKE_FS1
2003                         // clear & draw bg bitmap
2004                         GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
2005                         if (Tech_background_bitmap >= 0) {
2006                                 gr_set_bitmap(Tech_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2007                                 gr_bitmap(0, 0);
2008                         }
2009 #endif
2010                         techroom_ships_render(frametime);
2011
2012 #ifdef MAKE_FS1
2013                         if (ShipWin01) {
2014                                 gr_set_bitmap(ShipWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2015                                 gr_bitmap(223, 104);
2016                         }
2017
2018                         if (ShipWin02) {
2019                                 gr_set_bitmap(ShipWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2020                                 gr_bitmap(621, 124);
2021                         }
2022
2023                         if (ShipWin03) {
2024                                 gr_set_bitmap(ShipWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2025                                 gr_bitmap(223, 338);
2026                         }
2027
2028                         if (ShipWin04) {
2029                                 gr_set_bitmap(ShipWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2030                                 gr_bitmap(218, 124);
2031                         }
2032 #endif
2033
2034                         break;
2035
2036                 case WEAPONS_DATA_TAB:
2037 #ifdef MAKE_FS1
2038                         // clear & draw bg bitmap
2039                         GR_MAYBE_CLEAR_RES(Tech_data_background_bitmap);
2040                         if (Tech_data_background_bitmap >= 0) {
2041                                 gr_set_bitmap(Tech_data_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2042                                 gr_bitmap(0, 0);
2043                         }
2044 #endif
2045                         techroom_weapons_render2(frametime);
2046
2047                         break;
2048
2049                 case INTEL_DATA_TAB:
2050 #ifdef MAKE_FS1
2051                         // clear & draw bg bitmap
2052                         GR_MAYBE_CLEAR_RES(Tech_data_background_bitmap);
2053                         if (Tech_data_background_bitmap >= 0) {
2054                                 gr_set_bitmap(Tech_data_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2055                                 gr_bitmap(0, 0);
2056                         }
2057 #endif
2058                         techroom_intel_render(frametime);
2059
2060                         break;
2061         }
2062
2063         Ui_window.draw();
2064
2065         for (i=TECH_DATABASE_TAB; i<=CREDITS_TAB; i++) {
2066                 if (Buttons[gr_screen.res][i].button.button_down()) {
2067                         break;
2068                 }
2069         }
2070         if (i > CREDITS_TAB) {
2071                 Buttons[gr_screen.res][TECH_DATABASE_TAB].button.draw_forced(2);
2072         }
2073
2074         for (i=0; i<NUM_TABS; i++){
2075                 if (Buttons[gr_screen.res][i].button.button_down()){
2076                         break;
2077                 }
2078         }
2079         if (i == NUM_TABS){
2080                 Buttons[gr_screen.res][Tab].button.draw_forced(2);
2081         }
2082
2083         // blit help overlay if active
2084         help_overlay_maybe_blit(TECH_ROOM_OVERLAY);
2085
2086         gr_flip();
2087 }
2088