From f14842ef45c82aed96477c832b8fff5b766fe334 Mon Sep 17 00:00:00 2001
From: Lactozilla <jp6781615@gmail.com>
Date: Sat, 22 Feb 2025 04:57:12 -0300
Subject: [PATCH 1/3] Minor translation fixes and refactoring - Separated code
 into a function so that behavior is more consistent between renderers - Made
 TC_ALLWHITE, TC_METALSONIC and TC_BOSS able to be combined with translations

---
 src/hardware/hw_md2.c | 33 ++---------------------
 src/r_draw.c          |  7 ++---
 src/r_things.c        | 62 ++++++++++++++++++++++++++++++-------------
 src/r_things.h        |  3 ++-
 src/r_translation.c   | 16 +++++------
 src/r_translation.h   |  4 +--
 6 files changed, 62 insertions(+), 63 deletions(-)

diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 9318671422..c7256666a5 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1,7 +1,7 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 1999-2024 by Sonic Team Junior.
+// Copyright (C) 1999-2025 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -1473,37 +1473,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
 
 		if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
 		{
-			INT32 skinnum = TC_DEFAULT;
+			INT32 skinnum = R_GetTranslationIndexForThing(spr->mobj, spr->mobj->color);
 
-			if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
-			{
-				if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
-					skinnum = TC_ALLWHITE;
-				else if (spr->mobj->type == MT_METALSONIC_BATTLE)
-					skinnum = TC_METALSONIC;
-				else
-					skinnum = TC_BOSS;
-			}
-			else if ((skincolornum_t)spr->mobj->color != SKINCOLOR_NONE)
-			{
-				if (spr->mobj->colorized)
-					skinnum = TC_RAINBOW;
-				else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD
-					&& (spr->mobj->player->charflags & SF_DASHMODE)
-					&& ((leveltime/2) & 1))
-				{
-					if (spr->mobj->player->charflags & SF_MACHINE)
-						skinnum = TC_DASHMODE;
-					else
-						skinnum = TC_RAINBOW;
-				}
-				else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
-					skinnum = ((skin_t*)spr->mobj->skin)->skinnum;
-				else
-					skinnum = TC_DEFAULT;
-			}
-
-			// Translation or skin number found
 			HWR_GetBlendedTexture(gpatch, blendgpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
 		}
 		else // Sprite
diff --git a/src/r_draw.c b/src/r_draw.c
index 906398ec49..4710a93c2f 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 1999-2024 by Sonic Team Junior.
+// Copyright (C) 1999-2025 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -456,7 +456,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 translatio
 		for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
 			dest_colormap[i] = (UINT8)i;
 
-		// White!
+		// Boss flashing inverts the grayscale ramp
 		if (translation == TC_BOSS)
 		{
 			UINT8 *originalColormap = R_GetTranslationColormap(TC_DEFAULT, (skincolornum_t)color, GTC_CACHE);
@@ -468,6 +468,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 translatio
 				dest_colormap[31-i] = i;
 			}
 		}
+		// Metal Sonic flashing
 		else if (translation == TC_METALSONIC)
 		{
 			for (i = 0; i < 6; i++)
@@ -555,7 +556,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
 		// Rebuild the cache if necessary
 		if (skincolor_modified[color])
 		{
-			// Moved up here so that R_UpdateTranslationRemaps doesn't cause a stack overflow,
+			// Moved up here so that R_UpdateTranslationRemaps doesn't cause infinite recursion,
 			// since in this situation, it will call R_GetTranslationColormap
 			skincolor_modified[color] = false;
 
diff --git a/src/r_things.c b/src/r_things.c
index 2c0529e47a..7ff4d5bd58 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 1999-2024 by Sonic Team Junior.
+// Copyright (C) 1999-2025 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -957,12 +957,21 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
 	dc_texturemid = basetexturemid;
 }
 
-UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation)
+INT32 R_GetTranslationIndexForThing(mobj_t *mobj, skincolornum_t color)
 {
 	INT32 skinnum = TC_DEFAULT;
 
-	boolean is_player = mobj->skin && mobj->sprite == SPR_PLAY;
-	if (is_player) // This thing is a player!
+	if (R_ThingIsFlashing(mobj)) // Bosses "flash"
+	{
+		if (mobj->type == MT_CYBRAKDEMON || mobj->colorized)
+			return TC_ALLWHITE;
+		else if (mobj->type == MT_METALSONIC_BATTLE)
+			return TC_METALSONIC;
+		else
+			return TC_BOSS;
+	}
+
+	if (mobj->skin && mobj->sprite == SPR_PLAY) // This thing is a player!
 		skinnum = ((skin_t*)mobj->skin)->skinnum;
 
 	if (color != SKINCOLOR_NONE)
@@ -983,25 +992,42 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans
 		}
 	}
 
-	if (R_ThingIsFlashing(mobj)) // Bosses "flash"
+	return skinnum;
+}
+
+UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation)
+{
+	INT32 skinnum = R_GetTranslationIndexForThing(mobj, color);
+
+	boolean use_translation_colormap = color != SKINCOLOR_NONE;
+
+	if (skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || skinnum == TC_DASHMODE)
 	{
-		if (mobj->type == MT_CYBRAKDEMON || mobj->colorized)
-			return R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
-		else if (mobj->type == MT_METALSONIC_BATTLE)
-			return R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE);
-		else
-			return R_GetTranslationColormap(TC_BOSS, color, GTC_CACHE);
+		use_translation_colormap = true;
+
+		// Those translations don't support color remapping, so they
+		// will use SKINCOLOR_NONE always and reduce memory usage.
+		color = SKINCOLOR_NONE;
 	}
-	else if (translation != 0)
+	else if (skinnum == TC_BOSS)
 	{
-		UINT8 *tr = R_GetTranslationRemap(translation, color, skinnum);
-		if (tr != NULL)
-			return tr;
+		use_translation_colormap = true;
 	}
-	else if (color != SKINCOLOR_NONE)
+
+	if (translation != 0)
+	{
+		return R_GetTranslationRemap(translation, color, skinnum);
+	}
+	else if (use_translation_colormap)
+	{
 		return R_GetTranslationColormap(skinnum, color, GTC_CACHE);
-	else if (mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome.
-		return R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE);
+	}
+	else if (mobj->sprite == SPR_PLAY && (skinnum >= 0 && skinnum < numskins))
+	{
+		// Looks like a player, but doesn't have a color?
+		// Use the skin's prefcolor.
+		return R_GetTranslationColormap(TC_DEFAULT, skins[skinnum]->prefcolor, GTC_CACHE);
+	}
 
 	return NULL;
 }
diff --git a/src/r_things.h b/src/r_things.h
index ae21d2404b..4d6cd5094f 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 1999-2024 by Sonic Team Junior.
+// Copyright (C) 1999-2025 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -92,6 +92,7 @@ boolean R_ThingIsFullDark (mobj_t *thing);
 
 boolean R_ThingIsFlashing (mobj_t *thing);
 
+INT32 R_GetTranslationIndexForThing(mobj_t *mobj, skincolornum_t color);
 UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation);
 transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap);
 
diff --git a/src/r_translation.c b/src/r_translation.c
index 53bb0e6a0f..67dbdfab01 100644
--- a/src/r_translation.c
+++ b/src/r_translation.c
@@ -1,7 +1,7 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
 // Copyright (C) 1998-2006 by Randy Heit.
-// Copyright (C) 2023-2024 by Sonic Team Junior.
+// Copyright (C) 2023-2025 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -1120,7 +1120,7 @@ UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum)
 	if (!tr)
 		return NULL;
 
-	if (!tr->num_sources || skincolor == SKINCOLOR_NONE)
+	if (!tr->num_sources || (skincolor == SKINCOLOR_NONE && skinnum >= 0))
 		return tr->remap;
 
 	if (!tr->skincolor_remaps)
@@ -1144,20 +1144,20 @@ UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum)
 	return cache->colors;
 }
 
-static void R_UpdateTranslation(remaptable_t *tr, skincolornum_t skincolor, INT32 skinnum)
+static void R_UpdateTranslation(remaptable_t *tr, skincolornum_t skincolor, INT32 cache_index)
 {
-	if (!tr->num_sources || !tr->skincolor_remaps || !tr->skincolor_remaps[skinnum])
+	if (!tr->num_sources || !tr->skincolor_remaps || !tr->skincolor_remaps[cache_index])
 		return;
 
-	colorcache_t *cache = tr->skincolor_remaps[skinnum][skincolor];
+	colorcache_t *cache = tr->skincolor_remaps[cache_index][skincolor];
 	if (cache)
-		R_ApplyTranslationRemap(tr, cache->colors, skincolor, skinnum);
+		R_ApplyTranslationRemap(tr, cache->colors, skincolor, cache_index);
 }
 
-void R_UpdateTranslationRemaps(skincolornum_t skincolor, INT32 skinnum)
+void R_UpdateTranslationRemaps(skincolornum_t skincolor, INT32 cache_index)
 {
 	for (unsigned i = 0; i < numpaletteremaps; i++)
-		R_UpdateTranslation(paletteremaps[i], skincolor, skinnum);
+		R_UpdateTranslation(paletteremaps[i], skincolor, cache_index);
 }
 
 boolean R_TranslationIsValid(int id)
diff --git a/src/r_translation.h b/src/r_translation.h
index 9cae1a6470..ca0af716db 100644
--- a/src/r_translation.h
+++ b/src/r_translation.h
@@ -1,7 +1,7 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
 // Copyright (C) 1998-2006 by Randy Heit.
-// Copyright (C) 2023-2024 by Sonic Team Junior.
+// Copyright (C) 2023-2025 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -87,7 +87,7 @@ const char *R_GetCustomTranslationName(unsigned id);
 unsigned R_NumCustomTranslations(void);
 remaptable_t *R_GetTranslationByID(int id);
 UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum);
-void R_UpdateTranslationRemaps(skincolornum_t skincolor, INT32 skinnum);
+void R_UpdateTranslationRemaps(skincolornum_t skincolor, INT32 cache_index);
 boolean R_TranslationIsValid(int id);
 
 void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum);
-- 
GitLab


From 3f57bff8329d317ba11f16e9eb9b3e776fe3a877 Mon Sep 17 00:00:00 2001
From: Lactozilla <jp6781615@gmail.com>
Date: Sat, 22 Feb 2025 05:07:15 -0300
Subject: [PATCH 2/3] Fix animated skincolors not working with translations

---
 src/r_translation.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_translation.c b/src/r_translation.c
index 67dbdfab01..41087e2725 100644
--- a/src/r_translation.c
+++ b/src/r_translation.c
@@ -1149,7 +1149,7 @@ static void R_UpdateTranslation(remaptable_t *tr, skincolornum_t skincolor, INT3
 	if (!tr->num_sources || !tr->skincolor_remaps || !tr->skincolor_remaps[cache_index])
 		return;
 
-	colorcache_t *cache = tr->skincolor_remaps[cache_index][skincolor];
+	colorcache_t *cache = tr->skincolor_remaps[cache_index][skincolor - 1];
 	if (cache)
 		R_ApplyTranslationRemap(tr, cache->colors, skincolor, cache_index);
 }
-- 
GitLab


From 3b7d6a3e7ad148a34f9a4763b949ea10e71fab8a Mon Sep 17 00:00:00 2001
From: Lactozilla <jp6781615@gmail.com>
Date: Sat, 22 Feb 2025 05:08:51 -0300
Subject: [PATCH 3/3] Ensure R_UpdateTranslation returns early in some
 situations

---
 src/r_draw.c        | 17 +++++++++++++++--
 src/r_draw.h        |  2 ++
 src/r_translation.c |  4 +++-
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/r_draw.c b/src/r_draw.c
index 4710a93c2f..4bf50cf286 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -125,7 +125,7 @@ INT32 R_SkinTranslationToCacheIndex(INT32 translation)
 	}
 }
 
-static INT32 CacheIndexToSkin(INT32 index)
+INT32 R_CacheIndexToSkinTranslation(INT32 index)
 {
 	switch (index)
 	{
@@ -140,6 +140,19 @@ static INT32 CacheIndexToSkin(INT32 index)
 	}
 }
 
+boolean R_IsSkinTranslationRemappable(INT32 translation)
+{
+	switch (translation)
+	{
+		case TC_METALSONIC:
+		case TC_ALLWHITE:
+		case TC_DASHMODE:
+			return false;
+		default:
+			return true;
+	}
+}
+
 CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
 
 /** \brief Initializes the translucency tables used by the Software renderer.
@@ -567,7 +580,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags
 					colorcache_t *cache = translationtablecache[i][color];
 					if (cache)
 					{
-						R_GenerateTranslationColormap(cache->colors, CacheIndexToSkin(i), color, starttranscolor);
+						R_GenerateTranslationColormap(cache->colors, R_CacheIndexToSkinTranslation(i), color, starttranscolor);
 						R_UpdateTranslationRemaps(color, i);
 					}
 				}
diff --git a/src/r_draw.h b/src/r_draw.h
index d5c5b4e25d..bfcf09fab0 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -90,6 +90,8 @@ enum
 };
 
 INT32 R_SkinTranslationToCacheIndex(INT32 translation);
+INT32 R_CacheIndexToSkinTranslation(INT32 index);
+boolean R_IsSkinTranslationRemappable(INT32 translation);
 
 // Amount of colors in the palette
 #define NUM_PALETTE_ENTRIES 256
diff --git a/src/r_translation.c b/src/r_translation.c
index 41087e2725..9fa76272a4 100644
--- a/src/r_translation.c
+++ b/src/r_translation.c
@@ -1146,7 +1146,9 @@ UINT8 *R_GetTranslationRemap(int id, skincolornum_t skincolor, INT32 skinnum)
 
 static void R_UpdateTranslation(remaptable_t *tr, skincolornum_t skincolor, INT32 cache_index)
 {
-	if (!tr->num_sources || !tr->skincolor_remaps || !tr->skincolor_remaps[cache_index])
+	if (skincolor == SKINCOLOR_NONE
+	|| !R_IsSkinTranslationRemappable(R_CacheIndexToSkinTranslation(cache_index))
+	|| !tr->num_sources || !tr->skincolor_remaps || !tr->skincolor_remaps[cache_index])
 		return;
 
 	colorcache_t *cache = tr->skincolor_remaps[cache_index][skincolor - 1];
-- 
GitLab