From d6346fb0c6987a5bad559fee5b4a61b5270070dd Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 3 Oct 2016 21:44:00 +0300 Subject: [PATCH 01/62] Fixed compilation with GCC or Clang --- src/g_shared/sbarinfo_commands.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 13c98d833..d105ab818 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1187,12 +1187,12 @@ class CommandDrawNumber : public CommandDrawString if (!(cvartype == CVAR_Bool || cvartype == CVAR_Int)) { - sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName); + sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName.GetChars()); } } else { - sc.ScriptMessage("CVar '%s' does not exist", cvarName); + sc.ScriptMessage("CVar '%s' does not exist", cvarName.GetChars()); } if (parenthesized) sc.MustGetToken(')'); From 594b344be9a91bcd1da6bebb8b3047069554b8de Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Mon, 3 Oct 2016 22:00:49 -0500 Subject: [PATCH 02/62] Don't use MIN when clamping topclip. - This was fine with fixed point numbers, since they could never be outside of short range when converted to regular ints. With floating point numbers now, that condition no longer holds. --- src/r_things.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index a45a6826a..179ffec97 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2097,7 +2097,7 @@ void R_DrawSprite (vissprite_t *spr) { // seen below floor: clip top if (!spr->bIsVoxel && h > topclip) { - topclip = MIN (h, viewheight); + topclip = short(MIN(h, viewheight)); } hzt = MIN(hzt, hz); } @@ -2127,7 +2127,7 @@ void R_DrawSprite (vissprite_t *spr) { // seen in the middle: clip top if (!spr->bIsVoxel && h > topclip) { - topclip = MIN (h, viewheight); + topclip = MIN(h, viewheight); } hzt = MIN(hzt, hz); } @@ -2181,7 +2181,7 @@ void R_DrawSprite (vissprite_t *spr) int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); if (h > topclip) { - topclip = MIN(h, viewheight); + topclip = short(MIN(h, viewheight)); } } hzt = MIN(hzt, sclipTop); @@ -2204,7 +2204,7 @@ void R_DrawSprite (vissprite_t *spr) h = (centeryfrac - FixedMul (h-viewz, scale)) >> FRACBITS; if (h > topclip) { - topclip = MIN (h, viewheight); + topclip = short(MIN(h, viewheight)); } } #endif From 15cbf4bae66359a3ffe9eb2b20b30ca31df39768 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 4 Oct 2016 09:28:19 +0200 Subject: [PATCH 03/62] - fixed: DecoHandleRuntimeState must check all parent classes when trying to determine if the target is a valid state. It should also ensure that both the calling and target state belong to the same actor. Although unlikely it cannot be entirely ruled out that a bogus index randomly points to a seemingly valid state elsewhere. --- src/thingdef/thingdef_expression.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 700ac94bb..c2b2d25e6 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -4956,6 +4956,25 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) return this; } +static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int index) +{ + PClassActor *cls = stateowner->GetClass(); + + while (cls != RUNTIME_CLASS(AActor)) + { + // both calling and target state need to belong to the same class. + if (cls->OwnsState(stateinfo->mCallingState)) + { + return cls->OwnsState(stateinfo->mCallingState + index); + } + + // We can safely assume the ParentClass is of type PClassActor + // since we stop when we see the Actor base class. + cls = static_cast(cls->ParentClass); + } + return false; +} + static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) { PARAM_PROLOGUE; @@ -4963,7 +4982,7 @@ static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numpa PARAM_POINTER(stateinfo, FStateParamInfo); PARAM_INT(index); - if (index == 0 || !stateowner->GetClass()->OwnsState(stateinfo->mCallingState + index)) + if (index == 0 || !VerifyJumpTarget(stateowner, stateinfo, index)) { // Null is returned if the location was invalid which means that no jump will be performed // if used as return value From 0e9f808c8a3000b376aa607a987a8d96a969a45f Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 4 Oct 2016 10:04:33 -0500 Subject: [PATCH 04/62] Fixed: FLATSPRITES were drawn backwards. --- src/gl/scene/gl_sprite.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index ab88f2f9c..e9748fba6 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -138,10 +138,10 @@ void GLSprite::CalculateVertices(FVector3 *v) mat.Rotate(0, 1, 0, - actor->Angles.Roll.Degrees); mat.Translate(-x, -z, -y); } - v[0] = mat * FVector3(x1, z, y2); - v[1] = mat * FVector3(x2, z, y2); - v[2] = mat * FVector3(x1, z, y1); - v[3] = mat * FVector3(x2, z, y1); + v[0] = mat * FVector3(x2, z, y2); + v[1] = mat * FVector3(x1, z, y2); + v[2] = mat * FVector3(x2, z, y1); + v[3] = mat * FVector3(x1, z, y1); return; } From 2d320a2e86ba63b438c6423bc80035415e22f26a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 09:59:19 +0200 Subject: [PATCH 05/62] - added an option to disable the pickup screen flash. --- src/g_shared/a_pickups.cpp | 4 +++- wadsrc/static/language.enu | 1 + wadsrc/static/menudef.txt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index e80e54818..d24f114bd 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -23,6 +23,8 @@ #include "serializer.h" static FRandom pr_restore ("RestorePos"); +CVAR(Bool, r_pickupflash, true, CVAR_ARCHIVE); + IMPLEMENT_CLASS(PClassInventory) @@ -1089,7 +1091,7 @@ void AInventory::Touch (AActor *toucher) if (player != NULL) { PlayPickupSound (player->mo); - if (!(ItemFlags & IF_NOSCREENFLASH)) + if (!(ItemFlags & IF_NOSCREENFLASH) && r_pickupflash) { player->bonuscount = BONUSADD; } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 4839e1146..87ecb865b 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1803,6 +1803,7 @@ DSPLYMNU_DIMCOLOR = "Dim color"; DSPLYMNU_MOVEBOB = "View bob amount while moving"; DSPLYMNU_STILLBOB = "View bob amount while not moving"; DSPLYMNU_BOBSPEED = "Weapon bob speed"; +DSPLYMNU_PIFLASH = "Show pickup screen flash"; // HUD Options HUDMNU_TITLE = "HUD Options"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 0bcbd3af7..17eb80666 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -675,6 +675,7 @@ OptionMenu "VideoOptions" Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 + Option "$DSPLYMNU_PIFLASH", "r_pickupflash", "OnOff" Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes" Option "$DSPLYMNU_BLOODTYPE", "cl_bloodtype", "BloodTypes" From 5b350dcdd502b5c744ec67ebde7e7d2279033e86 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 16:27:12 +0200 Subject: [PATCH 06/62] - gave Boom's point pusher and puller things the NOCLIP flag so that they won't get moved around by scrollers. --- wadsrc/static/actors/shared/sharedmisc.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wadsrc/static/actors/shared/sharedmisc.txt b/wadsrc/static/actors/shared/sharedmisc.txt index bfe7d5519..fe5ac72d8 100644 --- a/wadsrc/static/actors/shared/sharedmisc.txt +++ b/wadsrc/static/actors/shared/sharedmisc.txt @@ -75,12 +75,14 @@ ACTOR PointPusher { +NOBLOCKMAP +INVISIBLE + +NOCLIP } ACTOR PointPuller { +NOBLOCKMAP +INVISIBLE + +NOCLIP } // Bloody gibs ------------------------------------------------------------- From aeb5377821df5914d2d279c43dedf57190f4e6bb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 16:45:12 +0200 Subject: [PATCH 07/62] - do not generate SYSEX events when playing MIDIs through FMod, because there has been a report that it doesn't work correctly. --- src/sound/music_hmi_midiout.cpp | 2 +- src/sound/music_smf_midiout.cpp | 2 +- src/sound/music_xmi_midiout.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/music_hmi_midiout.cpp b/src/sound/music_hmi_midiout.cpp index 21790784c..7d9d36926 100644 --- a/src/sound/music_hmi_midiout.cpp +++ b/src/sound/music_hmi_midiout.cpp @@ -657,7 +657,7 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdi if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = ReadVarLen(track); - if (len >= (MAX_EVENTS-1)*3*4) + if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) { // This message will never fit. Throw it away. track->TrackP += len; } diff --git a/src/sound/music_smf_midiout.cpp b/src/sound/music_smf_midiout.cpp index ffcbc9f62..a045998a8 100644 --- a/src/sound/music_smf_midiout.cpp +++ b/src/sound/music_smf_midiout.cpp @@ -598,7 +598,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = track->ReadVarLen(); - if (len >= (MAX_EVENTS-1)*3*4) + if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) { // This message will never fit. Throw it away. track->TrackP += len; } diff --git a/src/sound/music_xmi_midiout.cpp b/src/sound/music_xmi_midiout.cpp index a9cbcd2c6..b56e8f6f8 100644 --- a/src/sound/music_xmi_midiout.cpp +++ b/src/sound/music_xmi_midiout.cpp @@ -528,7 +528,7 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay, ptrdif if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = track->ReadVarLen(); - if (len >= (MAX_EVENTS-1)*3*4) + if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) { // This message will never fit. Throw it away. track->EventP += len; } From 59d5b42abf1e716027c0fdf10d076912e0ce1454 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 19:02:53 +0200 Subject: [PATCH 08/62] - fixed: G_UnsnapshotLevel should abort with an error if it cannot read the savegame. - fixed: The exception handler in G_DoLoadGame needs to rethrow the exception it receives. --- src/g_game.cpp | 2 +- src/g_level.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 629202ea5..48bda24f5 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1999,7 +1999,7 @@ void G_DoLoadGame () { // delete the resource file if anything goes wrong in here. if (resfile != nullptr) delete resfile; - return; + throw; } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 90b31138d..119cde378 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1512,7 +1512,11 @@ void G_UnSnapshotLevel (bool hubLoad) if (level.info->isValid()) { FSerializer arc; - if (!arc.OpenReader(&level.info->Snapshot)) return; + if (!arc.OpenReader(&level.info->Snapshot)) + { + I_Error("Failed to load savegame"); + return; + } G_SerializeLevel (arc, hubLoad); level.FromSnapshot = true; From c56d2eecb005c6bbb8000c70cedc6f537123ba57 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 08:50:46 +0200 Subject: [PATCH 09/62] - rewrote AActor::DestroyAllInventory so that it clears the item's link to its owner and the owner's inventory list before destroying them. There have been reports about crashes in here with Linux that point to some of the code that gets called here doing unwanted things on the owner, so with these links cleared that should no longer be possible. --- src/p_mobj.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 496f52e86..022504919 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -685,11 +685,30 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate void AActor::DestroyAllInventory () { - while (Inventory != NULL) + AInventory *inv = Inventory; + if (inv != nullptr) { - AInventory *item = Inventory; - item->Destroy (); - assert (item != Inventory); + TArray toDelete; + + // Delete the list in a two stage approach. + // This is necessary because an item may destroy another item (e.g. sister weapons) + // which would break the list and leave parts of it undestroyed, maybe doing bad things later. + while (inv != nullptr) + { + toDelete.Push(inv); + AInventory *item = inv->Inventory; + inv->Inventory = nullptr; + inv->Owner = nullptr; + inv = item; + } + for (auto p : toDelete) + { + // the item may already have been deleted by another one, so check this here to avoid problems. + if (!(p->ObjectFlags & OF_EuthanizeMe)) + { + p->Destroy(); + } + } } } From d7bb5bb41ed8e853095d5207b74a2079589c716e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 12:08:38 +0200 Subject: [PATCH 10/62] - fixed: ZCC_OpInfoType::FindBestProto was missing checks for exact match of the required conversion before testing if it is a F32->F64 conversion. Of course, since 0 means that there is no conversion it also means that there is no data that could be checked. --- src/zscript/zcc_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zscript/zcc_expr.cpp b/src/zscript/zcc_expr.cpp index 0cd399d64..e1a091b18 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/zscript/zcc_expr.cpp @@ -162,11 +162,11 @@ ZCC_OpProto *ZCC_OpInfoType::FindBestProto( // [[float32 (op) int]] will choose the integer version instead of the floating point // version, which we do not want. int test_dist1 = dist1, test_dist2 = dist2; - if (routes[0][cur_route1][0]->ConvertConstant == FtoD) + if (test_dist1 > 0 && routes[0][cur_route1][0]->ConvertConstant == FtoD) { test_dist1--; } - if (routes[1][cur_route2][0]->ConvertConstant == FtoD) + if (test_dist2 > 0 && routes[1][cur_route2][0]->ConvertConstant == FtoD) { test_dist2--; } From 99c4d03ad4b3151375edb8b015bd25021c2e3193 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 21:20:49 +0200 Subject: [PATCH 11/62] - fixed: DCeiling's main constructor could leave some fields uninitialized. --- src/p_ceiling.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 32e5d62be..e90dd2096 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -214,6 +214,12 @@ DCeiling::DCeiling (sector_t *sec, double speed1, double speed2, int silent) m_Speed = m_Speed1 = speed1; m_Speed2 = speed2; m_Silent = silent; + m_BottomHeight = 0; + m_TopHeight = 0; + m_Direction = 0; + m_Texture = FNullTextureID(); + m_Tag = 0; + m_OldDirection = 0; } //============================================================================ From 02f66fa34e2bdb63ca1ba740c5b35b7388550120 Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Thu, 6 Oct 2016 20:01:20 -0400 Subject: [PATCH 12/62] - Backported blood_fade_scalar from Skulltag - Added new pickup_fade_scalar which works the same way for pickups - Default for blood_fade_scalar is 1.0 instead of 0.5 from Skulltag. --- src/v_blend.cpp | 11 +++++++++-- wadsrc/static/menudef.txt | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/v_blend.cpp b/src/v_blend.cpp index e1552105f..c13ed547c 100644 --- a/src/v_blend.cpp +++ b/src/v_blend.cpp @@ -52,7 +52,8 @@ #include "v_palette.h" #include "d_player.h" - +CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0 +CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups // [RH] Amount of red flash for up to 114 damage points. Calculated by hand // using a logarithmic scale and my trusty HP48G. @@ -113,6 +114,9 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int if (CPlayer->bonuscount) { cnt = CPlayer->bonuscount << 3; + + // [SP] Allow player to tone down intensity of pickup flash. + cnt = (int)( cnt * pickup_fade_scalar ); V_AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f, BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend); @@ -124,7 +128,10 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int if (painFlash.a != 0) { cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)]; - + + // [BC] Allow users to tone down the intensity of the blood on the screen. + cnt = (int)( cnt * blood_fade_scalar ); + if (cnt) { if (cnt > maxpainblend) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 17eb80666..95eedaf25 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -660,6 +660,8 @@ OptionMenu "VideoOptions" Slider "$DSPLYMNU_BRIGHTNESS", "Gamma", 0.75, 3.0, 0.05, 2 Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn" + Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 1 + Slider "$DSPLYMNU_PICKUPFADE", "pickup_fade_scalar", 0.0, 1.0, 0.05, 1 Option "$DSPLYMNU_COLUMNMETHOD", "r_columnmethod", "ColumnMethods" StaticText " " @@ -692,6 +694,7 @@ OptionMenu "VideoOptions" Slider "$DSPLYMNU_MOVEBOB", "movebob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_STILLBOB", "stillbob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1, 2 + } //------------------------------------------------------------------------------------------- From 3ccc85876c342a565fe74cd711ff592f5a4bea0c Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Thu, 6 Oct 2016 20:05:30 -0400 Subject: [PATCH 13/62] - Forgot to add language entries. --- wadsrc/static/language.enu | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 87ecb865b..dafd80617 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1782,6 +1782,8 @@ DSPLYMNU_CAPFPS = "Rendering Interpolation"; DSPLYMNU_COLUMNMETHOD = "Column render mode"; DSPLYMNU_WIPETYPE = "Screen wipe style"; DSPLYMNU_SHOWENDOOM = "Show ENDOOM screen"; +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"; From ee66d220348f32d8c1baa2db753c2690f51017ef Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 08:46:06 +0200 Subject: [PATCH 14/62] Revert "- added an option to disable the pickup screen flash." This reverts commit 2d320a2e86ba63b438c6423bc80035415e22f26a. The feature has been superseded by pickup_fade_scalar and is no longer needed. --- src/g_shared/a_pickups.cpp | 4 +--- wadsrc/static/language.enu | 1 - wadsrc/static/menudef.txt | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index d24f114bd..e80e54818 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -23,8 +23,6 @@ #include "serializer.h" static FRandom pr_restore ("RestorePos"); -CVAR(Bool, r_pickupflash, true, CVAR_ARCHIVE); - IMPLEMENT_CLASS(PClassInventory) @@ -1091,7 +1089,7 @@ void AInventory::Touch (AActor *toucher) if (player != NULL) { PlayPickupSound (player->mo); - if (!(ItemFlags & IF_NOSCREENFLASH) && r_pickupflash) + if (!(ItemFlags & IF_NOSCREENFLASH)) { player->bonuscount = BONUSADD; } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index dafd80617..50d14ab75 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1805,7 +1805,6 @@ DSPLYMNU_DIMCOLOR = "Dim color"; DSPLYMNU_MOVEBOB = "View bob amount while moving"; DSPLYMNU_STILLBOB = "View bob amount while not moving"; DSPLYMNU_BOBSPEED = "Weapon bob speed"; -DSPLYMNU_PIFLASH = "Show pickup screen flash"; // HUD Options HUDMNU_TITLE = "HUD Options"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 95eedaf25..cd004bb0d 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -677,7 +677,6 @@ OptionMenu "VideoOptions" Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 - Option "$DSPLYMNU_PIFLASH", "r_pickupflash", "OnOff" Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes" Option "$DSPLYMNU_BLOODTYPE", "cl_bloodtype", "BloodTypes" From 06ca41f8b51572717fd7b78a907bb8b9390b0b35 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 13:59:29 +0200 Subject: [PATCH 15/62] - do not declare PNamedType::Outer as DObject. Ultimately we may have to get a fully qualified name out of this, so Outer should be a type that can handle this feature. The new class for this is currently used as base for PType and PSymbol so that PNamedType inherits from it and maybe later a namespace symbol can, too. --- src/dobjtype.cpp | 23 +++++++++++++++++++---- src/dobjtype.h | 37 +++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 9693da137..c3d0702f3 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -670,6 +670,20 @@ void PNamedType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = TypeName; } +//========================================================================== +// +// PNamedType :: QualifiedName +// +//========================================================================== + +FString PNamedType::QualifiedName() const +{ + FString out; + if (Outer != nullptr) out = Outer->QualifiedName(); + out << "::" << TypeName; + return out; +} + /* PInt *******************************************************************/ IMPLEMENT_CLASS(PInt) @@ -1752,7 +1766,7 @@ PEnum::PEnum() // //========================================================================== -PEnum::PEnum(FName name, DObject *outer) +PEnum::PEnum(FName name, PTypeBase *outer) : PNamedType(name, outer), ValueType(NULL) { } @@ -1766,7 +1780,7 @@ PEnum::PEnum(FName name, DObject *outer) // //========================================================================== -PEnum *NewEnum(FName name, DObject *outer) +PEnum *NewEnum(FName name, PTypeBase *outer) { size_t bucket; PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket); @@ -2149,7 +2163,7 @@ PStruct::PStruct() // //========================================================================== -PStruct::PStruct(FName name, DObject *outer) +PStruct::PStruct(FName name, PTypeBase *outer) : PNamedType(name, outer) { } @@ -2310,7 +2324,7 @@ size_t PStruct::PropagateMark() // //========================================================================== -PStruct *NewStruct(FName name, DObject *outer) +PStruct *NewStruct(FName name, PTypeBase *outer) { size_t bucket; PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket); @@ -3360,6 +3374,7 @@ CCMD(typetable) // Symbol tables ------------------------------------------------------------ +IMPLEMENT_ABSTRACT_CLASS(PTypeBase); IMPLEMENT_ABSTRACT_CLASS(PSymbol); IMPLEMENT_CLASS(PSymbolConst); IMPLEMENT_CLASS(PSymbolConstNumeric); diff --git a/src/dobjtype.h b/src/dobjtype.h index 62cfa6753..338c51f98 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -22,12 +22,28 @@ typedef std::pair FTypeAndOffset; // Symbol information ------------------------------------------------------- -class PSymbol : public DObject +class PTypeBase : public DObject { - DECLARE_ABSTRACT_CLASS(PSymbol, DObject); + DECLARE_ABSTRACT_CLASS(PTypeBase, DObject) + +public: + virtual FString QualifiedName() const + { + return ""; + } +}; + +class PSymbol : public PTypeBase +{ + DECLARE_ABSTRACT_CLASS(PSymbol, PTypeBase); public: virtual ~PSymbol(); + virtual FString QualifiedName() const + { + return SymbolName.GetChars(); + } + FName SymbolName; protected: @@ -153,13 +169,13 @@ extern PSymbolTable GlobalSymbols; struct ZCC_ExprConstant; class PClassType; -class PType : public DObject +class PType : public PTypeBase { //DECLARE_ABSTRACT_CLASS_WITH_META(PType, DObject, PClassType); // We need to unravel the _WITH_META macro, since PClassType isn't defined yet, // and we can't define it until we've defined PClass. But we can't define that // without defining PType. - DECLARE_ABSTRACT_CLASS(PType, DObject) + DECLARE_ABSTRACT_CLASS(PType, PTypeBase) HAS_OBJECT_POINTERS; protected: enum { MetaClassNum = CLASSREG_PClassType }; @@ -332,14 +348,15 @@ class PNamedType : public PCompoundType DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType); HAS_OBJECT_POINTERS; public: - DObject *Outer; // object this type is contained within + PTypeBase *Outer; // object this type is contained within FName TypeName; // this type's name PNamedType() : Outer(NULL) {} - PNamedType(FName name, DObject *outer) : Outer(outer), TypeName(name) {} + PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {} virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + virtual FString QualifiedName() const; }; // Basic types -------------------------------------------------------------- @@ -533,7 +550,7 @@ class PEnum : public PNamedType DECLARE_CLASS(PEnum, PNamedType); HAS_OBJECT_POINTERS; public: - PEnum(FName name, DObject *outer); + PEnum(FName name, PTypeBase *outer); PType *ValueType; TMap Values; @@ -610,7 +627,7 @@ class PStruct : public PNamedType { DECLARE_CLASS(PStruct, PNamedType); public: - PStruct(FName name, DObject *outer); + PStruct(FName name, PTypeBase *outer); TArray Fields; @@ -822,8 +839,8 @@ PDynArray *NewDynArray(PType *type); PPointer *NewPointer(PType *type); PClassPointer *NewClassPointer(PClass *restrict); PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname); -PEnum *NewEnum(FName name, DObject *outer); -PStruct *NewStruct(FName name, DObject *outer); +PEnum *NewEnum(FName name, PTypeBase *outer); +PStruct *NewStruct(FName name, PTypeBase *outer); PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes); // Built-in types ----------------------------------------------------------- From d819aafcf309dcce2caff2215a7c8b108f9abc27 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 15:28:25 +0200 Subject: [PATCH 16/62] - changed handling of duplicate classes in DECORATE. Instead of replacing the original, the second class will get renamed now, using the originating file as an identifier. In the vast majority of cases this should do exactly what is needed: Create an unconflicting second class that can coexist with the original. Unless the class is used by name this should eliminate all problems with this, but so far I haven't seen anything that used them by name. This is choosing the lesser of two evils. While some mod out there may get broken, the old setup meant that the first class of a given name could not be written out to a savegame because it was not retrievable when loading it back. --- src/d_dehacked.cpp | 15 ++++++++--- src/dobjtype.cpp | 25 ++++++++++-------- src/thingdef/olddecorations.cpp | 3 ++- src/thingdef/thingdef.cpp | 45 +++++++++++++++++++++++++++++++-- 4 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 9e068b596..dd71fdf75 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2985,9 +2985,11 @@ static bool LoadDehSupp () void FinishDehPatch () { unsigned int touchedIndex; + unsigned int nameindex = 0; for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex) { + PClassActor *subclass; PClassActor *type = TouchedActors[touchedIndex]; AActor *defaults1 = GetDefaultByType (type); if (!(defaults1->flags & MF_SPECIAL)) @@ -2997,9 +2999,16 @@ void FinishDehPatch () // Create a new class that will serve as the actual pickup char typeNameBuilder[32]; - mysnprintf (typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", touchedIndex); - PClassActor *subclass = static_cast(RUNTIME_CLASS(ADehackedPickup)-> - CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup))); + // + do + { + // Retry until we find a free name. This is unlikely to happen but not impossible. + mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++); + subclass = static_cast(RUNTIME_CLASS(ADehackedPickup)-> + CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup))); + } + while (subclass == nullptr); + AActor *defaults2 = GetDefaultByType (subclass); memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c3d0702f3..37ff26fe3 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2861,10 +2861,7 @@ void PClass::InsertIntoHash () found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket); if (found != NULL) { // This type has already been inserted - // ... but there is no need whatsoever to make it a fatal error! - if (!strictdecorate) Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); - else I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); - TypeTable.ReplaceType(this, found, bucket); + I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); } else { @@ -3029,15 +3026,23 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) PClass *existclass = static_cast(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket)); // This is a placeholder so fill it in - if (existclass != NULL && (existclass->Size == TentativeClass)) + if (existclass != nullptr) { - type = const_cast(existclass); - if (!IsDescendantOf(type->ParentClass)) + if (existclass->Size == TentativeClass) { - I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + type = const_cast(existclass); + if (!IsDescendantOf(type->ParentClass)) + { + I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + } + DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars()); + notnew = true; + } + else + { + // a different class with the same name already exists. Let the calling code deal with this. + return nullptr; } - DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars()); - notnew = true; } else { diff --git a/src/thingdef/olddecorations.cpp b/src/thingdef/olddecorations.cpp index 3ea0c4788..9afbfc965 100644 --- a/src/thingdef/olddecorations.cpp +++ b/src/thingdef/olddecorations.cpp @@ -140,6 +140,7 @@ DEFINE_CLASS_PROPERTY(respawns, 0, FakeInventory) // Reads an old style decoration object // //========================================================================== +PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName); void ParseOldDecoration(FScanner &sc, EDefinitionType def) { @@ -154,7 +155,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) sc.MustGetString(); typeName = FName(sc.String); - type = static_cast(parent->CreateDerivedClass (typeName, parent->Size)); + type = DecoDerivedClass(FScriptPosition(sc), parent, typeName); ResetBaggage(&bag, parent); bag.Info = type; #ifdef _DEBUG diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 32d4f1ce0..41e1e9542 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -68,13 +68,44 @@ TDeletingArray ActorDamageFuncs; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void InitThingdef(); -void ParseDecorate (FScanner &sc); +void ParseDecorate(FScanner &ctx); // STATIC FUNCTION PROTOTYPES -------------------------------------------- PClassActor *QuestItemClasses[31]; +EXTERN_CVAR(Bool, strictdecorate); + +PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName) +{ + PClassActor *type = static_cast(parent->CreateDerivedClass(typeName, parent->Size)); + if (type == nullptr) + { + FString newname = typeName.GetChars(); + FString sourcefile = sc.FileName; + + sourcefile.Substitute(":", "@"); + newname << '@' << sourcefile; + if (strictdecorate) + { + sc.Message(MSG_ERROR, "Tried to define class '%s' more than once.", typeName.GetChars()); + } + else + { + // Due to backwards compatibility issues this cannot be an unconditional error. + sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars()); + } + type = static_cast(parent->CreateDerivedClass(newname, parent->Size)); + if (type == nullptr) + { + // This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless. + sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars()); + } + } + return type; +} //========================================================================== // // Starts a new actor definition @@ -141,7 +172,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par else { create: - ti = static_cast(parent->CreateDerivedClass (typeName, parent->Size)); + ti = DecoDerivedClass(sc, parent, typeName); } ti->Replacee = ti->Replacement = NULL; @@ -428,6 +459,16 @@ void LoadActors () while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) { FScanner sc(lump); + + if (Wads.GetLumpFile(lump) == 0) + { + // define namespace 'zdoom' + } + else + { + // use namespace 'zdoom' + } + ParseDecorate (sc); } FinishThingdef(); From 9a72ef1bf1c985e34f21c3fe5817b37e82b0b65c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 8 Oct 2016 15:47:16 +0300 Subject: [PATCH 17/62] Added detection of current macOS version --- src/posix/cocoa/i_main.mm | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index bbe344809..d8f0e74cf 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -130,6 +130,53 @@ void Mac_I_FatalError(const char* const message) } +static void I_DetectOS() +{ + SInt32 majorVersion = 0; + Gestalt(gestaltSystemVersionMajor, &majorVersion); + + SInt32 minorVersion = 0; + Gestalt(gestaltSystemVersionMinor, &minorVersion); + + SInt32 bugFixVersion = 0; + Gestalt(gestaltSystemVersionBugFix, &bugFixVersion); + + const char* name = "Unknown version"; + + if (10 == majorVersion) switch (minorVersion) + { + case 4: name = "Mac OS X Tiger"; break; + case 5: name = "Mac OS X Leopard"; break; + case 6: name = "Mac OS X Snow Leopard"; break; + case 7: name = "Mac OS X Lion"; break; + case 8: name = "OS X Mountain Lion"; break; + case 9: name = "OS X Mavericks"; break; + case 10: name = "OS X Yosemite"; break; + case 11: name = "OS X El Capitan"; break; + case 12: name = "macOS Sierra"; break; + } + + char release[16] = {}; + size_t size = sizeof release - 1; + sysctlbyname("kern.osversion", release, &size, nullptr, 0); + + const char* const architecture = +#ifdef __i386__ + "32-bit Intel"; +#elif defined __x86_64__ + "64-bit Intel"; +#elif defined __ppc__ + "32-bit PowerPC"; +#elif defined __ppc64__ + "64-bit PowerPC"; +#else + "Unknown"; +#endif + + Printf("OS: %s %d.%d.%d (%s) %s\n", name, majorVersion, minorVersion, bugFixVersion, release, architecture); +} + + DArgs* Args; // command line arguments @@ -165,6 +212,8 @@ void OriginalMainTry(int argc, char** argv) progdir += "/"; C_InitConsole(80 * 8, 25 * 8, false); + + I_DetectOS(); D_DoomMain(); } From 779e6acb7bed8b0fa265c85fc63e28d039808512 Mon Sep 17 00:00:00 2001 From: Christopher Bruns Date: Sun, 9 Oct 2016 13:05:50 -0400 Subject: [PATCH 18/62] Create "final" two non-VR 3D modes: Column-interleaved and checkerboard. --- src/gl/renderer/gl_renderbuffers.h | 1 - src/gl/renderer/gl_renderer.cpp | 6 + src/gl/renderer/gl_renderer.h | 4 + src/gl/shaders/gl_present3dRowshader.cpp | 40 ++++-- src/gl/shaders/gl_present3dRowshader.h | 33 +++-- src/gl/shaders/gl_presentshader.cpp | 25 ++-- src/gl/shaders/gl_presentshader.h | 16 ++- src/gl/stereo3d/gl_interleaved3d.cpp | 133 +++++++++++++++--- src/gl/stereo3d/gl_interleaved3d.h | 21 ++- src/gl/stereo3d/gl_stereo_cvars.cpp | 6 + wadsrc/static/language.enu | 2 + wadsrc/static/menudef.zz | 2 + .../static/shaders/glsl/present_checker3d.fp | 37 +++++ .../static/shaders/glsl/present_column3d.fp | 35 +++++ wadsrc/static/shaders/glsl/present_row3d.fp | 6 +- 15 files changed, 300 insertions(+), 67 deletions(-) create mode 100644 wadsrc/static/shaders/glsl/present_checker3d.fp create mode 100644 wadsrc/static/shaders/glsl/present_column3d.fp diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 5fe05f5ac..4477718f4 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -2,7 +2,6 @@ #define __GL_RENDERBUFFERS_H #include "gl/shaders/gl_shader.h" -#include "gl/renderer/gl_renderer.h" class FGLBloomTextureLevel { diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index be1b96f15..0ffafef49 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -105,6 +105,8 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mTonemapPalette = nullptr; mBuffers = nullptr; mPresentShader = nullptr; + mPresent3dCheckerShader = nullptr; + mPresent3dColumnShader = nullptr; mPresent3dRowShader = nullptr; mBloomExtractShader = nullptr; mBloomCombineShader = nullptr; @@ -139,6 +141,8 @@ void FGLRenderer::Initialize(int width, int height) mFXAAShader = new FFXAAShader; mFXAALumaShader = new FFXAALumaShader; mPresentShader = new FPresentShader(); + mPresent3dCheckerShader = new FPresent3DCheckerShader(); + mPresent3dColumnShader = new FPresent3DColumnShader(); mPresent3dRowShader = new FPresent3DRowShader(); m2DDrawer = new F2DDrawer; @@ -192,6 +196,8 @@ FGLRenderer::~FGLRenderer() } if (mBuffers) delete mBuffers; if (mPresentShader) delete mPresentShader; + if (mPresent3dCheckerShader) delete mPresent3dCheckerShader; + if (mPresent3dColumnShader) delete mPresent3dColumnShader; if (mPresent3dRowShader) delete mPresent3dRowShader; if (mBloomExtractShader) delete mBloomExtractShader; if (mBloomCombineShader) delete mBloomCombineShader; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 65e31c52f..19bc93af0 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -31,6 +31,8 @@ class FLensShader; class FFXAALumaShader; class FFXAAShader; class FPresentShader; +class FPresent3DCheckerShader; +class FPresent3DColumnShader; class FPresent3DRowShader; class F2DDrawer; class FHardwareTexture; @@ -109,6 +111,8 @@ public: FFXAALumaShader *mFXAALumaShader; FFXAAShader *mFXAAShader; FPresentShader *mPresentShader; + FPresent3DCheckerShader *mPresent3dCheckerShader; + FPresent3DColumnShader *mPresent3dColumnShader; FPresent3DRowShader *mPresent3dRowShader; FTexture *gllight; diff --git a/src/gl/shaders/gl_present3dRowshader.cpp b/src/gl/shaders/gl_present3dRowshader.cpp index 607e4ede6..d8369a3b6 100644 --- a/src/gl/shaders/gl_present3dRowshader.cpp +++ b/src/gl/shaders/gl_present3dRowshader.cpp @@ -38,23 +38,37 @@ #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_present3dRowshader.h" +void FPresentStereoShaderBase::Init(const char * vtx_shader_name, const char * program_name) +{ + FPresentShaderBase::Init(vtx_shader_name, program_name); + LeftEyeTexture.Init(mShader, "LeftEyeTexture"); + RightEyeTexture.Init(mShader, "RightEyeTexture"); + WindowPositionParity.Init(mShader, "WindowPositionParity"); +} + +void FPresent3DCheckerShader::Bind() +{ + if (!mShader) + { + Init("shaders/glsl/present_checker3d.fp", "shaders/glsl/presentChecker3d"); + } + mShader.Bind(); +} + +void FPresent3DColumnShader::Bind() +{ + if (!mShader) + { + Init("shaders/glsl/present_column3d.fp", "shaders/glsl/presentColumn3d"); + } + mShader.Bind(); +} + void FPresent3DRowShader::Bind() { if (!mShader) { - mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); - mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present_row3d.fp", "", 330); - mShader.SetFragDataLocation(0, "FragColor"); - mShader.Link("shaders/glsl/presentRow3d"); - mShader.SetAttribLocation(0, "PositionInProjection"); - mShader.SetAttribLocation(1, "UV"); - LeftEyeTexture.Init(mShader, "LeftEyeTexture"); - RightEyeTexture.Init(mShader, "RightEyeTexture"); - InvGamma.Init(mShader, "InvGamma"); - Contrast.Init(mShader, "Contrast"); - Brightness.Init(mShader, "Brightness"); - Scale.Init(mShader, "UVScale"); - VerticalPixelOffset.Init(mShader, "VerticalPixelOffset"); + Init("shaders/glsl/present_row3d.fp", "shaders/glsl/presentRow3d"); } mShader.Bind(); } diff --git a/src/gl/shaders/gl_present3dRowshader.h b/src/gl/shaders/gl_present3dRowshader.h index 8e3bd772d..10419d7f5 100644 --- a/src/gl/shaders/gl_present3dRowshader.h +++ b/src/gl/shaders/gl_present3dRowshader.h @@ -29,22 +29,35 @@ #define GL_PRESENT3DROWSHADER_H_ #include "gl_shaderprogram.h" +#include "gl_presentshader.h" -class FPresent3DRowShader +class FPresentStereoShaderBase : public FPresentShaderBase { public: - void Bind(); - FBufferedUniformSampler LeftEyeTexture; FBufferedUniformSampler RightEyeTexture; - FBufferedUniform1f InvGamma; - FBufferedUniform1f Contrast; - FBufferedUniform1f Brightness; - FBufferedUniform2f Scale; - FBufferedUniform1i VerticalPixelOffset; + FBufferedUniform1i WindowPositionParity; -private: - FShaderProgram mShader; +protected: + void Init(const char * vtx_shader_name, const char * program_name) override; +}; + +class FPresent3DCheckerShader : public FPresentStereoShaderBase +{ +public: + void Bind() override; +}; + +class FPresent3DColumnShader : public FPresentStereoShaderBase +{ +public: + void Bind() override; +}; + +class FPresent3DRowShader : public FPresentStereoShaderBase +{ +public: + void Bind() override; }; // GL_PRESENT3DROWSHADER_H_ diff --git a/src/gl/shaders/gl_presentshader.cpp b/src/gl/shaders/gl_presentshader.cpp index 39d20d0fc..15acc74fb 100644 --- a/src/gl/shaders/gl_presentshader.cpp +++ b/src/gl/shaders/gl_presentshader.cpp @@ -36,21 +36,26 @@ #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_presentshader.h" +void FPresentShaderBase::Init(const char * vtx_shader_name, const char * program_name) +{ + mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); + mShader.Compile(FShaderProgram::Fragment, vtx_shader_name, "", 330); + mShader.SetFragDataLocation(0, "FragColor"); + mShader.Link(program_name); + mShader.SetAttribLocation(0, "PositionInProjection"); + mShader.SetAttribLocation(1, "UV"); + InvGamma.Init(mShader, "InvGamma"); + Contrast.Init(mShader, "Contrast"); + Brightness.Init(mShader, "Brightness"); + Scale.Init(mShader, "UVScale"); +} + void FPresentShader::Bind() { if (!mShader) { - mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); - mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present.fp", "", 330); - mShader.SetFragDataLocation(0, "FragColor"); - mShader.Link("shaders/glsl/present"); - mShader.SetAttribLocation(0, "PositionInProjection"); - mShader.SetAttribLocation(1, "UV"); + Init("shaders/glsl/present.fp", "shaders/glsl/present"); InputTexture.Init(mShader, "InputTexture"); - InvGamma.Init(mShader, "InvGamma"); - Contrast.Init(mShader, "Contrast"); - Brightness.Init(mShader, "Brightness"); - Scale.Init(mShader, "UVScale"); } mShader.Bind(); } diff --git a/src/gl/shaders/gl_presentshader.h b/src/gl/shaders/gl_presentshader.h index 6f4e899bb..6f9e1bfd7 100644 --- a/src/gl/shaders/gl_presentshader.h +++ b/src/gl/shaders/gl_presentshader.h @@ -3,19 +3,27 @@ #include "gl_shaderprogram.h" -class FPresentShader +class FPresentShaderBase { public: - void Bind(); + virtual void Bind() = 0; - FBufferedUniformSampler InputTexture; FBufferedUniform1f InvGamma; FBufferedUniform1f Contrast; FBufferedUniform1f Brightness; FBufferedUniform2f Scale; -private: +protected: + virtual void Init(const char * vtx_shader_name, const char * program_name); FShaderProgram mShader; }; +class FPresentShader : public FPresentShaderBase +{ +public: + void Bind() override; + + FBufferedUniformSampler InputTexture; +}; + #endif \ No newline at end of file diff --git a/src/gl/stereo3d/gl_interleaved3d.cpp b/src/gl/stereo3d/gl_interleaved3d.cpp index 036a84b0b..029d233e4 100644 --- a/src/gl/stereo3d/gl_interleaved3d.cpp +++ b/src/gl/stereo3d/gl_interleaved3d.cpp @@ -43,10 +43,25 @@ EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_contrast) EXTERN_CVAR(Bool, fullscreen) -EXTERN_CVAR(Int, win_y) // pixel position of top of display window +EXTERN_CVAR(Int, win_x) // screen pixel position of left of display window +EXTERN_CVAR(Int, win_y) // screen pixel position of top of display window namespace s3d { +/* static */ +const CheckerInterleaved3D& CheckerInterleaved3D::getInstance(float ipd) +{ + static CheckerInterleaved3D instance(ipd); + return instance; +} + +/* static */ +const ColumnInterleaved3D& ColumnInterleaved3D::getInstance(float ipd) +{ + static ColumnInterleaved3D instance(ipd); + return instance; +} + /* static */ const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd) { @@ -54,11 +69,7 @@ const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd) return instance; } -RowInterleaved3D::RowInterleaved3D(double ipdMeters) - : TopBottom3D(ipdMeters) -{} - -void RowInterleaved3D::Present() const +static void prepareInterleavedPresent(FPresentStereoShaderBase& shader) { GLRenderer->mBuffers->BindOutputFB(); GLRenderer->ClearBorders(); @@ -79,27 +90,102 @@ void RowInterleaved3D::Present() const const GL_IRECT& box = GLRenderer->mOutputLetterbox; glViewport(box.left, box.top, box.width, box.height); - bool applyGamma = true; + shader.Bind(); + shader.LeftEyeTexture.Set(0); + shader.RightEyeTexture.Set(1); - GLRenderer->mPresent3dRowShader->Bind(); - GLRenderer->mPresent3dRowShader->LeftEyeTexture.Set(0); - GLRenderer->mPresent3dRowShader->RightEyeTexture.Set(1); - - if (!applyGamma || GLRenderer->framebuffer->IsHWGammaActive()) + if ( GLRenderer->framebuffer->IsHWGammaActive() ) { - GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f); - GLRenderer->mPresent3dRowShader->Contrast.Set(1.0f); - GLRenderer->mPresent3dRowShader->Brightness.Set(0.0f); + shader.InvGamma.Set(1.0f); + shader.Contrast.Set(1.0f); + shader.Brightness.Set(0.0f); } else { - GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f / clamp(Gamma, 0.1f, 4.f)); - GLRenderer->mPresent3dRowShader->Contrast.Set(clamp(vid_contrast, 0.1f, 3.f)); - GLRenderer->mPresent3dRowShader->Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); + shader.InvGamma.Set(1.0f / clamp(Gamma, 0.1f, 4.f)); + shader.Contrast.Set(clamp(vid_contrast, 0.1f, 3.f)); + shader.Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); } - GLRenderer->mPresent3dRowShader->Scale.Set( + shader.Scale.Set( GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(), GLRenderer->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()); +} + +// fixme: I don't know how to get absolute window position on Mac and Linux +// fixme: I don't know how to get window border decoration size anywhere +// So for now I'll hard code the border effect on my test machine. +// Workaround for others is to fuss with vr_swap_eyes CVAR until it looks right. +// Presumably the top/left window border on my test machine has an odd number of pixels +// in the horizontal direction, and an even number in the vertical direction. +#define WINDOW_BORDER_HORIZONTAL_PARITY 1 +#define WINDOW_BORDER_VERTICAL_PARITY 0 + +void CheckerInterleaved3D::Present() const +{ + prepareInterleavedPresent(*GLRenderer->mPresent3dCheckerShader); + + // Compute absolute offset from top of screen to top of current display window + // because we need screen-relative, not window-relative, scan line parity + int windowVOffset = 0; + int windowHOffset = 0; + +#ifdef _WIN32 + if (!fullscreen) { + I_SaveWindowedPos(); // update win_y CVAR + windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2; + windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2; + } +#endif // _WIN32 + + GLRenderer->mPresent3dCheckerShader->WindowPositionParity.Set( + (windowVOffset + + windowHOffset + + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom + ) % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset + ); + + GLRenderer->RenderScreenQuad(); +} + +void s3d::CheckerInterleaved3D::AdjustViewports() const +{ + // decrease the total pixel count by 2, but keep the same aspect ratio + const float sqrt2 = 1.41421356237f; + // Change size of renderbuffer, and align to screen + GLRenderer->mSceneViewport.height /= sqrt2; + GLRenderer->mSceneViewport.top /= sqrt2; + GLRenderer->mSceneViewport.width /= sqrt2; + GLRenderer->mSceneViewport.left /= sqrt2; + + GLRenderer->mScreenViewport.height /= sqrt2; + GLRenderer->mScreenViewport.top /= sqrt2; + GLRenderer->mScreenViewport.width /= sqrt2; + GLRenderer->mScreenViewport.left /= sqrt2; +} + +void ColumnInterleaved3D::Present() const +{ + prepareInterleavedPresent(*GLRenderer->mPresent3dColumnShader); + + // Compute absolute offset from top of screen to top of current display window + // because we need screen-relative, not window-relative, scan line parity + int windowHOffset = 0; + +#ifdef _WIN32 + if (!fullscreen) { + I_SaveWindowedPos(); // update win_y CVAR + windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2; + } +#endif // _WIN32 + + GLRenderer->mPresent3dColumnShader->WindowPositionParity.Set(windowHOffset); + + GLRenderer->RenderScreenQuad(); +} + +void RowInterleaved3D::Present() const +{ + prepareInterleavedPresent(*GLRenderer->mPresent3dRowShader); // Compute absolute offset from top of screen to top of current display window // because we need screen-relative, not window-relative, scan line parity @@ -108,13 +194,14 @@ void RowInterleaved3D::Present() const #ifdef _WIN32 if (! fullscreen) { I_SaveWindowedPos(); // update win_y CVAR - windowVOffset = win_y; + windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2; } #endif // _WIN32 - GLRenderer->mPresent3dRowShader->VerticalPixelOffset.Set( - windowVOffset // fixme: vary with window location - + box.height % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset + GLRenderer->mPresent3dRowShader->WindowPositionParity.Set( + (windowVOffset + + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom + ) % 2 ); GLRenderer->RenderScreenQuad(); diff --git a/src/gl/stereo3d/gl_interleaved3d.h b/src/gl/stereo3d/gl_interleaved3d.h index 30aef7d5a..78bd19483 100644 --- a/src/gl/stereo3d/gl_interleaved3d.h +++ b/src/gl/stereo3d/gl_interleaved3d.h @@ -42,15 +42,30 @@ #include "gl/system/gl_system.h" #include "gl/renderer/gl_renderstate.h" -class FPresent3DRowShader; - namespace s3d { +class CheckerInterleaved3D : public SideBySideSquished +{ +public: + static const CheckerInterleaved3D& getInstance(float ipd); + CheckerInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {} + void Present() const override; + void AdjustViewports() const override; +}; + +class ColumnInterleaved3D : public SideBySideSquished +{ +public: + static const ColumnInterleaved3D& getInstance(float ipd); + ColumnInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {} + void Present() const override; +}; + class RowInterleaved3D : public TopBottom3D { public: static const RowInterleaved3D& getInstance(float ipd); - RowInterleaved3D(double ipdMeters); + RowInterleaved3D(double ipdMeters) : TopBottom3D(ipdMeters) {} void Present() const override; }; diff --git a/src/gl/stereo3d/gl_stereo_cvars.cpp b/src/gl/stereo3d/gl_stereo_cvars.cpp index 16296393d..fe5ae3261 100644 --- a/src/gl/stereo3d/gl_stereo_cvars.cpp +++ b/src/gl/stereo3d/gl_stereo_cvars.cpp @@ -107,6 +107,12 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode() case 12: setCurrentMode(RowInterleaved3D::getInstance(vr_ipd)); break; + case 13: + setCurrentMode(ColumnInterleaved3D::getInstance(vr_ipd)); + break; + case 14: + setCurrentMode(CheckerInterleaved3D::getInstance(vr_ipd)); + break; case 0: default: setCurrentMode(MonoView::getInstance()); diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 83cddb8c5..a5ffb4a2c 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2707,6 +2707,8 @@ OPTVAL_SBSFULL = "Side-by-side Full"; OPTVAL_SBSNARROW = "Side-by-side Narrow"; OPTVAL_TOPBOTTOM = "Top/Bottom"; OPTVAL_ROWINTERLEAVED = "Row Interleaved"; +OPTVAL_COLUMNINTERLEAVED = "Column Interleaved"; +OPTVAL_CHECKERBOARD = "Checkerboard"; OPTVAL_QUADBUFFERED = "Quad-buffered"; OPTVAL_UNCHARTED2 = "Uncharted 2"; OPTVAL_HEJLDAWSON = "Hejl Dawson"; diff --git a/wadsrc/static/menudef.zz b/wadsrc/static/menudef.zz index 7e798a039..253f984eb 100644 --- a/wadsrc/static/menudef.zz +++ b/wadsrc/static/menudef.zz @@ -180,6 +180,8 @@ OptionValue VRMode 4, "$OPTVAL_SBSNARROW" 11, "$OPTVAL_TOPBOTTOM" 12, "$OPTVAL_ROWINTERLEAVED" + 13, "$OPTVAL_COLUMNINTERLEAVED" + 14, "$OPTVAL_CHECKERBOARD" 5, "$OPTVAL_LEFTEYE" 6, "$OPTVAL_RIGHTEYE" 7, "$OPTVAL_QUADBUFFERED" diff --git a/wadsrc/static/shaders/glsl/present_checker3d.fp b/wadsrc/static/shaders/glsl/present_checker3d.fp new file mode 100644 index 000000000..5247261e0 --- /dev/null +++ b/wadsrc/static/shaders/glsl/present_checker3d.fp @@ -0,0 +1,37 @@ + +in vec2 TexCoord; +out vec4 FragColor; + +uniform sampler2D LeftEyeTexture; +uniform sampler2D RightEyeTexture; +uniform float InvGamma; +uniform float Contrast; +uniform float Brightness; +uniform int WindowPositionParity; // top-of-window might not be top-of-screen + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even + int thisHorizontalPixel = int(gl_FragCoord.x); // column + bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row + + thisHorizontalPixel // and each column + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, TexCoord); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, TexCoord); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders/glsl/present_column3d.fp b/wadsrc/static/shaders/glsl/present_column3d.fp new file mode 100644 index 000000000..b46246cf0 --- /dev/null +++ b/wadsrc/static/shaders/glsl/present_column3d.fp @@ -0,0 +1,35 @@ + +in vec2 TexCoord; +out vec4 FragColor; + +uniform sampler2D LeftEyeTexture; +uniform sampler2D RightEyeTexture; +uniform float InvGamma; +uniform float Contrast; +uniform float Brightness; +uniform int WindowPositionParity; // top-of-window might not be top-of-screen + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisHorizontalPixel = int(gl_FragCoord.x); // zero-based column index from left + bool isLeftEye = (thisHorizontalPixel // because we want to alternate eye view on each column + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, TexCoord); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, TexCoord); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders/glsl/present_row3d.fp b/wadsrc/static/shaders/glsl/present_row3d.fp index 8ae72d1e0..50b27ac26 100644 --- a/wadsrc/static/shaders/glsl/present_row3d.fp +++ b/wadsrc/static/shaders/glsl/present_row3d.fp @@ -7,7 +7,7 @@ uniform sampler2D RightEyeTexture; uniform float InvGamma; uniform float Contrast; uniform float Brightness; -uniform int VerticalPixelOffset; // top-of-window might not be top-of-screen +uniform int WindowPositionParity; // top-of-window might not be top-of-screen vec4 ApplyGamma(vec4 c) { @@ -19,9 +19,9 @@ vec4 ApplyGamma(vec4 c) void main() { - int thisVerticalPixel = int(gl_FragCoord.y + 1.0); // Bottom row is typically the right eye, when WindowHeight is even + int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row - + VerticalPixelOffset // because the window might not be aligned to the screen + + WindowPositionParity // because the window might not be aligned to the screen ) % 2 == 0; vec4 inputColor; if (isLeftEye) { From a771a3edd4b9794a1afea4317250ad0b2c95642a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 8 Oct 2016 18:36:34 +0300 Subject: [PATCH 19/62] Fixed potential crash caused by A_Warp() ACSF_Warp case was refactored to express its intention clearly http://forum.zdoom.org/viewtopic.php?f=2&t=53734 --- src/p_acs.cpp | 79 +++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 0a2ccddac..71ef65f22 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5821,43 +5821,54 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) // [ZK] A_Warp in ACS case ACSF_Warp: { - int tid_dest = args[0]; - int xofs = args[1]; - int yofs = args[2]; - int zofs = args[3]; - int angle = args[4]; - int flags = args[5]; - const char *statename = argCount > 6 ? FBehavior::StaticLookupString(args[6]) : ""; - bool exact = argCount > 7 ? !!args[7] : false; - int heightoffset = argCount > 8 ? args[8] : 0; - int radiusoffset = argCount > 9 ? args[9] : 0; - int pitch = argCount > 10 ? args[10] : 0; - - FState *state = argCount > 6 ? activator->GetClass()->FindStateByString(statename, exact) : 0; - - AActor *reference; - if((flags & WARPF_USEPTR) && tid_dest != AAPTR_DEFAULT) + if (nullptr == activator) { - reference = COPY_AAPTR(activator, tid_dest); - } - else - { - reference = SingleActorFromTID(tid_dest, activator); - } - - // If there is no activator or actor to warp to, fail. - if (activator == NULL || !reference) return false; - - if (P_Thing_Warp(activator, reference, ACSToDouble(xofs), ACSToDouble(yofs), ACSToDouble(zofs), ACSToAngle(angle), flags, ACSToDouble(heightoffset), ACSToDouble(radiusoffset), ACSToAngle(pitch))) - { - if (state && argCount > 6) - { - activator->SetState(state); - } - return true; } - return false; + + const int dest = args[0]; + const int flags = args[5]; + + AActor* const reference = ((flags & WARPF_USEPTR) && (AAPTR_DEFAULT != dest)) + ? COPY_AAPTR(activator, dest) + : SingleActorFromTID(dest, activator); + + if (nullptr == reference) + { + // there is no actor to warp to + return false; + } + + const double xofs = ACSToDouble(args[1]); + const double yofs = ACSToDouble(args[2]); + const double zofs = ACSToDouble(args[3]); + const DAngle angle = ACSToAngle(args[4]); + const double heightoffset = argCount > 8 ? ACSToDouble(args[8]) : 0.0; + const double radiusoffset = argCount > 9 ? ACSToDouble(args[9]) : 0.0; + const DAngle pitch = ACSToAngle(argCount > 10 ? args[10] : 0); + + if (!P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch)) + { + return false; + } + + if (argCount > 6) + { + const char* const statename = FBehavior::StaticLookupString(args[6]); + + if (nullptr != statename) + { + const bool exact = argCount > 7 && !!args[7]; + FState* const state = activator->GetClass()->FindStateByString(statename, exact); + + if (nullptr != state) + { + activator->SetState(state); + } + } + } + + return true; } case ACSF_GetMaxInventory: actor = SingleActorFromTID(args[0], activator); From 31ca5a1900062e5e5bee074d8b2c4919361cf55b Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sat, 8 Oct 2016 11:04:12 -0500 Subject: [PATCH 20/62] Added OverlayX/Y(int layer) - Retrieves the X/Y positions of an overlay. - A_OverlayFlags and A_OverlayOffset now interpret a layer of 0 to mean 'use this calling layer'. --- src/p_pspr.cpp | 52 ++++++++++++++++++++++++++++++++-- wadsrc/static/actors/actor.txt | 2 ++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index fab7e38d8..e5b076acd 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1006,7 +1006,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) PARAM_FLOAT_OPT(wx) { wx = 0.; } PARAM_FLOAT_OPT(wy) { wy = 32.; } PARAM_INT_OPT(flags) { flags = 0; } - A_OverlayOffset(self, layer, wx, wy, flags); + A_OverlayOffset(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), wx, wy, flags); return 0; } @@ -1033,10 +1033,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) PARAM_INT(flags); PARAM_BOOL(set); - if (self->player == nullptr) + if (!ACTION_CALL_FROM_PSPRITE()) return 0; - DPSprite *pspr = self->player->FindPSprite(layer); + DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex)); if (pspr == nullptr) return 0; @@ -1049,6 +1049,52 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) return 0; } +//--------------------------------------------------------------------------- +// +// PROC OverlayX/Y +// Action function to return the X/Y of an overlay. +//--------------------------------------------------------------------------- + +static double GetOverlayPosition(AActor *self, int layer, bool gety) +{ + if (layer) + { + DPSprite *pspr = self->player->FindPSprite(layer); + + if (pspr != nullptr) + { + return gety ? (pspr->y) : (pspr->x); + } + } + return 0.; +} + +DEFINE_ACTION_FUNCTION(AActor, OverlayX) +{ + PARAM_ACTION_PROLOGUE; + PARAM_INT_OPT(layer) { layer = 0; } + + if (ACTION_CALL_FROM_PSPRITE()) + { + double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), false); + ACTION_RETURN_FLOAT(res); + } + ACTION_RETURN_FLOAT(0.); +} + +DEFINE_ACTION_FUNCTION(AActor, OverlayY) +{ + PARAM_ACTION_PROLOGUE; + PARAM_INT_OPT(layer) { layer = 0; } + + if (ACTION_CALL_FROM_PSPRITE()) + { + double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), true); + ACTION_RETURN_FLOAT(res); + } + ACTION_RETURN_FLOAT(0.); +} + //--------------------------------------------------------------------------- // // PROC OverlayID diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 44b801f51..fb6b4c832 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -58,6 +58,8 @@ ACTOR Actor native //: Thinker native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); action native int OverlayID(); + action native float OverlayX(int layer = 0); + action native float OverlayY(int layer = 0); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. From 084bf8c57691c40e22c188a8aab37a914197d3bb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 00:23:50 +0200 Subject: [PATCH 21/62] - fixed: VisibleAngle and VisiblePitch actor properties require both parameters to be present, but the second one was set to optional. --- src/thingdef/thingdef_properties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index d60cda823..80ee6c22f 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1435,7 +1435,7 @@ DEFINE_PROPERTY(spriterotation, F, Actor) //========================================================================== // //========================================================================== -DEFINE_PROPERTY(visibleangles, Ff, Actor) +DEFINE_PROPERTY(visibleangles, FF, Actor) { PROP_DOUBLE_PARM(visstart, 0); PROP_DOUBLE_PARM(visend, 1); @@ -1446,7 +1446,7 @@ DEFINE_PROPERTY(visibleangles, Ff, Actor) //========================================================================== // //========================================================================== -DEFINE_PROPERTY(visiblepitch, Ff, Actor) +DEFINE_PROPERTY(visiblepitch, FF, Actor) { PROP_DOUBLE_PARM(visstart, 0); PROP_DOUBLE_PARM(visend, 1); From dde25820e24e6e243eae96d53a9a19e437bc1c6c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 09:08:31 +0200 Subject: [PATCH 22/62] - fixed winding of voxel polygons. --- src/gl/models/gl_voxels.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gl/models/gl_voxels.cpp b/src/gl/models/gl_voxels.cpp index 288b1a9db..6e84bd7ab 100644 --- a/src/gl/models/gl_voxels.cpp +++ b/src/gl/models/gl_voxels.cpp @@ -314,12 +314,12 @@ void FVoxelModel::MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &chec } if (cull & 4) { - AddFace(x, y, z, x+1, y, z, x, y, z+c, x+1, y, z+c, *col, check); + AddFace(x+1, y, z, x, y, z, x+1, y, z+c, x, y, z+c, *col, check); } if (cull & 8) { - AddFace(x+1, y+1, z, x, y+1, z, x+1, y+1, z+c, x, y+1, z+c, *col, check); - } + AddFace(x, y+1, z, x+1, y+1, z, x, y+1, z+c, x+1, y+1, z+c, *col, check); + } z+=c; col+=c; } From 7510ad1635f3c4f26b905d6d10bb95bb7a2c0e88 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 11 Oct 2016 14:52:47 +0300 Subject: [PATCH 23/62] Fixed missing fake floors in deferred buffer mode wow.wad is now genuine and authentic... --- src/gl/scene/gl_flats.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 394ca1626..c41e7664f 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -187,21 +187,18 @@ void GLFlat::DrawSubsector(subsector_t * sub) unsigned int vi[4]; vi[0] = 0; - for (unsigned int i = 1; i < sub->numlines-1; i += 2) + for (unsigned int i = 0; i < sub->numlines - 2; i += 2) { - if (i < sub->numlines - 3) + for (unsigned int j = 1; j < 4; j++) { - for (unsigned int j = 1; j < 4; j++) - { - vi[j] = MIN(i + j, sub->numlines - 1); - } - for (unsigned int x = 0; x < 4; x++) - { - vertex_t *vt = sub->firstline[vi[x]].v1; - qd.Set(x, vt->fX(), plane.plane.ZatPoint(vt) + dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f); - } - qd.Render(GL_TRIANGLE_FAN); + vi[j] = MIN(i + j, sub->numlines - 1); } + for (unsigned int x = 0; x < 4; x++) + { + vertex_t *vt = sub->firstline[vi[x]].v1; + qd.Set(x, vt->fX(), plane.plane.ZatPoint(vt) + dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f); + } + qd.Render(GL_TRIANGLE_FAN); } } From bdbc7c3fb75e4b2b0b682f135e0802b711342190 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 14:43:17 +0200 Subject: [PATCH 24/62] - removed CreateDamageFunction, because it's no longer needed for defining a 'damage' constant. --- src/thingdef/thingdef.cpp | 29 ----------------------------- src/thingdef/thingdef.h | 8 -------- 2 files changed, 37 deletions(-) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 41e1e9542..9af031b04 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -480,32 +480,3 @@ void LoadActors () if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms } - - -//========================================================================== -// -// CreateDamageFunction -// -// Creates a damage function suitable for a constant, non-expressioned -// value. -// -//========================================================================== - -VMScriptFunction *CreateDamageFunction(int dmg) -{ - if (dmg == 0) - { - // For zero damage, do not create a function so that the special collision detection case still works as before. - return NULL; - } - else - { - VMFunctionBuilder build; - build.Registers[REGT_POINTER].Get(1); // The self pointer - build.EmitRetInt(0, false, dmg); - build.EmitRetInt(1, true, 0); - VMScriptFunction *sfunc = build.MakeFunction(); - sfunc->NumArgs = 1; - return sfunc; - } -} diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 3a419b112..565da573a 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -164,14 +164,6 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) bag->statedef.MakeStateDefines(stateclass); } -//========================================================================== -// -// Damage function creation -// -//========================================================================== - -VMScriptFunction *CreateDamageFunction(int dmg); - //========================================================================== // // Action function lookup From 5dc94a10c352ae05c49b00436f5b36f55059181a Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 11 Oct 2016 14:44:31 -0500 Subject: [PATCH 25/62] Added A_SetInventory. - Sets the absolute amount of an inventory actor. - Limits itself to the range [0, MaxAmount]. Setting beyondMax to true disregards the MaxAmount. Default is false. --- src/p_mobj.cpp | 2 + src/thingdef/thingdef_codeptr.cpp | 86 +++++++++++++++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 3 files changed, 89 insertions(+) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 022504919..1ebec242e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -634,6 +634,7 @@ void AActor::RemoveInventory(AInventory *item) bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate, bool notakeinfinite) { + amount = abs(amount); AInventory *item = FindInventory(itemclass); if (item == NULL) @@ -666,6 +667,7 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate item->IsKindOf(RUNTIME_CLASS(AAmmo))) { // Nothing to do here, except maybe res = false;? Would it make sense? + result = false; } else if (!amount || amount>=item->Amount) { diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 3b4e6203e..c6bc8215b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2622,6 +2622,92 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) ACTION_RETURN_INT(count); } +//=========================================================================== +// +// A_SetInventory +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory) +{ + PARAM_ACTION_PROLOGUE; + PARAM_CLASS(itemtype, AInventory); + PARAM_INT(amount); + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_BOOL_OPT(beyondMax) { beyondMax = false; } + + bool res = false; + + if (itemtype == nullptr) + { + ACTION_RETURN_BOOL(false); + } + + AActor *mobj = COPY_AAPTR(self, ptr); + + if (mobj == nullptr) + { + ACTION_RETURN_BOOL(false); + } + + AInventory *item = mobj->FindInventory(itemtype); + + if (item != nullptr) + { + // A_SetInventory sets the absolute amount. + // Subtract or set the appropriate amount as necessary. + + if (amount == item->Amount) + { + // Nothing was changed. + ACTION_RETURN_BOOL(false); + } + else if (amount <= 0) + { + //Remove it all. + res = (mobj->TakeInventory(itemtype, item->Amount, true, false)); + ACTION_RETURN_BOOL(res); + } + else if (amount < item->Amount) + { + int amt = abs(item->Amount - amount); + res = (mobj->TakeInventory(itemtype, amt, true, false)); + ACTION_RETURN_BOOL(res); + } + else + { + item->Amount = (beyondMax ? amount : clamp(amount, 0, item->MaxAmount)); + ACTION_RETURN_BOOL(true); + } + } + else + { + if (amount <= 0) + { + ACTION_RETURN_BOOL(false); + } + item = static_cast(Spawn(itemtype)); + if (item == nullptr) + { + ACTION_RETURN_BOOL(false); + } + else + { + item->Amount = amount; + item->flags |= MF_DROPPED; + item->ItemFlags |= IF_IGNORESKILL; + item->ClearCounters(); + if (!item->CallTryPickup(mobj)) + { + item->Destroy(); + ACTION_RETURN_BOOL(false); + } + ACTION_RETURN_BOOL(true); + } + } + ACTION_RETURN_BOOL(false); +} + //=========================================================================== // // A_TakeInventory diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index fb6b4c832..eecc843d3 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -211,6 +211,7 @@ ACTOR Actor native //: Thinker native state A_JumpIfTargetInsideMeleeRange(state label); native state A_JumpIfInventory(class itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); native state A_JumpIfArmorType(name Type, state label, int amount = 1); + action native bool A_SetInventory(class itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false); native bool A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); native bool A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); action native bool A_SpawnItem(class itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); From 3de83b8943e1ed13aaad9da723f0671b8c3dad40 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 11 Oct 2016 17:20:58 -0500 Subject: [PATCH 26/62] Added PSPF_FLIP. Flips the overlay on the X axis. --- src/p_pspr.h | 1 + src/r_things.cpp | 2 +- wadsrc/static/actors/constants.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_pspr.h b/src/p_pspr.h index 7e5109657..ea03e109f 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -57,6 +57,7 @@ enum PSPFlags PSPF_ADDBOB = 1 << 1, PSPF_POWDOUBLE = 1 << 2, PSPF_CVARFAST = 1 << 3, + PSPF_FLIP = 1 << 6, }; class DPSprite : public DObject diff --git a/src/r_things.cpp b/src/r_things.cpp index 179ffec97..ab75c15b0 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1404,7 +1404,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double vis->pic = tex; vis->ColormapNum = 0; - if (flip) + if (!(flip) != !(pspr->Flags & PSPF_FLIP)) { vis->xiscale = -FLOAT2FIXED(pspritexiscale * tex->Scale.X); vis->startfrac = (tex->GetWidth() << FRACBITS) - 1; diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index dce2488c2..df3bb860b 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -598,6 +598,7 @@ enum PSPF_ADDBOB = 1 << 1, PSPF_POWDOUBLE = 1 << 2, PSPF_CVARFAST = 1 << 3, + PSPF_FLIP = 1 << 6, }; // Default psprite layers From 41bf9def805cc832fed9d7efa02b6d1a71b9f170 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 11 Oct 2016 20:15:46 -0500 Subject: [PATCH 27/62] GZDoom compatibility for PSPF_FLIP. --- src/gl/scene/gl_weapon.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index cfa5c05d7..a2a12f947 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -129,19 +129,20 @@ void FGLRenderer::DrawPSprite (player_t * player,DPSprite *psp, float sx, float y1 = viewwindowy + vh / 2 - (ftexturemid * scale); y2 = y1 + (r.height * scale) + 1; - if (!mirror) + if (!(mirror) != !(psp->Flags & PSPF_FLIP)) { - fU1=tex->GetSpriteUL(); - fV1=tex->GetSpriteVT(); - fU2=tex->GetSpriteUR(); - fV2=tex->GetSpriteVB(); + fU2 = tex->GetSpriteUL(); + fV1 = tex->GetSpriteVT(); + fU1 = tex->GetSpriteUR(); + fV2 = tex->GetSpriteVB(); } else { - fU2=tex->GetSpriteUL(); - fV1=tex->GetSpriteVT(); - fU1=tex->GetSpriteUR(); - fV2=tex->GetSpriteVB(); + fU1 = tex->GetSpriteUL(); + fV1 = tex->GetSpriteVT(); + fU2 = tex->GetSpriteUR(); + fV2 = tex->GetSpriteVB(); + } if (tex->GetTransparent() || OverrideShader != -1) From 6f92efc72cb87baee5550de42a2b0c489774f704 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Oct 2016 12:43:26 +0200 Subject: [PATCH 28/62] - renamed thingdef_codeptr.cpp and moved it out of thingdef/. Ultimately, thingdef should only contain code that is directly related to the DECORATE parser, but that's not the case with this file. It's only function definitions which get used during gameplay and will also be accessed by ZScript. The change is intentionally on master so that pull requests can adjust to it now instead of creating conflicts later. --- src/CMakeLists.txt | 2 +- src/{thingdef/thingdef_codeptr.cpp => p_actionfunctions.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{thingdef/thingdef_codeptr.cpp => p_actionfunctions.cpp} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03299bb0a..ebfac3050 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1090,6 +1090,7 @@ set (PCH_SOURCES p_3dfloors.cpp p_3dmidtex.cpp p_acs.cpp + p_actionfunctions.cpp p_buildmap.cpp p_ceiling.cpp p_conversation.cpp @@ -1227,7 +1228,6 @@ set (PCH_SOURCES textures/warptexture.cpp thingdef/olddecorations.cpp thingdef/thingdef.cpp - thingdef/thingdef_codeptr.cpp thingdef/thingdef_data.cpp thingdef/thingdef_exp.cpp thingdef/thingdef_expression.cpp diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/p_actionfunctions.cpp similarity index 100% rename from src/thingdef/thingdef_codeptr.cpp rename to src/p_actionfunctions.cpp From de56be6c01bdb2747b93a5072591f2af29363f2d Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 21:41:54 -0500 Subject: [PATCH 29/62] Lemon update 2016-04-29 11:28:35 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Lemon bug fix: Do not merge action routines unless their destructors are also identical. Problem and suggested fix reported on the mailing list by Kelvin Sherlock. (user: drh) --- tools/lemon/lemon.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 546cf515e..c796f4f12 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -4404,7 +4404,8 @@ void ReportTable( writeRuleText(out, rp); fprintf(out," */\n"); lineno++; for(rp2=rp->next; rp2; rp2=rp2->next){ - if( rp2->code==rp->code ){ + if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix + && rp2->codeSuffix == rp->codeSuffix ){ fprintf(out," case %d: /*",rp2->iRule); writeRuleText(out, rp2); fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; @@ -4413,7 +4414,7 @@ void ReportTable( } emit_code(out,rp,lemp,&lineno); fprintf(out," break;\n"); lineno++; - rp->code = 0; + rp->code = 0; } /* Finally, output the default: rule. We choose as the default: all ** empty actions. */ From 45d441f103160e3a9f326b97d3b2ff23392aa7b2 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 21:48:29 -0500 Subject: [PATCH 30/62] Lemon update 2016-04-29 11:28:35 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Lemon bug fix: Do not merge action routines unless their destructors are also identical. Problem and suggested fix reported on the mailing list by Kelvin Sherlock. (user: drh) --- tools/lemon/lemon.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index c796f4f12..56364f897 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -3559,10 +3559,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ rp->line = rp->ruleline; } - if( rp->lhsalias==0 ){ - /* There is no LHS value symbol. */ - lhsdirect = 1; - }else if( rp->nrhs==0 ){ + if( rp->nrhs==0 ){ /* If there are no RHS symbols, then writing directly to the LHS is ok */ lhsdirect = 1; }else if( rp->rhsalias[0]==0 ){ @@ -3575,6 +3572,9 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ rp->rhs[0]->index,1-rp->nrhs,0); rp->codePrefix = Strsafe(append_str(0,0,0,0,0)); } + }else if( rp->lhsalias==0 ){ + /* There is no LHS value symbol. */ + lhsdirect = 1; }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){ /* The LHS symbol and the left-most RHS symbol are the same, so ** direct writing is allowed */ @@ -3717,7 +3717,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ /* Suffix code generation complete */ cp = append_str(0,0,0,0,0); - if( cp ) rp->codeSuffix = Strsafe(cp); + if( cp && cp[0] ) rp->codeSuffix = Strsafe(cp); return rc; } @@ -4399,7 +4399,14 @@ void ReportTable( for(rp=lemp->rule; rp; rp=rp->next){ struct rule *rp2; /* Other rules with the same action */ if( rp->code==0 ) continue; - if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ + if( rp->code[0]=='\n' + && rp->code[1]==0 + && rp->codePrefix==0 + && rp->codeSuffix==0 + ){ + /* No actions, so this will be part of the "default:" rule */ + continue; + } fprintf(out," case %d: /* ",rp->iRule); writeRuleText(out, rp); fprintf(out," */\n"); lineno++; @@ -4422,6 +4429,8 @@ void ReportTable( for(rp=lemp->rule; rp; rp=rp->next){ if( rp->code==0 ) continue; assert( rp->code[0]=='\n' && rp->code[1]==0 ); + assert( rp->codePrefix==0 ); + assert( rp->codeSuffix==0 ); fprintf(out," /* (%d) ", rp->iRule); writeRuleText(out, rp); fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; From 0d67d107abb6d7de0a4305c18f506609cd925bb8 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 22:07:01 -0500 Subject: [PATCH 31/62] Lemon update 2016-05-23 14:24:31 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Fix comment typos and improve clarity of presention in Lemon. The output should be identical. (user: drh) --- tools/lemon/lemon.c | 51 ++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 56364f897..27487b160 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -192,6 +192,8 @@ struct rule { const char *code; /* The code executed when this rule is reduced */ const char *codePrefix; /* Setup code before code[] above */ const char *codeSuffix; /* Breakdown code after code[] above */ + int noCode; /* True if this rule has no associated C code */ + int codeEmitted; /* True if the code has been emitted already */ struct symbol *precsym; /* Precedence symbol for this rule */ int index; /* An index number for this rule */ int iRule; /* Rule number as used in the generated tables */ @@ -253,7 +255,7 @@ struct state { struct config *bp; /* The basis configurations for this state */ struct config *cfp; /* All configurations in this set */ int statenum; /* Sequential number for this state */ - struct action *ap; /* Array of actions for this state */ + struct action *ap; /* List of actions for this state */ int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ int iDfltReduce; /* Default action is to REDUCE by this rule */ @@ -1483,7 +1485,7 @@ static void handle_C_option(char *z){ } } -/* Merge together to lists of rules order by rule.iRule */ +/* Merge together to lists of rules ordered by rule.iRule */ static struct rule *Rule_merge(struct rule *pA, struct rule *pB){ struct rule *pFirst = 0; struct rule **ppPrev = &pFirst; @@ -1627,7 +1629,10 @@ int main(int argc, char **argv) for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); lem.nterminal = i; - /* Assign sequential rule numbers */ + /* Assign sequential rule numbers. Start with 0. Put rules that have no + ** reduce action C-code associated with them last, so that the switch() + ** statement that selects reduction actions will have a smaller jump table. + */ for(i=0, rp=lem.rule; rp; rp=rp->next){ rp->iRule = rp->code ? i++ : -1; } @@ -2179,7 +2184,7 @@ static void parseonetoken(struct pstate *psp) "There is no prior rule upon which to attach the code \ fragment which begins on this line."); psp->errorcnt++; - }else if( psp->prevrule->code!=0 ){ + }else if( psp->prevrule->code!=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Code fragment beginning on this line is not the first \ to follow the previous rule."); @@ -2187,7 +2192,8 @@ to follow the previous rule."); }else{ psp->prevrule->line = psp->tokenlineno; psp->prevrule->code = &x[1]; - } + psp->prevrule->noCode = 0; + } }else if( x[0]=='[' ){ psp->state = PRECEDENCE_MARK_1; }else{ @@ -2293,6 +2299,7 @@ to follow the previous rule."); rp->lhsalias = psp->lhsalias; rp->nrhs = psp->nrhs; rp->code = 0; + rp->noCode = 1; rp->precsym = 0; rp->index = psp->gp->nrule++; rp->nextlhs = rp->lhs->rule; @@ -3531,9 +3538,8 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2, int bNoSubst) } /* -** zCode is a string that is the action associated with a rule. Expand -** the symbols in this string so that the refer to elements of the parser -** stack. +** Write and transform the rp->code string so that symbols are expanded. +** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate. ** ** Return 1 if the expanded code requires that "yylhsminor" local variable ** to be defined. @@ -3557,6 +3563,9 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ static char newlinestr[2] = { '\n', '\0' }; rp->code = newlinestr; rp->line = rp->ruleline; + rp->noCode = 1; + }else{ + rp->noCode = 0; } if( rp->nrhs==0 ){ @@ -3571,6 +3580,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, rp->rhs[0]->index,1-rp->nrhs,0); rp->codePrefix = Strsafe(append_str(0,0,0,0,0)); + rp->noCode = 0; } }else if( rp->lhsalias==0 ){ /* There is no LHS value symbol. */ @@ -3717,7 +3727,10 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ /* Suffix code generation complete */ cp = append_str(0,0,0,0,0); - if( cp && cp[0] ) rp->codeSuffix = Strsafe(cp); + if( cp && cp[0] ){ + rp->codeSuffix = Strsafe(cp); + rp->noCode = 0; + } return rc; } @@ -4398,13 +4411,9 @@ void ReportTable( /* First output rules other than the default: rule */ for(rp=lemp->rule; rp; rp=rp->next){ struct rule *rp2; /* Other rules with the same action */ - if( rp->code==0 ) continue; - if( rp->code[0]=='\n' - && rp->code[1]==0 - && rp->codePrefix==0 - && rp->codeSuffix==0 - ){ - /* No actions, so this will be part of the "default:" rule */ + if( rp->codeEmitted ) continue; + if( rp->noCode ){ + /* No C code actions, so this will be part of the "default:" rule */ continue; } fprintf(out," case %d: /* ",rp->iRule); @@ -4416,21 +4425,19 @@ void ReportTable( fprintf(out," case %d: /*",rp2->iRule); writeRuleText(out, rp2); fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; - rp2->code = 0; + rp2->codeEmitted = 1; } } emit_code(out,rp,lemp,&lineno); fprintf(out," break;\n"); lineno++; - rp->code = 0; + rp->codeEmitted = 1; } /* Finally, output the default: rule. We choose as the default: all ** empty actions. */ fprintf(out," default:\n"); lineno++; for(rp=lemp->rule; rp; rp=rp->next){ - if( rp->code==0 ) continue; - assert( rp->code[0]=='\n' && rp->code[1]==0 ); - assert( rp->codePrefix==0 ); - assert( rp->codeSuffix==0 ); + if( rp->codeEmitted ) continue; + assert( rp->noCode ); fprintf(out," /* (%d) ", rp->iRule); writeRuleText(out, rp); fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; From 64bd551d203c4f302ecb933a3773a282b01f4716 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 22:09:13 -0500 Subject: [PATCH 32/62] Lemon update 2016-05-23 14:24:31 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Fix comment typos and improve clarity of presention in Lemon. The output should be identical. (user: drh) --- tools/lemon/lemon.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 27487b160..9994b940f 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -245,6 +245,7 @@ struct action { struct state *stp; /* The new state, if a shift */ struct rule *rp; /* The rule, if a reduce */ } x; + struct symbol *spOpt; /* SHIFTREDUCE optimization to this symbol */ struct action *next; /* Next action for this state */ struct action *collide; /* Next action with the same hash */ }; @@ -435,6 +436,7 @@ void Action_add( *app = newaction; newaction->type = type; newaction->sp = sp; + newaction->spOpt = 0; if( type==SHIFT ){ newaction->x.stp = (struct state *)arg; }else{ @@ -3160,6 +3162,9 @@ int PrintAction( result = 0; break; } + if( result && ap->spOpt ){ + fprintf(fp," /* because %s==%s */", ap->sp->name, ap->spOpt->name); + } return result; } @@ -4513,7 +4518,7 @@ void ReportHeader(struct lemon *lemp) void CompressTables(struct lemon *lemp) { struct state *stp; - struct action *ap, *ap2; + struct action *ap, *ap2, *nextap; struct rule *rp, *rp2, *rbest; int nbest, n; int i; @@ -4590,6 +4595,36 @@ void CompressTables(struct lemon *lemp) } } } + + /* If a SHIFTREDUCE action specifies a rule that has a single RHS term + ** (meaning that the SHIFTREDUCE will land back in the state where it + ** started) and if there is no C-code associated with the reduce action, + ** then we can go ahead and convert the action to be the same as the + ** action for the RHS of the rule. + */ + for(i=0; instate; i++){ + stp = lemp->sorted[i]; + for(ap=stp->ap; ap; ap=nextap){ + nextap = ap->next; + if( ap->type!=SHIFTREDUCE ) continue; + rp = ap->x.rp; + if( rp->noCode==0 ) continue; + if( rp->nrhs!=1 ) continue; +#if 1 + /* Only apply this optimization to non-terminals. It would be OK to + ** apply it to terminal symbols too, but that makes the parser tables + ** larger. */ + if( ap->sp->indexnterminal ) continue; +#endif + /* If we reach this point, it means the optimization can be applied */ + nextap = ap; + for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){} + assert( ap2!=0 ); + ap->spOpt = ap2->sp; + ap->type = ap2->type; + ap->x = ap2->x; + } + } } From 96afce241d6bc08cfdb0018ea6e5f0c23e8ba5c8 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 22:18:20 -0500 Subject: [PATCH 33/62] Lemon update 2016-05-24 18:55:08 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Enhance Lemon and the parser template so that it can once again build parsers that have no unreachable branches. (user: drh) --- tools/lemon/lemon.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 9994b940f..a1453716a 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -198,6 +198,7 @@ struct rule { int index; /* An index number for this rule */ int iRule; /* Rule number as used in the generated tables */ Boolean canReduce; /* True if this rule is ever reduced */ + Boolean doesReduce; /* Reduce actions occur after optimization */ struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *next; /* Next rule in the global list */ }; @@ -4154,6 +4155,19 @@ void ReportTable( } free(ax); + /* Mark rules that are actually used for reduce actions after all + ** optimizations have been applied + */ + for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE; + for(i=0; inxstate; i++){ + struct action *ap; + for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ + if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){ + ap->x.rp->doesReduce = i; + } + } + } + /* Finish rendering the constants now that the action table has ** been computed */ fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; @@ -4445,7 +4459,12 @@ void ReportTable( assert( rp->noCode ); fprintf(out," /* (%d) ", rp->iRule); writeRuleText(out, rp); - fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; + if( rp->doesReduce ){ + fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; + }else{ + fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n", + rp->iRule); lineno++; + } } fprintf(out," break;\n"); lineno++; tplt_xfer(lemp->name,in,out,&lineno); From 3b1a04888506adf9b97424d9e31c185c51873798 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 22:22:04 -0500 Subject: [PATCH 34/62] Lemon update 2016-05-24 18:55:08 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Enhance Lemon and the parser template so that it can once again build parsers that have no unreachable branches. (user: drh) --- tools/lemon/lemon.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index a1453716a..1e673be8a 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -4233,20 +4233,21 @@ void ReportTable( fprintf(out, "};\n"); lineno++; /* Output the yy_shift_ofst[] table */ - fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; n = lemp->nxstate; while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; - fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; - fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; - fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; + fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++; + fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; + fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; + fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; fprintf(out, "static const %s yy_shift_ofst[] = {\n", - minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++; + minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz)); + lineno++; lemp->tablesize += n*sz; for(i=j=0; isorted[i]; ofst = stp->iTknOfst; - if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; + if( ofst==NO_OFFSET ) ofst = lemp->nactiontab; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", ofst); if( j==9 || i==n-1 ){ From 696beca40f92e33d08ac976f1bf5a7753aa01089 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 22:23:28 -0500 Subject: [PATCH 35/62] Lemon update 2016-08-16 16:46:40 on branch trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Fix a bug in destructorprocessing of Lemon. That has no impact on the SQLite grammar. The bug was introduced by prior work to optimize the Lemon-generated parser used by SQLite. (user: drh) --- tools/lemon/lemon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 1e673be8a..f2da9c6f8 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -167,7 +167,8 @@ struct symbol { int useCnt; /* Number of times used */ char *destructor; /* Code which executes whenever this symbol is ** popped from the stack during error processing */ - int destLineno; /* Line number for start of destructor */ + int destLineno; /* Line number for start of destructor. Set to + ** -1 for duplicate destructors. */ char *datatype; /* The data type of information held by this ** object. Only used if type==NONTERMINAL */ int dtnum; /* The data type number. In the parser, the value @@ -4387,6 +4388,7 @@ void ReportTable( for(i=0; insymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; + if( sp->destLineno<0 ) continue; /* Already emitted */ fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; /* Combine duplicate destructors into a single case */ @@ -4397,7 +4399,7 @@ void ReportTable( && strcmp(sp->destructor,sp2->destructor)==0 ){ fprintf(out," case %d: /* %s */\n", sp2->index, sp2->name); lineno++; - sp2->destructor = 0; + sp2->destLineno = -1; /* Avoid emitting this destructor again */ } } From 97107b6b6d7704660e356bbb016f132e2bfebe91 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 13 Oct 2016 22:30:12 -0500 Subject: [PATCH 36/62] Update lempar.c to 2016-10-04 version - Every update rolled into one, because I'm pretty sure I missed some while updating lemon.c (not counting today's commits), since it wasn't always updated at the same time as lemon.c. - In particular, I think this check-in from 2016-06-06 was very important to us after commit 3d5867d29e8932d238084e5c66dead1b4502f82f (For the Lemon-generated parser, add a new action type SHIFTREDUCE and use it to further compress the parser tables and improve parser performance.): * Fix lempar.c so that the shift-reduce optimization works for error processing. --- src/zscript/zcc-parse.lemon | 2 +- tools/lemon/lempar.c | 263 +++++++++++++++++++----------------- 2 files changed, 141 insertions(+), 124 deletions(-) diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index ee8296ff6..12cbb6625 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -77,7 +77,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) FString unexpected, expecting; int i; - int stateno = yypParser->yystack[yypParser->yyidx].stateno; + int stateno = yypParser->yytos->stateno; unexpected << "Unexpected " << ZCCTokenName(yymajor); diff --git a/tools/lemon/lempar.c b/tools/lemon/lempar.c index 0549a9dad..0e360bab9 100644 --- a/tools/lemon/lempar.c +++ b/tools/lemon/lempar.c @@ -41,6 +41,7 @@ ***************** Begin makeheaders token definitions *************************/ %% /**************** End makeheaders token definitions ***************************/ + /* The next section is a series of control #defines. ** various aspects of the generated parser. ** YYCODETYPE is the data type used to store the integer codes @@ -50,8 +51,6 @@ ** YYNOCODE is a number of type YYCODETYPE that is not used for ** any terminal or nonterminal symbol. ** YYFALLBACK If defined, this indicates that one or more tokens -** have fall-back values which should be used if the -** original value of the token will not parse. ** (also known as: "terminal symbols") have fall-back ** values which should be used if the original symbol ** would not parse. This permits keywords to sometimes @@ -126,7 +125,7 @@ ** ** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE ** and YY_MAX_REDUCE - +** ** N == YY_ERROR_ACTION A syntax error has occurred. ** ** N == YY_ACCEPT_ACTION The parser accepts its input. @@ -135,16 +134,20 @@ ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as +** Given state S and lookahead X, the action is computed as either: ** -** yy_action[ yy_shift_ofst[S] + X ] +** (A) N = yy_action[ yy_shift_ofst[S] + X ] +** (B) N = yy_default[S] ** -** If the index value yy_shift_ofst[S]+X is out of range or if the value -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] -** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The yy_shift_ofst[S]+X value is out of range, or +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** -** The formula above is for computing the action when the lookahead is +** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of @@ -213,9 +216,9 @@ typedef struct yyStackEntry yyStackEntry; /* The state of the parser is completely contained in an instance of ** the following structure */ struct yyParser { - int yyidx; /* Index of top element in stack */ + yyStackEntry *yytos; /* Pointer to top element of the stack */ #ifdef YYTRACKMAXSTACKDEPTH - int yyidxMax; /* Maximum value of yyidx */ + int yyhwm; /* High-water mark of the stack */ #endif #ifndef YYNOERRORRECOVERY int yyerrcnt; /* Shifts left before out of the error */ @@ -224,6 +227,7 @@ struct yyParser { #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ + yyStackEntry yystk0; /* First stack entry */ #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ #endif @@ -278,26 +282,37 @@ static const char *const yyRuleName[] = { }; #endif /* NDEBUG */ + #if YYSTACKDEPTH<=0 /* -** Try to increase the size of the parser stack. +** Try to increase the size of the parser stack. Return the number +** of errors. Return 0 on success. */ -static void yyGrowStack(yyParser *p){ +static int yyGrowStack(yyParser *p){ int newSize; + int idx; yyStackEntry *pNew; newSize = p->yystksz*2 + 100; - pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + idx = p->yytos ? (int)(p->yytos - p->yystack) : 0; + if( p->yystack==&p->yystk0 ){ + pNew = malloc(newSize*sizeof(pNew[0])); + if( pNew ) pNew[0] = p->yystk0; + }else{ + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + } if( pNew ){ p->yystack = pNew; - p->yystksz = newSize; + p->yytos = &p->yystack[idx]; #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", - yyTracePrompt, p->yystksz); + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", + yyTracePrompt, p->yystksz, newSize); } #endif + p->yystksz = newSize; } + return pNew==0; } #endif @@ -326,15 +341,24 @@ void *ParseAlloc(void *(CDECL *mallocProc)(YYMALLOCARGTYPE)){ yyParser *pParser; pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); if( pParser ){ - pParser->yyidx = -1; #ifdef YYTRACKMAXSTACKDEPTH - pParser->yyidxMax = 0; + pParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 + pParser->yytos = NULL; pParser->yystack = NULL; pParser->yystksz = 0; - yyGrowStack(pParser); + if( yyGrowStack(pParser) ){ + pParser->yystack = &pParser->yystk0; + pParser->yystksz = 1; + } #endif +#ifndef YYNOERRORRECOVERY + pParser->yyerrcnt = -1; +#endif + pParser->yytos = pParser->yystack; + pParser->yystack[0].stateno = 0; + pParser->yystack[0].major = 0; } return pParser; } @@ -378,8 +402,9 @@ static void yy_destructor( */ static void yy_pop_parser_stack(yyParser *pParser){ yyStackEntry *yytos; - assert( pParser->yyidx>=0 ); - yytos = &pParser->yystack[pParser->yyidx--]; + assert( pParser->yytos!=0 ); + assert( pParser->yytos > pParser->yystack ); + yytos = pParser->yytos--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sPopping %s\n", @@ -390,10 +415,10 @@ static void yy_pop_parser_stack(yyParser *pParser){ yy_destructor(pParser, yytos->major, &yytos->minor); } -/* +/* ** Deallocate and destroy a parser. Destructors are called for ** all stack elements before shutting the parser down. -* +** ** If the YYPARSEFREENEVERNULL macro exists (for example because it ** is defined in a %include section of the input grammar) then it is ** assumed that the input pointer is never NULL. @@ -406,9 +431,9 @@ void ParseFree( #ifndef YYPARSEFREENEVERNULL if( pParser==0 ) return; #endif - while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); + while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 - free(pParser->yystack); + if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); #endif (*freeProc)((void*)pParser); } @@ -419,7 +444,7 @@ void ParseFree( #ifdef YYTRACKMAXSTACKDEPTH int ParseStackPeak(void *p){ yyParser *pParser = (yyParser*)p; - return pParser->yyidxMax; + return pParser->yyhwm; } #endif @@ -432,56 +457,53 @@ static unsigned int yy_find_shift_action( YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; - int stateno = pParser->yystack[pParser->yyidx].stateno; + int stateno = pParser->yytos->stateno; if( stateno>=YY_MIN_REDUCE ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); do{ i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; assert( iLookAhead!=YYNOCODE ); i += iLookAhead; if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } #endif #ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( + { + int j = i - iLookAhead + YYWILDCARD; + if( #if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 + ){ #ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* YYWILDCARD */ } +#endif /* YYWILDCARD */ return yy_default[stateno]; }else{ return yy_action[i]; @@ -500,7 +522,7 @@ static int yy_find_reduce_action( int i; #ifdef YYERRORSYMBOL if( stateno>YY_REDUCE_COUNT ){ - return yy_default[stateno]; + return yy_default[stateno]; } #else assert( stateno<=YY_REDUCE_COUNT ); @@ -525,15 +547,15 @@ static int yy_find_reduce_action( */ static void yyStackOverflow(yyParser *yypParser){ ParseARG_FETCH; - yypParser->yyidx--; + yypParser->yytos--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser - ** stack ever overflows */ + ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ %% /******** End %stack_overflow code ********************************************/ @@ -548,11 +570,11 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){ if( yyTraceFILE ){ if( yyNewStateyystack[yypParser->yyidx].major], + yyTracePrompt,yyTokenName[yypParser->yytos->major], yyNewState); }else{ fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]); + yyTracePrompt,yyTokenName[yypParser->yytos->major]); } } } @@ -570,27 +592,30 @@ static void yy_shift( ParseTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; - yypParser->yyidx++; + yypParser->yytos++; #ifdef YYTRACKMAXSTACKDEPTH - if( yypParser->yyidx>yypParser->yyidxMax ){ - yypParser->yyidxMax = yypParser->yyidx; + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); } #endif -#if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH ){ +#if YYSTACKDEPTH>0 + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){ yyStackOverflow(yypParser); return; } #else - if( yypParser->yyidx>=yypParser->yystksz ){ - yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz ){ + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ + if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); return; } } #endif - yytos = &yypParser->yystack[yypParser->yyidx]; + if( yyNewState > YY_MAX_SHIFT ){ + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yytos = yypParser->yytos; yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor.yy0 = yyMinor; @@ -622,7 +647,7 @@ static void yy_reduce( yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; - yymsp = &yypParser->yystack[yypParser->yyidx]; + yymsp = yypParser->yytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; @@ -636,22 +661,23 @@ static void yy_reduce( ** enough on the stack to push the LHS value */ if( yyRuleInfo[yyruleno].nrhs==0 ){ #ifdef YYTRACKMAXSTACKDEPTH - if( yypParser->yyidx>yypParser->yyidxMax ){ - yypParser->yyidxMax = yypParser->yyidx; + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); } #endif -#if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH-1 ){ +#if YYSTACKDEPTH>0 + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){ yyStackOverflow(yypParser); return; } #else - if( yypParser->yyidx>=yypParser->yystksz-1 ){ - yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz-1 ){ + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ + if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); return; } + yymsp = yypParser->yytos; } #endif } @@ -674,15 +700,17 @@ static void yy_reduce( yysize = yyRuleInfo[yyruleno].nrhs; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - yypParser->yyidx -= yysize - 1; + if( yyact>YY_MAX_SHIFT ){ + yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } yymsp -= yysize-1; + yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact); }else{ assert( yyact == YY_ACCEPT_ACTION ); - yypParser->yyidx -= yysize; + yypParser->yytos -= yysize; yy_accept(yypParser); } } @@ -700,7 +728,7 @@ static void yy_parse_failed( fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); } #endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ /************ Begin %parse_failure code ***************************************/ @@ -738,7 +766,10 @@ static void yy_accept( fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); } #endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif + assert( yypParser->yytos==yypParser->yystack ); /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ @@ -782,28 +813,8 @@ void Parse( #endif yyParser *yypParser; /* The parser */ - /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; - if( yypParser->yyidx<0 ){ -#if YYSTACKDEPTH<=0 - if( yypParser->yystksz <=0 ){ - yyStackOverflow(yypParser); - return; - } -#endif - yypParser->yyidx = 0; -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n", - yyTracePrompt); - } -#endif - } + assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif @@ -818,7 +829,6 @@ void Parse( do{ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; @@ -827,11 +837,11 @@ void Parse( }else if( yyact <= YY_MAX_REDUCE ){ yy_reduce(yypParser,yyact-YY_MIN_REDUCE); }else{ + assert( yyact == YY_ERROR_ACTION ); + yyminorunion.yy0 = yyminor; #ifdef YYERRORSYMBOL int yymx; #endif - assert( yyact == YY_ERROR_ACTION ); - yyminorunion.yy0 = yyminor; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); @@ -840,7 +850,7 @@ void Parse( #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". + ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** @@ -860,7 +870,7 @@ void Parse( if( yypParser->yyerrcnt<0 ){ yy_syntax_error(yypParser,yymajor,yyminor); } - yymx = yypParser->yystack[yypParser->yyidx].major; + yymx = yypParser->yytos->major; if( yymx==YYERRORSYMBOL || yyerrorhit ){ #ifndef NDEBUG if( yyTraceFILE ){ @@ -871,18 +881,20 @@ void Parse( yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yymajor = YYNOCODE; }else{ - while( - yypParser->yyidx >= 0 && - yymx != YYERRORSYMBOL && - (yyact = yy_find_reduce_action( - yypParser->yystack[yypParser->yyidx].stateno, + while( yypParser->yytos >= yypParser->yystack + && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yypParser->yytos->stateno, YYERRORSYMBOL)) >= YY_MIN_REDUCE ){ yy_pop_parser_stack(yypParser); } - if( yypParser->yyidx < 0 || yymajor==0 ){ + if( yypParser->yytos < yypParser->yystack || yymajor==0 ){ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_parse_failed(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); @@ -901,7 +913,7 @@ void Parse( yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yymajor = YYNOCODE; - + #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** @@ -919,18 +931,23 @@ void Parse( yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif } yymajor = YYNOCODE; #endif } - }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); + }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ - int i; + yyStackEntry *i; + char cDiv = '['; fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); - for(i=1; i<=yypParser->yyidx; i++) - fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ', - yyTokenName[yypParser->yystack[i].major]); + for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){ + fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); + cDiv = ' '; + } fprintf(yyTraceFILE,"]\n"); } #endif From d6b3cbe0c9aae8549670dc6f28dcdff55c10f260 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 14 Oct 2016 13:39:19 +0300 Subject: [PATCH 37/62] Fixed serialization of MovePoly class objects See http://forum.zdoom.org/viewtopic.php?t=53787 Removed "speed" field which is serialized in the parent class --- src/po_man.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/po_man.cpp b/src/po_man.cpp index 2eed96596..c779a8049 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -265,7 +265,6 @@ void DMovePoly::Serialize(FSerializer &arc) { Super::Serialize (arc); arc("angle", m_Angle) - ("speed", m_Speed); ("speedv", m_Speedv); } From 58d44e89c95b1b2b2252ba1f24ebba8961e6d6c3 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 14 Oct 2016 17:03:26 +0300 Subject: [PATCH 38/62] Use single helper for xBRZ scalers --- src/gl/textures/gl_hqresize.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/gl/textures/gl_hqresize.cpp b/src/gl/textures/gl_hqresize.cpp index fe523c79d..866a41f2a 100644 --- a/src/gl/textures/gl_hqresize.cpp +++ b/src/gl/textures/gl_hqresize.cpp @@ -266,21 +266,10 @@ static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t* return newBuffer; } -static unsigned char *xbrzoldHelper( void (*xbrzFunction) ( size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz_old::ScalerCfg& cfg, int yFirst, int yLast ), - const int N, - unsigned char *inputBuffer, - const int inWidth, - const int inHeight, - int &outWidth, - int &outHeight ) +static void xbrzOldScale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, xbrz::ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast) { - outWidth = N * inWidth; - outHeight = N *inHeight; - - unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; - xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), inWidth, inHeight, xbrz_old::ScalerCfg(), 0, std::numeric_limits::max()); - delete[] inputBuffer; - return newBuffer; + static_assert(sizeof(xbrz::ScalerCfg) == sizeof(xbrz_old::ScalerCfg), "ScalerCfg classes have different layout"); + xbrz_old::scale(factor, src, trg, srcWidth, srcHeight, reinterpret_cast(cfg), yFirst, yLast); } @@ -372,7 +361,7 @@ unsigned char *gl_CreateUpsampledTextureBuffer ( const FTexture *inputTexture, u case 13: case 14: case 15: - return xbrzoldHelper(xbrz_old::scale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight ); + return xbrzHelper(xbrzOldScale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight ); } } From c3ced5842ac2b103ca332dbe8ff1e01916af6cde Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 14 Oct 2016 17:14:49 +0300 Subject: [PATCH 39/62] Added multithreaded upscaling with xBRZ (macOS only) --- src/gl/textures/gl_hqresize.cpp | 52 ++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/gl/textures/gl_hqresize.cpp b/src/gl/textures/gl_hqresize.cpp index 866a41f2a..253d91f4b 100644 --- a/src/gl/textures/gl_hqresize.cpp +++ b/src/gl/textures/gl_hqresize.cpp @@ -46,6 +46,17 @@ #include "gl/xbr/xbrz.h" #include "gl/xbr/xbrz_old.h" +#ifdef __APPLE__ +# include +# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +# define GZ_USE_LIBDISPATCH +# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#endif // __APPLE__ + +#ifdef GZ_USE_LIBDISPATCH +# include +#endif // GZ_USE_LIBDISPATCH + CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { if (self < 0 || self > 16) @@ -76,6 +87,22 @@ CVAR (Flag, gl_texture_hqresize_textures, gl_texture_hqresize_targets, 1); CVAR (Flag, gl_texture_hqresize_sprites, gl_texture_hqresize_targets, 2); CVAR (Flag, gl_texture_hqresize_fonts, gl_texture_hqresize_targets, 4); +#ifdef GZ_USE_LIBDISPATCH +CVAR(Bool, gl_texture_hqresize_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); + +CUSTOM_CVAR(Int, gl_texture_hqresize_mt_width, 16, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 2) self = 2; + if (self > 1024) self = 1024; +} + +CUSTOM_CVAR(Int, gl_texture_hqresize_mt_height, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 2) self = 2; + if (self > 1024) self = 1024; +} +#endif // GZ_USE_LIBDISPATCH + static void scale2x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight ) { @@ -261,7 +288,30 @@ static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t* outHeight = N *inHeight; unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; - xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits::max()); + +#ifdef GZ_USE_LIBDISPATCH + const int thresholdWidth = gl_texture_hqresize_mt_width; + const int thresholdHeight = gl_texture_hqresize_mt_height; + + if (gl_texture_hqresize_multithread + && inWidth > thresholdWidth + && inHeight > thresholdHeight) + { + const dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_apply(inHeight / thresholdHeight + 1, queue, ^(size_t sliceY) + { + xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), + inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), sliceY * thresholdHeight, (sliceY + 1) * thresholdHeight); + }); + } + else +#endif // GZ_USE_LIBDISPATCH + { + xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), + inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits::max()); + } + delete[] inputBuffer; return newBuffer; } From 657abb374b8682ea1b36ae89622d11ac697d08f8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 14 Oct 2016 11:24:03 +0200 Subject: [PATCH 40/62] Fix SkyViewpoint skyboxes not being rendered --- src/r_plane.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index ff23492ab..07001bf1b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1314,7 +1314,7 @@ void R_DrawPortals () vissprite_p = firstvissprite; visplaneStack.Pop (pl); - if (pl->Alpha > 0) + if (pl->Alpha > 0 && pl->picnum != skyflatnum) { R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true); } From 36aff68501d4e21c9ea6d24474dafd7bf68b108b Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 14 Oct 2016 15:23:23 +0200 Subject: [PATCH 41/62] Fix divide by zero if yscale is too small a number --- src/r_things.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index ab75c15b0..99ca68b60 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -408,7 +408,7 @@ void R_DrawVisSprite (vissprite_t *vis) ESPSResult mode; bool ispsprite = (!vis->sector && vis->gpos != FVector3(0, 0, 0)); - if (vis->xscale == 0 || vis->yscale == 0) + if (vis->xscale == 0 || fabs(vis->yscale) < (1.0f / 32000.0f)) { // scaled to 0; can't see return; } From 0370592422830fcf22796d86977df53d4b5d52b1 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 14 Oct 2016 14:31:58 +0300 Subject: [PATCH 42/62] Fixed serialization of DSeqPolyNode class objects Polyobject pointer was not serialized at all --- src/s_sndseq.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 23837c28b..3b39965ff 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -442,7 +442,7 @@ IMPLEMENT_CLASS (DSeqPolyNode) void DSeqPolyNode::Serialize(FSerializer &arc) { Super::Serialize (arc); - //arc << m_Poly; + arc("poly", m_Poly); } IMPLEMENT_CLASS (DSeqSectorNode) From 0df6ba69516d239a3a5f255a72e1b0edb0673c72 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Fri, 14 Oct 2016 09:13:31 +0200 Subject: [PATCH 43/62] First, take care of usdf.txt Updated about the new 'goodbye' property. --- specs/usdf.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/specs/usdf.txt b/specs/usdf.txt index 1367ccfbf..c3c286f20 100644 --- a/specs/usdf.txt +++ b/specs/usdf.txt @@ -87,14 +87,16 @@ conversation // Starts a dialog. page // Starts a new page. Pages are automatically numbered starting at 1. { - name = ; // Name that goes in the upper left hand corner - panel = ; // Name of lump to render as the background. - voice = ; // Narration sound lump. - dialog = ; // Dialog of the page. - drop = ; // mobj for the object to drop if the actor is - // killed. - link = ; // Page to jump to if all ifitem conditions are - // satisified. + name = ; // Name that goes in the upper left hand corner + panel = ; // Name of lump to render as the background. + voice = ; // Narration sound lump. + dialog = ; // Dialog of the page. + goodbye = ; // Custom goodbye message. If omitted then the + // generic goodbyes will be displayed instead. + drop = ; // mobj for the object to drop if the actor is + // killed. + link = ; // Page to jump to if all ifitem conditions are + // satisified. // jumps to the specified page if the player has the specified amount // or more of item in their inventory. This can be repeated as many From 1ab990f81f2021b4912635cda5321c89e7e0fd84 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Fri, 14 Oct 2016 09:17:35 +0200 Subject: [PATCH 44/62] Again... --- specs/usdf.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/usdf.txt b/specs/usdf.txt index c3c286f20..093c9e7d7 100644 --- a/specs/usdf.txt +++ b/specs/usdf.txt @@ -91,7 +91,7 @@ conversation // Starts a dialog. panel = ; // Name of lump to render as the background. voice = ; // Narration sound lump. dialog = ; // Dialog of the page. - goodbye = ; // Custom goodbye message. If omitted then the + goodbye = ; // Custom goodbye message. If omitted then the // generic goodbyes will be displayed instead. drop = ; // mobj for the object to drop if the actor is // killed. From ecffd0bea653e04a5a2deb648c70eee546371336 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Fri, 14 Oct 2016 11:55:50 +0200 Subject: [PATCH 45/62] Done the code changes. This time only nulls I've added are nullptrs --- src/namedef.h | 1 + src/p_conversation.cpp | 25 +++++++++++++++++++++---- src/p_conversation.h | 1 + src/p_usdf.cpp | 6 +++++- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 36953e385..eab87c503 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -584,6 +584,7 @@ xx(Dialog) xx(Ifitem) xx(Choice) xx(Link) +xx(Goodbye) // Special menus xx(Mainmenu) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index a697223e7..31fa25030 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -556,6 +556,7 @@ FStrifeDialogueNode::~FStrifeDialogueNode () { if (SpeakerName != NULL) delete[] SpeakerName; if (Dialogue != NULL) delete[] Dialogue; + if (Goodbye != nullptr) delete[] Goodbye; FStrifeDialogueReply *tokill = Children; while (tokill != NULL) { @@ -743,10 +744,26 @@ public: ++i; V_FreeBrokenLines (ReplyLines); } - char goodbye[25]; - mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1+(pr_randomspeech() % NUM_RANDOM_GOODBYES)); - const char *goodbyestr = GStrings[goodbye]; - if (goodbyestr == NULL) goodbyestr = "Bye."; + const char *goodbyestr = CurNode->Goodbye; + if (goodbyestr == nullptr) + { + char goodbye[25]; + mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1 + (pr_randomspeech() % NUM_RANDOM_GOODBYES)); + goodbyestr = GStrings[goodbye]; + if (goodbyestr == nullptr) goodbyestr = "Bye."; + } + else if (strncmp(goodbyestr, "RANDOM_", 7) == 0) + { + FString byetext; + + byetext.Format("TXT_%s_%02d", goodbyestr, 1 + (pr_randomspeech() % NUM_RANDOM_LINES)); + goodbyestr = GStrings[byetext]; + if (goodbyestr == nullptr) goodbyestr = "Bye."; + } + else if (goodbyestr[0] == '$') + { + goodbyestr = GStrings(goodbyestr + 1); + } mResponses.Push(mResponseLines.Size()); mResponseLines.Push(FString(goodbyestr)); diff --git a/src/p_conversation.h b/src/p_conversation.h index d6ba65d78..5b068fb04 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -30,6 +30,7 @@ struct FStrifeDialogueNode FSoundID SpeakerVoice; FTextureID Backdrop; char *Dialogue; + char *Goodbye = nullptr; // must init to null for binary scripts to work as intended FStrifeDialogueReply *Children; }; diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index 13a02b964..dccec7c21 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -286,6 +286,7 @@ class USDFParser : public UDMFParserBase FString SpeakerName; FString Dialogue; + FString Goodbye; while (!sc.CheckToken('}')) { @@ -331,7 +332,9 @@ class USDFParser : public UDMFParserBase node->ItemCheckNode = CheckInt(key); break; - + case NAME_Goodbye: + Goodbye = CheckString(key); + break; } } else @@ -354,6 +357,7 @@ class USDFParser : public UDMFParserBase } node->SpeakerName = ncopystring(SpeakerName); node->Dialogue = ncopystring(Dialogue); + node->Goodbye = ncopystring(Goodbye); return true; } From 08504dcbe235415a4243e8c76f26ed54b0255a04 Mon Sep 17 00:00:00 2001 From: FishyClockwork Date: Fri, 14 Oct 2016 15:17:19 +0200 Subject: [PATCH 46/62] Added a small check just in case... --- src/p_conversation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 31fa25030..1762ae98e 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -763,6 +763,7 @@ public: else if (goodbyestr[0] == '$') { goodbyestr = GStrings(goodbyestr + 1); + if (goodbyestr == nullptr) goodbyestr = "Bye."; } mResponses.Push(mResponseLines.Size()); mResponseLines.Push(FString(goodbyestr)); From 2e882a41a33f0a7d45d229a817e5a9db2ce4e725 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Oct 2016 23:13:08 +0200 Subject: [PATCH 47/62] - removed some redundancy. --- src/p_conversation.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 1762ae98e..f216d9d78 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -750,7 +750,6 @@ public: char goodbye[25]; mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1 + (pr_randomspeech() % NUM_RANDOM_GOODBYES)); goodbyestr = GStrings[goodbye]; - if (goodbyestr == nullptr) goodbyestr = "Bye."; } else if (strncmp(goodbyestr, "RANDOM_", 7) == 0) { @@ -758,13 +757,12 @@ public: byetext.Format("TXT_%s_%02d", goodbyestr, 1 + (pr_randomspeech() % NUM_RANDOM_LINES)); goodbyestr = GStrings[byetext]; - if (goodbyestr == nullptr) goodbyestr = "Bye."; } else if (goodbyestr[0] == '$') { goodbyestr = GStrings(goodbyestr + 1); - if (goodbyestr == nullptr) goodbyestr = "Bye."; } + if (goodbyestr == nullptr) goodbyestr = "Bye."; mResponses.Push(mResponseLines.Size()); mResponseLines.Push(FString(goodbyestr)); From f23e5d26775c7e5af8f60f9dc66dee2a469c0f46 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Fri, 14 Oct 2016 22:02:55 -0500 Subject: [PATCH 48/62] Fixed: XLAT would not parse - Disable the changes from commit 96afce241d6bc08cfdb0018ea6e5f0c23e8ba5c8 because it appears to not recognize default rules that reduce as reducing. - When tracing a parser, flush after every line output in case an assert is hit so you can actually see what it did up to that point. --- tools/lemon/lemon.c | 8 ++++++++ tools/lemon/lempar.c | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index f2da9c6f8..bdc004a17 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -199,7 +199,9 @@ struct rule { int index; /* An index number for this rule */ int iRule; /* Rule number as used in the generated tables */ Boolean canReduce; /* True if this rule is ever reduced */ +#if 0 Boolean doesReduce; /* Reduce actions occur after optimization */ +#endif struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *next; /* Next rule in the global list */ }; @@ -4156,6 +4158,7 @@ void ReportTable( } free(ax); +#if 0 /* Mark rules that are actually used for reduce actions after all ** optimizations have been applied */ @@ -4168,6 +4171,7 @@ void ReportTable( } } } +#endif /* Finish rendering the constants now that the action table has ** been computed */ @@ -4462,12 +4466,16 @@ void ReportTable( assert( rp->noCode ); fprintf(out," /* (%d) ", rp->iRule); writeRuleText(out, rp); +#if 0 if( rp->doesReduce ){ +#endif fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; +#if 0 }else{ fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n", rp->iRule); lineno++; } +#endif } fprintf(out," break;\n"); lineno++; tplt_xfer(lemp->name,in,out,&lineno); diff --git a/tools/lemon/lempar.c b/tools/lemon/lempar.c index 0e360bab9..93b612017 100644 --- a/tools/lemon/lempar.c +++ b/tools/lemon/lempar.c @@ -308,6 +308,7 @@ static int yyGrowStack(yyParser *p){ if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", yyTracePrompt, p->yystksz, newSize); + fflush(yyTraceFILE); } #endif p->yystksz = newSize; @@ -410,6 +411,7 @@ static void yy_pop_parser_stack(yyParser *pParser){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); + fflush(yyTraceFILE); } #endif yy_destructor(pParser, yytos->major, &yytos->minor); @@ -474,6 +476,7 @@ static unsigned int yy_find_shift_action( if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + fflush(yyTraceFILE); } #endif assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ @@ -498,6 +501,7 @@ static unsigned int yy_find_shift_action( fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + fflush(yyTraceFILE); } #endif /* NDEBUG */ return yy_action[j]; @@ -551,6 +555,7 @@ static void yyStackOverflow(yyParser *yypParser){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); + fflush(yyTraceFILE); } #endif while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); @@ -576,6 +581,7 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){ fprintf(yyTraceFILE,"%sShift '%s'\n", yyTracePrompt,yyTokenName[yypParser->yytos->major]); } + fflush(yyTraceFILE); } } #else @@ -653,6 +659,7 @@ static void yy_reduce( yysize = yyRuleInfo[yyruleno].nrhs; fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, yyRuleName[yyruleno], yymsp[-yysize].stateno); + fflush(yyTraceFILE); } #endif /* NDEBUG */ @@ -726,6 +733,7 @@ static void yy_parse_failed( #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); + fflush(yyTraceFILE); } #endif while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); @@ -764,12 +772,17 @@ static void yy_accept( #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); + fflush(yyTraceFILE); } #endif #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif +#if 0 assert( yypParser->yytos==yypParser->yystack ); +#else + while (yypParser->yytos>yypParser->yystack) yy_pop_parser_stack(yypParser); +#endif /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ @@ -823,6 +836,7 @@ void Parse( #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + fflush(yyTraceFILE); } #endif @@ -845,6 +859,7 @@ void Parse( #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); + fflush(yyTraceFILE); } #endif #ifdef YYERRORSYMBOL @@ -876,6 +891,7 @@ void Parse( if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sDiscard input token %s\n", yyTracePrompt,yyTokenName[yymajor]); + fflush(yyTraceFILE); } #endif yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); @@ -949,6 +965,7 @@ void Parse( cDiv = ' '; } fprintf(yyTraceFILE,"]\n"); + fflush(yyTraceFILE); } #endif return; From 162da2fcafbb4c9e55d2272470c81b0a29e2ad9a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Oct 2016 10:51:48 +0200 Subject: [PATCH 49/62] - allow to specify "none" to set an actor's translation to the identity table. --- src/r_data/r_translate.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index bf9365002..983baea58 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1207,6 +1207,10 @@ int R_FindCustomTranslation(const char *name) { return TRANSLATION(TRANSLATION_Standard, 7); } + else if (!stricmp(name, "None")) + { + return 0; + } int *t = customTranslationMap.CheckKey(FName(name, true)); return (t != nullptr)? *t : -1; } From 58ec0e4594d2cd112e9da5ba1d5f764edc35290f Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sat, 15 Oct 2016 20:57:56 -0500 Subject: [PATCH 50/62] Add OF_Transient flag for objects that shouldn't be written to disk --- src/dobject.h | 4 ++++ src/serializer.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dobject.h b/src/dobject.h index 51102bc4c..91a80f9d0 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -201,6 +201,7 @@ enum EObjectFlags OF_EuthanizeMe = 1 << 5, // Object wants to die OF_Cleanup = 1 << 6, // Object is now being deleted by the collector OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning + OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk) OF_WhiteBits = OF_White0 | OF_White1, OF_MarkBits = OF_WhiteBits | OF_Black, @@ -573,6 +574,9 @@ protected: } }; +// When you write to a pointer to an Object, you must call this for +// proper bookkeeping in case the Object holding this pointer has +// already been processed by the GC. static inline void GC::WriteBarrier(DObject *pointing, DObject *pointed) { if (pointed != NULL && pointed->IsWhite() && pointing->IsBlack()) diff --git a/src/serializer.cpp b/src/serializer.cpp index 7861701c0..3a66a8397 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -1451,7 +1451,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje { ndx = -1; } - else if (value->ObjectFlags & OF_EuthanizeMe) + else if (value->ObjectFlags & (OF_EuthanizeMe | OF_Transient)) { return arc; } From ae14993ba44dff703a190782bcf03594fb74d901 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sat, 15 Oct 2016 21:14:34 -0500 Subject: [PATCH 51/62] Fixed: Possible invalid processing for Crash states that immediately destroy the actor - Setting an actor's Crash state has the potential to destroy the actor if the Crash state has one or more 0-tic states that end with Stop. This was not taken into account when the object's Z velocity was 0, but it was under the floor anyway. --- src/p_mobj.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 1ebec242e..8f926ea77 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3799,6 +3799,8 @@ void AActor::Tick () else if (Z() <= floorz) { Crash(); + if (ObjectFlags & OF_EuthanizeMe) + return; // actor was destroyed } CheckPortalTransition(true); From e4281454ceebb8714020e6bf1a2c0274d72e5723 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sat, 15 Oct 2016 21:40:24 -0500 Subject: [PATCH 52/62] Split ANIMATED into three parts, filtered by game that uses them - ANIMATED contained definitions for Doom, Heretic, and Strife, all crammed into a single file. This meant that animations from one game could erroneously make their way into maps for another game that provided custom textures with names that matched textures that animated in the other game. There are now three separate ANIMATED lumps with only the animations defined for the original game and no others. The one that gets loaded depends on the game being played. - Added documentation for the ANIMATED file format to the comment for FTextureManager::InitAnimated(), since I had to figure it out from the code. --- src/textures/animations.cpp | 10 ++++++++++ wadsrc/static/animated.lmp | Bin 1450 -> 0 bytes wadsrc/static/filter/game-doomchex/animated.lmp | Bin 0 -> 507 bytes wadsrc/static/filter/game-heretic/animated.lmp | Bin 0 -> 185 bytes wadsrc/static/filter/game-strife/animated.lmp | Bin 0 -> 760 bytes 5 files changed, 10 insertions(+) delete mode 100644 wadsrc/static/animated.lmp create mode 100644 wadsrc/static/filter/game-doomchex/animated.lmp create mode 100644 wadsrc/static/filter/game-heretic/animated.lmp create mode 100644 wadsrc/static/filter/game-strife/animated.lmp diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 74f9b1f55..f46289f07 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -161,6 +161,16 @@ FAnimDef *FTextureManager::AddComplexAnim (FTextureID picnum, const TArray entries, terminated by a 0xFF byte. Each entry +// is 23 bytes long and consists of the following fields: +// Byte 0: Bit 1 set for wall texture, clear for flat texture. +// Bytes 1-9: '\0'-terminated name of first texture. +// Bytes 10-18: '\0'-terminated name of last texture. +// Bytes 19-22: Tics per frame (stored in little endian order). +// //========================================================================== CVAR(Bool, debuganimated, false, 0) diff --git a/wadsrc/static/animated.lmp b/wadsrc/static/animated.lmp deleted file mode 100644 index 100c804c8a8aa4148ed05df34bccf8de671248b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1450 zcmY+E%Z{Tk5Jio8G@939J|zbFwKN2iC=Nu11oevl|B9J=t89|A6zTYM<+^N&nBjVI zeODQyV2$}<@aGpdcd^cp^^~7!(CG$m{~M7V#J=lfas9lD$r?8{&uY3a?qSY==%( zf!z0c;gVXwn%@s0=tM&_yI?XW(+FVJB)gcFIi7oDCwQ#p(~)Z4HybS4@qFPN8-Zud zY|+e?Q*y;QR*gB91|`J4C2jc<{lQ0cxy$`HfTY3S<*vjvT7r+VR>F5f_P{5_A#)Ib}j0fN}D{5Xx}B0vMhK8OOVQ;iq5~*h1po1-!3*6;S=}KTg2= AssI20 diff --git a/wadsrc/static/filter/game-doomchex/animated.lmp b/wadsrc/static/filter/game-doomchex/animated.lmp new file mode 100644 index 0000000000000000000000000000000000000000..016ce1fa3ff2b51f2f3f9b30f7919609cfdae182 GIT binary patch literal 507 zcmY+AOAdlS5Ja1}@i@R>qRU1GLKwizfZYEi+S4DRtR63wqA6JR2?y^01S)_l(9<8d z`PdkkPNoG+2Ye%C0Wy%(k~XYsN7cZPJ$J{rKBw{yAaGNi!Z`bqY6PrX-Y6~bm#%8l z4=K6Om%1U}EubZr6tIiq%TWnK#g}lJbi-)^(M3N-e_#lpfRY~4*00OvK;b8y|C`eU zj?-K+ccd{sk=7fxKN9LZu0p8 Dh$dJa literal 0 HcmV?d00001 diff --git a/wadsrc/static/filter/game-heretic/animated.lmp b/wadsrc/static/filter/game-heretic/animated.lmp new file mode 100644 index 0000000000000000000000000000000000000000..80102c88e203ad1ccffd5f13a6e480f81111b5b1 GIT binary patch literal 185 zcmYL>K@NZ*39gl6-&O=>w zaqkjr+>67nou_Jyd12t)o9dpPTEM#x)e=%#h?kIzGT);>U;|)wHcVr@o{*j3e|2fq z-m2@{wa=*q)|%O(nf;0{AdKiKfp z*s$slR8Q5V$I%9tz`HND#A-uUUFr&BDBw_3T`)6Rs{5-Wr Date: Sun, 16 Oct 2016 09:12:43 +0200 Subject: [PATCH 53/62] - use the newly added OF_Transient flag to avoid writing out the owned dynamic lights to savegames instead of destroying and recreating them each time. --- src/gl/dynlights/gl_dynlight.cpp | 1 + src/gl/scene/gl_scene.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index 3fffe3641..ae19ecf60 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -1081,6 +1081,7 @@ void gl_AttachLight(AActor *actor, unsigned int count, const FLightDefaults *lig light = Spawn(actor->Pos(), NO_REPLACE); light->target = actor; light->owned = true; + light->ObjectFlags |= OF_Transient; actor->dynamiclights.Push(light); } light->flags2&=~MF2_DORMANT; diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 4b7bc762f..b53be4aaa 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -1199,7 +1199,6 @@ void FGLInterface::StateChanged(AActor *actor) void FGLInterface::StartSerialize(FSerializer &arc) { - gl_DeleteAllAttachedLights(); if (arc.BeginObject("glinfo")) { arc("fogdensity", fogdensity) @@ -1211,8 +1210,11 @@ void FGLInterface::StartSerialize(FSerializer &arc) void FGLInterface::EndSerialize(FSerializer &arc) { - gl_RecreateAllAttachedLights(); - if (arc.isReading()) gl_InitPortals(); + if (arc.isReading()) + { + gl_RecreateAllAttachedLights(); + gl_InitPortals(); + } } //=========================================================================== From 9dd42be15f72b5128be823e6aeb0adafa3915486 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sun, 16 Oct 2016 16:22:21 -0400 Subject: [PATCH 54/62] - 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 55/62] - 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 56/62] - 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 57/62] 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 58/62] 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 59/62] 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 60/62] - 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 61/62] - 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) From 96437d95fa62e0694e1c8bf4e289df0d0f320523 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 20 Oct 2016 10:36:23 +0200 Subject: [PATCH 62/62] - use the new ZDoom code for retrieving a sky's cap color to avoid redundancies. --- src/gl/textures/gl_texture.cpp | 37 +--------------------------------- src/gl/textures/gl_texture.h | 1 - src/textures/textures.h | 4 ---- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/src/gl/textures/gl_texture.cpp b/src/gl/textures/gl_texture.cpp index ce6ff398c..8aaa98ae6 100644 --- a/src/gl/textures/gl_texture.cpp +++ b/src/gl/textures/gl_texture.cpp @@ -167,7 +167,7 @@ void gl_GenerateGlobalBrightmapFromColormap() // component becomes one. // //=========================================================================== -PalEntry averageColor(const DWORD *data, int size, int maxout) +static PalEntry averageColor(const DWORD *data, int size, int maxout) { int i; unsigned int r, g, b; @@ -216,10 +216,7 @@ FTexture::MiscGLInfo::MiscGLInfo() throw() GlowColor = 0; GlowHeight = 128; bSkybox = false; - FloorSkyColor = 0; - CeilingSkyColor = 0; bFullbright = false; - bSkyColorDone = false; bBrightmapChecked = false; bDisableFullbright = false; bNoFilter = false; @@ -326,38 +323,6 @@ void FTexture::GetGlowColor(float *data) data[2]=gl_info.GlowColor.b/255.0f; } -//=========================================================================== -// -// Gets the average color of a texture for use as a sky cap color -// -//=========================================================================== - -PalEntry FTexture::GetSkyCapColor(bool bottom) -{ - PalEntry col; - int w; - int h; - - if (!gl_info.bSkyColorDone) - { - gl_info.bSkyColorDone = true; - - unsigned char *buffer = GLRenderer->GetTextureBuffer(this, w, h); - - if (buffer) - { - gl_info.CeilingSkyColor = averageColor((DWORD *) buffer, w * MIN(30, h), 0); - if (h>30) - { - gl_info.FloorSkyColor = averageColor(((DWORD *) buffer)+(h-30)*w, w * 30, 0); - } - else gl_info.FloorSkyColor = gl_info.CeilingSkyColor; - delete[] buffer; - } - } - return bottom? gl_info.FloorSkyColor : gl_info.CeilingSkyColor; -} - //=========================================================================== // // Finds gaps in the texture which can be skipped by the renderer diff --git a/src/gl/textures/gl_texture.h b/src/gl/textures/gl_texture.h index 9ee9b27f9..455678f85 100644 --- a/src/gl/textures/gl_texture.h +++ b/src/gl/textures/gl_texture.h @@ -24,7 +24,6 @@ protected: void gl_GenerateGlobalBrightmapFromColormap(); -PalEntry averageColor(const DWORD *data, int size, int maxout); diff --git a/src/textures/textures.h b/src/textures/textures.h index 518787dc0..cc5bba389 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -307,8 +307,6 @@ public: FGLTexture *SystemTexture[2]; FTexture *Brightmap; PalEntry GlowColor; - PalEntry FloorSkyColor; - PalEntry CeilingSkyColor; int GlowHeight; FloatRect *areas; int areacount; @@ -318,7 +316,6 @@ public: bool bGlowing:1; // Texture glows bool bFullbright:1; // always draw fullbright bool bSkybox:1; // This is a skybox - bool bSkyColorDone:1; // Fill color for sky char bBrightmapChecked:1; // Set to 1 if brightmap has been checked bool bDisableFullbright:1; // This texture will not be displayed as fullbright sprite bool bNoFilter:1; @@ -331,7 +328,6 @@ public: MiscGLInfo gl_info; void GetGlowColor(float *data); - PalEntry GetSkyCapColor(bool bottom); bool isGlowing() { return gl_info.bGlowing; } bool isFullbright() { return gl_info.bFullbright; } void CreateDefaultBrightmap();