[Scummvm-git-logs] scummvm master -> a5c4876862027617e82b2385414971f796eda0f9

dreammaster dreammaster at scummvm.org
Wed Mar 10 05:17:23 UTC 2021


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

Summary:
f97407f6ca AGS: Move game_run.cpp globals to Globals
2d82d32577 AGS: Move draw.cpp globals to Globals
dbdac3c3cf AGS: Move walkablearea.cpp globals to Globals
f6e83fa57e AGS: Move sys_events.cpp globals to Globals
b38289e5aa AGS: Move room.cpp globals to Globals
c7b1836e53 AGS: Move invwindow.cpp globals to Globals
a5c4876862 AGS: Move mouse.cpp globals to Globals


Commit: f97407f6cae4ca8712f1b4776b2369c2ae4342e7
    https://github.com/scummvm/scummvm/commit/f97407f6cae4ca8712f1b4776b2369c2ae4342e7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:14:02-08:00

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

Changed paths:
    engines/ags/engine/ac/characterinfo_engine.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/game.h
    engines/ags/engine/ac/gamestate.h
    engines/ags/engine/ac/global_screen.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/runtime_defines.h
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/characterinfo_engine.cpp b/engines/ags/engine/ac/characterinfo_engine.cpp
index a317ae825e..5bf469a910 100644
--- a/engines/ags/engine/ac/characterinfo_engine.cpp
+++ b/engines/ags/engine/ac/characterinfo_engine.cpp
@@ -41,8 +41,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern unsigned int loopcounter;
-
 #define Random __Rand
 
 int CharacterInfo::get_effective_y() {
@@ -449,7 +447,7 @@ void CharacterInfo::update_character_idle(CharacterExtras *chex, int &doing_noth
 	else if ((doing_nothing == 0) || ((flags & CHF_FIXVIEW) != 0))
 		idleleft = idletime;
 	// count idle time
-	else if ((loopcounter % 40 == 0) || (chex->process_idle_this_time == 1)) {
+	else if ((_G(loopcounter) % 40 == 0) || (chex->process_idle_this_time == 1)) {
 		idleleft--;
 		if (idleleft == -1) {
 			int useloop = loop;
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index c9364dd3f1..b546bf7924 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -89,7 +89,6 @@ extern "C" void ios_render();
 #endif
 
 extern char noWalkBehindsAtAll;
-extern unsigned int loopcounter;
 extern char *walkBehindExists;  // whether a WB area is in this column
 extern int *walkBehindStartY, *walkBehindEndY;
 extern int walkBehindLeft[MAX_WALK_BEHINDS], walkBehindTop[MAX_WALK_BEHINDS];
@@ -1906,7 +1905,7 @@ void draw_fps(const Rect &viewport) {
 	wouttext_outline(fpsDisplay, 1, 1, font, text_color, fps_buffer);
 
 	char loop_buffer[60];
-	sprintf(loop_buffer, "Loop %u", loopcounter);
+	sprintf(loop_buffer, "Loop %u", _G(loopcounter));
 	wouttext_outline(fpsDisplay, viewport.GetWidth() / 2, 1, font, text_color, loop_buffer);
 
 	if (ddb)
@@ -2259,7 +2258,7 @@ static void update_shakescreen() {
 	// TODO: unify blocking and non-blocking shake update
 	_GP(play).shake_screen_yoff = 0;
 	if (_GP(play).shakesc_length > 0) {
-		if ((loopcounter % _GP(play).shakesc_delay) < (_GP(play).shakesc_delay / 2))
+		if ((_G(loopcounter) % _GP(play).shakesc_delay) < (_GP(play).shakesc_delay / 2))
 			_GP(play).shake_screen_yoff = _GP(play).shakesc_amount;
 	}
 }
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index b55fa7c458..8020519373 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -126,7 +126,6 @@ extern Bitmap **guibg;
 extern IDriverDependantBitmap **guibgbmp;
 extern char transFileName[MAX_PATH];
 extern color palette[256];
-extern unsigned int loopcounter;
 extern Bitmap *raw_saved_screen;
 extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
 extern IGraphicsDriver *gfxDriver;
diff --git a/engines/ags/engine/ac/game.h b/engines/ags/engine/ac/game.h
index 975ae48c5d..296fa80e9a 100644
--- a/engines/ags/engine/ac/game.h
+++ b/engines/ags/engine/ac/game.h
@@ -196,7 +196,6 @@ void get_message_text(int msnum, char *buffer, char giveErr = 1);
 
 bool unserialize_audio_script_object(int index, const char *objectType, const char *serializedData, int dataSize);
 
-extern unsigned int loopcounter;
 extern void set_loop_counter(unsigned int new_counter);
 extern int game_paused;
 
diff --git a/engines/ags/engine/ac/gamestate.h b/engines/ags/engine/ac/gamestate.h
index 7e48b1314e..a06a564250 100644
--- a/engines/ags/engine/ac/gamestate.h
+++ b/engines/ags/engine/ac/gamestate.h
@@ -191,7 +191,7 @@ struct GameState {
 	int   silent_midi = 0;
 	int   silent_midi_channel = 0;
 	int   current_music_repeating = 0;  // remember what the loop flag was when this music started
-	unsigned long shakesc_delay = 0;  // unsigned long to match loopcounter
+	unsigned long shakesc_delay = 0;  // unsigned long to match _G(loopcounter)
 	int   shakesc_amount = 0, shakesc_length = 0;
 	int   rtint_red = 0, rtint_green = 0, rtint_blue = 0, rtint_level = 0, rtint_light = 0;
 	bool  rtint_enabled = 0;
diff --git a/engines/ags/engine/ac/global_screen.cpp b/engines/ags/engine/ac/global_screen.cpp
index 041ba55277..15497bb4a1 100644
--- a/engines/ags/engine/ac/global_screen.cpp
+++ b/engines/ags/engine/ac/global_screen.cpp
@@ -42,9 +42,7 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern IGraphicsDriver *gfxDriver;
-
 extern color palette[256];
-extern unsigned int loopcounter;
 
 void FlipScreen(int amount) {
 	if ((amount < 0) | (amount > 3)) quit("!FlipScreen: invalid argument (0-3)");
@@ -70,7 +68,7 @@ void ShakeScreen(int severe) {
 
 	if (gfxDriver->RequiresFullRedrawEachFrame()) {
 		for (int hh = 0; hh < 40; hh++) {
-			loopcounter++;
+			_G(loopcounter)++;
 			_G(platform)->Delay(50);
 
 			render_graphics();
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 01ab4f5454..b8d2adbb86 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -86,7 +86,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern Bitmap *walkareabackup, *walkable_areas_temp;
-extern unsigned int loopcounter;
 extern IDriverDependantBitmap *roomBackgroundBmp;
 extern IGraphicsDriver *gfxDriver;
 extern Bitmap *raw_saved_screen;
diff --git a/engines/ags/engine/ac/runtime_defines.h b/engines/ags/engine/ac/runtime_defines.h
index 23d7425f81..e3bf9ae8b0 100644
--- a/engines/ags/engine/ac/runtime_defines.h
+++ b/engines/ags/engine/ac/runtime_defines.h
@@ -116,7 +116,7 @@ const int LegacyRoomVolumeFactor = 30;
 #define FOR_SCRIPT    2
 #define FOR_EXITLOOP  3
 #define CHMLSOFFS (MAX_ROOM_OBJECTS+1)    // reserve this many movelists for objects & stuff
-#define abort_all_conditions restrict_until
+#define abort_all_conditions _G(restrict_until)
 #define MAX_SCRIPT_AT_ONCE 10
 #define EVENT_NONE       0
 #define EVENT_INPROGRESS 1
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 10b055cfa8..50da482977 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -210,7 +210,7 @@ HSaveError WriteGameState(PStream out) {
 	_GP(play).WriteForSavegame(out.get());
 	// Other dynamic values
 	out->WriteInt32(_G(frames_per_second));
-	out->WriteInt32(loopcounter);
+	out->WriteInt32(_G(loopcounter));
 	out->WriteInt32(_G(ifacepopped));
 	out->WriteInt32(game_paused);
 	// Mouse cursor
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index eac940f223..fc3135b87e 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -77,15 +77,11 @@ extern int game_paused;
 extern int getloctype_index;
 extern int cur_mode;
 extern char noWalkBehindsAtAll;
-
 extern int cur_mode, cur_cursor;
 
 // Checks if user interface should remain disabled for now
 static int ShouldStayInWaitMode();
 
-static int numEventsAtStartOfFunction;
-static uint32 t1 = 0; // AGS_Clock::now();  // timer for FPS // ... 't1'... how very appropriate.. :)
-
 #define UNTIL_ANIMEND   1
 #define UNTIL_MOVEEND   2
 #define UNTIL_CHARIS0   3
@@ -95,14 +91,6 @@ static uint32 t1 = 0; // AGS_Clock::now();  // timer for FPS // ... 't1'... how
 #define UNTIL_SHORTIS0  7
 #define UNTIL_INTISNEG  8
 
-// Following 3 parameters instruct the engine to run game loops until
-// certain condition is not fullfilled.
-static int restrict_until = 0;
-static int user_disabled_for = 0;
-static const void *user_disabled_data = nullptr;
-
-unsigned int loopcounter = 0;
-static unsigned int lastcounter = 0;
 
 static void ProperExit() {
 	_G(want_exit) = 0;
@@ -176,10 +164,10 @@ static int game_loop_check_ground_level_interactions() {
 		// if in a Wait loop which is no longer valid (probably
 		// because the Region interaction did a NewRoom), abort
 		// the rest of the loop
-		if ((restrict_until) && (!ShouldStayInWaitMode())) {
+		if ((_G(restrict_until)) && (!ShouldStayInWaitMode())) {
 			// cancel the Rep Exec and Stands on Hotspot events that
 			// we just added -- otherwise the event queue gets huge
-			_G(numevents) = numEventsAtStartOfFunction;
+			_G(numevents) = _G(numEventsAtStartOfFunction);
 			return 0;
 		}
 	} // end if checking ground level interactions
@@ -451,7 +439,7 @@ static void check_keyboard_controls() {
 	// }
 
 	if (kgn == eAGSKeyCodeAltV && (::AGS::g_events->getModifierFlags() & KB_CTRL_FLAG)
-			&& (_GP(play).wait_counter < 1) && (_G(is_text_overlay) == 0) && (restrict_until == 0)) {
+			&& (_GP(play).wait_counter < 1) && (_G(is_text_overlay) == 0) && (_G(restrict_until) == 0)) {
 		// make sure we can't interrupt a Wait()
 		// and desync the music to cutscene
 		_GP(play).debug_mode++;
@@ -667,12 +655,12 @@ static void game_loop_update_background_animation() {
 }
 
 static void game_loop_update_loop_counter() {
-	loopcounter++;
+	_G(loopcounter)++;
 
 	if (_GP(play).wait_counter > 0) _GP(play).wait_counter--;
 	if (_GP(play).shakesc_length > 0) _GP(play).shakesc_length--;
 
-	if (loopcounter % 5 == 0) {
+	if (_G(loopcounter) % 5 == 0) {
 		update_ambient_sound_vol();
 		update_directional_sound_vol();
 	}
@@ -680,13 +668,13 @@ static void game_loop_update_loop_counter() {
 
 static void game_loop_update_fps() {
 	auto t2 = AGS_Clock::now();
-	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
-	auto frames = loopcounter - lastcounter;
+	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - _G(t1));
+	auto frames = _G(loopcounter) - _G(lastcounter);
 
 	if (duration >= std::chrono::milliseconds(1000) && frames > 0) {
 		_G(fps) = 1000.0f * frames / duration.count();
-		t1 = t2;
-		lastcounter = loopcounter;
+		_G(t1) = t2;
+		_G(lastcounter) = _G(loopcounter);
 	}
 }
 
@@ -700,9 +688,9 @@ float get_current_fps() {
 }
 
 void set_loop_counter(unsigned int new_counter) {
-	loopcounter = new_counter;
-	t1 = AGS_Clock::now();
-	lastcounter = loopcounter;
+	_G(loopcounter) = new_counter;
+	_G(t1) = AGS_Clock::now();
+	_G(lastcounter) = _G(loopcounter);
 	_G(fps) = std::numeric_limits<float>::quiet_undefined();
 }
 
@@ -710,7 +698,7 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
 
 	int res;
 
-	numEventsAtStartOfFunction = _G(numevents);
+	_G(numEventsAtStartOfFunction) = _G(numevents);
 
 	if (_G(want_exit)) {
 		ProperExit();
@@ -809,29 +797,29 @@ static void UpdateMouseOverLocation() {
 
 // Checks if user interface should remain disabled for now
 static int ShouldStayInWaitMode() {
-	if (restrict_until == 0)
+	if (_G(restrict_until) == 0)
 		quit("end_wait_loop called but game not in loop_until state");
-	int retval = restrict_until;
+	int retval = _G(restrict_until);
 
-	if (restrict_until == UNTIL_MOVEEND) {
-		const short *wkptr = (const short *)user_disabled_data;
+	if (_G(restrict_until) == UNTIL_MOVEEND) {
+		const short *wkptr = (const short *)_G(user_disabled_data);
 		if (wkptr[0] < 1) retval = 0;
-	} else if (restrict_until == UNTIL_CHARIS0) {
-		const char *chptr = (const char *)user_disabled_data;
+	} else if (_G(restrict_until) == UNTIL_CHARIS0) {
+		const char *chptr = (const char *)_G(user_disabled_data);
 		if (chptr[0] == 0) retval = 0;
-	} else if (restrict_until == UNTIL_NEGATIVE) {
-		const short *wkptr = (const short *)user_disabled_data;
+	} else if (_G(restrict_until) == UNTIL_NEGATIVE) {
+		const short *wkptr = (const short *)_G(user_disabled_data);
 		if (wkptr[0] < 0) retval = 0;
-	} else if (restrict_until == UNTIL_INTISNEG) {
-		const int *wkptr = (const int *)user_disabled_data;
+	} else if (_G(restrict_until) == UNTIL_INTISNEG) {
+		const int *wkptr = (const int *)_G(user_disabled_data);
 		if (wkptr[0] < 0) retval = 0;
-	} else if (restrict_until == UNTIL_NOOVERLAY) {
+	} else if (_G(restrict_until) == UNTIL_NOOVERLAY) {
 		if (_G(is_text_overlay) < 1) retval = 0;
-	} else if (restrict_until == UNTIL_INTIS0) {
-		const int *wkptr = (const int *)user_disabled_data;
+	} else if (_G(restrict_until) == UNTIL_INTIS0) {
+		const int *wkptr = (const int *)_G(user_disabled_data);
 		if (wkptr[0] == 0) retval = 0;
-	} else if (restrict_until == UNTIL_SHORTIS0) {
-		const short *wkptr = (const short *)user_disabled_data;
+	} else if (_G(restrict_until) == UNTIL_SHORTIS0) {
+		const short *wkptr = (const short *)_G(user_disabled_data);
 		if (wkptr[0] == 0) retval = 0;
 	} else quit("loop_until: unknown until event");
 
@@ -839,23 +827,23 @@ static int ShouldStayInWaitMode() {
 }
 
 static int UpdateWaitMode() {
-	if (restrict_until == 0) {
+	if (_G(restrict_until) == 0) {
 		return RETURN_CONTINUE;
 	}
 
-	restrict_until = ShouldStayInWaitMode();
+	_G(restrict_until) = ShouldStayInWaitMode();
 	_G(our_eip) = 77;
 
-	if (restrict_until != 0) {
+	if (_G(restrict_until) != 0) {
 		return RETURN_CONTINUE;
 	}
 
-	auto was_disabled_for = user_disabled_for;
+	auto was_disabled_for = _G(user_disabled_for);
 
 	set_default_cursor();
 	guis_need_update = 1;
 	_GP(play).disabled_user_interface--;
-	user_disabled_for = 0;
+	_G(user_disabled_for) = 0;
 
 	switch (was_disabled_for) {
 		// case FOR_ANIMATION:
@@ -867,7 +855,7 @@ static int UpdateWaitMode() {
 		quit("err: for_script obsolete (v2.1 and earlier only)");
 		break;
 	default:
-		quit("Unknown user_disabled_for in end restrict_until");
+		quit("Unknown _G(user_disabled_for) in end _G(restrict_until)");
 	}
 
 	// we shouldn't get here.
@@ -900,9 +888,9 @@ static void SetupLoopParameters(int untilwhat, const void *udata) {
 		(cur_mode != CURS_WAIT))
 		set_mouse_cursor(CURS_WAIT);
 
-	restrict_until = untilwhat;
-	user_disabled_data = udata;
-	user_disabled_for = FOR_EXITLOOP;
+	_G(restrict_until) = untilwhat;
+	_G(user_disabled_data) = udata;
+	_G(user_disabled_for) = FOR_EXITLOOP;
 }
 
 // This function is called from lot of various functions
@@ -914,9 +902,9 @@ static void GameLoopUntilEvent(int untilwhat, const void *daaa) {
 	// this function can get called in a nested context, so
 	// remember the state of these vars in case a higher level
 	// call needs them
-	auto cached_restrict_until = restrict_until;
-	auto cached_user_disabled_data = user_disabled_data;
-	auto cached_user_disabled_for = user_disabled_for;
+	auto cached_restrict_until = _G(restrict_until);
+	auto cached_user_disabled_data = _G(user_disabled_data);
+	auto cached_user_disabled_for = _G(user_disabled_for);
 
 	SetupLoopParameters(untilwhat, daaa);
 	while (GameTick() == 0 && !_G(abort_engine)) {
@@ -924,9 +912,9 @@ static void GameLoopUntilEvent(int untilwhat, const void *daaa) {
 
 	_G(our_eip) = 78;
 
-	restrict_until = cached_restrict_until;
-	user_disabled_data = cached_user_disabled_data;
-	user_disabled_for = cached_user_disabled_for;
+	_G(restrict_until) = cached_restrict_until;
+	_G(user_disabled_data) = cached_user_disabled_data;
+	_G(user_disabled_for) = cached_user_disabled_for;
 }
 
 void GameLoopUntilValueIsZero(const char *value) {
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 5849caa2db..2ac9bfb349 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -547,6 +547,24 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup game_run globals
+	 * @{
+	 */
+
+	 // Following 3 parameters instruct the engine to run game loops until
+	 // certain condition is not fullfilled.
+	int _restrict_until = 0;
+	int _user_disabled_for = 0;
+	const void *_user_disabled_data = nullptr;
+
+	unsigned int _loopcounter = 0;
+	unsigned int _lastcounter = 0;
+	int _numEventsAtStartOfFunction = 0;
+	uint32 _t1 = 0; // timer for FPS
+
+	 /**@}*/
+
 	/**
 	 * \defgroup global_dialog globals
 	 * @{


Commit: 2d82d3257727ee3ba976f9ca33970db0ab3e9e57
    https://github.com/scummvm/scummvm/commit/2d82d3257727ee3ba976f9ca33970db0ab3e9e57
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:14:02-08:00

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

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/draw.h
    engines/ags/engine/ac/drawingsurface.cpp
    engines/ags/engine/ac/dynamicsprite.cpp
    engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_debug.cpp
    engines/ags/engine/ac/global_drawingsurface.cpp
    engines/ags/engine/ac/global_dynamicsprite.cpp
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/ac/global_object.cpp
    engines/ags/engine/ac/global_screen.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/mouse.cpp
    engines/ags/engine/ac/object.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/screen.cpp
    engines/ags/engine/ac/sprite.cpp
    engines/ags/engine/ac/system.cpp
    engines/ags/engine/ac/walkbehind.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/gui/cscidialog.cpp
    engines/ags/engine/gui/guidialog.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/engine_setup.cpp
    engines/ags/engine/main/graphics_mode.cpp
    engines/ags/engine/main/quit.cpp
    engines/ags/engine/main/update.cpp
    engines/ags/engine/platform/windows/acplwin.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/plugins/agsplugin.cpp


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 400ac29137..9afc2a0c28 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -80,8 +80,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 extern Bitmap *walkable_areas_temp;
-extern IGraphicsDriver *gfxDriver;
-extern Bitmap **actsps;
 
 // **** CHARACTER: FUNCTIONS ****
 
@@ -2071,12 +2069,12 @@ void CheckViewFrameForCharacter(CharacterInfo *chi) {
 }
 
 Bitmap *GetCharacterImage(int charid, int *isFlipped) {
-	if (!gfxDriver->HasAcceleratedTransform()) {
-		if (actsps[charid + MAX_ROOM_OBJECTS] != nullptr) {
-			// the actsps image is pre-flipped, so no longer register the image as such
+	if (!_G(gfxDriver)->HasAcceleratedTransform()) {
+		if (_G(actsps)[charid + MAX_ROOM_OBJECTS] != nullptr) {
+			// the _G(actsps) image is pre-flipped, so no longer register the image as such
 			if (isFlipped)
 				*isFlipped = 0;
-			return actsps[charid + MAX_ROOM_OBJECTS];
+			return _G(actsps)[charid + MAX_ROOM_OBJECTS];
 		}
 	}
 	CharacterInfo *chin = &_GP(game).chars[charid];
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 1c3c051910..15453b2b80 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -71,7 +71,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 extern int cur_mode, cur_cursor;
-extern IGraphicsDriver *gfxDriver;
 
 void Dialog_Start(ScriptDialog *sd) {
 	RunDialog(sd->id);
@@ -780,14 +779,14 @@ void DialogOptions::Redraw() {
 	if ((ddb != nullptr) &&
 	        ((ddb->GetWidth() != dirtywidth) ||
 	         (ddb->GetHeight() != dirtyheight))) {
-		gfxDriver->DestroyDDB(ddb);
+		_G(gfxDriver)->DestroyDDB(ddb);
 		ddb = nullptr;
 	}
 
 	if (ddb == nullptr)
-		ddb = gfxDriver->CreateDDBFromBitmap(subBitmap, options_surface_has_alpha, false);
+		ddb = _G(gfxDriver)->CreateDDBFromBitmap(subBitmap, options_surface_has_alpha, false);
 	else
-		gfxDriver->UpdateDDBFromBitmap(ddb, subBitmap, options_surface_has_alpha);
+		_G(gfxDriver)->UpdateDDBFromBitmap(ddb, subBitmap, options_surface_has_alpha);
 
 	if (runGameLoopsInBackground) {
 		render_graphics(ddb, dirtyx, dirtyy);
@@ -988,7 +987,7 @@ void DialogOptions::Close() {
 	}
 
 	if (ddb != nullptr)
-		gfxDriver->DestroyDDB(ddb);
+		_G(gfxDriver)->DestroyDDB(ddb);
 	delete subBitmap;
 
 	set_mouse_cursor(curswas);
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index b546bf7924..8acfaf4c2b 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -107,38 +107,6 @@ color palette[256];
 
 COLOR_MAP maincoltable;
 
-IGraphicsDriver *gfxDriver;
-IDriverDependantBitmap *blankImage = nullptr;
-IDriverDependantBitmap *blankSidebarImage = nullptr;
-IDriverDependantBitmap *debugConsole = nullptr;
-
-// actsps is used for temporary storage of the bitamp image
-// of the latest version of the sprite
-int actSpsCount = 0;
-Bitmap **actsps;
-IDriverDependantBitmap * *actspsbmp;
-// temporary cache of walk-behind for this actsps image
-Bitmap **actspswb;
-IDriverDependantBitmap * *actspswbbmp;
-CachedActSpsData *actspswbcache;
-
-bool current_background_is_dirty = false;
-
-// Room background sprite
-IDriverDependantBitmap *roomBackgroundBmp = nullptr;
-
-Bitmap **guibg = nullptr;
-IDriverDependantBitmap **guibgbmp = nullptr;
-
-
-Bitmap *debugConsoleBuffer = nullptr;
-
-// whether there are currently remnants of a DisplaySpeech
-bool screen_is_dirty = false;
-
-Bitmap *raw_saved_screen = nullptr;
-Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
-
 
 SpriteListEntry::SpriteListEntry()
 	: bmp(nullptr)
@@ -213,7 +181,7 @@ Bitmap *convert_32_to_32bgr(Bitmap *tempbl) {
 // could copy them to texture without additional changes.
 // AGS own OpenGL renderer tries to sync its behavior with the former one.
 //
-// TODO: make gfxDriver->GetCompatibleBitmapFormat describe all necessary
+// TODO: make _G(gfxDriver)->GetCompatibleBitmapFormat describe all necessary
 // conversions, so that we did not have to guess.
 //
 Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
@@ -264,7 +232,7 @@ Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
 }
 
 Bitmap *ReplaceBitmapWithSupportedFormat(Bitmap *bitmap) {
-	Bitmap *new_bitmap = GfxUtil::ConvertBitmap(bitmap, gfxDriver->GetCompatibleBitmapFormat(bitmap->GetColorDepth()));
+	Bitmap *new_bitmap = GfxUtil::ConvertBitmap(bitmap, _G(gfxDriver)->GetCompatibleBitmapFormat(bitmap->GetColorDepth()));
 	if (new_bitmap != bitmap)
 		delete bitmap;
 	return new_bitmap;
@@ -302,11 +270,11 @@ Bitmap *CopyScreenIntoBitmap(int width, int height, bool at_native_res) {
 	Bitmap *dst = new Bitmap(width, height, _GP(game).GetColorDepth());
 	GraphicResolution want_fmt;
 	// If the size and color depth are supported we may copy right into our bitmap
-	if (gfxDriver->GetCopyOfScreenIntoBitmap(dst, at_native_res, &want_fmt))
+	if (_G(gfxDriver)->GetCopyOfScreenIntoBitmap(dst, at_native_res, &want_fmt))
 		return dst;
 	// Otherwise we might need to copy between few bitmaps...
 	Bitmap *buf_screenfmt = new Bitmap(want_fmt.Width, want_fmt.Height, want_fmt.ColorDepth);
-	gfxDriver->GetCopyOfScreenIntoBitmap(buf_screenfmt, at_native_res);
+	_G(gfxDriver)->GetCopyOfScreenIntoBitmap(buf_screenfmt, at_native_res);
 	// If at least size matches then we may blit
 	if (dst->GetSize() == buf_screenfmt->GetSize()) {
 		dst->Blit(buf_screenfmt);
@@ -414,8 +382,8 @@ void create_blank_image(int coldepth) {
 		Bitmap *blank = BitmapHelper::CreateBitmap(16, 16, coldepth);
 		blank = ReplaceBitmapWithSupportedFormat(blank);
 		blank->Clear();
-		blankImage = gfxDriver->CreateDDBFromBitmap(blank, false, true);
-		blankSidebarImage = gfxDriver->CreateDDBFromBitmap(blank, false, true);
+		_G(blankImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
+		_G(blankSidebarImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
 		delete blank;
 /*	} catch (Ali3DException gfxException) {
 		quit((char *)gfxException._message);
@@ -423,12 +391,12 @@ void create_blank_image(int coldepth) {
 }
 
 void destroy_blank_image() {
-	if (blankImage)
-		gfxDriver->DestroyDDB(blankImage);
-	if (blankSidebarImage)
-		gfxDriver->DestroyDDB(blankSidebarImage);
-	blankImage = nullptr;
-	blankSidebarImage = nullptr;
+	if (_G(blankImage))
+		_G(gfxDriver)->DestroyDDB(_G(blankImage));
+	if (_G(blankSidebarImage))
+		_G(gfxDriver)->DestroyDDB(_G(blankSidebarImage));
+	_G(blankImage) = nullptr;
+	_G(blankSidebarImage) = nullptr;
 }
 
 int MakeColor(int color_index) {
@@ -438,7 +406,7 @@ int MakeColor(int color_index) {
 }
 
 void init_draw_method() {
-	if (gfxDriver->HasAcceleratedTransform()) {
+	if (_G(gfxDriver)->HasAcceleratedTransform()) {
 		walkBehindMethod = DrawAsSeparateSprite;
 		create_blank_image(_GP(game).GetColorDepth());
 	} else {
@@ -447,8 +415,8 @@ void init_draw_method() {
 
 	on_mainviewport_changed();
 	init_room_drawdata();
-	if (gfxDriver->UsesMemoryBackBuffer())
-		gfxDriver->GetMemoryBackBuffer()->Clear();
+	if (_G(gfxDriver)->UsesMemoryBackBuffer())
+		_G(gfxDriver)->GetMemoryBackBuffer()->Clear();
 }
 
 void dispose_draw_method() {
@@ -463,7 +431,7 @@ void dispose_room_drawdata() {
 }
 
 void on_mainviewport_changed() {
-	if (!gfxDriver->RequiresFullRedrawEachFrame()) {
+	if (!_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
 		init_invalid_regions(-1, _GP(play).GetMainViewport().GetSize(), RectWH(_GP(play).GetMainViewport().GetSize()));
 		if (_GP(game).GetGameRes().ExceedsByAny(_GP(play).GetMainViewport().GetSize()))
 			clear_letterbox_borders();
@@ -493,7 +461,7 @@ void prepare_roomview_frame(Viewport *view) {
 			int room_width = data_to_game_coord(_GP(thisroom).Width);
 			int room_height = data_to_game_coord(_GP(thisroom).Height);
 			Size alloc_sz = Size::Clamp(cam_sz * 2, Size(1, 1), Size(room_width, room_height));
-			camera_buffer.reset(new Bitmap(alloc_sz.Width, alloc_sz.Height, gfxDriver->GetMemoryBackBuffer()->GetColorDepth()));
+			camera_buffer.reset(new Bitmap(alloc_sz.Width, alloc_sz.Height, _G(gfxDriver)->GetMemoryBackBuffer()->GetColorDepth()));
 		}
 
 		if (!camera_frame || camera_frame->GetSize() != cam_sz) {
@@ -511,7 +479,7 @@ void sync_roomview(Viewport *view) {
 }
 
 void init_room_drawdata() {
-	if (gfxDriver->RequiresFullRedrawEachFrame())
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	// Make sure all frame buffers are created for software drawing
 	int view_count = _GP(play).GetRoomViewportCount();
@@ -521,7 +489,7 @@ void init_room_drawdata() {
 }
 
 void on_roomviewport_created(int index) {
-	if (!gfxDriver || gfxDriver->RequiresFullRedrawEachFrame())
+	if (!_G(gfxDriver) || _G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	if ((size_t)index < _GP(CameraDrawData).size())
 		return;
@@ -529,18 +497,18 @@ void on_roomviewport_created(int index) {
 }
 
 void on_roomviewport_deleted(int index) {
-	if (gfxDriver->RequiresFullRedrawEachFrame())
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	_GP(CameraDrawData).erase(_GP(CameraDrawData).begin() + index);
 	delete_invalid_regions(index);
 }
 
 void on_roomviewport_changed(Viewport *view) {
-	if (gfxDriver->RequiresFullRedrawEachFrame())
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	if (!view->IsVisible() || view->GetCamera() == nullptr)
 		return;
-	const bool off = !IsRectInsideRect(RectWH(gfxDriver->GetMemoryBackBuffer()->GetSize()), view->GetRect());
+	const bool off = !IsRectInsideRect(RectWH(_G(gfxDriver)->GetMemoryBackBuffer()->GetSize()), view->GetRect());
 	const bool off_changed = off != _GP(CameraDrawData)[view->GetID()].IsOffscreen;
 	_GP(CameraDrawData)[view->GetID()].IsOffscreen = off;
 	if (view->HasChangedSize())
@@ -550,11 +518,11 @@ void on_roomviewport_changed(Viewport *view) {
 	// TODO: don't have to do this all the time, perhaps do "dirty rect" method
 	// and only clear previous viewport location?
 	invalidate_screen();
-	gfxDriver->GetMemoryBackBuffer()->Clear();
+	_G(gfxDriver)->GetMemoryBackBuffer()->Clear();
 }
 
 void detect_roomviewport_overlaps(size_t z_index) {
-	if (gfxDriver->RequiresFullRedrawEachFrame())
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	// Find out if we overlap or are overlapped by anything;
 	const auto &viewports = _GP(play).GetRoomViewportsZOrdered();
@@ -578,7 +546,7 @@ void detect_roomviewport_overlaps(size_t z_index) {
 }
 
 void on_roomcamera_changed(Camera *cam) {
-	if (gfxDriver->RequiresFullRedrawEachFrame())
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
 	if (cam->HasChangedSize()) {
 		auto viewrefs = cam->GetLinkedViewports();
@@ -593,11 +561,11 @@ void on_roomcamera_changed(Camera *cam) {
 }
 
 void mark_screen_dirty() {
-	screen_is_dirty = true;
+	_G(screen_is_dirty) = true;
 }
 
 bool is_screen_dirty() {
-	return screen_is_dirty;
+	return _G(screen_is_dirty);
 }
 
 void invalidate_screen() {
@@ -619,7 +587,7 @@ void invalidate_sprite(int x1, int y1, IDriverDependantBitmap *pic, bool in_room
 }
 
 void mark_current_background_dirty() {
-	current_background_is_dirty = true;
+	_G(current_background_is_dirty) = true;
 }
 
 
@@ -631,22 +599,22 @@ void draw_and_invalidate_text(Bitmap *ds, int x1, int y1, int font, color_t text
 // Renders black borders for the legacy boxed game mode,
 // where whole game screen changes size between large and small rooms
 void render_black_borders() {
-	if (gfxDriver->UsesMemoryBackBuffer())
+	if (_G(gfxDriver)->UsesMemoryBackBuffer())
 		return;
 	{
-		gfxDriver->BeginSpriteBatch(RectWH(_GP(game).GetGameRes()), SpriteTransform());
+		_G(gfxDriver)->BeginSpriteBatch(RectWH(_GP(game).GetGameRes()), SpriteTransform());
 		const Rect &viewport = _GP(play).GetMainViewport();
 		if (viewport.Top > 0) {
 			// letterbox borders
-			blankImage->SetStretch(_GP(game).GetGameRes().Width, viewport.Top, false);
-			gfxDriver->DrawSprite(0, 0, blankImage);
-			gfxDriver->DrawSprite(0, viewport.Bottom + 1, blankImage);
+			_G(blankImage)->SetStretch(_GP(game).GetGameRes().Width, viewport.Top, false);
+			_G(gfxDriver)->DrawSprite(0, 0, _G(blankImage));
+			_G(gfxDriver)->DrawSprite(0, viewport.Bottom + 1, _G(blankImage));
 		}
 		if (viewport.Left > 0) {
 			// sidebar borders for widescreen
-			blankSidebarImage->SetStretch(viewport.Left, viewport.GetHeight(), false);
-			gfxDriver->DrawSprite(0, 0, blankSidebarImage);
-			gfxDriver->DrawSprite(viewport.Right + 1, 0, blankSidebarImage);
+			_G(blankSidebarImage)->SetStretch(viewport.Left, viewport.GetHeight(), false);
+			_G(gfxDriver)->DrawSprite(0, 0, _G(blankSidebarImage));
+			_G(gfxDriver)->DrawSprite(viewport.Right + 1, 0, _G(blankSidebarImage));
 		}
 	}
 }
@@ -655,23 +623,23 @@ void render_black_borders() {
 void render_to_screen() {
 	// Stage: final plugin callback (still drawn on game screen
 	if (pl_any_want_hook(AGSE_FINALSCREENDRAW)) {
-		gfxDriver->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
-		gfxDriver->DrawSprite(AGSE_FINALSCREENDRAW, 0, nullptr);
+		_G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
+		_G(gfxDriver)->DrawSprite(AGSE_FINALSCREENDRAW, 0, nullptr);
 	}
 	// Stage: engine overlay
 	construct_engine_overlay();
 
 	// only vsync in full screen mode, it makes things worse in a window
-	gfxDriver->EnableVsyncBeforeRender((_GP(scsystem).vsync > 0) && (!_GP(scsystem).windowed));
+	_G(gfxDriver)->EnableVsyncBeforeRender((_GP(scsystem).vsync > 0) && (!_GP(scsystem).windowed));
 
 	bool succeeded = false;
 	while (!succeeded) {
 //		try {
 			// For software renderer, need to blacken upper part of the game frame when shaking screen moves image down
 			const Rect &viewport = _GP(play).GetMainViewport();
-			if (_GP(play).shake_screen_yoff > 0 && !gfxDriver->RequiresFullRedrawEachFrame())
-				gfxDriver->ClearRectangle(viewport.Left, viewport.Top, viewport.GetWidth() - 1, _GP(play).shake_screen_yoff, nullptr);
-			gfxDriver->Render(0, _GP(play).shake_screen_yoff, (GlobalFlipType)_GP(play).screen_flipped);
+			if (_GP(play).shake_screen_yoff > 0 && !_G(gfxDriver)->RequiresFullRedrawEachFrame())
+				_G(gfxDriver)->ClearRectangle(viewport.Left, viewport.Top, viewport.GetWidth() - 1, _GP(play).shake_screen_yoff, nullptr);
+			_G(gfxDriver)->Render(0, _GP(play).shake_screen_yoff, (GlobalFlipType)_GP(play).screen_flipped);
 
 #if AGS_PLATFORM_OS_ANDROID
 			if (_GP(game).color_depth == 1)
@@ -691,8 +659,8 @@ void render_to_screen() {
 // Blanks out borders around main viewport in case it became smaller (e.g. after loading another room)
 void clear_letterbox_borders() {
 	const Rect &viewport = _GP(play).GetMainViewport();
-	gfxDriver->ClearRectangle(0, 0, _GP(game).GetGameRes().Width - 1, viewport.Top - 1, nullptr);
-	gfxDriver->ClearRectangle(0, viewport.Bottom + 1, _GP(game).GetGameRes().Width - 1, _GP(game).GetGameRes().Height - 1, nullptr);
+	_G(gfxDriver)->ClearRectangle(0, 0, _GP(game).GetGameRes().Width - 1, viewport.Top - 1, nullptr);
+	_G(gfxDriver)->ClearRectangle(0, viewport.Bottom + 1, _GP(game).GetGameRes().Width - 1, _GP(game).GetGameRes().Height - 1, nullptr);
 }
 
 void draw_game_screen_callback() {
@@ -743,18 +711,18 @@ IDriverDependantBitmap *recycle_ddb_bitmap(IDriverDependantBitmap *bimp, Bitmap
 		// same colour depth, width and height -> reuse
 		if (((bimp->GetColorDepth() + 1) / 8 == source->GetBPP()) &&
 		        (bimp->GetWidth() == source->GetWidth()) && (bimp->GetHeight() == source->GetHeight())) {
-			gfxDriver->UpdateDDBFromBitmap(bimp, source, hasAlpha);
+			_G(gfxDriver)->UpdateDDBFromBitmap(bimp, source, hasAlpha);
 			return bimp;
 		}
 
-		gfxDriver->DestroyDDB(bimp);
+		_G(gfxDriver)->DestroyDDB(bimp);
 	}
-	bimp = gfxDriver->CreateDDBFromBitmap(source, hasAlpha, opaque);
+	bimp = _G(gfxDriver)->CreateDDBFromBitmap(source, hasAlpha, opaque);
 	return bimp;
 }
 
 void invalidate_cached_walkbehinds() {
-	memset(&actspswbcache[0], 0, sizeof(CachedActSpsData) * actSpsCount);
+	memset(&_G(actspswbcache)[0], 0, sizeof(CachedActSpsData) * _G(actSpsCount));
 }
 
 // sort_out_walk_behinds: modifies the supplied sprite by overwriting parts
@@ -872,26 +840,26 @@ void sort_out_char_sprite_walk_behind(int actspsIndex, int xx, int yy, int basel
 	if (noWalkBehindsAtAll)
 		return;
 
-	if ((!actspswbcache[actspsIndex].valid) ||
-	        (actspswbcache[actspsIndex].xWas != xx) ||
-	        (actspswbcache[actspsIndex].yWas != yy) ||
-	        (actspswbcache[actspsIndex].baselineWas != basel)) {
-		actspswb[actspsIndex] = recycle_bitmap(actspswb[actspsIndex], _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth(), width, height, true);
-		Bitmap *wbSprite = actspswb[actspsIndex];
-
-		actspswbcache[actspsIndex].isWalkBehindHere = sort_out_walk_behinds(wbSprite, xx, yy, basel, _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), actsps[actspsIndex], zoom);
-		actspswbcache[actspsIndex].xWas = xx;
-		actspswbcache[actspsIndex].yWas = yy;
-		actspswbcache[actspsIndex].baselineWas = basel;
-		actspswbcache[actspsIndex].valid = 1;
-
-		if (actspswbcache[actspsIndex].isWalkBehindHere) {
-			actspswbbmp[actspsIndex] = recycle_ddb_bitmap(actspswbbmp[actspsIndex], actspswb[actspsIndex], false);
+	if ((!_G(actspswbcache)[actspsIndex].valid) ||
+	        (_G(actspswbcache)[actspsIndex].xWas != xx) ||
+	        (_G(actspswbcache)[actspsIndex].yWas != yy) ||
+	        (_G(actspswbcache)[actspsIndex].baselineWas != basel)) {
+		_G(actspswb)[actspsIndex] = recycle_bitmap(_G(actspswb)[actspsIndex], _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth(), width, height, true);
+		Bitmap *wbSprite = _G(actspswb)[actspsIndex];
+
+		_G(actspswbcache)[actspsIndex].isWalkBehindHere = sort_out_walk_behinds(wbSprite, xx, yy, basel, _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), _G(actsps)[actspsIndex], zoom);
+		_G(actspswbcache)[actspsIndex].xWas = xx;
+		_G(actspswbcache)[actspsIndex].yWas = yy;
+		_G(actspswbcache)[actspsIndex].baselineWas = basel;
+		_G(actspswbcache)[actspsIndex].valid = 1;
+
+		if (_G(actspswbcache)[actspsIndex].isWalkBehindHere) {
+			_G(actspswbbmp)[actspsIndex] = recycle_ddb_bitmap(_G(actspswbbmp)[actspsIndex], _G(actspswb)[actspsIndex], false);
 		}
 	}
 
-	if (actspswbcache[actspsIndex].isWalkBehindHere) {
-		add_to_sprite_list(actspswbbmp[actspsIndex], xx, yy, basel, 0, -1, true);
+	if (_G(actspswbcache)[actspsIndex].isWalkBehindHere) {
+		add_to_sprite_list(_G(actspswbbmp)[actspsIndex], xx, yy, basel, 0, -1, true);
 	}
 }
 
@@ -1123,7 +1091,7 @@ void get_local_tint(int xpp, int ypp, int nolight,
 
 
 
-// Applies the specified RGB Tint or Light Level to the actsps
+// Applies the specified RGB Tint or Light Level to the _G(actsps)
 // sprite indexed with actspsindex
 void apply_tint_or_light(int actspsindex, int light_level,
                          int tint_amount, int tint_red, int tint_green,
@@ -1138,7 +1106,7 @@ void apply_tint_or_light(int actspsindex, int light_level,
 	}
 
 // we can only do tint/light if the colour depths match
-	if (_GP(game).GetColorDepth() == actsps[actspsindex]->GetColorDepth()) {
+	if (_GP(game).GetColorDepth() == _G(actsps)[actspsindex]->GetColorDepth()) {
 		Bitmap *oldwas;
 		// if the caller supplied a source bitmap, ->Blit from it
 		// (used as a speed optimisation where possible)
@@ -1146,10 +1114,10 @@ void apply_tint_or_light(int actspsindex, int light_level,
 			oldwas = blitFrom;
 		// otherwise, make a new target bmp
 		else {
-			oldwas = actsps[actspsindex];
-			actsps[actspsindex] = BitmapHelper::CreateBitmap(oldwas->GetWidth(), oldwas->GetHeight(), coldept);
+			oldwas = _G(actsps)[actspsindex];
+			_G(actsps)[actspsindex] = BitmapHelper::CreateBitmap(oldwas->GetWidth(), oldwas->GetHeight(), coldept);
 		}
-		Bitmap *active_spr = actsps[actspsindex];
+		Bitmap *active_spr = _G(actsps)[actspsindex];
 
 		if (tint_amount) {
 			// It is an RGB tint
@@ -1183,15 +1151,15 @@ void apply_tint_or_light(int actspsindex, int light_level,
 	} else if (blitFrom) {
 		// sprite colour depth != game colour depth, so don't try and tint
 		// but we do need to do something, so copy the source
-		Bitmap *active_spr = actsps[actspsindex];
+		Bitmap *active_spr = _G(actsps)[actspsindex];
 		active_spr->Blit(blitFrom, 0, 0, 0, 0, active_spr->GetWidth(), active_spr->GetHeight());
 	}
 
 }
 
-// Draws the specified 'sppic' sprite onto actsps[useindx] at the
+// Draws the specified 'sppic' sprite onto _G(actsps)[useindx] at the
 // specified width and height, and flips the sprite if necessary.
-// Returns 1 if something was drawn to actsps; returns 0 if no
+// Returns 1 if something was drawn to _G(actsps); returns 0 if no
 // scaling or stretching was required, in which case nothing was done
 int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
                           int sppic, int newwidth, int newheight,
@@ -1200,8 +1168,8 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 	int actsps_used = 1;
 
 	// create and blank out the new sprite
-	actsps[useindx] = recycle_bitmap(actsps[useindx], coldept, newwidth, newheight, true);
-	Bitmap *active_spr = actsps[useindx];
+	_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, newwidth, newheight, true);
+	Bitmap *active_spr = _G(actsps)[useindx];
 
 	if (zoom_level != 100) {
 		// Scaled character
@@ -1216,7 +1184,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 
 		if (isMirrored) {
 			Bitmap *tempspr = BitmapHelper::CreateBitmap(newwidth, newheight, coldept);
-			tempspr->Fill(actsps[useindx]->GetMaskColor());
+			tempspr->Fill(_G(actsps)[useindx]->GetMaskColor());
 			if ((IS_ANTIALIAS_SPRITES) && ((_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) == 0))
 				tempspr->AAStretchBlt(_GP(spriteset)[sppic], RectWH(0, 0, newwidth, newheight), Shared::kBitmap_Transparency);
 			else
@@ -1237,17 +1205,17 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 		aa_mode |= AA_HFLIP;
 
 		aa_set_mode(aa_mode);
-		->AAStretchBlt(actsps[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
+		->AAStretchBlt(_G(actsps)[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
 		}
 		else if (isMirrored) {
 		Bitmap *tempspr = BitmapHelper::CreateBitmap_ (coldept, newwidth, newheight);
-		->Clear (tempspr, ->GetMaskColor(actsps[useindx]));
+		->Clear (tempspr, ->GetMaskColor(_G(actsps)[useindx]));
 		->StretchBlt (tempspr, _GP(spriteset)[sppic], 0, 0, newwidth, newheight);
-		->FlipBlt(Shared::kBitmap_HFlip, (actsps[useindx], tempspr, 0, 0);
+		->FlipBlt(Shared::kBitmap_HFlip, (_G(actsps)[useindx], tempspr, 0, 0);
 		wfreeblock (tempspr);
 		}
 		else
-		->StretchBlt(actsps[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
+		->StretchBlt(_G(actsps)[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
 		*/
 		if (_G(in_new_room))
 			unselect_palette();
@@ -1261,7 +1229,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 			active_spr->FlipBlt(_GP(spriteset)[sppic], 0, 0, Shared::kBitmap_HFlip);
 		else
 			actsps_used = 0;
-		//->Blit (_GP(spriteset)[sppic], actsps[useindx], 0, 0, 0, 0, actsps[useindx]->GetWidth(), actsps[useindx]->GetHeight());
+		//->Blit (_GP(spriteset)[sppic], _G(actsps)[useindx], 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
 	}
 
 	return actsps_used;
@@ -1269,12 +1237,12 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 
 
 
-// create the actsps[aa] image with the object drawn correctly
-// returns 1 if nothing at all has changed and actsps is still
+// create the _G(actsps)[aa] image with the object drawn correctly
+// returns 1 if nothing at all has changed and _G(actsps) is still
 // intact from last time; 0 otherwise
 int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware) {
 	int useindx = aa;
-	bool hardwareAccelerated = !alwaysUseSoftware && gfxDriver->HasAcceleratedTransform();
+	bool hardwareAccelerated = !alwaysUseSoftware && _G(gfxDriver)->HasAcceleratedTransform();
 
 	if (_GP(spriteset)[_G(objs)[aa].num] == nullptr)
 		quitprintf("There was an error drawing object %d. Its current sprite, %d, is invalid.", aa, _G(objs)[aa].num);
@@ -1347,7 +1315,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 	        (walkBehindMethod != DrawOverCharSprite) &&
 	        (_G(objcache)[aa].image != nullptr) &&
 	        (_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
-	        (actsps[useindx] != nullptr)) {
+	        (_G(actsps)[useindx] != nullptr)) {
 		// HW acceleration
 		_G(objcache)[aa].tintamntwas = tint_level;
 		_G(objcache)[aa].tintredwas = tint_red;
@@ -1361,7 +1329,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 		return 1;
 	}
 
-	if ((!hardwareAccelerated) && (gfxDriver->HasAcceleratedTransform())) {
+	if ((!hardwareAccelerated) && (_G(gfxDriver)->HasAcceleratedTransform())) {
 		// They want to draw it in software mode with the D3D driver,
 		// so force a redraw
 		_G(objcache)[aa].sppic = -389538;
@@ -1380,17 +1348,17 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 	        (_G(objcache)[aa].mirroredWas == isMirrored)) {
 		// the image is the same, we can use it cached!
 		if ((walkBehindMethod != DrawOverCharSprite) &&
-		        (actsps[useindx] != nullptr))
+		        (_G(actsps)[useindx] != nullptr))
 			return 1;
 		// Check if the X & Y co-ords are the same, too -- if so, there
 		// is scope for further optimisations
 		if ((_G(objcache)[aa].xwas == _G(objs)[aa].x) &&
 		        (_G(objcache)[aa].ywas == _G(objs)[aa].y) &&
-		        (actsps[useindx] != nullptr) &&
+		        (_G(actsps)[useindx] != nullptr) &&
 		        (walk_behind_baselines_changed == 0))
 			return 1;
-		actsps[useindx] = recycle_bitmap(actsps[useindx], coldept, sprwidth, sprheight);
-		actsps[useindx]->Blit(_G(objcache)[aa].image, 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
+		_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, sprwidth, sprheight);
+		_G(actsps)[useindx]->Blit(_G(objcache)[aa].image, 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
 		return 0;
 	}
 
@@ -1402,8 +1370,8 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 		actspsUsed = scale_and_flip_sprite(useindx, coldept, zoom_level,
 		                                   _G(objs)[aa].num, sprwidth, sprheight, isMirrored);
 	} else {
-		// ensure actsps exists
-		actsps[useindx] = recycle_bitmap(actsps[useindx], coldept, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
+		// ensure _G(actsps) exists
+		_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
 	}
 
 	// direct read from source bitmap, where possible
@@ -1418,13 +1386,13 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 		                    tint_green, tint_blue, tint_light, coldept,
 		                    comeFrom);
 	} else if (!actspsUsed) {
-		actsps[useindx]->Blit(_GP(spriteset)[_G(objs)[aa].num], 0, 0, 0, 0, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
+		_G(actsps)[useindx]->Blit(_GP(spriteset)[_G(objs)[aa].num], 0, 0, 0, 0, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
 	}
 
 	// Re-use the bitmap if it's the same size
 	_G(objcache)[aa].image = recycle_bitmap(_G(objcache)[aa].image, coldept, sprwidth, sprheight);
 	// Create the cached image and store it
-	_G(objcache)[aa].image->Blit(actsps[useindx], 0, 0, 0, 0, sprwidth, sprheight);
+	_G(objcache)[aa].image->Blit(_G(actsps)[useindx], 0, 0, 0, 0, sprwidth, sprheight);
 	_G(objcache)[aa].sppic = _G(objs)[aa].num;
 	_G(objcache)[aa].tintamntwas = tint_level;
 	_G(objcache)[aa].tintredwas = tint_red;
@@ -1471,36 +1439,36 @@ void prepare_objects_for_drawing() {
 		} else if (walkBehindMethod == DrawAsSeparateCharSprite) {
 			sort_out_char_sprite_walk_behind(useindx, atxp, atyp, usebasel, _G(objs)[aa].zoom, _G(objs)[aa].last_width, _G(objs)[aa].last_height);
 		} else if ((!actspsIntact) && (walkBehindMethod == DrawOverCharSprite)) {
-			sort_out_walk_behinds(actsps[useindx], atxp, atyp, usebasel);
+			sort_out_walk_behinds(_G(actsps)[useindx], atxp, atyp, usebasel);
 		}
 
-		if ((!actspsIntact) || (actspsbmp[useindx] == nullptr)) {
+		if ((!actspsIntact) || (_G(actspsbmp)[useindx] == nullptr)) {
 			bool hasAlpha = (_GP(game).SpriteInfos[_G(objs)[aa].num].Flags & SPF_ALPHACHANNEL) != 0;
 
-			if (actspsbmp[useindx] != nullptr)
-				gfxDriver->DestroyDDB(actspsbmp[useindx]);
-			actspsbmp[useindx] = gfxDriver->CreateDDBFromBitmap(actsps[useindx], hasAlpha);
+			if (_G(actspsbmp)[useindx] != nullptr)
+				_G(gfxDriver)->DestroyDDB(_G(actspsbmp)[useindx]);
+			_G(actspsbmp)[useindx] = _G(gfxDriver)->CreateDDBFromBitmap(_G(actsps)[useindx], hasAlpha);
 		}
 
-		if (gfxDriver->HasAcceleratedTransform()) {
-			actspsbmp[useindx]->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
-			actspsbmp[useindx]->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
-			actspsbmp[useindx]->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
+		if (_G(gfxDriver)->HasAcceleratedTransform()) {
+			_G(actspsbmp)[useindx]->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
+			_G(actspsbmp)[useindx]->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
+			_G(actspsbmp)[useindx]->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
 
 			if (_G(objcache)[aa].tintamntwas > 0) {
 				if (_G(objcache)[aa].tintlightwas == 0)  // luminance of 0 -- pass 1 to enable
-					actspsbmp[useindx]->SetLightLevel(1);
+					_G(actspsbmp)[useindx]->SetLightLevel(1);
 				else if (_G(objcache)[aa].tintlightwas < 250)
-					actspsbmp[useindx]->SetLightLevel(_G(objcache)[aa].tintlightwas);
+					_G(actspsbmp)[useindx]->SetLightLevel(_G(objcache)[aa].tintlightwas);
 				else
-					actspsbmp[useindx]->SetLightLevel(0);
+					_G(actspsbmp)[useindx]->SetLightLevel(0);
 			} else if (_G(objcache)[aa].lightlevwas != 0)
-				actspsbmp[useindx]->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
+				_G(actspsbmp)[useindx]->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
 			else
-				actspsbmp[useindx]->SetLightLevel(0);
+				_G(actspsbmp)[useindx]->SetLightLevel(0);
 		}
 
-		add_to_sprite_list(actspsbmp[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, _G(objs)[aa].num);
+		add_to_sprite_list(_G(actspsbmp)[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, _G(objs)[aa].num);
 	}
 }
 
@@ -1649,14 +1617,14 @@ void prepare_characters_for_drawing() {
 		        (_G(charcache)[aa].tintlightwas == tint_light) &&
 		        (_G(charcache)[aa].lightlevwas == light_level)) {
 			if (walkBehindMethod == DrawOverCharSprite) {
-				actsps[useindx] = recycle_bitmap(actsps[useindx], _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
-				actsps[useindx]->Blit(_G(charcache)[aa].image, 0, 0, 0, 0, actsps[useindx]->GetWidth(), actsps[useindx]->GetHeight());
+				_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
+				_G(actsps)[useindx]->Blit(_G(charcache)[aa].image, 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
 			} else {
 				usingCachedImage = true;
 			}
 		} else if ((_G(charcache)[aa].inUse) &&
 		           (_G(charcache)[aa].sppic == specialpic) &&
-		           (gfxDriver->HasAcceleratedTransform())) {
+		           (_G(gfxDriver)->HasAcceleratedTransform())) {
 			usingCachedImage = true;
 		} else if (_G(charcache)[aa].inUse) {
 			//destroy_bitmap (_G(charcache)[aa].image);
@@ -1700,22 +1668,22 @@ void prepare_characters_for_drawing() {
 		// If cache needs to be re-drawn
 		if (!_G(charcache)[aa].inUse) {
 
-			// create the base sprite in actsps[useindx], which will
+			// create the base sprite in _G(actsps)[useindx], which will
 			// be scaled and/or flipped, as appropriate
 			int actspsUsed = 0;
-			if (!gfxDriver->HasAcceleratedTransform()) {
+			if (!_G(gfxDriver)->HasAcceleratedTransform()) {
 				actspsUsed = scale_and_flip_sprite(
 				                 useindx, coldept, zoom_level, sppic,
 				                 newwidth, newheight, isMirrored);
 			} else {
-				// ensure actsps exists
-				actsps[useindx] = recycle_bitmap(actsps[useindx], coldept, _GP(game).SpriteInfos[sppic].Width, _GP(game).SpriteInfos[sppic].Height);
+				// ensure _G(actsps) exists
+				_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, _GP(game).SpriteInfos[sppic].Width, _GP(game).SpriteInfos[sppic].Height);
 			}
 
 			_G(our_eip) = 335;
 
 			if (((light_level != 0) || (tint_amount != 0)) &&
-			        (!gfxDriver->HasAcceleratedTransform())) {
+			        (!_G(gfxDriver)->HasAcceleratedTransform())) {
 				// apply the lightening or tinting
 				Bitmap *comeFrom = nullptr;
 				// if possible, direct read from the source image
@@ -1727,14 +1695,14 @@ void prepare_characters_for_drawing() {
 				                    comeFrom);
 			} else if (!actspsUsed) {
 				// no scaling, flipping or tinting was done, so just blit it normally
-				actsps[useindx]->Blit(_GP(spriteset)[sppic], 0, 0, 0, 0, actsps[useindx]->GetWidth(), actsps[useindx]->GetHeight());
+				_G(actsps)[useindx]->Blit(_GP(spriteset)[sppic], 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
 			}
 
 			// update the character cache with the new image
 			_G(charcache)[aa].inUse = 1;
-			//_G(charcache)[aa].image = BitmapHelper::CreateBitmap_ (coldept, actsps[useindx]->GetWidth(), actsps[useindx]->GetHeight());
-			_G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, actsps[useindx]->GetWidth(), actsps[useindx]->GetHeight());
-			_G(charcache)[aa].image->Blit(actsps[useindx], 0, 0, 0, 0, actsps[useindx]->GetWidth(), actsps[useindx]->GetHeight());
+			//_G(charcache)[aa].image = BitmapHelper::CreateBitmap_ (coldept, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
+			_G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
+			_G(charcache)[aa].image->Blit(_G(actsps)[useindx], 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
 
 		} // end if !cache.inUse
 
@@ -1753,31 +1721,31 @@ void prepare_characters_for_drawing() {
 		} else if (walkBehindMethod == DrawAsSeparateCharSprite) {
 			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);
+			sort_out_walk_behinds(_G(actsps)[useindx], bgX, bgY, usebasel);
 		}
 
-		if ((!usingCachedImage) || (actspsbmp[useindx] == nullptr)) {
+		if ((!usingCachedImage) || (_G(actspsbmp)[useindx] == nullptr)) {
 			bool hasAlpha = (_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) != 0;
 
-			actspsbmp[useindx] = recycle_ddb_bitmap(actspsbmp[useindx], actsps[useindx], hasAlpha);
+			_G(actspsbmp)[useindx] = recycle_ddb_bitmap(_G(actspsbmp)[useindx], _G(actsps)[useindx], hasAlpha);
 		}
 
-		if (gfxDriver->HasAcceleratedTransform()) {
-			actspsbmp[useindx]->SetStretch(newwidth, newheight);
-			actspsbmp[useindx]->SetFlippedLeftRight(isMirrored != 0);
-			actspsbmp[useindx]->SetTint(tint_red, tint_green, tint_blue, (tint_amount * 256) / 100);
+		if (_G(gfxDriver)->HasAcceleratedTransform()) {
+			_G(actspsbmp)[useindx]->SetStretch(newwidth, newheight);
+			_G(actspsbmp)[useindx]->SetFlippedLeftRight(isMirrored != 0);
+			_G(actspsbmp)[useindx]->SetTint(tint_red, tint_green, tint_blue, (tint_amount * 256) / 100);
 
 			if (tint_amount != 0) {
 				if (tint_light == 0) // tint with 0 luminance, pass as 1 instead
-					actspsbmp[useindx]->SetLightLevel(1);
+					_G(actspsbmp)[useindx]->SetLightLevel(1);
 				else if (tint_light < 250)
-					actspsbmp[useindx]->SetLightLevel(tint_light);
+					_G(actspsbmp)[useindx]->SetLightLevel(tint_light);
 				else
-					actspsbmp[useindx]->SetLightLevel(0);
+					_G(actspsbmp)[useindx]->SetLightLevel(0);
 			} else if (light_level != 0)
-				actspsbmp[useindx]->SetLightLevel((light_level * 25) / 10 + 256);
+				_G(actspsbmp)[useindx]->SetLightLevel((light_level * 25) / 10 + 256);
 			else
-				actspsbmp[useindx]->SetLightLevel(0);
+				_G(actspsbmp)[useindx]->SetLightLevel(0);
 
 		}
 
@@ -1786,7 +1754,7 @@ void prepare_characters_for_drawing() {
 		chin->actx = atxp;
 		chin->acty = atyp;
 
-		add_to_sprite_list(actspsbmp[useindx], bgX, bgY, usebasel, chin->transparency, sppic);
+		add_to_sprite_list(_G(actspsbmp)[useindx], bgX, bgY, usebasel, chin->transparency, sppic);
 	}
 }
 
@@ -1796,22 +1764,22 @@ void prepare_room_sprites() {
 	// Background sprite is required for the non-software renderers always,
 	// and for software renderer in case there are overlapping viewports.
 	// Note that software DDB is just a tiny wrapper around bitmap, so overhead is negligible.
-	if (roomBackgroundBmp == nullptr) {
+	if (_G(roomBackgroundBmp) == nullptr) {
 		update_polled_stuff_if_runtime();
-		roomBackgroundBmp = gfxDriver->CreateDDBFromBitmap(_GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), false, true);
-	} else if (current_background_is_dirty) {
+		_G(roomBackgroundBmp) = _G(gfxDriver)->CreateDDBFromBitmap(_GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), false, true);
+	} else if (_G(current_background_is_dirty)) {
 		update_polled_stuff_if_runtime();
-		gfxDriver->UpdateDDBFromBitmap(roomBackgroundBmp, _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), false);
+		_G(gfxDriver)->UpdateDDBFromBitmap(_G(roomBackgroundBmp), _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), false);
 	}
-	if (gfxDriver->RequiresFullRedrawEachFrame()) {
-		if (current_background_is_dirty || walkBehindsCachedForBgNum != _GP(play).bg_frame) {
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
+		if (_G(current_background_is_dirty) || walkBehindsCachedForBgNum != _GP(play).bg_frame) {
 			if (walkBehindMethod == DrawAsSeparateSprite) {
 				update_walk_behind_images();
 			}
 		}
-		add_thing_to_draw(roomBackgroundBmp, 0, 0, 0, false);
+		add_thing_to_draw(_G(roomBackgroundBmp), 0, 0, 0, false);
 	}
-	current_background_is_dirty = false; // Note this is only place where this flag is checked
+	_G(current_background_is_dirty) = false; // Note this is only place where this flag is checked
 
 	clear_sprite_list();
 
@@ -1829,9 +1797,9 @@ void prepare_room_sprites() {
 
 // Draws the black surface behind (or rather between) the room viewports
 void draw_preroom_background() {
-	if (gfxDriver->RequiresFullRedrawEachFrame())
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame())
 		return;
-	update_black_invreg_and_reset(gfxDriver->GetMemoryBackBuffer());
+	update_black_invreg_and_reset(_G(gfxDriver)->GetMemoryBackBuffer());
 }
 
 // Draws the room background on the given surface.
@@ -1851,7 +1819,7 @@ PBitmap draw_room_background(Viewport *view, const SpriteTransform &room_trans)
 	// 32-bit virtual screen).
 	// Also see comment to ALSoftwareGraphicsDriver::RenderToBackBuffer().
 	const int view_index = view->GetID();
-	Bitmap *ds = gfxDriver->GetMemoryBackBuffer();
+	Bitmap *ds = _G(gfxDriver)->GetMemoryBackBuffer();
 	// If separate bitmap was prepared for this view/camera pair then use it, draw untransformed
 	// and blit transformed whole surface later.
 	const bool draw_to_camsurf = _GP(CameraDrawData)[view_index].Frame != nullptr;
@@ -1909,11 +1877,11 @@ void draw_fps(const Rect &viewport) {
 	wouttext_outline(fpsDisplay, viewport.GetWidth() / 2, 1, font, text_color, loop_buffer);
 
 	if (ddb)
-		gfxDriver->UpdateDDBFromBitmap(ddb, fpsDisplay, false);
+		_G(gfxDriver)->UpdateDDBFromBitmap(ddb, fpsDisplay, false);
 	else
-		ddb = gfxDriver->CreateDDBFromBitmap(fpsDisplay, false);
+		ddb = _G(gfxDriver)->CreateDDBFromBitmap(fpsDisplay, false);
 	int yp = viewport.GetHeight() - fpsDisplay->GetHeight();
-	gfxDriver->DrawSprite(1, yp, ddb);
+	_G(gfxDriver)->DrawSprite(1, yp, ddb);
 	invalidate_sprite(1, yp, ddb, false);
 }
 
@@ -1952,14 +1920,14 @@ void draw_gui_and_overlays() {
 			for (aa = 0; aa < _GP(game).numgui; aa++) {
 				if (!_GP(guis)[aa].IsDisplayed()) continue;
 
-				if (guibg[aa] == nullptr)
+				if (_G(guibg)[aa] == nullptr)
 					recreate_guibg_image(&_GP(guis)[aa]);
 
 				_G(eip_guinum) = aa;
 				_G(our_eip) = 370;
-				guibg[aa]->ClearTransparent();
+				_G(guibg)[aa]->ClearTransparent();
 				_G(our_eip) = 372;
-				_GP(guis)[aa].DrawAt(guibg[aa], 0, 0);
+				_GP(guis)[aa].DrawAt(_G(guibg)[aa], 0, 0);
 				_G(our_eip) = 373;
 
 				bool isAlpha = false;
@@ -1968,14 +1936,14 @@ void draw_gui_and_overlays() {
 
 					if ((_GP(game).options[OPT_NEWGUIALPHA] == kGuiAlphaRender_Legacy) && (_GP(guis)[aa].BgImage > 0)) {
 						// old-style (pre-3.0.2) GUI alpha rendering
-						repair_alpha_channel(guibg[aa], _GP(spriteset)[_GP(guis)[aa].BgImage]);
+						repair_alpha_channel(_G(guibg)[aa], _GP(spriteset)[_GP(guis)[aa].BgImage]);
 					}
 				}
 
-				if (guibgbmp[aa] != nullptr) {
-					gfxDriver->UpdateDDBFromBitmap(guibgbmp[aa], guibg[aa], isAlpha);
+				if (_G(guibgbmp)[aa] != nullptr) {
+					_G(gfxDriver)->UpdateDDBFromBitmap(_G(guibgbmp)[aa], _G(guibg)[aa], isAlpha);
 				} else {
-					guibgbmp[aa] = gfxDriver->CreateDDBFromBitmap(guibg[aa], isAlpha);
+					_G(guibgbmp)[aa] = _G(gfxDriver)->CreateDDBFromBitmap(_G(guibg)[aa], isAlpha);
 				}
 				_G(our_eip) = 374;
 			}
@@ -1992,7 +1960,7 @@ void draw_gui_and_overlays() {
 			        (_GP(guis)[aa].PopupStyle != kGUIPopupNoAutoRemove))
 				continue;
 
-			add_thing_to_draw(guibgbmp[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency, _GP(guis)[aa].HasAlphaChannel());
+			add_thing_to_draw(_G(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency, _GP(guis)[aa].HasAlphaChannel());
 
 			// only poll if the interface is enabled (mouseovers should not
 			// work while in Wait state)
@@ -2035,10 +2003,10 @@ void put_sprite_list_on_screen(bool in_room) {
 				thisThing->bmp->SetTransparency(thisThing->transparent);
 			}
 
-			gfxDriver->DrawSprite(thisThing->x, thisThing->y, thisThing->bmp);
+			_G(gfxDriver)->DrawSprite(thisThing->x, thisThing->y, thisThing->bmp);
 		} else if (thisThing->transparent == TRANS_RUN_PLUGIN) {
 			// meta entry to run the plugin hook
-			gfxDriver->DrawSprite(thisThing->x, thisThing->y, nullptr);
+			_G(gfxDriver)->DrawSprite(thisThing->x, thisThing->y, nullptr);
 		} else
 			quit("Unknown entry in draw list");
 	}
@@ -2055,7 +2023,7 @@ bool GfxDriverNullSpriteCallback(int x, int y) {
 }
 
 void GfxDriverOnInitCallback(void *data) {
-	pl_run_plugin_init_gfx_hooks(gfxDriver->GetDriverID(), data);
+	pl_run_plugin_init_gfx_hooks(_G(gfxDriver)->GetDriverID(), data);
 }
 
 // Schedule room rendering: background, objects, characters
@@ -2077,9 +2045,9 @@ static void construct_room_view() {
 		                           (float)view_rc.GetWidth() / (float)cam_rc.GetWidth(),
 		                           (float)view_rc.GetHeight() / (float)cam_rc.GetHeight(),
 		                           0.f);
-		if (gfxDriver->RequiresFullRedrawEachFrame()) {
+		if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
 			// we draw everything as a sprite stack
-			gfxDriver->BeginSpriteBatch(view_rc, room_trans, Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
+			_G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans, Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
 		} else {
 			if (_GP(CameraDrawData)[viewport->GetID()].Frame == nullptr && _GP(CameraDrawData)[viewport->GetID()].IsOverlap) {
 				// room background is prepended to the sprite stack
@@ -2091,12 +2059,12 @@ static void construct_room_view() {
 				// coordinates (cam1 -> screen -> cam2).
 				// It's not clear whether this is worth the effort, but if it is,
 				// then we'd need to optimise view/cam data first.
-				gfxDriver->BeginSpriteBatch(view_rc, room_trans);
-				gfxDriver->DrawSprite(0, 0, roomBackgroundBmp);
+				_G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans);
+				_G(gfxDriver)->DrawSprite(0, 0, _G(roomBackgroundBmp));
 			} else {
 				// room background is drawn by dirty rects system
 				PBitmap bg_surface = draw_room_background(viewport.get(), room_trans);
-				gfxDriver->BeginSpriteBatch(view_rc, room_trans, Point(), kFlip_None, bg_surface);
+				_G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans, Point(), kFlip_None, bg_surface);
 			}
 		}
 		put_sprite_list_on_screen(true);
@@ -2107,14 +2075,14 @@ static void construct_room_view() {
 
 // Schedule ui rendering
 static void construct_ui_view() {
-	gfxDriver->BeginSpriteBatch(_GP(play).GetUIViewportAbs(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
+	_G(gfxDriver)->BeginSpriteBatch(_GP(play).GetUIViewportAbs(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
 	draw_gui_and_overlays();
 	put_sprite_list_on_screen(false);
 	clear_draw_list();
 }
 
 void construct_game_scene(bool full_redraw) {
-	gfxDriver->ClearDrawLists();
+	_G(gfxDriver)->ClearDrawLists();
 
 	if (_GP(play).fast_forward)
 		return;
@@ -2124,8 +2092,8 @@ void construct_game_scene(bool full_redraw) {
 	// React to changes to viewports and cameras (possibly from script) just before the render
 	_GP(play).UpdateViewports();
 
-	gfxDriver->UseSmoothScaling(IS_ANTIALIAS_SPRITES);
-	gfxDriver->RenderSpritesAtScreenResolution(_GP(usetup).RenderAtScreenRes, _GP(usetup).Supersampling);
+	_G(gfxDriver)->UseSmoothScaling(IS_ANTIALIAS_SPRITES);
+	_G(gfxDriver)->RenderSpritesAtScreenResolution(_GP(usetup).RenderAtScreenRes, _GP(usetup).Supersampling);
 
 	pl_run_plugin_hooks(AGSE_PRERENDER, 0);
 
@@ -2142,10 +2110,10 @@ void construct_game_scene(bool full_redraw) {
 	if (_GP(play).screen_is_faded_out == 0 && _G(is_complete_overlay) == 0) {
 		if (_G(displayed_room) >= 0) {
 			construct_room_view();
-		} else if (!gfxDriver->RequiresFullRedrawEachFrame()) {
+		} else if (!_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
 			// black it out so we don't get cursor trails
 			// TODO: this is possible to do with dirty rects system now too (it can paint black rects outside of room viewport)
-			gfxDriver->GetMemoryBackBuffer()->Fill(0);
+			_G(gfxDriver)->GetMemoryBackBuffer()->Fill(0);
 		}
 	}
 
@@ -2158,9 +2126,9 @@ void construct_game_scene(bool full_redraw) {
 }
 
 void construct_game_screen_overlay(bool draw_mouse) {
-	gfxDriver->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
+	_G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GlobalFlipType)_GP(play).screen_flipped);
 	if (pl_any_want_hook(AGSE_POSTSCREENDRAW))
-		gfxDriver->DrawSprite(AGSE_POSTSCREENDRAW, 0, nullptr);
+		_G(gfxDriver)->DrawSprite(AGSE_POSTSCREENDRAW, 0, nullptr);
 
 	// TODO: find out if it's okay to move cursor animation and state update
 	// to the update loop instead of doing it in the drawing routine
@@ -2198,28 +2166,28 @@ void construct_game_screen_overlay(bool draw_mouse) {
 
 	// Stage: mouse cursor
 	if (draw_mouse && !_GP(play).mouse_cursor_hidden && _GP(play).screen_is_faded_out == 0) {
-		gfxDriver->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), mouseCursor);
+		_G(gfxDriver)->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), mouseCursor);
 		invalidate_sprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), mouseCursor, false);
 	}
 
 	if (_GP(play).screen_is_faded_out == 0) {
 		// Stage: screen fx
 		if (_GP(play).screen_tint >= 1)
-			gfxDriver->SetScreenTint(_GP(play).screen_tint & 0xff, (_GP(play).screen_tint >> 8) & 0xff, (_GP(play).screen_tint >> 16) & 0xff);
+			_G(gfxDriver)->SetScreenTint(_GP(play).screen_tint & 0xff, (_GP(play).screen_tint >> 8) & 0xff, (_GP(play).screen_tint >> 16) & 0xff);
 		// Stage: legacy letterbox mode borders
 		render_black_borders();
 	}
 
-	if (_GP(play).screen_is_faded_out != 0 && gfxDriver->RequiresFullRedrawEachFrame()) {
+	if (_GP(play).screen_is_faded_out != 0 && _G(gfxDriver)->RequiresFullRedrawEachFrame()) {
 		const Rect &main_viewport = _GP(play).GetMainViewport();
-		gfxDriver->BeginSpriteBatch(main_viewport, SpriteTransform());
-		gfxDriver->SetScreenFade(_GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
+		_G(gfxDriver)->BeginSpriteBatch(main_viewport, SpriteTransform());
+		_G(gfxDriver)->SetScreenFade(_GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
 	}
 }
 
 void construct_engine_overlay() {
 	const Rect &viewport = RectWH(_GP(game).GetGameRes());
-	gfxDriver->BeginSpriteBatch(viewport, SpriteTransform());
+	_G(gfxDriver)->BeginSpriteBatch(viewport, SpriteTransform());
 
 	// draw the debug console, if appropriate
 	if ((_GP(play).debug_mode > 0) && (_G(display_console) != 0)) {
@@ -2228,26 +2196,26 @@ void construct_engine_overlay() {
 		int txtspacing = getfontspacing_outlined(font);
 		int barheight = getheightoflines(font, DEBUG_CONSOLE_NUMLINES - 1) + 4;
 
-		if (debugConsoleBuffer == nullptr) {
-			debugConsoleBuffer = BitmapHelper::CreateBitmap(viewport.GetWidth(), barheight, _GP(game).GetColorDepth());
-			debugConsoleBuffer = ReplaceBitmapWithSupportedFormat(debugConsoleBuffer);
+		if (_G(debugConsoleBuffer) == nullptr) {
+			_G(debugConsoleBuffer) = BitmapHelper::CreateBitmap(viewport.GetWidth(), barheight, _GP(game).GetColorDepth());
+			_G(debugConsoleBuffer) = ReplaceBitmapWithSupportedFormat(_G(debugConsoleBuffer));
 		}
 
-		color_t draw_color = debugConsoleBuffer->GetCompatibleColor(15);
-		debugConsoleBuffer->FillRect(Rect(0, 0, viewport.GetWidth() - 1, barheight), draw_color);
-		color_t text_color = debugConsoleBuffer->GetCompatibleColor(16);
+		color_t draw_color = _G(debugConsoleBuffer)->GetCompatibleColor(15);
+		_G(debugConsoleBuffer)->FillRect(Rect(0, 0, viewport.GetWidth() - 1, barheight), draw_color);
+		color_t text_color = _G(debugConsoleBuffer)->GetCompatibleColor(16);
 		for (int jj = _G(first_debug_line); jj != _G(last_debug_line); jj = (jj + 1) % DEBUG_CONSOLE_NUMLINES) {
-			wouttextxy(debugConsoleBuffer, 1, ypp, font, text_color, _G(debug_line)[jj]);
+			wouttextxy(_G(debugConsoleBuffer), 1, ypp, font, text_color, _G(debug_line)[jj]);
 			ypp += txtspacing;
 		}
 
-		if (debugConsole == nullptr)
-			debugConsole = gfxDriver->CreateDDBFromBitmap(debugConsoleBuffer, false, true);
+		if (_G(debugConsole) == nullptr)
+			_G(debugConsole) = _G(gfxDriver)->CreateDDBFromBitmap(_G(debugConsoleBuffer), false, true);
 		else
-			gfxDriver->UpdateDDBFromBitmap(debugConsole, debugConsoleBuffer, false);
+			_G(gfxDriver)->UpdateDDBFromBitmap(_G(debugConsole), _G(debugConsoleBuffer), false);
 
-		gfxDriver->DrawSprite(0, 0, debugConsole);
-		invalidate_sprite(0, 0, debugConsole, false);
+		_G(gfxDriver)->DrawSprite(0, 0, _G(debugConsole));
+		invalidate_sprite(0, 0, _G(debugConsole), false);
 	}
 
 	if (_G(display_fps) != kFPS_Hide)
@@ -2281,7 +2249,7 @@ void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY
 	// NOTE: extraBitmap will always be drawn with the UI render stage
 	if (extraBitmap != nullptr) {
 		invalidate_sprite(extraX, extraY, extraBitmap, false);
-		gfxDriver->DrawSprite(extraX, extraY, extraBitmap);
+		_G(gfxDriver)->DrawSprite(extraX, extraY, extraBitmap);
 	}
 	construct_game_screen_overlay(true);
 	render_to_screen();
@@ -2295,7 +2263,7 @@ void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY
 		}
 	}
 
-	screen_is_dirty = false;
+	_G(screen_is_dirty) = false;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index f16e202373..b9d246f8a0 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -147,8 +147,8 @@ void draw_game_screen_callback();
 void GfxDriverOnInitCallback(void *data);
 bool GfxDriverNullSpriteCallback(int x, int y);
 void putpixel_compensate(Shared::Bitmap *g, int xx, int yy, int col);
-// create the actsps[aa] image with the object drawn correctly
-// returns 1 if nothing at all has changed and actsps is still
+// create the _G(actsps)[aa] image with the object drawn correctly
+// returns 1 if nothing at all has changed and _G(actsps) is still
 // intact from last time; 0 otherwise
 int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware);
 void clear_letterbox_borders();
diff --git a/engines/ags/engine/ac/drawingsurface.cpp b/engines/ags/engine/ac/drawingsurface.cpp
index 774182ac55..4e4775018d 100644
--- a/engines/ags/engine/ac/drawingsurface.cpp
+++ b/engines/ags/engine/ac/drawingsurface.cpp
@@ -52,8 +52,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
-
 // ** SCRIPT DRAWINGSURFACE OBJECT
 
 void DrawingSurface_Release(ScriptDrawingSurface *sds) {
@@ -100,8 +98,8 @@ void DrawingSurface_Release(ScriptDrawingSurface *sds) {
 		sds->dynamicSpriteNumber = -1;
 	}
 	if (sds->dynamicSurfaceNumber >= 0) {
-		delete dynamicallyCreatedSurfaces[sds->dynamicSurfaceNumber];
-		dynamicallyCreatedSurfaces[sds->dynamicSurfaceNumber] = nullptr;
+		delete _G(dynamicallyCreatedSurfaces)[sds->dynamicSurfaceNumber];
+		_G(dynamicallyCreatedSurfaces)[sds->dynamicSurfaceNumber] = nullptr;
 		sds->dynamicSurfaceNumber = -1;
 	}
 	sds->modified = 0;
@@ -128,8 +126,8 @@ ScriptDrawingSurface *DrawingSurface_CreateCopy(ScriptDrawingSurface *sds) {
 	Bitmap *sourceBitmap = sds->GetBitmapSurface();
 
 	for (int i = 0; i < MAX_DYNAMIC_SURFACES; i++) {
-		if (dynamicallyCreatedSurfaces[i] == nullptr) {
-			dynamicallyCreatedSurfaces[i] = BitmapHelper::CreateBitmapCopy(sourceBitmap);
+		if (_G(dynamicallyCreatedSurfaces)[i] == nullptr) {
+			_G(dynamicallyCreatedSurfaces)[i] = BitmapHelper::CreateBitmapCopy(sourceBitmap);
 			ScriptDrawingSurface *newSurface = new ScriptDrawingSurface();
 			newSurface->dynamicSurfaceNumber = i;
 			newSurface->hasAlphaChannel = sds->hasAlphaChannel;
diff --git a/engines/ags/engine/ac/dynamicsprite.cpp b/engines/ags/engine/ac/dynamicsprite.cpp
index 72f18b08aa..0cad3ffe47 100644
--- a/engines/ags/engine/ac/dynamicsprite.cpp
+++ b/engines/ags/engine/ac/dynamicsprite.cpp
@@ -50,7 +50,6 @@ using namespace Shared;
 using namespace Engine;
 
 extern color palette[256];
-extern AGS::Engine::IGraphicsDriver *gfxDriver;
 
 // ** SCRIPT DYNAMIC SPRITE
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp b/engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
index 79e443c06b..ea3391b59c 100644
--- a/engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
+++ b/engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
@@ -35,11 +35,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-
-
-extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
-
-
 Bitmap *ScriptDrawingSurface::GetBitmapSurface() {
 	// TODO: consider creating weak_ptr here, and store one in the DrawingSurface!
 	if (roomBackgroundNumber >= 0)
@@ -47,7 +42,7 @@ Bitmap *ScriptDrawingSurface::GetBitmapSurface() {
 	else if (dynamicSpriteNumber >= 0)
 		return _GP(spriteset)[dynamicSpriteNumber];
 	else if (dynamicSurfaceNumber >= 0)
-		return dynamicallyCreatedSurfaces[dynamicSurfaceNumber];
+		return _G(dynamicallyCreatedSurfaces)[dynamicSurfaceNumber];
 	else if (linkedBitmapOnly != nullptr)
 		return linkedBitmapOnly;
 	else if (roomMaskType > kRoomAreaNone)
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 14a9c2d5e4..14c439eb89 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -49,10 +49,8 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern color palette[256];
-extern IGraphicsDriver *gfxDriver;
 extern color old_palette[256];
 
-
 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,
@@ -227,8 +225,8 @@ void process_event(EventHappened *evp) {
 		else if (theTransition == FADE_NORMAL) {
 			my_fade_in(palette, 5);
 		} else if (theTransition == FADE_BOXOUT) {
-			if (!gfxDriver->UsesMemoryBackBuffer()) {
-				gfxDriver->BoxOutEffect(false, get_fixed_pixel_size(16), 1000 / GetGameSpeed());
+			if (!_G(gfxDriver)->UsesMemoryBackBuffer()) {
+				_G(gfxDriver)->BoxOutEffect(false, get_fixed_pixel_size(16), 1000 / GetGameSpeed());
 			} else {
 				// First of all we render the game once again and save backbuffer from further editing.
 				// We put temporary bitmap as a new backbuffer for the transition period, and
@@ -236,10 +234,10 @@ void process_event(EventHappened *evp) {
 				set_palette_range(palette, 0, 255, 0);
 				construct_game_scene(true);
 				construct_game_screen_overlay(false);
-				gfxDriver->RenderToBackBuffer();
-				Bitmap *saved_backbuf = gfxDriver->GetMemoryBackBuffer();
+				_G(gfxDriver)->RenderToBackBuffer();
+				Bitmap *saved_backbuf = _G(gfxDriver)->GetMemoryBackBuffer();
 				Bitmap *temp_scr = new Bitmap(saved_backbuf->GetWidth(), saved_backbuf->GetHeight(), saved_backbuf->GetColorDepth());
-				gfxDriver->SetMemoryBackBuffer(temp_scr);
+				_G(gfxDriver)->SetMemoryBackBuffer(temp_scr);
 				temp_scr->Clear();
 				render_to_screen();
 
@@ -253,13 +251,13 @@ void process_event(EventHappened *evp) {
 					boxhit = Math::Clamp(boxhit, 0, viewport.GetHeight());
 					int lxp = viewport.GetWidth() / 2 - boxwid / 2;
 					int lyp = viewport.GetHeight() / 2 - boxhit / 2;
-					gfxDriver->Vsync();
+					_G(gfxDriver)->Vsync();
 					temp_scr->Blit(saved_backbuf, lxp, lyp, lxp, lyp,
 						boxwid, boxhit);
 					render_to_screen();
 					WaitForNextFrame();
 				}
-				gfxDriver->SetMemoryBackBuffer(saved_backbuf);
+				_G(gfxDriver)->SetMemoryBackBuffer(saved_backbuf);
 			}
 			_GP(play).screen_is_faded_out = 0;
 		} else if (theTransition == FADE_CROSSFADE) {
@@ -280,7 +278,7 @@ void process_event(EventHappened *evp) {
 				if (transparency > 16) {
 					// on last frame of fade (where transparency < 16), don't
 					// draw the old screen on top
-					gfxDriver->DrawSprite(0, 0, ddb);
+					_G(gfxDriver)->DrawSprite(0, 0, ddb);
 				}
 				render_to_screen();
 				update_polled_stuff_if_runtime();
@@ -292,7 +290,7 @@ void process_event(EventHappened *evp) {
 			delete saved_viewport_bitmap;
 			saved_viewport_bitmap = nullptr;
 			set_palette_range(palette, 0, 255, 0);
-			gfxDriver->DestroyDDB(ddb);
+			_G(gfxDriver)->DestroyDDB(ddb);
 		} else if (theTransition == FADE_DISSOLVE) {
 			int pattern[16] = { 0, 4, 14, 9, 5, 11, 2, 8, 10, 3, 12, 7, 15, 6, 13, 1 };
 			int aa, bb, cc;
@@ -312,10 +310,10 @@ void process_event(EventHappened *evp) {
 						saved_viewport_bitmap->PutPixel(bb + pattern[aa] / 4, cc + pattern[aa] % 4, maskCol);
 					}
 				}
-				gfxDriver->UpdateDDBFromBitmap(ddb, saved_viewport_bitmap, false);
+				_G(gfxDriver)->UpdateDDBFromBitmap(ddb, saved_viewport_bitmap, false);
 				construct_game_scene(true);
 				construct_game_screen_overlay(false);
-				gfxDriver->DrawSprite(0, 0, ddb);
+				_G(gfxDriver)->DrawSprite(0, 0, ddb);
 				render_to_screen();
 				update_polled_stuff_if_runtime();
 				WaitForNextFrame();
@@ -324,7 +322,7 @@ void process_event(EventHappened *evp) {
 			delete saved_viewport_bitmap;
 			saved_viewport_bitmap = nullptr;
 			set_palette_range(palette, 0, 255, 0);
-			gfxDriver->DestroyDDB(ddb);
+			_G(gfxDriver)->DestroyDDB(ddb);
 		}
 
 	} else if (evp->type == EV_IFACECLICK)
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 8020519373..2ea9ded253 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -115,20 +115,8 @@ extern int cur_mode, cur_cursor;
 extern int _G(psp_gfx_renderer);
 #endif
 
-extern int actSpsCount;
-extern Bitmap **actsps;
-extern IDriverDependantBitmap * *actspsbmp;
-// temporary cache of walk-behind for this actsps image
-extern Bitmap **actspswb;
-extern IDriverDependantBitmap * *actspswbbmp;
-extern CachedActSpsData *actspswbcache;
-extern Bitmap **guibg;
-extern IDriverDependantBitmap **guibgbmp;
 extern char transFileName[MAX_PATH];
 extern color palette[256];
-extern Bitmap *raw_saved_screen;
-extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
-extern IGraphicsDriver *gfxDriver;
 
 //=============================================================================
 
@@ -459,11 +447,11 @@ void unload_game_file() {
 	_GP(characterScriptObjNames).clear();
 	free(_G(charextra));
 	free(_G(mls));
-	free(actsps);
-	free(actspsbmp);
-	free(actspswb);
-	free(actspswbbmp);
-	free(actspswbcache);
+	free(_G(actsps));
+	free(_G(actspsbmp));
+	free(_G(actspswb));
+	free(_G(actspswbbmp));
+	free(_G(actspswbcache));
 
 	if ((_G(gameinst) != nullptr) && (_G(gameinst)->pc != 0)) {
 		quit("Error: unload_game called while script still running");
@@ -531,12 +519,12 @@ void unload_game_file() {
 	_G(scrDialog) = nullptr;
 
 	for (int i = 0; i < _GP(game).numgui; ++i) {
-		free(guibg[i]);
-		guibg[i] = nullptr;
+		free(_G(guibg)[i]);
+		_G(guibg)[i] = nullptr;
 	}
 
 	_GP(guiScriptObjNames).clear();
-	free(guibg);
+	free(_G(guibg));
 	_GP(guis).clear();
 	free(_G(scrGui));
 
@@ -1262,7 +1250,7 @@ void restore_game_displayed_room_status(Stream *in, RestoredData &r_data) {
 		bb = in->ReadInt32();
 
 		if (bb)
-			raw_saved_screen = read_serialized_bitmap(in);
+			_G(raw_saved_screen) = read_serialized_bitmap(in);
 
 		// get the current troom, in case they save in room 600 or whatever
 		ReadRoomStatus_Aligned(&_GP(troom), in);
@@ -1740,8 +1728,8 @@ void display_switch_out_suspend() {
 // Called whenever game gets input focus
 void display_switch_in() {
 	_G(switched_away) = false;
-	if (gfxDriver) {
-		DisplayMode mode = gfxDriver->GetDisplayMode();
+	if (_G(gfxDriver)) {
+		DisplayMode mode = _G(gfxDriver)->GetDisplayMode();
 		if (!mode.Windowed)
 			_G(platform)->EnterFullscreenMode(mode);
 	}
@@ -1766,8 +1754,8 @@ void display_switch_in_resume() {
 	} // -- AudioChannelsLock
 
 	// clear the screen if necessary
-	if (gfxDriver && gfxDriver->UsesMemoryBackBuffer())
-		gfxDriver->ClearRectangle(0, 0, _GP(game).GetGameRes().Width - 1, _GP(game).GetGameRes().Height - 1, nullptr);
+	if (_G(gfxDriver) && _G(gfxDriver)->UsesMemoryBackBuffer())
+		_G(gfxDriver)->ClearRectangle(0, 0, _GP(game).GetGameRes().Width - 1, _GP(game).GetGameRes().Height - 1, nullptr);
 
 	_G(platform)->ResumeApplication();
 }
diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index a4f427e086..4765ee2958 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -53,14 +53,13 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
 extern TreeMap *transtree;
 extern char transFileName[MAX_PATH];
 
 String GetRuntimeInfo() {
-	DisplayMode mode = gfxDriver->GetDisplayMode();
-	Rect render_frame = gfxDriver->GetRenderDestination();
-	PGfxFilter filter = gfxDriver->GetGraphicsFilter();
+	DisplayMode mode = _G(gfxDriver)->GetDisplayMode();
+	Rect render_frame = _G(gfxDriver)->GetRenderDestination();
+	PGfxFilter filter = _G(gfxDriver)->GetGraphicsFilter();
 	String runtimeInfo = String::FromFormat(
 		"Adventure Game Studio run-time engine[ACI version %s"
 		"[Game resolution %d x %d (%d-bit)"
@@ -69,7 +68,7 @@ String GetRuntimeInfo() {
 		_G(EngineVersion).LongString.GetCStr(), _GP(game).GetGameRes().Width, _GP(game).GetGameRes().Height, _GP(game).GetColorDepth(),
 		mode.Width, mode.Height, mode.ColorDepth, (_G(convert_16bit_bgr)) ? " BGR" : "",
 		mode.Windowed ? " W" : "",
-		gfxDriver->GetDriverName(), filter->GetInfo().Name.GetCStr(),
+		_G(gfxDriver)->GetDriverName(), filter->GetInfo().Name.GetCStr(),
 		render_frame.GetWidth(), render_frame.GetHeight(),
 		_GP(spriteset).GetCacheSize() / 1024, _GP(spriteset).GetMaxCacheSize() / 1024, _GP(spriteset).GetLockedSize() / 1024);
 	if (_GP(play).separate_music_lib)
@@ -111,12 +110,12 @@ void script_debug(int cmdd, int dataa) {
 		Rect mask_src = Rect(camera.Left / _GP(thisroom).MaskResolution, camera.Top / _GP(thisroom).MaskResolution, camera.Right / _GP(thisroom).MaskResolution, camera.Bottom / _GP(thisroom).MaskResolution);
 		view_bmp->StretchBlt(tempw, mask_src, RectWH(0, 0, viewport.GetWidth(), viewport.GetHeight()), Shared::kBitmap_Transparency);
 
-		IDriverDependantBitmap *ddb = gfxDriver->CreateDDBFromBitmap(view_bmp, false, true);
+		IDriverDependantBitmap *ddb = _G(gfxDriver)->CreateDDBFromBitmap(view_bmp, false, true);
 		render_graphics(ddb, viewport.Left, viewport.Top);
 
 		delete tempw;
 		delete view_bmp;
-		gfxDriver->DestroyDDB(ddb);
+		_G(gfxDriver)->DestroyDDB(ddb);
 		ags_wait_until_keypress();
 		invalidate_screen();
 	} else if (cmdd == 3) {
@@ -165,12 +164,12 @@ void script_debug(int cmdd, int dataa) {
 		Rect mask_src = Rect(camera.Left / _GP(thisroom).MaskResolution, camera.Top / _GP(thisroom).MaskResolution, camera.Right / _GP(thisroom).MaskResolution, camera.Bottom / _GP(thisroom).MaskResolution);
 		view_bmp->StretchBlt(tempw, mask_src, RectWH(0, 0, viewport.GetWidth(), viewport.GetHeight()), Shared::kBitmap_Transparency);
 
-		IDriverDependantBitmap *ddb = gfxDriver->CreateDDBFromBitmap(view_bmp, false, true);
+		IDriverDependantBitmap *ddb = _G(gfxDriver)->CreateDDBFromBitmap(view_bmp, false, true);
 		render_graphics(ddb, viewport.Left, viewport.Top);
 
 		delete tempw;
 		delete view_bmp;
-		gfxDriver->DestroyDDB(ddb);
+		_G(gfxDriver)->DestroyDDB(ddb);
 		ags_wait_until_keypress();
 	} else if (cmdd == 99)
 		ccSetOption(SCOPT_DEBUGRUN, dataa);
diff --git a/engines/ags/engine/ac/global_drawingsurface.cpp b/engines/ags/engine/ac/global_drawingsurface.cpp
index 63c0743f08..418f09e422 100644
--- a/engines/ags/engine/ac/global_drawingsurface.cpp
+++ b/engines/ags/engine/ac/global_drawingsurface.cpp
@@ -43,12 +43,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern Bitmap *raw_saved_screen;
-
-
-
-
-
 // Raw screen writing routines - similar to old CapturedStuff
 #define RAW_START() _GP(play).raw_drawing_surface = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic; _GP(play).raw_modified[_GP(play).bg_frame] = 1
 #define RAW_END()
@@ -56,27 +50,27 @@ extern Bitmap *raw_saved_screen;
 
 // RawSaveScreen: copy the current screen to a backup bitmap
 void RawSaveScreen() {
-	if (raw_saved_screen != nullptr)
-		delete raw_saved_screen;
+	if (_G(raw_saved_screen) != nullptr)
+		delete _G(raw_saved_screen);
 	PBitmap source = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic;
-	raw_saved_screen = BitmapHelper::CreateBitmapCopy(source.get());
+	_G(raw_saved_screen) = BitmapHelper::CreateBitmapCopy(source.get());
 }
 // RawRestoreScreen: copy backup bitmap back to screen; we
 // deliberately don't free the Bitmap *cos they can multiple restore
 // and it gets freed on room exit anyway
 void RawRestoreScreen() {
-	if (raw_saved_screen == nullptr) {
+	if (_G(raw_saved_screen) == nullptr) {
 		debug_script_warn("RawRestoreScreen: unable to restore, since the screen hasn't been saved previously.");
 		return;
 	}
 	PBitmap deston = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic;
-	deston->Blit(raw_saved_screen, 0, 0, 0, 0, deston->GetWidth(), deston->GetHeight());
+	deston->Blit(_G(raw_saved_screen), 0, 0, 0, 0, deston->GetWidth(), deston->GetHeight());
 	invalidate_screen();
 	mark_current_background_dirty();
 }
 // Restores the backup bitmap, but tints it to the specified level
 void RawRestoreScreenTinted(int red, int green, int blue, int opacity) {
-	if (raw_saved_screen == nullptr) {
+	if (_G(raw_saved_screen) == nullptr) {
 		debug_script_warn("RawRestoreScreenTinted: unable to restore, since the screen hasn't been saved previously.");
 		return;
 	}
@@ -88,7 +82,7 @@ void RawRestoreScreenTinted(int red, int green, int blue, int opacity) {
 	debug_script_log("RawRestoreTinted RGB(%d,%d,%d) %d%%", red, green, blue, opacity);
 
 	PBitmap deston = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic;
-	tint_image(deston.get(), raw_saved_screen, red, green, blue, opacity);
+	tint_image(deston.get(), _G(raw_saved_screen), red, green, blue, opacity);
 	invalidate_screen();
 	mark_current_background_dirty();
 }
diff --git a/engines/ags/engine/ac/global_dynamicsprite.cpp b/engines/ags/engine/ac/global_dynamicsprite.cpp
index b1477530d8..e3800c48f5 100644
--- a/engines/ags/engine/ac/global_dynamicsprite.cpp
+++ b/engines/ags/engine/ac/global_dynamicsprite.cpp
@@ -36,9 +36,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-extern IGraphicsDriver *gfxDriver;
-
 int LoadImageFile(const char *filename) {
 	ResolvedPath rp;
 	if (!ResolveScriptPath(filename, true, rp))
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 934e993393..e853b9996f 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -82,7 +82,6 @@ extern unsigned int load_new_game;
 extern int load_new_game_restore;
 extern int gui_disabled_style;
 extern int getloctype_index;
-extern IGraphicsDriver *gfxDriver;
 extern color palette[256];
 
 #if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 45275c406a..09abcf76ff 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -52,11 +52,6 @@ using namespace AGS::Shared;
 
 #define OVERLAPPING_OBJECT 1000
 
-extern int actSpsCount;
-extern Bitmap **actsps;
-extern IDriverDependantBitmap **actspsbmp;
-extern IGraphicsDriver *gfxDriver;
-
 int GetObjectIDAtScreen(int scrx, int scry) {
 	// translate screen co-ordinates to room co-ordinates
 	VpPoint vpt = _GP(play).ScreenToRoomDivDown(scrx, scry);
@@ -257,13 +252,13 @@ void MergeObject(int obn) {
 	//Bitmap *oldabuf = graphics->bmp;
 	//abuf = _GP(thisroom).BgFrames.Graphic[_GP(play).bg_frame];
 	PBitmap bg_frame = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic;
-	if (bg_frame->GetColorDepth() != actsps[obn]->GetColorDepth())
+	if (bg_frame->GetColorDepth() != _G(actsps)[obn]->GetColorDepth())
 		quit("!MergeObject: unable to merge object due to color depth differences");
 
 	int xpos = data_to_game_coord(_G(objs)[obn].x);
 	int ypos = (data_to_game_coord(_G(objs)[obn].y) - theHeight);
 
-	draw_sprite_support_alpha(bg_frame.get(), false, xpos, ypos, actsps[obn], (_GP(game).SpriteInfos[_G(objs)[obn].num].Flags & SPF_ALPHACHANNEL) != 0);
+	draw_sprite_support_alpha(bg_frame.get(), false, xpos, ypos, _G(actsps)[obn], (_GP(game).SpriteInfos[_G(objs)[obn].num].Flags & SPF_ALPHACHANNEL) != 0);
 	invalidate_screen();
 	mark_current_background_dirty();
 
@@ -495,13 +490,13 @@ void GetObjectPropertyText(int item, const char *property, char *bufer) {
 }
 
 Bitmap *GetObjectImage(int obj, int *isFlipped) {
-	if (!gfxDriver->HasAcceleratedTransform()) {
-		if (actsps[obj] != nullptr) {
-			// the actsps image is pre-flipped, so no longer register the image as such
+	if (!_G(gfxDriver)->HasAcceleratedTransform()) {
+		if (_G(actsps)[obj] != nullptr) {
+			// the _G(actsps) image is pre-flipped, so no longer register the image as such
 			if (isFlipped)
 				*isFlipped = 0;
 
-			return actsps[obj];
+			return _G(actsps)[obj];
 		}
 	}
 	return _GP(spriteset)[_G(objs)[obj].num];
diff --git a/engines/ags/engine/ac/global_screen.cpp b/engines/ags/engine/ac/global_screen.cpp
index 15497bb4a1..ddbe845cc0 100644
--- a/engines/ags/engine/ac/global_screen.cpp
+++ b/engines/ags/engine/ac/global_screen.cpp
@@ -41,7 +41,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
 extern color palette[256];
 
 void FlipScreen(int amount) {
@@ -66,7 +65,7 @@ void ShakeScreen(int severe) {
 	_GP(play).shakesc_amount = severe;
 	_GP(play).mouse_cursor_hidden++;
 
-	if (gfxDriver->RequiresFullRedrawEachFrame()) {
+	if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
 		for (int hh = 0; hh < 40; hh++) {
 			_G(loopcounter)++;
 			_G(platform)->Delay(50);
@@ -78,7 +77,7 @@ void ShakeScreen(int severe) {
 	} else {
 		// Optimized variant for software render: create game scene once and shake it
 		construct_game_scene();
-		gfxDriver->RenderToBackBuffer();
+		_G(gfxDriver)->RenderToBackBuffer();
 		for (int hh = 0; hh < 40; hh++) {
 			_G(platform)->Delay(50);
 			const int yoff = hh % 2 == 0 ? 0 : severe;
@@ -135,7 +134,7 @@ void my_fade_out(int spdd) {
 		return;
 
 	if (_GP(play).screen_is_faded_out == 0)
-		gfxDriver->FadeOut(spdd, _GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
+		_G(gfxDriver)->FadeOut(spdd, _GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
 
 	if (_GP(game).color_depth > 1)
 		_GP(play).screen_is_faded_out = 1;
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 050d88311b..3f87d41d22 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -64,10 +64,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern int cur_mode, cur_cursor;
-extern Bitmap **guibg;
-extern IDriverDependantBitmap **guibgbmp;
-extern IGraphicsDriver *gfxDriver;
-
 
 ScriptGUI *GUI_AsTextWindow(ScriptGUI *tehgui) {
 	// Internally both GUI and TextWindow are implemented by same class
@@ -550,15 +546,15 @@ int adjust_y_for_guis(int yy) {
 
 void recreate_guibg_image(GUIMain *tehgui) {
 	int ifn = tehgui->ID;
-	delete guibg[ifn];
-	guibg[ifn] = BitmapHelper::CreateBitmap(tehgui->Width, tehgui->Height, _GP(game).GetColorDepth());
-	if (guibg[ifn] == nullptr)
+	delete _G(guibg)[ifn];
+	_G(guibg)[ifn] = BitmapHelper::CreateBitmap(tehgui->Width, tehgui->Height, _GP(game).GetColorDepth());
+	if (_G(guibg)[ifn] == nullptr)
 		quit("SetGUISize: internal error: unable to reallocate gui cache");
-	guibg[ifn] = ReplaceBitmapWithSupportedFormat(guibg[ifn]);
+	_G(guibg)[ifn] = ReplaceBitmapWithSupportedFormat(_G(guibg)[ifn]);
 
-	if (guibgbmp[ifn] != nullptr) {
-		gfxDriver->DestroyDDB(guibgbmp[ifn]);
-		guibgbmp[ifn] = nullptr;
+	if (_G(guibgbmp)[ifn] != nullptr) {
+		_G(gfxDriver)->DestroyDDB(_G(guibgbmp)[ifn]);
+		_G(guibgbmp)[ifn] = nullptr;
 	}
 }
 
diff --git a/engines/ags/engine/ac/mouse.cpp b/engines/ags/engine/ac/mouse.cpp
index ec825bbfdc..ea3421082a 100644
--- a/engines/ags/engine/ac/mouse.cpp
+++ b/engines/ags/engine/ac/mouse.cpp
@@ -53,8 +53,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
-
 extern void ags_domouse(int str);
 extern int misbuttondown(int buno);
 
@@ -378,8 +376,8 @@ void update_inv_cursor(int invnum) {
 
 void update_cached_mouse_cursor() {
 	if (mouseCursor != nullptr)
-		gfxDriver->DestroyDDB(mouseCursor);
-	mouseCursor = gfxDriver->CreateDDBFromBitmap(_G(mousecurs)[0], alpha_blend_cursor != 0);
+		_G(gfxDriver)->DestroyDDB(mouseCursor);
+	mouseCursor = _G(gfxDriver)->CreateDDBFromBitmap(_G(mousecurs)[0], alpha_blend_cursor != 0);
 }
 
 void set_new_cursor_graphic(int spriteslot) {
diff --git a/engines/ags/engine/ac/object.cpp b/engines/ags/engine/ac/object.cpp
index 3eacf82319..d599ab3d78 100644
--- a/engines/ags/engine/ac/object.cpp
+++ b/engines/ags/engine/ac/object.cpp
@@ -56,7 +56,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 extern Bitmap *walkable_areas_temp;
-extern IGraphicsDriver *gfxDriver;
 
 int Object_IsCollidingWithObject(ScriptObject *objj, ScriptObject *obj2) {
 	return AreObjectsColliding(objj->id, obj2->id);
@@ -515,7 +514,7 @@ int is_pos_in_sprite(int xx, int yy, int arx, int ary, Bitmap *sprit, int spww,
 		int xpos = data_to_game_coord(xx - arx);
 		int ypos = data_to_game_coord(yy - ary);
 
-		if (gfxDriver->HasAcceleratedTransform()) {
+		if (_G(gfxDriver)->HasAcceleratedTransform()) {
 			// hardware acceleration, so the sprite in memory will not have
 			// been stretched, it will be original size. Thus, adjust our
 			// calculations to compensate
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 4cd92f51a6..2af5973aac 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -47,8 +47,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
-
 void Overlay_Remove(ScriptOverlay *sco) {
 	sco->Remove();
 }
@@ -151,7 +149,7 @@ void dispose_overlay(ScreenOverlay &over) {
 	delete over.pic;
 	over.pic = nullptr;
 	if (over.bmp != nullptr)
-		gfxDriver->DestroyDDB(over.bmp);
+		_G(gfxDriver)->DestroyDDB(over.bmp);
 	over.bmp = nullptr;
 	// if the script didn't actually use the Overlay* return
 	// value, dispose of the pointer
@@ -205,7 +203,7 @@ size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic
 	}
 	ScreenOverlay over;
 	over.pic = piccy;
-	over.bmp = gfxDriver->CreateDDBFromBitmap(piccy, alphaChannel);
+	over.bmp = _G(gfxDriver)->CreateDDBFromBitmap(piccy, alphaChannel);
 	over.x = x;
 	over.y = y;
 	over._offsetX = pic_offx;
@@ -267,9 +265,9 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
 void recreate_overlay_ddbs() {
 	for (auto &over : _GP(screenover)) {
 		if (over.bmp)
-			gfxDriver->DestroyDDB(over.bmp);
+			_G(gfxDriver)->DestroyDDB(over.bmp);
 		if (over.pic)
-			over.bmp = gfxDriver->CreateDDBFromBitmap(over.pic, false);
+			over.bmp = _G(gfxDriver)->CreateDDBFromBitmap(over.pic, false);
 		else
 			over.bmp = nullptr;
 	}
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index b8d2adbb86..4c544ae53b 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -86,21 +86,9 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern Bitmap *walkareabackup, *walkable_areas_temp;
-extern IDriverDependantBitmap *roomBackgroundBmp;
-extern IGraphicsDriver *gfxDriver;
-extern Bitmap *raw_saved_screen;
-extern int actSpsCount;
-extern Bitmap **actsps;
-extern IDriverDependantBitmap * *actspsbmp;
-extern Bitmap **actspswb;
-extern IDriverDependantBitmap * *actspswbbmp;
-extern CachedActSpsData *actspswbcache;
 extern color palette[256];
 extern int mouse_z_was;
 
-extern Bitmap **guibg;
-extern IDriverDependantBitmap **guibgbmp;
-
 RGB_MAP rgb_table;  // for 256-col antialiasing
 int new_room_flags = 0;
 int gs_to_newroom = -1;
@@ -252,9 +240,9 @@ void unload_old_room() {
 	cancel_all_scripts();
 	_G(numevents) = 0;  // cancel any pending room events
 
-	if (roomBackgroundBmp != nullptr) {
-		gfxDriver->DestroyDDB(roomBackgroundBmp);
-		roomBackgroundBmp = nullptr;
+	if (_G(roomBackgroundBmp) != nullptr) {
+		_G(gfxDriver)->DestroyDDB(_G(roomBackgroundBmp));
+		_G(roomBackgroundBmp) = nullptr;
 	}
 
 	if (_G(croom) == nullptr) ;
@@ -269,8 +257,8 @@ void unload_old_room() {
 	_GP(play).bg_frame = 0;
 	_GP(play).bg_frame_locked = 0;
 	remove_screen_overlay(-1);
-	delete raw_saved_screen;
-	raw_saved_screen = nullptr;
+	delete _G(raw_saved_screen);
+	_G(raw_saved_screen) = nullptr;
 	for (ff = 0; ff < MAX_ROOM_BGFRAMES; ff++)
 		_GP(play).raw_modified[ff] = 0;
 	for (size_t i = 0; i < _GP(thisroom).LocalVariables.size() && i < MAX_GLOBAL_VARIABLES; ++i)
@@ -312,25 +300,25 @@ void unload_old_room() {
 		delete _G(objcache)[ff].image;
 		_G(objcache)[ff].image = nullptr;
 	}
-	// clear the actsps buffers to save memory, since the
+	// clear the _G(actsps) buffers to save memory, since the
 	// objects/characters involved probably aren't on the
 	// new screen. this also ensures all cached data is flushed
 	for (ff = 0; ff < MAX_ROOM_OBJECTS + _GP(game).numcharacters; ff++) {
-		delete actsps[ff];
-		actsps[ff] = nullptr;
+		delete _G(actsps)[ff];
+		_G(actsps)[ff] = nullptr;
 
-		if (actspsbmp[ff] != nullptr)
-			gfxDriver->DestroyDDB(actspsbmp[ff]);
-		actspsbmp[ff] = nullptr;
+		if (_G(actspsbmp)[ff] != nullptr)
+			_G(gfxDriver)->DestroyDDB(_G(actspsbmp)[ff]);
+		_G(actspsbmp)[ff] = nullptr;
 
-		delete actspswb[ff];
-		actspswb[ff] = nullptr;
+		delete _G(actspswb)[ff];
+		_G(actspswb)[ff] = nullptr;
 
-		if (actspswbbmp[ff] != nullptr)
-			gfxDriver->DestroyDDB(actspswbbmp[ff]);
-		actspswbbmp[ff] = nullptr;
+		if (_G(actspswbbmp)[ff] != nullptr)
+			_G(gfxDriver)->DestroyDDB(_G(actspswbbmp)[ff]);
+		_G(actspswbbmp)[ff] = nullptr;
 
-		actspswbcache[ff].valid = 0;
+		_G(actspswbcache)[ff].valid = 0;
 	}
 
 	// if Hide Player Character was ticked, restore it to visible
@@ -923,12 +911,12 @@ void new_room(int newnum, CharacterInfo *forchar) {
 
 		// Delete all gui background images
 		for (int i = 0; i < _GP(game).numgui; i++) {
-			delete guibg[i];
-			guibg[i] = nullptr;
+			delete _G(guibg)[i];
+			_G(guibg)[i] = nullptr;
 
-			if (guibgbmp[i])
-				gfxDriver->DestroyDDB(guibgbmp[i]);
-			guibgbmp[i] = nullptr;
+			if (_G(guibgbmp)[i])
+				_G(gfxDriver)->DestroyDDB(_G(guibgbmp)[i]);
+			_G(guibgbmp)[i] = nullptr;
 		}
 		guis_need_update = 1;
 	}
diff --git a/engines/ags/engine/ac/screen.cpp b/engines/ags/engine/ac/screen.cpp
index 0f8ac9094f..555ff8137b 100644
--- a/engines/ags/engine/ac/screen.cpp
+++ b/engines/ags/engine/ac/screen.cpp
@@ -42,10 +42,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-extern IGraphicsDriver *gfxDriver;
-
-
 void my_fade_in(PALETTE p, int speed) {
 	if (_GP(game).color_depth > 1) {
 		set_palette(p);
@@ -57,7 +53,7 @@ void my_fade_in(PALETTE p, int speed) {
 		}
 	}
 
-	gfxDriver->FadeIn(speed, p, _GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
+	_G(gfxDriver)->FadeIn(speed, p, _GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
 }
 
 Bitmap *saved_viewport_bitmap = nullptr;
@@ -79,7 +75,7 @@ void current_fade_out_effect() {
 	} else if (theTransition == FADE_NORMAL) {
 		my_fade_out(5);
 	} else if (theTransition == FADE_BOXOUT) {
-		gfxDriver->BoxOutEffect(true, get_fixed_pixel_size(16), 1000 / GetGameSpeed());
+		_G(gfxDriver)->BoxOutEffect(true, get_fixed_pixel_size(16), 1000 / GetGameSpeed());
 		_GP(play).screen_is_faded_out = 1;
 	} else {
 		get_palette(old_palette);
@@ -105,7 +101,7 @@ IDriverDependantBitmap *prepare_screen_for_transition_in() {
 		delete saved_viewport_bitmap;
 		saved_viewport_bitmap = clippedBuffer;
 	}
-	IDriverDependantBitmap *ddb = gfxDriver->CreateDDBFromBitmap(saved_viewport_bitmap, false);
+	IDriverDependantBitmap *ddb = _G(gfxDriver)->CreateDDBFromBitmap(saved_viewport_bitmap, false);
 	return ddb;
 }
 
diff --git a/engines/ags/engine/ac/sprite.cpp b/engines/ags/engine/ac/sprite.cpp
index 628d20689d..91265daaf0 100644
--- a/engines/ags/engine/ac/sprite.cpp
+++ b/engines/ags/engine/ac/sprite.cpp
@@ -39,8 +39,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern color palette[256];
-extern IGraphicsDriver *gfxDriver;
-
 
 void get_new_size_for_sprite(int ee, int ww, int hh, int &newwid, int &newhit) {
 	newwid = ww;
diff --git a/engines/ags/engine/ac/system.cpp b/engines/ags/engine/ac/system.cpp
index 6df3424766..7a29dd637a 100644
--- a/engines/ags/engine/ac/system.cpp
+++ b/engines/ags/engine/ac/system.cpp
@@ -52,8 +52,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
-
 bool System_HasInputFocus() {
 	return !_G(switched_away);
 }
@@ -108,7 +106,7 @@ const char *System_GetVersion() {
 }
 
 int System_GetHardwareAcceleration() {
-	return gfxDriver->HasAcceleratedTransform() ? 1 : 0;
+	return _G(gfxDriver)->HasAcceleratedTransform() ? 1 : 0;
 }
 
 int System_GetNumLock() {
@@ -132,7 +130,7 @@ int System_GetVsync() {
 }
 
 void System_SetVsync(int newValue) {
-	if (ags_stricmp(gfxDriver->GetDriverID(), "D3D9") != 0)
+	if (ags_stricmp(_G(gfxDriver)->GetDriverID(), "D3D9") != 0)
 		_GP(scsystem).vsync = newValue;
 }
 
@@ -146,7 +144,7 @@ void System_SetWindowed(int windowed) {
 }
 
 int System_GetSupportsGammaControl() {
-	return gfxDriver->SupportsGammaControl();
+	return _G(gfxDriver)->SupportsGammaControl();
 }
 
 int System_GetGamma() {
@@ -161,8 +159,8 @@ void System_SetGamma(int newValue) {
 		debug_script_log("Gamma control set to %d", newValue);
 		_GP(play).gamma_adjustment = newValue;
 
-		if (gfxDriver->SupportsGammaControl())
-			gfxDriver->SetGamma(newValue);
+		if (_G(gfxDriver)->SupportsGammaControl())
+			_G(gfxDriver)->SetGamma(newValue);
 	}
 }
 
diff --git a/engines/ags/engine/ac/walkbehind.cpp b/engines/ags/engine/ac/walkbehind.cpp
index eeb6d33025..91bdf984b8 100644
--- a/engines/ags/engine/ac/walkbehind.cpp
+++ b/engines/ags/engine/ac/walkbehind.cpp
@@ -33,10 +33,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-extern IGraphicsDriver *gfxDriver;
-
-
 char *walkBehindExists = nullptr;  // whether a WB area is in this column
 int *walkBehindStartY = nullptr, *walkBehindEndY = nullptr;
 char noWalkBehindsAtAll = 0;
@@ -72,9 +68,9 @@ void update_walk_behind_images() {
 			update_polled_stuff_if_runtime();
 
 			if (walkBehindBitmap[ee] != nullptr) {
-				gfxDriver->DestroyDDB(walkBehindBitmap[ee]);
+				_G(gfxDriver)->DestroyDDB(walkBehindBitmap[ee]);
 			}
-			walkBehindBitmap[ee] = gfxDriver->CreateDDBFromBitmap(wbbmp, false);
+			walkBehindBitmap[ee] = _G(gfxDriver)->CreateDDBFromBitmap(wbbmp, false);
 			delete wbbmp;
 		}
 	}
@@ -104,7 +100,7 @@ void recache_walk_behinds() {
 		walkBehindBottom[ee] = 0;
 
 		if (walkBehindBitmap[ee] != nullptr) {
-			gfxDriver->DestroyDDB(walkBehindBitmap[ee]);
+			_G(gfxDriver)->DestroyDDB(walkBehindBitmap[ee]);
 			walkBehindBitmap[ee] = nullptr;
 		}
 	}
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 36df26259a..4869bcaeb2 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -57,12 +57,6 @@ namespace AGS3 {
 using namespace Shared;
 using namespace Engine;
 
-extern int actSpsCount;
-extern Bitmap **actsps;
-extern IDriverDependantBitmap **actspsbmp;
-extern Bitmap **actspswb;
-extern IDriverDependantBitmap **actspswbbmp;
-extern CachedActSpsData *actspswbcache;
 extern AGSStaticObject GlobalStaticManager;
 
 namespace AGS {
@@ -332,12 +326,12 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
 	_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;
-	actsps = (Bitmap **)calloc(actSpsCount, sizeof(Bitmap *));
-	actspsbmp = (IDriverDependantBitmap **)calloc(actSpsCount, sizeof(IDriverDependantBitmap *));
-	actspswb = (Bitmap **)calloc(actSpsCount, sizeof(Bitmap *));
-	actspswbbmp = (IDriverDependantBitmap **)calloc(actSpsCount, sizeof(IDriverDependantBitmap *));
-	actspswbcache = (CachedActSpsData *)calloc(actSpsCount, sizeof(CachedActSpsData));
+	_G(actSpsCount) = _GP(game).numcharacters + MAX_ROOM_OBJECTS + 2;
+	_G(actsps) = (Bitmap **)calloc(_G(actSpsCount), sizeof(Bitmap *));
+	_G(actspsbmp) = (IDriverDependantBitmap **)calloc(_G(actSpsCount), sizeof(IDriverDependantBitmap *));
+	_G(actspswb) = (Bitmap **)calloc(_G(actSpsCount), sizeof(Bitmap *));
+	_G(actspswbbmp) = (IDriverDependantBitmap **)calloc(_G(actSpsCount), sizeof(IDriverDependantBitmap *));
+	_G(actspswbcache) = (CachedActSpsData *)calloc(_G(actSpsCount), sizeof(CachedActSpsData));
 	_GP(play).charProps.resize(_GP(game).numcharacters);
 	_G(old_dialog_scripts) = ents.OldDialogScripts;
 	_G(old_speech_lines) = ents.OldSpeechLines;
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index c8ed36982e..f227cd6ee6 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -72,13 +72,6 @@ using namespace Engine;
 // function is currently implemented in game.cpp
 HSaveError restore_game_data(Stream *in, SavegameVersion svg_version, const PreservedParams &pp, RestoredData &r_data);
 
-
-extern Bitmap **guibg;
-extern AGS::Engine::IDriverDependantBitmap **guibgbmp;
-extern AGS::Engine::IGraphicsDriver *gfxDriver;
-extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
-extern Bitmap *raw_saved_screen;
-
 namespace AGS {
 namespace Engine {
 
@@ -326,8 +319,8 @@ void DoBeforeRestore(PreservedParams &pp) {
 	pp.MusicVOX = _GP(play).separate_music_lib;
 
 	unload_old_room();
-	delete raw_saved_screen;
-	raw_saved_screen = nullptr;
+	delete _G(raw_saved_screen);
+	_G(raw_saved_screen) = nullptr;
 	remove_screen_overlay(-1);
 	_G(is_complete_overlay) = 0;
 	_G(is_text_overlay) = 0;
@@ -344,12 +337,12 @@ void DoBeforeRestore(PreservedParams &pp) {
 
 	// cleanup GUI backgrounds
 	for (int i = 0; i < _GP(game).numgui; ++i) {
-		delete guibg[i];
-		guibg[i] = nullptr;
+		delete _G(guibg)[i];
+		_G(guibg)[i] = nullptr;
 
-		if (guibgbmp[i])
-			gfxDriver->DestroyDDB(guibgbmp[i]);
-		guibgbmp[i] = nullptr;
+		if (_G(guibgbmp)[i])
+			_G(gfxDriver)->DestroyDDB(_G(guibgbmp)[i]);
+		_G(guibgbmp)[i] = nullptr;
 	}
 
 	// preserve script data sizes and cleanup scripts
@@ -451,7 +444,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	// restore these to the ones retrieved from the save game
 	const size_t dynsurf_num = Math::Min((uint)MAX_DYNAMIC_SURFACES, r_data.DynamicSurfaces.size());
 	for (size_t i = 0; i < dynsurf_num; ++i) {
-		dynamicallyCreatedSurfaces[i] = r_data.DynamicSurfaces[i];
+		_G(dynamicallyCreatedSurfaces)[i] = r_data.DynamicSurfaces[i];
 	}
 
 	for (int i = 0; i < _GP(game).numgui; ++i)
@@ -600,8 +593,8 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	update_directional_sound_vol();
 
 	for (int i = 0; i < _GP(game).numgui; ++i) {
-		guibg[i] = BitmapHelper::CreateBitmap(_GP(guis)[i].Width, _GP(guis)[i].Height, _GP(game).GetColorDepth());
-		guibg[i] = ReplaceBitmapWithSupportedFormat(guibg[i]);
+		_G(guibg)[i] = BitmapHelper::CreateBitmap(_GP(guis)[i].Width, _GP(guis)[i].Height, _GP(game).GetColorDepth());
+		_G(guibg)[i] = ReplaceBitmapWithSupportedFormat(_G(guibg)[i]);
 	}
 
 	recreate_overlay_ddbs();
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 50da482977..4f4c4fe65b 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -64,8 +64,6 @@ namespace AGS3 {
 using namespace Shared;
 
 extern color palette[256];
-extern Bitmap *dynamicallyCreatedSurfaces[MAX_DYNAMIC_SURFACES];
-extern Bitmap *raw_saved_screen;
 
 namespace AGS {
 namespace Engine {
@@ -777,11 +775,11 @@ HSaveError ReadOverlays(PStream in, int32_t cmp_ver, const PreservedParams &pp,
 HSaveError WriteDynamicSurfaces(PStream out) {
 	out->WriteInt32(MAX_DYNAMIC_SURFACES);
 	for (int i = 0; i < MAX_DYNAMIC_SURFACES; ++i) {
-		if (dynamicallyCreatedSurfaces[i] == nullptr) {
+		if (_G(dynamicallyCreatedSurfaces)[i] == nullptr) {
 			out->WriteInt8(0);
 		} else {
 			out->WriteInt8(1);
-			serialize_bitmap(dynamicallyCreatedSurfaces[i], out.get());
+			serialize_bitmap(_G(dynamicallyCreatedSurfaces)[i], out.get());
 		}
 	}
 	return HSaveError::None();
@@ -893,9 +891,9 @@ HSaveError WriteThisRoom(PStream out) {
 		if (_GP(play).raw_modified[i])
 			serialize_bitmap(_GP(thisroom).BgFrames[i].Graphic.get(), out.get());
 	}
-	out->WriteBool(raw_saved_screen != nullptr);
-	if (raw_saved_screen)
-		serialize_bitmap(raw_saved_screen, out.get());
+	out->WriteBool(_G(raw_saved_screen) != nullptr);
+	if (_G(raw_saved_screen))
+		serialize_bitmap(_G(raw_saved_screen), out.get());
 
 	// room region state
 	for (int i = 0; i < MAX_ROOM_REGIONS; ++i) {
@@ -940,7 +938,7 @@ HSaveError ReadThisRoom(PStream in, int32_t cmp_ver, const PreservedParams &pp,
 			r_data.RoomBkgScene[i] = nullptr;
 	}
 	if (in->ReadBool())
-		raw_saved_screen = read_serialized_bitmap(in.get());
+		_G(raw_saved_screen) = read_serialized_bitmap(in.get());
 
 	// room region state
 	for (int i = 0; i < MAX_ROOM_REGIONS; ++i) {
diff --git a/engines/ags/engine/gui/cscidialog.cpp b/engines/ags/engine/gui/cscidialog.cpp
index 68d7d18edf..21aeead1d9 100644
--- a/engines/ags/engine/gui/cscidialog.cpp
+++ b/engines/ags/engine/gui/cscidialog.cpp
@@ -48,8 +48,6 @@ namespace AGS3 {
 using AGS::Shared::Bitmap;
 namespace BitmapHelper = AGS::Shared::BitmapHelper;
 
-extern IGraphicsDriver *gfxDriver;
-
 //-----------------------------------------------------------------------------
 // DIALOG SYSTEM STUFF below
 
diff --git a/engines/ags/engine/gui/guidialog.cpp b/engines/ags/engine/gui/guidialog.cpp
index 3943ac26dd..6294eaa07a 100644
--- a/engines/ags/engine/gui/guidialog.cpp
+++ b/engines/ags/engine/gui/guidialog.cpp
@@ -39,8 +39,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
-
 namespace {
 
 // TODO: store drawing surface inside old gui classes instead
@@ -93,14 +91,14 @@ Bitmap *get_gui_screen() {
 
 void clear_gui_screen() {
 	if (dialogDDB)
-		gfxDriver->DestroyDDB(dialogDDB);
+		_G(gfxDriver)->DestroyDDB(dialogDDB);
 	dialogDDB = nullptr;
 	delete windowBuffer;
 	windowBuffer = nullptr;
 }
 
 void refresh_gui_screen() {
-	gfxDriver->UpdateDDBFromBitmap(dialogDDB, windowBuffer, false);
+	_G(gfxDriver)->UpdateDDBFromBitmap(dialogDDB, windowBuffer, false);
 	render_graphics(dialogDDB, windowPosX, windowPosY);
 }
 
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index cabc5ba1bf..c5f901f319 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -84,11 +84,7 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern char pexbuf[STD_BUFFER_SIZE];
-extern IGraphicsDriver *gfxDriver;
-extern Bitmap **actsps;
 extern color palette[256];
-extern Bitmap **guibg;
-extern IDriverDependantBitmap **guibgbmp;
 
 #define ALLEGRO_KEYBOARD_HANDLER
 
@@ -569,23 +565,23 @@ void show_preload() {
 		Debug::Printf("Displaying preload image");
 		if (splashsc->GetColorDepth() == 8)
 			set_palette_range(temppal, 0, 255, 0);
-		if (gfxDriver->UsesMemoryBackBuffer())
-			gfxDriver->GetMemoryBackBuffer()->Clear();
+		if (_G(gfxDriver)->UsesMemoryBackBuffer())
+			_G(gfxDriver)->GetMemoryBackBuffer()->Clear();
 
 		const Rect &view = _GP(play).GetMainViewport();
 		Bitmap *tsc = BitmapHelper::CreateBitmapCopy(splashsc, _GP(game).GetColorDepth());
-		if (!gfxDriver->HasAcceleratedTransform() && view.GetSize() != tsc->GetSize()) {
+		if (!_G(gfxDriver)->HasAcceleratedTransform() && view.GetSize() != tsc->GetSize()) {
 			Bitmap *stretched = new Bitmap(view.GetWidth(), view.GetHeight(), tsc->GetColorDepth());
 			stretched->StretchBlt(tsc, RectWH(0, 0, view.GetWidth(), view.GetHeight()));
 			delete tsc;
 			tsc = stretched;
 		}
-		IDriverDependantBitmap *ddb = gfxDriver->CreateDDBFromBitmap(tsc, false, true);
+		IDriverDependantBitmap *ddb = _G(gfxDriver)->CreateDDBFromBitmap(tsc, false, true);
 		ddb->SetStretch(view.GetWidth(), view.GetHeight());
-		gfxDriver->ClearDrawLists();
-		gfxDriver->DrawSprite(0, 0, ddb);
+		_G(gfxDriver)->ClearDrawLists();
+		_G(gfxDriver)->DrawSprite(0, 0, ddb);
 		render_to_screen();
-		gfxDriver->DestroyDDB(ddb);
+		_G(gfxDriver)->DestroyDDB(ddb);
 		delete splashsc;
 		delete tsc;
 		_G(platform)->Delay(500);
@@ -616,7 +612,7 @@ void engine_init_game_settings() {
 	int ee;
 
 	for (ee = 0; ee < MAX_ROOM_OBJECTS + _GP(game).numcharacters; ee++)
-		actsps[ee] = nullptr;
+		_G(actsps)[ee] = nullptr;
 
 	for (ee = 0; ee < 256; ee++) {
 		if (_GP(game).paluses[ee] != PAL_BACKGROUND)
@@ -683,11 +679,11 @@ void engine_init_game_settings() {
 		_G(charextra)[ee].animwait = 0;
 	}
 	// multiply up gui positions
-	guibg = (Bitmap **)malloc(sizeof(Bitmap *) * _GP(game).numgui);
-	guibgbmp = (IDriverDependantBitmap **)malloc(sizeof(IDriverDependantBitmap *) * _GP(game).numgui);
+	_G(guibg) = (Bitmap **)malloc(sizeof(Bitmap *) * _GP(game).numgui);
+	_G(guibgbmp) = (IDriverDependantBitmap **)malloc(sizeof(IDriverDependantBitmap *) * _GP(game).numgui);
 	for (ee = 0; ee < _GP(game).numgui; ee++) {
-		guibg[ee] = nullptr;
-		guibgbmp[ee] = nullptr;
+		_G(guibg)[ee] = nullptr;
+		_G(guibgbmp)[ee] = nullptr;
 	}
 
 	_G(our_eip) = -5;
@@ -1258,11 +1254,11 @@ bool engine_try_set_gfxmode_any(const ScreenSetup &setup) {
 }
 
 bool engine_try_switch_windowed_gfxmode() {
-	if (!gfxDriver || !gfxDriver->IsModeSet())
+	if (!_G(gfxDriver) || !_G(gfxDriver)->IsModeSet())
 		return false;
 
 	// Keep previous mode in case we need to revert back
-	DisplayMode old_dm = gfxDriver->GetDisplayMode();
+	DisplayMode old_dm = _G(gfxDriver)->GetDisplayMode();
 	GameFrameSetup old_frame = graphics_mode_get_render_frame();
 
 	// Release engine resources that depend on display mode
@@ -1300,7 +1296,7 @@ bool engine_try_switch_windowed_gfxmode() {
 	if (res) {
 		// If succeeded (with any case), update engine objects that rely on
 		// active display mode.
-		if (gfxDriver->GetDisplayMode().Windowed)
+		if (_G(gfxDriver)->GetDisplayMode().Windowed)
 			init_desktop = get_desktop_size();
 		engine_post_gfxmode_setup(init_desktop);
 	}
@@ -1309,7 +1305,7 @@ bool engine_try_switch_windowed_gfxmode() {
 }
 
 void engine_shutdown_gfxmode() {
-	if (!gfxDriver)
+	if (!_G(gfxDriver))
 		return;
 
 	engine_pre_gfxsystem_shutdown();
diff --git a/engines/ags/engine/main/engine_setup.cpp b/engines/ags/engine/main/engine_setup.cpp
index ebb3d0328f..6e790b5198 100644
--- a/engines/ags/engine/main/engine_setup.cpp
+++ b/engines/ags/engine/main/engine_setup.cpp
@@ -51,7 +51,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern int _places_r, _places_g, _places_b;
-extern IGraphicsDriver *gfxDriver;
 
 // Convert guis position and size to proper game resolution.
 // Necessary for pre 3.1.0 games only to sync with modern engine.
@@ -143,17 +142,17 @@ void engine_init_resolution_settings(const Size game_size) {
 
 // Setup gfx driver callbacks and options
 void engine_post_gfxmode_driver_setup() {
-	gfxDriver->SetCallbackForPolling(update_polled_stuff_if_runtime);
-	gfxDriver->SetCallbackToDrawScreen(draw_game_screen_callback, construct_engine_overlay);
-	gfxDriver->SetCallbackForNullSprite(GfxDriverNullSpriteCallback);
+	_G(gfxDriver)->SetCallbackForPolling(update_polled_stuff_if_runtime);
+	_G(gfxDriver)->SetCallbackToDrawScreen(draw_game_screen_callback, construct_engine_overlay);
+	_G(gfxDriver)->SetCallbackForNullSprite(GfxDriverNullSpriteCallback);
 }
 
 // Reset gfx driver callbacks
 void engine_pre_gfxmode_driver_cleanup() {
-	gfxDriver->SetCallbackForPolling(nullptr);
-	gfxDriver->SetCallbackToDrawScreen(nullptr, nullptr);
-	gfxDriver->SetCallbackForNullSprite(nullptr);
-	gfxDriver->SetMemoryBackBuffer(nullptr);
+	_G(gfxDriver)->SetCallbackForPolling(nullptr);
+	_G(gfxDriver)->SetCallbackToDrawScreen(nullptr, nullptr);
+	_G(gfxDriver)->SetCallbackForNullSprite(nullptr);
+	_G(gfxDriver)->SetMemoryBackBuffer(nullptr);
 }
 
 // Setup virtual screen
@@ -296,7 +295,7 @@ void engine_setup_scsystem_screen(const DisplayMode &dm) {
 }
 
 void engine_post_gfxmode_setup(const Size &init_desktop) {
-	DisplayMode dm = gfxDriver->GetDisplayMode();
+	DisplayMode dm = _G(gfxDriver)->GetDisplayMode();
 	// If color depth has changed (or graphics mode was inited for the
 	// very first time), we also need to recreate bitmaps
 	bool has_driver_changed = _GP(scsystem).coldepth != dm.ColorDepth;
diff --git a/engines/ags/engine/main/graphics_mode.cpp b/engines/ags/engine/main/graphics_mode.cpp
index d06bd38f60..36153b71b4 100644
--- a/engines/ags/engine/main/graphics_mode.cpp
+++ b/engines/ags/engine/main/graphics_mode.cpp
@@ -50,9 +50,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-
-extern IGraphicsDriver *gfxDriver;
-
 GameFrameSetup::GameFrameSetup()
 	: ScaleDef(kFrame_IntScale)
 	, ScaleFactor(1) {
@@ -99,12 +96,12 @@ bool create_gfx_driver(const String &gfx_driver_id) {
 		return false;
 	}
 	Debug::Printf("Using graphics factory: %s", gfx_driver_id.GetCStr());
-	gfxDriver = _G(GfxFactory)->GetDriver();
-	if (!gfxDriver) {
+	_G(gfxDriver) = _G(GfxFactory)->GetDriver();
+	if (!_G(gfxDriver)) {
 		Debug::Printf(kDbgMsg_Error, "Failed to create graphics driver. Error: %s", get_allegro_error());
 		return false;
 	}
-	Debug::Printf("Created graphics driver: %s", gfxDriver->GetDriverName());
+	Debug::Printf("Created graphics driver: %s", _G(gfxDriver)->GetDriverName());
 	return true;
 }
 
@@ -262,7 +259,7 @@ bool try_init_compatible_mode(const DisplayMode &dm, const bool match_device_rat
 		Debug::Printf("Maximal allowed window size: %d x %d", device_size.Width, device_size.Height);
 	DisplayMode dm_compat = dm;
 
-	std::unique_ptr<IGfxModeList> modes(gfxDriver->GetSupportedModeList(dm.ColorDepth));  // TODO: use unique_ptr when available
+	std::unique_ptr<IGfxModeList> modes(_G(gfxDriver)->GetSupportedModeList(dm.ColorDepth));  // TODO: use unique_ptr when available
 
 	// Windowed mode
 	if (dm.Windowed) {
@@ -323,7 +320,7 @@ bool try_init_mode_using_setup(const Size &game_size, const DisplayModeSetup &dm
 }
 
 void log_out_driver_modes(const int color_depth) {
-	IGfxModeList *modes = gfxDriver->GetSupportedModeList(color_depth);
+	IGfxModeList *modes = _G(gfxDriver)->GetSupportedModeList(color_depth);
 	if (!modes) {
 		Debug::Printf(kDbgMsg_Error, "Couldn't get a list of supported resolutions for color depth = %d", color_depth);
 		return;
@@ -357,7 +354,7 @@ bool create_gfx_driver_and_init_mode_any(const String &gfx_driver_id, const Size
 		return false;
 
 	const int use_col_depth =
-		color_depth.Forced ? color_depth.Bits : gfxDriver->GetDisplayDepthForNativeDepth(color_depth.Bits);
+		color_depth.Forced ? color_depth.Bits : _G(gfxDriver)->GetDisplayDepthForNativeDepth(color_depth.Bits);
 	// Log out supported driver modes
 	log_out_driver_modes(use_col_depth);
 
@@ -384,7 +381,7 @@ bool simple_create_gfx_driver_and_init_mode(const String &gfx_driver_id,
 		return false;
 	}
 
-	const int col_depth = gfxDriver->GetDisplayDepthForNativeDepth(color_depth.Bits);
+	const int col_depth = _G(gfxDriver)->GetDisplayDepthForNativeDepth(color_depth.Bits);
 
 	DisplayMode dm(GraphicResolution(game_size.Width, game_size.Height, col_depth),
 		dm_setup.Windowed, dm_setup.RefreshRate, dm_setup.VSync);
@@ -412,7 +409,7 @@ void display_gfx_mode_error(const Size &game_size, const ScreenSetup &setup, con
 
 	String main_error;
 	ScreenSizeSetup scsz = setup.DisplayMode.ScreenSize;
-	PGfxFilter filter = gfxDriver ? gfxDriver->GetGraphicsFilter() : PGfxFilter();
+	PGfxFilter filter = _G(gfxDriver) ? _G(gfxDriver)->GetGraphicsFilter() : PGfxFilter();
 	Size wanted_screen;
 	if (scsz.SizeDef == kScreenDef_Explicit)
 		main_error.Format("There was a problem initializing graphics mode %d x %d (%d-bit), or finding nearest compatible mode, with game size %d x %d and filter '%s'.",
@@ -498,11 +495,11 @@ bool graphics_mode_create_renderer(const String &driver_id) {
 	if (!create_gfx_driver(driver_id))
 		return false;
 
-	gfxDriver->SetCallbackOnInit(GfxDriverOnInitCallback);
-	gfxDriver->SetCallbackOnSurfaceUpdate(GfxDriverOnSurfaceUpdate);
+	_G(gfxDriver)->SetCallbackOnInit(GfxDriverOnInitCallback);
+	_G(gfxDriver)->SetCallbackOnSurfaceUpdate(GfxDriverOnSurfaceUpdate);
 	// TODO: this is remains of the old code; find out if this is really
 	// the best time and place to set the tint method
-	gfxDriver->SetTintMethod(TintReColourise);
+	_G(gfxDriver)->SetTintMethod(TintReColourise);
 	return true;
 }
 
@@ -527,12 +524,12 @@ bool graphics_mode_set_dm(const DisplayMode &dm) {
 	if (dm.RefreshRate >= 50)
 		request_refresh_rate(dm.RefreshRate);
 
-	if (!gfxDriver->SetDisplayMode(dm, nullptr)) {
+	if (!_G(gfxDriver)->SetDisplayMode(dm, nullptr)) {
 		Debug::Printf(kDbgMsg_Error, "Failed to init gfx mode. Error: %s", get_allegro_error());
 		return false;
 	}
 
-	DisplayMode rdm = gfxDriver->GetDisplayMode();
+	DisplayMode rdm = _G(gfxDriver)->GetDisplayMode();
 	if (rdm.Windowed)
 		_GP(SavedWindowedSetting).Dm = rdm;
 	else
@@ -543,37 +540,37 @@ bool graphics_mode_set_dm(const DisplayMode &dm) {
 }
 
 bool graphics_mode_update_render_frame() {
-	if (!gfxDriver || !gfxDriver->IsModeSet() || !gfxDriver->IsNativeSizeValid())
+	if (!_G(gfxDriver) || !_G(gfxDriver)->IsModeSet() || !_G(gfxDriver)->IsNativeSizeValid())
 		return false;
 
-	DisplayMode dm = gfxDriver->GetDisplayMode();
+	DisplayMode dm = _G(gfxDriver)->GetDisplayMode();
 	Size screen_size = Size(dm.Width, dm.Height);
-	Size native_size = gfxDriver->GetNativeSize();
+	Size native_size = _G(gfxDriver)->GetNativeSize();
 	Size frame_size = set_game_frame_after_screen_size(native_size, screen_size, _GP(CurFrameSetup));
 	Rect render_frame = CenterInRect(RectWH(screen_size), RectWH(frame_size));
 
-	if (!gfxDriver->SetRenderFrame(render_frame)) {
+	if (!_G(gfxDriver)->SetRenderFrame(render_frame)) {
 		Debug::Printf(kDbgMsg_Error, "Failed to set render frame (%d, %d, %d, %d : %d x %d). Error: %s",
 			render_frame.Left, render_frame.Top, render_frame.Right, render_frame.Bottom,
 			render_frame.GetWidth(), render_frame.GetHeight(), get_allegro_error());
 		return false;
 	}
 
-	Rect dst_rect = gfxDriver->GetRenderDestination();
+	Rect dst_rect = _G(gfxDriver)->GetRenderDestination();
 	Debug::Printf("Render frame set, render dest (%d, %d, %d, %d : %d x %d)",
 		dst_rect.Left, dst_rect.Top, dst_rect.Right, dst_rect.Bottom, dst_rect.GetWidth(), dst_rect.GetHeight());
 	// init game scaling transformation
-	_GP(GameScaling).Init(native_size, gfxDriver->GetRenderDestination());
+	_GP(GameScaling).Init(native_size, _G(gfxDriver)->GetRenderDestination());
 	return true;
 }
 
 bool graphics_mode_set_native_size(const Size &native_size) {
-	if (!gfxDriver || native_size.IsNull())
+	if (!_G(gfxDriver) || native_size.IsNull())
 		return false;
-	if (!gfxDriver->SetNativeSize(native_size))
+	if (!_G(gfxDriver)->SetNativeSize(native_size))
 		return false;
 	// if render frame translation was already set, then update it with new native size
-	if (gfxDriver->IsRenderFrameValid())
+	if (_G(gfxDriver)->IsRenderFrameValid())
 		graphics_mode_update_render_frame();
 	return true;
 }
@@ -586,7 +583,7 @@ bool graphics_mode_set_render_frame(const GameFrameSetup &frame_setup) {
 	if (!frame_setup.IsValid())
 		return false;
 	_GP(CurFrameSetup) = frame_setup;
-	if (gfxDriver->GetDisplayMode().Windowed)
+	if (_G(gfxDriver)->GetDisplayMode().Windowed)
 		_GP(SavedWindowedSetting).FrameSetup = frame_setup;
 	else
 		_GP(SavedFullscreenSetting).FrameSetup = frame_setup;
@@ -614,7 +611,7 @@ void graphics_mode_shutdown() {
 	if (_G(GfxFactory))
 		_G(GfxFactory)->Shutdown();
 	_G(GfxFactory) = nullptr;
-	gfxDriver = nullptr;
+	_G(gfxDriver) = nullptr;
 
 	// Tell Allegro that we are no longer in graphics mode
 	set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index 0fef30aebf..0f1589b5ff 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -57,7 +57,6 @@ using namespace AGS::Engine;
 extern char pexbuf[STD_BUFFER_SIZE];
 extern int need_to_stop_cd;
 extern int use_cdplayer;
-extern IGraphicsDriver *gfxDriver;
 
 // TODO: move to test unit
 extern Bitmap *test_allegro_bitmap;
@@ -197,7 +196,7 @@ void quit_delete_temp_files() {
 void allegro_bitmap_test_release() {
 	delete test_allegro_bitmap;
 	if (test_allegro_ddb)
-		gfxDriver->DestroyDDB(test_allegro_ddb);
+		_G(gfxDriver)->DestroyDDB(test_allegro_ddb);
 }
 
 // quit - exits the engine, shutting down everything gracefully
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index 4f07b387f4..5e2ba89620 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -54,8 +54,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
-
 int do_movelist_move(int16_t *mlnum, int32_t *xx, int32_t *yy) {
 	int need_to_fix_sprite = 0;
 	if (mlnum[0] < 1) quit("movelist_move: attempted to move on a non-exist movelist");
@@ -416,7 +414,7 @@ void update_sierra_speech() {
 				DrawViewFrame(frame_pic, blink_vf, view_frame_x, view_frame_y, face_has_alpha);
 			}
 
-			gfxDriver->UpdateDDBFromBitmap(_GP(screenover)[_G(face_talking)].bmp, _GP(screenover)[_G(face_talking)].pic, face_has_alpha);
+			_G(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/platform/windows/acplwin.cpp b/engines/ags/engine/platform/windows/acplwin.cpp
index 54ca3377ea..5222ef878a 100644
--- a/engines/ags/engine/platform/windows/acplwin.cpp
+++ b/engines/ags/engine/platform/windows/acplwin.cpp
@@ -54,8 +54,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern GameSetup usetup;
-extern int _G(our_eip);
-extern IGraphicsDriver *gfxDriver;
 extern color palette[256];
 
 //include <shlobj.h>
@@ -962,7 +960,7 @@ LPDIRECTDRAWSURFACE2 IAGSEngine::GetBitmapSurface(BITMAP *bmp) {
 
 	BMP_EXTRA_INFO *bei = (BMP_EXTRA_INFO *)bmp->extra;
 
-	if (bmp == gfxDriver->GetMemoryBackBuffer()->GetAllegroBitmap())
+	if (bmp == _G(gfxDriver)->GetMemoryBackBuffer()->GetAllegroBitmap())
 		invalidate_screen();
 
 	return bei->surf;
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 6c92da4c78..1c88231bf7 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -127,6 +127,9 @@ Globals::Globals() {
 	_CameraDrawData = new std::vector<RoomCameraDrawData>();
 	_sprlist = new std::vector<SpriteListEntry>();
 	_thingsToDrawList = new std::vector<SpriteListEntry>();
+	_dynamicallyCreatedSurfaces = new AGS::Shared::Bitmap *[MAX_DYNAMIC_SURFACES];
+	Common::fill(_dynamicallyCreatedSurfaces, _dynamicallyCreatedSurfaces +
+		MAX_DYNAMIC_SURFACES, (AGS::Shared::Bitmap *)nullptr);
 
 	// draw_software.cpp globals
 	_BlackRects = new DirtyRects();
@@ -280,6 +283,7 @@ Globals::~Globals() {
 	delete _CameraDrawData;
 	delete _sprlist;
 	delete _thingsToDrawList;
+	delete[] _dynamicallyCreatedSurfaces;
 
 	// draw_software.cpp globals
 	delete _BlackRects;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 2ac9bfb349..43fa5ed096 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -65,7 +65,9 @@ class RoomStruct;
 namespace Engine {
 
 class ConsoleOutputTarget;
+class IDriverDependantBitmap;
 class IGfxDriverFactory;
+class IGraphicsDriver;
 class LogFile;
 class MessageBuffer;
 struct PlaneScaling;
@@ -84,6 +86,7 @@ struct AGSDeSerializer;
 struct AGSPlatformDriver;
 struct AmbientSound;
 struct AnimatingGUIButton;
+struct CachedActSpsData;
 struct CCAudioChannel;
 struct CCAudioClip;
 struct CCCharacter;
@@ -373,6 +376,31 @@ public:
 	std::vector<SpriteListEntry> *_sprlist;
 	std::vector<SpriteListEntry> *_thingsToDrawList;
 
+	AGS::Engine::IGraphicsDriver *_gfxDriver = nullptr;
+	AGS::Engine::IDriverDependantBitmap *_blankImage = nullptr;
+	AGS::Engine::IDriverDependantBitmap *_blankSidebarImage = nullptr;
+	AGS::Engine::IDriverDependantBitmap *_debugConsole = nullptr;
+
+	// actsps is used for temporary storage of the bitamp image
+	// of the latest version of the sprite
+	int _actSpsCount = 0;
+	AGS::Shared::Bitmap **_actsps = nullptr;
+	AGS::Engine::IDriverDependantBitmap **_actspsbmp = nullptr;
+	// temporary cache of walk-behind for this actsps image
+	AGS::Shared::Bitmap **_actspswb = nullptr;
+	AGS::Engine::IDriverDependantBitmap **_actspswbbmp = nullptr;
+	CachedActSpsData *_actspswbcache = nullptr;
+	bool _current_background_is_dirty = false;
+	// Room background sprite
+	AGS::Engine::IDriverDependantBitmap *_roomBackgroundBmp = nullptr;
+	AGS::Shared::Bitmap **_guibg = nullptr;
+	AGS::Engine::IDriverDependantBitmap **_guibgbmp = nullptr;
+	AGS::Shared::Bitmap *_debugConsoleBuffer = nullptr;
+	// whether there are currently remnants of a DisplaySpeech
+	bool _screen_is_dirty = false;
+	AGS::Shared::Bitmap *_raw_saved_screen = nullptr;
+	AGS::Shared::Bitmap **_dynamicallyCreatedSurfaces = nullptr;
+
 	/**@}*/
 
 	/**
diff --git a/engines/ags/plugins/agsplugin.cpp b/engines/ags/plugins/agsplugin.cpp
index 4e1dda63de..521a3ab0c7 100644
--- a/engines/ags/plugins/agsplugin.cpp
+++ b/engines/ags/plugins/agsplugin.cpp
@@ -84,7 +84,6 @@ using namespace AGS::Shared;
 using namespace AGS::Shared::Memory;
 using namespace AGS::Engine;
 
-extern IGraphicsDriver *gfxDriver;
 extern int game_paused;
 extern color palette[256];
 extern PluginObjectReader pluginReaders[MAX_PLUGIN_OBJECT_READERS];
@@ -159,23 +158,23 @@ void IAGSEngine::RegisterScriptFunction(const char *name, void *addy) {
 	ccAddExternalPluginFunction(name, addy);
 }
 const char *IAGSEngine::GetGraphicsDriverID() {
-	if (gfxDriver == nullptr)
+	if (_G(gfxDriver) == nullptr)
 		return nullptr;
 
-	return gfxDriver->GetDriverID();
+	return _G(gfxDriver)->GetDriverID();
 }
 
 BITMAP *IAGSEngine::GetScreen() {
 	// TODO: we could actually return stage buffer here, will that make a difference?
-	if (!gfxDriver->UsesMemoryBackBuffer())
+	if (!_G(gfxDriver)->UsesMemoryBackBuffer())
 		quit("!This plugin requires software graphics driver.");
 
-	Bitmap *buffer = gfxDriver->GetMemoryBackBuffer();
+	Bitmap *buffer = _G(gfxDriver)->GetMemoryBackBuffer();
 	return buffer ? (BITMAP *)buffer->GetAllegroBitmap() : nullptr;
 }
 
 BITMAP *IAGSEngine::GetVirtualScreen() {
-	Bitmap *stage = gfxDriver->GetStageBackBuffer();
+	Bitmap *stage = _G(gfxDriver)->GetStageBackBuffer();
 	return stage ? (BITMAP *)stage->GetAllegroBitmap() : nullptr;
 }
 
@@ -227,7 +226,7 @@ int IAGSEngine::GetSavedData(char *buffer, int32 bufsize) {
 }
 
 void IAGSEngine::DrawText(int32 x, int32 y, int32 font, int32 color, const char *text) {
-	Bitmap *ds = gfxDriver->GetStageBackBuffer();
+	Bitmap *ds = _G(gfxDriver)->GetStageBackBuffer();
 	if (!ds)
 		return;
 	color_t text_color = ds->GetCompatibleColor(color);
@@ -248,7 +247,7 @@ uint8 *IAGSEngine::GetRawBitmapSurface(BITMAP *bmp) {
 		quit("!IAGSEngine::GetRawBitmapSurface: invalid bitmap for access to surface");
 	acquire_bitmap(bmp);
 
-	Bitmap *stage = gfxDriver->GetStageBackBuffer();
+	Bitmap *stage = _G(gfxDriver)->GetStageBackBuffer();
 	if (stage && bmp == stage->GetAllegroBitmap())
 		plugins[this->pluginId].invalidatedRegion = 0;
 
@@ -262,7 +261,7 @@ int IAGSEngine::GetBitmapPitch(BITMAP *bmp) {
 void IAGSEngine::ReleaseBitmapSurface(BITMAP *bmp) {
 	release_bitmap(bmp);
 
-	Bitmap *stage = gfxDriver->GetStageBackBuffer();
+	Bitmap *stage = _G(gfxDriver)->GetStageBackBuffer();
 	if (stage && bmp == stage->GetAllegroBitmap()) {
 		// plugin does not manaually invalidate stuff, so
 		// we must invalidate the whole screen to be safe
@@ -342,7 +341,7 @@ void IAGSEngine::DrawTextWrapped(int32 xx, int32 yy, int32 wid, int32 font, int3
 	if (break_up_text_into_lines(text, _GP(fontLines), wid, font) == 0)
 		return;
 
-	Bitmap *ds = gfxDriver->GetStageBackBuffer();
+	Bitmap *ds = _G(gfxDriver)->GetStageBackBuffer();
 	if (!ds)
 		return;
 	color_t text_color = ds->GetCompatibleColor(color);
@@ -353,17 +352,17 @@ void IAGSEngine::DrawTextWrapped(int32 xx, int32 yy, int32 wid, int32 font, int3
 
 Bitmap glVirtualScreenWrap;
 void IAGSEngine::SetVirtualScreen(BITMAP *bmp) {
-	if (!gfxDriver->UsesMemoryBackBuffer()) {
+	if (!_G(gfxDriver)->UsesMemoryBackBuffer()) {
 		debug_script_warn("SetVirtualScreen: this plugin requires software graphics driver to work correctly.");
-		// we let it continue since gfxDriver is supposed to ignore this request without throwing an exception
+		// we let it continue since _G(gfxDriver) is supposed to ignore this request without throwing an exception
 	}
 
 	if (bmp) {
 		glVirtualScreenWrap.WrapAllegroBitmap(bmp, true);
-		gfxDriver->SetMemoryBackBuffer(&glVirtualScreenWrap);
+		_G(gfxDriver)->SetMemoryBackBuffer(&glVirtualScreenWrap);
 	} else {
 		glVirtualScreenWrap.Destroy();
-		gfxDriver->SetMemoryBackBuffer(nullptr);
+		_G(gfxDriver)->SetMemoryBackBuffer(nullptr);
 	}
 }
 
@@ -372,7 +371,7 @@ int IAGSEngine::LookupParserWord(const char *word) {
 }
 
 void IAGSEngine::BlitBitmap(int32 x, int32 y, BITMAP *bmp, int32 masked) {
-	Bitmap *ds = gfxDriver->GetStageBackBuffer();
+	Bitmap *ds = _G(gfxDriver)->GetStageBackBuffer();
 	if (!ds)
 		return;
 	wputblock_raw(ds, x, y, bmp, masked);
@@ -380,18 +379,18 @@ void IAGSEngine::BlitBitmap(int32 x, int32 y, BITMAP *bmp, int32 masked) {
 }
 
 void IAGSEngine::BlitSpriteTranslucent(int32 x, int32 y, BITMAP *bmp, int32 trans) {
-	Bitmap *ds = gfxDriver->GetStageBackBuffer();
+	Bitmap *ds = _G(gfxDriver)->GetStageBackBuffer();
 	if (!ds)
 		return;
 	Bitmap wrap(bmp, true);
-	if (gfxDriver->UsesMemoryBackBuffer())
+	if (_G(gfxDriver)->UsesMemoryBackBuffer())
 		GfxUtil::DrawSpriteWithTransparency(ds, &wrap, x, y, trans);
 	else
 		GfxUtil::DrawSpriteBlend(ds, Point(x, y), &wrap, kBlendMode_Alpha, true, false, trans);
 }
 
 void IAGSEngine::BlitSpriteRotated(int32 x, int32 y, BITMAP *bmp, int32 angle) {
-	Bitmap *ds = gfxDriver->GetStageBackBuffer();
+	Bitmap *ds = _G(gfxDriver)->GetStageBackBuffer();
 	if (!ds)
 		return;
 	// FIXME: call corresponding Graphics Blit


Commit: dbdac3c3cfe2f50ac4379aec86a858bedc75179c
    https://github.com/scummvm/scummvm/commit/dbdac3c3cfe2f50ac4379aec86a858bedc75179c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:14:03-08:00

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

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/object.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/walkablearea.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 9afc2a0c28..11aacf232c 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -79,8 +79,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern Bitmap *walkable_areas_temp;
-
 // **** CHARACTER: FUNCTIONS ****
 
 void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addIndex) {
@@ -2150,8 +2148,8 @@ void get_char_blocking_rect(int charid, int *x1, int *y1, int *width, int *y2) {
 		cwidth += fromx;
 		fromx = 0;
 	}
-	if (fromx + cwidth >= mask_to_room_coord(walkable_areas_temp->GetWidth()))
-		cwidth = mask_to_room_coord(walkable_areas_temp->GetWidth()) - fromx;
+	if (fromx + cwidth >= mask_to_room_coord(_G(walkable_areas_temp)->GetWidth()))
+		cwidth = mask_to_room_coord(_G(walkable_areas_temp)->GetWidth()) - fromx;
 
 	if (x1)
 		*x1 = fromx;
diff --git a/engines/ags/engine/ac/object.cpp b/engines/ags/engine/ac/object.cpp
index d599ab3d78..771f2e4be8 100644
--- a/engines/ags/engine/ac/object.cpp
+++ b/engines/ags/engine/ac/object.cpp
@@ -55,8 +55,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-extern Bitmap *walkable_areas_temp;
-
 int Object_IsCollidingWithObject(ScriptObject *objj, ScriptObject *obj2) {
 	return AreObjectsColliding(objj->id, obj2->id);
 }
@@ -474,8 +472,8 @@ void get_object_blocking_rect(int objid, int *x1, int *y1, int *width, int *y2)
 		cwidth += fromx;
 		fromx = 0;
 	}
-	if (fromx + cwidth >= mask_to_room_coord(walkable_areas_temp->GetWidth()))
-		cwidth = mask_to_room_coord(walkable_areas_temp->GetWidth()) - fromx;
+	if (fromx + cwidth >= mask_to_room_coord(_G(walkable_areas_temp)->GetWidth()))
+		cwidth = mask_to_room_coord(_G(walkable_areas_temp)->GetWidth()) - fromx;
 
 	if (x1)
 		*x1 = fromx;
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 4c544ae53b..53345a5954 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -85,7 +85,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern Bitmap *walkareabackup, *walkable_areas_temp;
 extern color palette[256];
 extern int mouse_z_was;
 
@@ -485,16 +484,16 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
 	_G(our_eip) = 203;
 	_G(in_new_room) = 1;
 
-	// walkable_areas_temp is used by the pathfinder to generate a
+	// _G(walkable_areas_temp) is used by the pathfinder to generate a
 	// copy of the walkable areas - allocate it here to save time later
-	delete walkable_areas_temp;
-	walkable_areas_temp = BitmapHelper::CreateBitmap(_GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight(), 8);
+	delete _G(walkable_areas_temp);
+	_G(walkable_areas_temp) = BitmapHelper::CreateBitmap(_GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight(), 8);
 
 	// Make a backup copy of the walkable areas prior to
 	// any RemoveWalkableArea commands
-	delete walkareabackup;
+	delete _G(walkareabackup);
 	// copy the walls screen
-	walkareabackup = BitmapHelper::CreateBitmapCopy(_GP(thisroom).WalkAreaMask.get());
+	_G(walkareabackup) = BitmapHelper::CreateBitmapCopy(_GP(thisroom).WalkAreaMask.get());
 
 	_G(our_eip) = 204;
 	update_polled_stuff_if_runtime();
diff --git a/engines/ags/engine/ac/walkablearea.cpp b/engines/ags/engine/ac/walkablearea.cpp
index 64bdd3eb5d..9551941bad 100644
--- a/engines/ags/engine/ac/walkablearea.cpp
+++ b/engines/ags/engine/ac/walkablearea.cpp
@@ -38,10 +38,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-
-
-Bitmap *walkareabackup = nullptr, *walkable_areas_temp = nullptr;
-
 void redo_walkable_areas() {
 
 	// since this is an 8-bit memory bitmap, we can just use direct
@@ -49,12 +45,12 @@ void redo_walkable_areas() {
 	if ((!_GP(thisroom).WalkAreaMask->IsLinearBitmap()) || (_GP(thisroom).WalkAreaMask->GetColorDepth() != 8))
 		quit("Walkable areas bitmap not linear");
 
-	_GP(thisroom).WalkAreaMask->Blit(walkareabackup, 0, 0, 0, 0, _GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight());
+	_GP(thisroom).WalkAreaMask->Blit(_G(walkareabackup), 0, 0, 0, 0, _GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight());
 
 	int hh, ww;
-	for (hh = 0; hh < walkareabackup->GetHeight(); hh++) {
+	for (hh = 0; hh < _G(walkareabackup)->GetHeight(); hh++) {
 		uint8_t *walls_scanline = _GP(thisroom).WalkAreaMask->GetScanLineForWriting(hh);
-		for (ww = 0; ww < walkareabackup->GetWidth(); ww++) {
+		for (ww = 0; ww < _G(walkareabackup)->GetWidth(); ww++) {
 			//      if (_GP(play).walkable_areas_on[_getpixel(_GP(thisroom).WalkAreaMask,ww,hh)]==0)
 			if (_GP(play).walkable_areas_on[walls_scanline[ww]] == 0)
 				walls_scanline[ww] = 0;
@@ -121,14 +117,14 @@ void remove_walkable_areas_from_temp(int fromx, int cwidth, int starty, int endy
 	endy = room_to_mask_coord(endy);
 
 	int yyy;
-	if (endy >= walkable_areas_temp->GetHeight())
-		endy = walkable_areas_temp->GetHeight() - 1;
+	if (endy >= _G(walkable_areas_temp)->GetHeight())
+		endy = _G(walkable_areas_temp)->GetHeight() - 1;
 	if (starty < 0)
 		starty = 0;
 
 	for (; cwidth > 0; cwidth--) {
 		for (yyy = starty; yyy <= endy; yyy++)
-			walkable_areas_temp->PutPixel(fromx, yyy, 0);
+			_G(walkable_areas_temp)->PutPixel(fromx, yyy, 0);
 		fromx++;
 	}
 
@@ -142,11 +138,11 @@ int is_point_in_rect(int x, int y, int left, int top, int right, int bottom) {
 
 Bitmap *prepare_walkable_areas(int sourceChar) {
 	// copy the walkable areas to the temp bitmap
-	walkable_areas_temp->Blit(_GP(thisroom).WalkAreaMask.get(), 0, 0, 0, 0, _GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight());
+	_G(walkable_areas_temp)->Blit(_GP(thisroom).WalkAreaMask.get(), 0, 0, 0, 0, _GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight());
 	// if the character who's moving doesn't Bitmap *, don't bother checking
 	if (sourceChar < 0);
 	else if (_GP(game).chars[sourceChar].flags & CHF_NOBLOCKING)
-		return walkable_areas_temp;
+		return _G(walkable_areas_temp);
 
 	int ww;
 	// for each character in the current room, make the area under
@@ -156,8 +152,8 @@ Bitmap *prepare_walkable_areas(int sourceChar) {
 		if (_GP(game).chars[ww].room != _G(displayed_room)) continue;
 		if (ww == sourceChar) continue;
 		if (_GP(game).chars[ww].flags & CHF_NOBLOCKING) continue;
-		if (room_to_mask_coord(_GP(game).chars[ww].y) >= walkable_areas_temp->GetHeight()) continue;
-		if (room_to_mask_coord(_GP(game).chars[ww].x) >= walkable_areas_temp->GetWidth()) continue;
+		if (room_to_mask_coord(_GP(game).chars[ww].y) >= _G(walkable_areas_temp)->GetHeight()) continue;
+		if (room_to_mask_coord(_GP(game).chars[ww].x) >= _G(walkable_areas_temp)->GetWidth()) continue;
 		if ((_GP(game).chars[ww].y < 0) || (_GP(game).chars[ww].x < 0)) continue;
 
 		CharacterInfo *char1 = &_GP(game).chars[ww];
@@ -177,8 +173,8 @@ Bitmap *prepare_walkable_areas(int sourceChar) {
 		if (_G(objs)[ww].on != 1) continue;
 		if ((_G(objs)[ww].flags & OBJF_SOLID) == 0)
 			continue;
-		if (room_to_mask_coord(_G(objs)[ww].y) >= walkable_areas_temp->GetHeight()) continue;
-		if (room_to_mask_coord(_G(objs)[ww].x) >= walkable_areas_temp->GetWidth()) continue;
+		if (room_to_mask_coord(_G(objs)[ww].y) >= _G(walkable_areas_temp)->GetHeight()) continue;
+		if (room_to_mask_coord(_G(objs)[ww].x) >= _G(walkable_areas_temp)->GetWidth()) continue;
 		if ((_G(objs)[ww].y < 0) || (_G(objs)[ww].x < 0)) continue;
 
 		int x1, y1, width, y2;
@@ -194,7 +190,7 @@ Bitmap *prepare_walkable_areas(int sourceChar) {
 		remove_walkable_areas_from_temp(x1, width, y1, y2);
 	}
 
-	return walkable_areas_temp;
+	return _G(walkable_areas_temp);
 }
 
 // return the walkable area at the character's feet, taking into account
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 43fa5ed096..08cbdd9ab2 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -903,6 +903,15 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup walkablearea globals
+	 * @{
+	 */
+
+	AGS::Shared::Bitmap *_walkareabackup = nullptr, *_walkable_areas_temp = nullptr;
+
+	/**@}*/
+
 public:
 	Globals();
 	~Globals();


Commit: f6e83fa57e7054e1b0ab23f9bc54034fb8308e15
    https://github.com/scummvm/scummvm/commit/f6e83fa57e7054e1b0ab23f9bc54034fb8308e15
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:14:03-08:00

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

Changed paths:
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/sys_events.cpp
    engines/ags/globals.h
    engines/ags/plugins/agsplugin.cpp


diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 53345a5954..9e772c6266 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -86,7 +86,6 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern color palette[256];
-extern int mouse_z_was;
 
 RGB_MAP rgb_table;  // for 256-col antialiasing
 int new_room_flags = 0;
@@ -939,7 +938,7 @@ int find_highest_room_entered() {
 void first_room_initialization() {
 	_G(starting_room) = _G(displayed_room);
 	set_loop_counter(0);
-	mouse_z_was = _G(mouse_z);
+	_G(mouse_z_was) = _G(mouse_z);
 }
 
 void check_new_room() {
diff --git a/engines/ags/engine/ac/sys_events.cpp b/engines/ags/engine/ac/sys_events.cpp
index 55af823055..5f3ecc6176 100644
--- a/engines/ags/engine/ac/sys_events.cpp
+++ b/engines/ags/engine/ac/sys_events.cpp
@@ -40,14 +40,10 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 extern volatile unsigned long globalTimerCounter;
-int pluginSimulatedClick;
-
 extern void domouse(int str);
 extern int mgetbutton();
 extern int misbuttondown(int buno);
 
-int mouse_z_was = 0;
-
 int ags_kbhit() {
 	return keypressed();
 }
@@ -66,9 +62,9 @@ int ags_misbuttondown(int but) {
 int ags_mgetbutton() {
 	int result;
 
-	if (pluginSimulatedClick > NONE) {
-		result = pluginSimulatedClick;
-		pluginSimulatedClick = NONE;
+	if (_G(pluginSimulatedClick) > NONE) {
+		result = _G(pluginSimulatedClick);
+		_G(pluginSimulatedClick) = NONE;
 	} else {
 		result = mgetbutton();
 	}
@@ -85,12 +81,12 @@ void ags_domouse(int what) {
 
 int ags_check_mouse_wheel() {
 	int result = 0;
-	if ((_G(mouse_z) != mouse_z_was) && (_GP(game).options[OPT_MOUSEWHEEL] != 0)) {
-		if (_G(mouse_z) > mouse_z_was)
+	if ((_G(mouse_z) != _G(mouse_z_was)) && (_GP(game).options[OPT_MOUSEWHEEL] != 0)) {
+		if (_G(mouse_z) > _G(mouse_z_was))
 			result = 1;
 		else
 			result = -1;
-		mouse_z_was = _G(mouse_z);
+		_G(mouse_z_was) = _G(mouse_z);
 	}
 	return result;
 }
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 08cbdd9ab2..4dbf320143 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -903,6 +903,16 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup walkablearea globals
+	 * @{
+	 */
+
+	int _pluginSimulatedClick = 0;
+	int _mouse_z_was = 0;
+
+	/**@}*/
+
 	/**
 	 * \defgroup walkablearea globals
 	 * @{
diff --git a/engines/ags/plugins/agsplugin.cpp b/engines/ags/plugins/agsplugin.cpp
index 521a3ab0c7..1e2eb02226 100644
--- a/engines/ags/plugins/agsplugin.cpp
+++ b/engines/ags/plugins/agsplugin.cpp
@@ -89,10 +89,9 @@ extern color palette[256];
 extern PluginObjectReader pluginReaders[MAX_PLUGIN_OBJECT_READERS];
 extern int numPluginReaders;
 extern RuntimeScriptValue GlobalReturnValue;
-extern int pluginSimulatedClick;
 
 void PluginSimulateMouseClick(int pluginButtonID) {
-	pluginSimulatedClick = pluginButtonID - 1;
+	_G(pluginSimulatedClick) = pluginButtonID - 1;
 }
 
 // **************** PLUGIN IMPLEMENTATION ****************


Commit: b38289e5aa99a3b542d2a6ec23cb23220da39ab8
    https://github.com/scummvm/scummvm/commit/b38289e5aa99a3b542d2a6ec23cb23220da39ab8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:14:04-08:00

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

Changed paths:
    engines/ags/engine/ac/global_room.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index f9e280d9db..7c8a01aa81 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -45,8 +45,6 @@ namespace AGS3 {
 using namespace Shared;
 
 extern int in_inv_screen, inv_screen_newroom;
-extern int gs_to_newroom;
-
 
 void SetAmbientTint(int red, int green, int blue, int opacity, int luminance) {
 	if ((red < 0) || (green < 0) || (blue < 0) ||
@@ -125,7 +123,7 @@ void NewRoom(int nrnum) {
 			StopMoving(_GP(game).playercharacter);
 		}
 	} else if (_G(in_graph_script))
-		gs_to_newroom = nrnum;
+		_G(gs_to_newroom) = nrnum;
 }
 
 
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 9e772c6266..25ec79ca78 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -87,10 +87,6 @@ using namespace AGS::Engine;
 
 extern color palette[256];
 
-RGB_MAP rgb_table;  // for 256-col antialiasing
-int new_room_flags = 0;
-int gs_to_newroom = -1;
-
 ScriptDrawingSurface *Room_GetDrawingSurfaceForBackground(int backgroundNumber) {
 	if (_G(displayed_room) < 0)
 		quit("!Room.GetDrawingSurfaceForBackground: no room is currently loaded");
@@ -650,8 +646,8 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
 			if (palette[ff].b > 63)
 				palette[ff].b = 63;
 		}
-		create_rgb_table(&rgb_table, palette, nullptr);
-		_G(rgb_map) = &rgb_table;
+		create_rgb_table(&_GP(rgb_table), palette, nullptr);
+		_G(rgb_map) = &_GP(rgb_table);
 	}
 	_G(our_eip) = 211;
 	if (forchar != nullptr) {
@@ -852,7 +848,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
 		if (_G(objs)[cc].on == 2)
 			MergeObject(cc);
 	}
-	new_room_flags = 0;
+	_G(new_room_flags) = 0;
 	_GP(play).gscript_timer = -1; // avoid screw-ups with changing screens
 	_GP(play).player_on_region = 0;
 	// trash any input which they might have done while it was loading
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 1c88231bf7..a81d4f4c47 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -223,6 +223,9 @@ Globals::Globals() {
 	// overlay.cpp globals
 	_screenover = new std::vector<ScreenOverlay>();
 
+	// room.cpp globals
+	_rgb_table = new RGB_MAP();
+
 	// route_finder_impl.cpp globals
 	_navpoints = new int32_t[MAXNEEDSTAGES];
 	_nav = new Navigation();
@@ -374,6 +377,9 @@ Globals::~Globals() {
 	// overlay.cpp globals
 	delete _screenover;
 
+	// room.cpp globals
+	delete _rgb_table;
+
 	// route_finder_impl.cpp globals
 	delete _navpoints;
 	delete _nav;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 4dbf320143..5bce83cc6e 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -834,6 +834,17 @@ public:
 
 	 /**@}*/
 
+	/**
+	 * \defgroup room globals
+	 * @{
+	 */
+
+	RGB_MAP *_rgb_table;  // for 256-col antialiasing
+	int _new_room_flags = 0;
+	int _gs_to_newroom = -1;
+
+	/**@}*/
+
 	/**
 	 * \defgroup route_finder_impl globals
 	 * @{


Commit: c7b1836e53bcb0866f7edbba3cb5f315e6df870e
    https://github.com/scummvm/scummvm/commit/c7b1836e53bcb0866f7edbba3cb5f315e6df870e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:14:04-08:00

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

Changed paths:
    engines/ags/engine/ac/global_room.cpp
    engines/ags/engine/ac/invwindow.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index 7c8a01aa81..02793bf22f 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -44,8 +44,6 @@ namespace AGS3 {
 
 using namespace Shared;
 
-extern int in_inv_screen, inv_screen_newroom;
-
 void SetAmbientTint(int red, int green, int blue, int opacity, int luminance) {
 	if ((red < 0) || (green < 0) || (blue < 0) ||
 		(red > 255) || (green > 255) || (blue > 255) ||
@@ -106,8 +104,8 @@ void NewRoom(int nrnum) {
 	} else if (_G(in_enters_screen)) {
 		setevent(EV_NEWROOM, nrnum);
 		return;
-	} else if (in_inv_screen) {
-		inv_screen_newroom = nrnum;
+	} else if (_G(in_inv_screen)) {
+		_G(inv_screen_newroom) = nrnum;
 		return;
 	} else if ((_G(inside_script) == 0) & (_G(in_graph_script) == 0)) {
 		new_room(nrnum, _G(playerchar));
diff --git a/engines/ags/engine/ac/invwindow.cpp b/engines/ags/engine/ac/invwindow.cpp
index d8abeb7b5b..0318a07a64 100644
--- a/engines/ags/engine/ac/invwindow.cpp
+++ b/engines/ags/engine/ac/invwindow.cpp
@@ -53,10 +53,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-int in_inv_screen = 0, inv_screen_newroom = -1;
-
-// *** INV WINDOW FUNCTIONS
-
 void InvWindow_SetCharacterToUse(GUIInvWindow *guii, CharacterInfo *chaa) {
 	if (chaa == nullptr)
 		guii->CharId = -1;
@@ -216,8 +212,8 @@ void InventoryScreen::Prepare() {
 	top_item = 0;
 	num_visible_items = 0;
 	MAX_ITEMAREA_HEIGHT = ((_GP(play).GetUIViewport().GetHeight() - BUTTONAREAHEIGHT) - get_fixed_pixel_size(20));
-	in_inv_screen++;
-	inv_screen_newroom = -1;
+	_G(in_inv_screen)++;
+	_G(inv_screen_newroom) = -1;
 
 	// Sprites 2041, 2042 and 2043 were hardcoded in the older versions of
 	// the engine to be used in the built-in inventory window.
@@ -242,13 +238,13 @@ int InventoryScreen::Redraw() {
 		update_invorder();
 	if (_G(charextra)[_GP(game).playercharacter].invorder_count == 0) {
 		DisplayMessage(996);
-		in_inv_screen--;
+		_G(in_inv_screen)--;
 		return -1;
 	}
 
-	if (inv_screen_newroom >= 0) {
-		in_inv_screen--;
-		NewRoom(inv_screen_newroom);
+	if (_G(inv_screen_newroom) >= 0) {
+		_G(in_inv_screen)--;
+		NewRoom(_G(inv_screen_newroom));
 		return -1;
 	}
 
@@ -480,7 +476,7 @@ void InventoryScreen::Close() {
 	clear_gui_screen();
 	set_default_cursor();
 	invalidate_screen();
-	in_inv_screen--;
+	_G(in_inv_screen)--;
 }
 
 int __actual_invscreen() {
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 5bce83cc6e..dce3f1b1e0 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -713,6 +713,15 @@ public:
 
 	/**@}*/
 
+	/**
+	 * \defgroup invwindow globals
+	 * @{
+	 */
+
+	int _in_inv_screen = 0, _inv_screen_newroom = -1;
+
+	/**@}*/
+
 	/**
 	 * \defgroup lzw globals
 	 * @{


Commit: a5c4876862027617e82b2385414971f796eda0f9
    https://github.com/scummvm/scummvm/commit/a5c4876862027617e82b2385414971f796eda0f9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-03-09T21:15:12-08:00

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

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/inventoryitem.cpp
    engines/ags/engine/ac/mouse.cpp
    engines/ags/engine/ac/mouse.h
    engines/ags/engine/device/mousew32.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/main/game_run.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 11aacf232c..0cf1e5b0a4 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -758,7 +758,7 @@ void Character_SetAsPlayer(CharacterInfo *chaa) {
 		_G(playerchar)->activeinv = -1;
 
 	// They had inv selected, so change the cursor
-	if (cur_mode == MODE_USE) {
+	if (_G(cur_mode) == MODE_USE) {
 		if (_G(playerchar)->activeinv < 0)
 			SetNextCursor();
 		else
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 15453b2b80..61d8d30003 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 int cur_mode, cur_cursor;
-
 void Dialog_Start(ScriptDialog *sd) {
 	RunDialog(sd->id);
 }
@@ -451,7 +449,7 @@ void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground) {
 	usingfont = FONT_NORMAL;
 	lineheight = getfontheight_outlined(usingfont);
 	linespacing = getfontspacing_outlined(usingfont);
-	curswas = cur_cursor;
+	curswas = _G(cur_cursor);
 	bullet_wid = 0;
 	ddb = nullptr;
 	subBitmap = nullptr;
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 8acfaf4c2b..5da672db75 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -97,10 +97,6 @@ extern IDriverDependantBitmap *walkBehindBitmap[MAX_WALK_BEHINDS];
 extern int walkBehindsCachedForBgNum;
 extern WalkBehindMethodEnum walkBehindMethod;
 extern int walk_behind_baselines_changed;
-extern int cur_mode, cur_cursor;
-extern int mouse_frame, mouse_delay;
-extern int lastmx, lastmy;
-extern IDriverDependantBitmap *mouseCursor;
 extern int bg_just_changed;
 
 color palette[256];
@@ -2133,41 +2129,41 @@ void construct_game_screen_overlay(bool draw_mouse) {
 	// TODO: find out if it's okay to move cursor animation and state update
 	// to the update loop instead of doing it in the drawing routine
 	// update animating mouse cursor
-	if (_GP(game).mcurs[cur_cursor].view >= 0) {
+	if (_GP(game).mcurs[_G(cur_cursor)].view >= 0) {
 		ags_domouse(DOMOUSE_NOCURSOR);
 		// only on mousemove, and it's not moving
-		if (((_GP(game).mcurs[cur_cursor].flags & MCF_ANIMMOVE) != 0) &&
-		        (_G(mousex) == lastmx) && (_G(mousey) == lastmy));
+		if (((_GP(game).mcurs[_G(cur_cursor)].flags & MCF_ANIMMOVE) != 0) &&
+		        (_G(mousex) == _G(lastmx)) && (_G(mousey) == _G(lastmy)));
 		// only on hotspot, and it's not on one
-		else if (((_GP(game).mcurs[cur_cursor].flags & MCF_HOTSPOT) != 0) &&
+		else if (((_GP(game).mcurs[_G(cur_cursor)].flags & MCF_HOTSPOT) != 0) &&
 		         (GetLocationType(game_to_data_coord(_G(mousex)), game_to_data_coord(_G(mousey))) == 0))
-			set_new_cursor_graphic(_GP(game).mcurs[cur_cursor].pic);
-		else if (mouse_delay > 0) mouse_delay--;
+			set_new_cursor_graphic(_GP(game).mcurs[_G(cur_cursor)].pic);
+		else if (_G(mouse_delay) > 0) _G(mouse_delay)--;
 		else {
-			int viewnum = _GP(game).mcurs[cur_cursor].view;
+			int viewnum = _GP(game).mcurs[_G(cur_cursor)].view;
 			int loopnum = 0;
 			if (loopnum >= _G(views)[viewnum].numLoops)
 				quitprintf("An animating mouse cursor is using view %d which has no loops", viewnum + 1);
 			if (_G(views)[viewnum].loops[loopnum].numFrames < 1)
 				quitprintf("An animating mouse cursor is using view %d which has no frames in loop %d", viewnum + 1, loopnum);
 
-			mouse_frame++;
-			if (mouse_frame >= _G(views)[viewnum].loops[loopnum].numFrames)
-				mouse_frame = 0;
-			set_new_cursor_graphic(_G(views)[viewnum].loops[loopnum].frames[mouse_frame].pic);
-			mouse_delay = _G(views)[viewnum].loops[loopnum].frames[mouse_frame].speed + 5;
-			CheckViewFrame(viewnum, loopnum, mouse_frame);
+			_G(mouse_frame)++;
+			if (_G(mouse_frame) >= _G(views)[viewnum].loops[loopnum].numFrames)
+				_G(mouse_frame) = 0;
+			set_new_cursor_graphic(_G(views)[viewnum].loops[loopnum].frames[_G(mouse_frame)].pic);
+			_G(mouse_delay) = _G(views)[viewnum].loops[loopnum].frames[_G(mouse_frame)].speed + 5;
+			CheckViewFrame(viewnum, loopnum, _G(mouse_frame));
 		}
-		lastmx = _G(mousex);
-		lastmy = _G(mousey);
+		_G(lastmx) = _G(mousex);
+		_G(lastmy) = _G(mousey);
 	}
 
 	ags_domouse(DOMOUSE_NOCURSOR);
 
 	// Stage: mouse cursor
 	if (draw_mouse && !_GP(play).mouse_cursor_hidden && _GP(play).screen_is_faded_out == 0) {
-		_G(gfxDriver)->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), mouseCursor);
-		invalidate_sprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), mouseCursor, false);
+		_G(gfxDriver)->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), _G(mouseCursor));
+		invalidate_sprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), _G(mouseCursor), false);
 	}
 
 	if (_GP(play).screen_is_faded_out == 0) {
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 2ea9ded253..e58c1776a5 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -109,8 +109,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern int cur_mode, cur_cursor;
-
 #if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
 extern int _G(psp_gfx_renderer);
 #endif
@@ -248,7 +246,7 @@ void setup_for_dialog() {
 	acdialog_font = _GP(play).normal_font;
 	if (!_GP(play).mouse_cursor_hidden)
 		ags_domouse(DOMOUSE_ENABLE);
-	oldmouse = cur_cursor;
+	oldmouse = _G(cur_cursor);
 	set_mouse_cursor(CURS_ARROW);
 }
 void restore_after_dialog() {
@@ -2225,7 +2223,7 @@ void RegisterGameAPI() {
 void RegisterStaticObjects() {
 	ccAddExternalStaticObject("game", &_GP(play), &GameStaticManager);
 	ccAddExternalStaticObject("gs_globals", &_GP(play).globalvars[0], &GlobalStaticManager);
-	ccAddExternalStaticObject("mouse", &scmouse, &GlobalStaticManager);
+	ccAddExternalStaticObject("mouse", &_GP(scmouse), &GlobalStaticManager);
 	ccAddExternalStaticObject("palette", &palette[0], &GlobalStaticManager);
 	ccAddExternalStaticObject("system", &_GP(scsystem), &GlobalStaticManager);
 	ccAddExternalStaticObject("savegameindex", &_GP(play).filenumbers[0], &GlobalStaticManager);
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 3f87d41d22..a518ab0da7 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -63,8 +63,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-extern int cur_mode, cur_cursor;
-
 ScriptGUI *GUI_AsTextWindow(ScriptGUI *tehgui) {
 	// Internally both GUI and TextWindow are implemented by same class
 	return _GP(guis)[tehgui->id].IsTextWindow() ? &_G(scrGui)[tehgui->id] : nullptr;
@@ -303,7 +301,7 @@ void remove_popup_interface(int ifacenum) {
 	_GP(guis)[ifacenum].SetConceal(true);
 	if (_G(mousey) <= _GP(guis)[ifacenum].PopupAtMouseY)
 		_GP(mouse).SetPosition(Point(_G(mousex), _GP(guis)[ifacenum].PopupAtMouseY + 2));
-	if ((!IsInterfaceEnabled()) && (cur_cursor == cur_mode))
+	if ((!IsInterfaceEnabled()) && (_G(cur_cursor) == _G(cur_mode)))
 		// Only change the mouse cursor if it hasn't been specifically changed first
 		set_mouse_cursor(CURS_WAIT);
 	else if (IsInterfaceEnabled())
@@ -634,10 +632,10 @@ void gui_on_mouse_up(const int wasongui, const int wasbutdown) {
 					force_event(EV_TEXTSCRIPT, TS_MCLICK, wasbutdown + 4);
 				} else if (wasbutdown == 2) // right-click is always Look
 					run_event_block_inv(iit, 0);
-				else if (cur_mode == MODE_HAND)
+				else if (_G(cur_mode) == MODE_HAND)
 					SetActiveInventory(iit);
 				else
-					RunInventoryInteraction(iit, cur_mode);
+					RunInventoryInteraction(iit, _G(cur_mode));
 				_G(evblocknum) = -1;
 			}
 		} else quit("clicked on unknown control type");
diff --git a/engines/ags/engine/ac/inventoryitem.cpp b/engines/ags/engine/ac/inventoryitem.cpp
index 61f16edaf4..546ce49f6a 100644
--- a/engines/ags/engine/ac/inventoryitem.cpp
+++ b/engines/ags/engine/ac/inventoryitem.cpp
@@ -41,8 +41,6 @@
 
 namespace AGS3 {
 
-extern int cur_cursor;
-
 void InventoryItem_SetCursorGraphic(ScriptInvItem *iitem, int newSprite) {
 	set_inv_item_cursorpic(iitem->id, newSprite);
 }
@@ -115,9 +113,9 @@ 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) && (_G(playerchar)->activeinv == invItemId)) {
+	if ((_G(cur_cursor) == MODE_USE) && (_G(playerchar)->activeinv == invItemId)) {
 		update_inv_cursor(invItemId);
-		set_mouse_cursor(cur_cursor);
+		set_mouse_cursor(_G(cur_cursor));
 	}
 }
 
diff --git a/engines/ags/engine/ac/mouse.cpp b/engines/ags/engine/ac/mouse.cpp
index ea3421082a..e38a4c478f 100644
--- a/engines/ags/engine/ac/mouse.cpp
+++ b/engines/ags/engine/ac/mouse.cpp
@@ -56,15 +56,6 @@ using namespace AGS::Engine;
 extern void ags_domouse(int str);
 extern int misbuttondown(int buno);
 
-ScriptMouse scmouse;
-int cur_mode, cur_cursor;
-int mouse_frame = 0, mouse_delay = 0;
-int lastmx = -1, lastmy = -1;
-char alpha_blend_cursor = 0;
-Bitmap *dotted_mouse_cursor = nullptr;
-IDriverDependantBitmap *mouseCursor = nullptr;
-Bitmap *blank_mouse_cursor = nullptr;
-
 // The mouse functions are static so the script doesn't pass
 // in an object parameter
 void Mouse_SetVisible(int isOn) {
@@ -114,56 +105,56 @@ void set_mouse_cursor(int newcurs) {
 	msethotspot(hotspotx, hotspoty);
 
 	// if it's same cursor and there's animation in progress, then don't assign a new pic just yet
-	if (newcurs == cur_cursor && _GP(game).mcurs[newcurs].view >= 0 &&
-		(mouse_frame > 0 || mouse_delay > 0)) {
+	if (newcurs == _G(cur_cursor) && _GP(game).mcurs[newcurs].view >= 0 &&
+		(_G(mouse_frame) > 0 || _G(mouse_delay) > 0)) {
 		return;
 	}
 
 	// reset animation timing only if it's another cursor
-	if (newcurs != cur_cursor) {
-		cur_cursor = newcurs;
-		mouse_frame = 0;
-		mouse_delay = 0;
+	if (newcurs != _G(cur_cursor)) {
+		_G(cur_cursor) = newcurs;
+		_G(mouse_frame) = 0;
+		_G(mouse_delay) = 0;
 	}
 
 	// Assign new pic
 	set_new_cursor_graphic(_GP(game).mcurs[newcurs].pic);
-	delete dotted_mouse_cursor;
-	dotted_mouse_cursor = nullptr;
+	delete _G(dotted_mouse_cursor);
+	_G(dotted_mouse_cursor) = nullptr;
 
 	// If it's inventory cursor, draw hotspot crosshair sprite upon it
 	if ((newcurs == MODE_USE) && (_GP(game).mcurs[newcurs].pic > 0) &&
 		((_GP(game).hotdot > 0) || (_GP(game).invhotdotsprite > 0))) {
 		// If necessary, create a copy of the cursor and put the hotspot
 		// dot onto it
-		dotted_mouse_cursor = BitmapHelper::CreateBitmapCopy(_G(mousecurs)[0]);
+		_G(dotted_mouse_cursor) = BitmapHelper::CreateBitmapCopy(_G(mousecurs)[0]);
 
 		if (_GP(game).invhotdotsprite > 0) {
-			draw_sprite_slot_support_alpha(dotted_mouse_cursor,
+			draw_sprite_slot_support_alpha(_G(dotted_mouse_cursor),
 				(_GP(game).SpriteInfos[_GP(game).mcurs[newcurs].pic].Flags & SPF_ALPHACHANNEL) != 0,
 				hotspotx - _GP(game).SpriteInfos[_GP(game).invhotdotsprite].Width / 2,
 				hotspoty - _GP(game).SpriteInfos[_GP(game).invhotdotsprite].Height / 2,
 				_GP(game).invhotdotsprite);
 		} else {
-			putpixel_compensate(dotted_mouse_cursor, hotspotx, hotspoty, MakeColor(_GP(game).hotdot));
+			putpixel_compensate(_G(dotted_mouse_cursor), hotspotx, hotspoty, MakeColor(_GP(game).hotdot));
 
 			if (_GP(game).hotdotouter > 0) {
 				int outercol = MakeColor(_GP(game).hotdotouter);
 
-				putpixel_compensate(dotted_mouse_cursor, hotspotx + get_fixed_pixel_size(1), hotspoty, outercol);
-				putpixel_compensate(dotted_mouse_cursor, hotspotx, hotspoty + get_fixed_pixel_size(1), outercol);
-				putpixel_compensate(dotted_mouse_cursor, hotspotx - get_fixed_pixel_size(1), hotspoty, outercol);
-				putpixel_compensate(dotted_mouse_cursor, hotspotx, hotspoty - get_fixed_pixel_size(1), outercol);
+				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx + get_fixed_pixel_size(1), hotspoty, outercol);
+				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx, hotspoty + get_fixed_pixel_size(1), outercol);
+				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx - get_fixed_pixel_size(1), hotspoty, outercol);
+				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx, hotspoty - get_fixed_pixel_size(1), outercol);
 			}
 		}
-		_G(mousecurs)[0] = dotted_mouse_cursor;
+		_G(mousecurs)[0] = _G(dotted_mouse_cursor);
 		update_cached_mouse_cursor();
 	}
 }
 
 // set_default_cursor: resets visual appearance to current mode (walk, look, etc)
 void set_default_cursor() {
-	set_mouse_cursor(cur_mode);
+	set_mouse_cursor(_G(cur_mode));
 }
 
 // permanently change cursor graphic
@@ -176,7 +167,7 @@ void ChangeCursorGraphic(int curs, int newslot) {
 
 	_GP(game).mcurs[curs].pic = newslot;
 	_GP(spriteset).Precache(newslot);
-	if (curs == cur_mode)
+	if (curs == _G(cur_mode))
 		set_mouse_cursor(curs);
 }
 
@@ -192,8 +183,8 @@ void ChangeCursorHotspot(int curs, int x, int y) {
 		quit("!ChangeCursorHotspot: invalid mouse cursor");
 	_GP(game).mcurs[curs].hotx = data_to_game_coord(x);
 	_GP(game).mcurs[curs].hoty = data_to_game_coord(y);
-	if (curs == cur_cursor)
-		set_mouse_cursor(cur_cursor);
+	if (curs == _G(cur_cursor))
+		set_mouse_cursor(_G(cur_cursor));
 }
 
 void Mouse_ChangeModeView(int curs, int newview) {
@@ -208,16 +199,16 @@ void Mouse_ChangeModeView(int curs, int newview) {
 		precache_view(newview);
 	}
 
-	if (curs == cur_cursor)
-		mouse_delay = 0;  // force update
+	if (curs == _G(cur_cursor))
+		_G(mouse_delay) = 0;  // force update
 }
 
 void SetNextCursor() {
-	set_cursor_mode(find_next_enabled_cursor(cur_mode + 1));
+	set_cursor_mode(find_next_enabled_cursor(_G(cur_mode) + 1));
 }
 
 void SetPreviousCursor() {
-	set_cursor_mode(find_previous_enabled_cursor(cur_mode - 1));
+	set_cursor_mode(find_previous_enabled_cursor(_G(cur_mode) - 1));
 }
 
 // set_cursor_mode: changes mode and appearance
@@ -237,7 +228,7 @@ void set_cursor_mode(int newmode) {
 		}
 		update_inv_cursor(_G(playerchar)->activeinv);
 	}
-	cur_mode = newmode;
+	_G(cur_mode) = newmode;
 	set_default_cursor();
 
 	debug_script_log("Cursor mode set to %d", newmode);
@@ -274,14 +265,14 @@ void disable_cursor_mode(int modd) {
 			gbpt->SetEnabled(false);
 		}
 	}
-	if (cur_mode == modd) find_next_enabled_cursor(modd);
+	if (_G(cur_mode) == modd) find_next_enabled_cursor(modd);
 	guis_need_update = 1;
 }
 
 void RefreshMouse() {
 	ags_domouse(DOMOUSE_NOCURSOR);
-	scmouse.x = game_to_data_coord(_G(mousex));
-	scmouse.y = game_to_data_coord(_G(mousey));
+	_GP(scmouse).x = game_to_data_coord(_G(mousex));
+	_GP(scmouse).y = game_to_data_coord(_G(mousey));
 }
 
 void SetMousePosition(int newx, int newy) {
@@ -302,7 +293,7 @@ void SetMousePosition(int newx, int newy) {
 }
 
 int GetCursorMode() {
-	return cur_mode;
+	return _G(cur_mode);
 }
 
 int IsButtonDown(int which) {
@@ -342,12 +333,12 @@ void Mouse_EnableControl(bool on) {
 //=============================================================================
 
 int GetMouseCursor() {
-	return cur_cursor;
+	return _G(cur_cursor);
 }
 
 void update_script_mouse_coords() {
-	scmouse.x = game_to_data_coord(_G(mousex));
-	scmouse.y = game_to_data_coord(_G(mousey));
+	_GP(scmouse).x = game_to_data_coord(_G(mousex));
+	_GP(scmouse).y = game_to_data_coord(_G(mousey));
 }
 
 void update_inv_cursor(int invnum) {
@@ -375,9 +366,9 @@ void update_inv_cursor(int invnum) {
 }
 
 void update_cached_mouse_cursor() {
-	if (mouseCursor != nullptr)
-		_G(gfxDriver)->DestroyDDB(mouseCursor);
-	mouseCursor = _G(gfxDriver)->CreateDDBFromBitmap(_G(mousecurs)[0], alpha_blend_cursor != 0);
+	if (_G(mouseCursor) != nullptr)
+		_G(gfxDriver)->DestroyDDB(_G(mouseCursor));
+	_G(mouseCursor) = _G(gfxDriver)->CreateDDBFromBitmap(_G(mousecurs)[0], _G(alpha_blend_cursor) != 0);
 }
 
 void set_new_cursor_graphic(int spriteslot) {
@@ -386,16 +377,16 @@ void set_new_cursor_graphic(int spriteslot) {
 	// It looks like spriteslot 0 can be used in games with version 2.72 and lower.
 	// The NULL check should ensure that the sprite is valid anyway.
 	if (((spriteslot < 1) && (loaded_game_file_version > kGameVersion_272)) || (_G(mousecurs)[0] == nullptr)) {
-		if (blank_mouse_cursor == nullptr) {
-			blank_mouse_cursor = BitmapHelper::CreateTransparentBitmap(1, 1, _GP(game).GetColorDepth());
+		if (_G(blank_mouse_cursor) == nullptr) {
+			_G(blank_mouse_cursor) = BitmapHelper::CreateTransparentBitmap(1, 1, _GP(game).GetColorDepth());
 		}
-		_G(mousecurs)[0] = blank_mouse_cursor;
+		_G(mousecurs)[0] = _G(blank_mouse_cursor);
 	}
 
 	if (_GP(game).SpriteInfos[spriteslot].Flags & SPF_ALPHACHANNEL)
-		alpha_blend_cursor = 1;
+		_G(alpha_blend_cursor) = 1;
 	else
-		alpha_blend_cursor = 0;
+		_G(alpha_blend_cursor) = 0;
 
 	update_cached_mouse_cursor();
 }
diff --git a/engines/ags/engine/ac/mouse.h b/engines/ags/engine/ac/mouse.h
index 95e455fdf6..25a9271489 100644
--- a/engines/ags/engine/ac/mouse.h
+++ b/engines/ags/engine/ac/mouse.h
@@ -75,11 +75,6 @@ void set_new_cursor_graphic(int spriteslot);
 int find_next_enabled_cursor(int startwith);
 int find_previous_enabled_cursor(int startwith);
 
-extern ScriptMouse scmouse;
-
-extern int cur_mode;
-extern int cur_cursor;
-
 } // namespace AGS3
 
 #endif
diff --git a/engines/ags/engine/device/mousew32.cpp b/engines/ags/engine/device/mousew32.cpp
index 77c70de3d4..68d898a8e0 100644
--- a/engines/ags/engine/device/mousew32.cpp
+++ b/engines/ags/engine/device/mousew32.cpp
@@ -71,7 +71,6 @@ enum {
 };
 
 extern char lib_file_name[13];
-extern char alpha_blend_cursor;
 extern color palette[256];
 
 static const int MB_ARRAY[3] = { 1, 2, 4 };
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 4f4c4fe65b..39d0ba329c 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -212,8 +212,8 @@ HSaveError WriteGameState(PStream out) {
 	out->WriteInt32(_G(ifacepopped));
 	out->WriteInt32(game_paused);
 	// Mouse cursor
-	out->WriteInt32(cur_mode);
-	out->WriteInt32(cur_cursor);
+	out->WriteInt32(_G(cur_mode));
+	out->WriteInt32(_G(cur_cursor));
 	out->WriteInt32(_G(mouse_on_iface));
 
 	// Viewports and cameras
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index fc3135b87e..2e948abf8d 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -75,9 +75,7 @@ using namespace AGS::Shared;
 
 extern int game_paused;
 extern int getloctype_index;
-extern int cur_mode;
 extern char noWalkBehindsAtAll;
-extern int cur_mode, cur_cursor;
 
 // Checks if user interface should remain disabled for now
 static int ShouldStayInWaitMode();
@@ -786,7 +784,7 @@ static void UpdateMouseOverLocation() {
 		_GP(play).get_loc_name_save_cursor = -1;
 		set_cursor_mode(_GP(play).restore_cursor_mode_to);
 
-		if (cur_mode == _GP(play).restore_cursor_mode_to) {
+		if (_G(cur_mode) == _GP(play).restore_cursor_mode_to) {
 			// make sure it changed -- the new mode might have been disabled
 			// in which case don't change the image
 			set_mouse_cursor(_GP(play).restore_cursor_image_to);
@@ -884,8 +882,8 @@ static void SetupLoopParameters(int untilwhat, const void *udata) {
 	guis_need_update = 1;
 	// Only change the mouse cursor if it hasn't been specifically changed first
 	// (or if it's speech, always change it)
-	if (((cur_cursor == cur_mode) || (untilwhat == UNTIL_NOOVERLAY)) &&
-		(cur_mode != CURS_WAIT))
+	if (((_G(cur_cursor) == _G(cur_mode)) || (untilwhat == UNTIL_NOOVERLAY)) &&
+		(_G(cur_mode) != CURS_WAIT))
 		set_mouse_cursor(CURS_WAIT);
 
 	_G(restrict_until) = untilwhat;
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index a81d4f4c47..90d6eef95f 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -42,6 +42,7 @@
 #include "ags/engine/ac/event.h"
 #include "ags/engine/ac/gamesetup.h"
 #include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/movelist.h"
 #include "ags/engine/ac/objectcache.h"
 #include "ags/engine/ac/roomstatus.h"
@@ -217,6 +218,9 @@ Globals::Globals() {
 	// managedobjectpool.cpp globals
 	_pool = new ManagedObjectPool();
 
+	// mouse.cpp globals
+	_scmouse = new ScriptMouse();
+
 	// mousew32.cpp globals
 	_mouse = new Mouse();
 
@@ -371,6 +375,9 @@ Globals::~Globals() {
 	// managedobjectpool.cpp globals
 	delete _pool;
 
+	// mouse.cpp globals
+	delete _scmouse;
+
 	// mousew32.cpp globals
 	delete _mouse;
 
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index dce3f1b1e0..cf74260b7f 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -130,6 +130,7 @@ struct ScriptDrawingSurface;
 struct ScriptGUI;
 struct ScriptHotspot;
 struct ScriptInvItem;
+struct ScriptMouse;
 struct ScriptObject;
 struct ScriptPosition;
 struct ScriptRegion;
@@ -808,6 +809,15 @@ public:
 	char _ignore_bounds = 0;
 	AGS::Shared::Bitmap *_mousecurs[MAXCURSORS];
 
+	ScriptMouse *_scmouse;
+	int _cur_mode = 0, _cur_cursor = 0;
+	int _mouse_frame = 0, _mouse_delay = 0;
+	int _lastmx = -1, _lastmy = -1;
+	char _alpha_blend_cursor = 0;
+	AGS::Shared::Bitmap *_dotted_mouse_cursor = nullptr;
+	AGS::Engine::IDriverDependantBitmap *_mouseCursor = nullptr;
+	AGS::Shared::Bitmap *_blank_mouse_cursor = nullptr;
+
 	/**@}*/
 
 	/**




More information about the Scummvm-git-logs mailing list