diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 3888dad854a49d0810ed916424166041e6cc2508..07b06b967616004d4d8f2721289bfe97f3c2efd3 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -810,7 +810,8 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
 	Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
 }
 
-
+#define NORMALFOG 0x00000000
+#define FADEFOG 0x19000000
 
 // -----------------+
 // HWR_DrawMD2      : Draw MD2
@@ -832,28 +833,12 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
 	run?
 	*/
 
-static UINT32 HWR_GetModelSprite2(mobj_t *mobj)
-{
-	UINT8 spr2 = 0;
-	UINT32 frame = 0;
-	spritedef_t *sprdef;
-	while (spr2 != mobj->sprite2)
-	{
-		sprdef = &((skin_t *)mobj->skin)->sprites[spr2];
-		frame += sprdef->numframes;
-		spr2++;
-	}
-	return frame;
-}
-
 static boolean HWR_CanInterpolateModel(mobj_t *mobj)
 {
-	return (!(mobj->state->nextstate == S_PLAY_WAIT && mobj->state == &states[S_PLAY_STND]))
+	return (!(mobj->state->nextstate == S_PLAY_WAIT && mobj->state == &states[S_PLAY_STND] && !(mobj->sprite2 & FF_SPR2SUPER)))
 	&& (mobj->state != &states[S_PLAY_ROLL]);
 }
 
-#define NORMALFOG 0x00000000
-#define FADEFOG 0x19000000
 void HWR_DrawMD2(gr_vissprite_t *spr)
 {
 	FSurfaceInfo Surf;
@@ -861,6 +846,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 	char filename[64];
 	INT32 frame = 0;
 	INT32 nextFrame = -1;
+	UINT8 spr2 = 0;
 	FTransform p;
 	md2_t *md2;
 	UINT8 color[4];
@@ -1024,10 +1010,17 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 		}
 
 		//FIXME: this is not yet correct
-		frame = (spr->mobj->frame & FF_FRAMEMASK);
 		if (spr->mobj->sprite2)
-			frame = HWR_GetModelSprite2(spr->mobj) + frame;
-		frame %= md2->model->meshes[0].numFrames;
+		{
+			spr2 = (spr->mobj->sprite2 & ~FF_SPR2SUPER);
+			frame = (spr->mobj->frame & FF_FRAMEMASK);
+			if (spr->mobj->sprite2 & FF_SPR2SUPER)
+				frame = md2->model->spr2frames[spr2].superframes[frame];
+			else
+				frame = md2->model->spr2frames[spr2].frames[frame];
+		}
+		else
+			frame = (spr->mobj->frame & FF_FRAMEMASK);
 
 #ifdef USE_MODEL_NEXTFRAME
 		if (cv_grmodels.value == 1 && tics <= durs)
@@ -1040,8 +1033,10 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 					nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
 					if (nextFrame >= framecount)
 						nextFrame = 0;
-					nextFrame = HWR_GetModelSprite2(spr->mobj) + nextFrame;
-					nextFrame %= md2->model->meshes[0].numFrames;
+					if (spr->mobj->sprite2 & FF_SPR2SUPER)
+						nextFrame = md2->model->spr2frames[spr2].superframes[nextFrame];
+					else
+						nextFrame = md2->model->spr2frames[spr2].frames[nextFrame];
 				}
 			}
 			else
@@ -1052,7 +1047,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 					nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
 					if (nextFrame >= spr->mobj->state->var1)
 						nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK);
-					nextFrame %= md2->model->meshes[0].numFrames;
 					//next = &md2->model->meshes[0].frames[nextFrame];
 				}
 				else
@@ -1060,7 +1054,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 					if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
 						&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_WAIT) && spr->mobj->state == &states[S_PLAY_STND]))
 					{
-						nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
+						nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK);
 						//next = &md2->model->meshes[0].frames[nextFrame];
 					}
 				}
diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c
index 3805deffb0657651a7157b753632ad7841259098..803573ade5e0645b6a678fc94e9cb7d7cb5f67f4 100644
--- a/src/hardware/hw_md2load.c
+++ b/src/hardware/hw_md2load.c
@@ -252,6 +252,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
 	md2triangle_t *tris;
 	md2texcoord_t *texcoords;
 	md2frame_t *frames;
+	char *fname = NULL;
 
 	int t;
 
@@ -326,6 +327,15 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
 	texcoords = (md2texcoord_t*)&buffer[header->offsetST];
 	frames = (md2frame_t*)&buffer[header->offsetFrames];
 
+	retModel->framenames = (char*)Z_Calloc(header->numFrames*16, ztag, 0);
+	fname = retModel->framenames;
+	for (i = 0; i < header->numFrames; i++)
+	{
+		memcpy(fname, frames->name, 16);
+		fname += 16;
+		frames++;
+	}
+
 	// Read in textures
 	retModel->numMaterials = header->numSkins;
 
diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c
index 53f6034c046b9c02d87f04ee67f00bf15b57e819..87931d27ba104e1f9a4109515f6497ad19bae453 100644
--- a/src/hardware/hw_md3load.c
+++ b/src/hardware/hw_md3load.c
@@ -148,6 +148,8 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
 {
 	const float WUNITS = 1.0f;
 	model_t *retModel = NULL;
+	md3Frame *frames = NULL;
+	char *fname = NULL;
 	md3modelHeader *mdh;
 	long fileLen;
 	long fileReadLen;
@@ -227,6 +229,16 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
 
 	retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0);
 
+	frames = (md3Frame*)&buffer[mdh->offsetFrames];
+	retModel->framenames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0);
+	fname = retModel->framenames;
+	for (i = 0; i < mdh->numFrames; i++)
+	{
+		memcpy(fname, frames->name, 16);
+		fname += 16;
+		frames++;
+	}
+
 	matCount = 0;
 	for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++)
 	{
diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c
index 2c36f974414df2b1319c5a774602483a4ecd6190..dfbc4d54ce76e9ea14dfc1672f04453f9d5a8a22 100644
--- a/src/hardware/hw_model.c
+++ b/src/hardware/hw_model.c
@@ -7,11 +7,14 @@
 	the licensing is for Sonic Robo Blast 2.
 */
 
-#include "../z_zone.h"
 #include "../doomdef.h"
+#include "../doomtype.h"
+#include "../info.h"
+#include "../z_zone.h"
 #include "hw_model.h"
 #include "hw_md2load.h"
 #include "hw_md3load.h"
+#include "hw_md2.h"
 #include "u_list.h"
 #include <string.h>
 
@@ -195,6 +198,7 @@ model_t *LoadModel(const char *filename, int ztag)
 
 	Optimize(model);
 	GeneratePolygonNormals(model, ztag);
+	LoadModelSprite2(model);
 
 	// Default material properties
 	for (i = 0 ; i < model->numMaterials; i++)
@@ -218,6 +222,84 @@ model_t *LoadModel(const char *filename, int ztag)
 	return model;
 }
 
+void HWR_ReloadModels(void)
+{
+	size_t i;
+	INT32 s;
+
+	for (s = 0; s < MAXSKINS; s++)
+	{
+		if (md2_playermodels[s].model)
+			LoadModelSprite2(md2_playermodels[s].model);
+	}
+
+	for (i = 0; i < NUMSPRITES; i++)
+	{
+		if (md2_models[i].model)
+			LoadModelSprite2(md2_models[i].model);
+	}
+}
+
+void LoadModelSprite2(model_t *model)
+{
+	INT32 i;
+	modelspr2frames_t *spr2frames = NULL;
+	INT32 numframes = model->meshes[0].numFrames;
+	char *framename = model->framenames;
+
+	if (!framename)
+		return;
+
+	for (i = 0; i < numframes; i++)
+	{
+		char prefix[6];
+		char name[5];
+		char framechar[3];
+		UINT8 frame = 0;
+		UINT8 spr2idx;
+
+		memset(&prefix, 0x00, 6);
+		memset(&name, 0x00, 5);
+		memset(&framechar, 0x00, 3);
+
+		if (strlen(framename) >= 8)
+		{
+			char *modelframename = framename;
+			memcpy(&prefix, modelframename, 5);
+			modelframename += 5;
+			memcpy(&name, modelframename, 4);
+			modelframename += 4;
+			memcpy(&framechar, modelframename, 2);
+			frame = atoi(framechar);
+
+			if ((!memcmp(prefix, "SPR2_", 5)) || (!memcmp(prefix, "SUPER", 5)))
+			{
+				spr2idx = 0;
+				while (spr2idx < NUMPLAYERSPRITES)
+				{
+					if (!memcmp(spr2names[spr2idx], name, 4))
+					{
+						if (!spr2frames)
+							spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
+						if (!memcmp(prefix, "SUPER", 5))
+							spr2frames[spr2idx].superframes[frame] = i;
+						else
+							spr2frames[spr2idx].frames[frame] = i;
+						break;
+					}
+					spr2idx++;
+				}
+			}
+		}
+
+		framename += 16;
+	}
+
+	if (model->spr2frames)
+		Z_Free(model->spr2frames);
+	model->spr2frames = spr2frames;
+}
+
 //
 // GenerateVertexNormals
 //
diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h
index 1803f4c5c32f2e93dfe52a440c58742c8fd8d9cf..af9020ef90f5ba9962e1a5764d5787860a5d4652 100644
--- a/src/hardware/hw_model.h
+++ b/src/hardware/hw_model.h
@@ -73,6 +73,12 @@ typedef struct tag_s
 //	matrix_t transform;
 } tag_t;
 
+typedef struct
+{
+	INT32 frames[256];
+	INT32 superframes[256];
+} modelspr2frames_t;
+
 typedef struct model_s
 {
 	int maxNumFrames;
@@ -86,15 +92,21 @@ typedef struct model_s
 
 	char *mdlFilename;
 	boolean unloaded;
+
+	modelspr2frames_t *spr2frames;
+	char *framenames;
 } model_t;
 
 extern int numModels;
 extern model_t *modelHead;
 
+void HWR_ReloadModels(void);
+
 tag_t *GetTagByName(model_t *model, char *name, int frame);
 model_t *LoadModel(const char *filename, int ztag);
 void UnloadModel(model_t *model);
 void Optimize(model_t *model);
+void LoadModelSprite2(model_t *model);
 void GenerateVertexNormals(model_t *model);
 void GeneratePolygonNormals(model_t *model, int ztag);
 void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
diff --git a/src/p_setup.c b/src/p_setup.c
index d0cd14b22d3011a64e26a23e44be00739420adeb..cb8f25457d1796a6419b113f5975da168e8a376f 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -75,6 +75,7 @@
 #ifdef HWRENDER
 #include "hardware/hw_main.h"
 #include "hardware/hw_light.h"
+#include "hardware/hw_model.h"
 #endif
 
 #ifdef ESLOPE
@@ -3479,6 +3480,10 @@ boolean P_AddWadFile(const char *wadfilename)
 	if (!mapsadded)
 		CONS_Printf(M_GetText("No maps added\n"));
 
+#ifdef HWRENDER
+	HWR_ReloadModels();
+#endif // HWRENDER
+
 	// reload status bar (warning should have valid player!)
 	if (gamestate == GS_LEVEL)
 		ST_Start();