]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamehelp/contexthelp.cpp
const-char warning fixes
[taylor/freespace2.git] / src / gamehelp / contexthelp.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/GameHelp/ContextHelp.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Functions to drive the context-sensitive help 
16  *
17  * $Log$
18  * Revision 1.8  2005/03/29 02:18:47  taylor
19  * Various 64-bit platform fixes
20  * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
21  * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
22  * Streaming audio support (big thanks to Pierre Willenbrock!!)
23  * Removed dependance on strings.tbl for FS1 since we don't actually need it now
24  *
25  * Revision 1.7  2004/09/20 01:31:44  theoddone33
26  * GCC 3.4 fixes.
27  *
28  * Revision 1.6  2003/06/11 18:30:32  taylor
29  * plug memory leaks
30  *
31  * Revision 1.5  2003/05/25 02:30:42  taylor
32  * Freespace 1 support
33  *
34  * Revision 1.4  2002/06/17 06:33:09  relnev
35  * ryan's struct patch for gcc 2.95
36  *
37  * Revision 1.3  2002/06/09 04:41:17  relnev
38  * added copyright header
39  *
40  * Revision 1.2  2002/05/07 03:16:44  theoddone33
41  * The Great Newline Fix
42  *
43  * Revision 1.1.1.1  2002/05/03 03:28:09  root
44  * Initial import.
45  *
46  * 
47  * 16    8/22/99 4:22p Jefff
48  * removed 2nd tech room overlay stuff
49  * 
50  * 15    8/09/99 5:54p Jefff
51  * tech room overlay changes
52  * 
53  * 14    7/27/99 7:18p Jefff
54  * fixed a debug function for adjsuting overlays in-game
55  * 
56  * 13    7/20/99 1:49p Dave
57  * Peter Drake build. Fixed some release build warnings.
58  * 
59  * 12    7/16/99 10:07a Jefff
60  * Removed legacy bitmap overlay code
61  * 
62  * 11    7/16/99 10:04a Jefff
63  * 
64  * 10    7/15/99 9:20a Andsager
65  * FS2_DEMO initial checkin
66  * 
67  * 9     7/11/99 6:40p Jefff
68  * 
69  * 8     7/08/99 6:25p Jefff
70  * got new help system working
71  * 
72  * 7     6/03/99 10:15p Dave
73  * Put in temporary main hall screen.
74  * 
75  * 6     3/25/99 8:32p Neilk
76  * temporary barracks help removal
77  * 
78  * 5     2/15/99 9:37a Dave
79  * Removed infinite loop from context help parse code.
80  * 
81  * 4     2/11/99 4:05p Neilk
82  * Temporary checkin
83  * 
84  * 3     1/29/99 2:37p Neilk
85  * foundation for a new help system
86  * 
87  * 2     10/07/98 10:52a Dave
88  * Initial checkin.
89  * 
90  * 1     10/07/98 10:48a Dave
91  * 
92  * 92    5/06/98 11:49p Lawrance
93  * Add help overlay for command brief
94  * 
95  * 91    5/05/98 1:49a Lawrance
96  * Add in missing help overlays
97  * 
98  * 90    4/25/98 2:00p Dave
99  * Installed a bunch of multiplayer context help screens. Reworked ingame
100  * join ship select screen. Fix places where network timestamps get hosed.
101  * 
102  * 89    4/20/98 12:03a Lawrance
103  * make gray help shader lighter
104  * 
105  * 88    4/11/98 7:59p Lawrance
106  * Add support for help overlays
107  * 
108  * 87    3/12/98 5:36p John
109  * Took out any unused shaders.  Made shader code take rgbc instead of
110  * matrix and vector since noone used it like a matrix and it would have
111  * been impossible to do in hardware.   Made Glide implement a basic
112  * shader for online help.  
113  * 
114  * 86    3/09/98 9:55p Lawrance
115  * split off gameplay help, rip out obsolete code
116  * 
117  * 85    3/05/98 11:15p Hoffoss
118  * Changed non-game key checking to use game_check_key() instead of
119  * game_poll().
120  * 
121  * 84    2/28/98 9:47p Lawrance
122  * Fix couple of typos
123  * 
124  * 83    2/28/98 7:02p Lawrance
125  * overhaul on-line help
126  * 
127 */
128 #include <string.h>
129 #include <setjmp.h>
130
131 #include "contexthelp.h"
132 #include "gamesequence.h"
133 #include "freespace.h"
134 #include "mainhallmenu.h"
135 #include "key.h"
136 #include "bmpman.h"
137 #include "2d.h"
138 #include "timer.h"
139 #include "math.h"
140 #include "mouse.h"
141 #include "controlsconfig.h"
142 #include "techmenu.h"
143 #include "parselo.h"
144 #include "localize.h"
145 #include "alphacolors.h"
146
147
148 ////////////////////////////////////////////////////////////////////
149 // private function prototypes / structs
150 ////////////////////////////////////////////////////////////////////
151 void parse_helptbl();
152 void help_overlay_blit(int overlay_id);
153 void help_overlay_init();
154
155
156 typedef struct {
157         int x_begin, y_begin, x_end, y_end;
158 } help_line;
159
160 typedef struct {
161         vector vtx[HELP_MAX_PLINE_VERTICES];
162         vector *pvtx[HELP_MAX_PLINE_VERTICES];
163         int vtxcount;
164 } help_pline;
165
166 typedef struct {
167         int x_coord, y_coord;
168         char* string;
169 } help_text;
170
171 typedef struct {
172         int x_coord, y_coord;
173 } help_left_bracket;
174
175 typedef struct {
176         int x_coord, y_coord;
177 } help_right_bracket;
178
179 typedef struct {
180         help_pline                              plinelist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
181         help_text                               textlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
182         help_left_bracket               lbracketlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
183         help_right_bracket      rbracketlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
184         int plinecount;
185         int textcount;
186         int lbracketcount;
187         int rbracketcount;
188 } help_overlay;
189
190 // Added for FS1
191 const char *Help_overlays[MAX_HELP_OVERLAYS] = {
192         "ship_help_over",
193         "weapon_help_over",
194 #ifndef FS1_DEMO
195         "brief_help_over",
196         "main_help_overlay",
197 #else
198         "Briefing_Help_Overlay_Demo",
199         "main_help_overlay_demo",
200 #endif
201         "barracks_help",
202         "control_help",
203         "debrief_help",
204         "multicreate_help",
205         "multistart_help",
206         "multijoin_help",
207         "main_help_overlay2",
208         "hotkey_help",
209         "campaign_help",
210         "simulator_help",
211         "tech_help",
212 //      "tech_help2",
213         "command_help"
214 };
215
216 // new help.tbl file way
217 const char *help_overlay_section_names[MAX_HELP_OVERLAYS] = {
218         "$ship",                                        // ship_help
219         "$weapon",                              // weapon_help
220         "$briefing",                    // briefing
221         "$main",                                        //      main help overlay
222         "$barracks",                    // barracks
223         "$control",                             // control help
224         "$debrief",                             // debrief help
225         "$multicreate",         // multicreate help
226         "$multistart",                  // multistart help
227         "$multijoin",                   // multijoin help
228         "$main2",                               // main help overlay2
229         "$hotkey",                              // hotkey help
230         "$campaign",                    // campaign help
231         "$simulator",                   //      simulator help
232         "$tech",                                        // tech help
233         "$command"                              // command help
234 };
235
236 ////////////////////////////////////////////////////////////////////
237 // Game-wide globals
238 ////////////////////////////////////////////////////////////////////
239 shader Grey_shader;
240
241 ////////////////////////////////////////////////////////////////////
242 // Module globals
243 ////////////////////////////////////////////////////////////////////
244 #ifndef MAKE_FS1
245 static int help_left_bracket_bitmap;
246 static int help_right_bracket_bitmap;
247 #endif
248 static help_overlay help_overlaylist[MAX_HELP_OVERLAYS];
249
250 static int current_helpid = -1;         // the currently active overlay_id, only really used for the debug console funxions
251 int Help_overlay_flags;
252 static int Source_game_state;                   // state from where F1 was pressed
253
254 #ifdef MAKE_FS1
255 static int Overlay = -1;
256 #endif
257
258 ////////////////////////////////////////////////////////////////////
259 // Public Functions
260 ////////////////////////////////////////////////////////////////////
261
262
263 // query whether a help overlay is active (ie being displayed)
264 int help_overlay_active(int overlay_id)
265 {
266         Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
267         return Help_overlay_flags & (1<<overlay_id);
268 }
269
270 // stop displaying a help overlay
271 void help_overlay_set_state(int overlay_id, int state)
272 {
273         Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
274
275         if ( state > 0 ) {
276                 Help_overlay_flags |= (1<<overlay_id);
277                 current_helpid = overlay_id;
278         } else {
279                 Help_overlay_flags &= ~(1<<overlay_id);
280                 //current_helpid = -1;
281         }
282
283 }
284
285 // load in the bitmap for a help overlay
286 // FIXME - leftover from the old bitmap overlay days - prune this out sometime
287 void help_overlay_load(int overlay_id)
288 {
289         return;
290
291
292 // unload a bitmap of a help overlay
293 // FIXME - leftover from the old bitmap overlay days - prune this out sometime
294 void help_overlay_unload(int overlay_id)
295 {
296 #ifdef MAKE_FS1
297         if (Overlay >= 0) {
298                 bm_unload(Overlay);
299         }
300 #else
301         return; 
302 #endif
303 }
304
305 // maybe blit a bitmap of a help overlay to the screen
306 void help_overlay_maybe_blit(int overlay_id)
307 {
308         Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
309
310         if ( Help_overlay_flags & (1<<overlay_id) ) {
311                 context_help_grey_screen();
312                 help_overlay_blit(overlay_id);                          
313         }
314 }
315
316 // reset the flags for the help overlays
317 void help_overlay_reset_all()
318 {
319         Help_overlay_flags = 0;
320 }
321
322 // Set up Grey_shader, which is used game-wide to grey out background when using help overlays
323 void create_grey_shader()
324 {
325         float tmp,c;
326
327         tmp = 0.4f/3.0f;
328
329         // The c matrix brightens everything a bit.
330 //      c = 0.125f;
331         c = 0.110f;
332
333         gr_create_shader( &Grey_shader, tmp, tmp, tmp, c );
334 }
335
336 // called at game startup to init all help related data
337 void context_help_init() 
338 {
339         create_grey_shader();
340         help_overlay_reset_all();
341         help_overlay_init();
342 }
343
344 // called in game_shutdown() to clean up help stuff
345 void context_help_close()
346 {
347 #ifndef MAKE_FS1
348         int i, j;
349
350         for (i=0; i<MAX_HELP_OVERLAYS; i++) {
351                 for (j=0; j<HELP_MAX_ITEM; j++) {
352                         if (help_overlaylist[i].textlist[GR_640][j].string != NULL) {
353                                 free(help_overlaylist[i].textlist[GR_640][j].string);
354                                 help_overlaylist[i].textlist[GR_640][j].string = NULL;
355                         }
356                 }
357         }
358 #endif
359 }
360
361 void context_help_grey_screen()
362 {
363         gr_set_shader(&Grey_shader);
364         gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height);
365 }
366
367 // launch_context_help() will switch to a context sensitive help state
368 void launch_context_help()
369 {
370         // look at the state the game was in when F1 was pressed
371         Source_game_state = gameseq_get_state();
372
373         switch (Source_game_state) {
374
375                 case GS_STATE_MAIN_MENU:
376 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
377                         int main_hall_num;
378                         main_hall_num = (main_hall_id() == 0) ? MH_OVERLAY : MH2_OVERLAY;
379                         if ( !help_overlay_active(main_hall_num) ) {
380                                 help_overlay_set_state(main_hall_num, 1);
381                         }
382                         else {
383                                 help_overlay_set_state(main_hall_num, 0);
384                         }
385 #endif
386                         break;
387
388                 case GS_STATE_GAME_PLAY:
389                 case GS_STATE_GAME_PAUSED:
390                 case GS_STATE_TRAINING_PAUSED:
391                         gameseq_post_event(GS_EVENT_GAMEPLAY_HELP);
392                         break;
393
394                 case GS_STATE_BRIEFING:
395                         if ( !help_overlay_active(BR_OVERLAY) ) {
396                                 help_overlay_set_state(BR_OVERLAY, 1);
397                         }
398                         else {
399                                 help_overlay_set_state(BR_OVERLAY, 0);
400                         }
401                         break;
402
403                 case GS_STATE_SHIP_SELECT:
404                         if ( !help_overlay_active(SS_OVERLAY) ) {
405                                 help_overlay_set_state(SS_OVERLAY, 1);
406                         }
407                         else {
408                                 help_overlay_set_state(SS_OVERLAY, 0);
409                         }
410                         break;
411
412                 case GS_STATE_WEAPON_SELECT:
413                         if ( !help_overlay_active(WL_OVERLAY) ) {
414                                 help_overlay_set_state(WL_OVERLAY, 1);
415                         }
416                         else {
417                                 help_overlay_set_state(WL_OVERLAY, 0);
418                         }
419                         break;
420
421                 case GS_STATE_BARRACKS_MENU:
422                         if ( !help_overlay_active(BARRACKS_OVERLAY) ) {
423                                 help_overlay_set_state(BARRACKS_OVERLAY, 1);
424                         }
425                         else {
426                                 help_overlay_set_state(BARRACKS_OVERLAY, 0);
427                         }
428                         break;
429
430                 case GS_STATE_CONTROL_CONFIG:
431                         if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
432                                 help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 1);
433                         }
434                         else {
435                                 help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
436                         }
437                         break;
438
439                 case GS_STATE_DEBRIEF:
440                         if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
441                                 help_overlay_set_state(DEBRIEFING_OVERLAY, 1);
442                         }
443                         else {
444                                 help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
445                         }
446                         break;
447
448                 case GS_STATE_MULTI_HOST_SETUP:
449                         if ( !help_overlay_active(MULTI_CREATE_OVERLAY) ) {
450                                 help_overlay_set_state(MULTI_CREATE_OVERLAY, 1);
451                         }
452                         else {
453                                 help_overlay_set_state(MULTI_CREATE_OVERLAY, 0);
454                         }
455                         break;
456
457                 case GS_STATE_MULTI_START_GAME:
458                         if ( !help_overlay_active(MULTI_START_OVERLAY) ) {
459                                 help_overlay_set_state(MULTI_START_OVERLAY, 1);
460                         }
461                         else {
462                                 help_overlay_set_state(MULTI_START_OVERLAY, 0);
463                         }
464                         break;
465
466                 case GS_STATE_MULTI_JOIN_GAME:
467                         if ( !help_overlay_active(MULTI_JOIN_OVERLAY) ) {
468                                 help_overlay_set_state(MULTI_JOIN_OVERLAY, 1);
469                         }
470                         else {
471                                 help_overlay_set_state(MULTI_JOIN_OVERLAY, 0);
472                         }
473                         break;
474
475                 case GS_STATE_HOTKEY_SCREEN:
476                         if ( !help_overlay_active(HOTKEY_OVERLAY) ) {
477                                 help_overlay_set_state(HOTKEY_OVERLAY, 1);
478                         }
479                         else {
480                                 help_overlay_set_state(HOTKEY_OVERLAY, 0);
481                         }
482                         break;
483
484                 case GS_STATE_CAMPAIGN_ROOM:
485                         if ( !help_overlay_active(CAMPAIGN_ROOM_OVERLAY) ) {
486                                 help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 1);
487                         }
488                         else {
489                                 help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 0);
490                         }
491                         break;
492
493                 case GS_STATE_SIMULATOR_ROOM:
494                         if ( !help_overlay_active(SIM_ROOM_OVERLAY) ) {
495                                 help_overlay_set_state(SIM_ROOM_OVERLAY, 1);
496                         }
497                         else {
498                                 help_overlay_set_state(SIM_ROOM_OVERLAY, 0);
499                         }
500                         break;
501
502                 case GS_STATE_TECH_MENU: {                              
503                         if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
504                                 help_overlay_set_state(TECH_ROOM_OVERLAY, 1);
505                         }
506                         else {
507                                 help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
508                         }
509                         break;
510                 }
511
512                 case GS_STATE_CMD_BRIEF:
513                         if ( !help_overlay_active(CMD_BRIEF_OVERLAY) ) {
514                                 help_overlay_set_state(CMD_BRIEF_OVERLAY, 1);
515                         }
516                         else {
517                                 help_overlay_set_state(CMD_BRIEF_OVERLAY, 0);
518                         }
519                         break;
520
521                 default:
522                         nprintf(("Warning","WARNING ==> There is no context help available for state %s\n", GS_state_text[Source_game_state-1]));
523                         break;
524
525         } // end switch
526 }
527
528
529 // Called once at the beginning of the game to load help bitmaps & data
530 void help_overlay_init() 
531 {
532 #ifndef MAKE_FS1
533         // load right_bracket bitmap
534         help_right_bracket_bitmap = bm_load("right_bracket");
535         if(help_right_bracket_bitmap < 0){
536                 // we failed to load the bitmap - this is very bad
537                 Int3();
538         }
539
540         // load left_bracket bitmap
541         help_left_bracket_bitmap = bm_load("left_bracket");
542         if(help_left_bracket_bitmap < 0){
543                 // we failed to load the bitmap - this is very bad
544                 Int3();
545         }
546
547         // parse help.tbl
548         parse_helptbl();
549 #endif
550 }
551
552
553 // parses help.tbl and populates help_overlaylist[]
554 void parse_helptbl()
555 {
556 #ifndef MAKE_FS1
557         int overlay_id, currcount;
558         char buf[HELP_MAX_STRING_LENGTH + 1];
559         int i;
560
561         // open localization
562         lcl_ext_open();
563         
564         read_file_text(HELP_OVERLAY_FILENAME);
565
566         // for each overlay...
567         for (overlay_id=0; overlay_id<MAX_HELP_OVERLAYS; overlay_id++) {
568
569                 reset_parse();
570                 skip_to_string(help_overlay_section_names[overlay_id]);
571
572                 // clear out counters in the overlay struct
573                 help_overlaylist[overlay_id].plinecount = 0;
574                 help_overlaylist[overlay_id].textcount = 0;
575                 help_overlaylist[overlay_id].rbracketcount = 0;
576                 help_overlaylist[overlay_id].lbracketcount = 0;
577                 
578                 // read in all elements for this overlay
579                 while (!(check_for_string("$end")))  {
580
581                         if (optional_string("+pline")) {
582
583                                 currcount = help_overlaylist[overlay_id].plinecount;
584                                 int a, b;               // temp vars to read in int before cast to float;
585
586                                 if (currcount < HELP_MAX_ITEM) {
587                                         // read number of pline vertices
588                                         stuff_int(&help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount);         // note that it is read into GR_640
589                                         // help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtxcount = help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount;                    // set equal to 1024 version vertex count to prevent bugs
590                                         Assert(help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount <= HELP_MAX_PLINE_VERTICES);
591                                         // get 640x480 vertex coordinates
592                                         for (i=0; i<help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; i++) {
593                                                 stuff_int(&a);
594                                                 stuff_int(&b);
595                                                 help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.x = (float)a;
596                                                 help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.y = (float)b;
597                                                 help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.z = 0.0f;
598                                                 help_overlaylist[overlay_id].plinelist[GR_640][currcount].pvtx[i] = &help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i];
599                                         }
600                                         // get 1024x768 vertex coordinates
601                                         for (i=0; i<help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; i++) {
602                                                 stuff_int(&a);
603                                                 stuff_int(&b);
604                                                 help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.x = (float)a;
605                                                 help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.y = (float)b;
606                                                 help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.z = 0.0f;
607                                                 help_overlaylist[overlay_id].plinelist[GR_1024][currcount].pvtx[i] = &help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i];
608                                         }
609                                 }
610
611                                 //mprintf(("Found pline - start location (%f,%f), end location (%f,%f)\n", help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[0].x, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[0].y, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[2].x, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[2].y));
612                                 help_overlaylist[overlay_id].plinecount++;
613
614                         } else if (optional_string("+text")) {
615
616                                 currcount = help_overlaylist[overlay_id].textcount;
617
618                                 if (currcount < HELP_MAX_ITEM) {
619                                         // get 640x480 coordinates
620                                         stuff_int(&(help_overlaylist[overlay_id].textlist[GR_640][currcount].x_coord));
621                                         stuff_int(&(help_overlaylist[overlay_id].textlist[GR_640][currcount].y_coord));
622                                         // get 1024x768 coordinates
623                                         stuff_int(&(help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord));
624                                         stuff_int(&(help_overlaylist[overlay_id].textlist[GR_1024][currcount].y_coord));
625
626                                         // get string (always use the GR_640 one)
627                                         stuff_string(buf, F_MESSAGE, NULL);
628                                         help_overlaylist[overlay_id].textlist[GR_640][currcount].string = strdup(buf);
629
630                                         //mprintf(("Found text %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].textlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].textlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord));
631                                         help_overlaylist[overlay_id].textcount++;
632                                 }
633
634                         } else if (optional_string("+right_bracket")) {
635
636                                 currcount = help_overlaylist[overlay_id].rbracketcount;
637
638                                 if (currcount < HELP_MAX_ITEM) {
639                                         // get 640x480 coordinates
640                                         stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].x_coord));
641                                         stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].y_coord));
642                                         // get 1024x768 coordinates
643                                         stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].x_coord));
644                                         stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].y_coord));
645
646                                         //mprintf(("Found rbracket %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].y_coord));
647                                         help_overlaylist[overlay_id].rbracketcount++;
648                                 }
649
650                         } else if (optional_string("+left_bracket")) {
651
652                                 currcount = help_overlaylist[overlay_id].lbracketcount;
653
654                                 if (currcount < HELP_MAX_ITEM) {
655                                         // get 640x480 coordinates
656                                         stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].x_coord));
657                                         stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].y_coord));
658                                         // get 1024x768 coordinates
659                                         stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].x_coord));
660                                         stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].y_coord));
661
662                                         //mprintf(("Found lbracket %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].y_coord));
663                                         help_overlaylist[overlay_id].lbracketcount++;
664                                 }
665
666                         } else {
667                                 // help.tbl is corrupt
668                                 Assert(0);
669
670                         }               // end if
671
672                 }               // end while
673         }               // end for
674
675         // close localization
676         lcl_ext_close();
677 #endif
678 }
679
680
681
682 // draw overlay on the screen
683 void help_overlay_blit(int overlay_id) 
684 {
685 #ifdef MAKE_FS1
686         Overlay = bm_load(Help_overlays[overlay_id]);
687         if (Overlay < 0){
688                 Int3();
689         }
690
691         if (Overlay >= 0){
692                 gr_set_bitmap(Overlay, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
693                 gr_bitmap(0, 0);
694         }
695 #else
696         int idx, width, height;
697         int plinecount = help_overlaylist[overlay_id].plinecount;
698         int textcount = help_overlaylist[overlay_id].textcount;
699         int rbracketcount = help_overlaylist[overlay_id].rbracketcount;
700         int lbracketcount = help_overlaylist[overlay_id].lbracketcount;
701
702         Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
703
704         // this draws each line of help text with white on black text (use the GR_640 index for the string)
705         for (idx = 0; idx < textcount; idx++) {
706                 gr_set_color_fast(&Color_black);
707                 gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist[GR_640][idx].string, strlen(help_overlaylist[overlay_id].textlist[GR_640][idx].string));
708                 gr_rect(help_overlaylist[overlay_id].textlist[gr_screen.res][idx].x_coord-2*HELP_PADDING, help_overlaylist[overlay_id].textlist[gr_screen.res][idx].y_coord-3*HELP_PADDING, width+4*HELP_PADDING, height+4*HELP_PADDING);
709                 gr_set_color_fast(&Color_bright_white);
710                 gr_printf(help_overlaylist[overlay_id].textlist[gr_screen.res][idx].x_coord, help_overlaylist[overlay_id].textlist[gr_screen.res][idx].y_coord, help_overlaylist[overlay_id].textlist[GR_640][idx].string);
711         }
712
713         // this draws each right bracket
714         for (idx = 0; idx < rbracketcount; idx++) {
715                 gr_set_bitmap(help_right_bracket_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
716                 gr_bitmap(help_overlaylist[overlay_id].rbracketlist[gr_screen.res][idx].x_coord, help_overlaylist[overlay_id].rbracketlist[gr_screen.res][idx].y_coord);
717         }
718
719         // this draws each left bracket
720         for (idx = 0; idx < lbracketcount; idx++) {
721                 gr_set_bitmap(help_left_bracket_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
722                 gr_bitmap(help_overlaylist[overlay_id].lbracketlist[gr_screen.res][idx].x_coord, help_overlaylist[overlay_id].lbracketlist[gr_screen.res][idx].y_coord);
723         }       
724
725         // this draws each 2d line for the help screen
726         //gr_set_color_fast(&Color_yellow);
727         gr_set_color(255, 255, 0);
728         for (idx = 0; idx<plinecount; idx++) {
729                 gr_pline_special(help_overlaylist[overlay_id].plinelist[gr_screen.res][idx].pvtx        , help_overlaylist[overlay_id].plinelist[GR_640][idx].vtxcount, HELP_PLINE_THICKNESS);
730         }
731 #endif  // MAKE_FS1
732 }
733
734
735 // --------------------------------------------------
736 // DEBUGGING STUFF
737 // --------------------------------------------------
738
739 DCF(help_reload, "Reloads help overlay data from help.tbl")
740 {
741         if (Dc_command) {
742                 parse_helptbl();
743         }
744
745         if (Dc_help)    {
746                 dc_printf( "Usage: sample\nCrashes your machine.\n" );
747         }
748
749         if (Dc_status)  {
750                 dc_printf( "Yes, my master." );
751         }
752 }
753
754 int h_textnum=0, h_amt=0, h_vtx = 0;
755
756 void nudgetext_x(int textnum, int amount)
757 {
758         help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].x_coord += amount;
759 }
760 void nudgetext_y(int textnum, int amount)
761 {
762         help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].y_coord += amount;
763 }
764 void nudgepline_x(int plinenum, int plinevert, int amount)
765 {
766         help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[plinevert].xyz.x += amount;
767 }
768 void nudgepline_y(int plinenum, int plinevert, int amount)
769 {
770         help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[plinevert].xyz.y += amount;
771 }
772 void nudgerbracket_x(int num, int amount)
773 {
774         help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].x_coord += amount;
775 }
776 void nudgerbracket_y(int num, int amount)
777 {
778         help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].y_coord += amount;
779 }
780 void nudgelbracket_x(int num, int amount)
781 {
782         help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].x_coord += amount;
783 }
784 void nudgelbracket_y(int num, int amount)
785 {
786         help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].y_coord += amount;
787 }
788 void showtextpos(int textnum)
789 {
790         dc_printf("text %d is now located at (%d, %d)", textnum, help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].x_coord, help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].y_coord );
791 }
792 void showrbracketpos(int num)
793 {
794         dc_printf("rbracket %d is now located at (%d, %d)", num, help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].x_coord, help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].y_coord );
795 }
796 void showlbracketpos(int num)
797 {
798         dc_printf("lbracket %d on overlay %d is now located at (%d, %d)", num, current_helpid, help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].x_coord, help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].y_coord );
799 }
800 void showplinepos(int plinenum)
801 {
802         int i;
803         dc_printf("pline %d on overlay %d vertices are now ", plinenum, current_helpid, help_overlaylist[current_helpid].textlist[gr_screen.res][plinenum].y_coord );
804         for (i=0; i<help_overlaylist[current_helpid].plinelist[GR_640][plinenum].vtxcount; i++)
805         {
806                 dc_printf("(%3.0f %3.0f) ", help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[i].xyz.x, help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[i].xyz.y);
807         }
808 }
809
810 DCF(help_nudgetext_x, "Use to visually position overlay text.")
811 {
812         if (Dc_command) {
813                 dc_get_arg(ARG_INT);
814                 if(Dc_arg_type & ARG_INT){
815                          h_textnum = Dc_arg_int;                
816                 }
817                 dc_get_arg(ARG_INT);
818                 if(Dc_arg_type & ARG_INT){
819                          h_amt = Dc_arg_int;            
820                 }
821                 nudgetext_x(h_textnum, h_amt);
822         }
823
824         if (Dc_help)    {
825                 dc_printf( "Usage: sample\nCrashes your machine.\n" );
826         }
827
828         if (Dc_status)  {
829                 showtextpos(h_textnum);
830         }
831 }
832
833 DCF(help_nudgetext_y, "Use to visually position overlay text.")
834 {
835         if (Dc_command) {
836                 dc_get_arg(ARG_INT);
837                 if(Dc_arg_type & ARG_INT){
838                          h_textnum = Dc_arg_int;                
839                 }
840                 dc_get_arg(ARG_INT);
841                 if(Dc_arg_type & ARG_INT){
842                          h_amt = Dc_arg_int;            
843                 }
844                 nudgetext_y(h_textnum, h_amt);
845         }
846
847         if (Dc_help)    {
848                 dc_printf( "Usage: sample\nCrashes your machine.\n" );
849         }
850
851         if (Dc_status)  {
852                 showtextpos(h_textnum);
853         }
854 }
855
856 DCF(help_nudgepline_x, "Use to visually position overlay polylines.")
857 {
858         if (Dc_command) {
859                 dc_get_arg(ARG_INT);
860                 if(Dc_arg_type & ARG_INT){
861                          h_textnum = Dc_arg_int;                
862                 }
863                 dc_get_arg(ARG_INT);
864                 if(Dc_arg_type & ARG_INT){
865                          h_vtx = Dc_arg_int;            
866                 }
867                 dc_get_arg(ARG_INT);
868                 if(Dc_arg_type & ARG_INT){
869                          h_amt = Dc_arg_int;            
870                 }
871                 nudgepline_x(h_textnum, h_vtx, h_amt);
872         }
873
874         if (Dc_help)    {
875                 dc_printf( "Usage: help_nudgepline [pline_number] [vertex_number] [distance]\n" );
876         }
877
878         if (Dc_status)  {
879                 showplinepos(h_textnum);
880         }
881 }
882
883
884 DCF(help_nudgepline_y, "Use to visually position overlay polylines.")
885 {
886         if (Dc_command) {
887                 dc_get_arg(ARG_INT);
888                 if(Dc_arg_type & ARG_INT){
889                          h_textnum = Dc_arg_int;                
890                 }
891                 dc_get_arg(ARG_INT);
892                 if(Dc_arg_type & ARG_INT){
893                          h_vtx = Dc_arg_int;            
894                 }
895                 dc_get_arg(ARG_INT);
896                 if(Dc_arg_type & ARG_INT){
897                          h_amt = Dc_arg_int;            
898                 }
899                 nudgepline_y(h_textnum, h_vtx, h_amt);
900         }
901
902         if (Dc_help)    {
903                 dc_printf( "Usage: help_nudgepline [pline_number] [vertex_number] [distance]\n" );
904         }
905
906         if (Dc_status)  {
907                 showplinepos(h_textnum);
908         }
909 }
910
911
912 DCF(help_nudgerbracket_x, "Use to visually position overlay right bracket.")
913 {
914         if (Dc_command) {
915                 dc_get_arg(ARG_INT);
916                 if(Dc_arg_type & ARG_INT){
917                          h_textnum = Dc_arg_int;                
918                 }
919                 dc_get_arg(ARG_INT);
920                 if(Dc_arg_type & ARG_INT){
921                          h_amt = Dc_arg_int;            
922                 }
923                 nudgerbracket_x(h_textnum, h_amt);
924         }
925
926         if (Dc_help)    {
927                 dc_printf( "Usage: help_nudgerbracket_x [num] [amount]\n" );
928         }
929
930         if (Dc_status)  {
931                 showrbracketpos(h_textnum);
932         }
933 }
934
935 DCF(help_nudgerbracket_y, "Use to visually position overlay right bracket.")
936 {
937         if (Dc_command) {
938                 dc_get_arg(ARG_INT);
939                 if(Dc_arg_type & ARG_INT){
940                          h_textnum = Dc_arg_int;                
941                 }
942                 dc_get_arg(ARG_INT);
943                 if(Dc_arg_type & ARG_INT){
944                          h_amt = Dc_arg_int;            
945                 }
946                 nudgerbracket_y(h_textnum, h_amt);
947         }
948
949         if (Dc_help)    {
950                 dc_printf( "Usage: help_nudgerbracket_y [num] [amount]\n" );
951         }
952
953         if (Dc_status)  {
954                 showrbracketpos(h_textnum);
955         }
956 }
957
958
959
960
961 DCF(help_nudgelbracket_x, "Use to visually position overlay left bracket.")
962 {
963         if (Dc_command) {
964                 dc_get_arg(ARG_INT);
965                 if(Dc_arg_type & ARG_INT){
966                          h_textnum = Dc_arg_int;                
967                 }
968                 dc_get_arg(ARG_INT);
969                 if(Dc_arg_type & ARG_INT){
970                          h_amt = Dc_arg_int;            
971                 }
972                 nudgelbracket_x(h_textnum, h_amt);
973         }
974
975         if (Dc_help)    {
976                 dc_printf( "Usage: help_nudgelbracket_x [num] [amount]\n" );
977         }
978
979         if (Dc_status)  {
980                 showlbracketpos(h_textnum);
981         }
982 }
983
984 DCF(help_nudgelbracket_y, "Use to visually position overlay left bracket.")
985 {
986         if (Dc_command) {
987                 dc_get_arg(ARG_INT);
988                 if(Dc_arg_type & ARG_INT){
989                          h_textnum = Dc_arg_int;                
990                 }
991                 dc_get_arg(ARG_INT);
992                 if(Dc_arg_type & ARG_INT){
993                          h_amt = Dc_arg_int;            
994                 }
995                 nudgelbracket_y(h_textnum, h_amt);
996         }
997
998         if (Dc_help)    {
999                 dc_printf( "Usage: help_nudgelbracket_y [num] [amount]\n" );
1000         }
1001
1002         if (Dc_status)  {
1003                 showlbracketpos(h_textnum);
1004         }
1005 }