diff --git a/src/g_level.h b/src/g_level.h index a5b3006ac..8360bd45e 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -338,6 +338,7 @@ struct level_info_t TArray PrecacheSounds; TArray PrecacheTextures; + TArray PrecacheClasses; level_info_t() { diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index b6c3a376a..78ba9142b 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1083,6 +1083,18 @@ DEFINE_MAP_OPTION(PrecacheTextures, true) } while (parse.sc.CheckString(",")); } +DEFINE_MAP_OPTION(PrecacheClasses, true) +{ + parse.ParseAssign(); + + do + { + parse.sc.MustGetString(); + //the class list is not initialized here so all we can do is store the class's name. + info->PrecacheClasses.Push(parse.sc.String); + } while (parse.sc.CheckString(",")); +} + DEFINE_MAP_OPTION(redirect, true) { parse.ParseAssign(); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 56437e133..fcc18ae55 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3158,7 +3158,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c int style = sv_dropstyle; if (style == 0) { - style = (gameinfo.gametype == GAME_Strife) ? 2 : 1; + style = gameinfo.defaultdropstyle; } if (style == 2) { @@ -3206,7 +3206,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c void P_TossItem (AActor *item) { int style = sv_dropstyle; - if (style==0) style= gameinfo.defaultdropstyle; + if (style==0) style = gameinfo.defaultdropstyle; if (style==2) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b7d887195..ecd6b8d1c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -638,20 +638,23 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat) // This shouldn't count for the item statistics! item->ClearCounters(); - if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) + if (!givecheat || amount > 0) { - static_cast(item)->SaveAmount *= amount; - } - else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) - { - static_cast(item)->SaveAmount *= amount; - } - else - { - if (!givecheat) - item->Amount = amount; + if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) + { + static_cast(item)->SaveAmount *= amount; + } + else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) + { + static_cast(item)->SaveAmount *= amount; + } else - item->Amount = MIN (amount, item->MaxAmount); + { + if (!givecheat) + item->Amount = amount; + else + item->Amount = MIN (amount, item->MaxAmount); + } } if (!item->CallTryPickup (this)) { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 762f4b794..cdb180e60 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3366,6 +3366,83 @@ void P_GetPolySpots (MapData * map, TArray &spots, TAr } } + +//=========================================================================== +// +// P_PrecacheLevel +// +// Preloads all relevant graphics for the level. +// +//=========================================================================== + +static void P_PrecacheLevel() +{ + int i; + BYTE *hitlist; + TMap actorhitlist; + int cnt = TexMan.NumTextures(); + + if (demoplayback) + return; + + hitlist = new BYTE[cnt]; + memset(hitlist, 0, cnt); + + AActor *actor; + TThinkerIterator iterator; + + while ((actor = iterator.Next())) + { + actorhitlist[actor->GetClass()] = true; + } + + for (unsigned i = 0; i < level.info->PrecacheClasses.Size(); i++) + { + // level.info can only store names, no class pointers. + PClassActor *cls = PClass::FindActor(level.info->PrecacheClasses[i]); + if (cls != NULL) actorhitlist[cls] = true; + } + + for (i = numsectors - 1; i >= 0; i--) + { + hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat; + } + + for (i = numsides - 1; i >= 0; i--) + { + hitlist[sides[i].GetTexture(side_t::top).GetIndex()] |= FTextureManager::HIT_Wall; + hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] |= FTextureManager::HIT_Wall; + hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall; + } + + // Sky texture is always present. + // Note that F_SKY1 is the name used to + // indicate a sky floor/ceiling as a flat, + // while the sky texture is stored like + // a wall texture, with an episode dependant + // name. + + if (sky1texture.isValid()) + { + hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky; + } + if (sky2texture.isValid()) + { + hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky; + } + + for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++) + { + FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); + if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall; + } + + Renderer->Precache(hitlist, actorhitlist); + + delete[] hitlist; +} + extern polyblock_t **PolyBlockMap; void P_FreeLevelData () @@ -4094,7 +4171,7 @@ void P_SetupLevel (const char *lumpname, int position) // preload graphics and sounds if (precache) { - TexMan.PrecacheLevel (); + P_PrecacheLevel (); S_PrecacheLevel (); } times[17].Unclock(); diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 8a3664ac8..67a516f9c 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -494,6 +494,17 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit) // clip to the part of the sector we are in if (hit.Z > ff_top) { + // 3D floor height is the same as the floor height. We need to test a second spot to see if it is above or below + if (fabs(bf - ff_top) < EQUAL_EPSILON) + { + double cf = entersector->floorplane.ZatPoint(entersector->centerspot); + double ffc = rover->top.plane->ZatPoint(entersector->centerspot); + if (ffc > cf) + { + bf = ff_top - EQUAL_EPSILON; + } + } + // above if (bf < ff_top) { @@ -505,6 +516,17 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit) } else if (hit.Z < ff_bottom) { + // 3D floor height is the same as the ceiling height. We need to test a second spot to see if it is above or below + if (fabs(bc - ff_bottom) < EQUAL_EPSILON) + { + double cc = entersector->ceilingplane.ZatPoint(entersector->centerspot); + double fcc = rover->bottom.plane->ZatPoint(entersector->centerspot); + if (fcc < cc) + { + bc = ff_bottom + EQUAL_EPSILON; + } + } + //below if (bc > ff_bottom) { diff --git a/src/r_renderer.h b/src/r_renderer.h index 115ac64c9..6c65fc12f 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -28,7 +28,7 @@ struct FRenderer virtual bool UsesColormap() const = 0; // precache one texture - virtual void PrecacheTexture(FTexture *tex, int cache) = 0; + virtual void Precache(BYTE *texhitlist, TMap &actorhitlist) = 0; // render 3D view virtual void RenderView(player_t *player) = 0; diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index d563986f7..07edf25e9 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -98,6 +98,55 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache) } } +void FSoftwareRenderer::Precache(BYTE *texhitlist, TMap &actorhitlist) +{ + BYTE *spritelist = new BYTE[sprites.Size()]; + TMap::Iterator it(actorhitlist); + TMap::Pair *pair; + + memset(spritelist, 0, sprites.Size()); + + while (it.NextPair(pair)) + { + PClassActor *cls = pair->Key; + + for (int i = 0; i < cls->NumOwnedStates; i++) + { + spritelist[cls->OwnedStates[i].sprite] = true; + } + } + + // Precache textures (and sprites). + + for (int i = (int)(sprites.Size() - 1); i >= 0; i--) + { + if (spritelist[i]) + { + int j, k; + for (j = 0; j < sprites[i].numframes; j++) + { + const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j]; + + for (k = 0; k < 16; k++) + { + FTextureID pic = frame->Texture[k]; + if (pic.isValid()) + { + texhitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite; + } + } + } + } + } + delete[] spritelist; + + int cnt = TexMan.NumTextures(); + for (int i = cnt - 1; i >= 0; i--) + { + PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]); + } +} + //=========================================================================== // // Render the view diff --git a/src/r_swrenderer.h b/src/r_swrenderer.h index 939547797..3e5fed9bc 100644 --- a/src/r_swrenderer.h +++ b/src/r_swrenderer.h @@ -9,7 +9,8 @@ struct FSoftwareRenderer : public FRenderer virtual bool UsesColormap() const; // precache one texture - virtual void PrecacheTexture(FTexture *tex, int cache); + void PrecacheTexture(FTexture *tex, int cache); + virtual void Precache(BYTE *texhitlist, TMap &actorhitlist); // render 3D view virtual void RenderView(player_t *player); diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 6c7bb97df..8bc1b4868 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -500,6 +500,7 @@ int S_AddSoundLump (const char *logicalname, int lump) sfxinfo_t newsfx; newsfx.data.Clear(); + newsfx.data3d.Clear(); newsfx.name = logicalname; newsfx.lumpnum = lump; newsfx.next = 0; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index ac4dbc78f..d888c9ec2 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -98,6 +98,7 @@ extern float S_GetMusicVolume (const char *music); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +static void S_LoadSound3D(sfxinfo_t *sfx); static bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, float limit_range, AActor *actor, int channel); static bool S_IsChannelUsed(AActor *actor, int channel, int *seen); static void S_ActivatePlayList(bool goBack); @@ -546,8 +547,11 @@ void S_UnloadSound (sfxinfo_t *sfx) { if (sfx->data.isValid()) { + if(sfx->data3d.isValid() && sfx->data != sfx->data3d) + GSnd->UnloadSound(sfx->data3d); GSnd->UnloadSound(sfx->data); sfx->data.Clear(); + sfx->data3d.Clear(); DPrintf("Unloaded sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); } } @@ -1098,9 +1102,10 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO if (attenuation > 0) { + S_LoadSound3D(sfx); SoundListener listener; S_SetListener(listener, players[consoleplayer].camera); - chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); + chan = (FSoundChan*)GSnd->StartSound3D (sfx->data3d, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); } else { @@ -1194,12 +1199,13 @@ void S_RestartSound(FSoundChan *chan) return; } + S_LoadSound3D(sfx); SoundListener listener; S_SetListener(listener, players[consoleplayer].camera); chan->ChanFlags &= ~(CHAN_EVICTED|CHAN_ABSTIME); - ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch, - chan->Priority, pos, vel, chan->EntChannel, startflags, chan); + ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data3d, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch, + chan->Priority, pos, vel, chan->EntChannel, startflags, chan); } else { @@ -1339,31 +1345,35 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) BYTE *sfxdata = new BYTE[size]; wlump.Read(sfxdata, size); SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]); + std::pair snd; // If the sound is voc, use the custom loader. if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0) { - sfx->data = GSnd->LoadSoundVoc(sfxdata, size); + snd = GSnd->LoadSoundVoc(sfxdata, size); } // If the sound is raw, just load it as such. else if (sfx->bLoadRAW) { - sfx->data = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart); + snd = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart); } // Otherwise, try the sound as DMX format. else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8) { int frequency = LittleShort(((WORD *)sfxdata)[1]); if (frequency == 0) frequency = 11025; - sfx->data = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart); + snd = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart); } // If that fails, let the sound system try and figure it out. else { - sfx->data = GSnd->LoadSound(sfxdata, size); + snd = GSnd->LoadSound(sfxdata, size); } - delete[] sfxdata; + + sfx->data = snd.first; + if(snd.second) + sfx->data3d = sfx->data; } if (!sfx->data.isValid()) @@ -1379,6 +1389,53 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) return sfx; } +static void S_LoadSound3D(sfxinfo_t *sfx) +{ + if (GSnd->IsNull()) return; + + if(sfx->data3d.isValid()) + return; + + unsigned int i; + + DPrintf("Loading monoized sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); + + int size = Wads.LumpLength(sfx->lumpnum); + if(size <= 0) return; + + FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum); + BYTE *sfxdata = new BYTE[size]; + wlump.Read(sfxdata, size); + SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]); + std::pair snd; + + // If the sound is voc, use the custom loader. + if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0) + { + snd = GSnd->LoadSoundVoc(sfxdata, size, true); + } + // If the sound is raw, just load it as such. + else if (sfx->bLoadRAW) + { + snd = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart, true); + } + // Otherwise, try the sound as DMX format. + else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8) + { + int frequency = LittleShort(((WORD *)sfxdata)[1]); + if (frequency == 0) frequency = 11025; + snd = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart, -1, true); + } + // If that fails, let the sound system try and figure it out. + else + { + snd = GSnd->LoadSound(sfxdata, size, true); + } + delete[] sfxdata; + + sfx->data3d = snd.first; +} + //========================================================================== // // S_CheckSingular diff --git a/src/s_sound.h b/src/s_sound.h index ad06195e1..acdee2a2c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -36,6 +36,9 @@ struct sfxinfo_t // Next field is for use by the system sound interface. // A non-null data means the sound has been loaded. SoundHandle data; + // Also for the sound interface. Used for 3D positional + // sounds, may be the same as data. + SoundHandle data3d; FString name; // [RH] Sound name defined in SNDINFO int lumpnum; // lump number of sfx diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index a62998d3d..72e3c0a05 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -2510,7 +2510,7 @@ void FMODSoundRenderer::UpdateSounds() // //========================================================================== -SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) +std::pair FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { FMOD_CREATESOUNDEXINFO exinfo; SoundHandle retval = { NULL }; @@ -2518,7 +2518,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ if (length <= 0) { - return retval; + return std::make_pair(retval, true); } InitCreateSoundExInfo(&exinfo); @@ -2550,7 +2550,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ break; default: - return retval; + return std::make_pair(retval, true); } const FMOD_MODE samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_OPENRAW; @@ -2561,7 +2561,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ if (result != FMOD_OK) { DPrintf("Failed to allocate sample: Error %d\n", result); - return retval; + return std::make_pair(retval, true); } if (loopstart >= 0) @@ -2572,7 +2572,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ } retval.data = sample; - return retval; + return std::make_pair(retval, true); } //========================================================================== @@ -2581,12 +2581,12 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ // //========================================================================== -SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length) +std::pair FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize) { FMOD_CREATESOUNDEXINFO exinfo; SoundHandle retval = { NULL }; - if (length == 0) return retval; + if (length == 0) return std::make_pair(retval, true); InitCreateSoundExInfo(&exinfo); exinfo.length = length; @@ -2599,11 +2599,11 @@ SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length) if (result != FMOD_OK) { DPrintf("Failed to allocate sample: Error %d\n", result); - return retval; + return std::make_pair(retval, true); } SetCustomLoopPts(sample); retval.data = sample; - return retval; + return std::make_pair(retval, true); } //========================================================================== diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index eaf643c85..33b1f4bf7 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -15,8 +15,8 @@ public: void SetSfxVolume (float volume); void SetMusicVolume (float volume); - SoundHandle LoadSound(BYTE *sfxdata, int length); - SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1); + std::pair LoadSound(BYTE *sfxdata, int length, bool monoize); + std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false); void UnloadSound (SoundHandle sfx); unsigned int GetMSLength(SoundHandle sfx); unsigned int GetSampleLength(SoundHandle sfx); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 894951d1b..f19e080c3 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -135,15 +135,15 @@ public: void SetMusicVolume (float volume) { } - SoundHandle LoadSound(BYTE *sfxdata, int length) + std::pair LoadSound(BYTE *sfxdata, int length, bool monoize) { SoundHandle retval = { NULL }; - return retval; + return std::make_pair(retval, true); } - SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) + std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { SoundHandle retval = { NULL }; - return retval; + return std::make_pair(retval, true); } void UnloadSound (SoundHandle sfx) { @@ -456,7 +456,7 @@ FString SoundStream::GetStats() // //========================================================================== -SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length) +std::pair SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length, bool monoize) { BYTE * data = NULL; int len, frequency, channels, bits, loopstart, loopend; @@ -600,7 +600,7 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length) } } while (false); - SoundHandle retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend); + std::pair retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend, monoize); if (data) delete[] data; return retval; } diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 836d62019..ef0743c05 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -95,9 +95,10 @@ public: virtual bool IsNull() { return false; } virtual void SetSfxVolume (float volume) = 0; virtual void SetMusicVolume (float volume) = 0; - virtual SoundHandle LoadSound(BYTE *sfxdata, int length) = 0; - SoundHandle LoadSoundVoc(BYTE *sfxdata, int length); - virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1) = 0; + // Returns a pair containing a sound handle and a boolean indicating the sound can be used in 3D. + virtual std::pair LoadSound(BYTE *sfxdata, int length, bool monoize=false) = 0; + std::pair LoadSoundVoc(BYTE *sfxdata, int length, bool monoize=false); + virtual std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false) = 0; virtual void UnloadSound (SoundHandle sfx) = 0; // unloads a sound from memory virtual unsigned int GetMSLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency virtual unsigned int GetSampleLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency diff --git a/src/sound/i_soundinternal.h b/src/sound/i_soundinternal.h index 279ffdf88..c86c6cdaa 100644 --- a/src/sound/i_soundinternal.h +++ b/src/sound/i_soundinternal.h @@ -91,6 +91,11 @@ struct SoundHandle bool isValid() const { return data != NULL; } void Clear() { data = NULL; } + + bool operator==(const SoundHandle &rhs) const + { return data == rhs.data; } + bool operator!=(const SoundHandle &rhs) const + { return !(*this == rhs); } }; struct FISoundChannel diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 9b7de9e43..56dfb4a4c 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1019,11 +1019,11 @@ float OpenALSoundRenderer::GetOutputRate() } -SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) +std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { SoundHandle retval = { NULL }; - if(length == 0) return retval; + if(length == 0) return std::make_pair(retval, true); if(bits == -8) { @@ -1033,6 +1033,33 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre bits = -bits; } + if(channels > 1 && monoize) + { + size_t frames = length / channels * 8 / bits; + if(bits == 16) + { + for(size_t i = 0;i < frames;i++) + { + int sum = 0; + for(int c = 0;c < channels;c++) + sum = ((short*)sfxdata)[i*channels + c]; + ((short*)sfxdata)[i] = sum / channels; + } + } + else if(bits == 8) + { + for(size_t i = 0;i < frames;i++) + { + int sum = 0; + for(int c = 0;c < channels;c++) + sum = sfxdata[i*channels + c] - 128; + sfxdata[i] = (sum / channels) + 128; + } + } + length /= channels; + channels = 1; + } + ALenum format = AL_NONE; if(bits == 16) { @@ -1048,7 +1075,7 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre if(format == AL_NONE || frequency <= 0) { Printf("Unhandled format: %d bit, %d channel, %d hz\n", bits, channels, frequency); - return retval; + return std::make_pair(retval, true); } length -= length%(channels*bits/8); @@ -1061,7 +1088,7 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre Printf("Failed to buffer data: %s\n", alGetString(err)); alDeleteBuffers(1, &buffer); getALError(); - return retval; + return std::make_pair(retval, true); } if((loopstart > 0 || loopend > 0) && AL.SOFT_loop_points) @@ -1085,10 +1112,10 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre } retval.data = MAKE_PTRID(buffer); - return retval; + return std::make_pair(retval, channels==1); } -SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) +std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize) { SoundHandle retval = { NULL }; MemoryReader reader((const char*)sfxdata, length); @@ -1098,15 +1125,15 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) int srate; SoundDecoder *decoder = CreateDecoder(&reader); - if(!decoder) return retval; + if(!decoder) return std::make_pair(retval, true); decoder->getInfo(&srate, &chans, &type); - if(chans == ChannelConfig_Mono) + if(chans == ChannelConfig_Mono || monoize) { if(type == SampleType_UInt8) format = AL_FORMAT_MONO8; if(type == SampleType_Int16) format = AL_FORMAT_MONO16; } - if(chans == ChannelConfig_Stereo) + else if(chans == ChannelConfig_Stereo) { if(type == SampleType_UInt8) format = AL_FORMAT_STEREO8; if(type == SampleType_Int16) format = AL_FORMAT_STEREO16; @@ -1117,10 +1144,28 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), GetSampleTypeName(type)); delete decoder; - return retval; + return std::make_pair(retval, true); } TArray data = decoder->readAll(); + if(chans != ChannelConfig_Mono && monoize) + { + // TODO: Handle this better if ChannelConfig ever gets more channel configurations. + size_t frames = data.Size() / 2 / (type == SampleType_Int16 ? 2 : 1); + if(type == SampleType_Int16) + { + short *sfxdata = (short*)&data[0]; + for(size_t i = 0;i < frames;i++) + sfxdata[i] = (sfxdata[i*2 + 0]-0 + sfxdata[i*2 + 1]-0)/2; + } + else if(type == SampleType_UInt8) + { + BYTE *sfxdata = (BYTE*)&data[0]; + for(size_t i = 0;i < frames;i++) + sfxdata[i] = (sfxdata[i*2 + 0]-128 + sfxdata[i*2 + 1]-128)/2 + 128; + } + data.Resize(data.Size()/2); + } ALuint buffer = 0; alGenBuffers(1, &buffer); @@ -1133,12 +1178,12 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) alDeleteBuffers(1, &buffer); getALError(); delete decoder; - return retval; + return std::make_pair(retval, true); } retval.data = MAKE_PTRID(buffer); delete decoder; - return retval; + return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize)); } void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index f528dbc6a..2644b171a 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -71,8 +71,8 @@ public: virtual void SetSfxVolume(float volume); virtual void SetMusicVolume(float volume); - virtual SoundHandle LoadSound(BYTE *sfxdata, int length); - virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1); + virtual std::pair LoadSound(BYTE *sfxdata, int length, bool monoize); + virtual std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false); virtual void UnloadSound(SoundHandle sfx); virtual unsigned int GetMSLength(SoundHandle sfx); virtual unsigned int GetSampleLength(SoundHandle sfx); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index c87522b8d..95c976f8c 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1226,46 +1226,6 @@ int FTextureManager::CountLumpTextures (int lumpnum) return 0; } -//=========================================================================== -// -// R_PrecacheLevel -// - -// Preloads all relevant graphics for the level. -// -//=========================================================================== - -void FTextureManager::PrecacheLevel (void) -{ - BYTE *hitlist; - int cnt = NumTextures(); - - if (demoplayback) - return; - - precacheTime = I_FPSTime(); - - hitlist = new BYTE[cnt]; - memset (hitlist, 0, cnt); - - screen->GetHitlist(hitlist); - - for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++) - { - FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst); - if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall; - } - - for (int i = cnt - 1; i >= 0; i--) - { - Renderer->PrecacheTexture(ByIndex(i), hitlist[i]); - } - - delete[] hitlist; -} - - - //========================================================================== // diff --git a/src/textures/textures.h b/src/textures/textures.h index c0ab164aa..91246c0fe 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -448,7 +448,6 @@ public: void UnloadAll (); int NumTextures () const { return (int)Textures.Size(); } - void PrecacheLevel (void); void WriteTexture (FArchive &arc, int picnum); int ReadTexture (FArchive &arc); diff --git a/src/v_video.cpp b/src/v_video.cpp index 52b8fdc86..01a73950b 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1207,83 +1207,6 @@ void DFrameBuffer::WipeCleanup() wipe_Cleanup(); } -//=========================================================================== -// -// Create texture hitlist -// -//=========================================================================== - -void DFrameBuffer::GetHitlist(BYTE *hitlist) -{ - BYTE *spritelist; - int i; - - spritelist = new BYTE[sprites.Size()]; - - // Precache textures (and sprites). - memset (spritelist, 0, sprites.Size()); - - { - AActor *actor; - TThinkerIterator iterator; - - while ( (actor = iterator.Next ()) ) - spritelist[actor->sprite] = 1; - } - - for (i = (int)(sprites.Size () - 1); i >= 0; i--) - { - if (spritelist[i]) - { - int j, k; - for (j = 0; j < sprites[i].numframes; j++) - { - const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j]; - - for (k = 0; k < 16; k++) - { - FTextureID pic = frame->Texture[k]; - if (pic.isValid()) - { - hitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite; - } - } - } - } - } - - delete[] spritelist; - - for (i = numsectors - 1; i >= 0; i--) - { - hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] = - hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat; - } - - for (i = numsides - 1; i >= 0; i--) - { - hitlist[sides[i].GetTexture(side_t::top).GetIndex()] = - hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] = - hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall; - } - - // Sky texture is always present. - // Note that F_SKY1 is the name used to - // indicate a sky floor/ceiling as a flat, - // while the sky texture is stored like - // a wall texture, with an episode dependant - // name. - - if (sky1texture.isValid()) - { - hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky; - } - if (sky2texture.isValid()) - { - hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky; - } -} - //========================================================================== // // DFrameBuffer :: GameRestart diff --git a/src/v_video.h b/src/v_video.h index 0f3fb8224..58dd2d9cb 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -395,8 +395,7 @@ public: virtual FNativePalette *CreatePalette(FRemapTable *remap); // Precaches or unloads a texture - virtual void GetHitlist(BYTE *hitlist); - + // Report a game restart virtual void GameRestart();