Index: code/controlconfig/controlsconfig.cpp
===================================================================
--- code/controlconfig/controlsconfig.cpp	(revision 10737)
+++ code/controlconfig/controlsconfig.cpp	(working copy)
@@ -179,6 +179,8 @@
 static UI_WINDOW Ui_window;
 static unsigned int Defaults_cycle_pos; // the controls preset that was last selected
 
+int Control_config_overlay_id;
+
 static struct {
 	int key;  // index of other control in conflict with this one
 	int joy;  // index of other control in conflict with this one
@@ -1294,8 +1296,8 @@
 	Ui_window.tooltip_handler = control_config_tooltip_handler;
 
 	// load in help overlay bitmap	
-	help_overlay_load(CONTROL_CONFIG_OVERLAY);
-	help_overlay_set_state(CONTROL_CONFIG_OVERLAY,0);
+	Control_config_overlay_id = help_overlay_get_index(CONTROL_CONFIG_OVERLAY);
+	help_overlay_set_state(Control_config_overlay_id,0);
 
 	// reset conflict flashing
 	Conflict_stamp = -1;
@@ -1385,9 +1387,6 @@
 	while (Config_item_undo){
 		free_undo_block();
 	}
-
-	// unload the overlay bitmap
-	help_overlay_unload(CONTROL_CONFIG_OVERLAY);
 	
 	if (Background_bitmap){
 		bm_release(Background_bitmap);
@@ -1499,7 +1498,7 @@
 			}
 
 		} else {
-			if (help_overlay_active(CONTROL_CONFIG_OVERLAY)) {
+			if (help_overlay_active(Control_config_overlay_id)) {
 				CC_Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 				Ui_window.set_ignore_gadgets(1);
 			}
@@ -1509,14 +1508,14 @@
 			Ui_window.process(0);
 
 			if ( (k > 0) || B1_JUST_RELEASED ) {
-				if (help_overlay_active(CONTROL_CONFIG_OVERLAY)) {
-					help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
+				if (help_overlay_active(Control_config_overlay_id)) {
+					help_overlay_set_state(Control_config_overlay_id, 0);
 					Ui_window.set_ignore_gadgets(0);
 					k = 0;
 				}
 			}
 
-			if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
+			if ( !help_overlay_active(Control_config_overlay_id) ) {
 				Ui_window.set_ignore_gadgets(0);
 			}
 
@@ -1610,7 +1609,7 @@
 		}
 
 	} else if (Search_mode) {
-		if (help_overlay_active(CONTROL_CONFIG_OVERLAY)) {
+		if (help_overlay_active(Control_config_overlay_id)) {
 			CC_Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 			Ui_window.set_ignore_gadgets(1);
 		}
@@ -1620,14 +1619,14 @@
 		Ui_window.process(0);
 
 		if ( (k > 0) || B1_JUST_RELEASED ) {
-			if ( help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
-				help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
+			if ( help_overlay_active(Control_config_overlay_id) ) {
+				help_overlay_set_state(Control_config_overlay_id, 0);
 				Ui_window.set_ignore_gadgets(0);
 				k = 0;
 			}
 		}
 
-		if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
+		if ( !help_overlay_active(Control_config_overlay_id) ) {
 			Ui_window.set_ignore_gadgets(0);
 		}
 
@@ -1721,7 +1720,7 @@
 
 		CC_Buttons[gr_screen.res][UNDO_BUTTON].button.enable(Config_item_undo != NULL);
 
-		if ( help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
+		if ( help_overlay_active(Control_config_overlay_id) ) {
 			CC_Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 			Ui_window.set_ignore_gadgets(1);
 		}
@@ -1729,14 +1728,14 @@
 		k = Ui_window.process();
 
 		if ( (k > 0) || B1_JUST_RELEASED ) {
-			if ( help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
-				help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
+			if ( help_overlay_active(Control_config_overlay_id) ) {
+				help_overlay_set_state(Control_config_overlay_id, 0);
 				Ui_window.set_ignore_gadgets(0);
 				k = 0;
 			}
 		}
 
-		if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
+		if ( !help_overlay_active(Control_config_overlay_id) ) {
 			Ui_window.set_ignore_gadgets(0);
 		}
 
@@ -2109,7 +2108,7 @@
 	}
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(CONTROL_CONFIG_OVERLAY);
+	help_overlay_maybe_blit(Control_config_overlay_id);
 
 	gr_flip();
 }
Index: code/controlconfig/controlsconfig.h
===================================================================
--- code/controlconfig/controlsconfig.h	(revision 10737)
+++ code/controlconfig/controlsconfig.h	(working copy)
@@ -288,6 +288,8 @@
 extern int Invert_axis[];
 extern int Invert_axis_defaults[];
 
+extern int Control_config_overlay_id;
+
 extern config_item Control_config[];		//!< Stores the keyboard configuration
 extern SCP_vector<config_item*> Control_config_presets; // tabled control presets; pointers to config_item arrays
 extern char **Scan_code_text;
Index: code/gamehelp/contexthelp.cpp
===================================================================
--- code/gamehelp/contexthelp.cpp	(revision 10737)
+++ code/gamehelp/contexthelp.cpp	(working copy)
@@ -14,6 +14,17 @@
 #include "gamehelp/contexthelp.h"
 #include "gamesequence/gamesequence.h"
 #include "menuui/mainhallmenu.h"
+#include "missionui/missionbrief.h"
+#include "missionui/missionshipchoice.h"
+#include "missionui/missionweaponchoice.h"
+#include "menuui/barracks.h"
+#include "controlconfig/controlsconfig.h"
+#include "missionui/missiondebrief.h"
+#include "network/multiui.h"
+#include "mission/missionhotkey.h"
+#include "menuui/readyroom.h"
+#include "menuui/techmenu.h"
+#include "missionui/missioncmdbrief.h"
 #include "graphics/2d.h"
 #include "parse/parselo.h"
 #include "localization/localize.h"
@@ -26,7 +37,7 @@
 ////////////////////////////////////////////////////////////////////
 // private function prototypes / structs
 ////////////////////////////////////////////////////////////////////
-void parse_helptbl();
+void parse_helptbl(const char *filename);
 void help_overlay_blit(int overlay_id);
 void help_overlay_init();
 
@@ -55,6 +66,7 @@
 } help_right_bracket;
 
 typedef struct {
+	char name[HELP_MAX_NAME_LENGTH];
 	help_pline				plinelist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
 	help_text				textlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
 	help_left_bracket		lbracketlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
@@ -65,26 +77,6 @@
 	int rbracketcount;
 } help_overlay;
 
-// new help.tbl file way
-char *help_overlay_section_names[MAX_HELP_OVERLAYS] = {
-	"$ship",					// ship_help
-	"$weapon",				// weapon_help
-	"$briefing",			// briefing
-	"$main",					//	main help overlay
-	"$barracks",			// barracks
-	"$control",				// control help
-	"$debrief",				// debrief help
-	"$multicreate",		// multicreate help
-	"$multistart",			// multistart help
-	"$multijoin",			// multijoin help
-	"$main2",				// main help overlay2
-	"$hotkey",				// hotkey help
-	"$campaign",			// campaign help
-	"$simulator",			//	simulator help
-	"$tech",					// tech help
-	"$command"				// command help
-};
-
 ////////////////////////////////////////////////////////////////////
 // Game-wide globals
 ////////////////////////////////////////////////////////////////////
@@ -96,6 +88,7 @@
 static int help_left_bracket_bitmap;
 static int help_right_bracket_bitmap;
 static help_overlay help_overlaylist[MAX_HELP_OVERLAYS];
+int num_help_overlays;
 
 static int current_helpid = -1;		// the currently active overlay_id, only really used for the debug console funxions
 int Help_overlay_flags;
@@ -106,10 +99,26 @@
 ////////////////////////////////////////////////////////////////////
 
 
+int help_overlay_get_index(const char* overlay_name)
+{
+	for (int i = 0; i < num_help_overlays; i++) {
+		if (!stricmp(overlay_name, help_overlaylist[i].name)) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
 // query whether a help overlay is active (ie being displayed)
 int help_overlay_active(int overlay_id)
 {
-	Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
+	Assert(overlay_id < MAX_HELP_OVERLAYS);
+
+	if (overlay_id < 0) {
+		return 0;
+	}
+
 	return Help_overlay_flags & (1<<overlay_id);
 }
 
@@ -116,38 +125,26 @@
 // stop displaying a help overlay
 void help_overlay_set_state(int overlay_id, int state)
 {
-	Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
+	Assert(overlay_id < MAX_HELP_OVERLAYS);
 
-	if ( state > 0 ) {
-		Help_overlay_flags |= (1<<overlay_id);
-		current_helpid = overlay_id;
-	} else {
-		Help_overlay_flags &= ~(1<<overlay_id);
-		//current_helpid = -1;
+	if (overlay_id >= 0 && overlay_id < num_help_overlays) {
+		if ( state > 0 ) {
+			Help_overlay_flags |= (1<<overlay_id);
+			current_helpid = overlay_id;
+		} else {
+			Help_overlay_flags &= ~(1<<overlay_id);
+			//current_helpid = -1;
+		}
 	}
 
 }
 
-// load in the bitmap for a help overlay
-// FIXME - leftover from the old bitmap overlay days - prune this out sometime
-void help_overlay_load(int overlay_id)
-{
-	return;
-} 
-
-// unload a bitmap of a help overlay
-// FIXME - leftover from the old bitmap overlay days - prune this out sometime
-void help_overlay_unload(int overlay_id)
-{
-	return; 
-}
-
 // maybe blit a bitmap of a help overlay to the screen
 void help_overlay_maybe_blit(int overlay_id)
 {
-	Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
+	Assert(overlay_id < MAX_HELP_OVERLAYS);
 
-	if ( Help_overlay_flags & (1<<overlay_id) ) {
+	if ( overlay_id >= 0 && (Help_overlay_flags & (1<<overlay_id)) ) {
 		context_help_grey_screen();
 		help_overlay_blit(overlay_id);				
 	}
@@ -190,6 +187,8 @@
 // launch_context_help() will switch to a context sensitive help state
 void launch_context_help()
 {
+	int overlay_id = -1;
+
 	// look at the state the game was in when F1 was pressed
 	Source_game_state = gameseq_get_state();
 
@@ -196,14 +195,7 @@
 	switch (Source_game_state) {
 
 		case GS_STATE_MAIN_MENU:
-			int main_hall_num;
-			main_hall_num = (main_hall_id() == 0) ? MH_OVERLAY : MH2_OVERLAY;
-			if ( !help_overlay_active(main_hall_num) ) {
-				help_overlay_set_state(main_hall_num, 1);
-			}
-			else {
-				help_overlay_set_state(main_hall_num, 0);
-			}
+			overlay_id = main_hall_get_overlay_id();
 			break;
 
 		case GS_STATE_GAME_PLAY:
@@ -213,139 +205,59 @@
 			break;
 
 		case GS_STATE_BRIEFING:
-			if ( !help_overlay_active(BR_OVERLAY) ) {
-				help_overlay_set_state(BR_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(BR_OVERLAY, 0);
-			}
+			overlay_id = Briefing_overlay_id;
 			break;
 
 		case GS_STATE_SHIP_SELECT:
-			if ( !help_overlay_active(SS_OVERLAY) ) {
-				help_overlay_set_state(SS_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(SS_OVERLAY, 0);
-			}
+			overlay_id = Ship_select_overlay_id;
 			break;
 
 		case GS_STATE_WEAPON_SELECT:
-			if ( !help_overlay_active(WL_OVERLAY) ) {
-				help_overlay_set_state(WL_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(WL_OVERLAY, 0);
-			}
+			overlay_id = Weapon_select_overlay_id;
 			break;
 
 		case GS_STATE_BARRACKS_MENU:
-			if ( !help_overlay_active(BARRACKS_OVERLAY) ) {
-				help_overlay_set_state(BARRACKS_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(BARRACKS_OVERLAY, 0);
-			}
+			overlay_id = Barracks_overlay_id;
 			break;
 
 		case GS_STATE_CONTROL_CONFIG:
-			if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
-				help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
-			}
+			overlay_id = Control_config_overlay_id;
 			break;
 
 		case GS_STATE_DEBRIEF:
-			if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
-				help_overlay_set_state(DEBRIEFING_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
-			}
+			overlay_id = Debrief_overlay_id;
 			break;
 
 		case GS_STATE_MULTI_HOST_SETUP:
-			if ( !help_overlay_active(MULTI_CREATE_OVERLAY) ) {
-				help_overlay_set_state(MULTI_CREATE_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(MULTI_CREATE_OVERLAY, 0);
-			}
+			overlay_id = Multi_create_overlay_id;
 			break;
 
 		case GS_STATE_MULTI_START_GAME:
-			if ( !help_overlay_active(MULTI_START_OVERLAY) ) {
-				help_overlay_set_state(MULTI_START_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(MULTI_START_OVERLAY, 0);
-			}
+			overlay_id = Multi_sg_overlay_id;
 			break;
-/*
-		case GS_STATE_NET_CHAT:
-			if (!help_overlay_active(FS2OX_OVERLAY) ) {
-				help_overlay_set_state(FS2OX_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(FS2OX_OVERLAY, 1);
-			}
-			break;
-*/
+
 		case GS_STATE_MULTI_JOIN_GAME:
-			if ( !help_overlay_active(MULTI_JOIN_OVERLAY) ) {
-				help_overlay_set_state(MULTI_JOIN_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(MULTI_JOIN_OVERLAY, 0);
-			}
+			overlay_id = Multi_join_overlay_id;
 			break;
 
 		case GS_STATE_HOTKEY_SCREEN:
-			if ( !help_overlay_active(HOTKEY_OVERLAY) ) {
-				help_overlay_set_state(HOTKEY_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(HOTKEY_OVERLAY, 0);
-			}
+			overlay_id = Hotkey_overlay_id;
 			break;
 
 		case GS_STATE_CAMPAIGN_ROOM:
-			if ( !help_overlay_active(CAMPAIGN_ROOM_OVERLAY) ) {
-				help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 0);
-			}
+			overlay_id = Campaign_room_overlay_id;
 			break;
 
 		case GS_STATE_SIMULATOR_ROOM:
-			if ( !help_overlay_active(SIM_ROOM_OVERLAY) ) {
-				help_overlay_set_state(SIM_ROOM_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(SIM_ROOM_OVERLAY, 0);
-			}
+			overlay_id = Sim_room_overlay_id;
 			break;
 
-		case GS_STATE_TECH_MENU: {				
-			if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
-				help_overlay_set_state(TECH_ROOM_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
-			}
+		case GS_STATE_TECH_MENU:
+			overlay_id = Techroom_overlay_id;
 			break;
-		}
 
 		case GS_STATE_CMD_BRIEF:
-			if ( !help_overlay_active(CMD_BRIEF_OVERLAY) ) {
-				help_overlay_set_state(CMD_BRIEF_OVERLAY, 1);
-			}
-			else {
-				help_overlay_set_state(CMD_BRIEF_OVERLAY, 0);
-			}
+			overlay_id = Cmd_brief_overlay_id;
 			break;
 
 		default:
@@ -353,6 +265,15 @@
 			break;
 
 	} // end switch
+
+	if (overlay_id >= 0) {
+		if ( !help_overlay_active(overlay_id) ) {
+			help_overlay_set_state(overlay_id, 1);
+		}
+		else {
+			help_overlay_set_state(overlay_id, 0);
+		}
+	}
 }
 
 void close_help(){
@@ -376,14 +297,21 @@
 	Assertion( help_left_bracket_bitmap >= 0, "Failed to load bitmap left_bracket for help overlay\n");
 
 	atexit(close_help);
+
+	num_help_overlays = 0;
+
 	// parse help.tbl
-	parse_helptbl();
+	parse_helptbl(HELP_OVERLAY_FILENAME);
+
+	// look for any modular tables
+	parse_modular_table(NOX("*-hlp.tbm"), parse_helptbl);
 }
 
 // parses help.tbl and populates help_overlaylist[]
-void parse_helptbl()
+void parse_helptbl(const char *filename)
 {
 	int overlay_id, currcount;
+	char name[HELP_MAX_NAME_LENGTH];
 	char buf[HELP_MAX_STRING_LENGTH + 1];
 	int i, rval;
 
@@ -391,19 +319,37 @@
 	lcl_ext_open();
 	
 	if ((rval = setjmp(parse_abort)) != 0) {
-		mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", HELP_OVERLAY_FILENAME, rval));
+		mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", filename, rval));
 		lcl_ext_close();
 		return;
 	} 
 
-	read_file_text(HELP_OVERLAY_FILENAME, CF_TYPE_TABLES);
+	read_file_text(filename, CF_TYPE_TABLES);
+	reset_parse();
 
 	// for each overlay...
-	for (overlay_id=0; overlay_id<MAX_HELP_OVERLAYS; overlay_id++) {
+	while (optional_string("$")) {
 
-		reset_parse();
-		skip_to_string(help_overlay_section_names[overlay_id]);
+		stuff_string(name, F_NAME, HELP_MAX_NAME_LENGTH);
 
+		overlay_id = help_overlay_get_index(name);
+
+		if (overlay_id < 0) {
+			if (num_help_overlays >= MAX_HELP_OVERLAYS) {
+				Warning(LOCATION, "Could not load help overlay after '%s' as maximum number of help overlays was reached (Max is %d)", help_overlaylist[overlay_id - 1].name, MAX_HELP_OVERLAYS);
+
+				if (!skip_to_string("$end")) {
+					Error(LOCATION, "Couldn't find $end. Help.tbl or -hlp.tbm is invalid.\n");
+				}
+
+				continue;
+			} else {
+				overlay_id = num_help_overlays;
+				strcpy_s(help_overlaylist[overlay_id].name, name);
+				num_help_overlays++;
+			}
+		}
+
 		// clear out counters in the overlay struct
 		help_overlaylist[overlay_id].plinecount = 0;
 		help_overlaylist[overlay_id].textcount = 0;
@@ -411,7 +357,7 @@
 		help_overlaylist[overlay_id].lbracketcount = 0;
 		
 		// read in all elements for this overlay
-		while (!(check_for_string("$end")))  {
+		while (!(optional_string("$end")))  {
 
 			if (optional_string("+pline")) {
 
@@ -505,7 +451,7 @@
 			}		// end if
 
 		}		// end while
-	}		// end for
+	}		// end while
 
 	// close localization
 	lcl_ext_close();
@@ -564,7 +510,9 @@
 		dc_printf( "Usage: sample\nCrashes your machine.\n" );
 	}
 
-	parse_helptbl();
+	num_help_overlays = 0;
+	parse_helptbl(HELP_OVERLAY_FILENAME);
+	parse_modular_table(NOX("*-hlp.tbm"), parse_helptbl);
 }
 
 int h_textnum=0, h_amt=0, h_vtx = 0;
Index: code/gamehelp/contexthelp.h
===================================================================
--- code/gamehelp/contexthelp.h	(revision 10737)
+++ code/gamehelp/contexthelp.h	(working copy)
@@ -16,33 +16,29 @@
 
 // Help overlays
 //
-// Adding a help overlay:    1) Add a #define that uniquely identifies your help overlay
-//									  2) Increment MAX_HELP_OVERLAYS
-//									  3) Add the filename for the help overlay to Help_overlays[] array in ContextHelp.cpp
-//
-#define	MAX_HELP_OVERLAYS				16	// Must be kept current
+#define	MAX_HELP_OVERLAYS				30
 
-#define	SS_OVERLAY						0	// ship selection help
-#define	WL_OVERLAY						1	// weapons loadout help
-#define	BR_OVERLAY						2	// briefing help
-#define	MH_OVERLAY						3	// main hall help
-#define	BARRACKS_OVERLAY				4	// barracks help
-#define	CONTROL_CONFIG_OVERLAY		5	// control config help
-#define	DEBRIEFING_OVERLAY			6	// debriefing help
-#define	MULTI_CREATE_OVERLAY			7	// multi create game help
-#define	MULTI_START_OVERLAY			8	// multi start game help overlay
-#define	MULTI_JOIN_OVERLAY			9	// join game help overlay
-#define	MH2_OVERLAY						10	// main hall 2 help overlay
-#define	HOTKEY_OVERLAY					11 // hotkey assignment help overlay
-#define	CAMPAIGN_ROOM_OVERLAY		12 // campaign room help overlay
-#define	SIM_ROOM_OVERLAY				13	// sim room help overlay
-#define	TECH_ROOM_OVERLAY				14	// tech room (general) help overlay
-#define	CMD_BRIEF_OVERLAY				15 // command briefing help overlay
-//#define FS2OX_OVERLAY					16 // Chat help overlay
+#define	SS_OVERLAY						"ship"	// ship selection help
+#define	WL_OVERLAY						"weapon"	// weapons loadout help
+#define	BR_OVERLAY						"briefing"	// briefing help
+#define	MH_OVERLAY						"main"	// main hall help
+#define	BARRACKS_OVERLAY				"barracks"	// barracks help
+#define	CONTROL_CONFIG_OVERLAY		"control"	// control config help
+#define	DEBRIEFING_OVERLAY			"debrief"	// debriefing help
+#define	MULTI_CREATE_OVERLAY			"multicreate"	// multi create game help
+#define	MULTI_START_OVERLAY			"multistart"	// multi start game help overlay
+#define	MULTI_JOIN_OVERLAY			"multijoin"	// join game help overlay
+#define	MH2_OVERLAY						"main2"	// main hall 2 help overlay
+#define	HOTKEY_OVERLAY					"hotkey" // hotkey assignment help overlay
+#define	CAMPAIGN_ROOM_OVERLAY		"campaign" // campaign room help overlay
+#define	SIM_ROOM_OVERLAY				"simulator"	// sim room help overlay
+#define	TECH_ROOM_OVERLAY				"tech"	// tech room (general) help overlay
+#define	CMD_BRIEF_OVERLAY				"command" // command briefing help overlay
 
 // other help overlay constants
 #define HELP_MAX_ITEM				50				// max number of screen elements per element type per overlay
 #define HELP_PADDING		1							//
+#define HELP_MAX_NAME_LENGTH	32			// max string length for overlay name
 #define HELP_MAX_STRING_LENGTH	128			// max string length for text overlay element
 #define HELP_MAX_PLINE_VERTICES	21				// good for 20 segments, can prolly reduce this (FIXME)
 #define HELP_PLINE_THICKNESS		2
@@ -49,10 +45,9 @@
 #define HELP_OVERLAY_FILENAME		"help.tbl"
 
 // help overlay calls
+int	help_overlay_get_index(const char* overlay_name);
 int	help_overlay_active(int overlay_id);
 void	help_overlay_set_state(int overlay_id, int state);
-void	help_overlay_load(int overlay_id);
-void	help_overlay_unload(int overlay_id);
 void	help_overlay_maybe_blit(int overlay_id);
 
 void context_help_init();			// called once at game startup
Index: code/menuui/barracks.cpp
===================================================================
--- code/menuui/barracks.cpp	(revision 10737)
+++ code/menuui/barracks.cpp	(working copy)
@@ -290,6 +290,8 @@
 static int Rank_pips_bitmaps;
 static int Rank_pips_count;
 
+int Barracks_overlay_id;
+
 void barracks_squad_change_popup();
 
 
@@ -1381,8 +1383,8 @@
 	Inputbox.hide();
 
 	// load in help overlay bitmap	
-	help_overlay_load(BARRACKS_OVERLAY);
-	help_overlay_set_state(BARRACKS_OVERLAY,0);	
+	Barracks_overlay_id = help_overlay_get_index(BARRACKS_OVERLAY);
+	help_overlay_set_state(Barracks_overlay_id,0);	
 
 	// other init stuff
 	Barracks_callsign_enter_mode = 0;	
@@ -1433,8 +1435,8 @@
 	int k = Ui_window.process();
 
 	if ( k > 0 ) {
-		if ( help_overlay_active(BARRACKS_OVERLAY) ) {
-			help_overlay_set_state(BARRACKS_OVERLAY,0);
+		if ( help_overlay_active(Barracks_overlay_id) ) {
+			help_overlay_set_state(Barracks_overlay_id,0);
 			k = 0;
 		}
 	}
@@ -1476,7 +1478,7 @@
 				break;
 
 			case KEY_ESC:  // cancel
-				if (!help_overlay_active(BARRACKS_OVERLAY)) {
+				if (!help_overlay_active(Barracks_overlay_id)) {
 					if (Num_pilots && !barracks_pilot_accepted()) {
 						gameseq_post_event(GS_EVENT_MAIN_MENU);
 					} else {
@@ -1484,7 +1486,7 @@
 					}
 				} else {
 					// kill the overlay
-					help_overlay_set_state(BARRACKS_OVERLAY,0);
+					help_overlay_set_state(Barracks_overlay_id,0);
 				}
 				break;
 
@@ -1541,7 +1543,7 @@
 
 	// check mouse over help
 	if (mouse_down(MOUSE_LEFT_BUTTON)) {
-		help_overlay_set_state(BARRACKS_OVERLAY, 0);
+		help_overlay_set_state(Barracks_overlay_id, 0);
 	}
 
 	// do pilot pic stuff
@@ -1611,7 +1613,7 @@
 	barracks_display_pilot_stats();
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(BARRACKS_OVERLAY);	
+	help_overlay_maybe_blit(Barracks_overlay_id);	
 	
 	// flip the page
 	gr_flip();
@@ -1638,9 +1640,6 @@
 		}
 	}
 
-	// unload the overlay bitmap
-	help_overlay_unload(BARRACKS_OVERLAY);
-
 	if(Stat_labels != NULL)
 	{
 		delete[] Stat_labels;
Index: code/menuui/barracks.h
===================================================================
--- code/menuui/barracks.h	(revision 10737)
+++ code/menuui/barracks.h	(working copy)
@@ -12,6 +12,8 @@
 #ifndef _BARRACKS_H
 #define _BARRACKS_H
 
+extern int Barracks_overlay_id;
+
 // initialize the barracks 
 void barracks_init();
 
Index: code/menuui/mainhallmenu.cpp
===================================================================
--- code/menuui/mainhallmenu.cpp	(revision 10737)
+++ code/menuui/mainhallmenu.cpp	(working copy)
@@ -535,12 +535,13 @@
 	}
 
 	// load in help overlay bitmap
-	if (Main_hall == &Main_hall_defines.at(gr_screen.res).at(0)) {
-		Main_hall_overlay_id = MH_OVERLAY;
+	if (!Main_hall->help_overlay_name.empty()) {
+		Main_hall_overlay_id = help_overlay_get_index(Main_hall->help_overlay_name.c_str());
+	} else if (Main_hall == &Main_hall_defines.at(gr_screen.res).at(0)) {
+		Main_hall_overlay_id = help_overlay_get_index(MH_OVERLAY);
 	} else {
-		Main_hall_overlay_id = MH2_OVERLAY;
+		Main_hall_overlay_id = help_overlay_get_index(MH2_OVERLAY);
 	}
-	help_overlay_load(Main_hall_overlay_id);
 	help_overlay_set_state(Main_hall_overlay_id,0);
 
 	// check to see if the "very first pilot" flag is set, and load the overlay if so
@@ -925,9 +926,6 @@
 		}
 	}
 
-	// unload the overlay bitmap
-	help_overlay_unload(Main_hall_overlay_id);
-
 	// close any snazzy menu details
 	snazzy_menu_close();
 
@@ -1654,6 +1652,15 @@
 	}
 }
 
+int main_hall_get_overlay_id()
+{
+	if (Main_hall==NULL) {
+		return -1;
+	} else {
+		return Main_hall_overlay_id;
+	}
+}
+
 // what main hall we're on
 int main_hall_id()
 {
@@ -1935,6 +1942,11 @@
 				m->substitute_music_name = temp_string;
 			}
 
+			if (optional_string("+Help Overlay:")) {
+				stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
+				m->help_overlay_name = temp_string;
+			}
+
 			// intercom sounds
 			required_string("+Num Intercom Sounds:");
 			stuff_int(&m->num_random_intercom_sounds);
Index: code/menuui/mainhallmenu.h
===================================================================
--- code/menuui/mainhallmenu.h	(revision 10737)
+++ code/menuui/mainhallmenu.h	(working copy)
@@ -28,6 +28,9 @@
 	SCP_string music_name;
 	SCP_string substitute_music_name;
 
+	// help overlay
+	SCP_string help_overlay_name;
+
 	// intercom defines -------------------
 
 	// # of intercom sounds
@@ -140,6 +143,8 @@
 
 void main_hall_get_name(SCP_string &name, unsigned int index);
 
+int main_hall_get_overlay_id();
+
 // what main hall we're on
 int main_hall_id();
 
Index: code/menuui/readyroom.cpp
===================================================================
--- code/menuui/readyroom.cpp	(revision 10737)
+++ code/menuui/readyroom.cpp	(working copy)
@@ -221,6 +221,9 @@
 static UI_WINDOW Ui_window;
 static UI_BUTTON List_buttons[LIST_BUTTONS_MAX];  // buttons for each line of text in list
 
+int Sim_room_overlay_id;
+int Campaign_room_overlay_id;
+
 // globals
 bool Campaign_room_no_campaigns = false;
 
@@ -1049,8 +1052,8 @@
 	Background_bitmap = bm_load(Sim_filename[gr_screen.res]);
 
 	// load in help overlay bitmap	
-	help_overlay_load(SIM_ROOM_OVERLAY);
-	help_overlay_set_state(SIM_ROOM_OVERLAY,0);
+	Sim_room_overlay_id = help_overlay_get_index(SIM_ROOM_OVERLAY);
+	help_overlay_set_state(Sim_room_overlay_id,0);
 
 	Scroll_offset = Selected_line = 0;
 
@@ -1151,9 +1154,6 @@
 	// free global Campaign_* list stuff
 	mission_campaign_free_list();
 
-	// unload the overlay bitmap
-	help_overlay_unload(SIM_ROOM_OVERLAY);
-
 	campaign_mission_hash_table_delete();
 
 	Ui_window.destroy();
@@ -1183,7 +1183,7 @@
 			break;
 		}
 
-	if ( help_overlay_active(SIM_ROOM_OVERLAY) ) {
+	if ( help_overlay_active(Sim_room_overlay_id) ) {
 		Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 		Ui_window.set_ignore_gadgets(1);
 	}
@@ -1191,14 +1191,14 @@
 	k = Ui_window.process() & ~KEY_DEBUGGED;
 
 	if ( (k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(SIM_ROOM_OVERLAY) ) {
-			help_overlay_set_state(SIM_ROOM_OVERLAY, 0);
+		if ( help_overlay_active(Sim_room_overlay_id) ) {
+			help_overlay_set_state(Sim_room_overlay_id, 0);
 			Ui_window.set_ignore_gadgets(0);
 			k = 0;
 		}
 	}
 
-	if ( !help_overlay_active(SIM_ROOM_OVERLAY) ) {
+	if ( !help_overlay_active(Sim_room_overlay_id) ) {
 		Ui_window.set_ignore_gadgets(0);
 	}
 
@@ -1355,7 +1355,7 @@
 		List_buttons[i++].disable();
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(SIM_ROOM_OVERLAY);
+	help_overlay_maybe_blit(Sim_room_overlay_id);
 
 	gr_flip();
 }
@@ -1680,8 +1680,8 @@
 	Background_bitmap = bm_load(Campaign_filename[gr_screen.res]);
 
 	// load in help overlay bitmap	
-	help_overlay_load(CAMPAIGN_ROOM_OVERLAY);
-	help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY,0);
+	Campaign_room_overlay_id = help_overlay_get_index(CAMPAIGN_ROOM_OVERLAY);
+	help_overlay_set_state(Campaign_room_overlay_id,0);
 
 	Num_desc_lines = 0;
 	Desc_scroll_offset = Scroll_offset = 0;
@@ -1723,9 +1723,6 @@
 	// free the global Campaign_* list stuff
 	mission_campaign_free_list();
 
-	// unload the overlay bitmap
-	help_overlay_unload(CAMPAIGN_ROOM_OVERLAY);
-
 	Ui_window.destroy();
 	common_free_interface_palette();		// restore game palette
 	Pilot.save_player();
@@ -1739,7 +1736,7 @@
 	int font_height = gr_get_font_height();
 	int select_tease_line = -1;  // line mouse is down on, but won't be selected until button released
 
-	if ( help_overlay_active(CAMPAIGN_ROOM_OVERLAY) ) {
+	if ( help_overlay_active(Campaign_room_overlay_id) ) {
 		// Cr_buttons[gr_screen.res][CR_HELP_BUTTON].button.reset_status();
 		Ui_window.set_ignore_gadgets(1);
 	}
@@ -1747,14 +1744,14 @@
 	k = Ui_window.process() & ~KEY_DEBUGGED;
 
 	if ( (k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(CAMPAIGN_ROOM_OVERLAY) ) {
-			help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 0);
+		if ( help_overlay_active(Campaign_room_overlay_id) ) {
+			help_overlay_set_state(Campaign_room_overlay_id, 0);
 			Ui_window.set_ignore_gadgets(0);
 			k = 0;
 		}
 	}
 
-	if ( !help_overlay_active(CAMPAIGN_ROOM_OVERLAY) ) {
+	if ( !help_overlay_active(Campaign_room_overlay_id) ) {
 		Ui_window.set_ignore_gadgets(0);
 	}
 
@@ -1875,7 +1872,7 @@
 	}
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(CAMPAIGN_ROOM_OVERLAY);
+	help_overlay_maybe_blit(Campaign_room_overlay_id);
 
 	gr_flip();
 }
Index: code/menuui/readyroom.h
===================================================================
--- code/menuui/readyroom.h	(revision 10737)
+++ code/menuui/readyroom.h	(working copy)
@@ -9,6 +9,9 @@
 
 
 
+extern int Sim_room_overlay_id;
+extern int Campaign_room_overlay_id;
+
 void sim_room_init();
 void sim_room_close();
 void sim_room_do_frame(float frametime);
Index: code/menuui/techmenu.cpp
===================================================================
--- code/menuui/techmenu.cpp	(revision 10737)
+++ code/menuui/techmenu.cpp	(working copy)
@@ -214,6 +214,8 @@
 static int Weapons_loaded = 0;
 static int Intel_loaded = 0;
 
+int Techroom_overlay_id;
+
 // out entry data struct & vars
 typedef struct {
 	int	index;		// index into the master table that its in (ie Ship_info[])
@@ -1155,7 +1157,8 @@
 	Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.set_hotkey(KEY_PAGEDOWN);
 
 	// init help overlay states
-	help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
+	Techroom_overlay_id = help_overlay_get_index(TECH_ROOM_OVERLAY);
+	help_overlay_set_state(Techroom_overlay_id, 0);
 
 	// setup slider
 	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_classes, Tech_slider_filename[gr_screen.res], &tech_scroll_list_up, &tech_scroll_list_down, &tech_ship_scroll_capture);
@@ -1250,7 +1253,7 @@
 	int i, k;	
 
 	// turn off controls when overlay is on
-	if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
+	if ( help_overlay_active(Techroom_overlay_id) ) {
 		Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 		Ui_window.set_ignore_gadgets(1);
 	}
@@ -1265,14 +1268,14 @@
 	k = Ui_window.process() & ~KEY_DEBUGGED;
 
 	if ( (k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
-			help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
+		if ( help_overlay_active(Techroom_overlay_id) ) {
+			help_overlay_set_state(Techroom_overlay_id, 0);
 			Ui_window.set_ignore_gadgets(0);
 			k = 0;
 		}
 	}
 
-	if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
+	if ( !help_overlay_active(Techroom_overlay_id) ) {
 		Ui_window.set_ignore_gadgets(0);
 	}
 
@@ -1391,7 +1394,7 @@
 	}
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(TECH_ROOM_OVERLAY);
+	help_overlay_maybe_blit(Techroom_overlay_id);
 
 	gr_flip();
 }
Index: code/menuui/techmenu.h
===================================================================
--- code/menuui/techmenu.h	(revision 10737)
+++ code/menuui/techmenu.h	(working copy)
@@ -29,6 +29,8 @@
 #define IIF_IN_TECH_DATABASE			(1 << 0)	// in tech database? - Goober5000
 #define IIF_DEFAULT_IN_TECH_DATABASE	(1 << 1)	// in tech database by default? - Goober5000
 
+extern int Techroom_overlay_id;
+
 extern intel_data Intel_info[MAX_INTEL_ENTRIES];
 extern int Intel_info_size;
 
Index: code/mission/missionhotkey.cpp
===================================================================
--- code/mission/missionhotkey.cpp	(revision 10737)
+++ code/mission/missionhotkey.cpp	(working copy)
@@ -276,6 +276,8 @@
 static UI_BUTTON List_buttons[LIST_BUTTONS_MAX];  // buttons for each line of text in list
 //static UI_BUTTON List_region;
 
+int Hotkey_overlay_id;
+
 //////////////////////
 
 
@@ -954,7 +956,8 @@
 	Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);
 
 	// ensure help overlay is off
-	help_overlay_set_state(HOTKEY_OVERLAY,0);
+	Hotkey_overlay_id = help_overlay_get_index(HOTKEY_OVERLAY);
+	help_overlay_set_state(Hotkey_overlay_id,0);
 
 	// load in relevant bitmaps
 	Background_bitmap = bm_load(Hotkey_background_fname[gr_screen.res]);
@@ -986,9 +989,6 @@
 	if (Wing_bmp >= 0)
 		bm_release(Wing_bmp);
 
-	// unload the overlay bitmap
-//	help_overlay_unload(HOTKEY_OVERLAY);
-
 	// unpause all weapon sounds
 	weapon_unpause_sounds();
 
@@ -1013,7 +1013,7 @@
 	int select_tease_line = -1;  // line mouse is down on, but won't be selected until button released
 	color circle_color;
 
-	if ( help_overlay_active(HOTKEY_OVERLAY) ) {
+	if ( help_overlay_active(Hotkey_overlay_id) ) {
 		Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 		Ui_window.set_ignore_gadgets(1);
 	}
@@ -1021,14 +1021,14 @@
 	k = Ui_window.process() & ~KEY_DEBUGGED;
 
 	if ( (k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(HOTKEY_OVERLAY) ) {
-			help_overlay_set_state(HOTKEY_OVERLAY, 0);
+		if ( help_overlay_active(Hotkey_overlay_id) ) {
+			help_overlay_set_state(Hotkey_overlay_id, 0);
 			Ui_window.set_ignore_gadgets(0);
 			k = 0;
 		}
 	}
 
-	if ( !help_overlay_active(HOTKEY_OVERLAY) ) {
+	if ( !help_overlay_active(Hotkey_overlay_id) ) {
 		Ui_window.set_ignore_gadgets(0);
 	}
 
@@ -1268,7 +1268,7 @@
 		List_buttons[i++].disable();
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(HOTKEY_OVERLAY);
+	help_overlay_maybe_blit(Hotkey_overlay_id);
 
 	gr_flip();
 }
Index: code/mission/missionhotkey.h
===================================================================
--- code/mission/missionhotkey.h	(revision 10737)
+++ code/mission/missionhotkey.h	(working copy)
@@ -26,4 +26,6 @@
 // function to return the hotkey set number of the given key
 extern int mission_hotkey_get_set_num( int k );
 
+extern int Hotkey_overlay_id;
+
 #endif
Index: code/missionui/missionbrief.cpp
===================================================================
--- code/missionui/missionbrief.cpp	(revision 10737)
+++ code/missionui/missionbrief.cpp	(working copy)
@@ -73,6 +73,8 @@
 int	Briefing_music_handle = -1;
 int	Briefing_music_begin_timestamp = 0;
 
+int Briefing_overlay_id = -1;
+
 // --------------------------------------------------------------------------------------
 // Module scope globals
 // --------------------------------------------------------------------------------------
@@ -870,7 +872,8 @@
 	common_flash_button_init();
 	common_music_init(SCORE_BRIEFING);
 
-	help_overlay_set_state(BR_OVERLAY,0);
+	Briefing_overlay_id = help_overlay_get_index(BR_OVERLAY);
+	help_overlay_set_state(Briefing_overlay_id,0);
 
 	if ( Brief_inited == TRUE ) {
 		common_buttons_maybe_reload(&Brief_ui_window);	// AL 11-21-97: this is necessary since we may returning from the hotkey
@@ -897,8 +900,6 @@
 	nprintf(("Alan","Entering brief_init()\n"));
 	common_select_init();
 
-	help_overlay_load(BR_OVERLAY);
-
 	// Set up the mask regions
    // initialize the different regions of the menu that will react when the mouse moves over it
 	Num_briefing_regions = 0;
@@ -1480,7 +1481,7 @@
 		Brief_mouse_up_flag = 0;
 	}
 
-	if ( help_overlay_active(BR_OVERLAY) ) {
+	if ( help_overlay_active(Briefing_overlay_id) ) {
 		common_flash_button_init();
 		brief_turn_off_closeup_icon();
 	}
@@ -1628,7 +1629,7 @@
 	common_render(frametime);
 
 	if ( Current_brief_stage < (Num_brief_stages-1) ) {
-		if ( !help_overlay_active(BR_OVERLAY) && brief_time_to_advance(Current_brief_stage) ) {
+		if ( !help_overlay_active(Briefing_overlay_id) && brief_time_to_advance(Current_brief_stage) ) {
 			brief_do_next_pressed(0);
 			common_flash_button_init();
 			Brief_last_auto_advance = timer_get_milliseconds();
@@ -1754,7 +1755,7 @@
 	brief_maybe_flash_button();
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(BR_OVERLAY);	
+	help_overlay_maybe_blit(Briefing_overlay_id);	
 
 	gr_flip();	
 
@@ -1797,8 +1798,6 @@
 		bm_release(Brief_background_bitmap);
 		Brief_background_bitmap = -1;
 	}
-
-	help_overlay_unload(BR_OVERLAY);
 }
 
 // ------------------------------------------------------------------------------------
Index: code/missionui/missionbrief.h
===================================================================
--- code/missionui/missionbrief.h	(revision 10737)
+++ code/missionui/missionbrief.h	(working copy)
@@ -43,6 +43,8 @@
 extern int	Briefing_music_handle;
 extern int	Briefing_music_begin_timestamp;
 
+extern int Briefing_overlay_id;
+
 extern int Briefing_paused;	// for stopping audio and stage progression
 
 struct brief_icon;
Index: code/missionui/missioncmdbrief.cpp
===================================================================
--- code/missionui/missioncmdbrief.cpp	(revision 10737)
+++ code/missionui/missioncmdbrief.cpp	(working copy)
@@ -183,6 +183,8 @@
 
 static int Uses_scroll_buttons = 0;
 
+int Cmd_brief_overlay_id;
+
 void cmd_brief_init_voice()
 {
 	int i;
@@ -605,8 +607,8 @@
 	}
 
 	// load in help overlay bitmap	
-	help_overlay_load(CMD_BRIEF_OVERLAY);
-	help_overlay_set_state(CMD_BRIEF_OVERLAY,0);
+	Cmd_brief_overlay_id = help_overlay_get_index(CMD_BRIEF_OVERLAY);
+	help_overlay_set_state(Cmd_brief_overlay_id,0);
 
 	for (i=0; i<Cur_cmd_brief->num_stages; i++)
 		cmd_brief_ani_wave_init(i);
@@ -636,9 +638,6 @@
 		if (Cmd_brief_background_bitmap >= 0)
 			bm_release(Cmd_brief_background_bitmap);
 
-		// unload the overlay bitmap
-		help_overlay_unload(CMD_BRIEF_OVERLAY);
-
 		Ui_window.destroy();
 
 		game_flush();
@@ -660,7 +659,7 @@
 		return;
 	}
 
-	if ( help_overlay_active(CMD_BRIEF_OVERLAY) ) {
+	if ( help_overlay_active(Cmd_brief_overlay_id) ) {
 		Cmd_brief_buttons[gr_screen.res][CMD_BRIEF_BUTTON_HELP].button.reset_status();
 		Ui_window.set_ignore_gadgets(1);
 	}
@@ -668,14 +667,14 @@
 	k = Ui_window.process() & ~KEY_DEBUGGED;
 
 	if ( (k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(CMD_BRIEF_OVERLAY) ) {
-			help_overlay_set_state(CMD_BRIEF_OVERLAY, 0);
+		if ( help_overlay_active(Cmd_brief_overlay_id) ) {
+			help_overlay_set_state(Cmd_brief_overlay_id, 0);
 			Ui_window.set_ignore_gadgets(0);
 			k = 0;
 		}
 	}
 
-	if ( !help_overlay_active(CMD_BRIEF_OVERLAY) ) {
+	if ( !help_overlay_active(Cmd_brief_overlay_id) ) {
 		Ui_window.set_ignore_gadgets(0);
 	}
 
@@ -751,7 +750,7 @@
 	}
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(CMD_BRIEF_OVERLAY);
+	help_overlay_maybe_blit(Cmd_brief_overlay_id);
 
 	gr_flip();
 }
Index: code/missionui/missioncmdbrief.h
===================================================================
--- code/missionui/missioncmdbrief.h	(revision 10737)
+++ code/missionui/missioncmdbrief.h	(working copy)
@@ -36,6 +36,8 @@
 extern cmd_brief Cmd_briefs[MAX_TVT_TEAMS];
 extern cmd_brief *Cur_cmd_brief;  // pointer to one of the Cmd_briefs elements (the active one)
 
+extern int Cmd_brief_overlay_id;
+
 void cmd_brief_init(int stages);
 void cmd_brief_close();
 void cmd_brief_do_frame(float frametime);
Index: code/missionui/missiondebrief.cpp
===================================================================
--- code/missionui/missiondebrief.cpp	(revision 10737)
+++ code/missionui/missiondebrief.cpp	(working copy)
@@ -341,6 +341,8 @@
 static int Multi_list_size;
 static int Multi_list_offset;
 
+int Debrief_overlay_id;
+
 int Debrief_multi_stages_loaded = 0;
 int Debrief_multi_voice_loaded = 0;
 
@@ -854,8 +856,8 @@
 	debrief_buttons_init();
 
 	// load in help overlay bitmap	
-	help_overlay_load(DEBRIEFING_OVERLAY);
-	help_overlay_set_state(DEBRIEFING_OVERLAY,0);
+	Debrief_overlay_id = help_overlay_get_index(DEBRIEFING_OVERLAY);
+	help_overlay_set_state(Debrief_overlay_id,0);
 
 	if ( Game_mode & GM_MULTIPLAYER ) {
 		// close down any old instances of the chatbox
@@ -2169,9 +2171,6 @@
 	// clear out debrief info parsed from mission file - taylor
 	mission_debrief_common_reset();
 
-	// unload the overlay bitmap
-//	help_overlay_unload(DEBRIEFING_OVERLAY);
-
 	// clear out award text 
 	Debrief_award_text_num_lines = 0;
 
@@ -2412,7 +2411,7 @@
 		Debrief_multi_voice_loaded = 1;
 	}
 
-	if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
+	if ( help_overlay_active(Debrief_overlay_id) ) {
 		Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
 		Debrief_ui_window.set_ignore_gadgets(1);
 	}
@@ -2427,8 +2426,8 @@
 	}
 
 	if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
-			help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
+		if ( help_overlay_active(Debrief_overlay_id) ) {
+			help_overlay_set_state(Debrief_overlay_id, 0);
 			Debrief_ui_window.set_ignore_gadgets(0);
 			k = 0;
 			new_k = 0;
@@ -2435,7 +2434,7 @@
 		}
 	}
 
-	if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
+	if ( !help_overlay_active(Debrief_overlay_id) ) {
 		Debrief_ui_window.set_ignore_gadgets(0);
 	}
 
@@ -2588,13 +2587,13 @@
 	// AL 3-6-98: Needed to move key reading here, since popups are launched from this code, and we don't
 	//				  want to include the mouse pointer which is drawn in the flip
 
-	if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
+	if ( !help_overlay_active(Debrief_overlay_id) ) {
 		debrief_check_buttons();
 		debrief_do_keys(new_k);	
 	}
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(DEBRIEFING_OVERLAY);
+	help_overlay_maybe_blit(Debrief_overlay_id);
 
 	gr_flip();
 
Index: code/missionui/missiondebrief.h
===================================================================
--- code/missionui/missiondebrief.h	(revision 10737)
+++ code/missionui/missiondebrief.h	(working copy)
@@ -13,6 +13,8 @@
 #define __MISSIONDEBRIEF_H__
 
 
+extern int Debrief_overlay_id;
+
 extern int Debrief_multi_stages_loaded;
 
 void debrief_init();
Index: code/missionui/missionscreencommon.cpp
===================================================================
--- code/missionui/missionscreencommon.cpp	(revision 10737)
+++ code/missionui/missionscreencommon.cpp	(working copy)
@@ -582,7 +582,7 @@
 	int	k, new_k;
 
 
-	if ( help_overlay_active(BR_OVERLAY) || help_overlay_active(SS_OVERLAY) || help_overlay_active(WL_OVERLAY) ) {
+	if ( help_overlay_active(Briefing_overlay_id) || help_overlay_active(Ship_select_overlay_id) || help_overlay_active(Weapon_select_overlay_id) ) {
 		Common_buttons[0][gr_screen.res][COMMON_HELP_BUTTON].button.reset_status();
 		Common_buttons[1][gr_screen.res][COMMON_HELP_BUTTON].button.reset_status();
 		Common_buttons[2][gr_screen.res][COMMON_HELP_BUTTON].button.reset_status();
@@ -600,10 +600,10 @@
 	}
 
 	if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
-		if ( help_overlay_active(BR_OVERLAY) || help_overlay_active(SS_OVERLAY) || help_overlay_active(WL_OVERLAY) ) {
-			help_overlay_set_state(BR_OVERLAY, 0);
-			help_overlay_set_state(SS_OVERLAY, 0);
-			help_overlay_set_state(WL_OVERLAY, 0);
+		if ( help_overlay_active(Briefing_overlay_id) || help_overlay_active(Ship_select_overlay_id) || help_overlay_active(Weapon_select_overlay_id) ) {
+			help_overlay_set_state(Briefing_overlay_id, 0);
+			help_overlay_set_state(Ship_select_overlay_id, 0);
+			help_overlay_set_state(Weapon_select_overlay_id, 0);
 			Active_ui_window->set_ignore_gadgets(0);
 			k = 0;
 			new_k = 0;
Index: code/missionui/missionshipchoice.cpp
===================================================================
--- code/missionui/missionshipchoice.cpp	(revision 10737)
+++ code/missionui/missionshipchoice.cpp	(working copy)
@@ -123,6 +123,8 @@
 ////////////////////////////////////////////////////////////
 UI_WINDOW	Ship_select_ui_window;	
 
+int Ship_select_overlay_id = -1;
+
 static int Ship_anim_coords[GR_NUM_RESOLUTIONS][2] = {
 	{
 		257, 84		// GR_640
@@ -658,7 +660,8 @@
 
 	Ss_mouse_down_on_region = -1;
 
-	help_overlay_set_state(SS_OVERLAY,0);
+	Ship_select_overlay_id = help_overlay_get_index(SS_OVERLAY);
+	help_overlay_set_state(Ship_select_overlay_id,0);
 
 	if ( Ship_select_open ) {
 		//reset the animation
@@ -691,8 +694,6 @@
 	ShipSelectMaskData = (ubyte*)ShipSelectMaskPtr->data;	
 	bm_get_info(ShipSelectMaskBitmap, &Shipselect_mask_w, &Shipselect_mask_h);
 
-	help_overlay_load(SS_OVERLAY);
-
 	// Set up the mask regions
    // initialize the different regions of the menu that will react when the mouse moves over it
 	Num_mask_regions = 0;
@@ -1456,7 +1457,7 @@
 	if(!Cmdline_ship_choice_3d)
 	{
 		if ( (Selected_ss_class >= 0) && (Ss_icons[Selected_ss_class].ss_anim.num_frames > 0) ) {
-			generic_anim_render(&Ss_icons[Selected_ss_class].ss_anim, (help_overlay_active(SS_OVERLAY)) ? 0 : frametime, Ship_anim_coords[gr_screen.res][0], Ship_anim_coords[gr_screen.res][1], true);
+			generic_anim_render(&Ss_icons[Selected_ss_class].ss_anim, (help_overlay_active(Ship_select_overlay_id)) ? 0 : frametime, Ship_anim_coords[gr_screen.res][0], Ship_anim_coords[gr_screen.res][1], true);
 		}
 	}
 
@@ -1507,7 +1508,7 @@
 	ss_maybe_flash_button();
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(SS_OVERLAY);
+	help_overlay_maybe_blit(Ship_select_overlay_id);
 
 	// If the commit button was pressed, do the commit button actions.  Done at the end of the
 	// loop so there isn't a skip in the animation (since ship_create() can take a long time if
@@ -1601,7 +1602,6 @@
 
 	// unload the bitmaps
 	bm_release(ShipSelectMaskBitmap);
-	help_overlay_unload(SS_OVERLAY);
 
 	Ship_select_ui_window.destroy();
 
Index: code/missionui/missionshipchoice.h
===================================================================
--- code/missionui/missionshipchoice.h	(revision 10737)
+++ code/missionui/missionshipchoice.h	(working copy)
@@ -59,6 +59,8 @@
 extern float ShipSelectScreenShipRot;
 extern int	 ShipSelectModelNum;
 
+extern int Ship_select_overlay_id;
+
 void draw_wing_block(int wb_num, int hot_slot, int selected_slot, int class_select, bool ship_selection = true);
 void ship_select_init();
 void ship_select_do(float frametime);
Index: code/missionui/missionweaponchoice.cpp
===================================================================
--- code/missionui/missionweaponchoice.cpp	(revision 10737)
+++ code/missionui/missionweaponchoice.cpp	(working copy)
@@ -95,6 +95,8 @@
 
 extern int anim_timer_start;
 
+extern int Weapon_select_overlay_id = -1;
+
 // convenient struct for handling all button controls
 struct wl_buttons {
 	char *filename;
@@ -1955,7 +1957,8 @@
 	Assert( Wss_slots != NULL );
 	wl_set_disabled_weapons(Wss_slots[Selected_wl_slot].ship_class);
 
-	help_overlay_set_state(WL_OVERLAY,0);
+	Weapon_select_overlay_id = help_overlay_get_index(WL_OVERLAY);
+	help_overlay_set_state(Weapon_select_overlay_id,0);
 
 	if ( Weapon_select_open ) {
 		wl_maybe_reset_selected_weapon_class();
@@ -2679,7 +2682,7 @@
 		if ( Weapon_anim_class != Selected_wl_class )
 			start_weapon_animation(Selected_wl_class);
  
-		generic_anim_render(&Cur_Anim, (help_overlay_active(WL_OVERLAY)) ? 0 : frametime, weapon_ani_coords[0], weapon_ani_coords[1], true);
+		generic_anim_render(&Cur_Anim, (help_overlay_active(Weapon_select_overlay_id)) ? 0 : frametime, weapon_ani_coords[0], weapon_ani_coords[1], true);
 	}
 
 	if ( !Background_playing ) {
@@ -2814,7 +2817,7 @@
 	}
 
 	// blit help overlay if active
-	help_overlay_maybe_blit(WL_OVERLAY);
+	help_overlay_maybe_blit(Weapon_select_overlay_id);
 	gr_flip();	
 
 	// If the commit button was pressed, do the commit button actions.  Done at the end of the
@@ -2851,8 +2854,6 @@
 	Weapon_ui_window.destroy();
 
 	// unload bitmaps
-	help_overlay_unload(WL_OVERLAY);
-
 	bm_release(WeaponSelectMaskBitmap);
 
 	wl_unload_icons();
Index: code/missionui/missionweaponchoice.h
===================================================================
--- code/missionui/missionweaponchoice.h	(revision 10737)
+++ code/missionui/missionweaponchoice.h	(working copy)
@@ -36,6 +36,8 @@
 #define ICON_SHIP_SECONDARY_3		38
 
 
+extern int Weapon_select_overlay_id;
+
 void weapon_select_init();
 void weapon_select_common_init();
 void weapon_select_do(float frametime);
Index: code/network/multiui.cpp
===================================================================
--- code/network/multiui.cpp	(revision 10737)
+++ code/network/multiui.cpp	(working copy)
@@ -732,6 +732,8 @@
 // our join request
 join_request Multi_join_request;
 
+int Multi_join_overlay_id;
+
 // LOCAL function definitions
 void multi_join_check_buttons();
 void multi_join_button_pressed(int n);
@@ -881,8 +883,8 @@
 	multi_common_set_palette();
 
 	// load the help overlay
-	help_overlay_load(MULTI_JOIN_OVERLAY);
-	help_overlay_set_state(MULTI_JOIN_OVERLAY,0);
+	Multi_join_overlay_id = help_overlay_get_index(MULTI_JOIN_OVERLAY);
+	help_overlay_set_state(Multi_join_overlay_id,0);
 	
 	// try to login to the tracker
 	if (MULTI_IS_TRACKER_GAME) {
@@ -1045,8 +1047,8 @@
 	// process any keypresses
 	switch(k){
 	case KEY_ESC :
-		if(help_overlay_active(MULTI_JOIN_OVERLAY)){
-			help_overlay_set_state(MULTI_JOIN_OVERLAY,0);
+		if(help_overlay_active(Multi_join_overlay_id)){
+			help_overlay_set_state(Multi_join_overlay_id,0);
 		} else {		
 			if (MULTI_IS_TRACKER_GAME) {
 				gameseq_post_event(GS_EVENT_PXO);
@@ -1098,7 +1100,7 @@
 	}	
 
 	if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
-		help_overlay_set_state(MULTI_JOIN_OVERLAY, 0);
+		help_overlay_set_state(Multi_join_overlay_id, 0);
 	}
 
 	// do any network related stuff
@@ -1132,7 +1134,7 @@
 	multi_join_blit_top_stuff();
 
 	// draw the help overlay
-	help_overlay_maybe_blit(MULTI_JOIN_OVERLAY);
+	help_overlay_maybe_blit(Multi_join_overlay_id);
 	
 	// flip the buffer
 	gr_flip();
@@ -1152,11 +1154,8 @@
 	// unload any bitmaps
 	if(!bm_unload(Multi_join_bitmap)){
 		nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_join_bitmap_fname[gr_screen.res]));
-	}
+	}	
 
-	// unload the help overlay
-	help_overlay_unload(MULTI_JOIN_OVERLAY);	
-
 	// free up the active game list
 	multi_free_active_games();
 	
@@ -1222,10 +1221,10 @@
 
 	// help overlay
 	case MJ_HELP:
-		if(!help_overlay_active(MULTI_JOIN_OVERLAY)){
-			help_overlay_set_state(MULTI_JOIN_OVERLAY,1);
+		if(!help_overlay_active(Multi_join_overlay_id)){
+			help_overlay_set_state(Multi_join_overlay_id,1);
 		} else {
-			help_overlay_set_state(MULTI_JOIN_OVERLAY,0);
+			help_overlay_set_state(Multi_join_overlay_id,0);
 		}
 		break;
 
@@ -2263,6 +2262,8 @@
 // hold temporary values in this structure when on a standalone server
 netgame_info Multi_sg_netgame_temp;
 
+int Multi_sg_overlay_id;
+
 // forward declarations
 void multi_sg_check_buttons();
 void multi_sg_button_pressed(int n);
@@ -2342,8 +2343,8 @@
 	}
 
 	// load the help overlay
-	help_overlay_load(MULTI_START_OVERLAY);
-	help_overlay_set_state(MULTI_START_OVERLAY,0);
+	Multi_sg_overlay_id = help_overlay_get_index(MULTI_START_OVERLAY);
+	help_overlay_set_state(Multi_sg_overlay_id,0);
 
 	// intiialize the rank selection items	
 	multi_sg_select_rank_default();	
@@ -2429,8 +2430,8 @@
 	// process any keypresses
 	switch(k){
 	case KEY_ESC :		
-		if(help_overlay_active(MULTI_START_OVERLAY)){
-			help_overlay_set_state(MULTI_START_OVERLAY,0);
+		if(help_overlay_active(Multi_sg_overlay_id)){
+			help_overlay_set_state(Multi_sg_overlay_id,0);
 		} else {
 			gamesnd_play_iface(SND_USER_SELECT);
 			multi_quit_game(PROMPT_NONE);
@@ -2446,7 +2447,7 @@
 	}	
 
 	if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
-		help_overlay_set_state(MULTI_START_OVERLAY, 0);
+		help_overlay_set_state(Multi_sg_overlay_id, 0);
 	}
 
 	// check to see if the user has selected a different rank
@@ -2478,7 +2479,7 @@
 	multi_sg_draw_radio_buttons();
 
 	// draw the help overlay
-	help_overlay_maybe_blit(MULTI_START_OVERLAY);
+	help_overlay_maybe_blit(Multi_sg_overlay_id);
 	
 	// flip the buffer
 	gr_flip();
@@ -2495,9 +2496,6 @@
 	if(!bm_unload(Multi_sg_bitmap)){
 		nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_sg_bitmap_fname[gr_screen.res]));
 	}
-
-	// unload the help overlay
-	help_overlay_unload(MULTI_START_OVERLAY);
 	
 	// destroy the UI_WINDOW
 	Multi_sg_window.destroy();	
@@ -2526,10 +2524,10 @@
 
 	// help overlay	
 	case MSG_HELP:
-		if(!help_overlay_active(MULTI_START_OVERLAY)){
-			help_overlay_set_state(MULTI_START_OVERLAY,1);
+		if(!help_overlay_active(Multi_sg_overlay_id)){
+			help_overlay_set_state(Multi_sg_overlay_id,1);
 		} else {
-			help_overlay_set_state(MULTI_START_OVERLAY,0);
+			help_overlay_set_state(Multi_sg_overlay_id,0);
 		}
 		break;
 
@@ -3339,6 +3337,8 @@
 SCP_vector<multi_create_info> Multi_create_mission_list;
 SCP_vector<multi_create_info> Multi_create_campaign_list;
 
+int Multi_create_overlay_id;
+
 // LOCAL function definitions
 void multi_create_check_buttons();
 void multi_create_button_pressed(int n);
@@ -3574,8 +3574,8 @@
 	chatbox_create();
 
 	// load the help overlay 
-	help_overlay_load(MULTI_CREATE_OVERLAY);
-	help_overlay_set_state(MULTI_CREATE_OVERLAY, 0);
+	Multi_create_overlay_id = help_overlay_get_index(MULTI_CREATE_OVERLAY);
+	help_overlay_set_state(Multi_create_overlay_id, 0);
 
 	// initialize the common notification messaging
 	multi_common_notify_init();		
@@ -3785,8 +3785,8 @@
 	switch(k){	
 		// same as the cancel button
 		case KEY_ESC: {
-			if ( help_overlay_active(MULTI_CREATE_OVERLAY) ) {
-				help_overlay_set_state(MULTI_CREATE_OVERLAY, 0);
+			if ( help_overlay_active(Multi_create_overlay_id) ) {
+				help_overlay_set_state(Multi_create_overlay_id, 0);
 			} else {		
 				gamesnd_play_iface(SND_USER_SELECT);		
 				multi_quit_game(PROMPT_HOST);		
@@ -3802,7 +3802,7 @@
 	}	
 
 	if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
-		help_overlay_set_state(MULTI_CREATE_OVERLAY, 0);
+		help_overlay_set_state(Multi_create_overlay_id, 0);
 	}
 
 	// process any button clicks
@@ -3889,7 +3889,7 @@
 	multi_common_voice_display_status();
 
 	// blit the help overlay if necessary
-	help_overlay_maybe_blit(MULTI_CREATE_OVERLAY);
+	help_overlay_maybe_blit(Multi_create_overlay_id);
 
 	// test code
 	if(MULTI_IS_TRACKER_GAME){
@@ -3925,9 +3925,6 @@
 	if(!bm_unload(Multi_create_bitmap)){
 		nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_create_bitmap_fname[gr_screen.res]));
 	}		
-
-	// unload the help overlay
-	help_overlay_unload(MULTI_CREATE_OVERLAY);
 	
 	// destroy the chatbox
 	// chatbox_close();
@@ -3975,10 +3972,10 @@
 
 	// help button
 	case MC_HELP :
-		if(!help_overlay_active(MULTI_CREATE_OVERLAY)){
-			help_overlay_set_state(MULTI_CREATE_OVERLAY,1);
+		if(!help_overlay_active(Multi_create_overlay_id)){
+			help_overlay_set_state(Multi_create_overlay_id,1);
 		} else {
-			help_overlay_set_state(MULTI_CREATE_OVERLAY,0);
+			help_overlay_set_state(Multi_create_overlay_id,0);
 		}
 		break;
 
Index: code/network/multiui.h
===================================================================
--- code/network/multiui.h	(revision 10737)
+++ code/network/multiui.h	(working copy)
@@ -85,6 +85,8 @@
 extern SCP_vector<multi_create_info> Multi_create_mission_list;
 extern SCP_vector<multi_create_info> Multi_create_campaign_list;
 
+extern int Multi_create_overlay_id;
+
 void multi_create_list_load_missions();
 void multi_create_list_load_campaigns();
 
@@ -94,8 +96,12 @@
 // returns an index into Multi_create_campaign_list
 int multi_create_lookup_campaign(char *fname);
 
+extern int Multi_sg_overlay_id;
+
 void multi_sg_rank_build_name(char *in,char *out);
 
+extern int Multi_join_overlay_id;
+
 void multi_join_game_init();
 void multi_join_game_close();
 void multi_join_game_do_frame();
