diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index fcd0066d4f115b69ec4c4017f9546b68cde7cf0e..b66fd900fce4cf9f23e0f8dd3995af42b15c48ab 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -164,6 +164,12 @@ enum side_e {
 	side_offsety_mid,
 	side_offsetx_bot,
 	side_offsety_bot,
+	side_scalex_top,
+	side_scaley_top,
+	side_scalex_mid,
+	side_scaley_mid,
+	side_scalex_bot,
+	side_scaley_bot,
 	side_toptexture,
 	side_bottomtexture,
 	side_midtexture,
@@ -184,6 +190,12 @@ static const char *const side_opt[] = {
 	"offsety_mid",
 	"offsetx_bot",
 	"offsety_bot",
+	"scalex_top",
+	"scaley_top",
+	"scalex_mid",
+	"scaley_mid",
+	"scalex_bot",
+	"scaley_bot",
 	"toptexture",
 	"bottomtexture",
 	"midtexture",
@@ -1102,6 +1114,24 @@ static int side_get(lua_State *L)
 	case side_offsety_bot:
 		lua_pushfixed(L, side->offsety_bot);
 		return 1;
+	case side_scalex_top:
+		lua_pushfixed(L, side->scalex_top);
+		return 1;
+	case side_scaley_top:
+		lua_pushfixed(L, side->scaley_top);
+		return 1;
+	case side_scalex_mid:
+		lua_pushfixed(L, side->scalex_mid);
+		return 1;
+	case side_scaley_mid:
+		lua_pushfixed(L, side->scaley_mid);
+		return 1;
+	case side_scalex_bot:
+		lua_pushfixed(L, side->scalex_bot);
+		return 1;
+	case side_scaley_bot:
+		lua_pushfixed(L, side->scaley_bot);
+		return 1;
 	case side_toptexture:
 		lua_pushinteger(L, side->toptexture);
 		return 1;
@@ -1177,6 +1207,24 @@ static int side_set(lua_State *L)
 	case side_offsety_bot:
 		side->offsety_bot = luaL_checkfixed(L, 3);
 		break;
+	case side_scalex_top:
+		side->scalex_top = luaL_checkfixed(L, 3);
+		break;
+	case side_scaley_top:
+		side->scaley_top = luaL_checkfixed(L, 3);
+		break;
+	case side_scalex_mid:
+		side->scalex_mid = luaL_checkfixed(L, 3);
+		break;
+	case side_scaley_mid:
+		side->scaley_mid = luaL_checkfixed(L, 3);
+		break;
+	case side_scalex_bot:
+		side->scalex_bot = luaL_checkfixed(L, 3);
+		break;
+	case side_scaley_bot:
+		side->scaley_bot = luaL_checkfixed(L, 3);
+		break;
 	case side_toptexture:
 		side->toptexture = luaL_checkinteger(L, 3);
 		break;
diff --git a/src/p_setup.c b/src/p_setup.c
index de251915ebfbeb6deb8842d15bd661e7822abd56..34c066952e3d97649a39a2cd57e745f344dbdc06 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1228,6 +1228,9 @@ static void P_LoadSidedefs(UINT8 *data)
 		sd->offsetx_top = sd->offsetx_mid = sd->offsetx_bot = 0;
 		sd->offsety_top = sd->offsety_mid = sd->offsety_bot = 0;
 
+		sd->scalex_top = sd->scalex_mid = sd->scalex_bot = FRACUNIT;
+		sd->scaley_top = sd->scaley_mid = sd->scaley_bot = FRACUNIT;
+
 		P_SetSidedefSector(i, SHORT(msd->sector));
 
 		// Special info stored in texture fields!
@@ -1754,18 +1757,18 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char
 		sides[i].textureoffset = atol(val)<<FRACBITS;
 	else if (fastcmp(param, "offsety"))
 		sides[i].rowoffset = atol(val)<<FRACBITS;
-	else if (fastcmp(param, "offsetx_top"))
-		sides[i].offsetx_top = atol(val) << FRACBITS;
-	else if (fastcmp(param, "offsetx_mid"))
-		sides[i].offsetx_mid = atol(val) << FRACBITS;
-	else if (fastcmp(param, "offsetx_bottom"))
-		sides[i].offsetx_bot = atol(val) << FRACBITS;
-	else if (fastcmp(param, "offsety_top"))
-		sides[i].offsety_top = atol(val) << FRACBITS;
-	else if (fastcmp(param, "offsety_mid"))
-		sides[i].offsety_mid = atol(val) << FRACBITS;
-	else if (fastcmp(param, "offsety_bottom"))
-		sides[i].offsety_bot = atol(val) << FRACBITS;
+	else if (fastcmp(param, "scalex_top"))
+		sides[i].scalex_top = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "scalex_mid"))
+		sides[i].scalex_mid = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "scalex_bottom"))
+		sides[i].scalex_bot = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "scaley_top"))
+		sides[i].scaley_top = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "scaley_mid"))
+		sides[i].scaley_mid = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "scaley_bottom"))
+		sides[i].scaley_bot = FLOAT_TO_FIXED(atof(val));
 	else if (fastcmp(param, "texturetop"))
 		sides[i].toptexture = R_TextureNumForName(val);
 	else if (fastcmp(param, "texturebottom"))
@@ -2453,6 +2456,18 @@ static void P_WriteTextmap(void)
 			fprintf(f, "offsetx_bottom = %d;\n", wsides[i].offsetx_bot >> FRACBITS);
 		if (wsides[i].offsety_bot != 0)
 			fprintf(f, "offsety_bottom = %d;\n", wsides[i].offsety_bot >> FRACBITS);
+		if (wsides[i].scalex_top != FRACUNIT)
+			fprintf(f, "scalex_top = %f;\n", FIXED_TO_FLOAT(wsides[i].scalex_top));
+		if (wsides[i].scaley_top != FRACUNIT)
+			fprintf(f, "scaley_top = %f;\n", FIXED_TO_FLOAT(wsides[i].scaley_top));
+		if (wsides[i].scalex_mid != FRACUNIT)
+			fprintf(f, "scalex_mid = %f;\n", FIXED_TO_FLOAT(wsides[i].scalex_mid));
+		if (wsides[i].scaley_mid != FRACUNIT)
+			fprintf(f, "scaley_mid = %f;\n", FIXED_TO_FLOAT(wsides[i].scaley_mid));
+		if (wsides[i].scalex_bot != FRACUNIT)
+			fprintf(f, "scalex_bottom = %f;\n", FIXED_TO_FLOAT(wsides[i].scalex_bot));
+		if (wsides[i].scaley_bot != FRACUNIT)
+			fprintf(f, "scaley_bottom = %f;\n", FIXED_TO_FLOAT(wsides[i].scaley_bot));
 		if (wsides[i].toptexture > 0 && wsides[i].toptexture < numtextures)
 			fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[wsides[i].toptexture]->name);
 		if (wsides[i].bottomtexture > 0 && wsides[i].bottomtexture < numtextures)
@@ -2803,6 +2818,8 @@ static void P_LoadTextmap(void)
 		sd->rowoffset = 0;
 		sd->offsetx_top = sd->offsetx_mid = sd->offsetx_bot = 0;
 		sd->offsety_top = sd->offsety_mid = sd->offsety_bot = 0;
+		sd->scalex_top = sd->scalex_mid = sd->scalex_bot = FRACUNIT;
+		sd->scaley_top = sd->scaley_mid = sd->scaley_bot = FRACUNIT;
 		sd->toptexture = R_TextureNumForName("-");
 		sd->midtexture = R_TextureNumForName("-");
 		sd->bottomtexture = R_TextureNumForName("-");
diff --git a/src/r_defs.h b/src/r_defs.h
index b93099793903b0911f75a9dabcbb40ed74190c2d..5a5a43110d9260cf74bfd4443dbcd0474b7a8dc9 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -518,6 +518,9 @@ typedef struct
 	fixed_t offsetx_top, offsetx_mid, offsetx_bot;
 	fixed_t offsety_top, offsety_mid, offsety_bot;
 
+	fixed_t scalex_top, scalex_mid, scalex_bot;
+	fixed_t scaley_top, scaley_mid, scaley_bot;
+
 	// Texture indices.
 	// We do not maintain names here.
 	INT32 toptexture, bottomtexture, midtexture;