From fd6a71cac585feff3244403119afe1aff239b59a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Apr 2021 20:37:04 +0200 Subject: [PATCH 1/7] - fixed a random crash with an empty sprite I just experienced. --- source/games/blood/src/actor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index a3fcf58f5..1ffdd1d79 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -2854,7 +2854,7 @@ spritetype *actDropObject(spritetype *pSprite, int nType) { else if (nType >= kItemAmmoBase && nType < kItemAmmoMax) pSprite2 = actDropAmmo(pSprite, nType); else if (nType >= kItemWeaponBase && nType < kItemWeaponMax) pSprite2 = actDropWeapon(pSprite, nType); - if (pSprite2) { + if (pSprite2 && pSprite->picnum > -1) { int top, bottom; GetSpriteExtents(pSprite2, &top, &bottom); if (bottom >= pSprite2->z) From 6142f9d79581962dd8c738d68715b8b4a012da22 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Apr 2021 21:13:24 +0200 Subject: [PATCH 2/7] - added CHANF_FORCE flag for forcing non-looped sounds to start, even when sound is paused. Blood needs this for its PlayerSound controller, which is run right on map load - so without this it wouldn't start the sound when a map is initiated from the console. --- source/common/audio/sound/i_soundinternal.h | 1 + source/common/audio/sound/s_sound.cpp | 2 +- source/games/blood/src/triggers.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/common/audio/sound/i_soundinternal.h b/source/common/audio/sound/i_soundinternal.h index be3486440..1ef4178d4 100644 --- a/source/common/audio/sound/i_soundinternal.h +++ b/source/common/audio/sound/i_soundinternal.h @@ -31,6 +31,7 @@ enum EChanFlag CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them. CHANF_LOCAL = 16384, // only plays locally for the calling actor CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood) + CHANF_FORCE = 65536, // Start, even if sound is paused. }; typedef TFlags EChanFlags; diff --git a/source/common/audio/sound/s_sound.cpp b/source/common/audio/sound/s_sound.cpp index 4521ebd90..7fdbd74c6 100644 --- a/source/common/audio/sound/s_sound.cpp +++ b/source/common/audio/sound/s_sound.cpp @@ -528,7 +528,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, // sound is paused and a non-looped sound is being started. // Such a sound would play right after unpausing which wouldn't sound right. - if (!(chanflags & CHANF_LOOP) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE)) && SoundPaused) + if (!(chanflags & CHANF_LOOP) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE|CHANF_FORCE)) && SoundPaused) { return NULL; } diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index 4bbaf9c7f..8da50f7af 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -595,7 +595,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event) break; gMe->restTime = 0; } - sndStartSample(pXSprite->data1, -1, 1, 0); + sndStartSample(pXSprite->data1, -1, 1, 0, CHANF_FORCE); break; case kThingObjectGib: case kThingObjectExplode: From 9b977ba96e6692ef77029cde35a62300f8032c2f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Apr 2021 22:42:24 +0200 Subject: [PATCH 3/7] - fixed mixup of values 0 and -1 in sound code. 0 means 'default', -1 means 'silent'. This caused playback issues for useSoundGen. All other places were passing proper volume values along, this is the only one to read the volume from map data. --- source/games/blood/src/sfx.cpp | 7 ++++--- source/games/blood/src/sound.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/games/blood/src/sfx.cpp b/source/games/blood/src/sfx.cpp index b12c01b3e..dd64ab3e4 100644 --- a/source/games/blood/src/sfx.cpp +++ b/source/games/blood/src/sfx.cpp @@ -149,7 +149,8 @@ FSoundID getSfx(FSoundID soundId, float &attenuation, int &pitch, int &relvol) auto udata = soundEngine->GetUserData(soundId); if (pitch < 0) pitch = udata ? udata[0] : 0x10000; - if (relvol < 0) relvol = udata && udata[2] ? udata[2] : 80; + if (relvol < 0) relvol = 0; + else if (relvol == 0) relvol = udata && udata[2] ? udata[2] : 80; if (relvol > 255) relvol = 255; // Limit the attenuation. More than 2.0 is simply too much. attenuation = relvol > 0 ? clamp(80.f / relvol, 0.f, 2.f) : 1.f; @@ -167,7 +168,7 @@ void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector) float attenuation; int pitch = -1; - int relvol = -1; + int relvol = 0; sid = getSfx(sid, attenuation, pitch, relvol); auto sfx = soundEngine->GetSfx(sid); EChanFlags flags = CHANF_OVERLAP; @@ -225,7 +226,7 @@ void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitc void sfxPlay3DSound(spritetype* pSprite, int soundId, int a3, int a4) { - sfxPlay3DSoundCP(pSprite, soundId, a3, a4, -1, -1); + sfxPlay3DSoundCP(pSprite, soundId, a3, a4, -1); } diff --git a/source/games/blood/src/sound.h b/source/games/blood/src/sound.h index 8f9566234..a4c384910 100644 --- a/source/games/blood/src/sound.h +++ b/source/games/blood/src/sound.h @@ -54,7 +54,7 @@ void sfxInit(void); void sfxTerm(void); void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector); void sfxPlay3DSound(spritetype *pSprite, int soundId, int a3 = -1, int a4 = 0); -void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3 = -1, int a4 = 0, int pitch = 0, int volume = -1); +void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3 = -1, int a4 = 0, int pitch = 0, int volume = 0); void sfxKill3DSound(spritetype *pSprite, int a2 = -1, int a3 = -1); void sfxKillAllSounds(void); void sfxSetReverb(bool toggle); From 135dd1f081c280840ca278054b791cc028d1cc44 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Apr 2021 00:31:23 +0200 Subject: [PATCH 4/7] - added PlaySound CCNDs. --- source/core/raze_sound.cpp | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/source/core/raze_sound.cpp b/source/core/raze_sound.cpp index 463fece92..5d6130895 100644 --- a/source/core/raze_sound.cpp +++ b/source/core/raze_sound.cpp @@ -254,3 +254,46 @@ void S_SerializeSounds(FSerializer& arc) GSnd->UpdateSounds(); } +//========================================================================== +// +// CCMD playsound +// +//========================================================================== + +CCMD(playsound) +{ + if (argv.argc() > 1) + { + FSoundID id = argv[1]; + if (id == 0) + { + Printf("'%s' is not a sound\n", argv[1]); + } + else + { + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, CHANF_UI | CHANF_NOPAUSE, id, 1.f, ATTN_NORM); + } + } +} + +//========================================================================== +// +// CCMD playsound +// +//========================================================================== + +CCMD(playsoundid) +{ + if (argv.argc() > 1) + { + FSoundID id = soundEngine->FindSoundByResID((int)strtol(argv[1], nullptr, 0)); + if (id == 0) + { + Printf("'%s' is not a sound\n", argv[1]); + } + else + { + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, CHANF_UI | CHANF_NOPAUSE, id, 1.f, ATTN_NORM); + } + } +} From d25838fe151b38b2a2b2a50bf5315a7404a3cd36 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Apr 2021 00:01:29 +0200 Subject: [PATCH 5/7] - Blood: fixed issue with INI detection when having content added by RFS files. --- source/games/blood/src/levels.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index 462fbe316..34f1c6d40 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -121,7 +121,8 @@ static const char* DefFile(void) int numlumps = fileSystem.GetNumEntries(); for (int i = numlumps - 1; i >= 0; i--) { - if (fileSystem.GetFileContainer(i) <= fileSystem.GetMaxIwadNum()) break; + int fileno = fileSystem.GetFileContainer(i); + if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) break; FString fn = fileSystem.GetFileFullName(i, false); FString ext = fn.Right(4); if (ext.CompareNoCase(".ini") == 0) From f87e40131f266a7b3a26e9eaf6e979a2ca2c0967 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Apr 2021 00:10:43 +0200 Subject: [PATCH 6/7] - Blood: add a dummy sound entry at index 0. Parts of the sound system treat entry 0 as "no sound" so nothing placed there would play. This made the one custom sound in "The Way of Ira" not play because as the last sound being defined it ended up in the first, invalid slot. --- source/core/raze_sound.cpp | 85 +++++++++++++++++++------------- source/games/blood/src/sfx.cpp | 9 ---- source/games/blood/src/sound.cpp | 6 ++- source/games/blood/src/sound.h | 2 - 4 files changed, 54 insertions(+), 48 deletions(-) diff --git a/source/core/raze_sound.cpp b/source/core/raze_sound.cpp index 5d6130895..a306f8520 100644 --- a/source/core/raze_sound.cpp +++ b/source/core/raze_sound.cpp @@ -208,50 +208,50 @@ void S_SerializeSounds(FSerializer& arc) { FSoundChan* chan; - GSnd->Sync(true); +GSnd->Sync(true); - if (arc.isWriting()) +if (arc.isWriting()) +{ + // Count channels and accumulate them so we can store them in + // reverse order. That way, they will be in the same order when + // reloaded later as they are now. + TArray chans = soundEngine->AllActiveChannels(); + + if (chans.Size() > 0 && arc.BeginArray("sounds")) { - // Count channels and accumulate them so we can store them in - // reverse order. That way, they will be in the same order when - // reloaded later as they are now. - TArray chans = soundEngine->AllActiveChannels(); - - if (chans.Size() > 0 && arc.BeginArray("sounds")) + for (unsigned int i = chans.Size(); i-- != 0; ) { - for (unsigned int i = chans.Size(); i-- != 0; ) - { - // Replace start time with sample position. - uint64_t start = chans[i]->StartTime; - chans[i]->StartTime = GSnd ? GSnd->GetPosition(chans[i]) : 0; - arc(nullptr, *chans[i]); - chans[i]->StartTime = start; - } - arc.EndArray(); + // Replace start time with sample position. + uint64_t start = chans[i]->StartTime; + chans[i]->StartTime = GSnd ? GSnd->GetPosition(chans[i]) : 0; + arc(nullptr, *chans[i]); + chans[i]->StartTime = start; } + arc.EndArray(); } - else +} +else +{ + unsigned int count; + + soundEngine->StopAllChannels(); + if (arc.BeginArray("sounds")) { - unsigned int count; - - soundEngine->StopAllChannels(); - if (arc.BeginArray("sounds")) + count = arc.ArraySize(); + for (unsigned int i = 0; i < count; ++i) { - count = arc.ArraySize(); - for (unsigned int i = 0; i < count; ++i) - { - chan = (FSoundChan*)soundEngine->GetChannel(nullptr); - arc(nullptr, *chan); - // Sounds always start out evicted when restored from a save. - chan->ChanFlags |= CHANF_EVICTED | CHANF_ABSTIME; - } - arc.EndArray(); + chan = (FSoundChan*)soundEngine->GetChannel(nullptr); + arc(nullptr, *chan); + // Sounds always start out evicted when restored from a save. + chan->ChanFlags |= CHANF_EVICTED | CHANF_ABSTIME; } - // Add a small delay so that eviction only runs once the game is up and runnnig. - soundEngine->SetRestartTime(I_GetTime() + 2); + arc.EndArray(); } - GSnd->Sync(false); - GSnd->UpdateSounds(); + // Add a small delay so that eviction only runs once the game is up and runnnig. + soundEngine->SetRestartTime(I_GetTime() + 2); +} +GSnd->Sync(false); +GSnd->UpdateSounds(); } //========================================================================== @@ -297,3 +297,18 @@ CCMD(playsoundid) } } } + +//========================================================================== +// +// CCMD listsounds +// +//========================================================================== + +CCMD(listsounds) +{ + auto& S_sfx = soundEngine->GetSounds(); + for (unsigned i = 0; i < S_sfx.Size(); i++) + { + Printf("%4d: name = %s, resId = %d, lumpnum = %d\n", i, S_sfx[i].name.GetChars(), S_sfx[i].ResourceId, S_sfx[i].lumpnum); + } +} diff --git a/source/games/blood/src/sfx.cpp b/source/games/blood/src/sfx.cpp index dd64ab3e4..f1ac8e609 100644 --- a/source/games/blood/src/sfx.cpp +++ b/source/games/blood/src/sfx.cpp @@ -58,15 +58,6 @@ public: }; -void sfxInit(void) -{ - soundEngine = new BloodSoundEngine; -} - -void sfxTerm() -{ -} - //========================================================================== // // diff --git a/source/games/blood/src/sound.cpp b/source/games/blood/src/sound.cpp index eb67e2082..28dae78bb 100644 --- a/source/games/blood/src/sound.cpp +++ b/source/games/blood/src/sound.cpp @@ -106,7 +106,8 @@ static void S_AddBloodSFX(int lumpnum) void sndInit(void) { - sfxInit(); + soundEngine = new BloodSoundEngine; + soundEngine->AddSoundLump("", 0, 0, -1, 6); // add a dummy entry at index #0 for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--) { auto type = fileSystem.GetResourceType(i); @@ -117,7 +118,8 @@ void sndInit(void) } else if (!stricmp(type, "WAV") || !stricmp(type, "OGG") || !stricmp(type, "FLAC") || !stricmp(type, "VOC")) { - soundEngine->AddSoundLump(fileSystem.GetFileFullName(i), i, 0, fileSystem.GetResourceId(i)| 0x40000000, 6); // mark the resource ID as special. + if (fileSystem.GetFileNamespace(i) != ns_music) + soundEngine->AddSoundLump(fileSystem.GetFileFullName(i), i, 0, fileSystem.GetResourceId(i)| 0x40000000, 6); // mark the resource ID as special. } } soundEngine->HashSounds(); diff --git a/source/games/blood/src/sound.h b/source/games/blood/src/sound.h index a4c384910..7b7659e2f 100644 --- a/source/games/blood/src/sound.h +++ b/source/games/blood/src/sound.h @@ -50,8 +50,6 @@ void sndProcess(void); void sndTerm(void); void sndInit(void); -void sfxInit(void); -void sfxTerm(void); void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector); void sfxPlay3DSound(spritetype *pSprite, int soundId, int a3 = -1, int a4 = 0); void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3 = -1, int a4 = 0, int pitch = 0, int volume = 0); From a15ac437225893b4e2f1025782ffce988a390b35 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Apr 2021 00:20:45 +0200 Subject: [PATCH 7/7] - enable embedding of blood.rff and sounds.rff in mod archives when playing Blood Some mods provide pregenerated resources, this allows loading them without picking them apart first. --- source/common/filesystem/file_7z.cpp | 2 +- source/common/filesystem/file_directory.cpp | 2 +- source/common/filesystem/file_pak.cpp | 2 +- source/common/filesystem/file_zip.cpp | 2 +- source/common/filesystem/resourcefile.cpp | 15 +++------------ source/common/filesystem/resourcefile.h | 3 ++- source/core/initfs.cpp | 5 +++++ 7 files changed, 14 insertions(+), 17 deletions(-) diff --git a/source/common/filesystem/file_7z.cpp b/source/common/filesystem/file_7z.cpp index 8d0d64bb2..f207702d0 100644 --- a/source/common/filesystem/file_7z.cpp +++ b/source/common/filesystem/file_7z.cpp @@ -293,7 +293,7 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) lump_p->Owner = this; lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED; lump_p->Position = i; - lump_p->CheckEmbedded(); + lump_p->CheckEmbedded(filter); lump_p++; } // Resize the lump record array to its actual size diff --git a/source/common/filesystem/file_directory.cpp b/source/common/filesystem/file_directory.cpp index 7654764cb..4f2c94eba 100644 --- a/source/common/filesystem/file_directory.cpp +++ b/source/common/filesystem/file_directory.cpp @@ -209,7 +209,7 @@ void FDirectory::AddEntry(const char *fullpath, int size) lump_p->LumpSize = size; lump_p->Owner = this; lump_p->Flags = 0; - lump_p->CheckEmbedded(); + lump_p->CheckEmbedded(nullptr); } diff --git a/source/common/filesystem/file_pak.cpp b/source/common/filesystem/file_pak.cpp index 5ff9ff886..13aafa985 100644 --- a/source/common/filesystem/file_pak.cpp +++ b/source/common/filesystem/file_pak.cpp @@ -109,7 +109,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) Lumps[i].Owner = this; Lumps[i].Position = LittleLong(fileinfo[i].filepos); Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen); - Lumps[i].CheckEmbedded(); + Lumps[i].CheckEmbedded(filter); } GenerateHash(); PostProcessArchive(&Lumps[0], sizeof(Lumps[0]), filter); diff --git a/source/common/filesystem/file_zip.cpp b/source/common/filesystem/file_zip.cpp index 2adca1160..f33b60ba4 100644 --- a/source/common/filesystem/file_zip.cpp +++ b/source/common/filesystem/file_zip.cpp @@ -337,7 +337,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) lump_p->CRC32 = zip_fh->CRC32; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); - lump_p->CheckEmbedded(); + lump_p->CheckEmbedded(filter); lump_p++; } diff --git a/source/common/filesystem/resourcefile.cpp b/source/common/filesystem/resourcefile.cpp index d718d74ec..5fc484b23 100644 --- a/source/common/filesystem/resourcefile.cpp +++ b/source/common/filesystem/resourcefile.cpp @@ -122,7 +122,7 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const return 0 == filePath.CompareNoCase(resPath); } -void FResourceLump::CheckEmbedded() +void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi) { // Checks for embedded archives const char *c = strstr(FullName, ".wad"); @@ -130,22 +130,13 @@ void FResourceLump::CheckEmbedded() { Flags |= LUMPF_EMBEDDED; } - /* later - else + else if (lfi) for (auto& fstr : lfi->embeddings) { - if (c==NULL) c = strstr(Name, ".zip"); - if (c==NULL) c = strstr(Name, ".pk3"); - if (c==NULL) c = strstr(Name, ".7z"); - if (c==NULL) c = strstr(Name, ".pak"); - if (c && strlen(c) <= 4) + if (!stricmp(FullName, fstr)) { - // Mark all embedded archives in any directory Flags |= LUMPF_EMBEDDED; - memset(Name, 0, 8); } } - */ - } diff --git a/source/common/filesystem/resourcefile.h b/source/common/filesystem/resourcefile.h index bfd20e816..5e9276c76 100644 --- a/source/common/filesystem/resourcefile.h +++ b/source/common/filesystem/resourcefile.h @@ -15,6 +15,7 @@ struct LumpFilterInfo // The following are for checking if the root directory of a zip can be removed. TArray reservedFolders; TArray requiredPrefixes; + TArray embeddings; std::function postprocessFunc; }; @@ -111,7 +112,7 @@ public: virtual int GetIndexNum() const { return -1; } virtual int GetNamespace() const { return 0; } void LumpNameSetup(FString iname); - void CheckEmbedded(); + void CheckEmbedded(LumpFilterInfo* lfi); virtual FCompressedBuffer GetRawData(); void *Lock(); // validates the cache and increases the refcount. diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index 6910d2cdf..3ad2283f4 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -388,6 +388,11 @@ void InitFileSystem(TArray& groups) LumpFilterInfo lfi; for (auto p : iwad_folders) lfi.reservedFolders.Push(p); for (auto p = iwad_reserved(); *p; p++) lfi.requiredPrefixes.Push(*p); + if (isBlood()) + { + lfi.embeddings.Push("blood.rff"); + lfi.embeddings.Push("sounds.rff"); + } lfi.dotFilter = LumpFilter;