From f93b1b8d7b5e6f4b73e73513e74f6e84c377dfaa Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 19 Apr 2021 04:01:49 -0300 Subject: [PATCH 1/7] Raise the skin limit to 256. --- src/d_clisrv.c | 6 +- src/d_main.c | 7 +- src/d_netcmd.c | 18 +++-- src/d_player.h | 2 +- src/deh_soc.c | 31 ++++----- src/dehacked.c | 2 +- src/doomdef.h | 3 +- src/g_game.c | 2 +- src/hardware/hw_md2.c | 16 +++-- src/hardware/hw_md2.h | 2 +- src/hardware/hw_model.c | 3 +- src/lua_playerlib.c | 3 +- src/m_cond.c | 3 +- src/m_menu.c | 141 ++++++++++++++++++++++------------------ src/m_menu.h | 7 +- src/p_saveg.c | 4 +- src/r_picformats.c | 9 ++- src/r_skins.c | 55 ++++++++-------- src/r_skins.h | 5 +- src/sounds.h | 4 +- src/st_stuff.c | 15 ++++- src/st_stuff.h | 6 +- 22 files changed, 195 insertions(+), 149 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7c2dec6a1..f1c24fe5a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2463,6 +2463,8 @@ void CL_ClearPlayer(INT32 playernum) { if (players[playernum].mo) P_RemoveMobj(players[playernum].mo); + if (players[playernum].availabilities) + Z_Free(players[playernum].availabilities); memset(&players[playernum], 0, sizeof (player_t)); memset(playeraddress[playernum], 0, sizeof(*playeraddress)); } @@ -4486,9 +4488,9 @@ static INT16 Consistancy(void) { if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - + mo = (mobj_t *)th; - + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) { ret -= mo->type; diff --git a/src/d_main.c b/src/d_main.c index 23a2c0133..e9d236a9b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -813,7 +813,8 @@ void D_StartTitle(void) for (i = 0; i < MAXPLAYERS; i++) CL_ClearPlayer(i); - players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); + R_GetSkinAvailabilities(&players[1].availabilities); // players[1] is supposed to be for 2p splitscreen = false; SplitScreen_OnChange(); @@ -1216,10 +1217,6 @@ void D_SRB2Main(void) // Make backups of some SOCcable tables. P_BackupTables(); - // Setup character tables - // Have to be done here before files are loaded - M_InitCharacterTables(); - mainwads = 3; // doesn't include music.dta #ifdef USE_PATCH_DTA mainwads++; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 09f9d4651..14349d559 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1235,7 +1235,7 @@ static void SendNameAndColor(void) && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) return; - players[consoleplayer].availabilities = R_GetSkinAvailabilities(); + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); // We'll handle it later if we're not playing. if (!Playing()) @@ -1319,9 +1319,9 @@ static void SendNameAndColor(void) // Finally write out the complete packet and send it off. WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME); - WRITEUINT32(p, (UINT32)players[consoleplayer].availabilities); WRITEUINT16(p, (UINT16)cv_playercolor.value); WRITEUINT8(p, (UINT8)cv_skin.value); + WRITEMEM(p, players[consoleplayer].availabilities, sizeof(bitarray_t) * numskins); SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf); } @@ -1363,7 +1363,7 @@ static void SendNameAndColor2(void) } } - players[secondplaya].availabilities = R_GetSkinAvailabilities(); + R_GetSkinAvailabilities(&players[secondplaya].availabilities); // We'll handle it later if we're not playing. if (!Playing()) @@ -1455,10 +1455,13 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) #endif READSTRINGN(*cp, name, MAXPLAYERNAME); - p->availabilities = READUINT32(*cp); color = READUINT16(*cp); skin = READUINT8(*cp); + if (p->availabilities == NULL) + p->availabilities = Z_Malloc(sizeof(bitarray_t) * numskins, PU_STATIC, NULL); + READMEM(*cp, p->availabilities, sizeof(bitarray_t) * numskins); + // set name if (player_name_changes[playernum] < MAXNAMECHANGES) { @@ -1491,9 +1494,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) kick = true; // availabilities - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < numskins; s++) { - if (!skins[s].availability && (p->availabilities & (1 << s))) + if (!skins[s].availability && in_bit_array(p->availabilities, s)) { kick = true; break; @@ -4278,7 +4281,8 @@ void Command_ExitGame_f(void) for (i = 0; i < MAXPLAYERS; i++) CL_ClearPlayer(i); - players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); + R_GetSkinAvailabilities(&players[1].availabilities); // players[1] is supposed to be for 2p splitscreen = false; SplitScreen_OnChange(); diff --git a/src/d_player.h b/src/d_player.h index 2e7afed88..d90dd79ff 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -379,7 +379,7 @@ typedef struct player_s UINT16 skincolor; INT32 skin; - UINT32 availabilities; + bitarray_t *availabilities; UINT32 score; // player score fixed_t dashspeed; // dashing speed diff --git a/src/deh_soc.c b/src/deh_soc.c index 5b12ea1b0..046ed885a 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -162,23 +162,20 @@ void clear_levels(void) static boolean findFreeSlot(INT32 *num) { - // Send the character select entry to a free slot. - while (*num < MAXSKINS && (description[*num].used)) - *num = *num+1; + if (description) + { + // Send the character select entry to a free slot. + while (*num < numdescriptions && (description[*num].used)) + (*num)++; + } - // No more free slots. :( - if (*num >= MAXSKINS) + // No more free slots. + if (*num >= MAXCHARACTERSLOTS) return false; + else if (*num >= numdescriptions) + M_InitCharacterTables((*num) + 1); - // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...) - description[*num].picname[0] = '\0'; - description[*num].nametag[0] = '\0'; - description[*num].displayname[0] = '\0'; - description[*num].oppositecolor = SKINCOLOR_NONE; - description[*num].tagtextcolor = SKINCOLOR_NONE; - description[*num].tagoutlinecolor = SKINCOLOR_NONE; - - // Found one! ^_^ + // Found one! return (description[*num].used = true); } @@ -891,7 +888,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) INT32 value; #endif char *lastline; - INT32 skinnumbers[MAXSKINS]; + INT32 *skinnumbers = NULL; INT32 foundskins = 0; // allocate a spriteinfo @@ -980,6 +977,8 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) break; } + if (skinnumbers == NULL) + skinnumbers = Z_Malloc(sizeof(INT32) * numskins, PU_STATIC, NULL); skinnumbers[foundskins] = skinnum; foundskins++; } @@ -1043,6 +1042,8 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) Z_Free(s); Z_Free(info); + if (skinnumbers) + Z_Free(skinnumbers); } void readsprite2(MYFILE *f, INT32 num) diff --git a/src/dehacked.c b/src/dehacked.c index c2ea28d27..8d3c5725f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -241,7 +241,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) i = 0; if (fastcmp(word, "CHARACTER")) { - if (i >= 0 && i < 32) + if (i >= 0 && i < MAXCHARACTERSLOTS) readPlayer(f, i); else { diff --git a/src/doomdef.h b/src/doomdef.h index 52abc9597..e7831f689 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -220,7 +220,8 @@ extern char logfilename[1024]; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 32 -#define MAXSKINS 32 +#define MAXSKINS 256 +#define MAXCHARACTERSLOTS (MAXSKINS * 2) #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 diff --git a/src/g_game.c b/src/g_game.c index 13423ce77..7f48556ff 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2486,7 +2486,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT8 mare; UINT16 skincolor; INT32 skin; - UINT32 availabilities; + bitarray_t *availabilities; tic_t jointime; tic_t quittime; boolean spectator; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5caf344f7..cba322b2a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -71,7 +71,7 @@ #endif md2_t md2_models[NUMSPRITES]; -md2_t md2_playermodels[MAXSKINS]; +md2_t *md2_playermodels = NULL; /* @@ -490,7 +490,11 @@ void HWR_InitModels(void) size_t prefixlen; CONS_Printf("HWR_InitModels()...\n"); - for (s = 0; s < MAXSKINS; s++) + + if (numskins && md2_playermodels == NULL) + md2_playermodels = Z_Malloc(sizeof(md2_t), PU_STATIC, NULL); + + for (s = 0; s < numskins; s++) { md2_playermodels[s].scale = -1.0f; md2_playermodels[s].model = NULL; @@ -501,6 +505,7 @@ void HWR_InitModels(void) md2_playermodels[s].notfound = true; md2_playermodels[s].error = false; } + for (i = 0; i < NUMSPRITES; i++) { md2_models[i].scale = -1.0f; @@ -561,7 +566,7 @@ void HWR_InitModels(void) addskinmodel: // add player model - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < numskins; s++) { if (stricmp(skinname, skins[s].name) == 0) { @@ -581,7 +586,7 @@ modelfound: fclose(f); } -void HWR_AddPlayerModel(int skin) // For skins that were added after startup +void HWR_AddPlayerModel(INT32 skin) // For skins that were added after startup { FILE *f; char name[24], filename[32]; @@ -608,6 +613,9 @@ void HWR_AddPlayerModel(int skin) // For skins that were added after startup } } + // realloc player models table + md2_playermodels = Z_Realloc(md2_playermodels, sizeof(md2_t) * numskins, PU_STATIC, NULL); + // length of the player model prefix prefixlen = strlen(PLAYERMODELPREFIX); diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 0f4d2c7bc..42787115a 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -37,7 +37,7 @@ typedef struct } md2_t; extern md2_t md2_models[NUMSPRITES]; -extern md2_t md2_playermodels[MAXSKINS]; +extern md2_t *md2_playermodels; void HWR_InitModels(void); void HWR_AddPlayerModel(INT32 skin); diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 4ed03744b..86e2a0c70 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -10,6 +10,7 @@ #include "../doomdef.h" #include "../doomtype.h" #include "../info.h" +#include "../r_skins.h" #include "../z_zone.h" #include "hw_model.h" #include "hw_md2load.h" @@ -238,7 +239,7 @@ void HWR_ReloadModels(void) size_t i; INT32 s; - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < numskins; s++) { if (md2_playermodels[s].model) LoadModelSprite2(md2_playermodels[s].model); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0eb54808f..b05e21ca9 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -16,6 +16,7 @@ #include "d_player.h" #include "g_game.h" #include "p_local.h" +#include "r_skins.h" #include "lua_script.h" #include "lua_libs.h" @@ -161,7 +162,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"skin")) lua_pushinteger(L, plr->skin); else if (fastcmp(field,"availabilities")) - lua_pushinteger(L, plr->availabilities); + lua_pushinteger(L, R_GetAvailabilitiesBits(plr->availabilities)); else if (fastcmp(field,"score")) lua_pushinteger(L, plr->score); else if (fastcmp(field,"dashspeed")) diff --git a/src/m_cond.c b/src/m_cond.c index 36fcd7cf2..44ac94373 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -285,7 +285,8 @@ void M_SilentUpdateUnlockablesAndEmblems(void) unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1); } - players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); + R_GetSkinAvailabilities(&players[1].availabilities); // players[1] is supposed to be for 2p } // Emblem unlocking shit diff --git a/src/m_menu.c b/src/m_menu.c index 0fca39801..0c5c706a8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -126,7 +126,9 @@ M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 -description_t description[MAXSKINS]; +description_t *description = NULL; +INT32 numdescriptions = 0; + INT16 char_on = -1, startchar = 0; static char *char_notes = NULL; @@ -255,7 +257,7 @@ static void M_ConfirmTeamScramble(INT32 choice); static void M_ConfirmTeamChange(INT32 choice); static void M_SecretsMenu(INT32 choice); static void M_SetupChoosePlayer(INT32 choice); -static UINT8 M_SetupChoosePlayerDirect(INT32 choice); +static UINT16 M_SetupChoosePlayerDirect(INT32 choice); static void M_QuitSRB2(INT32 choice); menu_t SP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; @@ -3970,24 +3972,32 @@ void M_Init(void) #endif } -void M_InitCharacterTables(void) +static void M_InitCharacterDescription(INT32 i) { - UINT8 i; - // Setup description table - for (i = 0; i < MAXSKINS; i++) - { - description[i].used = false; - strcpy(description[i].notes, "???"); - strcpy(description[i].picname, ""); - strcpy(description[i].nametag, ""); - strcpy(description[i].skinname, ""); - strcpy(description[i].displayname, ""); - description[i].prev = description[i].next = 0; - description[i].charpic = NULL; - description[i].namepic = NULL; - description[i].oppositecolor = description[i].tagtextcolor = description[i].tagoutlinecolor = 0; - } + description_t *desc = &description[i]; + desc->picname[0] = '\0'; + desc->nametag[0] = '\0'; + desc->skinname[0] = '\0'; + desc->displayname[0] = '\0'; + desc->prev = desc->next = 0; + desc->charpic = NULL; + desc->namepic = NULL; + desc->oppositecolor = SKINCOLOR_NONE; + desc->tagtextcolor = SKINCOLOR_NONE; + desc->tagoutlinecolor = SKINCOLOR_NONE; + strcpy(desc->notes, "???"); +} + +void M_InitCharacterTables(INT32 num) +{ + INT32 i = numdescriptions; + + description = Z_Realloc(description, sizeof(description_t) * num, PU_STATIC, NULL); + numdescriptions = num; + + for (; i < numdescriptions; i++) + M_InitCharacterDescription(i); } // ========================================================================== @@ -4981,7 +4991,7 @@ static void M_PatchSkinNameTable(void) for (j = 0; j < MAXSKINS; j++) { - if (skins[j].name[0] != '\0' && R_SkinUsable(-1, j)) + if (j < numskins && skins[j].name[0] != '\0' && R_SkinUsable(-1, j)) { skins_cons_t[j].strvalue = skins[j].realname; skins_cons_t[j].value = j+1; @@ -8961,64 +8971,67 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); } -static UINT8 M_SetupChoosePlayerDirect(INT32 choice) +static UINT16 M_SetupChoosePlayerDirect(INT32 choice) { INT32 skinnum; - UINT8 i; - UINT8 firstvalid = 255, lastvalid = 255; + UINT16 i; + UINT16 firstvalid = 65535, lastvalid = 65535; boolean allowed = false; - char *and; (void)choice; if (!mapheaderinfo[startmap-1] || mapheaderinfo[startmap-1]->forcecharacter[0] == '\0') { - for (i = 0; i < MAXSKINS; i++) // Handle charsels, availability, and unlocks. + for (i = 0; i < numdescriptions; i++) // Handle charsels, availability, and unlocks. { - if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. + char *and; + + // If the character's disabled through SOC, there's nothing we can do for it. + if (!description[i].used) + continue; + + and = strchr(description[i].skinname, '&'); + + if (and) { - and = strchr(description[i].skinname, '&'); - if (and) - { - char firstskin[SKINNAMESIZE+1]; - if (mapheaderinfo[startmap-1] && mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS) // skip tagteam characters for NiGHTS levels - continue; - strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); - firstskin[(and - description[i].skinname)] = '\0'; - description[i].skinnum[0] = R_SkinAvailable(firstskin); - description[i].skinnum[1] = R_SkinAvailable(and+1); - } + char firstskin[SKINNAMESIZE+1]; + if (mapheaderinfo[startmap-1] && mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS) // skip tagteam characters for NiGHTS levels + continue; + strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); + firstskin[(and - description[i].skinname)] = '\0'; + description[i].skinnum[0] = R_SkinAvailable(firstskin); + description[i].skinnum[1] = R_SkinAvailable(and+1); + } + else + { + description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); + description[i].skinnum[1] = -1; + } + + skinnum = description[i].skinnum[0]; + + if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) + { + // Handling order. + if (firstvalid == 65535) + firstvalid = i; else { - description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); - description[i].skinnum[1] = -1; + description[i].prev = lastvalid; + description[lastvalid].next = i; } - skinnum = description[i].skinnum[0]; - if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) - { - // Handling order. - if (firstvalid == 255) - firstvalid = i; - else - { - description[i].prev = lastvalid; - description[lastvalid].next = i; - } - lastvalid = i; + lastvalid = i; - if (i == char_on) - allowed = true; + if (i == char_on) + allowed = true; - M_CacheCharacterSelectEntry(i, skinnum); - } - // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. + M_CacheCharacterSelectEntry(i, skinnum); } + // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. } } if (firstvalid == lastvalid) // We're being forced into a specific character, so might as well just skip it. - { return firstvalid; - } // One last bit of order we can't do in the iteration above. description[firstvalid].prev = lastvalid; @@ -9027,7 +9040,7 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) if (!allowed) { char_on = firstvalid; - if (startchar > 0 && startchar < MAXSKINS) + if (startchar > 0 && startchar < numdescriptions) { INT16 workchar = startchar; while (workchar--) @@ -9035,13 +9048,13 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) } } - return MAXSKINS; + return MAXCHARACTERSLOTS; } static void M_SetupChoosePlayer(INT32 choice) { - UINT8 skinset = M_SetupChoosePlayerDirect(choice); - if (skinset != MAXSKINS) + UINT16 skinset = M_SetupChoosePlayerDirect(choice); + if (skinset != MAXCHARACTERSLOTS) { M_ChoosePlayer(skinset); return; @@ -9362,7 +9375,7 @@ static void M_ChoosePlayer(INT32 choice) UINT8 skinnum; // skip this if forcecharacter or no characters available - if (choice == 255) + if (choice == 65535) { skinnum = botskin = 0; botingame = false; @@ -10431,7 +10444,7 @@ static void M_MarathonLiveEventBackup(INT32 choice) // Going to Marathon menu... static void M_Marathon(INT32 choice) { - UINT8 skinset; + UINT16 skinset; INT32 mapnum = 0; if (choice != -1 && FIL_FileExists(liveeventbackup)) @@ -10454,7 +10467,7 @@ static void M_Marathon(INT32 choice) skinset = M_SetupChoosePlayerDirect(-1); - SP_MarathonMenu[marathonplayer].status = (skinset == MAXSKINS) ? IT_KEYHANDLER|IT_STRING : IT_NOTHING|IT_DISABLED; + SP_MarathonMenu[marathonplayer].status = (skinset == MAXCHARACTERSLOTS) ? IT_KEYHANDLER|IT_STRING : IT_NOTHING|IT_DISABLED; while (mapnum < NUMMAPS) { diff --git a/src/m_menu.h b/src/m_menu.h index 0465128ef..018d5c7e7 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -200,8 +200,8 @@ void M_Drawer(void); // Called by D_SRB2Main, loads the config file. void M_Init(void); -// Called by D_SRB2Main also, sets up the playermenu and description tables. -void M_InitCharacterTables(void); +// Called by deh_soc.c, sets up the playermenu and description tables. +void M_InitCharacterTables(INT32 num); // Called by intro code to force menu up upon a keypress, // does nothing if menu is already up. @@ -431,7 +431,8 @@ typedef struct INT32 gamemap; } saveinfo_t; -extern description_t description[MAXSKINS]; +extern description_t *description; +extern INT32 numdescriptions; extern consvar_t cv_showfocuslost; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; diff --git a/src/p_saveg.c b/src/p_saveg.c index 03229e740..80bdfa09e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -139,7 +139,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].skincolor); WRITEINT32(save_p, players[i].skin); - WRITEUINT32(save_p, players[i].availabilities); + WRITEMEM(save_p, players[i].availabilities, sizeof(bitarray_t) * numskins); WRITEUINT32(save_p, players[i].score); WRITEFIXED(save_p, players[i].dashspeed); WRITESINT8(save_p, players[i].lives); @@ -353,7 +353,7 @@ static void P_NetUnArchivePlayers(void) players[i].skincolor = READUINT8(save_p); players[i].skin = READINT32(save_p); - players[i].availabilities = READUINT32(save_p); + READMEM(save_p, players[i].availabilities, sizeof(bitarray_t) * numskins); players[i].score = READUINT32(save_p); players[i].dashspeed = READFIXED(save_p); // dashing speed players[i].lives = READSINT8(save_p); diff --git a/src/r_picformats.c b/src/r_picformats.c index f87362c76..ff2b9f15a 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2018-2021 by Jaime "Lactozilla" Passos. // Copyright (C) 2019-2020 by Sonic Team Junior. // // This program is free software distributed under the @@ -1494,7 +1494,7 @@ static void R_ParseSpriteInfo(boolean spr2) spritenum_t sprnum = NUMSPRITES; playersprite_t spr2num = NUMPLAYERSPRITES; INT32 i; - INT32 skinnumbers[MAXSKINS]; + INT32 *skinnumbers = NULL; INT32 foundskins = 0; // Sprite name @@ -1592,6 +1592,8 @@ static void R_ParseSpriteInfo(boolean spr2) if (skinnum == -1) I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + if (skinnumbers == NULL) + skinnumbers = Z_Malloc(sizeof(INT32) * numskins, PU_STATIC, NULL); skinnumbers[foundskins] = skinnum; foundskins++; } @@ -1630,8 +1632,11 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); } + Z_Free(sprinfoToken); Z_Free(info); + if (skinnumbers) + Z_Free(skinnumbers); } // diff --git a/src/r_skins.c b/src/r_skins.c index 6f150f234..bfbc3e18f 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -18,6 +18,7 @@ #include "st_stuff.h" #include "w_wad.h" #include "z_zone.h" +#include "m_menu.h" #include "m_misc.h" #include "info.h" // spr2names #include "i_video.h" // rendermode @@ -32,13 +33,7 @@ #endif INT32 numskins = 0; -skin_t skins[MAXSKINS]; - -// FIXTHIS: don't work because it must be inistilised before the config load -//#define SKINVALUES -#ifdef SKINVALUES -CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; -#endif +skin_t *skins = NULL; // // P_GetSkinSprite2 @@ -160,30 +155,37 @@ static void Sk_SetDefaultValue(skin_t *skin) // void R_InitSkins(void) { -#ifdef SKINVALUES - INT32 i; - - for (i = 0; i <= MAXSKINS; i++) - { - skin_cons_t[i].value = 0; - skin_cons_t[i].strvalue = NULL; - } -#endif - // no default skin! numskins = 0; } -UINT32 R_GetSkinAvailabilities(void) +void R_GetSkinAvailabilities(bitarray_t **response) +{ + INT32 s; + + if (*response == NULL) + (*response) = Z_Calloc(sizeof(bitarray_t) * numskins, PU_STATIC, NULL); + + for (s = 0; s < numskins; s++) + { + if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) + set_bit_array((*response), s); + else + unset_bit_array((*response), s); + } +} + +UINT32 R_GetAvailabilitiesBits(bitarray_t *availabilities) { INT32 s; UINT32 response = 0; - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < min(numskins, 32); s++) { - if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) + if (in_bit_array(availabilities, s)) response |= (1 << s); } + return response; } @@ -193,7 +195,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... || (!skins[skinnum].availability) - || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) + || (((netgame || multiplayer) && playernum != -1) ? (in_bit_array(players[playernum].availabilities, skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. @@ -594,6 +596,7 @@ void R_AddSkins(UINT16 wadnum) buf2[size] = '\0'; // set defaults + skins = Z_Realloc(skins, sizeof(skin_t) * (numskins + 1), PU_STATIC, NULL); skin = &skins[numskins]; Sk_SetDefaultValue(skin); skin->wadnum = wadnum; @@ -695,17 +698,13 @@ next_token: if (!skin->availability) // Safe to print... CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); -#ifdef SKINVALUES - skin_cons_t[numskins].value = numskins; - skin_cons_t[numskins].strvalue = skin->name; -#endif + + numskins++; #ifdef HWRENDER if (rendermode == render_opengl) - HWR_AddPlayerModel(numskins); + HWR_AddPlayerModel(numskins-1); #endif - - numskins++; } return; } diff --git a/src/r_skins.h b/src/r_skins.h index fbbb38743..f2e76afcb 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -86,7 +86,7 @@ typedef struct /// Externs extern INT32 numskins; -extern skin_t skins[MAXSKINS]; +extern skin_t *skins; /// Function prototypes void R_InitSkins(void); @@ -94,7 +94,8 @@ void R_InitSkins(void); void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 boolean R_SkinUsable(INT32 playernum, INT32 skinnum); -UINT32 R_GetSkinAvailabilities(void); +void R_GetSkinAvailabilities(bitarray_t **response); +UINT32 R_GetAvailabilitiesBits(bitarray_t *availabilities); INT32 R_SkinAvailable(const char *name); void R_PatchSkins(UINT16 wadnum); void R_AddSkins(UINT16 wadnum); diff --git a/src/sounds.h b/src/sounds.h index e49dd2f3e..7a2e3bc25 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -43,7 +43,7 @@ typedef enum // free sfx for S_AddSoundFx() #define NUMSFXFREESLOTS 1600 // Matches SOC Editor. -#define NUMSKINSFXSLOTS (MAXSKINS*NUMSKINSOUNDS) +#define NUMSKINSFXSLOTS (128*NUMSKINSOUNDS) // // SoundFX struct. @@ -874,7 +874,7 @@ typedef enum // free slots for S_AddSoundFx() at run-time -------------------- sfx_freeslot0, // - // ... 60 free sounds here ... + // ... 1600 free sounds here ... // sfx_lastfreeslot = sfx_freeslot0 + NUMSFXFREESLOTS-1, // end of freeslots --------------------------------------------- diff --git a/src/st_stuff.c b/src/st_stuff.c index a1fbbec03..cd4582f6d 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -50,8 +50,8 @@ UINT16 objectsdrawn = 0; // STATUS BAR DATA // -patch_t *faceprefix[MAXSKINS]; // face status patches -patch_t *superprefix[MAXSKINS]; // super face status patches +patch_t **faceprefix; // face status patches +patch_t **superprefix; // super face status patches // ------------------------------------------ // status bar overlay @@ -368,6 +368,17 @@ void ST_ReloadSkinFaceGraphics(void) { INT32 i; + if (faceprefix) + Z_Free(faceprefix); + if (superprefix) + Z_Free(superprefix); + + if (!numskins) + return; + + faceprefix = Z_Malloc(sizeof(patch_t *) * numskins, PU_STATIC, NULL); + superprefix = Z_Malloc(sizeof(patch_t *) * numskins, PU_STATIC, NULL); + for (i = 0; i < numskins; i++) ST_LoadFaceGraphics(i); } diff --git a/src/st_stuff.h b/src/st_stuff.h index 4ea307d2b..c31651cd5 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -42,7 +42,7 @@ void ST_UnloadGraphics(void); void ST_LoadGraphics(void); // face load graphics, called when skin changes -void ST_LoadFaceGraphics(INT32 playernum); +void ST_LoadFaceGraphics(INT32 skinnum); void ST_ReloadSkinFaceGraphics(void); void ST_doPaletteStuff(void); @@ -76,8 +76,8 @@ extern patch_t *sboscore; extern patch_t *sbotime; extern patch_t *sbocolon; extern patch_t *sboperiod; -extern patch_t *faceprefix[MAXSKINS]; // face status patches -extern patch_t *superprefix[MAXSKINS]; // super face status patches +extern patch_t **faceprefix; // face status patches +extern patch_t **superprefix; // super face status patches extern patch_t *livesback; extern patch_t *stlivex; extern patch_t *ngradeletters[7]; From f2472d88b8a5c0b4b873f2491b1b3f3d2374cfe7 Mon Sep 17 00:00:00 2001 From: lachablock Date: Mon, 9 Aug 2021 17:30:05 +1000 Subject: [PATCH 2/7] Fix some crashes --- src/hardware/hw_md2.c | 2 +- src/hardware/hw_model.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 6f9863406..81e20f069 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -492,7 +492,7 @@ void HWR_InitModels(void) CONS_Printf("HWR_InitModels()...\n"); if (numskins && md2_playermodels == NULL) - md2_playermodels = Z_Malloc(sizeof(md2_t), PU_STATIC, NULL); + md2_playermodels = Z_Malloc(sizeof(md2_t) * numskins, PU_STATIC, NULL); for (s = 0; s < numskins; s++) { diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 86e2a0c70..52f9ce6ea 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -239,11 +239,13 @@ void HWR_ReloadModels(void) size_t i; INT32 s; - for (s = 0; s < numskins; s++) - { - if (md2_playermodels[s].model) - LoadModelSprite2(md2_playermodels[s].model); - } + if (md2_playermodels != NULL) + for (s = 0; s < numskins; s++) + { + CONS_Printf("%u\n", s); + if (md2_playermodels[s].model) + LoadModelSprite2(md2_playermodels[s].model); + } for (i = 0; i < NUMSPRITES; i++) { From 2aa9bb59ef15570248a39c1eb4b6adcbb5a2e821 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 9 Aug 2021 15:57:07 -0300 Subject: [PATCH 3/7] Memory management fixes Date: Mon Aug 9 15:57:07 2021 -0300 --- src/command.c | 2 +- src/d_netcmd.c | 52 ++++----- src/deh_soc.c | 2 +- src/f_finale.c | 14 +-- src/g_demo.c | 18 +-- src/g_game.c | 22 ++-- src/hardware/hw_main.c | 12 +- src/hardware/hw_md2.c | 238 +++++++++++--------------------------- src/hardware/hw_md2.h | 8 +- src/hardware/hw_md2load.c | 4 +- src/hardware/hw_md3load.c | 4 +- src/hardware/hw_model.c | 29 ++--- src/hardware/hw_model.h | 9 +- src/hu_stuff.c | 2 +- src/lua_hudlib.c | 8 +- src/lua_mobjlib.c | 4 +- src/lua_skinlib.c | 12 +- src/m_menu.c | 66 +++++------ src/p_enemy.c | 16 +-- src/p_mobj.c | 20 ++-- src/p_saveg.c | 8 +- src/p_setup.c | 44 +++---- src/p_spec.c | 2 +- src/p_user.c | 30 ++--- src/r_draw.c | 2 +- src/r_picformats.c | 2 +- src/r_skins.c | 28 ++--- src/r_skins.h | 3 +- src/r_things.c | 20 +--- src/st_stuff.c | 22 ++-- src/v_video.c | 4 +- src/y_inter.c | 16 +-- 32 files changed, 303 insertions(+), 420 deletions(-) diff --git a/src/command.c b/src/command.c index ae4a7178e..2897922e1 100644 --- a/src/command.c +++ b/src/command.c @@ -1944,7 +1944,7 @@ static void CV_SetValueMaybeStealth(consvar_t *var, INT32 value, boolean stealth if ((value < 0) || (value >= numskins)) tmpskin = "None"; else - tmpskin = skins[value].name; + tmpskin = skins[value]->name; strncpy(val, tmpskin, SKINNAMESIZE); } else diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0a7172b12..d5da66066 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1187,9 +1187,9 @@ static void ForceAllSkins(INT32 forcedskin) if (!dedicated) // But don't do this for dedicated servers, of course. { if (i == consoleplayer) - CV_StealthSet(&cv_skin, skins[forcedskin].name); + CV_StealthSet(&cv_skin, skins[forcedskin]->name); else if (i == secondarydisplayplayer) - CV_StealthSet(&cv_skin2, skins[forcedskin].name); + CV_StealthSet(&cv_skin2, skins[forcedskin]->name); } } } @@ -1221,8 +1221,8 @@ static void SendNameAndColor(void) CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor); else if (skincolors[atoi(cv_playercolor.defaultvalue)].accessible) CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue); - else if (skins[players[consoleplayer].skin].prefcolor && skincolors[skins[players[consoleplayer].skin].prefcolor].accessible) - CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor); + else if (skins[players[consoleplayer].skin]->prefcolor && skincolors[skins[players[consoleplayer].skin]->prefcolor].accessible) + CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin]->prefcolor); else { UINT16 i = 0; while (iname)) return; players[consoleplayer].availabilities = R_GetSkinAvailabilities(); @@ -1257,7 +1257,7 @@ static void SendNameAndColor(void) if (metalrecording) { // Starring Metal Sonic as themselves, obviously. SetPlayerSkinByNum(consoleplayer, 5); - CV_StealthSet(&cv_skin, skins[5].name); + CV_StealthSet(&cv_skin, skins[5]->name); } else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) { @@ -1268,11 +1268,11 @@ static void SendNameAndColor(void) //notsame = (cv_skin.value != players[consoleplayer].skin); SetPlayerSkin(consoleplayer, cv_skin.string); - CV_StealthSet(&cv_skin, skins[cv_skin.value].name); + CV_StealthSet(&cv_skin, skins[cv_skin.value]->name); /*if (notsame) { - CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor); + CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value]->prefcolor); players[consoleplayer].skincolor = cv_playercolor.value % numskincolors; @@ -1283,7 +1283,7 @@ static void SendNameAndColor(void) else { cv_skin.value = players[consoleplayer].skin; - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin]->name); // will always be same as current SetPlayerSkin(consoleplayer, cv_skin.string); } @@ -1306,7 +1306,7 @@ static void SendNameAndColor(void) // Don't change skin if the server doesn't want you to. if (!CanChangeSkin(consoleplayer)) - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin]->name); // check if player has the skin loaded (cv_skin may have // the name of a skin that was available in the previous game) @@ -1314,7 +1314,7 @@ static void SendNameAndColor(void) if ((cv_skin.value < 0) || !R_SkinUsable(consoleplayer, cv_skin.value)) { INT32 defaultSkinNum = GetPlayerDefaultSkin(consoleplayer); - CV_StealthSet(&cv_skin, skins[defaultSkinNum].name); + CV_StealthSet(&cv_skin, skins[defaultSkinNum]->name); cv_skin.value = defaultSkinNum; } @@ -1355,8 +1355,8 @@ static void SendNameAndColor2(void) CV_StealthSetValue(&cv_playercolor2, players[secondplaya].skincolor); else if (skincolors[atoi(cv_playercolor2.defaultvalue)].accessible) CV_StealthSet(&cv_playercolor, cv_playercolor2.defaultvalue); - else if (skins[players[secondplaya].skin].prefcolor && skincolors[skins[players[secondplaya].skin].prefcolor].accessible) - CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor); + else if (skins[players[secondplaya].skin]->prefcolor && skincolors[skins[players[secondplaya].skin]->prefcolor].accessible) + CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin]->prefcolor); else { UINT16 i = 0; while (iname); } else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin)) { @@ -1408,11 +1408,11 @@ static void SendNameAndColor2(void) //notsame = (cv_skin2.value != players[secondplaya].skin); SetPlayerSkin(secondplaya, cv_skin2.string); - CV_StealthSet(&cv_skin2, skins[cv_skin2.value].name); + CV_StealthSet(&cv_skin2, skins[cv_skin2.value]->name); /*if (notsame) { - CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor); + CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin]->prefcolor); players[secondplaya].skincolor = cv_playercolor2.value % numskincolors; @@ -1423,7 +1423,7 @@ static void SendNameAndColor2(void) else { cv_skin2.value = players[secondplaya].skin; - CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin].name); + CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin]->name); // will always be same as current SetPlayerSkin(secondplaya, cv_skin2.string); } @@ -1512,7 +1512,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) { illegalMask &= ~(1 << i); } - + if ((p->availabilities & illegalMask) != 0) { kick = true; @@ -1534,9 +1534,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) SetPlayerSkinByNum(playernum, forcedskin); if (playernum == consoleplayer) - CV_StealthSet(&cv_skin, skins[forcedskin].name); + CV_StealthSet(&cv_skin, skins[forcedskin]->name); else if (playernum == secondarydisplayplayer) - CV_StealthSet(&cv_skin2, skins[forcedskin].name); + CV_StealthSet(&cv_skin2, skins[forcedskin]->name); } else SetPlayerSkinByNum(playernum, skin); @@ -2112,7 +2112,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) if (modeattacking) { SetPlayerSkinByNum(0, cv_chooseskin.value-1); - players[0].skincolor = skins[players[0].skin].prefcolor; + players[0].skincolor = skins[players[0].skin]->prefcolor; CV_StealthSetValue(&cv_playercolor, players[0].skincolor); } @@ -4467,7 +4467,7 @@ static void ForceSkin_OnChange(void) CONS_Printf("The server has lifted the forced skin restrictions.\n"); else { - CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name); + CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value]->name); ForceAllSkins(cv_forceskin.value); } } @@ -4508,7 +4508,7 @@ static void Skin_OnChange(void) if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player. && (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y { - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin]->name); return; } @@ -4517,7 +4517,7 @@ static void Skin_OnChange(void) else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin]->name); } } @@ -4536,7 +4536,7 @@ static void Skin2_OnChange(void) else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); - CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name); + CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin]->name); } } @@ -4554,7 +4554,7 @@ static void Color_OnChange(void) { if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player. { - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin]->name); return; } diff --git a/src/deh_soc.c b/src/deh_soc.c index eb08cf0c5..4c63a4d6a 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1055,7 +1055,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) for (i = 0; i < foundskins; i++) { size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; + skin_t *skin = skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); } diff --git a/src/f_finale.c b/src/f_finale.c index 4d9a8f825..27f62ec5b 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1624,9 +1624,9 @@ void F_GameEvaluationDrawer(void) rtatext = (marathonmode & MA_INGAME) ? "In-game timer" : "RTA timer"; cuttext = (marathonmode & MA_NOCUTSCENES) ? "" : " w/ cutscenes"; if (botskin) - endingtext = va("%s & %s, %s%s", skins[players[consoleplayer].skin].realname, skins[botskin-1].realname, rtatext, cuttext); + endingtext = va("%s & %s, %s%s", skins[players[consoleplayer].skin]->realname, skins[botskin-1]->realname, rtatext, cuttext); else - endingtext = va("%s, %s%s", skins[players[consoleplayer].skin].realname, rtatext, cuttext); + endingtext = va("%s, %s%s", skins[players[consoleplayer].skin]->realname, rtatext, cuttext); V_DrawCenteredString(BASEVIDWIDTH/2, 182, V_SNAPTOBOTTOM|(ultimatemode ? V_REDMAP : V_YELLOWMAP), endingtext); } } @@ -1748,9 +1748,9 @@ static void F_CacheEnding(void) UINT8 skinnum = players[consoleplayer].skin; spritedef_t *sprdef; spriteframe_t *sprframe; - if (skins[skinnum].sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2)) + if (skins[skinnum]->sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2)) { - sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; // character head, skin specific sprframe = &sprdef->spriteframes[XTRA_ENDING]; endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY); @@ -2196,7 +2196,7 @@ void F_EndingDrawer(void) boolean donttouch = false; const char *str; if (goodending) - str = va("[S] %s: Engage.", skins[players[consoleplayer].skin].realname); + str = va("[S] %s: Engage.", skins[players[consoleplayer].skin]->realname); else str = "[S] Eggman: Abscond."; @@ -3576,7 +3576,7 @@ void F_StartContinue(void) S_ChangeMusicInternal("_conti", false); S_StopSounds(); - contskins[0] = &skins[players[consoleplayer].skin]; + contskins[0] = skins[players[consoleplayer].skin]; cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL); cont_spr2[0][2] = contskins[0]->contangle & 7; contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE); @@ -3592,7 +3592,7 @@ void F_StartContinue(void) else // HACK secondplaya = 1; - contskins[1] = &skins[players[secondplaya].skin]; + contskins[1] = skins[players[secondplaya].skin]; cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL); cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7; contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE); diff --git a/src/g_demo.c b/src/g_demo.c index 701f930e5..5187bf07e 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -488,7 +488,7 @@ void G_WriteGhostTic(mobj_t *ghost) if (ghost->player->followmobj->colorized) followtic |= FZT_COLORIZED; if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins)); + WRITEUINT8(demo_p,(UINT8)(((skin_t *)ghost->player->followmobj->skin)->skinnum)); oldghost.flags2 |= MF2_AMBUSH; } @@ -757,7 +757,7 @@ void G_GhostTicker(void) g->mo->color = SKINCOLOR_WHITE; break; case GHC_NIGHTSSKIN: // not actually a colour - g->mo->skin = &skins[DEFAULTNIGHTSSKIN]; + g->mo->skin = skins[DEFAULTNIGHTSSKIN]; break; } } @@ -900,7 +900,7 @@ void G_GhostTicker(void) follow->colorized = true; if (followtic & FZT_SKIN) - follow->skin = &skins[READUINT8(g->p)]; + follow->skin = skins[READUINT8(g->p)]; } if (follow) { @@ -1144,7 +1144,7 @@ void G_ReadMetalTic(mobj_t *metal) follow->colorized = true; if (followtic & FZT_SKIN) - follow->skin = &skins[READUINT8(metal_p)]; + follow->skin = skins[READUINT8(metal_p)]; } if (follow) { @@ -1329,7 +1329,7 @@ void G_WriteMetalTic(mobj_t *metal) if (metal->player->followmobj->colorized) followtic |= FZT_COLORIZED; if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins)); + WRITEUINT8(demo_p,(UINT8)(((skin_t *)metal->player->followmobj->skin)->skinnum)); oldmetal.flags2 |= MF2_AMBUSH; } @@ -1976,7 +1976,7 @@ void G_DoPlayDemo(char *defdemoname) G_InitNew(false, G_BuildMapName(gamemap), true, true, false); // Set color - players[0].skincolor = skins[players[0].skin].prefcolor; + players[0].skincolor = skins[players[0].skin]->prefcolor; for (i = 0; i < numskincolors; i++) if (!stricmp(skincolors[i].name,color)) { @@ -2221,11 +2221,11 @@ void G_AddGhost(char *defdemoname) gh->oldmo.z = gh->mo->z; // Set skin - gh->mo->skin = &skins[0]; + gh->mo->skin = skins[0]; for (i = 0; i < numskins; i++) - if (!stricmp(skins[i].name,skin)) + if (!stricmp(skins[i]->name,skin)) { - gh->mo->skin = &skins[i]; + gh->mo->skin = skins[i]; break; } gh->oldmo.skin = gh->mo->skin; diff --git a/src/g_game.c b/src/g_game.c index 13fdab877..6b3354de7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -582,14 +582,14 @@ static void G_UpdateRecordReplays(void) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (FIL_FileExists(lastdemo)) { UINT8 *buf; size_t len = FIL_ReadFile(lastdemo, &buf); - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) { // Better time, save this demo. if (FIL_FileExists(bestdemo)) @@ -598,7 +598,7 @@ static void G_UpdateRecordReplays(void) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) { // Better score, save this demo. if (FIL_FileExists(bestdemo)) @@ -607,7 +607,7 @@ static void G_UpdateRecordReplays(void) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2))) { // Better rings, save this demo. if (FIL_FileExists(bestdemo)) @@ -704,14 +704,14 @@ void G_SetNightsRecords(void) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (FIL_FileExists(lastdemo)) { UINT8 *buf; size_t len = FIL_ReadFile(lastdemo, &buf); - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);; + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1]->name);; if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) { // Better time, save this demo. if (FIL_FileExists(bestdemo)) @@ -720,7 +720,7 @@ void G_SetNightsRecords(void) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) { // Better score, save this demo. if (FIL_FileExists(bestdemo)) @@ -4733,7 +4733,7 @@ cleanup: // void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS) { - UINT16 color = skins[pickedchar].prefcolor; + UINT16 color = skins[pickedchar]->prefcolor; paused = false; if (demoplayback) @@ -4746,7 +4746,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b if (savedata.lives > 0) { if ((botingame = ((botskin = savedata.botskin) != 0))) - botcolor = skins[botskin-1].prefcolor; + botcolor = skins[botskin-1]->prefcolor; } else if (splitscreen != SSSG) { @@ -4754,9 +4754,9 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b SplitScreen_OnChange(); } - color = skins[pickedchar].prefcolor; + color = skins[pickedchar]->prefcolor; SetPlayerSkinByNum(consoleplayer, pickedchar); - CV_StealthSet(&cv_skin, skins[pickedchar].name); + CV_StealthSet(&cv_skin, skins[pickedchar]->name); CV_StealthSetValue(&cv_playercolor, color); if (mapname) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d413e3bbe..66df7d2cd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4870,7 +4870,7 @@ static void HWR_DrawSprites(void) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - if (!cv_glmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) + if (!cv_glmodels.value || !md2_playermodels[((skin_t*)spr->mobj->skin)->skinnum].found || md2_playermodels[((skin_t*)spr->mobj->skin)->skinnum].scale < 0.0f) HWR_DrawSprite(spr); else { @@ -4880,7 +4880,7 @@ static void HWR_DrawSprites(void) } else { - if (!cv_glmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + if (!cv_glmodels.value || !md2_models[spr->mobj->sprite].found || md2_models[spr->mobj->sprite].scale < 0.0f) HWR_DrawSprite(spr); else { @@ -5029,11 +5029,11 @@ static void HWR_ProjectSprite(mobj_t *thing) if (cv_glmodels.value) //Yellow: Only MD2's dont disappear { if (thing->skin && thing->sprite == SPR_PLAY) - md2 = &md2_playermodels[( (skin_t *)thing->skin - skins )]; + md2 = &md2_playermodels[((skin_t *)thing->skin)->skinnum]; else md2 = &md2_models[thing->sprite]; - if (md2->notfound || md2->scale < 0.0f) + if (!md2->found || md2->scale < 0.0f) return; } else @@ -5359,8 +5359,8 @@ static void HWR_ProjectSprite(mobj_t *thing) } else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { - size_t skinnum = (skin_t*)thing->skin-skins; - vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE); + INT32 skinnum = ((skin_t*)thing->skin)->skinnum; + vis->colormap = R_GetTranslationColormap(skinnum, thing->color, GTC_CACHE); } else vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 81e20f069..b54e14089 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -34,6 +34,7 @@ #include "../m_misc.h" #include "../w_wad.h" #include "../z_zone.h" +#include "../r_state.h" #include "../r_things.h" #include "../r_draw.h" #include "../p_tick.h" @@ -72,6 +73,7 @@ md2_t md2_models[NUMSPRITES]; md2_t *md2_playermodels = NULL; +size_t md2_numplayermodels = 0; /* @@ -483,28 +485,6 @@ static boolean nomd2s = false; void HWR_InitModels(void) { size_t i; - INT32 s; - FILE *f; - char name[24], filename[32]; - float scale, offset; - size_t prefixlen; - - CONS_Printf("HWR_InitModels()...\n"); - - if (numskins && md2_playermodels == NULL) - md2_playermodels = Z_Malloc(sizeof(md2_t) * numskins, PU_STATIC, NULL); - - for (s = 0; s < numskins; s++) - { - md2_playermodels[s].scale = -1.0f; - md2_playermodels[s].model = NULL; - md2_playermodels[s].grpatch = NULL; - md2_playermodels[s].notexturefile = false; - md2_playermodels[s].noblendfile = false; - md2_playermodels[s].skin = -1; - md2_playermodels[s].notfound = true; - md2_playermodels[s].error = false; - } for (i = 0; i < NUMSPRITES; i++) { @@ -513,82 +493,23 @@ void HWR_InitModels(void) md2_models[i].grpatch = NULL; md2_models[i].notexturefile = false; md2_models[i].noblendfile = false; - md2_models[i].skin = -1; - md2_models[i].notfound = true; + md2_models[i].found = false; md2_models[i].error = false; } - // read the models.dat file - //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); - - if (!f) - { - f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); - if (!f) - { - CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); - nomd2s = true; - return; - } - } - - // length of the player model prefix - prefixlen = strlen(PLAYERMODELPREFIX); - - while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) - { - char *skinname = name; - size_t len = strlen(name); - - // check for the player model prefix. - if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen)) - { - skinname += prefixlen; - goto addskinmodel; - } - - // add sprite model - if (len == 4) // must be 4 characters long exactly. otherwise it's not a sprite name. - { - for (i = 0; i < NUMSPRITES; i++) - { - if (stricmp(name, sprnames[i]) == 0) - { - md2_models[i].scale = scale; - md2_models[i].offset = offset; - md2_models[i].notfound = false; - strcpy(md2_models[i].filename, filename); - goto modelfound; - } - } - } - -addskinmodel: - // add player model - for (s = 0; s < numskins; s++) - { - if (stricmp(skinname, skins[s].name) == 0) - { - md2_playermodels[s].skin = s; - md2_playermodels[s].scale = scale; - md2_playermodels[s].offset = offset; - md2_playermodels[s].notfound = false; - strcpy(md2_playermodels[s].filename, filename); - goto modelfound; - } - } - -modelfound: - // move on to next line... - continue; - } - fclose(f); + if (numsprites && numskins) + HWR_LoadModels(); } -void HWR_AddPlayerModel(INT32 skin) // For skins that were added after startup +void HWR_LoadModels(void) { + size_t i; + INT32 s; FILE *f; + + // name[24] is used to check for names in the models.dat file that match with sprites or player skins + // sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long + // PLAYERMODELPREFIX is 6 characters long char name[24], filename[32]; float scale, offset; size_t prefixlen; @@ -596,7 +517,23 @@ void HWR_AddPlayerModel(INT32 skin) // For skins that were added after startup if (nomd2s) return; - //CONS_Printf("HWR_AddPlayerModel()...\n"); + // realloc player models table + if (numskins != (INT32)md2_numplayermodels) + { + md2_numplayermodels = (size_t)numskins; + md2_playermodels = Z_Realloc(md2_playermodels, sizeof(md2_t) * md2_numplayermodels, PU_STATIC, NULL); + + for (s = 0; s < numskins; s++) + { + md2_playermodels[s].scale = -1.0f; + md2_playermodels[s].model = NULL; + md2_playermodels[s].grpatch = NULL; + md2_playermodels[s].notexturefile = false; + md2_playermodels[s].noblendfile = false; + md2_playermodels[s].found = false; + md2_playermodels[s].error = false; + } + } // read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden @@ -613,92 +550,57 @@ void HWR_AddPlayerModel(INT32 skin) // For skins that were added after startup } } - // realloc player models table - md2_playermodels = Z_Realloc(md2_playermodels, sizeof(md2_t) * numskins, PU_STATIC, NULL); - // length of the player model prefix prefixlen = strlen(PLAYERMODELPREFIX); - // Check for any models that match the names of player skins! while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) { char *skinname = name; size_t len = strlen(name); - // ignore the player model prefix. + // Check for the player model prefix. if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen)) + { skinname += prefixlen; - - if (stricmp(skinname, skins[skin].name) == 0) - { - md2_playermodels[skin].skin = skin; - md2_playermodels[skin].scale = scale; - md2_playermodels[skin].offset = offset; - md2_playermodels[skin].notfound = false; - strcpy(md2_playermodels[skin].filename, filename); - goto playermodelfound; + goto addskinmodel; } + + // Add sprite models. + // Must be 4 characters long exactly. Otherwise, it's not a sprite name. + if (len == 4) + { + for (i = 0; i < numsprites; i++) + { + if (stricmp(name, sprnames[i]) == 0) + { + md2_models[i].scale = scale; + md2_models[i].offset = offset; + md2_models[i].found = true; + strcpy(md2_models[i].filename, filename); + goto modelfound; + } + } + } + +addskinmodel: + // Add player models. + for (s = 0; s < numskins; s++) + { + if (stricmp(skinname, skins[s]->name) == 0) + { + md2_playermodels[s].scale = scale; + md2_playermodels[s].offset = offset; + md2_playermodels[s].found = true; + strcpy(md2_playermodels[s].filename, filename); + goto modelfound; + } + } + +modelfound: + // Move on to the next line... + continue; } - md2_playermodels[skin].notfound = true; -playermodelfound: - fclose(f); -} - -void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after startup -{ - FILE *f; - // name[24] is used to check for names in the models.dat file that match with sprites or player skins - // sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long - // PLAYERMODELPREFIX is 6 characters long - char name[24], filename[32]; - float scale, offset; - - if (nomd2s) - return; - - if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check - return; - - // Read the models.dat file - //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); - - if (!f) - { - f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); - if (!f) - { - CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); - nomd2s = true; - return; - } - } - - // Check for any models that match the names of sprite names! - while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) - { - // length of the sprite name - size_t len = strlen(name); - if (len != 4) // must be 4 characters long exactly. otherwise it's not a sprite name. - continue; - - // check for the player model prefix. - if (!strnicmp(name, PLAYERMODELPREFIX, strlen(PLAYERMODELPREFIX))) - continue; // that's not a sprite... - - if (stricmp(name, sprnames[spritenum]) == 0) - { - md2_models[spritenum].scale = scale; - md2_models[spritenum].offset = offset; - md2_models[spritenum].notfound = false; - strcpy(md2_models[spritenum].filename, filename); - goto spritemodelfound; - } - } - - md2_models[spritenum].notfound = true; -spritemodelfound: fclose(f); } @@ -1369,8 +1271,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // 2. draw model with correct position, rotation,... if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) // Use the player MD2 list if the mobj has a skin and is using the player sprites { - md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; - md2->skin = (skin_t*)spr->mobj->skin-skins; + INT32 skinnum = ((skin_t*)spr->mobj->skin)->skinnum; + md2 = &md2_playermodels[skinnum]; sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; } else @@ -1468,7 +1370,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) skinnum = TC_RAINBOW; } else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); + skinnum = ((skin_t*)spr->mobj->skin)->skinnum; else skinnum = TC_DEFAULT; } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 4b36df7f8..ff14f6274 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -31,17 +31,17 @@ typedef struct boolean notexturefile; // true if texture file was not found void *blendgrpatch; boolean noblendfile; // true if blend texture file was not found - boolean notfound; - INT32 skin; + boolean found; boolean error; } md2_t; extern md2_t md2_models[NUMSPRITES]; extern md2_t *md2_playermodels; +extern size_t md2_numplayermodels; void HWR_InitModels(void); -void HWR_AddPlayerModel(INT32 skin); -void HWR_AddSpriteModel(size_t spritenum); +void HWR_LoadModels(void); + boolean HWR_DrawModel(gl_vissprite_t *spr); #define PLAYERMODELPREFIX "PLAYER" diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index fed81e411..ce8eb35f3 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -328,8 +328,8 @@ 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; + retModel->frameNames = (char*)Z_Calloc(header->numFrames*16, ztag, 0); + fname = retModel->frameNames; for (i = 0; i < header->numFrames; i++) { md2frame_t *fr = (md2frame_t*)&buffer[header->offsetFrames + foffset]; diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index 87931d27b..eccc48424 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -230,8 +230,8 @@ 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; + 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); diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 52f9ce6ea..8aaf0ba08 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -11,6 +11,7 @@ #include "../doomtype.h" #include "../info.h" #include "../r_skins.h" +#include "../r_state.h" #include "../z_zone.h" #include "hw_model.h" #include "hw_md2load.h" @@ -142,9 +143,7 @@ tag_t *GetTagByName(model_t *model, char *name, int frame) // // LoadModel // -// Load a model and -// convert it to the -// internal format. +// Load a model and convert it to the internal format. // model_t *LoadModel(const char *filename, int ztag) { @@ -194,9 +193,6 @@ model_t *LoadModel(const char *filename, int ztag) return NULL; } - model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0); - strcpy(model->mdlFilename, filename); - Optimize(model); GeneratePolygonNormals(model, ztag); LoadModelSprite2(model); @@ -237,17 +233,16 @@ model_t *LoadModel(const char *filename, int ztag) void HWR_ReloadModels(void) { size_t i; - INT32 s; - if (md2_playermodels != NULL) - for (s = 0; s < numskins; s++) - { - CONS_Printf("%u\n", s); - if (md2_playermodels[s].model) - LoadModelSprite2(md2_playermodels[s].model); - } + HWR_LoadModels(); - for (i = 0; i < NUMSPRITES; i++) + for (i = 0; i < md2_numplayermodels; i++) + { + if (md2_playermodels[i].model) + LoadModelSprite2(md2_playermodels[i].model); + } + + for (i = 0; i < numsprites; i++) { if (md2_models[i].model) LoadModelInterpolationSettings(md2_models[i].model); @@ -258,7 +253,7 @@ void LoadModelInterpolationSettings(model_t *model) { INT32 i; INT32 numframes = model->meshes[0].numFrames; - char *framename = model->framenames; + char *framename = model->frameNames; if (!framename) return; @@ -298,7 +293,7 @@ void LoadModelSprite2(model_t *model) INT32 i; modelspr2frames_t *spr2frames = NULL; INT32 numframes = model->meshes[0].numFrames; - char *framename = model->framenames; + char *framename = model->frameNames; if (!framename) return; diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index 6b39eb24d..f057271df 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -91,17 +91,14 @@ typedef struct model_s { int maxNumFrames; - int numMaterials; - material_t *materials; int numMeshes; mesh_t *meshes; + int numMaterials; + material_t *materials; int numTags; tag_t *tags; - char *mdlFilename; - boolean unloaded; - - char *framenames; + char *frameNames; boolean interpolate[256]; modelspr2frames_t *spr2frames; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e0eaf8fb1..cca000c87 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2240,7 +2240,7 @@ void HU_Erase(void) // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== -#define supercheckdef (!(players[tab[i].num].charflags & SF_NOSUPERSPRITES) && ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER))) +#define supercheckdef (!(players[tab[i].num].charflags & SF_NOSUPERSPRITES) && ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin]->flags & SF_SUPER))) #define greycheckdef (players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD || (G_IsSpecialStage(gamemap) && players[tab[i].num].exiting)) // diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 9a3e676d5..20dbd7dce 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -501,7 +501,7 @@ static int libd_getSprite2Patch(lua_State *L) { const char *name = luaL_checkstring(L, 1); for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, name)) + if (fastcmp(skins[i]->name, name)) break; if (i >= numskins) return 0; @@ -543,9 +543,9 @@ static int libd_getSprite2Patch(lua_State *L) if (super) j |= FF_SPR2SUPER; - j = P_GetSkinSprite2(&skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary + j = P_GetSkinSprite2(skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary - sprdef = &skins[i].sprites[j]; + sprdef = &skins[i]->sprites[j]; // set frame number frame = luaL_optinteger(L, 2, 0); @@ -573,7 +573,7 @@ static int libd_getSprite2Patch(lua_State *L) INT32 rot = R_GetRollAngle(rollangle); if (rot) { - patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<flip & (1<sprinfo[j], rot); LUA_PushUserdata(L, rotsprite, META_PATCH); lua_pushboolean(L, false); lua_pushboolean(L, true); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index cf8ccab2c..d56f0d019 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -638,10 +638,10 @@ static int mobj_set(lua_State *L) strlcpy(skin, luaL_checkstring(L, 3), sizeof skin); strlwr(skin); // all skin names are lowercase for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, skin)) + if (fastcmp(skins[i]->name, skin)) { if (!mo->player || R_SkinUsable(mo->player-players, i)) - mo->skin = &skins[i]; + mo->skin = skins[i]; return 0; } return luaL_error(L, "mobj.skin '%s' not found!", skin); diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index e66a379e9..1a3b1d067 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -226,7 +226,7 @@ static int skin_num(lua_State *L) // skins are always valid, only added, never removed I_Assert(skin != NULL); - lua_pushinteger(L, skin-skins); + lua_pushinteger(L, skin->skinnum); return 1; } @@ -245,14 +245,14 @@ static int lib_iterateSkins(lua_State *L) lua_remove(L, 1); // state is unused. if (!lua_isnil(L, 1)) - i = (INT32)(*((skin_t **)luaL_checkudata(L, 1, META_SKIN)) - skins) + 1; + i = (INT32)((*((skin_t **)luaL_checkudata(L, 1, META_SKIN)))->skinnum) + 1; else i = 0; // skins are always valid, only added, never removed if (i < numskins) { - LUA_PushUserdata(L, &skins[i], META_SKIN); + LUA_PushUserdata(L, skins[i], META_SKIN); return 1; } @@ -272,7 +272,7 @@ static int lib_getSkin(lua_State *L) return luaL_error(L, "skins[] index %d out of range (0 - %d)", i, MAXSKINS-1); if (i >= numskins) return 0; - LUA_PushUserdata(L, &skins[i], META_SKIN); + LUA_PushUserdata(L, skins[i], META_SKIN); return 1; } @@ -287,9 +287,9 @@ static int lib_getSkin(lua_State *L) // find skin by name for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, field)) + if (fastcmp(skins[i]->name, field)) { - LUA_PushUserdata(L, &skins[i], META_SKIN); + LUA_PushUserdata(L, skins[i], META_SKIN); return 1; } diff --git a/src/m_menu.c b/src/m_menu.c index e83398ef1..ca4486bf6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2311,7 +2311,7 @@ void Nextmap_OnChange(void) SP_NightsAttackMenu[naghost].status = IT_DISABLED; // Check if file exists, if not, disable REPLAY option - sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name); + sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name); #ifdef OLDNREPLAYNAME sprintf(tabaseold,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); @@ -2382,7 +2382,7 @@ void Nextmap_OnChange(void) SP_TimeAttackMenu[taghost].status = IT_DISABLED; // Check if file exists, if not, disable REPLAY option - sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name); + sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name); for (i = 0; i < 5; i++) { SP_ReplayMenu[i].status = IT_DISABLED; SP_GuestReplayMenu[i].status = IT_DISABLED; @@ -3080,7 +3080,7 @@ static void M_ChangeCvar(INT32 choice) { SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); if (skinno != -1) - CV_SetValue(cv,skins[skinno].prefcolor); + CV_SetValue(cv,skins[skinno]->prefcolor); return; } CV_Set(cv,cv->defaultvalue); @@ -4993,9 +4993,9 @@ static void M_PatchSkinNameTable(void) for (j = 0; j < MAXSKINS; j++) { - if (j < numskins && skins[j].name[0] != '\0' && R_SkinUsable(-1, j)) + if (j < numskins && skins[j]->name[0] != '\0' && R_SkinUsable(-1, j)) { - skins_cons_t[j].strvalue = skins[j].realname; + skins_cons_t[j].strvalue = skins[j]->realname; skins_cons_t[j].value = j+1; } else @@ -8397,7 +8397,7 @@ static void M_DrawLoadGameData(void) savetodraw--; if (savegameinfo[savetodraw].lives > 0) - charskin = &skins[savegameinfo[savetodraw].skinnum]; + charskin = skins[savegameinfo[savetodraw].skinnum]; // signpost background { @@ -8531,7 +8531,7 @@ static void M_DrawLoadGameData(void) // botskin first if (savegameinfo[savetodraw].botskin) { - skin_t *charbotskin = &skins[savegameinfo[savetodraw].botskin-1]; + skin_t *charbotskin = skins[savegameinfo[savetodraw].botskin-1]; sprdef = &charbotskin->sprites[SPR2_SIGN]; if (!sprdef->numframes) goto skipbot; @@ -9091,9 +9091,9 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) { if (!(description[i].picname[0])) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) + if (skins[skinnum]->sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); } @@ -9308,7 +9308,7 @@ static void M_DrawSetupChoosePlayerMenu(void) { const INT32 my = 16; - skin_t *charskin = &skins[0]; + skin_t *charskin = skins[0]; INT32 skinnum = 0; UINT16 col; UINT8 *colormap = NULL; @@ -9340,7 +9340,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Find skin number from description[] skinnum = description[char_on].skinnum[0]; - charskin = &skins[skinnum]; + charskin = skins[skinnum]; // Use the opposite of the character's skincolor col = description[char_on].oppositecolor; @@ -9443,7 +9443,7 @@ static void M_DrawSetupChoosePlayerMenu(void) prevoutlinecolor = description[prev].tagoutlinecolor; if (prevtext[0] == '\0') prevpatch = description[prev].namepic; - charskin = &skins[description[prev].skinnum[0]]; + charskin = skins[description[prev].skinnum[0]]; if (!prevtextcolor) prevtextcolor = charskin->prefcolor; if (!prevoutlinecolor) @@ -9473,7 +9473,7 @@ static void M_DrawSetupChoosePlayerMenu(void) nextoutlinecolor = description[next].tagoutlinecolor; if (nexttext[0] == '\0') nextpatch = description[next].namepic; - charskin = &skins[description[next].skinnum[0]]; + charskin = skins[description[next].skinnum[0]]; if (!nexttextcolor) nexttextcolor = charskin->prefcolor; if (!nextoutlinecolor) @@ -9531,7 +9531,7 @@ static void M_ChoosePlayer(INT32 choice) if ((botingame = (description[choice].skinnum[1] != -1))) { // this character has a second skin botskin = (UINT8)(description[choice].skinnum[1]+1); - botcolor = skins[description[choice].skinnum[1]].prefcolor; + botcolor = skins[description[choice].skinnum[1]]->prefcolor; } else botskin = botcolor = 0; @@ -9816,7 +9816,7 @@ void M_DrawTimeAttackMenu(void) { INT32 i, x, y, empatx, empaty, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfUrFace; // my WHAT + patch_t *PictureOfUrFace; patch_t *empatch; M_SetMenuCurBackground("RECATKBG"); @@ -9885,9 +9885,9 @@ void M_DrawTimeAttackMenu(void) // Character face! { - if (skins[cv_chooseskin.value-1].sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) + if (skins[cv_chooseskin.value-1]->sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) { - spritedef_t *sprdef = &skins[cv_chooseskin.value-1].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[cv_chooseskin.value-1]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); } @@ -10326,7 +10326,7 @@ static void M_ChooseNightsAttack(INT32 choice) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value)); - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1].name); + snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1]->name); if (!cv_autorecord.value) remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); @@ -10355,7 +10355,7 @@ static void M_ChooseTimeAttack(INT32 choice) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value)); - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1].name); + snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1]->name); if (!cv_autorecord.value) remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); @@ -10395,7 +10395,7 @@ static void M_ReplayTimeAttack(INT32 choice) return; } // srb2/replay/main/map01-sonic-time-best.lmp - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which)); + G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name, which)); } else if (currentMenu == &SP_NightsReplayDef) { @@ -10415,7 +10415,7 @@ static void M_ReplayTimeAttack(INT32 choice) return; } - demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which); + demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name, which); #ifdef OLDNREPLAYNAME // Check for old style named NiGHTS replay if a new style replay doesn't exist. if (!FIL_FileExists(demoname)) @@ -10445,7 +10445,7 @@ static void M_OverwriteGuest(const char *which) char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); UINT8 *buf; size_t len; - len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which), &buf); + len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name, which), &buf); if (!len) { return; @@ -11875,11 +11875,11 @@ static void M_DrawSetupMultiPlayerMenu(void) // draw skin string V_DrawRightAlignedString(BASEVIDWIDTH - x, y, ((MP_PlayerSetupMenu[1].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 1 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, - skins[setupm_fakeskin].realname); + skins[setupm_fakeskin]->realname); if (itemOn == 1 && (MP_PlayerSetupMenu[1].status & IT_TYPE) != IT_SPACE) { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skins[setupm_fakeskin].realname, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skins[setupm_fakeskin]->realname, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, '\x1C' | V_YELLOWMAP, false); V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, '\x1D' | V_YELLOWMAP, false); @@ -11900,7 +11900,7 @@ static void M_DrawSetupMultiPlayerMenu(void) // draw box around character V_DrawFill(x-(charw/2), y, charw, 84, 159); - sprdef = &skins[setupm_fakeskin].sprites[multi_spr2]; + sprdef = &skins[setupm_fakeskin]->sprites[multi_spr2]; if (!setupm_fakecolor->color || !sprdef->numframes) // should never happen but hey, who knows goto faildraw; @@ -11921,7 +11921,7 @@ static void M_DrawSetupMultiPlayerMenu(void) V_DrawFixedPatch( x<highresscale, skins[setupm_fakeskin]->shieldscale), flags, patch, colormap); goto colordraw; @@ -12051,7 +12051,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) setupm_fakeskin = numskins-1; } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); } else if (itemOn == 2) // player color { @@ -12067,7 +12067,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) { S_StartSound(NULL,sfx_strpst); // you know what? always putting these in the buffer won't hurt anything. - COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name)); + COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin]->name)); COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor->color)); break; } @@ -12084,7 +12084,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) setupm_fakeskin = 0; } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); } else if (itemOn == 2) // player color { @@ -12105,7 +12105,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } else if (itemOn == 2) { - UINT16 col = skins[setupm_fakeskin].prefcolor; + UINT16 col = skins[setupm_fakeskin]->prefcolor; if ((setupm_fakecolor->color != col) && skincolors[col].accessible) { S_StartSound(NULL,sfx_menu1); // Tails @@ -12195,7 +12195,7 @@ static void M_SetupMultiPlayer(INT32 choice) else MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -12239,7 +12239,7 @@ static void M_SetupMultiPlayer2(INT32 choice) else MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -12257,7 +12257,7 @@ static boolean M_QuitMultiPlayerMenu(void) setupm_name[l] =0; COM_BufAddText (va("%s \"%s\"\n",setupm_cvname->name,setupm_name)); } - COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name)); + COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin]->name)); // send color if changed if (setupm_fakecolor->color != setupm_cvcolor->value) COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor->color)); diff --git a/src/p_enemy.c b/src/p_enemy.c index 6a92c5d33..5504b0d1c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3609,7 +3609,7 @@ void A_1upThinker(mobj_t *actor) } } - if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) + if (closestplayer == -1 || skins[players[closestplayer].skin]->sprites[SPR2_LIFE].numframes == 0) { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. if (actor->tracer) { @@ -3627,7 +3627,7 @@ void A_1upThinker(mobj_t *actor) { P_SetTarget(&actor->tracer, P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY)); P_SetTarget(&actor->tracer->target, actor); - actor->tracer->skin = &skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame + actor->tracer->skin = skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame P_SetMobjState(actor->tracer, actor->info->seestate); // The overlay is going to be one tic early turning off and on @@ -3637,7 +3637,7 @@ void A_1upThinker(mobj_t *actor) } actor->tracer->color = players[closestplayer].mo->color; - actor->tracer->skin = &skins[players[closestplayer].skin]; + actor->tracer->skin = skins[players[closestplayer].skin]; } // Function: A_MonitorPop @@ -3707,7 +3707,7 @@ void A_MonitorPop(mobj_t *actor) P_SetTarget(&newmobj->tracer, livesico); livesico->color = newmobj->target->player->mo->color; - livesico->skin = &skins[newmobj->target->player->skin]; + livesico->skin = skins[newmobj->target->player->skin]; P_SetMobjState(livesico, newmobj->info->seestate); // We're using the overlay, so use the overlay 1up sprite (no text) @@ -3793,7 +3793,7 @@ void A_GoldMonitorPop(mobj_t *actor) P_SetTarget(&newmobj->tracer, livesico); livesico->color = newmobj->target->player->mo->color; - livesico->skin = &skins[newmobj->target->player->skin]; + livesico->skin = skins[newmobj->target->player->skin]; P_SetMobjState(livesico, newmobj->info->seestate); // We're using the overlay, so use the overlay 1up sprite (no text) @@ -5172,7 +5172,7 @@ void A_SignPlayer(mobj_t *actor) if (!actor->target->player) return; - skin = &skins[actor->target->player->skin]; + skin = skins[actor->target->player->skin]; facecolor = actor->target->player->skincolor; if (signcolor) @@ -5203,10 +5203,10 @@ void A_SignPlayer(mobj_t *actor) if (!SignSkinCheck(player, skincount)) skinnum++; } - skin = &skins[skinnum]; + skin = skins[skinnum]; } else // specific skin - skin = &skins[locvar1]; + skin = skins[locvar1]; facecolor = skin->prefcolor; if (signcolor) diff --git a/src/p_mobj.c b/src/p_mobj.c index da7385be5..4fd4e94d8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -207,7 +207,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) return P_SetPlayerMobjState(mobj, S_PLAY_FALL); // Catch swimming versus flying - if ((state == S_PLAY_FLY || (state == S_PLAY_GLIDE && skins[player->skin].sprites[SPR2_SWIM].numframes)) + if ((state == S_PLAY_FLY || (state == S_PLAY_GLIDE && skins[player->skin]->sprites[SPR2_SWIM].numframes)) && player->mo->eflags & MFE_UNDERWATER && !player->skidtime) return P_SetPlayerMobjState(player->mo, S_PLAY_SWIM); else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) @@ -325,7 +325,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) mobj->tics = st->tics; // Adjust the player's animation speed to match their velocity. - if (state == S_PLAY_STND && player->powers[pw_super] && skins[player->skin].sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) // if no super wait, don't wait at all + if (state == S_PLAY_STND && player->powers[pw_super] && skins[player->skin]->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) // if no super wait, don't wait at all mobj->tics = -1; else if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) mobj->tics = 2; @@ -3292,7 +3292,7 @@ void P_MobjCheckWater(mobj_t *mobj) { // Water removes electric and non-water fire shields... if (electric) P_FlashPal(p, PAL_WHITE, 1); - + p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; } } @@ -10707,10 +10707,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) nummaprings++; break; case MT_METALSONIC_RACE: - mobj->skin = &skins[5]; + mobj->skin = skins[5]; /* FALLTHRU */ case MT_METALSONIC_BATTLE: - mobj->color = skins[5].prefcolor; + mobj->color = skins[5]->prefcolor; sc = 5; break; case MT_FANG: @@ -11381,7 +11381,7 @@ void P_SpawnPlayer(INT32 playernum) // set 'spritedef' override in mobj for player skins.. (see ProjectSprite) // (usefulness: when body mobj is detached from player (who respawns), // the dead body mobj retains the skin through the 'spritedef' override). - mobj->skin = &skins[p->skin]; + mobj->skin = skins[p->skin]; P_SetupStateAnimation(mobj, mobj->state); mobj->health = 1; @@ -11389,14 +11389,14 @@ void P_SpawnPlayer(INT32 playernum) p->bonustime = false; p->realtime = leveltime; - p->followitem = skins[p->skin].followitem; + p->followitem = skins[p->skin]->followitem; // Make sure player's stats are reset if they were in dashmode! if (p->dashmode) { p->dashmode = 0; - p->normalspeed = skins[p->skin].normalspeed; - p->jumpfactor = skins[p->skin].jumpfactor; + p->normalspeed = skins[p->skin]->normalspeed; + p->jumpfactor = skins[p->skin]->jumpfactor; } // Clear lastlinehit and lastsidehit @@ -11412,7 +11412,7 @@ void P_SpawnPlayer(INT32 playernum) P_FlashPal(p, 0, 0); // Resets // Set bounds accurately. - mobj->radius = FixedMul(skins[p->skin].radius, mobj->scale); + mobj->radius = FixedMul(skins[p->skin]->radius, mobj->scale); mobj->height = P_GetPlayerHeight(p); if (!leveltime && !p->spectator && ((maptol & TOL_NIGHTS) == TOL_NIGHTS) != (G_IsSpecialStage(gamemap))) // non-special NiGHTS stage or special non-NiGHTS stage diff --git a/src/p_saveg.c b/src/p_saveg.c index 770c641b9..24ee14583 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -76,11 +76,11 @@ static inline void P_ArchivePlayer(void) // Write skin names, so that loading skins in different orders // doesn't change who the save file is for! - WRITESTRINGN(save_p, skins[player->skin].name, SKINNAMESIZE); + WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE); if (botskin != 0) { - WRITESTRINGN(save_p, skins[botskin-1].name, SKINNAMESIZE); + WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE); } else { @@ -1815,7 +1815,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (diff2 & MD2_CVMEM) WRITEINT32(save_p, mobj->cvmem); if (diff2 & MD2_SKIN) - WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins)); + WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); if (diff2 & MD2_COLOR) WRITEUINT16(save_p, mobj->color); if (diff2 & MD2_EXTVAL1) @@ -2855,7 +2855,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_CVMEM) mobj->cvmem = READINT32(save_p); if (diff2 & MD2_SKIN) - mobj->skin = &skins[READUINT8(save_p)]; + mobj->skin = skins[READUINT8(save_p)]; if (diff2 & MD2_COLOR) mobj->color = READUINT16(save_p); if (diff2 & MD2_EXTVAL1) diff --git a/src/p_setup.c b/src/p_setup.c index 498759b73..2546dcb98 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3235,7 +3235,7 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] |= TMSC_BACKTOFRONTCEILING; lines[i].special = 720; break; - + case 900: //Translucent wall (10%) case 901: //Translucent wall (20%) case 902: //Translucent wall (30%) @@ -3622,19 +3622,19 @@ static void P_ForceCharacter(const char *forcecharskin) if (splitscreen) { SetPlayerSkin(secondarydisplayplayer, forcecharskin); - if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin].prefcolor) + if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin]->prefcolor) { - CV_StealthSetValue(&cv_playercolor2, skins[players[secondarydisplayplayer].skin].prefcolor); - players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin].prefcolor; + CV_StealthSetValue(&cv_playercolor2, skins[players[secondarydisplayplayer].skin]->prefcolor); + players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin]->prefcolor; } } SetPlayerSkin(consoleplayer, forcecharskin); // normal player colors in single player - if ((unsigned)cv_playercolor.value != skins[players[consoleplayer].skin].prefcolor) + if ((unsigned)cv_playercolor.value != skins[players[consoleplayer].skin]->prefcolor) { - CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor); - players[consoleplayer].skincolor = skins[players[consoleplayer].skin].prefcolor; + CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin]->prefcolor); + players[consoleplayer].skincolor = skins[players[consoleplayer].skin]->prefcolor; } } } @@ -3678,8 +3678,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_bestscore.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i]->name)); } } @@ -3691,8 +3691,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i]->name)); } } @@ -3704,8 +3704,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_bestrings.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-rings-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-rings-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-rings-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-rings-best.lmp", gpath, skins[i]->name)); } } @@ -3717,8 +3717,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i]->name)); } } @@ -3748,8 +3748,8 @@ static void P_LoadNightsGhosts(void) if (cv_ghost_bestscore.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i]->name)); } } @@ -3761,8 +3761,8 @@ static void P_LoadNightsGhosts(void) if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i]->name)); } } @@ -3774,8 +3774,8 @@ static void P_LoadNightsGhosts(void) if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i]->name)); } } @@ -4251,7 +4251,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) players[consoleplayer].lives = savedata.lives; players[consoleplayer].score = savedata.score; if ((botingame = ((botskin = savedata.botskin) != 0))) - botcolor = skins[botskin-1].prefcolor; + botcolor = skins[botskin-1]->prefcolor; emeralds = savedata.emeralds; savedata.lives = 0; } diff --git a/src/p_spec.c b/src/p_spec.c index 4b566acfb..34ef688c8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1779,7 +1779,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller case 331: // continuous case 332: // each time case 333: // once - if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) + if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin]->name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) return false; break; case 334: // object dye - continuous diff --git a/src/p_user.c b/src/p_user.c index c3184b52f..d3fe4c454 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -682,8 +682,8 @@ static void P_DeNightserizePlayer(player_t *player) player->mo->flags &= ~MF_NOGRAVITY; - player->mo->skin = &skins[player->skin]; - player->followitem = skins[player->skin].followitem; + player->mo->skin = skins[player->skin]; + player->followitem = skins[player->skin]->followitem; player->mo->color = player->skincolor; G_GhostAddColor(GHC_RETURNSKIN); @@ -785,12 +785,12 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->mo->height = P_GetPlayerHeight(player); // Just to make sure jumping into the drone doesn't result in a squashed hitbox. player->oldscale = player->mo->scale; - if (skins[player->skin].sprites[SPR2_NFLY].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. + if (skins[player->skin]->sprites[SPR2_NFLY].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { - player->mo->skin = &skins[DEFAULTNIGHTSSKIN]; + player->mo->skin = skins[DEFAULTNIGHTSSKIN]; if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) - player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; - player->followitem = skins[DEFAULTNIGHTSSKIN].followitem; + player->mo->color = skins[DEFAULTNIGHTSSKIN]->prefcolor; + player->followitem = skins[DEFAULTNIGHTSSKIN]->followitem; G_GhostAddColor(GHC_NIGHTSSKIN); } } @@ -4264,7 +4264,7 @@ static void P_DoSuperStuff(player_t *player) player->mo->color = (player->pflags & PF_GODMODE && cv_debug == 0) ? (SKINCOLOR_SUPERSILVER1 + 5*(((signed)leveltime >> 1) % 7)) // A wholesome easter egg. - : skins[player->skin].supercolor + abs( ( (player->powers[pw_super] >> 1) % 9) - 4); // This is where super flashing is handled. + : skins[player->skin]->supercolor + abs( ( (player->powers[pw_super] >> 1) % 9) - 4); // This is where super flashing is handled. G_GhostAddColor(GHC_SUPER); @@ -11469,7 +11469,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) P_SetThingPosition(fume); // If dashmode is high enough, spawn a trail - if (player->normalspeed >= skins[player->skin].normalspeed*2) + if (player->normalspeed >= skins[player->skin]->normalspeed*2) P_SpawnGhostMobj(fume); } @@ -12294,20 +12294,20 @@ void P_PlayerThink(player_t *player) { if (prevdashmode >= DASHMODE_THRESHOLD) { - player->normalspeed = skins[player->skin].normalspeed; // Reset to default if not capable of entering dash mode. - player->jumpfactor = skins[player->skin].jumpfactor; + player->normalspeed = skins[player->skin]->normalspeed; // Reset to default if not capable of entering dash mode. + player->jumpfactor = skins[player->skin]->jumpfactor; } } else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground. { - if (player->normalspeed < skins[player->skin].normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic + if (player->normalspeed < skins[player->skin]->normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic player->normalspeed += FRACUNIT/5; // Enter Dash Mode smoothly. - if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. + if (player->jumpfactor < FixedMul(skins[player->skin]->jumpfactor, 5*FRACUNIT/4)) // Boost jump height. player->jumpfactor += FRACUNIT/300; } - if (player->normalspeed >= skins[player->skin].normalspeed*2) + if (player->normalspeed >= skins[player->skin]->normalspeed*2) { mobj_t *ghost = P_SpawnGhostMobj(player->mo); // Spawns afterimages ghost->fuse = 2; // Makes the images fade quickly @@ -12319,8 +12319,8 @@ void P_PlayerThink(player_t *player) { if (dashmode >= DASHMODE_THRESHOLD) // catch getting the flag! { - player->normalspeed = skins[player->skin].normalspeed; - player->jumpfactor = skins[player->skin].jumpfactor; + player->normalspeed = skins[player->skin]->normalspeed; + player->jumpfactor = skins[player->skin]->jumpfactor; S_StartSound(player->mo, sfx_kc65); } dashmode = 0; diff --git a/src/r_draw.c b/src/r_draw.c index f0a19a462..7b0d88e7d 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -548,7 +548,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U if (skinnum < 0 && skinnum > TC_DEFAULT) I_Error("Invalid translation colormap index %d.", skinnum); - starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR; + starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum]->starttranscolor : DEFAULT_STARTTRANSCOLOR; if (starttranscolor >= NUM_PALETTE_ENTRIES) I_Error("Invalid startcolor #%d.", starttranscolor); diff --git a/src/r_picformats.c b/src/r_picformats.c index bd457b62f..5c2544a7f 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1612,7 +1612,7 @@ static void R_ParseSpriteInfo(boolean spr2) for (i = 0; i < foundskins; i++) { size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; + skin_t *skin = skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); } diff --git a/src/r_skins.c b/src/r_skins.c index fd2f1b17b..b0dcda035 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -33,7 +33,7 @@ #endif INT32 numskins = 0; -skin_t *skins = NULL; +skin_t **skins = NULL; // // P_GetSkinSprite2 @@ -100,7 +100,7 @@ static void Sk_SetDefaultValue(skin_t *skin) // memset(skin, 0, sizeof (skin_t)); snprintf(skin->name, - sizeof skin->name, "skin %u", (UINT32)(skin-skins)); + sizeof skin->name, "skin %u", (UINT32)(skin->skinnum)); skin->name[sizeof skin->name - 1] = '\0'; skin->wadnum = INT16_MAX; @@ -221,7 +221,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) // Force 2. return true; } - + if (metalrecording && skinnum == 5) { // Force 3. @@ -268,7 +268,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) } } -// returns true if the skin name is found (loaded from pwad) +// returns the skin number if the skin name is found (loaded from pwad) // warning return -1 if not found INT32 R_SkinAvailable(const char *name) { @@ -277,8 +277,8 @@ INT32 R_SkinAvailable(const char *name) for (i = 0; i < numskins; i++) { // search in the skin list - if (stricmp(skins[i].name,name)==0) - return i; + if (!stricmp(skins[i]->name,name)) + return skins[i]->skinnum; } return -1; } @@ -286,7 +286,7 @@ INT32 R_SkinAvailable(const char *name) // Auxillary function that actually sets the skin static void SetSkin(player_t *player, INT32 skinnum) { - skin_t *skin = &skins[skinnum]; + skin_t *skin = skins[skinnum]; UINT16 newcolor = 0; player->skin = skinnum; @@ -347,7 +347,7 @@ static void SetSkin(player_t *player, INT32 skinnum) fixed_t radius = FixedMul(skin->radius, player->mo->scale); if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { - skin = &skins[DEFAULTNIGHTSSKIN]; + skin = skins[DEFAULTNIGHTSSKIN]; player->followitem = skin->followitem; if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) newcolor = skin->prefcolor; // will be updated in thinker to flashing @@ -687,9 +687,10 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) buf2[size] = '\0'; // set defaults - skins = Z_Realloc(skins, sizeof(skin_t) * (numskins + 1), PU_STATIC, NULL); - skin = &skins[numskins]; + skins = Z_Realloc(skins, sizeof(skin_t*) * (numskins + 1), PU_STATIC, NULL); + skin = skins[numskins] = Z_Calloc(sizeof(skin_t), PU_STATIC, NULL); Sk_SetDefaultValue(skin); + skin->skinnum = numskins; skin->wadnum = wadnum; hudname = realname = false; // parse @@ -785,11 +786,6 @@ next_token: CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); numskins++; - -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerModel(numskins-1); -#endif } return; } @@ -858,7 +854,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile) strlwr(value); skinnum = R_SkinAvailable(value); if (skinnum != -1) - skin = &skins[skinnum]; + skin = skins[skinnum]; else { CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); diff --git a/src/r_skins.h b/src/r_skins.h index c95060fa7..67f34aa66 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -32,6 +32,7 @@ typedef struct { char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin + UINT32 skinnum; UINT16 wadnum; skinflags_t flags; @@ -84,7 +85,7 @@ typedef struct /// Externs extern INT32 numskins; -extern skin_t *skins; +extern skin_t **skins; /// Function prototypes void R_InitSkins(void); diff --git a/src/r_things.c b/src/r_things.c index 0283712b8..69a9eb5e9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -476,10 +476,6 @@ void R_AddSpriteDefs(UINT16 wadnum) if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) { -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddSpriteModel(i); -#endif // if a new sprite was added (not just replaced) addsprites++; #ifndef ZDEBUG @@ -553,14 +549,10 @@ void R_InitSprites(void) } ST_ReloadSkinFaceGraphics(); - // - // check if all sprites have frames - // - /* - for (i = 0; i < numsprites; i++) - if (sprites[i].numframes < 1) - CONS_Debug(DBG_SETUP, "R_InitSprites: sprite %s has no frames at all\n", sprnames[i]); - */ +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_LoadModels(); +#endif } // @@ -772,8 +764,8 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) } else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - return R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); + INT32 skinnum = ((skin_t*)vis->mobj->skin)->skinnum; + return R_GetTranslationColormap(skinnum, vis->mobj->color, GTC_CACHE); } else // Use the defaults return R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); diff --git a/src/st_stuff.c b/src/st_stuff.c index 130460f49..88affcf0a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -345,14 +345,14 @@ void ST_LoadGraphics(void) // made separate so that skins code can reload custom face graphics void ST_LoadFaceGraphics(INT32 skinnum) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_LIFEPIC) + if (skins[skinnum]->sprites[SPR2_XTRA].numframes > XTRA_LIFEPIC) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC]; faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); - if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC) + if (skins[skinnum]->sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC) { - sprdef = &skins[skinnum].sprites[SPR2_XTRA|FF_SPR2SUPER]; + sprdef = &skins[skinnum]->sprites[SPR2_XTRA|FF_SPR2SUPER]; sprframe = &sprdef->spriteframes[0]; superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); } @@ -960,14 +960,14 @@ static void ST_drawLivesArea(void) // name v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER); - if (strlen(skins[stplyr->skin].hudname) <= 5) - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); - else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48) - V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); - else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40) - V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); + if (strlen(skins[stplyr->skin]->hudname) <= 5) + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); + else if (V_StringWidth(skins[stplyr->skin]->hudname, v_colmap) <= 48) + V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); + else if (V_ThinStringWidth(skins[stplyr->skin]->hudname, v_colmap) <= 40) + V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); else - V_DrawThinString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); + V_DrawThinString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); // Power Stones collected if (G_RingSlingerGametype() && LUA_HudEnabled(hud_powerstones)) diff --git a/src/v_video.c b/src/v_video.c index de05df2d5..661938287 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1041,9 +1041,9 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ // void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor) { - if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CONTINUE) + if (skinnum >= 0 && skinnum < numskins && skins[skinnum]->sprites[SPR2_XTRA].numframes > XTRA_CONTINUE) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE]; patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); diff --git a/src/y_inter.c b/src/y_inter.c index 6d876d7bd..8897d2b99 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1358,22 +1358,22 @@ void Y_StartIntermission(void) else { // too long so just show "YOU GOT THROUGH THE ACT" - if (strlen(skins[players[consoleplayer].skin].realname) > 13) + if (strlen(skins[players[consoleplayer].skin]->realname) > 13) { strcpy(data.coop.passed1, "you got"); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); } // long enough that "X GOT" won't fit so use "X PASSED THE ACT" - else if (strlen(skins[players[consoleplayer].skin].realname) > 8) + else if (strlen(skins[players[consoleplayer].skin]->realname) > 8) { - strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); + strcpy(data.coop.passed1, skins[players[consoleplayer].skin]->realname); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); } // length is okay for normal use else { snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); } } @@ -1445,7 +1445,7 @@ void Y_StartIntermission(void) { snprintf(data.spec.passed1, sizeof data.spec.passed1, "%s", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; strcpy(data.spec.passed2, "got them all!"); @@ -1454,17 +1454,17 @@ void Y_StartIntermission(void) strcpy(data.spec.passed3, "can now become"); snprintf(data.spec.passed4, sizeof data.spec.passed4, "Super %s", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); data.spec.passed4[sizeof data.spec.passed4 - 1] = '\0'; } } else { - if (strlen(skins[players[consoleplayer].skin].realname) <= SKINNAMESIZE-5) + if (strlen(skins[players[consoleplayer].skin]->realname) <= SKINNAMESIZE-5) { snprintf(data.spec.passed1, sizeof data.spec.passed1, "%s got", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; } else From 655b48b52e56f70449b88d66e05dda3927a17c02 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 10 Aug 2021 00:46:36 -0300 Subject: [PATCH 4/7] Refactor and optimize translation caching --- src/lua_infolib.c | 3 - src/m_menu.c | 6 +- src/r_draw.c | 157 +++++++++++++++++++++++++++------------------- src/r_draw.h | 2 +- src/st_stuff.c | 14 +---- 5 files changed, 97 insertions(+), 85 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index af2d99a0c..bec2e488a 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -30,9 +30,6 @@ #include "lua_hud.h" // hud_running errors #include "lua_hook.h" // hook_cmd_running errors -extern CV_PossibleValue_t Color_cons_t[]; -extern UINT8 skincolor_modified[]; - boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor); state_t *astate; diff --git a/src/m_menu.c b/src/m_menu.c index ca4486bf6..083de2de1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9111,7 +9111,7 @@ static UINT16 M_SetupChoosePlayerDirect(INT32 choice) { INT32 skinnum, botskinnum; UINT16 i; - UINT16 firstvalid = 65535, lastvalid = 65535; + INT32 firstvalid = INT32_MAX, lastvalid = INT32_MAX; boolean allowed = false; (void)choice; @@ -9155,7 +9155,7 @@ static UINT16 M_SetupChoosePlayerDirect(INT32 choice) } // Handling order. - if (firstvalid == 65535) + if (firstvalid == INT32_MAX) firstvalid = i; else { @@ -9518,7 +9518,7 @@ static void M_ChoosePlayer(INT32 choice) UINT8 skinnum; // skip this if forcecharacter or no characters available - if (choice == 65535) + if (choice == INT32_MAX) { skinnum = botskin = 0; botingame = false; diff --git a/src/r_draw.c b/src/r_draw.c index 7b0d88e7d..a9dbb9358 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -122,54 +122,56 @@ float focallengthf, zeroheight; UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; // ========================================================================= -// TRANSLATION COLORMAP CODE +// TRANSLATION COLORMAP CODE // ========================================================================= -#define DEFAULT_TT_CACHE_INDEX MAXSKINS -#define BOSS_TT_CACHE_INDEX (MAXSKINS + 1) -#define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2) -#define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3) -#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4) -#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5) -#define DASHMODE_TT_CACHE_INDEX (MAXSKINS + 6) -#define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 +#define DEFAULT_STARTTRANSCOLOR 96 -static UINT8 **translationtablecache[MAXSKINS + 7] = {NULL}; -UINT8 skincolor_modified[MAXSKINCOLORS]; - -static INT32 SkinToCacheIndex(INT32 skinnum) +enum { - switch (skinnum) + DEFAULT_TT_CACHE_INDEX, + BOSS_TT_CACHE_INDEX, + METALSONIC_TT_CACHE_INDEX, + ALLWHITE_TT_CACHE_INDEX, + RAINBOW_TT_CACHE_INDEX, + BLINK_TT_CACHE_INDEX, + DASHMODE_TT_CACHE_INDEX, + + TT_CACHE_SIZE +}; + +static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL}; +static UINT8 **skintranslationcache[NUM_PALETTE_ENTRIES] = {NULL}; + +boolean skincolor_modified[MAXSKINCOLORS]; + +static INT32 TranslationToCacheIndex(INT32 translation) +{ + switch (translation) { - case TC_DEFAULT: return DEFAULT_TT_CACHE_INDEX; case TC_BOSS: return BOSS_TT_CACHE_INDEX; case TC_METALSONIC: return METALSONIC_TT_CACHE_INDEX; case TC_ALLWHITE: return ALLWHITE_TT_CACHE_INDEX; case TC_RAINBOW: return RAINBOW_TT_CACHE_INDEX; case TC_BLINK: return BLINK_TT_CACHE_INDEX; case TC_DASHMODE: return DASHMODE_TT_CACHE_INDEX; - default: break; + default: return DEFAULT_TT_CACHE_INDEX; } - - return skinnum; } -static INT32 CacheIndexToSkin(INT32 ttc) +static INT32 CacheIndexToTranslation(INT32 index) { - switch (ttc) + switch (index) { - case DEFAULT_TT_CACHE_INDEX: return TC_DEFAULT; case BOSS_TT_CACHE_INDEX: return TC_BOSS; case METALSONIC_TT_CACHE_INDEX: return TC_METALSONIC; case ALLWHITE_TT_CACHE_INDEX: return TC_ALLWHITE; case RAINBOW_TT_CACHE_INDEX: return TC_RAINBOW; case BLINK_TT_CACHE_INDEX: return TC_BLINK; case DASHMODE_TT_CACHE_INDEX: return TC_DASHMODE; - default: break; + default: return TC_DEFAULT; } - - return ttc; } CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; @@ -398,18 +400,18 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) RGBA_t color; UINT8 brightness; INT32 j; - UINT8 colorbrightnesses[16]; + UINT8 colorbrightnesses[COLORRAMPSIZE]; UINT16 brightdif; INT32 temp; // first generate the brightness of all the colours of that skincolour - for (i = 0; i < 16; i++) + for (i = 0; i < COLORRAMPSIZE; i++) { color = V_GetColor(skincolors[skincolor].ramp[i]); SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue); } - // next, for every colour in the palette, choose the transcolor that has the closest brightness + // next, for every colour in the palette, choose the translated colour that has the closest brightness for (i = 0; i < NUM_PALETTE_ENTRIES; i++) { if (i == 0 || i == 31) // pure black and pure white don't change @@ -420,7 +422,7 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) color = V_GetColor(i); SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue); brightdif = 256; - for (j = 0; j < 16; j++) + for (j = 0; j < COLORRAMPSIZE; j++) { temp = abs((INT16)brightness - (INT16)colorbrightnesses[j]); if (temp < brightdif) @@ -436,28 +438,29 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) /** \brief Generates a translation colormap. - \param dest_colormap colormap to populate - \param skinnum skin number, or a translation mode - \param color translation color + \param dest_colormap colormap to populate + \param translation translation mode + \param color translation color + \param starttranscolor starting point of the translation \return void */ -static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color) +static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 translation, UINT16 color, INT32 starttranscolor) { - INT32 i, starttranscolor, skinramplength; + INT32 i, skinramplength; // Handle a couple of simple special cases - if (skinnum < TC_DEFAULT) + if (translation < TC_DEFAULT) { - switch (skinnum) + switch (translation) { case TC_ALLWHITE: memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8)); return; case TC_RAINBOW: if (color >= numskincolors) - I_Error("Invalid skin color #%hu.", (UINT16)color); - if (color != SKINCOLOR_NONE) + I_Error("Invalid skin color #%hu", (UINT16)color); + else if (color != SKINCOLOR_NONE) { R_RainbowColormap(dest_colormap, color); return; @@ -465,8 +468,8 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U break; case TC_BLINK: if (color >= numskincolors) - I_Error("Invalid skin color #%hu.", (UINT16)color); - if (color != SKINCOLOR_NONE) + I_Error("Invalid skin color #%hu", (UINT16)color); + else if (color != SKINCOLOR_NONE) { memset(dest_colormap, skincolors[color].ramp[3], NUM_PALETTE_ENTRIES * sizeof(UINT8)); return; @@ -480,26 +483,28 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U dest_colormap[i] = (UINT8)i; // White! - if (skinnum == TC_BOSS) + if (translation == TC_BOSS) { UINT8 *originalColormap = R_GetTranslationColormap(TC_DEFAULT, (skincolornum_t)color, GTC_CACHE); - for (i = 0; i < 16; i++) + if (starttranscolor >= NUM_PALETTE_ENTRIES) + I_Error("Invalid startcolor #%d", starttranscolor); + for (i = 0; i < COLORRAMPSIZE; i++) { - dest_colormap[DEFAULT_STARTTRANSCOLOR + i] = originalColormap[DEFAULT_STARTTRANSCOLOR + i]; + dest_colormap[starttranscolor + i] = originalColormap[starttranscolor + i]; dest_colormap[31-i] = i; } } - else if (skinnum == TC_METALSONIC) + else if (translation == TC_METALSONIC) { for (i = 0; i < 6; i++) { dest_colormap[skincolors[SKINCOLOR_BLUE].ramp[12-i]] = skincolors[SKINCOLOR_BLUE].ramp[i]; } dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0; - for (i = 0; i < 16; i++) + for (i = 0; i < COLORRAMPSIZE; i++) dest_colormap[96+i] = dest_colormap[skincolors[SKINCOLOR_COBALT].ramp[i]]; } - else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices + else if (translation == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices { // greens -> ketchups dest_colormap[96] = dest_colormap[97] = 48; @@ -543,26 +548,21 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U } if (color >= numskincolors) - I_Error("Invalid skin color #%hu.", (UINT16)color); - - if (skinnum < 0 && skinnum > TC_DEFAULT) - I_Error("Invalid translation colormap index %d.", skinnum); - - starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum]->starttranscolor : DEFAULT_STARTTRANSCOLOR; + I_Error("Invalid skin color #%hu", (UINT16)color); if (starttranscolor >= NUM_PALETTE_ENTRIES) - I_Error("Invalid startcolor #%d.", starttranscolor); + I_Error("Invalid startcolor #%d", starttranscolor); // Fill in the entries of the palette that are fixed for (i = 0; i < starttranscolor; i++) dest_colormap[i] = (UINT8)i; - i = starttranscolor + 16; + i = starttranscolor + COLORRAMPSIZE; if (i < NUM_PALETTE_ENTRIES) { for (i = (UINT8)i; i < NUM_PALETTE_ENTRIES; i++) dest_colormap[i] = (UINT8)i; - skinramplength = 16; + skinramplength = COLORRAMPSIZE; } else skinramplength = i - NUM_PALETTE_ENTRIES; // shouldn't this be NUM_PALETTE_ENTRIES - starttranscolor? @@ -575,7 +575,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U /** \brief Retrieves a translation colormap from the cache. - \param skinnum number of skin, TC_DEFAULT or TC_BOSS + \param skinnum number of skin, or translation modes \param color translation color \param flags set GTC_CACHE to use the cache @@ -583,25 +583,47 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U */ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags) { - UINT8* ret; - INT32 skintableindex = SkinToCacheIndex(skinnum); // Adjust if we want the default colormap - INT32 i; + UINT8 ***cache = NULL; + INT32 index, starttranscolor; + UINT8 *ret; + + // Adjust if we want the default colormap + if (skinnum >= numskins) + I_Error("Invalid skin number %d", skinnum); + else if (skinnum >= 0) + { + cache = skintranslationcache; + starttranscolor = index = skins[skinnum]->starttranscolor; + } + else if (skinnum <= TC_DEFAULT) + { + cache = translationtablecache; + starttranscolor = DEFAULT_STARTTRANSCOLOR; + index = TranslationToCacheIndex(skinnum); + } + else + I_Error("Invalid translation %d", skinnum); if (flags & GTC_CACHE) { // Allocate table for skin if necessary - if (!translationtablecache[skintableindex]) - translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); + if (!cache[index]) + cache[index] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); // Get colormap - ret = translationtablecache[skintableindex][color]; + ret = cache[index][color]; // Rebuild the cache if necessary if (skincolor_modified[color]) { - for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) + INT32 i; + + for (i = 0; i < TT_CACHE_SIZE; i++) if (translationtablecache[i] && translationtablecache[i][color]) - R_GenerateTranslationColormap(translationtablecache[i][color], CacheIndexToSkin(i), color); + R_GenerateTranslationColormap(translationtablecache[i][color], CacheIndexToTranslation(i), color, starttranscolor); + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + if (skintranslationcache[i] && skintranslationcache[i][color]) + R_GenerateTranslationColormap(skintranslationcache[i][color], 0, color, i); skincolor_modified[color] = false; } @@ -612,11 +634,11 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags if (!ret) { ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8); - R_GenerateTranslationColormap(ret, skinnum, color); + R_GenerateTranslationColormap(ret, skinnum, color, starttranscolor); // Cache the colormap if desired if (flags & GTC_CACHE) - translationtablecache[skintableindex][color] = ret; + cache[index][color] = ret; } return ret; @@ -634,9 +656,12 @@ void R_FlushTranslationColormapCache(void) { INT32 i; - for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) + for (i = 0; i < TT_CACHE_SIZE; i++) if (translationtablecache[i]) memset(translationtablecache[i], 0, MAXSKINCOLORS * sizeof(UINT8**)); + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + if (skintranslationcache[i]) + memset(skintranslationcache[i], 0, MAXSKINCOLORS * sizeof(UINT8**)); } UINT16 R_GetColorByName(const char *name) diff --git a/src/r_draw.h b/src/r_draw.h index 2173c7a5a..6d7e89f35 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -147,7 +147,7 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel); boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); // Color ramp modification should force a recache -extern UINT8 skincolor_modified[]; +extern boolean skincolor_modified[]; void R_InitViewBuffer(INT32 width, INT32 height); void R_InitViewBorder(void); diff --git a/src/st_stuff.c b/src/st_stuff.c index 88affcf0a..1db91da7a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -128,8 +128,6 @@ static patch_t *gotrflag; static patch_t *gotbflag; static patch_t *fnshico; -static boolean facefreed[MAXPLAYERS]; - hudinfo_t hudinfo[NUMHUDITEMS] = { { 16, 176, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_LIVES @@ -361,17 +359,14 @@ void ST_LoadFaceGraphics(INT32 skinnum) } else faceprefix[skinnum] = superprefix[skinnum] = W_CachePatchName("MISSING", PU_HUDGFX); // ditto - facefreed[skinnum] = false; } void ST_ReloadSkinFaceGraphics(void) { INT32 i; - if (faceprefix) - Z_Free(faceprefix); - if (superprefix) - Z_Free(superprefix); + Z_Free(faceprefix); + Z_Free(superprefix); if (!numskins) return; @@ -421,11 +416,6 @@ lumpnum_t st_borderpatchnum; void ST_Init(void) { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - facefreed[i] = true; - if (dedicated) return; From 1a84f1bcba730c5924debce96473639f0ca7fb67 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 10 Aug 2021 15:17:22 -0300 Subject: [PATCH 5/7] Minor changes and fixes --- src/d_player.h | 4 +- src/deh_soc.c | 103 +++++++++++++++++++++++------------------ src/dehacked.c | 22 ++++++--- src/dehacked.h | 1 + src/doomdef.h | 7 +-- src/g_game.c | 2 +- src/hardware/hw_main.c | 2 +- src/hardware/hw_md2.c | 2 +- src/m_menu.h | 4 +- src/r_picformats.c | 9 ++-- src/r_skins.c | 2 +- src/r_skins.h | 4 +- src/r_things.c | 2 +- src/y_inter.c | 8 ++-- 14 files changed, 96 insertions(+), 76 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 54ab34288..1418b7c52 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -375,10 +375,10 @@ typedef struct player_s UINT16 flashcount; UINT16 flashpal; - // Player skin colorshift, 0-15 for which color to draw player. + // Player skin colorshift, which color to draw player. UINT16 skincolor; - INT32 skin; + UINT8 skin; UINT32 availabilities; UINT32 score; // player score diff --git a/src/deh_soc.c b/src/deh_soc.c index 4c63a4d6a..2624d183c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -187,7 +187,7 @@ void clear_levels(void) P_AllocMapHeader(gamemap-1); } -static boolean findFreeSlot(INT32 *num) +static boolean findCharacterSlot(INT32 *num) { if (description) { @@ -213,30 +213,43 @@ void readPlayer(MYFILE *f, INT32 num) char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word; char *word2; - char *displayname = ZZ_Alloc(MAXLINELEN+1); - INT32 i; boolean slotfound = false; + boolean failure = false; + INT32 i; + + if (num < 0 || num >= MAXCHARACTERSLOTS) + { + deh_warning("Character %d out of range (0 - %d)", num, MAXCHARACTERSLOTS-1); + failure = true; + } + + #define FINDSLOT \ + if (!failure && !slotfound && (slotfound = findCharacterSlot(&num)) == false) { \ + failure = true; \ + deh_warning("Too many characters, ignoring"); \ + } #define SLOTFOUND \ - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) \ - goto done; - - displayname[MAXLINELEN] = '\0'; + FINDSLOT \ + if (failure) \ + continue; do { if (myfgets(s, MAXLINELEN, f)) { + char stringvalue[MAXLINELEN]; + if (s[0] == '\n') break; - for (i = 0; i < MAXLINELEN-3; i++) + stringvalue[0] = '\0'; + + for (i = 0; i < MAXLINELEN-3 && !failure; i++) { - char *tmp; if (s[i] == '=') { - tmp = &s[i+2]; - strncpy(displayname, tmp, SKINNAMESIZE); + strlcpy(stringvalue, &s[i+2], sizeof stringvalue); break; } } @@ -251,7 +264,13 @@ void readPlayer(MYFILE *f, INT32 num) { char *playertext = NULL; - SLOTFOUND + FINDSLOT + + if (failure) + { + ignorelinesuntilhash(f); + continue; + } // A friendly neighborhood alias for brevity's sake #define NOTE_SIZE sizeof(description[num].notes) @@ -271,7 +290,7 @@ void readPlayer(MYFILE *f, INT32 num) myhashfgets(playertext, NOTE_SIZE, f), NOTE_SIZE); } else - strcpy(description[num].notes, ""); + description[num].notes[0] = '\0'; // For some reason, cutting the string did not work above. Most likely due to strcpy or strcat... // It works down here, though. @@ -300,37 +319,32 @@ void readPlayer(MYFILE *f, INT32 num) if (word2[strlen(word2)-1] == '\n') word2[strlen(word2)-1] = '\0'; - i = atoi(word2); if (fastcmp(word, "PICNAME")) { SLOTFOUND strncpy(description[num].picname, word2, 8); } - // new character select else if (fastcmp(word, "DISPLAYNAME")) { + char *cur = NULL; + SLOTFOUND - // replace '#' with line breaks - // (also remove any '\n') + + // Remove any line breaks + cur = strchr(stringvalue, '\n'); + if (cur) + *cur = '\0'; + + // Turn '#' into line breaks + cur = strchr(stringvalue, '#'); + while (cur) { - char *cur = NULL; - - // remove '\n' - cur = strchr(displayname, '\n'); - if (cur) - *cur = '\0'; - - // turn '#' into '\n' - cur = strchr(displayname, '#'); - while (cur) - { - *cur = '\n'; - cur = strchr(cur, '#'); - } + *cur = '\n'; + cur = strchr(cur, '#'); } - // copy final string - strncpy(description[num].displayname, displayname, SKINNAMESIZE); + + strlcpy(description[num].displayname, stringvalue, sizeof description[num].displayname); } else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR")) { @@ -361,10 +375,12 @@ void readPlayer(MYFILE *f, INT32 num) Because of this, you are allowed to edit any previous entries you like, but only if you signal that you are purposely doing so by disabling and then reenabling the slot. */ - if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false) - goto done; + i = atoi(word2); + if (i && !slotfound && (slotfound = findCharacterSlot(&num)) == false) + failure = true; - description[num].used = (!!i); + if (!failure) + description[num].used = (!!i); } else if (fastcmp(word, "SKINNAME")) { @@ -373,13 +389,12 @@ void readPlayer(MYFILE *f, INT32 num) strlcpy(description[num].skinname, word2, sizeof description[num].skinname); strlwr(description[num].skinname); } - else + else if (!failure) deh_warning("readPlayer %d: unknown word '%s'", num, word); } } while (!myfeof(f)); // finish when the line is empty + #undef FINDSLOT #undef SLOTFOUND -done: - Z_Free(displayname); Z_Free(s); } @@ -920,7 +935,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) INT32 value; #endif char *lastline; - INT32 *skinnumbers = NULL; + UINT8 *skinnumbers = NULL; INT32 foundskins = 0; // allocate a spriteinfo @@ -1010,8 +1025,8 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) } if (skinnumbers == NULL) - skinnumbers = Z_Malloc(sizeof(INT32) * numskins, PU_STATIC, NULL); - skinnumbers[foundskins] = skinnum; + skinnumbers = Z_Malloc(sizeof(UINT8) * numskins, PU_STATIC, NULL); + skinnumbers[foundskins] = (UINT8)skinnum; foundskins++; } else if (fastcmp(word, "DEFAULT")) @@ -1054,8 +1069,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) } for (i = 0; i < foundskins; i++) { - size_t skinnum = skinnumbers[i]; - skin_t *skin = skins[skinnum]; + skin_t *skin = skins[skinnumbers[i]]; spriteinfo_t *sprinfo = skin->sprinfo; M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); } @@ -1121,7 +1135,6 @@ void readsprite2(MYFILE *f, INT32 num) Z_Free(s); } -// copypasted from readPlayer :] void readgametype(MYFILE *f, char *gtname) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); diff --git a/src/dehacked.c b/src/dehacked.c index 7a8e2e9d6..ac9a4a46a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -169,6 +169,20 @@ static void ignorelines(MYFILE *f) Z_Free(s); } +void ignorelinesuntilhash(MYFILE *f) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '#') + break; + } + } while (!myfeof(f)); + Z_Free(s); +} + static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -226,13 +240,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) i = 0; if (fastcmp(word, "CHARACTER")) { - if (i >= 0 && i < MAXCHARACTERSLOTS) - readPlayer(f, i); - else - { - deh_warning("Character %d out of range (0 - 31)", i); - ignorelines(f); - } + readPlayer(f, i); continue; } else if (fastcmp(word, "EMBLEM")) diff --git a/src/dehacked.h b/src/dehacked.h index 1b200e246..23765f8b7 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -61,4 +61,5 @@ typedef struct #define myfeof(a) (a->data + a->size <= a->curpos) char *myfgets(char *buf, size_t bufsize, MYFILE *f); char *myhashfgets(char *buf, size_t bufsize, MYFILE *f); +void ignorelinesuntilhash(MYFILE *f); #endif diff --git a/src/doomdef.h b/src/doomdef.h index 5e7df3ecd..cf209bc8a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -220,10 +220,11 @@ extern char logfilename[1024]; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 32 -#define MAXSKINS 256 -#define MAXCHARACTERSLOTS (MAXSKINS * 2) -#define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 +#define PLAYERSMASK (MAXPLAYERS-1) + +#define MAXSKINS 256 +#define MAXCHARACTERSLOTS (MAXSKINS * 3) #define COLORRAMPSIZE 16 #define MAXCOLORNAME 32 diff --git a/src/g_game.c b/src/g_game.c index 6b3354de7..2908b9f01 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2488,7 +2488,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT8 laps; UINT8 mare; UINT16 skincolor; - INT32 skin; + UINT8 skin; UINT32 availabilities; tic_t jointime; tic_t quittime; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 66df7d2cd..4913714b1 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5359,7 +5359,7 @@ static void HWR_ProjectSprite(mobj_t *thing) } else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { - INT32 skinnum = ((skin_t*)thing->skin)->skinnum; + UINT8 skinnum = ((skin_t*)thing->skin)->skinnum; vis->colormap = R_GetTranslationColormap(skinnum, thing->color, GTC_CACHE); } else diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index b54e14089..06f2ecf34 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1271,7 +1271,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // 2. draw model with correct position, rotation,... if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) // Use the player MD2 list if the mobj has a skin and is using the player sprites { - INT32 skinnum = ((skin_t*)spr->mobj->skin)->skinnum; + UINT8 skinnum = ((skin_t*)spr->mobj->skin)->skinnum; md2 = &md2_playermodels[skinnum]; sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; } diff --git a/src/m_menu.h b/src/m_menu.h index 3e2f6f9ae..b7c5c797b 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -375,10 +375,8 @@ typedef struct patch_t *charpic; UINT8 prev; UINT8 next; - - // new character select char displayname[SKINNAMESIZE+1]; - SINT8 skinnum[2]; + INT16 skinnum[2]; UINT16 oppositecolor; char nametag[8]; patch_t *namepic; diff --git a/src/r_picformats.c b/src/r_picformats.c index 5c2544a7f..3e1ea8eb9 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1498,7 +1498,7 @@ static void R_ParseSpriteInfo(boolean spr2) spritenum_t sprnum = NUMSPRITES; playersprite_t spr2num = NUMPLAYERSPRITES; INT32 i; - INT32 *skinnumbers = NULL; + UINT8 *skinnumbers = NULL; INT32 foundskins = 0; // Sprite name @@ -1597,8 +1597,8 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); if (skinnumbers == NULL) - skinnumbers = Z_Malloc(sizeof(INT32) * numskins, PU_STATIC, NULL); - skinnumbers[foundskins] = skinnum; + skinnumbers = Z_Malloc(sizeof(UINT8) * numskins, PU_STATIC, NULL); + skinnumbers[foundskins] = (UINT8)skinnum; foundskins++; } else if (stricmp(sprinfoToken, "FRAME")==0) @@ -1611,8 +1611,7 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); for (i = 0; i < foundskins; i++) { - size_t skinnum = skinnumbers[i]; - skin_t *skin = skins[skinnum]; + skin_t *skin = skins[skinnumbers[i]]; spriteinfo_t *sprinfo = skin->sprinfo; M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); } diff --git a/src/r_skins.c b/src/r_skins.c index b0dcda035..c4cac6ce2 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -278,7 +278,7 @@ INT32 R_SkinAvailable(const char *name) { // search in the skin list if (!stricmp(skins[i]->name,name)) - return skins[i]->skinnum; + return i; } return -1; } diff --git a/src/r_skins.h b/src/r_skins.h index 67f34aa66..8cf3f640b 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -31,8 +31,8 @@ /// The skin_t struct typedef struct { - char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin - UINT32 skinnum; + char name[SKINNAMESIZE+1]; // name of the skin + UINT8 skinnum; UINT16 wadnum; skinflags_t flags; diff --git a/src/r_things.c b/src/r_things.c index 69a9eb5e9..b4a45f966 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -764,7 +764,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) } else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { - INT32 skinnum = ((skin_t*)vis->mobj->skin)->skinnum; + UINT8 skinnum = ((skin_t*)vis->mobj->skin)->skinnum; return R_GetTranslationColormap(skinnum, vis->mobj->color, GTC_CACHE); } else // Use the defaults diff --git a/src/y_inter.c b/src/y_inter.c index 8897d2b99..8a8fcd425 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1617,7 +1617,7 @@ static void Y_CalculateMatchWinners(void) { data.match.scores[data.match.numplayers] = players[i].score; data.match.color[data.match.numplayers] = &players[i].skincolor; - data.match.character[data.match.numplayers] = &players[i].skin; + data.match.character[data.match.numplayers] = players[i].skin; data.match.name[data.match.numplayers] = player_names[i]; data.match.spectator[data.match.numplayers] = players[i].spectator; data.match.num[data.match.numplayers] = i; @@ -1662,7 +1662,7 @@ static void Y_CalculateTimeRaceWinners(void) { data.match.scores[data.match.numplayers] = players[i].realtime; data.match.color[data.match.numplayers] = &players[i].skincolor; - data.match.character[data.match.numplayers] = &players[i].skin; + data.match.character[data.match.numplayers] = players[i].skin; data.match.name[data.match.numplayers] = player_names[i]; data.match.num[data.match.numplayers] = i; } @@ -1788,7 +1788,7 @@ static void Y_CalculateCompetitionWinners(void) strncpy(data.competition.name[data.competition.numplayers], tempname, 9); data.competition.color[data.competition.numplayers] = &players[winner].skincolor; - data.competition.character[data.competition.numplayers] = &players[winner].skin; + data.competition.character[data.competition.numplayers] = players[winner].skin; completed[winner] = true; data.competition.numplayers++; @@ -2110,7 +2110,7 @@ static void Y_AwardSpecialStageBonus(void) if (players[i].gotcontinue) data.spec.continues |= 0x80; data.spec.playercolor = &players[i].skincolor; - data.spec.playerchar = &players[i].skin; + data.spec.playerchar = players[i].skin; } } } From 290adb23726da907099f59936a8e8103677f6031 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 10 Aug 2021 17:02:43 -0300 Subject: [PATCH 6/7] Add a descriptive comment about the MAXSKINS macro --- src/doomdef.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index cf209bc8a..43e25b064 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -223,8 +223,13 @@ extern char logfilename[1024]; #define MAXPLAYERNAME 21 #define PLAYERSMASK (MAXPLAYERS-1) +// Don't make MAXSKINS higher than 256, since skin numbers are used with an +// UINT8 in various parts of the codebase. If you do anyway, the data type +// of those variables will have to be changed into at least an UINT16. +// This change must affect code such as demo recording and playback, +// and the structure of some networking packets and commands. #define MAXSKINS 256 -#define MAXCHARACTERSLOTS (MAXSKINS * 3) +#define MAXCHARACTERSLOTS (MAXSKINS * 3) // Should be higher than MAXSKINS. #define COLORRAMPSIZE 16 #define MAXCOLORNAME 32 From 85f6e37ed08dbdb4f69a038fa6ca4bc6703489dc Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 23 Nov 2023 13:56:42 -0300 Subject: [PATCH 7/7] Update comment --- src/lua_script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_script.c b/src/lua_script.c index 9dea62b83..188983c12 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1345,7 +1345,7 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex)); WRITEUINT8(save_p, ARCH_SKIN); - WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS is only 32 + WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256 break; } default: