From 9dd42be15f72b5128be823e6aeb0adafa3915486 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sun, 16 Oct 2016 16:22:21 -0400 Subject: [PATCH 1/8] - Fixed: Demo playback on Windows XP since we don't patch fstat for v140_xp bug. --- src/m_misc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 824fe0533..c49b342ce 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -123,7 +123,8 @@ int M_ReadFile (char const *name, BYTE **buffer) handle = open (name, O_RDONLY | O_BINARY, 0666); if (handle == -1) I_Error ("Couldn't read file %s", name); - if (fstat (handle,&fileinfo) == -1) + // [BL] Use stat instead of fstat for v140_xp hack + if (stat (name,&fileinfo) == -1) I_Error ("Couldn't read file %s", name); length = fileinfo.st_size; buf = new BYTE[length]; @@ -149,7 +150,8 @@ int M_ReadFileMalloc (char const *name, BYTE **buffer) handle = open (name, O_RDONLY | O_BINARY, 0666); if (handle == -1) I_Error ("Couldn't read file %s", name); - if (fstat (handle,&fileinfo) == -1) + // [BL] Use stat instead of fstat for v140_xp hack + if (stat (name,&fileinfo) == -1) I_Error ("Couldn't read file %s", name); length = fileinfo.st_size; buf = (BYTE*)M_Malloc(length); From 741c9edf421a757d5a8d003964b0ca4f8815262b Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 17 Oct 2016 00:19:08 -0400 Subject: [PATCH 2/8] - Clear out GCC 6.2 warnings (interestingly they now check for misleading indentation which found a good case in fragglescript/t_func.cpp even though I believe it was harmless) --- src/fragglescript/t_func.cpp | 2 +- src/p_acs.cpp | 4 ++-- src/p_ceiling.cpp | 2 +- src/p_saveg.cpp | 8 ++++---- src/resourcefiles/file_zip.cpp | 3 ++- src/serializer.cpp | 4 ++-- src/serializer.h | 2 +- src/sound/music_hmi_midiout.cpp | 4 ++-- src/sound/music_smf_midiout.cpp | 6 +++--- src/sound/music_xmi_midiout.cpp | 6 +++--- src/thingdef/thingdef_expression.cpp | 6 +++--- 11 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index a02ec947f..cc096ed60 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -497,7 +497,7 @@ DFsSection *FParser::looping_section() if(!best || (current->start_index > best->start_index)) best = current; // save it } - current = current->next; + current = current->next; } } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 71ef65f22..fcbff904a 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1616,7 +1616,7 @@ void FBehavior::StaticSerializeModuleStates (FSerializer &arc) { if (arc.isReading()) { - int modnum = arc.ArraySize(); + auto modnum = arc.ArraySize(); if (modnum != StaticModules.Size()) { I_Error("Level was saved with a different number of ACS modules. (Have %d, save has %d)", StaticModules.Size(), modnum); @@ -2933,7 +2933,7 @@ void DACSThinker::Serialize(FSerializer &arc) if (arc.BeginArray("runningscripts")) { auto cnt = arc.ArraySize(); - for (int i = 0; i < cnt; i++) + for (unsigned i = 0; i < cnt; i++) { SavingRunningscript srs; arc(nullptr, srs); diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index e90dd2096..29b0c5095 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -184,7 +184,7 @@ void DCeiling::Tick () case DCeiling::ceilLowerAndCrush: if (m_CrushMode == ECrushMode::crushSlowdown) m_Speed = 1. / 8; - break; + break; default: break; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 9bb9f82e8..46cdd767b 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -888,10 +888,10 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) // deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered. BYTE chk[16] = { 0 }; arc.Array("checksum", chk, 16); - if (arc.GetSize("linedefs") != numlines || - arc.GetSize("sidedefs") != numsides || - arc.GetSize("sectors") != numsectors || - arc.GetSize("polyobjs") != po_NumPolyobjs || + if (arc.GetSize("linedefs") != (unsigned)numlines || + arc.GetSize("sidedefs") != (unsigned)numsides || + arc.GetSize("sectors") != (unsigned)numsectors || + arc.GetSize("polyobjs") != (unsigned)po_NumPolyobjs || memcmp(chk, level.md5, 16)) { I_Error("Savegame is from a different level"); diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 73193062c..8713fe554 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -392,7 +392,8 @@ int FZipLump::FillCache() int FZipLump::GetFileOffset() { if (Method != METHOD_STORED) return -1; - if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); return Position; + if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); + return Position; } //========================================================================== diff --git a/src/serializer.cpp b/src/serializer.cpp index 3a66a8397..49226ce80 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -381,7 +381,7 @@ void FSerializer::Close() // //========================================================================== -int FSerializer::ArraySize() +unsigned FSerializer::ArraySize() { if (r != nullptr && r->mObjects.Last().mObject->IsArray()) { @@ -709,7 +709,7 @@ FSerializer &FSerializer::Sprite(const char *key, int32_t &spritenum, int32_t *d { if (val->IsString()) { - int name = *reinterpret_cast(val->GetString()); + uint32_t name = *reinterpret_cast(val->GetString()); for (auto hint = NumStdSprites; hint-- != 0; ) { if (sprites[hint].dwName == name) diff --git a/src/serializer.h b/src/serializer.h index a3e1f531e..4797a4bce 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -60,7 +60,7 @@ public: FWriter *w = nullptr; FReader *r = nullptr; - int ArraySize(); + unsigned ArraySize(); void WriteKey(const char *key); void WriteObjects(); diff --git a/src/sound/music_hmi_midiout.cpp b/src/sound/music_hmi_midiout.cpp index 7d9d36926..691970765 100644 --- a/src/sound/music_hmi_midiout.cpp +++ b/src/sound/music_hmi_midiout.cpp @@ -145,8 +145,8 @@ HMISong::HMISong (FileReader &reader, EMidiDevice type, const char *args) MusHeader = new BYTE[len]; SongLen = len; NumTracks = 0; - if (reader.Read(MusHeader, len) != len) - return; + if (reader.Read(MusHeader, len) != len) + return; // Do some validation of the MIDI file if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0) diff --git a/src/sound/music_smf_midiout.cpp b/src/sound/music_smf_midiout.cpp index a045998a8..ae0c47e80 100644 --- a/src/sound/music_smf_midiout.cpp +++ b/src/sound/music_smf_midiout.cpp @@ -114,10 +114,10 @@ MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type, const char *args) return; } #endif - SongLen = reader.GetLength(); + SongLen = reader.GetLength(); MusHeader = new BYTE[SongLen]; - if (reader.Read(MusHeader, SongLen) != SongLen) - return; + if (reader.Read(MusHeader, SongLen) != SongLen) + return; // Do some validation of the MIDI file if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6) diff --git a/src/sound/music_xmi_midiout.cpp b/src/sound/music_xmi_midiout.cpp index b56e8f6f8..c9a2e9c46 100644 --- a/src/sound/music_xmi_midiout.cpp +++ b/src/sound/music_xmi_midiout.cpp @@ -117,10 +117,10 @@ XMISong::XMISong (FileReader &reader, EMidiDevice type, const char *args) return; } #endif - SongLen = reader.GetLength(); + SongLen = reader.GetLength(); MusHeader = new BYTE[SongLen]; - if (reader.Read(MusHeader, SongLen) != SongLen) - return; + if (reader.Read(MusHeader, SongLen) != SongLen) + return; // Find all the songs in this file. NumSongs = FindXMIDforms(MusHeader, SongLen, NULL); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index c2b2d25e6..7c55e5286 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -91,7 +91,7 @@ static const FLOP FxFlops[] = // //========================================================================== -FCompileContext::FCompileContext(PClassActor *cls, PPrototype *ret) : Class(cls), ReturnProto(ret) +FCompileContext::FCompileContext(PClassActor *cls, PPrototype *ret) : ReturnProto(ret), Class(cls) { } @@ -959,7 +959,7 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build) //========================================================================== FxPreIncrDecr::FxPreIncrDecr(FxExpression *base, int token) -: FxExpression(base->ScriptPosition), Base(base), Token(token) +: FxExpression(base->ScriptPosition), Token(token), Base(base) { AddressRequested = false; AddressWritable = false; @@ -1045,7 +1045,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) //========================================================================== FxPostIncrDecr::FxPostIncrDecr(FxExpression *base, int token) -: FxExpression(base->ScriptPosition), Base(base), Token(token) +: FxExpression(base->ScriptPosition), Token(token), Base(base) { } From b4bdb8fa7d2a0bc870270185106d2b3854249f31 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 17 Oct 2016 00:22:06 -0400 Subject: [PATCH 3/8] - Fixed: Assertion failure if a save was loaded without starting a new game (due to uninitialized RNG). --- src/m_random.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/m_random.cpp b/src/m_random.cpp index e0a55d095..60ce12fd6 100644 --- a/src/m_random.cpp +++ b/src/m_random.cpp @@ -331,6 +331,10 @@ void FRandom::StaticReadRNGState(FSerializer &arc) FRandom *rng; arc("rngseed", rngseed); + + // Call StaticClearRandom in order to ensure that SFMT is initialized + FRandom::StaticClearRandom (); + if (arc.BeginArray("rngs")) { int count = arc.ArraySize(); From d2a9f7ac6f47232c3370cce28806b23933d2b45b Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Mon, 17 Oct 2016 21:45:06 -0500 Subject: [PATCH 4/8] Fix Raise definition for DoomImp --- wadsrc/static/actors/doom/doomimp.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/actors/doom/doomimp.txt b/wadsrc/static/actors/doom/doomimp.txt index a5725e724..008cc5229 100644 --- a/wadsrc/static/actors/doom/doomimp.txt +++ b/wadsrc/static/actors/doom/doomimp.txt @@ -52,7 +52,8 @@ ACTOR DoomImp TROO U -1 Stop Raise: - TROO MLKJI 8 + TROO ML 8 + TROO KJI 6 Goto See } } From 5de811257883b512f6c44c7d3997fedcc1297b88 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 19 Oct 2016 23:52:09 +0200 Subject: [PATCH 5/8] Add support for capping sky with a solid color --- src/r_draw.cpp | 241 +++++++++++++++++++++++++++++++++++++ src/r_draw.h | 7 ++ src/r_plane.cpp | 165 +++++++++++++++++++++++++ src/textures/texture.cpp | 73 +++++++++++ src/textures/textures.h | 6 + wadsrc/static/language.enu | 1 + wadsrc/static/menudef.txt | 1 + 7 files changed, 494 insertions(+) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 80b91ed2d..5f592223b 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -110,6 +110,8 @@ DWORD vplce[4]; DWORD vince[4]; BYTE* palookupoffse[4]; const BYTE* bufplce[4]; +const BYTE* bufplce2[4]; +uint32_t bufheight[4]; // just for profiling int dccount; @@ -2142,6 +2144,245 @@ void tmvline4_revsubclamp () } while (--count); } +void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom) +{ + uint8_t *dest = dc_dest; + int count = dc_count; + int pitch = dc_pitch; + const uint8_t *source0 = bufplce[0]; + int textureheight0 = bufheight[0]; + + int32_t frac = vplce[0]; + int32_t fracstep = vince[0]; + + int start_fade = 2; // How fast it should fade out + + int solid_top_r = RPART(solid_top); + int solid_top_g = GPART(solid_top); + int solid_top_b = BPART(solid_top); + int solid_bottom_r = RPART(solid_bottom); + int solid_bottom_g = GPART(solid_bottom); + int solid_bottom_b = BPART(solid_bottom); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + uint8_t fg = source0[sample_index]; + + int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); + int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + + if (alpha_top == 256 && alpha_bottom == 256) + { + *dest = fg; + } + else + { + int inv_alpha_top = 256 - alpha_top; + int inv_alpha_bottom = 256 - alpha_bottom; + + const auto &c = GPalette.BaseColors[fg]; + int c_red = c.r; + int c_green = c.g; + int c_blue = c.b; + c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8; + c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8; + c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8; + c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8; + c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8; + c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8; + *dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)]; + } + + frac += fracstep; + dest += pitch; + } +} + +void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom) +{ + for (int col = 0; col < 4; col++) + { + uint8_t *dest = dc_dest + col; + int count = dc_count; + int pitch = dc_pitch; + const uint8_t *source0 = bufplce[col]; + int textureheight0 = bufheight[0]; + + int32_t frac = vplce[col]; + int32_t fracstep = vince[col]; + + int start_fade = 2; // How fast it should fade out + + int solid_top_r = RPART(solid_top); + int solid_top_g = GPART(solid_top); + int solid_top_b = BPART(solid_top); + int solid_bottom_r = RPART(solid_bottom); + int solid_bottom_g = GPART(solid_bottom); + int solid_bottom_b = BPART(solid_bottom); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + uint8_t fg = source0[sample_index]; + + int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); + int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + + if (alpha_top == 256 && alpha_bottom == 256) + { + *dest = fg; + } + else + { + int inv_alpha_top = 256 - alpha_top; + int inv_alpha_bottom = 256 - alpha_bottom; + + const auto &c = GPalette.BaseColors[fg]; + int c_red = c.r; + int c_green = c.g; + int c_blue = c.b; + c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8; + c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8; + c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8; + c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8; + c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8; + c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8; + *dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)]; + } + + frac += fracstep; + dest += pitch; + } + } +} + +void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom) +{ + uint8_t *dest = dc_dest; + int count = dc_count; + int pitch = dc_pitch; + const uint8_t *source0 = bufplce[0]; + const uint8_t *source1 = bufplce2[0]; + int textureheight0 = bufheight[0]; + uint32_t maxtextureheight1 = bufheight[1] - 1; + + int32_t frac = vplce[0]; + int32_t fracstep = vince[0]; + + int start_fade = 2; // How fast it should fade out + + int solid_top_r = RPART(solid_top); + int solid_top_g = GPART(solid_top); + int solid_top_b = BPART(solid_top); + int solid_bottom_r = RPART(solid_bottom); + int solid_bottom_g = GPART(solid_bottom); + int solid_bottom_b = BPART(solid_bottom); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + uint8_t fg = source0[sample_index]; + if (fg == 0) + { + uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + fg = source1[sample_index2]; + } + + int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); + int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + + if (alpha_top == 256 && alpha_bottom == 256) + { + *dest = fg; + } + else + { + int inv_alpha_top = 256 - alpha_top; + int inv_alpha_bottom = 256 - alpha_bottom; + + const auto &c = GPalette.BaseColors[fg]; + int c_red = c.r; + int c_green = c.g; + int c_blue = c.b; + c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8; + c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8; + c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8; + c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8; + c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8; + c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8; + *dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)]; + } + + frac += fracstep; + dest += pitch; + } +} + +void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom) +{ + for (int col = 0; col < 4; col++) + { + uint8_t *dest = dc_dest + col; + int count = dc_count; + int pitch = dc_pitch; + const uint8_t *source0 = bufplce[col]; + const uint8_t *source1 = bufplce2[col]; + int textureheight0 = bufheight[0]; + uint32_t maxtextureheight1 = bufheight[1] - 1; + + int32_t frac = vplce[col]; + int32_t fracstep = vince[col]; + + int start_fade = 2; // How fast it should fade out + + int solid_top_r = RPART(solid_top); + int solid_top_g = GPART(solid_top); + int solid_top_b = BPART(solid_top); + int solid_bottom_r = RPART(solid_bottom); + int solid_bottom_g = GPART(solid_bottom); + int solid_bottom_b = BPART(solid_bottom); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + uint8_t fg = source0[sample_index]; + if (fg == 0) + { + uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + fg = source1[sample_index2]; + } + + int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); + int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + + if (alpha_top == 256 && alpha_bottom == 256) + { + *dest = fg; + } + else + { + int inv_alpha_top = 256 - alpha_top; + int inv_alpha_bottom = 256 - alpha_bottom; + + const auto &c = GPalette.BaseColors[fg]; + int c_red = c.r; + int c_green = c.g; + int c_blue = c.b; + c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8; + c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8; + c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8; + c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8; + c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8; + c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8; + *dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)]; + } + + frac += fracstep; + dest += pitch; + } + } +} //========================================================================== // diff --git a/src/r_draw.h b/src/r_draw.h index cb2f68f33..c45700a21 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -51,6 +51,8 @@ extern "C" DWORD vplce[4]; extern "C" DWORD vince[4]; extern "C" BYTE* palookupoffse[4]; extern "C" const BYTE* bufplce[4]; +extern "C" const BYTE* bufplce2[4]; +extern "C" uint32_t bufheight[4]; // [RH] Temporary buffer for column drawing extern "C" BYTE *dc_temp; @@ -293,4 +295,9 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_ // transmaskwallscan is like maskwallscan, but it can also blend to the background void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); +void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom); +void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom); +void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom); +void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom); + #endif diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 07001bf1b..8c12b3ca2 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -63,6 +63,8 @@ #pragma warning(disable:4244) #endif +CVAR(Bool, r_capsky, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); + //EXTERN_CVAR (Int, tx) //EXTERN_CVAR (Int, ty) @@ -898,8 +900,171 @@ static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x) return composite; } +static void R_DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, double scale, double texturemid, double yrepeat) +{ + uint32_t height = frontskytex->GetHeight(); + + for (int i = 0; i < columns; i++) + { + double uv_stepd = skyiscale * yrepeat; + double v = (texturemid + uv_stepd * (y1 - CenterY + 0.5)) / height; + double v_step = uv_stepd / height; + + uint32_t uv_pos = (uint32_t)(v * 0x01000000); + uint32_t uv_step = (uint32_t)(v_step * 0x01000000); + + int x = start_x + i; + if (MirrorFlags & RF_XFLIP) + x = (viewwidth - x); + + DWORD ang, angle1, angle2; + + ang = (skyangle + xtoviewangle[x]) ^ skyflip; + angle1 = (DWORD)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS); + angle2 = (DWORD)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS); + + bufplce[i] = (const BYTE *)frontskytex->GetColumn(angle1, nullptr); + bufplce2[i] = backskytex ? (const BYTE *)backskytex->GetColumn(angle2, nullptr) : nullptr; + + vince[i] = uv_step; + vplce[i] = uv_pos; + } + + bufheight[0] = height; + bufheight[1] = backskytex ? backskytex->GetHeight() : height; + dc_dest = (ylookup[y1] + start_x) + dc_destorg; + dc_count = y2 - y1; + + uint32_t solid_top = frontskytex->GetSWSkyCapColor(false); + uint32_t solid_bottom = frontskytex->GetSWSkyCapColor(true); + + if (columns == 4) + if (!backskytex) + R_DrawSingleSkyCol4(solid_top, solid_bottom); + else + R_DrawDoubleSkyCol4(solid_top, solid_bottom); + else + if (!backskytex) + R_DrawSingleSkyCol1(solid_top, solid_bottom); + else + R_DrawDoubleSkyCol1(solid_top, solid_bottom); +} + +static void R_DrawSkyColumn(int start_x, int y1, int y2, int columns) +{ + if (1 << frontskytex->HeightBits == frontskytex->GetHeight()) + { + double texturemid = skymid * frontskytex->Scale.Y + frontskytex->GetHeight(); + R_DrawSkyColumnStripe(start_x, y1, y2, columns, frontskytex->Scale.Y, texturemid, frontskytex->Scale.Y); + } + else + { + double yrepeat = frontskytex->Scale.Y; + double scale = frontskytex->Scale.Y * skyscale; + double iscale = 1 / scale; + short drawheight = short(frontskytex->GetHeight() * scale); + double topfrac = fmod(skymid + iscale * (1 - CenterY), frontskytex->GetHeight()); + if (topfrac < 0) topfrac += frontskytex->GetHeight(); + double texturemid = topfrac - iscale * (1 - CenterY); + R_DrawSkyColumnStripe(start_x, y1, y2, columns, scale, texturemid, yrepeat); + } +} + +static void R_DrawCapSky(visplane_t *pl) +{ + int x1 = pl->left; + int x2 = pl->right; + short *uwal = (short *)pl->top; + short *dwal = (short *)pl->bottom; + + // Calculate where 4 column alignment begins and ends: + int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2); + int aligned_x2 = clamp(x2 / 4 * 4, x1, x2); + + // First unaligned columns: + for (int x = x1; x < aligned_x1; x++) + { + int y1 = uwal[x]; + int y2 = dwal[x]; + if (y2 <= y1) + continue; + + R_DrawSkyColumn(x, y1, y2, 1); + } + + // The aligned columns + for (int x = aligned_x1; x < aligned_x2; x += 4) + { + // Find y1, y2, light and uv values for four columns: + int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] }; + int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] }; + + // Figure out where we vertically can start and stop drawing 4 columns in one go + int middle_y1 = y1[0]; + int middle_y2 = y2[0]; + for (int i = 1; i < 4; i++) + { + middle_y1 = MAX(y1[i], middle_y1); + middle_y2 = MIN(y2[i], middle_y2); + } + + // If we got an empty column in our set we cannot draw 4 columns in one go: + bool empty_column_in_set = false; + for (int i = 0; i < 4; i++) + { + if (y2[i] <= y1[i]) + empty_column_in_set = true; + } + if (empty_column_in_set || middle_y2 <= middle_y1) + { + for (int i = 0; i < 4; i++) + { + if (y2[i] <= y1[i]) + continue; + + R_DrawSkyColumn(x + i, y1[i], y2[i], 1); + } + continue; + } + + // Draw the first rows where not all 4 columns are active + for (int i = 0; i < 4; i++) + { + if (y1[i] < middle_y1) + R_DrawSkyColumn(x + i, y1[i], middle_y1, 1); + } + + // Draw the area where all 4 columns are active + R_DrawSkyColumn(x, middle_y1, middle_y2, 4); + + // Draw the last rows where not all 4 columns are active + for (int i = 0; i < 4; i++) + { + if (middle_y2 < y2[i]) + R_DrawSkyColumn(x + i, middle_y2, y2[i], 1); + } + } + + // The last unaligned columns: + for (int x = aligned_x2; x < x2; x++) + { + int y1 = uwal[x]; + int y2 = dwal[x]; + if (y2 <= y1) + continue; + + R_DrawSkyColumn(x, y1, y2, 1); + } +} + static void R_DrawSky (visplane_t *pl) { + if (r_capsky) + { + R_DrawCapSky(pl); + return; + } + int x; float swal; diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 7b90c295f..f3c9e19a1 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -45,6 +45,7 @@ #include "v_video.h" #include "m_fixed.h" #include "textures/textures.h" +#include "v_palette.h" typedef bool (*CheckFunc)(FileReader & file); typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum); @@ -569,6 +570,78 @@ void FTexture::SetScaledSize(int fitwidth, int fitheight) if (int(Scale.Y * fitheight) != Height) Scale.Y += (1 / 65536.); } +//=========================================================================== +// +// Gets the average color of a texture for use as a sky cap color +// +//=========================================================================== + +namespace +{ + PalEntry averageColor(const DWORD *data, int size, int maxout) + { + int i; + unsigned int r, g, b; + + // First clear them. + r = g = b = 0; + if (size == 0) + { + return PalEntry(255, 255, 255); + } + for (i = 0; i < size; i++) + { + r += BPART(data[i]); + g += GPART(data[i]); + b += RPART(data[i]); + } + + r = r / size; + g = g / size; + b = b / size; + + int maxv = MAX(MAX(r, g), b); + + if (maxv && maxout) + { + r = Scale(r, maxout, maxv); + g = Scale(g, maxout, maxv); + b = Scale(b, maxout, maxv); + } + return PalEntry(255, r, g, b); + } +} + +PalEntry FTexture::GetSWSkyCapColor(bool bottom) +{ + PalEntry col; + int w; + int h; + + if (!bSWSkyColorDone) + { + bSWSkyColorDone = true; + + FBitmap bitmap; + bitmap.Create(GetWidth(), GetHeight()); + CopyTrueColorPixels(&bitmap, 0, 0); + int w = GetWidth(); + int h = GetHeight(); + + const uint32_t *buffer = (const uint32_t *)bitmap.GetPixels(); + if (buffer) + { + SWCeilingSkyColor = averageColor((DWORD *)buffer, w * MIN(30, h), 0); + if (h>30) + { + SWFloorSkyColor = averageColor(((DWORD *)buffer) + (h - 30)*w, w * 30, 0); + } + else SWFloorSkyColor = SWCeilingSkyColor; + } + } + return bottom ? SWFloorSkyColor : SWCeilingSkyColor; +} + FDummyTexture::FDummyTexture () { diff --git a/src/textures/textures.h b/src/textures/textures.h index 298b169f2..9402417f7 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -239,6 +239,7 @@ public: } void SetScaledSize(int fitwidth, int fitheight); + PalEntry GetSWSkyCapColor(bool bottom); virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches. @@ -259,6 +260,11 @@ protected: Rotations = other->Rotations; } +private: + bool bSWSkyColorDone = false; + PalEntry SWFloorSkyColor; + PalEntry SWCeilingSkyColor; + public: static void FlipSquareBlock (BYTE *block, int x, int y); static void FlipSquareBlockRemap (BYTE *block, int x, int y, const BYTE *remap); diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 50d14ab75..5a10527ac 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1787,6 +1787,7 @@ DSPLYMNU_PICKUPFADE = "Pickup Flash Intensity"; DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used DSPLYMNU_STRETCHSKY = "Stretch short skies"; +DSPLYMNU_CAPSKY = "Cap skies with solid color"; DSPLYMNU_DRAWFUZZ = "Use fuzz effect"; DSPLYMNU_TRANSSOUL = "Lost Soul translucency"; DSPLYMNU_FAKECONTRAST = "Use fake contrast"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index cd004bb0d..f7131be55 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -674,6 +674,7 @@ OptionMenu "VideoOptions" //Option "$DSPLYMNU_ATTACHEDSURFACES", "vid_attachedsurfaces", "OnOff" } + Option "$DSPLYMNU_CAPSKY", "r_capsky", "OnOff" Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 From 2fe545a4fdbaa0020517861d2d4de02f3e108a14 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 20 Oct 2016 00:59:51 +0200 Subject: [PATCH 6/8] Merge r_stretchsky and r_capsky into r_skymode --- src/r_plane.cpp | 4 ++-- src/r_sky.cpp | 5 +++-- wadsrc/static/language.enu | 6 ++++-- wadsrc/static/menudef.txt | 10 ++++++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 8c12b3ca2..5ddf36f59 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -63,7 +63,7 @@ #pragma warning(disable:4244) #endif -CVAR(Bool, r_capsky, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +EXTERN_CVAR(Int, r_skymode) //EXTERN_CVAR (Int, tx) //EXTERN_CVAR (Int, ty) @@ -1059,7 +1059,7 @@ static void R_DrawCapSky(visplane_t *pl) static void R_DrawSky (visplane_t *pl) { - if (r_capsky) + if (r_skymode == 2) { R_DrawCapSky(pl); return; diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 9ea44db48..58caa09bd 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -49,7 +49,8 @@ fixed_t sky1cyl, sky2cyl; double sky1pos, sky2pos; // [RH] Stretch sky texture if not taller than 128 pixels? -CUSTOM_CVAR (Bool, r_stretchsky, true, CVAR_ARCHIVE) +// Also now controls capped skies. 0 = normal, 1 = stretched, 2 = capped +CUSTOM_CVAR (Int, r_skymode, 2, CVAR_ARCHIVE) { R_InitSkyMap (); } @@ -99,7 +100,7 @@ void R_InitSkyMap () skytexturemid = 0; if (skyheight >= 128 && skyheight < 200) { - skystretch = (r_stretchsky + skystretch = (r_skymode == 1 && skyheight >= 128 && level.IsFreelookAllowed() && !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0; diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 5a10527ac..096d0832c 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1786,8 +1786,7 @@ DSPLYMNU_BLOODFADE = "Blood Flash Intensity"; DSPLYMNU_PICKUPFADE = "Pickup Flash Intensity"; DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used -DSPLYMNU_STRETCHSKY = "Stretch short skies"; -DSPLYMNU_CAPSKY = "Cap skies with solid color"; +DSPLYMNU_SKYMODE = "Sky render mode"; DSPLYMNU_DRAWFUZZ = "Use fuzz effect"; DSPLYMNU_TRANSSOUL = "Lost Soul translucency"; DSPLYMNU_FAKECONTRAST = "Use fake contrast"; @@ -2188,6 +2187,9 @@ OPTVAL_INVERTED = "Inverted"; OPTVAL_NOTINVERTED = "Not Inverted"; OPTVAL_ORIGINAL = "Original"; OPTVAL_OPTIMIZED = "Optimized"; +OPTVAL_NORMAL = "Normal"; +OPTVAL_STRETCH = "Stretch"; +OPTVAL_CAPPED = "Capped"; OPTVAL_PARTICLES = "Particles"; OPTVAL_SPRITES = "Sprites"; OPTVAL_SPRITESPARTICLES = "Sprites & Particles"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index f7131be55..7b06a7e7f 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -600,6 +600,13 @@ OptionValue ColumnMethods 1.0, "$OPTVAL_OPTIMIZED" } +OptionValue SkyModes +{ + 0.0, "$OPTVAL_NORMAL" + 1.0, "$OPTVAL_STRETCH" + 2.0, "$OPTVAL_CAPPED" +} + OptionValue RocketTrailTypes { 0.0, "$OPTVAL_OFF" @@ -674,8 +681,7 @@ OptionMenu "VideoOptions" //Option "$DSPLYMNU_ATTACHEDSURFACES", "vid_attachedsurfaces", "OnOff" } - Option "$DSPLYMNU_CAPSKY", "r_capsky", "OnOff" - Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" + Option "$DSPLYMNU_SKYMODE", "r_skymode", "SkyModes" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" From 19d070c9bd3b92c335e8378b098cfdd91207ee1a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 20 Oct 2016 09:08:07 +0200 Subject: [PATCH 7/8] - fixed: averageColor swapped red and blue. - renamed some stuff --- src/r_plane.cpp | 4 ++-- src/textures/texture.cpp | 14 +++++++------- src/textures/textures.h | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 5ddf36f59..07efb84b4 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -935,8 +935,8 @@ static void R_DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, doub dc_dest = (ylookup[y1] + start_x) + dc_destorg; dc_count = y2 - y1; - uint32_t solid_top = frontskytex->GetSWSkyCapColor(false); - uint32_t solid_bottom = frontskytex->GetSWSkyCapColor(true); + uint32_t solid_top = frontskytex->GetSkyCapColor(false); + uint32_t solid_bottom = frontskytex->GetSkyCapColor(true); if (columns == 4) if (!backskytex) diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index f3c9e19a1..bc0eaffa3 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -591,9 +591,9 @@ namespace } for (i = 0; i < size; i++) { - r += BPART(data[i]); + b += BPART(data[i]); g += GPART(data[i]); - b += RPART(data[i]); + r += RPART(data[i]); } r = r / size; @@ -612,7 +612,7 @@ namespace } } -PalEntry FTexture::GetSWSkyCapColor(bool bottom) +PalEntry FTexture::GetSkyCapColor(bool bottom) { PalEntry col; int w; @@ -631,15 +631,15 @@ PalEntry FTexture::GetSWSkyCapColor(bool bottom) const uint32_t *buffer = (const uint32_t *)bitmap.GetPixels(); if (buffer) { - SWCeilingSkyColor = averageColor((DWORD *)buffer, w * MIN(30, h), 0); + CeilingSkyColor = averageColor((DWORD *)buffer, w * MIN(30, h), 0); if (h>30) { - SWFloorSkyColor = averageColor(((DWORD *)buffer) + (h - 30)*w, w * 30, 0); + FloorSkyColor = averageColor(((DWORD *)buffer) + (h - 30)*w, w * 30, 0); } - else SWFloorSkyColor = SWCeilingSkyColor; + else FloorSkyColor = CeilingSkyColor; } } - return bottom ? SWFloorSkyColor : SWCeilingSkyColor; + return bottom ? FloorSkyColor : CeilingSkyColor; } diff --git a/src/textures/textures.h b/src/textures/textures.h index 9402417f7..ad1d9ba8c 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -239,7 +239,7 @@ public: } void SetScaledSize(int fitwidth, int fitheight); - PalEntry GetSWSkyCapColor(bool bottom); + PalEntry GetSkyCapColor(bool bottom); virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches. @@ -262,8 +262,8 @@ protected: private: bool bSWSkyColorDone = false; - PalEntry SWFloorSkyColor; - PalEntry SWCeilingSkyColor; + PalEntry FloorSkyColor; + PalEntry CeilingSkyColor; public: static void FlipSquareBlock (BYTE *block, int x, int y); From 4b956a2f2b4ac964c96fb37b68f9d7fd9657a68d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 20 Oct 2016 09:56:45 +0200 Subject: [PATCH 8/8] - added support for the skyoffset property that had been settable in ANIMDEFS for GZDoom. This will only have an effect in sky mode 2. --- src/r_sky.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 58caa09bd..37312cbae 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -48,6 +48,11 @@ bool skystretch; fixed_t sky1cyl, sky2cyl; double sky1pos, sky2pos; +CUSTOM_CVAR(Int, testskyoffset, 0, 0) +{ + R_InitSkyMap(); +} + // [RH] Stretch sky texture if not taller than 128 pixels? // Also now controls capped skies. 0 = normal, 1 = stretched, 2 = capped CUSTOM_CVAR (Int, r_skymode, 2, CVAR_ARCHIVE) @@ -55,6 +60,7 @@ CUSTOM_CVAR (Int, r_skymode, 2, CVAR_ARCHIVE) R_InitSkyMap (); } + int freelookviewheight; //========================================================================== @@ -108,7 +114,7 @@ void R_InitSkyMap () } else if (skyheight > 200) { - skytexturemid = (200 - skyheight) * skytex1->Scale.Y; + skytexturemid = (200 - skyheight) * skytex1->Scale.Y +(r_skymode == 2 ? skytex1->SkyOffset + testskyoffset : 0); } if (viewwidth != 0 && viewheight != 0)