From edec1088b9dd49df179e704937bf5c79288a3072 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 5 Feb 2024 00:59:31 +0100 Subject: [PATCH 01/37] Support LF_MIXNIGHTSCOUNTDOWN for old-style special stages --- src/p_tick.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index 4ab388486..6fd566ea5 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -564,6 +564,12 @@ void P_DoTeamscrambling(void) CV_SetValue(&cv_teamscramble, 0); } + +// +// P_DoSpecialStageStuff() +// +// For old-style (non-NiGHTS) special stages +// static inline void P_DoSpecialStageStuff(void) { boolean stillalive = false; @@ -601,7 +607,15 @@ static inline void P_DoSpecialStageStuff(void) if (--players[i].nightstime > 6) { if (P_IsLocalPlayer(&players[i]) && oldnightstime > 10*TICRATE && players[i].nightstime <= 10*TICRATE) - S_ChangeMusicInternal("_drown", false); + { + if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + { + S_FadeMusic(0, 10*MUSICRATE); + S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. + } + else + S_ChangeMusicInternal("_drown", false); + } stillalive = true; } else if (!players[i].exiting) From af4e64d1a5f370a9495a5b2259c192bc51458ad6 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 5 Feb 2024 01:28:35 +0100 Subject: [PATCH 02/37] Make Extra Time powerup work in old-style special stages --- src/p_inter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index d8765e7a2..c51e43801 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1332,7 +1332,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSEXTRATIME: - if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + boolean eligible = player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)); + if ((player->bot && player->bot != BOT_MPAI) || !eligible) return; if (!G_IsSpecialStage(gamemap)) { @@ -1344,7 +1345,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) + if (playeringame[i] && eligible) { players[i].nightstime += special->info->speed; players[i].startedtime += special->info->speed; From 9ca5ce01f1fde4680820af7d0e31dc7ce38181fd Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 14 Mar 2024 13:56:47 +0100 Subject: [PATCH 03/37] No longer store wadnum in sprnames --- src/deh_lua.c | 11 +---------- src/deh_soc.c | 7 +------ src/lua_script.c | 3 --- src/r_things.c | 3 --- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index c056db82a..b73479263 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -59,23 +59,14 @@ static inline int lib_freeslot(lua_State *L) } else if (fastcmp(type, "SPR")) { - char wad; spritenum_t j; - lua_getfield(L, LUA_REGISTRYINDEX, "WAD"); - wad = (char)lua_tointeger(L, -1); - lua_pop(L, 1); for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++) { if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8))) - { - if (!sprnames[j][4] && memcmp(sprnames[j],word,4)==0) - sprnames[j][4] = wad; continue; // Already allocated, next. - } // Found a free slot! CONS_Printf("Sprite SPR_%s allocated.\n",word); strncpy(sprnames[j],word,4); - //sprnames[j][4] = 0; used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, j); @@ -456,7 +447,7 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) else if (fastncmp("SPR_",word,4)) { p = word+4; for (i = 0; i < NUMSPRITES; i++) - if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) { + if (fastncmp(p,sprnames[i],4)) { // updating overridden sprnames is not implemented for soc parser, // so don't use cache if (mathlib) diff --git a/src/deh_soc.c b/src/deh_soc.c index 65db63ebb..6b90b6a86 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -443,14 +443,9 @@ void readfreeslots(MYFILE *f) for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { if (used_spr[(i-SPR_FIRSTFREESLOT)/8] & (1<<(i%8))) - { - if (!sprnames[i][4] && memcmp(sprnames[i],word,4)==0) - sprnames[i][4] = (char)f->wad; continue; // Already allocated, next. - } // Found a free slot! strncpy(sprnames[i],word,4); - //sprnames[i][4] = 0; used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, i); @@ -4183,7 +4178,7 @@ spritenum_t get_sprite(const char *word) if (fastncmp("SPR_",word,4)) word += 4; // take off the SPR_ for (i = 0; i < NUMSPRITES; i++) - if (!sprnames[i][4] && memcmp(word,sprnames[i],4)==0) + if (memcmp(word,sprnames[i],4)==0) return i; deh_warning("Couldn't find sprite named 'SPR_%s'",word); return SPR_NULL; diff --git a/src/lua_script.c b/src/lua_script.c index b62fa675e..057899555 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -622,9 +622,6 @@ static inline boolean LUA_LoadFile(MYFILE *f, char *name) if (!gL) // Lua needs to be initialized LUA_ClearState(); - lua_pushinteger(gL, f->wad); - lua_setfield(gL, LUA_REGISTRYINDEX, "WAD"); - lua_pushcfunction(gL, LUA_GetErrorMessage); errorhandlerindex = lua_gettop(gL); diff --git a/src/r_things.c b/src/r_things.c index 76e680687..d56b473b8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -480,9 +480,6 @@ void R_AddSpriteDefs(UINT16 wadnum) // for (i = 0; i < numsprites; i++) { - if (sprnames[i][4] && wadnum >= (UINT16)sprnames[i][4]) - continue; - if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) { // if a new sprite was added (not just replaced) From 8073b8b3f0f85bd2201ed47f30e80d62d072dcf8 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 14 Mar 2024 20:20:12 +0100 Subject: [PATCH 04/37] Fix rare Lua bug when updating a SPR_ constant --- src/deh_lua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index b73479263..9c9e62a69 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -740,7 +740,7 @@ void LUA_UpdateSprName(const char *name, lua_Integer value) if (!lua_isnil(gL, -1)) { - lua_pushstring(gL, name); + lua_pushstring(gL, fullname); lua_pushinteger(gL, value); lua_rawset(gL, LUA_GLOBALSINDEX); } From 092ac6643e924a8b4dab9e50482754ac6a944f08 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 14 Mar 2024 20:32:10 +0100 Subject: [PATCH 05/37] Allow sprite names with up to 64 characters --- src/deh_lua.c | 12 ++++++++---- src/deh_soc.c | 7 +++++-- src/hardware/hw_md2.c | 18 +++++++----------- src/info.c | 5 +++-- src/info.h | 5 +++-- src/r_picformats.c | 19 ++++++------------- src/r_things.c | 6 +++--- 7 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 9c9e62a69..0effe4fa7 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -60,13 +60,17 @@ static inline int lib_freeslot(lua_State *L) else if (fastcmp(type, "SPR")) { spritenum_t j; + + if (strlen(word) > MAXSPRITENAME) + return luaL_error(L, "Sprite name is longer than %d characters\n", strlen(word)); + for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++) { if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8))) continue; // Already allocated, next. // Found a free slot! CONS_Printf("Sprite SPR_%s allocated.\n",word); - strncpy(sprnames[j],word,4); + strcpy(sprnames[j], word); used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, j); @@ -447,7 +451,7 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) else if (fastncmp("SPR_",word,4)) { p = word+4; for (i = 0; i < NUMSPRITES; i++) - if (fastncmp(p,sprnames[i],4)) { + if (fastcmp(p,sprnames[i])) { // updating overridden sprnames is not implemented for soc parser, // so don't use cache if (mathlib) @@ -729,12 +733,12 @@ static inline int lib_getenum(lua_State *L) // If a sprname has been "cached" to _G, update it to a new value. void LUA_UpdateSprName(const char *name, lua_Integer value) { - char fullname[9] = "SPR_XXXX"; + char fullname[4 + MAXSPRITENAME + 1] = "SPR_"; if (!gL) return; - strncpy(&fullname[4], name, 4); + strcpy(&fullname[4], name); lua_pushstring(gL, fullname); lua_rawget(gL, LUA_GLOBALSINDEX); diff --git a/src/deh_soc.c b/src/deh_soc.c index 6b90b6a86..fe43cd283 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -440,12 +440,15 @@ void readfreeslots(MYFILE *f) S_AddSoundFx(word, false, 0, false); else if (fastcmp(type, "SPR")) { + if (strlen(word) > MAXSPRITENAME) + I_Error("Sprite name is longer than %d characters\n", strlen(word)); + for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { if (used_spr[(i-SPR_FIRSTFREESLOT)/8] & (1<<(i%8))) continue; // Already allocated, next. // Found a free slot! - strncpy(sprnames[i],word,4); + strcpy(sprnames[i], word); used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, i); @@ -4178,7 +4181,7 @@ spritenum_t get_sprite(const char *word) if (fastncmp("SPR_",word,4)) word += 4; // take off the SPR_ for (i = 0; i < NUMSPRITES; i++) - if (memcmp(word,sprnames[i],4)==0) + if (!strcmp(word, sprnames[i])) return i; deh_warning("Couldn't find sprite named 'SPR_%s'",word); return SPR_NULL; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 656fbc4a6..0bb8de851 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -571,19 +571,15 @@ void HWR_LoadModels(void) } // 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++) { - for (i = 0; i < numsprites; i++) + if (stricmp(name, sprnames[i]) == 0) { - 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; - } + md2_models[i].scale = scale; + md2_models[i].offset = offset; + md2_models[i].found = true; + strcpy(md2_models[i].filename, filename); + goto modelfound; } } diff --git a/src/info.c b/src/info.c index ab46cdbc7..9b33a57ab 100644 --- a/src/info.c +++ b/src/info.c @@ -26,9 +26,10 @@ #include "hardware/hw_light.h" #endif + // Hey, moron! If you change this table, don't forget about the sprite enum in info.h and the sprite lights in hw_light.c! // For the sake of constant merge conflicts, let's spread this out -char sprnames[NUMSPRITES + 1][5] = +char sprnames[NUMSPRITES + 1][MAXSPRITENAME + 1] = { "NULL", // invisible object "UNKN", @@ -525,7 +526,7 @@ char sprnames[NUMSPRITES + 1][5] = "GWLR", }; -char spr2names[NUMPLAYERSPRITES][5] = +char spr2names[NUMPLAYERSPRITES][MAXSPRITENAME + 1] = { "STND", "WAIT", diff --git a/src/info.h b/src/info.h index 9475b2302..0361f6428 100644 --- a/src/info.h +++ b/src/info.h @@ -575,6 +575,7 @@ extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION]; #define NUMMOBJFREESLOTS 1024 #define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS #define NUMSTATEFREESLOTS (NUMMOBJFREESLOTS*8) +#define MAXSPRITENAME 64 // Hey, moron! If you change this table, don't forget about sprnames in info.c and the sprite lights in hw_light.c! typedef enum sprite @@ -4383,8 +4384,8 @@ typedef struct } state_t; extern state_t states[NUMSTATES]; -extern char sprnames[NUMSPRITES + 1][5]; -extern char spr2names[NUMPLAYERSPRITES][5]; +extern char sprnames[NUMSPRITES + 1][MAXSPRITENAME + 1]; +extern char spr2names[NUMPLAYERSPRITES][MAXSPRITENAME + 1]; extern playersprite_t spr2defaults[NUMPLAYERSPRITES]; extern state_t *astate; extern playersprite_t free_spr2; diff --git a/src/r_picformats.c b/src/r_picformats.c index e4a59f211..a75f15baf 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1570,7 +1570,7 @@ static void R_ParseSpriteInfo(boolean spr2) spriteinfo_t *info; char *sprinfoToken; size_t sprinfoTokenLength; - char newSpriteName[5]; // no longer dynamically allocated + char newSpriteName[MAXSPRITENAME + 1]; // no longer dynamically allocated spritenum_t sprnum = NUMSPRITES; playersprite_t spr2num = NUMPLAYERSPRITES; INT32 i; @@ -1584,17 +1584,10 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 4) - { - I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); - } - else - { - memset(&newSpriteName, 0, 5); - M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); - // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer - strupr(newSpriteName); // Just do this now so we don't have to worry about it - } + if (sprinfoTokenLength > MAXSPRITENAME) + I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" is longer than %d characters", sprinfoToken, MAXSPRITENAME); + strcpy(newSpriteName, sprinfoToken); + strupr(newSpriteName); // Just do this now so we don't have to worry about it Z_Free(sprinfoToken); if (!spr2) @@ -1603,7 +1596,7 @@ static void R_ParseSpriteInfo(boolean spr2) { if (i == NUMSPRITES) I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); - if (!memcmp(newSpriteName,sprnames[i],4)) + if (!strcmp(newSpriteName, sprnames[i])) { sprnum = i; break; diff --git a/src/r_things.c b/src/r_things.c index d56b473b8..1a17def1d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -383,7 +383,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 { case SRF_NONE: // no rotations were found for that frame at all - I_Error("R_AddSingleSpriteDef: No patches found for %.4s frame %c", sprname, R_Frame2Char(frame)); + I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame)); break; case SRF_SINGLE: @@ -393,7 +393,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 case SRF_2D: // both Left and Right rotations // we test to see whether the left and right slots are present if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) - I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (L-R mode)", + I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (L-R mode)", sprname, R_Frame2Char(frame)); break; @@ -404,7 +404,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // we test the patch lump, or the id lump whatever // if it was not loaded the two are LUMPERROR if (sprtemp[frame].lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (1-%c mode)", + I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (1-%c mode)", sprname, R_Frame2Char(frame), ((sprtemp[frame].rotate & SRF_3DGE) ? 'G' : '8')); break; } From 1c415749f74a2b13c4ca82d3af1ccd2ba92e95ff Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 15 Mar 2024 15:45:35 +0100 Subject: [PATCH 06/37] Refactor R_AddSpriteDefs --- src/r_things.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 1a17def1d..c9e1b7445 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -429,14 +429,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 return true; } -// -// Search for sprites replacements in a wad whose names are in namelist -// -void R_AddSpriteDefs(UINT16 wadnum) +static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded) { - size_t i, addsprites = 0; + size_t i; UINT16 start, end; - char wadname[MAX_WADPATH]; // Find the sprites section in this resource file. switch (wadfiles[wadnum]->type) @@ -474,7 +470,6 @@ void R_AddSpriteDefs(UINT16 wadnum) return; } - // // scan through lumps, for each sprite, find all the sprite frames // @@ -483,15 +478,29 @@ void R_AddSpriteDefs(UINT16 wadnum) if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) { // if a new sprite was added (not just replaced) - addsprites++; + (*ptr_spritesadded)++; #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", sprnames[i], wadnum); #endif } } + *ptr_framesadded += end - start; +} + +// +// Search for sprites replacements in a wad whose names are in namelist +// +void R_AddSpriteDefs(UINT16 wadnum) +{ + char wadname[MAX_WADPATH]; + size_t spritesadded = 0; + size_t framesadded = 0; + + AddShortSpriteDefs(wadnum, &spritesadded, &framesadded); + nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); - CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites)); + CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, framesadded, sizeu1(spritesadded)); } // From 837c3a7be36e32e6f44b6770f58c9bd2e0ea29fe Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 15 Mar 2024 20:06:21 +0100 Subject: [PATCH 07/37] Refactor R_AddSingleSpriteDef --- src/r_things.c | 62 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index c9e1b7445..42eea1e25 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -238,6 +238,40 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].flip &= ~(1<= 64) + return false; + + if (namelen == 8) + { + *ret_frame2 = R_Char2Frame(name[6]); + *ret_rotation2 = R_Char2Rotation(name[7]); + if (*ret_frame2 >= 64) + return false; + } + else + { + *ret_frame2 = 255; + *ret_rotation2 = 255; + } + + return true; +} + // Install a single sprite, given its identifying name (4 chars) // // (originally part of R_AddSpriteDefs) @@ -254,8 +288,6 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) { UINT16 l; - UINT8 frame; - UINT8 rotation; lumpinfo_t *lumpinfo; UINT16 numadded = 0; @@ -286,11 +318,12 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 { INT16 width, height; INT16 topoffset, leftoffset; + UINT8 frame, frame2; + UINT8 rotation, rotation2; - frame = R_Char2Frame(lumpinfo[l].name[4]); - rotation = R_Char2Rotation(lumpinfo[l].name[5]); + boolean good = GetFramesAndRotationsFromLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2); - if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-... + if (!good) // Give an actual NAME error -_-... { CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); continue; @@ -322,19 +355,8 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 //---------------------------------------------------- R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0); - - if (lumpinfo[l].name[6]) - { - frame = R_Char2Frame(lumpinfo[l].name[6]); - rotation = R_Char2Rotation(lumpinfo[l].name[7]); - - if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-... - { - CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); - continue; - } - R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1); - } + if (frame2 != 255) + R_InstallSpriteLump(wadnum, l, numspritelumps, frame2, rotation2, 1); if (++numspritelumps >= max_spritelumps) { @@ -377,7 +399,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // // some checks to help development // - for (frame = 0; frame < maxframe; frame++) + for (UINT8 frame = 0; frame < maxframe; frame++) { switch (sprtemp[frame].rotate) { @@ -399,7 +421,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 default: // must have all 8/16 frames - rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8); + UINT8 rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8); while (rotation--) // we test the patch lump, or the id lump whatever // if it was not loaded the two are LUMPERROR From 33f176fd5bfa5ce0d0f915f705253c67c4a39dca Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 15 Mar 2024 20:15:38 +0100 Subject: [PATCH 08/37] Refactor R_AddSingleSpriteDef --- src/r_things.c | 77 +++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 42eea1e25..866d668f9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -272,6 +272,47 @@ static boolean GetFramesAndRotationsFromLumpName( return true; } +// Some checks to help development +static void CheckFrame(const char *sprname) +{ + for (UINT8 frame = 0; frame < maxframe; frame++) + { + spriteframe_t *spriteframe = &sprtemp[frame]; + + switch (spriteframe->rotate) + { + case SRF_NONE: + // no rotations were found for that frame at all + I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame)); + break; + + case SRF_SINGLE: + // only the first rotation is needed + break; + + case SRF_2D: // both Left and Right rotations + // we test to see whether the left and right slots are present + if ((spriteframe->lumppat[2] == LUMPERROR) || (spriteframe->lumppat[6] == LUMPERROR)) + I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (L-R mode)", + sprname, R_Frame2Char(frame)); + break; + + default: + // must have all 8/16 frames + UINT8 rotation = ((spriteframe->rotate & SRF_3DGE) ? 16 : 8); + while (rotation--) + { + // we test the patch lump, or the id lump whatever + // if it was not loaded the two are LUMPERROR + if (spriteframe->lumppat[rotation] == LUMPERROR) + I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (1-%c mode)", + sprname, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); + } + break; + } + } +} + // Install a single sprite, given its identifying name (4 chars) // // (originally part of R_AddSpriteDefs) @@ -396,41 +437,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 maxframe++; - // - // some checks to help development - // - for (UINT8 frame = 0; frame < maxframe; frame++) - { - switch (sprtemp[frame].rotate) - { - case SRF_NONE: - // no rotations were found for that frame at all - I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame)); - break; - - case SRF_SINGLE: - // only the first rotation is needed - break; - - case SRF_2D: // both Left and Right rotations - // we test to see whether the left and right slots are present - if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (L-R mode)", - sprname, R_Frame2Char(frame)); - break; - - default: - // must have all 8/16 frames - UINT8 rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8); - while (rotation--) - // we test the patch lump, or the id lump whatever - // if it was not loaded the two are LUMPERROR - if (sprtemp[frame].lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (1-%c mode)", - sprname, R_Frame2Char(frame), ((sprtemp[frame].rotate & SRF_3DGE) ? 'G' : '8')); - break; - } - } + CheckFrame(sprname); // allocate space for the frames present and copy sprtemp to it if (spritedef->numframes && // has been allocated From 42c610af9cbc4fa36a41017a364fbf1a4b64d0a2 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 15 Mar 2024 21:02:41 +0100 Subject: [PATCH 09/37] Fix GetFramesAndRotationsFromShortLumpName --- src/r_things.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 866d668f9..4bfcaf7e0 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -253,14 +253,14 @@ static boolean GetFramesAndRotationsFromLumpName( *ret_frame = R_Char2Frame(name[4]); *ret_rotation = R_Char2Rotation(name[5]); - if (*ret_frame >= 64) + if (*ret_frame >= 64 || *ret_rotation == 255) return false; if (namelen == 8) { *ret_frame2 = R_Char2Frame(name[6]); *ret_rotation2 = R_Char2Rotation(name[7]); - if (*ret_frame2 >= 64) + if (*ret_frame2 >= 64 || *ret_rotation2 == 255) return false; } else From 99a9e5fcc9057ffeba39f7fef38b1b5154d4932c Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 15 Mar 2024 21:22:12 +0100 Subject: [PATCH 10/37] Add support for LongSprites/ folder --- src/r_skins.c | 4 +- src/r_things.c | 138 +++++++++++++++++++++++++++++++++++++++++-------- src/r_things.h | 4 +- src/w_wad.c | 41 +++++++++++++++ src/w_wad.h | 2 + 5 files changed, 165 insertions(+), 24 deletions(-) diff --git a/src/r_skins.c b/src/r_skins.c index 29a1556c0..d0d2eed62 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -625,7 +625,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski newlastlump++; // load all sprite sets we are aware of... for super! for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump); + R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump, false); newlastlump--; *lastlump = newlastlump; // okay, make the normal sprite set loading end there @@ -633,7 +633,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski // load all sprite sets we are aware of... for normal stuff. for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump, false); if (skin->sprites[0].numframes == 0) CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]); diff --git a/src/r_things.c b/src/r_things.c index 4bfcaf7e0..317aa6c56 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -116,6 +116,14 @@ static INT32 drawsegs_xrange_count = 0; // // ========================================================================== +spritenum_t R_GetSpriteNumByName(const char *name) +{ + for (spritenum_t i = 0; i < NUMSPRITES; i++) + if (!strcmp(name, sprnames[i])) + return i; + return NUMSPRITES; +} + // // // @@ -147,9 +155,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { // the lump should be used for all rotations if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple rot = 0 lump\n", spritename, frame, cn); else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message. - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has rotations and a rot = 0 lump\n", spritename, frame, cn); sprtemp[frame].rotate = SRF_SINGLE; for (r = 0; r < 16; r++) @@ -169,15 +177,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (sprtemp[frame].rotate == SRF_NONE) sprtemp[frame].rotate = SRF_SINGLE; else if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has L/R rotations and a rot = 0 lump\n", spritename, frame, cn); else if (sprtemp[frame].rotate == SRF_3D) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-8 rotations\n", spritename, frame, cn); else if (sprtemp[frame].rotate == SRF_3DGE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-G rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-G rotations\n", spritename, frame, cn); else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L)) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple L rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple L rotations\n", spritename, frame, cn); else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R)) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple R rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple R rotations\n", spritename, frame, cn); sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D) @@ -204,9 +212,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (sprtemp[frame].rotate == SRF_NONE) sprtemp[frame].rotate = SRF_SINGLE; else if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8/G rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has 1-8/G rotations and a rot = 0 lump\n", spritename, frame, cn); else if (sprtemp[frame].rotate & SRF_2D) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8/G rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-8/G rotations\n", spritename, frame, cn); // make 0 based rotation--; @@ -226,7 +234,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch } if (sprtemp[frame].lumppat[rotation] != LUMPERROR) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, cr); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c (%c%c) has two lumps mapped to it\n", spritename, frame, cr, cn, cr); // lumppat & lumpid are the same for original Doom, but different // when using sprites in pwad : the lumppat points the new graphics @@ -238,7 +246,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].flip &= ~(1< 4) + return false; + + char framepart[4 + 1]; // Max 9999 + strlcpy(framepart, name, framelen + 1); + + for (size_t i = 0; i < framelen; i++) + if (!isdigit(framepart[i])) + return false; + + *ret_frame = atoi(framepart); + *ret_rotation = R_Char2Rotation(*(underscore + 1)); + if (*ret_frame >= 64 || *ret_rotation == 255) + return false; + + *ret_frame2 = 255; + *ret_rotation2 = 255; + + return true; +} + // Some checks to help development static void CheckFrame(const char *sprname) { @@ -283,7 +325,7 @@ static void CheckFrame(const char *sprname) { case SRF_NONE: // no rotations were found for that frame at all - I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame)); + I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d (%c)", sprname, frame, R_Frame2Char(frame)); break; case SRF_SINGLE: @@ -293,8 +335,8 @@ static void CheckFrame(const char *sprname) case SRF_2D: // both Left and Right rotations // we test to see whether the left and right slots are present if ((spriteframe->lumppat[2] == LUMPERROR) || (spriteframe->lumppat[6] == LUMPERROR)) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (L-R mode)", - sprname, R_Frame2Char(frame)); + I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (L-R mode)", + sprname, frame, R_Frame2Char(frame)); break; default: @@ -305,8 +347,8 @@ static void CheckFrame(const char *sprname) // we test the patch lump, or the id lump whatever // if it was not loaded the two are LUMPERROR if (spriteframe->lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (1-%c mode)", - sprname, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); + I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (1-%c mode)", + sprname, frame, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); } break; } @@ -317,16 +359,17 @@ static void CheckFrame(const char *sprname) // // (originally part of R_AddSpriteDefs) // -// Pass: name of sprite : 4 chars +// Pass: name of sprite // spritedef_t // wadnum : wad number, indexes wadfiles[], where patches // for frames are found // startlump : first lump to search for sprite frames // endlump : AFTER the last lump to search +// longname : whether to use long sprite names or 4-char names // // Returns true if the sprite was succesfully added // -boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) +boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname) { UINT16 l; lumpinfo_t *lumpinfo; @@ -355,14 +398,18 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 for (l = startlump; l < endlump; l++) { - if (memcmp(lumpinfo[l].name,sprname,4)==0) + // For long sprites, the startlump-endlump range only includes + // relevant lumps, so no check needed in that case + if (longname || !memcmp(lumpinfo[l].name, sprname, 4)) { INT16 width, height; INT16 topoffset, leftoffset; UINT8 frame, frame2; UINT8 rotation, rotation2; - boolean good = GetFramesAndRotationsFromLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2); + boolean good = longname ? + GetFramesAndRotationsFromLongLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2) : + GetFramesAndRotationsFromShortLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2); if (!good) // Give an actual NAME error -_-... { @@ -504,7 +551,7 @@ static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t * // for (i = 0; i < numsprites; i++) { - if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) + if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end, false)) { // if a new sprite was added (not just replaced) (*ptr_spritesadded)++; @@ -517,6 +564,54 @@ static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t * *ptr_framesadded += end - start; } +static void AddLongSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded) +{ + if (!W_FileHasFolders(wadfiles[wadnum])) + return; + + UINT16 start = W_CheckNumForFolderStartPK3("LongSprites/", wadnum, 0); + UINT16 end = W_CheckNumForFolderEndPK3("LongSprites/", wadnum, start); + + if (start == INT16_MAX || end == INT16_MAX || start >= end) + return; + + size_t lumpnum = start; + + while (lumpnum < end) + { + if (W_IsLumpFolder(wadnum, lumpnum)) + { + lumpnum++; + continue; + } + + UINT16 folderstart, folderend; + char *folderpath = W_GetLumpFolderPathPK3(wadnum, lumpnum); + folderstart = lumpnum; + folderend = W_CheckNumForFolderEndPK3(folderpath, wadnum, lumpnum); + Z_Free(folderpath); + + spritenum_t sprnum; + char *sprname = W_GetLumpFolderNamePK3(wadnum, lumpnum); + strupr(sprname); + sprnum = R_GetSpriteNumByName(sprname); + Z_Free(sprname); + + if (sprnum != NUMSPRITES && R_AddSingleSpriteDef(sprname, &sprites[sprnum], wadnum, folderstart, folderend, true)) + { + // A new sprite was added (not just replaced) + (*ptr_spritesadded)++; +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "long sprite %s set in pwad %d\n", sprname, wadnum); +#endif + } + + lumpnum = folderend; + } + + *ptr_framesadded += end - start; +} + // // Search for sprites replacements in a wad whose names are in namelist // @@ -527,6 +622,7 @@ void R_AddSpriteDefs(UINT16 wadnum) size_t framesadded = 0; AddShortSpriteDefs(wadnum, &spritesadded, &framesadded); + AddLongSpriteDefs(wadnum, &spritesadded, &framesadded); nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, framesadded, sizeu1(spritesadded)); diff --git a/src/r_things.h b/src/r_things.h index f68d75a83..3daf55c42 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -27,7 +27,9 @@ #define FEETADJUST (4<lumpinfo[lump].fullname; + + const char *slash = strrchr(fullname, '/'); + INT32 pathlen = slash ? slash - fullname : 0; + + char *path = Z_Calloc(pathlen + 1, PU_STATIC, NULL); + strncpy(path, fullname, pathlen); + + return path; +} + +char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump) +{ + const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname; + size_t start, end; + + INT32 i = strlen(fullname); + + i--; + while (i >= 0 && fullname[i] != '/') + i--; + if (i < 0) + return NULL; + end = i; + + i--; + while (i >= 0 && fullname[i] != '/') + i--; + if (i < 0) + return NULL; + start = i + 1; + + size_t namelen = end - start; + char *foldername = Z_Calloc(namelen + 1, PU_STATIC, NULL); + strncpy(foldername, fullname + start, namelen); + + return foldername; +} + void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps) { size_t name_length = strlen(name); diff --git a/src/w_wad.h b/src/w_wad.h index e043e4d62..80e0e32fd 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -180,6 +180,8 @@ UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlu UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump); +char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump); +char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump); void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); From 178d29cf0c6002b31349739422a48fb0f7d81e7a Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 00:51:23 +0100 Subject: [PATCH 11/37] Allow up to 256 frames per sprite --- src/lua_infolib.c | 6 +++--- src/p_pspr.h | 2 +- src/r_defs.h | 2 ++ src/r_picformats.h | 2 +- src/r_things.c | 20 ++++++++++---------- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 0bcbcc5b9..cff72deb4 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -359,8 +359,8 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) default: TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); } - if ((idx < 0) || (idx >= 64)) - return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, 63); + if ((idx < 0) || (idx >= MAXFRAMENUM)) + return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, MAXFRAMENUM - 1); // the values in pivot[] are also tables if (PopPivotSubTable(info->pivot, L, stk+2, idx)) info->available = true; @@ -555,7 +555,7 @@ static int pivotlist_set(lua_State *L) static int pivotlist_num(lua_State *L) { - lua_pushinteger(L, 64); + lua_pushinteger(L, MAXFRAMENUM); return 1; } diff --git a/src/p_pspr.h b/src/p_pspr.h index be0d9f39e..5fb676763 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -35,7 +35,7 @@ #pragma interface #endif -/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 63, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER) +/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 255, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER) #define FF_FRAMEMASK 0xff /// \brief Frame flags - SPR2: Super sprite2 diff --git a/src/r_defs.h b/src/r_defs.h index cb94dd6e5..da4dd2d70 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -976,6 +976,8 @@ typedef struct #endif } spriteframe_t; +#define MAXFRAMENUM 256 + // // A sprite definition: a number of animation frames. // diff --git a/src/r_picformats.h b/src/r_picformats.h index 3ee9805d8..098f927a5 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -100,7 +100,7 @@ typedef struct typedef struct { - spriteframepivot_t pivot[64]; + spriteframepivot_t pivot[MAXFRAMENUM]; boolean available; } spriteinfo_t; diff --git a/src/r_things.c b/src/r_things.c index 317aa6c56..4e60e913f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -77,7 +77,7 @@ spriteinfo_t spriteinfo[NUMSPRITES]; spritedef_t *sprites; size_t numsprites; -static spriteframe_t sprtemp[64]; +static spriteframe_t sprtemp[MAXFRAMENUM]; static size_t maxframe; static const char *spritename; @@ -248,9 +248,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch static boolean GetFramesAndRotationsFromShortLumpName( const char *name, - UINT8 *ret_frame, + INT32 *ret_frame, UINT8 *ret_rotation, - UINT8 *ret_frame2, + INT32 *ret_frame2, UINT8 *ret_rotation2 ) { @@ -273,7 +273,7 @@ static boolean GetFramesAndRotationsFromShortLumpName( } else { - *ret_frame2 = 255; + *ret_frame2 = -1; *ret_rotation2 = 255; } @@ -282,9 +282,9 @@ static boolean GetFramesAndRotationsFromShortLumpName( static boolean GetFramesAndRotationsFromLongLumpName( const char *name, - UINT8 *ret_frame, + INT32 *ret_frame, UINT8 *ret_rotation, - UINT8 *ret_frame2, + INT32 *ret_frame2, UINT8 *ret_rotation2 ) { @@ -305,10 +305,10 @@ static boolean GetFramesAndRotationsFromLongLumpName( *ret_frame = atoi(framepart); *ret_rotation = R_Char2Rotation(*(underscore + 1)); - if (*ret_frame >= 64 || *ret_rotation == 255) + if (*ret_frame >= MAXFRAMENUM || *ret_rotation == 255) return false; - *ret_frame2 = 255; + *ret_frame2 = -1; *ret_rotation2 = 255; return true; @@ -404,7 +404,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 { INT16 width, height; INT16 topoffset, leftoffset; - UINT8 frame, frame2; + INT32 frame, frame2; UINT8 rotation, rotation2; boolean good = longname ? @@ -443,7 +443,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 //---------------------------------------------------- R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0); - if (frame2 != 255) + if (frame2 != -1) R_InstallSpriteLump(wadnum, l, numspritelumps, frame2, rotation2, 1); if (++numspritelumps >= max_spritelumps) From b3844a9ca5e2bff8e9b2832feca5c9943c73d5e5 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 16:14:52 +0100 Subject: [PATCH 12/37] Cleanup initfreeslots() --- src/deh_tables.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/deh_tables.h b/src/deh_tables.h index 42716f9b4..b71a2a23b 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -26,10 +26,10 @@ extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. #define initfreeslots() {\ - memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\ - memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\ - memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\ - memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\ + memset(FREE_STATES, 0, sizeof(FREE_STATES));\ + memset(FREE_MOBJS, 0, sizeof(FREE_MOBJS));\ + memset(FREE_SKINCOLORS, 0, sizeof(FREE_SKINCOLORS));\ + memset(used_spr, 0, sizeof(used_spr));\ memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));\ } From 45d54c38f74d3b8c681e73957e4fe4dfe1523792 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 16:26:33 +0100 Subject: [PATCH 13/37] Use bitarray_t for used_spr --- src/deh_lua.c | 4 ++-- src/deh_soc.c | 4 ++-- src/deh_tables.c | 2 +- src/deh_tables.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 0effe4fa7..3176f5d69 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -66,12 +66,12 @@ static inline int lib_freeslot(lua_State *L) for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++) { - if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8))) + if (in_bit_array(used_spr, j - SPR_FIRSTFREESLOT)) continue; // Already allocated, next. // Found a free slot! CONS_Printf("Sprite SPR_%s allocated.\n",word); strcpy(sprnames[j], word); - used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now. + set_bit_array(used_spr, j - SPR_FIRSTFREESLOT); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, j); lua_pushinteger(L, j); diff --git a/src/deh_soc.c b/src/deh_soc.c index fe43cd283..5e068313d 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -445,11 +445,11 @@ void readfreeslots(MYFILE *f) for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { - if (used_spr[(i-SPR_FIRSTFREESLOT)/8] & (1<<(i%8))) + if (in_bit_array(used_spr, i - SPR_FIRSTFREESLOT)) continue; // Already allocated, next. // Found a free slot! strcpy(sprnames[i], word); - used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now. + set_bit_array(used_spr, i - SPR_FIRSTFREESLOT); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, i); break; diff --git a/src/deh_tables.c b/src/deh_tables.c index ed401d68a..c7c7c6040 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -31,7 +31,7 @@ char *FREE_STATES[NUMSTATEFREESLOTS]; char *FREE_MOBJS[NUMMOBJFREESLOTS]; char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; -UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. +bitarray_t used_spr[BIT_ARRAY_SIZE(NUMSPRITEFREESLOTS)]; // Sprite freeslots in use const char NIGHTSGRADE_LIST[] = { 'F', // GRADE_F diff --git a/src/deh_tables.h b/src/deh_tables.h index b71a2a23b..b6986adff 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -23,7 +23,7 @@ extern char *FREE_STATES[NUMSTATEFREESLOTS]; extern char *FREE_MOBJS[NUMMOBJFREESLOTS]; extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; -extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. +extern bitarray_t used_spr[BIT_ARRAY_SIZE(NUMSPRITEFREESLOTS)]; // Sprite freeslots in use #define initfreeslots() {\ memset(FREE_STATES, 0, sizeof(FREE_STATES));\ From a6b71826f91ee018cd9fdeef1b1f7a7e4bfadd30 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 17:00:59 +0100 Subject: [PATCH 14/37] Use R_GetSpriteNumByName everywhere --- src/deh_lua.c | 24 +++++++++++++----------- src/deh_soc.c | 6 +++--- src/lua_hudlib.c | 4 +--- src/lua_infolib.c | 25 +++++++++---------------- src/r_picformats.c | 13 +++---------- 5 files changed, 29 insertions(+), 43 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 3176f5d69..3d6d8b455 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -450,17 +450,19 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) } else if (fastncmp("SPR_",word,4)) { p = word+4; - for (i = 0; i < NUMSPRITES; i++) - if (fastcmp(p,sprnames[i])) { - // updating overridden sprnames is not implemented for soc parser, - // so don't use cache - if (mathlib) - lua_pushinteger(L, i); - else - CacheAndPushConstant(L, word, i); - return 1; - } - if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word); + i = R_GetSpriteNumByName(p); + if (i != NUMSPRITES) + { + // updating overridden sprnames is not implemented for soc parser, + // so don't use cache + if (mathlib) + lua_pushinteger(L, i); + else + CacheAndPushConstant(L, word, i); + return 1; + } + else if (mathlib) + return luaL_error(L, "sprite '%s' could not be found.\n", word); return 0; } else if (fastncmp("SPR2_",word,5)) { diff --git a/src/deh_soc.c b/src/deh_soc.c index 5e068313d..269598459 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -4180,9 +4180,9 @@ spritenum_t get_sprite(const char *word) return atoi(word); if (fastncmp("SPR_",word,4)) word += 4; // take off the SPR_ - for (i = 0; i < NUMSPRITES; i++) - if (!strcmp(word, sprnames[i])) - return i; + i = R_GetSpriteNumByName(word); + if (i != NUMSPRITES) + return i; deh_warning("Couldn't find sprite named 'SPR_%s'",word); return SPR_NULL; } diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index ddd6c6888..d6771f108 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -492,9 +492,7 @@ static int libd_getSpritePatch(lua_State *L) else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "THOK" { const char *name = lua_tostring(L, 1); - for (i = 0; i < NUMSPRITES; i++) - if (fastcmp(name, sprnames[i])) - break; + i = R_GetSpriteNumByName(name); if (i >= NUMSPRITES) return 0; } diff --git a/src/lua_infolib.c b/src/lua_infolib.c index cff72deb4..eeb1067a3 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -88,12 +88,12 @@ static int lib_getSprname(lua_State *L) else if (lua_isstring(L, 1)) { const char *name = lua_tostring(L, 1); - for (i = 0; i < NUMSPRITES; i++) - if (fastcmp(name, sprnames[i])) - { - lua_pushinteger(L, i); - return 1; - } + i = R_GetSpriteNumByName(name); + if (i != NUMSPRITES) + { + lua_pushinteger(L, i); + return 1; + } } return 0; } @@ -245,22 +245,15 @@ static int lib_getSpriteInfo(lua_State *L) if (lua_isstring(L, 1)) { const char *name = lua_tostring(L, 1); - INT32 spr; - for (spr = 0; spr < NUMSPRITES; spr++) - { - if (fastcmp(name, sprnames[spr])) - { - i = spr; - break; - } - } - if (i == NUMSPRITES) + INT32 spr = R_GetSpriteNumByName(name); + if (spr == NUMSPRITES) { char *check; i = strtol(name, &check, 10); if (check == name || *check != '\0') return luaL_error(L, "unknown sprite name %s", name); } + i = spr; } else i = luaL_checkinteger(L, 1); diff --git a/src/r_picformats.c b/src/r_picformats.c index a75f15baf..d71657021 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1592,16 +1592,9 @@ static void R_ParseSpriteInfo(boolean spr2) if (!spr2) { - for (i = 0; i <= NUMSPRITES; i++) - { - if (i == NUMSPRITES) - I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); - if (!strcmp(newSpriteName, sprnames[i])) - { - sprnum = i; - break; - } - } + sprnum = R_GetSpriteNumByName(newSpriteName); + if (sprnum == NUMSPRITES) + I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); } else { From de8a4bb3e147d99640ad3ba2afd40d90cc96233d Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 17:21:35 +0100 Subject: [PATCH 15/37] Fix compiler warnings --- src/deh_lua.c | 2 +- src/deh_soc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 3d6d8b455..0d5f48ce1 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -62,7 +62,7 @@ static inline int lib_freeslot(lua_State *L) spritenum_t j; if (strlen(word) > MAXSPRITENAME) - return luaL_error(L, "Sprite name is longer than %d characters\n", strlen(word)); + return luaL_error(L, "Sprite name is longer than %s characters\n", sizeu1(strlen(word))); for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++) { diff --git a/src/deh_soc.c b/src/deh_soc.c index 269598459..6e4c087d5 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -441,7 +441,7 @@ void readfreeslots(MYFILE *f) else if (fastcmp(type, "SPR")) { if (strlen(word) > MAXSPRITENAME) - I_Error("Sprite name is longer than %d characters\n", strlen(word)); + I_Error("Sprite name is longer than %s characters\n", sizeu1(strlen(word))); for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { From a0c253f81e2a1a102be95409629748c82fc658bd Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 17:49:34 +0100 Subject: [PATCH 16/37] Fix invalid syntax --- src/r_things.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 4e60e913f..d21f9465e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -340,15 +340,17 @@ static void CheckFrame(const char *sprname) break; default: - // must have all 8/16 frames - UINT8 rotation = ((spriteframe->rotate & SRF_3DGE) ? 16 : 8); - while (rotation--) { - // we test the patch lump, or the id lump whatever - // if it was not loaded the two are LUMPERROR - if (spriteframe->lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (1-%c mode)", - sprname, frame, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); + // must have all 8/16 frames + UINT8 rotation = ((spriteframe->rotate & SRF_3DGE) ? 16 : 8); + while (rotation--) + { + // we test the patch lump, or the id lump whatever + // if it was not loaded the two are LUMPERROR + if (spriteframe->lumppat[rotation] == LUMPERROR) + I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (1-%c mode)", + sprname, frame, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); + } } break; } From 9b6c642345e67bbdf6cc790c70182f5b7edeb2eb Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 18:13:43 +0100 Subject: [PATCH 17/37] Fix infinite loop --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index d21f9465e..795f7cb5c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -317,7 +317,7 @@ static boolean GetFramesAndRotationsFromLongLumpName( // Some checks to help development static void CheckFrame(const char *sprname) { - for (UINT8 frame = 0; frame < maxframe; frame++) + for (UINT32 frame = 0; frame < maxframe; frame++) { spriteframe_t *spriteframe = &sprtemp[frame]; From dc3436df78046343bfe8f6448a9e7f06c396b347 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 18:54:10 +0100 Subject: [PATCH 18/37] Fix compiler warnings --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 795f7cb5c..53d54765e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -627,7 +627,7 @@ void R_AddSpriteDefs(UINT16 wadnum) AddLongSpriteDefs(wadnum, &spritesadded, &framesadded); nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); - CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, framesadded, sizeu1(spritesadded)); + CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu1(spritesadded)); } // From 737156659252c2ed6adc20bfd4eaa0e4b959b7d4 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 19:35:56 +0100 Subject: [PATCH 19/37] Fix error message for too long sprite names --- src/deh_lua.c | 2 +- src/deh_soc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 0d5f48ce1..64fb52fc7 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -62,7 +62,7 @@ static inline int lib_freeslot(lua_State *L) spritenum_t j; if (strlen(word) > MAXSPRITENAME) - return luaL_error(L, "Sprite name is longer than %s characters\n", sizeu1(strlen(word))); + return luaL_error(L, "Sprite name is longer than %d characters\n", MAXSPRITENAME); for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++) { diff --git a/src/deh_soc.c b/src/deh_soc.c index 6e4c087d5..d1643fd4e 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -441,7 +441,7 @@ void readfreeslots(MYFILE *f) else if (fastcmp(type, "SPR")) { if (strlen(word) > MAXSPRITENAME) - I_Error("Sprite name is longer than %s characters\n", sizeu1(strlen(word))); + I_Error("Sprite name is longer than %d characters\n", MAXSPRITENAME); for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { From 4ebda932bb784c24a728c5d6a91e384d5c4f6261 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 16 Mar 2024 19:36:18 +0100 Subject: [PATCH 20/37] Cleanup --- src/r_things.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 53d54765e..64f40c62e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -137,9 +137,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging INT32 r; - lumpnum_t lumppat = wad; - lumppat <<= 16; - lumppat += lump; + lumpnum_t lumppat = (wad << 16) + lump; if (maxframe ==(size_t)-1 || frame > maxframe) maxframe = frame; From 761a97292783b0f25ca7ab988c7a29a6145afb6e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 17 Mar 2024 00:27:19 +0100 Subject: [PATCH 21/37] Fix R_AddSingleSpriteDef for short sprite names --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 64f40c62e..ba3bf736a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -400,7 +400,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 { // For long sprites, the startlump-endlump range only includes // relevant lumps, so no check needed in that case - if (longname || !memcmp(lumpinfo[l].name, sprname, 4)) + if (longname || (strlen(sprname) == 4 && !memcmp(lumpinfo[l].name, sprname, 4))) { INT16 width, height; INT16 topoffset, leftoffset; From 0f6f6afb447f895cb6a8dbb721f0fc08c81199b6 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 17 Mar 2024 00:28:25 +0100 Subject: [PATCH 22/37] Fix sprite and frame addition logging --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index ba3bf736a..d317c0bd8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -625,7 +625,7 @@ void R_AddSpriteDefs(UINT16 wadnum) AddLongSpriteDefs(wadnum, &spritesadded, &framesadded); nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); - CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu1(spritesadded)); + CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu2(spritesadded)); } // From f6cb5d563cce3cf4576ffdc5f50dfe352b249c8b Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 17 Mar 2024 00:40:29 +0100 Subject: [PATCH 23/37] Only log sprite and frame additions when at least one was added --- src/r_things.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index d317c0bd8..bda754dba 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -624,8 +624,11 @@ void R_AddSpriteDefs(UINT16 wadnum) AddShortSpriteDefs(wadnum, &spritesadded, &framesadded); AddLongSpriteDefs(wadnum, &spritesadded, &framesadded); - nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); - CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu2(spritesadded)); + if (spritesadded || framesadded) + { + nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); + CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu2(spritesadded)); + } } // From 0e57d70b95dd9f035d8eb261d38689d9901090a5 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 17 Mar 2024 00:41:38 +0100 Subject: [PATCH 24/37] Automatically mirror long sprites for missing rotations --- src/r_things.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index bda754dba..5c4698e5d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -312,6 +312,38 @@ static boolean GetFramesAndRotationsFromLongLumpName( return true; } +static UINT8 GetOppositeRotation(UINT8 rotation, UINT8 flags) +{ + if (flags & ~SRF_3DMASK) + I_Error("GetOppositeRotation: rotation type not supported"); + + UINT8 numrotations = (flags == SRF_3D) ? 8 : 16; + return (rotation == 1) ? 1 : numrotations + 2 - rotation; +} + +static void MirrorMissingRotations(void) +{ + for (UINT32 framenum = 0; framenum < maxframe; framenum++) + { + spriteframe_t *frame = &sprtemp[framenum]; + + if (!(frame->rotate & SRF_3DMASK)) + continue; + + UINT8 numrotations = frame->rotate == SRF_3D ? 8 : 16; + + for (UINT8 rotation = 1; rotation <= numrotations; rotation++) + { + if (frame->lumppat[rotation - 1] != LUMPERROR) + continue; + + UINT8 baserotation = GetOppositeRotation(rotation, frame->rotate); + UINT32 lumpnum = frame->lumppat[baserotation - 1]; + R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation], framenum, rotation, 1); + } + } +} + // Some checks to help development static void CheckFrame(const char *sprname) { @@ -484,6 +516,9 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 maxframe++; + if (longname) + MirrorMissingRotations(); + CheckFrame(sprname); // allocate space for the frames present and copy sprtemp to it From 49fa45039e7bc3f1964269363c2f770a4fa71ff6 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 20 Mar 2024 18:06:19 +0100 Subject: [PATCH 25/37] Fix error report when some frames are missing --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 5c4698e5d..534ce7368 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -327,7 +327,7 @@ static void MirrorMissingRotations(void) { spriteframe_t *frame = &sprtemp[framenum]; - if (!(frame->rotate & SRF_3DMASK)) + if (frame->rotate == SRF_NONE || !(frame->rotate & SRF_3DMASK)) continue; UINT8 numrotations = frame->rotate == SRF_3D ? 8 : 16; From d00c6a8ab9ec3b9ed890106cb1b10162d3a8bb14 Mon Sep 17 00:00:00 2001 From: Hanicef Date: Wed, 20 Mar 2024 22:49:12 +0100 Subject: [PATCH 26/37] Fix softlock on old special stages when running out of time due to being hit --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 406f4af22..83b2e7c8b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3640,7 +3640,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (player->nightstime > 5*TICRATE) player->nightstime -= 5*TICRATE; else - player->nightstime = 0; + player->nightstime = 1; } P_DoPlayerPain(player, inflictor, source); From 95457b8fe0f18e97e4de77098ce79a985ca66764 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 21 Mar 2024 11:03:05 -0400 Subject: [PATCH 27/37] Fix stringop-truncation warnings for Debian Bookworm builds --- src/filesrch.c | 2 +- src/s_sound.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 6429b6fa2..944e8447f 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -1185,7 +1185,7 @@ boolean preparefilemenu(boolean samedepth) { if (!filenamebuf[i][0]) { - strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH); + strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH-1); filenamebuf[i][MAX_WADPATH - 1] = '\0'; nameonly(filenamebuf[i]); } diff --git a/src/s_sound.c b/src/s_sound.c index aa049899f..5155b90e8 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2494,11 +2494,11 @@ static void Command_Tunes_f(void) track = (UINT16)atoi(COM_Argv(2))-1; strncpy(mapmusname, tunearg, 7); + mapmusname[6] = 0; if (argc > 4) position = (UINT32)atoi(COM_Argv(4)); - mapmusname[6] = 0; mapmusflags = (track & MUSIC_TRACKMASK); mapmusposition = position; From dfecbe87b8e987faf037bb90006ab10614099d62 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 21 Mar 2024 19:30:45 +0100 Subject: [PATCH 28/37] Fix FreeBSD build error --- src/p_inter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 6e96a9508..e73cd1fce 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1365,8 +1365,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSEXTRATIME: - boolean eligible = player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)); - if ((player->bot && player->bot != BOT_MPAI) || !eligible) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)))) return; if (!G_IsSpecialStage(gamemap)) { @@ -1378,7 +1377,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && eligible) + if (playeringame[i] && (player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)))) { players[i].nightstime += special->info->speed; players[i].startedtime += special->info->speed; From 6b4dac747837b6c4f32464aad16100c12eeed38d Mon Sep 17 00:00:00 2001 From: Logan Aerl Arias Date: Sat, 23 Mar 2024 04:50:19 +0000 Subject: [PATCH 29/37] replace CPM with vcpkg --- .gitignore | 1 + CMakeLists.txt | 96 +- CMakePresets.json | 257 ++- cmake/CPM.cmake | 21 - cmake/Modules/FindGME.cmake | 33 - cmake/Modules/FindOPENMPT.cmake | 33 - cmake/Modules/Findlibgme.cmake | 38 + cmake/Modules/Findlibopenmpt.cmake | 37 + cmake/Modules/Findminiupnpc.cmake | 39 + cmake/PatchFile.cmake | 30 + cmake/Toolchains/mingw-w64-i686.cmake | 16 + cmake/Toolchains/mingw-w64-x86_64.cmake | 16 + .../include/{ => miniupnpc}/igd_desc_parse.h | 0 .../include/{ => miniupnpc}/miniupnpc.h | 0 .../{ => miniupnpc}/miniupnpc_declspec.h | 0 .../include/{ => miniupnpc}/miniupnpctypes.h | 0 .../include/{ => miniupnpc}/miniwget.h | 0 .../{ => miniupnpc}/portlistingparse.h | 0 .../include/{ => miniupnpc}/upnpcommands.h | 0 .../include/{ => miniupnpc}/upnpdev.h | 0 .../include/{ => miniupnpc}/upnperrors.h | 0 .../include/{ => miniupnpc}/upnpreplyparse.h | 0 src/CMakeLists.txt | 74 +- src/netcode/i_tcp.c | 14 +- src/sdl/CMakeLists.txt | 240 ++- src/sdl/i_system.c | 2 +- src/tests/CMakeLists.txt | 3 - src/tests/boolcompat.cpp | 8 - ...00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch | 26 + thirdparty/CMakeLists.txt | 23 +- thirdparty/Ccache.cmake | 15 + thirdparty/cpm-libgme.cmake | 16 - thirdparty/cpm-png.cmake | 69 - thirdparty/cpm-sdl2-mixer.cmake | 22 - thirdparty/cpm-sdl2.cmake | 28 - thirdparty/cpm-zlib.cmake | 18 - thirdparty/{cpm-curl.cmake => curl.cmake} | 39 +- thirdparty/libapng.cmake | 38 + .../{cpm-openmpt.cmake => libopenmpt.cmake} | 60 +- thirdparty/libpng-1.6.40-apng.patch | 1728 +++++++++++++++++ thirdparty/openmpt_svn_version.h | 10 - thirdparty/sdl2-mixer-ext.cmake | 39 + thirdparty/sdl2.cmake | 61 + thirdparty/vcpkg-overlays/.placeholder | 0 thirdparty/zlib.cmake | 36 + vcpkg-configuration.json | 6 + vcpkg.json | 85 + 47 files changed, 2859 insertions(+), 418 deletions(-) delete mode 100644 cmake/CPM.cmake delete mode 100644 cmake/Modules/FindGME.cmake delete mode 100644 cmake/Modules/FindOPENMPT.cmake create mode 100644 cmake/Modules/Findlibgme.cmake create mode 100644 cmake/Modules/Findlibopenmpt.cmake create mode 100644 cmake/Modules/Findminiupnpc.cmake create mode 100644 cmake/PatchFile.cmake create mode 100644 cmake/Toolchains/mingw-w64-i686.cmake create mode 100644 cmake/Toolchains/mingw-w64-x86_64.cmake rename libs/miniupnpc/include/{ => miniupnpc}/igd_desc_parse.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/miniupnpc.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/miniupnpc_declspec.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/miniupnpctypes.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/miniwget.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/portlistingparse.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/upnpcommands.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/upnpdev.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/upnperrors.h (100%) rename libs/miniupnpc/include/{ => miniupnpc}/upnpreplyparse.h (100%) delete mode 100644 src/tests/CMakeLists.txt delete mode 100644 src/tests/boolcompat.cpp create mode 100644 thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch create mode 100644 thirdparty/Ccache.cmake delete mode 100644 thirdparty/cpm-libgme.cmake delete mode 100644 thirdparty/cpm-png.cmake delete mode 100644 thirdparty/cpm-sdl2-mixer.cmake delete mode 100644 thirdparty/cpm-sdl2.cmake delete mode 100644 thirdparty/cpm-zlib.cmake rename thirdparty/{cpm-curl.cmake => curl.cmake} (55%) create mode 100644 thirdparty/libapng.cmake rename thirdparty/{cpm-openmpt.cmake => libopenmpt.cmake} (82%) create mode 100644 thirdparty/libpng-1.6.40-apng.patch delete mode 100644 thirdparty/openmpt_svn_version.h create mode 100644 thirdparty/sdl2-mixer-ext.cmake create mode 100644 thirdparty/sdl2.cmake create mode 100644 thirdparty/vcpkg-overlays/.placeholder create mode 100644 thirdparty/zlib.cmake create mode 100644 vcpkg-configuration.json create mode 100644 vcpkg.json diff --git a/.gitignore b/.gitignore index 4ba05f7ca..a3d823fa2 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ Win32_LIB_ASM_Release /CMakeUserPresets.json /out /objs/VC10 +/thirdparty/vcpkg-overlays diff --git a/CMakeLists.txt b/CMakeLists.txt index 358e62cc4..3b08a9fac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,6 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") include(CMakeDependentOption) -include(cmake/CPM.cmake) file(STRINGS src/version.h SRB2_VERSION) string(REGEX MATCH "[0-9]+\\.[0-9.]+" SRB2_VERSION ${SRB2_VERSION}) @@ -46,28 +45,23 @@ SET(CPACK_OUTPUT_FILE_PREFIX package) include(CPack) # Options - -if("${CMAKE_SYSTEM_NAME}" MATCHES Linux) - set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT ON) +if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) + if(DEFINED VCPKG_TARGET_TRIPLET) + set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT ON) + else() + set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF) + endif() else() - set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF) + set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT ON) endif() # Clang tidy options will be ignored if CMAKE__CLANG_TIDY are set. option(SRB2_CONFIG_ENABLE_CLANG_TIDY_C "Enable default clang-tidy check configuration for C" OFF) option(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX "Enable default clang-tidy check configuration for C++" OFF) option( - SRB2_CONFIG_SYSTEM_LIBRARIES - "Link dependencies using CMake's find_package and do not use internal builds" - ${SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT} -) -option(SRB2_CONFIG_ENABLE_TESTS "Build the test suite" ON) -# This option isn't recommended for distribution builds and probably won't work (yet). -cmake_dependent_option( - SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES - "Use dynamic libraries when compiling internal dependencies" - OFF "NOT SRB2_CONFIG_SYSTEM_LIBRARIES" - OFF + SRB2_CONFIG_STATIC_STDLIB + "Link static version of standard library. All dependencies must also be static" + ON ) option(SRB2_CONFIG_HWRENDER "Enable hardware render (OpenGL) support" ON) option(SRB2_CONFIG_USE_GME "Enable GME playback support" OFF) @@ -82,64 +76,28 @@ option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF) option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF) set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.") -if(SRB2_CONFIG_ENABLE_TESTS) - # https://github.com/catchorg/Catch2 - CPMAddPackage( - NAME Catch2 - VERSION 3.4.0 - GITHUB_REPOSITORY catchorg/Catch2 - OPTIONS - "CATCH_INSTALL_DOCS OFF" - ) - list(APPEND CMAKE_MODULE_PATH "${Catch2_SOURCE_DIR}/extras") - include(CTest) - include(Catch) - add_executable(srb2tests) - # To add tests, use target_sources to add individual test files to the target in subdirs. - target_link_libraries(srb2tests PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) - target_compile_features(srb2tests PRIVATE c_std_11 cxx_std_17) - catch_discover_tests(srb2tests) -endif() - -# Enable CCache -# (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options) -if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows) - option(USE_CCACHE "Enable ccache support" OFF) - - if(USE_CCACHE) - find_program(CCACHE_TOOL_PATH ccache) - if(CCACHE_TOOL_PATH) - set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) - set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) - else() - message(WARNING "USE_CCACHE was set but ccache is not found (set CCACHE_TOOL_PATH)") - endif() - endif() -else() - CPMAddPackage( - NAME Ccache.cmake - GITHUB_REPOSITORY TheLartians/Ccache.cmake - VERSION 1.2 - ) -endif() - # Dependencies add_subdirectory(thirdparty) -if("${SRB2_CONFIG_SYSTEM_LIBRARIES}") - find_package(ZLIB REQUIRED) - find_package(PNG REQUIRED) - find_package(SDL2 REQUIRED) - find_package(SDL2_mixer REQUIRED) - find_package(CURL REQUIRED) - find_package(OPENMPT REQUIRED) - - # libgme defaults to "Nuked" YM2612 emulator, which is - # very SLOW. The system library probably uses the - # default so just always build it. - #find_package(GME REQUIRED) +if(SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) + set(SRB2_INTERNAL_LIBRARY_TYPE SHARED) + set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES OFF) +else() + set(SRB2_INTERNAL_LIBRARY_TYPE STATIC) + set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES ON) endif() + +find_package(ZLIB REQUIRED) +find_package(PNG REQUIRED) +find_package(CURL REQUIRED) +find_package(libopenmpt QUIET) +if("${SRB2_CONFIG_USE_GME}") + find_package(libgme QUIET) +endif() +find_package(miniupnpc QUIET) + + if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) message(FATAL_ERROR "In-source builds will bring you a world of pain. Please make a separate directory to invoke CMake from.") endif() diff --git a/CMakePresets.json b/CMakePresets.json index effea7260..8cb95d797 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -2,26 +2,263 @@ "version": 3, "configurePresets": [ { - "name": "default", - "description": "Build using default generator", - "binaryDir": "build", + "name": "__debug", + "hidden": true, "cacheVariables": { + "SRB2_CONFIG_DEV_BUILD": "ON", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "__develop", + "hidden": true, + "cacheVariables": { + "CMAKE_C_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "SRB2_CONFIG_DEV_BUILD": "ON", "CMAKE_BUILD_TYPE": "RelWithDebInfo" } }, { - "name": "debug", - "description": "Build for development (no optimizations)", - "inherits": "default", + "name": "__release", + "hidden": true, "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" + "CMAKE_C_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "SRB2_CONFIG_DEV_BUILD": "OFF", + "CMAKE_BUILD_TYPE": "RelWithDebInfo" } + }, + { + "name": "__testers", + "hidden": true, + "cacheVariables": { + "CMAKE_C_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "SRB2_CONFIG_DEV_BUILD": "ON", + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "SRB2_CONFIG_TESTERS": "ON" + } + }, + { + "name": "__ninja", + "hidden": true, + "generator": "Ninja", + "cacheVariables": { + "CMAKE_COLOR_DIAGNOSTICS": "ON" + } + }, + { + "name": "__vcpkg-toolchain", + "hidden": true, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + } + }, + { + "name": "__compiler-mingw-w64-i686", + "hidden": true, + "cacheVariables": { + "CMAKE_C_COMPILER": "i686-w64-mingw32-gcc", + "CMAKE_CXX_COMPILER": "i686-w64-mingw32-g++" + } + }, + { + "name": "__mingw-dynamic", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x86-mingw-dynamic" + } + }, + { + "name": "__mingw-static", + "hidden": true, + "cacheVariables": { + "VCPKG_HOST_TRIPLET": "x86-mingw-static", + "VCPKG_TARGET_TRIPLET": "x86-mingw-static" + } + }, + { + "name": "__osx_x64", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-osx" + } + }, + { + "name": "__osx_arm64", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm64-osx" + } + }, + + { + "name": "ninja-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja"] + }, + { + "name": "ninja-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja"] + }, + { + "name": "ninja-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja"] + }, + { + "name": "ninja-testers", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__testers", "__ninja"] + }, + + { + "name": "ninja-vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja", "__vcpkg-toolchain"] + }, + { + "name": "ninja-vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja", "__vcpkg-toolchain"] + }, + { + "name": "ninja-vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja", "__vcpkg-toolchain"] + }, + { + "name": "ninja-vcpkg-testers", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__testers", "__ninja", "__vcpkg-toolchain"] + }, + + { + "name": "ninja-x86_mingw_static_vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + { + "name": "ninja-x86_mingw_static_vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + { + "name": "ninja-x86_mingw_static_vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + { + "name": "ninja-x86_mingw_static_vcpkg-testers", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__testers", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + + { + "name": "ninja-x64_osx_vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja", "__vcpkg-toolchain", "__osx_x64"] + }, + { + "name": "ninja-x64_osx_vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja", "__vcpkg-toolchain", "__osx_x64"] + }, + { + "name": "ninja-x64_osx_vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja", "__vcpkg-toolchain", "__osx_x64"] + }, + + { + "name": "ninja-arm64_osx_vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja", "__vcpkg-toolchain", "__osx_arm64"] + }, + { + "name": "ninja-arm64_osx_vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja", "__vcpkg-toolchain", "__osx_arm64"] + }, + { + "name": "ninja-arm64_osx_vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja", "__vcpkg-toolchain", "__osx_arm64"] } ], + "buildPresets": [ { - "name": "default", - "configurePreset": "default" + "name": "ninja-debug", + "configurePreset": "ninja-debug" + }, + { + "name": "ninja-develop", + "configurePreset": "ninja-develop" + }, + { + "name": "ninja-release", + "configurePreset": "ninja-release" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-debug", + "configurePreset": "ninja-x86_mingw_static_vcpkg-debug" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-develop", + "configurePreset": "ninja-x86_mingw_static_vcpkg-develop" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-release", + "configurePreset": "ninja-x86_mingw_static_vcpkg-release" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-testers", + "configurePreset": "ninja-x86_mingw_static_vcpkg-testers" + }, + { + "name": "ninja-x64_osx_vcpkg-debug", + "configurePreset": "ninja-x64_osx_vcpkg-debug" + }, + { + "name": "ninja-x64_osx_vcpkg-develop", + "configurePreset": "ninja-x64_osx_vcpkg-develop" + }, + { + "name": "ninja-x64_osx_vcpkg-release", + "configurePreset": "ninja-x64_osx_vcpkg-release" + }, + { + "name": "ninja-arm64_osx_vcpkg-debug", + "configurePreset": "ninja-arm64_osx_vcpkg-debug" + }, + { + "name": "ninja-arm64_osx_vcpkg-develop", + "configurePreset": "ninja-arm64_osx_vcpkg-develop" + }, + { + "name": "ninja-arm64_osx_vcpkg-release", + "configurePreset": "ninja-arm64_osx_vcpkg-release" } ] -} +} \ No newline at end of file diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake deleted file mode 100644 index fba27d2fe..000000000 --- a/cmake/CPM.cmake +++ /dev/null @@ -1,21 +0,0 @@ -set(CPM_DOWNLOAD_VERSION 0.38.7) - -if(CPM_SOURCE_CACHE) - set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -elseif(DEFINED ENV{CPM_SOURCE_CACHE}) - set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -else() - set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -endif() - -# Expand relative path. This is important if the provided path contains a tilde (~) -get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) -if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) - message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") - file(DOWNLOAD - https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake - ${CPM_DOWNLOAD_LOCATION} - ) -endif() - -include(${CPM_DOWNLOAD_LOCATION}) diff --git a/cmake/Modules/FindGME.cmake b/cmake/Modules/FindGME.cmake deleted file mode 100644 index 3af0a94be..000000000 --- a/cmake/Modules/FindGME.cmake +++ /dev/null @@ -1,33 +0,0 @@ -include(LibFindMacros) - -libfind_pkg_check_modules(GME_PKGCONF GME) - -find_path(GME_INCLUDE_DIR - NAMES gme.h - PATHS - ${GME_PKGCONF_INCLUDE_DIRS} - "/usr/include/gme" - "/usr/local/include/gme" -) - -find_library(GME_LIBRARY - NAMES gme - PATHS - ${GME_PKGCONF_LIBRARY_DIRS} - "/usr/lib" - "/usr/local/lib" -) - -set(GME_PROCESS_INCLUDES GME_INCLUDE_DIR) -set(GME_PROCESS_LIBS GME_LIBRARY) -libfind_process(GME) - -if(GME_FOUND AND NOT TARGET gme) - add_library(gme UNKNOWN IMPORTED) - set_target_properties( - gme - PROPERTIES - IMPORTED_LOCATION "${GME_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${GME_INCLUDE_DIR}" - ) -endif() diff --git a/cmake/Modules/FindOPENMPT.cmake b/cmake/Modules/FindOPENMPT.cmake deleted file mode 100644 index 7e5b2d5a3..000000000 --- a/cmake/Modules/FindOPENMPT.cmake +++ /dev/null @@ -1,33 +0,0 @@ -include(LibFindMacros) - -libfind_pkg_check_modules(OPENMPT_PKGCONF OPENMPT) - -find_path(OPENMPT_INCLUDE_DIR - NAMES libopenmpt.h - PATHS - ${OPENMPT_PKGCONF_INCLUDE_DIRS} - "/usr/include/libopenmpt" - "/usr/local/include/libopenmpt" -) - -find_library(OPENMPT_LIBRARY - NAMES openmpt - PATHS - ${OPENMPT_PKGCONF_LIBRARY_DIRS} - "/usr/lib" - "/usr/local/lib" -) - -set(OPENMPT_PROCESS_INCLUDES OPENMPT_INCLUDE_DIR) -set(OPENMPT_PROCESS_LIBS OPENMPT_LIBRARY) -libfind_process(OPENMPT) - -if(OPENMPT_FOUND AND NOT TARGET openmpt) - add_library(openmpt UNKNOWN IMPORTED) - set_target_properties( - openmpt - PROPERTIES - IMPORTED_LOCATION "${OPENMPT_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${OPENMPT_INCLUDE_DIR}" - ) -endif() diff --git a/cmake/Modules/Findlibgme.cmake b/cmake/Modules/Findlibgme.cmake new file mode 100644 index 000000000..6b693a7fd --- /dev/null +++ b/cmake/Modules/Findlibgme.cmake @@ -0,0 +1,38 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libgme_PKGCONF gme libgme) + +find_path(libgme_INCLUDE_DIR + NAMES gme.h + PATHS + ${libgme_PKGCONF_INCLUDE_DIRS} + "/usr/include" + "/usr/local/include" + PATH_SUFFIXES + gme +) + +find_library(libgme_LIBRARY + NAMES gme + PATHS + ${libgme_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(libgme + REQUIRED_VARS libgme_LIBRARY libgme_INCLUDE_DIR) + +if(libgme_FOUND AND NOT TARGET gme) + add_library(gme UNKNOWN IMPORTED) + set_target_properties( + gme + PROPERTIES + IMPORTED_LOCATION "${libgme_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${libgme_INCLUDE_DIR}" + ) + add_library(gme::gme ALIAS gme) +endif() + +mark_as_advanced(libgme_LIBRARY libgme_INCLUDE_DIR) diff --git a/cmake/Modules/Findlibopenmpt.cmake b/cmake/Modules/Findlibopenmpt.cmake new file mode 100644 index 000000000..d7de22134 --- /dev/null +++ b/cmake/Modules/Findlibopenmpt.cmake @@ -0,0 +1,37 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libopenmpt_PKGCONF openmpt) + +find_path(libopenmpt_INCLUDE_DIR + NAMES libopenmpt.h + PATHS + ${libopenmpt_PKGCONF_INCLUDE_DIRS} + "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/libopenmpt" + "/usr/include/libopenmpt" + "/usr/local/include/libopenmpt" +) + +find_library(libopenmpt_LIBRARY + NAMES openmpt + PATHS + ${libopenmpt_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(libopenmpt + REQUIRED_VARS libopenmpt_LIBRARY libopenmpt_INCLUDE_DIR) + +if(libopenmpt_FOUND AND NOT TARGET openmpt) + add_library(openmpt UNKNOWN IMPORTED) + set_target_properties( + openmpt + PROPERTIES + IMPORTED_LOCATION "${libopenmpt_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${libopenmpt_INCLUDE_DIR}" + ) + add_library(libopenmpt::libopenmpt ALIAS openmpt) +endif() + +mark_as_advanced(libopenmpt_LIBRARY libopenmpt_INCLUDE_DIR) diff --git a/cmake/Modules/Findminiupnpc.cmake b/cmake/Modules/Findminiupnpc.cmake new file mode 100644 index 000000000..f4931ad83 --- /dev/null +++ b/cmake/Modules/Findminiupnpc.cmake @@ -0,0 +1,39 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libminiupnpc_PKGCONF miniupnpc libminiupnpc) + +find_path(libminiupnpc_INCLUDE_DIR + NAMES miniupnpc.h + PATHS + ${libminiupnpc_PKGCONF_INCLUDE_DIRS} + "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include" + "/usr/include" + "/usr/local/include" + PATH_SUFFIXES + miniupnpc +) + +find_library(libminiupnpc_LIBRARY + NAMES miniupnpc + PATHS + ${libminiupnpc_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(miniupnpc + REQUIRED_VARS libminiupnpc_LIBRARY libminiupnpc_INCLUDE_DIR) + +if(miniupnpc_FOUND AND NOT TARGET miniupnpc) + add_library(miniupnpc UNKNOWN IMPORTED) + set_target_properties( + miniupnpc + PROPERTIES + IMPORTED_LOCATION "${libminiupnpc_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${libminiupnpc_INCLUDE_DIR}" + ) + add_library(miniupnpc::miniupnpc ALIAS miniupnpc) +endif() + +mark_as_advanced(libminiupnpc_LIBRARY libminiupnpc_INCLUDE_DIR) diff --git a/cmake/PatchFile.cmake b/cmake/PatchFile.cmake new file mode 100644 index 000000000..f80da3434 --- /dev/null +++ b/cmake/PatchFile.cmake @@ -0,0 +1,30 @@ +# use GNU Patch from any platform + +if(WIN32) + # prioritize Git Patch on Windows as other Patches may be very old and incompatible. + find_package(Git) + if(Git_FOUND) + get_filename_component(GIT_DIR ${GIT_EXECUTABLE} DIRECTORY) + get_filename_component(GIT_DIR ${GIT_DIR} DIRECTORY) + endif() +endif() + +find_program(PATCH +NAMES patch +HINTS ${GIT_DIR} +PATH_SUFFIXES usr/bin +) + +if(NOT PATCH) + message(FATAL_ERROR "Did not find GNU Patch") +endif() + +execute_process(COMMAND ${PATCH} ${in_file} --input=${patch_file} --output=${out_file} --ignore-whitespace +TIMEOUT 15 +COMMAND_ECHO STDOUT +RESULT_VARIABLE ret +) + +if(NOT ret EQUAL 0) + message(FATAL_ERROR "Failed to apply patch ${patch_file} to ${in_file} with ${PATCH}") +endif() \ No newline at end of file diff --git a/cmake/Toolchains/mingw-w64-i686.cmake b/cmake/Toolchains/mingw-w64-i686.cmake new file mode 100644 index 000000000..6b327291d --- /dev/null +++ b/cmake/Toolchains/mingw-w64-i686.cmake @@ -0,0 +1,16 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX i686-w64-mingw32) + +# cross compilers to use for C, C++ and Fortran +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) + +# modify default behavior of FIND_XXX() commands +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/cmake/Toolchains/mingw-w64-x86_64.cmake b/cmake/Toolchains/mingw-w64-x86_64.cmake new file mode 100644 index 000000000..2f22e13d8 --- /dev/null +++ b/cmake/Toolchains/mingw-w64-x86_64.cmake @@ -0,0 +1,16 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) + +# cross compilers to use for C, C++ and Fortran +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) + +# modify default behavior of FIND_XXX() commands +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/libs/miniupnpc/include/igd_desc_parse.h b/libs/miniupnpc/include/miniupnpc/igd_desc_parse.h similarity index 100% rename from libs/miniupnpc/include/igd_desc_parse.h rename to libs/miniupnpc/include/miniupnpc/igd_desc_parse.h diff --git a/libs/miniupnpc/include/miniupnpc.h b/libs/miniupnpc/include/miniupnpc/miniupnpc.h similarity index 100% rename from libs/miniupnpc/include/miniupnpc.h rename to libs/miniupnpc/include/miniupnpc/miniupnpc.h diff --git a/libs/miniupnpc/include/miniupnpc_declspec.h b/libs/miniupnpc/include/miniupnpc/miniupnpc_declspec.h similarity index 100% rename from libs/miniupnpc/include/miniupnpc_declspec.h rename to libs/miniupnpc/include/miniupnpc/miniupnpc_declspec.h diff --git a/libs/miniupnpc/include/miniupnpctypes.h b/libs/miniupnpc/include/miniupnpc/miniupnpctypes.h similarity index 100% rename from libs/miniupnpc/include/miniupnpctypes.h rename to libs/miniupnpc/include/miniupnpc/miniupnpctypes.h diff --git a/libs/miniupnpc/include/miniwget.h b/libs/miniupnpc/include/miniupnpc/miniwget.h similarity index 100% rename from libs/miniupnpc/include/miniwget.h rename to libs/miniupnpc/include/miniupnpc/miniwget.h diff --git a/libs/miniupnpc/include/portlistingparse.h b/libs/miniupnpc/include/miniupnpc/portlistingparse.h similarity index 100% rename from libs/miniupnpc/include/portlistingparse.h rename to libs/miniupnpc/include/miniupnpc/portlistingparse.h diff --git a/libs/miniupnpc/include/upnpcommands.h b/libs/miniupnpc/include/miniupnpc/upnpcommands.h similarity index 100% rename from libs/miniupnpc/include/upnpcommands.h rename to libs/miniupnpc/include/miniupnpc/upnpcommands.h diff --git a/libs/miniupnpc/include/upnpdev.h b/libs/miniupnpc/include/miniupnpc/upnpdev.h similarity index 100% rename from libs/miniupnpc/include/upnpdev.h rename to libs/miniupnpc/include/miniupnpc/upnpdev.h diff --git a/libs/miniupnpc/include/upnperrors.h b/libs/miniupnpc/include/miniupnpc/upnperrors.h similarity index 100% rename from libs/miniupnpc/include/upnperrors.h rename to libs/miniupnpc/include/miniupnpc/upnperrors.h diff --git a/libs/miniupnpc/include/upnpreplyparse.h b/libs/miniupnpc/include/miniupnpc/upnpreplyparse.h similarity index 100% rename from libs/miniupnpc/include/upnpreplyparse.h rename to libs/miniupnpc/include/miniupnpc/upnpreplyparse.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 486f4e913..20caecf7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -134,10 +134,13 @@ add_dependencies(SRB2SDL2 _SRB2_reconf) if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows") target_link_options(SRB2SDL2 PRIVATE "-Wl,--disable-dynamicbase") - if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}") + if("${SRB2_CONFIG_STATIC_STDLIB}") # On MinGW with internal libraries, link the standard library statically target_link_options(SRB2SDL2 PRIVATE "-static") endif() + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + target_link_options(SRB2SDL2 PRIVATE "-Wl,--large-address-aware") + endif() endif() target_compile_features(SRB2SDL2 PRIVATE c_std_11 cxx_std_17) @@ -182,12 +185,7 @@ if("${SRB2_CONFIG_USE_GME}") endif() endif() -target_link_libraries(SRB2SDL2 PRIVATE openmpt) -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_OPENMPT) - -target_link_libraries(SRB2SDL2 PRIVATE ZLIB::ZLIB PNG::PNG CURL::libcurl) -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_ZLIB -DHAVE_PNG -DHAVE_CURL -D_LARGEFILE64_SOURCE) -target_sources(SRB2SDL2 PRIVATE apng.c) +target_compile_definitions(SRB2SDL2 PRIVATE -D_LARGEFILE64_SOURCE) set(SRB2_HAVE_THREADS ON) target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) @@ -403,8 +401,66 @@ if(SRB2_CONFIG_PROFILEMODE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") endif() add_subdirectory(sdl) -if(SRB2_CONFIG_ENABLE_TESTS) - add_subdirectory(tests) + +if(TARGET ZLIB::ZLIB) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_ZLIB) + message(STATUS "Zlib Found") +else() + message(STATUS "No Zlib Found") +endif() + +if(TARGET PNG::PNG) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_PNG) + target_sources(SRB2SDL2 PRIVATE apng.c ${libapng_HEADER}) + target_include_directories(SRB2SDL2 PRIVATE ${libapng_INCLUDE_DIRS} ${libpng_BINARY_DIR}) + #message(STATUS "libpng inc DIRS at ${libapng_INCLUDE_DIRS}") + #message(STATUS "libpng bin DIRS at ${libpng_BINARY_DIR}") + #message(STATUS "png.h at ${libapng_HEADER}") + message(STATUS "libpng Found") +else() + message(STATUS "No libpng Found") +endif() + +if(TARGET PNG::PNG AND TARGET ZLIB::ZLIB) +#libpng links zlib too? +target_link_libraries(SRB2SDL2 PRIVATE PNG::PNG) +endif() + +if(NOT TARGET PNG::PNG AND TARGET ZLIB::ZLIB) +#got no libpng? we need zlib +target_link_libraries(SRB2SDL2 PRIVATE ZLIB::ZLIB) +endif() + +if(TARGET gme::gme) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_GME) + target_link_libraries(SRB2SDL2 PRIVATE gme::gme) + message(STATUS "libgme Found") +else() + message(STATUS "No libgme Found") +endif() + +if(TARGET libopenmpt::libopenmpt) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_OPENMPT) + target_link_libraries(SRB2SDL2 PRIVATE libopenmpt::libopenmpt) + message(STATUS "libopenmpt Found") +else() + message(STATUS "No libopenmpt Found") +endif() + +if(TARGET CURL::libcurl) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_CURL) + target_link_libraries(SRB2SDL2 PRIVATE CURL::libcurl) + message(STATUS "libcurl Found") +else() + message(STATUS "No libcurl Found") +endif() + +if(TARGET miniupnpc::miniupnpc) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MINIUPNPC) + target_link_libraries(SRB2SDL2 PRIVATE miniupnpc::miniupnpc) + message(STATUS "miniupnpc Found") +else() + message(STATUS "No miniupnpc Found") endif() # strip debug symbols into separate file when using gcc. diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 0148c485a..6a50f440b 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -114,16 +114,10 @@ typedef union } mysockaddr_t; #ifdef HAVE_MINIUPNPC - #ifdef MINIUPNP_STATICLIB - #include "miniwget.h" - #include "miniupnpc.h" - #include "upnpcommands.h" - #else - #include "miniupnpc/miniwget.h" - #include "miniupnpc/miniupnpc.h" - #include "miniupnpc/upnpcommands.h" - #endif - static boolean UPNP_support = true; + #include "miniupnpc/miniwget.h" + #include "miniupnpc/miniupnpc.h" + #include "miniupnpc/upnpcommands.h" + static boolean UPNP_support = true; #endif // HAVE_MINIUPNC #define MAXBANS 100 diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index 5aca04d12..ee48fa2b1 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -1,7 +1,6 @@ # Declare SDL2 interface sources target_sources(SRB2SDL2 PRIVATE - mixer_sound.c ogl_sdl.c i_threads.c i_net.c @@ -13,6 +12,161 @@ target_sources(SRB2SDL2 PRIVATE hwsym_sdl.c ) +# Compatibility flag with later versions of GCC +# We should really fix our code to not need this +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) +endif() + +# Yes we know we use insecure CRT functions... +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + target_compile_definitions(SRB2SDL2 PRIVATE -D_CRT_SECURE_NO_WARNINGS) +endif() + +# Compiler warnings configuration +target_compile_options(SRB2SDL2 PRIVATE + # Using generator expressions to handle per-language compile options + + # C, GNU + # This is a direct translation from versions.mk + $<$,$>: + -Wall + -Wno-trigraphs + -W # Was controlled by RELAXWARNINGS + -pedantic + -Wpedantic + -Wfloat-equal + -Wundef + -Wpointer-arith + -Wbad-function-cast + -Wcast-qual + -Wcast-align # Was controlled by NOCASTALIGNWARN + -Wwrite-strings + -Wsign-compare + -Wmissing-prototypes + -Wmissing-declarations + -Wmissing-noreturn + -Winline + -Wformat-y2k + -Wformat-security + + $<$,2.9.5>: + -Wno-div-by-zero + -Wendif-labels + -Wdisabled-optimization + > + + $<$,4.0.0>: + -Wold-style-definition + -Wmissing-field-initializers + > + + $<$,4.1.0>: + -Wshadow + > + + $<$,4.3.0>: + -funit-at-a-time + -Wlogical-op + > + + $<$,4.5.0>: + -Wlogical-op + -Wno-error=array-bounds + > + + $<$,4.6.0>: + -Wno-suggest-attribute=noreturn + -Wno-error=suggest-attribute=noreturn + -Werror=vla + > + + $<$,5.4.0>: + -Wno-logical-op + -Wno-error=logical-op + > + + $<$,6.1.0>: + -Wno-tautological-compare + -Wno-error=tautological-compare + > + + $<$,7.1.0>: + -Wno-error=format-overflow=2 + -Wimplicit-fallthrough=4 + > + + $<$,8.1.0>: + -Wno-error=format-overflow + -Wno-error=stringop-truncation + -Wno-error=stringop-overflow + -Wno-format-overflow + -Wno-stringop-truncation + -Wno-stringop-overflow + -Wno-error=multistatement-macros + > + + $<$,9.1.0>: + -Wno-error=address-of-packed-member + > + > + + # C, Clang and Apple Clang + $<$,$,$>>: + -Wall + -Wno-absolute-value + -Wno-trigraphs + -Wno-error=non-literal-null-conversion + -Wno-error=constant-conversion + -Wno-unused-but-set-variable + -Wno-error=unused-but-set-variable + -Wno-shorten-64-to-32 + > + + # C, MSVC + $<$,$>: + # All warnings at and before Visual Studio 2019 RTM + # https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warnings-by-compiler-version?view=msvc-170 + /Wv:19.20.27004.0 + > + + # C++, GNU, Clang and Apple Clang + $<$,$,$,$>>: + -Wall + -Wno-unused-function + -Wno-unused-but-set-variable + -Wno-unused-private-field + > + + # C++, MSVC + $<$,$>: + /Wv:19.20.27004.0 + > + + # GNU + $<$: + -fmax-errors=5 + > +) +if(SRB2_CONFIG_ERRORMODE) + target_compile_options(SRB2SDL2 PRIVATE + $<$,$,$>: + -Werror + > + + $<$: + /WX + > + ) +endif() + +# Link warnings configuration +target_link_options(SRB2SDL2 PRIVATE + $<$: + # -Wl,--as-needed - Was controlled by NOLDWARNING + > +) + if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) target_sources(SRB2SDL2 PRIVATE ../win32/win_dbg.c @@ -62,12 +216,6 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2main) endif() -if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}") - target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2-static SDL2_mixer::SDL2_mixer-static) -else() - target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2 SDL2_mixer::SDL2_mixer) -endif() - if("${CMAKE_SYSTEM_NAME}" MATCHES Linux) target_link_libraries(SRB2SDL2 PRIVATE m rt) endif() @@ -81,8 +229,84 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) ) endif() -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) +find_package(SDL2 CONFIG REQUIRED) +find_package(SDL2 REQUIRED) +if(TARGET SDL2main) + target_link_libraries(SRB2SDL2 PRIVATE SDL2main) +endif() target_compile_definitions(SRB2SDL2 PRIVATE -DDIRECTFULLSCREEN -DHAVE_SDL) +target_include_directories(SRB2SDL2 PRIVATE ${SDL2_INCLUDE_DIR}) + +find_package(SDL2_mixer_ext CONFIG QUIET) +find_package(SDL2_mixer_ext QUIET) +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static OR TARGET SDL2_mixer_ext OR TARGET SDL2_mixer_ext_Static) + if(NOT TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static AND TARGET SDL2_mixer_ext_Static) + add_library(SDL2_mixer_ext::SDL2_mixer_ext_Static ALIAS SDL2_mixer_ext_Static) + endif() + if(NOT TARGET SDL2_mixer_ext::SDL2_mixer_ext AND TARGET SDL2_mixer_ext) + add_library(SDL2_mixer_ext::SDL2_mixer_ext ALIAS SDL2_mixer_ext) + endif() + if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + if(TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer_ext::SDL2_mixer_ext_Static) + else() + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer_ext::SDL2_mixer_ext) + endif() + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DHAVE_MIXERX -DSOUND=SOUND_MIXER) + endif() +endif() + +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + message(STATUS "SDL2_mixer_ext found, skipping SDL2_mixer") +else() + message(STATUS "SDL2_mixer_ext not found, going to try SDL2_mixer") + find_package(SDL2_mixer CONFIG QUIET) + find_package(SDL2_mixer QUIET) + if(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static OR TARGET SDL2_mixer OR TARGET SDL2_mixer_Static) + if(NOT TARGET SDL2_mixer::SDL2_mixer-static AND TARGET SDL2_mixer_Static) + add_library(SDL2_mixer::SDL2_mixer-static ALIAS SDL2_mixer_Static) + endif() + if(NOT TARGET SDL2_mixer::SDL2_mixer AND TARGET SDL2_mixer) + add_library(SDL2_mixer::SDL2_mixer ALIAS SDL2_mixer) + endif() + if(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static) + if(TARGET SDL2_mixer::SDL2_mixer-static) + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer::SDL2_mixer-static) + else() + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer::SDL2_mixer) + endif() + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) + endif() + endif() +endif() + +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static OR TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static) + target_sources(SRB2SDL2 PRIVATE mixer_sound.c) + target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2) +else() + target_sources(SRB2SDL2 PRIVATE sdl_sound.c) + target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2) +endif() + +if(TARGET SDL2::SDL2) + message(STATUS "SDL2 Found") +else() + message(STATUS "no SDL2 Found") +endif() + +if(TARGET SDL2::SDL2main) + message(STATUS "SDL2main Found") +else() + message(STATUS "No SDL2main Found") +endif() + +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + message(STATUS "SDL2_mixer_ext Found") +elseif(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static) + message(STATUS "SDL2_mixer found") +else() + message(STATUS "no SDL2_mixer_ext or SDL2_mixer Found") +endif() #### Installation #### if("${CMAKE_SYSTEM_NAME}" MATCHES Darwin) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 9f0fa0250..2d051888d 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2305,7 +2305,7 @@ void I_SleepDuration(precise_t duration) int status; do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); while (status == EINTR); -#else +#elif defined (MIN_SLEEP_DURATION_MS) UINT64 precision = I_GetPrecisePrecision(); INT32 sleepvalue = cv_sleep.value; UINT64 delaygranularity; diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt deleted file mode 100644 index 28c4ce492..000000000 --- a/src/tests/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(srb2tests PRIVATE - boolcompat.cpp -) diff --git a/src/tests/boolcompat.cpp b/src/tests/boolcompat.cpp deleted file mode 100644 index fee40cd36..000000000 --- a/src/tests/boolcompat.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#include "../doomtype.h" - -TEST_CASE("C++ bool is convertible to doomtype.h boolean") { - REQUIRE(static_cast(true) == 1); - REQUIRE(static_cast(false) == 0); -} diff --git a/thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch b/thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch new file mode 100644 index 000000000..0e7f55f1b --- /dev/null +++ b/thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch @@ -0,0 +1,26 @@ +--- a/CMakeLists.txt 2023-11-22 22:42:53.000000000 -0500 ++++ b/CMakeLists.txt 2024-02-15 18:46:57.852076200 -0500 +@@ -45,6 +45,7 @@ + + option(SDL_MIXER_X_STATIC "Build static library of SDL Mixer X" ${SDL_MIXER_X_STATIC_ENABLED_BY_DEFAULT}) + option(SDL_MIXER_X_SHARED "Build shared library of SDL Mixer X" ${SDL_MIXER_X_SHARED_ENABLED_BY_DEFAULT}) ++ option(SDL_MIXER_X_DISABLE_INSTALL "Disable install of SDL Mixer X" OFF) + else() + set(SDL_MIXER_X_STATIC ON) + set(SDL_MIXER_X_SHARED OFF) +@@ -475,6 +476,7 @@ + add_subdirectory(examples) + endif() + ++if(NOT SDL_MIXER_X_DISABLE_INSTALL) + if(SDL_MIXER_X_STATIC AND NOT BUILD_AS_VB6_BINDING) + install(TARGETS SDL2_mixer_ext_Static + EXPORT SDL2MixerExtStaticTargets +@@ -500,6 +502,7 @@ + NAMESPACE SDL2_mixer_ext:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2_mixer_ext") + endif() ++endif() + + + if(BUILD_AS_VB6_BINDING) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 19aa22c9b..5114cbe2c 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,23 +1,2 @@ -macro(export) -endmacro() -if(SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) - set(SRB2_INTERNAL_LIBRARY_TYPE SHARED) - set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES OFF) -else() - set(SRB2_INTERNAL_LIBRARY_TYPE STATIC) - set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES ON) -endif() - -if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") - include("cpm-sdl2.cmake") - include("cpm-sdl2-mixer.cmake") - include("cpm-zlib.cmake") - include("cpm-png.cmake") - include("cpm-curl.cmake") - include("cpm-openmpt.cmake") -endif() - -if("${SRB2_CONFIG_USE_GME}") - include("cpm-libgme.cmake") -endif() +include("Ccache.cmake") diff --git a/thirdparty/Ccache.cmake b/thirdparty/Ccache.cmake new file mode 100644 index 000000000..6ca0d9fa0 --- /dev/null +++ b/thirdparty/Ccache.cmake @@ -0,0 +1,15 @@ +# Enable CCache +# (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options) +if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows) + option(USE_CCACHE "Enable ccache support" OFF) + + if(USE_CCACHE) + find_program(CCACHE_TOOL_PATH ccache) + if(CCACHE_TOOL_PATH) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) + else() + message(WARNING "USE_CCACHE was set but ccache is not found (set CCACHE_TOOL_PATH)") + endif() + endif() +endif() \ No newline at end of file diff --git a/thirdparty/cpm-libgme.cmake b/thirdparty/cpm-libgme.cmake deleted file mode 100644 index f15bc3b31..000000000 --- a/thirdparty/cpm-libgme.cmake +++ /dev/null @@ -1,16 +0,0 @@ -CPMAddPackage( - NAME libgme - VERSION 0.6.3 - URL "https://bitbucket.org/mpyne/game-music-emu/get/e76bdc0cb916e79aa540290e6edd0c445879d3ba.zip" - EXCLUDE_FROM_ALL ON - OPTIONS - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "ENABLE_UBSAN OFF" - "GME_YM2612_EMU MAME" -) - -if(libgme_ADDED) - target_compile_features(gme PRIVATE cxx_std_11) - # libgme's CMakeLists.txt already links this - #target_link_libraries(gme PRIVATE ZLIB::ZLIB) -endif() diff --git a/thirdparty/cpm-png.cmake b/thirdparty/cpm-png.cmake deleted file mode 100644 index f16ac037b..000000000 --- a/thirdparty/cpm-png.cmake +++ /dev/null @@ -1,69 +0,0 @@ -CPMAddPackage( - NAME png - VERSION 1.6.38 - URL "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.38.zip" - # png cmake build is broken on msys/mingw32 - DOWNLOAD_ONLY YES -) - -if(png_ADDED) - # Since png's cmake build is broken, we're going to create a target manually - set( - PNG_SOURCES - png.h - pngconf.h - pngpriv.h - pngdebug.h - pnginfo.h - pngstruct.h - png.c - pngerror.c - pngget.c - pngmem.c - pngpread.c - pngread.c - pngrio.c - pngrtran.c - pngrutil.c - pngset.c - pngtrans.c - pngwio.c - pngwrite.c - pngwtran.c - pngwutil.c - ) - list(TRANSFORM PNG_SOURCES PREPEND "${png_SOURCE_DIR}/") - - add_custom_command( - OUTPUT "${png_BINARY_DIR}/include/png.h" "${png_BINARY_DIR}/include/pngconf.h" - COMMAND ${CMAKE_COMMAND} -E copy "${png_SOURCE_DIR}/png.h" "${png_SOURCE_DIR}/pngconf.h" "${png_BINARY_DIR}/include" - DEPENDS "${png_SOURCE_DIR}/png.h" "${png_SOURCE_DIR}/pngconf.h" - VERBATIM - ) - add_custom_command( - OUTPUT "${png_BINARY_DIR}/include/pnglibconf.h" - COMMAND ${CMAKE_COMMAND} -E copy "${png_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt" "${png_BINARY_DIR}/include/pnglibconf.h" - DEPENDS "${png_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt" - VERBATIM - ) - list( - APPEND PNG_SOURCES - "${png_BINARY_DIR}/include/png.h" - "${png_BINARY_DIR}/include/pngconf.h" - "${png_BINARY_DIR}/include/pnglibconf.h" - ) - add_library(png "${SRB2_INTERNAL_LIBRARY_TYPE}" ${PNG_SOURCES}) - - # Disable ARM NEON since having it automatic breaks libpng external build on clang for some reason - target_compile_definitions(png PRIVATE -DPNG_ARM_NEON_OPT=0) - - # The png includes need to be available to consumers - target_include_directories(png PUBLIC "${png_BINARY_DIR}/include") - - # ... and these also need to be present only for png build - target_include_directories(png PRIVATE "${ZLIB_SOURCE_DIR}") - target_include_directories(png PRIVATE "${ZLIB_BINARY_DIR}") - target_include_directories(png PRIVATE "${png_BINARY_DIR}") - target_link_libraries(png PRIVATE ZLIB::ZLIB) - add_library(PNG::PNG ALIAS png) -endif() diff --git a/thirdparty/cpm-sdl2-mixer.cmake b/thirdparty/cpm-sdl2-mixer.cmake deleted file mode 100644 index b7dfeae0d..000000000 --- a/thirdparty/cpm-sdl2-mixer.cmake +++ /dev/null @@ -1,22 +0,0 @@ -CPMAddPackage( - NAME SDL2_mixer - VERSION 2.6.2 - URL "https://github.com/libsdl-org/SDL_mixer/archive/refs/tags/release-2.6.2.zip" - EXCLUDE_FROM_ALL ON - OPTIONS - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL2MIXER_INSTALL OFF" - "SDL2MIXER_DEPS_SHARED OFF" - "SDL2MIXER_SAMPLES OFF" - "SDL2MIXER_VENDORED ON" - "SDL2MIXER_FLAC ON" - "SDL2MIXER_FLAC_LIBFLAC OFF" - "SDL2MIXER_FLAC_DRFLAC ON" - "SDL2MIXER_MOD OFF" - "SDL2MIXER_MP3 ON" - "SDL2MIXER_MP3_DRMP3 ON" - "SDL2MIXER_MIDI ON" - "SDL2MIXER_OPUS OFF" - "SDL2MIXER_VORBIS STB" - "SDL2MIXER_WAVE ON" -) diff --git a/thirdparty/cpm-sdl2.cmake b/thirdparty/cpm-sdl2.cmake deleted file mode 100644 index 0bb404e4c..000000000 --- a/thirdparty/cpm-sdl2.cmake +++ /dev/null @@ -1,28 +0,0 @@ -set( - internal_sdl2_options - - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL_SHARED ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL_STATIC ${NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL_TEST OFF" - "SDL2_DISABLE_INSTALL ON" -) - -if(${CMAKE_SYSTEM} MATCHES Windows) - list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") -endif() -if(${CMAKE_SYSTEM} MATCHES Darwin) - list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") -endif() -if(${CMAKE_SYSTEM} MATCHES Linux) - list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN ON") -endif() - -CPMAddPackage( - NAME SDL2 - VERSION 2.28.5 - GITHUB_REPOSITORY "libsdl-org/SDL" - GIT_TAG release-2.28.5 - EXCLUDE_FROM_ALL ON - OPTIONS ${internal_sdl2_options} -) diff --git a/thirdparty/cpm-zlib.cmake b/thirdparty/cpm-zlib.cmake deleted file mode 100644 index f0a2c33ae..000000000 --- a/thirdparty/cpm-zlib.cmake +++ /dev/null @@ -1,18 +0,0 @@ -CPMAddPackage( - NAME zlib - VERSION 1.3.1 - GITHUB_REPOSITORY "madler/zlib" - GIT_TAG v1.3.1 - EXCLUDE_FROM_ALL - OPTIONS - "ZLIB_BUILD_EXAMPLES OFF" -) - -if(zlib_ADDED) - if(SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) - add_library(ZLIB::ZLIB ALIAS zlib) - endif() - if(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) - add_library(ZLIB::ZLIB ALIAS zlibstatic) - endif() -endif() diff --git a/thirdparty/cpm-curl.cmake b/thirdparty/curl.cmake similarity index 55% rename from thirdparty/cpm-curl.cmake rename to thirdparty/curl.cmake index 3d8c6e61d..5c3aa26e3 100644 --- a/thirdparty/cpm-curl.cmake +++ b/thirdparty/curl.cmake @@ -1,8 +1,16 @@ +if(TARGET CURL::libcurl) + return() +endif() + +message(STATUS "Third-party: creating target 'CURL::libcurl'") + +set(CURL_ENABLE_EXPORT_TARGET OFF CACHE BOOL "" FORCE) + set( internal_curl_options "BUILD_CURL_EXE OFF" - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" + "BUILD_SHARED_LIBS OFF" "CURL_DISABLE_TESTS ON" "HTTP_ONLY ON" "CURL_DISABLE_CRYPTO_AUTH ON" @@ -26,10 +34,25 @@ if(${CMAKE_SYSTEM} MATCHES Linux) list(APPEND internal_curl_options "CURL_USE_OPENSSL ON") endif() -CPMAddPackage( - NAME curl - VERSION 7.86.0 - URL "https://github.com/curl/curl/archive/refs/tags/curl-7_86_0.zip" - EXCLUDE_FROM_ALL ON - OPTIONS ${internal_curl_options} -) +include(FetchContent) + +if (CURL_USE_THIRDPARTY) + FetchContent_Declare( + curl + VERSION 7.88.1 + GITHUB_REPOSITORY "curl/curl" + GIT_TAG curl-7_88_1 + EXCLUDE_FROM_ALL ON + OPTIONS ${internal_curl_options} + ) +else() + FetchContent_Declare( + curl + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/curl/" + EXCLUDE_FROM_ALL ON + OPTIONS ${internal_curl_options} + ) +endif() + +FetchContent_MakeAvailable(curl) + diff --git a/thirdparty/libapng.cmake b/thirdparty/libapng.cmake new file mode 100644 index 000000000..f4bc50ff1 --- /dev/null +++ b/thirdparty/libapng.cmake @@ -0,0 +1,38 @@ +if(TARGET libapng_static) + return() +endif() + +message(STATUS "Third-party: creating target 'libapng_static'") + +set(PNG_SHARED OFF CACHE BOOL "" FORCE) +set(PNG_BUILD_ZLIB ON CACHE BOOL "" FORCE) + +include(FetchContent) + + FetchContent_Declare( + libapng-local + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/libapng/" + EXCLUDE_FROM_ALL ON + DOWNLOAD_ONLY YES + OPTION + "PNG_SHARED OFF" + "PNG_EXECUTABLES OFF" + "PNG_TESTS OFF" + "PNG_BUILD_ZLIB ON" + ) + +FetchContent_MakeAvailable(libapng-local) + +#add_custom_command( +#OUTPUT ${libapng-local_BINARY_DIR}/CMakeLists.txt +#COMMAND ${CMAKE_COMMAND} +# -Din_file:FILEPATH=${libapng-locall_SOURCE_DIR}/CMakeLists.txt +# -Dpatch_file:FILEPATH=${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/00-libapng-ZLIB.patch +# -Dout_file:FILEPATH=${libapng-local_BINARY_DIR}/CMakeLists.txt +# -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/PatchFile.cmake +#DEPENDS ${libapng-local_SOURCE_DIR}/CMakeLists.txt +#) + +set(libapng_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/libapng" "${libapng_BINARY_DIR}" CACHE PATH "" FORCE) + +set(libapng_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/libapng/png.h" "${CMAKE_CURRENT_SOURCE_DIR}/libapng/pngconf.h" CACHE PATH "" FORCE) diff --git a/thirdparty/cpm-openmpt.cmake b/thirdparty/libopenmpt.cmake similarity index 82% rename from thirdparty/cpm-openmpt.cmake rename to thirdparty/libopenmpt.cmake index 01f7ff75f..256b4c406 100644 --- a/thirdparty/cpm-openmpt.cmake +++ b/thirdparty/libopenmpt.cmake @@ -1,13 +1,33 @@ -CPMAddPackage( - NAME openmpt - VERSION 0.4.30 - URL "https://github.com/OpenMPT/openmpt/archive/refs/tags/libopenmpt-0.4.30.zip" - DOWNLOAD_ONLY ON -) +if(TARGET libopenmpt) + #return() +endif() -if(openmpt_ADDED) +message(STATUS "Third-party: creating target 'libopenmpt'") + + +include(FetchContent) + +if (libopenmpt_USE_THIRDPARTY) + FetchContent_Declare( + libopenmpt-local + GITHUB_REPOSITORY openmpt + GIT_TAG libopenmpt-0.4.38 + version 0.4.38 + EXCLUDE_FROM_ALL ON + ) +else() + FetchContent_Declare( + libopenmpt-local + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/libopenmpt/" + EXCLUDE_FROM_ALL ON + ) +endif() + +FetchContent_MakeAvailable(libopenmpt) + +if(aaaa-libopenmpt-local_ADDED) set( - openmpt_SOURCES + libopenmpt-local_SOURCES # minimp3 # -DMPT_WITH_MINIMP3 @@ -264,26 +284,26 @@ if(openmpt_ADDED) libopenmpt/libopenmpt_impl.cpp libopenmpt/libopenmpt_ext_impl.cpp ) - list(TRANSFORM openmpt_SOURCES PREPEND "${openmpt_SOURCE_DIR}/") + list(TRANSFORM libopenmpt-local_SOURCES PREPEND "${libopenmpt-local_SOURCE_DIR}/") # -DLIBOPENMPT_BUILD configure_file("openmpt_svn_version.h" "svn_version.h") - add_library(openmpt "${SRB2_INTERNAL_LIBRARY_TYPE}" ${openmpt_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/svn_version.h) + add_library(libopenmpt STATIC ${libopenmpt-local_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/svn_version.h) if("${CMAKE_C_COMPILER_ID}" STREQUAL GNU OR "${CMAKE_C_COMPILER_ID}" STREQUAL Clang OR "${CMAKE_C_COMPILER_ID}" STREQUAL AppleClang) - target_compile_options(openmpt PRIVATE "-g0") + target_compile_options(libopenmpt PRIVATE "-g0") endif() if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND "${CMAKE_C_COMPILER_ID}" STREQUAL MSVC) - target_link_libraries(openmpt PRIVATE Rpcrt4) + target_link_libraries(libopenmpt PRIVATE Rpcrt4) endif() - target_compile_features(openmpt PRIVATE cxx_std_11) - target_compile_definitions(openmpt PRIVATE -DLIBOPENMPT_BUILD) + target_compile_features(libopenmpt PRIVATE cxx_std_11) + target_compile_definitions(libopenmpt PRIVATE -DLIBOPENMPT_BUILD) - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}/common") - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}/src") - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}/include") - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}") - target_include_directories(openmpt PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}/common") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}/src") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}/include") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}") + target_include_directories(libopenmpt PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") # I wish this wasn't necessary, but it is - target_include_directories(openmpt PUBLIC "${openmpt_SOURCE_DIR}") + target_include_directories(libopenmpt PUBLIC "${libopenmpt-local_SOURCE_DIR}") endif() diff --git a/thirdparty/libpng-1.6.40-apng.patch b/thirdparty/libpng-1.6.40-apng.patch new file mode 100644 index 000000000..c5b870004 --- /dev/null +++ b/thirdparty/libpng-1.6.40-apng.patch @@ -0,0 +1,1728 @@ +diff -Naru libpng-1.6.40.org/png.h libpng-1.6.40/png.h +--- libpng-1.6.40.org/png.h 2023-09-10 11:12:23.044481879 +0900 ++++ libpng-1.6.40/png.h 2023-09-10 11:08:58.964075833 +0900 +@@ -330,6 +330,10 @@ + # include "pnglibconf.h" + #endif + ++#define PNG_APNG_SUPPORTED ++#define PNG_READ_APNG_SUPPORTED ++#define PNG_WRITE_APNG_SUPPORTED ++ + #ifndef PNG_VERSION_INFO_ONLY + /* Machine specific configuration. */ + # include "pngconf.h" +@@ -425,6 +429,17 @@ + * See pngconf.h for base types that vary by machine/system + */ + ++#ifdef PNG_APNG_SUPPORTED ++/* dispose_op flags from inside fcTL */ ++#define PNG_DISPOSE_OP_NONE 0x00U ++#define PNG_DISPOSE_OP_BACKGROUND 0x01U ++#define PNG_DISPOSE_OP_PREVIOUS 0x02U ++ ++/* blend_op flags from inside fcTL */ ++#define PNG_BLEND_OP_SOURCE 0x00U ++#define PNG_BLEND_OP_OVER 0x01U ++#endif /* PNG_APNG_SUPPORTED */ ++ + /* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +@@ -746,6 +761,10 @@ + #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ + #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ + #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ ++#ifdef PNG_APNG_SUPPORTED ++#define PNG_INFO_acTL 0x20000U ++#define PNG_INFO_fcTL 0x40000U ++#endif + + /* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using +@@ -783,6 +802,10 @@ + #ifdef PNG_PROGRESSIVE_READ_SUPPORTED + typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); + typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); ++#ifdef PNG_APNG_SUPPORTED ++typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp, ++ png_uint_32)); ++#endif + + /* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the +@@ -3226,6 +3249,74 @@ + /******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ ++#ifdef PNG_APNG_SUPPORTED ++PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays)); ++ ++PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); ++ ++PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr, ++ png_infop info_ptr)); ++ ++PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr, ++ png_infop info_ptr)); ++ ++PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL, ++ (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, ++ png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset, ++ png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op, ++ png_byte *blend_op)); ++ ++PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL, ++ (png_structp png_ptr, png_infop info_ptr, png_uint_32 width, ++ png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op)); ++ ++PNG_EXPORT(256, png_uint_32, png_get_next_frame_width, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(257, png_uint_32, png_get_next_frame_height, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden, ++ (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden)); ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr, ++ png_infop info_ptr)); ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr, ++ png_progressive_frame_ptr frame_info_fn, ++ png_progressive_frame_ptr frame_end_fn)); ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr, ++ png_infop info_ptr, png_bytepp row_pointers, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op)); ++ ++PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr, ++ png_infop info_ptr)); ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++#endif /* PNG_APNG_SUPPORTED */ + + /* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. +@@ -3235,7 +3326,11 @@ + * one to use is one more than this.) + */ + #ifdef PNG_EXPORT_LAST_ORDINAL ++#ifdef PNG_APNG_SUPPORTED ++ PNG_EXPORT_LAST_ORDINAL(269); ++#else + PNG_EXPORT_LAST_ORDINAL(249); ++#endif /* PNG_APNG_SUPPORTED */ + #endif + + #ifdef __cplusplus +diff -Naru libpng-1.6.40.org/pngget.c libpng-1.6.40/pngget.c +--- libpng-1.6.40.org/pngget.c 2023-09-10 11:09:32.954139030 +0900 ++++ libpng-1.6.40/pngget.c 2023-09-10 11:08:58.922075757 +0900 +@@ -1257,4 +1257,166 @@ + # endif + #endif + ++#ifdef PNG_APNG_SUPPORTED ++png_uint_32 PNGAPI ++png_get_acTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 *num_frames, png_uint_32 *num_plays) ++{ ++ png_debug1(1, "in %s retrieval function", "acTL"); ++ ++ if (png_ptr != NULL && info_ptr != NULL && ++ (info_ptr->valid & PNG_INFO_acTL) && ++ num_frames != NULL && num_plays != NULL) ++ { ++ *num_frames = info_ptr->num_frames; ++ *num_plays = info_ptr->num_plays; ++ return (1); ++ } ++ ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_num_frames(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_num_frames()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->num_frames); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_num_plays(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_num_plays()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->num_plays); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 *width, png_uint_32 *height, ++ png_uint_32 *x_offset, png_uint_32 *y_offset, ++ png_uint_16 *delay_num, png_uint_16 *delay_den, ++ png_byte *dispose_op, png_byte *blend_op) ++{ ++ png_debug1(1, "in %s retrieval function", "fcTL"); ++ ++ if (png_ptr != NULL && info_ptr != NULL && ++ (info_ptr->valid & PNG_INFO_fcTL) && ++ width != NULL && height != NULL && ++ x_offset != NULL && y_offset != NULL && ++ delay_num != NULL && delay_den != NULL && ++ dispose_op != NULL && blend_op != NULL) ++ { ++ *width = info_ptr->next_frame_width; ++ *height = info_ptr->next_frame_height; ++ *x_offset = info_ptr->next_frame_x_offset; ++ *y_offset = info_ptr->next_frame_y_offset; ++ *delay_num = info_ptr->next_frame_delay_num; ++ *delay_den = info_ptr->next_frame_delay_den; ++ *dispose_op = info_ptr->next_frame_dispose_op; ++ *blend_op = info_ptr->next_frame_blend_op; ++ return (1); ++ } ++ ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_width()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_width); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_height()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_height); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_x_offset()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_x_offset); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_y_offset()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_y_offset); ++ return (0); ++} ++ ++png_uint_16 PNGAPI ++png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_delay_num()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_delay_num); ++ return (0); ++} ++ ++png_uint_16 PNGAPI ++png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_delay_den()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_delay_den); ++ return (0); ++} ++ ++png_byte PNGAPI ++png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_dispose_op()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_dispose_op); ++ return (0); ++} ++ ++png_byte PNGAPI ++png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_blend_op()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_blend_op); ++ return (0); ++} ++ ++png_byte PNGAPI ++png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_first_frame_is_hidden()"); ++ ++ if (png_ptr != NULL) ++ return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN); ++ ++ PNG_UNUSED(info_ptr) ++ ++ return 0; ++} ++#endif /* PNG_APNG_SUPPORTED */ + #endif /* READ || WRITE */ +diff -Naru libpng-1.6.40.org/pnginfo.h libpng-1.6.40/pnginfo.h +--- libpng-1.6.40.org/pnginfo.h 2022-11-24 08:37:51.507052183 +0900 ++++ libpng-1.6.40/pnginfo.h 2023-09-10 11:08:58.922075757 +0900 +@@ -263,5 +263,18 @@ + png_bytepp row_pointers; /* the image bits */ + #endif + ++#ifdef PNG_APNG_SUPPORTED ++ png_uint_32 num_frames; /* including default image */ ++ png_uint_32 num_plays; ++ png_uint_32 next_frame_width; ++ png_uint_32 next_frame_height; ++ png_uint_32 next_frame_x_offset; ++ png_uint_32 next_frame_y_offset; ++ png_uint_16 next_frame_delay_num; ++ png_uint_16 next_frame_delay_den; ++ png_byte next_frame_dispose_op; ++ png_byte next_frame_blend_op; ++#endif ++ + }; + #endif /* PNGINFO_H */ +diff -Naru libpng-1.6.40.org/pngpread.c libpng-1.6.40/pngpread.c +--- libpng-1.6.40.org/pngpread.c 2022-11-24 08:37:51.507052183 +0900 ++++ libpng-1.6.40/pngpread.c 2023-09-10 11:08:58.922075757 +0900 +@@ -195,6 +195,106 @@ + + chunk_name = png_ptr->chunk_name; + ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->num_frames_read > 0 && ++ png_ptr->num_frames_read < info_ptr->num_frames) ++ { ++ if (chunk_name == png_IDAT) ++ { ++ /* Discard trailing IDATs for the first frame */ ++ if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1) ++ png_error(png_ptr, "out of place IDAT"); ++ ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ else if (chunk_name == png_fdAT) ++ { ++ if (png_ptr->buffer_size < 4) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_ensure_sequence_number(png_ptr, 4); ++ ++ if (!(png_ptr->mode & PNG_HAVE_fcTL)) ++ { ++ /* Discard trailing fdATs for frames other than the first */ ++ if (png_ptr->num_frames_read < 2) ++ png_error(png_ptr, "out of place fdAT"); ++ ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ ++ else ++ { ++ /* frame data follows */ ++ png_ptr->idat_size = png_ptr->push_length - 4; ++ png_ptr->mode |= PNG_HAVE_IDAT; ++ png_ptr->process_mode = PNG_READ_IDAT_MODE; ++ ++ return; ++ } ++ } ++ ++ else if (chunk_name == png_fcTL) ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_read_reset(png_ptr); ++ png_ptr->mode &= ~PNG_HAVE_fcTL; ++ ++ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); ++ ++ if (!(png_ptr->mode & PNG_HAVE_fcTL)) ++ png_error(png_ptr, "missing required fcTL chunk"); ++ ++ png_read_reinit(png_ptr, info_ptr); ++ png_progressive_read_reset(png_ptr); ++ ++ if (png_ptr->frame_info_fn != NULL) ++ (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read); ++ ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ ++ return; ++ } ++ ++ else ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ png_warning(png_ptr, "Skipped (ignored) a chunk " ++ "between APNG chunks"); ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ ++ return; ++ } ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ + if (chunk_name == png_IDAT) + { + if ((png_ptr->mode & PNG_AFTER_IDAT) != 0) +@@ -261,6 +361,9 @@ + + else if (chunk_name == png_IDAT) + { ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_have_info(png_ptr, info_ptr); ++#endif + png_ptr->idat_size = png_ptr->push_length; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); +@@ -406,6 +509,30 @@ + png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + #endif ++#ifdef PNG_READ_APNG_SUPPORTED ++ else if (chunk_name == png_acTL) ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length); ++ } ++ ++ else if (chunk_name == png_fcTL) ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); ++ } ++ ++#endif /* PNG_READ_APNG_SUPPORTED */ + + else + { +@@ -539,7 +666,11 @@ + png_byte chunk_tag[4]; + + /* TODO: this code can be commoned up with the same code in push_read */ ++#ifdef PNG_READ_APNG_SUPPORTED ++ PNG_PUSH_SAVE_BUFFER_IF_LT(12) ++#else + PNG_PUSH_SAVE_BUFFER_IF_LT(8) ++#endif + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); +@@ -547,17 +678,64 @@ + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0) ++ { ++ if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) ++ { ++ png_ptr->process_mode = PNG_READ_CHUNK_MODE; ++ if (png_ptr->frame_end_fn != NULL) ++ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); ++ png_ptr->num_frames_read++; ++ return; ++ } ++ else ++ { ++ if (png_ptr->chunk_name == png_IEND) ++ png_error(png_ptr, "Not enough image data"); ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ png_warning(png_ptr, "Skipping (ignoring) a chunk between " ++ "APNG chunks"); ++ png_crc_finish(png_ptr, png_ptr->push_length); ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ } ++ else ++#endif ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0) ++#else + if (png_ptr->chunk_name != png_IDAT) ++#endif + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0) + png_error(png_ptr, "Not enough compressed data"); + ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->frame_end_fn != NULL) ++ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); ++ png_ptr->num_frames_read++; ++#endif ++ + return; + } + + png_ptr->idat_size = png_ptr->push_length; ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->num_frames_read > 0) ++ { ++ png_ensure_sequence_number(png_ptr, 4); ++ png_ptr->idat_size -= 4; ++ } ++#endif + } + + if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) +@@ -631,6 +809,15 @@ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + ++#ifdef PNG_READ_APNG_SUPPORTED ++ /* If the app is not APNG-aware, decode only the first frame */ ++ if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0) ++ { ++ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; ++ return; ++ } ++#endif ++ + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. +@@ -1085,6 +1272,18 @@ + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); + } + ++#ifdef PNG_READ_APNG_SUPPORTED ++void PNGAPI ++png_set_progressive_frame_fn(png_structp png_ptr, ++ png_progressive_frame_ptr frame_info_fn, ++ png_progressive_frame_ptr frame_end_fn) ++{ ++ png_ptr->frame_info_fn = frame_info_fn; ++ png_ptr->frame_end_fn = frame_end_fn; ++ png_ptr->apng_flags |= PNG_APNG_APP; ++} ++#endif ++ + png_voidp PNGAPI + png_get_progressive_ptr(png_const_structrp png_ptr) + { +diff -Naru libpng-1.6.40.org/pngpriv.h libpng-1.6.40/pngpriv.h +--- libpng-1.6.40.org/pngpriv.h 2023-09-10 11:09:32.954139030 +0900 ++++ libpng-1.6.40/pngpriv.h 2023-09-10 11:08:58.923075759 +0900 +@@ -628,6 +628,10 @@ + #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ + #define PNG_WROTE_eXIf 0x4000U + #define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ ++#ifdef PNG_APNG_SUPPORTED ++#define PNG_HAVE_acTL 0x10000U ++#define PNG_HAVE_fcTL 0x20000U ++#endif + + /* Flags for the transformations the PNG library does on the image data */ + #define PNG_BGR 0x0001U +@@ -864,6 +868,16 @@ + #define png_tRNS PNG_U32(116, 82, 78, 83) + #define png_zTXt PNG_U32(122, 84, 88, 116) + ++#ifdef PNG_APNG_SUPPORTED ++#define png_acTL PNG_U32( 97, 99, 84, 76) ++#define png_fcTL PNG_U32(102, 99, 84, 76) ++#define png_fdAT PNG_U32(102, 100, 65, 84) ++ ++/* For png_struct.apng_flags: */ ++#define PNG_FIRST_FRAME_HIDDEN 0x0001U ++#define PNG_APNG_APP 0x0002U ++#endif ++ + /* The following will work on (signed char*) strings, whereas the get_uint_32 + * macro will fail on top-bit-set values because of the sign extension. + */ +@@ -1635,6 +1649,47 @@ + */ + #endif + ++#ifdef PNG_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op), PNG_EMPTY); ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr, ++ png_infop info_ptr),PNG_EMPTY); ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY); ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr, ++ png_const_bytep data, png_size_t length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY); ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++#endif /* PNG_APNG_SUPPORTED */ ++ + /* Added at libpng version 1.4.0 */ + #ifdef PNG_COLORSPACE_SUPPORTED + /* These internal functions are for maintaining the colorspace structure within +diff -Naru libpng-1.6.40.org/pngread.c libpng-1.6.40/pngread.c +--- libpng-1.6.40.org/pngread.c 2022-11-24 08:37:51.508052181 +0900 ++++ libpng-1.6.40/pngread.c 2023-09-10 11:08:58.923075759 +0900 +@@ -161,6 +161,9 @@ + + else if (chunk_name == png_IDAT) + { ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_have_info(png_ptr, info_ptr); ++#endif + png_ptr->idat_size = length; + break; + } +@@ -255,6 +258,17 @@ + png_handle_iTXt(png_ptr, info_ptr, length); + #endif + ++#ifdef PNG_READ_APNG_SUPPORTED ++ else if (chunk_name == png_acTL) ++ png_handle_acTL(png_ptr, info_ptr, length); ++ ++ else if (chunk_name == png_fcTL) ++ png_handle_fcTL(png_ptr, info_ptr, length); ++ ++ else if (chunk_name == png_fdAT) ++ png_handle_fdAT(png_ptr, info_ptr, length); ++#endif ++ + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); +@@ -262,6 +276,72 @@ + } + #endif /* SEQUENTIAL_READ */ + ++#ifdef PNG_READ_APNG_SUPPORTED ++void PNGAPI ++png_read_frame_head(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */ ++ ++ png_debug(0, "Reading frame head"); ++ ++ if (!(png_ptr->mode & PNG_HAVE_acTL)) ++ png_error(png_ptr, "attempt to png_read_frame_head() but " ++ "no acTL present"); ++ ++ /* do nothing for the main IDAT */ ++ if (png_ptr->num_frames_read == 0) ++ return; ++ ++ png_read_reset(png_ptr); ++ png_ptr->flags &= ~PNG_FLAG_ROW_INIT; ++ png_ptr->mode &= ~PNG_HAVE_fcTL; ++ ++ have_chunk_after_DAT = 0; ++ for (;;) ++ { ++ png_uint_32 length = png_read_chunk_header(png_ptr); ++ ++ if (png_ptr->chunk_name == png_IDAT) ++ { ++ /* discard trailing IDATs for the first frame */ ++ if (have_chunk_after_DAT || png_ptr->num_frames_read > 1) ++ png_error(png_ptr, "png_read_frame_head(): out of place IDAT"); ++ png_crc_finish(png_ptr, length); ++ } ++ ++ else if (png_ptr->chunk_name == png_fcTL) ++ { ++ png_handle_fcTL(png_ptr, info_ptr, length); ++ have_chunk_after_DAT = 1; ++ } ++ ++ else if (png_ptr->chunk_name == png_fdAT) ++ { ++ png_ensure_sequence_number(png_ptr, length); ++ ++ /* discard trailing fdATs for frames other than the first */ ++ if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1) ++ png_crc_finish(png_ptr, length - 4); ++ else if(png_ptr->mode & PNG_HAVE_fcTL) ++ { ++ png_ptr->idat_size = length - 4; ++ png_ptr->mode |= PNG_HAVE_IDAT; ++ ++ break; ++ } ++ else ++ png_error(png_ptr, "png_read_frame_head(): out of place fdAT"); ++ } ++ else ++ { ++ png_warning(png_ptr, "Skipped (ignored) a chunk " ++ "between APNG chunks"); ++ png_crc_finish(png_ptr, length); ++ } ++ } ++} ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ + /* Optional call to update the users info_ptr structure */ + void PNGAPI + png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) +diff -Naru libpng-1.6.40.org/pngrutil.c libpng-1.6.40/pngrutil.c +--- libpng-1.6.40.org/pngrutil.c 2022-11-24 08:37:51.510052177 +0900 ++++ libpng-1.6.40/pngrutil.c 2023-09-10 11:08:58.923075759 +0900 +@@ -864,6 +864,11 @@ + filter_type = buf[11]; + interlace_type = buf[12]; + ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_ptr->first_frame_width = width; ++ png_ptr->first_frame_height = height; ++#endif ++ + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; +@@ -2858,6 +2863,179 @@ + } + #endif + ++#ifdef PNG_READ_APNG_SUPPORTED ++void /* PRIVATE */ ++png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++{ ++ png_byte data[8]; ++ png_uint_32 num_frames; ++ png_uint_32 num_plays; ++ png_uint_32 didSet; ++ ++ png_debug(1, "in png_handle_acTL"); ++ ++ if (!(png_ptr->mode & PNG_HAVE_IHDR)) ++ { ++ png_error(png_ptr, "Missing IHDR before acTL"); ++ } ++ else if (png_ptr->mode & PNG_HAVE_IDAT) ++ { ++ png_warning(png_ptr, "Invalid acTL after IDAT skipped"); ++ png_crc_finish(png_ptr, length); ++ return; ++ } ++ else if (png_ptr->mode & PNG_HAVE_acTL) ++ { ++ png_warning(png_ptr, "Duplicate acTL skipped"); ++ png_crc_finish(png_ptr, length); ++ return; ++ } ++ else if (length != 8) ++ { ++ png_warning(png_ptr, "acTL with invalid length skipped"); ++ png_crc_finish(png_ptr, length); ++ return; ++ } ++ ++ png_crc_read(png_ptr, data, 8); ++ png_crc_finish(png_ptr, 0); ++ ++ num_frames = png_get_uint_31(png_ptr, data); ++ num_plays = png_get_uint_31(png_ptr, data + 4); ++ ++ /* the set function will do error checking on num_frames */ ++ didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays); ++ if(didSet) ++ png_ptr->mode |= PNG_HAVE_acTL; ++} ++ ++void /* PRIVATE */ ++png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++{ ++ png_byte data[22]; ++ png_uint_32 width; ++ png_uint_32 height; ++ png_uint_32 x_offset; ++ png_uint_32 y_offset; ++ png_uint_16 delay_num; ++ png_uint_16 delay_den; ++ png_byte dispose_op; ++ png_byte blend_op; ++ ++ png_debug(1, "in png_handle_fcTL"); ++ ++ png_ensure_sequence_number(png_ptr, length); ++ ++ if (!(png_ptr->mode & PNG_HAVE_IHDR)) ++ { ++ png_error(png_ptr, "Missing IHDR before fcTL"); ++ } ++ else if (png_ptr->mode & PNG_HAVE_IDAT) ++ { ++ /* for any frames other then the first this message may be misleading, ++ * but correct. PNG_HAVE_IDAT is unset before the frame head is read ++ * i can't think of a better message */ ++ png_warning(png_ptr, "Invalid fcTL after IDAT skipped"); ++ png_crc_finish(png_ptr, length-4); ++ return; ++ } ++ else if (png_ptr->mode & PNG_HAVE_fcTL) ++ { ++ png_warning(png_ptr, "Duplicate fcTL within one frame skipped"); ++ png_crc_finish(png_ptr, length-4); ++ return; ++ } ++ else if (length != 26) ++ { ++ png_warning(png_ptr, "fcTL with invalid length skipped"); ++ png_crc_finish(png_ptr, length-4); ++ return; ++ } ++ ++ png_crc_read(png_ptr, data, 22); ++ png_crc_finish(png_ptr, 0); ++ ++ width = png_get_uint_31(png_ptr, data); ++ height = png_get_uint_31(png_ptr, data + 4); ++ x_offset = png_get_uint_31(png_ptr, data + 8); ++ y_offset = png_get_uint_31(png_ptr, data + 12); ++ delay_num = png_get_uint_16(data + 16); ++ delay_den = png_get_uint_16(data + 18); ++ dispose_op = data[20]; ++ blend_op = data[21]; ++ ++ if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) ++ { ++ png_warning(png_ptr, "fcTL for the first frame must have zero offset"); ++ return; ++ } ++ ++ if (info_ptr != NULL) ++ { ++ if (png_ptr->num_frames_read == 0 && ++ (width != info_ptr->width || height != info_ptr->height)) ++ { ++ png_warning(png_ptr, "size in first frame's fcTL must match " ++ "the size in IHDR"); ++ return; ++ } ++ ++ /* The set function will do more error checking */ ++ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, ++ x_offset, y_offset, delay_num, delay_den, ++ dispose_op, blend_op); ++ ++ png_read_reinit(png_ptr, info_ptr); ++ ++ png_ptr->mode |= PNG_HAVE_fcTL; ++ } ++} ++ ++void /* PRIVATE */ ++png_have_info(png_structp png_ptr, png_infop info_ptr) ++{ ++ if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) ++ { ++ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; ++ info_ptr->num_frames++; ++ } ++} ++ ++void /* PRIVATE */ ++png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++{ ++ png_ensure_sequence_number(png_ptr, length); ++ ++ /* This function is only called from png_read_end(), png_read_info(), ++ * and png_push_read_chunk() which means that: ++ * - the user doesn't want to read this frame ++ * - or this is an out-of-place fdAT ++ * in either case it is safe to ignore the chunk with a warning */ ++ png_warning(png_ptr, "ignoring fdAT chunk"); ++ png_crc_finish(png_ptr, length - 4); ++ PNG_UNUSED(info_ptr) ++} ++ ++void /* PRIVATE */ ++png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length) ++{ ++ png_byte data[4]; ++ png_uint_32 sequence_number; ++ ++ if (length < 4) ++ png_error(png_ptr, "invalid fcTL or fdAT chunk found"); ++ ++ png_crc_read(png_ptr, data, 4); ++ sequence_number = png_get_uint_31(png_ptr, data); ++ ++ if (sequence_number != png_ptr->next_seq_num) ++ png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence " ++ "number found"); ++ ++ png_ptr->next_seq_num++; ++} ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ + #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ + static int +@@ -4166,7 +4344,38 @@ + { + uInt avail_in; + png_bytep buffer; ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_uint_32 bytes_to_skip = 0; ++ ++ while (png_ptr->idat_size == 0 || bytes_to_skip != 0) ++ { ++ png_crc_finish(png_ptr, bytes_to_skip); ++ bytes_to_skip = 0; + ++ png_ptr->idat_size = png_read_chunk_header(png_ptr); ++ if (png_ptr->num_frames_read == 0) ++ { ++ if (png_ptr->chunk_name != png_IDAT) ++ png_error(png_ptr, "Not enough image data"); ++ } ++ else ++ { ++ if (png_ptr->chunk_name == png_IEND) ++ png_error(png_ptr, "Not enough image data"); ++ if (png_ptr->chunk_name != png_fdAT) ++ { ++ png_warning(png_ptr, "Skipped (ignored) a chunk " ++ "between APNG chunks"); ++ bytes_to_skip = png_ptr->idat_size; ++ continue; ++ } ++ ++ png_ensure_sequence_number(png_ptr, png_ptr->idat_size); ++ ++ png_ptr->idat_size -= 4; ++ } ++ } ++#else + while (png_ptr->idat_size == 0) + { + png_crc_finish(png_ptr, 0); +@@ -4178,7 +4387,7 @@ + if (png_ptr->chunk_name != png_IDAT) + png_error(png_ptr, "Not enough image data"); + } +- ++#endif /* PNG_READ_APNG_SUPPORTED */ + avail_in = png_ptr->IDAT_read_size; + + if (avail_in > png_ptr->idat_size) +@@ -4241,6 +4450,9 @@ + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_ptr->num_frames_read++; ++#endif + + if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0) + png_chunk_benign_error(png_ptr, "Extra compressed data"); +@@ -4678,4 +4890,80 @@ + + png_ptr->flags |= PNG_FLAG_ROW_INIT; + } ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++/* This function is to be called after the main IDAT set has been read and ++ * before a new IDAT is read. It resets some parts of png_ptr ++ * to make them usable by the read functions again */ ++void /* PRIVATE */ ++png_read_reset(png_structp png_ptr) ++{ ++ png_ptr->mode &= ~PNG_HAVE_IDAT; ++ png_ptr->mode &= ~PNG_AFTER_IDAT; ++ png_ptr->row_number = 0; ++ png_ptr->pass = 0; ++} ++ ++void /* PRIVATE */ ++png_read_reinit(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_ptr->width = info_ptr->next_frame_width; ++ png_ptr->height = info_ptr->next_frame_height; ++ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); ++ png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, ++ png_ptr->width); ++ if (png_ptr->prev_row) ++ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); ++} ++ ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++/* same as png_read_reset() but for the progressive reader */ ++void /* PRIVATE */ ++png_progressive_read_reset(png_structp png_ptr) ++{ ++#ifdef PNG_READ_INTERLACING_SUPPORTED ++ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ ++ ++ /* Start of interlace block */ ++ const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; ++ ++ /* Offset to next interlace block */ ++ const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; ++ ++ /* Start of interlace block in the y direction */ ++ const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; ++ ++ /* Offset to next interlace block in the y direction */ ++ const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; ++ ++ if (png_ptr->interlaced) ++ { ++ if (!(png_ptr->transformations & PNG_INTERLACE)) ++ png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - ++ png_pass_ystart[0]) / png_pass_yinc[0]; ++ else ++ png_ptr->num_rows = png_ptr->height; ++ ++ png_ptr->iwidth = (png_ptr->width + ++ png_pass_inc[png_ptr->pass] - 1 - ++ png_pass_start[png_ptr->pass]) / ++ png_pass_inc[png_ptr->pass]; ++ } ++ else ++#endif /* PNG_READ_INTERLACING_SUPPORTED */ ++ { ++ png_ptr->num_rows = png_ptr->height; ++ png_ptr->iwidth = png_ptr->width; ++ } ++ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED; ++ if (inflateReset(&(png_ptr->zstream)) != Z_OK) ++ png_error(png_ptr, "inflateReset failed"); ++ png_ptr->zstream.avail_in = 0; ++ png_ptr->zstream.next_in = 0; ++ png_ptr->zstream.next_out = png_ptr->row_buf; ++ png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth, ++ png_ptr->iwidth) + 1; ++} ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ ++#endif /* PNG_READ_APNG_SUPPORTED */ + #endif /* READ */ +diff -Naru libpng-1.6.40.org/pngset.c libpng-1.6.40/pngset.c +--- libpng-1.6.40.org/pngset.c 2023-09-10 11:09:32.954139030 +0900 ++++ libpng-1.6.40/pngset.c 2023-09-10 11:08:58.932075775 +0900 +@@ -280,6 +280,11 @@ + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); ++ ++#ifdef PNG_APNG_SUPPORTED ++ /* for non-animated png. this may be overwritten from an acTL chunk later */ ++ info_ptr->num_frames = 1; ++#endif + } + + #ifdef PNG_oFFs_SUPPORTED +@@ -1149,6 +1154,147 @@ + } + #endif /* sPLT */ + ++#ifdef PNG_APNG_SUPPORTED ++png_uint_32 PNGAPI ++png_set_acTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays) ++{ ++ png_debug1(1, "in %s storage function", "acTL"); ++ ++ if (png_ptr == NULL || info_ptr == NULL) ++ { ++ png_warning(png_ptr, ++ "Call to png_set_acTL() with NULL png_ptr " ++ "or info_ptr ignored"); ++ return (0); ++ } ++ if (num_frames == 0) ++ { ++ png_warning(png_ptr, ++ "Ignoring attempt to set acTL with num_frames zero"); ++ return (0); ++ } ++ if (num_frames > PNG_UINT_31_MAX) ++ { ++ png_warning(png_ptr, ++ "Ignoring attempt to set acTL with num_frames > 2^31-1"); ++ return (0); ++ } ++ if (num_plays > PNG_UINT_31_MAX) ++ { ++ png_warning(png_ptr, ++ "Ignoring attempt to set acTL with num_plays " ++ "> 2^31-1"); ++ return (0); ++ } ++ ++ info_ptr->num_frames = num_frames; ++ info_ptr->num_plays = num_plays; ++ ++ info_ptr->valid |= PNG_INFO_acTL; ++ ++ return (1); ++} ++ ++/* delay_num and delay_den can hold any 16-bit values including zero */ ++png_uint_32 PNGAPI ++png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op) ++{ ++ png_debug1(1, "in %s storage function", "fcTL"); ++ ++ if (png_ptr == NULL || info_ptr == NULL) ++ { ++ png_warning(png_ptr, ++ "Call to png_set_fcTL() with NULL png_ptr or info_ptr " ++ "ignored"); ++ return (0); ++ } ++ ++ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ if (blend_op == PNG_BLEND_OP_OVER) ++ { ++ if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) && ++ !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) ++ { ++ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless " ++ "and wasteful for opaque images, ignored"); ++ blend_op = PNG_BLEND_OP_SOURCE; ++ } ++ } ++ ++ info_ptr->next_frame_width = width; ++ info_ptr->next_frame_height = height; ++ info_ptr->next_frame_x_offset = x_offset; ++ info_ptr->next_frame_y_offset = y_offset; ++ info_ptr->next_frame_delay_num = delay_num; ++ info_ptr->next_frame_delay_den = delay_den; ++ info_ptr->next_frame_dispose_op = dispose_op; ++ info_ptr->next_frame_blend_op = blend_op; ++ ++ info_ptr->valid |= PNG_INFO_fcTL; ++ ++ return (1); ++} ++ ++void /* PRIVATE */ ++png_ensure_fcTL_is_valid(png_structp png_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op) ++{ ++ if (width == 0 || width > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid width in fcTL (> 2^31-1)"); ++ if (height == 0 || height > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid height in fcTL (> 2^31-1)"); ++ if (x_offset > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)"); ++ if (y_offset > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)"); ++ if (width + x_offset > png_ptr->first_frame_width || ++ height + y_offset > png_ptr->first_frame_height) ++ png_error(png_ptr, "dimensions of a frame are greater than" ++ "the ones in IHDR"); ++ ++ if (dispose_op != PNG_DISPOSE_OP_NONE && ++ dispose_op != PNG_DISPOSE_OP_BACKGROUND && ++ dispose_op != PNG_DISPOSE_OP_PREVIOUS) ++ png_error(png_ptr, "invalid dispose_op in fcTL"); ++ ++ if (blend_op != PNG_BLEND_OP_SOURCE && ++ blend_op != PNG_BLEND_OP_OVER) ++ png_error(png_ptr, "invalid blend_op in fcTL"); ++ ++ PNG_UNUSED(delay_num) ++ PNG_UNUSED(delay_den) ++} ++ ++png_uint_32 PNGAPI ++png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr, ++ png_byte is_hidden) ++{ ++ png_debug(1, "in png_first_frame_is_hidden()"); ++ ++ if (png_ptr == NULL) ++ return 0; ++ ++ if (is_hidden) ++ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; ++ else ++ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; ++ ++ PNG_UNUSED(info_ptr) ++ ++ return 1; ++} ++#endif /* PNG_APNG_SUPPORTED */ ++ + #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + static png_byte + check_location(png_const_structrp png_ptr, int location) +diff -Naru libpng-1.6.40.org/pngstruct.h libpng-1.6.40/pngstruct.h +--- libpng-1.6.40.org/pngstruct.h 2022-11-24 08:37:51.510052177 +0900 ++++ libpng-1.6.40/pngstruct.h 2023-09-10 11:08:58.924075760 +0900 +@@ -399,6 +399,27 @@ + png_byte filter_type; + #endif + ++#ifdef PNG_APNG_SUPPORTED ++ png_uint_32 apng_flags; ++ png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */ ++ png_uint_32 first_frame_width; ++ png_uint_32 first_frame_height; ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_uint_32 num_frames_read; /* incremented after all image data of */ ++ /* a frame is read */ ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++ png_progressive_frame_ptr frame_info_fn; /* frame info read callback */ ++ png_progressive_frame_ptr frame_end_fn; /* frame data read callback */ ++#endif ++#endif ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_uint_32 num_frames_to_write; ++ png_uint_32 num_frames_written; ++#endif ++#endif /* PNG_APNG_SUPPORTED */ ++ + /* New members added in libpng-1.2.0 */ + + /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +diff -Naru libpng-1.6.40.org/pngtest.c libpng-1.6.40/pngtest.c +--- libpng-1.6.40.org/pngtest.c 2023-09-10 11:12:23.044481879 +0900 ++++ libpng-1.6.40/pngtest.c 2023-09-10 11:08:58.924075760 +0900 +@@ -875,6 +875,10 @@ + volatile int num_passes; + int pass; + int bit_depth, color_type; ++#ifdef PNG_APNG_SUPPORTED ++ png_uint_32 num_frames; ++ png_uint_32 num_plays; ++#endif + + row_buf = NULL; + error_parameters.file_name = inname; +@@ -1383,6 +1387,22 @@ + } + } + #endif ++ ++#ifdef PNG_APNG_SUPPORTED ++ if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL)) ++ { ++ if (png_get_acTL(read_ptr, read_info_ptr, &num_frames, &num_plays)) ++ { ++ png_byte is_hidden; ++ pngtest_debug2("Handling acTL chunks (frames %ld, plays %ld)", ++ num_frames, num_plays); ++ png_set_acTL(write_ptr, write_info_ptr, num_frames, num_plays); ++ is_hidden = png_get_first_frame_is_hidden(read_ptr, read_info_ptr); ++ png_set_first_frame_is_hidden(write_ptr, write_info_ptr, is_hidden); ++ } ++ } ++#endif ++ + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; +@@ -1463,6 +1483,110 @@ + t_misc += (t_stop - t_start); + t_start = t_stop; + #endif ++#ifdef PNG_APNG_SUPPORTED ++ if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL)) ++ { ++ png_uint_32 frame; ++ for (frame = 0; frame < num_frames; frame++) ++ { ++ png_uint_32 frame_width; ++ png_uint_32 frame_height; ++ png_uint_32 x_offset; ++ png_uint_32 y_offset; ++ png_uint_16 delay_num; ++ png_uint_16 delay_den; ++ png_byte dispose_op; ++ png_byte blend_op; ++ png_read_frame_head(read_ptr, read_info_ptr); ++ if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_fcTL)) ++ { ++ png_get_next_frame_fcTL(read_ptr, read_info_ptr, ++ &frame_width, &frame_height, ++ &x_offset, &y_offset, ++ &delay_num, &delay_den, ++ &dispose_op, &blend_op); ++ } ++ else ++ { ++ frame_width = width; ++ frame_height = height; ++ x_offset = 0; ++ y_offset = 0; ++ delay_num = 1; ++ delay_den = 1; ++ dispose_op = PNG_DISPOSE_OP_NONE; ++ blend_op = PNG_BLEND_OP_SOURCE; ++ } ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_write_frame_head(write_ptr, write_info_ptr, (png_bytepp)&row_buf, ++ frame_width, frame_height, ++ x_offset, y_offset, ++ delay_num, delay_den, ++ dispose_op, blend_op); ++#endif ++ for (pass = 0; pass < num_passes; pass++) ++ { ++# ifdef calc_pass_height ++ png_uint_32 pass_height; ++ ++ if (num_passes == 7) /* interlaced */ ++ { ++ if (PNG_PASS_COLS(frame_width, pass) > 0) ++ pass_height = PNG_PASS_ROWS(frame_height, pass); ++ ++ else ++ pass_height = 0; ++ } ++ ++ else /* not interlaced */ ++ pass_height = frame_height; ++# else ++# define pass_height frame_height ++# endif ++ ++ pngtest_debug1("Writing row data for pass %d", pass); ++ for (y = 0; y < pass_height; y++) ++ { ++#ifndef SINGLE_ROWBUF_ALLOC ++ pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); ++ ++ row_buf = (png_bytep)png_malloc(read_ptr, ++ png_get_rowbytes(read_ptr, read_info_ptr)); ++ ++ pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf, ++ (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr)); ++ ++#endif /* !SINGLE_ROWBUF_ALLOC */ ++ png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); ++ ++#ifdef PNG_WRITE_SUPPORTED ++#ifdef PNGTEST_TIMING ++ t_stop = (float)clock(); ++ t_decode += (t_stop - t_start); ++ t_start = t_stop; ++#endif ++ png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); ++#ifdef PNGTEST_TIMING ++ t_stop = (float)clock(); ++ t_encode += (t_stop - t_start); ++ t_start = t_stop; ++#endif ++#endif /* PNG_WRITE_SUPPORTED */ ++ ++#ifndef SINGLE_ROWBUF_ALLOC ++ pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); ++ png_free(read_ptr, row_buf); ++ row_buf = NULL; ++#endif /* !SINGLE_ROWBUF_ALLOC */ ++ } ++ } ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_write_frame_tail(write_ptr, write_info_ptr); ++#endif ++ } ++ } ++ else ++#endif + for (pass = 0; pass < num_passes; pass++) + { + # ifdef calc_pass_height +diff -Naru libpng-1.6.40.org/pngwrite.c libpng-1.6.40/pngwrite.c +--- libpng-1.6.40.org/pngwrite.c 2023-09-10 11:09:32.955139032 +0900 ++++ libpng-1.6.40/pngwrite.c 2023-09-10 11:08:58.924075760 +0900 +@@ -128,6 +128,10 @@ + * the application continues writing the PNG. So check the 'invalid' + * flag here too. + */ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ if (info_ptr->valid & PNG_INFO_acTL) ++ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); ++#endif + #ifdef PNG_GAMMA_SUPPORTED + # ifdef PNG_WRITE_gAMA_SUPPORTED + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && +@@ -373,6 +377,11 @@ + png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); + #endif + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ if (png_ptr->num_frames_written != png_ptr->num_frames_to_write) ++ png_error(png_ptr, "Not enough frames written"); ++#endif ++ + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +@@ -1475,6 +1484,43 @@ + } + #endif + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++void PNGAPI ++png_write_frame_head(png_structp png_ptr, png_infop info_ptr, ++ png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op) ++{ ++ png_debug(1, "in png_write_frame_head"); ++ ++ /* there is a chance this has been set after png_write_info was called, ++ * so it would be set but not written. is there a way to be sure? */ ++ if (!(info_ptr->valid & PNG_INFO_acTL)) ++ png_error(png_ptr, "png_write_frame_head(): acTL not set"); ++ ++ png_write_reset(png_ptr); ++ ++ png_write_reinit(png_ptr, info_ptr, width, height); ++ ++ if ( !(png_ptr->num_frames_written == 0 && ++ (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) ) ++ png_write_fcTL(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ PNG_UNUSED(row_pointers) ++} ++ ++void PNGAPI ++png_write_frame_tail(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_write_frame_tail"); ++ ++ png_ptr->num_frames_written++; ++ ++ PNG_UNUSED(info_ptr) ++} ++#endif /* PNG_WRITE_APNG_SUPPORTED */ + + #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED + /* Initialize the write structure - general purpose utility. */ +diff -Naru libpng-1.6.40.org/pngwutil.c libpng-1.6.40/pngwutil.c +--- libpng-1.6.40.org/pngwutil.c 2022-11-24 08:37:51.511052176 +0900 ++++ libpng-1.6.40/pngwutil.c 2023-09-10 11:08:58.952075811 +0900 +@@ -821,6 +821,11 @@ + /* Write the chunk */ + png_write_complete_chunk(png_ptr, png_IHDR, buf, 13); + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_ptr->first_frame_width = width; ++ png_ptr->first_frame_height = height; ++#endif ++ + if ((png_ptr->do_filter) == PNG_NO_FILTERS) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || +@@ -1002,8 +1007,17 @@ + optimize_cmf(data, png_image_size(png_ptr)); + #endif + +- if (size > 0) +- png_write_complete_chunk(png_ptr, png_IDAT, data, size); ++ if (size > 0) ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ { ++ if (png_ptr->num_frames_written == 0) ++#endif ++ png_write_complete_chunk(png_ptr, png_IDAT, data, size); ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ else ++ png_write_fdAT(png_ptr, data, size); ++ } ++#endif /* PNG_WRITE_APNG_SUPPORTED */ + png_ptr->mode |= PNG_HAVE_IDAT; + + png_ptr->zstream.next_out = data; +@@ -1050,7 +1064,17 @@ + #endif + + if (size > 0) ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ { ++ if (png_ptr->num_frames_written == 0) ++#endif + png_write_complete_chunk(png_ptr, png_IDAT, data, size); ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ else ++ png_write_fdAT(png_ptr, data, size); ++ } ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++ + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; +@@ -1885,6 +1909,82 @@ + } + #endif + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++void /* PRIVATE */ ++png_write_acTL(png_structp png_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays) ++{ ++ png_byte buf[8]; ++ ++ png_debug(1, "in png_write_acTL"); ++ ++ png_ptr->num_frames_to_write = num_frames; ++ ++ if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ++ num_frames--; ++ ++ png_save_uint_32(buf, num_frames); ++ png_save_uint_32(buf + 4, num_plays); ++ ++ png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8); ++} ++ ++void /* PRIVATE */ ++png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op) ++{ ++ png_byte buf[26]; ++ ++ png_debug(1, "in png_write_fcTL"); ++ ++ if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) ++ png_error(png_ptr, "x and/or y offset for the first frame aren't 0"); ++ if (png_ptr->num_frames_written == 0 && ++ (width != png_ptr->first_frame_width || ++ height != png_ptr->first_frame_height)) ++ png_error(png_ptr, "width and/or height in the first frame's fcTL " ++ "don't match the ones in IHDR"); ++ ++ /* more error checking */ ++ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ png_save_uint_32(buf, png_ptr->next_seq_num); ++ png_save_uint_32(buf + 4, width); ++ png_save_uint_32(buf + 8, height); ++ png_save_uint_32(buf + 12, x_offset); ++ png_save_uint_32(buf + 16, y_offset); ++ png_save_uint_16(buf + 20, delay_num); ++ png_save_uint_16(buf + 22, delay_den); ++ buf[24] = dispose_op; ++ buf[25] = blend_op; ++ ++ png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26); ++ ++ png_ptr->next_seq_num++; ++} ++ ++void /* PRIVATE */ ++png_write_fdAT(png_structp png_ptr, ++ png_const_bytep data, png_size_t length) ++{ ++ png_byte buf[4]; ++ ++ png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length)); ++ ++ png_save_uint_32(buf, png_ptr->next_seq_num); ++ png_write_chunk_data(png_ptr, buf, 4); ++ ++ png_write_chunk_data(png_ptr, data, length); ++ ++ png_write_chunk_end(png_ptr); ++ ++ png_ptr->next_seq_num++; ++} ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++ + /* Initializes the row writing capability of libpng */ + void /* PRIVATE */ + png_write_start_row(png_structrp png_ptr) +@@ -2778,4 +2878,39 @@ + } + #endif /* WRITE_FLUSH */ + } ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++void /* PRIVATE */ ++png_write_reset(png_structp png_ptr) ++{ ++ png_ptr->row_number = 0; ++ png_ptr->pass = 0; ++ png_ptr->mode &= ~PNG_HAVE_IDAT; ++} ++ ++void /* PRIVATE */ ++png_write_reinit(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 width, png_uint_32 height) ++{ ++ if (png_ptr->num_frames_written == 0 && ++ (width != png_ptr->first_frame_width || ++ height != png_ptr->first_frame_height)) ++ png_error(png_ptr, "width and/or height in the first frame's fcTL " ++ "don't match the ones in IHDR"); ++ if (width > png_ptr->first_frame_width || ++ height > png_ptr->first_frame_height) ++ png_error(png_ptr, "width and/or height for a frame greater than" ++ "the ones in IHDR"); ++ ++ png_set_IHDR(png_ptr, info_ptr, width, height, ++ info_ptr->bit_depth, info_ptr->color_type, ++ info_ptr->interlace_type, info_ptr->compression_type, ++ info_ptr->filter_type); ++ ++ png_ptr->width = width; ++ png_ptr->height = height; ++ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); ++ png_ptr->usr_width = png_ptr->width; ++} ++#endif /* PNG_WRITE_APNG_SUPPORTED */ + #endif /* WRITE */ +diff -Naru libpng-1.6.40.org/scripts/symbols.def libpng-1.6.40/scripts/symbols.def +--- libpng-1.6.40.org/scripts/symbols.def 2022-11-24 08:37:51.515052168 +0900 ++++ libpng-1.6.40/scripts/symbols.def 2023-09-10 11:08:58.925075762 +0900 +@@ -253,3 +253,23 @@ + png_set_eXIf @247 + png_get_eXIf_1 @248 + png_set_eXIf_1 @249 ++ png_get_acTL @250 ++ png_set_acTL @251 ++ png_get_num_frames @252 ++ png_get_num_plays @253 ++ png_get_next_frame_fcTL @254 ++ png_set_next_frame_fcTL @255 ++ png_get_next_frame_width @256 ++ png_get_next_frame_height @257 ++ png_get_next_frame_x_offset @258 ++ png_get_next_frame_y_offset @259 ++ png_get_next_frame_delay_num @260 ++ png_get_next_frame_delay_den @261 ++ png_get_next_frame_dispose_op @262 ++ png_get_next_frame_blend_op @263 ++ png_get_first_frame_is_hidden @264 ++ png_set_first_frame_is_hidden @265 ++ png_read_frame_head @266 ++ png_set_progressive_frame_fn @267 ++ png_write_frame_head @268 ++ png_write_frame_tail @269 diff --git a/thirdparty/openmpt_svn_version.h b/thirdparty/openmpt_svn_version.h deleted file mode 100644 index a45ed9f22..000000000 --- a/thirdparty/openmpt_svn_version.h +++ /dev/null @@ -1,10 +0,0 @@ - -#pragma once -#define OPENMPT_VERSION_SVNVERSION "17963" -#define OPENMPT_VERSION_REVISION 17963 -#define OPENMPT_VERSION_DIRTY 0 -#define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.32" -#define OPENMPT_VERSION_DATE "2022-09-25T14:19:05.052596Z" -#define OPENMPT_VERSION_IS_PACKAGE 1 - diff --git a/thirdparty/sdl2-mixer-ext.cmake b/thirdparty/sdl2-mixer-ext.cmake new file mode 100644 index 000000000..a52b11584 --- /dev/null +++ b/thirdparty/sdl2-mixer-ext.cmake @@ -0,0 +1,39 @@ +if(TARGET SDL2_mixer_ext_Static) + return() +endif() + +message(STATUS "Third-party: creating target 'SDL2_mixer_ext::SDL2_mixer_ext'") + +set(SDL_MIXER_X_SHARED ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES} CACHE BOOL "" FORCE) +set(SDL_MIXER_X_STATIC ${NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES} CACHE BOOL "" FORCE) +set(SDL_MIXER_X_DISABLE_INSTALL ON CACHE BOOL "" FORCE) +set(USE_SYSTEM_SDL2 ON CACHE BOOL "" FORCE) +set(SDL2_INCLUDE_PATH ${SDL2_INCLUDE_DIR} CACHE PATH "" FORCE) +set(USE_XMP OFF CACHE PATH "" FORCE) + +set( + internal_SDL2_mixer_ext_options + "SDL_MIXER_X_SHARED ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" + "SDL_MIXER_X_STATIC ${NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" + "SDL_MIXER_X_DISABLE_INSTALL ON" + "USE_SYSTEM_SDL2 ON" + "USE_XMP OFF" +) + +if(${CMAKE_SYSTEM} MATCHES Windows) + #list(APPEND internal_SDL2_mixer_ext_options "DOWNLOAD_AUDIO_CODECS_DEPENDENCY ON") + #set(DOWNLOAD_AUDIO_CODECS_DEPENDENCY ON CACHE BOOL "" FORCE) +endif() + +include(FetchContent) + + +FetchContent_Declare( + SDL2_mixer_ext + OPTIONS ${internal_SDL2_mixer_ext_options} + GIT_TAG "2.6.0-1" + GIT_REPOSITORY "https://github.com/STJr/SDL-Mixer-X.git" +) + +FetchContent_MakeAvailable(SDL2_mixer_ext) + diff --git a/thirdparty/sdl2.cmake b/thirdparty/sdl2.cmake new file mode 100644 index 000000000..16fbd7563 --- /dev/null +++ b/thirdparty/sdl2.cmake @@ -0,0 +1,61 @@ +if(TARGET SDL2-static) + return() +endif() + +message(STATUS "Third-party: creating target 'SDL2::SDL2'") + +set(SDL_STATIC ON CACHE BOOL "" FORCE) +set(SDL_SHARED OFF CACHE BOOL "" FORCE) +set(SDL_TEST OFF CACHE BOOL "" FORCE) +set(SDL2_DISABLE_INSTALL OFF CACHE BOOL "" FORCE) + +set( + internal_sdl2_options + + "SDL_STATIC ON" + "SDL_SHARED OFF" + "SDL_TEST OFF" + "SDL2_DISABLE_INSTALL OFF" +) + +if(${CMAKE_SYSTEM} MATCHES Windows) + list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") + option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" OFF) + set(SDL2_DISABLE_SDL2MAIN OFF CACHE BOOL "" FORCE) +endif() +if(${CMAKE_SYSTEM} MATCHES Darwin) + list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") + option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" OFF) + set(SDL2_DISABLE_SDL2MAIN OFF CACHE BOOL "" FORCE) +endif() +if(${CMAKE_SYSTEM} MATCHES Linux) + list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN ON") + option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" ON) + set(SDL2_DISABLE_SDL2MAIN ON CACHE BOOL "" FORCE) +endif() + +include(FetchContent) + +if (SDL2_USE_THIRDPARTY) + FetchContent_Declare( + SDL2 + VERSION 2.30.0 + GITHUB_REPOSITORY "libsdl-org/SDL" + GIT_TAG release-2.30.0 + OPTIONS ${internal_sdl2_options} + OVERRIDE_FIND_PACKAGE + ) +else() + FetchContent_Declare( + SDL2 + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/SDL2/" + OPTIONS ${internal_sdl2_options} + OVERRIDE_FIND_PACKAGE + ) +endif() + +FetchContent_MakeAvailable(SDL2) + +set(SDL2_INCLUDE_DIR "${SDL2_BINARY_DIR}/include" CACHE PATH "" FORCE) +set(SDL2_LIBRARY "${SDL2_BINARY_DIR}/SDL2-staticd.lib" CACHE PATH "" FORCE) +set(SDL2_DIR ${SDL2_BINARY_DIR} CACHE PATH "" FORCE) diff --git a/thirdparty/vcpkg-overlays/.placeholder b/thirdparty/vcpkg-overlays/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/thirdparty/zlib.cmake b/thirdparty/zlib.cmake new file mode 100644 index 000000000..257609f77 --- /dev/null +++ b/thirdparty/zlib.cmake @@ -0,0 +1,36 @@ +if(TARGET ZLIB::ZLIB) + return() +endif() + +message(STATUS "Third-party: creating target 'ZLIB::ZLIB'") + +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +include(FetchContent) + +if (zlib_USE_THIRDPARTY) + FetchContent_Declare( + ZLIB + GITHUB_REPOSITORY "madler/zlib" + GIT_TAG v1.3.1 + OVERRIDE_FIND_PACKAGE + OPTIONS + "ZLIB_BUILD_EXAMPLES OFF" + ) +else() + FetchContent_Declare( + ZLIB + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/zlib/" + OVERRIDE_FIND_PACKAGE + OPTIONS + "ZLIB_BUILD_EXAMPLES OFF" + ) +endif() + +FetchContent_MakeAvailable(ZLIB) + + +add_library(ZLIB::ZLIB ALIAS zlibstatic) + +set(ZLIB_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/zlib" "${zlib_BINARY_DIR}" CACHE PATH "" FORCE) + diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 000000000..547114800 --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json", + "overlay-ports": [ + "./thirdparty/vcpkg-overlays" + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 000000000..07c4244ad --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "name": "srb2", + "version": "1.0.0", + "builtin-baseline": "c823fd3e57035b10d970a96da2796a2db55e5df5", + "dependencies": [ + "curl", + { + "name": "libgme", + "platform": "!(windows & mingw) & !native" + }, + { + "name": "libopenmpt", + "platform": "!(windows & mingw)" + }, + "libpng", + "miniupnpc", + "sdl2", + { + "name": "sdl2-mixer-ext", + "features": [ + { + "name": "cmd", + "platform": "linux" + }, + { + "name": "libflac", + "platform": "!(windows & mingw & !static)" + }, + { + "name": "libgme", + "platform": "!(windows & mingw) & !native" + }, + { + "name": "libmodplug", + "platform": "!(windows & mingw)" + }, + { + "name": "libopnmidi", + "platform": "!(windows & mingw)" + }, + { + "name": "libvorbis", + "platform": "!(windows & mingw & !static)" + }, + { + "name": "libxmp", + "platform": "!(windows & mingw)" + }, + { + "name": "mpg123", + "platform": "!(windows & mingw)" + }, + { + "name": "nativemidi", + "platform": "!(windows & mingw)" + }, + { + "name": "opusfile", + "platform": "!(windows & mingw)" + }, + { + "name": "pxtone", + "platform": "!(windows & mingw)" + }, + { + "name": "timidity", + "platform": "!(windows & mingw)" + }, + { + "name": "wavpack", + "platform": "!(windows & mingw)" + } + ] + }, + "zlib" + ], + "overrides": [ + { + "name": "sdl2", + "version": "2.28.5", + "port-version": 1 + } + ] +} From f406e9bbb57c89e3d6c58710dcbb91316664bda5 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 3 Apr 2024 20:39:53 +0200 Subject: [PATCH 30/37] Throw a Lua error when R_Frame2Char is called with a frame number without character representation --- src/lua_baselib.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9e4eebeb0..f6b8f462b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3030,6 +3030,9 @@ static int lib_rFrame2Char(lua_State *L) //HUDSAFE c[0] = R_Frame2Char(ch); + if (c[0] == '\xFF') + return luaL_error(L, "frame %u cannot be represented by a character", ch); + c[1] = 0; lua_pushstring(L, c); From 32a3683e07bb31db1cf8a3f22446a85fea69649e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 3 Apr 2024 22:06:03 +0200 Subject: [PATCH 31/37] Fix error message when a patch is missing --- src/r_things.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 534ce7368..7d9701105 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -355,7 +355,10 @@ static void CheckFrame(const char *sprname) { case SRF_NONE: // no rotations were found for that frame at all - I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d (%c)", sprname, frame, R_Frame2Char(frame)); + if (frame < 64) + I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d (%c)", sprname, frame, R_Frame2Char(frame)); + else + I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d", sprname, frame); break; case SRF_SINGLE: From eaf0ba6658328c3b8fd4f6e8a00caa59c09a9673 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 3 Apr 2024 22:07:59 +0200 Subject: [PATCH 32/37] Error out when a sprite definition contains a subfolder --- src/r_things.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index 7d9701105..076777597 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -433,6 +433,9 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 for (l = startlump; l < endlump; l++) { + if (W_IsLumpFolder(wadnum, l)) + I_Error("R_AddSingleSpriteDef: all frame lumps for a sprite should be contained inside a single folder\n"); + // For long sprites, the startlump-endlump range only includes // relevant lumps, so no check needed in that case if (longname || (strlen(sprname) == 4 && !memcmp(lumpinfo[l].name, sprname, 4))) From 245a82112fda2b782d0e12b5fc41e7c3959135e8 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 3 Apr 2024 22:39:58 +0200 Subject: [PATCH 33/37] Make rotation optional for long sprites --- src/r_things.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 076777597..102efdec9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -287,10 +287,8 @@ static boolean GetFramesAndRotationsFromLongLumpName( ) { const char *underscore = strchr(name, '_'); - if (!underscore) - return false; - size_t framelen = underscore - name; + size_t framelen = underscore ? (size_t)(underscore - name) : strlen(name); if (framelen < 1 || framelen > 4) return false; @@ -302,7 +300,7 @@ static boolean GetFramesAndRotationsFromLongLumpName( return false; *ret_frame = atoi(framepart); - *ret_rotation = R_Char2Rotation(*(underscore + 1)); + *ret_rotation = underscore ? R_Char2Rotation(*(underscore + 1)) : 0; if (*ret_frame >= MAXFRAMENUM || *ret_rotation == 255) return false; From 22106ef8b118e2062d76e2ca100645fbf3027a50 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 3 Apr 2024 23:24:54 +0200 Subject: [PATCH 34/37] Fix short sprite names triggering an error --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 102efdec9..90d1bf646 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -431,7 +431,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 for (l = startlump; l < endlump; l++) { - if (W_IsLumpFolder(wadnum, l)) + if (longname && W_IsLumpFolder(wadnum, l)) I_Error("R_AddSingleSpriteDef: all frame lumps for a sprite should be contained inside a single folder\n"); // For long sprites, the startlump-endlump range only includes From 8a6b5d7c0f863753290c8630ae7c143432f7188c Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 4 Apr 2024 00:06:33 +0200 Subject: [PATCH 35/37] Support setting two frames per lump for long sprites --- src/r_things.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 90d1bf646..004e0a6c2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -278,17 +278,20 @@ static boolean GetFramesAndRotationsFromShortLumpName( return true; } -static boolean GetFramesAndRotationsFromLongLumpName( +static boolean GetSingleFrameAndRotation( const char *name, + size_t len, INT32 *ret_frame, - UINT8 *ret_rotation, - INT32 *ret_frame2, - UINT8 *ret_rotation2 + UINT8 *ret_rotation ) { const char *underscore = strchr(name, '_'); - size_t framelen = underscore ? (size_t)(underscore - name) : strlen(name); + // Found but past the part of the name we are parsing + if ((size_t)(underscore - name) >= len) + underscore = NULL; + + size_t framelen = underscore ? (size_t)(underscore - name) : len; if (framelen < 1 || framelen > 4) return false; @@ -304,8 +307,36 @@ static boolean GetFramesAndRotationsFromLongLumpName( if (*ret_frame >= MAXFRAMENUM || *ret_rotation == 255) return false; - *ret_frame2 = -1; - *ret_rotation2 = 255; + return true; +} + +static boolean GetFramesAndRotationsFromLongLumpName( + const char *name, + INT32 *ret_frame, + UINT8 *ret_rotation, + INT32 *ret_frame2, + UINT8 *ret_rotation2 +) +{ + const char *plus = strchr(name, '+'); + + if (plus) + { + size_t len1 = plus - name; + + if (!GetSingleFrameAndRotation(name, len1, ret_frame, ret_rotation)) + return false; + if (!GetSingleFrameAndRotation(plus + 1, strlen(name) - len1 - 1, ret_frame2, ret_rotation2)) + return false; + } + else + { + if (!GetSingleFrameAndRotation(name, strlen(name), ret_frame, ret_rotation)) + return false; + + *ret_frame2 = -1; + *ret_rotation2 = 255; + } return true; } @@ -444,7 +475,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 UINT8 rotation, rotation2; boolean good = longname ? - GetFramesAndRotationsFromLongLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2) : + GetFramesAndRotationsFromLongLumpName(lumpinfo[l].longname, &frame, &rotation, &frame2, &rotation2) : GetFramesAndRotationsFromShortLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2); if (!good) // Give an actual NAME error -_-... From a1649186ce44fe99a6811a9ba41c50b0da240ba2 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 5 Apr 2024 17:31:42 +0200 Subject: [PATCH 36/37] Fix some error messages --- src/r_things.c | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 004e0a6c2..3bda42a4a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -136,6 +136,12 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging + char framedescription[256]; + if (cn != '\xFF') + sprintf(framedescription, "%s frame %d (%c)", spritename, frame, cn); + else + sprintf(framedescription, "%s frame %d", spritename, frame); + INT32 r; lumpnum_t lumppat = (wad << 16) + lump; @@ -153,9 +159,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { // the lump should be used for all rotations if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple rot = 0 lump\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple rot = 0 lump\n", framedescription); else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message. - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has rotations and a rot = 0 lump\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has rotations and a rot = 0 lump\n", framedescription); sprtemp[frame].rotate = SRF_SINGLE; for (r = 0; r < 16; r++) @@ -175,15 +181,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (sprtemp[frame].rotate == SRF_NONE) sprtemp[frame].rotate = SRF_SINGLE; else if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has L/R rotations and a rot = 0 lump\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has L/R rotations and a rot = 0 lump\n", framedescription); else if (sprtemp[frame].rotate == SRF_3D) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-8 rotations\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-8 rotations\n", framedescription); else if (sprtemp[frame].rotate == SRF_3DGE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-G rotations\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-G rotations\n", framedescription); else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L)) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple L rotations\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple L rotations\n", framedescription); else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R)) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple R rotations\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple R rotations\n", framedescription); sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D) @@ -210,9 +216,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (sprtemp[frame].rotate == SRF_NONE) sprtemp[frame].rotate = SRF_SINGLE; else if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has 1-8/G rotations and a rot = 0 lump\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has 1-8/G rotations and a rot = 0 lump\n", framedescription); else if (sprtemp[frame].rotate & SRF_2D) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-8/G rotations\n", spritename, frame, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-8/G rotations\n", framedescription); // make 0 based rotation--; @@ -232,7 +238,12 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch } if (sprtemp[frame].lumppat[rotation] != LUMPERROR) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c (%c%c) has two lumps mapped to it\n", spritename, frame, cr, cn, cr); + { + if (cn != '\xFF') + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c (%c%c) has two lumps mapped to it\n", spritename, frame, cr, cn, cr); + else + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c has two lumps mapped to it\n", spritename, frame, cr); + } // lumppat & lumpid are the same for original Doom, but different // when using sprites in pwad : the lumppat points the new graphics @@ -380,14 +391,17 @@ static void CheckFrame(const char *sprname) { spriteframe_t *spriteframe = &sprtemp[frame]; + char framedescription[256]; + if (frame < 64) + sprintf(framedescription, "%s frame %d (%c)", sprname, frame, R_Frame2Char(frame)); + else + sprintf(framedescription, "%s frame %d", sprname, frame); + switch (spriteframe->rotate) { case SRF_NONE: // no rotations were found for that frame at all - if (frame < 64) - I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d (%c)", sprname, frame, R_Frame2Char(frame)); - else - I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d", sprname, frame); + I_Error("R_AddSingleSpriteDef: No patches found for %s", framedescription); break; case SRF_SINGLE: @@ -397,8 +411,8 @@ static void CheckFrame(const char *sprname) case SRF_2D: // both Left and Right rotations // we test to see whether the left and right slots are present if ((spriteframe->lumppat[2] == LUMPERROR) || (spriteframe->lumppat[6] == LUMPERROR)) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (L-R mode)", - sprname, frame, R_Frame2Char(frame)); + I_Error("R_AddSingleSpriteDef: Sprite %s is missing rotations (L-R mode)", + framedescription); break; default: @@ -410,8 +424,8 @@ static void CheckFrame(const char *sprname) // we test the patch lump, or the id lump whatever // if it was not loaded the two are LUMPERROR if (spriteframe->lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (1-%c mode)", - sprname, frame, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); + I_Error("R_AddSingleSpriteDef: Sprite %s is missing rotations (1-%c mode)", + framedescription, ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); } } break; From 4a9462761a434665fa071e46c8e98afe2ead3d33 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 5 Apr 2024 19:10:15 +0200 Subject: [PATCH 37/37] Fix early free --- src/r_things.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 3bda42a4a..c46d81624 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -679,7 +679,6 @@ static void AddLongSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *p char *sprname = W_GetLumpFolderNamePK3(wadnum, lumpnum); strupr(sprname); sprnum = R_GetSpriteNumByName(sprname); - Z_Free(sprname); if (sprnum != NUMSPRITES && R_AddSingleSpriteDef(sprname, &sprites[sprnum], wadnum, folderstart, folderend, true)) { @@ -690,6 +689,8 @@ static void AddLongSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *p #endif } + Z_Free(sprname); + lumpnum = folderend; }