This commit is contained in:
Rachael Alexanderson 2017-11-22 18:08:16 -05:00
commit 339b2b8aec
13 changed files with 672 additions and 57 deletions

2
.gitignore vendored
View file

@ -52,3 +52,5 @@
/src/r_drawersasm.obj
/src/r_drawersasm.o
.vs
/src/gl/unused
/mapfiles_release/*.map

View file

@ -702,6 +702,7 @@ set ( SWRENDER_SOURCES
swrenderer/r_swrenderer.cpp
swrenderer/r_memory.cpp
swrenderer/r_renderthread.cpp
swrenderer/drawers/r_draw.cpp
swrenderer/drawers/r_draw_pal.cpp
swrenderer/drawers/r_draw_rgba.cpp
swrenderer/drawers/r_thread.cpp
@ -959,6 +960,7 @@ set (PCH_SOURCES
stats.cpp
stringtable.cpp
teaminfo.cpp
umapinfo.cpp
v_blend.cpp
v_collection.cpp
v_draw.cpp

View file

@ -253,7 +253,7 @@ struct FSpecialAction
{
FName Type; // this is initialized before the actors...
uint8_t Action;
int Args[5]; // must allow 16 bit tags for 666 & 667!
int Args[5];
};
class DScroller;
@ -307,6 +307,11 @@ struct FExitText
FString mText;
FString mMusic;
FString mBackdrop;
FExitText(int def = 0, int order = -1, const FString &text = "", const FString &backdrop = "", const FString &music = "")
: mDefined(int16_t(def)), mOrder(int16_t(order)), mText(text), mMusic(music), mBackdrop(backdrop)
{
}
};
struct level_info_t
@ -619,5 +624,8 @@ struct FEpisode
extern TArray<FEpisode> AllEpisodes;
int ParseUMapInfo(int lumpnum);
void CommitUMapinfo(level_info_t *defaultinfo);
#endif //__G_LEVEL_H__

View file

@ -2206,7 +2206,7 @@ void G_ParseMapInfo (FString basemapinfo)
parse.ParseMapInfo(baselump, gamedefaults, defaultinfo);
}
static const char *mapinfonames[] = { "MAPINFO", "ZMAPINFO", NULL };
static const char *mapinfonames[] = { "MAPINFO", "ZMAPINFO", "UMAPINFO", NULL };
int nindex;
// Parse any extra MAPINFOs.
@ -2222,10 +2222,28 @@ void G_ParseMapInfo (FString basemapinfo)
if (altlump >= 0) continue;
}
FMapInfoParser parse(nindex == 1? FMapInfoParser::FMT_New : FMapInfoParser::FMT_Unknown);
level_info_t defaultinfo;
parse.ParseMapInfo(lump, gamedefaults, defaultinfo);
else if (nindex == 2)
{
// MAPINFO and ZMAPINFO will override UMAPINFO if in the same WAD.
int wad = Wads.GetLumpFile(lump);
int altlump = Wads.CheckNumForName("ZMAPINFO", ns_global, wad, true);
if (altlump >= 0) continue;
altlump = Wads.CheckNumForName("MAPINFO", ns_global, wad, true);
if (altlump >= 0) continue;
}
if (nindex != 2)
{
CommitUMapinfo(&gamedefaults); // UMPAINFOs are collected until a regular MAPINFO is found so that they properly use the base settings.
FMapInfoParser parse(nindex == 1 ? FMapInfoParser::FMT_New : FMapInfoParser::FMT_Unknown);
level_info_t defaultinfo;
parse.ParseMapInfo(lump, gamedefaults, defaultinfo);
}
else
{
ParseUMapInfo(lump);
}
}
CommitUMapinfo(&gamedefaults); // commit remaining UMPAINFOs.
if (AllEpisodes.Size() == 0)
{

View file

@ -724,6 +724,18 @@ FName FMapInfoParser::ParseEndGame()
//
//==========================================================================
FName MakeEndPic(const char *string)
{
FString seqname;
seqname << "@EndPic_" << string;
FIntermissionDescriptor *desc = new FIntermissionDescriptor;
FIntermissionAction *action = new FIntermissionAction;
action->mBackground = string;
desc->mActions.Push(action);
ReplaceIntermission(seqname, desc);
return FName(seqname);
}
FName FMapInfoParser::CheckEndSequence()
{
const char *seqname = NULL;
@ -756,14 +768,7 @@ FName FMapInfoParser::CheckEndSequence()
{
ParseComma();
sc.MustGetString ();
FString seqname;
seqname << "@EndPic_" << sc.String;
FIntermissionDescriptor *desc = new FIntermissionDescriptor;
FIntermissionAction *action = new FIntermissionAction;
action->mBackground = sc.String;
desc->mActions.Push(action);
ReplaceIntermission(seqname, desc);
return FName(seqname);
return MakeEndPic(sc.String);
}
else if (sc.Compare("endbunny"))
{

View file

@ -119,7 +119,7 @@ namespace TriScreenDrawerModes
}
template<typename SamplerT>
FORCEINLINE unsigned int SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int &fuzzpos)
FORCEINLINE unsigned int SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int x, int y)
{
if (SamplerT::Mode == (int)Samplers::Shaded)
{
@ -140,12 +140,23 @@ namespace TriScreenDrawerModes
}
else if (SamplerT::Mode == (int)Samplers::Fuzz)
{
using namespace swrenderer;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
sampleshadeout = (sampleshadeout * fuzzcolormap[fuzzpos++]) >> 5;
if (fuzzpos >= FUZZTABLE) fuzzpos = 0;
fixed_t fuzzscale = (200 << FRACBITS) / viewheight;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
return sampleshadeout;
}
else
@ -373,8 +384,6 @@ private:
uint32_t srcalpha = args->uniforms->SrcAlpha();
uint32_t destalpha = args->uniforms->DestAlpha();
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
auto lights = args->uniforms->Lights();
auto num_lights = args->uniforms->NumLights();
FVector3 worldnormal = args->uniforms->Normal();
@ -505,7 +514,7 @@ private:
// Sample fgcolor
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[ix];
unsigned int ifgcolor = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + ix, destY + y);
posU += stepU;
posV += stepV;
@ -608,7 +617,7 @@ private:
// Sample fgcolor
if (SamplerT::Mode == (int)Samplers::FogBoundary && (mask0 & (1 << 31))) color = dest[x];
unsigned int ifgcolor = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x, destY + y);
posU += stepU;
posV += stepV;
@ -711,7 +720,7 @@ private:
// Sample fgcolor
if (SamplerT::Mode == (int)Samplers::FogBoundary && (mask1 & (1 << 31))) color = dest[x];
unsigned int ifgcolor = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x, destY + 4 + y);
posU += stepU;
posV += stepV;
@ -773,7 +782,11 @@ public:
{
using namespace TriScreenDrawerModes;
if (args->SimpleShade())
if (SamplerT::Mode == (int)Samplers::Fuzz)
{
Loop<NoShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
else if (args->SimpleShade())
{
Loop<SimpleShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
@ -869,15 +882,12 @@ private:
int count = x1 - x0;
int fuzzpos = (ScreenTriangle::FuzzStart + x0 * 123 + y0) % FUZZTABLE;
uint32_t posV = startV;
for (int y = y0; y < y1; y++, posV += stepV)
{
int coreBlock = y / 8;
if (coreBlock % thread->num_cores != thread->core)
{
fuzzpos = (fuzzpos + count) % FUZZTABLE;
continue;
}
@ -896,7 +906,7 @@ private:
// Sample fgcolor
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = *dest;
unsigned int ifgcolor = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i, y);
posU += stepU;
// Shade and blend

View file

@ -107,7 +107,7 @@ namespace TriScreenDrawerModes
}
template<typename SamplerT>
FORCEINLINE unsigned int VECTORCALL SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int &fuzzpos)
FORCEINLINE unsigned int VECTORCALL SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int x, int y)
{
if (SamplerT::Mode == (int)Samplers::Shaded)
{
@ -128,12 +128,23 @@ namespace TriScreenDrawerModes
}
else if (SamplerT::Mode == (int)Samplers::Fuzz)
{
using namespace swrenderer;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
sampleshadeout = (sampleshadeout * fuzzcolormap[fuzzpos++]) >> 5;
if (fuzzpos >= FUZZTABLE) fuzzpos = 0;
fixed_t fuzzscale = (200 << FRACBITS) / viewheight;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
return sampleshadeout;
}
else
@ -392,8 +403,6 @@ private:
uint32_t srcalpha = args->uniforms->SrcAlpha();
uint32_t destalpha = args->uniforms->DestAlpha();
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
auto lights = args->uniforms->Lights();
auto num_lights = args->uniforms->NumLights();
__m128 worldnormal = _mm_setr_ps(args->uniforms->Normal().X, args->uniforms->Normal().Y, args->uniforms->Normal().Z, 0.0f);
@ -518,13 +527,13 @@ private:
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[ix * 2];
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + ix * 2, destY + y);
posU += stepU;
posV += stepV;
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[ix * 2 + 1];
ifgcolor[1] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + ix * 2 + 1, destY + y);
posU += stepU;
posV += stepV;
@ -626,13 +635,13 @@ private:
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[x * 2];
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x * 2, destY + y);
posU += stepU;
posV += stepV;
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[x * 2 + 1];
ifgcolor[1] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x * 2 + 1, destY + y);
posU += stepU;
posV += stepV;
@ -736,13 +745,13 @@ private:
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary && (mask1 & (1 << 31))) color = dest[x * 2];
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x * 2, destY + 4 + y);
posU += stepU;
posV += stepV;
if (SamplerT::Mode == (int)Samplers::FogBoundary && (mask1 & (1 << 30))) color = dest[x * 2 + 1];
ifgcolor[1] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x * 2 + 1, destY + 4 + y);
posU += stepU;
posV += stepV;
@ -889,15 +898,12 @@ private:
int count = x1 - x0;
int sseCount = count / 2;
int fuzzpos = (ScreenTriangle::FuzzStart + x0 * 123 + y0) % FUZZTABLE;
uint32_t posV = startV;
for (int y = y0; y < y1; y++, posV += stepV)
{
int coreBlock = y / 8;
if (coreBlock % thread->num_cores != thread->core)
{
fuzzpos = (fuzzpos + count) % FUZZTABLE;
continue;
}
@ -917,12 +923,12 @@ private:
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[0];
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i * 2, y);
posU += stepU;
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[1];
ifgcolor[1] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i * 2 + 1, y);
posU += stepU;
// Shade and blend
@ -948,7 +954,7 @@ private:
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = *dest;
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + sseCount * 2, y);
ifgcolor[1] = 0;
ifgshade[1] = 0;
posU += stepU;

View file

@ -79,7 +79,7 @@ namespace TriScreenDrawerModes
}
template<typename SamplerT>
FORCEINLINE unsigned int SampleShade8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, int &fuzzpos)
FORCEINLINE unsigned int SampleShade8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, int x, int y)
{
if (SamplerT::Mode == (int)Samplers::Shaded)
{
@ -97,11 +97,22 @@ namespace TriScreenDrawerModes
}
else if (SamplerT::Mode == (int)Samplers::Fuzz)
{
using namespace swrenderer;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0;
sampleshadeout = (sampleshadeout * fuzzcolormap[fuzzpos++]) >> 5;
if (fuzzpos >= FUZZTABLE) fuzzpos = 0;
fixed_t fuzzscale = (200 << FRACBITS) / viewheight;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
return sampleshadeout;
}
else
@ -228,8 +239,6 @@ public:
uint32_t srcalpha = args->uniforms->SrcAlpha();
uint32_t destalpha = args->uniforms->DestAlpha();
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
// Calculate gradients
const ShadedTriVertex &v1 = *args->v1;
ScreenTriangleStepVariables gradientX = args->gradientX;
@ -292,7 +301,7 @@ public:
uint8_t bgcolor = dest[ix];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = bgcolor;
uint8_t fgcolor = Sample8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, color, translation);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + ix, destY + y);
if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256;
dest[ix] = ShadeAndBlend8<BlendT>(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha);
posU += stepU;
@ -342,7 +351,7 @@ public:
uint8_t bgcolor = dest[x];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = bgcolor;
uint8_t fgcolor = Sample8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, color, translation);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x, destY + y);
if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256;
dest[x] = ShadeAndBlend8<BlendT>(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha);
}
@ -394,7 +403,7 @@ public:
uint8_t bgcolor = dest[x];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = bgcolor;
uint8_t fgcolor = Sample8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, color, translation);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, destX + x, destY + 4 + y);
if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256;
dest[x] = ShadeAndBlend8<BlendT>(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha);
}
@ -458,15 +467,12 @@ public:
int count = x1 - x0;
int fuzzpos = (ScreenTriangle::FuzzStart + x0 * 123 + y0) % FUZZTABLE;
uint32_t posV = startV;
for (int y = y0; y < y1; y++, posV += stepV)
{
int coreBlock = y / 8;
if (coreBlock % thread->num_cores != thread->core)
{
fuzzpos = (fuzzpos + count) % FUZZTABLE;
continue;
}
@ -478,7 +484,7 @@ public:
uint8_t bgcolor = *dest;
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = bgcolor;
uint8_t fgcolor = Sample8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, color, translation);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, fuzzpos);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i, y);
*dest = ShadeAndBlend8<BlendT>(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha);
posU += stepU;

View file

@ -119,6 +119,8 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
P_FindParticleSubsectors();
PO_LinkToSubsectors();
swrenderer::R_UpdateFuzzPosFrameStart();
if (APART(R_OldBlend)) NormalLight.Maps = realcolormaps.Maps;
else NormalLight.Maps = realcolormaps.Maps + NUMCOLORMAPS * 256 * R_OldBlend;

View file

@ -949,6 +949,76 @@ bool FScanner::Compare (const char *text)
return (stricmp (text, String) == 0);
}
//==========================================================================
//
// Convenience helpers that parse an entire number including a leading minus or plus sign
//
//==========================================================================
bool FScanner::ScanValue(bool allowfloat)
{
bool neg = false;
if (!GetToken())
{
return false;
}
if (TokenType == '-' || TokenType == '+')
{
neg = TokenType == '-';
if (!GetToken())
{
return false;
}
}
if (TokenType != TK_IntConst && (TokenType != TK_FloatConst || !allowfloat))
{
return false;
}
if (neg)
{
Number = -Number;
Float = -Float;
}
return true;
}
bool FScanner::CheckValue(bool allowfloat)
{
auto savedstate = SavePos();
bool res = ScanValue(allowfloat);
if (!res) RestorePos(savedstate);
return res;
}
void FScanner::MustGetValue(bool allowfloat)
{
if (!ScanValue(allowfloat)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
}
bool FScanner::CheckBoolToken()
{
if (CheckToken(TK_True))
{
Number = 1;
Float = 1;
return true;
}
if (CheckToken(TK_False))
{
Number = 0;
Float = 0;
return true;
}
return false;
}
void FScanner::MustGetBoolToken()
{
if (!CheckBoolToken())
ScriptError("Expected true or false");
}
//==========================================================================
//
// FScanner :: TokenName

View file

@ -57,6 +57,12 @@ public:
bool GetFloat();
void MustGetFloat();
bool CheckFloat();
// Token based variant
bool CheckValue(bool allowfloat);
void MustGetValue(bool allowfloat);
bool CheckBoolToken();
void MustGetBoolToken();
void UnGet();
@ -107,6 +113,9 @@ protected:
bool StateOptions;
bool Escape;
VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default
bool ScanValue(bool allowfloat);
};
enum

View file

@ -193,7 +193,7 @@ namespace swrenderer
void R_UpdateFuzzPosFrameStart()
{
if (r_fuzzscale)
if (r_fuzzscale || r_polyrenderer)
{
static int next_random = 0;
@ -207,7 +207,7 @@ namespace swrenderer
void R_UpdateFuzzPos(const SpriteDrawerArgs &args)
{
if (!r_fuzzscale)
if (!r_fuzzscale && !r_polyrenderer)
{
int yl = MAX(args.FuzzY1(), 1);
int yh = MIN(args.FuzzY2(), fuzzviewheight);

477
src/umapinfo.cpp Normal file
View file

@ -0,0 +1,477 @@
//-----------------------------------------------------------------------------
//
// Copyright 2017 Christoph Oelckers
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "w_wad.h"
#include "g_level.h"
#include "sc_man.h"
#include "r_defs.h"
#include "p_setup.h"
#include "gi.h"
FName MakeEndPic(const char *string);
struct BossAction
{
int type;
int special;
int tag;
};
struct UMapEntry
{
FString MapName;
FString LevelName;
FString InterText;
FString InterTextSecret;
TArray<FSpecialAction> BossActions;
char levelpic[9] = "";
char nextmap[9] = "";
char nextsecret[9] = "";
char music[9] = "";
char skytexture[9] = "";
char endpic[9] = "";
char exitpic[9] = "";
char enterpic[9] = "";
char interbackdrop[9] = "FLOOR4_8";
char intermusic[9] = "";
int partime = 0;
int nointermission = 0;
};
static TArray<UMapEntry> Maps;
// -----------------------------------------------
//
// Parses a set of string and concatenates them
//
// -----------------------------------------------
static FString ParseMultiString(FScanner &scanner, int error)
{
FString build;
if (scanner.CheckToken(TK_Identifier))
{
if (!stricmp(scanner.String, "clear"))
{
return "-";
}
else
{
scanner.ScriptError("Either 'clear' or string constant expected");
}
}
do
{
scanner.MustGetToken(TK_StringConst);
if (build.Len() > 0) build += "\n";
build += scanner.String;
}
while (scanner.CheckToken(','));
return build;
}
// -----------------------------------------------
//
// Parses a lump name. The buffer must be at least 9 characters.
//
// -----------------------------------------------
static int ParseLumpName(FScanner &scanner, char *buffer)
{
scanner.MustGetToken(TK_StringConst);
if (strlen(scanner.String) > 8)
{
scanner.ScriptError("String too long. Maximum size is 8 characters.");
return 0;
}
uppercopy(buffer, scanner.String);
return 1;
}
// -----------------------------------------------
//
// Parses a standard property that is already known
// These do not get stored in the property list
// but in dedicated struct member variables.
//
// -----------------------------------------------
static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape)
{
// find the next line with content.
// this line is no property.
scanner.MustGetToken(TK_Identifier);
FString pname = scanner.String;
scanner.MustGetToken('=');
if (!pname.CompareNoCase("levelname"))
{
scanner.MustGetToken(TK_StringConst);
mape->LevelName = scanner.String;
}
else if (!pname.CompareNoCase("next"))
{
ParseLumpName(scanner, mape->nextmap);
}
else if (!pname.CompareNoCase("nextsecret"))
{
ParseLumpName(scanner, mape->nextsecret);
}
else if (!pname.CompareNoCase("levelpic"))
{
ParseLumpName(scanner, mape->levelpic);
}
else if (!pname.CompareNoCase("skytexture"))
{
ParseLumpName(scanner, mape->skytexture);
}
else if (!pname.CompareNoCase("music"))
{
ParseLumpName(scanner, mape->music);
}
else if (!pname.CompareNoCase("endpic"))
{
ParseLumpName(scanner, mape->endpic);
}
else if (!pname.CompareNoCase("endcast"))
{
scanner.MustGetBoolToken();
if (scanner.Number) strcpy(mape->endpic, "$CAST");
else strcpy(mape->endpic, "-");
}
else if (!pname.CompareNoCase("endbunny"))
{
scanner.MustGetBoolToken();
if (scanner.Number) strcpy(mape->endpic, "$BUNNY");
else strcpy(mape->endpic, "-");
}
else if (!pname.CompareNoCase("endgame"))
{
scanner.MustGetBoolToken();
if (scanner.Number) strcpy(mape->endpic, "!");
else strcpy(mape->endpic, "-");
}
else if (!pname.CompareNoCase("exitpic"))
{
ParseLumpName(scanner, mape->exitpic);
}
else if (!pname.CompareNoCase("enterpic"))
{
ParseLumpName(scanner, mape->enterpic);
}
else if (!pname.CompareNoCase("nointermission"))
{
scanner.MustGetBoolToken();
mape->nointermission = scanner.Number;
}
else if (!pname.CompareNoCase("partime"))
{
scanner.MustGetValue(false);
mape->partime = TICRATE * scanner.Number;
}
else if (!pname.CompareNoCase("intertext"))
{
mape->InterText = ParseMultiString(scanner, 1);
if (mape->InterText.IsEmpty()) return 0;
}
else if (!pname.CompareNoCase("intertextsecret"))
{
mape->InterTextSecret = ParseMultiString(scanner, 1);
if (mape->InterTextSecret.IsEmpty()) return 0;
}
else if (!pname.CompareNoCase("interbackdrop"))
{
ParseLumpName(scanner, mape->interbackdrop);
}
else if (!pname.CompareNoCase("intermusic"))
{
ParseLumpName(scanner, mape->intermusic);
}
else if (!pname.CompareNoCase("episode"))
{
FString Episode = ParseMultiString(scanner, 1);
if (Episode.IsEmpty()) return 0;
if (Episode.Compare("-") == 0)
{
// clear the given episode
for (unsigned i = 0; i < AllEpisodes.Size(); i++)
{
if (AllEpisodes[i].mEpisodeMap.CompareNoCase(mape->MapName) == 0)
{
AllEpisodes.Delete(i);
break;
}
}
}
else
{
auto split = Episode.Split("\n");
// add the given episode
FEpisode epi;
epi.mEpisodeName = split[1];
epi.mEpisodeMap = mape->MapName;
epi.mPicName = split[0];
epi.mShortcut = split[2][0];
unsigned i;
for (i = 0; i < AllEpisodes.Size(); i++)
{
if (AllEpisodes[i].mEpisodeMap.CompareNoCase(mape->MapName) == 0)
{
AllEpisodes[i] = std::move(epi);
break;
}
}
if (i == AllEpisodes.Size())
{
AllEpisodes.Push(epi);
}
}
}
else if (!pname.CompareNoCase("bossaction"))
{
scanner.MustGetToken(TK_Identifier);
int classnum, special, tag;
if (!stricmp(scanner.String, "clear"))
{
// mark level free of boss actions
classnum = special = tag = -1;
mape->BossActions.Clear();
}
else
{
FName type = scanner.String;
scanner.MustGetToken(',');
scanner.MustGetValue(false);
int special = scanner.Number;
scanner.MustGetToken(',');
scanner.MustGetValue(false);
int tag = scanner.Number;
// allow no 0-tag specials here, unless a level exit.
if (tag != 0 || special == 11 || special == 51 || special == 52 || special == 124)
{
FSpecialAction & bossact = mape->BossActions[mape->BossActions.Reserve(1)];
line_t line;
maplinedef_t mld;
mld.special = special;
mld.tag = tag;
P_TranslateLineDef(&line, &mld);
bossact = { type, (uint8_t)line.special, {line.args[0], line.args[1],line.args[2],line.args[3],line.args[4]} };
}
}
}
else
{
// Skip over all unknown properties.
do
{
if (!scanner.CheckValue(true))
{
scanner.MustGetAnyToken();
if (scanner.TokenType != TK_Identifier && scanner.TokenType != TK_StringConst && scanner.TokenType != TK_True && scanner.TokenType != TK_False)
{
scanner.ScriptError("Identifier or value expected");
}
}
} while (scanner.CheckToken(','));
}
return 1;
}
// -----------------------------------------------
//
// Parses a complete map entry
//
// -----------------------------------------------
static int ParseMapEntry(FScanner &scanner, UMapEntry *val)
{
scanner.MustGetToken(TK_Identifier);
val->MapName = scanner.String;
scanner.MustGetToken('{');
while(!scanner.CheckToken('}'))
{
ParseStandardProperty(scanner, val);
}
return 1;
}
// -----------------------------------------------
//
// Parses a complete UMAPINFO lump
//
// -----------------------------------------------
int ParseUMapInfo(int lumpnum)
{
FScanner scanner(lumpnum);
unsigned int i;
while (scanner.GetToken())
{
scanner.TokenMustBe(TK_Map);
UMapEntry parsed;
ParseMapEntry(scanner, &parsed);
// Endpic overrides level exits.
if (parsed.endpic[0])
{
parsed.nextmap[0] = parsed.nextsecret[0] = 0;
if (parsed.endpic[0] == '!') parsed.endpic[0] = 0;
}
/*
else if (!parsed.nextmap[0] && !parsed.endpic[0])
{
if (!parsed.MapName.CompareNoCase("MAP30")) uppercopy(parsed.endpic, "$CAST");
else if (!parsed.MapName.CompareNoCase("E1M8")) uppercopy(parsed.endpic, gameinfo.creditPages.Last());
else if (!parsed.MapName.CompareNoCase("E2M8")) uppercopy(parsed.endpic, "VICTORY");
else if (!parsed.MapName.CompareNoCase("E3M8")) uppercopy(parsed.endpic, "$BUNNY");
else if (!parsed.MapName.CompareNoCase("E4M8")) uppercopy(parsed.endpic, "ENDPIC");
else if (gameinfo.gametype == GAME_Chex && !parsed.MapName.CompareNoCase("E1M5")) uppercopy(parsed.endpic, "CREDIT");
else
{
parsed.nextmap[0] = 0; // keep previous setting
}
}
*/
// Does this property already exist? If yes, replace it.
for(i = 0; i < Maps.Size(); i++)
{
if (!parsed.MapName.Compare(Maps[i].MapName))
{
Maps[i] = parsed;
return 1;
}
}
// Not found so create a new one.
Maps.Push(parsed);
}
return 1;
}
// This will get called if after an UMAPINFO lump a regular (Z)MAPINFO is found or when MAPINFO parsing is complete.
void CommitUMapinfo(level_info_t *defaultinfo)
{
for (auto &map : Maps)
{
auto levelinfo = FindLevelInfo(map.MapName);
if (levelinfo == nullptr)
{
// Map did not exist yet.
auto levelindex = wadlevelinfos.Reserve(1);
levelinfo = &wadlevelinfos[levelindex];
*levelinfo = *defaultinfo;
}
if (map.MapName.IsNotEmpty()) levelinfo->MapName = map.MapName;
if (map.LevelName.IsNotEmpty())
{
levelinfo->LevelName = map.LevelName;
levelinfo->PName = ""; // clear the map name patch to force the string version to be shown - unless explicitly overridden right next.
}
if (map.levelpic[0]) levelinfo->PName = map.levelpic;
if (map.nextmap[0]) levelinfo->NextMap = map.nextmap;
else if (map.endpic[0])
{
FName name;
if (!stricmp(map.endpic, "$CAST"))
{
name = "INTER_CAST";
}
else if (!stricmp(map.endpic, "$BUNNY"))
{
name = "INTER_BUNNY";
}
else
{
name = MakeEndPic(map.endpic);
}
if (name != NAME_None)
{
levelinfo->NextMap.Format("enDSeQ%04x", int(name));
}
}
if (map.nextsecret[0]) levelinfo->NextSecretMap = map.nextsecret;
if (map.music[0])
{
levelinfo->Music = map.music;
levelinfo->musicorder = 0;
}
if (map.skytexture[0])
{
levelinfo->SkyPic1 = map.skytexture;
levelinfo->skyspeed1 = 0;
levelinfo->SkyPic2 = "";
levelinfo->skyspeed2 = 0;
}
if (map.partime > 0) levelinfo->partime = map.partime;
if (map.enterpic[0]) levelinfo->EnterPic = map.enterpic;
if (map.exitpic[0]) levelinfo->ExitPic = map.exitpic;
if (map.intermusic[0])
{
levelinfo->InterMusic = map.intermusic;
levelinfo->intermusicorder = 0;
}
if (map.BossActions.Size() > 0)
{
// Setting a boss action will deactivate the flag based monster actions.
levelinfo->specialactions = std::move(map.BossActions);
levelinfo->flags &= ~(LEVEL_BRUISERSPECIAL | LEVEL_CYBORGSPECIAL | LEVEL_SPIDERSPECIAL | LEVEL_MAP07SPECIAL | LEVEL_MINOTAURSPECIAL | LEVEL_HEADSPECIAL | LEVEL_SORCERER2SPECIAL | LEVEL_SPECACTIONSMASK | LEVEL_SPECKILLMONSTERS);
}
const int exflags = FExitText::DEF_TEXT | FExitText::DEF_BACKDROP | FExitText::DEF_MUSIC;
if (map.InterText.IsNotEmpty())
{
if (map.InterText.Compare("-") != 0)
levelinfo->ExitMapTexts[NAME_Normal] = { exflags, 0, map.InterText, map.interbackdrop, map.intermusic[0]? map.intermusic : gameinfo.intermissionMusic };
else
levelinfo->ExitMapTexts[NAME_Normal] = { 0, 0 };
}
if (map.InterTextSecret.IsNotEmpty())
{
if (map.InterTextSecret.Compare("-") != 0)
levelinfo->ExitMapTexts[NAME_Secret] = { exflags, 0, map.InterTextSecret, map.interbackdrop, map.intermusic[0] ? map.intermusic : gameinfo.intermissionMusic };
else
levelinfo->ExitMapTexts[NAME_Secret] = { 0, 0 };
}
if (map.nointermission) levelinfo->flags |= LEVEL_NOINTERMISSION;
}
// All done. If we get here again, start fresh.
Maps.Clear();
Maps.ShrinkToFit();
}