diff --git a/src/doomstat.h b/src/doomstat.h
index 7678c86b708d13e8a291b9f453fb3d0a16f4c76a..421b6579fd856d5d43e77ece03926241dede1021 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -129,6 +129,9 @@ extern INT16 titlemap;
 extern boolean hidetitlepics;
 extern INT16 bootmap; //bootmap for loading a map on startup
 
+extern INT16 tutorialmap; // map to load for tutorial
+extern boolean tutorialmode; // are we in a tutorial right now?
+
 extern boolean looptitle;
 
 // CTF colors.
diff --git a/src/g_game.c b/src/g_game.c
index 0a392fa854c7203deb21be38152eafc35b22750d..38289bcb234f9ed46021a3c803619ff52041d410 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -127,6 +127,9 @@ INT16 titlemap = 0;
 boolean hidetitlepics = false;
 INT16 bootmap; //bootmap for loading a map on startup
 
+INT16 tutorialmap = 0; // map to load for tutorial
+boolean tutorialmode = false; // are we in a tutorial right now?
+
 boolean looptitle = false;
 
 UINT8 skincolor_redteam = SKINCOLOR_RED;
diff --git a/src/g_input.c b/src/g_input.c
index 77239621c695c8a07f9e8c5046811586103d7097..1e3b83b5627eb640c31d6ec7b091014666f65d5e 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -48,13 +48,25 @@ INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
 INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
 
 // lists of GC codes for selective operation
-INT32 gcmovement[num_gcmovement] = {
+const INT32 gclist_tutorial[num_gclist_tutorial] = {
 	gc_forward, gc_backward, gc_strafeleft, gc_straferight,
-	gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview,
-	gc_jump, gc_use
-	// , gc_fire, gc_firenormal
+	gc_lookup, gc_lookdown, gc_turnleft, gc_turnright//, gc_centerview,
+	//gc_jump, gc_use,
+	//gc_fire, gc_firenormal
 };
 
+const INT32 gclist_movement[num_gclist_movement] = {
+	gc_forward, gc_backward, gc_strafeleft, gc_straferight
+};
+
+const INT32 gclist_camera[num_gclist_camera] = {
+	gc_lookup, gc_lookdown, gc_turnleft, gc_turnright
+};
+
+const INT32 gclist_jump[num_gclist_jump] = { gc_jump };
+
+const INT32 gclist_use[num_gclist_use] = { gc_use };
+
 typedef struct
 {
 	UINT8 time;
@@ -681,7 +693,7 @@ void G_DefineDefaultControls(void)
 	}
 }
 
-INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen)
+INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen)
 {
 	INT32 i, j, gc;
 	boolean skipscheme;
@@ -708,7 +720,7 @@ INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen)
 	return gcs_custom;
 }
 
-void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen)
+void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen)
 {
 	INT32 i, gc;
 
diff --git a/src/g_input.h b/src/g_input.h
index f8989fc6c2968c58a9619d09cf7546469db5a4c2..a70ff9104ffdefb0dc8444e573389c1117eaed92 100644
--- a/src/g_input.h
+++ b/src/g_input.h
@@ -128,8 +128,17 @@ extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; //
 #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
 #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
 
-#define num_gcmovement 11 // 13
-extern INT32 gcmovement[num_gcmovement];
+#define num_gclist_tutorial 8 // 13
+#define num_gclist_movement 4
+#define num_gclist_camera 4
+#define num_gclist_jump 1
+#define num_gclist_use 1
+
+extern const INT32 gclist_tutorial[num_gclist_tutorial];
+extern const INT32 gclist_movement[num_gclist_movement];
+extern const INT32 gclist_camera[num_gclist_camera];
+extern const INT32 gclist_jump[num_gclist_jump];
+extern const INT32 gclist_use[num_gclist_use];
 
 // peace to my little coder fingers!
 // check a gamecontrol being active or not
@@ -146,8 +155,8 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);
 void Command_Setcontrol_f(void);
 void Command_Setcontrol2_f(void);
 void G_DefineDefaultControls(void);
-INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen);
-void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen);
+INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen);
+void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen);
 void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]);
 void G_CheckDoubleUsage(INT32 keynum);