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/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; diff --git a/source/core/raze_sound.cpp b/source/core/raze_sound.cpp index 463fece92..a306f8520 100644 --- a/source/core/raze_sound.cpp +++ b/source/core/raze_sound.cpp @@ -208,49 +208,107 @@ 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(); } +//========================================================================== +// +// 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); + } + } +} + +//========================================================================== +// +// 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/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) 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) diff --git a/source/games/blood/src/sfx.cpp b/source/games/blood/src/sfx.cpp index b12c01b3e..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() -{ -} - //========================================================================== // // @@ -149,7 +140,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 +159,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 +217,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.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 8f9566234..7b7659e2f 100644 --- a/source/games/blood/src/sound.h +++ b/source/games/blood/src/sound.h @@ -50,11 +50,9 @@ 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 = -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); diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index 5320726f6..ebd6aa6ec 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: