[Scummvm-git-logs] scummvm master -> 5a6b282c7c5c3752a46f61e7f11890f79705d0b8

dreammaster dreammaster at scummvm.org
Tue Mar 9 04:08:11 UTC 2021


This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
d12bb69417 AGS: Move event.cpp globals to Globals
f05ad88320 AGS: Move gui.cpp globals to Globals
dc019af530 AGS: Move character.cpp globals to Globals
81976cb994 AGS: Move dialog.cpp globals to Globals
764271844a AGS: Move global_object globals to Globals
5a6b282c7c AGS: Move engine_setup.cpp globals to Globals


Commit: d12bb6941727cb4554120ed688ca655a940748c4
    https://github.com/scummvm/scummvm/commit/d12bb6941727cb4554120ed688ca655a940748c4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-08T18:29:32-08:00

Commit Message:
AGS: Move event.cpp globals to Globals

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/event.h
    engines/ags/engine/ac/global_character.cpp
    engines/ags/engine/ac/global_hotspot.cpp
    engines/ags/engine/ac/global_inventoryitem.cpp
    engines/ags/engine/ac/global_object.cpp
    engines/ags/engine/ac/global_region.cpp
    engines/ags/engine/ac/global_room.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/invwindow.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index d3f36a0f39..ec577aff9f 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -364,7 +364,7 @@ void FaceDirectionalLoop(CharacterInfo *char1, int direction, int blockingStyle)
 	// Change facing only if the desired direction is different
 	if (direction != char1->loop) {
 		if ((_GP(game).options[OPT_TURNTOFACELOC] != 0) &&
-		        (in_enters_screen == 0)) {
+		        (_G(in_enters_screen) == 0)) {
 			const int no_diagonal = useDiagonal(char1);
 			const int highestLoopForTurning = no_diagonal != 1 ? kDirLoop_Last : kDirLoop_LastOrthogonal;
 			if ((char1->loop <= highestLoopForTurning)) {
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index d87a809a64..14a9c2d5e4 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -48,42 +48,26 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
 extern color palette[256];
 extern IGraphicsDriver *gfxDriver;
-
 extern color old_palette[256];
 
-int in_enters_screen = 0, done_es_error = 0;
-int in_leaves_screen = -1;
-
-EventHappened event[MAXEVENTS + 1];
-int numevents = 0;
-
-const char *evblockbasename;
-int evblocknum;
-
-int inside_processevent = 0;
-int eventClaimed = EVENT_NONE;
-
-const char *tsnames[4] = { nullptr, REP_EXEC_NAME, "on_key_press", "on_mouse_click" };
-
 
 int run_claimable_event(const char *tsname, bool includeRoom, int numParams, const RuntimeScriptValue *params, bool *eventWasClaimed) {
 	*eventWasClaimed = true;
 	// Run the room script function, and if it is not claimed,
 	// then run the main one
-	// We need to remember the eventClaimed variable's state, in case
+	// We need to remember the _G(eventClaimed) variable's state, in case
 	// this is a nested event
-	int eventClaimedOldValue = eventClaimed;
-	eventClaimed = EVENT_INPROGRESS;
+	int eventClaimedOldValue = _G(eventClaimed);
+	_G(eventClaimed) = EVENT_INPROGRESS;
 	int toret;
 
 	if (includeRoom && _G(roominst)) {
 		toret = RunScriptFunctionIfExists(_G(roominst), tsname, numParams, params);
 
-		if (eventClaimed == EVENT_CLAIMED) {
-			eventClaimed = eventClaimedOldValue;
+		if (_G(eventClaimed) == EVENT_CLAIMED) {
+			_G(eventClaimed) = eventClaimedOldValue;
 			return toret;
 		}
 	}
@@ -92,13 +76,13 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 	for (int kk = 0; kk < _G(numScriptModules); kk++) {
 		toret = RunScriptFunctionIfExists(_GP(moduleInst)[kk], tsname, numParams, params);
 
-		if (eventClaimed == EVENT_CLAIMED) {
-			eventClaimed = eventClaimedOldValue;
+		if (_G(eventClaimed) == EVENT_CLAIMED) {
+			_G(eventClaimed) = eventClaimedOldValue;
 			return toret;
 		}
 	}
 
-	eventClaimed = eventClaimedOldValue;
+	_G(eventClaimed) = eventClaimedOldValue;
 	*eventWasClaimed = false;
 	return 0;
 }
@@ -109,7 +93,7 @@ void run_on_event(int evtype, RuntimeScriptValue &wparam) {
 }
 
 void run_room_event(int id) {
-	evblockbasename = "room";
+	_G(evblockbasename) = "room";
 
 	if (_GP(thisroom).EventHandlers != nullptr) {
 		run_interaction_script(_GP(thisroom).EventHandlers.get(), id);
@@ -119,7 +103,7 @@ void run_room_event(int id) {
 }
 
 void run_event_block_inv(int invNum, int event_) {
-	evblockbasename = "inventory%d";
+	_G(evblockbasename) = "inventory%d";
 	if (loaded_game_file_version > kGameVersion_272) {
 		run_interaction_script(_GP(game).invScripts[invNum].get(), event_);
 	} else {
@@ -130,20 +114,20 @@ void run_event_block_inv(int invNum, int event_) {
 
 // event list functions
 void setevent(int evtyp, int ev1, int ev2, int ev3) {
-	event[numevents].type = evtyp;
-	event[numevents].data1 = ev1;
-	event[numevents].data2 = ev2;
-	event[numevents].data3 = ev3;
-	event[numevents].player = _GP(game).playercharacter;
-	numevents++;
-	if (numevents >= MAXEVENTS) quit("too many events posted");
+	_G(event)[_G(numevents)].type = evtyp;
+	_G(event)[_G(numevents)].data1 = ev1;
+	_G(event)[_G(numevents)].data2 = ev2;
+	_G(event)[_G(numevents)].data3 = ev3;
+	_G(event)[_G(numevents)].player = _GP(game).playercharacter;
+	_G(numevents)++;
+	if (_G(numevents) >= MAXEVENTS) quit("too many events posted");
 }
 
 // TODO: this is kind of a hack, which forces event to be processed even if
 // it was fired from insides of other event processing.
 // The proper solution would be to do the event processing overhaul in AGS.
 void force_event(int evtyp, int ev1, int ev2, int ev3) {
-	if (inside_processevent)
+	if (_G(inside_processevent))
 		runevent_now(evtyp, ev1, ev2, ev3);
 	else
 		setevent(evtyp, ev1, ev2, ev3);
@@ -154,17 +138,17 @@ void process_event(EventHappened *evp) {
 	if (evp->type == EV_TEXTSCRIPT) {
 		_G(ccError) = 0;
 		if (evp->data2 > -1000) {
-			QueueScriptFunction(kScInstGame, tsnames[evp->data1], 1, RuntimeScriptValue().SetInt32(evp->data2));
+			QueueScriptFunction(kScInstGame, _G(tsnames)[evp->data1], 1, RuntimeScriptValue().SetInt32(evp->data2));
 		} else {
-			QueueScriptFunction(kScInstGame, tsnames[evp->data1]);
+			QueueScriptFunction(kScInstGame, _G(tsnames)[evp->data1]);
 		}
 	} else if (evp->type == EV_NEWROOM) {
 		NewRoom(evp->data1);
 	} else if (evp->type == EV_RUNEVBLOCK) {
 		Interaction *evpt = nullptr;
 		PInteractionScripts scriptPtr = nullptr;
-		const char *oldbasename = evblockbasename;
-		int   oldblocknum = evblocknum;
+		const char *oldbasename = _G(evblockbasename);
+		int   oldblocknum = _G(evblocknum);
 
 		if (evp->data1 == EVB_HOTSPOT) {
 
@@ -173,8 +157,8 @@ void process_event(EventHappened *evp) {
 			else
 				evpt = &_G(croom)->intrHotspot[evp->data2];
 
-			evblockbasename = "hotspot%d";
-			evblocknum = evp->data2;
+			_G(evblockbasename) = "hotspot%d";
+			_G(evblocknum) = evp->data2;
 			//Debug::Printf("Running hotspot interaction for hotspot %d, event %d", evp->data2, evp->data3);
 		} else if (evp->data1 == EVB_ROOM) {
 
@@ -183,9 +167,9 @@ void process_event(EventHappened *evp) {
 			else
 				evpt = &_G(croom)->intrRoom;
 
-			evblockbasename = "room";
+			_G(evblockbasename) = "room";
 			if (evp->data3 == 5) {
-				in_enters_screen++;
+				_G(in_enters_screen)++;
 				run_on_event(GE_ENTER_ROOM, RuntimeScriptValue().SetInt32(_G(displayed_room)));
 
 			}
@@ -199,11 +183,11 @@ void process_event(EventHappened *evp) {
 		} else
 			quit("process_event: RunEvBlock: unknown evb type");
 
-		evblockbasename = oldbasename;
-		evblocknum = oldblocknum;
+		_G(evblockbasename) = oldbasename;
+		_G(evblocknum) = oldblocknum;
 
 		if ((evp->data3 == 5) && (evp->data1 == EVB_ROOM))
-			in_enters_screen--;
+			_G(in_enters_screen)--;
 	} else if (evp->type == EV_FADEIN) {
 		// if they change the transition type before the fadein, make
 		// sure the screen doesn't freeze up
@@ -362,7 +346,7 @@ void runevent_now(int evtyp, int ev1, int ev2, int ev3) {
 void processallevents(int numev, EventHappened *evlist) {
 	int dd;
 
-	if (inside_processevent)
+	if (_G(inside_processevent))
 		return;
 
 	// make a copy of the events - if processing an event includes
@@ -373,7 +357,7 @@ void processallevents(int numev, EventHappened *evlist) {
 
 	int room_was = _GP(play).room_changes;
 
-	inside_processevent++;
+	_G(inside_processevent)++;
 
 	for (dd = 0; dd < numev; dd++) {
 
@@ -383,21 +367,21 @@ void processallevents(int numev, EventHappened *evlist) {
 			break;  // changed room, so discard other events
 	}
 
-	inside_processevent--;
+	_G(inside_processevent)--;
 }
 
 void update_events() {
-	processallevents(numevents, &event[0]);
-	numevents = 0;
+	processallevents(_G(numevents), &_G(event)[0]);
+	_G(numevents) = 0;
 }
 // end event list functions
 
 
 void ClaimEvent() {
-	if (eventClaimed == EVENT_NONE)
+	if (_G(eventClaimed) == EVENT_NONE)
 		quit("!ClaimEvent: no event to claim");
 
-	eventClaimed = EVENT_CLAIMED;
+	_G(eventClaimed) = EVENT_CLAIMED;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/event.h b/engines/ags/engine/ac/event.h
index 2e1fb955fe..eeb041c1df 100644
--- a/engines/ags/engine/ac/event.h
+++ b/engines/ags/engine/ac/event.h
@@ -73,19 +73,6 @@ void update_events();
 // end event list functions
 void ClaimEvent();
 
-extern int in_enters_screen, done_es_error;
-extern int in_leaves_screen;
-
-extern EventHappened event[MAXEVENTS + 1];
-extern int numevents;
-
-extern const char *evblockbasename;
-extern int evblocknum;
-
-extern int eventClaimed;
-
-extern const char *tsnames[4];
-
 } // namespace AGS3
 
 #endif
diff --git a/engines/ags/engine/ac/global_character.cpp b/engines/ags/engine/ac/global_character.cpp
index 73e4ba7ae6..3e216eed32 100644
--- a/engines/ags/engine/ac/global_character.cpp
+++ b/engines/ags/engine/ac/global_character.cpp
@@ -389,8 +389,8 @@ void RunCharacterInteraction(int cc, int mood) {
 	else if (mood == MODE_CUSTOM1) passon = 6;
 	else if (mood == MODE_CUSTOM2) passon = 7;
 
-	evblockbasename = "character%d";
-	evblocknum = cc;
+	_G(evblockbasename) = "character%d";
+	_G(evblocknum) = cc;
 	if (loaded_game_file_version > kGameVersion_272) {
 		if (passon >= 0)
 			run_interaction_script(_GP(game).charScripts[cc].get(), passon, 4, (passon == 3));
diff --git a/engines/ags/engine/ac/global_hotspot.cpp b/engines/ags/engine/ac/global_hotspot.cpp
index b8175233da..8bc11cf533 100644
--- a/engines/ags/engine/ac/global_hotspot.cpp
+++ b/engines/ags/engine/ac/global_hotspot.cpp
@@ -115,11 +115,11 @@ void RunHotspotInteraction(int hotspothere, int mood) {
 
 	// can't use the setevent functions because this ProcessClick is only
 	// executed once in a eventlist
-	const char *oldbasename = evblockbasename;
-	int   oldblocknum = evblocknum;
+	const char *oldbasename = _G(evblockbasename);
+	int   oldblocknum = _G(evblocknum);
 
-	evblockbasename = "hotspot%d";
-	evblocknum = hotspothere;
+	_G(evblockbasename) = "hotspot%d";
+	_G(evblocknum) = hotspothere;
 
 	if (_GP(thisroom).Hotspots[hotspothere].EventHandlers != nullptr) {
 		if (passon >= 0)
@@ -128,8 +128,8 @@ void RunHotspotInteraction(int hotspothere, int mood) {
 	} else {
 		if (passon >= 0) {
 			if (run_interaction_event(&_G(croom)->intrHotspot[hotspothere], passon, 5, (passon == 3))) {
-				evblockbasename = oldbasename;
-				evblocknum = oldblocknum;
+				_G(evblockbasename) = oldbasename;
+				_G(evblocknum) = oldblocknum;
 				return;
 			}
 		}
@@ -137,8 +137,8 @@ void RunHotspotInteraction(int hotspothere, int mood) {
 		run_interaction_event(&_G(croom)->intrHotspot[hotspothere], 5);
 	}
 
-	evblockbasename = oldbasename;
-	evblocknum = oldblocknum;
+	_G(evblockbasename) = oldbasename;
+	_G(evblocknum) = oldblocknum;
 }
 
 int GetHotspotProperty(int hss, const char *property) {
diff --git a/engines/ags/engine/ac/global_inventoryitem.cpp b/engines/ags/engine/ac/global_inventoryitem.cpp
index da80d98935..f82d49a1d1 100644
--- a/engines/ags/engine/ac/global_inventoryitem.cpp
+++ b/engines/ags/engine/ac/global_inventoryitem.cpp
@@ -39,14 +39,9 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-
-
 extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
-extern const char *evblockbasename;
-extern int evblocknum;
 extern CharacterInfo *playerchar;
 
-
 void set_inv_item_pic(int invi, int piccy) {
 	if ((invi < 1) || (invi > _GP(game).numinvitems))
 		quit("!SetInvItemPic: invalid inventory item specified");
@@ -112,7 +107,7 @@ void RunInventoryInteraction(int iit, int modd) {
 	if ((iit < 0) || (iit >= _GP(game).numinvitems))
 		quit("!RunInventoryInteraction: invalid inventory number");
 
-	evblocknum = iit;
+	_G(evblocknum) = iit;
 	if (modd == MODE_LOOK)
 		run_event_block_inv(iit, 0);
 	else if (modd == MODE_HAND)
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index ea6a8a2923..21ba573e8b 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -410,8 +410,8 @@ void RunObjectInteraction(int aa, int mood) {
 		cdata = playerchar->activeinv;
 		_GP(play).usedinv = cdata;
 	}
-	evblockbasename = "object%d";
-	evblocknum = aa;
+	_G(evblockbasename) = "object%d";
+	_G(evblocknum) = aa;
 
 	if (_GP(thisroom).Objects[aa].EventHandlers != nullptr) {
 		if (passon >= 0) {
diff --git a/engines/ags/engine/ac/global_region.cpp b/engines/ags/engine/ac/global_region.cpp
index 4632666c3d..ee20d291f8 100644
--- a/engines/ags/engine/ac/global_region.cpp
+++ b/engines/ags/engine/ac/global_region.cpp
@@ -36,9 +36,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern const char *evblockbasename;
-extern int evblocknum;
-
 int GetRegionIDAtRoom(int xxx, int yyy) {
 	// if the co-ordinates are off the edge of the screen,
 	// correct them to be just within
@@ -150,11 +147,11 @@ void RunRegionInteraction(int regnum, int mood) {
 	// while another interaction (eg. hotspot) is in a Wait
 	// command, and leaving our basename would call the wrong
 	// script later on
-	const char *oldbasename = evblockbasename;
-	int   oldblocknum = evblocknum;
+	const char *oldbasename = _G(evblockbasename);
+	int   oldblocknum = _G(evblocknum);
 
-	evblockbasename = "region%d";
-	evblocknum = regnum;
+	_G(evblockbasename) = "region%d";
+	_G(evblocknum) = regnum;
 
 	if (_GP(thisroom).Regions[regnum].EventHandlers != nullptr) {
 		run_interaction_script(_GP(thisroom).Regions[regnum].EventHandlers.get(), mood);
@@ -162,8 +159,8 @@ void RunRegionInteraction(int regnum, int mood) {
 		run_interaction_event(&_G(croom)->intrRegion[regnum], mood);
 	}
 
-	evblockbasename = oldbasename;
-	evblocknum = oldblocknum;
+	_G(evblockbasename) = oldbasename;
+	_G(evblocknum) = oldblocknum;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index 25f0756c01..a53ebb83b0 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -45,11 +45,7 @@ namespace AGS3 {
 using namespace Shared;
 
 extern CharacterInfo *playerchar;
-
-extern int in_enters_screen;
-extern int in_leaves_screen;
 extern int in_inv_screen, inv_screen_newroom;
-
 extern int gs_to_newroom;
 
 
@@ -106,11 +102,11 @@ void NewRoom(int nrnum) {
 
 	get_script_position(_GP(last_in_dialog_request_script_pos));
 
-	if (in_leaves_screen >= 0) {
+	if (_G(in_leaves_screen) >= 0) {
 		// NewRoom called from the Player Leaves Screen event -- just
 		// change which room it will go to
-		in_leaves_screen = nrnum;
-	} else if (in_enters_screen) {
+		_G(in_leaves_screen) = nrnum;
+	} else if (_G(in_enters_screen)) {
 		setevent(EV_NEWROOM, nrnum);
 		return;
 	} else if (in_inv_screen) {
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 61ae7c1c33..da76e24815 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -636,7 +636,7 @@ void gui_on_mouse_up(const int wasongui, const int wasbutdown) {
 			mouse_ifacebut_yoffs = _G(mousey) - (guio->Y) - _GP(guis)[wasongui].Y;
 			int iit = offset_over_inv((GUIInvWindow *)guio);
 			if (iit >= 0) {
-				evblocknum = iit;
+				_G(evblocknum) = iit;
 				_GP(play).used_inv_on = iit;
 				if (_GP(game).options[OPT_HANDLEINVCLICKS]) {
 					// Let the script handle the click
@@ -648,7 +648,7 @@ void gui_on_mouse_up(const int wasongui, const int wasbutdown) {
 					SetActiveInventory(iit);
 				else
 					RunInventoryInteraction(iit, cur_mode);
-				evblocknum = -1;
+				_G(evblocknum) = -1;
 			}
 		} else quit("clicked on unknown control type");
 		if (_GP(guis)[wasongui].PopupStyle == kGUIPopupMouseY)
diff --git a/engines/ags/engine/ac/invwindow.cpp b/engines/ags/engine/ac/invwindow.cpp
index 174773ab58..e8f348d6bb 100644
--- a/engines/ags/engine/ac/invwindow.cpp
+++ b/engines/ags/engine/ac/invwindow.cpp
@@ -53,18 +53,10 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-
-
 extern CharacterExtras *charextra;
-
 extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
-
-extern int evblocknum;
 extern CharacterInfo *playerchar;
 
-
-
-
 int in_inv_screen = 0, inv_screen_newroom = -1;
 
 // *** INV WINDOW FUNCTIONS
@@ -385,7 +377,7 @@ bool InventoryScreen::Run() {
 		if (mouseY < buttonyp) {
 			int clickedon = isonitem;
 			if (clickedon < 0) return true; // continue inventory screen loop
-			evblocknum = dii[clickedon].num;
+			_G(evblocknum) = dii[clickedon].num;
 			_GP(play).used_inv_on = dii[clickedon].num;
 
 			if (cmode == MODE_LOOK) {
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index ef2e98f826..7e0f8ccbe1 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -85,14 +85,8 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-
-extern int numevents;
 extern CharacterExtras *charextra;
-extern int done_es_error;
 extern Bitmap *walkareabackup, *walkable_areas_temp;
-
-extern int in_leaves_screen;
 extern CharacterInfo *playerchar;
 extern unsigned int loopcounter;
 extern IDriverDependantBitmap *roomBackgroundBmp;
@@ -259,7 +253,7 @@ void unload_old_room() {
 	}
 
 	cancel_all_scripts();
-	numevents = 0;  // cancel any pending room events
+	_G(numevents) = 0;  // cancel any pending room events
 
 	if (roomBackgroundBmp != nullptr) {
 		gfxDriver->DestroyDDB(roomBackgroundBmp);
@@ -435,7 +429,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
 
 	String room_filename;
 	int cc;
-	done_es_error = 0;
+	_G(done_es_error) = 0;
 	_GP(play).room_changes ++;
 	// TODO: find out why do we need to temporarily lower color depth to 8-bit.
 	// Or do we? There's a serious usability problem in this: if any bitmap is
@@ -904,7 +898,7 @@ void new_room(int newnum, CharacterInfo *forchar) {
 	update_polled_stuff_if_runtime();
 
 	// we are currently running Leaves Screen scripts
-	in_leaves_screen = newnum;
+	_G(in_leaves_screen) = newnum;
 
 	// player leaves screen event
 	run_room_event(8);
@@ -914,8 +908,8 @@ void new_room(int newnum, CharacterInfo *forchar) {
 	pl_run_plugin_hooks(AGSE_LEAVEROOM, _G(displayed_room));
 
 	// update the new room number if it has been altered by OnLeave scripts
-	newnum = in_leaves_screen;
-	in_leaves_screen = -1;
+	newnum = _G(in_leaves_screen);
+	_G(in_leaves_screen) = -1;
 
 	if ((playerchar->following >= 0) &&
 	        (_GP(game).chars[playerchar->following].room != newnum)) {
@@ -1020,7 +1014,7 @@ void on_background_frame_change() {
 	if (_GP(game).color_depth > 1)
 		setpal();
 
-	if (in_enters_screen)
+	if (_G(in_enters_screen))
 		return;
 
 	// Don't update the palette if it hasn't changed
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index e6ee93e992..2b633ad3fe 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -78,8 +78,6 @@ extern int ifacepopped;
 
 extern int game_paused;
 extern int getloctype_index;
-extern int in_enters_screen, done_es_error;
-extern int in_leaves_screen;
 extern CharacterInfo *playerchar;
 extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
 extern int cur_mode;
@@ -119,12 +117,12 @@ static void ProperExit() {
 }
 
 static void game_loop_check_problems_at_start() {
-	if ((in_enters_screen != 0) & (_G(displayed_room) == _G(starting_room)))
+	if ((_G(in_enters_screen) != 0) & (_G(displayed_room) == _G(starting_room)))
 		quit("!A text script run in the Player Enters Screen event caused the\n"
 			"screen to be updated. If you need to use Wait(), do so in After Fadein");
-	if ((in_enters_screen != 0) && (done_es_error == 0)) {
+	if ((_G(in_enters_screen) != 0) && (_G(done_es_error) == 0)) {
 		debug_script_warn("Wait() was used in Player Enters Screen - use Enters Screen After Fadein instead");
-		done_es_error = 1;
+		_G(done_es_error) = 1;
 	}
 	if (_G(no_blocking_functions))
 		quit("!A blocking function was called from within a non-blocking event such as " REP_EXEC_ALWAYS_NAME);
@@ -187,7 +185,7 @@ static int game_loop_check_ground_level_interactions() {
 		if ((restrict_until) && (!ShouldStayInWaitMode())) {
 			// cancel the Rep Exec and Stands on Hotspot events that
 			// we just added -- otherwise the event queue gets huge
-			numevents = numEventsAtStartOfFunction;
+			_G(numevents) = numEventsAtStartOfFunction;
 			return 0;
 		}
 	} // end if checking ground level interactions
@@ -543,7 +541,7 @@ static void check_room_edges(int numevents_was) {
 		// if not in Player Enters Screen (allow walking in from off-screen)
 		int edgesActivated[4] = { 0, 0, 0, 0 };
 		// Only do it if nothing else has happened (eg. mouseclick)
-		if ((numevents == numevents_was) &&
+		if ((_G(numevents) == numevents_was) &&
 			((_GP(play).ground_level_areas_disabled & GLED_INTERACTION) == 0)) {
 
 			if (playerchar->x <= _GP(thisroom).Edges.Left)
@@ -578,7 +576,7 @@ static void game_loop_check_controls(bool checkControls) {
 	// don't let the player do anything before the screen fades in
 	if ((_G(in_new_room) == 0) && (checkControls)) {
 		int inRoom = _G(displayed_room);
-		int numevents_was = numevents;
+		int numevents_was = _G(numevents);
 		check_controls();
 		check_room_edges(numevents_was);
 		// If an inventory interaction changed the room
@@ -718,7 +716,7 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
 
 	int res;
 
-	numEventsAtStartOfFunction = numevents;
+	numEventsAtStartOfFunction = _G(numevents);
 
 	if (_G(want_exit)) {
 		ProperExit();
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 65dd3bc5c0..6396d5e7a4 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -180,7 +180,7 @@ int run_interaction_script(InteractionScripts *nint, int evnt, int chkAny, int i
 
 	RuntimeScriptValue rval_null;
 
-	if ((strstr(evblockbasename, "character") != nullptr) || (strstr(evblockbasename, "inventory") != nullptr)) {
+	if ((strstr(_G(evblockbasename), "character") != nullptr) || (strstr(_G(evblockbasename), "inventory") != nullptr)) {
 		// Character or Inventory (global script)
 		QueueScriptFunction(kScInstGame, nint->ScriptFuncNames[evnt]);
 	} else {
@@ -378,8 +378,8 @@ int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, int numParam,
 	_G(ccError) = cachedCcError;
 
 	// if the game has been restored, ensure that any further scripts are not run
-	if ((oldRestoreCount != gameHasBeenRestored) && (eventClaimed == EVENT_INPROGRESS))
-		eventClaimed = EVENT_CLAIMED;
+	if ((oldRestoreCount != gameHasBeenRestored) && (_G(eventClaimed) == EVENT_INPROGRESS))
+		_G(eventClaimed) = EVENT_CLAIMED;
 
 	return toret;
 }
@@ -635,14 +635,14 @@ int run_interaction_commandlist(InteractionCommandList *nicl, int *timesrun, int
 		{ // Run script
 			TempEip tempip(4001);
 			RuntimeScriptValue rval_null;
-			if ((strstr(evblockbasename, "character") != nullptr) || (strstr(evblockbasename, "inventory") != nullptr)) {
+			if ((strstr(_G(evblockbasename), "character") != nullptr) || (strstr(_G(evblockbasename), "inventory") != nullptr)) {
 				// Character or Inventory (global script)
-				const char *torun = make_ts_func_name(evblockbasename, evblocknum, nicl->Cmds[i].Data[0].Value);
+				const char *torun = make_ts_func_name(_G(evblockbasename), _G(evblocknum), nicl->Cmds[i].Data[0].Value);
 				// we are already inside the mouseclick event of the script, can't nest calls
 				QueueScriptFunction(kScInstGame, torun);
 			} else {
 				// Other (room script)
-				const char *torun = make_ts_func_name(evblockbasename, evblocknum, nicl->Cmds[i].Data[0].Value);
+				const char *torun = make_ts_func_name(_G(evblockbasename), _G(evblocknum), nicl->Cmds[i].Data[0].Value);
 				QueueScriptFunction(kScInstRoom, torun);
 			}
 			break;
@@ -852,15 +852,15 @@ void run_unhandled_event(int evnt) {
 		return;
 
 	int evtype = 0;
-	if (ags_strnicmp(evblockbasename, "hotspot", 7) == 0) evtype = 1;
-	else if (ags_strnicmp(evblockbasename, "object", 6) == 0) evtype = 2;
-	else if (ags_strnicmp(evblockbasename, "character", 9) == 0) evtype = 3;
-	else if (ags_strnicmp(evblockbasename, "inventory", 9) == 0) evtype = 5;
-	else if (ags_strnicmp(evblockbasename, "region", 6) == 0)
+	if (ags_strnicmp(_G(evblockbasename), "hotspot", 7) == 0) evtype = 1;
+	else if (ags_strnicmp(_G(evblockbasename), "object", 6) == 0) evtype = 2;
+	else if (ags_strnicmp(_G(evblockbasename), "character", 9) == 0) evtype = 3;
+	else if (ags_strnicmp(_G(evblockbasename), "inventory", 9) == 0) evtype = 5;
+	else if (ags_strnicmp(_G(evblockbasename), "region", 6) == 0)
 		return;  // no unhandled_events for regions
 
 	// clicked Hotspot 0, so change the type code
-	if ((evtype == 1) & (evblocknum == 0) & (evnt != 0) & (evnt != 5) & (evnt != 6))
+	if ((evtype == 1) & (_G(evblocknum) == 0) & (evnt != 0) & (evnt != 5) & (evnt != 6))
 		evtype = 4;
 	if ((evtype == 1) & ((evnt == 0) | (evnt == 5) | (evnt == 6)))
 		;  // character stands on hotspot, mouse moves over hotspot, any click
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 0a21d46f34..acf1975f90 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -39,6 +39,7 @@
 #include "ags/shared/util/directory.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/draw_software.h"
+#include "ags/engine/ac/event.h"
 #include "ags/engine/ac/gamesetup.h"
 #include "ags/engine/ac/gamestate.h"
 #include "ags/engine/ac/movelist.h"
@@ -126,6 +127,9 @@ Globals::Globals() {
 	// engine.cpp globals
 	_ResPaths = new ResourcePaths();
 
+	// event.cpp globals
+	_event = new EventHappened[MAXEVENTS + 1];
+
 	// fonts.cpp globals
 	_fonts = new std::vector<AGS::Shared::Font>();
 	_ttfRenderer = new TTFFontRenderer();
@@ -267,6 +271,9 @@ Globals::~Globals() {
 	// engine.cpp globals
 	delete _ResPaths;
 
+	// event.cpp globals
+	delete[] _event;
+
 	// fonts.cpp globals
 	delete _fonts;
 	delete _ttfRenderer;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 38d9cade56..f80a8c9b31 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -30,6 +30,7 @@
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/main/engine.h"
 #include "ags/engine/media/audio/audiodefines.h"
+#include "ags/engine/script/script.h"
 #include "ags/lib/std/array.h"
 #include "ags/lib/std/set.h"
 #include "ags/lib/allegro/color.h"
@@ -97,6 +98,7 @@ struct CharacterCache;
 struct COLOR_MAP;
 struct DirtyRects;
 struct ExecutingScript;
+struct EventHappened;
 struct GameFrameSetup;
 struct GameSetup;
 struct GameSetupStruct;
@@ -348,6 +350,27 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup event globals
+	 * @{
+	 */
+
+	int _in_enters_screen = 0, _done_es_error = 0;
+	int _in_leaves_screen = -1;
+
+	EventHappened *_event;
+	int _numevents = 0;
+
+	const char *_evblockbasename = nullptr;
+	int _evblocknum = 0;
+
+	int _inside_processevent = 0;
+	int _eventClaimed = 0;
+
+	const char *_tsnames[4] = { nullptr, REP_EXEC_NAME, "on_key_press", "on_mouse_click" };
+
+	/**@}*/
+
 	/**
 	 * \defgroup file globals
 	 * @{


Commit: f05ad88320ce0e8a9ab353453d8b2db7ff62dac8
    https://github.com/scummvm/scummvm/commit/f05ad88320ce0e8a9ab353453d8b2db7ff62dac8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-08T18:41:26-08:00

Commit Message:
AGS: Move gui.cpp globals to Globals

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_inventoryitem.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/gui.h
    engines/ags/engine/ac/invwindow.cpp
    engines/ags/engine/ac/sprite.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/gui/gui_engine.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/game_file.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/platform/windows/win_ex_handling.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 819b1cc71f..4e1c327fce 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -103,7 +103,6 @@ extern int walk_behind_baselines_changed;
 
 extern CharacterExtras *charextra;
 extern CharacterInfo *playerchar;
-extern int eip_guinum;
 extern int cur_mode, cur_cursor;
 extern int mouse_frame, mouse_delay;
 extern int lastmx, lastmy;
@@ -1570,7 +1569,7 @@ void prepare_characters_for_drawing() {
 	for (int aa = 0; aa < _GP(game).numcharacters; aa++) {
 		if (_GP(game).chars[aa].on == 0) continue;
 		if (_GP(game).chars[aa].room != _G(displayed_room)) continue;
-		eip_guinum = aa;
+		_G(eip_guinum) = aa;
 		const int useindx = aa + MAX_ROOM_OBJECTS;
 
 		CharacterInfo *chin = &_GP(game).chars[aa];
@@ -1962,7 +1961,7 @@ void draw_gui_and_overlays() {
 				if (guibg[aa] == nullptr)
 					recreate_guibg_image(&_GP(guis)[aa]);
 
-				eip_guinum = aa;
+				_G(eip_guinum) = aa;
 				_G(our_eip) = 370;
 				guibg[aa]->ClearTransparent();
 				_G(our_eip) = 372;
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 09b7a01fe9..e40e3162fe 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -116,10 +116,6 @@ extern int numLipLines, curLipLine, curLipLinePhoneme;
 extern CharacterExtras *charextra;
 extern DialogTopic *dialog;
 
-extern int ifacepopped;  // currently displayed pop-up GUI (-1 if none)
-extern int mouse_on_iface;   // mouse cursor is over this interface
-extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
-
 #if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
 extern int _G(psp_gfx_renderer);
 #endif
@@ -1165,10 +1161,10 @@ void restore_game_dialogs(Stream *in) {
 }
 
 void restore_game_more_dynamic_values(Stream *in) {
-	mouse_on_iface = in->ReadInt32();
+	_G(mouse_on_iface) = in->ReadInt32();
 	in->ReadInt32(); // mouse_on_iface_button
 	in->ReadInt32(); // mouse_pushed_iface
-	ifacepopped = in->ReadInt32();
+	_G(ifacepopped) = in->ReadInt32();
 	game_paused = in->ReadInt32();
 }
 
@@ -1572,8 +1568,8 @@ CutsceneSkipStyle get_cutscene_skipstyle() {
 void start_skipping_cutscene() {
 	_GP(play).fast_forward = 1;
 	// if a drop-down icon bar is up, remove it as it will pause the game
-	if (ifacepopped >= 0)
-		remove_popup_interface(ifacepopped);
+	if (_G(ifacepopped) >= 0)
+		remove_popup_interface(_G(ifacepopped));
 
 	// if a text message is currently displayed, remove it
 	if (_G(is_text_overlay) > 0)
diff --git a/engines/ags/engine/ac/global_inventoryitem.cpp b/engines/ags/engine/ac/global_inventoryitem.cpp
index f82d49a1d1..d2262bc45a 100644
--- a/engines/ags/engine/ac/global_inventoryitem.cpp
+++ b/engines/ags/engine/ac/global_inventoryitem.cpp
@@ -39,7 +39,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
 extern CharacterInfo *playerchar;
 
 void set_inv_item_pic(int invi, int piccy) {
@@ -80,8 +79,8 @@ int GetInvAt(int xxx, int yyy) {
 		int onobj = _GP(guis)[ongui].FindControlUnderMouse();
 		GUIObject *guio = _GP(guis)[ongui].GetControl(onobj);
 		if (guio) {
-			mouse_ifacebut_xoffs = _G(mousex) - (guio->X);
-			mouse_ifacebut_yoffs = _G(mousey) - (guio->Y);
+			_G(mouse_ifacebut_xoffs) = _G(mousex) - (guio->X);
+			_G(mouse_ifacebut_yoffs) = _G(mousey) - (guio->Y);
 		}
 		_G(mousex) = mxwas;
 		_G(mousey) = mywas;
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index da76e24815..3a6b5bbb40 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -68,12 +68,6 @@ extern Bitmap **guibg;
 extern IDriverDependantBitmap **guibgbmp;
 extern IGraphicsDriver *gfxDriver;
 
-int ifacepopped = -1; // currently displayed pop-up GUI (-1 if none)
-int mouse_on_iface = -1; // mouse cursor is over this interface
-int mouse_ifacebut_xoffs = -1, mouse_ifacebut_yoffs = -1;
-
-int eip_guinum, eip_guiobj;
-
 
 ScriptGUI *GUI_AsTextWindow(ScriptGUI *tehgui) {
 	// Internally both GUI and TextWindow are implemented by same class
@@ -307,8 +301,8 @@ void GUI_ProcessClick(int x, int y, int mbut) {
 //=============================================================================
 
 void remove_popup_interface(int ifacenum) {
-	if (ifacepopped != ifacenum) return;
-	ifacepopped = -1;
+	if (_G(ifacepopped) != ifacenum) return;
+	_G(ifacepopped) = -1;
 	UnPauseGame();
 	_GP(guis)[ifacenum].SetConceal(true);
 	if (_G(mousey) <= _GP(guis)[ifacenum].PopupAtMouseY)
@@ -319,7 +313,7 @@ void remove_popup_interface(int ifacenum) {
 	else if (IsInterfaceEnabled())
 		set_default_cursor();
 
-	if (ifacenum == mouse_on_iface) mouse_on_iface = -1;
+	if (ifacenum == _G(mouse_on_iface)) _G(mouse_on_iface) = -1;
 	guis_need_update = 1;
 }
 
@@ -589,7 +583,7 @@ int gui_on_mouse_move() {
 			if (_GP(guis)[guin].PopupStyle != kGUIPopupMouseY) continue;
 			if (_G(is_complete_overlay) > 0) break; // interfaces disabled
 			//    if (_GP(play).disabled_user_interface>0) break;
-			if (ifacepopped == guin) continue;
+			if (_G(ifacepopped) == guin) continue;
 			if (!_GP(guis)[guin].IsVisible()) continue;
 			// Don't allow it to be popped up while skipping cutscene
 			if (_GP(play).fast_forward) continue;
@@ -598,7 +592,7 @@ int gui_on_mouse_move() {
 				set_mouse_cursor(CURS_ARROW);
 				_GP(guis)[guin].SetConceal(false);
 				guis_need_update = 1;
-				ifacepopped = guin;
+				_G(ifacepopped) = guin;
 				PauseGame();
 				break;
 			}
@@ -632,8 +626,8 @@ void gui_on_mouse_up(const int wasongui, const int wasbutdown) {
 		if ((cttype == kGUIButton) || (cttype == kGUISlider) || (cttype == kGUIListBox)) {
 			force_event(EV_IFACECLICK, wasongui, i, wasbutdown);
 		} else if (cttype == kGUIInvWindow) {
-			mouse_ifacebut_xoffs = _G(mousex) - (guio->X) - _GP(guis)[wasongui].X;
-			mouse_ifacebut_yoffs = _G(mousey) - (guio->Y) - _GP(guis)[wasongui].Y;
+			_G(mouse_ifacebut_xoffs) = _G(mousex) - (guio->X) - _GP(guis)[wasongui].X;
+			_G(mouse_ifacebut_yoffs) = _G(mousey) - (guio->Y) - _GP(guis)[wasongui].Y;
 			int iit = offset_over_inv((GUIInvWindow *)guio);
 			if (iit >= 0) {
 				_G(evblocknum) = iit;
diff --git a/engines/ags/engine/ac/gui.h b/engines/ags/engine/ac/gui.h
index d871b601a2..d3ed4aed14 100644
--- a/engines/ags/engine/ac/gui.h
+++ b/engines/ags/engine/ac/gui.h
@@ -87,11 +87,6 @@ void    gui_on_mouse_hold(const int wasongui, const int wasbutdown);
 void    gui_on_mouse_up(const int wasongui, const int wasbutdown);
 void    gui_on_mouse_down(const int guin, const int mbut);
 
-extern int ifacepopped;
-
-extern int ifacepopped;
-extern int mouse_on_iface;
-
 } // namespace AGS3
 
 #endif
diff --git a/engines/ags/engine/ac/invwindow.cpp b/engines/ags/engine/ac/invwindow.cpp
index e8f348d6bb..b9ae29f8de 100644
--- a/engines/ags/engine/ac/invwindow.cpp
+++ b/engines/ags/engine/ac/invwindow.cpp
@@ -54,7 +54,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 extern CharacterExtras *charextra;
-extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
 extern CharacterInfo *playerchar;
 
 int in_inv_screen = 0, inv_screen_newroom = -1;
@@ -149,11 +148,11 @@ ScriptInvItem *InvWindow_GetItemAtIndex(GUIInvWindow *guii, int index) {
 int offset_over_inv(GUIInvWindow *inv) {
 	if (inv->ItemWidth <= 0 || inv->ItemHeight <= 0)
 		return -1;
-	int mover = mouse_ifacebut_xoffs / data_to_game_coord(inv->ItemWidth);
+	int mover = _G(mouse_ifacebut_xoffs) / data_to_game_coord(inv->ItemWidth);
 	// if it's off the edge of the visible items, ignore
 	if (mover >= inv->ColCount)
 		return -1;
-	mover += (mouse_ifacebut_yoffs / data_to_game_coord(inv->ItemHeight)) * inv->ColCount;
+	mover += (_G(mouse_ifacebut_yoffs) / data_to_game_coord(inv->ItemHeight)) * inv->ColCount;
 	if (mover >= inv->ColCount * inv->RowCount)
 		return -1;
 
diff --git a/engines/ags/engine/ac/sprite.cpp b/engines/ags/engine/ac/sprite.cpp
index 33226e9629..628d20689d 100644
--- a/engines/ags/engine/ac/sprite.cpp
+++ b/engines/ags/engine/ac/sprite.cpp
@@ -38,7 +38,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern int eip_guinum, eip_guiobj;
 extern color palette[256];
 extern IGraphicsDriver *gfxDriver;
 
@@ -148,8 +147,8 @@ void initialize_sprite(int ee) {
 		curspr = _GP(spriteset)[ee];
 		get_new_size_for_sprite(ee, curspr->GetWidth(), curspr->GetHeight(), newwid, newhit);
 
-		eip_guinum = ee;
-		eip_guiobj = newwid;
+		_G(eip_guinum) = ee;
+		_G(eip_guiobj) = newwid;
 
 		if ((newwid != curspr->GetWidth()) || (newhit != curspr->GetHeight())) {
 			tmpdbl = BitmapHelper::CreateTransparentBitmap(newwid, newhit, curspr->GetColorDepth());
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 9e6b8b641e..2a517244b0 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -352,7 +352,7 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
 	// 4. Initialize certain runtime variables
 	//
 	game_paused = 0;  // reset the game paused flag
-	ifacepopped = -1;
+	_G(ifacepopped) = -1;
 
 	String svg_suffix;
 	if (_GP(game).saveGameFileExtension[0] != 0)
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 9e60c68627..1147b293ad 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -212,12 +212,12 @@ HSaveError WriteGameState(PStream out) {
 	// Other dynamic values
 	out->WriteInt32(_G(frames_per_second));
 	out->WriteInt32(loopcounter);
-	out->WriteInt32(ifacepopped);
+	out->WriteInt32(_G(ifacepopped));
 	out->WriteInt32(game_paused);
 	// Mouse cursor
 	out->WriteInt32(cur_mode);
 	out->WriteInt32(cur_cursor);
-	out->WriteInt32(mouse_on_iface);
+	out->WriteInt32(_G(mouse_on_iface));
 
 	// Viewports and cameras
 	int viewcam_flags = 0;
@@ -303,12 +303,12 @@ HSaveError ReadGameState(PStream in, int32_t cmp_ver, const PreservedParams &pp,
 	// Other dynamic values
 	r_data.FPS = in->ReadInt32();
 	set_loop_counter(in->ReadInt32());
-	ifacepopped = in->ReadInt32();
+	_G(ifacepopped) = in->ReadInt32();
 	game_paused = in->ReadInt32();
 	// Mouse cursor state
 	r_data.CursorMode = in->ReadInt32();
 	r_data.CursorID = in->ReadInt32();
-	mouse_on_iface = in->ReadInt32();
+	_G(mouse_on_iface) = in->ReadInt32();
 
 	// Viewports and cameras
 	if (svg_ver < kGSSvgVersion_3510) {
diff --git a/engines/ags/engine/gui/gui_engine.cpp b/engines/ags/engine/gui/gui_engine.cpp
index be92431187..a52a122659 100644
--- a/engines/ags/engine/gui/gui_engine.cpp
+++ b/engines/ags/engine/gui/gui_engine.cpp
@@ -47,7 +47,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 // For engine these are defined in ac.cpp
-extern int eip_guiobj;
 extern void replace_macro_tokens(const char *, String &);
 
 // For engine these are defined in acfonts.cpp
@@ -99,11 +98,11 @@ bool is_sprite_alpha(int spr) {
 }
 
 void set_eip_guiobj(int eip) {
-	eip_guiobj = eip;
+	_G(eip_guiobj) = eip;
 }
 
 int get_eip_guiobj() {
-	return eip_guiobj;
+	return _G(eip_guiobj);
 }
 
 bool outlineGuiObjects = false;
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 2509018070..bf7d6a5552 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -85,8 +85,6 @@ using namespace AGS::Engine;
 
 extern char check_dynamic_sprites_at_exit;
 extern char pexbuf[STD_BUFFER_SIZE];
-extern int eip_guinum;
-extern int eip_guiobj;
 extern SpeechLipSyncLine *splipsync;
 extern int numLipLines, curLipLine, curLipLinePhoneme;
 
diff --git a/engines/ags/engine/main/game_file.cpp b/engines/ags/engine/main/game_file.cpp
index def0418591..4979b39f0a 100644
--- a/engines/ags/engine/main/game_file.cpp
+++ b/engines/ags/engine/main/game_file.cpp
@@ -59,7 +59,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern int ifacepopped;
 extern DialogTopic *dialog;
 
 
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 2b633ad3fe..175c8ded38 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -73,13 +73,9 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern int mouse_on_iface;   // mouse cursor is over this interface
-extern int ifacepopped;
-
 extern int game_paused;
 extern int getloctype_index;
 extern CharacterInfo *playerchar;
-extern int mouse_ifacebut_xoffs, mouse_ifacebut_yoffs;
 extern int cur_mode;
 extern char noWalkBehindsAtAll;
 extern CharacterExtras *charextra;
@@ -213,9 +209,9 @@ static void check_mouse_controls() {
 
 	mongu = gui_on_mouse_move();
 
-	mouse_on_iface = mongu;
-	if ((ifacepopped >= 0) && (_G(mousey) >= _GP(guis)[ifacepopped].Y + _GP(guis)[ifacepopped].Height))
-		remove_popup_interface(ifacepopped);
+	_G(mouse_on_iface) = mongu;
+	if ((_G(ifacepopped) >= 0) && (_G(mousey) >= _GP(guis)[_G(ifacepopped)].Y + _GP(guis)[_G(ifacepopped)].Height))
+		remove_popup_interface(_G(ifacepopped));
 
 	// check mouse clicks on GUIs
 	static int wasbutdown = 0, wasongui = 0;
@@ -746,7 +742,7 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
 		return;
 	}
 
-	mouse_on_iface = -1;
+	_G(mouse_on_iface) = -1;
 
 	check_debug_keys();
 
@@ -798,7 +794,7 @@ static void UpdateMouseOverLocation() {
 
 	if ((_GP(play).get_loc_name_save_cursor >= 0) &&
 		(_GP(play).get_loc_name_save_cursor != _GP(play).get_loc_name_last_time) &&
-		(mouse_on_iface < 0) && (ifacepopped < 0)) {
+		(_G(mouse_on_iface) < 0) && (_G(ifacepopped) < 0)) {
 		// we have saved the cursor, but the mouse location has changed
 		// and it's time to restore it
 		_GP(play).get_loc_name_save_cursor = -1;
diff --git a/engines/ags/engine/platform/windows/win_ex_handling.cpp b/engines/ags/engine/platform/windows/win_ex_handling.cpp
index e08c6d7118..c57f728ac3 100644
--- a/engines/ags/engine/platform/windows/win_ex_handling.cpp
+++ b/engines/ags/engine/platform/windows/win_ex_handling.cpp
@@ -42,8 +42,8 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 extern int _G(our_eip);
-extern int eip_guinum;
-extern int eip_guiobj;
+extern int _G(eip_guinum);
+extern int _G(eip_guiobj);
 extern int proper_exit;
 
 char tempmsg[100];
@@ -61,7 +61,7 @@ static void DisplayException() {
 	sprintf(printfworkingspace, "An exception 0x%X occurred in ACWIN.EXE at EIP = 0x%08X; program pointer is %+d, ACI version %s, gtags (%d,%d)\n\n"
 	        "AGS cannot continue, this exception was fatal. Please note down the numbers above, remember what you were doing at the time and post the details on the AGS Technical Forum.\n\n%s\n\n"
 	        "Most versions of Windows allow you to press Ctrl+C now to copy this entire message to the clipboard for easy reporting.\n\n%s (code %d)",
-	        excinfo.ExceptionCode, (intptr_t)excinfo.ExceptionAddress, _G(our_eip), EngineVersion.LongString.GetCStr(), eip_guinum, eip_guiobj, script_callstack.GetCStr(),
+	        excinfo.ExceptionCode, (intptr_t)excinfo.ExceptionAddress, _G(our_eip), EngineVersion.LongString.GetCStr(), _G(eip_guinum), _G(eip_guiobj), script_callstack.GetCStr(),
 	        (miniDumpResultCode == 0) ? "An error file CrashInfo.dmp has been created. You may be asked to upload this file when reporting this problem on the AGS Forums." :
 	        "Unable to create an error dump file.", miniDumpResultCode);
 	MessageBoxA(win_get_window(), printfworkingspace, "Illegal exception", MB_ICONSTOP | MB_OK);
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index f80a8c9b31..01c7dec1d6 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -504,6 +504,18 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup gui globals
+	 * @{
+	 */
+
+	int _ifacepopped = -1; // currently displayed pop-up GUI (-1 if none)
+	int _mouse_on_iface = -1; // mouse cursor is over this interface
+	int _mouse_ifacebut_xoffs = -1, _mouse_ifacebut_yoffs = -1;
+	int _eip_guinum = 0, _eip_guiobj = 0;
+
+	/**@}*/
+
 	/**
 	 * \defgroup guibutton globals
 	 * @{


Commit: dc019af53060e665fed161382788241b2f3be9dd
    https://github.com/scummvm/scummvm/commit/dc019af53060e665fed161382788241b2f3be9dd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-08T19:04:35-08:00

Commit Message:
AGS: Move character.cpp globals to Globals

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/character.h
    engines/ags/engine/ac/characterinfo_engine.cpp
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/gamestate.cpp
    engines/ags/engine/ac/global_audio.cpp
    engines/ags/engine/ac/global_character.cpp
    engines/ags/engine/ac/global_debug.cpp
    engines/ags/engine/ac/global_hotspot.cpp
    engines/ags/engine/ac/global_inventoryitem.cpp
    engines/ags/engine/ac/global_object.cpp
    engines/ags/engine/ac/global_room.cpp
    engines/ags/engine/ac/guiinv.cpp
    engines/ags/engine/ac/inventoryitem.cpp
    engines/ags/engine/ac/invwindow.cpp
    engines/ags/engine/ac/mouse.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/main/game_start.cpp
    engines/ags/engine/main/update.cpp
    engines/ags/engine/media/audio/audio.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index ec577aff9f..f8136aadca 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -85,29 +85,6 @@ extern Bitmap **actsps;
 extern int said_speech_line;
 extern int said_text;
 
-//--------------------------------
-
-CharacterExtras *charextra;
-CharacterInfo *playerchar;
-int32_t _sc_PlayerCharPtr = 0;
-int char_lowest_yp;
-
-// Sierra-style speech settings
-int face_talking = -1, facetalkview = 0, facetalkwait = 0, facetalkframe = 0;
-int facetalkloop = 0, facetalkrepeat = 0, facetalkAllowBlink = 1;
-int facetalkBlinkLoop = 0;
-CharacterInfo *facetalkchar = nullptr;
-// Do override default portrait position during QFG4-style speech overlay update
-bool facetalk_qfg4_override_placement_x = false;
-bool facetalk_qfg4_override_placement_y = false;
-
-// lip-sync speech settings
-int loops_per_character, text_lips_offset, char_speaking = -1;
-int char_thinking = -1;
-const char *text_lips_text = nullptr;
-SpeechLipSyncLine *splipsync = nullptr;
-int numLipLines = 0, curLipLine = -1, curLipLinePhoneme = 0;
-
 // **** CHARACTER: FUNCTIONS ****
 
 void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addIndex) {
@@ -127,33 +104,33 @@ void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addInd
 
 	if (_GP(game).options[OPT_DUPLICATEINV] == 0) {
 		// Ensure it is only in the list once
-		for (ee = 0; ee < charextra[charid].invorder_count; ee++) {
-			if (charextra[charid].invorder[ee] == inum) {
+		for (ee = 0; ee < _G(charextra)[charid].invorder_count; ee++) {
+			if (_G(charextra)[charid].invorder[ee] == inum) {
 				// They already have the item, so don't add it to the list
-				if (chaa == playerchar)
+				if (chaa == _G(playerchar))
 					run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
 				return;
 			}
 		}
 	}
-	if (charextra[charid].invorder_count >= MAX_INVORDER)
+	if (_G(charextra)[charid].invorder_count >= MAX_INVORDER)
 		quit("!Too many inventory items added, max 500 display at one time");
 
 	if ((addIndex == SCR_NO_VALUE) ||
-	        (addIndex >= charextra[charid].invorder_count) ||
+	        (addIndex >= _G(charextra)[charid].invorder_count) ||
 	        (addIndex < 0)) {
 		// add new item at end of list
-		charextra[charid].invorder[charextra[charid].invorder_count] = inum;
+		_G(charextra)[charid].invorder[_G(charextra)[charid].invorder_count] = inum;
 	} else {
 		// insert new item at index
-		for (ee = charextra[charid].invorder_count - 1; ee >= addIndex; ee--)
-			charextra[charid].invorder[ee + 1] = charextra[charid].invorder[ee];
+		for (ee = _G(charextra)[charid].invorder_count - 1; ee >= addIndex; ee--)
+			_G(charextra)[charid].invorder[ee + 1] = _G(charextra)[charid].invorder[ee];
 
-		charextra[charid].invorder[addIndex] = inum;
+		_G(charextra)[charid].invorder[addIndex] = inum;
 	}
-	charextra[charid].invorder_count++;
+	_G(charextra)[charid].invorder_count++;
 	guis_need_update = 1;
-	if (chaa == playerchar)
+	if (chaa == _G(playerchar))
 		run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
 
 }
@@ -297,7 +274,7 @@ void Character_ChangeView(CharacterInfo *chap, int vii) {
 	chap->frame = 0;
 	chap->wait = 0;
 	chap->walkwait = 0;
-	charextra[chap->index_id].animwait = 0;
+	_G(charextra)[chap->index_id].animwait = 0;
 	FindReasonableLoopForCharacter(chap);
 }
 
@@ -677,7 +654,7 @@ void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi) {
 
 	if ((chap->activeinv == inum) & (chap->inv[inum] < 1)) {
 		chap->activeinv = -1;
-		if ((chap == playerchar) && (GetCursorMode() == MODE_USE))
+		if ((chap == _G(playerchar)) && (GetCursorMode() == MODE_USE))
 			set_cursor_mode(0);
 	}
 
@@ -685,18 +662,18 @@ void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi) {
 
 	if ((chap->inv[inum] == 0) || (_GP(game).options[OPT_DUPLICATEINV] > 0)) {
 		int xx, tt;
-		for (xx = 0; xx < charextra[charid].invorder_count; xx++) {
-			if (charextra[charid].invorder[xx] == inum) {
-				charextra[charid].invorder_count--;
-				for (tt = xx; tt < charextra[charid].invorder_count; tt++)
-					charextra[charid].invorder[tt] = charextra[charid].invorder[tt + 1];
+		for (xx = 0; xx < _G(charextra)[charid].invorder_count; xx++) {
+			if (_G(charextra)[charid].invorder[xx] == inum) {
+				_G(charextra)[charid].invorder_count--;
+				for (tt = xx; tt < _G(charextra)[charid].invorder_count; tt++)
+					_G(charextra)[charid].invorder[tt] = _G(charextra)[charid].invorder[tt + 1];
 				break;
 			}
 		}
 	}
 	guis_need_update = 1;
 
-	if (chap == playerchar)
+	if (chap == _G(playerchar))
 		run_on_event(GE_LOSE_INV, RuntimeScriptValue().SetInt32(inum));
 }
 
@@ -766,7 +743,7 @@ void Character_SetAsPlayer(CharacterInfo *chaa) {
 
 	//update_invorder();
 
-	debug_script_log("%s is new player character", playerchar->scrname);
+	debug_script_log("%s is new player character", _G(playerchar)->scrname);
 
 	// Within game_start, return now
 	if (_G(displayed_room) < 0)
@@ -775,23 +752,23 @@ void Character_SetAsPlayer(CharacterInfo *chaa) {
 	// Ignore invalid room numbers for the character and just place him in
 	// the current room for 2.x. Following script calls to NewRoom() will
 	// make sure this still works as intended.
-	if ((loaded_game_file_version <= kGameVersion_272) && (playerchar->room < 0))
-		playerchar->room = _G(displayed_room);
+	if ((loaded_game_file_version <= kGameVersion_272) && (_G(playerchar)->room < 0))
+		_G(playerchar)->room = _G(displayed_room);
 
-	if (_G(displayed_room) != playerchar->room)
-		NewRoom(playerchar->room);
+	if (_G(displayed_room) != _G(playerchar)->room)
+		NewRoom(_G(playerchar)->room);
 	else   // make sure it doesn't run the region interactions
-		_GP(play).player_on_region = GetRegionIDAtRoom(playerchar->x, playerchar->y);
+		_GP(play).player_on_region = GetRegionIDAtRoom(_G(playerchar)->x, _G(playerchar)->y);
 
-	if ((playerchar->activeinv >= 0) && (playerchar->inv[playerchar->activeinv] < 1))
-		playerchar->activeinv = -1;
+	if ((_G(playerchar)->activeinv >= 0) && (_G(playerchar)->inv[_G(playerchar)->activeinv] < 1))
+		_G(playerchar)->activeinv = -1;
 
 	// They had inv selected, so change the cursor
 	if (cur_mode == MODE_USE) {
-		if (playerchar->activeinv < 0)
+		if (_G(playerchar)->activeinv < 0)
 			SetNextCursor();
 		else
-			SetActiveInventory(playerchar->activeinv);
+			SetActiveInventory(_G(playerchar)->activeinv);
 	}
 
 }
@@ -828,7 +805,7 @@ void Character_SetIdleView(CharacterInfo *chaa, int iview, int itime) {
 	}
 	// if they switch to a swimming animation, kick it off immediately
 	if (itime == 0)
-		charextra[chaa->index_id].process_idle_this_time = 1;
+		_G(charextra)[chaa->index_id].process_idle_this_time = 1;
 
 }
 
@@ -837,35 +814,35 @@ bool Character_GetHasExplicitLight(CharacterInfo *ch) {
 }
 
 int Character_GetLightLevel(CharacterInfo *ch) {
-	return ch->has_explicit_light() ? charextra[ch->index_id].tint_light : 0;
+	return ch->has_explicit_light() ? _G(charextra)[ch->index_id].tint_light : 0;
 }
 
 void Character_SetLightLevel(CharacterInfo *chaa, int light_level) {
 	light_level = Math::Clamp(light_level, -100, 100);
 
-	charextra[chaa->index_id].tint_light = light_level;
+	_G(charextra)[chaa->index_id].tint_light = light_level;
 	chaa->flags &= ~CHF_HASTINT;
 	chaa->flags |= CHF_HASLIGHT;
 }
 
 int Character_GetTintRed(CharacterInfo *ch) {
-	return ch->has_explicit_tint() ? charextra[ch->index_id].tint_r : 0;
+	return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_r : 0;
 }
 
 int Character_GetTintGreen(CharacterInfo *ch) {
-	return ch->has_explicit_tint() ? charextra[ch->index_id].tint_g : 0;
+	return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_g : 0;
 }
 
 int Character_GetTintBlue(CharacterInfo *ch) {
-	return ch->has_explicit_tint() ? charextra[ch->index_id].tint_b : 0;
+	return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_b : 0;
 }
 
 int Character_GetTintSaturation(CharacterInfo *ch) {
-	return ch->has_explicit_tint() ? charextra[ch->index_id].tint_level : 0;
+	return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_level : 0;
 }
 
 int Character_GetTintLuminance(CharacterInfo *ch) {
-	return ch->has_explicit_tint() ? ((charextra[ch->index_id].tint_light * 10) / 25) : 0;
+	return ch->has_explicit_tint() ? ((_G(charextra)[ch->index_id].tint_light * 10) / 25) : 0;
 }
 
 void Character_SetOption(CharacterInfo *chaa, int flag, int yesorno) {
@@ -908,10 +885,10 @@ void Character_StopMoving(CharacterInfo *charp) {
 	if (chaa == _GP(play).skip_until_char_stops)
 		EndSkippingUntilCharStops();
 
-	if (charextra[chaa].xwas != INVALID_X) {
-		charp->x = charextra[chaa].xwas;
-		charp->y = charextra[chaa].ywas;
-		charextra[chaa].xwas = INVALID_X;
+	if (_G(charextra)[chaa].xwas != INVALID_X) {
+		charp->x = _G(charextra)[chaa].xwas;
+		charp->y = _G(charextra)[chaa].ywas;
+		_G(charextra)[chaa].xwas = INVALID_X;
 	}
 	if ((charp->walking > 0) && (charp->walking < TURNING_AROUND)) {
 		// if it's not a MoveCharDirect, make sure they end up on a walkable area
@@ -922,7 +899,7 @@ void Character_StopMoving(CharacterInfo *charp) {
 
 		charp->idleleft = charp->idletime;
 		// restart the idle animation straight away
-		charextra[chaa].process_idle_this_time = 1;
+		_G(charextra)[chaa].process_idle_this_time = 1;
 	}
 	if (charp->walking) {
 		// If the character is currently moving, stop them and reset their frame
@@ -941,11 +918,11 @@ void Character_Tint(CharacterInfo *chaa, int red, int green, int blue, int opaci
 
 	debug_script_log("Set %s tint RGB(%d,%d,%d) %d%%", chaa->scrname, red, green, blue, opacity);
 
-	charextra[chaa->index_id].tint_r = red;
-	charextra[chaa->index_id].tint_g = green;
-	charextra[chaa->index_id].tint_b = blue;
-	charextra[chaa->index_id].tint_level = opacity;
-	charextra[chaa->index_id].tint_light = (luminance * 25) / 10;
+	_G(charextra)[chaa->index_id].tint_r = red;
+	_G(charextra)[chaa->index_id].tint_g = green;
+	_G(charextra)[chaa->index_id].tint_b = blue;
+	_G(charextra)[chaa->index_id].tint_level = opacity;
+	_G(charextra)[chaa->index_id].tint_light = (luminance * 25) / 10;
 	chaa->flags &= ~CHF_HASLIGHT;
 	chaa->flags |= CHF_HASTINT;
 }
@@ -979,7 +956,7 @@ void Character_UnlockViewEx(CharacterInfo *chaa, int stopMoving) {
 	chaa->pic_xoffs = 0;
 	chaa->pic_yoffs = 0;
 	// restart the idle animation straight away
-	charextra[chaa->index_id].process_idle_this_time = 1;
+	_G(charextra)[chaa->index_id].process_idle_this_time = 1;
 
 }
 
@@ -1278,7 +1255,7 @@ void Character_SetIgnoreScaling(CharacterInfo *chaa, int yesorno) {
 	if (yesorno) {
 		// when setting IgnoreScaling to 1, should reset zoom level
 		// like it used to in pre-2.71
-		charextra[chaa->index_id].zoom = 100;
+		_G(charextra)[chaa->index_id].zoom = 100;
 	}
 	Character_SetManualScaling(chaa, yesorno);
 }
@@ -1412,7 +1389,7 @@ void Character_SetScaleVolume(CharacterInfo *chaa, int yesorno) {
 }
 
 int Character_GetScaling(CharacterInfo *chaa) {
-	return charextra[chaa->index_id].zoom;
+	return _G(charextra)[chaa->index_id].zoom;
 }
 
 void Character_SetScaling(CharacterInfo *chaa, int zoomlevel) {
@@ -1424,7 +1401,7 @@ void Character_SetScaling(CharacterInfo *chaa, int zoomlevel) {
 	if ((zoomlevel < 5) || (zoomlevel > 200))
 		quit("!Character.Scaling: scaling level must be between 5 and 200%");
 
-	charextra[chaa->index_id].zoom = zoomlevel;
+	_G(charextra)[chaa->index_id].zoom = zoomlevel;
 }
 
 int Character_GetSolid(CharacterInfo *chaa) {
@@ -1485,11 +1462,11 @@ void Character_SetSpeechView(CharacterInfo *chaa, int vii) {
 }
 
 bool Character_GetThinking(CharacterInfo *chaa) {
-	return char_thinking == chaa->index_id;
+	return _G(char_thinking) == chaa->index_id;
 }
 
 int Character_GetThinkingFrame(CharacterInfo *chaa) {
-	if (char_thinking == chaa->index_id)
+	if (_G(char_thinking) == chaa->index_id)
 		return chaa->thinkview > 0 ? chaa->frame : -1;
 
 	debug_script_warn("Character.ThinkingFrame: character is not currently thinking");
@@ -1574,16 +1551,14 @@ void Character_SetZ(CharacterInfo *chaa, int newval) {
 	chaa->z = newval;
 }
 
-extern int char_speaking;
-
 int Character_GetSpeakingFrame(CharacterInfo *chaa) {
 
-	if ((face_talking >= 0) && (facetalkrepeat)) {
-		if (facetalkchar->index_id == chaa->index_id) {
-			return facetalkframe;
+	if ((_G(face_talking) >= 0) && (_G(facetalkrepeat))) {
+		if (_G(facetalkchar)->index_id == chaa->index_id) {
+			return _G(facetalkframe);
 		}
-	} else if (char_speaking >= 0) {
-		if (char_speaking == chaa->index_id) {
+	} else if (_G(char_speaking) >= 0) {
+		if (_G(char_speaking) == chaa->index_id) {
 			return chaa->frame;
 		}
 	}
@@ -1631,7 +1606,7 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
 	// if they are currently walking, save the current Wait
 	if (chin->walking) {
 		waitWas = chin->walkwait;
-		animWaitWas = charextra[chac].animwait;
+		animWaitWas = _G(charextra)[chac].animwait;
 	}
 
 	StopMoving(chac);
@@ -1665,7 +1640,7 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
 		// are already moving
 		if (autoWalkAnims) {
 			chin->walkwait = waitWas;
-			charextra[chac].animwait = animWaitWas;
+			_G(charextra)[chac].animwait = animWaitWas;
 
 			if (_G(mls)[mslot].pos[0] != _G(mls)[mslot].pos[1]) {
 				fix_player_sprite(&_G(mls)[mslot], chin);
@@ -2033,10 +2008,10 @@ int wantMoveNow(CharacterInfo *chi, CharacterExtras *chex) {
 
 void setup_player_character(int charid) {
 	_GP(game).playercharacter = charid;
-	playerchar = &_GP(game).chars[charid];
-	_sc_PlayerCharPtr = ccGetObjectHandleFromAddress((char *)playerchar);
+	_G(playerchar) = &_GP(game).chars[charid];
+	_G(sc_PlayerCharPtr) = ccGetObjectHandleFromAddress((char *)_G(playerchar));
 	if (loaded_game_file_version < kGameVersion_270) {
-		ccAddExternalDynamicObject("player", playerchar, &_GP(ccDynamicCharacter));
+		ccAddExternalDynamicObject("player", _G(playerchar), &_GP(ccDynamicCharacter));
 	}
 }
 
@@ -2082,7 +2057,7 @@ void CheckViewFrameForCharacter(CharacterInfo *chi) {
 
 	if (chi->flags & CHF_SCALEVOLUME) {
 		// adjust the sound volume using the character's zoom level
-		int zoom_level = charextra[chi->index_id].zoom;
+		int zoom_level = _G(charextra)[chi->index_id].zoom;
 		if (zoom_level == 0)
 			zoom_level = 100;
 
@@ -2125,7 +2100,7 @@ CharacterInfo *GetCharacterAtRoom(int x, int y) {
 	return &_GP(game).chars[hsnum];
 }
 
-extern int char_lowest_yp, obj_lowest_yp;
+extern int obj_lowest_yp;
 
 int is_pos_on_character(int xx, int yy) {
 	int cc, sppic, lowestyp = 0, lowestwas = -1;
@@ -2143,8 +2118,8 @@ int is_pos_on_character(int xx, int yy) {
 		}
 
 		sppic = _G(views)[chin->view].loops[chin->loop].frames[chin->frame].pic;
-		int usewid = charextra[cc].width;
-		int usehit = charextra[cc].height;
+		int usewid = _G(charextra)[cc].width;
+		int usehit = _G(charextra)[cc].height;
 		if (usewid == 0) usewid = _GP(game).SpriteInfos[sppic].Width;
 		if (usehit == 0) usehit = _GP(game).SpriteInfos[sppic].Height;
 		int xxx = chin->x - game_to_data_coord(usewid) / 2;
@@ -2163,7 +2138,7 @@ int is_pos_on_character(int xx, int yy) {
 		lowestyp = use_base;
 		lowestwas = cc;
 	}
-	char_lowest_yp = lowestyp;
+	_G(char_lowest_yp) = lowestyp;
 	return lowestwas;
 }
 
@@ -2366,8 +2341,8 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 	int oldview = -1, oldloop = -1;
 	int ovr_type = 0;
 
-	text_lips_offset = 0;
-	text_lips_text = texx;
+	_G(text_lips_offset) = 0;
+	_G(text_lips_text) = texx;
 
 	Bitmap *closeupface = nullptr;
 	// TODO: we always call _display_at later which may also start voice-over;
@@ -2434,7 +2409,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 
 		if (tdyp < 0) {
 			int sppic = _G(views)[speakingChar->view].loops[speakingChar->loop].frames[0].pic;
-			int height = (charextra[aschar].height < 1) ? _GP(game).SpriteInfos[sppic].Height : charextra[aschar].height;
+			int height = (_G(charextra)[aschar].height < 1) ? _GP(game).SpriteInfos[sppic].Height : _G(charextra)[aschar].height;
 			tdyp = view->RoomToScreen(0, data_to_game_coord(_GP(game).chars[aschar].get_effective_y()) - height).first.Y
 			       - get_fixed_pixel_size(5);
 			if (isThought) // if it's a thought, lift it a bit further up
@@ -2535,19 +2510,19 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 			int ovr_yp = get_fixed_pixel_size(20);
 			int view_frame_x = 0;
 			int view_frame_y = 0;
-			facetalk_qfg4_override_placement_x = false;
-			facetalk_qfg4_override_placement_y = false;
+			_G(facetalk_qfg4_override_placement_x) = false;
+			_G(facetalk_qfg4_override_placement_y) = false;
 
 			if (_GP(game).options[OPT_SPEECHTYPE] == 3) {
 				// QFG4-style whole screen picture
 				closeupface = BitmapHelper::CreateBitmap(ui_view.GetWidth(), ui_view.GetHeight(), _GP(spriteset)[viptr->loops[0].frames[0].pic]->GetColorDepth());
 				closeupface->Clear(0);
 				if (xx < 0 && _GP(play).speech_portrait_placement) {
-					facetalk_qfg4_override_placement_x = true;
+					_G(facetalk_qfg4_override_placement_x) = true;
 					view_frame_x = _GP(play).speech_portrait_x;
 				}
 				if (yy < 0 && _GP(play).speech_portrait_placement) {
-					facetalk_qfg4_override_placement_y = true;
+					_G(facetalk_qfg4_override_placement_y) = true;
 					view_frame_y = _GP(play).speech_portrait_y;
 				} else {
 					view_frame_y = ui_view.GetHeight() / 2 - _GP(game).SpriteInfos[viptr->loops[0].frames[0].pic].Height / 2;
@@ -2620,19 +2595,19 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 			}
 			if (_GP(game).options[OPT_SPEECHTYPE] == 3)
 				overlay_x = 0;
-			face_talking = add_screen_overlay(overlay_x, ovr_yp, ovr_type, closeupface, closeupface_has_alpha);
-			facetalkframe = 0;
-			facetalkwait = viptr->loops[0].frames[0].speed + GetCharacterSpeechAnimationDelay(speakingChar);
-			facetalkloop = 0;
-			facetalkview = useview;
-			facetalkrepeat = (isThought) ? 0 : 1;
-			facetalkBlinkLoop = 0;
-			facetalkAllowBlink = 1;
+			_G(face_talking) = add_screen_overlay(overlay_x, ovr_yp, ovr_type, closeupface, closeupface_has_alpha);
+			_G(facetalkframe) = 0;
+			_G(facetalkwait) = viptr->loops[0].frames[0].speed + GetCharacterSpeechAnimationDelay(speakingChar);
+			_G(facetalkloop) = 0;
+			_G(facetalkview) = useview;
+			_G(facetalkrepeat) = (isThought) ? 0 : 1;
+			_G(facetalkBlinkLoop) = 0;
+			_G(facetalkAllowBlink) = 1;
 			if ((isThought) && (speakingChar->flags & CHF_NOBLINKANDTHINK))
-				facetalkAllowBlink = 0;
-			facetalkchar = &_GP(game).chars[aschar];
-			if (facetalkchar->blinktimer < 0)
-				facetalkchar->blinktimer = facetalkchar->blinkinterval;
+				_G(facetalkAllowBlink) = 0;
+			_G(facetalkchar) = &_GP(game).chars[aschar];
+			if (_G(facetalkchar)->blinktimer < 0)
+				_G(facetalkchar)->blinktimer = _G(facetalkchar)->blinkinterval;
 			textcol = -textcol;
 			overlayPositionFixed = true;
 		} else if (useview >= 0) {
@@ -2655,7 +2630,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 				speakingChar->loop = 0;
 			}
 
-			facetalkBlinkLoop = speakingChar->loop;
+			_G(facetalkBlinkLoop) = speakingChar->loop;
 
 			if (speakingChar->on && // don't bother checking if character is not visible (also fixes 'Trilby's Notes' legacy game)
 			        ((speakingChar->loop >= _G(views)[speakingChar->view].numLoops) ||
@@ -2678,7 +2653,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 			tdxp = OVR_AUTOPLACE;
 			tdyp = aschar;*/
 			if (!isThought)  // set up the lip sync if not thinking
-				char_speaking = aschar;
+				_G(char_speaking) = aschar;
 
 		}
 	} else
@@ -2693,7 +2668,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 		allowShrink = 0;
 
 	if (isThought)
-		char_thinking = aschar;
+		_G(char_thinking) = aschar;
 
 	_G(our_eip) = 155;
 	_display_at(tdxp, tdyp, bwidth, texx, DISPLAYTEXT_SPEECH, textcol, isThought, allowShrink, overlayPositionFixed);
@@ -2703,8 +2678,8 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 	if (closeupface != nullptr)
 		remove_screen_overlay(ovr_type);
 	mark_screen_dirty();
-	face_talking = -1;
-	facetalkchar = nullptr;
+	_G(face_talking) = -1;
+	_G(facetalkchar) = nullptr;
 	_G(our_eip) = 157;
 	if (oldview >= 0) {
 		speakingChar->flags &= ~CHF_FIXVIEW;
@@ -2721,19 +2696,19 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 		speakingChar->wait = 0;
 		speakingChar->idleleft = speakingChar->idletime;
 		// restart the idle animation straight away
-		charextra[aschar].process_idle_this_time = 1;
+		_G(charextra)[aschar].process_idle_this_time = 1;
 	}
-	char_speaking = -1;
-	char_thinking = -1;
+	_G(char_speaking) = -1;
+	_G(char_thinking) = -1;
 	if (_GP(play).IsBlockingVoiceSpeech())
 		stop_voice_speech();
 }
 
 int get_character_currently_talking() {
-	if ((face_talking >= 0) && (facetalkrepeat))
-		return facetalkchar->index_id;
-	else if (char_speaking >= 0)
-		return char_speaking;
+	if ((_G(face_talking) >= 0) && (_G(facetalkrepeat)))
+		return _G(facetalkchar)->index_id;
+	else if (_G(char_speaking) >= 0)
+		return _G(char_speaking);
 
 	return -1;
 }
@@ -2779,22 +2754,22 @@ int update_lip_sync(int talkview, int talkloop, int *talkframeptr) {
 	int talkwait = 0;
 
 	// lip-sync speech
-	const char *nowsaying = &text_lips_text[text_lips_offset];
+	const char *nowsaying = &_G(text_lips_text)[_G(text_lips_offset)];
 	// if it's an apostraphe, skip it (we'll, I'll, etc)
 	if (nowsaying[0] == '\'') {
-		text_lips_offset++;
+		_G(text_lips_offset)++;
 		nowsaying++;
 	}
 
-	if (text_lips_offset >= (int)strlen(text_lips_text))
+	if (_G(text_lips_offset) >= (int)strlen(_G(text_lips_text)))
 		talkframe = 0;
 	else {
-		talkframe = GetLipSyncFrame(nowsaying, &text_lips_offset);
+		talkframe = GetLipSyncFrame(nowsaying, &_G(text_lips_offset));
 		if (talkframe >= _G(views)[talkview].loops[talkloop].numFrames)
 			talkframe = 0;
 	}
 
-	talkwait = loops_per_character + _G(views)[talkview].loops[talkloop].frames[talkframe].speed;
+	talkwait = _G(loops_per_character) + _G(views)[talkview].loops[talkloop].frames[talkframe].speed;
 
 	talkframeptr[0] = talkframe;
 	return talkwait;
@@ -2802,7 +2777,7 @@ int update_lip_sync(int talkview, int talkloop, int *talkframeptr) {
 
 Rect GetCharacterRoomBBox(int charid, bool use_frame_0) {
 	int width, height;
-	const CharacterExtras &chex = charextra[charid];
+	const CharacterExtras &chex = _G(charextra)[charid];
 	const CharacterInfo &chin = _GP(game).chars[charid];
 	int frame = use_frame_0 ? 0 : chin.frame;
 	int pic = _G(views)[chin.view].loops[chin.loop].frames[frame].pic;
diff --git a/engines/ags/engine/ac/character.h b/engines/ags/engine/ac/character.h
index b21ff4206a..e58d653234 100644
--- a/engines/ags/engine/ac/character.h
+++ b/engines/ags/engine/ac/character.h
@@ -219,11 +219,6 @@ Rect GetCharacterRoomBBox(int charid, bool use_frame_0 = false);
 // or the one that is least far away from its camera; calculated as a perpendicular distance between two AABBs.
 PViewport FindNearestViewport(int charid);
 
-extern CharacterInfo *playerchar;
-extern CharacterExtras *charextra;
-
-extern int32_t _sc_PlayerCharPtr;
-
 // order of loops to turn character in circle from down to down
 extern int turnlooporder[8];
 
diff --git a/engines/ags/engine/ac/characterinfo_engine.cpp b/engines/ags/engine/ac/characterinfo_engine.cpp
index a1b25d5f39..a317ae825e 100644
--- a/engines/ags/engine/ac/characterinfo_engine.cpp
+++ b/engines/ags/engine/ac/characterinfo_engine.cpp
@@ -41,12 +41,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-
-
-
-
-extern int char_speaking;
-
 extern unsigned int loopcounter;
 
 #define Random __Rand
@@ -268,7 +262,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 			doing_nothing = 1;
 
 		if (wait > 0) wait--;
-		else if ((char_speaking == aa) && (_GP(game).options[OPT_LIPSYNCTEXT] != 0)) {
+		else if ((_G(char_speaking) == aa) && (_GP(game).options[OPT_LIPSYNCTEXT] != 0)) {
 			// currently talking with lip-sync speech
 			int fraa = frame;
 			wait = update_lip_sync(view, loop, &fraa) - 1;
@@ -312,7 +306,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 			} else
 				frame++;
 
-			if ((aa == char_speaking) &&
+			if ((aa == _G(char_speaking)) &&
 				(_GP(play).speech_in_post_state ||
 				((!_GP(play).speech_has_voice) &&
 					(_GP(play).close_mouth_speech_time > 0) &&
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index a8a54dd20c..79e12ba9b7 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -70,8 +70,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern CharacterInfo *playerchar;
-
 extern int cur_mode, cur_cursor;
 extern IGraphicsDriver *gfxDriver;
 
@@ -332,7 +330,7 @@ int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, in
 			text_color = ds->GetCompatibleColor(_GP(play).read_dialog_option_colour);
 		} else {
 			// 'unread' colour
-			text_color = ds->GetCompatibleColor(playerchar->talkcolor);
+			text_color = ds->GetCompatibleColor(_G(playerchar)->talkcolor);
 		}
 
 		if (mouseison == ww) {
@@ -757,7 +755,7 @@ void DialogOptions::Redraw() {
 		// Set up the text box, if present
 		parserInput->Y = curyp + data_to_game_coord(_GP(game).options[OPT_DIALOGGAP]);
 		parserInput->Width = areawid - get_fixed_pixel_size(10);
-		parserInput->TextColor = playerchar->talkcolor;
+		parserInput->TextColor = _G(playerchar)->talkcolor;
 		if (mouseison == DLG_OPTION_PARSER)
 			parserInput->TextColor = forecol;
 
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 97a18a590d..9030049181 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -60,16 +60,10 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Shared::BitmapHelper;
 
-
-
 extern int longestline;
 
-extern int loops_per_character;
-
-
 int display_message_aschar = 0;
 
-
 TopBarSettings topBar;
 struct DisplayVars {
 	int lineheight;    // font's height of single line
@@ -427,7 +421,7 @@ int GetTextDisplayTime(const char *text, int canberel) {
 	// This is calculated using a hard-coded 15 for the text speed,
 	// so that it's always the same no matter how fast the user
 	// can read.
-	loops_per_character = (((uselen / _GP(play).lipsync_speed) + 1) * fpstimer) / uselen;
+	_G(loops_per_character) = (((uselen / _GP(play).lipsync_speed) + 1) * fpstimer) / uselen;
 
 	int textDisplayTimeInMS = ((uselen / (_GP(play).text_speed + _GP(play).text_speed_modifier)) + 1) * 1000;
 	if (textDisplayTimeInMS < _GP(play).text_min_display_time_ms)
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 4e1c327fce..bfc7d686f8 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -100,9 +100,6 @@ extern IDriverDependantBitmap *walkBehindBitmap[MAX_WALK_BEHINDS];
 extern int walkBehindsCachedForBgNum;
 extern WalkBehindMethodEnum walkBehindMethod;
 extern int walk_behind_baselines_changed;
-
-extern CharacterExtras *charextra;
-extern CharacterInfo *playerchar;
 extern int cur_mode, cur_cursor;
 extern int mouse_frame, mouse_delay;
 extern int lastmx, lastmy;
@@ -1599,29 +1596,29 @@ void prepare_characters_for_drawing() {
 
 		// calculate the zoom level
 		if (chin->flags & CHF_MANUALSCALING)  // character ignores scaling
-			zoom_level = charextra[aa].zoom;
+			zoom_level = _G(charextra)[aa].zoom;
 		else if ((onarea <= 0) && (_GP(thisroom).WalkAreas[0].ScalingFar == 0)) {
-			zoom_level = charextra[aa].zoom;
+			zoom_level = _G(charextra)[aa].zoom;
 			// NOTE: room objects don't have this fix
 			if (zoom_level == 0)
 				zoom_level = 100;
 		} else
 			zoom_level = get_area_scaling(onarea, chin->x, chin->y);
 
-		charextra[aa].zoom = zoom_level;
+		_G(charextra)[aa].zoom = zoom_level;
 
 		tint_red = tint_green = tint_blue = tint_amount = tint_light = light_level = 0;
 
 		if (chin->flags & CHF_HASTINT) {
 			// object specific tint, use it
-			tint_red = charextra[aa].tint_r;
-			tint_green = charextra[aa].tint_g;
-			tint_blue = charextra[aa].tint_b;
-			tint_amount = charextra[aa].tint_level;
-			tint_light = charextra[aa].tint_light;
+			tint_red = _G(charextra)[aa].tint_r;
+			tint_green = _G(charextra)[aa].tint_g;
+			tint_blue = _G(charextra)[aa].tint_b;
+			tint_amount = _G(charextra)[aa].tint_level;
+			tint_light = _G(charextra)[aa].tint_light;
 			light_level = 0;
 		} else if (chin->flags & CHF_HASLIGHT) {
-			light_level = charextra[aa].tint_light;
+			light_level = _G(charextra)[aa].tint_light;
 		} else {
 			get_local_tint(chin->x, chin->y, chin->flags & CHF_NOLIGHTING,
 			               &tint_amount, &tint_red, &tint_green, &tint_blue,
@@ -1675,13 +1672,13 @@ void prepare_characters_for_drawing() {
 			// it needs to be stretched, so calculate the new dimensions
 
 			scale_sprite_size(sppic, zoom_level, &newwidth, &newheight);
-			charextra[aa].width = newwidth;
-			charextra[aa].height = newheight;
+			_G(charextra)[aa].width = newwidth;
+			_G(charextra)[aa].height = newheight;
 		} else {
 			// draw at original size, so just use the sprite width and height
 			// TODO: store width and height always, that's much simplier to use for reference!
-			charextra[aa].width = 0;
-			charextra[aa].height = 0;
+			_G(charextra)[aa].width = 0;
+			_G(charextra)[aa].height = 0;
 			newwidth = _GP(game).SpriteInfos[sppic].Width;
 			newheight = _GP(game).SpriteInfos[sppic].Height;
 		}
@@ -1757,7 +1754,7 @@ void prepare_characters_for_drawing() {
 				usebasel += _GP(thisroom).Height;
 			}
 		} else if (walkBehindMethod == DrawAsSeparateCharSprite) {
-			sort_out_char_sprite_walk_behind(useindx, bgX, bgY, usebasel, charextra[aa].zoom, newwidth, newheight);
+			sort_out_char_sprite_walk_behind(useindx, bgX, bgY, usebasel, _G(charextra)[aa].zoom, newwidth, newheight);
 		} else if (walkBehindMethod == DrawOverCharSprite) {
 			sort_out_walk_behinds(actsps[useindx], bgX, bgY, usebasel);
 		}
@@ -1946,12 +1943,12 @@ void draw_gui_and_overlays() {
 	if (((_G(debug_flags) & DBG_NOIFACE) == 0) && (_G(displayed_room) >= 0)) {
 		int aa;
 
-		if (playerchar->activeinv >= MAX_INV) {
+		if (_G(playerchar)->activeinv >= MAX_INV) {
 			quit("!The player.activeinv variable has been corrupted, probably as a result\n"
 			     "of an incorrect assignment in the game script.");
 		}
-		if (playerchar->activeinv < 1) gui_inv_pic = -1;
-		else gui_inv_pic = _GP(game).invinfo[playerchar->activeinv].pic;
+		if (_G(playerchar)->activeinv < 1) gui_inv_pic = -1;
+		else gui_inv_pic = _GP(game).invinfo[_G(playerchar)->activeinv].pic;
 		_G(our_eip) = 37;
 		if (guis_need_update) {
 			guis_need_update = 0;
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index e40e3162fe..18a6c275a9 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -110,17 +110,13 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern int cur_mode, cur_cursor;
-extern SpeechLipSyncLine *splipsync;
-extern int numLipLines, curLipLine, curLipLinePhoneme;
-
-extern CharacterExtras *charextra;
 extern DialogTopic *dialog;
 
 #if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
 extern int _G(psp_gfx_renderer);
 #endif
 
-extern int obj_lowest_yp, char_lowest_yp;
+extern int obj_lowest_yp;
 
 extern int actSpsCount;
 extern Bitmap **actsps;
@@ -465,7 +461,7 @@ void unload_game_file() {
 	_GP(play).FreeViewportsAndCameras();
 
 	_GP(characterScriptObjNames).clear();
-	free(charextra);
+	free(_G(charextra));
 	free(_G(mls));
 	free(actsps);
 	free(actspsbmp);
@@ -517,15 +513,15 @@ void unload_game_file() {
 	free(_G(charcache));
 	_G(charcache) = nullptr;
 
-	if (splipsync != nullptr) {
-		for (int i = 0; i < numLipLines; ++i) {
-			free(splipsync[i].endtimeoffs);
-			free(splipsync[i].frame);
+	if (_G(splipsync) != nullptr) {
+		for (int i = 0; i < _G(numLipLines); ++i) {
+			free(_G(splipsync)[i].endtimeoffs);
+			free(_G(splipsync)[i].frame);
 		}
-		free(splipsync);
-		splipsync = nullptr;
-		numLipLines = 0;
-		curLipLine = -1;
+		free(_G(splipsync));
+		_G(splipsync) = nullptr;
+		_G(numLipLines) = 0;
+		_G(curLipLine) = -1;
 	}
 
 	for (int i = 0; i < _GP(game).numdialog; ++i) {
@@ -1146,7 +1142,7 @@ void ReadGameSetupStructBase_Aligned(Stream *in) {
 void ReadCharacterExtras_Aligned(Stream *in) {
 	AlignedStream align_s(in, Shared::kAligned_Read);
 	for (int i = 0; i < _GP(game).numcharacters; ++i) {
-		charextra[i].ReadFromFile(&align_s);
+		_G(charextra)[i].ReadFromFile(&align_s);
 		align_s.Reset();
 	}
 }
@@ -1667,14 +1663,14 @@ int __GetLocationType(int xxx, int yyy, int allowHotspot0) {
 		wbat = 0;
 
 	if ((charat >= 0) && (objat >= 0)) {
-		if ((wbat > obj_lowest_yp) && (wbat > char_lowest_yp))
+		if ((wbat > obj_lowest_yp) && (wbat > _G(char_lowest_yp)))
 			winner = LOCTYPE_HOTSPOT;
-		else if (obj_lowest_yp > char_lowest_yp)
+		else if (obj_lowest_yp > _G(char_lowest_yp))
 			winner = LOCTYPE_OBJ;
 		else
 			winner = LOCTYPE_CHAR;
 	} else if (charat >= 0) {
-		if (wbat > char_lowest_yp)
+		if (wbat > _G(char_lowest_yp))
 			winner = LOCTYPE_HOTSPOT;
 		else
 			winner = LOCTYPE_CHAR;
@@ -1803,7 +1799,7 @@ void replace_tokens(const char *srcmes, char *destm, int maxlen) {
 			if (tokentype == 1) {
 				if ((inx < 1) | (inx >= _GP(game).numinvitems))
 					quit("!Display: invalid inv item specified in @IN@");
-				snprintf(tval, sizeof(tval), "%d", playerchar->inv[inx]);
+				snprintf(tval, sizeof(tval), "%d", _G(playerchar)->inv[inx]);
 			} else {
 				if ((inx < 0) | (inx >= MAXGSVALUES))
 					quit("!Display: invalid global int index speicifed in @GI@");
diff --git a/engines/ags/engine/ac/gamestate.cpp b/engines/ags/engine/ac/gamestate.cpp
index 8b7c171908..2e6011afe9 100644
--- a/engines/ags/engine/ac/gamestate.cpp
+++ b/engines/ags/engine/ac/gamestate.cpp
@@ -45,10 +45,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-extern CharacterInfo *playerchar;
-
-
 GameState::GameState() {
 	Common::fill(&globalvars[0], &globalvars[MAXGLOBALVARS], 0);
 	Common::fill(&reserved[0], &reserved[GAME_STATE_RESERVED_INTS], 0);
@@ -183,8 +179,8 @@ void GameState::UpdateRoomCamera(int index) {
 	if ((real_room_sz.Width > rc.GetWidth()) || (real_room_sz.Height > rc.GetHeight())) {
 		// TODO: split out into Camera Behavior
 		if (!cam->IsLocked()) {
-			int x = data_to_game_coord(playerchar->x) - rc.GetWidth() / 2;
-			int y = data_to_game_coord(playerchar->y) - rc.GetHeight() / 2;
+			int x = data_to_game_coord(_G(playerchar)->x) - rc.GetWidth() / 2;
+			int y = data_to_game_coord(_G(playerchar)->y) - rc.GetHeight() / 2;
 			cam->SetAt(x, y);
 		}
 	} else {
diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index 5c48f5a74c..2fedaefdc9 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -41,9 +41,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern SpeechLipSyncLine *splipsync;
-extern int numLipLines, curLipLine, curLipLinePhoneme;
-
 void StopAmbientSound(int channel) {
 	if ((channel < 0) || (channel >= MAX_SOUND_CHANNELS))
 		quit("!StopAmbientSound: invalid channel");
@@ -602,17 +599,17 @@ bool play_voice_speech(int charid, int sndid) {
 		return false;
 
 	int ii;  // Compare the base file name to the .pam file name
-	curLipLine = -1;  // See if we have voice lip sync for this line
-	curLipLinePhoneme = -1;
-	for (ii = 0; ii < numLipLines; ii++) {
-		if (ags_stricmp(splipsync[ii].filename, voice_file) == 0) {
-			curLipLine = ii;
+	_G(curLipLine) = -1;  // See if we have voice lip sync for this line
+	_G(curLipLinePhoneme) = -1;
+	for (ii = 0; ii < _G(numLipLines); ii++) {
+		if (ags_stricmp(_G(splipsync)[ii].filename, voice_file) == 0) {
+			_G(curLipLine) = ii;
 			break;
 		}
 	}
 	// if the lip-sync is being used for voice sync, disable
 	// the text-related lipsync
-	if (numLipLines > 0)
+	if (_G(numLipLines) > 0)
 		_GP(game).options[OPT_LIPSYNCTEXT] = 0;
 
 	// change Sierra w/bgrnd  to Sierra without background when voice
@@ -643,7 +640,7 @@ void stop_voice_speech() {
 	stop_voice_clip_impl();
 
 	// Reset lipsync
-	curLipLine = -1;
+	_G(curLipLine) = -1;
 	// Set back to Sierra w/bgrnd
 	if (_GP(play).no_textbg_when_voice == 2) {
 		_GP(play).no_textbg_when_voice = 1;
diff --git a/engines/ags/engine/ac/global_character.cpp b/engines/ags/engine/ac/global_character.cpp
index 3e216eed32..cc3e622904 100644
--- a/engines/ags/engine/ac/global_character.cpp
+++ b/engines/ags/engine/ac/global_character.cpp
@@ -52,13 +52,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-// defined in character unit
-extern CharacterExtras *charextra;
-extern CharacterInfo *playerchar;
-extern int32_t _sc_PlayerCharPtr;
-extern CharacterInfo *playerchar;
-
-
 void StopMoving(int chaa) {
 
 	Character_StopMoving(&_GP(game).chars[chaa]);
@@ -107,7 +100,7 @@ void SetCharacterIdle(int who, int iview, int itime) {
 int GetCharacterWidth(int ww) {
 	CharacterInfo *char1 = &_GP(game).chars[ww];
 
-	if (charextra[ww].width < 1) {
+	if (_G(charextra)[ww].width < 1) {
 		if ((char1->view < 0) ||
 			(char1->loop >= _G(views)[char1->view].numLoops) ||
 			(char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
@@ -117,13 +110,13 @@ int GetCharacterWidth(int ww) {
 
 		return _GP(game).SpriteInfos[_G(views)[char1->view].loops[char1->loop].frames[char1->frame].pic].Width;
 	} else
-		return charextra[ww].width;
+		return _G(charextra)[ww].width;
 }
 
 int GetCharacterHeight(int charid) {
 	CharacterInfo *char1 = &_GP(game).chars[charid];
 
-	if (charextra[charid].height < 1) {
+	if (_G(charextra)[charid].height < 1) {
 		if ((char1->view < 0) ||
 			(char1->loop >= _G(views)[char1->view].numLoops) ||
 			(char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
@@ -133,7 +126,7 @@ int GetCharacterHeight(int charid) {
 
 		return _GP(game).SpriteInfos[_G(views)[char1->view].loops[char1->loop].frames[char1->frame].pic].Height;
 	} else
-		return charextra[charid].height;
+		return _G(charextra)[charid].height;
 }
 
 
@@ -383,7 +376,7 @@ void RunCharacterInteraction(int cc, int mood) {
 	else if (mood == MODE_TALK) passon = 2;
 	else if (mood == MODE_USE) {
 		passon = 3;
-		cdata = playerchar->activeinv;
+		cdata = _G(playerchar)->activeinv;
 		_GP(play).usedinv = cdata;
 	} else if (mood == MODE_PICKUP) passon = 5;
 	else if (mood == MODE_CUSTOM1) passon = 6;
@@ -452,12 +445,12 @@ void SetActiveInventory(int iit) {
 	else if (iit != -1)
 		quitprintf("!SetActiveInventory: invalid inventory number %d", iit);
 
-	Character_SetActiveInventory(playerchar, tosend);
+	Character_SetActiveInventory(_G(playerchar), tosend);
 }
 
 void update_invorder() {
 	for (int cc = 0; cc < _GP(game).numcharacters; cc++) {
-		charextra[cc].invorder_count = 0;
+		_G(charextra)[cc].invorder_count = 0;
 		int ff, howmany;
 		// Iterate through all inv items, adding them once (or multiple
 		// times if requested) to the list.
@@ -467,16 +460,16 @@ void update_invorder() {
 				howmany = 1;
 
 			for (int ts = 0; ts < howmany; ts++) {
-				if (charextra[cc].invorder_count >= MAX_INVORDER)
+				if (_G(charextra)[cc].invorder_count >= MAX_INVORDER)
 					quit("!Too many inventory items to display: 500 max");
 
-				charextra[cc].invorder[charextra[cc].invorder_count] = ff;
-				charextra[cc].invorder_count++;
+				_G(charextra)[cc].invorder[_G(charextra)[cc].invorder_count] = ff;
+				_G(charextra)[cc].invorder_count++;
 			}
 		}
 	}
 	// backwards compatibility
-	_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
+	_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
 
 	guis_need_update = 1;
 }
@@ -485,18 +478,18 @@ void add_inventory(int inum) {
 	if ((inum < 0) || (inum >= MAX_INV))
 		quit("!AddInventory: invalid inventory number");
 
-	Character_AddInventory(playerchar, &_G(scrInv)[inum], SCR_NO_VALUE);
+	Character_AddInventory(_G(playerchar), &_G(scrInv)[inum], SCR_NO_VALUE);
 
-	_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
+	_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
 }
 
 void lose_inventory(int inum) {
 	if ((inum < 0) || (inum >= MAX_INV))
 		quit("!LoseInventory: invalid inventory number");
 
-	Character_LoseInventory(playerchar, &_G(scrInv)[inum]);
+	Character_LoseInventory(_G(playerchar), &_G(scrInv)[inum]);
 
-	_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
+	_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
 }
 
 void AddInventoryToCharacter(int charid, int inum) {
diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index d031ee70ec..8ef86a413d 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -53,7 +53,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern CharacterInfo *playerchar;
 extern int convert_16bit_bgr;
 extern IGraphicsDriver *gfxDriver;
 extern TreeMap *transtree;
@@ -91,7 +90,7 @@ void script_debug(int cmdd, int dataa) {
 	int rr;
 	if (cmdd == 0) {
 		for (rr = 1; rr < _GP(game).numinvitems; rr++)
-			playerchar->inv[rr] = 1;
+			_G(playerchar)->inv[rr] = 1;
 		update_invorder();
 		//    Display("invorder decided there are %d items[display %d",_GP(play).inv_numorder,_GP(play).inv_numdisp);
 	} else if (cmdd == 1) {
@@ -99,7 +98,7 @@ void script_debug(int cmdd, int dataa) {
 		Display(toDisplay.GetCStr());
 		//    Display("shftR: %d  shftG: %d  shftB: %d", _G(_rgb_r_shift_16), _G(_rgb_g_shift_16), _G(_rgb_b_shift_16));
 		//    Display("Remaining memory: %d kb",_go32_dpmi_remaining_virtual_memory()/1024);
-		//Display("Play char bcd: %d",->GetColorDepth(_GP(spriteset)[_G(views)[playerchar->view].frames[playerchar->loop][playerchar->frame].pic]));
+		//Display("Play char bcd: %d",->GetColorDepth(_GP(spriteset)[_G(views)[_G(playerchar)->view].frames[_G(playerchar)->loop][_G(playerchar)->frame].pic]));
 	} else if (cmdd == 2) {
 		// show walkable areas from here
 		// TODO: support multiple viewports?!
diff --git a/engines/ags/engine/ac/global_hotspot.cpp b/engines/ags/engine/ac/global_hotspot.cpp
index 8bc11cf533..75bc18bb05 100644
--- a/engines/ags/engine/ac/global_hotspot.cpp
+++ b/engines/ags/engine/ac/global_hotspot.cpp
@@ -42,8 +42,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern CharacterInfo *playerchar;
-
 void DisableHotspot(int hsnum) {
 	if ((hsnum < 1) | (hsnum >= MAX_ROOM_HOTSPOTS))
 		quit("!DisableHotspot: invalid hotspot specified");
@@ -104,7 +102,7 @@ void RunHotspotInteraction(int hotspothere, int mood) {
 	else if (mood == MODE_CUSTOM2) passon = 9;
 	else if (mood == MODE_USE) {
 		passon = 3;
-		cdata = playerchar->activeinv;
+		cdata = _G(playerchar)->activeinv;
 		_GP(play).usedinv = cdata;
 	}
 
diff --git a/engines/ags/engine/ac/global_inventoryitem.cpp b/engines/ags/engine/ac/global_inventoryitem.cpp
index d2262bc45a..0b0a7c2efd 100644
--- a/engines/ags/engine/ac/global_inventoryitem.cpp
+++ b/engines/ags/engine/ac/global_inventoryitem.cpp
@@ -39,8 +39,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern CharacterInfo *playerchar;
-
 void set_inv_item_pic(int invi, int piccy) {
 	if ((invi < 1) || (invi > _GP(game).numinvitems))
 		quit("!SetInvItemPic: invalid inventory item specified");
@@ -112,7 +110,7 @@ void RunInventoryInteraction(int iit, int modd) {
 	else if (modd == MODE_HAND)
 		run_event_block_inv(iit, 1);
 	else if (modd == MODE_USE) {
-		_GP(play).usedinv = playerchar->activeinv;
+		_GP(play).usedinv = _G(playerchar)->activeinv;
 		run_event_block_inv(iit, 3);
 	} else if (modd == MODE_TALK)
 		run_event_block_inv(iit, 2);
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 21ba573e8b..268372378b 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -52,8 +52,6 @@ using namespace AGS::Shared;
 
 #define OVERLAPPING_OBJECT 1000
 
-extern CharacterInfo *playerchar;
-
 extern int actSpsCount;
 extern Bitmap **actsps;
 extern IDriverDependantBitmap **actspsbmp;
@@ -407,7 +405,7 @@ void RunObjectInteraction(int aa, int mood) {
 	else if (mood == MODE_CUSTOM2) passon = 7;
 	else if (mood == MODE_USE) {
 		passon = 3;
-		cdata = playerchar->activeinv;
+		cdata = _G(playerchar)->activeinv;
 		_GP(play).usedinv = cdata;
 	}
 	_G(evblockbasename) = "object%d";
diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index a53ebb83b0..f9e280d9db 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -44,7 +44,6 @@ namespace AGS3 {
 
 using namespace Shared;
 
-extern CharacterInfo *playerchar;
 extern int in_inv_screen, inv_screen_newroom;
 extern int gs_to_newroom;
 
@@ -80,7 +79,7 @@ void NewRoom(int nrnum) {
 
 	if (_G(displayed_room) < 0) {
 		// called from game_start; change the room where the game will start
-		playerchar->room = nrnum;
+		_G(playerchar)->room = nrnum;
 		return;
 	}
 
@@ -113,16 +112,16 @@ void NewRoom(int nrnum) {
 		inv_screen_newroom = nrnum;
 		return;
 	} else if ((_G(inside_script) == 0) & (_G(in_graph_script) == 0)) {
-		new_room(nrnum, playerchar);
+		new_room(nrnum, _G(playerchar));
 		return;
 	} else if (_G(inside_script)) {
 		_G(curscript)->queue_action(ePSANewRoom, nrnum, "NewRoom");
 		// we might be within a MoveCharacterBlocking -- the room
 		// change should abort it
-		if ((playerchar->walking > 0) && (playerchar->walking < TURNING_AROUND)) {
+		if ((_G(playerchar)->walking > 0) && (_G(playerchar)->walking < TURNING_AROUND)) {
 			// nasty hack - make sure it doesn't move the character
 			// to a walkable area
-			_G(mls)[playerchar->walking].direct = 1;
+			_G(mls)[_G(playerchar)->walking].direct = 1;
 			StopMoving(_GP(game).playercharacter);
 		}
 	} else if (_G(in_graph_script))
@@ -131,7 +130,7 @@ void NewRoom(int nrnum) {
 
 
 void NewRoomEx(int nrnum, int newx, int newy) {
-	Character_ChangeRoom(playerchar, nrnum, newx, newy);
+	Character_ChangeRoom(_G(playerchar), nrnum, newx, newy);
 }
 
 void NewRoomNPC(int charid, int nrnum, int newx, int newy) {
diff --git a/engines/ags/engine/ac/guiinv.cpp b/engines/ags/engine/ac/guiinv.cpp
index 6df6170d56..bd557853c5 100644
--- a/engines/ags/engine/ac/guiinv.cpp
+++ b/engines/ags/engine/ac/guiinv.cpp
@@ -34,9 +34,6 @@ namespace AGS3 {
 
 extern int gui_disabled_style;
 
-extern CharacterExtras *charextra;
-
-
 namespace AGS {
 namespace Shared {
 
@@ -55,7 +52,7 @@ void GUIInvWindow::Draw(Bitmap *ds) {
 	// backwards compatibility
 	_GP(play).inv_numinline = ColCount;
 	_GP(play).inv_numdisp = RowCount * ColCount;
-	_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
+	_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
 	// if the user changes top_inv_item, switch into backwards
 	// compatibiltiy mode
 	if (_GP(play).inv_top)
@@ -68,12 +65,12 @@ void GUIInvWindow::Draw(Bitmap *ds) {
 	int at_x = X;
 	int at_y = Y;
 	int lastItem = TopItem + (ColCount * RowCount);
-	if (lastItem > charextra[GetCharacterId()].invorder_count)
-		lastItem = charextra[GetCharacterId()].invorder_count;
+	if (lastItem > _G(charextra)[GetCharacterId()].invorder_count)
+		lastItem = _G(charextra)[GetCharacterId()].invorder_count;
 
 	for (int item = TopItem; item < lastItem; ++item) {
 		// draw inv graphic
-		draw_gui_sprite(ds, _GP(game).invinfo[charextra[GetCharacterId()].invorder[item]].pic, at_x, at_y, true);
+		draw_gui_sprite(ds, _GP(game).invinfo[_G(charextra)[GetCharacterId()].invorder[item]].pic, at_x, at_y, true);
 		at_x += data_to_game_coord(ItemWidth);
 
 		// go to next row when appropriate
diff --git a/engines/ags/engine/ac/inventoryitem.cpp b/engines/ags/engine/ac/inventoryitem.cpp
index 547a411f63..61f16edaf4 100644
--- a/engines/ags/engine/ac/inventoryitem.cpp
+++ b/engines/ags/engine/ac/inventoryitem.cpp
@@ -41,10 +41,7 @@
 
 namespace AGS3 {
 
-
 extern int cur_cursor;
-extern CharacterInfo *playerchar;
-
 
 void InventoryItem_SetCursorGraphic(ScriptInvItem *iitem, int newSprite) {
 	set_inv_item_cursorpic(iitem->id, newSprite);
@@ -118,7 +115,7 @@ bool InventoryItem_SetTextProperty(ScriptInvItem *scii, const char *property, co
 void set_inv_item_cursorpic(int invItemId, int piccy) {
 	_GP(game).invinfo[invItemId].cursorPic = piccy;
 
-	if ((cur_cursor == MODE_USE) && (playerchar->activeinv == invItemId)) {
+	if ((cur_cursor == MODE_USE) && (_G(playerchar)->activeinv == invItemId)) {
 		update_inv_cursor(invItemId);
 		set_mouse_cursor(cur_cursor);
 	}
diff --git a/engines/ags/engine/ac/invwindow.cpp b/engines/ags/engine/ac/invwindow.cpp
index b9ae29f8de..d8abeb7b5b 100644
--- a/engines/ags/engine/ac/invwindow.cpp
+++ b/engines/ags/engine/ac/invwindow.cpp
@@ -53,9 +53,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern CharacterExtras *charextra;
-extern CharacterInfo *playerchar;
-
 int in_inv_screen = 0, inv_screen_newroom = -1;
 
 // *** INV WINDOW FUNCTIONS
@@ -112,7 +109,7 @@ int InvWindow_GetItemsPerRow(GUIInvWindow *guii) {
 }
 
 int InvWindow_GetItemCount(GUIInvWindow *guii) {
-	return charextra[guii->GetCharacterId()].invorder_count;
+	return _G(charextra)[guii->GetCharacterId()].invorder_count;
 }
 
 int InvWindow_GetRowCount(GUIInvWindow *guii) {
@@ -120,7 +117,7 @@ int InvWindow_GetRowCount(GUIInvWindow *guii) {
 }
 
 void InvWindow_ScrollDown(GUIInvWindow *guii) {
-	if ((charextra[guii->GetCharacterId()].invorder_count) >
+	if ((_G(charextra)[guii->GetCharacterId()].invorder_count) >
 		(guii->TopItem + (guii->ColCount * guii->RowCount))) {
 		guii->TopItem += guii->ColCount;
 		guis_need_update = 1;
@@ -138,9 +135,9 @@ void InvWindow_ScrollUp(GUIInvWindow *guii) {
 }
 
 ScriptInvItem *InvWindow_GetItemAtIndex(GUIInvWindow *guii, int index) {
-	if ((index < 0) || (index >= charextra[guii->GetCharacterId()].invorder_count))
+	if ((index < 0) || (index >= _G(charextra)[guii->GetCharacterId()].invorder_count))
 		return nullptr;
-	return &_G(scrInv)[charextra[guii->GetCharacterId()].invorder[index]];
+	return &_G(scrInv)[_G(charextra)[guii->GetCharacterId()].invorder[index]];
 }
 
 //=============================================================================
@@ -157,10 +154,10 @@ int offset_over_inv(GUIInvWindow *inv) {
 		return -1;
 
 	mover += inv->TopItem;
-	if ((mover < 0) || (mover >= charextra[inv->GetCharacterId()].invorder_count))
+	if ((mover < 0) || (mover >= _G(charextra)[inv->GetCharacterId()].invorder_count))
 		return -1;
 
-	return charextra[inv->GetCharacterId()].invorder[mover];
+	return _G(charextra)[inv->GetCharacterId()].invorder[mover];
 }
 
 //
@@ -241,9 +238,9 @@ int InventoryScreen::Redraw() {
 	numitems = 0;
 	widest = 0;
 	highest = 0;
-	if (charextra[_GP(game).playercharacter].invorder_count < 0)
+	if (_G(charextra)[_GP(game).playercharacter].invorder_count < 0)
 		update_invorder();
-	if (charextra[_GP(game).playercharacter].invorder_count == 0) {
+	if (_G(charextra)[_GP(game).playercharacter].invorder_count == 0) {
 		DisplayMessage(996);
 		in_inv_screen--;
 		return -1;
@@ -255,17 +252,17 @@ int InventoryScreen::Redraw() {
 		return -1;
 	}
 
-	for (int i = 0; i < charextra[_GP(game).playercharacter].invorder_count; ++i) {
-		if (_GP(game).invinfo[charextra[_GP(game).playercharacter].invorder[i]].name[0] != 0) {
-			dii[numitems].num = charextra[_GP(game).playercharacter].invorder[i];
-			dii[numitems].sprnum = _GP(game).invinfo[charextra[_GP(game).playercharacter].invorder[i]].pic;
+	for (int i = 0; i < _G(charextra)[_GP(game).playercharacter].invorder_count; ++i) {
+		if (_GP(game).invinfo[_G(charextra)[_GP(game).playercharacter].invorder[i]].name[0] != 0) {
+			dii[numitems].num = _G(charextra)[_GP(game).playercharacter].invorder[i];
+			dii[numitems].sprnum = _GP(game).invinfo[_G(charextra)[_GP(game).playercharacter].invorder[i]].pic;
 			int snn = dii[numitems].sprnum;
 			if (_GP(game).SpriteInfos[snn].Width > widest) widest = _GP(game).SpriteInfos[snn].Width;
 			if (_GP(game).SpriteInfos[snn].Height > highest) highest = _GP(game).SpriteInfos[snn].Height;
 			numitems++;
 		}
 	}
-	if (numitems != charextra[_GP(game).playercharacter].invorder_count)
+	if (numitems != _G(charextra)[_GP(game).playercharacter].invorder_count)
 		quit("inconsistent inventory calculations");
 
 	widest += get_fixed_pixel_size(4);
@@ -392,21 +389,21 @@ bool InventoryScreen::Run() {
 				_GP(play).usedinv = toret;
 
 				// set the activeinv so the script can check it
-				int activeinvwas = playerchar->activeinv;
-				playerchar->activeinv = toret;
+				int activeinvwas = _G(playerchar)->activeinv;
+				_G(playerchar)->activeinv = toret;
 
 				//ags_domouse(DOMOUSE_DISABLE);
 				run_event_block_inv(dii[clickedon].num, 3);
 
 				// if the script didn't change it, then put it back
-				if (playerchar->activeinv == toret)
-					playerchar->activeinv = activeinvwas;
+				if (_G(playerchar)->activeinv == toret)
+					_G(playerchar)->activeinv = activeinvwas;
 
 				// in case the script did anything to the screen, redraw it
 				UpdateGameOnce();
 
 				// They used the active item and lost it
-				if (playerchar->inv[toret] < 1) {
+				if (_G(playerchar)->inv[toret] < 1) {
 					cmode = CURS_ARROW;
 					set_mouse_cursor(cmode);
 					toret = -1;
@@ -508,7 +505,7 @@ int __actual_invscreen() {
 int invscreen() {
 	int selt = __actual_invscreen();
 	if (selt < 0) return -1;
-	playerchar->activeinv = selt;
+	_G(playerchar)->activeinv = selt;
 	guis_need_update = 1;
 	set_cursor_mode(MODE_USE);
 	return selt;
diff --git a/engines/ags/engine/ac/mouse.cpp b/engines/ags/engine/ac/mouse.cpp
index 9fec539b14..b9bb9b6f74 100644
--- a/engines/ags/engine/ac/mouse.cpp
+++ b/engines/ags/engine/ac/mouse.cpp
@@ -52,11 +52,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-
-
-
-extern CharacterInfo *playerchar;
 extern IGraphicsDriver *gfxDriver;
 
 extern void ags_domouse(int str);
@@ -237,11 +232,11 @@ void set_cursor_mode(int newmode) {
 		return;
 	}
 	if (newmode == MODE_USE) {
-		if (playerchar->activeinv == -1) {
+		if (_G(playerchar)->activeinv == -1) {
 			find_next_enabled_cursor(0);
 			return;
 		}
-		update_inv_cursor(playerchar->activeinv);
+		update_inv_cursor(_G(playerchar)->activeinv);
 	}
 	cur_mode = newmode;
 	set_default_cursor();
@@ -321,7 +316,7 @@ int IsButtonDown(int which) {
 
 int IsModeEnabled(int which) {
 	return (which < 0) || (which >= _GP(game).numcursors) ? 0 :
-		which == MODE_USE ? playerchar->activeinv > 0 :
+		which == MODE_USE ? _G(playerchar)->activeinv > 0 :
 	(_GP(game).mcurs[which].flags & MCF_DISABLED) == 0;
 }
 
@@ -410,7 +405,7 @@ bool is_standard_cursor_enabled(int curs) {
 	if ((_GP(game).mcurs[curs].flags & MCF_DISABLED) == 0) {
 		// inventory cursor, and they have an active item
 		if (curs == MODE_USE) {
-			if (playerchar->activeinv > 0)
+			if (_G(playerchar)->activeinv > 0)
 				return true;
 		}
 		// standard cursor that's not disabled, go with it
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 85c1da2bbd..4cd92f51a6 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -47,10 +47,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-extern int face_talking;
-
-extern CharacterExtras *charextra;
 extern IGraphicsDriver *gfxDriver;
 
 void Overlay_Remove(ScriptOverlay *sco) {
@@ -171,8 +167,8 @@ void remove_screen_overlay_index(size_t over_idx) {
 	_GP(screenover).erase(_GP(screenover).begin() + over_idx);
 	// if an overlay before the sierra-style speech one is removed,
 	// update the index
-	if (face_talking >= 0 && (size_t)face_talking > over_idx)
-		face_talking--;
+	if (_G(face_talking) >= 0 && (size_t)_G(face_talking) > over_idx)
+		_G(face_talking)--;
 }
 
 void remove_screen_overlay(int type) {
@@ -236,7 +232,7 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
 
 		auto view = FindNearestViewport(charid);
 		const int charpic = _G(views)[_GP(game).chars[charid].view].loops[_GP(game).chars[charid].loop].frames[0].pic;
-		const int height = (charextra[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : charextra[charid].height;
+		const int height = (_G(charextra)[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : _G(charextra)[charid].height;
 		Point screenpt = view->RoomToScreen(
 			data_to_game_coord(_GP(game).chars[charid].x),
 			data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 7e0f8ccbe1..8a6709088a 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -85,9 +85,7 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern CharacterExtras *charextra;
 extern Bitmap *walkareabackup, *walkable_areas_temp;
-extern CharacterInfo *playerchar;
 extern unsigned int loopcounter;
 extern IDriverDependantBitmap *roomBackgroundBmp;
 extern IGraphicsDriver *gfxDriver;
@@ -287,7 +285,7 @@ void unload_old_room() {
 			_G(charcache)[ff].inUse = 0;
 		}
 		// ensure that any half-moves (eg. with scaled movement) are stopped
-		charextra[ff].xwas = INVALID_X;
+		_G(charextra)[ff].xwas = INVALID_X;
 	}
 
 	_GP(play).swap_portrait_lastchar = -1;
@@ -422,7 +420,7 @@ static void update_all_viewcams_with_newroom() {
 	}
 }
 
-// forchar = playerchar on NewRoom, or NULL if restore saved game
+// forchar = _G(playerchar) on NewRoom, or NULL if restore saved game
 void load_new_room(int newnum, CharacterInfo *forchar) {
 
 	debug_script_log("Loading room %d", newnum);
@@ -911,11 +909,11 @@ void new_room(int newnum, CharacterInfo *forchar) {
 	newnum = _G(in_leaves_screen);
 	_G(in_leaves_screen) = -1;
 
-	if ((playerchar->following >= 0) &&
-	        (_GP(game).chars[playerchar->following].room != newnum)) {
+	if ((_G(playerchar)->following >= 0) &&
+	        (_GP(game).chars[_G(playerchar)->following].room != newnum)) {
 		// the player character is following another character,
 		// who is not in the new room. therefore, abort the follow
-		playerchar->following = -1;
+		_G(playerchar)->following = -1;
 	}
 	update_polled_stuff_if_runtime();
 
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 2a517244b0..ec62e136fa 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -256,7 +256,7 @@ HError InitAndRegisterGameEntities() {
 
 	setup_player_character(_GP(game).playercharacter);
 	if (loaded_game_file_version >= kGameVersion_270)
-		ccAddExternalStaticObject("player", &_sc_PlayerCharPtr, &GlobalStaticManager);
+		ccAddExternalStaticObject("player", &_G(sc_PlayerCharPtr), &GlobalStaticManager);
 	return HError::None();
 }
 
@@ -331,7 +331,7 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
 	//
 	// 3. Allocate and init game objects
 	//
-	charextra = (CharacterExtras *)calloc(_GP(game).numcharacters, sizeof(CharacterExtras));
+	_G(charextra) = (CharacterExtras *)calloc(_GP(game).numcharacters, sizeof(CharacterExtras));
 	_G(charcache) = (CharacterCache *)calloc(1, sizeof(CharacterCache) * _GP(game).numcharacters + 5);
 	_G(mls) = (MoveList *)calloc(_GP(game).numcharacters + MAX_ROOM_OBJECTS + 1, sizeof(MoveList));
 	actSpsCount = _GP(game).numcharacters + MAX_ROOM_OBJECTS + 2;
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 7bd9074781..5786f0f3a2 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -504,7 +504,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	set_cursor_mode(r_data.CursorMode);
 	set_mouse_cursor(r_data.CursorID);
 	if (r_data.CursorMode == MODE_USE)
-		SetActiveInventory(playerchar->activeinv);
+		SetActiveInventory(_G(playerchar)->activeinv);
 	// ensure that the current cursor is locked
 	_GP(spriteset).Precache(_GP(game).mcurs[r_data.CursorID].pic);
 
@@ -617,8 +617,8 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 
 	if (_G(displayed_room) < 0) {
 		// the restart point, no room was loaded
-		load_new_room(playerchar->room, playerchar);
-		playerchar->prevroom = -1;
+		load_new_room(_G(playerchar)->room, _G(playerchar));
+		_G(playerchar)->prevroom = -1;
 
 		first_room_initialization();
 	}
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 1147b293ad..18021028d3 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -480,7 +480,7 @@ HSaveError WriteCharacters(PStream out) {
 	out->WriteInt32(_GP(game).numcharacters);
 	for (int i = 0; i < _GP(game).numcharacters; ++i) {
 		_GP(game).chars[i].WriteToFile(out.get());
-		charextra[i].WriteToFile(out.get());
+		_G(charextra)[i].WriteToFile(out.get());
 		Properties::WriteValues(_GP(play).charProps[i], out.get());
 		if (loaded_game_file_version <= kGameVersion_272)
 			WriteTimesRun272(*_GP(game).intrChar[i], out.get());
@@ -496,7 +496,7 @@ HSaveError ReadCharacters(PStream in, int32_t cmp_ver, const PreservedParams &pp
 		return err;
 	for (int i = 0; i < _GP(game).numcharacters; ++i) {
 		_GP(game).chars[i].ReadFromFile(in.get());
-		charextra[i].ReadFromFile(in.get());
+		_G(charextra)[i].ReadFromFile(in.get());
 		Properties::ReadValues(_GP(play).charProps[i], in.get());
 		if (loaded_game_file_version <= kGameVersion_272)
 			ReadTimesRun272(*_GP(game).intrChar[i], in.get());
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index bf7d6a5552..5c4daff788 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -85,14 +85,10 @@ using namespace AGS::Engine;
 
 extern char check_dynamic_sprites_at_exit;
 extern char pexbuf[STD_BUFFER_SIZE];
-extern SpeechLipSyncLine *splipsync;
-extern int numLipLines, curLipLine, curLipLinePhoneme;
 
 extern IGraphicsDriver *gfxDriver;
 extern Bitmap **actsps;
 extern color palette[256];
-extern CharacterExtras *charextra;
-extern CharacterInfo *playerchar;
 extern Bitmap **guibg;
 extern IDriverDependantBitmap **guibgbmp;
 
@@ -319,15 +315,15 @@ void engine_locate_speech_pak() {
 				if (lipsync_fmt != 4) {
 					Debug::Printf(kDbgMsg_Info, "Unknown speech lip sync format (%d).\nLip sync disabled.", lipsync_fmt);
 				} else {
-					numLipLines = speechsync->ReadInt32();
-					splipsync = (SpeechLipSyncLine *)malloc(sizeof(SpeechLipSyncLine) * numLipLines);
-					for (int ee = 0; ee < numLipLines; ee++) {
-						splipsync[ee].numPhonemes = speechsync->ReadInt16();
-						speechsync->Read(splipsync[ee].filename, 14);
-						splipsync[ee].endtimeoffs = (int32_t *)malloc(splipsync[ee].numPhonemes * sizeof(int32_t));
-						speechsync->ReadArrayOfInt32(splipsync[ee].endtimeoffs, splipsync[ee].numPhonemes);
-						splipsync[ee].frame = (short *)malloc(splipsync[ee].numPhonemes * sizeof(short));
-						speechsync->ReadArrayOfInt16(splipsync[ee].frame, splipsync[ee].numPhonemes);
+					_G(numLipLines) = speechsync->ReadInt32();
+					_G(splipsync) = (SpeechLipSyncLine *)malloc(sizeof(SpeechLipSyncLine) * _G(numLipLines));
+					for (int ee = 0; ee < _G(numLipLines); ee++) {
+						_G(splipsync)[ee].numPhonemes = speechsync->ReadInt16();
+						speechsync->Read(_G(splipsync)[ee].filename, 14);
+						_G(splipsync)[ee].endtimeoffs = (int32_t *)malloc(_G(splipsync)[ee].numPhonemes * sizeof(int32_t));
+						speechsync->ReadArrayOfInt32(_G(splipsync)[ee].endtimeoffs, _G(splipsync)[ee].numPhonemes);
+						_G(splipsync)[ee].frame = (short *)malloc(_G(splipsync)[ee].numPhonemes * sizeof(short));
+						speechsync->ReadArrayOfInt16(_G(splipsync)[ee].frame, _G(splipsync)[ee].numPhonemes);
 					}
 				}
 				delete speechsync;
@@ -643,8 +639,8 @@ void engine_init_game_settings() {
 			precache_view(_GP(game).mcurs[ee].view);
 	}
 	// may as well preload the character gfx
-	if (playerchar->view >= 0)
-		precache_view(playerchar->view);
+	if (_G(playerchar)->view >= 0)
+		precache_view(_G(playerchar)->view);
 
 	for (ee = 0; ee < MAX_ROOM_OBJECTS; ee++)
 		_G(objcache)[ee].image = nullptr;
@@ -674,8 +670,8 @@ void engine_init_game_settings() {
 		_GP(game).chars[ee].baseline = -1;
 		_GP(game).chars[ee].walkwaitcounter = 0;
 		_GP(game).chars[ee].z = 0;
-		charextra[ee].xwas = INVALID_X;
-		charextra[ee].zoom = 100;
+		_G(charextra)[ee].xwas = INVALID_X;
+		_G(charextra)[ee].zoom = 100;
 		if (_GP(game).chars[ee].view >= 0) {
 			// set initial loop to 0
 			_GP(game).chars[ee].loop = 0;
@@ -683,10 +679,10 @@ void engine_init_game_settings() {
 			if (_G(views)[_GP(game).chars[ee].view].loops[0].numFrames < 1)
 				_GP(game).chars[ee].loop = 1;
 		}
-		charextra[ee].process_idle_this_time = 0;
-		charextra[ee].invorder_count = 0;
-		charextra[ee].slow_move_counter = 0;
-		charextra[ee].animwait = 0;
+		_G(charextra)[ee].process_idle_this_time = 0;
+		_G(charextra)[ee].invorder_count = 0;
+		_G(charextra)[ee].slow_move_counter = 0;
+		_G(charextra)[ee].animwait = 0;
 	}
 	// multiply up gui positions
 	guibg = (Bitmap **)malloc(sizeof(Bitmap *) * _GP(game).numgui);
@@ -698,8 +694,8 @@ void engine_init_game_settings() {
 
 	_G(our_eip) = -5;
 	for (ee = 0; ee < _GP(game).numinvitems; ee++) {
-		if (_GP(game).invinfo[ee].flags & IFLG_STARTWITH) playerchar->inv[ee] = 1;
-		else playerchar->inv[ee] = 0;
+		if (_GP(game).invinfo[ee].flags & IFLG_STARTWITH) _G(playerchar)->inv[ee] = 1;
+		else _G(playerchar)->inv[ee] = 0;
 	}
 	_GP(play).score = 0;
 	_GP(play).sierra_inv_color = 7;
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 175c8ded38..4c1bc746d1 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -75,10 +75,8 @@ using namespace AGS::Shared;
 
 extern int game_paused;
 extern int getloctype_index;
-extern CharacterInfo *playerchar;
 extern int cur_mode;
 extern char noWalkBehindsAtAll;
-extern CharacterExtras *charextra;
 
 extern int cur_mode, cur_cursor;
 
@@ -146,12 +144,12 @@ static void game_loop_do_late_update() {
 static int game_loop_check_ground_level_interactions() {
 	if ((_GP(play).ground_level_areas_disabled & GLED_INTERACTION) == 0) {
 		// check if he's standing on a hotspot
-		int hotspotThere = get_hotspot_at(playerchar->x, playerchar->y);
+		int hotspotThere = get_hotspot_at(_G(playerchar)->x, _G(playerchar)->y);
 		// run Stands on Hotspot event
 		setevent(EV_RUNEVBLOCK, EVB_HOTSPOT, hotspotThere, 0);
 
 		// check current region
-		int onRegion = GetRegionIDAtRoom(playerchar->x, playerchar->y);
+		int onRegion = GetRegionIDAtRoom(_G(playerchar)->x, _G(playerchar)->y);
 		int inRoom = _G(displayed_room);
 
 		if (onRegion != _GP(play).player_on_region) {
@@ -404,8 +402,8 @@ static void check_keyboard_controls() {
 		int ff;
 		// MACPORT FIX 9/6/5: added last %s
 		sprintf(infobuf, "In room %d %s[Player at %d, %d (view %d, loop %d, frame %d)%s%s%s",
-			_G(displayed_room), (noWalkBehindsAtAll ? "(has no walk-behinds)" : ""), playerchar->x, playerchar->y,
-			playerchar->view + 1, playerchar->loop, playerchar->frame,
+			_G(displayed_room), (noWalkBehindsAtAll ? "(has no walk-behinds)" : ""), _G(playerchar)->x, _G(playerchar)->y,
+			_G(playerchar)->view + 1, _G(playerchar)->loop, _G(playerchar)->frame,
 			(IsGamePaused() == 0) ? "" : "[Game paused.",
 			(_GP(play).ground_level_areas_disabled == 0) ? "" : "[Ground areas disabled.",
 			(IsInterfaceEnabled() == 0) ? "[Game in Wait state" : "");
@@ -438,7 +436,7 @@ static void check_keyboard_controls() {
 				_GP(game).chars[chd].x, _GP(game).chars[chd].y, _GP(game).chars[chd].z,
 				_GP(game).chars[chd].idleview, _GP(game).chars[chd].idletime, _GP(game).chars[chd].idleleft,
 				_GP(game).chars[chd].walking, _GP(game).chars[chd].animating, _GP(game).chars[chd].following,
-				_GP(game).chars[chd].flags, _GP(game).chars[chd].wait, charextra[chd].zoom);
+				_GP(game).chars[chd].flags, _GP(game).chars[chd].wait, _G(charextra)[chd].zoom);
 		}
 		Display(bigbuffer);
 
@@ -540,13 +538,13 @@ static void check_room_edges(int numevents_was) {
 		if ((_G(numevents) == numevents_was) &&
 			((_GP(play).ground_level_areas_disabled & GLED_INTERACTION) == 0)) {
 
-			if (playerchar->x <= _GP(thisroom).Edges.Left)
+			if (_G(playerchar)->x <= _GP(thisroom).Edges.Left)
 				edgesActivated[0] = 1;
-			else if (playerchar->x >= _GP(thisroom).Edges.Right)
+			else if (_G(playerchar)->x >= _GP(thisroom).Edges.Right)
 				edgesActivated[1] = 1;
-			if (playerchar->y >= _GP(thisroom).Edges.Bottom)
+			if (_G(playerchar)->y >= _GP(thisroom).Edges.Bottom)
 				edgesActivated[2] = 1;
-			else if (playerchar->y <= _GP(thisroom).Edges.Top)
+			else if (_G(playerchar)->y <= _GP(thisroom).Edges.Top)
 				edgesActivated[3] = 1;
 
 			if ((_GP(play).entered_edge >= 0) && (_GP(play).entered_edge <= 3)) {
diff --git a/engines/ags/engine/main/game_start.cpp b/engines/ags/engine/main/game_start.cpp
index fe67d9dad8..ea15c0db70 100644
--- a/engines/ags/engine/main/game_start.cpp
+++ b/engines/ags/engine/main/game_start.cpp
@@ -52,7 +52,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern CharacterInfo *playerchar;
 extern int convert_16bit_bgr;
 
 void start_game_init_editor_debugging() {
@@ -100,9 +99,9 @@ void start_game() {
 
 	if (_G(displayed_room) < 0) {
 		current_fade_out_effect();
-		load_new_room(playerchar->room, playerchar);
+		load_new_room(_G(playerchar)->room, _G(playerchar));
 		// load_new_room updates it, but it should be -1 in the first room
-		playerchar->prevroom = -1;
+		_G(playerchar)->prevroom = -1;
 	}
 
 	first_room_initialization();
@@ -131,7 +130,7 @@ void initialize_start_and_play_game(int override_start_room, int loadSaveOnStart
 
 		::AGS::g_vm->setRandomNumberSeed(_GP(play).randseed);
 		if (override_start_room)
-			playerchar->room = override_start_room;
+			_G(playerchar)->room = override_start_room;
 
 		Debug::Printf(kDbgMsg_Info, "Engine initialization complete");
 		Debug::Printf(kDbgMsg_Info, "Starting game");
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index bc9a1df257..4f07b387f4 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -54,15 +54,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern CharacterInfo *playerchar;
-extern CharacterExtras *charextra;
-extern CharacterInfo *facetalkchar;
-extern int face_talking, facetalkview, facetalkwait, facetalkframe;
-extern int facetalkloop, facetalkrepeat, facetalkAllowBlink;
-extern int facetalkBlinkLoop;
-extern bool facetalk_qfg4_override_placement_x, facetalk_qfg4_override_placement_y;
-extern SpeechLipSyncLine *splipsync;
-extern int numLipLines, curLipLine, curLipLinePhoneme;
 extern IGraphicsDriver *gfxDriver;
 
 int do_movelist_move(int16_t *mlnum, int32_t *xx, int32_t *yy) {
@@ -203,12 +194,12 @@ void update_shadow_areas() {
 	// shadow areas
 	int onwalkarea = get_walkable_area_at_character(_GP(game).playercharacter);
 	if (onwalkarea < 0);
-	else if (playerchar->flags & CHF_FIXVIEW);
+	else if (_G(playerchar)->flags & CHF_FIXVIEW);
 	else {
 		onwalkarea = _GP(thisroom).WalkAreas[onwalkarea].Light;
-		if (onwalkarea > 0) playerchar->view = onwalkarea - 1;
-		else if (_GP(thisroom).Options.PlayerView == 0) playerchar->view = playerchar->defview;
-		else playerchar->view = _GP(thisroom).Options.PlayerView - 1;
+		if (onwalkarea > 0) _G(playerchar)->view = onwalkarea - 1;
+		else if (_GP(thisroom).Options.PlayerView == 0) _G(playerchar)->view = _G(playerchar)->defview;
+		else _G(playerchar)->view = _GP(thisroom).Options.PlayerView - 1;
 	}
 }
 
@@ -218,7 +209,7 @@ void update_character_move_and_anim(int &numSheep, int *followingAsSheep) {
 		if (_GP(game).chars[aa].on != 1) continue;
 
 		CharacterInfo *chi = &_GP(game).chars[aa];
-		CharacterExtras *chex = &charextra[aa];
+		CharacterExtras *chex = &_G(charextra)[aa];
 
 		chi->UpdateMoveAndAnim(aa, chex, numSheep, followingAsSheep);
 	}
@@ -293,57 +284,57 @@ void update_sierra_speech() {
 		auto *ch = lock.GetChannel(SCHAN_SPEECH);
 		voice_pos_ms = ch ? ch->get_pos_ms() : -1;
 	}
-	if ((face_talking >= 0) && (_GP(play).fast_forward == 0)) {
+	if ((_G(face_talking) >= 0) && (_GP(play).fast_forward == 0)) {
 		int updatedFrame = 0;
 
-		if ((facetalkchar->blinkview > 0) && (facetalkAllowBlink)) {
-			if (facetalkchar->blinktimer > 0) {
+		if ((_G(facetalkchar)->blinkview > 0) && (_G(facetalkAllowBlink))) {
+			if (_G(facetalkchar)->blinktimer > 0) {
 				// countdown to playing blink anim
-				facetalkchar->blinktimer--;
-				if (facetalkchar->blinktimer == 0) {
-					facetalkchar->blinkframe = 0;
-					facetalkchar->blinktimer = -1;
+				_G(facetalkchar)->blinktimer--;
+				if (_G(facetalkchar)->blinktimer == 0) {
+					_G(facetalkchar)->blinkframe = 0;
+					_G(facetalkchar)->blinktimer = -1;
 					updatedFrame = 2;
 				}
-			} else if (facetalkchar->blinktimer < 0) {
+			} else if (_G(facetalkchar)->blinktimer < 0) {
 				// currently playing blink anim
-				if (facetalkchar->blinktimer < ((0 - 6) - _G(views)[facetalkchar->blinkview].loops[facetalkBlinkLoop].frames[facetalkchar->blinkframe].speed)) {
+				if (_G(facetalkchar)->blinktimer < ((0 - 6) - _G(views)[_G(facetalkchar)->blinkview].loops[_G(facetalkBlinkLoop)].frames[_G(facetalkchar)->blinkframe].speed)) {
 					// time to advance to next frame
-					facetalkchar->blinktimer = -1;
-					facetalkchar->blinkframe++;
+					_G(facetalkchar)->blinktimer = -1;
+					_G(facetalkchar)->blinkframe++;
 					updatedFrame = 2;
-					if (facetalkchar->blinkframe >= _G(views)[facetalkchar->blinkview].loops[facetalkBlinkLoop].numFrames) {
-						facetalkchar->blinkframe = 0;
-						facetalkchar->blinktimer = facetalkchar->blinkinterval;
+					if (_G(facetalkchar)->blinkframe >= _G(views)[_G(facetalkchar)->blinkview].loops[_G(facetalkBlinkLoop)].numFrames) {
+						_G(facetalkchar)->blinkframe = 0;
+						_G(facetalkchar)->blinktimer = _G(facetalkchar)->blinkinterval;
 					}
 				} else
-					facetalkchar->blinktimer--;
+					_G(facetalkchar)->blinktimer--;
 			}
 
 		}
 
-		if (curLipLine >= 0) {
+		if (_G(curLipLine) >= 0) {
 			// check voice lip sync
-			if (curLipLinePhoneme >= splipsync[curLipLine].numPhonemes) {
+			if (_G(curLipLinePhoneme) >= _G(splipsync)[_G(curLipLine)].numPhonemes) {
 				// the lip-sync has finished, so just stay idle
 			} else {
-				while ((curLipLinePhoneme < splipsync[curLipLine].numPhonemes) &&
-					((curLipLinePhoneme < 0) || (voice_pos_ms >= splipsync[curLipLine].endtimeoffs[curLipLinePhoneme]))) {
-					curLipLinePhoneme++;
-					if (curLipLinePhoneme >= splipsync[curLipLine].numPhonemes)
-						facetalkframe = _GP(game).default_lipsync_frame;
+				while ((_G(curLipLinePhoneme) < _G(splipsync)[_G(curLipLine)].numPhonemes) &&
+					((_G(curLipLinePhoneme) < 0) || (voice_pos_ms >= _G(splipsync)[_G(curLipLine)].endtimeoffs[_G(curLipLinePhoneme)]))) {
+					_G(curLipLinePhoneme)++;
+					if (_G(curLipLinePhoneme) >= _G(splipsync)[_G(curLipLine)].numPhonemes)
+						_G(facetalkframe) = _GP(game).default_lipsync_frame;
 					else
-						facetalkframe = splipsync[curLipLine].frame[curLipLinePhoneme];
+						_G(facetalkframe) = _G(splipsync)[_G(curLipLine)].frame[_G(curLipLinePhoneme)];
 
-					if (facetalkframe >= _G(views)[facetalkview].loops[facetalkloop].numFrames)
-						facetalkframe = 0;
+					if (_G(facetalkframe) >= _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].numFrames)
+						_G(facetalkframe) = 0;
 
 					updatedFrame |= 1;
 				}
 			}
-		} else if (facetalkwait > 0) facetalkwait--;
+		} else if (_G(facetalkwait) > 0) _G(facetalkwait)--;
 		// don't animate if the speech has finished
-		else if ((_GP(play).messagetime < 1) && (facetalkframe == 0) &&
+		else if ((_GP(play).messagetime < 1) && (_G(facetalkframe) == 0) &&
 			// if _GP(play).close_mouth_speech_time = 0, this means animation should play till
 			// the speech ends; but this should not work in voice mode, and also if the
 			// speech is in the "post" state
@@ -356,32 +347,32 @@ void update_sierra_speech() {
 				(!_GP(play).speech_has_voice &&
 				(_GP(play).messagetime < _GP(play).close_mouth_speech_time) &&
 					(_GP(play).close_mouth_speech_time > 0))) {
-				facetalkframe = 0;
-				facetalkwait = _GP(play).messagetime;
-			} else if ((_GP(game).options[OPT_LIPSYNCTEXT]) && (facetalkrepeat > 0)) {
+				_G(facetalkframe) = 0;
+				_G(facetalkwait) = _GP(play).messagetime;
+			} else if ((_GP(game).options[OPT_LIPSYNCTEXT]) && (_G(facetalkrepeat) > 0)) {
 				// lip-sync speech (and not a thought)
-				facetalkwait = update_lip_sync(facetalkview, facetalkloop, &facetalkframe);
-				// It is actually displayed for facetalkwait+1 loops
+				_G(facetalkwait) = update_lip_sync(_G(facetalkview), _G(facetalkloop), &_G(facetalkframe));
+				// It is actually displayed for _G(facetalkwait)+1 loops
 				// (because when it's 1, it gets --'d then wait for next time)
-				facetalkwait--;
+				_G(facetalkwait)--;
 			} else {
 				// normal non-lip-sync
-				facetalkframe++;
-				if ((facetalkframe >= _G(views)[facetalkview].loops[facetalkloop].numFrames) ||
+				_G(facetalkframe)++;
+				if ((_G(facetalkframe) >= _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].numFrames) ||
 					(!_GP(play).speech_has_voice && (_GP(play).messagetime < 1) && (_GP(play).close_mouth_speech_time > 0))) {
 
-					if ((facetalkframe >= _G(views)[facetalkview].loops[facetalkloop].numFrames) &&
-						(_G(views)[facetalkview].loops[facetalkloop].RunNextLoop())) {
-						facetalkloop++;
+					if ((_G(facetalkframe) >= _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].numFrames) &&
+						(_G(views)[_G(facetalkview)].loops[_G(facetalkloop)].RunNextLoop())) {
+						_G(facetalkloop)++;
 					} else {
-						facetalkloop = 0;
+						_G(facetalkloop) = 0;
 					}
-					facetalkframe = 0;
-					if (!facetalkrepeat)
-						facetalkwait = 999999;
+					_G(facetalkframe) = 0;
+					if (!_G(facetalkrepeat))
+						_G(facetalkwait) = 999999;
 				}
-				if ((facetalkframe != 0) || (facetalkrepeat == 1))
-					facetalkwait = _G(views)[facetalkview].loops[facetalkloop].frames[facetalkframe].speed + GetCharacterSpeechAnimationDelay(facetalkchar);
+				if ((_G(facetalkframe) != 0) || (_G(facetalkrepeat) == 1))
+					_G(facetalkwait) = _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)].speed + GetCharacterSpeechAnimationDelay(_G(facetalkchar));
 			}
 			updatedFrame |= 1;
 		}
@@ -390,42 +381,42 @@ void update_sierra_speech() {
 		if ((updatedFrame) && (_G(is_text_overlay) > 0)) {
 
 			if (updatedFrame & 1)
-				CheckViewFrame(facetalkview, facetalkloop, facetalkframe);
+				CheckViewFrame(_G(facetalkview), _G(facetalkloop), _G(facetalkframe));
 			if (updatedFrame & 2)
-				CheckViewFrame(facetalkchar->blinkview, facetalkBlinkLoop, facetalkchar->blinkframe);
+				CheckViewFrame(_G(facetalkchar)->blinkview, _G(facetalkBlinkLoop), _G(facetalkchar)->blinkframe);
 
-			int thisPic = _G(views)[facetalkview].loops[facetalkloop].frames[facetalkframe].pic;
+			int thisPic = _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)].pic;
 			int view_frame_x = 0;
 			int view_frame_y = 0;
 
 			if (_GP(game).options[OPT_SPEECHTYPE] == 3) {
 				// QFG4-style fullscreen dialog
-				if (facetalk_qfg4_override_placement_x) {
+				if (_G(facetalk_qfg4_override_placement_x)) {
 					view_frame_x = _GP(play).speech_portrait_x;
 				}
-				if (facetalk_qfg4_override_placement_y) {
+				if (_G(facetalk_qfg4_override_placement_y)) {
 					view_frame_y = _GP(play).speech_portrait_y;
 				} else {
-					view_frame_y = (_GP(screenover)[face_talking].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
+					view_frame_y = (_GP(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
 				}
-				_GP(screenover)[face_talking].pic->Clear(0);
+				_GP(screenover)[_G(face_talking)].pic->Clear(0);
 			} else {
-				_GP(screenover)[face_talking].pic->ClearTransparent();
+				_GP(screenover)[_G(face_talking)].pic->ClearTransparent();
 			}
 
-			Bitmap *frame_pic = _GP(screenover)[face_talking].pic;
-			const ViewFrame *face_vf = &_G(views)[facetalkview].loops[facetalkloop].frames[facetalkframe];
+			Bitmap *frame_pic = _GP(screenover)[_G(face_talking)].pic;
+			const ViewFrame *face_vf = &_G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)];
 			bool face_has_alpha = (_GP(game).SpriteInfos[face_vf->pic].Flags & SPF_ALPHACHANNEL) != 0;
 			DrawViewFrame(frame_pic, face_vf, view_frame_x, view_frame_y);
 
-			if ((facetalkchar->blinkview > 0) && (facetalkchar->blinktimer < 0)) {
-				ViewFrame *blink_vf = &_G(views)[facetalkchar->blinkview].loops[facetalkBlinkLoop].frames[facetalkchar->blinkframe];
+			if ((_G(facetalkchar)->blinkview > 0) && (_G(facetalkchar)->blinktimer < 0)) {
+				ViewFrame *blink_vf = &_G(views)[_G(facetalkchar)->blinkview].loops[_G(facetalkBlinkLoop)].frames[_G(facetalkchar)->blinkframe];
 				face_has_alpha |= (_GP(game).SpriteInfos[blink_vf->pic].Flags & SPF_ALPHACHANNEL) != 0;
 				// draw the blinking sprite on top
 				DrawViewFrame(frame_pic, blink_vf, view_frame_x, view_frame_y, face_has_alpha);
 			}
 
-			gfxDriver->UpdateDDBFromBitmap(_GP(screenover)[face_talking].bmp, _GP(screenover)[face_talking].pic, face_has_alpha);
+			gfxDriver->UpdateDDBFromBitmap(_GP(screenover)[_G(face_talking)].bmp, _GP(screenover)[_G(face_talking)].pic, face_has_alpha);
 		}  // end if updatedFrame
 	}
 }
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index 0487e6b750..1a228e44f9 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -100,8 +100,6 @@ void set_clip_to_channel(int chanid, SOUNDCLIP *clip) {
 }
 //-----------------------
 
-extern CharacterInfo *playerchar;
-
 void calculate_reserved_channel_count() {
 	int reservedChannels = 0;
 	for (size_t i = 0; i < _GP(game).audioClipTypes.size(); i++) {
@@ -513,8 +511,8 @@ SOUNDCLIP *load_sound_clip_from_old_style_number(bool isMusic, int indexNumber,
 //=============================================================================
 
 int get_volume_adjusted_for_distance(int volume, int sndX, int sndY, int sndMaxDist) {
-	int distx = playerchar->x - sndX;
-	int disty = playerchar->y - sndY;
+	int distx = _G(playerchar)->x - sndX;
+	int disty = _G(playerchar)->y - sndY;
 	// it uses Allegro's "fix" sqrt without the ::
 	int dist = (int)::sqrt((double)(distx * distx + disty * disty));
 
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 6396d5e7a4..9d02657702 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -56,7 +56,6 @@ namespace AGS3 {
 
 extern int gameHasBeenRestored;
 extern unsigned int load_new_game;
-extern CharacterInfo *playerchar;
 
 int run_dialog_request(int parmtr) {
 	_GP(play).stop_dialog_at_end = DIALOG_RUNNING;
@@ -494,7 +493,7 @@ void post_script_cleanup() {
 		case ePSANewRoom:
 			// only change rooms when all scripts are done
 			if (_G(num_scripts) == 0) {
-				new_room(thisData, playerchar);
+				new_room(thisData, _G(playerchar));
 				// don't allow any pending room scripts from the old room
 				// in run_another to be executed
 				return;
@@ -690,7 +689,7 @@ int run_interaction_commandlist(InteractionCommandList *nicl, int *timesrun, int
 			SetDialogOption(IPARAM1, IPARAM2, 0);
 			break;
 		case 12: // Go To Screen
-			Character_ChangeRoomAutoPosition(playerchar, IPARAM1, IPARAM2);
+			Character_ChangeRoomAutoPosition(_G(playerchar), IPARAM1, IPARAM2);
 			return -1;
 		case 13: // Add Inventory
 			add_inventory(IPARAM1);
@@ -729,7 +728,7 @@ int run_interaction_commandlist(InteractionCommandList *nicl, int *timesrun, int
 				cmdsrun[0] --;
 			break;
 		case 21: // if player has inventory item
-			if (playerchar->inv[IPARAM1] > 0)
+			if (_G(playerchar)->inv[IPARAM1] > 0)
 				if (run_interaction_commandlist(nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
 					return -1;
 			break;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 01c7dec1d6..89a30eaf78 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -95,6 +95,8 @@ struct CCInventory;
 struct CCObject;
 struct CCRegion;
 struct CharacterCache;
+struct CharacterExtras;
+struct CharacterInfo;
 struct COLOR_MAP;
 struct DirtyRects;
 struct ExecutingScript;
@@ -126,6 +128,7 @@ struct ScriptRegion;
 struct ScriptString;
 struct ScriptSystem;
 struct SOUNDCLIP;
+struct SpeechLipSyncLine;
 struct SpriteListEntry;
 struct StaticArray;
 struct SystemImports;
@@ -259,6 +262,34 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup character globals
+	 * @{
+	 */
+
+	CharacterExtras *_charextra = nullptr;
+	CharacterInfo *_playerchar = nullptr;
+	int32_t _sc_PlayerCharPtr = 0;
+	int _char_lowest_yp = 0;
+
+	// Sierra-style speech settings
+	int _face_talking = -1, _facetalkview = 0, _facetalkwait = 0, _facetalkframe = 0;
+	int _facetalkloop = 0, _facetalkrepeat = 0, _facetalkAllowBlink = 1;
+	int _facetalkBlinkLoop = 0;
+	CharacterInfo *_facetalkchar = nullptr;
+	// Do override default portrait position during QFG4-style speech overlay update
+	bool _facetalk_qfg4_override_placement_x = false;
+	bool _facetalk_qfg4_override_placement_y = false;
+
+	// lip-sync speech settings
+	int _loops_per_character, _text_lips_offset, _char_speaking = -1;
+	int _char_thinking = -1;
+	const char *_text_lips_text = nullptr;
+	SpeechLipSyncLine *_splipsync = nullptr;
+	int _numLipLines = 0, _curLipLine = -1, _curLipLinePhoneme = 0;
+
+	/**@}*/
+
 	/**
 	 * \defgroup debug globals
 	 * @{


Commit: 81976cb9946b37a6657afbbe5b61a135389f686e
    https://github.com/scummvm/scummvm/commit/81976cb9946b37a6657afbbe5b61a135389f686e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-08T19:22:34-08:00

Commit Message:
AGS: Move dialog.cpp globals to Globals

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/dialogoptionsrendering.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/dynobj/cc_serializer.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_dialog.cpp
    engines/ags/engine/ac/string.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/main/game_file.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/shared/game/main_game_file.cpp


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index f8136aadca..f6276e2a46 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -82,8 +82,6 @@ using namespace AGS::Shared;
 extern Bitmap *walkable_areas_temp;
 extern IGraphicsDriver *gfxDriver;
 extern Bitmap **actsps;
-extern int said_speech_line;
-extern int said_text;
 
 // **** CHARACTER: FUNCTIONS ****
 
@@ -2270,7 +2268,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 
 	EndSkippingUntilCharStops();
 
-	said_speech_line = 1;
+	_G(said_speech_line) = 1;
 
 	if (_GP(play).bgspeech_stay_on_display == 0) {
 		// remove any background speech
@@ -2281,7 +2279,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 				i++;
 		}
 	}
-	said_text = 1;
+	_G(said_text) = 1;
 
 	// the strings are pre-translated
 	//texx = get_translation(texx);
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 79e12ba9b7..1c3c051910 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -73,15 +73,6 @@ using namespace AGS::Shared;
 extern int cur_mode, cur_cursor;
 extern IGraphicsDriver *gfxDriver;
 
-DialogTopic *dialog;
-ScriptDialogOptionsRendering ccDialogOptionsRendering;
-ScriptDrawingSurface *dialogOptionsRenderingSurface;
-
-int said_speech_line; // used while in dialog to track whether screen needs updating
-int said_text = 0;
-int longestline = 0;
-
-
 void Dialog_Start(ScriptDialog *sd) {
 	RunDialog(sd->id);
 }
@@ -111,42 +102,42 @@ int Dialog_GetOptionState(ScriptDialog *sd, int option) {
 }
 
 int Dialog_HasOptionBeenChosen(ScriptDialog *sd, int option) {
-	if ((option < 1) || (option > dialog[sd->id].numoptions))
+	if ((option < 1) || (option > _G(dialog)[sd->id].numoptions))
 		quit("!Dialog.HasOptionBeenChosen: Invalid option number specified");
 	option--;
 
-	if (dialog[sd->id].optionflags[option] & DFLG_HASBEENCHOSEN)
+	if (_G(dialog)[sd->id].optionflags[option] & DFLG_HASBEENCHOSEN)
 		return 1;
 	return 0;
 }
 
 void Dialog_SetHasOptionBeenChosen(ScriptDialog *sd, int option, bool chosen) {
-	if (option < 1 || option > dialog[sd->id].numoptions) {
+	if (option < 1 || option > _G(dialog)[sd->id].numoptions) {
 		quit("!Dialog.HasOptionBeenChosen: Invalid option number specified");
 	}
 	option--;
 	if (chosen) {
-		dialog[sd->id].optionflags[option] |= DFLG_HASBEENCHOSEN;
+		_G(dialog)[sd->id].optionflags[option] |= DFLG_HASBEENCHOSEN;
 	} else {
-		dialog[sd->id].optionflags[option] &= ~DFLG_HASBEENCHOSEN;
+		_G(dialog)[sd->id].optionflags[option] &= ~DFLG_HASBEENCHOSEN;
 	}
 }
 
 int Dialog_GetOptionCount(ScriptDialog *sd) {
-	return dialog[sd->id].numoptions;
+	return _G(dialog)[sd->id].numoptions;
 }
 
 int Dialog_GetShowTextParser(ScriptDialog *sd) {
-	return (dialog[sd->id].topicFlags & DTFLG_SHOWPARSER) ? 1 : 0;
+	return (_G(dialog)[sd->id].topicFlags & DTFLG_SHOWPARSER) ? 1 : 0;
 }
 
 const char *Dialog_GetOptionText(ScriptDialog *sd, int option) {
-	if ((option < 1) || (option > dialog[sd->id].numoptions))
+	if ((option < 1) || (option > _G(dialog)[sd->id].numoptions))
 		quit("!Dialog.GetOptionText: Invalid option number specified");
 
 	option--;
 
-	return CreateNewScriptString(get_translation(dialog[sd->id].optionnames[option]));
+	return CreateNewScriptString(get_translation(_G(dialog)[sd->id].optionnames[option]));
 }
 
 int Dialog_GetID(ScriptDialog *sd) {
@@ -176,7 +167,7 @@ void get_dialog_script_parameters(unsigned char *&script, unsigned short *param1
 }
 
 int run_dialog_script(DialogTopic *dtpp, int dialogID, int offse, int optionIndex) {
-	said_speech_line = 0;
+	_G(said_speech_line) = 0;
 	int result = RUN_DIALOG_STAY;
 
 	if (_G(dialogScriptsInst)) {
@@ -208,7 +199,7 @@ int run_dialog_script(DialogTopic *dtpp, int dialogID, int offse, int optionInde
 				else
 					DisplaySpeech(get_translation(_G(old_speech_lines)[param2]), param1);
 
-				said_speech_line = 1;
+				_G(said_speech_line) = 1;
 				break;
 
 			case DCMD_OPTOFF:
@@ -301,7 +292,7 @@ int run_dialog_script(DialogTopic *dtpp, int dialogID, int offse, int optionInde
 	if (_G(in_new_room) > 0)
 		return RUN_DIALOG_STOP_DIALOG;
 
-	if (said_speech_line > 0) {
+	if (_G(said_speech_line) > 0) {
 		// the line below fixes the problem with the close-up face remaining on the
 		// screen after they finish talking; however, it makes the dialog options
 		// area flicker when going between topics.
@@ -385,14 +376,14 @@ void draw_gui_for_dialog_options(Bitmap *ds, GUIMain *guib, int dlgxp, int dlgyp
 }
 
 bool get_custom_dialog_options_dimensions(int dlgnum) {
-	ccDialogOptionsRendering.Reset();
-	ccDialogOptionsRendering.dialogID = dlgnum;
+	_GP(ccDialogOptionsRendering).Reset();
+	_GP(ccDialogOptionsRendering).dialogID = dlgnum;
 
-	_GP(getDialogOptionsDimensionsFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+	_GP(getDialogOptionsDimensionsFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 	run_function_on_non_blocking_thread(&_GP(getDialogOptionsDimensionsFunc));
 
-	if ((ccDialogOptionsRendering.width > 0) &&
-	        (ccDialogOptionsRendering.height > 0)) {
+	if ((_GP(ccDialogOptionsRendering).width > 0) &&
+	        (_GP(ccDialogOptionsRendering).height > 0)) {
 		return true;
 	}
 	return false;
@@ -484,7 +475,7 @@ void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground) {
 	if (_GP(game).options[OPT_DIALOGNUMBERED] == kDlgOptNumbering)
 		bullet_wid += wgettextwidth_compensate("9. ", usingfont);
 
-	said_text = 0;
+	_G(said_text) = 0;
 
 	update_polled_stuff_if_runtime();
 
@@ -493,7 +484,7 @@ void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground) {
 
 	set_mouse_cursor(CURS_ARROW);
 
-	dtop = &dialog[dlgnum];
+	dtop = &_G(dialog)[dlgnum];
 
 	chose = -1;
 	numdisp = 0;
@@ -540,10 +531,10 @@ void DialogOptions::Show() {
 	dlgxp = 1;
 	if (get_custom_dialog_options_dimensions(dlgnum)) {
 		usingCustomRendering = true;
-		dirtyx = data_to_game_coord(ccDialogOptionsRendering.x);
-		dirtyy = data_to_game_coord(ccDialogOptionsRendering.y);
-		dirtywidth = data_to_game_coord(ccDialogOptionsRendering.width);
-		dirtyheight = data_to_game_coord(ccDialogOptionsRendering.height);
+		dirtyx = data_to_game_coord(_GP(ccDialogOptionsRendering).x);
+		dirtyy = data_to_game_coord(_GP(ccDialogOptionsRendering).y);
+		dirtywidth = data_to_game_coord(_GP(ccDialogOptionsRendering).width);
+		dirtyheight = data_to_game_coord(_GP(ccDialogOptionsRendering).height);
 		dialog_abs_x = dirtyx;
 	} else if (_GP(game).options[OPT_DIALOGIFACE] > 0) {
 		GUIMain *guib = &_GP(guis)[_GP(game).options[OPT_DIALOGIFACE]];
@@ -612,8 +603,8 @@ void DialogOptions::Redraw() {
 
 	if (usingCustomRendering) {
 		tempScrn = recycle_bitmap(tempScrn, _GP(game).GetColorDepth(),
-		                          data_to_game_coord(ccDialogOptionsRendering.width),
-		                          data_to_game_coord(ccDialogOptionsRendering.height));
+		                          data_to_game_coord(_GP(ccDialogOptionsRendering).width),
+		                          data_to_game_coord(_GP(ccDialogOptionsRendering).height));
 	}
 
 	tempScrn->ClearTransparent();
@@ -626,26 +617,26 @@ void DialogOptions::Redraw() {
 	bool options_surface_has_alpha = false;
 
 	if (usingCustomRendering) {
-		ccDialogOptionsRendering.surfaceToRenderTo = dialogOptionsRenderingSurface;
-		ccDialogOptionsRendering.surfaceAccessed = false;
-		dialogOptionsRenderingSurface->linkedBitmapOnly = tempScrn;
-		dialogOptionsRenderingSurface->hasAlphaChannel = ccDialogOptionsRendering.hasAlphaChannel;
-		options_surface_has_alpha = dialogOptionsRenderingSurface->hasAlphaChannel != 0;
+		_GP(ccDialogOptionsRendering).surfaceToRenderTo = _G(dialogOptionsRenderingSurface);
+		_GP(ccDialogOptionsRendering).surfaceAccessed = false;
+		_G(dialogOptionsRenderingSurface)->linkedBitmapOnly = tempScrn;
+		_G(dialogOptionsRenderingSurface)->hasAlphaChannel = _GP(ccDialogOptionsRendering).hasAlphaChannel;
+		options_surface_has_alpha = _G(dialogOptionsRenderingSurface)->hasAlphaChannel != 0;
 
-		_GP(renderDialogOptionsFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+		_GP(renderDialogOptionsFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 		run_function_on_non_blocking_thread(&_GP(renderDialogOptionsFunc));
 
-		if (!ccDialogOptionsRendering.surfaceAccessed)
+		if (!_GP(ccDialogOptionsRendering).surfaceAccessed)
 			debug_script_warn("dialog_options_get_dimensions was implemented, but no dialog_options_render function drew anything to the surface");
 
 		if (parserInput) {
-			parserInput->X = data_to_game_coord(ccDialogOptionsRendering.parserTextboxX);
-			curyp = data_to_game_coord(ccDialogOptionsRendering.parserTextboxY);
-			areawid = data_to_game_coord(ccDialogOptionsRendering.parserTextboxWidth);
+			parserInput->X = data_to_game_coord(_GP(ccDialogOptionsRendering).parserTextboxX);
+			curyp = data_to_game_coord(_GP(ccDialogOptionsRendering).parserTextboxY);
+			areawid = data_to_game_coord(_GP(ccDialogOptionsRendering).parserTextboxWidth);
 			if (areawid == 0)
 				areawid = tempScrn->GetWidth();
 		}
-		ccDialogOptionsRendering.needRepaint = false;
+		_GP(ccDialogOptionsRendering).needRepaint = false;
 	} else if (is_textwindow) {
 		// text window behind the options
 		areawid = data_to_game_coord(_GP(play).max_dialogoption_width);
@@ -653,8 +644,8 @@ void DialogOptions::Redraw() {
 		padding = _GP(guis)[_GP(game).options[OPT_DIALOGIFACE]].Padding;
 		for (int i = 0; i < numdisp; ++i) {
 			break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[i]]), _GP(fontLines), areawid - ((2 * padding + 2) + bullet_wid), usingfont);
-			if (longestline > biggest)
-				biggest = longestline;
+			if (_G(longestline) > biggest)
+				biggest = _G(longestline);
 		}
 		if (biggest < areawid - ((2 * padding + 6) + bullet_wid))
 			areawid = biggest + ((2 * padding + 6) + bullet_wid);
@@ -671,7 +662,7 @@ void DialogOptions::Redraw() {
 		int txoffs = 0, tyoffs = 0, yspos = ui_view.GetHeight() / 2 - (2 * padding + needheight) / 2;
 		int xspos = ui_view.GetWidth() / 2 - areawid / 2;
 		// shift window to the right if QG4-style full-screen pic
-		if ((_GP(game).options[OPT_SPEECHTYPE] == 3) && (said_text > 0))
+		if ((_GP(game).options[OPT_SPEECHTYPE] == 3) && (_G(said_text) > 0))
 			xspos = (ui_view.GetWidth() - areawid) - get_fixed_pixel_size(10);
 
 		// needs to draw the right text window, not the default
@@ -816,7 +807,7 @@ bool DialogOptions::Run() {
 	}
 
 	if (new_custom_render) {
-		_GP(runDialogOptionRepExecFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+		_GP(runDialogOptionRepExecFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 		run_function_on_non_blocking_thread(&_GP(runDialogOptionRepExecFunc));
 	}
 
@@ -842,7 +833,7 @@ bool DialogOptions::Run() {
 				}
 			}
 		} else if (new_custom_render) {
-			_GP(runDialogOptionKeyPressHandlerFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+			_GP(runDialogOptionKeyPressHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 			_GP(runDialogOptionKeyPressHandlerFunc).params[1].SetInt32(GetKeyForKeyPressCb(gkey));
 			run_function_on_non_blocking_thread(&_GP(runDialogOptionKeyPressHandlerFunc));
 		}
@@ -863,15 +854,15 @@ bool DialogOptions::Run() {
 		if ((_G(mousex) >= dirtyx) && (_G(mousey) >= dirtyy) &&
 		        (_G(mousex) < dirtyx + tempScrn->GetWidth()) &&
 		        (_G(mousey) < dirtyy + tempScrn->GetHeight())) {
-			_GP(getDialogOptionUnderCursorFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+			_GP(getDialogOptionUnderCursorFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 			run_function_on_non_blocking_thread(&_GP(getDialogOptionUnderCursorFunc));
 
 			if (!_GP(getDialogOptionUnderCursorFunc).atLeastOneImplementationExists)
 				quit("!The script function dialog_options_get_active is not implemented. It must be present to use a custom dialogue system.");
 
-			mouseison = ccDialogOptionsRendering.activeOptionID;
+			mouseison = _GP(ccDialogOptionsRendering).activeOptionID;
 		} else {
-			ccDialogOptionsRendering.activeOptionID = -1;
+			_GP(ccDialogOptionsRendering).activeOptionID = -1;
 		}
 	} else if (_G(mousex) >= dialog_abs_x && _G(mousex) < (dialog_abs_x + areawid) &&
 	           _G(mousey) >= dlgyp && _G(mousey) < curyp) {
@@ -904,7 +895,7 @@ bool DialogOptions::Run() {
 	        !_GP(play).IsIgnoringInput()) {
 		if (mouseison < 0 && !new_custom_render) {
 			if (usingCustomRendering) {
-				_GP(runDialogOptionMouseClickHandlerFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+				_GP(runDialogOptionMouseClickHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 				_GP(runDialogOptionMouseClickHandlerFunc).params[1].SetInt32(mouseButtonPressed + 1);
 				run_function_on_non_blocking_thread(&_GP(runDialogOptionMouseClickHandlerFunc));
 
@@ -919,7 +910,7 @@ bool DialogOptions::Run() {
 			// they clicked the text box
 			parserActivated = 1;
 		} else if (new_custom_render) {
-			_GP(runDialogOptionMouseClickHandlerFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+			_GP(runDialogOptionMouseClickHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 			_GP(runDialogOptionMouseClickHandlerFunc).params[1].SetInt32(mouseButtonPressed + 1);
 			run_function_on_non_blocking_thread(&_GP(runDialogOptionMouseClickHandlerFunc));
 		} else if (usingCustomRendering) {
@@ -933,7 +924,7 @@ bool DialogOptions::Run() {
 
 	if (usingCustomRendering) {
 		if (mouseWheelTurn != 0) {
-			_GP(runDialogOptionMouseClickHandlerFunc).params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+			_GP(runDialogOptionMouseClickHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 			_GP(runDialogOptionMouseClickHandlerFunc).params[1].SetInt32((mouseWheelTurn < 0) ? 9 : 8);
 			run_function_on_non_blocking_thread(&_GP(runDialogOptionMouseClickHandlerFunc));
 
@@ -961,12 +952,12 @@ bool DialogOptions::Run() {
 		return true; // continue running loop
 	}
 	if (new_custom_render) {
-		if (ccDialogOptionsRendering.chosenOptionID >= 0) {
-			chose = ccDialogOptionsRendering.chosenOptionID;
-			ccDialogOptionsRendering.chosenOptionID = -1;
+		if (_GP(ccDialogOptionsRendering).chosenOptionID >= 0) {
+			chose = _GP(ccDialogOptionsRendering).chosenOptionID;
+			_GP(ccDialogOptionsRendering).chosenOptionID = -1;
 			return false; // end dialog options running loop
 		}
-		if (ccDialogOptionsRendering.needRepaint) {
+		if (_GP(ccDialogOptionsRendering).needRepaint) {
 			Redraw();
 			return true; // continue running loop
 		}
@@ -1046,7 +1037,7 @@ void do_conversation(int dlgnum) {
 	int dlgnum_was = dlgnum;
 	int previousTopics[MAX_TOPIC_HISTORY];
 	int numPrevTopics = 0;
-	DialogTopic *dtop = &dialog[dlgnum];
+	DialogTopic *dtop = &_G(dialog)[dlgnum];
 
 	// run the startup script
 	int tocar = run_dialog_script(dtop, dlgnum, dtop->startupentrypoint, 0);
@@ -1063,7 +1054,7 @@ void do_conversation(int dlgnum) {
 		if (dlgnum >= _GP(game).numdialog)
 			quit("!RunDialog: invalid dialog number specified");
 
-		dtop = &dialog[dlgnum];
+		dtop = &_G(dialog)[dlgnum];
 
 		if (dlgnum != dlgnum_was) {
 			// dialog topic changed, so play the startup
@@ -1097,11 +1088,11 @@ void do_conversation(int dlgnum) {
 			return;
 
 		if (chose == CHOSE_TEXTPARSER) {
-			said_speech_line = 0;
+			_G(said_speech_line) = 0;
 
 			tocar = run_dialog_request(dlgnum);
 
-			if (said_speech_line > 0) {
+			if (_G(said_speech_line) > 0) {
 				// fix the problem with the close-up face remaining on screen
 				DisableInterface();
 				UpdateGameOnce(); // redraw the screen to make sure it looks right
diff --git a/engines/ags/engine/ac/dialogoptionsrendering.cpp b/engines/ags/engine/ac/dialogoptionsrendering.cpp
index 2f368c6ea7..c36756e712 100644
--- a/engines/ags/engine/ac/dialogoptionsrendering.cpp
+++ b/engines/ags/engine/ac/dialogoptionsrendering.cpp
@@ -32,8 +32,6 @@
 
 namespace AGS3 {
 
-extern DialogTopic *dialog;
-
 // ** SCRIPT DIALOGOPTIONSRENDERING OBJECT
 
 void DialogOptionsRendering_Update(ScriptDialogOptionsRendering *dlgOptRender) {
@@ -123,7 +121,7 @@ int DialogOptionsRendering_GetActiveOptionID(ScriptDialogOptionsRendering *dlgOp
 }
 
 void DialogOptionsRendering_SetActiveOptionID(ScriptDialogOptionsRendering *dlgOptRender, int activeOptionID) {
-	int optionCount = dialog[_G(scrDialog)[dlgOptRender->dialogID].id].numoptions;
+	int optionCount = _G(dialog)[_G(scrDialog)[dlgOptRender->dialogID].id].numoptions;
 	if ((activeOptionID < 0) || (activeOptionID > optionCount))
 		quitprintf("DialogOptionsRenderingInfo.ActiveOptionID: invalid ID specified for this dialog (specified %d, valid range: 1..%d)", activeOptionID, optionCount);
 
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 9030049181..58e226f8dd 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -60,8 +60,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Shared::BitmapHelper;
 
-extern int longestline;
-
 int display_message_aschar = 0;
 
 TopBarSettings topBar;
@@ -115,8 +113,8 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 		// any top bar text
 		int topBarWid = wgettextwidth_compensate(topBar.text, topBar.font);
 		topBarWid += data_to_game_coord(_GP(play).top_bar_borderwidth + 2) * 2;
-		if (longestline < topBarWid)
-			longestline = topBarWid;
+		if (_G(longestline) < topBarWid)
+			_G(longestline) = topBarWid;
 		// the top bar should behave like DisplaySpeech wrt blocking
 		disp_type = DISPLAYTEXT_SPEECH;
 	}
@@ -140,13 +138,13 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 		yy = adjust_y_for_guis(yy);
 	}
 
-	if (longestline < wii - paddingDoubledScaled) {
+	if (_G(longestline) < wii - paddingDoubledScaled) {
 		// shrink the width of the dialog box to fit the text
 		int oldWid = wii;
 		//if ((asspch >= 0) || (allowShrink > 0))
 		// If it's not speech, or a shrink is allowed, then shrink it
 		if ((asspch == 0) || (allowShrink > 0))
-			wii = longestline + paddingDoubledScaled;
+			wii = _G(longestline) + paddingDoubledScaled;
 
 		// shift the dialog box right to align it, if necessary
 		if ((allowShrink == 2) && (xx >= 0))
diff --git a/engines/ags/engine/ac/dynobj/cc_serializer.cpp b/engines/ags/engine/ac/dynobj/cc_serializer.cpp
index 290708434b..dee0d9e55c 100644
--- a/engines/ags/engine/ac/dynobj/cc_serializer.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_serializer.cpp
@@ -36,8 +36,6 @@
 
 namespace AGS3 {
 
-extern ScriptDrawingSurface *dialogOptionsRenderingSurface;
-extern ScriptDialogOptionsRendering ccDialogOptionsRendering;
 extern PluginObjectReader pluginReaders[MAX_PLUGIN_OBJECT_READERS];
 extern int numPluginReaders;
 
@@ -85,10 +83,10 @@ void AGSDeSerializer::Unserialize(int index, const char *objectType, const char
 		sds->Unserialize(index, serializedData, dataSize);
 
 		if (sds->isLinkedBitmapOnly) {
-			dialogOptionsRenderingSurface = sds;
+			_G(dialogOptionsRenderingSurface) = sds;
 		}
 	} else if (strcmp(objectType, "DialogOptionsRendering") == 0) {
-		ccDialogOptionsRendering.Unserialize(index, serializedData, dataSize);
+		_GP(ccDialogOptionsRendering).Unserialize(index, serializedData, dataSize);
 	} else if (strcmp(objectType, "StringDictionary") == 0) {
 		Dict_Unserialize(index, serializedData, dataSize);
 	} else if (strcmp(objectType, "StringSet") == 0) {
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 18a6c275a9..aeed1b5472 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -110,7 +110,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern int cur_mode, cur_cursor;
-extern DialogTopic *dialog;
 
 #if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
 extern int _G(psp_gfx_renderer);
@@ -525,12 +524,12 @@ void unload_game_file() {
 	}
 
 	for (int i = 0; i < _GP(game).numdialog; ++i) {
-		if (dialog[i].optionscripts != nullptr)
-			free(dialog[i].optionscripts);
-		dialog[i].optionscripts = nullptr;
+		if (_G(dialog)[i].optionscripts != nullptr)
+			free(_G(dialog)[i].optionscripts);
+		_G(dialog)[i].optionscripts = nullptr;
 	}
-	free(dialog);
-	dialog = nullptr;
+	free(_G(dialog));
+	_G(dialog) = nullptr;
 	delete[] _G(scrDialog);
 	_G(scrDialog) = nullptr;
 
@@ -1153,7 +1152,7 @@ void restore_game_palette(Stream *in) {
 
 void restore_game_dialogs(Stream *in) {
 	for (int vv = 0; vv < _GP(game).numdialog; vv++)
-		in->ReadArrayOfInt32(&dialog[vv].optionflags[0], MAXTOPICOPTIONS);
+		in->ReadArrayOfInt32(&_G(dialog)[vv].optionflags[0], MAXTOPICOPTIONS);
 }
 
 void restore_game_more_dynamic_values(Stream *in) {
diff --git a/engines/ags/engine/ac/global_dialog.cpp b/engines/ags/engine/ac/global_dialog.cpp
index 7035af2108..0f63c7fef5 100644
--- a/engines/ags/engine/ac/global_dialog.cpp
+++ b/engines/ags/engine/ac/global_dialog.cpp
@@ -36,8 +36,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern DialogTopic *dialog;
-
 void RunDialog(int tum) {
 	if ((tum < 0) | (tum >= _GP(game).numdialog))
 		quit("!RunDialog: invalid topic number specified");
@@ -75,7 +73,7 @@ void StopDialog() {
 void SetDialogOption(int dlg, int opt, int onoroff, bool dlg_script) {
 	if ((dlg < 0) | (dlg >= _GP(game).numdialog))
 		quit("!SetDialogOption: Invalid topic number specified");
-	if ((opt < 1) | (opt > dialog[dlg].numoptions)) {
+	if ((opt < 1) | (opt > _G(dialog)[dlg].numoptions)) {
 		// Pre-3.1.1 games had "dialog scripts" that were written in different language and
 		// parsed differently; its "option-on/off" commands were more permissive.
 		if (dlg_script) {
@@ -86,23 +84,23 @@ void SetDialogOption(int dlg, int opt, int onoroff, bool dlg_script) {
 	}
 	opt--;
 
-	dialog[dlg].optionflags[opt] &= ~DFLG_ON;
-	if ((onoroff == 1) & ((dialog[dlg].optionflags[opt] & DFLG_OFFPERM) == 0))
-		dialog[dlg].optionflags[opt] |= DFLG_ON;
+	_G(dialog)[dlg].optionflags[opt] &= ~DFLG_ON;
+	if ((onoroff == 1) & ((_G(dialog)[dlg].optionflags[opt] & DFLG_OFFPERM) == 0))
+		_G(dialog)[dlg].optionflags[opt] |= DFLG_ON;
 	else if (onoroff == 2)
-		dialog[dlg].optionflags[opt] |= DFLG_OFFPERM;
+		_G(dialog)[dlg].optionflags[opt] |= DFLG_OFFPERM;
 }
 
 int GetDialogOption(int dlg, int opt) {
 	if ((dlg < 0) | (dlg >= _GP(game).numdialog))
 		quit("!GetDialogOption: Invalid topic number specified");
-	if ((opt < 1) | (opt > dialog[dlg].numoptions))
+	if ((opt < 1) | (opt > _G(dialog)[dlg].numoptions))
 		quit("!GetDialogOption: Invalid option number specified");
 	opt--;
 
-	if (dialog[dlg].optionflags[opt] & DFLG_OFFPERM)
+	if (_G(dialog)[dlg].optionflags[opt] & DFLG_OFFPERM)
 		return 2;
-	if (dialog[dlg].optionflags[opt] & DFLG_ON)
+	if (_G(dialog)[dlg].optionflags[opt] & DFLG_ON)
 		return 1;
 	return 0;
 }
diff --git a/engines/ags/engine/ac/string.cpp b/engines/ags/engine/ac/string.cpp
index ef8eab32f3..ddf4f192a9 100644
--- a/engines/ags/engine/ac/string.cpp
+++ b/engines/ags/engine/ac/string.cpp
@@ -40,10 +40,6 @@
 
 namespace AGS3 {
 
-
-extern int longestline;
-
-
 int String_IsNullOrEmpty(const char *thisString) {
 	if ((thisString == nullptr) || (thisString[0] == 0))
 		return 1;
@@ -241,7 +237,7 @@ size_t break_up_text_into_lines(const char *todis, SplitLines &lines, int wii, i
 		if (todis[0] == ' ') todis++;
 	}
 	lines.Reset();
-	longestline = 0;
+	_G(longestline) = 0;
 
 	// Don't attempt to display anything if the width is tiny
 	if (wii < 3)
@@ -257,13 +253,13 @@ size_t break_up_text_into_lines(const char *todis, SplitLines &lines, int wii, i
 		for (size_t rr = 0; rr < lines.Count(); rr++) {
 			lines[rr].Reverse();
 			line_length = wgettextwidth_compensate(lines[rr], fonnt);
-			if (line_length > longestline)
-				longestline = line_length;
+			if (line_length > _G(longestline))
+				_G(longestline) = line_length;
 		} else
 			for (size_t rr = 0; rr < lines.Count(); rr++) {
 				line_length = wgettextwidth_compensate(lines[rr], fonnt);
-				if (line_length > longestline)
-					longestline = line_length;
+				if (line_length > _G(longestline))
+					_G(longestline) = line_length;
 			}
 		return lines.Count();
 }
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index ec62e136fa..36df26259a 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -63,8 +63,6 @@ extern IDriverDependantBitmap **actspsbmp;
 extern Bitmap **actspswb;
 extern IDriverDependantBitmap **actspswbbmp;
 extern CachedActSpsData *actspswbcache;
-extern ScriptDialogOptionsRendering ccDialogOptionsRendering;
-extern ScriptDrawingSurface *dialogOptionsRenderingSurface;
 extern AGSStaticObject GlobalStaticManager;
 
 namespace AGS {
@@ -147,11 +145,11 @@ void InitAndRegisterDialogs() {
 
 // Initializes dialog options rendering objects and registers them in the script system
 void InitAndRegisterDialogOptions() {
-	ccRegisterManagedObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
+	ccRegisterManagedObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 
-	dialogOptionsRenderingSurface = new ScriptDrawingSurface();
-	dialogOptionsRenderingSurface->isLinkedBitmapOnly = true;
-	long dorsHandle = ccRegisterManagedObject(dialogOptionsRenderingSurface, dialogOptionsRenderingSurface);
+	_G(dialogOptionsRenderingSurface) = new ScriptDrawingSurface();
+	_G(dialogOptionsRenderingSurface)->isLinkedBitmapOnly = true;
+	long dorsHandle = ccRegisterManagedObject(_G(dialogOptionsRenderingSurface), _G(dialogOptionsRenderingSurface));
 	ccAddObjectReference(dorsHandle);
 }
 
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 18021028d3..0e29991f64 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -64,7 +64,6 @@ namespace AGS3 {
 using namespace Shared;
 
 extern color palette[256];
-extern DialogTopic *dialog;
 extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
 extern Bitmap *raw_saved_screen;
 
@@ -511,7 +510,7 @@ HSaveError ReadCharacters(PStream in, int32_t cmp_ver, const PreservedParams &pp
 HSaveError WriteDialogs(PStream out) {
 	out->WriteInt32(_GP(game).numdialog);
 	for (int i = 0; i < _GP(game).numdialog; ++i) {
-		dialog[i].WriteToSavegame(out.get());
+		_G(dialog)[i].WriteToSavegame(out.get());
 	}
 	return HSaveError::None();
 }
@@ -521,7 +520,7 @@ HSaveError ReadDialogs(PStream in, int32_t cmp_ver, const PreservedParams &pp, R
 	if (!AssertGameContent(err, in->ReadInt32(), _GP(game).numdialog, "Dialogs"))
 		return err;
 	for (int i = 0; i < _GP(game).numdialog; ++i) {
-		dialog[i].ReadFromSavegame(in.get());
+		_G(dialog)[i].ReadFromSavegame(in.get());
 	}
 	return err;
 }
diff --git a/engines/ags/engine/main/game_file.cpp b/engines/ags/engine/main/game_file.cpp
index 4979b39f0a..7259faefe0 100644
--- a/engines/ags/engine/main/game_file.cpp
+++ b/engines/ags/engine/main/game_file.cpp
@@ -59,9 +59,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern DialogTopic *dialog;
-
-
 // Test if engine supports extended capabilities required to run the game
 bool test_game_caps(const std::set<String> &caps, std::set<String> &failed_caps) {
 	// Currently we support nothing special
@@ -132,7 +129,7 @@ HError preload_game_data() {
 
 HError load_game_file() {
 	MainGameSource src;
-	LoadedGameEntities ents(_GP(game), dialog, _G(views));
+	LoadedGameEntities ents(_GP(game), _G(dialog), _G(views));
 	HGameFileError load_err = OpenMainGameFileFromDefaultAsset(src);
 	if (load_err) {
 		load_err = ReadGameData(ents, src.InputStream.get(), src.DataVersion);
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index acf1975f90..3ace0d4c8d 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -60,12 +60,13 @@
 #include "ags/engine/ac/dynobj/cc_audioclip.h"
 #include "ags/engine/ac/dynobj/managedobjectpool.h"
 #include "ags/engine/ac/dynobj/scriptaudiochannel.h"
-#include "ags/engine/ac/dynobj/scriptsystem.h"
+#include "ags/engine/ac/dynobj/scriptdialogoptionsrendering.h"
 #include "ags/engine/ac/dynobj/scripthotspot.h"
 #include "ags/engine/ac/dynobj/scriptinvitem.h"
 #include "ags/engine/ac/dynobj/scriptobject.h"
 #include "ags/engine/ac/dynobj/scriptregion.h"
 #include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/scriptsystem.h"
 #include "ags/engine/ac/statobj/staticarray.h"
 #include "ags/engine/debugging/consoleoutputtarget.h"
 #include "ags/engine/debugging/debugger.h"
@@ -114,6 +115,9 @@ Globals::Globals() {
 	// debugmanager.cpp globals
 	_DbgMgr = new AGS::Shared::DebugManager();
 
+	// dialog.cpp globals
+	_ccDialogOptionsRendering = new ScriptDialogOptionsRendering();
+
 	// draw.cpp globals
 	_CameraDrawData = new std::vector<RoomCameraDrawData>();
 	_sprlist = new std::vector<SpriteListEntry>();
@@ -258,6 +262,9 @@ Globals::~Globals() {
 	// debugmanager.cpp globals
 	delete _DbgMgr;
 
+	// dialog.cpp globals
+	delete _ccDialogOptionsRendering;
+
 	// draw.cpp globals
 	delete _CameraDrawData;
 	delete _sprlist;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 89a30eaf78..ce5fabeb98 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -98,6 +98,7 @@ struct CharacterCache;
 struct CharacterExtras;
 struct CharacterInfo;
 struct COLOR_MAP;
+struct DialogTopic;
 struct DirtyRects;
 struct ExecutingScript;
 struct EventHappened;
@@ -119,6 +120,8 @@ struct RuntimeScriptValue;
 struct ScreenOverlay;
 struct ScriptAudioChannel;
 struct ScriptDialog;
+struct ScriptDialogOptionsRendering;
+struct ScriptDrawingSurface;
 struct ScriptGUI;
 struct ScriptHotspot;
 struct ScriptInvItem;
@@ -337,7 +340,14 @@ public:
 	 * @{
 	 */
 
-	 // Old dialog support
+	DialogTopic *_dialog;
+	ScriptDialogOptionsRendering *_ccDialogOptionsRendering;
+	ScriptDrawingSurface *_dialogOptionsRenderingSurface = nullptr;
+
+	int _said_speech_line = 0; // used while in dialog to track whether screen needs updating
+	int _said_text = 0;
+	int _longestline = 0;
+	// Old dialog support
 	std::vector< std::shared_ptr<unsigned char> > _old_dialog_scripts;
 	std::vector<String> _old_speech_lines;
 
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index da582f485e..b1ccedfe9a 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -237,7 +237,7 @@ void ReadDialogs(DialogTopic *&dialog,
 	// double check and remove if proved unnecessary
 	dialog = (DialogTopic *)malloc(sizeof(DialogTopic) * dlg_count + 5);
 	for (int i = 0; i < dlg_count; ++i) {
-		dialog[i].ReadFromFile(in);
+		_G(dialog)[i].ReadFromFile(in);
 	}
 
 	if (data_ver > kGameVersion_310)
@@ -246,9 +246,9 @@ void ReadDialogs(DialogTopic *&dialog,
 	old_dialog_scripts.resize(dlg_count);
 	old_dialog_src.resize(dlg_count);
 	for (int i = 0; i < dlg_count; ++i) {
-		// NOTE: originally this was read into dialog[i].optionscripts
-		old_dialog_scripts[i].reset(new unsigned char[dialog[i].codesize]);
-		in->Read(old_dialog_scripts[i].get(), dialog[i].codesize);
+		// NOTE: originally this was read into _G(dialog)[i].optionscripts
+		old_dialog_scripts[i].reset(new unsigned char[_G(dialog)[i].codesize]);
+		in->Read(old_dialog_scripts[i].get(), _G(dialog)[i].codesize);
 
 		// Encrypted text script
 		int script_text_len = in->ReadInt32();


Commit: 764271844a04da4757ca051b243209d332bce237
    https://github.com/scummvm/scummvm/commit/764271844a04da4757ca051b243209d332bce237
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-08T20:03:22-08:00

Commit Message:
AGS: Move global_object globals to Globals

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_object.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index f6276e2a46..400ac29137 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -2098,8 +2098,6 @@ CharacterInfo *GetCharacterAtRoom(int x, int y) {
 	return &_GP(game).chars[hsnum];
 }
 
-extern int obj_lowest_yp;
-
 int is_pos_on_character(int xx, int yy) {
 	int cc, sppic, lowestyp = 0, lowestwas = -1;
 	for (cc = 0; cc < _GP(game).numcharacters; cc++) {
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index aeed1b5472..891c582667 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -115,8 +115,6 @@ extern int cur_mode, cur_cursor;
 extern int _G(psp_gfx_renderer);
 #endif
 
-extern int obj_lowest_yp;
-
 extern int actSpsCount;
 extern Bitmap **actsps;
 extern IDriverDependantBitmap * *actspsbmp;
@@ -1662,9 +1660,9 @@ int __GetLocationType(int xxx, int yyy, int allowHotspot0) {
 		wbat = 0;
 
 	if ((charat >= 0) && (objat >= 0)) {
-		if ((wbat > obj_lowest_yp) && (wbat > _G(char_lowest_yp)))
+		if ((wbat > _G(obj_lowest_yp)) && (wbat > _G(char_lowest_yp)))
 			winner = LOCTYPE_HOTSPOT;
-		else if (obj_lowest_yp > _G(char_lowest_yp))
+		else if (_G(obj_lowest_yp) > _G(char_lowest_yp))
 			winner = LOCTYPE_OBJ;
 		else
 			winner = LOCTYPE_CHAR;
@@ -1674,7 +1672,7 @@ int __GetLocationType(int xxx, int yyy, int allowHotspot0) {
 		else
 			winner = LOCTYPE_CHAR;
 	} else if (objat >= 0) {
-		if (wbat > obj_lowest_yp)
+		if (wbat > _G(obj_lowest_yp))
 			winner = LOCTYPE_HOTSPOT;
 		else
 			winner = LOCTYPE_OBJ;
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 268372378b..45275c406a 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -57,9 +57,6 @@ extern Bitmap **actsps;
 extern IDriverDependantBitmap **actspsbmp;
 extern IGraphicsDriver *gfxDriver;
 
-// Used for deciding whether a char or obj was closer
-int obj_lowest_yp;
-
 int GetObjectIDAtScreen(int scrx, int scry) {
 	// translate screen co-ordinates to room co-ordinates
 	VpPoint vpt = _GP(play).ScreenToRoomDivDown(scrx, scry);
@@ -94,7 +91,7 @@ int GetObjectIDAtRoom(int roomx, int roomy) {
 		bestshotwas = aa;
 		bestshotyp = usebasel;
 	}
-	obj_lowest_yp = bestshotyp;
+	_G(obj_lowest_yp) = bestshotyp;
 	return bestshotwas;
 }
 
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index ce5fabeb98..305dde1b1b 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -526,6 +526,16 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup global_object globals
+	 * @{
+	 */
+
+	// Used for deciding whether a char or obj was closer
+	int _obj_lowest_yp = 0;
+
+	/**@}*/
+
 	/**
 	 * \defgroup graphics_mode globals
 	 * @{


Commit: 5a6b282c7c5c3752a46f61e7f11890f79705d0b8
    https://github.com/scummvm/scummvm/commit/5a6b282c7c5c3752a46f61e7f11890f79705d0b8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-08T20:06:37-08:00

Commit Message:
AGS: Move engine_setup.cpp globals to Globals

Changed paths:
    engines/ags/ags.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/global_debug.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/main/engine_setup.cpp
    engines/ags/engine/main/game_start.cpp
    engines/ags/globals.h


diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index 01f9533ef4..29cbe35097 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -69,9 +69,6 @@ using namespace Engine;
 
 extern HSaveError load_game(int slotNumber, bool &data_overwritten);
 
-
-extern int convert_16bit_bgr;
-
 // this needs to be updated if the "play" struct changes
 #define SVG_VERSION_BWCOMPAT_MAJOR      3
 #define SVG_VERSION_BWCOMPAT_MINOR      2
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index bfc7d686f8..c9364dd3f1 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -88,8 +88,6 @@ extern "C" void android_render();
 extern "C" void ios_render();
 #endif
 
-extern int convert_16bit_bgr;
-
 extern char noWalkBehindsAtAll;
 extern unsigned int loopcounter;
 extern char *walkBehindExists;  // whether a WB area is in this column
@@ -260,7 +258,7 @@ Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
 			new_bitmap = BitmapHelper::CreateBitmapCopy(bitmap, game_col_depth);
 	}
 	// Special case when we must convert 16-bit RGB to BGR
-	else if (convert_16bit_bgr == 1 && bmp_col_depth == 16) {
+	else if (_G(convert_16bit_bgr) == 1 && bmp_col_depth == 16) {
 		new_bitmap = convert_16_to_16bgr(bitmap);
 	}
 	return new_bitmap;
diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index 8ef86a413d..a4f427e086 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -53,7 +53,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern int convert_16bit_bgr;
 extern IGraphicsDriver *gfxDriver;
 extern TreeMap *transtree;
 extern char transFileName[MAX_PATH];
@@ -68,7 +67,7 @@ String GetRuntimeInfo() {
 		"[Running %d x %d at %d-bit%s%s[GFX: %s; %s[Draw frame %d x %d["
 		"Sprite cache size: %d KB (limit %d KB; %d locked)",
 		_G(EngineVersion).LongString.GetCStr(), _GP(game).GetGameRes().Width, _GP(game).GetGameRes().Height, _GP(game).GetColorDepth(),
-		mode.Width, mode.Height, mode.ColorDepth, (convert_16bit_bgr) ? " BGR" : "",
+		mode.Width, mode.Height, mode.ColorDepth, (_G(convert_16bit_bgr)) ? " BGR" : "",
 		mode.Windowed ? " W" : "",
 		gfxDriver->GetDriverName(), filter->GetInfo().Name.GetCStr(),
 		render_frame.GetWidth(), render_frame.GetHeight(),
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 8a6709088a..01ab4f5454 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -374,8 +374,6 @@ void convert_room_coordinates_to_data_res(RoomStruct *rstruc) {
 	rstruc->Height /= mul;
 }
 
-extern int convert_16bit_bgr;
-
 void update_letterbox_mode() {
 	const Size real_room_sz = Size(data_to_game_coord(_GP(thisroom).Width), data_to_game_coord(_GP(thisroom).Height));
 	const Rect game_frame = RectWH(_GP(game).GetGameRes());
diff --git a/engines/ags/engine/main/engine_setup.cpp b/engines/ags/engine/main/engine_setup.cpp
index 0c12c1cec3..f93f95a5a6 100644
--- a/engines/ags/engine/main/engine_setup.cpp
+++ b/engines/ags/engine/main/engine_setup.cpp
@@ -50,13 +50,9 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-
 extern int _places_r, _places_g, _places_b;
 extern IGraphicsDriver *gfxDriver;
 
-int convert_16bit_bgr = 0;
-
 // Convert guis position and size to proper game resolution.
 // Necessary for pre 3.1.0 games only to sync with modern engine.
 void convert_gui_to_game_resolution(GameDataVersion filever) {
@@ -192,7 +188,7 @@ void engine_setup_color_conversions(int coldepth) {
 	// Most cards do 5-6-5 RGB, which is the format the files are saved in
 	// Some do 5-6-5 BGR, or  6-5-5 RGB, in which case convert the gfx
 	if ((coldepth == 16) && ((_G(_rgb_b_shift_16) != 0) || (_G(_rgb_r_shift_16) != 11))) {
-		convert_16bit_bgr = 1;
+		_G(convert_16bit_bgr) = 1;
 		if (_G(_rgb_r_shift_16) == 10) {
 			// some very old graphics cards lie about being 16-bit when they
 			// are in fact 15-bit ... get around this
diff --git a/engines/ags/engine/main/game_start.cpp b/engines/ags/engine/main/game_start.cpp
index ea15c0db70..2fcd1d199a 100644
--- a/engines/ags/engine/main/game_start.cpp
+++ b/engines/ags/engine/main/game_start.cpp
@@ -52,8 +52,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern int convert_16bit_bgr;
-
 void start_game_init_editor_debugging() {
 	if (_G(editor_debugging_enabled)) {
 		SetMultitasking(1);
@@ -118,7 +116,7 @@ void initialize_start_and_play_game(int override_start_room, int loadSaveOnStart
 
 		set_cursor_mode(MODE_WALK);
 
-		if (convert_16bit_bgr) {
+		if (_G(convert_16bit_bgr)) {
 			// Disable text as speech while displaying the warning message
 			// This happens if the user's graphics card does BGR order 16-bit colour
 			int oldalways = _GP(game).options[OPT_ALWAYSSPCH];
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 305dde1b1b..d1d76897f0 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -391,6 +391,16 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup engine_setup globals
+	 * @{
+	 */
+
+	int _convert_16bit_bgr = 0;
+
+	/**@}*/
+
+
 	/**
 	 * \defgroup event globals
 	 * @{




More information about the Scummvm-git-logs mailing list