From b6b78176d26f1a11f1e17b5f88a169c639f4138d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 21 Sep 2017 00:42:06 +0200 Subject: [PATCH 001/105] - Add FVector4 and DVector4 to the family of vectors --- src/vectors.h | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) diff --git a/src/vectors.h b/src/vectors.h index 7df929944..c6e6c1a5c 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -654,6 +654,283 @@ struct TVector3 } }; +template +struct TVector4 +{ + typedef TVector3 Vector3; + + vec_t X, Y, Z, W; + + TVector4() + { + } + + TVector4(vec_t a, vec_t b, vec_t c, vec_t d) + : X(a), Y(b), Z(c), W(d) + { + } + + TVector4(vec_t *o) + : X(o[0]), Y(o[1]), Z(o[2]), W(o[3]) + { + } + + TVector4(const TVector4 &other) + : X(other.X), Y(other.Y), Z(other.Z), W(other.W) + { + } + + TVector4(const Vector3 &xyz, vec_t w) + : X(xyz.X), Y(xyz.Y), Z(xyz.Z), W(w) + { + } + + void Zero() + { + Z = Y = X = W = 0; + } + + bool isZero() const + { + return X == 0 && Y == 0 && Z == 0 && W == 0; + } + + TVector4 &operator= (const TVector4 &other) + { + W = other.W, Z = other.Z, Y = other.Y, X = other.X; + return *this; + } + + // Access X and Y and Z as an array + vec_t &operator[] (int index) + { + return (&X)[index]; + } + + const vec_t &operator[] (int index) const + { + return (&X)[index]; + } + + // Test for equality + bool operator== (const TVector4 &other) const + { + return X == other.X && Y == other.Y && Z == other.Z && W = other.W; + } + + // Test for inequality + bool operator!= (const TVector4 &other) const + { + return X != other.X || Y != other.Y || Z != other.Z || W != other.W; + } + + // Test for approximate equality + bool ApproximatelyEquals(const TVector4 &other) const + { + return fabs(X - other.X) < EQUAL_EPSILON && fabs(Y - other.Y) < EQUAL_EPSILON && fabs(Z - other.Z) < EQUAL_EPSILON && fabs(W - other.W) < EQUAL_EPSILON; + } + + // Test for approximate inequality + bool DoesNotApproximatelyEqual(const TVector4 &other) const + { + return fabs(X - other.X) >= EQUAL_EPSILON || fabs(Y - other.Y) >= EQUAL_EPSILON || fabs(Z - other.Z) >= EQUAL_EPSILON || fabs(W - other.W) >= EQUAL_EPSILON; + } + + // Unary negation + TVector4 operator- () const + { + return TVector4(-X, -Y, -Z, -W); + } + + // Scalar addition + TVector4 &operator+= (vec_t scalar) + { + X += scalar, Y += scalar, Z += scalar; W += scalar; + return *this; + } + + friend TVector4 operator+ (const TVector4 &v, vec_t scalar) + { + return TVector4(v.X + scalar, v.Y + scalar, v.Z + scalar, v.W + scalar); + } + + friend TVector4 operator+ (vec_t scalar, const TVector4 &v) + { + return TVector4(v.X + scalar, v.Y + scalar, v.Z + scalar, v.W + scalar); + } + + // Scalar subtraction + TVector4 &operator-= (vec_t scalar) + { + X -= scalar, Y -= scalar, Z -= scalar, W -= scalar; + return *this; + } + + TVector4 operator- (vec_t scalar) const + { + return TVector4(X - scalar, Y - scalar, Z - scalar, W - scalar); + } + + // Scalar multiplication + TVector4 &operator*= (vec_t scalar) + { + X = vec_t(X *scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar), W = vec_t(W * scalar); + return *this; + } + + friend TVector4 operator* (const TVector4 &v, vec_t scalar) + { + return TVector4(v.X * scalar, v.Y * scalar, v.Z * scalar, v.W * scalar); + } + + friend TVector4 operator* (vec_t scalar, const TVector4 &v) + { + return TVector4(v.X * scalar, v.Y * scalar, v.Z * scalar, v.W * scalar); + } + + // Scalar division + TVector4 &operator/= (vec_t scalar) + { + scalar = 1 / scalar, X = vec_t(X * scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar), W = vec_t(W * scalar); + return *this; + } + + TVector4 operator/ (vec_t scalar) const + { + scalar = 1 / scalar; + return TVector4(X * scalar, Y * scalar, Z * scalar, W * scalar); + } + + // Vector addition + TVector4 &operator+= (const TVector4 &other) + { + X += other.X, Y += other.Y, Z += other.Z, W += other.W; + return *this; + } + + TVector4 operator+ (const TVector4 &other) const + { + return TVector4(X + other.X, Y + other.Y, Z + other.Z, W + other.W); + } + + // Vector subtraction + TVector4 &operator-= (const TVector4 &other) + { + X -= other.X, Y -= other.Y, Z -= other.Z, W -= other.W; + return *this; + } + + TVector4 operator- (const TVector4 &other) const + { + return TVector4(X - other.X, Y - other.Y, Z - other.Z, W - other.W); + } + + // Add a 3D vector to this 4D vector, leaving W unchanged. + TVector4 &operator+= (const Vector3 &other) + { + X += other.X, Y += other.Y, Z += other.Z; + return *this; + } + + // Subtract a 3D vector from this 4D vector, leaving W unchanged. + TVector4 &operator-= (const Vector3 &other) + { + X -= other.X, Y -= other.Y, Z -= other.Z; + return *this; + } + + // returns the XYZ fields as a 3D-vector. + Vector3 XYZ() const + { + return{ X, Y, Z }; + } + + // Add a 4D vector and a 3D vector. + friend TVector4 operator+ (const TVector4 &v4, const Vector3 &v3) + { + return TVector4(v4.X + v3.X, v4.Y + v3.Y, v4.Z + v3.Z, v4.W); + } + + friend TVector4 operator- (const TVector4 &v4, const Vector3 &v3) + { + return TVector4(v4.X - v3.X, v4.Y - v3.Y, v4.Z - v3.Z, v4.W); + } + + friend Vector3 operator+ (const Vector3 &v3, const TVector4 &v4) + { + return Vector3(v3.X + v4.X, v3.Y + v4.Y, v3.Z + v4.Z); + } + + // Subtract a 4D vector and a 3D vector. + // Discards the W component of the 4D vector and returns a 3D vector. + friend Vector3 operator- (const TVector3 &v3, const TVector4 &v4) + { + return Vector3(v3.X - v4.X, v3.Y - v4.Y, v3.Z - v4.Z); + } + + // Vector length + double Length() const + { + return g_sqrt(X*X + Y*Y + Z*Z + W*W); + } + + double LengthSquared() const + { + return X*X + Y*Y + Z*Z + W*W; + } + + // Return a unit vector facing the same direction as this one + TVector4 Unit() const + { + double len = Length(); + if (len != 0) len = 1 / len; + return *this * (vec_t)len; + } + + // Scales this vector into a unit vector + void MakeUnit() + { + double len = Length(); + if (len != 0) len = 1 / len; + *this *= (vec_t)len; + } + + // Resizes this vector to be the specified length (if it is not 0) + TVector4 &MakeResize(double len) + { + double vlen = Length(); + if (vlen != 0.) + { + double scale = len / vlen; + X = vec_t(X * scale); + Y = vec_t(Y * scale); + Z = vec_t(Z * scale); + w = vec_t(W * scale); + } + return *this; + } + + TVector4 Resized(double len) + { + double vlen = Length(); + if (vlen != 0.) + { + double scale = len / vlen; + return{ vec_t(X * scale), vec_t(Y * scale), vec_t(Z * scale), vec_t(W * scale) }; + } + else + { + return *this; + } + } + + // Dot product + vec_t operator | (const TVector4 &other) const + { + return X*other.X + Y*other.Y + Z*other.Z + W*other.W; + } +}; + template struct TMatrix3x3 { @@ -1383,12 +1660,14 @@ inline TMatrix3x3::TMatrix3x3(const TVector3 &axis, TAngle degrees) typedef TVector2 FVector2; typedef TVector3 FVector3; +typedef TVector4 FVector4; typedef TRotator FRotator; typedef TMatrix3x3 FMatrix3x3; typedef TAngle FAngle; typedef TVector2 DVector2; typedef TVector3 DVector3; +typedef TVector4 DVector4; typedef TRotator DRotator; typedef TMatrix3x3 DMatrix3x3; typedef TAngle DAngle; From 59ee89b622040f504ecd3aa59a63c6dc1a2c7b00 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 21 Sep 2017 01:21:21 +0200 Subject: [PATCH 002/105] - Make the relationship between TriMatrix, TriVertex and ShadedTriVertex more clean --- src/polyrenderer/drawers/poly_draw_args.h | 9 +++ src/polyrenderer/drawers/poly_drawer32.h | 2 +- src/polyrenderer/drawers/poly_drawer32_sse2.h | 2 +- src/polyrenderer/drawers/poly_drawer8.h | 2 +- src/polyrenderer/drawers/poly_triangle.cpp | 57 +++++++++++-------- src/polyrenderer/drawers/poly_triangle.h | 8 +-- src/polyrenderer/drawers/screen_triangle.cpp | 18 +++--- src/polyrenderer/drawers/screen_triangle.h | 30 +++++----- src/polyrenderer/math/tri_matrix.cpp | 26 ++++----- src/polyrenderer/math/tri_matrix.h | 2 +- 10 files changed, 82 insertions(+), 74 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 69b89a053..c53b0260f 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -46,6 +46,15 @@ public: float A, B, C, D; }; +struct TriVertex +{ + TriVertex() { } + TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w), u(u), v(v) { } + + float x, y, z, w; + float u, v; +}; + class PolyDrawArgs { public: diff --git a/src/polyrenderer/drawers/poly_drawer32.h b/src/polyrenderer/drawers/poly_drawer32.h index 571d6a8ad..2c85e257d 100644 --- a/src/polyrenderer/drawers/poly_drawer32.h +++ b/src/polyrenderer/drawers/poly_drawer32.h @@ -323,7 +323,7 @@ private: int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; // Calculate gradients - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; ScreenTriangleStepVariables gradientY = args->gradientY; ScreenTriangleStepVariables blockPosY; diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 67bac9aad..a88b92bd6 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -334,7 +334,7 @@ private: int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; // Calculate gradients - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; ScreenTriangleStepVariables gradientY = args->gradientY; ScreenTriangleStepVariables blockPosY; diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h index c54513b9c..f78d2a31c 100644 --- a/src/polyrenderer/drawers/poly_drawer8.h +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -231,7 +231,7 @@ public: int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; // Calculate gradients - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; ScreenTriangleStepVariables gradientY = args->gradientY; ScreenTriangleStepVariables blockPosY; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 408b16c12..2448e2544 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -146,8 +146,15 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c const TriMatrix &objectToClip = *drawargs.ObjectToClip(); // Apply transform to get clip coordinates: + FVector4 position = objectToClip * FVector4(v.x, v.y, v.z, v.w); + ShadedTriVertex sv; - sv.position = objectToClip * v; + sv.x = position.X; + sv.y = position.Y; + sv.z = position.Z; + sv.w = position.W; + sv.u = v.u; + sv.v = v.v; // Calculate gl_ClipDistance[i] for (int i = 0; i < 3; i++) @@ -162,12 +169,12 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert) { // A degenerate triangle has a zero cross product for two of its sides. - float ax = vert[1].position.x - vert[0].position.x; - float ay = vert[1].position.y - vert[0].position.y; - float az = vert[1].position.w - vert[0].position.w; - float bx = vert[2].position.x - vert[0].position.x; - float by = vert[2].position.y - vert[0].position.y; - float bz = vert[2].position.w - vert[0].position.w; + float ax = vert[1].x - vert[0].x; + float ay = vert[1].y - vert[0].y; + float az = vert[1].w - vert[0].w; + float bx = vert[2].x - vert[0].x; + float by = vert[2].y - vert[0].y; + float bz = vert[2].w - vert[0].w; float crossx = ay * bz - az * by; float crossy = az * bx - ax * bz; float crossz = ax * by - ay * bx; @@ -182,7 +189,7 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool return; // Cull, clip and generate additional vertices as needed - TriVertex clippedvert[max_additional_vertices]; + ShadedTriVertex clippedvert[max_additional_vertices]; int numclipvert = clipedge(vert, clippedvert); #ifdef NO_SSE @@ -273,7 +280,7 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool } } -int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert) +int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert) { // Clip and cull so that the following is true for all vertices: // -v.w <= v.x <= v.w @@ -288,16 +295,16 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe float *clipd = clipdistance; for (int i = 0; i < 3; i++) { - const auto &v = verts[i].position; + const auto &v = verts[i]; clipd[0] = v.x + v.w; clipd[1] = v.w - v.x; clipd[2] = v.y + v.w; clipd[3] = v.w - v.y; clipd[4] = v.z + v.w; clipd[5] = v.w - v.z; - clipd[6] = verts[i].clipDistance[0]; - clipd[7] = verts[i].clipDistance[1]; - clipd[8] = verts[i].clipDistance[2]; + clipd[6] = v.clipDistance[0]; + clipd[7] = v.clipDistance[1]; + clipd[8] = v.clipDistance[2]; for (int j = 0; j < 9; j++) needsclipping = needsclipping || clipd[i]; clipd += numclipdistances; @@ -308,14 +315,14 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe { for (int i = 0; i < 3; i++) { - memcpy(clippedvert + i, &verts[i].position, sizeof(TriVertex)); + memcpy(clippedvert + i, &verts[i], sizeof(ShadedTriVertex)); } return 3; } #else - __m128 mx = _mm_loadu_ps(&verts[0].position.x); - __m128 my = _mm_loadu_ps(&verts[1].position.x); - __m128 mz = _mm_loadu_ps(&verts[2].position.x); + __m128 mx = _mm_loadu_ps(&verts[0].x); + __m128 my = _mm_loadu_ps(&verts[1].x); + __m128 mz = _mm_loadu_ps(&verts[2].x); __m128 mw = _mm_setzero_ps(); _MM_TRANSPOSE4_PS(mx, my, mz, mw); __m128 clipd0 = _mm_add_ps(mx, mw); @@ -340,7 +347,7 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe { for (int i = 0; i < 3; i++) { - memcpy(clippedvert + i, &verts[i].position, sizeof(TriVertex)); + memcpy(clippedvert + i, &verts[i], sizeof(ShadedTriVertex)); } return 3; } @@ -429,16 +436,16 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe for (int i = 0; i < inputverts; i++) { auto &v = clippedvert[i]; - memset(&v, 0, sizeof(TriVertex)); + memset(&v, 0, sizeof(ShadedTriVertex)); for (int w = 0; w < 3; w++) { float weight = input[i * 3 + w]; - v.x += verts[w].position.x * weight; - v.y += verts[w].position.y * weight; - v.z += verts[w].position.z * weight; - v.w += verts[w].position.w * weight; - v.u += verts[w].position.u * weight; - v.v += verts[w].position.v * weight; + v.x += verts[w].x * weight; + v.y += verts[w].y * weight; + v.z += verts[w].z * weight; + v.w += verts[w].w * weight; + v.u += verts[w].u * weight; + v.v += verts[w].v * weight; } } return inputverts; diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index 04d26c7ea..4992f6972 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -29,12 +29,6 @@ #include "polyrenderer/drawers/poly_buffer.h" #include "polyrenderer/drawers/poly_draw_args.h" -struct ShadedTriVertex -{ - TriVertex position; - float clipDistance[3]; -}; - typedef void(*PolyDrawFuncPtr)(const TriDrawTriangleArgs *, WorkerThreadData *); class PolyTriangleDrawer @@ -50,7 +44,7 @@ private: static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread); static bool is_degenerate(const ShadedTriVertex *vertices); - static int clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert); + static int clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert); static int viewport_x, viewport_y, viewport_width, viewport_height, dest_pitch, dest_width, dest_height; static bool dest_bgra; diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index e7646c838..c0e4104fc 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -140,9 +140,9 @@ private: TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread) : args(args), thread(thread) { - const TriVertex &v1 = *args->v1; - const TriVertex &v2 = *args->v2; - const TriVertex &v3 = *args->v3; + const ShadedTriVertex &v1 = *args->v1; + const ShadedTriVertex &v2 = *args->v2; + const ShadedTriVertex &v3 = *args->v3; clipright = args->clipright; clipbottom = args->clipbottom; @@ -368,7 +368,7 @@ void TriangleBlock::DepthTest(const TriDrawTriangleArgs *args) int block = (X >> 3) + (Y >> 3) * zbufferPitch; float *depth = zbuffer + block * 64; - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; float stepXW = args->gradientX.W; float stepYW = args->gradientY.W; @@ -416,7 +416,7 @@ void TriangleBlock::DepthTest(const TriDrawTriangleArgs *args) int block = (X >> 3) + (Y >> 3) * zbufferPitch; float *depth = zbuffer + block * 64; - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; float stepXW = args->gradientX.W; float stepYW = args->gradientY.W; @@ -962,7 +962,7 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args) int block = (X >> 3) + (Y >> 3) * zbufferPitch; float *depth = zbuffer + block * 64; - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; float stepXW = args->gradientX.W; float stepYW = args->gradientY.W; @@ -1023,7 +1023,7 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args) int block = (X >> 3) + (Y >> 3) * zbufferPitch; float *depth = zbuffer + block * 64; - const TriVertex &v1 = *args->v1; + const ShadedTriVertex &v1 = *args->v1; float stepXW = args->gradientX.W; float stepYW = args->gradientY.W; @@ -1081,7 +1081,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thr #else -static void SortVertices(const TriDrawTriangleArgs *args, TriVertex **sortedVertices) +static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices) { sortedVertices[0] = args->v1; sortedVertices[1] = args->v2; @@ -1098,7 +1098,7 @@ static void SortVertices(const TriDrawTriangleArgs *args, TriVertex **sortedVert void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread) { // Sort vertices by Y position - TriVertex *sortedVertices[3]; + ShadedTriVertex *sortedVertices[3]; SortVertices(args, sortedVertices); int clipright = args->clipright; diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 6dfccbc06..d51c8b63e 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -41,13 +41,11 @@ struct WorkerThreadData } }; -struct TriVertex +struct ShadedTriVertex { - TriVertex() { } - TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w), u(u), v(v) { } - float x, y, z, w; float u, v; + float clipDistance[3]; }; struct ScreenTriangleStepVariables @@ -59,9 +57,9 @@ struct TriDrawTriangleArgs { uint8_t *dest; int32_t pitch; - TriVertex *v1; - TriVertex *v2; - TriVertex *v3; + ShadedTriVertex *v1; + ShadedTriVertex *v2; + ShadedTriVertex *v3; int32_t clipright; int32_t clipbottom; uint8_t *stencilValues; @@ -80,23 +78,29 @@ struct TriDrawTriangleArgs if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON)) return false; - gradientX.W = FindGradientX(bottomX, v1->w, v2->w, v3->w); - gradientY.W = FindGradientY(bottomY, v1->w, v2->w, v3->w); - gradientX.U = FindGradientX(bottomX, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); - gradientY.U = FindGradientY(bottomY, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); - gradientX.V = FindGradientX(bottomX, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); - gradientY.V = FindGradientY(bottomY, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); + gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f); + gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f); + gradientX.U = FindGradientX(bottomX, v1->u, v2->u, v3->u); + gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u); + gradientX.V = FindGradientX(bottomX, v1->v, v2->v, v3->v); + gradientY.V = FindGradientY(bottomY, v1->v, v2->v, v3->v); return true; } private: float FindGradientX(float bottomX, float c0, float c1, float c2) { + c0 *= v1->w; + c1 *= v2->w; + c2 *= v3->w; return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX; } float FindGradientY(float bottomY, float c0, float c1, float c2) { + c0 *= v1->w; + c1 *= v2->w; + c2 *= v3->w; return ((c1 - c2) * (v1->x - v3->x) - (c0 - c2) * (v2->x - v3->x)) / bottomY; } }; diff --git a/src/polyrenderer/math/tri_matrix.cpp b/src/polyrenderer/math/tri_matrix.cpp index 42343f601..df0e7d4e0 100644 --- a/src/polyrenderer/math/tri_matrix.cpp +++ b/src/polyrenderer/math/tri_matrix.cpp @@ -173,33 +173,27 @@ TriMatrix TriMatrix::operator*(const TriMatrix &mult) const return result; } -TriVertex TriMatrix::operator*(TriVertex v) const +FVector4 TriMatrix::operator*(const FVector4 &v) const { #ifdef NO_SSE - float vx = matrix[0 * 4 + 0] * v.x + matrix[1 * 4 + 0] * v.y + matrix[2 * 4 + 0] * v.z + matrix[3 * 4 + 0] * v.w; - float vy = matrix[0 * 4 + 1] * v.x + matrix[1 * 4 + 1] * v.y + matrix[2 * 4 + 1] * v.z + matrix[3 * 4 + 1] * v.w; - float vz = matrix[0 * 4 + 2] * v.x + matrix[1 * 4 + 2] * v.y + matrix[2 * 4 + 2] * v.z + matrix[3 * 4 + 2] * v.w; - float vw = matrix[0 * 4 + 3] * v.x + matrix[1 * 4 + 3] * v.y + matrix[2 * 4 + 3] * v.z + matrix[3 * 4 + 3] * v.w; - TriVertex sv; - sv.x = vx; - sv.y = vy; - sv.z = vz; - sv.w = vw; + float vx = matrix[0 * 4 + 0] * v.X + matrix[1 * 4 + 0] * v.Y + matrix[2 * 4 + 0] * v.Z + matrix[3 * 4 + 0] * v.W; + float vy = matrix[0 * 4 + 1] * v.X + matrix[1 * 4 + 1] * v.Y + matrix[2 * 4 + 1] * v.Z + matrix[3 * 4 + 1] * v.W; + float vz = matrix[0 * 4 + 2] * v.X + matrix[1 * 4 + 2] * v.Y + matrix[2 * 4 + 2] * v.Z + matrix[3 * 4 + 2] * v.W; + float vw = matrix[0 * 4 + 3] * v.X + matrix[1 * 4 + 3] * v.Y + matrix[2 * 4 + 3] * v.Z + matrix[3 * 4 + 3] * v.W; + return{ vx, vy, vz, vw }; #else __m128 m0 = _mm_loadu_ps(matrix); __m128 m1 = _mm_loadu_ps(matrix + 4); __m128 m2 = _mm_loadu_ps(matrix + 8); __m128 m3 = _mm_loadu_ps(matrix + 12); - __m128 mv = _mm_loadu_ps(&v.x); + __m128 mv = _mm_loadu_ps(&v.X); m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0))); m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1))); m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2))); m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3))); mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3); - TriVertex sv; - _mm_storeu_ps(&sv.x, mv); -#endif - sv.u = v.u; - sv.v = v.v; + FVector4 sv; + _mm_storeu_ps(&sv.X, mv); return sv; +#endif } diff --git a/src/polyrenderer/math/tri_matrix.h b/src/polyrenderer/math/tri_matrix.h index aa566a3f8..908ef247d 100644 --- a/src/polyrenderer/math/tri_matrix.h +++ b/src/polyrenderer/math/tri_matrix.h @@ -39,7 +39,7 @@ struct TriMatrix //static TriMatrix worldToView(const FRenderViewpoint &viewpoint); // Software renderer world to view space transform //static TriMatrix viewToClip(double focalTangent, double centerY, double invZtoScale); // Software renderer shearing projection - TriVertex operator*(TriVertex v) const; + FVector4 operator*(const FVector4 &v) const; TriMatrix operator*(const TriMatrix &m) const; float matrix[16]; From afdeed305bccc786fd019c191896426c8c1c87f6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 21 Sep 2017 04:39:40 +0200 Subject: [PATCH 003/105] - Fix typo --- src/vectors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vectors.h b/src/vectors.h index c6e6c1a5c..5fa0970f1 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -905,7 +905,7 @@ struct TVector4 X = vec_t(X * scale); Y = vec_t(Y * scale); Z = vec_t(Z * scale); - w = vec_t(W * scale); + W = vec_t(W * scale); } return *this; } From dd8a114bb821ccc5e3a15e34151de71a3d907ffd Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 21 Sep 2017 05:39:16 +0200 Subject: [PATCH 004/105] - Initial dynamic light support for softpoly --- src/polyrenderer/drawers/poly_draw_args.h | 13 +++ src/polyrenderer/drawers/poly_drawer32_sse2.h | 110 ++++++++++++++++-- src/polyrenderer/drawers/poly_triangle.cpp | 6 + src/polyrenderer/drawers/screen_triangle.h | 14 ++- src/polyrenderer/scene/poly_plane.cpp | 60 ++++++++++ src/polyrenderer/scene/poly_plane.h | 1 + src/polyrenderer/scene/poly_wall.cpp | 61 ++++++++++ src/polyrenderer/scene/poly_wall.h | 2 + 8 files changed, 257 insertions(+), 10 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index c53b0260f..6417669a0 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -55,6 +55,13 @@ struct TriVertex float u, v; }; +struct PolyLight +{ + uint32_t color; + float x, y, z; + float radius; +}; + class PolyDrawArgs { public: @@ -73,6 +80,7 @@ public: void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; } void SetColor(uint32_t bgra, uint8_t palindex); + void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; } void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); const TriMatrix *ObjectToClip() const { return mObjectToClip; } @@ -119,6 +127,9 @@ public: bool NearestFilter() const { return mNearestFilter; } bool FixedLight() const { return mFixedLight; } + PolyLight *Lights() const { return mLights; } + int NumLights() const { return mNumLights; } + private: const TriMatrix *mObjectToClip = nullptr; const TriVertex *mVertices = nullptr; @@ -155,6 +166,8 @@ private: bool mSimpleShade = true; bool mNearestFilter = true; bool mFixedLight = false; + PolyLight *mLights = nullptr; + int mNumLights = 0; }; class RectDrawArgs diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index a88b92bd6..1cef53719 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -142,9 +142,64 @@ namespace TriScreenDrawerModes } } - template - FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light) + FORCEINLINE __m128i VECTORCALL AddLights(__m128i material, __m128i fgcolor, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal) { + __m128i lit = _mm_setzero_si128(); + + for (int i = 0; i != num_lights; i++) + { + __m128 m256 = _mm_set1_ps(256.0f); + __m128 mSignBit = _mm_set1_ps(-0.0f); + + __m128 lightpos = _mm_loadu_ps(&lights[i].x); + __m128 light_radius = _mm_load_ss(&lights[i].radius); + + __m128 is_attenuated = _mm_cmpge_ss(light_radius, _mm_setzero_ps()); + is_attenuated = _mm_shuffle_ps(is_attenuated, is_attenuated, _MM_SHUFFLE(0, 0, 0, 0)); + light_radius = _mm_andnot_ps(mSignBit, light_radius); + + // L = light-pos + // dist = sqrt(dot(L, L)) + // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + __m128 L = _mm_sub_ps(lightpos, worldpos); + __m128 dist2 = _mm_mul_ps(L, L); + dist2 = _mm_add_ss(dist2, _mm_add_ss(_mm_shuffle_ps(dist2, dist2, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dist2, dist2, _MM_SHUFFLE(0, 0, 0, 2)))); + __m128 rcp_dist = _mm_rsqrt_ss(dist2); + __m128 dist = _mm_mul_ss(dist2, rcp_dist); + __m128 distance_attenuation = _mm_sub_ss(m256, _mm_min_ss(_mm_mul_ss(dist, light_radius), m256)); + distance_attenuation = _mm_shuffle_ps(distance_attenuation, distance_attenuation, _MM_SHUFFLE(0, 0, 0, 0)); + + // The simple light type + __m128 simple_attenuation = distance_attenuation; + + // The point light type + // diffuse = dot(N,L) * attenuation + __m128 dotNL = _mm_mul_ps(worldnormal, L); + dotNL = _mm_add_ss(dotNL, _mm_add_ss(_mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 2)))); + __m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation); + point_attenuation = _mm_shuffle_ps(point_attenuation, point_attenuation, _MM_SHUFFLE(0, 0, 0, 0)); + + __m128i attenuation = _mm_cvtps_epi32(_mm_or_ps(_mm_and_ps(is_attenuated, simple_attenuation), _mm_andnot_ps(is_attenuated, point_attenuation))); + attenuation = _mm_packs_epi32(_mm_shuffle_epi32(attenuation, _MM_SHUFFLE(0, 0, 0, 0)), _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(1, 1, 1, 1))); + + __m128i light_color = _mm_cvtsi32_si128(lights[i].color); + light_color = _mm_unpacklo_epi8(light_color, _mm_setzero_si128()); + light_color = _mm_shuffle_epi32(light_color, _MM_SHUFFLE(1, 0, 1, 0)); + + lit = _mm_add_epi16(lit, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenuation), 8)); + } + + lit = _mm_min_epi16(lit, _mm_set1_epi16(256)); + + fgcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(material, lit), 8)); + fgcolor = _mm_min_epi16(fgcolor, _mm_set1_epi16(255)); + return fgcolor; + } + + template + FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal) + { + __m128i material = fgcolor; if (ShadeModeT::Mode == (int)ShadeMode::Simple) { fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8); @@ -168,7 +223,8 @@ namespace TriScreenDrawerModes fgcolor = _mm_srli_epi16(_mm_add_epi16(shade_fade, fgcolor), 8); fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8); } - return fgcolor; + + return AddLights(material, fgcolor, lights, num_lights, worldpos, worldnormal); } template @@ -333,6 +389,11 @@ private: int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; + auto lights = args->uniforms->Lights(); + auto num_lights = args->uniforms->NumLights(); + __m128 worldpos = _mm_setzero_ps(); + __m128 worldnormal = _mm_setzero_ps(); + // Calculate gradients const ShadedTriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; @@ -341,9 +402,15 @@ private: blockPosY.W = v1.w + gradientX.W * (destX - v1.x) + gradientY.W * (destY - v1.y); blockPosY.U = v1.u * v1.w + gradientX.U * (destX - v1.x) + gradientY.U * (destY - v1.y); blockPosY.V = v1.v * v1.w + gradientX.V * (destX - v1.x) + gradientY.V * (destY - v1.y); + blockPosY.WorldX = v1.worldX * v1.w + gradientX.WorldX * (destX - v1.x) + gradientY.WorldX * (destY - v1.y); + blockPosY.WorldY = v1.worldY * v1.w + gradientX.WorldY * (destX - v1.x) + gradientY.WorldY * (destY - v1.y); + blockPosY.WorldZ = v1.worldZ * v1.w + gradientX.WorldZ * (destX - v1.x) + gradientY.WorldZ * (destY - v1.y); gradientX.W *= 8.0f; gradientX.U *= 8.0f; gradientX.V *= 8.0f; + gradientX.WorldX *= 8.0f; + gradientX.WorldY *= 8.0f; + gradientX.WorldZ *= 8.0f; // Output uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; @@ -404,10 +471,16 @@ private: fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); + worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; blockPosX.U += gradientX.U; blockPosX.V += gradientX.V; + blockPosX.WorldX += gradientX.WorldX; + blockPosX.WorldY += gradientX.WorldY; + blockPosX.WorldZ += gradientX.WorldZ; rcpW = 0x01000000 / blockPosX.W; int32_t nextU = (int32_t)(blockPosX.U * rcpW); @@ -462,7 +535,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -472,6 +545,9 @@ private: blockPosY.W += gradientY.W; blockPosY.U += gradientY.U; blockPosY.V += gradientY.V; + blockPosY.WorldX += gradientY.WorldX; + blockPosY.WorldY += gradientY.WorldY; + blockPosY.WorldZ += gradientY.WorldZ; dest += pitch; } @@ -488,10 +564,16 @@ private: fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); + worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; blockPosX.U += gradientX.U; blockPosX.V += gradientX.V; + blockPosX.WorldX += gradientX.WorldX; + blockPosX.WorldY += gradientX.WorldY; + blockPosX.WorldZ += gradientX.WorldZ; rcpW = 0x01000000 / blockPosX.W; int32_t nextU = (int32_t)(blockPosX.U * rcpW); @@ -551,7 +633,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -565,6 +647,9 @@ private: blockPosY.W += gradientY.W; blockPosY.U += gradientY.U; blockPosY.V += gradientY.V; + blockPosY.WorldX += gradientY.WorldX; + blockPosY.WorldY += gradientY.WorldY; + blockPosY.WorldZ += gradientY.WorldZ; dest += pitch; } @@ -579,10 +664,16 @@ private: fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); + worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; blockPosX.U += gradientX.U; blockPosX.V += gradientX.V; + blockPosX.WorldX += gradientX.WorldX; + blockPosX.WorldY += gradientX.WorldY; + blockPosX.WorldZ += gradientX.WorldZ; rcpW = 0x01000000 / blockPosX.W; int32_t nextU = (int32_t)(blockPosX.U * rcpW); @@ -642,7 +733,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -656,6 +747,9 @@ private: blockPosY.W += gradientY.W; blockPosY.U += gradientY.U; blockPosY.V += gradientY.V; + blockPosY.WorldX += gradientY.WorldX; + blockPosY.WorldY += gradientY.WorldY; + blockPosY.WorldZ += gradientY.WorldZ; dest += pitch; } @@ -798,7 +892,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, nullptr, 0, _mm_setzero_ps(), _mm_setzero_ps()); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -826,7 +920,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, nullptr, 0, _mm_setzero_ps(), _mm_setzero_ps()); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 2448e2544..beb283498 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -155,6 +155,9 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c sv.w = position.W; sv.u = v.u; sv.v = v.v; + sv.worldX = v.x; + sv.worldY = v.y; + sv.worldZ = v.z; // Calculate gl_ClipDistance[i] for (int i = 0; i < 3; i++) @@ -446,6 +449,9 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex * v.w += verts[w].w * weight; v.u += verts[w].u * weight; v.v += verts[w].v * weight; + v.worldX += verts[w].worldX * weight; + v.worldY += verts[w].worldY * weight; + v.worldZ += verts[w].worldZ * weight; } } return inputverts; diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index d51c8b63e..a76dc4b46 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -46,11 +46,13 @@ struct ShadedTriVertex float x, y, z, w; float u, v; float clipDistance[3]; + float worldX, worldY, worldZ; }; struct ScreenTriangleStepVariables { float W, U, V; + float WorldX, WorldY, WorldZ, Padding; // Padding so it can be loaded directly into a XMM register }; struct TriDrawTriangleArgs @@ -79,11 +81,19 @@ struct TriDrawTriangleArgs return false; gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f); - gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f); gradientX.U = FindGradientX(bottomX, v1->u, v2->u, v3->u); - gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u); gradientX.V = FindGradientX(bottomX, v1->v, v2->v, v3->v); + gradientX.WorldX = FindGradientX(bottomX, v1->worldX, v2->worldX, v3->worldX); + gradientX.WorldY = FindGradientX(bottomX, v1->worldY, v2->worldY, v3->worldY); + gradientX.WorldZ = FindGradientX(bottomX, v1->worldZ, v2->worldZ, v3->worldZ); + + gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f); + gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u); gradientY.V = FindGradientY(bottomY, v1->v, v2->v, v3->v); + gradientY.WorldX = FindGradientY(bottomY, v1->worldX, v2->worldX, v3->worldX); + gradientY.WorldY = FindGradientY(bottomY, v1->worldY, v2->worldY, v3->worldY); + gradientY.WorldZ = FindGradientY(bottomY, v1->worldZ, v2->worldZ, v3->worldZ); + return true; } diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 668053a01..766d4260b 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -32,6 +32,7 @@ #include "polyrenderer/scene/poly_light.h" #include "polyrenderer/poly_renderthread.h" #include "p_lnspec.h" +#include "a_dynlight.h" EXTERN_CVAR(Int, r_3dfloors) @@ -253,6 +254,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC if (!isSky) { + SetDynLights(thread, args, sub); args.SetTexture(tex); args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); @@ -277,6 +279,64 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC } } +void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub) +{ + FLightNode *light_list = sub->lighthead; + + auto cameraLight = PolyCameraLight::Instance(); + if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) + { + args.SetLights(nullptr, 0); // [SP] Don't draw dynlights if invul/lightamp active + return; + } + + // Calculate max lights that can touch the wall so we can allocate memory for the list + int max_lights = 0; + FLightNode *cur_node = light_list; + while (cur_node) + { + if (!(cur_node->lightsource->flags2&MF2_DORMANT)) + max_lights++; + cur_node = cur_node->nextLight; + } + + if (max_lights == 0) + { + args.SetLights(nullptr, 0); + return; + } + + int dc_num_lights = 0; + PolyLight *dc_lights = thread->FrameMemory->AllocMemory(max_lights); + + // Setup lights + cur_node = light_list; + while (cur_node) + { + if (!(cur_node->lightsource->flags2&MF2_DORMANT)) + { + //bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + + // To do: cull lights not touching subsector + + uint32_t red = cur_node->lightsource->GetRed(); + uint32_t green = cur_node->lightsource->GetGreen(); + uint32_t blue = cur_node->lightsource->GetBlue(); + + auto &light = dc_lights[dc_num_lights++]; + light.x = (float)cur_node->lightsource->X(); + light.y = (float)cur_node->lightsource->Y(); + light.z = (float)cur_node->lightsource->Z(); + light.radius = 256.0f / cur_node->lightsource->GetRadius(); + light.color = (red << 16) | (green << 8) | blue; + } + + cur_node = cur_node->nextLight; + } + + args.SetLights(dc_lights, dc_num_lights); +} + void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform) { for (uint32_t i = 0; i < sub->numlines; i++) diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 918640369..2293f4f63 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -62,6 +62,7 @@ public: private: void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform); + void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub); }; class Render3DFloorPlane diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 57e24da37..c90052b22 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -35,6 +35,7 @@ #include "polyrenderer/scene/poly_light.h" #include "polyrenderer/poly_renderthread.h" #include "g_levellocals.h" +#include "a_dynlight.h" EXTERN_CVAR(Bool, r_drawmirrors) EXTERN_CVAR(Bool, r_fogboundary) @@ -326,6 +327,8 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl args.SetTexture(Texture); args.SetClipPlane(0, clipPlane); + SetDynLights(thread, args); + if (FogBoundary) { args.SetStyle(TriBlendMode::FogBoundary); @@ -365,6 +368,64 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl RenderPolyDecal::RenderWallDecals(thread, worldToClip, clipPlane, LineSeg, StencilValue); } +void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) +{ + FLightNode *light_list = (LineSeg && LineSeg->sidedef) ? LineSeg->sidedef->lighthead : nullptr; + + auto cameraLight = PolyCameraLight::Instance(); + if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) + { + args.SetLights(nullptr, 0); // [SP] Don't draw dynlights if invul/lightamp active + return; + } + + // Calculate max lights that can touch the wall so we can allocate memory for the list + int max_lights = 0; + FLightNode *cur_node = light_list; + while (cur_node) + { + if (!(cur_node->lightsource->flags2&MF2_DORMANT)) + max_lights++; + cur_node = cur_node->nextLight; + } + + if (max_lights == 0) + { + args.SetLights(nullptr, 0); + return; + } + + int dc_num_lights = 0; + PolyLight *dc_lights = thread->FrameMemory->AllocMemory(max_lights); + + // Setup lights + cur_node = light_list; + while (cur_node) + { + if (!(cur_node->lightsource->flags2&MF2_DORMANT)) + { + //bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + + // To do: cull lights not touching wall + + uint32_t red = cur_node->lightsource->GetRed(); + uint32_t green = cur_node->lightsource->GetGreen(); + uint32_t blue = cur_node->lightsource->GetBlue(); + + auto &light = dc_lights[dc_num_lights++]; + light.x = (float)cur_node->lightsource->X(); + light.y = (float)cur_node->lightsource->Y(); + light.z = (float)cur_node->lightsource->Z(); + light.radius = 256.0f / cur_node->lightsource->GetRadius(); + light.color = (red << 16) | (green << 8) | blue; + } + + cur_node = cur_node->nextLight; + } + + args.SetLights(dc_lights, dc_num_lights); +} + void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices) { const auto &lightlist = Line->frontsector->e->XFloor.lightlist; diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 40b6d5509..6cb7aae2f 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -68,6 +68,8 @@ private: int GetLightLevel(); void DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices); + void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args); + static bool IsFogBoundary(sector_t *front, sector_t *back); static FTexture *GetTexture(const line_t *Line, const side_t *Side, side_t::ETexpart texpart); }; From 94a33229cc10303a2c8eb92d343926fb4d16e84c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 22 Sep 2017 00:56:14 +0200 Subject: [PATCH 005/105] - Remove unused function argument --- src/polyrenderer/scene/poly_cull.cpp | 2 +- src/polyrenderer/scene/poly_cull.h | 2 +- src/polyrenderer/scene/poly_scene.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index e759bdda4..a3361fd62 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -28,7 +28,7 @@ #include "poly_cull.h" #include "polyrenderer/poly_renderer.h" -void PolyCull::CullScene(const TriMatrix &worldToClip, const PolyClipPlane &portalClipPlane) +void PolyCull::CullScene(const PolyClipPlane &portalClipPlane) { ClearSolidSegments(); MarkViewFrustum(); diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index fe8000501..474a33bb6 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -29,7 +29,7 @@ class PolyCull { public: - void CullScene(const TriMatrix &worldToClip, const PolyClipPlane &portalClipPlane); + void CullScene(const PolyClipPlane &portalClipPlane); bool IsLineSegVisible(uint32_t subsectorDepth, uint32_t lineIndex) { diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 6f84c2d4f..a9a9cbf40 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -60,7 +60,7 @@ void RenderPolyScene::Render(int portalDepth) SectorPortals.clear(); LinePortals.clear(); - Cull.CullScene(WorldToClip, PortalPlane); + Cull.CullScene(PortalPlane); RenderSectors(); RenderPortals(portalDepth); } From ca2ef805b83ca632b9a4bca47e72e31f288f391f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 22 Sep 2017 00:57:51 +0200 Subject: [PATCH 006/105] - Implement the affine part of the dynamic lights in the softpoly TC SSE2 drawer --- src/polyrenderer/drawers/poly_drawer32_sse2.h | 66 ++++++++++++++----- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 1cef53719..0f69f5a4d 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -142,7 +142,14 @@ namespace TriScreenDrawerModes } } - FORCEINLINE __m128i VECTORCALL AddLights(__m128i material, __m128i fgcolor, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal) + FORCEINLINE __m128i VECTORCALL AddLights(__m128i material, __m128i fgcolor, __m128i dynlight) + { + fgcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(material, dynlight), 8)); + fgcolor = _mm_min_epi16(fgcolor, _mm_set1_epi16(255)); + return fgcolor; + } + + FORCEINLINE __m128i VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal) { __m128i lit = _mm_setzero_si128(); @@ -189,15 +196,11 @@ namespace TriScreenDrawerModes lit = _mm_add_epi16(lit, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenuation), 8)); } - lit = _mm_min_epi16(lit, _mm_set1_epi16(256)); - - fgcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(material, lit), 8)); - fgcolor = _mm_min_epi16(fgcolor, _mm_set1_epi16(255)); - return fgcolor; + return _mm_min_epi16(lit, _mm_set1_epi16(256)); } template - FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal) + FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light, __m128i dynlight) { __m128i material = fgcolor; if (ShadeModeT::Mode == (int)ShadeMode::Simple) @@ -224,7 +227,7 @@ namespace TriScreenDrawerModes fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8); } - return AddLights(material, fgcolor, lights, num_lights, worldpos, worldnormal); + return AddLights(material, fgcolor, dynlight); } template @@ -391,7 +394,6 @@ private: auto lights = args->uniforms->Lights(); auto num_lights = args->uniforms->NumLights(); - __m128 worldpos = _mm_setzero_ps(); __m128 worldnormal = _mm_setzero_ps(); // Calculate gradients @@ -472,7 +474,8 @@ private: lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); - worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + __m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; @@ -492,6 +495,13 @@ private: fixed_t lightstep = (lightnext - lightpos) / 8; lightstep = lightstep & lightmask; + mrcpW = _mm_set1_ps(1.0f / blockPosX.W); + worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW); + __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3); + dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff,0xffff,0,0))), _mm_set1_epi16(256)), _mm_setzero_si128()); + dynlightstep = _mm_slli_epi16(dynlightstep, 1); + for (int ix = 0; ix < 4; ix++) { // Load bgcolor @@ -535,11 +545,13 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result _mm_storel_epi64((__m128i*)(dest + ix * 2), outcolor); + + dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, dynlightstep), _mm_set1_epi16(256)), _mm_setzero_si128()); } blockPosY.W += gradientY.W; @@ -565,7 +577,8 @@ private: lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); - worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + __m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; @@ -585,6 +598,13 @@ private: fixed_t lightstep = (lightnext - lightpos) / 8; lightstep = lightstep & lightmask; + mrcpW = _mm_set1_ps(1.0f / blockPosX.W); + worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW); + __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3); + dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff, 0xffff, 0, 0))), _mm_set1_epi16(256)), _mm_setzero_si128()); + dynlightstep = _mm_slli_epi16(dynlightstep, 1); + for (int x = 0; x < 4; x++) { // Load bgcolor @@ -633,7 +653,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -641,6 +661,8 @@ private: if (mask0 & (1 << 31)) dest[x * 2] = desttmp[0]; if (mask0 & (1 << 30)) dest[x * 2 + 1] = desttmp[1]; + dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, dynlightstep), _mm_set1_epi16(256)), _mm_setzero_si128()); + mask0 <<= 2; } @@ -665,7 +687,8 @@ private: lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); - worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + __m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); + __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; @@ -685,6 +708,13 @@ private: fixed_t lightstep = (lightnext - lightpos) / 8; lightstep = lightstep & lightmask; + mrcpW = _mm_set1_ps(1.0f / blockPosX.W); + worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW); + __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3); + dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff, 0xffff, 0, 0))), _mm_set1_epi16(256)), _mm_setzero_si128()); + dynlightstep = _mm_slli_epi16(dynlightstep, 1); + for (int x = 0; x < 4; x++) { // Load bgcolor @@ -733,7 +763,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -741,6 +771,8 @@ private: if (mask1 & (1 << 31)) dest[x * 2] = desttmp[0]; if (mask1 & (1 << 30)) dest[x * 2 + 1] = desttmp[1]; + dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, dynlightstep), _mm_set1_epi16(256)), _mm_setzero_si128()); + mask1 <<= 2; } @@ -892,7 +924,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, nullptr, 0, _mm_setzero_ps(), _mm_setzero_ps()); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, _mm_setzero_si128()); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result @@ -920,7 +952,7 @@ private: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, nullptr, 0, _mm_setzero_ps(), _mm_setzero_ps()); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, _mm_setzero_si128()); __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result From 02fc585ae6ee5670a43716275fa470510e850629 Mon Sep 17 00:00:00 2001 From: JimmyZD Date: Thu, 21 Sep 2017 23:44:12 +0800 Subject: [PATCH 007/105] Updated "cream" and "olive" definitions in TEXTCOLO - Both cream and olive have been tweaked to now feature a broader range of shades, and so much starker, legible character outlines for the default fonts. - Cream now uses 2 shading ranges to ensure it retains the look of the brown palette while having this extra outline contrast. - This has so far been tested with the standard Doom smallfont, bigfont, and the ZDoom confont. --- wadsrc/static/textcolors.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/textcolors.txt b/wadsrc/static/textcolors.txt index 383cd41e4..1e93b97ca 100644 --- a/wadsrc/static/textcolors.txt +++ b/wadsrc/static/textcolors.txt @@ -140,7 +140,8 @@ Flat: Cream { - #CF8353 #FFD7BB + #6B4727 #BF7B4B 0 94 + #BF7B4B #FFBF9B 95 256 Console: #2B230F #BF7B4B 0 127 #FFB383 #FFFFFF 128 256 @@ -150,7 +151,7 @@ Flat: Olive { - #2F371F #7B7F50 + #171F07 #7B7F50 Console: #373F27 #7B7F63 0 127 #676B4F #D1D8A8 128 256 From e15a84f062cbc2c3162ea3518ce09958c88c02bc Mon Sep 17 00:00:00 2001 From: AraHaan Date: Fri, 22 Sep 2017 12:15:03 -0400 Subject: [PATCH 008/105] Changed Fatal Error Dialog title. This is to match all the parts that says GZDoom. --- src/win32/zdoom.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/zdoom.rc b/src/win32/zdoom.rc index 0d21faae5..3450c2a80 100644 --- a/src/win32/zdoom.rc +++ b/src/win32/zdoom.rc @@ -393,7 +393,7 @@ END IDD_CRASHDIALOG DIALOGEX 0, 0, 415, 308 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW -CAPTION "ZDoom Very Fatal Error" +CAPTION "GZDoom Very Fatal Error" FONT 8, "MS Shell Dlg", 400, 0, 0x0 BEGIN CONTROL "",IDC_CRASHTAB,"SysTabControl32",WS_TABSTOP,4,4,404,280 From 789214200cd8189cac2f2bef5f3f06f4d916e06d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 23 Sep 2017 02:27:39 +0200 Subject: [PATCH 009/105] - Attenuated lights support --- src/polyrenderer/drawers/poly_draw_args.h | 4 ++++ src/polyrenderer/drawers/poly_drawer32_sse2.h | 7 ++++--- src/polyrenderer/scene/poly_plane.cpp | 11 ++++++++--- src/polyrenderer/scene/poly_plane.h | 2 +- src/polyrenderer/scene/poly_wall.cpp | 15 ++++++++++++++- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 6417669a0..c3a685c88 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -130,6 +130,9 @@ public: PolyLight *Lights() const { return mLights; } int NumLights() const { return mNumLights; } + const FVector3 &Normal() const { return mNormal; } + void SetNormal(const FVector3 &normal) { mNormal = normal; } + private: const TriMatrix *mObjectToClip = nullptr; const TriVertex *mVertices = nullptr; @@ -168,6 +171,7 @@ private: bool mFixedLight = false; PolyLight *mLights = nullptr; int mNumLights = 0; + FVector3 mNormal; }; class RectDrawArgs diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 0f69f5a4d..f4d3cb392 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -180,9 +180,10 @@ namespace TriScreenDrawerModes __m128 simple_attenuation = distance_attenuation; // The point light type - // diffuse = dot(N,L) * attenuation - __m128 dotNL = _mm_mul_ps(worldnormal, L); + // diffuse = max(dot(N,normalize(L)),0) * attenuation + __m128 dotNL = _mm_mul_ps(worldnormal, _mm_mul_ps(L, _mm_shuffle_ps(rcp_dist, rcp_dist, _MM_SHUFFLE(0, 0, 0, 0)))); dotNL = _mm_add_ss(dotNL, _mm_add_ss(_mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 2)))); + dotNL = _mm_max_ss(dotNL, _mm_setzero_ps()); __m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation); point_attenuation = _mm_shuffle_ps(point_attenuation, point_attenuation, _MM_SHUFFLE(0, 0, 0, 0)); @@ -394,7 +395,7 @@ private: auto lights = args->uniforms->Lights(); auto num_lights = args->uniforms->NumLights(); - __m128 worldnormal = _mm_setzero_ps(); + __m128 worldnormal = _mm_setr_ps(args->uniforms->Normal().X, args->uniforms->Normal().Y, args->uniforms->Normal().Z, 0.0f); // Calculate gradients const ShadedTriVertex &v1 = *args->v1; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 766d4260b..2ec86327e 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -254,7 +254,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC if (!isSky) { - SetDynLights(thread, args, sub); + SetDynLights(thread, args, sub, ceiling); args.SetTexture(tex); args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); @@ -279,7 +279,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC } } -void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub) +void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling) { FLightNode *light_list = sub->lighthead; @@ -315,7 +315,7 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, { if (!(cur_node->lightsource->flags2&MF2_DORMANT)) { - //bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; // To do: cull lights not touching subsector @@ -329,12 +329,17 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, light.z = (float)cur_node->lightsource->Z(); light.radius = 256.0f / cur_node->lightsource->GetRadius(); light.color = (red << 16) | (green << 8) | blue; + if (is_point_light) + light.radius = -light.radius; } cur_node = cur_node->nextLight; } args.SetLights(dc_lights, dc_num_lights); + + DVector3 normal = ceiling ? sub->sector->ceilingplane.Normal() : sub->sector->floorplane.Normal(); + args.SetNormal({ (float)normal.X, (float)normal.Y, (float)normal.Z }); } void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform) diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 2293f4f63..74db247e6 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -62,7 +62,7 @@ public: private: void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform); - void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub); + void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); }; class Render3DFloorPlane diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index c90052b22..aba99a85a 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -404,7 +404,7 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) { if (!(cur_node->lightsource->flags2&MF2_DORMANT)) { - //bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; // To do: cull lights not touching wall @@ -418,12 +418,25 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) light.z = (float)cur_node->lightsource->Z(); light.radius = 256.0f / cur_node->lightsource->GetRadius(); light.color = (red << 16) | (green << 8) | blue; + if (is_point_light) + light.radius = -light.radius; } cur_node = cur_node->nextLight; } args.SetLights(dc_lights, dc_num_lights); + + // Face normal: + float dx = (float)(v2.X - v1.X); + float dy = (float)(v2.Y - v1.Y); + float nx = dy; + float ny = -dx; + float lensqr = nx * nx + ny * ny; + float rcplen = 1.0f / sqrt(lensqr); + nx *= rcplen; + ny *= rcplen; + args.SetNormal({ nx, ny, 0.0f }); } void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices) From f174111128465805d122f2e5167c5e54a42bfd13 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 23 Sep 2017 11:57:06 +0300 Subject: [PATCH 010/105] Fixed read beyond buffer boundary during font color parsing Printing of string that ends with '\c' led to undefined behavior Example: 'echo \c' in console --- src/v_font.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v_font.cpp b/src/v_font.cpp index 68422cd74..309f8d560 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2666,7 +2666,7 @@ EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int } else // Incomplete! { - color_value = ch - (*ch == '\0'); + color_value = ch - (newcolor == '\0'); return CR_UNDEFINED; } color_value = ch; @@ -2772,4 +2772,4 @@ DEFINE_ACTION_FUNCTION(FFont, GetCursor) { PARAM_SELF_STRUCT_PROLOGUE(FFont); ACTION_RETURN_STRING(FString(self->GetCursor())); -} \ No newline at end of file +} From abc8e4deac06e28317b286211c485afadf10f414 Mon Sep 17 00:00:00 2001 From: JimmyZD Date: Sat, 23 Sep 2017 16:01:07 +0800 Subject: [PATCH 011/105] Added four text colors: ice, fire, sapphire, teal https://forum.zdoom.org/viewtopic.php?t=57942 --- src/posix/cocoa/st_start.mm | 2 ++ src/v_font.h | 4 +++ src/v_text.h | 4 +++ wadsrc/static/language.enu | 4 +++ wadsrc/static/menudef.txt | 4 +++ wadsrc/static/textcolors.txt | 44 +++++++++++++++++++++++++++++ wadsrc/static/zscript/base.txt | 8 ++++++ wadsrc/static/zscript/constants.txt | 4 +++ 8 files changed, 74 insertions(+) diff --git a/src/posix/cocoa/st_start.mm b/src/posix/cocoa/st_start.mm index 36582c64b..6ce48e807 100644 --- a/src/posix/cocoa/st_start.mm +++ b/src/posix/cocoa/st_start.mm @@ -102,6 +102,8 @@ FBasicStartupScreen::FBasicStartupScreen(int maxProgress, bool showBar) consoleWindow.AddText(TEXTCOLOR_DARKGREEN "TEXTCOLOR_DARKGREEN\n" TEXTCOLOR_DARKRED "TEXTCOLOR_DARKRED\n"); consoleWindow.AddText(TEXTCOLOR_DARKBROWN "TEXTCOLOR_DARKBROWN\n" TEXTCOLOR_PURPLE "TEXTCOLOR_PURPLE\n"); consoleWindow.AddText(TEXTCOLOR_DARKGRAY "TEXTCOLOR_DARKGRAY\n" TEXTCOLOR_CYAN "TEXTCOLOR_CYAN\n"); + consoleWindow.AddText(TEXTCOLOR_ICE "TEXTCOLOR_ICE\n" TEXTCOLOR_FIRE "TEXTCOLOR_FIRE\n"); + consoleWindow.AddText(TEXTCOLOR_SAPPHIRE "TEXTCOLOR_SAPPHIRE\n" TEXTCOLOR_TEAL "TEXTCOLOR_TEAL\n"); consoleWindow.AddText(TEXTCOLOR_NORMAL "TEXTCOLOR_NORMAL\n" TEXTCOLOR_BOLD "TEXTCOLOR_BOLD\n"); consoleWindow.AddText(TEXTCOLOR_CHAT "TEXTCOLOR_CHAT\n" TEXTCOLOR_TEAMCHAT "TEXTCOLOR_TEAMCHAT\n"); consoleWindow.AddText("----------------------------------------------------------------\n"); diff --git a/src/v_font.h b/src/v_font.h index c3d2ce561..e1be6afb2 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -66,6 +66,10 @@ enum EColorRange : int CR_PURPLE, CR_DARKGRAY, CR_CYAN, + CR_ICE, + CR_FIRE, + CR_SAPPHIRE, + CR_TEAL, NUM_TEXT_COLORS, }; diff --git a/src/v_text.h b/src/v_text.h index 4c54b941b..b76024fa5 100644 --- a/src/v_text.h +++ b/src/v_text.h @@ -68,6 +68,10 @@ struct FBrokenLines #define TEXTCOLOR_PURPLE "\034T" #define TEXTCOLOR_DARKGRAY "\034U" #define TEXTCOLOR_CYAN "\034V" +#define TEXTCOLOR_ICE "\034W" +#define TEXTCOLOR_FIRE "\034X" +#define TEXTCOLOR_SAPPHIRE "\034Y" +#define TEXTCOLOR_TEAL "\034Z" #define TEXTCOLOR_NORMAL "\034-" #define TEXTCOLOR_BOLD "\034+" diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 8448665db..e440dc786 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2405,6 +2405,10 @@ C_DARKBROWN = "\csdark brown"; C_PURPLE = "\ctpurple"; C_DARKGRAY = "\cudark gray"; C_CYAN = "\cvcyan"; +C_ICE = "\cwice"; +C_FIRE = "\cxfire"; +C_SAPPHIRE = "\cysapphire"; +C_TEAL = "\czteal"; // Option Strings OPTSTR_SIMPLEARROW = "Simple arrow"; OPTSTR_HERETIC = "Heretic"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 729a914eb..fd46b153b 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -823,6 +823,10 @@ OptionValue TextColors 19.0, "$C_PURPLE" 20.0, "$C_DARKGRAY" 21.0, "$C_CYAN" + 22.0, "$C_ICE" + 23.0, "$C_FIRE" + 24.0, "$C_SAPPHIRE" + 25.0, "$C_TEAL" } OptionValue Crosshairs diff --git a/wadsrc/static/textcolors.txt b/wadsrc/static/textcolors.txt index 1e93b97ca..d8e40182e 100644 --- a/wadsrc/static/textcolors.txt +++ b/wadsrc/static/textcolors.txt @@ -218,3 +218,47 @@ Console: Flat: #00DDDD } + +Ice +{ + #343450 #7C7C98 0 94 + #7C7C98 #E0E0E0 95 256 +Console: + #343450 #7C7C98 0 127 + #7C7C98 #E0E0E0 128 256 +Flat: + #7C7C98 +} + +Fire +{ + #660000 #D57604 0 104 + #D57604 #FFFF00 105 256 +Console: + #6F0000 #D57604 0 127 + #D57604 #FFFF00 128 256 +Flat: + #D57604 +} + +Sapphire +{ + #000468 #506CFC 0 94 + #506CFC #50ECFC 95 256 +Console: + #000468 #506CFC 0 127 + #506CFC #50ECFC 128 256 +Flat: + #506CFC +} + +Teal +{ + #001F1F #236773 0 90 + #236773 #7BB3C3 91 256 +Console: + #001F1F #236773 0 127 + #236773 #7BB3C3 128 256 +Flat: + #236773 +} diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 630e74abb..351d4d949 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -210,6 +210,10 @@ struct Font native CR_PURPLE, CR_DARKGRAY, CR_CYAN, + CR_ICE, + CR_FIRE, + CR_SAPPHIRE, + CR_TEAL, NUM_TEXT_COLORS }; @@ -236,6 +240,10 @@ struct Font native const TEXTCOLOR_PURPLE = "\034T"; const TEXTCOLOR_DARKGRAY = "\034U"; const TEXTCOLOR_CYAN = "\034V"; + const TEXTCOLOR_ICE = "\034W"; + const TEXTCOLOR_FIRE = "\034X"; + const TEXTCOLOR_SAPPHIRE = "\034Y"; + const TEXTCOLOR_TEAL = "\034Z"; const TEXTCOLOR_NORMAL = "\034-"; const TEXTCOLOR_BOLD = "\034+"; diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 44f2e8c91..8fac0a22a 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1150,6 +1150,10 @@ const TEXTCOLOR_DARKBROWN = "\034S"; const TEXTCOLOR_PURPLE = "\034T"; const TEXTCOLOR_DARKGRAY = "\034U"; const TEXTCOLOR_CYAN = "\034V"; +const TEXTCOLOR_ICE = "\034W"; +const TEXTCOLOR_FIRE = "\034X"; +const TEXTCOLOR_SAPPHIRE = "\034Y"; +const TEXTCOLOR_TEAL = "\034Z"; const TEXTCOLOR_NORMAL = "\034-"; const TEXTCOLOR_BOLD = "\034+"; From f3ba92f03ce181fc07161017c7b18ff7b3e59acb Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 23 Sep 2017 14:14:59 +0200 Subject: [PATCH 012/105] - Add dynamic light to sprites --- src/polyrenderer/drawers/poly_draw_args.h | 3 ++ src/polyrenderer/drawers/poly_drawer32_sse2.h | 18 ++++--- src/polyrenderer/scene/poly_sprite.cpp | 49 +++++++++++++++++++ src/polyrenderer/scene/poly_sprite.h | 1 + 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index c3a685c88..34ef56eb2 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -81,6 +81,7 @@ public: void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; } void SetColor(uint32_t bgra, uint8_t palindex); void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; } + void SetDynLightColor(uint32_t color) { mDynLightColor = color; } void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); const TriMatrix *ObjectToClip() const { return mObjectToClip; } @@ -129,6 +130,7 @@ public: PolyLight *Lights() const { return mLights; } int NumLights() const { return mNumLights; } + uint32_t DynLightColor() const { return mDynLightColor; } const FVector3 &Normal() const { return mNormal; } void SetNormal(const FVector3 &normal) { mNormal = normal; } @@ -172,6 +174,7 @@ private: PolyLight *mLights = nullptr; int mNumLights = 0; FVector3 mNormal; + uint32_t mDynLightColor = 0; }; class RectDrawArgs diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index f4d3cb392..8c245eec9 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -149,9 +149,10 @@ namespace TriScreenDrawerModes return fgcolor; } - FORCEINLINE __m128i VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal) + FORCEINLINE __m128i VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal, uint32_t dynlightcolor) { - __m128i lit = _mm_setzero_si128(); + __m128i lit = _mm_unpacklo_epi8(_mm_cvtsi32_si128(dynlightcolor), _mm_setzero_si128()); + lit = _mm_shuffle_epi32(lit, _MM_SHUFFLE(1, 0, 1, 0)); for (int i = 0; i != num_lights; i++) { @@ -396,6 +397,7 @@ private: 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); + uint32_t dynlightcolor = args->uniforms->DynLightColor(); // Calculate gradients const ShadedTriVertex &v1 = *args->v1; @@ -476,7 +478,7 @@ private: __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); __m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); - __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; @@ -498,7 +500,7 @@ private: mrcpW = _mm_set1_ps(1.0f / blockPosX.W); worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW); - __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); __m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3); dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff,0xffff,0,0))), _mm_set1_epi16(256)), _mm_setzero_si128()); dynlightstep = _mm_slli_epi16(dynlightstep, 1); @@ -579,7 +581,7 @@ private: __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); __m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); - __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; @@ -601,7 +603,7 @@ private: mrcpW = _mm_set1_ps(1.0f / blockPosX.W); worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW); - __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); __m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3); dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff, 0xffff, 0, 0))), _mm_set1_epi16(256)), _mm_setzero_si128()); dynlightstep = _mm_slli_epi16(dynlightstep, 1); @@ -689,7 +691,7 @@ private: __m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W); __m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW); - __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; @@ -711,7 +713,7 @@ private: mrcpW = _mm_set1_ps(1.0f / blockPosX.W); worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW); - __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal); + __m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); __m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3); dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff, 0xffff, 0, 0))), _mm_set1_epi16(256)), _mm_setzero_si128()); dynlightstep = _mm_slli_epi16(dynlightstep, 1); diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 51a5bca51..b2590c357 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -154,6 +154,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight; PolyDrawArgs args; + SetDynlight(thing, args); args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); @@ -368,3 +369,51 @@ FTexture *RenderPolySprite::GetSpriteTexture(AActor *thing, /*out*/ bool &flipX) } } } + +void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args) +{ + float lit_red = 0; + float lit_green = 0; + float lit_blue = 0; + auto node = thing->Sector->lighthead; + while (node != nullptr) + { + ADynamicLight *light = node->lightsource; + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != thing) && !(light->lightflags&LF_DONTLIGHTACTORS)) + { + float lx = (float)(light->X() - thing->X()); + float ly = (float)(light->Y() - thing->Y()); + float lz = (float)(light->Z() - thing->Center()); + float LdotL = lx * lx + ly * ly + lz * lz; + float radius = node->lightsource->GetRadius(); + if (radius * radius >= LdotL) + { + float distance = sqrt(LdotL); + float attenuation = 1.0f - distance / radius; + if (attenuation > 0.0f) + { + float red = light->GetRed() * (1.0f / 255.0f); + float green = light->GetGreen() * (1.0f / 255.0f); + float blue = light->GetBlue() * (1.0f / 255.0f); + /*if (light->IsSubtractive()) + { + float bright = FVector3(lr, lg, lb).Length(); + FVector3 lightColor(lr, lg, lb); + red = (bright - lr) * -1; + green = (bright - lg) * -1; + blue = (bright - lb) * -1; + }*/ + + lit_red += red * attenuation; + lit_green += green * attenuation; + lit_blue += blue * attenuation; + } + } + } + node = node->nextLight; + } + lit_red = clamp(lit_red * 255.0f, 0.0f, 255.0f); + lit_green = clamp(lit_green * 255.0f, 0.0f, 255.0f); + lit_blue = clamp(lit_blue * 255.0f, 0.0f, 255.0f); + args.SetDynLightColor((((uint32_t)lit_red) << 16) | (((uint32_t)lit_green) << 8) | ((uint32_t)lit_blue)); +} diff --git a/src/polyrenderer/scene/poly_sprite.h b/src/polyrenderer/scene/poly_sprite.h index f634d7469..84c4905dc 100644 --- a/src/polyrenderer/scene/poly_sprite.h +++ b/src/polyrenderer/scene/poly_sprite.h @@ -37,6 +37,7 @@ private: static double PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, double spriteheight, double z); static double GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos); static double GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos); + static void SetDynlight(AActor *thing, PolyDrawArgs &args); }; class PolyTranslucentThing : public PolyTranslucentObject From 5ffd26abeb506fa23cfdc5c591d8837194d6e034 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 23 Sep 2017 15:51:40 +0200 Subject: [PATCH 013/105] - Add dynamic lights to the non-sse true color drawer --- src/polyrenderer/drawers/poly_drawer32.h | 140 +++++++++++++++++++++-- 1 file changed, 133 insertions(+), 7 deletions(-) diff --git a/src/polyrenderer/drawers/poly_drawer32.h b/src/polyrenderer/drawers/poly_drawer32.h index 2c85e257d..579488ea3 100644 --- a/src/polyrenderer/drawers/poly_drawer32.h +++ b/src/polyrenderer/drawers/poly_drawer32.h @@ -154,9 +154,62 @@ namespace TriScreenDrawerModes } } - template - FORCEINLINE BgraColor Shade32(BgraColor fgcolor, BgraColor mlight, uint32_t desaturate, uint32_t inv_desaturate, BgraColor shade_fade, BgraColor shade_light) + FORCEINLINE BgraColor VECTORCALL AddLights(BgraColor material, BgraColor fgcolor, BgraColor dynlight) { + fgcolor.r = MIN(fgcolor.r + ((material.r * dynlight.r) >> 8), (uint32_t)255); + fgcolor.g = MIN(fgcolor.g + ((material.g * dynlight.g) >> 8), (uint32_t)255); + fgcolor.b = MIN(fgcolor.b + ((material.b * dynlight.b) >> 8), (uint32_t)255); + return fgcolor; + } + + FORCEINLINE BgraColor VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, FVector3 worldpos, FVector3 worldnormal, uint32_t dynlightcolor) + { + BgraColor lit = dynlightcolor; + + for (int i = 0; i != num_lights; i++) + { + FVector3 lightpos = { lights[i].x, lights[i].y, lights[i].z }; + float light_radius = lights[i].radius; + + bool is_attenuated = light_radius < 0.0f; + if (is_attenuated) + light_radius = -light_radius; + + // L = light-pos + // dist = sqrt(dot(L, L)) + // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + FVector3 L = lightpos - worldpos; + float dist2 = L | L; + float rcp_dist = 1.0f / sqrt(dist2); + float dist = dist2 * rcp_dist; + float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f); + + // The simple light type + float simple_attenuation = distance_attenuation; + + // The point light type + // diffuse = max(dot(N,normalize(L)),0) * attenuation + float dotNL = worldnormal | (L * rcp_dist); + float point_attenuation = MAX(dotNL, 0.0f) * distance_attenuation; + + uint32_t attenuation = (uint32_t)(is_attenuated ? (int32_t)point_attenuation : (int32_t)simple_attenuation); + + BgraColor light_color = lights[i].color; + lit.r += (light_color.r * attenuation) >> 8; + lit.g += (light_color.g * attenuation) >> 8; + lit.b += (light_color.b * attenuation) >> 8; + } + + lit.r = MIN(lit.r, (uint32_t)256); + lit.g = MIN(lit.g, (uint32_t)256); + lit.b = MIN(lit.b, (uint32_t)256); + return lit; + } + + template + FORCEINLINE BgraColor Shade32(BgraColor fgcolor, BgraColor mlight, uint32_t desaturate, uint32_t inv_desaturate, BgraColor shade_fade, BgraColor shade_light, BgraColor dynlight) + { + BgraColor material = fgcolor; if (ShadeModeT::Mode == (int)ShadeMode::Simple) { fgcolor.r = (fgcolor.r * mlight.r) >> 8; @@ -170,7 +223,7 @@ namespace TriScreenDrawerModes fgcolor.g = (((shade_fade.g + ((fgcolor.g * inv_desaturate + intensity) >> 8) * mlight.g) >> 8) * shade_light.g) >> 8; fgcolor.b = (((shade_fade.b + ((fgcolor.b * inv_desaturate + intensity) >> 8) * mlight.b) >> 8) * shade_light.b) >> 8; } - return fgcolor; + return AddLights(material, fgcolor, dynlight); } template @@ -322,6 +375,11 @@ private: int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; + auto lights = args->uniforms->Lights(); + auto num_lights = args->uniforms->NumLights(); + FVector3 worldnormal = args->uniforms->Normal(); + uint32_t dynlightcolor = args->uniforms->DynLightColor(); + // Calculate gradients const ShadedTriVertex &v1 = *args->v1; ScreenTriangleStepVariables gradientX = args->gradientX; @@ -330,9 +388,15 @@ private: blockPosY.W = v1.w + gradientX.W * (destX - v1.x) + gradientY.W * (destY - v1.y); blockPosY.U = v1.u * v1.w + gradientX.U * (destX - v1.x) + gradientY.U * (destY - v1.y); blockPosY.V = v1.v * v1.w + gradientX.V * (destX - v1.x) + gradientY.V * (destY - v1.y); + blockPosY.WorldX = v1.worldX * v1.w + gradientX.WorldX * (destX - v1.x) + gradientY.WorldX * (destY - v1.y); + blockPosY.WorldY = v1.worldY * v1.w + gradientX.WorldY * (destX - v1.x) + gradientY.WorldY * (destY - v1.y); + blockPosY.WorldZ = v1.worldZ * v1.w + gradientX.WorldZ * (destX - v1.x) + gradientY.WorldZ * (destY - v1.y); gradientX.W *= 8.0f; gradientX.U *= 8.0f; gradientX.V *= 8.0f; + gradientX.WorldX *= 8.0f; + gradientX.WorldY *= 8.0f; + gradientX.WorldZ *= 8.0f; // Output uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; @@ -401,10 +465,16 @@ private: fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + FVector3 worldpos = FVector3(blockPosY.WorldX, blockPosY.WorldY, blockPosY.WorldZ) / blockPosY.W; + BgraColor dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); + ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; blockPosX.U += gradientX.U; blockPosX.V += gradientX.V; + blockPosX.WorldX += gradientX.WorldX; + blockPosX.WorldY += gradientX.WorldY; + blockPosX.WorldZ += gradientX.WorldZ; rcpW = 0x01000000 / blockPosX.W; int32_t nextU = (int32_t)(blockPosX.U * rcpW); @@ -416,6 +486,13 @@ private: fixed_t lightstep = (lightnext - lightpos) / 8; lightstep = lightstep & lightmask; + worldpos = FVector3(blockPosX.WorldX, blockPosX.WorldY, blockPosX.WorldZ) / blockPosX.W; + BgraColor dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); + BgraColor dynlightstep; + dynlightstep.r = int32_t(dynlightnext.r - dynlight.r) >> 3; + dynlightstep.g = int32_t(dynlightnext.g - dynlight.g) >> 3; + dynlightstep.b = int32_t(dynlightnext.b - dynlight.b) >> 3; + for (int ix = 0; ix < 8; ix++) { // Load bgcolor @@ -456,16 +533,23 @@ private: } // Shade and blend - BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light); + BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); BgraColor outcolor = Blend32(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha); // Store result dest[ix] = outcolor; + + dynlight.r = MAX(dynlight.r + dynlightstep.r, 0); + dynlight.g = MAX(dynlight.g + dynlightstep.g, 0); + dynlight.b = MAX(dynlight.b + dynlightstep.b, 0); } blockPosY.W += gradientY.W; blockPosY.U += gradientY.U; blockPosY.V += gradientY.V; + blockPosY.WorldX += gradientY.WorldX; + blockPosY.WorldY += gradientY.WorldY; + blockPosY.WorldZ += gradientY.WorldZ; dest += pitch; } @@ -482,10 +566,16 @@ private: fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + FVector3 worldpos = FVector3(blockPosY.WorldX, blockPosY.WorldY, blockPosY.WorldZ) / blockPosY.W; + BgraColor dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); + ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; blockPosX.U += gradientX.U; blockPosX.V += gradientX.V; + blockPosX.WorldX += gradientX.WorldX; + blockPosX.WorldY += gradientX.WorldY; + blockPosX.WorldZ += gradientX.WorldZ; rcpW = 0x01000000 / blockPosX.W; int32_t nextU = (int32_t)(blockPosX.U * rcpW); @@ -497,6 +587,13 @@ private: fixed_t lightstep = (lightnext - lightpos) / 8; lightstep = lightstep & lightmask; + worldpos = FVector3(blockPosX.WorldX, blockPosX.WorldY, blockPosX.WorldZ) / blockPosX.W; + BgraColor dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); + BgraColor dynlightstep; + dynlightstep.r = int32_t(dynlightnext.r - dynlight.r) >> 3; + dynlightstep.g = int32_t(dynlightnext.g - dynlight.g) >> 3; + dynlightstep.b = int32_t(dynlightnext.b - dynlight.b) >> 3; + for (int x = 0; x < 8; x++) { // Load bgcolor @@ -539,18 +636,25 @@ private: } // Shade and blend - BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light); + BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); BgraColor outcolor = Blend32(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha); // Store result if (mask0 & (1 << 31)) dest[x] = outcolor; mask0 <<= 1; + + dynlight.r = MAX(dynlight.r + dynlightstep.r, 0); + dynlight.g = MAX(dynlight.g + dynlightstep.g, 0); + dynlight.b = MAX(dynlight.b + dynlightstep.b, 0); } blockPosY.W += gradientY.W; blockPosY.U += gradientY.U; blockPosY.V += gradientY.V; + blockPosY.WorldX += gradientY.WorldX; + blockPosY.WorldY += gradientY.WorldY; + blockPosY.WorldZ += gradientY.WorldZ; dest += pitch; } @@ -565,10 +669,16 @@ private: fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); + FVector3 worldpos = FVector3(blockPosY.WorldX, blockPosY.WorldY, blockPosY.WorldZ) / blockPosY.W; + BgraColor dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); + ScreenTriangleStepVariables blockPosX = blockPosY; blockPosX.W += gradientX.W; blockPosX.U += gradientX.U; blockPosX.V += gradientX.V; + blockPosX.WorldX += gradientX.WorldX; + blockPosX.WorldY += gradientX.WorldY; + blockPosX.WorldZ += gradientX.WorldZ; rcpW = 0x01000000 / blockPosX.W; int32_t nextU = (int32_t)(blockPosX.U * rcpW); @@ -580,6 +690,13 @@ private: fixed_t lightstep = (lightnext - lightpos) / 8; lightstep = lightstep & lightmask; + worldpos = FVector3(blockPosX.WorldX, blockPosX.WorldY, blockPosX.WorldZ) / blockPosX.W; + BgraColor dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor); + BgraColor dynlightstep; + dynlightstep.r = int32_t(dynlightnext.r - dynlight.r) >> 3; + dynlightstep.g = int32_t(dynlightnext.g - dynlight.g) >> 3; + dynlightstep.b = int32_t(dynlightnext.b - dynlight.b) >> 3; + for (int x = 0; x < 8; x++) { // Load bgcolor @@ -622,18 +739,25 @@ private: } // Shade and blend - BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light); + BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); BgraColor outcolor = Blend32(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha); // Store result if (mask1 & (1 << 31)) dest[x] = outcolor; mask1 <<= 1; + + dynlight.r = MAX(dynlight.r + dynlightstep.r, 0); + dynlight.g = MAX(dynlight.g + dynlightstep.g, 0); + dynlight.b = MAX(dynlight.b + dynlightstep.b, 0); } blockPosY.W += gradientY.W; blockPosY.U += gradientY.U; blockPosY.V += gradientY.V; + blockPosY.WorldX += gradientY.WorldX; + blockPosY.WorldY += gradientY.WorldY; + blockPosY.WorldZ += gradientY.WorldZ; dest += pitch; } @@ -707,6 +831,8 @@ private: lightpos += lightpos >> 7; // 255 -> 256 BgraColor mlight; + BgraColor dynlight = 0; + // Shade constants int inv_desaturate; BgraColor shade_fade_lit, shade_light; @@ -774,7 +900,7 @@ private: posU += stepU; // Shade and blend - BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light); + BgraColor fgcolor = Shade32(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight); BgraColor outcolor = Blend32(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha); // Store result From d7164ba4e1fc1b7ba6710feb1a8af2abe7172892 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 23 Sep 2017 16:22:22 +0200 Subject: [PATCH 014/105] - Don't apply dynamic light to fullbright sprites --- src/polyrenderer/scene/poly_sprite.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index b2590c357..02cb9e657 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -372,6 +372,13 @@ FTexture *RenderPolySprite::GetSpriteTexture(AActor *thing, /*out*/ bool &flipX) void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args) { + bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); + if (fullbrightSprite) + { + args.SetDynLightColor(0); + return; + } + float lit_red = 0; float lit_green = 0; float lit_blue = 0; From cfc1bfd1e203b51605154ff336fa9c14fe55accd Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 24 Sep 2017 01:15:58 +0200 Subject: [PATCH 015/105] - Fixed FxPow::Resolve not specifying the ValueType --- src/scripting/backend/codegen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index bd8fcef9c..2af0f9ae7 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -3302,6 +3302,7 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx) right = (new FxFloatCast(right))->Resolve(ctx); ABORT(right); } + ValueType = TypeFloat64; if (left->isConstant() && right->isConstant()) { double v1 = static_cast(left)->GetValue().GetFloat(); From 48f9e535804f46c55f4499ba534d0ca6fdb49f5f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 24 Sep 2017 10:25:05 +0300 Subject: [PATCH 016/105] Added better error message for invalid class/struct member https://forum.zdoom.org/viewtopic.php?t=57959 --- src/scripting/backend/codegen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 2af0f9ae7..249537aaa 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6464,6 +6464,12 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) } } } + else + { + ScriptPosition.Message(MSG_ERROR, "%s is not a member of %s", Identifier.GetChars(), ccls->TypeName.GetChars()); + delete this; + return nullptr; + } } } From dfe05f10b712d644793a91c012bdf016054d5d89 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 26 Sep 2017 10:54:55 +0300 Subject: [PATCH 017/105] Fixed BlockLinesIterator class definition in ZScript https://forum.zdoom.org/viewtopic.php?t=57982 --- wadsrc/static/zscript/base.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 351d4d949..f9fd571ed 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -449,8 +449,8 @@ class BlockLinesIterator : Object native native Vector3 position; native int portalflags; - native static BlockThingsIterator Create(Actor origin, double checkradius = -1); - native static BlockThingsIterator CreateFromPos(Vector3 pos, double checkh, double checkradius, Sector sec = null); + native static BlockLinesIterator Create(Actor origin, double checkradius = -1); + native static BlockLinesIterator CreateFromPos(Vector3 pos, double checkh, double checkradius, Sector sec = null); native bool Next(); } From 2daa64428dcddb78c0477f2a47fe24f970d0e886 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 28 Sep 2017 12:16:47 +0300 Subject: [PATCH 018/105] Removed redundant dot from name of compatibility option https://forum.zdoom.org/viewtopic.php?t=58012 --- wadsrc/static/language.enu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index e440dc786..387477151 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2098,7 +2098,7 @@ CMPTMNU_SHORTTEX = "Find shortest textures like Doom"; CMPTMNU_STAIRS = "Use buggier stair building"; CMPTMNU_FLOORMOVE = "Use Doom's floor motion behavior"; CMPTMNU_POINTONLINE = "Use Doom's point-on-line algorithm"; -CMPTMNU_MULTIEXIT = "Level exit can be triggered more than once."; +CMPTMNU_MULTIEXIT = "Level exit can be triggered more than once"; CMPTMNU_PHYSICSBEHAVIOR = "Physics Behavior"; CMPTMNU_NOPASSOVER = "Actors are infinitely tall"; CMPTMNU_BOOMSCROLL = "Boom scrollers are additive"; From 3031d48bfbb6a834aa967ee853c91f4658a2d295 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 28 Sep 2017 11:33:53 -0400 Subject: [PATCH 019/105] - added TID to actorlist and similar commands output --- src/c_cmds.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 00a3e4ebe..748680e91 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -957,8 +957,13 @@ static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const cha { counter++; if (!countOnly) - Printf("%s at (%f,%f,%f)\n", + { + Printf("%s at (%f,%f,%f)", mo->GetClass()->TypeName.GetChars(), mo->X(), mo->Y(), mo->Z()); + if (mo->tid) + Printf(" (TID:%d)", mo->tid); + Printf("\n"); + } } } } From 0ee021a97248dbec97713342519ea7ff15fea913 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 29 Sep 2017 05:23:17 +0200 Subject: [PATCH 020/105] - Improve transfer heights support in softpoly --- src/polyrenderer/scene/poly_plane.cpp | 655 +++++++++++++++----------- src/polyrenderer/scene/poly_plane.h | 27 +- 2 files changed, 399 insertions(+), 283 deletions(-) diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 2ec86327e..b642057c3 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -47,238 +47,357 @@ void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &wo } void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) +{ + FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); + if (!portal || (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into + { + RenderNormal(thread, worldToClip, clipPlane, sub, stencilValue, ceiling, skyHeight); + } + else + { + RenderPortal(thread, worldToClip, clipPlane, sub, stencilValue, ceiling, skyHeight, portal, sectorPortals); + } +} + +void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - sector_t *fakesector = sub->sector->heightsec; - if (fakesector && (fakesector == sub->sector || (fakesector->MoreFlags & SECF_IGNOREHEIGHTSEC) == SECF_IGNOREHEIGHTSEC)) - fakesector = nullptr; - - bool fakeflooronly = fakesector && (fakesector->MoreFlags & SECF_FAKEFLOORONLY) == SECF_FAKEFLOORONLY; - - FTextureID picnum; - bool ccw; - sector_t *frontsector; - if (fakesector) + FTextureID picnum = GetPlaneTexture(sub, ceiling); + if (picnum != skyflatnum) { - // Floor and ceiling texture needs to be swapped sometimes? Why?? :( - - if (viewpoint.Pos.Z < fakesector->floorplane.Zat0()) // In water - { - if (ceiling) - { - picnum = fakesector->GetTexture(sector_t::ceiling); - ceiling = false; - frontsector = fakesector; - ccw = false; - } - else - { - picnum = fakesector->GetTexture(sector_t::floor); - frontsector = sub->sector; - ccw = true; - } - } - else if (viewpoint.Pos.Z >= fakesector->ceilingplane.Zat0() && !fakeflooronly) // In ceiling water - { - if (ceiling) - { - picnum = fakesector->GetTexture(sector_t::ceiling); - frontsector = sub->sector; - ccw = true; - } - else - { - picnum = fakesector->GetTexture(sector_t::floor); - frontsector = fakesector; - ccw = false; - ceiling = true; - } - } - else if (!ceiling) // Water surface - { - picnum = fakesector->GetTexture(sector_t::ceiling); - frontsector = fakesector; - ccw = true; - } - else if (!fakeflooronly) // Ceiling water surface - { - picnum = fakesector->GetTexture(sector_t::floor); - frontsector = fakesector; - ccw = true; - } - else // Upper ceiling - { - picnum = sub->sector->GetTexture(sector_t::ceiling); - ccw = true; - frontsector = sub->sector; - } - } - else - { - picnum = sub->sector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); - ccw = true; - frontsector = sub->sector; - } - - FTexture *tex = TexMan(picnum); - if (tex->UseType == FTexture::TEX_Null) - return; - - std::vector portalSegments; - FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); - PolyDrawSectorPortal *polyportal = nullptr; - if (portal && (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into - portal = nullptr; - - bool isSky = portal || picnum == skyflatnum; - - if (portal) - { - // Skip portals not facing the camera - if ((ceiling && frontsector->ceilingplane.PointOnSide(viewpoint.Pos) < 0) || - (!ceiling && frontsector->floorplane.PointOnSide(viewpoint.Pos) < 0)) - { + FTexture *tex = TexMan(picnum); + if (!tex || tex->UseType == FTexture::TEX_Null) return; - } - for (auto &p : sectorPortals) - { - if (p->Portal == portal) // To do: what other criteria do we need to check for? - { - polyportal = p.get(); - break; - } - } - if (!polyportal) - { - sectorPortals.push_back(std::unique_ptr(new PolyDrawSectorPortal(portal, ceiling))); - polyportal = sectorPortals.back().get(); - } + PolyPlaneUVTransform transform = GetPlaneTransform(sub, ceiling, tex); + TriVertex *vertices = CreatePlaneVertices(thread, sub, transform, GetSecPlane(sub, ceiling)); -#if 0 - // Calculate portal clipping - portalSegments.reserve(sub->numlines); - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - - DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; - DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; - bool backside = pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0; - if (!backside) - { - angle_t angle1, angle2; - if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) - portalSegments.push_back({ angle1, angle2 }); - } - else - { - angle_t angle1, angle2; - if (cull.GetAnglesForLine(line->v2->fX(), line->v2->fY(), line->v1->fX(), line->v1->fY(), angle1, angle2)) - portalSegments.push_back({ angle1, angle2 }); - } - } -#endif - } - - PolyPlaneUVTransform transform(ceiling ? frontsector->planes[sector_t::ceiling].xform : frontsector->planes[sector_t::floor].xform, tex); - - TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); - - if (ceiling) - { - if (!isSky) - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[sub->numlines - 1 - i] = transform.GetVertex(line->v1, frontsector->ceilingplane.ZatPoint(line->v1)); - } - } - else - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[sub->numlines - 1 - i] = transform.GetVertex(line->v1, skyHeight); - } - } - } - else - { - if (!isSky) - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[i] = transform.GetVertex(line->v1, frontsector->floorplane.ZatPoint(line->v1)); - } - } - else - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[i] = transform.GetVertex(line->v1, skyHeight); - } - } - } - - bool foggy = level.fadeto || frontsector->Colormap.FadeColor || (level.flags & LEVEL_HASFADETABLE); - - int lightlevel = ceiling ? frontsector->GetCeilingLight() : frontsector->GetFloorLight(); - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - lightlevel = clamp(lightlevel + actualextralight, 0, 255); - - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - FDynamicColormap *basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); - if (cameraLight->FixedLightLevel() < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size()) - { - lightlist_t *light = P_GetPlaneLight(frontsector, ceiling ? &frontsector->ceilingplane : &frontsector->floorplane, false); - basecolormap = GetColorTable(light->extra_colormap, frontsector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); - if (light->p_lightlevel != &frontsector->lightlevel) // If this is the real ceiling, don't discard plane lighting R_FakeFlat() accounted for. - { - lightlevel = *light->p_lightlevel; - } - } - - PolyDrawArgs args; - args.SetLight(basecolormap, lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); - //args.SetSubsectorDepth(isSky ? RenderPolyScene::SkySubsectorDepth : subsectorDepth); - args.SetTransform(&worldToClip); - args.SetFaceCullCCW(ccw); - args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue + 1); - args.SetClipPlane(0, clipPlane); - - if (!isSky) - { + PolyDrawArgs args; + SetLightLevel(thread, args, sub, ceiling); SetDynLights(thread, args, sub, ceiling); + args.SetTransform(&worldToClip); + args.SetFaceCullCCW(true); + args.SetStencilTestValue(stencilValue); + args.SetWriteStencil(true, stencilValue + 1); + args.SetClipPlane(0, clipPlane); args.SetTexture(tex); args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); } else { - if (portal) - { - args.SetWriteStencil(true, polyportal->StencilValue); - polyportal->Shape.push_back({ vertices, (int)sub->numlines, ccw }); - } - else - { - args.SetWriteStencil(true, 255); - } + TriVertex *vertices = CreateSkyPlaneVertices(thread, sub, skyHeight); + PolyDrawArgs args; + args.SetTransform(&worldToClip); + args.SetFaceCullCCW(true); + args.SetStencilTestValue(stencilValue); + args.SetWriteStencil(true, stencilValue + 1); + args.SetClipPlane(0, clipPlane); + args.SetWriteStencil(true, 255); args.SetWriteColor(false); args.SetWriteDepth(false); args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); - RenderSkyWalls(thread, args, sub, frontsector, portal, polyportal, ceiling, skyHeight, transform); + RenderSkyWalls(thread, args, sub, nullptr, ceiling, skyHeight); } } +void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals) +{ + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + + PolyDrawSectorPortal *polyportal = nullptr; + std::vector portalSegments; + + sector_t *frontsector = sub->sector; + + // Skip portals not facing the camera + if ((ceiling && frontsector->ceilingplane.PointOnSide(viewpoint.Pos) < 0) || + (!ceiling && frontsector->floorplane.PointOnSide(viewpoint.Pos) < 0)) + { + return; + } + + for (auto &p : sectorPortals) + { + if (p->Portal == portal) // To do: what other criteria do we need to check for? + { + polyportal = p.get(); + break; + } + } + if (!polyportal) + { + sectorPortals.push_back(std::unique_ptr(new PolyDrawSectorPortal(portal, ceiling))); + polyportal = sectorPortals.back().get(); + } + +#if 0 + // Calculate portal clipping + portalSegments.reserve(sub->numlines); + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[i]; + + DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; + DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; + bool backside = pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0; + if (!backside) + { + angle_t angle1, angle2; + if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) + portalSegments.push_back({ angle1, angle2 }); + } + else + { + angle_t angle1, angle2; + if (cull.GetAnglesForLine(line->v2->fX(), line->v2->fY(), line->v1->fX(), line->v1->fY(), angle1, angle2)) + portalSegments.push_back({ angle1, angle2 }); + } + } +#endif + + TriVertex *vertices = CreateSkyPlaneVertices(thread, sub, skyHeight); + + PolyDrawArgs args; + args.SetTransform(&worldToClip); + args.SetFaceCullCCW(true); + args.SetStencilTestValue(stencilValue); + args.SetWriteStencil(true, stencilValue + 1); + args.SetClipPlane(0, clipPlane); + args.SetWriteStencil(true, polyportal->StencilValue); + args.SetWriteColor(false); + args.SetWriteDepth(false); + args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); + + RenderSkyWalls(thread, args, sub, polyportal, ceiling, skyHeight); + + polyportal->Shape.push_back({ vertices, (int)sub->numlines, true }); +} + +void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight) +{ + sector_t *frontsector = sub->sector; + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[i]; + + double skyBottomz1 = frontsector->ceilingplane.ZatPoint(line->v1); + double skyBottomz2 = frontsector->ceilingplane.ZatPoint(line->v2); + if (line->backsector) + { + sector_t *backsector = line->backsector; + + double backceilz1 = backsector->ceilingplane.ZatPoint(line->v1); + double backfloorz1 = backsector->floorplane.ZatPoint(line->v1); + double backceilz2 = backsector->ceilingplane.ZatPoint(line->v2); + double backfloorz2 = backsector->floorplane.ZatPoint(line->v2); + + bool bothSkyCeiling = frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum; + + bool closedSector = backceilz1 == backfloorz1 && backceilz2 == backfloorz2; + if (ceiling && bothSkyCeiling && closedSector) + { + double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); + double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); + double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2); + double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2); + + double topceilz1 = frontceilz1; + double topceilz2 = frontceilz2; + double topfloorz1 = MIN(backceilz1, frontceilz1); + double topfloorz2 = MIN(backceilz2, frontceilz2); + double bottomceilz1 = MAX(frontfloorz1, backfloorz1); + double bottomceilz2 = MAX(frontfloorz2, backfloorz2); + double middleceilz1 = topfloorz1; + double middleceilz2 = topfloorz2; + double middlefloorz1 = MIN(bottomceilz1, middleceilz1); + double middlefloorz2 = MIN(bottomceilz2, middleceilz2); + + skyBottomz1 = middlefloorz1; + skyBottomz2 = middlefloorz2; + } + else if (bothSkyCeiling) + { + continue; + } + } + else if (polyportal && line->linedef && line->linedef->special == Line_Horizon) + { + // Not entirely correct as this closes the line horizon rather than allowing the floor to continue to infinity + skyBottomz1 = frontsector->floorplane.ZatPoint(line->v1); + skyBottomz2 = frontsector->floorplane.ZatPoint(line->v2); + } + + TriVertex *wallvert = thread->FrameMemory->AllocMemory(4); + + if (ceiling) + { + wallvert[0] = GetSkyVertex(line->v1, skyHeight); + wallvert[1] = GetSkyVertex(line->v2, skyHeight); + wallvert[2] = GetSkyVertex(line->v2, skyBottomz2); + wallvert[3] = GetSkyVertex(line->v1, skyBottomz1); + } + else + { + wallvert[0] = GetSkyVertex(line->v1, frontsector->floorplane.ZatPoint(line->v1)); + wallvert[1] = GetSkyVertex(line->v2, frontsector->floorplane.ZatPoint(line->v2)); + wallvert[2] = GetSkyVertex(line->v2, skyHeight); + wallvert[3] = GetSkyVertex(line->v1, skyHeight); + } + + args.DrawArray(thread, wallvert, 4, PolyDrawMode::TriangleFan); + + if (polyportal) + { + polyportal->Shape.push_back({ wallvert, 4, args.FaceCullCCW() }); + } + } +} + +sector_t *RenderPolyPlane::GetHeightSec(subsector_t *sub, bool ceiling) +{ + sector_t *controlsector = sub->sector->GetHeightSec(); + if (!controlsector || controlsector == sub->sector || (ceiling && !!(controlsector->MoreFlags & SECF_FAKEFLOORONLY))) + return nullptr; + else + return controlsector; +} + +HeightSecLocation RenderPolyPlane::GetHeightSecLocation(sector_t *controlsector) +{ + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + if (viewpoint.Pos.Z > controlsector->ceilingplane.ZatPoint(viewpoint.Pos.XY())) // Above control sector ceiling (A) + return HeightSecLocation::Above; + else if (viewpoint.Pos.Z > controlsector->floorplane.ZatPoint(viewpoint.Pos.XY())) // Between control sector ceiling and floor (B) + return HeightSecLocation::Between; + else + return HeightSecLocation::Below; +} + +FTextureID RenderPolyPlane::GetPlaneTexture(subsector_t *sub, bool ceiling) +{ + sector_t *controlsector = GetHeightSec(sub, ceiling); + if (!controlsector) + return sub->sector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); + + bool diffTex = !!(controlsector->MoreFlags & SECF_CLIPFAKEPLANES); + + switch (GetHeightSecLocation(controlsector)) + { + default: + case HeightSecLocation::Above: + if (diffTex && ceiling) + return sub->sector->GetTexture(sector_t::ceiling); + else + return controlsector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); + + case HeightSecLocation::Between: + return sub->sector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); + + case HeightSecLocation::Below: + if (diffTex && !ceiling) + return sub->sector->GetTexture(sector_t::floor); + else + return controlsector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); + } +} + +PolyPlaneUVTransform RenderPolyPlane::GetPlaneTransform(subsector_t *sub, bool ceiling, FTexture *tex) +{ + sector_t *controlsector = GetHeightSec(sub, ceiling); + if (!controlsector) + return PolyPlaneUVTransform(ceiling ? sub->sector->planes[sector_t::ceiling].xform : sub->sector->planes[sector_t::floor].xform, tex); + + bool diffTex = !!(controlsector->MoreFlags & SECF_CLIPFAKEPLANES); + + switch (GetHeightSecLocation(controlsector)) + { + default: + case HeightSecLocation::Above: + if (diffTex && ceiling) + return PolyPlaneUVTransform(sub->sector->planes[sector_t::ceiling].xform, tex); + else + return PolyPlaneUVTransform(ceiling ? controlsector->planes[sector_t::ceiling].xform : controlsector->planes[sector_t::floor].xform, tex); + + case HeightSecLocation::Between: + return PolyPlaneUVTransform(ceiling ? sub->sector->planes[sector_t::ceiling].xform : sub->sector->planes[sector_t::floor].xform, tex); + + case HeightSecLocation::Below: + if (diffTex && !ceiling) + return PolyPlaneUVTransform(sub->sector->planes[sector_t::floor].xform, tex); + else + return PolyPlaneUVTransform(ceiling ? controlsector->planes[sector_t::ceiling].xform : controlsector->planes[sector_t::floor].xform, tex); + } +} + +const secplane_t &RenderPolyPlane::GetSecPlane(subsector_t *sub, bool ceiling) +{ + sector_t *controlsector = GetHeightSec(sub, ceiling); + if (!controlsector) + return ceiling ? sub->sector->ceilingplane : sub->sector->floorplane; + + switch (GetHeightSecLocation(controlsector)) + { + default: + case HeightSecLocation::Above: + return ceiling ? sub->sector->ceilingplane : controlsector->ceilingplane; + case HeightSecLocation::Between: + return ceiling ? controlsector->ceilingplane : controlsector->floorplane; + case HeightSecLocation::Below: + return ceiling ? controlsector->floorplane : sub->sector->floorplane; + } +} + +void RenderPolyPlane::SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling) +{ + sector_t *lightSector = sub->sector; + sector_t *controlsector = GetHeightSec(sub, ceiling); + if (controlsector) + { + bool diffTex = !!(controlsector->MoreFlags & SECF_CLIPFAKEPLANES); + bool noFakeLight = !!(controlsector->MoreFlags & SECF_NOFAKELIGHT); + + switch (GetHeightSecLocation(controlsector)) + { + default: + case HeightSecLocation::Above: + // todo: upper texture as colormap + lightSector = controlsector; + break; + case HeightSecLocation::Between: + // normal texture as colormap + break; + case HeightSecLocation::Below: + // todo: lower texture as colormap + lightSector = controlsector; + break; + } + } + + bool foggy = level.fadeto || lightSector->Colormap.FadeColor || (level.flags & LEVEL_HASFADETABLE); + + int lightlevel = ceiling ? lightSector->GetCeilingLight() : lightSector->GetFloorLight(); + int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; + lightlevel = clamp(lightlevel + actualextralight, 0, 255); + + PolyCameraLight *cameraLight = PolyCameraLight::Instance(); + FDynamicColormap *basecolormap = GetColorTable(lightSector->Colormap, lightSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); + if (cameraLight->FixedLightLevel() < 0 && lightSector->e && lightSector->e->XFloor.lightlist.Size()) + { + lightlist_t *light = P_GetPlaneLight(lightSector, ceiling ? &lightSector->ceilingplane : &lightSector->floorplane, false); + basecolormap = GetColorTable(light->extra_colormap, lightSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); + if (light->p_lightlevel != &lightSector->lightlevel) // If this is the real ceiling, don't discard plane lighting R_FakeFlat() accounted for. + { + lightlevel = *light->p_lightlevel; + } + } + + args.SetLight(basecolormap, lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); +} + void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling) { FLightNode *light_list = sub->lighthead; @@ -342,83 +461,55 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, args.SetNormal({ (float)normal.X, (float)normal.Y, (float)normal.Z }); } -void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform) +TriVertex *RenderPolyPlane::CreatePlaneVertices(PolyRenderThread *thread, subsector_t *sub, const PolyPlaneUVTransform &transform, const secplane_t &plane) { - for (uint32_t i = 0; i < sub->numlines; i++) + TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); + + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + double planeZ = plane.ZatPoint(viewpoint.Pos.XY()); + if (viewpoint.Pos.Z < planeZ) { - seg_t *line = &sub->firstline[i]; - - double skyBottomz1 = frontsector->ceilingplane.ZatPoint(line->v1); - double skyBottomz2 = frontsector->ceilingplane.ZatPoint(line->v2); - if (line->backsector) + for (uint32_t i = 0; i < sub->numlines; i++) { - sector_t *backsector = line->backsector; - - double backceilz1 = backsector->ceilingplane.ZatPoint(line->v1); - double backfloorz1 = backsector->floorplane.ZatPoint(line->v1); - double backceilz2 = backsector->ceilingplane.ZatPoint(line->v2); - double backfloorz2 = backsector->floorplane.ZatPoint(line->v2); - - bool bothSkyCeiling = frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum; - - bool closedSector = backceilz1 == backfloorz1 && backceilz2 == backfloorz2; - if (ceiling && bothSkyCeiling && closedSector) - { - double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); - double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); - double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2); - double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2); - - double topceilz1 = frontceilz1; - double topceilz2 = frontceilz2; - double topfloorz1 = MIN(backceilz1, frontceilz1); - double topfloorz2 = MIN(backceilz2, frontceilz2); - double bottomceilz1 = MAX(frontfloorz1, backfloorz1); - double bottomceilz2 = MAX(frontfloorz2, backfloorz2); - double middleceilz1 = topfloorz1; - double middleceilz2 = topfloorz2; - double middlefloorz1 = MIN(bottomceilz1, middleceilz1); - double middlefloorz2 = MIN(bottomceilz2, middleceilz2); - - skyBottomz1 = middlefloorz1; - skyBottomz2 = middlefloorz2; - } - else if (bothSkyCeiling) - { - continue; - } - } - else if (portal && line->linedef && line->linedef->special == Line_Horizon) - { - // Not entirely correct as this closes the line horizon rather than allowing the floor to continue to infinity - skyBottomz1 = frontsector->floorplane.ZatPoint(line->v1); - skyBottomz2 = frontsector->floorplane.ZatPoint(line->v2); - } - - TriVertex *wallvert = thread->FrameMemory->AllocMemory(4); - - if (ceiling) - { - wallvert[0] = transform.GetVertex(line->v1, skyHeight); - wallvert[1] = transform.GetVertex(line->v2, skyHeight); - wallvert[2] = transform.GetVertex(line->v2, skyBottomz2); - wallvert[3] = transform.GetVertex(line->v1, skyBottomz1); - } - else - { - wallvert[0] = transform.GetVertex(line->v1, frontsector->floorplane.ZatPoint(line->v1)); - wallvert[1] = transform.GetVertex(line->v2, frontsector->floorplane.ZatPoint(line->v2)); - wallvert[2] = transform.GetVertex(line->v2, skyHeight); - wallvert[3] = transform.GetVertex(line->v1, skyHeight); - } - - args.DrawArray(thread, wallvert, 4, PolyDrawMode::TriangleFan); - - if (portal) - { - polyportal->Shape.push_back({ wallvert, 4, args.FaceCullCCW() }); + seg_t *line = &sub->firstline[sub->numlines - 1 - i]; + vertices[i] = transform.GetVertex(line->v1, plane.ZatPoint(line->v1)); } } + else + { + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[i]; + vertices[i] = transform.GetVertex(line->v1, plane.ZatPoint(line->v1)); + } + } + + return vertices; +} + +TriVertex *RenderPolyPlane::CreateSkyPlaneVertices(PolyRenderThread *thread, subsector_t *sub, double skyHeight) +{ + TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); + + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + if (viewpoint.Pos.Z < skyHeight) + { + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[sub->numlines - 1 - i]; + vertices[i] = GetSkyVertex(line->v1, skyHeight); + } + } + else + { + for (uint32_t i = 0; i < sub->numlines; i++) + { + seg_t *line = &sub->firstline[i]; + vertices[i] = GetSkyVertex(line->v1, skyHeight); + } + } + + return vertices; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 74db247e6..30d374e62 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -54,6 +54,13 @@ private: float xOffs, yOffs; }; +enum class HeightSecLocation +{ + Above, // Above control sector ceiling (A) + Between, // Between control sector ceiling and floor (B) + Below // Below control sector floor (C) +}; + class RenderPolyPlane { public: @@ -61,8 +68,26 @@ public: private: void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); - void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform); + + void RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals); + void RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight); + + void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight); + + void SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); + + FTextureID GetPlaneTexture(subsector_t *sub, bool ceiling); + PolyPlaneUVTransform GetPlaneTransform(subsector_t *sub, bool ceiling, FTexture *texture); + const secplane_t &GetSecPlane(subsector_t *sub, bool ceiling); + + sector_t *GetHeightSec(subsector_t *sub, bool ceiling); + HeightSecLocation GetHeightSecLocation(sector_t *controlsector); + + TriVertex *CreatePlaneVertices(PolyRenderThread *thread, subsector_t *sub, const PolyPlaneUVTransform &transform, const secplane_t &plane); + TriVertex *CreateSkyPlaneVertices(PolyRenderThread *thread, subsector_t *sub, double skyHeight); + + static TriVertex GetSkyVertex(vertex_t *v, double height) { return { (float)v->fX(), (float)v->fY(), (float)height, 1.0f, 0.0f, 0.0f }; } }; class Render3DFloorPlane From 5af8f6ccaa6616b7332b7b2bb0183f3c79b5b95c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 07:58:52 +0200 Subject: [PATCH 021/105] - removed metadata from INVGEMx. --- wadsrc/static/graphics/invgeml1.png | Bin 15350 -> 249 bytes wadsrc/static/graphics/invgeml2.png | Bin 15351 -> 251 bytes wadsrc/static/graphics/invgemr1.png | Bin 15351 -> 245 bytes wadsrc/static/graphics/invgemr2.png | Bin 15353 -> 247 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/wadsrc/static/graphics/invgeml1.png b/wadsrc/static/graphics/invgeml1.png index 3b7429588bd06f163d684ac84313bb1da3a35b27..60ed485ed5b98556ba7dfb3632e9afae132e1bd4 100644 GIT binary patch delta 191 zcmexX{*!TnBnKM<14I10KXWIiTIkg?a29w(7Bet#3xP1>rMq>1fYOpBt`Q}{`DrEP ziAAXl1&Nt?C3<|Hbw8i)vHH=)-ZUw`njxgN@xNA5X49| literal 15350 zcmeI3XH*ke8^>o~zwEktj%&ppgAFm6Ngx5n5I_Qg5=1}&8w`^Pj3k+u3=*(o?_IGM z>|*b|V(%4u$KHG8y^}z=G-r3uew;aE^5owC^S^g~w=iGssEF`(RV&x4j37wW&=5@| z`2HPys{CFF+>`yQtOZ|xm_y>M2=ZqQ?(-WmYmN(oc)QZkv23h13?~_*l+ZDWl+)$$Hxc7wSqiZxq0SfhGneD zOa)Ckt1E06jEPq3Y`fh48ja;PZDoV{00f0d%gwY#r<*A>lCm^o(nD@fyN9BKBc;20qlcvd{nLJ=%uiDnps+A+%_iV%td1MRa))G~%P z>6kRDn+h$RQas+pZj^>#DK(gn3W*Gp$Q98t43~T1a?Bm`#xV>saVSf9Xc--?PcP#k z#}!KO2YW!u(jH*_=m?hhTQ0B`^3jpFp0OASR!tj;BnmZ~l2mAMA*6K9Dm;)eFc#1) z@c1gUykaQJKGX0}la(b*Bo(Srg90f{>u?{X(o^oEBqW&LLoU&Ic#;xt4;>{TFbX3{ z%+o88QraPEwQzbFYYjuDa;v4#TK5mFq4YA=9W6B2=?DX);d=j1n<&SoOj9AW70l0c zXx@U^Yv0SFsNN+@iz*DXeNQqI7AwWAIA3wml5=ii&OM6Dv9Da5Ai3R4O>zr@(y7oA zrN!NHW)`N=|8@W!{!n_wZKNerre7^6hm~Dbv5A$@vuT8d3P=KT;_s|=hil2S()KEp z+x-o6$$@Z`mK>j=8C!NdRoteAgSi0uMcBtcrb5e<6}Rlr$8uw8NVV&|Pxp{HLc{0#Ldt3HIsG=~@F;dWfbNfI#O2NAVcuhf_?coD$@0T)bzHx_X5B7y}1E|>;yEa2ir1PcUQFb&>Vz{QIQ z76`at8oaT9ix&|r5OBdXcw+$1=HY-1zfy{V1a-OrokHv zxOfr40s$9HgEtm%@gjl+0xp;aZ!F;AMFa~3TrdsZSir@L2o?yqU>dx!fQuIqED&(P zG2% zfPericNO&N)yvJzt$q9Uef##!&o7Y43S3;kT~@t%^%^y5)T~*vR;^mKYuBz*rw%Zw zTeoh#diCnpuiv0SgN6+oHfq$UapT6|Nt-ljA{L8XU0s_tZQ86^v*yj4w`kF#Wy_Yp zxmBxH?(XibTep@-BvPpqMNx2)0{F}2at{v=Pft&ULZMVDy}Z1}Swrv9g12q~=P*6~CaB#bJ?LtCALPJAA&pUMJ5Ed4u)oR1T z!#j5D7!eWCsZ*!O$jGRusOaeE&Ye4V>Cz=8CMGsEHZCp>5a`yeTlenWd-UkhvuDrv z`1pi`1cD$E6B9|2)ai5-Md|hWq@<+eiOv$=Qg-WH1m z;A2@fH8r(QpFZH6qs?YZPfyRt$N(h!_3PKafByjk1`HfHaL}MZg9i`J%*-4zWXRB= zLx&9;HhlQ-5hF&79655-s8ORwj~+8-%-FGG$Bi2|e*E|e6DCZYIC0XXNs}i}o-$?1 z)TvXaO`A4-`t%tyW@Ke$&73)N)~s2xXV0E9XU^QYbLY*QH-G;81q&7|T)1%2qD9%+ z*^3u1Ub1A#(xpq6EnBvH`SKMjR;*mPa@DF;IXOA2SFc{PX3g5QYuBw?w|@Ql4I4IW z+_-VmrcIkSZ{D(H%hs)1w{6?Def#zuJ9g~cxpUX9UAuSh-m_=V-o1PG?c2A1|Na99 z4jepq@X(<{xw*NA4<9~qgGyLSEh^&2;C+`M`7)~#E&Z{NOi=g!@` zckkW1cmMwV2M-=ReE2XwKmXCAM~@#re)8nW)2C0LJ$v^2`STYqUc7wy^3|(XuV24@ z^XARlw{PFQd-wkR`wt&JeEj(F)2C0LKY#x6<;&NvU%!3(_Wk?!A3uKl{Q0w>pkVLo z`V+zI|Ba0dk3#(O^Yq|{XQ(D1+ICHKbp2oZuqp@r{af`g7Z{_m!iV`GX4Rhw)vxF2 ruUAR`JfZfs-2RmocpSX+wJMUG`M;BA-Lr3id?Yj|T(hQaLgxPg=l4#% diff --git a/wadsrc/static/graphics/invgeml2.png b/wadsrc/static/graphics/invgeml2.png index c06fe538542a9a9487996b7138e4a91badf93e17..44a6160e55084588424ea9563a94a82baacefb3c 100644 GIT binary patch delta 193 zcmexf{+n@vBnKM<14I10KXWIiTIkg?a29w(7Bet#3xP1>rMq>1fYOpBt`Q}{`DrEP ziAAXl1&Nt?C3<i!bl)dEH~f9)k@vnMoiJ#t=XPf)d0K1gs3n03%5zCIbX)DE8h9 zV($%m@4ffldqKtCu)cQ^2$ulP?w=j3veJMC*NCC!*2U|#jp)FdPHYgpdEUE;dAUN2*sst@# zDU+VguzD&`*Ob!vE_EYS1VbvpdX$MIm`EzqN-$jNi%YTAm>kD2$i$&^@lexxDk-y^ zhZL9j;u1gD15&zrfc>K<7~(Ivz*@*hufvmQi;-ZIl#xg#QL`yoftEHxO6RJ=gJ}b8 z0o?+_SD+O&Ls|BfhKHN13}Mod;VLC)5L1*M*I}fOSCT|7k|q+Eh?IKEMTy>ETk9~n z6eINn<}Cs4<6R$edpqYjy=tkI(9>ldIegh zwX|E#%;GfapH85|A4;#hMn(#0`qhSVSlLyTn^@^2CWEk$LCIiE{FS}#a4nnWYOg@q z)89aqod`#3+4(71vE}De!5(TjSPP(EgnbSq3bb5XX=R5#j-69OnqBWJ#lQ=du%E@L z@MYK3_+O{Omt9j!Gh<8?!|rl>M_rnsEcWDe91GFlCV^D?$YfqJ1?t-Dnh{0WNJE^8 z0{hp>u1a}vifem?dGV!r>`7s-Wlw}I6el`n3i>yV7Vx-W8k{kYixUwn;Bmn;IAb0cCn8wD zck;kBbu#EZ}j$G&o}(7bhZEz~h2xaK=0?PDHSP#|6{i zjCov~h+qMa3#P#t^SC$>!2%u^OoKD#ad9Go1w1a824~FU;zR@scw8_I&X~u=i3k?( zxL_KbF^`KA5iH>LCs z`U$=Z5F`ylkY@=9g3myZI`pJohe8pgDiRf;4M99T-QC?gbm#z*t5>h?>FKG_Xuz|0 zUAuM-3JU7oySGFlL697c1~~Ob5RJP#2=c5}YmFK;YSye-t5&VrwQJX@QwNyTty{NV zy?XWQ*Kg3ELBoa(8#QXwxN&1J(k4xs2!%oq509ozn>K6KtaRKsUAy4mV3kT05)u*`8rr^n`>?RE@bGXju8ti$MnpuY)#}K|$WEO) zMMXt*?%WxSF*-V0tJTKD#B}M>B{nuTE-o%UJ|2v^TeoiAyLa!=qesu4J$v=)m5`7? z5JX~PqE4sN>-8i_CM6{$Cnu+*q)-$E_@t($8Vm-b(P%Q6Xqq;g&3*dxu~;ks5yLQP zX=&-{>EJm>o6VM)nVFT9)wgfoe*OCO@85sGfB^#s4$RKZ9yDms;K74)a&m?Y88UR} z&|$-d4Ie&y#E20iM~)mdYSie_qsNRHGj{CQapT5~A3uJ=gb5QTPMkDp(&WjLr%ahL zb?Ve<)22Pbbm`J%%a$!)zI?@s6)RV+T(xS|>eZ|B^YhoNS+jQS+I8#JtzW->!-fqT zH*VatY18J-o40J)vUTg$ZQHhO-@bjvjvYI9?%cI&*Y4fB_w3oTckkYP`}XbMzyH92 z0|yTtJap*L;lqcI9656I=+R@xjvYUK{KSb9Cr_R{b?VgV)2GjzIdk^x*>mU4oj-s6 z!i5VLFJ8QK>C)xPm#C=LOf@ja3J%9fE#fuk(g@rF)zI^rS)$7-<-@JMA z_U+qu@7}$C|Ng^=4`Mk9fbuO@*XvT#+9)^=TSblsnO1FIbjyoD_Pf?lbz)1$Cj_A&3ki^zjSZQ;tH p|0|kUwcx<+-@;amig{8W$({aN{-0j`X8{8wJS0+;-!5VB{{bOSM+pD` diff --git a/wadsrc/static/graphics/invgemr1.png b/wadsrc/static/graphics/invgemr1.png index 2bc7b99f4fce5113f1559301133718d43e368056..a7ed50a46441935978d4ce929dc1cff12372322e 100644 GIT binary patch delta 187 zcmexf{*`fpBnKM<1H*=x>5C_)TIkg?a29w(7Bet#3xP1>rMq>1fYOpBt`Q}{`DrEP ziAAXl1&Nt?C3<IYF%e literal 15351 zcmeI3cTf}C9>>?`%$xgo@6LF~hS*}jf|_g!A!JR0KtND}2$5oCNj9*OWJ9t*z=pl| zuGqU`!QQd=-h1!8cjcW;ARL-|@16VS?o7xpXTRUy@0`ym>_0mqI;!389$p>@g8Uv4 zu89HP{{f%>{Z<|P9X2p!0@Gj(PqZV*e`_+IYRJqyPXr0@CUpsPf;JM0Z5wST@I(<%>USZ$| zsy&nr3?wiUG|qFFO%^-mQ1P94F%UD&D4*w)&}k}u5L1wsppE8*P&R@m6Z#AEBC#J& zt`Lf4{&I!9HBSP5qoM#*A`*xcm`sX^B)sB_ul4|u(q=GXF`BUAa^RPWpGwnK3`MiD zvV>VuA!SQJ#R`Q26-iKuL;w^5d$xtf9RiEp+m)mwkA|@8ZKRbZDGQIuizibVw2IGX z3c0W1aha{|LKb^5J3tY2;8s*D6rq)w40^Z6nqf0JyJpa%go!W{7TOMc;!1tiREnnT zsZ@p0j1t^mAQk(`1pxsHe?fp) zflC93WU0}JJ0WVdu)RWR4W-Xuc1v+;!(U7d*(;>(Xd}T%hnpY`)BC?#qLMTfN`;el zus*Y)bqiLn^DK)c(#y7%+%S>OGs%kE>;$vpRQ!@H=RU;TXB6Xc?pzGlGpCta&uj?7 zphU~GmUheSEVhw=XafWrmTV2wFktcYL%hYO~` z8gsZ<5y1iu7fgdS=5Vnhf(0Bdm;u%;9211PeG^Fb&rDm$*Di-~1yi;B~(&@Lr#2lH3ct6Uftt$7m5GrzwKu z4nmMGMd14hf@FvgZ zOiD_^aXdLWS+Ca{3XJ0~XxQ0>#FPv5?M`}OPBzkmPS+}r^J1`HfHaL}MZg9i^D zGGxfmp+koa8#a9S@DU?Mj2t;~)TmLTM~@yeX3W^JW5T;{`~?dZEL^y7 z(V|6*7cXA2WXaN{OP4KMwtV^W6)RS(T)8qoKY!J#RjXI8UbAM++O=y73JTV(Tep7w z`VAX4Y}~kU)22=FHi% zXV0BGcmDkO3l}b2ym;}_rAwDDU%qnX%GIk^uU)%#{rdGAH*Va#dGpq-TeolDzH{f! z-Me@1-Me@H{{06J9z1;b@X@13j~_pN^5n_Wr%#_fd-nYK^A|5(ynOlc)vH&pU%!6y z=FQu;Z{NLp_x}C+4<9~!{P^+Hr%#_hfBy32%h#`8zkU1m{rmSHKYslD`4cST;5Lu{ z02`nh9TOFcw0(Hl2!6;SG(kGYRpp6-KM>Jx)eAO{lYXP}{uRD7YO)zw=JV4lZtThQ p+H-w!l1>kZTJY~wGI!^V`bb=1HN7#``Wz%cB0{4ytAmpU{vWoQOt}C6 diff --git a/wadsrc/static/graphics/invgemr2.png b/wadsrc/static/graphics/invgemr2.png index 507548bc338a6df68cc94f58c7b674cf9706d8ea..e6912e21a175124a6f707bb9a9b7241935a08ccb 100644 GIT binary patch delta 189 zcmexa{+)4xBnKM<1H*=x>5C_)TIkg?a29w(7Bet#3xP1>rMq>1fYOpBt`Q}{`DrEP ziAAXl1&Nt?C3< o6bpSy10xD zHJE@JL6rVh6HcU)j3Ajzp^SdQ*E{wI1(eoL7%$gIG^QXjl?ux-lQB7wu|!Tf;j0z; zt6Y>;3?wj+3@)%5^hOJ2^%L6iVjyOlQK7&lVbcACfowrRf+k83M4L&0T=FShPB%tQ`2}Cro7+6NaK$ zSy|#NPcdyyL8ZRFzNkco%48y-5LvQ~3~m(}E$;Rt<$2Vkg)mblhN6uEHZPt`XE1(3 zAzR4tDjS!<eLJf;k@-qtlOfs%UCKpGhf@JXxnnNn$n zwxrTElyp3Stm!I@wv?$wQ+ zp>)p4sgQ|%Qe)pqD^-JyePXxSmV$kTlwhn_keS38+8j&MdX;^ZMU^8I1O?evm7q;L zWz^DH77ry_+2WjUXEsueGo%WvN4ZEU5y|ASQVAwgU@}QNi4P``KuPS%N;x#NmeOTc z$sxn!3e3wJ&H*Va=K%Xhi!=Bi$^vVlJX!+N(PjhAs3-%TLZT*PiV}4;LQ2P~!h&c$ zZ3f)}!&jo!HA61jO2fj976vyGWVl)d8pIT(#YkLA_$t8WBjiM~NK1NoihLvrg~-Rt zN9Rj=CgU=#!Uj>Jf$ddNt7#&G-7RIQwSO`-WUrFCi|3$5{DGdbok=F#Y$4el=O--Ra*jjHaYnHo+s?&sf<4Vt1iK+f ztrD%!>g<-oS!SdD-wCwmhwL@i$Vw%RzuHjtR5n%3Ni4LE$->QKUEz|N^Y!=_irB;bWg z*}r90_;F=x;;*gn@K%;v{EzVVozTCu@D1(B#i6oE>1+SfX4;X;EZ`( zoQPlnj|-;38S}U}5y1i;7fgdQ=5cW%f(1M-m)nalte=V;&bLB3QuVf@yHZJT6W|uz<$})8LGGT%3qt0gnr&!5Q;q%;Vxj1PgdvFb&R_$Hj>V7Vx-W8k{kYixUwn;Bmn;IAb0c zCn8wDkojRqZr6EXObaXW6Ex4W6y?b{zH;}K;Vga`lL33%{x^?T-t5?5%eOFgkkfA|? z1`QiFY}BYxK^T>((tkK0YBKAu%x#jIl?L9zA>Z?A5DR@7}%p^y!n7 zl!W7Wa&j_35L&I4BuSl4my(i_nwm;c6hM@op03yH4F-eJXryV{WHR;b+t+M114<0T zWMpJyW@dtWj#jHRJ3BikC#PS(e*OFRA249Rz<~n?4H`6f@ZcdshUDhv=H=xL9XfQ_ zuwlc84<9jN#K@5&M~xaadi3ZqW5$dfJ9gZ-apT92pD_lB z#*G^{ZQ8VX^X4sEwrt(Hb=$UW+qZAuv17;1ojZ5!+O>Q4?mc_<6c-oo-Me?+zJ2@m z?>}(hz`=tD4;?ym`0(K)M~)mldi2<_W5Po6w|`t;eeXV0HMfAQkQ%a<=-y?XWf_3Jlp-n@PL z_T9U8@87@w@ZrP9j~_pM`taTTK(}OgJy#iNO*9hx~OAP?*9Nf?nxQ| From 21f089c148a39dea16c3e1f9d8c0d97e228da98b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 08:02:37 +0200 Subject: [PATCH 022/105] - removed redundant content from wadsrc_extra, i.e. all files which were identical with the ones in wadsrc. --- .gitignore | 2 ++ wadsrc_extra/static/graphics/-badpatc.lmp | Bin 546 -> 0 bytes wadsrc_extra/static/graphics/bal7scr1.png | Bin 637 -> 0 bytes wadsrc_extra/static/graphics/bal7scr2.png | Bin 665 -> 0 bytes wadsrc_extra/static/graphics/bfglite1.png | Bin 1107 -> 0 bytes wadsrc_extra/static/graphics/bfglite2.png | Bin 1020 -> 0 bytes wadsrc_extra/static/graphics/bfgscrc1.png | Bin 2263 -> 0 bytes wadsrc_extra/static/graphics/bfgscrc2.png | Bin 2602 -> 0 bytes wadsrc_extra/static/graphics/blast1.png | Bin 2172 -> 0 bytes wadsrc_extra/static/graphics/bsmear1.png | Bin 1004 -> 0 bytes wadsrc_extra/static/graphics/bsmear2.png | Bin 1060 -> 0 bytes wadsrc_extra/static/graphics/bsplat1.png | Bin 595 -> 0 bytes wadsrc_extra/static/graphics/bsplat2.png | Bin 810 -> 0 bytes wadsrc_extra/static/graphics/bsplat3.png | Bin 346 -> 0 bytes wadsrc_extra/static/graphics/bsplat4.png | Bin 366 -> 0 bytes wadsrc_extra/static/graphics/bsplat5.png | Bin 399 -> 0 bytes wadsrc_extra/static/graphics/bsplat6.png | Bin 615 -> 0 bytes wadsrc_extra/static/graphics/bsplat7.png | Bin 229 -> 0 bytes wadsrc_extra/static/graphics/cbalscr1.png | Bin 636 -> 0 bytes wadsrc_extra/static/graphics/cbalscr2.png | Bin 665 -> 0 bytes wadsrc_extra/static/graphics/cbowmark.png | Bin 1680 -> 0 bytes wadsrc_extra/static/graphics/chip1.png | Bin 150 -> 0 bytes wadsrc_extra/static/graphics/chip2.png | Bin 137 -> 0 bytes wadsrc_extra/static/graphics/chip3.png | Bin 140 -> 0 bytes wadsrc_extra/static/graphics/chip4.png | Bin 132 -> 0 bytes wadsrc_extra/static/graphics/chip5.png | Bin 141 -> 0 bytes wadsrc_extra/static/graphics/cursor.png | Bin 264 -> 0 bytes wadsrc_extra/static/graphics/hamoback.png | Bin 831 -> 0 bytes wadsrc_extra/static/graphics/plasma1.png | Bin 1214 -> 0 bytes wadsrc_extra/static/graphics/plasma2.png | Bin 1446 -> 0 bytes wadsrc_extra/static/graphics/readyico.png | Bin 259 -> 0 bytes wadsrc_extra/static/graphics/scorch1.png | Bin 3488 -> 0 bytes wadsrc_extra/static/graphics/twirl.png | Bin 2660 -> 0 bytes wadsrc_extra/static/graphics/xhairb1.imgz | Bin 90 -> 0 bytes wadsrc_extra/static/graphics/xhairb2.png | Bin 128 -> 0 bytes wadsrc_extra/static/graphics/xhairb3.imgz | Bin 116 -> 0 bytes wadsrc_extra/static/graphics/xhairb4.imgz | Bin 82 -> 0 bytes wadsrc_extra/static/graphics/xhairb5.imgz | Bin 50 -> 0 bytes wadsrc_extra/static/graphics/xhairb6.imgz | Bin 72 -> 0 bytes wadsrc_extra/static/graphics/xhairb7.imgz | Bin 33 -> 0 bytes wadsrc_extra/static/graphics/xhairs1.imgz | Bin 49 -> 0 bytes wadsrc_extra/static/graphics/xhairs2.imgz | Bin 72 -> 0 bytes wadsrc_extra/static/graphics/xhairs3.imgz | Bin 49 -> 0 bytes wadsrc_extra/static/graphics/xhairs4.imgz | Bin 49 -> 0 bytes wadsrc_extra/static/graphics/xhairs5.imgz | Bin 33 -> 0 bytes wadsrc_extra/static/graphics/xhairs6.imgz | Bin 48 -> 0 bytes wadsrc_extra/static/graphics/xhairs7.imgz | Bin 25 -> 0 bytes wadsrc_extra/static/sounds/dsempty.lmp | Bin 12 -> 0 bytes wadsrc_extra/static/sprites/AFLYA0.png | Bin 111 -> 0 bytes wadsrc_extra/static/sprites/AFLYB0.png | Bin 95 -> 0 bytes wadsrc_extra/static/sprites/AFLYC0.png | Bin 111 -> 0 bytes wadsrc_extra/static/sprites/AFLYD0.png | Bin 112 -> 0 bytes wadsrc_extra/static/sprites/spkra0.png | Bin 525 -> 0 bytes wadsrc_extra/static/sprites/tlgla0.png | Bin 152 -> 0 bytes wadsrc_extra/static/sprites/tlglb0.png | Bin 152 -> 0 bytes wadsrc_extra/static/sprites/tlglc0.png | Bin 152 -> 0 bytes wadsrc_extra/static/sprites/tlgld0.png | Bin 152 -> 0 bytes wadsrc_extra/static/sprites/tlgle0.png | Bin 152 -> 0 bytes wadsrc_extra/static/sprites/tnt1a0.png | Bin 13 -> 0 bytes 59 files changed, 2 insertions(+) delete mode 100644 wadsrc_extra/static/graphics/-badpatc.lmp delete mode 100644 wadsrc_extra/static/graphics/bal7scr1.png delete mode 100644 wadsrc_extra/static/graphics/bal7scr2.png delete mode 100644 wadsrc_extra/static/graphics/bfglite1.png delete mode 100644 wadsrc_extra/static/graphics/bfglite2.png delete mode 100644 wadsrc_extra/static/graphics/bfgscrc1.png delete mode 100644 wadsrc_extra/static/graphics/bfgscrc2.png delete mode 100644 wadsrc_extra/static/graphics/blast1.png delete mode 100644 wadsrc_extra/static/graphics/bsmear1.png delete mode 100644 wadsrc_extra/static/graphics/bsmear2.png delete mode 100644 wadsrc_extra/static/graphics/bsplat1.png delete mode 100644 wadsrc_extra/static/graphics/bsplat2.png delete mode 100644 wadsrc_extra/static/graphics/bsplat3.png delete mode 100644 wadsrc_extra/static/graphics/bsplat4.png delete mode 100644 wadsrc_extra/static/graphics/bsplat5.png delete mode 100644 wadsrc_extra/static/graphics/bsplat6.png delete mode 100644 wadsrc_extra/static/graphics/bsplat7.png delete mode 100644 wadsrc_extra/static/graphics/cbalscr1.png delete mode 100644 wadsrc_extra/static/graphics/cbalscr2.png delete mode 100644 wadsrc_extra/static/graphics/cbowmark.png delete mode 100644 wadsrc_extra/static/graphics/chip1.png delete mode 100644 wadsrc_extra/static/graphics/chip2.png delete mode 100644 wadsrc_extra/static/graphics/chip3.png delete mode 100644 wadsrc_extra/static/graphics/chip4.png delete mode 100644 wadsrc_extra/static/graphics/chip5.png delete mode 100644 wadsrc_extra/static/graphics/cursor.png delete mode 100644 wadsrc_extra/static/graphics/hamoback.png delete mode 100644 wadsrc_extra/static/graphics/plasma1.png delete mode 100644 wadsrc_extra/static/graphics/plasma2.png delete mode 100644 wadsrc_extra/static/graphics/readyico.png delete mode 100644 wadsrc_extra/static/graphics/scorch1.png delete mode 100644 wadsrc_extra/static/graphics/twirl.png delete mode 100644 wadsrc_extra/static/graphics/xhairb1.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairb2.png delete mode 100644 wadsrc_extra/static/graphics/xhairb3.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairb4.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairb5.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairb6.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairb7.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs1.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs2.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs3.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs4.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs5.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs6.imgz delete mode 100644 wadsrc_extra/static/graphics/xhairs7.imgz delete mode 100644 wadsrc_extra/static/sounds/dsempty.lmp delete mode 100644 wadsrc_extra/static/sprites/AFLYA0.png delete mode 100644 wadsrc_extra/static/sprites/AFLYB0.png delete mode 100644 wadsrc_extra/static/sprites/AFLYC0.png delete mode 100644 wadsrc_extra/static/sprites/AFLYD0.png delete mode 100644 wadsrc_extra/static/sprites/spkra0.png delete mode 100644 wadsrc_extra/static/sprites/tlgla0.png delete mode 100644 wadsrc_extra/static/sprites/tlglb0.png delete mode 100644 wadsrc_extra/static/sprites/tlglc0.png delete mode 100644 wadsrc_extra/static/sprites/tlgld0.png delete mode 100644 wadsrc_extra/static/sprites/tlgle0.png delete mode 100644 wadsrc_extra/static/sprites/tnt1a0.png diff --git a/.gitignore b/.gitignore index a001e38de..e071ea2e8 100644 --- a/.gitignore +++ b/.gitignore @@ -46,7 +46,9 @@ /build_vc2015 /build_vc2015-32 /build_vc2015-64 +/build_vc2017-64 /build /llvm /src/r_drawersasm.obj /src/r_drawersasm.o +.vs diff --git a/wadsrc_extra/static/graphics/-badpatc.lmp b/wadsrc_extra/static/graphics/-badpatc.lmp deleted file mode 100644 index 3f3224f966d6123a718539101a6a8ddbce321aac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 546 zcmZ{gxedZV5JkVSjks*FAh1XXD1jO%fieil$qC2^$dD)k(E|x35LhChi{;PQ_*jFb zH<}&)IcG>Pz#JO@JF+K7awa$OATQ#3z=ABvimb_&9LR}W$d%m5le|gT0{X;|ghV~0 z#RnUCNHG%g$3;zFkwcOKF6EdYLTDtGK`2cRQ1tcD@WO zZ<8VvqvN>mxKpg%&}#8)jG!!N!Yl(e_<9wgw$n~OgGL6K=w_wTI=8G{)@q8?YPqd! F_W@_Vr|AFy diff --git a/wadsrc_extra/static/graphics/bal7scr1.png b/wadsrc_extra/static/graphics/bal7scr1.png deleted file mode 100644 index c3c21519105e3ba99634032f5ad92f47187a83b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 637 zcmV-@0)qXCP)e}v;e6vuNE97h~Sp_b)PfwC-A zDZ&b?EP-%}5C|-5356~Z0wDq-G*k$Ifig)7xhL88Y z@4b1_nZC>2ZddL|pCxyd;Yd~0;Z^VZC(<9N`XAFYCfeZQKXN(HbbIdlzUNrRt#a;i zr5fhL+;zP$^z7;Q=Rc&}nPFPE-lOB^nK!p@2JfJAq1m&*pXDo%kP0QSZyWD^vSK)1 z=tni)uD8`D&*Pare5}_%Cst3A`i>YDCM6X)uojSEvU^TUvA~DNXv?yU zbN1@>61ZVc6EU)81!;^w0HCHHMyToOwh(joW5Tr-e8C%$uM#0`b+M>4Hb#TqIXothn~_UA$2Ll7 znmGM;NhZrIFZN|c9gRg%nK{2subnhl6G{itSKR)J0_ikqt+34>+jDiHeZ9*&%$I`rYiMH z)b45zT>{p8rmaj}0RpHa$I;tBWc<6U!g*j?mW?(O!LT`QiQp42@^NBc6y1?@G?l>y z%^eMn-=QJ1%?hm~G^dII9i&)>@wAj1$@{xK^2hp`?aU2BgFvpoZDtxYU;~}4G?NNp3@7#^e_!lQw$94X*AOAJ8M0ZQCmh(J5KU#-j&w@p!+^@NAKU|35CA44lXx^tK`fV1nM#00000NkvXXu0mjff4C^7 diff --git a/wadsrc_extra/static/graphics/bfglite1.png b/wadsrc_extra/static/graphics/bfglite1.png deleted file mode 100644 index 882211642cf38b9d308e86cf543637c5d94cc1a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1107 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 diff --git a/wadsrc_extra/static/graphics/bfgscrc2.png b/wadsrc_extra/static/graphics/bfgscrc2.png deleted file mode 100644 index fab62b873747c682876564482a4a3f212de9d8c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2602 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 e$VQC||KH#8r$jp=M1^Pfu{XcB zlo3#6A;7>OB_f?Me@nC?ewCU@keH0h@|TATiY!0vjj2>o9#c$t%hUHW)i8vGMX|)$ z&Cg$E1^J+e$qQh0l-#MWZ=UT!5pv9M#_oas(^rlam?JyMgINlDP>PB;MWF~p+4G=> zMlL*dg-~Q#xzyoNpkTozpi!Q`eZM_cYn&K@;7Wb6O62EVUvTj9Y!fVTsf?849KFj* z{f|9;aQV`nTw?;!8{hwS|Fs{#UpB66B#;;lS`VIl_v`<&Tl4lsD&SWt*|FsQn=ikA z-rroC5$B3msaN;1W4o`t{dBOWFwWoNOD#Vw z*OTnD?y=WD@Ogjwe8Dk~sHiY7$0^WWD+L0$U?xX9I@~2HG#YDt!GL>XQO7u8(tjZI zVmC0rEgUqAm`GE1LxL9=N$u;N(TucKxr3q0B{%zfvV*~#KwIF2vj|TQ#aTGu|G0*8 z{GAZu4Te(H+C+070BP#9kCP(v}G^->lSwSRbc@N-!$)eJwI$d_Nlk@nfD90vfR zOR_YA)Nuef394)AOaysg*(c3g4e?(%aeIhpE>$Jt9^%ru9#BITAMP zP&{MG`R-{r$l7W ozMatKvzWd}XNWY?I05YW1ETNfcV}|INdN!<07*qoM6N<$g7VpSO8@`> diff --git a/wadsrc_extra/static/graphics/bsplat3.png b/wadsrc_extra/static/graphics/bsplat3.png deleted file mode 100644 index 5d9ad06ca225a12e250a6fb1f4fb5018cc09499a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 346 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9Z0VEhClN3FG6i0fIV-ko4VxHYqSv^3SAu%T) zL+ap3Ad8XF)5S5QA};hIqYHDQMEl3%YkU37djqbAaF@1rE#}*tGIL6Xq;Sg$KOs(K zj!7C!n|K-7I68VUxV33>CgaT8`;A4?{@5x61$|8Ucu03n&cY)MkJ>-| zet7wq$0_TKI=h)IF7A839@E~HQMpUJHLv8`n}~C+$!X8!-iN(yoRQgLR^J^n|8`4? o>yp5$`zNovqODmHF<0Xcb7Y;Pg+;_$X;8p;y85}Sb4q9e0HXAW9RL6T diff --git a/wadsrc_extra/static/graphics/bsplat4.png b/wadsrc_extra/static/graphics/bsplat4.png deleted file mode 100644 index e9ef345a8af1d33e0758e91bcd28429f5ed71634..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmV-!0g?WRP)pDp*N2fTpuVs03v z5~7=W!P~TKr;9q)-P276rXGAbFG3F@$at~<3}C{EIjK5GB19mu6NqqK-mp^>qfZB5 z4V!h!iEsdz?Fxo5RJTp02mO> zrDhSDD?DbQhG;UL3R6dy)j7XTgASDJ{FmW2P|`5h)J_jdUFt0RFM+Q)(H;K;lK=n! M07*qoM6N<$g11eSu>b%7 diff --git a/wadsrc_extra/static/graphics/bsplat5.png b/wadsrc_extra/static/graphics/bsplat5.png deleted file mode 100644 index ff822df4ca1af57eb888bbc4b51225eb39359443..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9e0VEidGaM{{6i0fIV-k?&1Y({xDQ6oX&5)QA zkRf&OB#^~u=IP=XQW2Nzz@VvK$riF8uy&t2OK8U7>*w{K3NSJ8#C*&BK3$n*$r7if zJ9L<|Nr~RW9QyI4SV((FgMqnJ<}V=6aVi|<;}_WqvFNV4<0zMVAjsOpv#Bt z_fLzhtE>-q+QomP!g}q5=KcH68oai(_de||p`vo&XzIoXrzg++6qNaoCt-oqii4>S zH~lHtZ#td9#YLsOte<6iP2wUOab^~S4O8~n=Nveou>O22M~CbFJdrK~0|l3sGqdGF rRxfHXWoa00000VQf%n8o|i`0006GNklA!pF7cq94yB zSWgy0`b9{?EQ`z3Ik)pSe}XuIAPoEu(#UPMKB>0-Mg`DnA+2>}DEA6}zs^7^cXG->qFTdja& z{?$i&HE9wrQfq#*bBd`1Bp5nDI8?3Q@zIWn`&l;ts!$#^lz#SPE6G9x0O3%FrFXuh zGq+7RB0Tyvx9(L(WgInf*&QLGQ9uKogaGv`e*k@Bb}v($u`mDt002ovPDHLkV1gPK B63qYr diff --git a/wadsrc_extra/static/graphics/bsplat7.png b/wadsrc_extra/static/graphics/bsplat7.png deleted file mode 100644 index 21f33724e551ad4bdaf28ef26f648452e0ec5a8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^d?3sLBp9rei+F()M|zQC5|9QdVh_uBkOHI`5_1AF zqz;}0F?&2+978JNk{KA;IN9{rST3yCxK+%ppjh4}BCmHsepKDgPDairASWqMTHIOR`}!MF0J=%=5RBfPr$8PC~D=o~qApy5GuL9+&fP_~*> SkD+KL$YGwYelF{r5}E)ZV@-?z diff --git a/wadsrc_extra/static/graphics/cbalscr1.png b/wadsrc_extra/static/graphics/cbalscr1.png deleted file mode 100644 index bed27db98b1b28443e68a7c2d69f0e4cb7a161d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 636 zcmV-?0)zdDP)5 z6k&x`mOwZ~2n3e3ghH1H10ez;G*k$Ifig+L-Q#?Sjc z?^o+WS5l|bk=m`Vk~;Emq$tYprhD~;^aqOe+c5NrI_UjFt_P}S%^d(-+tlynOP3o( zH=gE>$*N3njND} zO~9k5abzwbVtY>c>BKp$C<@q~CNnXTJIh_*9cD)^0OkB}pjE?gD54ZI2yvFb7MvqN zc(X!;*YUGJH<}Y+!ZJ2Aj`?_H8R8ipPqv)OA^l6 zyVu*xYxXh`Evu#%$2f%{s&jPAH!h*|CUr&vbrsvmiX7t=r7$6s5>iuW|N2-;-zDp^ zqHpOCgfLBmrFvfF*nxB%(kep;1<~dZS)DVwg=Iqb%^|PYj^%V=s8Z`JElT2wq_`-S zUgq1wi^Gxi7qGwh(joW5Tr-e8C%$uM#0`b+M>4Hb#TqIXothn~_UA$2Ll7 znmGM;NhZrIFZN|c9gRg%nK{2subnhl6G{itSKR)J0_ikqt+34>+jDiHeZ9*&%$I`rYiMH z)b45zT>{p8rmaj}0RpHa$I;tBWc<6U!g*j?mW?(O!LT`QiQp42@^NBc6y1?@G?l>y z%^eMn-=QJ1%?hm~G^dII9i&)>@wAj1$@{xK^2hp`?aU2BgFvpoZDtxYU;~}4G?NNp3@7#^e_!lQw$94X*AOAJ8M0ZQCmh(J5KU#-j&w@p!+^@NAKU|35CA44lXx^tK`fV1nM#00000NkvXXu0mjfh7>6i diff --git a/wadsrc_extra/static/graphics/cbowmark.png b/wadsrc_extra/static/graphics/cbowmark.png deleted file mode 100644 index d2740050730bc1914555f5bd8830cfa5022dd2ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1680 zcmV;B25E~MyG zR_vrMS~zX*y%lJ`SHD8hW9|itqK5{ulg4cB3ArLfGL1{;UXrAlP9 zFJHpv4}Olm?U%^l80vB@-`8(}Yi!60LW&^ff7z@vVm`^Oow{C%qxCNC{vP4QG}87z zgzH;Xz85VPJ7G-7D?B}>OYA8eHBF|jq>Zr3jKh|LH{W~!%gdFy`lzfpIleYu61XtM z(@lJr;zfJxQv!(OAnCW?d@!+5^p3lW#gdq3Qfa=%*q9$LF{DafIOpG9|EK1aakt+; zfDhmi7bebLjj3}%LL!8e)Q+fHg2@H}-YYPV)<`(KbpdvE9vr|brTu!z3IQX~h~(AO zW^yQyer3Kmg44S<=K$ag*z(+(eElvPe=TqoA$*<;Tb2b&r3hrfQl~ zgZxnAM#!IA#ArOkRgN?`+$XTe)>A}s)!ggtcQ8Bk$b&Z06i@1Ps z1dMS7j2H8enr=8o_1`VjUYt$f!W4qXnWjlQtcyU3P@_PlE+Vx89r7DJFYU!dOhnht z1y9p;Mf!UygTE-Jr+ui-=ldona}Ph1B=s(DKdeAgB5X3ESIG;}t4pQBkPH zJwJ88SL30?fyGNMX&YyKE9zBg0rh-gGKj`0=LxoI@P$Ku)tgm<#ZVMKx?5_3<Z%VJ zw{zu_q5uBo>~bj~a{3%jnq4Cy`67j!xQOLU7iX+)XPgW}?*?iAIBNa>wfYW#u{_3h zE!!VbtWG3sg3%F{rtQlcyFKhv3$k|bw_7jrHvoSu^XV`yU_-tt&`AhkV(I^Vd8xlx zX+emb)}3#Fui=rDM5H1%vQ0p~PIw7IrtU#TPE_sLoe*GWnyqm=q-Yx$%GA4L31gzj z<)iQK|31=e=yfEq?-meIO9pJyv-;)`?tzb3O=1{ko&mQ*)+!Vsc%`}S+wa=`4L}LFj`GpGhu#p5gp!Co6FwNAMcFVc>6f-aTSc>$FnC^=EvKw z1annNaVLI_<%E-Gpz-b3ozBT@=ykeZ13c6Rp?z=;HcAr!Y&;ytM=%qvttB^ERQq7i zIX(aySq4C?lkx@3glp?X>oRLH7@3#*0Q5yb0fYqfpU;LR1$CmVkZR|87D+K90Bul0 z5BFxmFdSP!RtF=@)2wRlFatbcb+XKYJ~awnWkr#RXL*D>VHT42dN3Q>XUp-lgNs9e zRVFl?$^2fpe-Au68{?Di%9EU_av0T*VPB2l9td#sF5gV!h7@mR)$=ppt?@AaEX(dK a4*myF_E)P0VEi18)w!7DUS3a$0Q)l0>TA>{QH44Lt;)q zhSb56Af~OSi(^Q|E!EQ-c@G%yFgu<*bJBvlJm9TY!+{+g6KaaDGEeDP`)r1Hp3kAm qcOEOwl}LVDqP)RhJZ!@K@Avhuzf&u+Fl{;jGRf1`&t;ucLK6TZc`&5_ diff --git a/wadsrc_extra/static/graphics/chip2.png b/wadsrc_extra/static/graphics/chip2.png deleted file mode 100644 index abb047789393438518e7853f77f75ad9f7e09e54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)M0VEi-Qg5#UQXJ_;j!8h81&Ep7na+{{(hP|? z0U1&UPlA{Ro-U3d6}LpYHgYmJ@Gu!~UcAdWYqi4x{d)~3PDZZq?h>$hmBp4oAa_|Ewj`SkOBp}TK!Uci+`++n=VopGY z)WMS=rm?4sV@Sm<)uS7E85DS!9nZfxY13W4z^_%LQ$*t9QQI9|$5t500*Bq_y eHw7nj9NEt;+Amp{R>ZUbq~Fuk&t;ucLK6Uuh$uAx diff --git a/wadsrc_extra/static/graphics/chip4.png b/wadsrc_extra/static/graphics/chip4.png deleted file mode 100644 index 9768fe3ad141e3c13a9d1f14fab9916be3249a7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)Q0VEjKd|b%_q&U)x9Fu@Fh|M(9XjK=GW=PBl z$dEdC62#Q@ba4!+h+}Qo$jM+Jz?7e+UOeqh!rWJiAH*2vREl}-=G%AMOrtoP*-E=s WMM6sDQ|^joAbp;$elF{r5}E)o3n8Ka diff --git a/wadsrc_extra/static/graphics/chip5.png b/wadsrc_extra/static/graphics/chip5.png deleted file mode 100644 index 421c3f3d23ce6860865649b0a5cdd36a13003af6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H0VEg%@^{?=ang$%lYle}2p0tM?+4Nhi8%oo zQU_0hm?oYsjv*Css>e2R9%0~NIrz5HdUxEF!%w^9dOkESmOQ}mpl0Svw?p5wuI*00 g_*S3kCwIdk?in*=&dB-v=K&eu>FVdQ&MBb@0C!$1&;S4c diff --git a/wadsrc_extra/static/graphics/cursor.png b/wadsrc_extra/static/graphics/cursor.png deleted file mode 100644 index c9ee9b6e3125e54fdca9d5e972b087500da7c9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eO!3HGrSK5O(9O*@lNkEzrh?xQ}sr~}eyFFbT zLn`8?UNYo5WFX`A@y)yg+AG3Ou*PiOvGW$Q#rEYL7417JnoG*oxMzHK`u0Q0MJDD|;l>-PzICnhYrTfRr}D&w=qX>T7z9dI_#JHU9!a7q9A9@nQExA1eDt`I(-zuz0^4F*qF KKbLh*2~7ZAXKRH3 diff --git a/wadsrc_extra/static/graphics/hamoback.png b/wadsrc_extra/static/graphics/hamoback.png deleted file mode 100644 index 4fb21c0539b987491d8d3c9875455fd52852905a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 831 zcmV-F1Hk-=P)X00000Qp)nB00099Nkl@1fv4};&_IXG?G0_TTlzEoXn zOf^pJx!kw*qB%lQ-aQCnc%icoigfxZ)_gS%aM2I>eF}Ct?uW9O_c_R$;C#Ee$9XB` zu{si$Ga3a-*0@iuk_hg~Nt8@!0GJ&TOMY^=08MJwJ?z4_@ZgE%uXHsN9LW;NeF?R? zmz;|z^K*U`8%hTu9^r*nr;9&JUbhz)p=QaS<@1ZU3J0!i7jKahBOiyUJd^Tde9u_m zP4jjrtdJci6)9=q6t?gI_LcKEOXX*hIA!0Pdr5~D>tC`2sxb`*iF1T#e`zYYlA6^H zlu5n6q978?rHji#>0rKp*pk0domktqa(li^J`Q1vLz1aYvLpUe9BibjVB zI%^I)@#K4>JlvZ=mL&iC*?=pjlq2Bhe*7%@=U%v7Q)()Q;BY5~DC39UY(bw%Wv^#C zqVo|4THZp4=M)}mbat4`0hUu1$>bP}Bx<6@3vrQWg2e~j>$Fm7cmoQ8xmzz*jyApx zkUwY7YsT%Z!{H9A-#%OYCkk6 zBw~dCZNRgg&+V9R@VFdbx|BY>#Yh8tjLn*$mSR?4OQK3a|K@m5;lrJSWjW1g`l{I? z7%tlaq*M}@w>$32j+0&H7`1jms~bqtba8|ixEF6Ko|@6V|HgJI-m`mP2(LLIi=XTX zQ{oVatx)Q@2R*i3#CQd0xPxyI)`t3PHIys!n1uYsw@;sVo{#L2mT3A63f#l5l8qdF zxD0m~19zIP=4W(&^XJ0BOUdrlL_#K^n~1=YW2avv%0AC|`w!8S&E(q5P$~cb002ov JPDHLkV1kcjjJ5y( diff --git a/wadsrc_extra/static/graphics/plasma1.png b/wadsrc_extra/static/graphics/plasma1.png deleted file mode 100644 index cdc99eeab698d589b4d36a20cd90cfebd397aaa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1214 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 S$IFud0000u)80%?ZCoPZ3e zgC{{ubx#+^kcwN$4NWb~oB?9It_F@w5)7FZpBW?!R4fk6oRMX~U|Y+`Fv&*sV8o%X PMj$<&u6{1-oD!Meji{s@F#)sK*C=JGy(wdPYsj+ diff --git a/wadsrc_extra/static/graphics/xhairb6.imgz b/wadsrc_extra/static/graphics/xhairb6.imgz deleted file mode 100644 index f730863e0e2ee68fd9c2c9e7b6b9fcc492657aba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 zcmebDb&uj_U}IosU|?VbVi@?tz;b}Wf#JX(hQAE|5Bvk-zYHMq4}=FKe*y7-pz<#V J7#Kbs007wC8`%H= diff --git a/wadsrc_extra/static/graphics/xhairb7.imgz b/wadsrc_extra/static/graphics/xhairb7.imgz deleted file mode 100644 index f059aa31862f1162fb8457b41c336ec48db478be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 acmebDb&q0ZU}j(hLKJX-;lKePW&i*==LG-& diff --git a/wadsrc_extra/static/graphics/xhairs1.imgz b/wadsrc_extra/static/graphics/xhairs1.imgz deleted file mode 100644 index 00aa6541194afc4d6cfae0fec5f63494617dbb0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 hcmebDb&q0YU}azeLR4@7#03%u4mcbDQ9vGu0050=2ZjIu diff --git a/wadsrc_extra/static/graphics/xhairs2.imgz b/wadsrc_extra/static/graphics/xhairs2.imgz deleted file mode 100644 index 0ed50d02de835d212215756702f4417853f594df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 rcmebDb&uj?;ACI{LPiDz_{+d>;4cF*`Geu#0VW0qAo&AD9HIsQeVZ3u diff --git a/wadsrc_extra/static/graphics/xhairs3.imgz b/wadsrc_extra/static/graphics/xhairs3.imgz deleted file mode 100644 index 066b67412aa82de3167dc9a2674d7081ca63158f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 ecmebDb&q0YU}azeLS%3N$T;nLeX9tD= diff --git a/wadsrc_extra/static/graphics/xhairs4.imgz b/wadsrc_extra/static/graphics/xhairs4.imgz deleted file mode 100644 index 8d3036d32072f91a020ee5b6b604aed78d3cd90e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 kcmebDb&q0YU}azeLKJY|zyXE>KoKD203v`aAa#HN0JLWch5!Hn diff --git a/wadsrc_extra/static/graphics/xhairs5.imgz b/wadsrc_extra/static/graphics/xhairs5.imgz deleted file mode 100644 index 482fb8987b314afc96088f564a186860fed71129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 WcmebDb&q0ZU}iuE2Y`Tq0f+!Uw*>wG diff --git a/wadsrc_extra/static/graphics/xhairs6.imgz b/wadsrc_extra/static/graphics/xhairs6.imgz deleted file mode 100644 index 6a996c9208a33a1bfd508a207f0e1085a58afe7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48 ucmebDb&q0aU}0cpU|?VbVi@?xz~JzY;Xeb*0fqx0nFIeA7!NS~IsgEr+6q7b diff --git a/wadsrc_extra/static/graphics/xhairs7.imgz b/wadsrc_extra/static/graphics/xhairs7.imgz deleted file mode 100644 index 520c28179023911953a0395761a8f7cdd3f640af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25 RcmebDb&q0XU}QiC2LK&+0r~&{ diff --git a/wadsrc_extra/static/sounds/dsempty.lmp b/wadsrc_extra/static/sounds/dsempty.lmp deleted file mode 100644 index cb6f1d2fce47a2fa04b442fe289b50d7e3ffbb40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12 RcmZQ(5Y%R2U|?tf0ssen0z?1+ diff --git a/wadsrc_extra/static/sprites/AFLYA0.png b/wadsrc_extra/static/sprites/AFLYA0.png deleted file mode 100644 index d12ca16c6edf797071310cda019fc11b2cda34b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y<1R@_u^>qR%&H$efR~8nQn3$N!lP9Mhy!ss| z$XF8O7tG-B>_!@pBjV}e7*Y|(+Q7&O~l+|Ci?V_d^9(;+D0I#7hc)78&qol`;+ E02=!mga7~l diff --git a/wadsrc_extra/static/sprites/AFLYB0.png b/wadsrc_extra/static/sprites/AFLYB0.png deleted file mode 100644 index 6f39e47d44e8077858d48c7e0107a71b9bd2e354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y@2qG2r+P(uRwg8_H*O-`?$&)AN>HL!giimi+ pIEGZju^wpT0rDC){Lys!E5)#gVc}`N>9>I*44$rjF6*2UngFi+7&`y} diff --git a/wadsrc_extra/static/sprites/AFLYC0.png b/wadsrc_extra/static/sprites/AFLYC0.png deleted file mode 100644 index bc2a9a37163c841d59f34b5105af4e75fe70ecb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m}3?%t)JlzhYI0Jk_Tv=FHVq#(@PoA85@alJ< zAY)08UoeBivm0qZj)zopr E08Q~5?f?J) diff --git a/wadsrc_extra/static/sprites/AFLYD0.png b/wadsrc_extra/static/sprites/AFLYD0.png deleted file mode 100644 index 8509a127daf5ecf1499ddb04c0cba0447e3ea238..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m}3?%t)JlzhYI0Jk_Tv=FHVq#(@PoA85@alJ< zAY)08UoeBivm0qZj;N=LV@O3D>j6eiAn(uySJSSG{n3n17#?1ANWK6RV(@hJb6Mw< G&;$UTkseF{ diff --git a/wadsrc_extra/static/sprites/spkra0.png b/wadsrc_extra/static/sprites/spkra0.png deleted file mode 100644 index 9af2d4d8379d36be6c2dc1b047964324f619e756..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 525 zcmV+o0`mQdP)_!uO(f<-uhgaIl^c?Sst zu4K=By*^gJhl_o^g?~Yy*wstY!2Tut02dqBPU(zzen8U42x$Y6)A|^3Qh|wCz2>;s z;v2ZK2p`S>6j3oLDFkfF zBs>9TP3%Ji=0NPjj390|H~^RfTu8%MOBU`#uB5KLHePRbjb* zeNg8dHxar~9^_wWFjpPV0}w zL#wSEy3FuTb1EO^=5sq^08k46jEvYv28K)n7)yPOY9C}KHi)$7>wuFAzOx@PoSt}H zt3L>2^B!Iz973NW=lPiEs>Q*Q=A)<;1;fk5faC6dleB8T4@k;Y%p`sQ+#KmBmV(^< P00000NkvXXu0mjfql(+x diff --git a/wadsrc_extra/static/sprites/tlgla0.png b/wadsrc_extra/static/sprites/tlgla0.png deleted file mode 100644 index de3dccc3424a9cf5512e8487cffaf4517c7ad662..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^QXn=XGmz{Jf3prqu?6^qxc>joP|v_{CF|ECpa@5L zkz*1_8Ax`rKMzRE($mE;gyVX00t4ggc`0mc%NK~TwY~6km=-?4fw_6&`C>MX2PQF0 rDtk;MB!2AWX;`DB(0#d>(?y6Oj)`;mf15-rpdk#Nu6{1-oD!MjoP|v_{CF|ECpa@5L zkz*1_8Ax`rKMzRE($mE;gyVX00t4ggc`0mc%NK~TwY~6km=-?4fw_6&`C>MX2PQF0 rDtk;MB!2AWX;`DB(0#d>(?y6Oj)`;mf15-rpdk#Nu6{1-oD!MjoP|v_{CF|ECpa@5L zkz*1_8Ax`rKMzRE($mE;gyVX00t4ggc`0mc%NK~TwY~6km=-?4fw_6&`C>MX2PQF0 rDtk;MB!2AWX;`DB(0#d>(?y6Oj)`;mf15-rpdk#Nu6{1-oD!MjoP|v_{CF|ECpa@5L zkz*1_8Ax`rKMzRE($mE;gyVX00t4ggc`0mc%NK~TwY~6km=-?4fw_6&`C>MX2PQF0 rDtk;MB!2AWX;`DB(0#d>(?y6Oj)`;mf15-rpdk#Nu6{1-oD!MjoP|v_{CF|ECpa@5L zkz*1_8Ax`rKMzRE($mE;gyVX00t4ggc`0mc%NK~TwY~6km=-?4fw_6&`C>MX2PQF0 rDtk;MB!2AWX;`DB(0#d>(?y6Oj)`;mf15-rpdk#Nu6{1-oD!M Date: Sat, 30 Sep 2017 08:07:45 +0200 Subject: [PATCH 023/105] - Restored the original dssecret sound for the main gzdoom.pk3 as there are no copyright issues with it and the replacement was just ridiculous. --- .../static/sounds/dssecret.flac | Bin wadsrc/static/sounds/dssecret.ogg | Bin 26399 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) rename {wadsrc_extra => wadsrc}/static/sounds/dssecret.flac (100%) delete mode 100644 wadsrc/static/sounds/dssecret.ogg diff --git a/wadsrc_extra/static/sounds/dssecret.flac b/wadsrc/static/sounds/dssecret.flac similarity index 100% rename from wadsrc_extra/static/sounds/dssecret.flac rename to wadsrc/static/sounds/dssecret.flac diff --git a/wadsrc/static/sounds/dssecret.ogg b/wadsrc/static/sounds/dssecret.ogg deleted file mode 100644 index dd55ed15803094f5b5ca7c2b5705ab6c29b25689..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26399 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ℜ~QQ zB?WNH6Ex=Q8h*bzbN)EGc6vL)9XR3rx-*wRb`M6r>BFQ}z zsy*4b+-vRP!^!N())_s8L1>3RWvbk*3EF6iezx-=R;EDJQnQiS#)euY>_k5)5*HAxXY=WWojYhFwb3QCHCuh!-V;W0F{t}n zF)|Sx1&-n+i@Y{ak_rljVdQ*!S92*$#oZ64SnN7fLw_gNMz0^QsEWJ0+5SA7h>bN) z>*B!!Fp&3V#4$COY0c9mW_lNH=+(cvxSp`vKo<_@Jg>Kh&?a2?HFU<2?o|*LGX9l9 z)S45Y>0f_18GO-3ju(NG{@1B%EfnA|7?!ys;uwcPcDFB5c423ZcDsnZ+Fw+h;7@7& zn##Lq;o3@EZtN#He8AB7sd@g`vCdnGvhxKQ%=EL>eQ19UOH7+GF=idCE+NBJQe5rJ z(ZZ-af7WqKpW|BPbwc-((!TB88;Yu!VmkACpyEs43IS?=Ow-M?e$SkEffl}hMk0RV z5Y4596b}tUMqbE~1xszZbh%0u-L3sj&V14FT(>8tR@eaNf7f^O+5a@y+Yf{%f+0pD{tES3rOX8Fmx3&BkAsk+7jgQBQc20sW+ZQ9QX?$fV|RsB_>p;Ls{KPAu@gh%?S5b^xVA&p-e0S_=(%?QBGR`#(WDMgJlJ7LS?e0AyIZ zOIH^+#8x>pWQ5hU5lP1euCOpG-_Q$#qr7m24>!_jyv^qoI`cJ~O-ro$lV0DW`w*++TbW~gqeHr6e?fbOyo=RNpv zzr%J-`IYQA`Z!u|^MjX0T{rs=~uyF8ST#m`S#Cxv!7Z0$O zDDoH8q6tV$s+p9H+nzIB8)3IP#+dc^I(th^JXk-TBt+KbvtS47)g}?m^`(^tg;UEd zY`SDeQLkFjz6aSwaD<-z(FvGJRW*orxrV$WFiH<1m#Hw*R{p%K z2FaulP+toaYkl@KwkD$e4Iw$8tyGY=zJN1}(^BpHfEEBJ7u<+RBE0(foflZL?Ta|k zx0i*gd7J#qrtuT@{*MWFWm1_$ta(G06(C*Eo3F)y*|V7v90L&`yM6RYKeG1i#B+qQ(N~1 zj%x%dfb-8^_Rcz zO*sZHX6?j5*CC<)L*4e%boJv#f@-J#xcwXHv4N8EKZx)*P-4>+Y(j<&_3Bu9|7b%R zti$8N5cU%rjdXts0%`5sIEqDB1wR(G)A<3&-Sq%5=+1m1niR>>p2^}B_)7xZ1rY3X zsO$qXbIz%$*Cm3tm9pYYQ{|@c5IT<>lpMSC?D?!>*4xuud8Jw_01R$?1UXGt({cxq zOJ{dY5B`ctm;3@~Z}*cda(}=OI=aVV*NO1HgV{(kJLlc@-9ydM;9O7<{ENt~LzJ)o zb@0DF@&6-ZS$`C^jX{Gob=EeMl@)$!ml>dm$#6L~GFLiB-(K*e*y6F~MbNgpD54?Z zN8??AoXXs1H}_~xAKxx7$fTF5x1O!%5Zt2PQ%xe7jgYOsXMU&_%f2X_ZR}XdSxqwMW}Sz3RMt6W1HCE8z6ng z27_QCE#cXrHc1RFmiezV0yiH5m}Dw%%2h{WL@&cap-ap4oUFkPG0w2!P`M0a|}J3IG5A From c22c93dd5112fdbcc7470a43cd7b6119d56833b2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 08:09:27 +0200 Subject: [PATCH 024/105] - the pistol icon was a contribution from the forum and also does not need replacement. --- wadsrc/static/sprites/pista0.png | Bin 150 -> 297 bytes wadsrc_extra/static/sprites/pista0.png | Bin 297 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 wadsrc_extra/static/sprites/pista0.png diff --git a/wadsrc/static/sprites/pista0.png b/wadsrc/static/sprites/pista0.png index e92b8729551030440e0db8c1324c49fdbf2ea5cb..74ff02360e95494dfa244cb90a2d5f5d570be7d2 100644 GIT binary patch delta 284 zcmbQnxROb+Gr-TCmrII^fq{Y7)59eQNXr5-KL<0A)DJdUJ5f=*-ZH=^#8sT1-P+n( zT3XuK*%>HjZf>rxudlAIuB@z_oSYmT9i5$>U0+|HpPwHd9`5h&@9yqiUS2LNEX+Lh z^Io6^#*!evU9Q7kczn8^WH*Ciaf4?asMvF-~FG&+iNALtKYojm5xS#859;=;zP&b<`@kK^Q?FKeJr=whU%BYVwsq0Uo%41} zFLY)1ZI_GE6wh~@64f+zZmrsUnUPmB=!RXuf>mlo6Y7#aYHMCTV%zj+wc5W+ fE?#qs^ZWQ8Z(%LUV65i`I*Y;6)z4*}Q$iB}Kgwqj delta 136 zcmZ3uWQGr-TCmrII^fq{Y7)59eQNOOQN2OE$)!oRP3qM~>lXMsm#F#`j)FbFd; z%$g$slr-^laSV}|y0p)ci$Otv$^FIu_<4GP8(ak{r2;OlxN}8KbOf9pMm-rJYD@<);T3K0RVd~C8huX diff --git a/wadsrc_extra/static/sprites/pista0.png b/wadsrc_extra/static/sprites/pista0.png deleted file mode 100644 index 74ff02360e95494dfa244cb90a2d5f5d570be7d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^vOvtw!3-qzgH6@~DUS3a$0QI9#C)M8+zWuTWq?nJ zt2jTqwY9ahw6wFcGf>Rj++1H@UtL{YSy?$bIXOByIy*bNzP>&`KR-M?+~42d-QB&s zyj)mVn0e~wy+93&B|(0{3=Yq3qyafyo-U3d6>+`iy@i+*d0YeI{#}T_`#*`d*Gf=V zzj?_kAE%$nn>iVh=kzA7da&(^@I2NH*Ha(V?OA<$Z7lbJJCdhft@3&-csIUs(T{EG zqLn-6?Ur8fOmULOqpjO67o{nl?>Hr@Y3$ruwfQn5uV&BCtMnf0tam<`(Do@ju?eT9m<9&kb}HgQu&X%Q~loCIEHvX955K From b4a84900df446c8011eafb19c46815d58297bd94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 08:15:32 +0200 Subject: [PATCH 025/105] - removed most placeholder sprites. It's better to leave them empty than having some random blobs of ugliness showing up. - restored unkna0.png as this file poses no copyright issues. - credits for maparrows. --- wadsrc/static/credits/maparrows.txt | 2 ++ wadsrc/static/sprites/GWANA0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1A0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1B0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1C0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1D0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1E0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1F0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS1G0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS2A0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS2B0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS2C0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS2D0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/PLS2E0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/amrka0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/iceca0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/icecb0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/icecc0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/icecd0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/minza0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/plyc/plyca1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyca2a8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyca3a7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyca4a6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyca5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycb1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycb2b8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycb3b7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycb4b6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycb5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycc1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycc2c8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycc3c7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycc4c6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycc5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycd1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycd2d8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycd3d7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycd4d6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycd5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyce1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyce2e8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyce3e7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyce4e6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyce5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycf1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycf2f8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycf3f7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycf4f6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycf5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycg1.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycg2g8.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycg3g7.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycg4g6.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycg5.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plych0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyci0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycj0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyck0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycl0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycm0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycn0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyco0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycp0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycq0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycr0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycs0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plyct0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycu0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycv0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/plyc/plycw0.lmp | Bin 48 -> 0 bytes wadsrc/static/sprites/rsmka0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/rsmkb0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/rsmkc0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/rsmkd0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/rsmke0.png | Bin 150 -> 0 bytes wadsrc/static/sprites/sgrna1.png | Bin 150 -> 0 bytes wadsrc/static/sprites/sgrna5.png | Bin 150 -> 0 bytes wadsrc/static/sprites/sgrna6a4.png | Bin 150 -> 0 bytes wadsrc/static/sprites/sgrna7a3.png | Bin 150 -> 0 bytes wadsrc/static/sprites/sgrna8a2.png | Bin 150 -> 0 bytes wadsrc/static/sprites/unkna0.png | Bin 286 -> 222 bytes 82 files changed, 2 insertions(+) create mode 100644 wadsrc/static/credits/maparrows.txt delete mode 100644 wadsrc/static/sprites/GWANA0.png delete mode 100644 wadsrc/static/sprites/PLS1A0.png delete mode 100644 wadsrc/static/sprites/PLS1B0.png delete mode 100644 wadsrc/static/sprites/PLS1C0.png delete mode 100644 wadsrc/static/sprites/PLS1D0.png delete mode 100644 wadsrc/static/sprites/PLS1E0.png delete mode 100644 wadsrc/static/sprites/PLS1F0.png delete mode 100644 wadsrc/static/sprites/PLS1G0.png delete mode 100644 wadsrc/static/sprites/PLS2A0.png delete mode 100644 wadsrc/static/sprites/PLS2B0.png delete mode 100644 wadsrc/static/sprites/PLS2C0.png delete mode 100644 wadsrc/static/sprites/PLS2D0.png delete mode 100644 wadsrc/static/sprites/PLS2E0.png delete mode 100644 wadsrc/static/sprites/amrka0.png delete mode 100644 wadsrc/static/sprites/iceca0.png delete mode 100644 wadsrc/static/sprites/icecb0.png delete mode 100644 wadsrc/static/sprites/icecc0.png delete mode 100644 wadsrc/static/sprites/icecd0.png delete mode 100644 wadsrc/static/sprites/minza0.png delete mode 100644 wadsrc/static/sprites/plyc/plyca1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyca2a8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyca3a7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyca4a6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyca5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycb1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycb2b8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycb3b7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycb4b6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycb5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycc1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycc2c8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycc3c7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycc4c6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycc5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycd1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycd2d8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycd3d7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycd4d6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycd5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyce1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyce2e8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyce3e7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyce4e6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyce5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycf1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycf2f8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycf3f7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycf4f6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycf5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycg1.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycg2g8.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycg3g7.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycg4g6.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycg5.lmp delete mode 100644 wadsrc/static/sprites/plyc/plych0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyci0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycj0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyck0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycl0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycm0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycn0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyco0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycp0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycq0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycr0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycs0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plyct0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycu0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycv0.lmp delete mode 100644 wadsrc/static/sprites/plyc/plycw0.lmp delete mode 100644 wadsrc/static/sprites/rsmka0.png delete mode 100644 wadsrc/static/sprites/rsmkb0.png delete mode 100644 wadsrc/static/sprites/rsmkc0.png delete mode 100644 wadsrc/static/sprites/rsmkd0.png delete mode 100644 wadsrc/static/sprites/rsmke0.png delete mode 100644 wadsrc/static/sprites/sgrna1.png delete mode 100644 wadsrc/static/sprites/sgrna5.png delete mode 100644 wadsrc/static/sprites/sgrna6a4.png delete mode 100644 wadsrc/static/sprites/sgrna7a3.png delete mode 100644 wadsrc/static/sprites/sgrna8a2.png diff --git a/wadsrc/static/credits/maparrows.txt b/wadsrc/static/credits/maparrows.txt new file mode 100644 index 000000000..193d3d330 --- /dev/null +++ b/wadsrc/static/credits/maparrows.txt @@ -0,0 +1,2 @@ +All content in /maparrows is from the Doom and Heretic source and licensed under the GPL. +See licenses.zip/gpl.txt for details. diff --git a/wadsrc/static/sprites/GWANA0.png b/wadsrc/static/sprites/GWANA0.png deleted file mode 100644 index eb8275dc39f3e323ad4cf7272fca20be1913bbff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHX4@tBDIv@&?kJ1s;*b z3=G`DAk4@xYmNj^(8SZlF+^hO(mqEn1_c2o_ZR=;=jjD*a22SO3b?r9&J{J)MJw-| o+q-m+?-U~|rrn$h6aMqdTC<1<1Piu(2I^<>v~CdL2& diff --git a/wadsrc/static/sprites/PLS1B0.png b/wadsrc/static/sprites/PLS1B0.png deleted file mode 100644 index 9f5787ee12435f57040e6249ce1e4cd2acd57666..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHWtF-B{kP3St*{L>4nJ za0`PlBg3pY5u&o67uA|enh*!CHypTX1B&t;ucLK6T5b0$>) diff --git a/wadsrc/static/sprites/PLS1C0.png b/wadsrc/static/sprites/PLS1C0.png deleted file mode 100644 index 2bbbdef7b3aabf2409fed799e963ae6b8d37c738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EU=n-8*G&boISV`@iy0WW zg+Z8+Vb&Z8prDDTi(`ny)TMonTnq{VOztoK$IsIX+~6uuDHU*W#hoi^s*6_MIk$J| l9^WZOR!qA&6(;=Wm$haQ5eOD+`wZ02;OXk;vd$@?2>>v~CdL2& diff --git a/wadsrc/static/sprites/PLS1D0.png b/wadsrc/static/sprites/PLS1D0.png deleted file mode 100644 index 9f5787ee12435f57040e6249ce1e4cd2acd57666..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHWtF-B{kP3St*{L>4nJ za0`PlBg3pY5u&o67uA|enh*!CHypTX1B&t;ucLK6T5b0$>) diff --git a/wadsrc/static/sprites/PLS1E0.png b/wadsrc/static/sprites/PLS1E0.png deleted file mode 100644 index eb2dae650c4ed1b1f185b31219c086271022eb53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfV3nKi+r8t^8!e77I;J! zGca%qgD@k*tT_@uK@(3G#}J9BOZyzT7!(AU++X~UpQjhN!BwDAD&XRZJ6F_H7p=T= oZtv1PzEg~>n09k2O!&_)Yt14e5G>gC8K|GZ)78&qol`;+0Dh1si~s-t diff --git a/wadsrc/static/sprites/PLS1F0.png b/wadsrc/static/sprites/PLS1F0.png deleted file mode 100644 index eb2dae650c4ed1b1f185b31219c086271022eb53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfV3nKi+r8t^8!e77I;J! zGca%qgD@k*tT_@uK@(3G#}J9BOZyzT7!(AU++X~UpQjhN!BwDAD&XRZJ6F_H7p=T= oZtv1PzEg~>n09k2O!&_)Yt14e5G>gC8K|GZ)78&qol`;+0Dh1si~s-t diff --git a/wadsrc/static/sprites/PLS1G0.png b/wadsrc/static/sprites/PLS1G0.png deleted file mode 100644 index f2405f0a9f246013f5ee5e69481f7e4645849400..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfV314i^W)kivVfP0*}aI z1_o|n5N2eUHAey{XyWPO7$PxsX`dq(gMt8)`-}ha^Yj8YxC&HC1zcQl=Zc!@qLp{f o?OnRZcZ!h}({4_M3IF+Jtyx3_f(6??1NAd_y85}Sb4q9e0MWZ8&j0`b diff --git a/wadsrc/static/sprites/PLS2A0.png b/wadsrc/static/sprites/PLS2A0.png deleted file mode 100644 index 1a8e66a042302327b6196f13174d7f5ed95e6797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHXS@ulu2L6-aXyctjR6 zFmMZlFeAgPITAoY6Hgb%5Q(Wv`y9C#6a<*uU;K}srx&=vRiIKT;NprqSJYG&t-Nz? n@6tWKQ;e*bc5^CB_|GqE%_1TYEZFuLsGq^p)z4*}Q$iB}WpyV_ diff --git a/wadsrc/static/sprites/PLS2B0.png b/wadsrc/static/sprites/PLS2B0.png deleted file mode 100644 index 021d5a581202d7222a209d513e337825fe0519e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHX*m?a6%G&p?{9z$3Dl zfq`2Xgc%uT&5-~Kns~Z6hDc0Z+ULl{pdi5H{^Ec9JiWjTt^$=(0T)-?xuT}JXyu)A mdzbF=|Z6{wU7xVYlZ6*bjGEAO1! nyL6B56eBC9-JA*&{`1RPvxo=;3$}d*>SyqD^>bP0l+XkK&DbT$ diff --git a/wadsrc/static/sprites/PLS2D0.png b/wadsrc/static/sprites/PLS2D0.png deleted file mode 100644 index 1a8e66a042302327b6196f13174d7f5ed95e6797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHXS@ulu2L6-aXyctjR6 zFmMZlFeAgPITAoY6Hgb%5Q(Wv`y9C#6a<*uU;K}srx&=vRiIKT;NprqSJYG&t-Nz? n@6tWKQ;e*bc5^CB_|GqE%_1TYEZFuLsGq^p)z4*}Q$iB}WpyV_ diff --git a/wadsrc/static/sprites/PLS2E0.png b/wadsrc/static/sprites/PLS2E0.png deleted file mode 100644 index d8700f9bd5cf2bbfa93bffc7731412f71252e76b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHXGEak7F?DI5BNu~$0F(QR|MBzm0ynq{R7wS0Tyf`$n(CsJch2oy my2p2lkrmT!PK62o`DLwHLgTe~DWM4f=29jG diff --git a/wadsrc/static/sprites/icecb0.png b/wadsrc/static/sprites/icecb0.png deleted file mode 100644 index e38dd6872fd77722c810d96a538a20449ae9af29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHW%*vtO|&-wLET3p^r= z85p>QL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@06cgmQL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@02YHLfB*mh diff --git a/wadsrc/static/sprites/icecd0.png b/wadsrc/static/sprites/icecd0.png deleted file mode 100644 index 0a07b1a3508c827bf7636e407651d4ba394a36f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHV^bixtId0cp+xkH}&M z25w;xW@MN(M*=8l;_2cTA~AJopCcE8f&i2Ii~sTS^a3}y3RFr3TwHPIikj-8m3PkV nUAo72ijfu5Zcc>>|M_LDSwsYa1=~IY^)q<7`njxgN@xNA#$hG3 diff --git a/wadsrc/static/sprites/minza0.png b/wadsrc/static/sprites/minza0.png deleted file mode 100644 index f413f0fa9d3d75323c7fa2e844b31918a4e9b70f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHXT0E7p8nr~#xo3p^r= z85p>QL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@07(cZ0ssI2 diff --git a/wadsrc/static/sprites/plyc/plyca1.lmp b/wadsrc/static/sprites/plyc/plyca1.lmp deleted file mode 100644 index fe9e627a28f7bfffcc9e516280496b9dee25bdcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48 ncmd;J;9%fqkY>ZN diff --git a/wadsrc/static/sprites/plyc/plyck0.lmp b/wadsrc/static/sprites/plyc/plyck0.lmp deleted file mode 100644 index c2ff6c0bb2d5a544d5547f569c106eed6da6e868..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48 ncmd;J;9wA85MaQL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@0C0*YXaE2J diff --git a/wadsrc/static/sprites/rsmkb0.png b/wadsrc/static/sprites/rsmkb0.png deleted file mode 100644 index 42b252fc7b73b8ce851c57c740f4f12489b64077..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHW@n09k2O!&_)Yt14e5G>gC8K|GZ)78&qol`;+0CQ6(Z~y=R diff --git a/wadsrc/static/sprites/rsmkc0.png b/wadsrc/static/sprites/rsmkc0.png deleted file mode 100644 index 1aaf234b55cf133a9b26444bd098a680142cd41d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfV3zOtM_j^@E=HX7I;J! zGca%qgD@k*tT_@uK@(3G#}J9BOZyzT7!(AU++X~UpQjhN!BwDAD&XRZJ6F_H7p=T= oZtv1PzEg~>n09k2O!&_)Yt14e5G>gC8K|GZ)78&qol`;+0G?(i-~a#s diff --git a/wadsrc/static/sprites/rsmkd0.png b/wadsrc/static/sprites/rsmkd0.png deleted file mode 100644 index 1a1e0e418b6e747d159552717eca2266100e2930..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfV40WtCfFbJqe^a3p^r= z85p>MV%)-v4727)00m7vT^vIsrY`MsQL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@07(cZ0ssI2 diff --git a/wadsrc/static/sprites/sgrna1.png b/wadsrc/static/sprites/sgrna1.png deleted file mode 100644 index 9e8fd362535ce62742cb02f24c5eb517ea63a169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHVsbGru#PB?F{63p^r= z85p>QL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@02YHLfB*mh diff --git a/wadsrc/static/sprites/sgrna5.png b/wadsrc/static/sprites/sgrna5.png deleted file mode 100644 index 9e8fd362535ce62742cb02f24c5eb517ea63a169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9EfHVsbGru#PB?F{63p^r= z85p>QL70(Y)*K0-poyo8V~E7mrG1WE3xFIohxdpi&ow_ ow|D6t-zi2`OuIQ1Cj94@wPq0!2o`Mn4Ajry>FVdQ&MBb@02YHLfB*mh diff --git a/wadsrc/static/sprites/sgrna6a4.png b/wadsrc/static/sprites/sgrna6a4.png deleted file mode 100644 index fb0bf70fa09b0adaf1d56cf97694ef873b48c2c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PF}(u*9Epc2g5N6Te_Y|a9Y$YKTt zZeb8+WSBKa0w`$W>Eak7F?DI5BNu~$0F(QR|MBzm0ynq{R7wS0Tyf`$n(CsJch2oy my2p2lkrmT!PK62o`DLwHLEak7F?DI5BNu~$0F(QR|MBzm0ynq{R7wS0Tyf`$n(CsJch2oy my2p2lkrmT!PK62o`DLwHLReI1qWhxu%dZbrE9-Mhm<4UJ+k-(4@^tlcS?9!*&;$SgBuef8 delta 271 zcmcb|IFD(9L_G^L0|P^2NcwRg#gSg*m;|H+fY?Z@dvywsW=VJSb!1@J*w6hZkrl}2 z5AX?b1=4Wv|Nnpg4F~4~`OGCje!-$w7+B9QjRSJ0d%8G=Xq-=-#K_m6z{9*+-{2wh zF?op}2Y>vZePpfcnV!yNGST%f4?H~|`OfyA!2Gp0H*%%FoXf%S#gB!l#i2pKr-6gx ziWduG#AY!Ljvv33I=B?~aNJO8X>`zyk>FsF*xS$$T6Hk!p!lYMe}~pC5^=kDbK3LY zJ%)@?&&9UOd4#(B_%!qQ{7{jAK7-ad$0x8&b)VU`H>REaoPE3m|Mu<}kQX>SUHx3v IIVCg!0OZ|aTmS$7 From b022f6dd8122239d6b73262ee6659d31f1540426 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 08:16:07 +0200 Subject: [PATCH 026/105] - removed unkna0 from wadsrc_extra. --- wadsrc_extra/static/sprites/unkna0.png | Bin 222 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 wadsrc_extra/static/sprites/unkna0.png diff --git a/wadsrc_extra/static/sprites/unkna0.png b/wadsrc_extra/static/sprites/unkna0.png deleted file mode 100644 index ba4d0581ae1952ad58861d80c00d9da3184cc293..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyJOMr-t_=VG*8|xMK$_u<@wUxC z7Gp_}UoeBivm0qZ4o7;CV-k=S0AeGp?$s$kI>*z+F{I*F>*Yo^21OCpi>v68O4?6b=hn0>|S0l-?(*mOBKiWy}>(_?=W_}VPKJM2w+!u!N3yB;K;6!=RT)z z0dr8ug?7dS6?Z_SKPPj#-SUeSF~`{mb%s+IM*CCq|0+3mqVdl@`k L{an^LB{Ts5_~lLZ From e5660e759a0ea1b30b2da0f92bee22afca47fbac Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 08:21:20 +0200 Subject: [PATCH 027/105] - moved amrka0.png to main gzdoom.pk3 as it poses no copyright issues. --- {wadsrc_extra => wadsrc}/static/sprites/amrka0.png | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename {wadsrc_extra => wadsrc}/static/sprites/amrka0.png (100%) diff --git a/wadsrc_extra/static/sprites/amrka0.png b/wadsrc/static/sprites/amrka0.png similarity index 100% rename from wadsrc_extra/static/sprites/amrka0.png rename to wadsrc/static/sprites/amrka0.png From 991dd941afe4f705a57353f059ac0be7888876a1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 08:30:01 +0200 Subject: [PATCH 028/105] - recompressed the dog sounds and removed the long stretches of silence at their ends. --- wadsrc/static/sounds/dsdgact.ogg | Bin 10185 -> 7661 bytes wadsrc/static/sounds/dsdgatk.ogg | Bin 9720 -> 6806 bytes wadsrc/static/sounds/dsdgdth.ogg | Bin 15074 -> 10816 bytes wadsrc/static/sounds/dsdgpain.ogg | Bin 8525 -> 5992 bytes wadsrc/static/sounds/dsdgsit.ogg | Bin 10274 -> 6163 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/wadsrc/static/sounds/dsdgact.ogg b/wadsrc/static/sounds/dsdgact.ogg index 925fd30673f8f6ceb3a32d71c7ef1f066a766795..2ff34e9fe1bf488eb2bdaccd3cd5ecbbae7ecefb 100644 GIT binary patch delta 4152 zcmYjUcRbV&_&-`Cg($KrE0mQZJ0yGWd0BDCp~KleNm2>Po|kntnHOgyBzvB9MzWoA zGR`>TSHJJ?kKgus=H?YDIb6T$3;~C>-?|zoBuhf{_>j_6v1ouXa66+&i%JX_^)gM^>P)_N4VT} zhdP-3-5v+fC`gD&h&{Z0Pap09^+Gs%JA3#D{yT{NZZ+(2DM&E>8)%y7 zs41wpdpf!~JE=H3dsQY+(gWwi`2T8u@$ZU%-me=s`ndw&uR=q^!xO?nQW9h1kqF-~ zAS666AUicaDm;ndIE787eoaz!Ftmbt(5u|_N`Jvx4;oUwuxDX^QY7Wv6H)bh^NB0h z+1&cZ8QwpQg&)UJHy?6K>M8s<@8Gs#xeefWB^dE@HX&W#O=GrgA=e`5+0 zbq|B0cBLlf;33(R*|UeeX<)ldk(#l$OWNE#kr~pSDAQ8Vp=pQb0xxT&bUMWt%8oO$ z;BjAfu>^oeA@Y~H9H}j2r9xy{JiDFoyzc={nB;3NCPSTS`YPKO49$%!1snI@T=7Xv zWao5!e5%%=F??hG461a%_kIKJ$7y@)zhN6>A+l;0!$iEtco}Bp(B`{M^GtfK^K@T7 zfcxrRlzie^9sVfNBZ&B`OmrOG6VMsnDEsN!1AQP*$kA{SdbS)lSyGLeCjW?ooSnUM z*&&^Y4%jZiXq+(gmNK)_qj$cIFf30BvomW_UhEcwE04>iixwzVW+86S8CZgg0JaV} z>zuMWkahE9J~ncDexgePQi(Wy0w;53Mav^6vaM_??X8vI&z2_K2=kb_l=_MhY1J&|kO3erJwpfE z(!l-%Qc+PCXrfRhdbJd3bqDQJJp1b=3~-_HQS&YuS`Nl<+CO6EVO_OW{x0juVqn$O z7{wJ)vFy}B*^o3ujMNCV%TYRAJQ~xN-$%~3G@2KVy=gTG^c@W(89k)nO2|esB-+aF z5VNn9ke|{=q|DTdWTIoJ7_jGA1oA1$vN=J2RixFBnU^6oE9{uY5Z#&HWw#iUP zH0V?D^j#3>8GmC$Ge}tieVI;^^<<)0RJg`|{qf4F?_RlMmKXg+Gp%$D4K|CDs@&Rm zG0ITKqb@vSR!S?^c^XcQtvu|+z-{x}QQwrQ`9DOp*uEX$ZnZt>N=lN2&o1Q320e>u+c$F|#mly~(Fty&Q}a57^F=ZW?wcGF<>Y!75xh zkkmBq@J%)o4zr;De(RO6yNRbYkcvx9kqvc7ibbI-oZyjiUsk&}?WMCrw-$HxvqtNa zWTSY}k#eN&T4LJ{uy>4gc!Noq8`#5};l6UF1Rl}N=hv8Pw=KKH<1jv`nik!)@U9N5 zah6+-W4CXE)RkS4D!P7H>OKQVzEzQEDEY15Y~9hI9DFC7 zZhvAbRO_St?k(D1=DqNWtD#n=4H40X1lxHwH?N7MPV771er-Dd`i52kRE4Hne)k$D7)I^t7CFbdyS&^%zgLSxae8c3&ic+$}AxxIdn0Bf7H2 zfA!k-#++*Mo9+4S-f1G~b$^+RXtsOX5UG7<(n{cqjpAb57trY={QAq3Q_z?;O44w~s}WNs(M`-;+)Rq-)=h5&w3PEQSfGX@?ujN9i@F<&n5pPpEX zu&Hbp^&E%wH3tN+!2&0D!gEQphBcm(OGH24;|(w|*RHmB*+KonZA~4O?N$4U>&6Kx z>OsvT2bLxVQ+W?B5e)3s61?v78j&4WuaE1!yA1-_(OAQowT?loDEm3g?}>ZD#b-t< zOu(7y2u6ReZ#l3wNxV+LOjhAp&L7y=#Ff}7@@>8L<5L@_SHGB>isnatuw>EDKEi54 z!hZF~wPTZ7rFyG|uT@t~O*tJun=W*k6bsfN7Vta;2mj19!FND36wAPKNPi8|kPq4< zP6!d5{o=b5!;boV{@eTw0xziUZ8t50I6zfYIllsfJ%68=wrSz_qZXXbaj1A@@+Kj& zIs)S`9q+81HQYXNv%cbbmZ}*g(uu3g93Rt1A88@N$mo(U``duIHR>YMNYfvgos>#> zTAK==`ftdPhIawuR~(UhPJT~jW^}GpM?>%bbcsy%jTF|pWd)D#W!=_$tQEx5pa94O zblgjj9qv9S>KDiXlFY7OGp#9<=Uk^;qb}r$sF^;7$l{ygPB4AA*E1wSX^SP~=wZo7 zq%*O)MulL}vkAK*0CqmxtUkR~t!@gxQm&53dH^w*g6 z^36PEn3_SGUH|q61q)=jZjPgM2+)Z7$q6zktDjQ4KSR>@P*xD+xTB7}mQvC# ze_832uy4IwZK80JDzrY7ap!qBv&h=mtb5c#1EUfE#7btRFxyl&r#V7XBeg?v6#|Btof~;%1-h!{?(}#M~lM45pUl^E{4_yr4BJO|i z=k?!Im;fVOR(?ppQGfO_osJ2Eaa!3GR%b>EtE>V1TxV~UjwXeJV>(}C?(Gl6;hhWa zU@V*RN>SV0cEzigWR@n8GZvfvw?d5hsoY!WnV_HcCa?%v^8WRhH9(t}FSQ^m&3YfD z73J#HvIyf)+AqCdesBk-og=|;CdAdyQAkZ2+$QtZ z>)UQ$%|)gd)86lOz*AJFB8*M(NIR)#$~afXLi%vTML$VW%Y1!Cscdvt6s}6F9c}h-R&dA-rM|T0iR5&Ah|$5BTRu4=emV+Jju_@63blC zY6h_M*SK~jHl}8%^dV+MDbw0cQJShhGxc*Ljk9##?8H138#}l1zS<^%ZYH$t`c%Cp zB^3iXJ~UUDwG3)?SzgwKEu|?YBZ#FCI{5ZEPA7rpfPB**d?$HmLy&umvR0!8M0eul zn~*RD;Ip_m^1QeS;v^xSTYqI;72jVHv}mb*-`J28i}rXIHTrcZ-y!k+XJFWnUk@uN zQBy_`l}4ub#QLQ)xvaPx=Vct>-3UcqFIs|6p6ko)?l>%v{&=No3BKX-%j`SyFho|_ zp#6&S2#tKSCKv|J1N(I?4F5$|W8a)(0~RVkd3clQ##5Y#!l1ZWukpQ}qjjcwwd^_U zI$axE>FQc3K4yd4obs$qoVD-`d1{FeJfJ$=BAXVmb*q@pRTF9cKE5A}71)EGWAm*@ z-dDT>wI1*KDTOK1!RB$Q$Lma{%@E!vf*RhHuzJ~3`QLWd8NYm~-s_^~1-T_fMnQR? zVW1CdO~ygGP+DD5@#Zsvm{^u>cex|fVZL8_Rx)DZ`E`N2Kyh;w>lv6K!9uO<#j+dN z8;G9gdE!0I`O}o==%&p4>ByF239Eqc4`Z2DKCh*EDFr$UZOhBJ1=W&m$twGA96dao z&Oz)d9zWy$7=Pg1RK)ggCf~K(IUfOtaE#~*l~jX3ik2nk4UX8qU4OZ|uu99%FnaIZ zM-KsbG*3s{PRRDclrJBu=2cH>md?%t{NxfHzD794syahN8dul2&3nVAeL*V-(@=C?qsu(sBBKwm@uWgi zNf1%!w@+@Tbt9l`fGY7IZcc(I<-jM_a1-S*%B9Gfe(Q5P)ibG%yw#Lig@xv?&zv8pH~jp^48B(8CX4~EJhuFs&beg>V3@qja(5l7N*>7 zH?Wp)Q>R#oy@#W`S2FeHqUa&u)$65VU2<2!DXh0$~%3) zW%~DNk)zdEelOSkzWnJ#sD^PpL@3Q+*Z0vN-v5|COmi?~bL;n0qGRc6O@AVJaKBhZeN4xq(MOFjz2E`S|Xu z99imn&oE+|sVO<54cFsscY&Y7q^*fjkpiK{Uk=uMO7Z390=~SRf-h;lN&?QD4%s;@ zd9Bhju4JlXWZWHEe?L_2m#WU1NapT|n~+w{p?+$5nEsW4 z*Osj><+n~Q{01fa}ij{BbvU!X_U=ANn-m6lNQ zLUFD}F^`RNYgkB2pL*j(r*Uj!l08^Qhw@;lTvruxJ|LdW>0e1AO z?e$pcm%9ZQvA-$+*~e)`KKTTs&9WEYtYOC(Ek9drb@s7 delta 6697 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 Q^UX7aN41#fP{0WEA6to#@c;k- delta 6228 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 delta 11623 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 B>n;EQ diff --git a/wadsrc/static/sounds/dsdgpain.ogg b/wadsrc/static/sounds/dsdgpain.ogg index 87120f163630729a9d9d52bc6ee87b3f270761d3..7726bb7dad49ede19ca6ebf2aaaaa604631bb768 100644 GIT binary patch delta 2470 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 diff --git a/wadsrc/static/sounds/dsdgsit.ogg b/wadsrc/static/sounds/dsdgsit.ogg index 91f5419c04c2deb712a108caea31b79a820b57f1..1fc2ddfd0ec69c4baec687f8b0176b978f82241a 100644 GIT binary patch delta 2643 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 B1=|1s delta 6786 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 From 970e6e21a221f71667fad24e558de697371da025 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 30 Sep 2017 12:30:48 +0300 Subject: [PATCH 029/105] Updated Travis CI configuration to use Xcode 9 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7bfb4c527..ef4d7165b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ git: matrix: include: - os: osx - osx_image: xcode8.3 + osx_image: xcode9 env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" From 72e1e869f686d6dd6d1ea246a6dc360f5f47e13c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Sep 2017 15:23:08 +0200 Subject: [PATCH 030/105] - removed the original dog sounds as they are questionable in terms of copyright and there's no reason to prefer them over their replacements. --- wadsrc_extra/static/sounds/DSDGACT.flac | Bin 4382 -> 0 bytes wadsrc_extra/static/sounds/DSDGATK.flac | Bin 2937 -> 0 bytes wadsrc_extra/static/sounds/DSDGDTH.flac | Bin 14703 -> 0 bytes wadsrc_extra/static/sounds/DSDGPAIN.flac | Bin 1679 -> 0 bytes wadsrc_extra/static/sounds/DSDGSIT.flac | Bin 1656 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 wadsrc_extra/static/sounds/DSDGACT.flac delete mode 100644 wadsrc_extra/static/sounds/DSDGATK.flac delete mode 100644 wadsrc_extra/static/sounds/DSDGDTH.flac delete mode 100644 wadsrc_extra/static/sounds/DSDGPAIN.flac delete mode 100644 wadsrc_extra/static/sounds/DSDGSIT.flac diff --git a/wadsrc_extra/static/sounds/DSDGACT.flac b/wadsrc_extra/static/sounds/DSDGACT.flac deleted file mode 100644 index 8d84062c7b87d574d21462735e0d11a9facf7b8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4382 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 Yl`55Ms#PSZDydaf$yF&@>Y|X&j4}o9p#T5? diff --git a/wadsrc_extra/static/sounds/DSDGATK.flac b/wadsrc_extra/static/sounds/DSDGATK.flac deleted file mode 100644 index 2a8353a2d942c2dd3c62db7838431c99505b07a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2937 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 diff --git a/wadsrc_extra/static/sounds/DSDGDTH.flac b/wadsrc_extra/static/sounds/DSDGDTH.flac deleted file mode 100644 index 641458584a20b70b18d8b50cead20771fb4a6c18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14703 zcmZ9yXH-+)6Ynh;FbTyZKm?>DA%u<)iZl^IfP_xyReDFIh=8IJ0)#4|Nf$!zQl%;& zy-9Ckp(K_h@0}NW);Vj=T6@oYzGv-o_IMaLYn?fB1_d|+`0K3BoULYT zfZRND#{9I{;?k}68Xf5L;;La#!KGRep<18yr>&mC>euhr|t!M|#kVqCCO6 zj!34=LnwS9-361i!#kfWR+75Wgp4&^55Bn_cMoh;L@x9`VF$pZemj*c$M8xvK3K0g z$`dm)ulQ?38TA5lCjr6d^NcU%|19hkqj| zlmdb4dZL^>Bl7dVmW|>O+yQW(WuX2DjRD+e4ibOgYYXw zQi=;y7c%!Qanz{OcGB$C(vaTi>(rG0aF05PsB}Bpg=b@gfU}nUD<}t+A8gJnoUL2z zRRgL401sjCQu(!nAs16+2t?J41nmz>c$Mi53dS+|TYBZBqvLb>D`(7VezC{~nkaQU zC5hcg4HUiio-sDwhFfdYSoIFM*1KY+BoY8$7P%*?4^g;E?t7@hFAA%F<0(@l&g&5d79SO^OOH2bj`f>V@!rq- zao3S5t>+iU*!Jm`7$W9V^3SVOPj>$tQ>(g13SropO4|wBv4w`H#|X+ro985dJAsvt zDo3_Nv_02%rcqNPyAO)db4%%)IXYpJS?h0`LX7qQvCALRWhe$SViT3E# z$D@JOE>r0mYv$Px>E@I!au675@yE#90VJ8jQ;4K?oqU>FajH1z|M=myj9+N!M z>cZ<>9aE96vgIZOO_pMoisSW6@h5xsYf#FaEroGX*%LIw-PPhNCD^%~IZ#HCoD zI7lVWPd?2Eg8)vQ347>}ybiN)i6lLazubG~z$_A!%I!B3I>9w%aam4HZjHlk++VYIw4xZ9fU= za$!GcZ!x+EK3d)g^_ zj@|mtYG!O9l~HC6J|!vnaHNMtE~+1(AcnVuqBr!H>A7<$HC36c&R4!%M{HP+RUgtB z$NCH*qahNW_5@;o?v}o3b<6oTc3Rrpn(G8Rceg}G99o>nqMvIk0dL|5`H zG~}8za`)Ooa7K3Lyb1O#mP@n*<8$9oPm^S9cn@QwI}2u8u&kc z86}{x=5l`ow^=9un}?t3kZLS(2ba-I-<(nU*!EwKQ+izlrs6rw6J>__>~g#~s@>H{ zmPYG$dj?rWp!WCNKA=gGrf#tg+R4fRxLOVw)DSCTPvQK*=S6NO(^2=+;S(iEO)rkp z-G{B5zJhlP;xj$s&c0GJ+;7Fq+all`ZqMdm1~1;Ld3e4x+gBpUIGpXiflne`@G1c4 z@lR=~D2cdyVBez;0u&|hJ+iweQdzZ8K2Tp&N<5bW_*otjg^SO-IwQ(jvU&hw5x^2K zfLTB)Ck%V8=N+Tm8Ia`A0RZ#1KLS-%Y60YHs|S}0On!67YT3G$ZnXI1$iDTzKP2FHDW^?2!~@smG653)ZEjl; z-}=yl&%DvEqc(#9t%E5`9Ey*ZFjN1wn|nB2@H;0oeDGy?R%8+TQ`n=3qe}}n!jY01 zP`edLdH(vmsaM_3$0KOiZ4hX9QOB%-q>Q$s6|sQCiPR0;SDCw23U{zl zxU-=wvY|D5dt!zc*IP0Mpm)Qr_uq&7aKiFdl~_9+Z`fpdRdM!#r#-yy`Ay{@FZ^)&5ex!&S{@c@P6ce*OER0;C4g$&x$nhaSR4ke@ zJK}&!cw=mPZv_43TLImUCH(or1Fl9$(c#H!7olfOTz|j^66Gfub6NqcBVLZ?&Gv_Z z*}rafohXjgwVVsN#S`o~^GNF670nS3qzix8-RrsE{o<2>nv5dI2fxGGZ&r9*@F|;) zXXHGm{hm1(Xj)k@7ix>Ta$Nd*wcJL6DFW8sRyR;p(dS=J`L6-kmzb8rB%})Y!k(!A zi@{m^LwdNiT2}BXSPXa#W~Sa3>j6;{(a?v;d02hh5@U@sztsmwJ`Zrz6s$9gS{khH zyP~K68N>@Nh6!;CExq{;3xtb1T-~!x=fw6@G>a>$EpG(;=!@sW8Bi)nBMJV0zCx*sXb%vcnC|sJi_7Zng_KBn#XOVqgGK#4Z<;kS)84sp z{gdih3Fs%2Z_{MT(?6^KvAYUtm0Y{Qq(oy1$}77?UtaqRJ>6)=Iyj)FzOBI`%T5OE z{RG4nOTAvn9AHX(!#?z26v%103~><+G7G=EsbFI~pZvLJOmqsXKP#vDuJtx8+eK7SV$jZv{*HG=RNIBM(h zf3h9O_AJVoKhL@u#$JM~JXjAf@EcD)zFU12_UX;;z^G%(l~W`uqKMp4>H*?ujK7h&CV@!?AN5;{1!SR{IqYXOt@;A#EQUSXGJ-1~y>m7xy1YmA5a7(&ZRZ_eeDg^QQ* zf%bT)EZW1N>!D3l>q}J;x|p)g-N?SGY%;)ETU$auw)W}Uc|eJa`mh1#b?4i7m#e84 zt1K;S!jhBo!<2MY`wdmgKPJ^ea;-N04RPh-yyN z-_v`Ho=H1du=MiJPRkMaltX^aoBDd8yPZ;2dOwBc^qxg*R zxSU%fS4Ia!TVZ#YLGq@pC|2OLlJ{3e34Bh;$4Q5hepca~QvQ~q$`fe>)|B*juC02s zr4GMzy^zQVN$v)hcC}gA&(3(j>n~aD`cc9Y69>+*uVil|)`OO=KjT}^T;lM3^`3mM zufJ*S%l1f7A4$^hQt_5U>d70!ul$D4tg6~|k2l>n@-Q1h^ z<#vfjb*3x$P(R-L&~>wD+xm5+cfm>-_l3}pWPqi)&{bFQA4i{5@ZV|Lqly>gE$>}T zirPhFkDTS4oCO|PSw37X-5XW!vz$r0Mr)r5M<$0Zo8G!QanRlSi}97fA;my*Z2`se;6BYiW^_orhF zmqR6Ye73?B=EaW&shboMoe{=Py5%e}W|{Wj$Mion0wka(=DXjA`3Lj|gsa#l%miB3 z{Ffd#g8pvQoTj;RM7P_GY0Jjnh5PXPrgWXO;N%QK{pEbx-WfrM(TZk zHnsOM?yLy^s9YRl5jbaA#Cj<&_m(h_Hhnj8KV#ZGoj&_*t~#aO?B=u5JEmG8w8mjV z+%|nw+gsS8SCVGB(ZF+@>_1}GZPcZNLdD&}`CP-8*San4pH$V{>{`bqJ-VBV8t4!f^Alafm_Xi%PAt-CB$kq-jJ^f~}@^L)i6zuAly0b$MHv(_3d zcZw=d_w>+G{NQ92OJJK=&kvVt3*>+^=~v7z`ul82%xT7a3&GyPlE*yudb3|6H5$>k zTQM>^(W#Lp_Ez2Fz*eJ#7&aSH$BZ^Aif1MB&9BBl-oyj`ocF3nKiFFDPtT#hH-K2e z#mk`!{I7}pNhW=6kEH~?b}TGJYw>kn@zsexzBY%oG+Ky#bolx8=Fb;D|7hpU&c1Nh z3oc^4>S@XqgrKWpn<&fG-WJa_3Ur7X4>Cs2JqutoWP;su1J6x*UeDur%Br662=L>@ z*DlT@N2Y$2`xJ6^gN zqi#JeZLVGQXj&;qb0z+O!+WStMUdmjRP<*F8r@VRjJ&(81Zkqf~)?^cZ=W_lZ589Jnm6@s$*Ihov*sK6g^0y1iyn^2Y8;95qe#(s{hk#y9=y z8ls(SD+HSf;9 z!7rJ~*)Cuz zDn-YqP7tUYOBUq1#hC&B~gubB7_{7B5y zeB*-e?(x-vOt;YtF{^yhme)hs{SG7f(uGm1=AjXYOVlc83&#b{9u zGk*%9^Fb~fu^#<<-Cow+x8`Yk%%Mr!BgL%NXAzZ`EEJQD-VSzcNcpw9Liys-xcS!BJ$K>GphgEDdjYp!-cNL= z{_LSfRfa2KDLV`Et`GfX|MMl^eYSQl%FHSa#>2xLgIB=|1pbEwUHH!=0~?xhh3vz- z%UE=2_nrqgzm(s;8eAT2$qqODP5eFiAtQv+Mwz8y<CzT4dOvR8_y3d` zldb5N9lqeUbH7zxiB5W0^rq=@cP(;(=dJYJ7yY}}o?3NWP&n+3a`}qdDv*D5{<3L< zT;$o0LNRKEjnq4pJy|Kc`71905qIC)ErQ7p8h!{1E0vI=J>FMuz|Zx<%@g$kWO64B zalzjU0D~#Y{I!l=znU&@z_`gpP7Uj%+aK4lk=eW!Vxvrn00C7}O=;x3TZ4(dXq!o> z+fLk15Fyj*pXQh)ppvA6D_7NxiQGH?36g|+1fzcRg?$5l&=6RjQ+i-`gS(=g@nzwI zNBlaCa5gKQYr+q-5vB);inXCZvsG9YXkb#l&v+)RV|>*^JVv}|=GYu9!+oUt>Zd7& zp%nDNau0&paG$?M?r&2#za*aEDr_UeIM>k|SPjJ&QHe8csC@>EXmH_0b=NsHUc-1` z1xv00?5yJj7cCb(9@_hd9Q*`SGJ)Mmqep|W-W^P~Vz|U5zGD)%w(|`ak+CRNf`6#e zI!c!8mEyxPV@;o(^a0A|I0>}bpYY}4az1%UzXcApsbUEzT*hM20BjP>sTPNHad?0N zD=^GV55q<*##I_mVLA!qm$i*C)V43W*RnK~EN(O<%Ql370^WTKzFsEp48D56&ujk<)cN~dLuA; z#q_%)-P|xQKQUitTzUGU2)je0bTxaDLQk0hZ`vrZ(z8;N@aMxLNi&{oQ=S@m;yR_N zITypEW64d@Nz`TszBoq@&RNHKas=ScVf$mc?ixfoZ5u#tl)9MCAudU-r8jNmXyDiiS)TKg zJJ6a)mR3ZAhQ@0)RoK3!_H^jRRYWCYx%ucrDVE(!t8?t8rGoZ_A&WeXiAVx_bKpZI zb1{uqgTAUOUBY%*=CqHHN>mV(h{*+MMdCQLuEnp>Pv8(p=G`C_t(?1vv4;}(&0b2! z;CS;cH19@9t-pCY<7X1v9rb&uvZqV9uB$GH^fm}${u8zPXGWQTAhb#}ufDfOE80EU zif`NN1#5Dn?iRh4B(9nnN?##cyco2xaZGtQ>_LQR$z9iz(7SJFs`S|xC{Q(A5+CLc zi8SEsV1XTN@MK>9ify@RAqpgH#HBzzYxil0@1MEsl)TyQRsME}`Ln(Hw2UnDXx}fI zzx>3HXjj-?8w1mNe#lY99;-f(aYf5f{`y#oVJgleugVWpAXyl+$yhFUTrjP|@=rPE zB%r#a13`?jsg*TRk&h(&_5tv`#izigGy{WL6WC-yyNh=;`{BGQvkdq)r=KJ%=WSz6TiZbP1k zf6%pQLQweRf6)Db$~2Qv;4`};qRWZ+g?f_|=3+NKr> zleXT8lr$JLl6(3%IDyrIL^WTVd}`)#!C(75dzqj>vt30?lf-1Vj zk#2`~rMGUjaM99F%C5b-7^hk06`A(B|`BgYB9QD>%a z6>(#x@n)Zu=z@1T&E;u_vUL<^%jqu#WUfpRNEui(KDu2UOAKg3*2L*HJQC1P!_mq; zyl$B%BBQuggX>cDR@`X`2JMv}Z&k9G#yQa{DIbTWvlT%gpE12#BTyIk)zcJxe(jRy zxL{lKr`|83a;x$a_ptH-s>fuWt~cC`9)^WBrW^@RoI_1fM#c8$sMyY$J;{N!Cap`u zk!zzTW86DW=a(x+&1yx?5YcEDbcX*yUa?U1;cV6ZA z866LTIcK_G!`k7fYM+m&x*rd$-ywPpZ^>WNGe`u7rkP5cSG23b&&8d~9Q%6oA+KXX zfZMhd|Ju{zn_XG!9qqPPe_mhpqH@Z9{DZlse(%rA8cELIVbQZ|Lpr>gfV4>;_j$r| zRyR!?AVt2fSP`^oO^&ojRPnuTf?{s^+rf!hz}Wu2WPk=Mq=+|SN3$@L^_pyJ{1 zvy6kQvbTgLQyGLx5b_VKn5pRZk>tY181+`dnW|ik2IQxr=!{6P9ZEPE6{DcpMiH;5 z6@{g$<`+YRe5RdoYs1{~@|&^=%JXGav0P}2ITg^hL>uxmjPSKAG3~OM(A&scZ#4`G(AauApu0hFsJoj%-GtQP8}GSXZz#~w)RGn5jfN%4;Kw-Y5L6EV zC0DB_2r}EaQxJn}MbM09whk*I>O8$+Nk2Tv#1%reCXir-bRlf&&zqo0jq&HJ2q7*z z5mF*iA3?U4Ne|Vv7#Ot47ZL7L*b>5L#VmHL8x}E7LS(U0*wTGLqd_NXOuBMnKnKL- zjT<3~S9P3{MZwm6^QMpzzXY=47}%Hczq;Z+I4vvl3>N7?EgK*%MeR>4b>dn%7H%ft z@A8(Ze&?PBoP}s52m$ZQJDf?zlA^t<4A#Q1*e#6oZ+i~;2W`Yp^Akb3+Vk!HVs3R%i;*6;kS%A4IKQ zrceze=&Y{LoKevP29V)1jfJ?z(9tNii0L#LYR!1mCzP_|X6IbX8pf4ZH+{>iF5CfmH-^{4 zc|KexiRlKXUQp;R{q+DijGB9YpFRok!GrL%!=~~ zb~+WZpV+$|@6%`;hDu2&7Oe-D-G8ynyY-*Sl&qu5N(qwafXI}do*@k*Uq7~zp$=p0 zgc7$d0CAlA1;(5@4o5}j{7A|74Vy%OHQNhNYT1QpwRKdBwN^;2fr>(NhbaA0n)HC@ zHm)+x&e>#A_A$@JrHAQ0?nJZj;(P<4a?iks2(HD%!BTBbO{z+BY^P`zLferW866Ox zUN+^4$W?QC@FIv>cQ~w1fC3;?UAiktI~a4{G|MmsD9lk{${sk*YN8`L(RiO;n2=wGi=0eS{xlgeo;PSAYd+P- zQBQI4rl!zRmZK~!q{tw^G++cX=vKlbv#GD12~c1aQN#FrNHowHoh&N;{v_AuhnxI| zG|Q&X!A*Ftm586%?37p72DHI{F88!dSzX;Os#6=1oaH#sCBsRk0FELQWQ0R~h9f}8 zZP)|btEf9m9Z&S4VH_y^1UEet>cGg zhgjt%PjYF?_p{17+HjWnn6DSJ>T?aNny-qn+JQSvN1Zv>R5-P&u$9^>P#xPm^N-t8 zNc*v1Zk3eZ8fkD%lEs1&YwS=JyEz}apD!Pxd{CNI=f)WZ*R6!Rgo=B%RU662wv%q8 z5AX?Doli}7oEe8FeN`#{!vIom>Psj#`DD9>f&82Ah2k z&G0a)RIk&O9s{U|1n1IIruq<1FSlt}-zs_Wq=P?Fm*XeJ*TC}lB|G{nD~|6`abP}H zOG0f66_MvAfTllh9dG5_&}Mz`LmZrP=GxRM{VF!2I1hW0J@!OP+Fx;wOt-q}Ey< z!h2DQ8u`g$h^Cm~wt2-yM%bXe(O1WQD^Fb{t_g}!4V3O`?}yG5Geb%S#l|>7Yge_z zEH$m7XS?t!w=diZ-8={-w-`PuD~tl0*}8g?6X*aCc0mN~5nUB_D!{ z(7d7qlP85Knx28q117ZtSyDRja4?ML4}z*@g|g249)~hx=NV)_YUhle`swL{R(4G! z(CK{91b0I&w@aBGwv5luNtCQ<_vUCBW%pZ~ZQEp*NsxJ~XEG!uBSALS^@ExQ*CZ2N zculDu?KuwTe4XGL`ETUCWloWEtIfv$b)|*A{ zX7Q#9WAB-yun*576K&%8%-knv%+MVVKIE2^HKOdtJOxrZ&)uW3pFvPPm>31>SZLHp z7|I!#PU6H%=-0S4Or5Ppm7+tVuOSUY*i&R$8UwO=XGX@Q?*S2OWL!t`TPNgw<}1fR zkpP()ot!;l6UhhF@m6k6Wn)$6J8zEGjD26&m)2Vj5VCsWw-_uF5qw#4T8 z8v*C+b?8mWdej1OHu6Q}#qt@#7rA4&lw)gp#p7hywcQ4r3nq2UEFhkarHH23hyEEK z@jNRxl+;S!evfN%?lpRTt>E6|-gIvrCv=~UV|Y*ROvKVZzF8%p)ua!LU%0vXg%!~H zB;haXv8PT+Jz{nD6@3_PgOC8r)dh^O+dCGGPU1&V`U8Y}szWoD&Qf;&tnp9}mw++cs!tWpqg*TvwQIom^rSttnMRvd z4OX6T`R0s0`>ti{QSYejRW!D!-1a^2?Glh^Oh3XrH&l9d)dD_wnTrj{^IMa#efrBr zU14S=r=BQvy>vjibd7O!*;ePg&r=hpI83y?T^nk>zr#wfa%g8btFNGLAmKV2v)KZ|#BLgxNPIgL}k_Y3ygv7y>KXEuca2cbP2qK_%@@}jRz*__t3 za4@(~+&2DPvt6`}113a&3f^p{v3sqGv3EzI#fBVMSua|A0V=knxfs>!H_HF#hZ-!O z%=*rL%Si|Qkk{Dq&pd?#$(JP3JnC>(R(S1F(aH{=)$dH;rFFVVH1SE~#D3tj+Lh4| zCGD~?O`WmSUN+h8K#try;rG%KQ%oh9m)_C2$Kj;P!xph^#Fyw=2EM{IUm-o@*1Uyi zO@`-mNm+ITWPiE%f|<^*Xe7Q4FC~oTXw*kH9-H2{Kt6Hp`o7ByCB)4snPQfR{-%wg zTOX^iYNcq<;h^l+s8U(-z|~n$Z2==}B-8IO^@O~1IGUZlVK3|a!pvU655JWrAhTZI zQCBPgX+wy;I-mT6Ow?ZMg9o?U2+!ew)-v0#82{+A2fgTd{N$e`*d(Am<{&83`s?kV zhhL7kacbAvMjof+G9e@NP*4LjH>ds8SsjsIeTSd>MXtdb*HRfG-4dVC2Iwb%J?4AP z`~~sM4r-jdaptzpBCi`yjjMb=Uik#g(h!{yS;a9~#oFbEYkK9#?y}{;m5YCV?MzcQ zmZ=dC-sB|Guzg0sweQM)35IaZ8k0bFgvatEyH``q_00KorEC%BeHzuLJu*|@#$b}O zOTNq3kyGsO)(9ynvlgBDW+UQ|ktw6Vol9Msb&e8$#J_?E2-aF#y!#oT7U%1i=QnKs zTUVb$kaom4tN7Q+BXUfK)>{KVCe~_p^uo1j;qtAd*YD@-b>;d=oiEW8eZnxWBuoEScyHV%Ld=|B0u^Fh5m1 zCH5v?HNel)^?Azmy4MmG4Q5rgfumWzi(z7B)ol&Ndis68`l3BY!o1WTbq9V?-Yzb` z;V`lF8LWXb7Gkkv`mNue*5_3WY?}hK4L&-(e--1Y2n_4KvJ%rz7IW5ixeX+BQ*Y~uS8k-u#MG)gRmazn*&U}0xe<4+B>Qcb*iLjr z%1*!^D?V4o=UjGJb|r06iC&>f>7jy}h9!-Blo}XcPNP zszh5n7v;kb(Y;cMV~m1$0BnVhyE~fqQ+MX+{`eJ%E8(j}XJ73n&Wj#N zC0(C*$_OOoCW7Q=tHb$mUrX1y#@b%dwr@OEI#O{7xo=y0vXvo02)n0;?HuELWtt|g z`3qzA%i}`7$w6rKAm!1vS5>M+|A>y>th6(}yd%e{*HTQdi1o!bvhU~YRC6hBmq!2I zL`2>F`0pGcFuhjW)P!V!T%u+0_m=yP<+C%ky%Ki*F!;n~Jb!FZZUA8aQ7O)9<*S-r z=UhO`)vKFj7mVbSAVz{Vkxc5DQ?F)%JA|M7jL_w<<2|9of`u;Ds$tyXMcNkwBtsi> zz9h0J8F3H2U$~>lS$(u`X$SMrj+2?Fb(jG!h)W5ZrotL|PaQ>NS4&m&I7TkQv(vh4 zNhF8rsI#PNHUV$l;yZo(sC)R5)RbyXCy6WnNI(DgJi%N^i5qmV`*LP%Y}uvyYekB{ zpTRSml4$!>$*~#ws+k#jJ`-xYJ!k1QHOZ@65eARL(D~&{vLD5F8S31j3W%r%HoM5r zy_qqsW?z53%qdp2eWd?Hn5BYDAU5 zuQa2qRe0&}9j26%*0EWz7Pa+g4qxl8a9;1FG|Z{J3*Adc9U!rwo$T z>Ad|wmrxR`>01K9T=?sT*9?oA5bGnaVg*j!<8AD@yqQThCw(Iba!Wryk7&`GJbqOF zPX57SB5PGWS9|<8L^giy3UrTZt`zX_E z$V-z_!0(ji1l{$MuRbE@?46 zM8J)bI%9$BD|dYRyJRe`sBD<4$lQ3&#&SFhbBxclB)LlX?Q+<7?b+ z#IDOSXeV3=xu+23JX&D{RrUf9nZXK}=4^Eq(yD1eSHO}I1wzVOL;i5RJ>xyb>hgr% z8wq#Lc#rCOa(utsa;L}2jsL}y>PNSoV>1=(YS&x@oVA6PoX2i!B&I@a>NS=xicq`< zIK$M;YUeyvxBvwLeIw&+3`D1xE5Jd>1Z0fVy+vN$v57>)ENh+}odqI>;#m~|XoZd2 znZgN3;eg?<5bj8uDBj;U!%$yucH#C0Z|?M;g*qipcj&+EzrR zeL%zRq;{>^EU8w)QUI1nf@peubYz9=I+{Al8V2w^<8ie@o03WDk22WFC~-;!yAJXD zFp7nFhM^2%B6qdq+hm?pm=vam{KFa|0sU^k#rz*5j1Nu{USf#&fOu?|=R0RE0D9M( zpr@@?v2^MQ{4MI_emlZL*ba(d|Bn=9pP$IbTGsk6>Vyzf?pGq0D_O5sK zLW&mPTLJMOYfuSj7M_LaRI`L1Kr67uh+{v4sV_fj^>L!T)QYwtCTm?u`hW$ zv+tx|E#s;^V%^^o6h4ac;CVth?&Od!^_M%)QB-9_Zo?;7%e<@EDLW-Wb|-3i_u z7uRoi(dfDM)Ycfs?A!}jpQV9!4o+cYwnTr_;WxkY{ zj@QdYHM!N2pmf62lp9s2z;Ld_T_k3VS?iLJ-^zqYYFK8@bqWre+A?!rTK+j;au}aJ zHy0OIml3E_Q=2$Tm&c=8(ZQZxBk~6E8ZQ|C6&)r46*gjEK6?(#&d!cg>i+r%dIsw% zoE<-9UMq}@=W8%CLI%sj~;x012zbMI8Kbi#i8_JNXQ79DKDBuN8*Voa9GnEL3vl~ zwu4TM1eQdSj{P|xkq8P3%KyQrQXWag52Vnf(p}PvprnETtG$2DL{5j&K@9 z^hQ2I7NisTIgrqWpoG$MgqDIRhMWI|0_>k%?5jz!tgj#3*R9Xprh zhSfWG9{f7(urzLh!U?r02#!;~>61bZPCyLAjht&|HXu~tyv((vqJH=HT9N`eQ{vhE zH<+NN%8lRX7{bQ7^=P(tUM3{f&)y&F_Sk3!<`#bk7-382Oiu)8jRJXq zJY`IQUk0Yn7zR}d*ZSHnwA5lP#@n0>1N<8PUJMM+G#_ndQSh8mitqYUgb%+Q;+Y0QOLADCi1qkBtYWKrj`;dB2w@VlbEL3)l&q%^x+>KP8QTX zQl<%F=%O~pM$m#_=;bx9X`S=l0&1pZl#(VM!<`Isw~VPLqyb-Bm`n4RZK0)nH8acw zKLHT{J=3{J&NI|Md_t(x({I4gf0f{rfLg;CSqVDr^A`A)TJMCkf9v(Nodqp4bL$&8 zJ~d0px3Dm$Ou73L@$LVS%#FG1YsAZ@>!5mNwu|Dl%v^j{$3jaT>PqTD^MFdlRJLeS zz6!zMno2cbk#~g`C-Wpqr((dQ`SrXxN7CP9tDMAFRaI5QkrfZaIf~S)YM`k}Re>B& zbeHm7;AUFyOu?Zn>?F7Wo=b7eRA53!Aq6mH%c5 z{NH33+NIrVy_@w7stnmoRjN0OWCL?}t5WiIk1^JXwagagf+sgq`;9;;hzC&AX{4Tp zSBxMCqDOMlxOSj?dI}ucNGXIK@40KL?oL~nie(zkV-q+iyMOZ#$zI}KR0%5MC~>dT zV)>hz9N}7-e1n!+#ga34Dkm$ihVdydRuV-@;W$0*^Ew4_>N^j+Ssdde`crSB0PycU zL9D08{)}9IB%tqLjAwlQuIaDE`P!~;y8r)d{SUDJW3X?${=b+aU(HgBe`fOZfA0Sp I08Z`yA8i0S5C8xG diff --git a/wadsrc_extra/static/sounds/DSDGPAIN.flac b/wadsrc_extra/static/sounds/DSDGPAIN.flac deleted file mode 100644 index 9ccfc60c16c683b2f5e0e1831016862566a06f30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1679 zcmV;A25|XiOkqO+001Ha00IC20IC21YXY$lZ~y=Z&gr_{y*zNS7^bq0c>OT#p925@ z5&!@I00000000000000000IDn001Z;0001TWoBh^Wo~0-AZ%%3Mod9NATcg7E-@f7 zFfcbTIWac?00030_?-d(D-j1u1Ox>H1q4z(Ux#o2MA@@u&6_rC*|TQNn>K9Ovu4ek zHf-4l;VL6RJQ$=TA~S@I1i7k-MuHZD3K|lKs2qe1*-;we5}@Z}5zJa;eX_cwN=!?s zs-C`ub{dqa6Px5z(wvVI2^EX4WhDr4UTa|DA2mq-ImRSPY&fFhB2?B6P|{LRbR%t% zxIs_z{3z^1BFs-1m8PWXAyRBonUXcgTazkLS`kR+)hK~7PZTL$DUp^$An=+YLXqMm z!Ye&#^@yUb5HcA{hI=mCE+Uwc2WzPa&`l>Pm_f%_= z)bl9s6?C=TI*eq=kqnKKXvioam$?lL=tiJf7f!r#7-C3gg|lF)7}4KZZnZ87ctc^r zL`D$DG@(6dGIyQCO;XlHtjI`@R6#(ci2wMV0s$)#Y((qm>rx;Nz@@UkC3-2s%qh*& z^HwvzENcV`AvSLfPHE(#lUIlm=eO}C3Z0E(?0=y`QPWwpTj>=b&KzlD&3bGqFWLTV zFw#ewu4;)Jdc8f#m|C}bgw=Ue*o9aKYbl!PIWD{odp130*iW@N)@-IKX}-;*R=QGD zx8-gl-|G^4CnA*Mtg`!%G0dQ}`6B$2m4=q3F4_nl?_9c4yR3TA+D?XR-_He@Gq6%oHk-~)SBtvrDj3=V!u|_uwAc?MY5v@}_-r}wa>jV-)idu%* zo>UOyhTiitdD}}{5b%nFC{3|tS`h2P#A`DOVhddL2uTGXTbAWZ5zMp5Scxcuo=|NL zdyrEQ_chQ`!x2JUCy22|9N9MjLNEXLodN(UtD1{y?H8@N6XdzQX%Q%^6jxoM*e#sch6HZRE#4<}p!bXTVD5xWzw5f_p zk|N4Hp@K1ar=K2hGo=#}NnVCNV&QIJ!AWPZlakDdB8Vm0aRngN-NYbKREn=X-s|Cm z-3{uY1wY*aV~WvCa?$1q5nM#HqA6xU4$rDTyn?K$EK=BSvMVj#x;hFr^wkl!;~pUi zRRTpF=s3AaH3UHJprY+&yVO=8Ii9W|>Om5ny)wpelTu3@EJD169#XqUM|TZE(2X#3 zLR@_E&Xs^SdjI&H0s|`%x=;o93&XyQXPnf(A&Pg2yYn51$2uO!^VOVLNqb10~i&Y{R=O&^hkTIyv z7}w4SXv+-r(Hm+ES;~E~oQEKCbbU#O7{r!$d0DO!*ICFzMTj8gSr78f9zbFqW7Ij2 zVg?)K#yc(MV-%^z*tgse#rnd7Ho?|~0QDSFA4mxW6cC6-gWRBj3>QWi(}W$il}JJw ziIE&(kg+Y0p}!k9>`4#T{Ji-kbK0*I21LMXGBqNU=N7%4^&_ch5Q z*oqGY0<6$Nwriy&E=uMPAUiZgKs|*`13iX^1bPGpln*Jw3K&e-fs1HmSHVGH455Xj zD6lK?iqN|x|M+bJ1kEcE%|tW)A3`Zn0Wsz4OejmtM)|=%iE0>8GmR?zWx`^Z{fIAj zRP`%}>HaA7{hBJLHeY9wbq5I=8BIi|CPooThMVIKafQrRJ<8>*gVOad(UQJPQko=^ zsy0+nPr|z}MFmNu3ob&5@nbyxNeu|2s}y)mPqZK-ij#SBrnn&9Ep6dtmEMFqrO7&| ZK~%zq^@tg&NgzU@Xz0_`;T;bE+DBwb-Jt*g diff --git a/wadsrc_extra/static/sounds/DSDGSIT.flac b/wadsrc_extra/static/sounds/DSDGSIT.flac deleted file mode 100644 index 6c17c01e5bf2b21e095bc5203bc5afec55407514..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1656 zcmV-;28a1(OkqO+001Hg00;m807n1?#R9PqZ~y=ZRVT~mlRg!~Gy?zt z5&!@I00000000000000000;nt001Z;0001TWoBh^Wo~0-AZ%%3Mod9NATcg7E-@f7 zFfcbTIWac?00030_`L!ED-mNt002@iuz~;o@PI%N&!;JvU;t2% z5Cb@zpPZl}K)l1xh#>+}$b$%;(`h+SZ+4hTosQPRKHCtvE~+!&RB9=4U-9>I+m}!jRTNN^SyVVp-(c=6ktcEsS$hO>eyausHRNkfib*bWo zB@)w2(qX$n6pcq6Z{jeMdDr#`dLj;b95t>BmG^8GLO|*-8#bnDj%r|GM-ZZ%NeHSF zf{sIto_!@v5^bdW;UeP;z2sB|(RoDOsmNOV^)qHfAZiV1Zpc0egvtMM=-Bxh)@ z&TgM=!b(t~Zxaz1VALQ#4G^+`xcLXypNJd5#)LM~P5s5W8QN7&`x{R5gZ}V>oM8!K z^3|;wQyJ)~7IfP$Qz2rCx$M$t#G^`kQEZ!k`n`b$33G`g;JwLDC9bZQ7gfAAt|h|* zOte8*Ygm*dwlb-6x1k)6yg_M1f|OU~qX#-2hR^na>nlDBL$6$aP#DbIdap7f!lp zG~#dksNitC*W7>@?#N>)Q^rS4GVNDgqXP?6e$RFV5a zB$o&CdECh_#bR*!`^jjYGzpJ;r7!87A1kU7MT=D`Bjp{?=3Hn~dbn?2H51~UEuqyD zS=I5@?s%)$l7t$nacU77N}Mrn;w(#@DP4Y?tTBdC^S4B(_>2)2>tvYh-eMRN} zc``-MP_dT1m6GvF7ak2SPOOFQn-Jk+8U?{Hm1c^hQSXceF0xtK%3ex|-(U<>s4A_A z5KKU6`c0(+2#bVFsD_4JKRft9AYF%uqEz#nP+vFMKwWMN^r2f(i&GSm3MVX9`P!A!4Kr1b$_Yn?WKRnZjJen%Uc@1b$jX0n=li zSqQo;NaW;wgd}mp_0`!f>SDxQH<^KfhgNZnRMo=is#z3GbS|3ml33uj7^W~^!h{SR zd{xfG$urKIj$w@n)o@VK*1(;v7=e3d_lZ?&ypYerN1CmK9BZE)Ag2zEg_0s5un*Y< z@IcxiH6-bx#fqjWj9G9dwc|Pj)zxf*u|dPiDH2UTqq*4tGPh8Xp2l7-a-g*Y%i=t$X{2B zY4Lb8c!PDhszD1yFL4cFFwfhoKSu_mhozfvkp~^wH>k&SS9mtMHBB7Z$R$a)Y=oNF zfeNZ@!o-TQC;3{5_x$BNgP8GJXci!hAVP^naJ@4Y+07EZ5g=J9hDs$8NP@IOn(L!v z6HPpbcCT{d2BB%Iq942XuuF)un8q1Tw6ajCL=r2vs|)peP_d$dC=zD1M2E%s~S+D_9O9fv2<3cTTaCna$s+B CN#>yd From 10429d4421b1f78aeb0ca56c7d41eb647502a876 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Sun, 1 Oct 2017 01:57:53 +0800 Subject: [PATCH 031/105] Removed all copyright-infringing dog sprites and provided a free replacement. --- wadsrc/static/credits/dog sprite.txt | 9 +++++++++ wadsrc/static/sprites/dogs/DOGSA1.png | Bin 155 -> 1280 bytes wadsrc/static/sprites/dogs/DOGSA2.png | Bin 0 -> 1553 bytes wadsrc/static/sprites/dogs/DOGSA2A8.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSA3.png | Bin 0 -> 1631 bytes wadsrc/static/sprites/dogs/DOGSA3A7.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSA4.png | Bin 0 -> 1533 bytes wadsrc/static/sprites/dogs/DOGSA4A6.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSA5.png | Bin 155 -> 1186 bytes wadsrc/static/sprites/dogs/DOGSA6.png | Bin 0 -> 1516 bytes wadsrc/static/sprites/dogs/DOGSA7.png | Bin 0 -> 1593 bytes wadsrc/static/sprites/dogs/DOGSA8.png | Bin 0 -> 1518 bytes wadsrc/static/sprites/dogs/DOGSB1.png | Bin 155 -> 1230 bytes wadsrc/static/sprites/dogs/DOGSB2.png | Bin 0 -> 1520 bytes wadsrc/static/sprites/dogs/DOGSB2B8.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSB3.png | Bin 0 -> 1607 bytes wadsrc/static/sprites/dogs/DOGSB3B7.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSB4.png | Bin 0 -> 1533 bytes wadsrc/static/sprites/dogs/DOGSB4B6.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSB5.png | Bin 155 -> 1210 bytes wadsrc/static/sprites/dogs/DOGSB6.png | Bin 0 -> 1498 bytes wadsrc/static/sprites/dogs/DOGSB7.png | Bin 0 -> 1592 bytes wadsrc/static/sprites/dogs/DOGSB8.png | Bin 0 -> 1514 bytes wadsrc/static/sprites/dogs/DOGSC1.png | Bin 155 -> 1297 bytes wadsrc/static/sprites/dogs/DOGSC2.png | Bin 0 -> 1506 bytes wadsrc/static/sprites/dogs/DOGSC2C8.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSC3.png | Bin 0 -> 1571 bytes wadsrc/static/sprites/dogs/DOGSC3C7.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSC4.png | Bin 0 -> 1531 bytes wadsrc/static/sprites/dogs/DOGSC4C6.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSC5.png | Bin 155 -> 1337 bytes wadsrc/static/sprites/dogs/DOGSC6.png | Bin 0 -> 1520 bytes wadsrc/static/sprites/dogs/DOGSC7.png | Bin 0 -> 1536 bytes wadsrc/static/sprites/dogs/DOGSC8.png | Bin 0 -> 1489 bytes wadsrc/static/sprites/dogs/DOGSD1.png | Bin 155 -> 1311 bytes wadsrc/static/sprites/dogs/DOGSD2.png | Bin 0 -> 1518 bytes wadsrc/static/sprites/dogs/DOGSD2D8.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSD3.png | Bin 0 -> 1588 bytes wadsrc/static/sprites/dogs/DOGSD3D7.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSD4.png | Bin 0 -> 1525 bytes wadsrc/static/sprites/dogs/DOGSD4D6.png | Bin 155 -> 0 bytes wadsrc/static/sprites/dogs/DOGSD5.png | Bin 155 -> 1326 bytes wadsrc/static/sprites/dogs/DOGSD6.png | Bin 0 -> 1542 bytes wadsrc/static/sprites/dogs/DOGSD7.png | Bin 0 -> 1573 bytes wadsrc/static/sprites/dogs/DOGSD8.png | Bin 0 -> 1503 bytes wadsrc/static/sprites/dogs/DOGSE1.png | Bin 155 -> 1362 bytes wadsrc/static/sprites/dogs/DOGSE2.png | Bin 155 -> 1517 bytes wadsrc/static/sprites/dogs/DOGSE3.png | Bin 155 -> 1548 bytes wadsrc/static/sprites/dogs/DOGSE4.png | Bin 155 -> 1598 bytes wadsrc/static/sprites/dogs/DOGSE5.png | Bin 155 -> 1438 bytes wadsrc/static/sprites/dogs/DOGSE6.png | Bin 155 -> 1550 bytes wadsrc/static/sprites/dogs/DOGSE7.png | Bin 155 -> 1554 bytes wadsrc/static/sprites/dogs/DOGSE8.png | Bin 155 -> 1559 bytes wadsrc/static/sprites/dogs/DOGSF1.png | Bin 155 -> 1397 bytes wadsrc/static/sprites/dogs/DOGSF2.png | Bin 155 -> 1571 bytes wadsrc/static/sprites/dogs/DOGSF3.png | Bin 155 -> 1602 bytes wadsrc/static/sprites/dogs/DOGSF4.png | Bin 155 -> 1566 bytes wadsrc/static/sprites/dogs/DOGSF5.png | Bin 155 -> 1403 bytes wadsrc/static/sprites/dogs/DOGSF6.png | Bin 155 -> 1517 bytes wadsrc/static/sprites/dogs/DOGSF7.png | Bin 155 -> 1596 bytes wadsrc/static/sprites/dogs/DOGSF8.png | Bin 155 -> 1608 bytes wadsrc/static/sprites/dogs/DOGSG1.png | Bin 155 -> 1389 bytes wadsrc/static/sprites/dogs/DOGSG2.png | Bin 155 -> 1588 bytes wadsrc/static/sprites/dogs/DOGSG3.png | Bin 155 -> 1644 bytes wadsrc/static/sprites/dogs/DOGSG4.png | Bin 155 -> 1520 bytes wadsrc/static/sprites/dogs/DOGSG5.png | Bin 155 -> 1350 bytes wadsrc/static/sprites/dogs/DOGSG6.png | Bin 155 -> 1521 bytes wadsrc/static/sprites/dogs/DOGSG7.png | Bin 155 -> 1622 bytes wadsrc/static/sprites/dogs/DOGSG8.png | Bin 155 -> 1570 bytes wadsrc/static/sprites/dogs/DOGSH1.png | Bin 155 -> 1310 bytes wadsrc/static/sprites/dogs/DOGSH2.png | Bin 155 -> 1531 bytes wadsrc/static/sprites/dogs/DOGSH3.png | Bin 155 -> 1592 bytes wadsrc/static/sprites/dogs/DOGSH4.png | Bin 155 -> 1483 bytes wadsrc/static/sprites/dogs/DOGSH5.png | Bin 155 -> 1294 bytes wadsrc/static/sprites/dogs/DOGSH6.png | Bin 155 -> 1467 bytes wadsrc/static/sprites/dogs/DOGSH7.png | Bin 155 -> 1578 bytes wadsrc/static/sprites/dogs/DOGSH8.png | Bin 155 -> 1569 bytes wadsrc/static/sprites/dogs/DOGSI0.png | Bin 155 -> 1690 bytes wadsrc/static/sprites/dogs/DOGSJ0.png | Bin 155 -> 1782 bytes wadsrc/static/sprites/dogs/DOGSK0.png | Bin 155 -> 1746 bytes wadsrc/static/sprites/dogs/DOGSL0.png | Bin 155 -> 1720 bytes wadsrc/static/sprites/dogs/DOGSM0.png | Bin 155 -> 1727 bytes wadsrc/static/sprites/dogs/DOGSN0.png | Bin 155 -> 1739 bytes wadsrc_extra/static/sprites/dogs/DOGSA1.png | Bin 416 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSA2A8.png | Bin 466 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSA3A7.png | Bin 479 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSA4A6.png | Bin 451 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSA5.png | Bin 387 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSB1.png | Bin 408 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSB2B8.png | Bin 475 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSB3B7.png | Bin 484 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSB4B6.png | Bin 445 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSB5.png | Bin 405 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSC1.png | Bin 362 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSC2C8.png | Bin 481 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSC3C7.png | Bin 504 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSC4C6.png | Bin 456 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSC5.png | Bin 391 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSD1.png | Bin 393 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSD2D8.png | Bin 462 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSD3D7.png | Bin 495 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSD4D6.png | Bin 445 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSD5.png | Bin 367 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE1.png | Bin 416 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE2.png | Bin 465 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE3.png | Bin 480 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE4.png | Bin 452 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE5.png | Bin 387 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE6.png | Bin 483 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE7.png | Bin 511 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSE8.png | Bin 472 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF1.png | Bin 458 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF2.png | Bin 475 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF3.png | Bin 484 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF4.png | Bin 445 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF5.png | Bin 407 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF6.png | Bin 466 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF7.png | Bin 484 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSF8.png | Bin 431 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG1.png | Bin 511 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG2.png | Bin 482 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG3.png | Bin 505 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG4.png | Bin 457 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG5.png | Bin 391 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG6.png | Bin 464 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG7.png | Bin 525 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSG8.png | Bin 467 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH1.png | Bin 510 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH2.png | Bin 462 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH3.png | Bin 495 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH4.png | Bin 445 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH5.png | Bin 368 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH6.png | Bin 439 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH7.png | Bin 479 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSH8.png | Bin 457 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSI0.png | Bin 532 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSJ0.png | Bin 573 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSK0.png | Bin 574 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSL0.png | Bin 584 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSM0.png | Bin 583 -> 0 bytes wadsrc_extra/static/sprites/dogs/DOGSN0.png | Bin 410 -> 0 bytes 141 files changed, 9 insertions(+) create mode 100644 wadsrc/static/credits/dog sprite.txt create mode 100644 wadsrc/static/sprites/dogs/DOGSA2.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSA2A8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSA3.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSA3A7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSA4.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSA4A6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSA6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSA7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSA8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSB2.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSB2B8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSB3.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSB3B7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSB4.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSB4B6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSB6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSB7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSB8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSC2.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSC2C8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSC3.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSC3C7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSC4.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSC4C6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSC6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSC7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSC8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSD2.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSD2D8.png create mode 100644 wadsrc/static/sprites/dogs/DOGSD3.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSD3D7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSD4.png delete mode 100644 wadsrc/static/sprites/dogs/DOGSD4D6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSD6.png create mode 100644 wadsrc/static/sprites/dogs/DOGSD7.png create mode 100644 wadsrc/static/sprites/dogs/DOGSD8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSA1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSA2A8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSA3A7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSA4A6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSA5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSB1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSB2B8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSB3B7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSB4B6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSB5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSC1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSC2C8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSC3C7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSC4C6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSC5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSD1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSD2D8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSD3D7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSD4D6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSD5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE2.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE3.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE4.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSE8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF2.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF3.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF4.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSF8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG2.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG3.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG4.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSG8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH1.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH2.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH3.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH4.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH5.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH6.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH7.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSH8.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSI0.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSJ0.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSK0.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSL0.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSM0.png delete mode 100644 wadsrc_extra/static/sprites/dogs/DOGSN0.png diff --git a/wadsrc/static/credits/dog sprite.txt b/wadsrc/static/credits/dog sprite.txt new file mode 100644 index 000000000..7bfe0c30d --- /dev/null +++ b/wadsrc/static/credits/dog sprite.txt @@ -0,0 +1,9 @@ +German Shepherd Dog Sprite + +Modeled from scratch and rendered in Blender by Nash Muhandes. + +Copyright © 2017 Nash Muhandes. All Rights Reserved. + +Forum thread - https://forum.zdoom.org/viewtopic.php?f=59&t=58035 + +Released under CC-BY - https://creativecommons.org/licenses/by/3.0/ diff --git a/wadsrc/static/sprites/dogs/DOGSA1.png b/wadsrc/static/sprites/dogs/DOGSA1.png index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..fcfbe8d65d18fe26856b64e27a1286f7aa7266a5 100644 GIT binary patch literal 1280 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 literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSA3A7.png b/wadsrc/static/sprites/dogs/DOGSA3A7.png deleted file mode 100644 index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 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 A>i_@% literal 155 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 Udljodx&QzG07*qoM6N<$g5vE(kN^Mx literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSB1.png b/wadsrc/static/sprites/dogs/DOGSB1.png index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..1163944ab9736b9b88d724ff0cdeec7c839a6946 100644 GIT binary patch literal 1230 zcmV;<1Tp)GP)|10LNpKy2WCYq zc26>RP%cI^COk4HK{6yfEhBa#TA81_cKP2Xaa&IxHSc zIVOHrHzFPy3kV2DEf|qxKnMo}l3zDOJ2OTxAYex^W=1SDEhixw6I?qX5(x!QL_0Yo z6c7vv1OoyqC?_Ks4<;52K{O{43kESJ9~=@2I4~(XBNBpFGiOIETtqQ7GB7nL9Vi+P zJ~}i$GAA4r4=yJrcvn4YT1z-GEIA_*IxQh58W1`(EHfYxPd6kl5DYyoAS)aYH6ju} zH!)gKM_foYXEY=y2nZbn1v(@WN-`gREiFbdABU;K_`b<~ z6pmguh*>k5Wjbn9LUUO|Og%Aq5?JbY0u9})+eWIAz5DuY%s zNjWT5Mmcj!E3I`!IV&GODHm}`DJd8XkYYeWDHM@lI42efja)RBV>vDx43=Uzfm1J$ zVmqK|J%v^?uX99PIvMk^LuO+!5=6@OGQqG~=S77Bk; zFM?JwY)LRWD;|$xK9pfNmSjAZVK{I{D1uu(p=v&;b4RRoNj@(lmug0LQ815QHm!9? zjcZazEEiKW9Gq`ShF3CTKO$&CCB%YH&WBJ=J~E45I)73xo!|k#00001bW%=J06^y0 zW&i*Id`Uz>R9M4fU>F6XU=)mkQ7{Td!6+C7Ll(S;P#-8T;>CRsdFwR=Mx0&0oZC%%Y}k>FOIqo(UykUiN1CsyfzA zej%|fWEs&}8sTkcVdLoR9~xEPN0t#YKb3_iBqrrW2FIi{w321S=V=|~%}uEV$1|{gv1H!#_DTIUg~eGJxfNYx8L@ux+!?cHO{mUJ%c<&~N|q7l)-Ij1VE)ICwMCV^ zQ&y8@#N{*V7OmN`b;ZQGp2;gWk!8fSE9W?tkhyB(HnNPk{^`;MD0B1nU1S+? z=f+hSbLXDVWEpY$9-O&*-*IwGc>3rroW1wR0dkCZ^86W`edzEpa*TNQ<}IAP|KL$d sYqgUnPElMlK6ps65iehjHZbS}00{tgr8@+NL;wH)07*qoM6N<$g6lVjIsgCw literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>jd5L~Pdr*tMKK%> zBnJmBBpeeG5oIbOY)&>tIWI*%IN`I5jdfF)s@X2p9td2n7Q% zA{DH4NGm5KLoXf`3Img5L6T!UPdO=?XhDr%JBeRAc2hZ{YeA1>L#J{_aZWOLQ8uo1 zNjfehA`=N)J|~-HJ0KDVhgdU7I4UL!2!KB?0|Ej90Rd)HKua_t8VvLPa|=Rva8ZH7$8gEMP$=fmbzrP%fu%L5p2FH8CzXH8N#TKR_oGWlA%4 zO)H9CI42hhFdYt^Z%kK4Iizq%TstF3JThWGBWgx0j9W9cc15UgLTyGScuXsfW<-o) zKdX39JuM(qM?7CdEkijmd0Rj>DIZQZBtbbckYYWXY)7xqu5&|TNHj=5JTf2=ZA>ve zDI3XzO&AXdds{ ~WLpH+NAoYE3v(KP_TUKDK;LJvJ{lB^XdYGCevsZ%;IhTQrhi zHg#7*QAj>hK{7NX7ll_eLp?SxEGVdNK&Na#BperjRWepPBuzjzSxY^(ct%h*AuAdS zFfJ`LF)bw(2#Q-bk6t!#N-JVZH$yZhK{qZ;KQm!JBs4B5RW=@hT|csQMr=qbqi;k- zDivi$EJ`mIa!M&xK`C?QZnIFw;IooPLANGefAJeg)YJ}x0RBN0kKHAgrsJ|+`4Fe|BXL_9Y# zQ#BnS7Y;ik5iA=HFB}bEJt8O<2~j>SynIPKB@$XjH9{#Bh+jQrK_fOZFhDyu!hcMv zZ$UR95HcPPZbv77Q!hF;GHFFAz0X=P00001bW%=J06^y0W&i*JdPzhF6X zU=)mkQ7{Td!6+C7Lk?VIV3;3;de;yh6JmMQe)4%!OH_Vx~j(`Cj z9V^8IXa87zj*FN7?E5*g<@eSvS+PIj+qe0uDmNd^@?7fs;57jwT-4eNMSd$h&XZSV_x`c!*GvD}tR1`n3Kd`U1QTs0);iuXxB?60qW-}R|^-nF(R-@o51 zy{TMs>v=no5#ppSA^K$7<~I-PZ^)cIw_w+-C4JAQu9^shGk`dU*SuOZQhgezCx_b#xo zG;7_s_JI9oLp|@^r${s5c(miZrJMdY{J-ducZ_xXIeL1ONI^Y_fJch`1Ld}w!h`|`sK44Y2wnm}UiPd}XUZX1ZP!|wLlw?KO4 zr;|A(=s%JD^;r7pcVPCa&fEWg1L*^MQ~wgH|3c>Kj1zzUr2U3)kKEbu0z}8xz9-g* ztRFxB{Car$_!}sH_Rob0V8*eSSR#!$^ASTHnm$9;K0 zx&gnRRsFaex*5uwap(!jCgdg_3HkgA#(VbTC&{(K-~7B2N8!Aq9~MRb9&IQL5dZ*{ W5FzRVMtz(B0000!Duh-rSUMxCbxD3! zHcl}bgJMU0U`m{7L$P{Gj%Y?pH6w#KFJ)FrYgk4l9~(3u4t-xnO*J5vVmSr`0%Jul zaZE2qIWAK}G)O}|WluhpWIK6ULK6uCNi`*xZAgw_JU1vDm2FCGR6l%KKVC~fW=1Yl zNkWTUI72=>TT44F91d4TH&Z_@RYyK2BOxgyArcJ=E+!x#6A3vlC=(D3EGj4#6A^w; zFEcD9HZw3sFdITG8fHNxMK~@)G%9XWK+ATYV zU{69_LoYQmF^gY5&xcWkU_ehiD{)aYIU^BhLM6t7OpIJKj$AftMklIrM1);Gidi#* zRWNo{J6=F4h+aOoc}byZJYqsAfK@hzUqf0sAZb!RlwmrYYeh>wGoEQeP)R~rNIFD3 zHZdR*RYp32Q!jT?Hi}y}dQviSR6Uz!JGXa6KQJUB69-E4NV|JTa8Wu?G#-gtHd8hqX;MHt zBob#!H99UNP(wLNL_BIqFN9VzPd_qMIwYuXKz~&+Ts?6kO*}7|WH~)KG(b2qU`aMJF)lkgH!d3tqHaWzVLD7P94Z(J zT~0x`c}FJ}36xR9M4fU>F6X zU=)mkQ7{Td!6+C7LkoP^OR*7me_o~3h|N7klo}CUc!4qlc%Qz_Kh{Bs3Gv)pxuQAK zPkbWZh`sykqT}|w*#6@8C$daA{-$~VmVHllaPSCk|8}i@=GvKm|2}-^HyOKX*L|2` zg8W;XUhYUu*q5F8t@_=Msn@Fi|NGef|KrC?t5*Ge^yuF`sJg{#|K0!bZH>FjbPOZJ z1d<|t?kY*yknv`BeZh~3FAPqe{PC-;v2ohUw*QM({`+@jJp;oEzrUY<-@mq|-{Z+$ ztd8T0`Fix3$SJAZcSpXdPbtu>eOG@n@4t3?+y80*{;&G{e|f#n#Hq_q{F*Z3OYbwR zCWw9&dR1BZsx$sT!hzB=Etjt3{Kz}8``xeZUsoQ@pJQ`>an+t#eGh!k+_`hy(+z*P zPHNcu{mX%@oR8AqvLw$;u6Uy}@zUWiNtp)2gxTZC{+6%!@r| z#j6ySWcDBV{CCv^BNI~+;`j2Y={0+!uHM>mSYqzMC`FYczwh0%u)O{CD+y-kcAfq3 zVQjw|ZE2X9{fA@QZq4D*lhwVu)<3{A`r{A}|e}3`kg`!eby$24~<_l^X3K#Aq z+64B??~5}I$zFW*_*F{pu^HKK9cSma+Sj5wV+@lAk?2zf0>hNNC=y?N1iM}AVrr)x|8LlAc>JnmovZ-v_%}G#px6{V`F!8gT>S+|Qd!VZ7VNn#*DA zxkMFwy>g9%Q2UjBreyRIILXukddfn--j~_or z5%jE$`f3`pA)@Un*@6R!U`S9Ujcw6Q@S000m4TEOI7dglND002ovPDHLk FV1f!Ij@1AF literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSB3B7.png b/wadsrc/static/sprites/dogs/DOGSB3B7.png deleted file mode 100644 index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 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 L6c3)Dl9~Sizl3=u literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>_LvrO%jfjL#%{D6ct1wDin!D(JCsQ z^{P6KBW)Q)rM6g67-hT|!Kv2b(Za~6ty+rK$}KcM-uq_W-}m0u6sI{PFftGTfDo&N zO7m0imw9%8-#3}_iv5_qq+FNpC(keai@WwxKW8k_IdlMUz9DEbZzcc)04d3Cqd#9t zB~UWYIQ1X(I|!UL(`!sn@*DqaUoFdv}%b&u*xY()d&>a zInsEpAc6)8*h+~oYJNn4S&;&BT`Km@#rn!jys_N2%!y=Se4~B%MAd0yqN1dw^wpCfyxRkzyy3P&u`UUXbB7=%UJ6x!-Xwmg<)n^8TQg92j ze5-u^qg@$9+#FoO)uO6h`Q+6an^6_pRp(UkSn1}Z#oAb>4$83NHa%KulkV}TZ8)fw z@*Tz`uba>j=mI;gN0mBAl&M$B=Lge*123*K;jwdaG~7~Cf)<5MTC~t0WYPjNlEj)g z7AQ@qbwhGCP00>HVMPiU3ChGjR8X1fXd6YygmLRqgC4g;~oD9ka)7n%_$nx?}MqZX^M3pZz}&aBcmcrY^o zNuua{=B(-zxj2%BC`7(Ag%($%2&7ZSU~0rcs&F-2=@eI|gZywh#A8SzgJ7kMz!FhD z1A#!8OHbs5s+2NyOen@@T<7>E{2%yeb(%9B(7t$B1OOiwS}C17tFyopKJ%o9wY@e~ z5oo%a5I(aL$f{Q={;Nzcq?m~T8~+O0wteYqa^$q_n;3pi`GY@7pP#xlyQfXy%E&E= z=?C_|>y4}&ZK~t!F1gmYc*Ho0&L|T4rjmCK=VE00m73Q#p4q#v*^sOBhP{nrL;bnt znk&bzRQJATyX4=uYg(bg+rNO-8e6@$W%y?Em#dOEk1qXrbE38FpXt%J!#7v~oiE=N z;W;DBj#EeIg`BVI4_1tHP7TEcw@vr-y&Com^^N!v*WIZ(cW3ms!&sy2E}dC6a(7F^ z@r8r5ppJ=G58CO`FCgbd`2M@c8#{`zz9ZdNAn(TAD5IvMmvJeE1mpSG(C1xkeIIU& zEO{-RI4>-Ivh!PSh(L0@-{l6TrkG*tFRNO)XlibOskh?#tlqwAdhp}K+bxd@cQW~_ zc9*?%jUSL3>w<$G41O_`eArvl6>_$u?ZdI=ma2i#@!;aEc~85?eP`odJqx>VwEs+S z7F;n{ceBCL-6;0;Pa-8v&#Y{0?KHCGK@JHgKWVRn_=}pSv%Tks-xhUOws-iN+b7#9 zUe?WPwK^WIA0*Q5xn8tZudn(0^}zcPgj`^6Vi1GnU`r-_9B&&N%!%36(f9uT@T9n& zJdhc>{MsJorOck>7U_5zyJ1 zR6iZ1sXFv@df@C$%Nx_c)~=?r`@+WdpPuJD-gs-17?#kx4<&#D(cXZGLp}AZL(20% yZ9H?zr;IaAqTaDz^CxER3x9igs&A<(e**w~vXYxC{JBo$A0J>fI;m#8r}lrz&L@HZ literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSB7.png b/wadsrc/static/sprites/dogs/DOGSB7.png new file mode 100644 index 0000000000000000000000000000000000000000..28f3967066ed878152ecd70f594ff64b14279ceb GIT binary patch literal 1592 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 QTmS$707*qoM6N<$g2Vqm9{>OV literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSC1.png b/wadsrc/static/sprites/dogs/DOGSC1.png index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..c7704ccebf1b49014908fecaf2b16c089a8d6fbb 100644 GIT binary patch literal 1297 zcmWNQe^62f0LL-49LkS}hzJ2b5O{#_-UH!*g8b(3TQCr*aEg($QY0-am#(ZUTeW@| zx2o!Ez8aE48e>n6QiE?40Bq{J~M%E;)DEGO}PX@HX+~* z*)u(bOtR|Lb8@pW468T6<1e(rn2g6SrkYWqNhLNRrP;Hx{4$o`swciRN6ZE)<)A_;a-rM?t6Z-T zL~Ur;qQs=!m>u@(pjH>W4uhAt5L~CwKx&^kQjt+))= zKuWN1l|<^($rjtnT?%GU!xJ${UISW8BYP3Hv?O0Epal)m6*WjPjlyM6`?WAkEx^^H z3O+r8Yh`n(D37Wa&}s~dE|0V?W?nqc2J--`N*MF%Ll%_^q($tQh7Y`B5$a&5786A6 z>Uk#AATCPzQ5($BNO&Nf7_z8CR&`J>X%1M{M5~jy#Gr&KC390QX}4FZ;!zvIo;6|2 zUnRp~wntUEF`_bxi;^A$N4PcxXLV2+x5>;JdB}!&;SvF(z^mf!j#s*?6ha0uiHqF| z=H6E8O0RThgZi5_uJ;#I9P2Q3x}^~fXQ^GJ7t)hBlrWb?tDyr+45xdXm1Tw1QkIy* zIJp|f_<&x_TpN(LyJYA3JYk;ynB5yx zH0VJu!qV~qltYrSND4M-bG@=RD3`Mf4lgtAY0`e!tnI0V%Q;j9k2X-R+%jJ!U{V}f z`KcbKvl2ei7()4w=qnMf>^|?!PW-B-p zy|8eFN7iHjR|S;`D}-=J->>TL$b2BHtJXh{V4AqSIFt9fZ01n?`Q}Du?!iX-*7ZSz z=r{*4H#(0>XZ&SXH~%mO8t=^7J+<89`BwC# z+PNKQvjYd-4CJbZ6L(%$k@xX0ZN8f}?wr1^I$85*-|?kmk2)VP(c#aBKVCOJeKr5m z%BRN87Yv=_+DDT~*5LHa==0MLm?v7E{v8cWOnYu!-m-J!RLjgJCEPILP6Jbnw%-Ve zyJwc~Ef=Ka^&`NKXHtJrypK13~jxAruX7}XzJHr{##Ts*?sj!Utr?? z80CsG{^!w)_@~#plXrI|E{t38@yDb49lt{d->V=H(&Gc}@%G8W%w`0a-EaHS(zyPA D?PQ#h literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>Hz6<}6rFEMEhZsyV_-QsIjVP2a!f5dBoQkI3UNp%JQERnS3FA=7sG*0 zcup)*G#yek9w8G6nr1vUDP(Cdr z84!V2H)uvGQaL4PPdaQ%FoRt{kYYVUG%1K*K9plVrg28Mc}99!J*#p@ZcQ~H5eA%R zKVwBLhhs&VYekAS79E>%M}bxkj7O*khuJoM}NR8xfRf zMq5NNCKU*0Niabw7jR86j$%TQU^$FjHYOMi%Y{#KR5@%>JAzs}JSG%xP&Z*hDXDZw zSw=T79}yW11X4pbL_Rw>B^85IFiI{MOFuO)DkdZp2s<}3Mm8vVR5dCj9zr}fBNq)x zKsrz}8%8@bLoy>?NjE(!94RIwZb&USFephqGAkVsE*lGEKqI1QJxMPa5DW@ABokai zE|Xt3I58}mWIC;KLb!QITsk1KbVE-?Jv<~5RyQ7uTQn;g3@I23G$Ir}Cly958m4YR zTS_}eJ28DzGM8gHfm1J!T{bfx5Hm0>ZAK_JArNIkCZ%jYB^C)!J~1^Q4?QLlQa>>} zBobsxH#;;gE*uRr9u6-pDp*A|Cr9?o00001bW%=J06^y0W&i*JY)M2xR9M4fU>F6X zU=)mkQ7{Td!6+C)po}u@n;962)=*@^eVd&O34Ih9v30_9hJeo$88NT7_r!$Pl$cOc zCo6aG`4b9EnBUM^H*<5W{$xKgcwqy@v1htbl3j+m2!>@ z19i|M8}`Z{(pm%P&p8E;J^O*ISb66&wc7NHN3kM}yv{75%T9zC5;kIMMcG*p)wjj-3BaiV@$x zHcqct^|@)X^0veoRx7?XUm-c69{bq3;nRn=lWRLv615ks{c)a*EZg~*;oT#JPXeDL zm1byJxc(&Bgo~L^A2Bc}{`vmlgM@U)+~uC6J0j`gZXkI?@P5UEt~M!+#WQb`YQpv8 zKi`1VqfX|QhwP6TG$Yau?jp^E%hR@jX*TACtherdWMG(-bE1GWBVOPA3#Okov)sQ6 zt`Jt|PtGODh)b6)fa!{AUM8sp{&RQgV&>ay}7Ee=8Yn@Qe@u0Q=+=YG5*0>;M1&07*qo IM6N<$f+0^UQ~&?~ literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSC2C8.png b/wadsrc/static/sprites/dogs/DOGSC2C8.png deleted file mode 100644 index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>9j$}njKQ=`?Gnr^ZQaB@eQZr9CBw=rKOfw%tG9qYCI%r5RIx8NbX+2UyH##;oL_Ih~K0LB}PJ&i7b4n^_NG@_uGaeEN zZd5@^JThELIY2KVMmsS;JUBKsGKMEE9u^NuK{}UZJ~J^dKs`D%A`>ViAPx-+6%h@6 zSv?2^1SKCHooPLKRyk!rBZO8mn`b>-Iv`s>Dvw_}DjN@_Yd(BbH9aR3vUEglM<}6g zMn^X)84d@eZ$_YKJRcMamT5#{J|bvLHIQdTs&7EBb3}b$NUwB7w|Pm5UOa?VF=j+8 zUrakvKQVe&Ja0=cgkMC2T|HYwGe<%`WlcF>LMlft8dgR*Lo6FE8w___Lry_Bj9WBX zNjqg!NKr^XBNPc&IUs;pIzu!kJ~l6hWJYaHHEmWvy?je(L?J}M&|TueShJ~==-H8&?2F&+-cg-$y;H!&|P zj9WE8EE`QaELK7?Gb$s1S2tZvL5N^LPBSJ5nQ%OK*Q$U$( zNJ%|1Qbs*UKsjViJwiP@rENh#HZM*@JtY+g&WBKNRzN;HIYmA=#eqyXH8CwGBQ`H9 zEE^3c772JxEvIiomSQ=razdSFJx4z{MLjl?U^Z7tJw7-#RY*NVJ~}rwGc_|XK|DA* zG%to%GB_d;OF=j~BN4WDMm;(=St?OX00001bW%=J06^y0W&i*Jtw}^dR9M4fU>F6X zU=)mkQ7{Td!6+Ch;NLzDoj>(83dpCp^|Y?9lPf7+*{OO#Js z?qBxd-j^%O-hX~NgA^m;Zms;~xaDZpv7%XKpT4ZR@oCK$*PAYD*M18p-i&yL;0b3g zWcL`f*-h*_*F911p0)YHo6Zsc|9{`Rmq;_-ocaCo{{4Bsd+e8fx0e`F9&d z@BVpjb#c?}A5Z7+-}T}9x9^*YG{fewYW16%Z|u7F zXB|;Stk)O+SNZPU^242Jyo<{;{=EP8_35)6#e2NA`}s^>_lc+!vq(_s|&oIwD zlqys{d)epDo1i|`*tT1G~@44;gr`oOfT7r51rsSch2eVvlS4DmyzpN@9A8eu#>PmrXJx;XJvWG zka3iYzoDaXM+icycf*V2fBzB_9=Wf6rKB=298SA@>MiR$a&j);CH7yeM;I8IPb$=Q zkyUoQ`rXTLJnIz$gJ7FZ%f_5s(oMMV>L3F{=ILKR=8EYHOpG6_B-w}qhk(S}w?K0k zOm$Zq?XG#?L9!90K;lj&kXXL8>u-VW(kBnd3Xfw&Kp&}WJBkmC%)BMA1Aw;#zdV#)?2&X#0~n+-{GN1INx1^~^V VIsS<;uLJ-9002ovPDHLkV1hd0ZAAb8 literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSC3C7.png b/wadsrc/static/sprites/dogs/DOGSC3C7.png deleted file mode 100644 index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>{EQwq>IVTrzO)xkk6B`Z%cTX@?LNZZ2ETL&Ui(WadaYBq+G^%h$ zsct}ZQ#O=fIX@~HH6<8WMK*CtE0<XhzepNLw z9u9w6KcsO@GbS5FJTw^+3^^|*Wm7|nV?}yhMjsOiV@*7QST%A^GD9^eQ9v|2CKfp{ zDQQI~W=AhdF&#fMC|5@~v2{gEKsIMWCsai>P(3dl5(!2;HokpHuW?6GK{HJ~GJR1l zJuxUqGa@!ECcAx2G$RysTSY-SH8LL_HA#0(4F;GchkcIW#jW zBbjJHEGZ@}Dkdi+A(UuDD zC^#t_PeeN?8xSWR7&$U6R6Hms84Y?*Ej1tyPCztTJ||v2Bym(cM?yV9Ix~-AJw!V- zr)@t^MLkR~87UYGIW{y-L_AP38bd!gI5smdDkPO*J0uhcE*%d=K|4D)Ha|N$L_a%0 zJvu)p6+AmROhrIeHXS`WI9E3xLOeG;CKEL>E}v{fEE^9zC>Wb&JEUztB^L~=aX~pP zBfWe`A{i1N6%CGDHJD^MD;f=8Jt0XyH(*3AW==glHZVgxHex>`KsYg0NjyF}IY&V| zH#0CdG%`RuI6F5oj%7wkL_s(r5ko*dvvx*9JvcKT5IiIjkzO}GCKE_IF-Jf-Mm{($ z8w^cBH#;{pLOwe`IyE~vH#adW07Lhg00001bW%=J06^y0W&i*Jg-Jv~R9M4fU>F6X zU=)mkQ7{Td!6+Cxpc_PdpvVY!4F-nRO%xfiWf}v6);fxexTSD^y1XVOCNwOVsyJmK zMUF6?F?F`m_a9G_$v2|WY`w}9lV2Y{CI2Lhwt+lyT z+Ap`?M~&LG_g+yBp>KKb?S#mm=+{+;^sC-eBfXp#eU z{)5?Go@-|^~T-23-iPaNG5Num+qw;jGLSoF>BW$?>qZ{NQEzV+VI7q6a>WW?hS zmn+w;_4WDxde7SvM-Rq6iCXwz?w{ZP=8#~-mfO49EGOPyv*T6#$1^`R#w=UB;#>Pn z-FX`x5o^SReIJ_Cu1u7aef0Nb?wS8-NjF?CES{gXaptVQONcb$Q?^H^7z3Zsw|kq@ zUY{%6o4#^C!*(70$q$SS=FTG0jCXS4SNSh+whK;P{=cO3=7Aod*v%V@rW&=_<#F@d{)pmi4U8?sEkloj}4J>A? zw=^L1OMWqtMhJZAyUD@E+z(=Z?mZ0?-hb!p$yH^<86kZ8CqsQzMR_HVEq(VcIXO+V z186%da|L5F1H(ntUE~;X^)Zm>VY=L1-g2X66g-(vE!6tiMxuelmoepqkHH*q+p_C~#{TFBvqa0>H^ zt!%&1Lzg>=_N924N!?Xt9$aHDbI~3%x;7ukej_`*b9Mq;c%4>LHhyMh2@l1fTU;IJZ7EKiP8OEctB380W75THnoVGUBr(vlNN zNMj-qjWUOT0d8yzfoQcVnJ_L?l@ce-NZI3sTk{pQW(BHMk%*RnG!&}NNJ)|jq6ECS z>?CfrF*Ai9P2=!tOBSY8F*KorR6Cb}vZQDNM`%5cKw5^@T1x z6exEPg*Ljvtf?+EwlC8c>!nr-%NE2y8U>`tl1sA*Kx)#XGy&%bxn>eIQF@XT6LeEm_${zE4_|GRb8HxoEI z-EFw`zQgxsK5JpNC^-J~=8*4;;NxRI#w*@8m43JC*6^$27m=z5rvr}3%^k1j-`wtZ z)d)|W`R1MX$^8fVm#I|SAjunOT{gS8{q3Ds!I=r3;UaY8xbjKx??+!EX})0a+4In{ z++uRRGBtVrb+hyQiQr72uXg&xi{le?YC&+=YwdWyaX`cyz47PUAJ&f}nCCYj=CY6Z zEMDXP;QNYyhLc7wMgHeLw~wuTwH9*` z)cY`L*tw#vsV%H}!!q)@+~_g|rz7?YPX+IZoqO>1dw+$m b?pwg=I{nqe#MsZ5*laltYk?)eRBrnprbD^d literal 155 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 literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSD1.png b/wadsrc/static/sprites/dogs/DOGSD1.png index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..e704b3f316d7d35087026ce20f1ac0a070aff3c6 100644 GIT binary patch literal 1311 zcmWNQc}$ZB0L8oE2ecJ>P)culAGEan+OHR-*JtV1LR+A)a#WBO9FkH%M6d>R7B;IA z5fM>5SUl%JRal0{4v%PbCTxpw(IrznrZdaNHsY~FWc}m4-^=^=s!kzh*_>CK(CP?DUa;O9S-v?aNu+2*mKQ0E7+?}7jdm4YgBR~99E zyYfpy1L4bdp&_ zYOSyMBw&)z@$A&p8k4Zfl268CI6x{DpYF2i`l_@|c3Gke-WJgE$rvFGzr9wy&YQ1d zW%9Byg#x08mdPfj9c(rZHyVe7MivoWBqirjm&O9dJSujy$#AOOR&C@s_+%O>v$qU{ zwK9-}GYLrsrFdtvy(j3&qhR!W(wY)UGc5eP)RdEwBIjgt*({q%0I`WDB9*${HiLSS!>B zsO2_|RW0`GSiL?)ImG(Z4~i*Ew^XajtzfHJG7!*M#AFF=>Aq%obEVR6;06lV3?f=c z$vD_z+PT8ehKRy;kst?K3es#KKaY-UbBaT-sMM?+YAE1SaYjBdzQWR3=dr5=RYiI+ zgWxqOhw8P(I!T!YJhx_l~(h_PMTQ7oyHGivrPz zG!QFSVjNe+l(AU=SU)HOhF;`WG}xo;`0~{|KIFw9JC)L59o z*Ub@XgwObbn{OALrx#auKRWgY?w0DX+#=wpjszE8n!?}KT`bx|*fci3>uy+g;Frs% zB9CY8G*SPVJ}a0$xp?LMy@?gloH_2D_)Oxjn~zEoiHJfXOVrvAA@4WLEqpUui?ozG zJ5~Wv*1r2{>b1_PsdV0*_{*u|GyUhz)G=hYRiT;PE$S-+3a>x0qlpUkygnLj_-x|h zzL$#0f$BHy?}f^z`_+Ay(`p>84=(`UPX^z%!+QvU>ByF;KcC)GJ^AtK^^WdVO^t(L z>SoL&46Z$do=v|-F^%IFJoQ8K&mKrA^RMWt?GvLNKQH!>rj-xBV@6i~ghrwM=I{9L SMhA|UToC0d^4b${L+pPFcA+-_ literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>%HF{S%Og}bvR5x~1J1rXYD_gH84yA;C52TmB^V8?a6*+~H;i98bxbYAflOXKB#T=$KPMDFC>B67 zC^|4FKP?_PCKXpV9ZxYDf>$(%Su}J?DOE!>&xumHdr4_UDUV<|PCqhJK{c0RI&@Ai zWkV-YJSka5HK1)mcuy@uD;GT`6K6ywC>IGV8Vhq#H!UhDX-F+KB^Y2mBC>TvTRkKf z5DH5}J#JAtH8U?gHZPE3K1o77FfJ=MG%+eAAUifPPDDH>BqBI7FOy_Hs&7F+DjBwT zMvh!HMKK~ZAP}NzJ!C~Lq-#EfRx&~;6fz(YhFUj)Q!j{JI!rt-SUV&z9uIIxC^jJy zQ$R2+9TAOQH$y)=J~}o?JTf~tH8U|UFdYpn8xAEF2~jj2NI+}DmpVRGan8* zBN90y5`9oDPe3#&84P_^HZ~y;Er|%Q00001bW%=J06^y0W&i*Jcu7P-R9M4fU>F6X zU=)mkQ7{Td!6+C?;0|Tluk$c47*J%wPwox|sksyx(aX|ugIAIwBicHdFLV5-zyRS^ zPA(?4CJIdGo*>4`e(kcH%5AcZm~>UJuj|TW<*ysJk)^+pZ=$FWf6p!1f9g~0{l6xX zVMIg27YUL6nRlkB8QT5(^Z5H0(v47Rlo4;gH+_}Syt_NX6ThFVtga&2jOJ!(0foB@ zo-g$aOW61)>q}YQg>xhtp`j?R`g6~Z|IhEo$88II`!@5~>(>`k-=8=SlskLrQbk=o zVKc5S1d;i_jGu(=o9*-G#j(>9znnXB;@z3-_iru~pFVzyXxF6N*y;Pva{ckI!9gMa zI`_XzPI~k0>)V2o(w9UV5&P}ilC6&(o$`LPee$bkQQzOZo^)0Tc6IK*pz=_osfEF=qksl}P&ULtw^H<7-zoe+02U zJ!N2c`GDvWHRIO39}w34<%egkgNr}i@qtJay5^?Am`@&BUt5N#U;>CV;nm?)i27h{ z&nz-ZzuFo&^T~%bwv^Saw_G0DxKd_>+o3hvcTw0v`04)dKZQm_?)x>`(xNK>0C|od UPpqU@^Z)<=07*qoM6N<$f~-7ADgXcg literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSD2D8.png b/wadsrc/static/sprites/dogs/DOGSD2D8.png deleted file mode 100644 index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 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 literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSD4D6.png b/wadsrc/static/sprites/dogs/DOGSD4D6.png deleted file mode 100644 index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>H89*-yR zxb0a%T7z;eTO6ESu2O#x%c?h6%7Rn`Wu2Y&HUzn(+LCVJ@y_;!zAatK<1OZ8`f?mW zzuFCM%0c=|i5v$R6TX~;zzm~wom(3yq|~wDEDkXw?BIyjOt8jdu(70E8cC}~8LUYa z6}pnq*E+Qp0yZYeN-c?jLNY=qa9e1nnVRXzB@knMI;@e$HF;B05~2^+yUiHr;&2E^ z4kiX_U9duYw>K9v0XSl^GAN)+VNtLxkNUPFt*014K^Ts7FnJN|B&eDqxdg>?7y49I(HPU=kxBWfZ0m8dmU=Bw`jmq;*0US! z6bf-PiKCE26k^gRr$_~wL^%b6`nWKfKrA%Q(qsXiuqjjD>`fVMvaR+~@zPir&|$_@ z2-Lv_J&vLB$Pg>0?_cYzb?a?3hRB7h%s`h@Y#H`6BR4j#OnqiK{ z84`;K=NFL)>KJ~xSry0z*D#8}N`OujANSLJCD?eYdlkAODTaTroXACGep_OrCpiz3 zNCKrzDHMrWS&GAqG=-CDu}UtB770`mF+-DP64gq>7)>-s z5f0LX88lV~Q!5gJN9xQ&-FgY35|1=klGIAnsAma;K%p#HwyOYgQYH-0FiB#QOaL2n zuw2xf%Xk>n%RO{tq@Js=sO8auRB0%Rz#Iu5^D`$K%$QP)p)d-WhSxHKRTK#5 zI0BkzbD2Org@6nOnYEEPitJm1N+QEa46)G&C=0W(gq^``43R7m&=`Ece!VC71B*6h zWn}Zrvolq}ecWTWHzQFj5t z=b!J*s<409-t79*u&evzy2o|3HN#UoP7U3D`g(Ju#CUw{%jd6)(|j}Ye>XMF9cA{% zHa?twyU-fwU8A|*RrE<@w(e#hD$=)Y;>pU>w^a0Zgh0n_$-bwg^ zyQiA&@;ILN03X=6%Wt@sw`4E6wZ8SY1FzmZ)?GPqXYS{|YWwiE(MyMJP}!5OlZk9# zPi0r%(CP8vi>EqwZZ>at>N?kbbMJ!#!c{kOjPTbl-n~7Vs#*wrw%(KWgTE-hy`wF6 z>`uYnlZsDtzY$qfI@0JhTZTrvrlXjpbXziaL_y@NSEou9A zBw!didvx&F&8)JH@4~7ozZvX!MiEZBW8u{=5!&|qPXZO+PwfuB0nSdG&zmw`yEi4c zQGDq|T!C{_qoC9H>6t=Hzv!x^6r9~R{#AuUB#Q_uZ}@m}|E1H?ILZ5!XMVddNUJV0 zy<5QBsl~3Ut1&N?3D@#3bf^ZLkD}_fgAE-MmJ!jFvAX#Bvc2!|+A9aok^WnQ!9sZ+ LM}~dWTC(+j+f%US literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>HR6;SOY(Gji zC7NS8DIptlQZ-#iHbpfkB^?)pUqL!CEOt^fTRkSTc1JugCW>4+qj5=KO+7j;C4*Kn zy?jYmJtu!vG|7cdHYXY-6$l#>4RA{?J~JqgU^X`}Cr~{tI3f@|H!^rrHeNj=b51Zy zKQmE9Ici8RWkV=vP&>eYO>kI6M?5xkSVXXOM=U8OK|MHeNGe!29zZlHwtGr$OD=j& zEJraOa#cRAcuGDtFib%6$M>;Q1IVV&^H(yISWI!WYKPs_wM5=E=gjh9DG8{T25o${@ zSU@g0BojF!5k535cU3%DIUgbx3^p_`Bo_@oDj1_`Jy=OQM?5rZMJ8lSJ5VNn zFnd!pT17T=N-HWJ6f!9xR68gu8xB@C9XvTVIy5g!KR72C3`jpZML;@dNG>%X4}4H9 z&4*DkFDpSmJV!w~E*lI)Ks`1f4<8Z-NJBt9J2*NxHbFo=L_9S$GcZ9sI%!5LoMk#j zKt4!7IYK=-FDxiaL_WHDM|)B*NHimAQ9eyD8Lo3fh*&a_Xhvc_A|ezBKR7cY6$(E# zE;cbOY*RlwHZw&l7DYQViCHo=E+=3;A(34*NIo_x8Vx%o5*!r|cug!wLOmK03NIWD zHZw6mJ2x{P4nimtJUBEeCnGf>5jG(YepE6j7YdDBHAFr*JR}i1H84RvI6pl)J|+`6 zHZ(doH!d6x9~KURSvWH=E+!TUEVGuZ00001bW%=J06^y0W&i*JkV!;AR9M4fU>F6X zU=)mkQ7{Td!6+EPU<(k3Qf5S$55w~Xt0*$!_g~j_4ofLA;(w)E|H^xm`D97ojTY_2 z6d15(#s;mkd&sy!<|O z?ZgMunswCQIn5%&fEPbkAAfpfq5T6#^JPWOO{5!e;`qM3PhakwJaKZ#w9<#<_#ye{ zuhrj=@1JEbVXE;)($nVKH$M+1{(AZO_-d0GJ%;+z`#VTA;oq;FCyyWc`R2u&uh+|3 zjP(9aAy#M4r0Z|~{rk6O>t4H)>$iP>di404yLXj^Pi^^BM}+P`|BDxGZitqb-Tr)S z`jViv$Bu1F*t21ucl#fK!c(U{JtD%0+3qg379tmUxvuf$7N7B4e*3}E<57q9FKQQR zy2B*+;W-gTyx)9bK@I<3&RlMeoSE}Hg5wW--v09YzeNR=*_T+ePJbjSAYOf$*O|{V z_fO8%tCu^L-A(!${q^8iRTk#PFIneL6C0YlHx=cyJ!E)S_kYLAl(#3Y-&|yOrKI$o z?EJ1dB*y6bN4uWyc=#vg?bb=n1qy7x8S>aakYvEEcPi&@{lA>f@bK|+rQ(MAGrt+m z-OnS%gw~2$v(9H<2hwU?D{g=x*{F`0EM|KU4e*VmH+?%07*qoM6N<$f;P`Zo&W#< literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSD7.png b/wadsrc/static/sprites/dogs/DOGSD7.png new file mode 100644 index 0000000000000000000000000000000000000000..febb03f610897ed3bfa3dd6bb4e0a0f303231e77 GIT binary patch literal 1573 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 FV1o6BFSY;x literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/dogs/DOGSE1.png b/wadsrc/static/sprites/dogs/DOGSE1.png index 145d202ee60c4b0ab7df6edb9db0305bfed9c870..5523039751a53acbd79d5b0d3f5f95f9868d8bf6 100644 GIT binary patch literal 1362 zcmV-Y1+DstP)~GanDLc13_yGh{&}J}4HibVhelG%z6) zLoy_da$QC*99~K|YgR{#TR3S{LP0PiepE4?XgzLBG>~#xUPm-*OEY9dDRfdcUO_33 zT{b%<6Le58QbRU2CL2&cGP!z3lw>}igKLv^VTfHjbzMkCG9y4J6}5LoWk)PhHXuwk zB{?e|SUV#}F(5rF95N>!G%6omK_^x|D_KA(CmazjEG!ol6D=SVkaJr}FB*|zJZ4Wi zJ2o&95)y7nFfS@45e^JCHa1~HEr4WAlzL+{A{0$JDt=cuHzO2BHYrp$BUwHuYEnOe zXjOt{P=Z%BOf(`S1_vt%2?qrPA_WE|4GCOAE|O$EED#HiU_6#$ISL2}R!BTQG%FAg z4QNj~9vT*LR6SZfCO<77TRtN!9TGex6Hz@Zk6$`*Sw&Jc9!fqn4G0BeK_wp;5m-k$ zF(4DHaYIZ!GA|qrUqB}n5DiZ=9xfaXb5JrE5)6G+HgQTTCm0N>Z$YqiMQ%kVi&`@n z5DF+74~AMbsc=DpQ!js3HilR;d`~P|L@*&45>+=JJ2EOqIxiCt4ZnU!&52SmDkOAS zLO?bxfL=szSw^LCN^C|aH83d|78OlDGcqL_b4)EYE+{xE9*ti*e`ZlSEh1)HQlxK1 z$AnHQ91>4DDkT;QGbS3Yazd1GR-bG`%!f~XQ7>XfE-o7ki(*34ic_g?K(}~Cc2zo1 zGaH6hF|&0>RyQ6sArP^1Ln|2zGanEl6$&*X5}Rf_Fdh&@EgVTVBvCmfhg>?Xa6y4t zIeb<(Ry-&w91jc#20||&IVc-YJuZD>OFkwOUPUk<5(bc8Hc&w{J0ud7U^hP}6fzzT zBNz~FO)@zn5F6X zU=)mkQ7{Td0Uf|0icL7Y3ru~Yz=)5VmH^3@8+KA)#!_2{yY_aA)>B}F)1}*1)|Z?q z35@G6Y%CmI{3tP^#Mjl*J+PD#BeL>+-28LiQes4HZgxOkK{X{tysEpEe5+;_B}TL- zCZ%SiJfXyho6qCZGhf}Lz=YPn_dowT^X2b6vQ1d{qV4yMgv&)$oomT7Vdb2%cP$Un z9t8cqznDxT=9Zh?o_VkEp0}yz-4)~+QE@FIvhr8(FB9pD*E-0|AmO1m;zB$Om6fE7 zy~r}*51;n$sF+wI$zLzk#0;__IT;moRawQ?_NyFc7~gC!eZ$cFv%8P1Vn>99^W?b?AN~QE7pC?;BF6|bLAJC18TNyi zlV)6fN{$gv%um6X6Z^kSCM#_%m=9z1O!#_*EF(5=fw7)XpE8XsBX;kBvHm@L_Ma>x z4jhCt*SsSyvmZHr4948{o;)MIe1^Mz-(K>J`2HQv{PvYRBYqr3Fi(s&8b=fW08W{- UV(+o+TL1t607*qoM6N<$g8LQOj{pDw literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>qOG`Q|Zb~khaZqSQDRWRX ze_1(>XiG&f9&}VWL^2|serJ1NOHMs7Wl1oiZACRA6t{dyX-6t79uqGpAsY_|SVl96 zVnc>rK#gKRm}NYkYefP90kU{VT2DrlV>@k8IfZ9Wq;5f0Nj)JG2fcq#d|N_XN<6W2 zMMgI*WI`q<7YcP(KW7w69veF(5;$7dJC7XGSYVG$%SNAcIvh zvUNm~UN#B|2w6BDDIF3?JTj7CIV1)LtZ_oEb4GbnH%&7glx9JgXF#fOL55yCplLmU zQ!i>qDw%CcDHjTRS36HYGczR_sC7+QadPjP%&vtG`4p} zP&OZYP%Shi8jM;rLq0h}G$$Y%7H~)@j$AcQJS|W-B{MH8vvx;bMly+8ICf1fHYpx{ zW>7dcG%g+yU_>q?8WATXA)aSEj$b=aGaM);BtJAO!GBC-K_fUL5-A!ERyQ6?G$FHg zMoBs^Fdq=8az~P7K)icNHzE>oP&PFo5n4w#c~UciRy0RIIYBNTLpU(Fc}FuI4q-kb zFdYrKdPqSh6hSH%L@E|?OfJ8DN^DIuqiQ~ZS~;9(K5R!SIx;MlVmPO5Ku|UzW=AfK zT{kZq3^^hZPB0laArNmzCo~@qsodO|00001bW%=J06^y0W&i*JcS%G+R9M4fU>F6X zU=)mkQ7{Td!Jr2}SAxh!N{ld=#lTQ?w1EN>1a=;I95dr91tx6Uwm?DOa~}mJbZ=qp z;_vMBAm4;_$6Gii-R|g*Cffu~cIKPcHZS6J-gll%6PlV@*=Ah(!1MmcruP-(8KK9= z%`~xj>*wze9^O4zMxGh%?OZI|XaC+3v2pL0jC`_;c)k41?+id{yFMY?kgFR$p1w78Q|r9@zK_T>BKu(Q$B!n4cjv8ov?HyAEF-2b^RhGQ z`80LCrNjLFnWxAxqF}{QV>!wGTazbS*gr`>N0u`zSILS#xO+?S=7G6CqE786$B5(d zLedfo+di(m{cZOy7r$fGq#I#-eVWYs_abdezs-E!qBeiWG15Kr=b50el(<;uOPxc1 zls0HQ^3NsNh}llRu0OuFWWuL85C7j$nYGOHOCE_PRKD&0#lWz7&4CFIKmT3by!Mvn zie03Z;Ga{b0MohdqMwKF{8xY8p{#v9XeUV~Wc5u1I)dSzxz$&n-)5@!X3o{J4lE|g zh!0=?fij!p)47ZP0vR_p_IB;Pbdn?^zAgC!jFhL|i5qv!Cu3;!rIV*9&)FGgFBLjwQ+c$69_ T_wWy300000NkvXXu0mjf`aC>5 literal 155 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 literal 155 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 Eg191PI{*Lx literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>TP)KsFc_6|r|j zdr>cMNGjNmR0|3S7!eFgKt7{wK#gEKcu_K7Jt0p%Ggm`0nrlXWT|#F|G=5e&gA} z5l%)vCmIlpT{(<%UUOVWKQt?DQ8%o1OC$vc9vKunG%Qat99~O2MKmW%IVxmBDQizS z9U2)J6%l1nKXFMYj$Jka0Rbil2stw@N;DxpDHlX99zZA+B_bUpAssd>BQh^7MmjM+ zGbk-4AT1~+J1rn8DJM@c8W0Bpa!DviEf+a6Ef)&}aY-pUF)5E;IA1*>cugz0c}HzW zC$V%yUsOvtD<7V1M?)Znnr1zI zQ!-6HGDSNxXh<(YI5ICF6l_Q=K`0YYCt|J8%;JN1_T3^V>^&$ zMrcGQWke}lMKV4xBs(%HJ~}o=D;6RX2dHg9R6Z&*B^psWCNdxrOfVaSS~!SUGf6fm zK|3}e9vdka2{|MbM>{i?XG3d6Cd7eEHz5x-9}b{sJuWLMP(U+jNiQuP5-b}IlwdYV zFB(%c8#yBpj9@*IUp7W98JlQ8mS#bAQZ`pWEki06XhkZlaY1}mHZmR$Zb>UOAP`_i zGFC=7hFCN(9}zk!95*&KVM#Y^Of*nEEn+_-A{P%jH#Ac}FN9t{N4JR}l}TQ!woIWZj#kZF6X zU=)mkQ7{Td0lmPV-xM1$qpXu+Gc*ergsLbr;<&J&K%o+4W_;lLvZnG@AtgreSM!vy zJ*e4Ez6mKd`rA^If=A#E>m=N*2>(c2nJ5^4cP@P%f_mmt*#7F-8_geqV=d^1{|FRI|9|CW7O@6o9!R_XXr0B^j-m-0%2!?f zC!YTXB)skZrXxRyGT`p#$9KMeJ$GvTlshNn&oeNTeA>8M4=nR5`^c+{#2E4E+rc%P z6V`uZn11b&0x)m>x>^7B?SF_FKY#ywwvPxiE+5|h;4qN(I@|vV7zoG9KQ*?%^zF_0 zk-Pf~u_1Eu-O@)Ffb^-Oe}1$|!9@4G`1w1JSR-CN`I-QtkCm4EIj#GaoGkYD-dZqy zs`MzsuFtjP7~y~SJ(%vC-^DOvy3-;uj5u$5x)~h0%Qges7q1>~B*Tn%&uqYSi0MQi zx%fXBMg+W`4QUsI2CO8r9{u^YwdELPEsD!4|NZ;VFbakw002g>FJ8sb!9D;0002ov JPDHLkV1mj_Qp*4U literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>`PmMJ^jD91w0@Of@MTbW%4T6bx=wLrO6oN;W4qB^P#G zM@KOqSvn#a6Ag)AKyO=1iEUV$c3YoqLwZ?0nRQo@bzE~%H;G(0nS5qjL^6F;HH~IQ zlVm@OT{($=9hHW}07mi>$a7rwRS~H7YJZ3^AJt!84TQ^@tFnCltdQ&x2Hy>*6Ml?Pu8m)0cQ$H|kSVwhUOp#|rOgSnM4-RHTC}c)5UO*>F zHYZ_0Cp{$+D;f+oArM71D6n%wqH;=3JT7HHByChaa$r$ABM~ z9y%oxAruK@Sx=W_J%L#{S3fQt77jZk5+fE1FC7kCJ0UF`4yJ8CKrkeqXFZ{5Jue;* zT|OjDF&nadQH57BRXZoOc1DC*I5;8^G#?HJ2L(GUAV4uCLP9|y1_qdCKuR_xI4B)x zNiZ}a5-S`KXhtkyOgfEYLVspbmwI7(VN5$G6*?vrhHO`yWjm#8KW0KGQaUMaNGgL> zFIJd9u8(jD_%Sz zNjNEwUNF6X zU=)mkQ7{Td1lUQj3Cp&TulLgoF!gXL`9@5?X9py&%vnHz7wnC+ziJv!m`#BZCLi`4 z*|-02KLtjdI4UE?FRt~B0wZLlCD;XcrF1EYPf0c|ZVu){$0#sDRA?_N6OYJo3XC|% z!YI6#Q-=~){MHlv|Nnr(FA9t>J$QhRPhC!t0wZkyt7)hz|2MQG--z<#|CQwb8{D-a z+k~6HKAPWGIef)Bx|B>4dT$!uh_%o+vpVVd;Q@I@v}9!*c@cB+tgEA!`yuj-$Sf-U zP*Q#R^cj~^KBumcW5Umzg1+3svlkpZoV|VH>c}zTUw-n{>v?6B7tTC%x^;;xSFB2n zx}1HqwX-VGEg?Ov_7xdMe2n~ZG39#Cy{?M*6PIfGrjTJoz{{|}V@Y=&J?gl9{$l8) zKV%s3JS1pJ_~Wmy-@LeeU;LIVBYt+bLs?6H{{2pt5mRr4 zLRqUf|JzKK5r1dhg|gQCT1j3;{q`Bg`o8KLc}8s63S+HXOJ*6qeFu#7{@E(>jClDD zZp4b`>h3G4oLt2vP#W`6&lag00000NkvXXu0mjf DRoLfn literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>22oVbhzJO072L~bw z2XItAcV0(aPfaKW2xvkjhAuD#0|RefQLAf1qEkJIHZj3~OHel-5)u*{5C=UF5qecS zY%?dLZ$*7jEmSoelw&+PC>qglV?%adO=nU-UrjxFTSSz2V2Wx^dQvp8 zeN=>JP;yc@j&WG2azl7oL9~BYlW0X{Niuw2NM1%Vw3T{}Wkq;hN0etnG$IvZMlWzt zIbusWj$u1yO*ct6Dp@@zgjh6dN-lX@KtnSpM>;TeR6MbGN^ws!DjN`5MKU%nDVS+S zPe(yfKQ1^T5>rP!Q9&|XKq`r4Ns3%JpKL;7K_^-~B}q9gMKvo*FB%vZ7kpMXNV9BWK7Djya;HZLU=2sk4YP%;`F7ZO4%87UbI9T5m07!xWdBs?k`Eh;KKIW`dw z4R1^^D#qK_LWduZ(SxWI$g^J61U%eo`-dQ!<=tL{~;RW`4Ng5T9~BNG7Ysip6FV|1C?g*=GA}bLB)fY_sBuOV5e~0*NmN5NiCQy& zR54#ZBttPGmuNybFeq(LHpYTZkY6{VYd$9#559d#LpUx}K{A9|Ih<%eNi-uwD;F;$ z93~eEJTWO-IUqGE9X%xzF&+=4Z9tS@IE`I5G93*s z91S`n5iA=GHX;%=AP_Vk4lo@J{C8WL00001bW%=J06^y0W&i*Jtw}^dR9M69)@4i^ zQ2+<%dw3wg`g`|n1oXSkbgM|6QLGb?b3-!sI5NXdGa&{ zKzEwm;$ntlBL<>OXL@nDt4;m|P@qt4^zihlj3xV>vd`QC6251uPgG48&}JQQa3~@+ zg9sCbX^+YoC(MoVDK#aAB-8^KGc?DJ898E#uhEgiMTWK&XX}C1GIYpfQg6*6r+tQI zX10YO!p!lL5RE!HZ_m1o7T&)qK&CO<8c%-jtquCbU7Yu7J>QBD+*#uIaQ)uUR+D+8vug7AbVMcfF`=?7nz(``>ORV z0sYvLHCkD7GE^5X;;@2CN}_V_v$=_>?SxiB8)~9~NpoXb=gE; zJl3^J=WtX@hz)k@ruK>doWoLyO42})nTskTjL;CgoR8Gxzb{buk{3O7{iVy2*%1!( zlFFn>@sfdM$@$lBM0A6FvRz$Vc;G1EKhO>W{By_x2XC(3%ML)o_tR%ZkypP5BpSbv z6~!aU1d#aJAypJj786Wp5PpLdO@{;cM35NyV5>@higEiUEEXUb34~6?x557-zX5|X VLFLLb9o+x`002ovPDHLkV1l{#IYs~g literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>fKo4>W<0TW zMca{8b4x5jOw^21 zx_U`+T1Ag(NTzg85d#8BS0t>K|MK#V@GRAE-)Su zSw}ZWFB?BD9a}^(KsGLNPBJMP5HTqskz+tYIygHlAX-K=MKB&HAQ?0(IU<2mFe@7lSwJg1D;=6_N0Mem za7rzNT|ae7Ek-sdT}U@{RXdtwJ8DEHm}WhhWp8irapS4BF& ze@duvLs3aWwR=m1TRVMm?fyKSDS#V^BX$LO5AT zK0-YiArM45Gg3x7K|3`* zIyN#eEi)btIU^A{HZ(CE4K*MSYwMHC00001bW%=J06^y0W&i*J%t=H+R9M4fU>F6X zU=)mkQ7{Td0amb$awCpXY(m+SA~On&NXr(c%z&ib`wOZmFw9r8?&ldgC!QD0ssb#U(K^W>SKv1`|XeTR4V9$RwuyU#VU z%&=0IkLY?{5(%hP8s9-nxfY%?4iLtZXC{_eQ(mt~(~$uq*O z-`r&0z+tOHp%)OuYeg6D8OZAkp(u`Rj)_(l)^W$G)42f&&+?~L_Ej4L7Th>12 zN0UxHdGe=w=3?tFAKv|Z_wMH=;-V(=Kg<0D=Fj&N6Zu7U*c|%$;Ed(0@8908{N=Is z@9ijJ1L6OJl=S3`ojaS_-~WIAr!u`}#pQ25*8lzc`u6LMB!uPT-~WIA|M&0r|M%`U z*3Fr*_{-~`H(&q!`62S&#$UhQF8CgBdBf@$oVq!7FvV}(vWx4`gZ~T+|K9(3x^vx` zN{a=z7j<1v+giRwH6t{Xvf>t!9Z9s=!JiL8Pi)KhxKP!-CL#K95$B0y0JtduNM9hs@ zArc2U91vSIA8%AYZ%s9YS2Al#F06A%hhalbJuYWcKY3X^c2hZiR55u`Fj-7NCm9ct zWx_Iyog4 zooPT*K{0$n55K%K6Y(^-2QZRE$DM&0ATuMDE7z$EHJw-Y*gIYRH zJ~2i=IYlcLlVCVnLM}u)F-1N&R7pNGF)cwT6;4GzNV~HZUtmKQ zDkUIfKqE&j7bO)4u5m-EZ$LpS8JlG~ML{|$CnRS=B%f$KAQK5lIxK!yIV2bkI3f{V zJ0M0gBV0u?QbjstPCT@BMTuH8SVc8iN9AF6X zU=)mkQ7{Td0S&=CicL7Rn_?qwT?7)z6dBP~KQ%aNH3bHoD=;r_ny`2~1xD0m)tXhD zJWh!>4ozq}**s}w9N7ja%E}x%B&~G*>%Am$jmVW;efr$H7WIE$SCH)tsm&h`e*M(^ z@BXJPYK>>l&gpyhH-`K;Q9WLA;)d7v4Ug85ZA8u0 z`HcU*KK#Dv+g@^wu>ap4K1v{NbKwKVFa+9BXf#JKgc7^VXY-CKKP? zUiRmH?BgH5Hj!q=|6L!-EIQit+6^40-FbB9+p`}(p8av3OQIpa-@i6Gvbpv0nvH9I z-nsek@r|3yzWI_KpcfoJE(uup`RDB)({E1t^ykT3lC#VEqxl~L!&iO2`{?%kg6*2*OQl!3>z<>xiLIdJ{b`(g&?!^a9s1#3ie|C1CTI#a9p zc^M959^Uq0?PP{tjl*rfNiK@z__8x*F&wa}Z{0>_<#s*qIC~mrC6HBobZa-6g%8WY z^fcBZ3=G{zyFQRxfN^D|vN1C-1YUf)kL+@kgFE#-kXjT{NwyI@FJI;ZsnF;*WE+w5 z@)RhQE!w}HY$K+4f{eJn>nZuw(vBVRl(o9nKHa@@KV?R2{=aSOK8BG206rKwf}?Hx Q#Q*>R07*qoM6N<$f_e8*8UO$Q literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>1Pdtyb$W)Rw`qb^xX7s9>6hbHADUa30P*w;|19Wcx?@vsf&) zDM^>^CF7ORZ?<>V8w-lP@N-nqb}xBeF=IpKQZMH?=v11;I@>aDy1bceI!Y3z(a1V00A1 z2@l+Bhbm3+oUr+vF#ml8uz<%&j2F@b0)v_b!E8h$7cGvB37zlEQi>x3U=Waq<3L^z zio$vdGil-o4ArQVvIJo|5T&IF97v#WJUT2uCgNj)kYy$;T?e4vP*lKQIN2#eLR|9YYRNSB+HyLdNzco*zmWhod>?*=YM6FgxzbwWOHGrsO zX+~o3b1MT%lW8Q?K+9G_9*}|IYta5+DteBtF{ktCc3f<}U z-sZiO{Yg}EQ`Vh(gI!w&w8>4Yp5pg^>ux;SwaWG2kGmtr)?l_9$x{y=>8-yog2rum z+wBVBYldg;zH;#O?>EjodpXR`iB}Xn+C{qaW*%A^f_uQuchys#gYMBoljRTFuJ;H> zvcEsLCUo3W^QPpVgp@5A}( zX8&s8@>9wFk%kZ2>ZUKRh&?wN@z{2Hz4Nmxsmbk|h7{{Hyox5Mu-oG|TU*Bqo%h;R zf^EL3xO)G_qNK4M&a=uFX0AAUqIZ1jr9ck1&uM#NUiT{R`OIiU`HiT8 zDeKmS6-|EgC+p6?jtS)V`EiCetb5f8O#H04`ggmmBPOPDe>C6XLINCpuDF2(aWm78 y|7|y)9F2HBSsc`H*duI-<~N4yG2~o6?!#I+{L8Iv!98=l?O>Vo7Tp=fR`)*vD*BrM literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>zQ$A=qc zHY#UFElNExeN!=2Iwo64H$^WVid;68YerH*G@EBav3N_1U_UJ!50hm15)4mCL^m@rH7zMNBo?V~LRv*LJ~b{sDHkat9y%%;9~~ST4+mR1 zA1fjoEi5WSK|nz$6HqoGAs-x0F&b(}EtX|ICl(1pDi=B<5zdHEZAK@6Q!uY}Mk*Z> zyn9HbYd~vDGJ#h$C>RTpUp5sF3o;%KKPwzlL^pO$F0FAweONneQ#@crE^bjdU_vWT zJuX&CKN}MaUrjzpK{`@39#BL&i(NTDIWt^KJW4}6pJ_i&MLbACIzKTcLp(J~J~fkI zH%U4#MLjkt9u-VQKs`4wJ~JvoIyOW(F-JQvKRGr?LOwJwEE>}Ax#)3_oW;<<1C`m#)OhP$_STaXJ zJUJv0ML#?`G%q|P5j-?4bV?~pL_ReyD{Dn2IW{wdRxlF6X zU=)mkQ7{Td0X@MM%8j@{! z@cHA7-j2?5u0DK7juB^07w-S|%PYQdUoUc!4s$MrL5TcvDI%EsV1zv_v-o4wMpNfJbSQrcj|`UcM^8pC(VSAd$*52 zIT*h3?%nObUgi8}Xuq}d>HGJjm=O5&UdY}D`y%H}UH1IUk9Qk@LjOuXmVGXtah_Ns z0)l?r4hh|{>dX4?>%W}J2aEmrbL{20O5#et`OB@>eY^SN$m+0&+cSkOd+x}F$y5+m zZ1wn9=`EaPv@m4%r>Ld6f_$B76Jtq?iVG%&=EkP|Ho>3v>|tPNW^L-3SWlu6{+kSH zEiCnY6LY}~GtrLl7QQ-HeVF(i7&Lnn#BZ9R@RNIJsEr$;e&z z{i3f!ShW|bxtS-EVZ_TzTiYS5&(&-kZRF(fe|~vTBNkoY`9xMpQ}nR-5wu;w+e&7U z`Qbd&|J__&WE!#Pz+b2l4VTDu#mB#pYNyWQJ_CgyZPPAFjre@-=TC-FKr8?N0pJvE Tt{~Q$00000NkvXXu0mjfv`;w7 literal 155 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 pJzX6=X|*r5QbMWBOMqv zBNatADsV?9H83eVGAl105i>I{YDOqjIww6kHfBdIJvA>H6c9c$DH{_DIV~h(KP5IS zBpn$SQ#~pi77z#r20Sk$B_JC|G$Uh4HgZcX84dE-Q>&He){`o@+;cSUNH*CPX?iyM9kNH#8a# z2N)3y84(IiF&s`uLu^GS5)KTa877L_nJ}w&!kX<%kJRw>_FST|>XHPmiG%iLxHk@TUVNO086An#8Kxs!Tdr>bR z5(qFP8dOF(fmSs{KR8T0Ffk$*GawOKJ0mtTFFH0eOD`EoE*L&FFpga|K07xkBq2F9 zF;qxDNkcv~GA}?pIUgAlM?*hTH60uk4kjZYMJ^jaI5IjjE^kgULp?S_F(ED|AwfVr zMLjrrPb^V094aU!C>IMc9u6oM2_g~(H83n^K_q!iEH*VXAQcTgI5RssH$gr+VL>Ng zKO{*tB!W~hI4K=JH7-vw8j@f+Gb|@aEf+5-Bbj76K{hTqGcQ&-A|MnBB^C;BNh_3L zH%vo3GcPMpM?E_>F(VfZb4w~qL_aVb4NXEiK0G=x9u7n*6>38zlVCSHH#0FXEae$K|Mr4K9yoQG#?Hs8xA`q6DlSnKRY!f6bL;f5=KEhLOeG{KRHA|JUu%&KqnJF zCKIS{K{GHcIU*1`H#I;#JV8G^=msYq00001bW%=J06^y0W&i*Jdr3q=R9M4fU>F6X zU=)mkQ7{Td!6+aD%w5lLX%Z78*!$G>)1qBj;lT78nEu>^{G7U zCtmc=oj{%en-1RG@O3hCM;rIbpX8a4^)zbBlADt|SlBq#$TK1P%k`kT<39Q+>r@AKmOZu3F|Z)2^IWfF{d zk`V`GmH&P4@70zKM!(O^yw-mF@xB;hjYy9V+X$jpr+!%W?d89J3l{2VJlfhl;nNSI z6UC#~r>FQZFa+;;_VjttxBquv{?-5e@s#@2ImCP9(-B{Pdk5{`&IOt8ag2 z{r>n-+u#!MM!dP?x8BL>{kiw+a_`=M{{8UF0QU=qSI%0_+)K0(_qI9q+nAj@^M3o% zTla5$P5Cl=&jsUm_kzyexkI!W$*YzNY+7h>;kSu*#M)b5KFpFnsWpS)-lsK3u5BgO zjN9S1y{pVkCrw|TwCBdG*^4erlhI^g`1tV0bmBNRg2{-gyKi=D}(JKHd{#81eY%wgMRYl-TKB z(oLu=-dhOgoEPC2C*6qGHCNvvj1Uqf!ym8DuS9T;i(OkovI&oVRRke;uE)EbNj75Z zuc{YF+*41|NH(JOS2YTM{*#tg5{;<)bpVC`v*{i&=Zn#1*^mVQ X5?CKyLiC_A00000NkvXXu0mjf!|*V2 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>Rne7Y&_gKYLw6EFKbVO)_3cHb*!tPCPJ1IWD(=R9;R$VN5-NQ!hR-CX{7B zh+sk`2nb6?L62WJT~SG3L@`l1Cm#_8PCG1(UO9PFG+;XKs`7xMm{!VOgJ_Z4?`&wL^&`V4+Y1AO@C7|jbA*EW<^s=LX~Abe_B09H70UN zDT-e_UO*>JI3`jw9z8lZE-NT79S&_qCqye5PB9v~c}Q|fDPSKTf>kdi8W6X9O>ajh z5DpBebV!9(GB_?JiC{h_9~vAQ8BRPcbWbc53ImH=ID=U@$%ayoTs2fXCssWvRYERr zOE6kSHAF8Sq;5iRQ8*_U4P8DXQ9CL>EFObiKW2G*>zzG%6xbKQbT{3!G;=J}MejHy?>(M}AZ? zM?ExBLpLoN3@{!KSvw;~KRAh9IZr}0NiiKoKs+rR4<;50Mlc>kH7QK{+vUP&AWZH&{U~Q#Bn!IyOH(J48M>XF(-eIUuKSLJ|%NS34s$F)cMN zCrU0DQ$R2p5ei2x8zv(kHZ?LZE-fx8C7@_MT|+F2Su=4|KdW#-S4cWlMmnErKQtyA zc3D7wS2vMiJa<<-P((W{9~G>1N_S8(D;W!dRWfc!DpEx{v35y0A`xjsC$@J*muf^x zJTSC(ModIHynIMCAP+%1G+s+PJT@>R69+ptGekZ*9u*E{K_xXZF+n^yJ2*BpFDfG& z6`5r^J0uc&Pc3&-ICxDfT{|E*ArL?}E_+uyb5}u}YC$U-4^T!wGae3EN<6-ONF6X zU=)mkQ7{Td!N>%wFH&wshf&ScUV)TUiVP7w@t`duCN?>zua!&_#CG1j$h7OgF_yzZ zGS|p4;QLGdip}v+55Ik2d-k=C90R^Lp3dfri(%e&pY_|TyJVQ~a^?oD2V3rMP2`P^ zI&?=;k7NT*z5Mxf|IaB$WyPgqYybUwa`2Noi6;E{zkkQ^)&}kNT)B>}fAXaJ;ntrY zZ-4A~y8mfb<@A~^aw6jI+yAF@9zQOt)Xmu4bAv1s&b|Hr@}AW5&U@Kkj2{tJf1ns$ zWaaPIv(9|a+_7QZx_l)flJ@N*+aL6xIN{RU*Uw)+&dk5RHDObEJTb1`WwEh+Gs1us zZ)eZ$T=Bjv<r{6-@hR@&db$ z9)8n4d_M6Erx9J&bx+@DUxje~U-^B0mi_soODwz2zADQGgu6>0& zYHYS|dGX`TmE}O@`!|1|ulW7?`Ojs)x()A?DAp@#J~?>z?d~(6|#m}FQ|IC_s zE$GbE_s={3%x-*Ov8TJ~O5TxqO_Lc8 zUffqdaRPB>R9*1g=|BB+@U_6@s}^25bzC^z)Ep%KWbVi6O<&)Uk}8+Z_nGAIyU zocwhAUE4$70AfvWS^S8z>P|v&+ByX!(N8meeF`Pgggb66JV^`;Tm@U=$gML%_LesT z4eICExRXp1Zmzvq3#7iXbLW!lh_7L{LDc$Z63XNnG4&QWXa8D%;z%=jCS1S21j0CU zc)~XFjQAG52FjXv;MhF!%s8}W8I<+mbAQC)cjTDyZ!whd>w4se)wf5RXd?*#0KDj4 URIejZ4gdfE07*qoM6N<$f>V-&DgXcg literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>T|QP!LLC(kJ3BjTP&!UGC_^nBAr}xV3kq3HN^V$1 zT|p^JHz+0x2r3B*J{A&vSv+}9EpAIMVo5cbYDHyFJ6T3Ga#T7{JuM&;2!&uor*cMG zIw6&2KB;j=E-EHlOg|(X6+tWIGU84HG2F@jVuq-{c+Yeg#{7QB2(dr~rJPdsf>J9A7eTRkOIMK`N-M~YoIja)Tq zL?%=|DLyqVCM6_fMlDc5HI!gCK{F>>K`t>P7&9IZc1$ZoG9;2;IZsADUP?PlJ~K8V z5=SiCv` zK^O<{Tidp6rM7L`jcwa@W81cEZ<0;2Vb|VGmbX1UX-}V;-Fu&UdjC(~Jk0NWGiT<^ z000ssNRS{wg5wWeWaToa&Chq5UJe}l3dtzRnv`BRPI}JVhIzB8N1+*f zaPkDayi6X^PEu!~HzY!8BACsZ8aFe2coumDBmuV!r!;tPiN`#@-_EHEjp(6?{x3=w%!f8rklJxWg#?O=9sH|OsCT9Ju29#E+ zUAgMUex)H^7*J%wE+M{ov^=p>s-|fB)*V`gH8s{44UvgN*LZfz&+62Ez1`c)vVxCi zhv(DWFuhR>5s7CBgP!asRDkMk<$yY%)-GdeoL3?178GQW6dEoXVM}}JJ2*%Itb9GK ztM_u18%>$rD)u&&=54)BpOPZlQ@^mrG*AIeJr3^W6n4R;3NUzn?qv+Sr$eHwc}qq;eWW*{5g)7L)c^n=1ay9iFnNT*Nn;7eXyd)N zPt2XmE$W)Ys?7p!=#{t|)no{#vV+i)BkimVW-_=XSLOYo9PADwn;ehABKkBz#pw2X8~jmBVt7Nr+BS3Euih?w1CO^# UWpeeGE&u=k07*qoM6N<$f}NEr+W-In literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>yRMP)(D8+zGqG>-;I3ufYLRCsf5D*O*5eqB|3oauX&Wu_u z91aHu1y3>>U_By6EE$((KS(trWk)ejK{YKVAZ}PhH!2?+5(%3|Jp=;+Mm8uj9}YPp z5j;0CL_0MyEGINBDNjE#TuC}67!5KX5K=@rQb9CUMK_&hJ5)9wA{Y>mT{og_MSfB* zj9)v2S1~IZ41Q5Aj$Ae+84x}v6fYbNnrA+OR52zP4l*7OHzpW*P%V5{I0gg)LMs^z z0s=1_40ui~Lo6C_ODr!R60mkgn`Ap=N;60^BC~ZxCl?AwFC2_qHHlj^YDOsz2?kR) zAx||SXG15LV>(+tCQv^yH6s>TNji*MG&M3WBq1Lp7!PY$Nn=hvNG}>XH84>&A#qA8 zARHK?Zbph-IzB5LI5RMlV?2{$IjC+whgdOkNhpwBHepIPVn#4%NG()2BWO-HJS-kM zHZ!AYK0-Y=v3E$7W_1Pc$EdTRL}6E;A+@NjWS!H#K-pE_+ZdOgk+n7!9>{ zMLsSdJuV_H8w@}(Bq9?BJ0%oOHX||}4V`L2H6&JCSEYm1I0%LMm@eFmz5ahgUF~WH~`IC$M-*fKo54aYChRKYvj!o@YE! zJS>1zFPmmPBozvTRxzb(Kr1C4CL|#+DkeH35n?_ffLS^_BoT;NGJjJrT{|D3YCk(9 z5`1M+ooYZoCKI1%JS!OrwRc5kNinZ=M=cr)sBb{RfJ=y3G@ofbJ|+?g2M3j5Ifz*^ zQa&v_BobdhCodilHX#sMKPn&-2(orXc~31tC>3QxC!1wD0s#SnRWMpPA9GPPidr;_ zS~I9^Kd5d&TRI=AZ$TRl1(IJk;#&}T00001bW%=J06^y0W&i*Is7XXYR9M4fU>F6X zU=)mkQ7{Td!6+C7qhJ)Ef&UbnaQ7i4y1xPOzUy}=FyV=@0YmeY{nyAgpu*NfR$V`} zaq1T`4VYMNVO*Li(ZA+)h-koF^@v1(nFelbbh^Z8GqI@Fl^qmmkcA?;?q0foDF|Zl3~Q8j`p8$&YnYu$uQ!;=U-RgoSz5( zkdx1@{=ErjA2~&q5jSq#hcSQuet&@s6TaVj0B4`Oc%B?bJbL^C&i?oB_Ta8<0ik=D UQZl?@mH+?%07*qoM6N<$f^J*6ga7~l literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>!b8jUG2$*O@%Y{#xZ%l<*G+<3VF(Vh4W<6$3IjV0#sB%V>X+^1XN@GYd zdR96_HY$~EPCzOdhh0BlM>GHc0JC^VbyYt#DIkkuLZfg>dR#$_WkX3jGB7D4Y*RgE zQ9xNoIB`xedQmV~OFqMdQb{>1HYFHaM>Z)dC?qW)7CA5}JUluZ77;fp9&1D^!+=e_ ze@Z1431&egTs$OnODbeQBcy9Sfm1J~Y(Fd-3qB?koNPyoS~F@!EPYZgZ%Z(LQZ6hV z5Vv?oY)mu1e@)VgQb;Wr*N;?3JvP*fQ=Mo(dQvi=Yd}mjBcX0cLMRl7TQ;e1LWEc} zP(d@of=^^lJ+OC6pln1a9TiGAC|E-=O*0*MQZ;l{J3=rbWJ4%cMK!;DNirZ3QZpMt zEgW4$FlkXdK{zsDN;p6}HbpotJS-k_ODtA59i3)8YDX(WIWRLUCM+c%wRlD)AR8zo zA)ahQZb>a57Z8zPIF4L5OE4QO9~6pTK89E|H83rpX*?ko4m&CvJ2NdP9~n|VFLq8Y zD=8;AGA%YTFF!9KR5l+vBN0YFJ17?lVL&D>DJEJxA}%W@MJ^jaJvuozHB2uVZbvAz zc14$DJCk2FKPMBsd`h}|NgNXma8Ng_c1x*lKzUa^a7!*rJ~b*E4o@-~H6RaxRWgug zMlc@|QA9bhbVF-KC^8=pMJpCIA`>qh4R1&(t#Uyk69_yvG%_$QDHsbmBM>$r5XOT| ziCQx^H8MUsI5;yeUOgf@G%$NlErVJ)r*1(^J~2{4HMxFHgjF##E-7(HC^j)HJS7s% zhfqEy6Dk=CCKd`U8w@cW4Kp4N+si0*00001bW%=J06^y0W&i*Jg-Jv~R9M4fU>F6X zU=)mkQ7{Td!6+C7qhO?ivPeozD49*60Vj*T+@VCj@yTYnUyADUzHZvIVe5BtOlbc6 z`E29LwvSDQPE&8V%zgCw?Y75<-tH&C1iqg?<yH;OKp0uh2uisEiZQkybS$H*a#+$qM!LcPjSnfIn&v>`a=7skFw(JQ;p0Q&0q9= z&8x?czi%XH#OVTNHb$0ncG zs`Kwft1Go_PrI(W?(OC2(M?L?xRTZ{`LRK$qP|+>+{{a-*Zuwf>&_nci8F(VH{$7K z>F!VbXRZm#3xB!%|I+P;3=h+u_4@@KA>N2tvwqF^_^IROhrZ?a|NZ$L2Ne4I@5<7^ zH^dw9?egEh3)-zNV?04~37#R9a z&3^Is|H_p}5_^sjX+q|gcmEk`K0Lp< zj^vSAW~ClIxAw(OhX1k8V literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>@ zPc9@J(1}omVMRMGBP=2rAQcO~dr6jSMn5hf0RRA6LNR|}M|D;_Q9m)0WkRcSNUd~4 zC>#@9N;#HdI$TCIV?ZQ|Wk^sn8X;egJOg2L>9)Dg!IVTu{S2iIW7j8x;ZBRIN zRXT53LsUaESWHDyMLBa+I(t_*T0SRCG967qI95hCJ})7LSvg@zH&r|)Gae3IJ|s3O z9y=uxl3_Y2CL%>cKz&m+on}2SE-WDv2R}J9NHHE-IUj*kFm6UDM>8XPSUY1lB0DT0 zOfVUEPAxVyG+sh0WlA)eXhK~>E^J9Hh+H~wRXrUR5XOQ`X-6zbI4d(C5nf6?Dk2<= zV?=3DK0Grkn`l3fXi9ipMR`;;a#lg5Z9%(xNTF*#W>7yHGf(>cu+AzKs`P;GA$htbWSib9uGt-7DhfdCm9c%YC}9G6hS^bRyH0uArMzO zBU3meUpygwQZF$rDl{JsLOnUBZ9qpX7cLwR%!p4-IVdh03^+G8FdYp(GAN*JMUP@W zUqv!tP(y-UKW$Mvq-#EpU^-7cELuuBrf@}BNb}MLRPo7z?RzK~Y0Bj$SrRG#{a9Jx@b9nr1s75(k)MI)+&^BNz@tJ~%rz zF+DmsTt6p9KRiS~IV>3qFdh*s91S!e54LzlJR}l7J2+rKB}hX&D;WzsIyW;hFSvO} zuXIGKaYRu^KSx11I3p2ALOzpVH*`%bX+UIyN*oH8M3bFg73%Wo5qu00001bW%=J06^y0W&i*J!bwCyR9M4fU>F6X zU=)mkQ7{Td!6+C7qhKh4a7qo>QP@nO3GG$0E;2Bft|Z%l%||BZmkDkWx#2{v2^B{J z1^A`2GNKRmw0?EI_V>@9KmVTndq#>87oKQ0uGAy?a}3cD}xO{rAmVE53aC^yhlfGRI|jP4ISG zc_C-}w%BcRH4mKcQ`j55S8J=z@&2n{K7D!o`{~rTk8j;7sX2(>6<+5q&6uJpC7+jN zd?+Pu`*z8LndO~Lv!`8sIRDSjPoM1O|9RVFwi~Yzvwr>hHE+U%vp2f7C~i(Yk{kN! z?bObguZ=&iulV_Az2D#8$B%#Ab$Sw^@L2c6>B*hxQF6fzo5c=q&HVXV?Lb}QwQJL| z|4#gU{MEN_r@IcEATn+wf(k^tV^hACgl*J5f1 zX%9CSb0m?uEj@kbyJGeK{|y&ge*CfURnNgf|78z8AaDFq+C@4x-|-o4eIPcqDzb7$V0dkhmy zcCqZ<^!&&BV1g#>d3omYhezL+gE<>MgUHptzFPw+p0JGpFIaz_BxFLN!?`mbzW+xN zySrf3DllVz(97q945&J~$Nut%{~J(6pDc2LvZ6v>oWrBt^Kko`HTN4H-C6PkUCLuI zlu@0`n}*v2-^p{2bliWpWQBgoJ&xumch)^aQ z5gr&5;+9ylbw)ukC0j%>4haT*S2?wNOg1DHH7FfPKQ~M@BU?u{PCG4QOg1?(D{D$L za8f%sDj!!oCs9N=Og%A4E*c~k4ZM9!Z&5mtVLhU9OnqEF91;m}OfEbr8E8^OqijQY zS3E~NHjiUJUQ0baEF5)PLrgg+T1q`vNkAhN3sg%%V@^A%bxV0qE{0w_YEwXQSw$)* zB|JPiIw~G9DIpaM1zJcq$AV68RzO5NG+00_R7E{bNkTn0Hb^@$OFl6_H8Bni3t2)k zHZCS19vo9dI4C3`NiiOvXgzmOF>6ynK`k9IAQDJBFKbIMO+PbOIwKVj4MR07GA=AS zB^5$FIel0=fmt{%E-X?yCrLp#N<=+6H#AB;`B^?k3SVcBLJvf9`GC4Lfmtr|XKsiG{J2f8;YD6YQ zKRaSTBZ^rwWk4i9Clg037GFIfUOgi>HZ(gV5>7E3J2^IEL@F^I4v$?nJ|+@5A`m?# z62yQ^Ar}xtDHUr`J4`<|HzE-~IyOi>HB?7EH6ao%9S})DI!-+>L_Ri3Ks8K4IVTnh zK{_@F6X zU=)mkQ7{Td!6+C7qhM%)11Bgp;^%W9ak`okBkuIi5p}+Jni3WQFEU zk+FaFcgMk;xP#vdFTDBs>g}PgR-~Bm>xN|8w+&%m}H~R1VmVE!drKy?GhS{5c>?GcV<7<}f+3?u=o{yJr^rF1r zg$m|b6Kq!PaNS=CY|2IvVqAY*CrT2e_?e`D&zilMWg!5-gj~)AS>F~eUpPvsu2$?^5CSUXJe+)NP zI_ccgBF=~-Rcp_m{Qvyj$NKlr%NhR3E#PhMX1Q~-LtyfZ*-JHvF`=&Z&(D+p85q8N z{9n@xGY-p0v#oq?hMj>gOt2?Wi!_60(JzJe^u);hflTpk6* zexP@_7GI&Xe!0Al l;wtLIIf{*F*gd!_ascpp5WuhKg^~aO002ovPDHLkV1hNeFna(1 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>2`Noe0YDkzS<3~%LRetNMu38 z+H9b!%&HYeHWuhQ@}SlN-FhFSNQ_V?%@M|hVWPRsMNGg2?WnZ%Rk8+Hk!v?*u|!Kg z&XI_NHF{`-z+jF5t8xs=q{z;Egffr}s>(FLE3yn6L$2^yGKq}!e%j}tSjM=5m5#L7 z2j62C>4d{gwsRfsKR+t0GN)m}$PEQB$5J*5w-PE!uValQ0mvL2W5AK0+nl9zYS2gT zt2CB4a2f+yJ;u>`T94&9==z10HMwe^owA#B5U4VcXogf&h^LroJ!jHeXl^eSc48jI7+YA5gHf*l`?}?1Ii^OMv*}>H(#5A3Zp=I8bfNFq;eo&Bv1s^ zKs1Sz(W$UFPKQB=n(t6WKnfHFNkpBJ5Ql33Ev!;Xk_i+f5I`-LATR(yY7GQv)ciUu zAjDCclsRBxIHF2drio}Rgu_ZVslfO$AVUkvFOO@vFeD z=L64fw$6?iMQ@E?o|Su*b3S}sbiy(uo;=Y!wX@*L@sgVp9l$8OXM|9kg26BLHeA0I z?CI+*WiQhNO9qM<*vn z>XL?;527B_JZAUCe7z7(*f*AUOH{dT#1^-n(lGtWTG&TN78P|>xl zge^xafqe7*4gYkh!Gp^ct6$%EcF8-~{p%mSoo{&W+$x(B_iAE%hPkLo)LBzoGXzaC zyP|%3y@cL6+~0b5zofx@Ds{ZAJUaOH!=CZ@zt#6OQ3^p>CM vITVm7_SfMJ=0{hCKDl`I(d6$Hrh#evHyhb}nHXJH$`4Fn<6P_^#^3fI3D3N$ literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>N%36bl7HEE+~UHYOq;dsjMJNjXD6JySauPEuCvbQ$;;nNH>aJJ54__Y)CF377ZK}4QNa^ zB@_sWT{=xYF;hl5lWIp}M=~fRA{`P5Og=Oi785NfCR02sR5u}+XFfY45j-&|MnFC& z8V^i6EGZ}^8yFTfDj+>LG&(6A5eNfBFCRE06R31cSVcE7DI!ESEk-;yR!KfJFf3a- zA0{0YbWk-wH!ma!2N)F-JvT2hBNs(KI$u2@ja@cLEf;S|D}+}xcu+5aR5W!BYMk^L;NGn-NK2=CQL^33>bVNHeEy;yXnPfYf zWIL#CLU2niidi#?VL+;IL3>axCmRt-HYOz)3~Nm^MLjlJJ0Vp{K} zJWeqhB^eNRO)F3|9ZEVbc~Ue>FdLz1Ji&fSE+7?BHy~Fvi3CM_!|JR}llLnkvbFpXO@MnOC{GAuAJEG!udGchkcI5kK?JV`@8U_BySJ0dnR zE_6*TRyG~Keo8|-HM)98fKx9wD2IPJ2^KsJvui-DHWz|Ks+`wOhi0B zIyEsJ4?a0FK07x!H8VaY5;q|a!_GPc00001bW%=J06^y0W&i*JMM*?KR9M4fU>F6X zU=)mkQ7{Td!6+C7qhRoWO;j+W;1}g)7#pmm%z%)MOVwxIT|=(+Yajl8pQE>B-AmPn zy5#8p+w%F#r~L{GHT#y&)X`9z8+ec;?dSgd`TTe9wVyu^?_G53f%bN-4O1orydqxz z*|QhE9R75s;m?KKb3eDuU!;F`?uyxuc0?8uYe4ab;~zffeE(7Q=JMN9VH=-4oA-Um z`ei0xql$=jLw3;Cm@^pm(U*N9z0i`&(Srq@^Bv=0E39R_VLE*H5p1B*loQa~{jid$rK(#q)@V-tK;J zGycDO|FZci2_{I3^ojq;QG9SP<@~Rc9!_p6Vt+L*K3!Wyya|%iX58xjAtTol%)sDt zZ`q@74_`d_dZWDJJ@G~e_x7-LiHXkM4CXmZvUT+Q|Mft9U3CrdB@`cf7qgJWP6%($ z>TmWy!Z_?$&mqV)Ql(FW1!R&mp|m zH!WtsWd7f1>%2mY5&e@`xj84pc<)z#vw}r3yiGoPH z1HG$AFY1)1%tGS*x3(nRh<_?d$VS{gdgTPEMm#@(Tz-KH7g>UX+K~?DtJ>igIqp3GcIvtR()GQU_U6LY(ailI(1%6 zdRRPzVMJz3H$5m9vv^K4A{7b>3RFZjSVA`ZAXrE~J0=xfQb;o|Ej%y&LwRT0HXgt1sNuX~=muN+IQ8Afj zK#p8ATRtjiMk{quH6aKFhg&(4UpaPJKyXbkL@pbHSvf{AA6z>jHzgNtS4K`ZA{i13 zY*IaqV?&8zL~~O*NIETRQa_bpIxHFvW==dNAR0U+5?wzhg;_LDF&czcGDbQtT|Om8 zJTqWQIZ8x7Ga(aALOEGTI@F6&Lp(Q8M?g$KH##;nDHjSwKszfYBaU4-Pe(pMJ2gN( zJ7GQ|MnF0?H8dO$2tPbIaaKV(BM~_`H9|2YuX941YC@A>H%vDrvvozLZ9hyi9ieGG zZAK?NFeR8|I-6!YKrbO%NI9)^MxAU&PDMReML3FJKCN*>TSPH2BpNLo4n;jRF)S!( zO*o5OH(y6JWI-l>RW&CW4SG*5PCzzRM><75Ib2IUkz+n%PCh{=6}NduJS`u1O)Eb; zHZ>p*NI*F+Ar><+FhxN38Gl^L;nq)dN9uC5QODY)) zt8+y_ClgdfIY>V?OF}tBJ2aAEI<|O584d+MH!nRmF)$nrJ2^HuG%`p*JwZGF6X zU=)mkQ7{Td!6+C7qhOeV)D;vP@u4Y@BK?cwA{ZQx?^sW!_KzR$-0^!D=Cu9_&(?!{ zBx$|1bk&#p*Oq*rHP!#T*NThlF7uYJuj3|8@7Mp|fBs$m^Z(rcx4*u*v1Ez8=j*r5 zWy1Aq*EZE~RaFww9`t=i?1KOQe=hnG6TAGj@40ic7R)^JYTDVi^1I7Qwr{9V$*UEV z!*9fmkc&5F{*8_O|95uywME~orq0s-uVZ_3(zHn@^Z1LlZQj5sw8sd)|7(wjPW-g+ z+vG1x|ISFnM&XZB3iIBWCnkGJ)2v4XDT^` zQ;+u_IN!QYOQdJQlvAe;wLiU7Tx=MR&jkHfQ(aDf=sfaw_POt`4}Wy?ur$%Uy1(tk z`)&s!WAVsGy$*|IAL{3QnQ?f}#Xm=%pK$N~)w^Na{_Xk1CWN=2UhD2S)PDEi+ljAU z?NqOPZg%3{^{ywS@3#LY))5V_6%3v}cyKqMMX7b?-sY1Z=G;qs`nj*?-MiD5h%#a8 zPD!bj9W~L(cNtVJylCubE}ZiDbK=uEFOU8EH-9lvM(oXLJkY839L)apV)xOaO+Kqv zUrD){`1{z&ZI6CkC2WF(%!LB!mr%|N#eK@?h?5J~RWKhe@Bk2h|3_Tv#=GpbKi zMM7B5F8|qzDkqYg{hsM@J_{kgY^hrYVfm}EMRU^U2tKvqaP zJuVL45DvD&52T|Za^p(38!sEB@GE%J|=EQCz44xnQlr+E*PF_KW;`Ra!DzFQ!sN+ zGZ+>WXiYdcC>ljKD|b^iNH88tJT7icGE+MySwb#(Q!^S94MQ>|TR$g1FeO4R9#AwK zF&z$YR6R~YIeb+%dR8}6LN#1OFgh$CA{`luTR1~BCz@zKhhahz5Dy^|2T3&~JuxUF z84*f9HDEy|XG$|#M>b17GZhU7Z(U9;DJN!0F;+MqoMk&aHZU+OCZTOYmS#e_dq_7V z6%7jsl3zGfMLK9xKRYxnc~37;G8%F6X zU=)mkQ7{Td!6+C7qhQ#AKNOpwXBtAO5t1`zkgs`;@=FkPLA9Gyoe!Sex%24$qX!Q< z7V>cyvQ{5$S7{+u@25|HxBmY0>G%8VzwfSn^JdbaqQ=T{CiZ^8eN{y1|K|Mu&R?r{ z_qN9Vp1Ub5-1*K66*ro-R9 z=4E!4uuPwQd1EsXMogVD^X>h&_kO>7vMDU!@87ldtqLy=^ENZ@uFrpdXl_UEU4kZ< zz1TMM&fj&{u`zpGxs&?8`wTFM!fB636^@`8O)hn-*w|8~j1j_#V6`s6~ zfC(qcCJ220!FfQuXZ~it^&kKJx_oT=&oedhU%wvtKxC3SBT~2jJHx@2f?}OTKuf>> zGk>o8f6lGC!(U&oTuGb}x4wMuV_;~=<0`&=6~zDe>ddMQTNc$G`SNPlE#i!50GA5S z%Y>)Ah6tR#V)*&Sg^&8*Lt`eV5?`(yFE~(9eGbAocWudz<3PIa-=*8LpAl=s$z!D# zC&GEJ9^Wwd0i=^oZBE-mtP!ue+rA)pHxK@IIt^y+KKbV?k z?j_QQ=L>El@%~+jUI?{4bIX#Q|922$#5NOSWNy@rpa0_^%xjN7|NopzOqBfmxzhu| zz4~}fLL!9uEBo15qC9fW+Q$7C692=h_=g)PE&VS)%-Fb%G9z~H%G#bYjB9BCw%|y* TQNW!b00000NkvXXu0mjfDaKp- literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>ISUUd2MN%MSeQRJFd!6KC>|9M4+Q}M3kd`X2M0_qAVWetK0P~URYprgJc?a9 zxRrLEb56>ohKF1@cT+WnXH9-uJfwYJ!;@=7Jvh6Ud{;+0o_=DHcVS9DHBTlQOh!JY ze_v5JB$#DAyMan5I{*M_RYWix4L>z3Kq(h>Q#VLLI!Hl0hG0U&oP0PZ7&|sIWk)ZPbY4zB zGka7udR|9PG8}AGL@_NZf@oBh zplLo{KqjqoL~=_mT0twGYCvsMK3F^@NiG?4Swd$*C{aQ-nrA>HEhrxsk7GVtNI0v7Xhb?PK|VW+U_CS@8HHCfKRP#4K{IhtH#Rdd zIyNz(Y(S=OL{>N;PeVCXL^s5NOO$0lj9WBOM?QN|Foa=5Vn#2)fK6jdIn0PqD;f)y zWIS9uBD;M|p>RqyBNUQmM1@{HOE@WCPCt=fHilh1SvVe&VmwShHe){{fmASEOgocd zIaoO%Ml2UXC>6STM>-@EdQUA53<`2eDyeZqnQTUXUqydYFg76&Nj)-aOf$KANqk#B zZca2Y9}p`W4s}Z^QZpNsU^lFAL6~GZIyf~rA`m_$6Pso{Di{l>Za_UZF)bSmG9C`e zg-?W5G13PIG#?Hz9SvXr0IL81u}sYe00001bW%=J06^y0W&i*KBuPX;R9M4fU>F6X zU=)mkQ7{Td!6={$F#Sof5xWa0HX=0=(RycQwy;Ap19& zW{3*hz01eG^4{vtdjq~Li+x$ga3d3U;6)lvY2A}h7H9}E)ngJiK>}W3i)+1 z+nV}6zy5#V|BIIThebP9e>?QtXR@{JH)4!fSCp$Hxnf0Q>HTd-e^oSJ>Du?;MCaMb zPXc{YH$B|j-MK%Quo-7ca#zXaRG+)nI`z)wihD_qj@LdsTi-kJPsjY4m1nO$e=zrW zH~}M0ZcHrMl+zJHhqDXdfYGm{nCx(rWm8 zboT7aA8-CK`ts=FX}bsaff9dT{+Z>rX#2-ce+cFj{k(3&zRy#e7X>W*`{&4!mvyI~ zpWh9ZO8W8R?*d{H`Hw#h2TQN*yUg(M%d3;$8Rk^3omSvE(=!*85kbF z3VM0t55sNyLv2?b5Bn2u#Iv7z_wy}ogK|vPx_Jw4JZ6|P&*9S56T67gead6^*5ii{ z-#R*T3Yh=u)1sNz-+)-oF0Mblh%w^xiDwfgYU% z_&yy;L(C<%U27c`g`hY@MS z+dZ$3AoE+ELTlNdKi?Bux4ylD#QXLB#nWG4*1LDanQ-mh*ROA1BL_{yix&{q`q#uc kVM*kbJ2Rq28+#-J0O$*k+-Uxf7XSbN07*qoM6N<$g4DXZ`v3p{ literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>J6awcNhTDUH8_+v zHD4$nN*5M$F(-LSF**|v3IqXnCMtbwX)_89CI$#FE-We}A~qr)h(I#8jclE1P9YWz zbX!Gn84}&9gg-hoV<;U`Gb!P*ikWg#)vk`Xc}A&fJ%>OgZ(U9}DJT`w-GofogG7}1TSwTh;3QrXbaX=)rc}!_Q zBT5$xQ708-91=z|Bse7%SU@&vI3j*jGe;y8Og}bsS3gHB7;#WFg1MEhZyg6%ERygIO03HZCgmz?QOrSG$&b?!uh^*Rgag z8|S)|LLC^PYCp-JeQO^RLn;=LW<_dDGh09_op@W4UpHJB4{lOBg-a}HMk{DB9c?KY zIWjDxZbf!ZE}CRIsdGj~I4xE~Ggdbsc2P1_KrUoPEiM`ioM=EiGb@s2L78JYnPxtC zSUiqhH*HERi()}HBo%{SL|sWYXH7UfEFMBLC4E>skX|>3STk8kJ!C;7t8hW8Z$Ou4 zLSQ{2a!oHeBN1*&FK_?=6c7w791d_R9HDVeQ#KxvQZimUA$BnxKPVSYEg2^n4QL}3 zjbA%pO+OC|2wFunplCdoWIcXXH&Z(%sdY=shf#A=I+R~KPdh6;EFe)c8gED`Y*IXO zNhwl3FN|9>fL1j)CmNk+JEw3%(TP#UgH2RHF=9Rzg770Ek6Cnf!o@_&KHzKBT zO0;)HtZ_wyRx?K{7LH~`rEEV=JT87wFE$?!D;fj)JWMtwdQU7!FB?536|r^ z(@_-1w_|sAcXxMpi>)XaV2gl+0tzSyN`px#J-WLjq`Mh4a=|v1Z2b1ybHJFvh;9FQ z_Wt;t_ulWF&$;)0@4N3JkP;7s6d^@O5mJN{Aw~S>2p~S<=FN}=eI*D-xVuNnPmbXm z0>nZDj~_8gPOh)cbVY=DPEsE^IzK<3H|L1y$b41V{2Ts*1`iis5pBwiVM8EjAVmUE zY0Q2QG@!)CizU7yC>N;Ij|GMz#76|6U|5#J;zYRrk!79ga{HEAFjUt6mWOwN+TGs> zmWTdJ-79^ETI7sT%1DzX3=gAo0)hpvA3=t)sj?5)SXkAd5D zz`A{Rnuv%v<=Nba_tBMFfxaqt+8AI47JFN?k~8Z80QWr$Jpx|_0v2!s(+k6kUi2No zi<+^9!UItJbcLqYp2CfHz!cyyZ*g=~h2Y2)0=`GYVJ`8RMi_2xF<56=YNfO3xe9lY zueWzJenSZVL=++Od$Vu^Xp@ZwScKOEJbBK#w|j|BhWoZ}e*Us>Nl;J$!CK}67JK&9 z$IEEPn(S_@0Ij?ao0yDCf2~`rUux(_p};LwTNQQISL>}U*TYTsyT z#b6i=Mrw5~iq7^sZ9_t(90*Q0PJ=0V-R1=q*}^=?rZ@c=TV8Z&E-f(ZLZTy)d7tc$ ziSQuu>Qo1!p`rfbRZ?z8UHxj2EW(=#_)i(t;e2F$2LYLzU>Yk50`QBKb55jSlbv4U z(>((GJMG-4f1C4J@XNX6TW?mhf-b;Q>b6#bMMxvL7lfeL^JCeLI+>FqNJeBdzOuJi zfWNJ2AGPo8I;T#J{$e#s0pXTZNqeo*Gsco4*axyC?)W0CT_r_i;I2uCfa}=O9=!MQ Y3t=YKN<0^-BLDyZ07*qoM6N<$g5Kq{Z2$lO literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>IpD!<~Co4ibqc8YUhYFeV<1 zEHZi_CX_rVi6Ish5DiKV5;Q6xeKH+%I5vP85y5{+NiryQPA;i`T)molVo^hDA0($} zL*1EUU>y@a5DAKEP&_j!LN)Lb)scEhBqOHL@10%ENf3YY#V+aR7A{$^T z8AufiHy9FqQ7&jaCZ}&mR3R6kS~M=K~LA-a@z zieW<9pl@6?A!koHF&+?G6AMZ~J3=)tcv?Y4Fd3c&D{@#taZE0l zYD8H)C1XM;Y(^)5Uqp;wJXR+bRTT_B7Y(y`OQdN%KQ=EZ7YQK}2ajAe$c0XUS2a8& z5`t7Pooz;kY*$Y=CcAq{NH!;wVK>5mN?tr6b5=bp91lY&6LG44><1NjykyB-Ejdy#CP2B_`369 z-tNS2;{9iKg`hzvA)LSooWKd3zzLkd37o)*0TZ8A?ieKTXz6%JZ~VVuTbqEyiVdsf*Dl}K2=#Q}40IMy)uzpBfW_u;GEP0N_Ws zr!XQOo_uM3B=exFCfz^K-{-BTvN((|nQaI%1gW#Y3~TGFfp>TlxfWdIG=^W$G1&MUwhn+Y-G$i;IX&z$33q^dp=L14HYOK@5$ zQSH{$X|(#p{1mGnb>CAeM0pVq#0^Q<_V@{Fo^Rb0)v=0zi6I_fsC?>#N0A`5h089u zotR`_S?$i~@0hute!X-yD}(h+Bo~#EkU*IT0A7Bn)79eW)aDo(t-hK;WAHhtgfrWp z%$mROSrUqlmXbstri~aS^DE#$f?1t*xQD+>keW|M)H6oTBMFa1Jlt)pv zWD-SlbL!2Ah1uCTXwTukbkR(kO06yFcrK*$w->(xKA7cFRSFl?cSaA2_Nu#1Ajg;0 zR$?2w%5j o(XZp7I|1}Bl+D0@4*E&I0dGO?kChF(DF6Tf07*qoM6N<$f{U)I5C8xG literal 155 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 VN#|ib32XoW002ovPDHLkV1ju9qfY<; literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>zGRX3Sb zGG#R)b4e(4JR+O`09Y#=H5(0+S~Mvc4U$bQQZO2QQ!!N<4;c>#BoYad{ z8oGT;m1;;s9u9^@D8__RLm3XEW;=TT0BI^2WJfQCPAzBv06qu=z<*4JRWxHyKd5v{ zT}e2LU_PsMOGY^_Nk2DvS3gH97idvGW=u9%MKwG$ElN5qby-BH003=MKfC|{gjFzq zIU=lSJ;?w7j7ck(003bg5`I1V#+PA+XP8+A4y zhF?FRcv!}OOFbkJlus_4WjnZdM}PnTqIFJ}XhOSwPlRDa$b(LKQZtfdKU_>dm18=5 zT|<{RY*OJ003tQ2thV1Y*$7s8VnB&3{MIMnPWPZU^l-2 z07(P`K^6-`5($Y>FIEu>zI;i3R5pcKIZF`>u5(0zMk*f>28jRw3j_i=BND4{LV#aI znr%uvH!{Nj098aajAcenKr^y%L;p`txc~r^005XIZmKP6BO2j2NeKbz?sDnwu3eLg^xxt1-} z{WTFcns6hC%7=E(7Rq~iHjfXoyt&}^F-PEopbbBMT=RWS%G*Z?=dN-d{ffvPK{%cC zA&BKGa;lJR6E2<^XQ^U#;Bdw3boBYf5*SvmC3lwGaZb|v;Io+t&Te3Bq4WUBZ5>}1bW$4*hZg-sQ4K{J|HOeK84iyF+xr}ZaD8A zJo(C%Pa+VxmE!{3s@(b%Sybg`<6&TLUr|@$`U61_L`{E@+$XwAOk!fl4mH)1=v~1) zQpn7_REP^k`VRq@FBiXcN6CPWB38)Z?}!egUHe>#ElPX07;H_9-&dDfrWL7fexp#7 zDd}x0j^c+(%Zj?o9CY}wz1MD@+~DE98Byv^oDEEXd_-+fb2k@ds5tSRS$MUMCH zFHQo;5TQc+h`eH-wT6Z~Gw9a)fT?md+gJQ8A$*6oYp(CQ$?`B`-Js#43jGavH%x*7 z?%h+qmDFAxb_>84#M|sxJ=U0X*&yt`hKD;h`HCgcNr=TLTd2=uLTBJ%VPw|4ew|!a zXXxqcK}PjEwumgR&1YD=->7dayR+wS{tE!%hW2&`2j>q$Hk-+8YC?^fLcJtsp|RvB hacA#{!Md+IJ_Dhz18ZNjfXM&=002ovPDHLkV1mUkr}Y2; literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&U$P6UyrTcAw6i0fIV-k?&1W5>x1?Co-U3d6>)DbpUh%a zlxPWjEkEb&zT{8;@};ajov)ROa~|OrHJ5WV__I80_0_DcQI>UYW_%I(lgc2qVoQRM z!^HzkUyY?SW~m2m5);}`b9(6+S4)Pp{@Z7Cb5%ZQ{H!_~8o?0Nw`!8Zj03x0-DY7D z-;*)Z`2eH9^coe9{p>F$a_sp0%uda~g;m9%l>qcTgQu&X%Q~lo FCIHhWniv28 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSA2A8.png b/wadsrc_extra/static/sprites/dogs/DOGSA2A8.png deleted file mode 100644 index 28c5781327308f9bf8ff9417e14e92a52d439fca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 466 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!TmyVUTp9HB!^6X^t*uw*J9~S3 zXJ=>Y>+5@)OWW&cDB2Eyt8tBus%@t;%xib$=3Dt^^+%0 zjyGXj2oz#03GxeOaCmkj4anh0FLF!*(h5Lq{i$rV8&F=|)5S5QBJSnKU{_su z=bW{syOuEo_}E*V+q8}K$zgWswTur$rr*DGFQVbhhjhh-$_LUFjr0F;OxfljCb&v* z-5vp{-~veN(n diff --git a/wadsrc_extra/static/sprites/dogs/DOGSA3A7.png b/wadsrc_extra/static/sprites/dogs/DOGSA3A7.png deleted file mode 100644 index 8777d2fd784c3742d78fe7d7b877b415118221b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479 zcmV<50U-W~P)OOE()oFBf-DD^ouoe^W1`Yd=FnLjV8(k6$-0FE3w1 zBWp(|e$jX?00001bW%=J06^y0W&i*H2xoFZVgLXDAOHXWJMwm`MgRZ-JxN4CRCr$P z)Y*!JFc5{|I<;kSpLzdxoumyiO+#b!)(>ybZ-F44@OV5PkH_PIyL+k64NySohHV4% z&U{n7vsY#o$@%K_x){Lhexa}|n<}F)3&Af17!AUO6I7TzgkY^e-z^2bQRGw8^ zc{kEO!%}@7QOxXkVSU2}-y1`5>_3%)p<ig5b zfEaoL0Ah}1*8)UlK*vuagy8RizCGofW82e({o&XH$k+FY0C&1bRqLMafOovV*B@Vd V478|h-(&y)002ovPDHLkV1n5)#g700 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSA4A6.png b/wadsrc_extra/static/sprites/dogs/DOGSA4A6.png deleted file mode 100644 index c13851c3b5301adaf0fa9cb58dbbbabd6c6f4c48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 451 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!>;rs4Tp9HB!^6X^t*yPiy;tWu z$2%*xhZ~psYwPRlXS=J{2kSdKJI_wG1}WDU&(6*cwwLdZH`i9?H#ax;HkV$upvD0x z$5;~N7tG-B>_!@p!;xO(m;|I1fY|y|*=jeSyqu?tV@O5Z+leQ$ju;5AR$tc3H~#rQ z-`88MnZGgOZE}c2$*M*2ZS{vzjAr_%2_HP2%->Nj5O8(&UkO3OZRcMYA6w?$=TqMd|;pnQrov*qr630o8xmrjf|VtF9EV%?FsI(3icJ1Fw@ z{N_yf&9bkJS(EvT6E9=OwTlju-h4^5Vs7KTx$|?2)B%AVIUl7q{Jy~7z`n2I`x}P$ pD}E-(Jy1H3Cl|2#@&Wl8W_xSiL-RaB{{cgc!PC{xWt~$(69ATIot4AG!&m1! zTU%RayQ>2w+ry3Z_4Uoo&AoxZT)IA3zdzpGUSE86vURY%ytXobc6RpSZ2NM5?NSq8 z37`hXk|4ie28U-i(tsR}^diS3Agutz)}P8&y8-Fjo-U3d6>)E`9M5A`6ln|0Tk2m} z`9GXDLQea&eb6M<`)p?4Jvc*RmRCrOUOa-e4FqF zmyk4r1*?wx$guT=bF!zjF>6ijSjEA0Wa7-JK?V!%<^7g>Jmb71^P_#{&pMb*-Rx&- zOR{xz+1!~KYW+t{E;{{Pbh*F<#yv#^cB(UZ8x$3mx~Le52~=G3a{H>z5NNhbe)fEc zgrzB)IZb#pm^E10F8yY^x7(PZg)t_6b}_@H<$EW>z`8hIp4v#p^PzCid YnII>ZFx1=I=R40%whj*u zx3;$4TXmX# znH8X5f3P95MB$2q!=tI!P4_e1X>d`xX1Ynnnq$Y;B1guc-ywfba51f9%zArKIZ<%4 z+v*GQj3GNR)?a93{KU3Fbj6)B;mqq6O>nq$KK@diz>b}qi;6lIIPBlQw1@HBlIx#^ zBlrXqdOIQ`vY3k0w`R`ji7n%}(Nbn?T{*dhY2)*!UwQ)-e#P8zJW%;=@4znwJD*9@MnelF{r5}E*L7M*(l diff --git a/wadsrc_extra/static/sprites/dogs/DOGSB2B8.png b/wadsrc_extra/static/sprites/dogs/DOGSB2B8.png deleted file mode 100644 index a9eabd29e0cce8e007da2a961cac56e6fac562f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 475 zcmV<10VMv3P)?SrORH}~e^W0vH#d)8H)}^HQ$HW0Yd-)007FAVKQ9+wLnC*0 zcZXLqe}8{>Pb-s?leZ%Ej{pDw0d!JMQvg8b*k%9#00?JtL1F*^03ZMW06X$_t406- z0We8KK~#8N?UXrk!!Qs8wFl0Fqz?Q4PxUP2#2L6s9H6UE8%<+~0(hHbu~;k?i^U?P zbGb>(SpK{k%*~q@k;rK{4cn$FZ4*kVIt9YDCSzoeK}CeWNlf6Y!1N+|9i4pwu&HWi z&SQjpa}h-(BR>MG(*W!YLMSSK+ks1hy@*lr$ydAgW5&SXksd_Mv8Zay|12QZmMB;rs4Tp9HB!^6X^t*yPiy|c5k z_4W13{k8k!&D+C`XD3_N2kWoScQ!XScXoCTwwGU=ZJ+I~4$`VG9`CH|Z7zK*>VFZC z&sY-V7tG-B>_!@p!;xO(m;|I1fY|y|*=jeSyuGK3V@O5Z+es%k9ai9BQSPk$IO)m% z{a-nGI`s|f3YPY-n>EekM`82H6r-6wYQpc2e-cadQC!L@)9LLZ)1k~Dpm|mB-glE) z@q5e?i+8bb*eSMbefFP8g&}^Ut+s-YwS$PW|Ktvdz4qS>R(&>1+RLmoPhrhT zTHc?JSKfHK(|G@Bou>7QlPtO_b!R>|mRuJuz`&#-7qHhm`|Ta;=lZi)CVp;b?a-{e zP+If4UE?R0v~k$obss&}tUg=A@^2brc5k+z1pBtKg5w($tzcXVH#dJ@ zvqR*=y*Yn4wNn~ai-o-bfI-UO>FVdQ&MBb@0NJd#9{>OV diff --git a/wadsrc_extra/static/sprites/dogs/DOGSB4B6.png b/wadsrc_extra/static/sprites/dogs/DOGSB4B6.png deleted file mode 100644 index fe2d2276b7cfefe3f0dfae822441d23fa968f7fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!>;rs4Tp9HBy}iA|!^5qutykwe zw}%^hn@gAbYX{rQJ3Bk~$D3!ntItlh&d$y@H#gVU*9YpW57xKW7uQzik9St~2<_Vg z6k;q1@(X5gcy=QV$l*vYa!dl!3P5cAscf|yP+r2*#WAEJ?(M~sdCrPFZGrx0%6)$S zJ0Hcoa#5aE(zJ)cM`HiFPh*n5l(jW#ZJ74NZylBXEDvNF*M3$}T4(=QZl%zf6KoH5 z`R!@Z$gqq!mp&=%nh(QC83vzQ!5n6cfn~2bZQqE`k-Cw^Aa{IWi{yclE&sTtn=!pn znleNCK*tIP4#TSd6*aw#Dk`1Xo!??NJ$om#_+6q#5L2j!$L=k6-qz0UXHv3W)>67J z_jc@_?*`NKj3!*+SUN2>@tMW0^O04*{@UJuStoMBvP7v}Jm4OK6UVQV(tRH}a}FVdQ&MBb@02Yy`LI3~& diff --git a/wadsrc_extra/static/sprites/dogs/DOGSB5.png b/wadsrc_extra/static/sprites/dogs/DOGSB5.png deleted file mode 100644 index a6ececcdd3840a6ad20b66586f5e8a6eda0c3927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 405 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!TmyVUTp9HBy}iAyt*yhu!&m1! zw}%^>o15zc1 ze%|*_>wwaXB|(0{3=Yq3qyae`=|zr7Kw1Hatv{8mb_3F{JY5_^D&pQ=wk%^-6mbds zcf_ZE(zpE~&1~*|A+i<^U8feD_b<3_GW%@W=9@XoKJ6A^4zWvSWt{pT#vt}+qmx9h z_Xd{`H-iPMzE4b%*kQj}`#=$=K$Mu8pvZzvUv{uFwVt2%-EIN@SA}XRlnw!*r`LU9u)$Z84t-!;Y0Rrz$0-aWdo`&sEo2 zI^iZ8^HFxa)lCiWWNJRtFmf<|V6NEl-kR^R;gMJScGt7Au=d0|XYJxxBg*{E+(E

aFr>mdKI;Vst0O*d9SpWb4 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSC1.png b/wadsrc_extra/static/sprites/dogs/DOGSC1.png deleted file mode 100644 index 06e84036995e3511f1f30d6fea9a16447e92115d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!Yyx~jTp9HB!^6W@=R4O2>(5TM z1_Ezy@Ah!x?Ck9Rc=K#`b$xw(XJ=<+W#xEh<;}(J<^J0B_4UE_@{=b|UOxTjTA(?M zB|(0{3=Yq3qyae`=|zr7Kw1Hatv{8mb_3EUJY5_^D&pRrv&>^L6mSllxYgrTZrYpQ z_pe@JV3V;-aBus%*y~5YQ~#||Yr|Gw&2s%+sQEDZLGFQoB?4v~n;ilh|IX!MDPrmr zU_4*kf8%@$+l<}H!tZXkb9^~&`D!+oMA9~AmM%rR#_J46_8JN{zDbjMaHd?O(W~qX z$L%fb2iO+8WRRX^?!aPo^4W)FOr`H`ub9PVEE8rL1*jFsNH|=q5^z6K z$Xsybg_r?<#oyx$?-^Crub$FOVhgUNjemL#%t-}`2d!_n zqW#@-NHn4|3z2vLAMJ--1EfUFmssSKA!4(D3Q;;C3?`^ehC<495O@i&witfrqrz42 zqQMYsg*(px!b*!E1Q98kXAuua-az3N0h5Pl0`M9*a&}Id1SF76ph**`Av-~CC;-mI zbSKOJDyWF{aRC#Azaxd2>%#(?zXe?c63eH~d>S|F8}}lKQ9-fYd=#z zA0s0pH#avAaC$%h0004WQchC8Qn!s# zAm{F1tl-{Y25pdk6o9*KzGm-*6oUF)e;c*L*ya#ezx4ZVK0q{btyNOEsQn2p6dS;rs4Tp9HBgYD(Ly}iT3!>z5Y z_4W0$fxun8++Vvr+<0}qbAP<~>||?@a(!`cbLqv|_U7j1^}+hi&d%D({7LR7q=9mb zB|(0{3=Yq3qyae`=|zr7Kw1Hatv{8mb_2>Qd%8G=RK&fVcs!5UkcahV$o3s7|NpP8 zoN~RRxHH`9i4ZT#-87D-FYZ2SlTW4?&Ajqhewp4|>F=Q(UK1T{SwanMB)_;$6foY% zSbe)GC)BiAwZF%FZ7(Yi>w|uFncxDEBJCM7Pn@3g;Cqut?|E6L%iIbFYIeT){d_iq zTgFu}j_uN4BGzADE&gNPjE9$_`(z*7f1@1Mz;v$Z=eqg483+FGcb;E-K)t|Bz_jc4 ztv_EMUC2yOT%`1Fy~0e%%atZ>Gy2x~X?~b#70_$X#L0L;c*Xk0Gc$iPm9V&c+2~|; zVJpjU%LiokI#XWrfx9g|H@u{;eOl|@O8-u5-pUXO@geCw~jx1>Jt*uw*JBNpd&rY_^c30Qe*I%4%zq#05TbaMyUpv@d-rL(dJ3CuhS=rlM8feU$ zhr2p}6k|z{UoeBivm0qZ4o7;CV-k>70AlM;WvktQ^nFhk$B>G+x0g=(u__9*1!n0j zSZ@8}-+C>Huj^ud>^6G%dWo~{s}|O$^;@IXhONGuCHk|Li|2=s(mMr#o8B*FzUwTw zkbYP*qEg1aFF_%NW9zjXjSGB&tEVO&SaR~S{sCXJ>RswwJAS8`wDi3b&cE}*bHRg< z;_71j}*VotYk2h}*H_pz^_BNL;_t%bhRtAF2#qL1e&d$!0Cr_@guUC$V zkp}V^OM?7@862M7NCR>>(u*9EfV2V-TYoBB?FOVDdb&7YaSBKPccK%>xIT6k`XV2sazxtamORVPlEf;>dUV74B4i=`95px4ly)`b}JID~t zxj>@XL9aYHuiTL5!kqcH7wd?!$my*Q&y;1oVv)thbh6QZvp)NQy+YEzU#=3EVEk3+ zAVc7G4)%^^%$sL(ed*dbzfy{C$Aq)3jLgRV>-iZO-p)Sp%;bC{H$zL?)QlB6948Lj zDe+7w{JPOnDoFf;^tYwS=IdED2qaiP2ohu$x}eJU;CBZ5hHI-h*Ib+ClprF|sd>GX g`Rmy=U*`X23wPyMXkGcC66je5Pgg&ebxsLQ0Nn14M*si- diff --git a/wadsrc_extra/static/sprites/dogs/DOGSD2D8.png b/wadsrc_extra/static/sprites/dogs/DOGSD2D8.png deleted file mode 100644 index 38dc1fe47a63019b6485bd04ca83aeefc23d24c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)aQ$HVTM<;i8 zcV9yze}8{BH#d`$lOrP|v-K3`00001bW%=J06^y0W&i*H2xoFZVgLXDAOHXWJMwm` zMgRZ-AW1|)RCr$P(Z_DYAP|7z=@j=Z$@{-)29z8&ml!NXd*GKj&IbnguSTQMXfzs) zuzvj^m33vF>gp|(h>l)BRU_fnDJ)A$dMr92S|^}nhNVqjg?aJ*1d^)K$4v`hFTh>y z`+P#6=`r0N^G?5joY#Gxmoq<+Qrd}R+gMWiOkSDC?AxDz29eDHmQaN!Bl0}M>0*q8 z=m1l2;Hkv8LPJym=80TT4UyTPDe@4B+=wCiJm+Sh#x6L6hyrcVROd@Hp|`dIE+8^X zxrZKLt(SnjQY-*-E08J1P=Kg`nJu>iLA3yy9554TjZ;do9Nhu4+ztR!1jKJZpbvlw znB}X0z!e}`?gLl^>O-19S3dwd(3u^_VcwN_DD&^#7f%8Tk=GS`v;Y7A07*qoM6N<$ Ef=x`dNdN!< diff --git a/wadsrc_extra/static/sprites/dogs/DOGSD3D7.png b/wadsrc_extra/static/sprites/dogs/DOGSD3D7.png deleted file mode 100644 index 5a003dfdc5d004642dd20e4f9e131b220ec185e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 495 zcmVDS1pqGSfQUJ__J(}B`TA`jLR5WG_*`zrE&xc*FwC>I-~DCT1t25Rh6P&L z1PG?A8p1e^;qS5l*%~-(1t^d52s`{K6A8CAavPVh_xKJGlA{`da=*L1T_+-J7yR-% z0P_Q#B2ex=juec@X1@T|&xZ+$U*PNb^fbz4?IfDhl=bDZJr7-jC0soWgfir&M zYF_aI7XVPAbAA*c3Ji`1YC44lOjrX6L^Pel#VwGMyb-8w&Qxa?#9wfdS}P!4F;11w4@cGT&_#FLw8RrFE1~DQ!igbBU3*ghgUOeYij@i0Bc7lOE()sLqj(= zH$N{ID&a>XDF0CjWuct`U8zZwCrNNKCcq+rKGw<}@bk60`gi^XEGFq=mdBLvts z4C*-(A^V3xAITHQj2y6!BjaI2$&nNp&twB}LV@YW1Hj~b3Mp1V)IGj}bC8-NDd*RV zIq(!S@bRCBwEe0(7Xz-py1wtG>O!jZ@p!+#E(hj#+Raf-sg%;1`&X|(`0V3tvTa&w zo%*E$5gDQ%9qrV5>n~38Ghb8U*5C$XvfBPVu#>sn3xKLx8G&BfLV4-B8VK_HN`h{pUG@Y4gs4+VNbRVoAnO2nWd0OJiK1!ec!Tp);rs4Tp9HB+ry2+!^2nSJL~J~ z_s5&p2kU3Mt9yHU2iwbATU(o(n>#x@+v|(ZPPPVW%FfP?cUJZ`moE3$UYu=z>tghL zpeSQWkY6x^!?PP{Kn_QGkz*2&Rsdq_Pi3p!fb=O(7srr_xVLA_^H>Z;ST4TLJicb< z|43K9CAJRy3ONV5w5q z-DDQ#-=d2T)X98rNS;zG=Gd4UlHSI2{%xkQzzNf(@dq3f=3G{0Vl%m8D>u=>!JWC| z!IXf8NH=FkhEjQl_q9x%EJg3OrtM_>lC{;y`M~YFt4*^t3|MzJHExg2zT#sk$Q7}4 zRzSnmR3<@2rZ-QSycBinM5T+RH4Gfq2k9m3=C8@O|H;VyZ{x#LvOr%kc)I$ztaD0e F0s#1x1?Co-U3d6>)DbpUh%a zlxPWjEkEb&zT{8;@};ajov)ROa~|OrHJ5WV__I80_0_DcQI>UYW_%I(lgc2qVoQRM z!^HzkUyY?SW~m2m5);}`b9(6+S4)Pp{@Z7Cb5%ZQ{H!_~8o?0Nw`!8Zj03x0-DY7D z-;*)Z`2eH9^coe9{p>F$a_sp0%uda~g;m9%l>qcTgQu&X%Q~lo FCIHhWniv28 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSE2.png b/wadsrc_extra/static/sprites/dogs/DOGSE2.png deleted file mode 100644 index 54c2cedcf33e483b80680242fb5ccb3ad4a6d40a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 465 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!TmyVUTp9HB!^6X^t*uw*J9~S3 zXJ=>Y>+5@)OWW&cDB2Eyt8tBus%@t;%xib$=3Dt^^+%0 zjyGXj2oz#03GxeOaCmkj4anh0FLF!*(h5Lq{i$rV8&F=&)5S5QBJSo1^fR1$rnW}Plq%<*i#ty<9#COTHl1R8W?!Gf1mE_k z)Y$WtEZ0RDiZ1tlK2sg7(sd*uJqP9^*DWv8` zrLs##y#i}|*M0dpUYc7k{M>w5aL#w@;;wrFZ)=&wn`E#0e^py#dVx23A?uXS9t-LY zeBhd4f8?e07IPVXgZqcn|D`ns{(btqa6fNy@&6FVdQ&MBb@ E01521h5!Hn diff --git a/wadsrc_extra/static/sprites/dogs/DOGSE3.png b/wadsrc_extra/static/sprites/dogs/DOGSE3.png deleted file mode 100644 index 07ceafac72415a71e920ee761453a2517ad840a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 480 zcmV<60U!Q}P)@?GD^ouoe^W02005(FKSM)9k6$-0FE3w1 zBWp(|Fe9-v00001bW%=J06^y0W&i*H2xoFZVgLXDAOHXWJMwm`MgRZ-K1oDDRCr$P z(?_c1Fc5{|I+YY0Z}2;J~{ z0di;l61lS%cW18k>hUre;I4Y1FikHJM`KosUJ5umlnYl7cGpsh^#Z*&HQx)u4d4h` zMS6KN(kH_d=sRf^R|L3x;Rf9rL$mLHY6U}ZUSzj0g8uz847Jvr_xVr4j^M4Zb9C#v zj^jRmcLj5Yan~;eUx)wb9g!X|bYRD()PvviV?WQO=-I&HW_>bm0k%^CVUGYjYXrt| zWVaIml7-z7vTuaVj_!jd;a*rmigyDF9aM*uat7usAvN2#(G!I_1DQe!B;qFmG?X|$ zeG0JQOaMTxx$Sy@$PCa*N0n0aYvA0T;*aZly0G8vdjR$NJ`tcw7l}yh=?;rs4Tp9HB!^6X^t*uw*JGX}$ z$2%)~dwZArYwPRlXS=J{2kSdKJI_wG1}WDU&(6*cwwLdZH`i9?H#ax;HkZEPv%(!H z$5;~N7tG-B>_!@p!;xO(m;|I1fY|y|*=jeSyu7E2V@O5Z+es(0m<bVEgWPfeiV7HUef5D0N`LeBt3~qAWQ}0-^WR3ZEHjx(5Crl^WStI23i-;8%O?Z-6 zBlhn5)0&3Kd$>3qZXDdDRG4?@m{q6Y%~{bL3sbq*l=Pid^SK~g!(3PMO14qgH#o?k zSvG(@%V2gs^D2+|{=W{&M77=*Pgrwq*IuTzM`geKUvegEON1f3O|f#v9`&caQ@ZWDK6JelF{r5}E*oj;Wpi diff --git a/wadsrc_extra/static/sprites/dogs/DOGSE5.png b/wadsrc_extra/static/sprites/dogs/DOGSE5.png deleted file mode 100644 index d21cc016e32a8f205c8f7cfd2f7903b5cf9429c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!oC178Tp9HBot>TIot4AG!&m1! zTU%RayQ>2w+ry3Z_4Uoo&AoxZT)IA3zdzpGUSE86vURY%ytXobc6RpSZ2NM5?NSq8 z37`hXk|4ie28U-i(tsR}^diS3Agutz)}P8&y8-Fjo-U3d6>)E`9M5A`6ln|0Tk2m} z`9GXDLQea&eb6M<`)p?4Jvc*RmRCrOUOa-e4FqF zmyk4r1*?wx$guT=bF!zjF>6ijSjEA0Wa7-JK?V!%<^7g>Jmb71^P_#{&pMb*-Rx&- zOR{xz+1!~KYW+t{E;{{Pbh*F<#yv#^cB(UZ8x$3mx~Le52~=G3a{H>z5NNhbe)fEc zgrzB)IZb#pm^E10F8yY^x7(PZg)t_6b}_@H<$EW>z`8hIp4v#p^PzCid YnII>ZF|7tLZ*FcLY%lL^E}iYJ?qK5i9w@^{2%me{gyNBmxUhKWT?0jgE3A@5HL+`Mqh zrH--ca#ScI>xs_~m(FoH$tUq5_rTwOd*3T=P3m#Y+v_Wn@JnTmTSsB!rkr+xCk%F` z+k91?t3KCRCCibptlv9RGxhx5*;Q$5HN1>FpXf>CW!YYkn6Q>HP0xpMcjqzY4f=U} z89o~P3^o=EnAK(S)#xP#)u&416!{pD(Kev^D-QMSIflDw1Anx z(&0>w4NuFI^V)ni76*^qPd`w>w1C~=OtXW4RqIYC!OR0&1e%!J9~`N9Z~lkj?^E87 Ui{`J{3Jg>RPgg&ebxsLQ0KL$)C;$Ke diff --git a/wadsrc_extra/static/sprites/dogs/DOGSE7.png b/wadsrc_extra/static/sprites/dogs/DOGSE7.png deleted file mode 100644 index 0994bbf7c2cdd05daf8a862c0d0dbeb4df90b534..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 511 zcmV?SrOIKG{J3Bk8Z$nEr8;4gjLqkK4UpFr=FLzHXe^W0%FBdmAH)}^H0001MYilDT zBP$~hUqd5PKOX{lj&J|~00DGTPE!Ct=GbNc000PQazSDM001BW002AkcB@7J00CD? zL_t(|UhR@eZiFxp0NtB+mYF2~|7yA!BcW`nx0Z6ek$$2P!u=HxIU#&(6;FHkXcfR$iQKZ?7+|t;}Cu zUS3~cKY8-x2w{;xpgP8qAirP+hi5m^fE^elm==Qbo^PuFhV&QtQc{Qzi^S3s3FxV_N0(srl0{=Qa227nm-+{q*-I z-ycQ)YwW(&@;fMLGU^0u`*SXM-RtCV)_}jaf$ogBT)mUwRBvT>?M6d|Rr4hC;}nzb zYcF7CZmbOPQcPR4j5|q^>59#=Lm%B4nj4}RJY;v2AN+orWrL24xPVw=A;apUjJ0~^ z9+?3NYiiHA{xQuf(>YC2iwcHha1N`E6+~0R#sNtU+wMe?3|sQ?QJd%)Ljk){@V5R^_z>` ziy0U;95mzuiZYf2`2{mLJiCzweZ92tD1zx^4Eqr zESxJ6z__|JQc810RP6PwT--X_@7M=qa|=b-FB5-jc~@#mQJIwheu$Vny`A{UzptQVkM{srLHL0w+UvmYHs0M8ISn%DN@dv*^ z?Kw{-&6LS(OcCJ{v+b%Ln@K-P` uy)iTXh3aOGBK^k0g+V7`|2PEx%ZqPY!R;VeDbWQCF9uInKbLh*2~7ZmV6M9W diff --git a/wadsrc_extra/static/sprites/dogs/DOGSF2.png b/wadsrc_extra/static/sprites/dogs/DOGSF2.png deleted file mode 100644 index 96eb731a5684eed93f913b5cba8e8cfdd6f45ce4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 475 zcmV<10VMv3P)?SrORH}~e^W0vH#d)8H)}^HQ$HW0Yd=FnLq9JU0001ALnC*0 zcZXLqe}8{>Pb-s?laytmu~;k?i^U?P z^SDXOIR3mE%*~q@k;rK{4acD>?GQ?-It9YDCSzoeK}CeWNlf6Y!1N+|?VWuBaHwi$ z&SQjpa}h-(BR>MG(*SG-ArzIr?Z73$R>UazdubMcl5Rf-TGm3_zGQ%f*+0iQa1nm?mh~1kC5{6`Z1h1x#iU$vMVT zP{Ez(k^o)%GXaDGgRQ(>Uwt}{a5!lqQc6LaVHKtXzxh@{(>E|&`7|4DZnp-^XBA+G z;rs4Tp9HB!^6X^t*yPiy|c5k z_4W13{k8k!&D+C`XD3_N2kV=go3GAy27+LF`Ni4x+3xBft@`5e&dT2A(#w`S4FvKT zOM?7@862M7NCR>>(u*9EfV2V-TYoBB?FN*$_jGX#sfc?!>E^T+1s)f5&fkx&{r!L6 zsxzTqe=XmhB6-{8dae)8GqW`xOfZn(33_$9y2Y;bn%oBUb%Gm}`xqQje4Hy{pMD8l z%JN`NrjUY)qvrd&|5-g4ULM#U;-FI2u&QmEs-WTWkSdGIKO`iB7>(vBRNYa!?#(cl z=hH`%H(S=8`EI!S!TAZEQxoGZpWD{?a90ykfWyuM=bE;fwS1qqKSJorJbf{RWzP=E z9l!rqz_eb$?cnU=#?y}2{GQvdU~BZi@No>QUW2_^MN))7^OI(d3RCg8FNQOA8$5oM z$jEX^GTCJnTebN5%y)Uy%hM)24%~d`=WXvPU+z^41_*pKS=i^1lCP&|eOo}K`rACw z=}hm=o?O4d$$dvu;QsL#q@xi$vv1Ek;RPH|WUY4yn0(^i YtS diff --git a/wadsrc_extra/static/sprites/dogs/DOGSF4.png b/wadsrc_extra/static/sprites/dogs/DOGSF4.png deleted file mode 100644 index d401f383a8f276bd12c9657af53507d40031482d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!>;rs4Tp9HBy}iA|!^5qutykwe zw}%^hn@gAbYX{rQXS=IAJ3IHsn`dWd&rY^BH#gVU*9YpW57xKW7uQzik9SsfZ@K$Y?JN@Gg`POyte7=c%6PnIkZXgCPU2i z&glZIYgtbJ^tq%pi&J4HbAx9!*FiOfQ)#vf+y6ENGe`3tcx*AnfO$s$wfKjZ+!}ma zjEY$$1VuR%-QLUhuQzOHQ7P8Fyv_6Cow-R@Yi!RwZvvM4 z8Uoub)89C(V%Q^_&08>0JK;6!5lMyfb2schQ{3cyZ4E;RLjn^+q33b?U kgfyf#uKYja-@|%_8`|8P^BR6D0>g^I)78&qol`;+0M3u71poj5 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSF5.png b/wadsrc_extra/static/sprites/dogs/DOGSF5.png deleted file mode 100644 index 1c969e23aa68ffcec8fad4d759d50a6d12b719d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!TmyVUTp9HBy}iAyt*yhu!&m1! zw}%^>o15$F>&H7Qdz(ww2kU3Mt2;Y8_s5$9b!2B}Z!UIUoNZt3uf4z8+g@LMcCvM_ zy}X6$$_qeg#*!evUgN3<(zq;5^5AIaEfY z<>Cz%Zo*x;!D%qSJ~ICZfcN|srgXD%)$JDxnk#gYyZcFM{gDGsApwi?YTR3OO0@ZG@DF* yLqNl%-AQfp7OdUFc>L#70fpLzE5D_GFrJvmz0PpXW=5dD89ZJ6T-G@yGywnzDVwwa diff --git a/wadsrc_extra/static/sprites/dogs/DOGSF6.png b/wadsrc_extra/static/sprites/dogs/DOGSF6.png deleted file mode 100644 index af3f163521c38494e19e88f418510f06b17548c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 466 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!ECYN(Tp9HBt*x!Y!^2nSJ9~S3 zm-}n?$D8Zx>(>YCw}%_YJ1fslwsv-QHa9n4oNceHtPIqb?XDhdFK_Ig{0_)rED7=p zW^j0RBMr#mNH20s0@4aVZ2hThwHr|0*we)^q$2L^<&$1)h61e@@60m#`r^0!nyDXF zKhT=SE%+od7ajZ6MtzYGSGFEZ@#7D-U!X%G-gVUDpZ7SQlHa#!$3OVXK|j+`pR z_;3b^-*Ky}I2exZV_-;s!C>=!#_u2U4inFdu=GVO+!3T8xQJ6jjP3e&?|U}l8L}4V zKVKHuQ4%)4;DLl<++!f>r24+5M%nz8*F{`P=6s)3r`7_xH~Zd4x7@k=f&W z!>w!Q`~y{YI=glTbTeJJ_{`yB39rGXLuT>^)~~qx~RNwq&``paybfN0a9sUe<<(HqoE?mFmVB?}Lkq&Fl8#9$W92q)q zE~;jK!s_x}G?Sq#o^hF`#P$13Enki^ToxDTzur>LC&BYcWOt4hFc=v;UHx3vIVCg! E0K`bSXaE2J diff --git a/wadsrc_extra/static/sprites/dogs/DOGSF7.png b/wadsrc_extra/static/sprites/dogs/DOGSF7.png deleted file mode 100644 index 8a79a7f387ea81dfb8b7dfabe85597e7fe3b11c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 484 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!TmyVUTp9HBy}iA|!^3AMTLVFT zu>R_N=l*zeeSQ7*aN}%ub!TU1Z*%GF>};S8dwp?pb8}^7<#=ahZDsyod--yI?Zw&l zpJwf!2b5+k3GxeOaCmkj4anh0FLF!*(h5Lq{i$rV8&KZT)5S5QBJS3<%$~~+7}mq!GeD!3$?C@D!k%mX%eui3Ff!3wNo(I zKf@r@NoCgb2Rf(o?lVg*7COrD$IC(6Wg2(Q&6ma85>^Ki=bt~fU0>+X)4qKc+t2AH zUtFwEAoh;+p5OAX3Cp^k-+$5&`Stzd#>`oEE}LQx+-~?Cc<2A@U@t={!Aw@eKL$(@ z(i=KE)J0ym>|~X=kR8|2bmnmKK6L@3v|Dm3n9JBoSRcN0_?-T1CYR}izp;!@0#&TS zxSrKL^^|XzdAyM2IQM)$(KA0f8LsYCoFglio#*=FB4=h>X;wkkv_eOpOWXX7&FYt) z;Pt$|mVf)QFAsvQzfN25;?Bp{1=UG)cf-ro<#sWx)NVNZ!LD?_WBda4(lYP(8`t>x Tp1=PL3QPu1S3j3^P6 z7k__$larHocXvlFTZ#Yx00DGTPE!Ct=GbNc000PQazSDM001BW002AkcB@7J009R{ zL_t(|UhUMmcEcbLhEdJVqRme7{;!$=sc?y)G+&|azi=qDd||WMY&M(C%)mb*LI7AC z>CXZn4gpBK?|c8=fg!J1K|&^Fk-4}ck;0o&{KjxmaA=32f0!S)-xqa4QpP=!q9f~t@MjTIpTGt3_O98nLV z?7)N6Tp%KZ0*E{X)I2}}cd9@+#_$wy!LE>)qYJg>eFXsQE~ON&+5se@0O?Lu+<2&!z(c?{ Z^$$5L3!rLUxY7Us002ovPDHLkV1ipGtX%*A diff --git a/wadsrc_extra/static/sprites/dogs/DOGSG1.png b/wadsrc_extra/static/sprites/dogs/DOGSG1.png deleted file mode 100644 index 0a1ca2d8ba87280969441d558339ef67d0f18c2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 511 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!q5^zETp9HB>x1=yz}wr~+S)oi zJiI^Ne09Eaw!3<~vvM>8LwmUK>}2cx)!slI_4W1H+1cg(+UDlw&d$!k_VUgQ43j5M zE-x=HW?=9(msVC*-dyZHfByV#1_md!%nG0$#*!evUcd?sc}_sXU=z0bow>>9S9i3 zvaRD>vZ{~E~VbJ#!c^XHqhcBrdJ&Dg(WtC|14B&M_9ZqL%4Tz%-*RqOMoRhZ%wzursj`kOQ( zA>Dh<9L9y;XVgARv#kDGo>0^K+OYo);{#Wx{NE}q43SO(mfyT?C|`+snh`GR&fxK` zjLF2UkLmZm%i8Veo%CUcb0K^U zl5Ac#w|O&Uz9~Gw{J@`;b=ND-EACFG_O4jABr5CBDRl*l3;qk#Bs3ULJU04pfYFzo xfqQ30*OF`941X?u6h0v-k`(Tz(eQt}{i{?g#c==t diff --git a/wadsrc_extra/static/sprites/dogs/DOGSG2.png b/wadsrc_extra/static/sprites/dogs/DOGSG2.png deleted file mode 100644 index bba91458bae662070a15881eb6e4e46ee659cd22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 482 zcmV<80UiE{P)N-0}VeO=8HQP$)y8kVILdM#8_l8XXTkz{z@4V!W3!KeL+NWUIr0(l)5 zV$AEh@-R*x4O*Y|@tj75fL~>2qma|O&f_#KpO-*jRAuj@Fw<{7MjL{KP4P_(1Edtg+$pjP-7)o(2HwiRTF#(cbfT6f7+)#j= zgWyQOKoHC#^Z5c0#J?l$Cg+m{kUs>MKmp79i}{EG4)}OEe-yad-xdH~+$~VxUjA%> YZ+6NI>tK&*djJ3c07*qoM6N<$f_uroa{vGU diff --git a/wadsrc_extra/static/sprites/dogs/DOGSG3.png b/wadsrc_extra/static/sprites/dogs/DOGSG3.png deleted file mode 100644 index 1e1915f5a7a4260930fd49c1634c847ef2527759..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 505 zcmVQ$HW=A5H%N0004WQchC%&5C!SY3;QJb|8LFfafl-O z>778|FLF!oRrQ9hB0`k&1$h|!_92*wq?9iORLlusS<+8Iou9(TIDlP1NyIjml&kHm zE6sED$8jG3s)UAwuL5b+-ADFW$T7mN`fk+KOw38tzvFo;K9M=|G)*bT5%w!|6)TW# z0r+AI@FQ`I5PmHLbA+@6R`>!lr3r9%fGUZBAVMpEEabk!_430J1ZTkE@85wb#&|N| ze&O**nF0dN#C)Pa5;ou0HX|SiY>5*ipiq37f$xHZC%`yQ6;><06kSzO0C?dO1y(hO zMTlURs?&E}^$Rb}isf@;&6E0Q~ChX7E5f_=4AgXMs6h v7@&@Dyh8V{k`mJ`pW)vLa9!Y4{^)-KHBb;S-`mo&00000NkvXXu0mjf58cp# diff --git a/wadsrc_extra/static/sprites/dogs/DOGSG4.png b/wadsrc_extra/static/sprites/dogs/DOGSG4.png deleted file mode 100644 index 1c3b62e3ca1a9de3ab0b31e3ca6576560e3d7640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 457 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!>;rs4Tp9HBgYD(Ly}iT3!>z5Y z_4W0$fxun8++Vvr+<0}qv$wf)f4uqZWNVNPeeuQF_Rh}E=H}+w%KY`g`W{yvTm?!n zmIV0)GdMiEkp|>&q!&3R0ciyww*FMM+6^eL;_2cTQW5ud;>osDn|OenxMbMc;5`)ayGeOVGX&Xka|CUG?C5)`|1pTQ6B??$A&f>9@RJ zow4V_I^_xL!e8v1e?DFRLwaJHzyHm$hWf4E?-*L6w4d$%m*pV*EMDb)KG*yMs~guu z-nsrzUaUQiO-xDa(LY8J<76(DqPCYW4rcP&1v6azqZ}Z>Fwvo&CuE%r_XRP5i?_M1 zHiawP(C(gbmuu=G)*l;mXLfe5pAeS$q-n__b#8~Kh0p?~`UYiz4-RMk^KA*zX!yN! u&V&34g>UQ~X7+u*=lkS0{A_*s{{t%{51-!w-^HMiX7F_Nb6Mw<&;$Uy^|1y3 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSG5.png b/wadsrc_extra/static/sprites/dogs/DOGSG5.png deleted file mode 100644 index 9921b16ffdda7aea9ec6ee203c0db31107fb5699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!oC178Tp9HBx1>Jt*uw*JBNpd&rY_^c30Qe*I%4%zq#05TbaMyUpv@d-rL(dJ3CuhS=rlM8feU$ zhr2p}6k|z{UoeBivm0qZ4o7;CV-k>70AlM;WvktQ^nFhk$B>G+x0g=(u__9*1!n0j zSZ@8}-+C>Huj^ud>^6G%dWo~{s}|O$^;@IXhONGuCHk|Li|2=s(mMr#o8B*FzUwTw zkbYP*qEg1aFF_%NW9zjXjSGB&tEVO&SaR~S{sCXJ>RswwJAS8`wDi3b&cE}*bHRg< z0WbcEP)pYcBO@b!Q!fAj z0AE8RMxyw^00001bW%=J06^y0W&i*H2xoFZVgLXDAOHXWJMwm`MgRZ-E=fc|RCr$P z(z|ZMFbsuZ9g@1s*S`O|mQ+wAU5v=tTK$7F@xy@~_fMP6X0zFBHjBjoN_-a}Dlnkn zw!i>X+5Ju6pi(G7yC)oxh$=JI6aGAJ0Ct~5Rt;Cc`AcW!oF4<80D%1p*!TU%NGYiR z*Z{5H>es|XaOKXS3XtQlZ-ZUb_a0&QR$*@fi2`u% z1ubW014PQ^y%!z;G)ko$k@Q}}wn0pQ8vtU72PNq-_s0MbYAU>j)};6N!N7oUFxL=b zdup=GtBn21{0!2ka zeFYj8ybVw_K$VvS%g|eR0v8j;lD6P8!NL1gb01~EAM6{l77PorVzIdZ0000@d{CoeBALqkJ{S2L?`LpwV=H#av+Hya}(BLDyZKQ9+wLnCWz zYj;m8DLUt%% zb}SH0Vm#n;K>!@_MWxmc6I_a^n%&M3oX@|7Gk6x5W#QRJpyXW4a+dlc@O`;FbmAhC zQeAi&;F$4JsHe?91m=1EBD(vfsMOYCY)Bwdr3Y967Qo*YE+OR1#@Om8e5X}ZWc7(+ zJVAfKJQLx_2Wc%-G}QG>7`FGZ!M&oraB8P0y7=t=K7EC0m0Fv#1P~@k(;M_VSfQy% zN?0SxOz?LHKwJl8NM%Jt>8%4EhN&iEek5+99@zCctC}$@<|aY{tOZHeUEdU*s`|CD zH8gV8djQG(fKDK!{)Rn~MEo5x{tWvAy1yo4M59#?gq=WfAB66AJb?m}Pk7VcvfgkF zf4yPfAAnQ9jCc}z;Ft;s P00000NkvXXu0mjf0&~(8 diff --git a/wadsrc_extra/static/sprites/dogs/DOGSG8.png b/wadsrc_extra/static/sprites/dogs/DOGSG8.png deleted file mode 100644 index eeecb38095f1f0425cf0fdef4c7e17d0a94ca406..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 467 zcmV;^0WAKBP)+<$Q$HU!H#dJ%FKcUS0000(Lqk6= z7b_zVBO@bscXxk(f0L7w01B`z00001bW%=J06^y0W&i*H2xoFZVgLXDAOHXWJMwm` zMgRZ-B}qgSu|H5BG4fRSR17T_xV+zVh7u8+sPwU)o_E2qnq)DZsF1^1Tseb1SQ z;sKTS%Ctr3q<_@VDI}g+Nv5f z84$q$_Kd-qtG!GT>Rti<3jjl4?~act`*M002ov JPDHLkV1kZ~wrl_Z diff --git a/wadsrc_extra/static/sprites/dogs/DOGSH1.png b/wadsrc_extra/static/sprites/dogs/DOGSH1.png deleted file mode 100644 index 281b58ebe343df98912be924aa8e1e76cf7a3d4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 510 zcmVgp=?0@Efec0g5;>-jbUB7!L{4A%6^;Zu;Uf|PXJ{n5tu6Q*i#`*ex64=@C|9MVUsZ4@8hwr0KquV zjlbbuuM8*fL6Am2KvS>yik~}h+W?3Iw3aer-B&;eEagD^-V8t@s{0M#)wK7~-L{0x zK#*JgIsleEVzL3;3q(BtHUi@bDD!FqvT6?iI{;7t0$ZL{0o2)nZ~z2WAa8){2G$+` zHel@oz_C^E;Q#{l0>QXXto!MiZ2&W$5X1lN2Ykv9LaE7CIsgCw07*qoM6N<$f)l*R A7ytkO diff --git a/wadsrc_extra/static/sprites/dogs/DOGSH2.png b/wadsrc_extra/static/sprites/dogs/DOGSH2.png deleted file mode 100644 index 38dc1fe47a63019b6485bd04ca83aeefc23d24c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)aQ$HVTM<;i8 zcV9yze}8{BH#d`$lOrP|v-K3`00001bW%=J06^y0W&i*H2xoFZVgLXDAOHXWJMwm` zMgRZ-AW1|)RCr$P(Z_DYAP|7z=@j=Z$@{-)29z8&ml!NXd*GKj&IbnguSTQMXfzs) zuzvj^m33vF>gp|(h>l)BRU_fnDJ)A$dMr92S|^}nhNVqjg?aJ*1d^)K$4v`hFTh>y z`+P#6=`r0N^G?5joY#Gxmoq<+Qrd}R+gMWiOkSDC?AxDz29eDHmQaN!Bl0}M>0*q8 z=m1l2;Hkv8LPJym=80TT4UyTPDe@4B+=wCiJm+Sh#x6L6hyrcVROd@Hp|`dIE+8^X zxrZKLt(SnjQY-*-E08J1P=Kg`nJu>iLA3yy9554TjZ;do9Nhu4+ztR!1jKJZpbvlw znB}X0z!e}`?gLl^>O-19S3dwd(3u^_VcwN_DD&^#7f%8Tk=GS`v;Y7A07*qoM6N<$ Ef=x`dNdN!< diff --git a/wadsrc_extra/static/sprites/dogs/DOGSH3.png b/wadsrc_extra/static/sprites/dogs/DOGSH3.png deleted file mode 100644 index 79c1a2b89439f4e7f9ff0599023d8da680d2f567..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 495 zcmV2x}sPDezp z`7C(FFJ<6MdO^esIx=(4t-*P2H($TaBFscj3LneO*aeWqndf1k_Pf6 zn}ETTi9#61G5lQ?FK)K)D-mX*CWEa5C zAetZ06oGR0ah70Y)8PrY{ytAw`~qL+&v(NLp+7J1>;d+IeXyv$g|7-nK#TyJ$&)xK zd_#FLw8RrFE1~DQ!igbBU3*ghgUOeYij@i0Bc7lOE()sLqj(= zH$N{ID&a>XDF0CjWuct`U8zZwCrNNKCcq+rKGw<}@bk60`gi^XEGFq=mdBLvts z4C*-(A^V3xAITHQj2y6!BjaI2$&nNp&twB}LV@YW1Hj~b3Mp1V)IGj}bC8-NDd*RV zIq(!S@bRCBwEe0(7Xz-py1wtG>O!jZ@p!+#E(hj#+Raf-sg%;1`&X|(`0V3tvTa&w zo%*E$5gDQ%9qrV5>n~38Ghb8U*5C$XvfBPVu#>sn3xKLx8G&BfLV4-B8VK_HN`h{pUG@Y4gs4+VNbRVoAnO2nWd0OJiK1!ec!Tp);rs4Tp9HBv)$F(!;Qnk!&m1! z>+9>+2kZC8n|phE2iwbATU(o(n>#x@+v|(ZPPPVW%FfP?cUJZ`moE3$UYu>eOW(r@ zD9Tt8Qn<;rdL14p0 z2Bj8BR+kbJkr(qV8**=}9Z(23buB7TMxs97mxal0=FL6T?v0v1M0sj1RWE<1=A-eT zS88!X#48phCKi>~tXI4uKCQDmmb>5(!`|$@4S(%E)cG+w--+4F)NC=1itF!v93BqO`D6I z%{q_Vy?(LzgMRedu+>+ywrX8rNT17khm%*qhnwpFXS)y6$<8@}vxS2Szw3uav>dTu z++zDY$JB>mcx9>b2X?-@*z_WkHVrSG2!1>G6WLz zLZk{fFSxZTE{I^AwSd9rY6*|WGTswqOLr;ra4zZm$!qhfj^{$``uvc)S`7wb?;FY( zDzgTe~DWM4fNS~*c diff --git a/wadsrc_extra/static/sprites/dogs/DOGSH7.png b/wadsrc_extra/static/sprites/dogs/DOGSH7.png deleted file mode 100644 index f4b990dc477ba44b05d083455120d7d9c32f4daf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479 zcmV<50U-W~P)Mx)Wl$le5uq zy3%oAZ2&v~)B(_X0kj7Y02C|$&<=nAFaVJTY;-sPyb^~HXxldGsJd|byj!6E-w$Q8 V4PmzVj7$Ik002ovPDHLkV1oO3zy1IK diff --git a/wadsrc_extra/static/sprites/dogs/DOGSH8.png b/wadsrc_extra/static/sprites/dogs/DOGSH8.png deleted file mode 100644 index 0cee775d28406b5bf8031416263eff24a3d81007..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 457 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!TmyVUTp9HBt*xzRCtG`ad$)%h zXS=KS$D4?%%pYtoUteEeUS2+V z^5nGbn>v6h7)yfuf*Bm1-ADs+IMRz8lYq1W5LEkAp5p#_uahhx2Hb(TIpJFuUYA}=yT@^ zPL7`Bp09hEuD4#hCESq5dp6^(|ARXFzWcwOTtd4m7&G2h*f1;I+o$xXf!nE+Yr|LO z4u$$VcFc!c``n8T^<5z%Q#F?AlO+F`k#+B`b-t#w?B|bA~B>b;Cmzm4Ign=Q=Yt=_<28AMfhj_*Y x7KQX=D?O%{EIZ0Wudys=R5}!;!t{SZ{(^%%DN#q6Yk(of;OXk;vd$@?2>^Fdu$}+_ diff --git a/wadsrc_extra/static/sprites/dogs/DOGSI0.png b/wadsrc_extra/static/sprites/dogs/DOGSI0.png deleted file mode 100644 index f45157160b81b4c6fad78160658771c74ff30070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 532 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!!UKFlTp9F1AUr&Lb-r_ZxUsdh zb$zhDx3_n&z5MKC>-`K2#S9Gg`r`fZ=H>p{+3xDs85m|WFx1!AM>8;V0}WwdNM~T! zTSZq4lQD(B@Kp*OquYb+J1T6D&f%6__W67K*tG*Uv;JYhi37tV{N{%ZN`mR zk&iyUZuztEb>F;?E8hx)S{Byw&+qtA(J7{IL{d0ZN$gQ((|MN@()0MgSnU0l;S)N|WmtQI91^S*`z@9*xM>EGiTV;;E>61Y(HDV z2}X~`l_n29N;Zg0xYQu}Nwq=q-gAF{9v-m=pY}=~H)Q$!_IA4Bif6We()WM6!{<=O S_Pib#)C``kelF{r5}E+Nk=0ND diff --git a/wadsrc_extra/static/sprites/dogs/DOGSJ0.png b/wadsrc_extra/static/sprites/dogs/DOGSJ0.png deleted file mode 100644 index dcca146ca11bb62c0721cd96be2692eff2e26b7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 573 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!q5^zETp9HB!^6X^t*!O-^=Btr zdwYA=2kWoScP?gNDEHTH4>!(sR}Z$AU(Ud=x!4`3sXyNQGy_9+c6K)dgEIre;%xi< z3=H-4_4fMWj~N)E85oq6m7SfPD*&1ov7srr_xVM*17BLy}xCVO8tDZN*=+FOrHzPFxE|1$Q-~8H?_}T9!+mGkl zz+leapJ76AEa4mslTr^wIcczlyy43TXKwL$Hn%unnps!tK69@I;R7?+Bkq>UDlV7O z@MKU4StYSSR!Me`eZXY7cU#U2Yt=lqxmH{ATk>16SU{-7NyeVL+EXu>2^)M;o)PFd zVK#%|^J#&-u1t@P%)i!u+Nn$1w&}ZfwwqE=&^N(d=eDkOHklHYdq$~bPrt9v9Nsx! ztQI`JwC@_HA)ETcFSqt~Uu82D-u{v+?)jWEuZxcCO-#SyLWaN}o;2`UmAUV4id!WoV4OxHVj zE}*PQ;F4ThETh1seIgtSCq7`}+37S(y+L@vo)6`Uf9~YhGUmyM{0O*Xeg+sJ44$rj JF6*2UngEy~*p~nR diff --git a/wadsrc_extra/static/sprites/dogs/DOGSK0.png b/wadsrc_extra/static/sprites/dogs/DOGSK0.png deleted file mode 100644 index 2a98ee18250cb159a90e9acda661283ad6d77fcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 574 zcmV-E0>S->P)?SrOMg=@t8YVd002`zA8SV^hgUPRb4RBD00000k6$;-003)i zYl{E?qia7y006%L0DpgfKQ9;K003J603#zKLqkJfLnAq)%xVAt00DGTPE!Ct=GbNc z000PQazSDM001BW002AkcB@7J00DkUL_t(|UhUGylG`v4MbQq3%t3K%|Nn1JHwH58 zDM>}Z2xA9UUDV9R>gGTWRUw zV-d#Du>yC1xeV~O?|VXt8>mSEBxJ4ze2+-i7_Zdihr3_OgbqKXi0zo(euc|g1auuP zdI0Ay%o!aD0jEELn^}X>6i9_|o_Vek5EuCjaXz1krP?FJcpltLM64Abq3^>m1Vl%< z-NvdyFZ6%yezOeH{sw(DLB!Ke3zRD|sq8Y+;4wlijwo&p59 zxC%m#nECe+;Fs3io(V+oq^4<<*aWy~GA zdwYB9>+4%vTh|BcFV41ic6RP&VDM*PsApi9oopTNtX#~%&>n6aY%d?pz+kU0zQ5W# z9cUB-Lw0s{xxe;i28QJf4BqC_vl$ppGcfFDU~mR16BOP8RKZvh8+4cR=4i}kAuR8WpxPx#{M79RjPORRvIv$6|iYKpwngYJm=0`rt0$+&4Jfe=9DJ= zFKQ2PJn+!ws%F!LgD=)fH>~RNShZ?X+mT79MLBK1{jJ+?A36V;hH7}DhA88a$CeBN z>z>`X_2bSqt)mjQ(i7Dg=imIU?sC0)`(BNx$8x^+6$M(n=6^F`J$RuaHsPO`Msd|9 zbCKQm_a)>Cp7w2+vp9(Nsn84-r8x>F`Wy-gF4L?VXU*HE(y=+~-4k~f`wQE|n_6ur z&PZ_B#kytp-99hnhvyRetX`{K==1Q-ZOn*?ZuJ$bz5c)7u0euHmzUvL{SE8iOU1md TpH^85j1mSGA zdwYB9>+4%vTh|BcFV41ic6RP&VDM*Pn4N4L@2p(Rz_7pCJDPzZ*j~P#fx%v19B52B z14Dbb@n!~w?Ck7vf9>TA4BqC_vl$pp0~IqcI5RN(dnL06sE)BD$S;_|;n|HeAcrHp z$T0~>D*&0dP7srr_xVIOs`yF-=Xnm*|9edfi{d>LFGnLh%6M2rf-T67a zrqZr|T3s#_yv_J4m~mWKSHGof&%6(Na^wzcvM`+Hnx{PBY4y|K9-arX_j4RVZ*pyU zBd8*|;bzVZWnIrnhvP!0)L!4a@8V|*{sM-Oxhr1ne7h@e4tIbT+nn`G9TJ&wnj3Ws zIa@woJ1;(ik%PrX1gt zGdcUQ_wHq4$zO6@^qAy|CHgw@zUO^knlW{6=safy4&RV(Ax#Mxdvp!{b6l~sy+9ivv&F#lo3>>E*%q{yQcIt8AIDEaq4{x4@jfvsfJB{Bkq&kJ3c%msW=im<1Hw zTDLY?iP-r+nH1U~=%RA)&D9t3{5QT_aw~sYcixLlM6|nbYuyji2OcqJtxaFsKGXT3 z(%iAvTXE?Vy|YC#J3dS1D1AS-bXn#)ZmaK)f5d#SyB_s)e?*>n_ropuowv3{@8J|v zR{G|`IPvnam5CW_Px<1?mQH!A8+f;UOR>8A9S*)N0uq|1f!<~CboFyt=akR{0CB9E AZ~y=R From e71e4b6dc8dc18365cb914b3595756f045d61633 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 30 Sep 2017 23:58:11 +0200 Subject: [PATCH 032/105] - Improved transfer heights support in softpoly --- src/polyrenderer/scene/poly_plane.cpp | 188 ++++--------------- src/polyrenderer/scene/poly_plane.h | 24 +-- src/polyrenderer/scene/poly_playersprite.cpp | 10 +- src/polyrenderer/scene/poly_scene.cpp | 162 +++++++++++++++- src/polyrenderer/scene/poly_scene.h | 22 +++ src/polyrenderer/scene/poly_wall.cpp | 11 +- src/polyrenderer/scene/poly_wall.h | 1 + 7 files changed, 235 insertions(+), 183 deletions(-) diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index b642057c3..f5485d096 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -36,46 +36,46 @@ EXTERN_CVAR(Int, r_3dfloors) -void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) +void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) { - if (sub->sector->CenterFloor() == sub->sector->CenterCeiling()) + if (fakeflat.FrontSector->CenterFloor() == fakeflat.FrontSector->CenterCeiling()) return; RenderPolyPlane plane; - plane.Render(thread, worldToClip, clipPlane, sub, stencilValue, true, skyCeilingHeight, sectorPortals); - plane.Render(thread, worldToClip, clipPlane, sub, stencilValue, false, skyFloorHeight, sectorPortals); + plane.Render(thread, worldToClip, clipPlane, fakeflat, stencilValue, true, skyCeilingHeight, sectorPortals); + plane.Render(thread, worldToClip, clipPlane, fakeflat, stencilValue, false, skyFloorHeight, sectorPortals); } -void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) +void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals) { - FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); + FSectorPortal *portal = fakeflat.FrontSector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); if (!portal || (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into { - RenderNormal(thread, worldToClip, clipPlane, sub, stencilValue, ceiling, skyHeight); + RenderNormal(thread, worldToClip, clipPlane, fakeflat, stencilValue, ceiling, skyHeight); } else { - RenderPortal(thread, worldToClip, clipPlane, sub, stencilValue, ceiling, skyHeight, portal, sectorPortals); + RenderPortal(thread, worldToClip, clipPlane, fakeflat, stencilValue, ceiling, skyHeight, portal, sectorPortals); } } -void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight) +void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - FTextureID picnum = GetPlaneTexture(sub, ceiling); + + FTextureID picnum = fakeflat.FrontSector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); if (picnum != skyflatnum) { FTexture *tex = TexMan(picnum); if (!tex || tex->UseType == FTexture::TEX_Null) return; - PolyPlaneUVTransform transform = GetPlaneTransform(sub, ceiling, tex); - TriVertex *vertices = CreatePlaneVertices(thread, sub, transform, GetSecPlane(sub, ceiling)); + PolyPlaneUVTransform transform = PolyPlaneUVTransform(ceiling ? fakeflat.FrontSector->planes[sector_t::ceiling].xform : fakeflat.FrontSector->planes[sector_t::floor].xform, tex); + TriVertex *vertices = CreatePlaneVertices(thread, fakeflat.Subsector, transform, ceiling ? fakeflat.FrontSector->ceilingplane : fakeflat.FrontSector->floorplane); PolyDrawArgs args; - SetLightLevel(thread, args, sub, ceiling); - SetDynLights(thread, args, sub, ceiling); + SetLightLevel(thread, args, fakeflat, ceiling); + SetDynLights(thread, args, fakeflat.Subsector, ceiling); args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); @@ -83,11 +83,11 @@ void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &wo args.SetClipPlane(0, clipPlane); args.SetTexture(tex); args.SetStyle(TriBlendMode::TextureOpaque); - args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); } else { - TriVertex *vertices = CreateSkyPlaneVertices(thread, sub, skyHeight); + TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight); PolyDrawArgs args; args.SetTransform(&worldToClip); @@ -98,24 +98,22 @@ void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &wo args.SetWriteStencil(true, 255); args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); - RenderSkyWalls(thread, args, sub, nullptr, ceiling, skyHeight); + RenderSkyWalls(thread, args, fakeflat.Subsector, nullptr, ceiling, skyHeight); } } -void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals) +void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; PolyDrawSectorPortal *polyportal = nullptr; std::vector portalSegments; - sector_t *frontsector = sub->sector; - // Skip portals not facing the camera - if ((ceiling && frontsector->ceilingplane.PointOnSide(viewpoint.Pos) < 0) || - (!ceiling && frontsector->floorplane.PointOnSide(viewpoint.Pos) < 0)) + if ((ceiling && fakeflat.FrontSector->ceilingplane.PointOnSide(viewpoint.Pos) < 0) || + (!ceiling && fakeflat.FrontSector->floorplane.PointOnSide(viewpoint.Pos) < 0)) { return; } @@ -159,7 +157,7 @@ void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &wo } #endif - TriVertex *vertices = CreateSkyPlaneVertices(thread, sub, skyHeight); + TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight); PolyDrawArgs args; args.SetTransform(&worldToClip); @@ -170,11 +168,11 @@ void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &wo args.SetWriteStencil(true, polyportal->StencilValue); args.SetWriteColor(false); args.SetWriteDepth(false); - args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); + args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); - RenderSkyWalls(thread, args, sub, polyportal, ceiling, skyHeight); + RenderSkyWalls(thread, args, fakeflat.Subsector, polyportal, ceiling, skyHeight); - polyportal->Shape.push_back({ vertices, (int)sub->numlines, true }); + polyportal->Shape.push_back({ vertices, (int)fakeflat.Subsector->numlines, true }); } void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight) @@ -257,139 +255,21 @@ void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &arg } } -sector_t *RenderPolyPlane::GetHeightSec(subsector_t *sub, bool ceiling) +void RenderPolyPlane::SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, const PolyTransferHeights &fakeflat, bool ceiling) { - sector_t *controlsector = sub->sector->GetHeightSec(); - if (!controlsector || controlsector == sub->sector || (ceiling && !!(controlsector->MoreFlags & SECF_FAKEFLOORONLY))) - return nullptr; - else - return controlsector; -} + bool foggy = level.fadeto || fakeflat.FrontSector->Colormap.FadeColor || (level.flags & LEVEL_HASFADETABLE); -HeightSecLocation RenderPolyPlane::GetHeightSecLocation(sector_t *controlsector) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - if (viewpoint.Pos.Z > controlsector->ceilingplane.ZatPoint(viewpoint.Pos.XY())) // Above control sector ceiling (A) - return HeightSecLocation::Above; - else if (viewpoint.Pos.Z > controlsector->floorplane.ZatPoint(viewpoint.Pos.XY())) // Between control sector ceiling and floor (B) - return HeightSecLocation::Between; - else - return HeightSecLocation::Below; -} - -FTextureID RenderPolyPlane::GetPlaneTexture(subsector_t *sub, bool ceiling) -{ - sector_t *controlsector = GetHeightSec(sub, ceiling); - if (!controlsector) - return sub->sector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); - - bool diffTex = !!(controlsector->MoreFlags & SECF_CLIPFAKEPLANES); - - switch (GetHeightSecLocation(controlsector)) - { - default: - case HeightSecLocation::Above: - if (diffTex && ceiling) - return sub->sector->GetTexture(sector_t::ceiling); - else - return controlsector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); - - case HeightSecLocation::Between: - return sub->sector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); - - case HeightSecLocation::Below: - if (diffTex && !ceiling) - return sub->sector->GetTexture(sector_t::floor); - else - return controlsector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); - } -} - -PolyPlaneUVTransform RenderPolyPlane::GetPlaneTransform(subsector_t *sub, bool ceiling, FTexture *tex) -{ - sector_t *controlsector = GetHeightSec(sub, ceiling); - if (!controlsector) - return PolyPlaneUVTransform(ceiling ? sub->sector->planes[sector_t::ceiling].xform : sub->sector->planes[sector_t::floor].xform, tex); - - bool diffTex = !!(controlsector->MoreFlags & SECF_CLIPFAKEPLANES); - - switch (GetHeightSecLocation(controlsector)) - { - default: - case HeightSecLocation::Above: - if (diffTex && ceiling) - return PolyPlaneUVTransform(sub->sector->planes[sector_t::ceiling].xform, tex); - else - return PolyPlaneUVTransform(ceiling ? controlsector->planes[sector_t::ceiling].xform : controlsector->planes[sector_t::floor].xform, tex); - - case HeightSecLocation::Between: - return PolyPlaneUVTransform(ceiling ? sub->sector->planes[sector_t::ceiling].xform : sub->sector->planes[sector_t::floor].xform, tex); - - case HeightSecLocation::Below: - if (diffTex && !ceiling) - return PolyPlaneUVTransform(sub->sector->planes[sector_t::floor].xform, tex); - else - return PolyPlaneUVTransform(ceiling ? controlsector->planes[sector_t::ceiling].xform : controlsector->planes[sector_t::floor].xform, tex); - } -} - -const secplane_t &RenderPolyPlane::GetSecPlane(subsector_t *sub, bool ceiling) -{ - sector_t *controlsector = GetHeightSec(sub, ceiling); - if (!controlsector) - return ceiling ? sub->sector->ceilingplane : sub->sector->floorplane; - - switch (GetHeightSecLocation(controlsector)) - { - default: - case HeightSecLocation::Above: - return ceiling ? sub->sector->ceilingplane : controlsector->ceilingplane; - case HeightSecLocation::Between: - return ceiling ? controlsector->ceilingplane : controlsector->floorplane; - case HeightSecLocation::Below: - return ceiling ? controlsector->floorplane : sub->sector->floorplane; - } -} - -void RenderPolyPlane::SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling) -{ - sector_t *lightSector = sub->sector; - sector_t *controlsector = GetHeightSec(sub, ceiling); - if (controlsector) - { - bool diffTex = !!(controlsector->MoreFlags & SECF_CLIPFAKEPLANES); - bool noFakeLight = !!(controlsector->MoreFlags & SECF_NOFAKELIGHT); - - switch (GetHeightSecLocation(controlsector)) - { - default: - case HeightSecLocation::Above: - // todo: upper texture as colormap - lightSector = controlsector; - break; - case HeightSecLocation::Between: - // normal texture as colormap - break; - case HeightSecLocation::Below: - // todo: lower texture as colormap - lightSector = controlsector; - break; - } - } - - bool foggy = level.fadeto || lightSector->Colormap.FadeColor || (level.flags & LEVEL_HASFADETABLE); - - int lightlevel = ceiling ? lightSector->GetCeilingLight() : lightSector->GetFloorLight(); + int lightlevel = ceiling ? fakeflat.CeilingLightLevel : fakeflat.FloorLightLevel; int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; lightlevel = clamp(lightlevel + actualextralight, 0, 255); PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - FDynamicColormap *basecolormap = GetColorTable(lightSector->Colormap, lightSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); - if (cameraLight->FixedLightLevel() < 0 && lightSector->e && lightSector->e->XFloor.lightlist.Size()) + FDynamicColormap *basecolormap = GetColorTable(fakeflat.FrontSector->Colormap, fakeflat.FrontSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); + if (cameraLight->FixedLightLevel() < 0 && fakeflat.FrontSector->e && fakeflat.FrontSector->e->XFloor.lightlist.Size()) { - lightlist_t *light = P_GetPlaneLight(lightSector, ceiling ? &lightSector->ceilingplane : &lightSector->floorplane, false); - basecolormap = GetColorTable(light->extra_colormap, lightSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); - if (light->p_lightlevel != &lightSector->lightlevel) // If this is the real ceiling, don't discard plane lighting R_FakeFlat() accounted for. + lightlist_t *light = P_GetPlaneLight(fakeflat.FrontSector, ceiling ? &fakeflat.FrontSector->ceilingplane : &fakeflat.FrontSector->floorplane, false); + basecolormap = GetColorTable(light->extra_colormap, fakeflat.FrontSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); + if (light->p_lightlevel != &fakeflat.FrontSector->lightlevel) // If this is the real ceiling, don't discard plane lighting R_FakeFlat() accounted for. { lightlevel = *light->p_lightlevel; } diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 30d374e62..c4af370c7 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -54,36 +54,22 @@ private: float xOffs, yOffs; }; -enum class HeightSecLocation -{ - Above, // Above control sector ceiling (A) - Between, // Between control sector ceiling and floor (B) - Below // Below control sector floor (C) -}; - class RenderPolyPlane { public: - static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); + static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); private: - void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); + void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals); - void RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals); - void RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight); + void RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals); + void RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight); void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight); - void SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); + void SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, const PolyTransferHeights &fakeflat, bool ceiling); void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); - FTextureID GetPlaneTexture(subsector_t *sub, bool ceiling); - PolyPlaneUVTransform GetPlaneTransform(subsector_t *sub, bool ceiling, FTexture *texture); - const secplane_t &GetSecPlane(subsector_t *sub, bool ceiling); - - sector_t *GetHeightSec(subsector_t *sub, bool ceiling); - HeightSecLocation GetHeightSecLocation(sector_t *controlsector); - TriVertex *CreatePlaneVertices(PolyRenderThread *thread, subsector_t *sub, const PolyPlaneUVTransform &transform, const secplane_t &plane); TriVertex *CreateSkyPlaneVertices(PolyRenderThread *thread, subsector_t *sub, double skyHeight); diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 57fc52c5b..8d467ef0a 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -57,6 +57,8 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) (r_deathcamera && viewpoint.camera->health <= 0)) return; + PolyTransferHeights fakeflat(viewpoint.camera->subsector); + FDynamicColormap *basecolormap; PolyCameraLight *cameraLight = PolyCameraLight::Instance(); if (cameraLight->FixedLightLevel() < 0 && viewpoint.sector->e && viewpoint.sector->e->XFloor.lightlist.Size()) @@ -89,10 +91,10 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) else { // This used to use camera->Sector but due to interpolation that can be incorrect // when the interpolated viewpoint is in a different sector than the camera. - //sec = FakeFlat(viewpoint.sector, &tempsec, &floorlight, &ceilinglight, nullptr, 0, 0, 0, 0); - // Softpoly has no FakeFlat (its FAKE! Everything is FAKE in Doom. Sigh. Might as well call it FooFlat!) - sec = viewpoint.camera->Sector; - floorlight = ceilinglight = sec->lightlevel; + + sec = fakeflat.FrontSector; + floorlight = fakeflat.FloorLightLevel; + ceilinglight = fakeflat.CeilingLightLevel; // [RH] set basecolormap basecolormap = GetColorTable(sec->Colormap, sec->SpecialColors[sector_t::sprites], true); diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index a9a9cbf40..02ad1842e 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -126,15 +126,17 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub } else { + PolyTransferHeights fakeflat(sub); + Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]); - RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); + RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, fakeflat, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); for (uint32_t i = 0; i < sub->numlines; i++) { if (Cull.IsLineSegVisible(subsectorDepth, i)) { seg_t *line = &sub->firstline[i]; - RenderLine(thread, sub, line, frontsector, subsectorDepth); + RenderLine(thread, sub, line, fakeflat.FrontSector, subsectorDepth); } } } @@ -393,3 +395,159 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) TranslucentObjects[0].clear(); } + +///////////////////////////////////////////////////////////////////////////// + +PolyTransferHeights::PolyTransferHeights(subsector_t *sub) : Subsector(sub) +{ + sector_t *sec = sub->sector; + + // If player's view height is underneath fake floor, lower the + // drawn ceiling to be just under the floor height, and replace + // the drawn floor and ceiling textures, and light level, with + // the control sector's. + // + // Similar for ceiling, only reflected. + + // [RH] allow per-plane lighting + FloorLightLevel = sec->GetFloorLight(); + CeilingLightLevel = sec->GetCeilingLight(); + + FakeSide = PolyWaterFakeSide::Center; + + const sector_t *s = sec->GetHeightSec(); + if (s != nullptr) + { + sector_t *heightsec = PolyRenderer::Instance()->Viewpoint.sector->heightsec; + bool underwater = (heightsec && heightsec->floorplane.PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos) <= 0); + bool doorunderwater = false; + int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES); + + // Replace sector being drawn with a copy to be hacked + tempsec = *sec; + + // Replace floor and ceiling height with control sector's heights. + if (diffTex) + { + if (s->floorplane.CopyPlaneIfValid(&tempsec.floorplane, &sec->ceilingplane)) + { + tempsec.SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); + } + else if (s->MoreFlags & SECF_FAKEFLOORONLY) + { + if (underwater) + { + tempsec.Colormap = s->Colormap; + if (!(s->MoreFlags & SECF_NOFAKELIGHT)) + { + tempsec.lightlevel = s->lightlevel; + + FloorLightLevel = s->GetFloorLight(); + CeilingLightLevel = s->GetCeilingLight(); + } + FakeSide = PolyWaterFakeSide::BelowFloor; + FrontSector = &tempsec; + return; + } + FrontSector = sec; + return; + } + } + else + { + tempsec.floorplane = s->floorplane; + } + + if (!(s->MoreFlags & SECF_FAKEFLOORONLY)) + { + if (diffTex) + { + if (s->ceilingplane.CopyPlaneIfValid(&tempsec.ceilingplane, &sec->floorplane)) + { + tempsec.SetTexture(sector_t::ceiling, s->GetTexture(sector_t::ceiling), false); + } + } + else + { + tempsec.ceilingplane = s->ceilingplane; + } + } + + double refceilz = s->ceilingplane.ZatPoint(PolyRenderer::Instance()->Viewpoint.Pos); + double orgceilz = sec->ceilingplane.ZatPoint(PolyRenderer::Instance()->Viewpoint.Pos); + + if (underwater || doorunderwater) + { + tempsec.floorplane = sec->floorplane; + tempsec.ceilingplane = s->floorplane; + tempsec.ceilingplane.FlipVert(); + tempsec.ceilingplane.ChangeHeight(-1 / 65536.); + tempsec.Colormap = s->Colormap; + } + + // killough 11/98: prevent sudden light changes from non-water sectors: + if (underwater || doorunderwater) + { + // head-below-floor hack + tempsec.SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false); + tempsec.planes[sector_t::floor].xform = s->planes[sector_t::floor].xform; + + tempsec.ceilingplane = s->floorplane; + tempsec.ceilingplane.FlipVert(); + tempsec.ceilingplane.ChangeHeight(-1 / 65536.); + if (s->GetTexture(sector_t::ceiling) == skyflatnum) + { + tempsec.floorplane = tempsec.ceilingplane; + tempsec.floorplane.FlipVert(); + tempsec.floorplane.ChangeHeight(+1 / 65536.); + tempsec.SetTexture(sector_t::ceiling, tempsec.GetTexture(sector_t::floor), false); + tempsec.planes[sector_t::ceiling].xform = tempsec.planes[sector_t::floor].xform; + } + else + { + tempsec.SetTexture(sector_t::ceiling, diffTex ? s->GetTexture(sector_t::floor) : s->GetTexture(sector_t::ceiling), false); + tempsec.planes[sector_t::ceiling].xform = s->planes[sector_t::ceiling].xform; + } + + if (!(s->MoreFlags & SECF_NOFAKELIGHT)) + { + tempsec.lightlevel = s->lightlevel; + + FloorLightLevel = s->GetFloorLight(); + CeilingLightLevel = s->GetCeilingLight(); + } + FakeSide = PolyWaterFakeSide::BelowFloor; + } + else if (heightsec && heightsec->ceilingplane.PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos) <= 0 && orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY)) + { + // Above-ceiling hack + tempsec.ceilingplane = s->ceilingplane; + tempsec.floorplane = s->ceilingplane; + tempsec.floorplane.FlipVert(); + tempsec.floorplane.ChangeHeight(+1 / 65536.); + tempsec.Colormap = s->Colormap; + + tempsec.SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false); + tempsec.SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false); + tempsec.planes[sector_t::ceiling].xform = tempsec.planes[sector_t::floor].xform = s->planes[sector_t::ceiling].xform; + + if (s->GetTexture(sector_t::floor) != skyflatnum) + { + tempsec.ceilingplane = sec->ceilingplane; + tempsec.SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); + tempsec.planes[sector_t::floor].xform = s->planes[sector_t::floor].xform; + } + + if (!(s->MoreFlags & SECF_NOFAKELIGHT)) + { + tempsec.lightlevel = s->lightlevel; + + FloorLightLevel = s->GetFloorLight(); + CeilingLightLevel = s->GetCeilingLight(); + } + FakeSide = PolyWaterFakeSide::AboveCeiling; + } + sec = &tempsec; + } + FrontSector = sec; +} diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index bf2d1b21d..db9394eb6 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -89,3 +89,25 @@ private: std::vector> SectorPortals; std::vector> LinePortals; }; + +enum class PolyWaterFakeSide +{ + Center, + BelowFloor, + AboveCeiling +}; + +class PolyTransferHeights +{ +public: + PolyTransferHeights(subsector_t *sub); + + subsector_t *Subsector = nullptr; + sector_t *FrontSector = nullptr; + PolyWaterFakeSide FakeSide = PolyWaterFakeSide::Center; + int FloorLightLevel = 0; + int CeilingLightLevel = 0; + +private: + sector_t tempsec; +}; diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index aba99a85a..20b9a1ade 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -96,6 +96,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world wall.Masked = false; wall.SubsectorDepth = subsectorDepth; wall.StencilValue = stencilValue; + wall.SectorLightLevel = frontsector->lightlevel; if (line->backsector == nullptr) { @@ -111,9 +112,10 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world return true; } } - else + else if (line->PartnerSeg) { - sector_t *backsector = line->backsector; + PolyTransferHeights fakeback(line->PartnerSeg->Subsector); + sector_t *backsector = fakeback.FrontSector; double backceilz1 = backsector->ceilingplane.ZatPoint(line->v1); double backfloorz1 = backsector->floorplane.ZatPoint(line->v1); @@ -215,6 +217,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const TriMatrix wall.Line = fakeFloor->master; wall.Side = fakeFloor->master->sidedef[0]; wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]); + wall.SectorLightLevel = frontsector->lightlevel; wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS); if (!wall.Additive && fakeFloor->alpha == 255) { @@ -318,7 +321,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl } PolyDrawArgs args; - args.SetLight(GetColorTable(Line->frontsector->Colormap, Line->frontsector->SpecialColors[sector_t::walltop]), GetLightLevel(), PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); + args.SetLight(Colormap, GetLightLevel(), PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); args.SetStencilTestValue(StencilValue); @@ -553,7 +556,7 @@ int RenderPolyWall::GetLightLevel() { bool foggy = false; int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - return clamp(Side->GetLightLevel(foggy, LineSeg->frontsector->lightlevel) + actualextralight, 0, 255); + return clamp(Side->GetLightLevel(foggy, SectorLightLevel) + actualextralight, 0, 255); } } diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 6cb7aae2f..5b2385db6 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -55,6 +55,7 @@ public: double UnpeggedCeil1 = 0.0; double UnpeggedCeil2 = 0.0; FSWColormap *Colormap = nullptr; + int SectorLightLevel = 0; bool Masked = false; bool Additive = false; double Alpha = 1.0; From bbaec90f61c9f0d6de58774d0e23187b147c3a3d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 25 Sep 2017 05:32:04 -0700 Subject: [PATCH 033/105] Fix speed of sound and unit scale --- src/sound/oalsound.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 6ee152cfd..683f25ae7 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -273,6 +273,7 @@ class OpenALSoundStream : public SoundStream alSourcef(Source, AL_MAX_GAIN, 1.f); alSourcef(Source, AL_GAIN, 1.f); alSourcef(Source, AL_PITCH, 1.f); + alSourcef(Source, AL_DOPPLER_FACTOR, 0.f); alSourcef(Source, AL_ROLLOFF_FACTOR, 0.f); alSourcef(Source, AL_SEC_OFFSET, 0.f); alSourcei(Source, AL_SOURCE_RELATIVE, AL_TRUE); @@ -821,8 +822,15 @@ OpenALSoundRenderer::OpenALSoundRenderer() AL.SOFT_source_resampler = !!alIsExtensionPresent("AL_SOFT_source_resampler"); AL.SOFT_source_spatialize = !!alIsExtensionPresent("AL_SOFT_source_spatialize"); - alDopplerFactor(0.5f); - alSpeedOfSound(343.3f * 96.0f); + // Speed of sound is in units per second. Presuming we want to simulate a + // typical speed of sound of 343.3 meters per second, multiply it by the + // units per meter scale (32?), and set the meters per unit to the scale's + // reciprocal. It's important to set these correctly for both doppler + // effects and reverb. + alSpeedOfSound(343.3f * 32.0f); + if(ALC.EXT_EFX) + alListenerf(AL_METERS_PER_UNIT, 1.0f/32.0f); + alDistanceModel(AL_INVERSE_DISTANCE); if(AL.EXT_source_distance_model) alEnable(AL_SOURCE_DISTANCE_MODEL); @@ -1568,6 +1576,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_REFERENCE_DISTANCE, 1.f); alSourcef(source, AL_MAX_DISTANCE, 1000.f); + alSourcef(source, AL_DOPPLER_FACTOR, 0.f); alSourcef(source, AL_ROLLOFF_FACTOR, 0.f); alSourcef(source, AL_MAX_GAIN, SfxVolume); alSourcef(source, AL_GAIN, SfxVolume*vol); @@ -1778,6 +1787,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); + alSourcef(source, AL_DOPPLER_FACTOR, 0.f); alSourcei(source, AL_LOOPING, (chanflags&SNDF_LOOP) ? AL_TRUE : AL_FALSE); From 4884a1f785632c994681c4e2ecce08acc435c609 Mon Sep 17 00:00:00 2001 From: AntiBlueQuirk Date: Sat, 30 Sep 2017 00:59:30 -0500 Subject: [PATCH 034/105] Fixed bugs with Line_PortalSetTarget and added more portal geometry warnings - A bug exists where portals that have been deactivated with Line_PortalSetTarget cannot be reactivated, even if given a valid target. - Another bug exists where portals that were created in an inactive state (using a target line tag of 0) could never be activated. (Even with the above bugfix.) - Linked portals that have been demoted to teleport portals because they do not have a return portal now emit a warning. - Portals that are supposed to be traversable, but do not have back-sector now demote to visual portals and emit a warning, because nothing could ever possibly traverse them anyway. --- src/portal.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/portal.cpp b/src/portal.cpp index 41158e0ee..b1edad7f9 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -307,10 +307,9 @@ void P_SpawnLinePortal(line_t* line) port->mType = PORTT_TELEPORT; } } - if (port->mDestination != nullptr) - { - port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : PORTF_TYPEINTERACTIVE; - } + port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : + port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : + PORTF_TYPEINTERACTIVE; } else if (line->args[2] == PORTT_LINKEDEE && line->args[0] == 0) { @@ -360,6 +359,13 @@ void P_SpawnLinePortal(line_t* line) void P_UpdatePortal(FLinePortal *port) { + if (port->mType != PORTT_VISUAL && port->mOrigin->backsector == nullptr && !(port->mOrigin->sidedef[0]->Flags & WALLF_POLYOBJ)) + { + Printf(TEXTCOLOR_RED "Warning: Traversable portals must have a back-sector and empty space behind them (or be on a polyobject)! Changing line %d to visual-portal!\n", port->mOrigin->Index()); + port->mType = PORTT_VISUAL; + port->mDefFlags &= ~(PORTF_PASSABLE | PORTF_SOUNDTRAVERSE); + } + if (port->mDestination == nullptr) { // Portal has no destination: switch it off @@ -374,6 +380,7 @@ void P_UpdatePortal(FLinePortal *port) // this is illegal. Demote the type to TELEPORT port->mType = PORTT_TELEPORT; port->mDefFlags &= ~PORTF_INTERACTIVE; + Printf(TEXTCOLOR_RED "Warning: linked portal did not have matching reverse portal. Changing line %d to teleport-portal!\n", port->mOrigin->Index()); } } else @@ -466,6 +473,10 @@ static bool ChangePortalLine(line_t *line, int destid) } SetRotation(portd); } + else + { + port->mFlags = port->mDefFlags; + } SetRotation(port); return true; } From 9e07babde58f4ac3de48213d07e69aa680e64eb4 Mon Sep 17 00:00:00 2001 From: AntiBlueQuirk Date: Mon, 2 Oct 2017 09:07:47 -0500 Subject: [PATCH 035/105] Fixed flags when demoting interactive portals Interactive portals demoted to visual due to not having a back-sector would not have their interactive flag properly cleared. --- src/portal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portal.cpp b/src/portal.cpp index b1edad7f9..9978d3284 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -363,7 +363,7 @@ void P_UpdatePortal(FLinePortal *port) { Printf(TEXTCOLOR_RED "Warning: Traversable portals must have a back-sector and empty space behind them (or be on a polyobject)! Changing line %d to visual-portal!\n", port->mOrigin->Index()); port->mType = PORTT_VISUAL; - port->mDefFlags &= ~(PORTF_PASSABLE | PORTF_SOUNDTRAVERSE); + port->mDefFlags &= ~(PORTF_PASSABLE | PORTF_SOUNDTRAVERSE | PORTF_INTERACTIVE); } if (port->mDestination == nullptr) From 4f35940c73546f1417110bb92e3968678142e48b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 7 Oct 2017 10:12:34 +0300 Subject: [PATCH 036/105] Fixed applying of height argument in A_Fire() function https://forum.zdoom.org/viewtopic.php?t=58090 --- wadsrc/static/zscript/doom/archvile.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt index 8e0a98dcb..79c69a324 100644 --- a/wadsrc/static/zscript/doom/archvile.txt +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -170,7 +170,7 @@ extend class Actor // don't move it if the vile lost sight if (!target.CheckSight (dest, 0) ) return; - SetOrigin(dest.Vec3Angle(24, dest.angle, height), true); + SetOrigin(dest.Vec3Angle(24, dest.angle, spawnheight), true); } void A_FireCrackle() From 557958577b8c1a52cb9ca40c68783ff1793410ec Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 7 Oct 2017 13:37:13 +0300 Subject: [PATCH 037/105] Removed all code needed to support macOS earlier than 10.7 Lion --- src/CMakeLists.txt | 2 +- src/posix/cocoa/i_common.h | 128 ------------------------------ src/posix/cocoa/i_input.mm | 6 +- src/posix/cocoa/i_main.mm | 5 +- src/posix/cocoa/i_video.mm | 105 +++--------------------- src/posix/cocoa/st_console.mm | 7 +- src/posix/osx/iwadpicker_cocoa.mm | 9 +-- src/posix/sdl/sdlvideo.cpp | 8 -- 8 files changed, 17 insertions(+), 253 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c8372ca3..bc88800ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1301,7 +1301,7 @@ endif() if( APPLE ) set_target_properties(zdoom PROPERTIES - LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL" + LINK_FLAGS "-framework Cocoa -framework IOKit -framework OpenGL" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/zdoom-info.plist" ) endif() diff --git a/src/posix/cocoa/i_common.h b/src/posix/cocoa/i_common.h index 5b2d6f6cb..be395cf76 100644 --- a/src/posix/cocoa/i_common.h +++ b/src/posix/cocoa/i_common.h @@ -56,9 +56,6 @@ extern RenderBufferOptions rbOpts; // Version of AppKit framework we are interested in // The following values are needed to build with earlier SDKs -#define AppKit10_4 824 -#define AppKit10_5 949 -#define AppKit10_6 1038 #define AppKit10_7 1138 #define AppKit10_8 1187 #define AppKit10_9 1265 @@ -69,11 +66,6 @@ extern RenderBufferOptions rbOpts; @end -inline bool I_IsHiDPISupported() -{ - return NSAppKitVersionNumber >= AppKit10_7; -} - void I_ProcessEvent(NSEvent* event); void I_ProcessJoysticks(); @@ -82,124 +74,4 @@ NSSize I_GetContentViewSize(const NSWindow* window); void I_SetMainWindowVisible(bool visible); void I_SetNativeMouse(bool wantNative); - -// The following definitions are required to build with older OS X SDKs - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 - -typedef unsigned int NSUInteger; -typedef int NSInteger; - -typedef float CGFloat; - -// From HIToolbox/Events.h -enum -{ - kVK_ANSI_F = 0x03, - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static const NSOpenGLPixelFormatAttribute NSOpenGLPFAAllowOfflineRenderers = NSOpenGLPixelFormatAttribute(96); - -@interface NSWindow(SetCollectionBehavior) -- (void)setCollectionBehavior:(NSUInteger)collectionBehavior; -@end - -typedef NSUInteger NSWindowCollectionBehavior; - -#endif // prior to 10.5 - - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 - -enum -{ - NSApplicationActivationPolicyRegular -}; - -typedef NSInteger NSApplicationActivationPolicy; - -@interface NSApplication(ActivationPolicy) -- (BOOL)setActivationPolicy:(NSApplicationActivationPolicy)activationPolicy; -@end - -@interface NSWindow(SetStyleMask) -- (void)setStyleMask:(NSUInteger)styleMask; -@end - -#endif // prior to 10.6 - - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 - -@interface NSView(HiDPIStubs) -- (NSPoint)convertPointToBacking:(NSPoint)aPoint; -- (NSSize)convertSizeToBacking:(NSSize)aSize; -- (NSSize)convertSizeFromBacking:(NSSize)aSize; - -- (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag; -@end - -@interface NSView(Compatibility) -- (NSRect)convertRectToBacking:(NSRect)aRect; -@end - -@interface NSScreen(HiDPIStubs) -- (NSRect)convertRectToBacking:(NSRect)aRect; -@end - -static const NSWindowCollectionBehavior NSWindowCollectionBehaviorFullScreenAuxiliary = NSWindowCollectionBehavior(1 << 8); - -static const auto NSOpenGLPFAOpenGLProfile = NSOpenGLPixelFormatAttribute(96); -static const auto NSOpenGLProfileVersionLegacy = NSOpenGLPixelFormatAttribute(0x1000); -static const auto NSOpenGLProfileVersion3_2Core = NSOpenGLPixelFormatAttribute(0x3200); - -#endif // prior to 10.7 - #endif // COCOA_I_COMMON_INCLUDED diff --git a/src/posix/cocoa/i_input.mm b/src/posix/cocoa/i_input.mm index 4f0aa25d5..eff9640be 100644 --- a/src/posix/cocoa/i_input.mm +++ b/src/posix/cocoa/i_input.mm @@ -480,11 +480,7 @@ void NSEventToGameMousePosition(NSEvent* inEvent, event_t* outEvent) const NSPoint screenPos = [NSEvent mouseLocation]; const NSPoint windowPos = [window convertScreenToBase:screenPos]; - - const NSPoint viewPos = I_IsHiDPISupported() - ? [view convertPointToBacking:windowPos] - : [view convertPoint:windowPos fromView:nil]; - + const NSPoint viewPos = [view convertPointToBacking:windowPos]; const CGFloat frameHeight = I_GetContentViewSize(window).height; const CGFloat posX = ( viewPos.x - rbOpts.shiftX) / rbOpts.pixelScale; diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index 0b49a6d21..4ac42261a 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -273,10 +273,7 @@ int OriginalMain(int argc, char** argv) // --------------------------------------------------------------------------- -@interface ApplicationController : NSResponder -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 - -#endif +@interface ApplicationController : NSResponder { } diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index e0f1e6c68..393ca6a89 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -35,8 +35,6 @@ #include "i_common.h" -#import - // Avoid collision between DObject class and Objective-C #define Class ObjectClass @@ -69,19 +67,6 @@ #undef Class -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 - -@implementation NSView(Compatibility) - -- (NSRect)convertRectToBacking:(NSRect)aRect -{ - return [self convertRect:aRect toView:[self superview]]; -} - -@end - -#endif // prior to 10.7 - @implementation NSWindow(ExitAppOnClose) - (void)exitAppOnClose @@ -304,7 +289,6 @@ private: bool m_fullscreen; bool m_hiDPI; - void SetStyleMask(NSUInteger styleMask); void SetFullscreenMode(int width, int height); void SetWindowedMode(int width, int height); void SetMode(int width, int height, bool fullscreen, bool hiDPI); @@ -510,18 +494,14 @@ NSOpenGLPixelFormat* CreatePixelFormat(const NSOpenGLPixelFormatAttribute profil attributes[i++] = NSOpenGLPixelFormatAttribute(24); attributes[i++] = NSOpenGLPFAStencilSize; attributes[i++] = NSOpenGLPixelFormatAttribute(8); - - if (NSAppKitVersionNumber >= AppKit10_5 && !vid_autoswitch) + attributes[i++] = NSOpenGLPFAOpenGLProfile; + attributes[i++] = profile; + + if (!vid_autoswitch) { attributes[i++] = NSOpenGLPFAAllowOfflineRenderers; } - if (NSAppKitVersionNumber >= AppKit10_7) - { - attributes[i++] = NSOpenGLPFAOpenGLProfile; - attributes[i++] = profile; - } - attributes[i] = NSOpenGLPixelFormatAttribute(0); return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; @@ -553,11 +533,6 @@ CocoaVideo::CocoaVideo() // There is no support for OpenGL 3.3 before Mavericks defaultProfile = NSOpenGLProfileVersionLegacy; } - else if (0 == vid_renderer && vid_glswfb && NSAppKitVersionNumber < AppKit10_7) - { - // There is no support for OpenGL 3.x before Lion - defaultProfile = NSOpenGLProfileVersionLegacy; - } else if (const char* const glversion = Args->CheckValue("-glversion")) { // Check for explicit version specified in command line @@ -738,26 +713,6 @@ void CocoaVideo::SetWindowVisible(bool visible) } -static bool HasModernFullscreenAPI() -{ - return NSAppKitVersionNumber >= AppKit10_6; -} - -void CocoaVideo::SetStyleMask(const NSUInteger styleMask) -{ - // Before 10.6 it's impossible to change window's style mask - // To workaround this new window should be created with required style mask - // This method should not be called when running on Snow Leopard or newer - - assert(!HasModernFullscreenAPI()); - - CocoaWindow* tempWindow = CreateCocoaWindow(styleMask); - [tempWindow setContentView:[m_window contentView]]; - - [m_window close]; - m_window = tempWindow; -} - void CocoaVideo::SetFullscreenMode(const int width, const int height) { NSScreen* screen = [m_window screen]; @@ -783,20 +738,8 @@ void CocoaVideo::SetFullscreenMode(const int width, const int height) if (!m_fullscreen) { - if (HasModernFullscreenAPI()) - { - [m_window setLevel:LEVEL_FULLSCREEN]; - [m_window setStyleMask:STYLE_MASK_FULLSCREEN]; - } - else - { - // Old Carbon-based way to make fullscreen window above dock and menu - // It's supported on 64-bit, but on 10.6 and later the following is preferred: - // [NSWindow setLevel:NSMainMenuWindowLevel + 1] - - SetSystemUIMode(kUIModeAllHidden, 0); - SetStyleMask(STYLE_MASK_FULLSCREEN); - } + [m_window setLevel:LEVEL_FULLSCREEN]; + [m_window setStyleMask:STYLE_MASK_FULLSCREEN]; [m_window setHidesOnDeactivate:YES]; } @@ -821,16 +764,8 @@ void CocoaVideo::SetWindowedMode(const int width, const int height) if (m_fullscreen) { - if (HasModernFullscreenAPI()) - { - [m_window setLevel:LEVEL_WINDOWED]; - [m_window setStyleMask:STYLE_MASK_WINDOWED]; - } - else - { - SetSystemUIMode(kUIModeNormal, 0); - SetStyleMask(STYLE_MASK_WINDOWED); - } + [m_window setLevel:LEVEL_WINDOWED]; + [m_window setStyleMask:STYLE_MASK_WINDOWED]; [m_window setHidesOnDeactivate:NO]; } @@ -851,11 +786,8 @@ void CocoaVideo::SetMode(const int width, const int height, const bool fullscree return; } - if (I_IsHiDPISupported()) - { - NSOpenGLView* const glView = [m_window contentView]; - [glView setWantsBestResolutionOpenGLSurface:hiDPI]; - } + NSOpenGLView* const glView = [m_window contentView]; + [glView setWantsBestResolutionOpenGLSurface:hiDPI]; if (fullscreen) { @@ -1115,11 +1047,7 @@ bool CocoaFrameBuffer::IsFullscreen() void CocoaFrameBuffer::SetVSync(bool vsync) { -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 - const long value = vsync ? 1 : 0; -#else // 10.5 or newer const GLint value = vsync ? 1 : 0; -#endif // prior to 10.5 [[NSOpenGLContext currentContext] setValues:&value forParameter:NSOpenGLCPSwapInterval]; @@ -1237,11 +1165,7 @@ bool SDLGLFB::IsFullscreen() void SDLGLFB::SetVSync(bool vsync) { -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 - const long value = vsync ? 1 : 0; -#else // 10.5 or newer const GLint value = vsync ? 1 : 0; -#endif // prior to 10.5 [[NSOpenGLContext currentContext] setValues:&value forParameter:NSOpenGLCPSwapInterval]; @@ -1473,14 +1397,7 @@ CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(Bool, vid_hidpi, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { - if (I_IsHiDPISupported()) - { - CocoaVideo::UseHiDPI(self); - } - else if (0 != self) - { - self = 0; - } + CocoaVideo::UseHiDPI(self); } diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 67f906c69..87d93038f 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -113,11 +113,8 @@ FConsoleWindow::FConsoleWindow() [m_window center]; [m_window exitAppOnClose]; - if (NSAppKitVersionNumber >= AppKit10_7) - { - // Do not allow fullscreen mode for this window - [m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; - } + // Do not allow fullscreen mode for this window + [m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; [[m_window contentView] addSubview:m_scrollView]; diff --git a/src/posix/osx/iwadpicker_cocoa.mm b/src/posix/osx/iwadpicker_cocoa.mm index 9367dc53f..6b8a10b6a 100644 --- a/src/posix/osx/iwadpicker_cocoa.mm +++ b/src/posix/osx/iwadpicker_cocoa.mm @@ -50,10 +50,6 @@ #include #include -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 -// Missing type definition for 10.4 and earlier -typedef unsigned int NSUInteger; -#endif // prior to 10.5 CVAR(String, osx_additional_parameters, "", CVAR_ARCHIVE | CVAR_NOSET | CVAR_GLOBALCONFIG); @@ -68,10 +64,7 @@ enum static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; // Class to convert the IWAD data into a form that Cocoa can use. -@interface IWADTableData : NSObject -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 - -#endif +@interface IWADTableData : NSObject { NSMutableArray *data; } diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 905e2de78..c1d830659 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -501,14 +501,6 @@ void SDLFB::SetVSync (bool vsync) if (CGLContextObj context = CGLGetCurrentContext()) { // Apply vsync for native backend only (where OpenGL context is set) - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 - // Inconsistency between 10.4 and 10.5 SDKs: - // third argument of CGLSetParameter() is const long* on 10.4 and const GLint* on 10.5 - // So, GLint typedef'ed to long instead of int to workaround this issue - typedef long GLint; -#endif // prior to 10.5 - const GLint value = vsync ? 1 : 0; CGLSetParameter(context, kCGLCPSwapInterval, &value); } From 7a43fa6ed7d7ec20e429983d903847bf16cee8e7 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 7 Oct 2017 15:13:41 +0300 Subject: [PATCH 038/105] Cocoa window uses OpenGL 2.1 for software renderer --- src/posix/cocoa/i_video.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 393ca6a89..b8765c1a6 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -533,6 +533,11 @@ CocoaVideo::CocoaVideo() // There is no support for OpenGL 3.3 before Mavericks defaultProfile = NSOpenGLProfileVersionLegacy; } + else if (0 == vid_renderer && 0 == vid_glswfb) + { + // Software renderer uses OpenGL 2.1 for blitting + defaultProfile = NSOpenGLProfileVersionLegacy; + } else if (const char* const glversion = Args->CheckValue("-glversion")) { // Check for explicit version specified in command line From 57ecc4ce30a38eecb3eb955c387495c78679517d Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 7 Oct 2017 14:53:57 +0300 Subject: [PATCH 039/105] Removed the last deprecated method in Cocoa backend src/posix/cocoa/i_input.mm:482:36: warning: 'convertScreenToBase:' is deprecated: first deprecated in macOS 10.7 - Use -convertRectFromScreen: instead [-Wdeprecated-declarations] --- src/posix/cocoa/i_input.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/posix/cocoa/i_input.mm b/src/posix/cocoa/i_input.mm index eff9640be..7eda4785d 100644 --- a/src/posix/cocoa/i_input.mm +++ b/src/posix/cocoa/i_input.mm @@ -479,8 +479,9 @@ void NSEventToGameMousePosition(NSEvent* inEvent, event_t* outEvent) const NSView* view = [window contentView]; const NSPoint screenPos = [NSEvent mouseLocation]; - const NSPoint windowPos = [window convertScreenToBase:screenPos]; - const NSPoint viewPos = [view convertPointToBacking:windowPos]; + const NSRect screenRect = NSMakeRect(screenPos.x, screenPos.y, 0, 0); + const NSRect windowRect = [window convertRectFromScreen:screenRect]; + const NSPoint viewPos = [view convertPointToBacking:windowRect.origin]; const CGFloat frameHeight = I_GetContentViewSize(window).height; const CGFloat posX = ( viewPos.x - rbOpts.shiftX) / rbOpts.pixelScale; From 65966badb285e8ee8ffeb8aeed3fa679edfba32e Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 7 Oct 2017 16:30:49 +0300 Subject: [PATCH 040/105] Fixed crash on attempt to register IDs for undefined class https://forum.zdoom.org/viewtopic.php?t=46670&start=16#p1021785 --- src/info.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 1eee76fcd..94b263105 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -355,8 +355,16 @@ void PClassActor::RegisterIDs() return; } + FActorInfo *actorInfo = ActorInfo(); + + if (nullptr == actorInfo) + { + // Undefined class, exiting + return; + } + // Conversation IDs have never been filtered by game so we cannot start doing that. - auto ConversationID = ActorInfo()->ConversationID; + auto ConversationID = actorInfo->ConversationID; if (ConversationID > 0) { StrifeTypes[ConversationID] = cls; @@ -365,9 +373,9 @@ void PClassActor::RegisterIDs() Printf(TEXTCOLOR_RED"Conversation ID %d refers to hidden class type '%s'\n", ConversationID, cls->TypeName.GetChars()); } } - if (ActorInfo()->GameFilter == GAME_Any || (ActorInfo()->GameFilter & gameinfo.gametype)) + if (actorInfo->GameFilter == GAME_Any || (ActorInfo()->GameFilter & gameinfo.gametype)) { - auto SpawnID = ActorInfo()->SpawnID; + auto SpawnID = actorInfo->SpawnID; if (SpawnID > 0) { SpawnableThings[SpawnID] = cls; @@ -376,7 +384,7 @@ void PClassActor::RegisterIDs() Printf(TEXTCOLOR_RED"Spawn ID %d refers to hidden class type '%s'\n", SpawnID, cls->TypeName.GetChars()); } } - auto DoomEdNum = ActorInfo()->DoomEdNum; + auto DoomEdNum = actorInfo->DoomEdNum; if (DoomEdNum != -1) { FDoomEdEntry *oldent = DoomEdMap.CheckKey(DoomEdNum); From 44373b414fb639f514316a828c02050768b2216c Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 7 Oct 2017 19:36:42 -0400 Subject: [PATCH 041/105] - bump for 3.3pre --- src/version.h | 12 ++++++------ wadsrc/static/zscript.txt | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/version.h b/src/version.h index f7c7da4be..a4328141d 100644 --- a/src/version.h +++ b/src/version.h @@ -48,22 +48,22 @@ const char *GetVersionString(); #ifdef GIT_DESCRIPTION #define VERSIONSTR GIT_DESCRIPTION #else -#define VERSIONSTR "3.2pre" +#define VERSIONSTR "3.3pre" #endif // The version as seen in the Windows resource -#define RC_FILEVERSION 3,1,9999,0 -#define RC_PRODUCTVERSION 3,1,9999,0 +#define RC_FILEVERSION 3,2,9999,0 +#define RC_PRODUCTVERSION 3,2,9999,0 #define RC_PRODUCTVERSION2 VERSIONSTR -// These are for content versioning. The current state is '3.2'. +// These are for content versioning. The current state is '3.3'. #define VER_MAJOR 3 -#define VER_MINOR 2 +#define VER_MINOR 3 #define VER_REVISION 0 // Version identifier for network games. // Bump it every time you do a release unless you're certain you // didn't change anything that will affect sync. -#define NETGAMEVERSION 234 +#define NETGAMEVERSION 235 // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 1cabc4975..919e2f97f 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "2.5" +version "3.3" #include "zscript/base.txt" #include "zscript/sounddata.txt" #include "zscript/mapdata.txt" From 69abf095c9dfe5f80eb75811eca416b8ff8cf859 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 7 Oct 2017 20:18:37 -0400 Subject: [PATCH 042/105] - added vid_cropaspect. This cvar turns vid_aspect into a letterboxing function that will crop the unused sides of the screen away, instead of stretching it. Requires one of the non-legacy OpenGL framebuffers to work. --- src/gl/system/gl_framebuffer.cpp | 6 ++++-- src/gl/system/gl_swframebuffer.cpp | 4 ++-- src/r_videoscale.cpp | 11 +++++++++-- src/r_videoscale.h | 4 ++-- src/v_video.cpp | 2 +- wadsrc/static/language.enu | 2 ++ wadsrc/static/menudef.txt | 6 ++++++ 7 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index f4e68791e..b10b8b418 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -182,8 +182,10 @@ void OpenGLFrameBuffer::Update() Unlock(); CheckBench(); - int clientWidth = ViewportScaledWidth(IsFullscreen() ? VideoWidth : GetClientWidth()); - int clientHeight = ViewportScaledHeight(IsFullscreen() ? VideoHeight : GetClientHeight()); + int initialWidth = IsFullscreen() ? VideoWidth : GetClientWidth(); + int initialHeight = IsFullscreen() ? VideoHeight : GetClientHeight(); + int clientWidth = ViewportScaledWidth(initialWidth, initialHeight); + int clientHeight = ViewportScaledHeight(initialWidth, initialHeight); if (clientWidth > 0 && clientHeight > 0 && (Width != clientWidth || Height != clientHeight)) { // Do not call Resize here because it's only for software canvases diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 937778847..85bddf8c6 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -1304,8 +1304,8 @@ void OpenGLSWFrameBuffer::Flip() if (!IsFullscreen()) { - int clientWidth = ViewportScaledWidth(GetClientWidth()); - int clientHeight = ViewportScaledHeight(GetClientHeight()); + int clientWidth = ViewportScaledWidth(GetClientWidth(), GetClientHeight()); + int clientHeight = ViewportScaledHeight(GetClientWidth(), GetClientHeight()); if (clientWidth > 0 && clientHeight > 0 && (Width != clientWidth || Height != clientHeight)) { Resize(clientWidth, clientHeight); diff --git a/src/r_videoscale.cpp b/src/r_videoscale.cpp index 29c4eb03e..0bffc91bf 100644 --- a/src/r_videoscale.cpp +++ b/src/r_videoscale.cpp @@ -24,6 +24,7 @@ #include #include "c_dispatch.h" #include "c_cvars.h" +#include "v_video.h" #define NUMSCALEMODES 5 @@ -64,6 +65,8 @@ CUSTOM_CVAR(Int, vid_scalemode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) self = 0; } +CVAR(Bool, vid_cropaspect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + bool ViewportLinearScale() { if (isOutOfBounds(vid_scalemode)) @@ -72,17 +75,21 @@ bool ViewportLinearScale() return (vid_scalefactor > 1.0) ? true : vScaleTable[vid_scalemode].isLinear; } -int ViewportScaledWidth(int width) +int ViewportScaledWidth(int width, int height) { if (isOutOfBounds(vid_scalemode)) vid_scalemode = 0; + if (vid_cropaspect && height > 0) + width = (width/height > ActiveRatio(width, height)) ? height * ActiveRatio(width, height) : width; return vScaleTable[vid_scalemode].GetScaledWidth((int)((float)width * vid_scalefactor)); } -int ViewportScaledHeight(int height) +int ViewportScaledHeight(int width, int height) { if (isOutOfBounds(vid_scalemode)) vid_scalemode = 0; + if (vid_cropaspect && height > 0) + height = (width/height < ActiveRatio(width, height)) ? width / ActiveRatio(width, height) : height; return vScaleTable[vid_scalemode].GetScaledHeight((int)((float)height * vid_scalefactor)); } diff --git a/src/r_videoscale.h b/src/r_videoscale.h index 002fc7c38..2fcbbc85b 100644 --- a/src/r_videoscale.h +++ b/src/r_videoscale.h @@ -25,7 +25,7 @@ #define __VIDEOSCALE_H__ EXTERN_CVAR (Int, vid_scalemode) bool ViewportLinearScale(); -int ViewportScaledWidth(int width); -int ViewportScaledHeight(int height); +int ViewportScaledWidth(int width, int height); +int ViewportScaledHeight(int width, int height); bool ViewportIsScaled43(); #endif //__VIDEOSCALE_H__ \ No newline at end of file diff --git a/src/v_video.cpp b/src/v_video.cpp index 4bbe646ad..b9dfeae08 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -783,7 +783,7 @@ void DSimpleCanvas::Unlock () //========================================================================== DFrameBuffer::DFrameBuffer (int width, int height, bool bgra) - : DSimpleCanvas (ViewportScaledWidth(width), ViewportScaledHeight(height), bgra) + : DSimpleCanvas (ViewportScaledWidth(width, height), ViewportScaledHeight(width, height), bgra) { LastMS = LastSec = FrameCount = LastCount = LastTic = 0; Accel2D = false; diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 387477151..e68c9ae86 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2191,6 +2191,7 @@ VIDMNU_FULLSCREEN = "Fullscreen"; VIDMNU_HIDPI = "Retina/HiDPI support"; VIDMNU_ASPECTRATIO = "Aspect ratio"; VIDMNU_FORCEASPECT = "Force aspect ratio"; +VIDMNU_CROPASPECT = "Forced ratio style"; VIDMNU_5X4ASPECTRATIO = "Enable 5:4 aspect ratio"; VIDMNU_SCALEMODE = "Resolution scale"; VIDMNU_SCALEFACTOR = "Scale Factor"; @@ -2381,6 +2382,7 @@ OPTVAL_VTAZDOOM = "Auto (ZDoom Preferred)"; OPTVAL_VTAVANILLA = "Auto (Vanilla Preferred)"; OPTVAL_SCALENEAREST = "Scaled (Nearest)"; OPTVAL_SCALELINEAR = "Scaled (Linear)"; +OPTVAL_LETTERBOX = "Letterbox"; // Colors C_BRICK = "\cabrick"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index fd46b153b..b3cd95a21 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1868,6 +1868,11 @@ OptionValue ScaleModes 3, "640x400" 4, "1280x800" } +OptionValue CropAspect +{ + 0, "$OPTVAL_STRETCH" + 1, "$OPTVAL_LETTERBOX" +} OptionMenu VideoModeMenu protected { @@ -1880,6 +1885,7 @@ OptionMenu VideoModeMenu protected } Option "$VIDMNU_ASPECTRATIO", "menu_screenratios", "Ratios" Option "$VIDMNU_FORCEASPECT", "vid_aspect", "ForceRatios" + Option "$VIDMNU_CROPASPECT", "vid_cropaspect", "CropAspect" Option "$VIDMNU_5X4ASPECTRATIO", "vid_tft", "YesNo" Option "$VIDMNU_SCALEMODE", "vid_scalemode", "ScaleModes" Slider "$VIDMNU_SCALEFACTOR", "vid_scalefactor", 0.25, 2.0, 0.25, 2 From fc0ae896b2e2ad8941eff82033e350623b9a033a Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 10 Oct 2017 06:38:07 -0400 Subject: [PATCH 043/105] - remove vid_tft and vid_nowidescreen and associated menu option. Their functionality was supersceded and extended by vid_aspect==3 (which has the same effect as setting both to true anyhow), and it was mostly just redundant. --- src/menu/videomenu.cpp | 33 --------------------------------- src/v_video.cpp | 21 --------------------- wadsrc/static/menudef.txt | 10 ---------- 3 files changed, 64 deletions(-) diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 7d434843b..cea99cd42 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -74,7 +74,6 @@ EXTERN_CVAR (Int, vid_defwidth) EXTERN_CVAR (Int, vid_defheight) EXTERN_CVAR (Int, vid_defbits) EXTERN_CVAR (Bool, fullscreen) -EXTERN_CVAR (Bool, vid_tft) // Defined below int testingmode; // Holds time to revert to old mode int OldWidth, OldHeight, OldBits; @@ -87,43 +86,12 @@ CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE) { self = -1; } - else if (self == 4 && !vid_tft) - { - self = 0; - } else { BuildModesList (screen->VideoWidth, screen->VideoHeight, DisplayBits); } } -CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - const int OptionMenuItemOptionBase_OP_VALUES = 0x11001; - - DOptionMenuDescriptor *opt = GetVideoModeMenu(); - if (opt != NULL) - { - DMenuItemBase *it = opt->GetItem("menu_screenratios"); - if (it != NULL) - { - if (self) - { - it->SetString(OptionMenuItemOptionBase_OP_VALUES, "RatiosTFT"); - } - else - { - it->SetString(OptionMenuItemOptionBase_OP_VALUES, "Ratios"); - } - } - } - setsizeneeded = true; - if (StatusBar != NULL) - { - StatusBar->CallScreenSizeChanged(); - } -} - //============================================================================= // @@ -278,7 +246,6 @@ void M_InitVideoModesMenu () size_t currval = 0; M_RefreshModesList(); - vid_tft.Callback(); for (unsigned int i = 1; i <= 32 && currval < countof(BitTranslate); i++) { diff --git a/src/v_video.cpp b/src/v_video.cpp index b9dfeae08..926812534 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1592,16 +1592,6 @@ void V_Shutdown() V_ClearFonts(); } -EXTERN_CVAR (Bool, vid_tft) -CUSTOM_CVAR (Bool, vid_nowidescreen, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) -{ - setsizeneeded = true; - if (StatusBar != NULL) - { - StatusBar->CallScreenSizeChanged(); - } -} - CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) { setsizeneeded = true; @@ -1632,17 +1622,6 @@ int ActiveFakeRatio(int width, int height) { fakeratio = 0; } - if (vid_nowidescreen) - { - if (!vid_tft) - { - fakeratio = 0; - } - else - { - fakeratio = (height * 5 / 4 == width) ? 4 : 0; - } - } return fakeratio; } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b3cd95a21..3d0621c3f 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1842,15 +1842,6 @@ OptionValue ForceRatios 6.0, "21:9" } OptionValue Ratios -{ - 0.0, "4:3" - 1.0, "16:9" - 2.0, "16:10" - 3.0, "17:10" - 6.0, "21:9" - -1, "$OPTVAL_ALL" -} -OptionValue RatiosTFT { 0.0, "4:3" 4.0, "5:4" @@ -1886,7 +1877,6 @@ OptionMenu VideoModeMenu protected Option "$VIDMNU_ASPECTRATIO", "menu_screenratios", "Ratios" Option "$VIDMNU_FORCEASPECT", "vid_aspect", "ForceRatios" Option "$VIDMNU_CROPASPECT", "vid_cropaspect", "CropAspect" - Option "$VIDMNU_5X4ASPECTRATIO", "vid_tft", "YesNo" Option "$VIDMNU_SCALEMODE", "vid_scalemode", "ScaleModes" Slider "$VIDMNU_SCALEFACTOR", "vid_scalefactor", 0.25, 2.0, 0.25, 2 StaticText " " From 7d67d5e9986eb5e79bca96205544acd5b44b4be2 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 10 Oct 2017 07:23:05 -0400 Subject: [PATCH 044/105] - fixed possible erroneous comparison, also fixed a couple compiler warnings in the process --- src/r_videoscale.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_videoscale.cpp b/src/r_videoscale.cpp index 0bffc91bf..ff8e7eb28 100644 --- a/src/r_videoscale.cpp +++ b/src/r_videoscale.cpp @@ -80,7 +80,7 @@ int ViewportScaledWidth(int width, int height) if (isOutOfBounds(vid_scalemode)) vid_scalemode = 0; if (vid_cropaspect && height > 0) - width = (width/height > ActiveRatio(width, height)) ? height * ActiveRatio(width, height) : width; + width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width; return vScaleTable[vid_scalemode].GetScaledWidth((int)((float)width * vid_scalefactor)); } @@ -89,7 +89,7 @@ int ViewportScaledHeight(int width, int height) if (isOutOfBounds(vid_scalemode)) vid_scalemode = 0; if (vid_cropaspect && height > 0) - height = (width/height < ActiveRatio(width, height)) ? width / ActiveRatio(width, height) : height; + height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height; return vScaleTable[vid_scalemode].GetScaledHeight((int)((float)height * vid_scalefactor)); } From 80701927e89a31c10b94e2fba27a6f75586d15e1 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Wed, 11 Oct 2017 17:22:22 +0200 Subject: [PATCH 045/105] Fixed: don't interpolate view movements if a key press didn't result in any changes. --- src/d_main.cpp | 4 ++-- src/g_game.cpp | 14 ++++---------- src/g_game.h | 4 ++-- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 923d510ec..90dbb99b4 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -328,12 +328,12 @@ void D_PostEvent (const event_t *ev) int look = int(ev->y * m_pitch * mouse_sensitivity * 16.0); if (invertmouse) look = -look; - G_AddViewPitch (look); + G_AddViewPitch (look, true); events[eventhead].y = 0; } if (!Button_Strafe.bDown && !lookstrafe) { - G_AddViewAngle (int(ev->x * m_yaw * mouse_sensitivity * 8.0)); + G_AddViewAngle (int(ev->x * m_yaw * mouse_sensitivity * 8.0), true); events[eventhead].x = 0; } if ((events[eventhead].x | events[eventhead].y) == 0) diff --git a/src/g_game.cpp b/src/g_game.cpp index d3dd47f46..584cddfa1 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -608,24 +608,20 @@ void G_BuildTiccmd (ticcmd_t *cmd) if (Button_Right.bDown) { G_AddViewAngle (angleturn[tspeed]); - LocalKeyboardTurner = true; } if (Button_Left.bDown) { G_AddViewAngle (-angleturn[tspeed]); - LocalKeyboardTurner = true; } } if (Button_LookUp.bDown) { G_AddViewPitch (lookspeed[speed]); - LocalKeyboardTurner = true; } if (Button_LookDown.bDown) { G_AddViewPitch (-lookspeed[speed]); - LocalKeyboardTurner = true; } if (Button_MoveUp.bDown) @@ -701,12 +697,10 @@ void G_BuildTiccmd (ticcmd_t *cmd) if (joyaxes[JOYAXIS_Pitch] != 0) { G_AddViewPitch(joyint(joyaxes[JOYAXIS_Pitch] * 2048)); - LocalKeyboardTurner = true; } if (joyaxes[JOYAXIS_Yaw] != 0) { G_AddViewAngle(joyint(-1280 * joyaxes[JOYAXIS_Yaw])); - LocalKeyboardTurner = true; } side -= joyint(sidemove[speed] * joyaxes[JOYAXIS_Side]); @@ -794,7 +788,7 @@ void G_BuildTiccmd (ticcmd_t *cmd) //[Graf Zahl] This really helps if the mouse update rate can't be increased! CVAR (Bool, smooth_mouse, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) -void G_AddViewPitch (int look) +void G_AddViewPitch (int look, bool mouse) { if (gamestate == GS_TITLELEVEL) { @@ -837,11 +831,11 @@ void G_AddViewPitch (int look) } if (look != 0) { - LocalKeyboardTurner = smooth_mouse; + LocalKeyboardTurner = (!mouse || smooth_mouse); } } -void G_AddViewAngle (int yaw) +void G_AddViewAngle (int yaw, bool mouse) { if (gamestate == GS_TITLELEVEL) { @@ -857,7 +851,7 @@ void G_AddViewAngle (int yaw) LocalViewAngle -= yaw; if (yaw != 0) { - LocalKeyboardTurner = smooth_mouse; + LocalKeyboardTurner = (!mouse || smooth_mouse); } } diff --git a/src/g_game.h b/src/g_game.h index 3a11e31f2..2ac019059 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -89,10 +89,10 @@ void G_DoReborn (int playernum, bool freshbot); void G_DoPlayerPop(int playernum); // Adds pitch to consoleplayer's viewpitch and clamps it -void G_AddViewPitch (int look); +void G_AddViewPitch (int look, bool mouse = false); // Adds to consoleplayer's viewangle if allowed -void G_AddViewAngle (int yaw); +void G_AddViewAngle (int yaw, bool mouse = false); #define BODYQUESIZE 32 class AActor; From 2e4ffbb1d17bb1b352d9f1cc66e069a5e31375c0 Mon Sep 17 00:00:00 2001 From: Dugan Chen Date: Thu, 12 Oct 2017 07:01:46 -0700 Subject: [PATCH 046/105] If *nix, add default gzdoom.pk3 directory t File.Search paths --- src/gameconfigfile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index cfbbe5fb7..6e731d2bc 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -150,6 +150,10 @@ FGameConfigFile::FGameConfigFile () #else SetValueForKey ("Path", "~/" GAME_DIR, true); SetValueForKey ("Path", SHARE_DIR, true); + SetValueForKey ("Path", "/usr/local/share/doom", true); + SetValueForKey ("Path", "/usr/local/share/games/doom", true); + SetValueForKey ("Path", "/usr/share/doom", true); + SetValueForKey ("Path", "/usr/share/games/doom", true); #endif SetValueForKey ("Path", "$DOOMWADDIR", true); } From 1b6f77a473c356a1e1c691bfdbf8b453c6876910 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 12 Oct 2017 11:54:56 -0400 Subject: [PATCH 047/105] - fixed: inverted vertically texture uniforms for custom post-process shaders, and also changed their input format to BGRA to match the standard. --- src/gl/shaders/gl_postprocessshader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gl/shaders/gl_postprocessshader.cpp b/src/gl/shaders/gl_postprocessshader.cpp index d4ab9bbc9..3e0a3202a 100644 --- a/src/gl/shaders/gl_postprocessshader.cpp +++ b/src/gl/shaders/gl_postprocessshader.cpp @@ -234,12 +234,12 @@ void PostProcessShaderInstance::BindTextures() { FBitmap bitmap; bitmap.Create(tex->GetWidth(), tex->GetHeight()); - tex->CopyTrueColorPixels(&bitmap, 0, 0); + tex->CopyTrueColorPixels(&bitmap, 0, 0, 6); GLuint handle = 0; glGenTextures(1, &handle); glBindTexture(GL_TEXTURE_2D, handle); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex->GetWidth(), tex->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.GetPixels()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex->GetWidth(), tex->GetHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, bitmap.GetPixels()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); mTextureHandles[tex] = handle; From 0ccd388d9151f63c83a8046735a3f6a5d082cf0c Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 12 Oct 2017 12:44:00 -0400 Subject: [PATCH 048/105] - reverted the texture flip from the previous commit --- src/gl/shaders/gl_postprocessshader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/shaders/gl_postprocessshader.cpp b/src/gl/shaders/gl_postprocessshader.cpp index 3e0a3202a..1b62b1b14 100644 --- a/src/gl/shaders/gl_postprocessshader.cpp +++ b/src/gl/shaders/gl_postprocessshader.cpp @@ -234,7 +234,7 @@ void PostProcessShaderInstance::BindTextures() { FBitmap bitmap; bitmap.Create(tex->GetWidth(), tex->GetHeight()); - tex->CopyTrueColorPixels(&bitmap, 0, 0, 6); + tex->CopyTrueColorPixels(&bitmap, 0, 0); GLuint handle = 0; glGenTextures(1, &handle); From 30c6cf82ca3a76cf675be07844bf729b0c2a7061 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 14 Oct 2017 13:05:15 -0400 Subject: [PATCH 049/105] - added ability to change slider color using mapinfo's gameinfo --- src/gi.cpp | 2 ++ src/gi.h | 1 + wadsrc/static/mapinfo/chex.txt | 1 + wadsrc/static/mapinfo/doomcommon.txt | 1 + wadsrc/static/mapinfo/heretic.txt | 1 + wadsrc/static/mapinfo/hexen.txt | 1 + wadsrc/static/mapinfo/mindefaults.txt | 1 + wadsrc/static/mapinfo/strife.txt | 1 + wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/menu/optionmenuitems.txt | 4 ++-- wadsrc/static/zscript/menu/playercontrols.txt | 2 +- 11 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/gi.cpp b/src/gi.cpp index 202122b32..54ed81be5 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -63,6 +63,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, intermissioncounter) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_single) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_coop) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_dm) +DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mSliderColor) const char *GameNames[17] = @@ -382,6 +383,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_COLOR(dimcolor, "dimcolor") GAMEINFOKEY_FLOAT(dimamount, "dimamount") GAMEINFOKEY_FLOAT(bluramount, "bluramount") + GAMEINFOKEY_STRING(mSliderColor, "menuslidercolor") GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount") GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") diff --git a/src/gi.h b/src/gi.h index 97ce7f99c..b4aacbaf7 100644 --- a/src/gi.h +++ b/src/gi.h @@ -173,6 +173,7 @@ struct gameinfo_t FName mFontColorHeader; FName mFontColorHighlight; FName mFontColorSelection; + FName mSliderColor; FString mBackButton; double gibfactor; int TextScreenX; diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index 87ecf5aa4..1eab8b20e 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -39,6 +39,7 @@ gameinfo dimcolor = "ff d7 00" dimamount = 0.2 bluramount = 0.0 + menuslidercolor = "Orange" definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 diff --git a/wadsrc/static/mapinfo/doomcommon.txt b/wadsrc/static/mapinfo/doomcommon.txt index b4fea47a6..cb97fbabf 100644 --- a/wadsrc/static/mapinfo/doomcommon.txt +++ b/wadsrc/static/mapinfo/doomcommon.txt @@ -39,6 +39,7 @@ gameinfo dimcolor = "ff d7 00" dimamount = 0.2 bluramount = 0.0 + menuslidercolor = "Orange" definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt index 3481f82af..63468afb5 100644 --- a/wadsrc/static/mapinfo/heretic.txt +++ b/wadsrc/static/mapinfo/heretic.txt @@ -39,6 +39,7 @@ gameinfo dimcolor = "00 00 ff" dimamount = 0.2 bluramount = 0 + menuslidercolor = "Orange" definventorymaxamount = 16 defaultrespawntime = 12 defaultdropstyle = 1 diff --git a/wadsrc/static/mapinfo/hexen.txt b/wadsrc/static/mapinfo/hexen.txt index 64cf3b4f7..8c959c33b 100644 --- a/wadsrc/static/mapinfo/hexen.txt +++ b/wadsrc/static/mapinfo/hexen.txt @@ -38,6 +38,7 @@ gameinfo dimcolor = "00 00 ff" dimamount = 0.2 bluramount = 0.0 + menuslidercolor = "Orange" definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 diff --git a/wadsrc/static/mapinfo/mindefaults.txt b/wadsrc/static/mapinfo/mindefaults.txt index 4199a0a6f..ad7c1395f 100644 --- a/wadsrc/static/mapinfo/mindefaults.txt +++ b/wadsrc/static/mapinfo/mindefaults.txt @@ -28,6 +28,7 @@ gameinfo dimcolor = "6f 00 6b" dimamount = 0.8 bluramount = 0.0 + menuslidercolor = "Orange" definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 diff --git a/wadsrc/static/mapinfo/strife.txt b/wadsrc/static/mapinfo/strife.txt index 5d320dd26..1a57e5337 100644 --- a/wadsrc/static/mapinfo/strife.txt +++ b/wadsrc/static/mapinfo/strife.txt @@ -39,6 +39,7 @@ gameinfo dimcolor = "ff d7 00" dimamount = 0.2 bluramount = 0 + menuslidercolor = "Orange" definventorymaxamount = 25 defaultrespawntime = 16 defaultdropstyle = 2 diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index f9fd571ed..898265995 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -333,6 +333,7 @@ struct GameInfoStruct native native GIFont mStatscreenFinishedFont; native double gibfactor; native bool intermissioncounter; + native Name mSliderColor; } class Object native diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index a778dc682..f08dca713 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -694,13 +694,13 @@ class OptionMenuSliderBase : OptionMenuItem if (!mSliderShort) { Menu.DrawConText(Font.CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12"); - Menu.DrawConText(Font.CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13"); + Menu.DrawConText(Font.FindFontColor(gameinfo.mSliderColor), x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13"); } else { // On 320x200 we need a shorter slider Menu.DrawConText(Font.CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x12"); - Menu.DrawConText(Font.CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13"); + Menu.DrawConText(Font.FindFontColor(gameinfo.mSliderColor), x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13"); right -= 5*8*CleanXfac_1; } diff --git a/wadsrc/static/zscript/menu/playercontrols.txt b/wadsrc/static/zscript/menu/playercontrols.txt index 4200627d9..6b3a9bcf4 100644 --- a/wadsrc/static/zscript/menu/playercontrols.txt +++ b/wadsrc/static/zscript/menu/playercontrols.txt @@ -506,7 +506,7 @@ class ListMenuItemSlider : ListMenuItemSelectable y = (y - 100) * CleanYfac + screen.GetHeight() / 2; screen.DrawText (ConFont, Font.CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); - screen.DrawText (ConFont, Font.CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, "\x13", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); + screen.DrawText (ConFont, Font.FindFontColor(gameinfo.mSliderColor), x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, "\x13", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); } //============================================================================= From 4fb355d8da8b752be74b2aa583b9890870ad18fb Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 14 Oct 2017 17:41:43 -0400 Subject: [PATCH 050/105] - added 'startuptype' to iwadinfo, allowing to change the game startup screen with custom iwads --- src/d_iwad.cpp | 16 ++++++++++++++++ src/d_main.h | 36 ++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 44ecb2ff5..ebce048bc 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -182,6 +182,21 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, sc.MustGetString(); iwad->Required = sc.String; } + else if (sc.Compare("StartupType")) + { + sc.MustGetStringName("="); + sc.MustGetString(); + FString sttype = sc.String; + if (!sttype.CompareNoCase("DOOM")) + iwad->StartupType = FStartupInfo::DoomStartup; + else if (!sttype.CompareNoCase("HERETIC")) + iwad->StartupType = FStartupInfo::HereticStartup; + else if (!sttype.CompareNoCase("HEXEN")) + iwad->StartupType = FStartupInfo::HexenStartup; + else if (!sttype.CompareNoCase("STRIFE")) + iwad->StartupType = FStartupInfo::StrifeStartup; + else iwad->StartupType = FStartupInfo::DefaultStartup; + } else { sc.ScriptError("Unknown keyword '%s'", sc.String); @@ -739,6 +754,7 @@ const FIWADInfo *FIWadManager::FindIWAD(TArray &wadfiles, const char *i DoomStartupInfo.BkColor = iwad_info->BkColor; DoomStartupInfo.FgColor = iwad_info->FgColor; } + if (DoomStartupInfo.Type == 0) DoomStartupInfo.Type = iwad_info->StartupType; I_SetIWADInfo(); return iwad_info; } diff --git a/src/d_main.h b/src/d_main.h index e5abd0e01..1fa0368d6 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -74,6 +74,23 @@ struct WadStuff FString Name; }; +struct FStartupInfo +{ + FString Name; + uint32_t FgColor; // Foreground color for title banner + uint32_t BkColor; // Background color for title banner + FString Song; + int Type; + enum + { + DefaultStartup, + DoomStartup, + HereticStartup, + HexenStartup, + StrifeStartup, + }; +}; + struct FIWADInfo { FString Name; // Title banner text for this IWAD @@ -85,6 +102,7 @@ struct FIWADInfo uint32_t FgColor = 0; // Foreground color for title banner uint32_t BkColor = 0xc0c0c0; // Background color for title banner EGameType gametype = GAME_Doom; // which game are we playing? + int StartupType = FStartupInfo::DefaultStartup; // alternate startup type FString MapInfo; // Base mapinfo to load TArray Load; // Wads to be loaded with this one. TArray Lumps; // Lump names for identification @@ -104,24 +122,6 @@ struct FFoundWadInfo } }; -struct FStartupInfo -{ - FString Name; - uint32_t FgColor; // Foreground color for title banner - uint32_t BkColor; // Background color for title banner - FString Song; - int Type; - enum - { - DefaultStartup, - DoomStartup, - HereticStartup, - HexenStartup, - StrifeStartup, - }; - -}; - extern FStartupInfo DoomStartupInfo; //========================================================================== From 07c32912629dcc8e58ceda7c3b7b04f58ba6a3c9 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 14 Oct 2017 17:44:17 -0400 Subject: [PATCH 051/105] - fixed: removed erroneous 'defaultrespawntime' macro double so that there's only one --- src/gi.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gi.cpp b/src/gi.cpp index 54ed81be5..19cfd3ee7 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -386,7 +386,6 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRING(mSliderColor, "menuslidercolor") GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount") GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") - GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle") GAMEINFOKEY_STRING(Endoom, "endoom") GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false) From 4f5b459703e6865bb29912c74a63e423b4b277b2 Mon Sep 17 00:00:00 2001 From: Dugan Chen Date: Sat, 14 Oct 2017 23:19:53 -0700 Subject: [PATCH 052/105] Remove SHARE_DIR from FileSearch.Directories for *nix --- src/gameconfigfile.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 6e731d2bc..f6fc12dfa 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -149,7 +149,6 @@ FGameConfigFile::FGameConfigFile () SetValueForKey ("Path", "$PROGDIR", true); #else SetValueForKey ("Path", "~/" GAME_DIR, true); - SetValueForKey ("Path", SHARE_DIR, true); SetValueForKey ("Path", "/usr/local/share/doom", true); SetValueForKey ("Path", "/usr/local/share/games/doom", true); SetValueForKey ("Path", "/usr/share/doom", true); From 13584b9a9dc8100ccfec02f1cf1d63d7c235ed79 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 21 Oct 2017 10:47:13 +0300 Subject: [PATCH 053/105] Fixed applying of compatibility settings for IWADs https://forum.zdoom.org/viewtopic.php?t=58239 --- src/compatibility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 947b7ffae..8c3cc16c5 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -465,7 +465,7 @@ void CheckCompatibility(MapData *map) // When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT. // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. - if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATSHORTTEX) && level.maptype == MAPTYPE_DOOM) + if (Wads.GetLumpFile(map->lumpnum) == Wads.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && level.maptype == MAPTYPE_DOOM) { ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX; From 724d711d1f39396a651a0af0fd9d63a1bddcb6b1 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 21 Oct 2017 11:10:36 +0300 Subject: [PATCH 054/105] Fixed a few cases when IWAD was checked by hardcoded index --- src/g_game.cpp | 2 +- src/gl/data/gl_data.cpp | 2 +- src/intermission/intermission_parse.cpp | 2 +- src/v_font.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 584cddfa1..db5c1cb2e 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2193,7 +2193,7 @@ static void PutSaveWads (FSerializer &arc) arc.AddString("Game WAD", name); // Name of wad the map resides in - if (Wads.GetLumpFile (level.lumpnum) > 1) + if (Wads.GetLumpFile (level.lumpnum) > Wads.GetIwadNum()) { name = Wads.GetWadName (Wads.GetLumpFile (level.lumpnum)); arc.AddString("Map WAD", name); diff --git a/src/gl/data/gl_data.cpp b/src/gl/data/gl_data.cpp index d0b1a4a28..9a7c2e037 100644 --- a/src/gl/data/gl_data.cpp +++ b/src/gl/data/gl_data.cpp @@ -87,7 +87,7 @@ void AdjustSpriteOffsets() for (int i = 0; i < numtex; i++) { - if (Wads.GetLumpFile(i) > 1) break; // we are past the IWAD + if (Wads.GetLumpFile(i) > Wads.GetIwadNum()) break; // we are past the IWAD if (Wads.GetLumpNamespace(i) == ns_sprites && Wads.GetLumpFile(i) == Wads.GetIwadNum()) { char str[9]; diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index d8f46d2c3..2c3114afe 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -299,7 +299,7 @@ bool FIntermissionActionTextscreen::ParseKey(FScanner &sc) else { // only print an error if coming from a PWAD - if (Wads.GetLumpFile(sc.LumpNum) > 1) + if (Wads.GetLumpFile(sc.LumpNum) > Wads.GetIwadNum()) sc.ScriptMessage("Unknown text lump '%s'", sc.String); mText.Format("Unknown text lump '%s'", sc.String); } diff --git a/src/v_font.cpp b/src/v_font.cpp index 309f8d560..b475fb558 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2361,7 +2361,7 @@ void V_InitFontColors () // which are used by the menu. So we have no choice but to skip this lump so that // all colors work properly. // The text colors should be the end user's choice anyway. - if (Wads.GetLumpFile(lump) == 1) continue; + if (Wads.GetLumpFile(lump) == Wads.GetIwadNum()) continue; } FScanner sc(lump); while (sc.GetString()) From 88deddbc3bc75ad0e62de882b149839d6fa5f112 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 21 Oct 2017 11:37:43 +0300 Subject: [PATCH 055/105] Fixed arch-vile bleeding when damaging target https://forum.zdoom.org/viewtopic.php?t=58220 --- wadsrc/static/zscript/doom/archvile.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/doom/archvile.txt b/wadsrc/static/zscript/doom/archvile.txt index 79c69a324..c6c3f53a8 100644 --- a/wadsrc/static/zscript/doom/archvile.txt +++ b/wadsrc/static/zscript/doom/archvile.txt @@ -136,7 +136,7 @@ extend class Actor A_PlaySound(snd, CHAN_WEAPON); int newdam = targ.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none'); - TraceBleed (newdam > 0 ? newdam : initialdmg, targ); + targ.TraceBleed (newdam > 0 ? newdam : initialdmg, self); Actor fire = tracer; if (fire) From b871b1898d390a6de478cfc795f0675ff2b25878 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 21 Oct 2017 18:07:24 +0100 Subject: [PATCH 056/105] OpenBSD build fix. - No timidity user defined parameters supported. - Shared libraries versioning policy differs on OpenBSD. --- src/sound/mididevices/music_timiditypp_mididevice.cpp | 10 ++++++++++ src/sound/oalsound.cpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index 335265326..b0ce41ead 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -48,7 +48,9 @@ #include #include +#ifndef __OpenBSD__ #include +#endif #include #include @@ -533,7 +535,9 @@ bool TimidityPPMIDIDevice::LaunchTimidity () } int forkres; +#ifndef __OpenBSD__ wordexp_t words; +#endif glob_t glb; // Get timidity executable path @@ -541,8 +545,10 @@ bool TimidityPPMIDIDevice::LaunchTimidity () glob(ExeName.GetChars(), 0, NULL, &glb); if(glb.gl_pathc != 0) exename = glb.gl_pathv[0]; +#ifndef __OpenBSD__ // Get user-defined extra args wordexp(timidity_extargs, &words, WRDE_NOCMD); +#endif std::string chorusarg = std::string("-EFchorus=") + *timidity_chorus; std::string reverbarg = std::string("-EFreverb=") + *timidity_reverb; @@ -557,8 +563,10 @@ bool TimidityPPMIDIDevice::LaunchTimidity () std::vector arglist; arglist.push_back(exename); +#ifndef __OpenBSD__ for(size_t i = 0;i < words.we_wordc;i++) arglist.push_back(words.we_wordv[i]); +#endif if(**timidity_config != '\0') { arglist.push_back("-c"); @@ -611,7 +619,9 @@ bool TimidityPPMIDIDevice::LaunchTimidity () }*/ } +#ifndef __OpenBSD__ wordfree(&words); +#endif globfree (&glb); return ChildProcess != -1; #endif // _WIN32 diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 683f25ae7..b9b0a1b10 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -72,6 +72,8 @@ CVAR (String, snd_alresampler, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) #define OPENALLIB "openal32.dll" #elif defined(__APPLE__) #define OPENALLIB "OpenAL.framework/OpenAL" +#elif defined(__OpenBSD__) +#define OPENALLIB "libopenal.so" #else #define OPENALLIB "libopenal.so.1" #endif From 832c8f6754264de5f323668ef81493690cb0798b Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 23 Oct 2017 03:35:57 -0400 Subject: [PATCH 057/105] - added new Ice Shards, and removed the zd_extra version --- wadsrc/static/sprites/iceca0.png | Bin 0 -> 270 bytes wadsrc/static/sprites/icecb0.png | Bin 0 -> 229 bytes wadsrc/static/sprites/icecc0.png | Bin 0 -> 194 bytes wadsrc/static/sprites/icecd0.png | Bin 0 -> 125 bytes wadsrc_extra/static/sprites/iceca0.png | Bin 193 -> 0 bytes wadsrc_extra/static/sprites/icecb0.png | Bin 189 -> 0 bytes wadsrc_extra/static/sprites/icecc0.png | Bin 155 -> 0 bytes wadsrc_extra/static/sprites/icecd0.png | Bin 118 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 wadsrc/static/sprites/iceca0.png create mode 100644 wadsrc/static/sprites/icecb0.png create mode 100644 wadsrc/static/sprites/icecc0.png create mode 100644 wadsrc/static/sprites/icecd0.png delete mode 100644 wadsrc_extra/static/sprites/iceca0.png delete mode 100644 wadsrc_extra/static/sprites/icecb0.png delete mode 100644 wadsrc_extra/static/sprites/icecc0.png delete mode 100644 wadsrc_extra/static/sprites/icecd0.png diff --git a/wadsrc/static/sprites/iceca0.png b/wadsrc/static/sprites/iceca0.png new file mode 100644 index 0000000000000000000000000000000000000000..d09c2f39ca074064773072f4921696bae38f3fb8 GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRZ!3HF6%}!4MQXJ_;j!8h81&CSM!|XMIG-rWF zWHAE+w=f7ZGR&GI0Tf*0>Eak7G1a$Um+w%31k3Z%~roGIZ2~i<|Vg-$k!FGyADX7Qd*vA_dn8}Q{c$smgkTAR1O*Z zVV*SM$k%B*7w8l*ur(|GeaO*J{#D6ZcFuMy<7C78Tkbu&efPNiteKwct#>?H0CYEl Mr>mdKI;Vst0Qya0dH?_b literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/icecb0.png b/wadsrc/static/sprites/icecb0.png new file mode 100644 index 0000000000000000000000000000000000000000..d4e1544b8f9e427a66b2c7697cf5e5a3cc2c4991 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!3HG%vEKg;5=bv{Oajs@K+MV>X0HjPISV`@ ziy0WWg+Z8+Vb&Z8pkTA7i(?4K%+Ov#z9t6|*5~SB^UE}O(-jK%_O`G`YV|9$RmzL~*8sOI|YV%5tQ8`iJV;Y^d3c+BK* zcZ<*ChKl-=+c}vm!i63m%HwM+{kteCCBj^H{`c`njxgN@xNArMF5B literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/icecc0.png b/wadsrc/static/sprites/icecc0.png new file mode 100644 index 0000000000000000000000000000000000000000..7ab9e68f0b5d10fe5426dfe10f5b4b0a24032c24 GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJy0V3D3_&Eb9j`SkOBp}TU!ZD(5JV2VWz$3Dl zfq`2Xgc%uT&5-~KCV09yhH%VeJ!mM{Vj$vr@pt-)1uB`$Vr33Y+D(%VGKz{F;7}4X ze7N<<;rqoov1R$mDogoZKD04o-cWio_SBLqpC#QGmb81Fx>DLaMf0g@3rEAlbLF#a iTRb%N_y0C(u+PX)cszU7(SJa@7(8A5T-G@yGywqFxH|U$ literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/icecd0.png b/wadsrc/static/sprites/icecd0.png new file mode 100644 index 0000000000000000000000000000000000000000..0a2be07f2ba4c75d3a518aeb6ad8924e340742f5 GIT binary patch literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m`1|*BN@u~nRj`SkOBp}TQ!Y6K*H~?wR0*}aI z1_o|n5N2eUHAey{DDCOu7{W0#d4^Hy+4{Es|0N~<)=vI^`s7Jt1_pmVb{+d3Z6}~I N22WQ%mvv4FO#q|39R&aY literal 0 HcmV?d00001 diff --git a/wadsrc_extra/static/sprites/iceca0.png b/wadsrc_extra/static/sprites/iceca0.png deleted file mode 100644 index d6b3049234c15b0b3e9f884b354b40d3b6e22bba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^AT|dJGmtd8Qrrrpv;urWT>mrt@9LP})G$3Sr@5@8 z+s!3<+LYCsHXL8JWVfGBvYw9fqzTKTBJ!;){N-aV9RliNED7=pW^j0RBMoF;dXZxi zkY)w3UD~r$fV82fi(?3fY;wYbR0hU*oC=dp3c0YYk}xn}*FqQ=Q1v5B2yO9RuaHJPGCIM+y zAZEW}QN9&O8+f`nhH%IxCnP*b0%F5y43k8qR&h&6%u+Jtm5>P9651sxA!gOe$rRe5 cVJXGHkf+QhGdr`R52%;H)78&qol`;+0J(TGrvLx| diff --git a/wadsrc_extra/static/sprites/icecc0.png b/wadsrc_extra/static/sprites/icecc0.png deleted file mode 100644 index 8865d990947ebe99542fda4fc962c7b67832643e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)S!VDzWzUBA^q~rp8LR|kd{I|03_wz}fH)nHK z$NZ*-=}8IYc{$C?mh7H3W%a#iAyJ@8#*!evUi zBiS2n0;M?8iyV_c>OoknC|(Ol^Le^BhH%Ix3kW78gaP>%7(D#>y|w{a44$rjF6*2U FngB*;7@YtB From d98ed1ca6946ddd72ae4aabeb90c9edc61095d80 Mon Sep 17 00:00:00 2001 From: Kevin Caccamo Date: Sun, 22 Oct 2017 16:28:24 -0400 Subject: [PATCH 058/105] New grenade sprites I took these sprites from Eriguns1: https://github.com/XaserAcheron/eriguns --- wadsrc/static/sprites/SGRNA1.png | Bin 0 -> 330 bytes wadsrc/static/sprites/SGRNA2A8.png | Bin 0 -> 377 bytes wadsrc/static/sprites/SGRNA3A7.png | Bin 0 -> 425 bytes wadsrc/static/sprites/SGRNA4A6.png | Bin 0 -> 328 bytes wadsrc/static/sprites/SGRNA5.png | Bin 0 -> 257 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 wadsrc/static/sprites/SGRNA1.png create mode 100644 wadsrc/static/sprites/SGRNA2A8.png create mode 100644 wadsrc/static/sprites/SGRNA3A7.png create mode 100644 wadsrc/static/sprites/SGRNA4A6.png create mode 100644 wadsrc/static/sprites/SGRNA5.png diff --git a/wadsrc/static/sprites/SGRNA1.png b/wadsrc/static/sprites/SGRNA1.png new file mode 100644 index 0000000000000000000000000000000000000000..21c6a74dabdfa4ac3adef9916b15a23b5cb1df0d GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kj`SkOBp?kEVtX>*_A`)XEDmya zVpw-h<|UBBlJ4m1$iT3%pZiZDE0E7w;1OBOz`%DHgc*Qx@SC7X)B|Nrc7!}G4v z)~!;0^O7lB`ig|@|KC!MnC9xG8I@MG?(_PS-QR1cN39k+mO1OnotG{KMvLZb<`PJ{ zx6L=HN65*-_et9kfx>LxmwS?p9QxUKnU%h+nW5nPwB*<8S{wfboU9A`9nXJ?b}=mw zk<=AaQdr}*J??*jk4Yz^*n|I*Czu9=agrsXa6hzz&I^?tKiJS S!nr_iF?hQAxvXanMpx`f07sn6_|D}`n z@-`a?wBBqqVr6CCQ8KgXlB%+STbGDjqhpZ41K0UWr^_4@a&p=9XY%g%_iSgcE8bry zqkAmlz2%MPrc-9_?cce_PxIy`ooU6}N@H_pEn`Yu=E3b@Q`wVtP-<81Y(tiC_L3t4 zPegnQc-<{K4?KS!&`@%KLvf0&<-eTevltk*yniU?v+0V^Y9*1YmPdc>`ycHzsiAJI zSt>h&j-bz~nYI7kZwj4jA31piw_u1qt9QiWo`^KwxBO)l{EXMUq66|To@2ZCbxld+ zE`gO3ytb~lv08ne@BF#j3i4NtvZCLIu+Gk^ZE^_WGB|pCum1Z_%c~}RVBIY)A+xH* R#uOL|44$rjF6*2UngCS%jj#X! literal 0 HcmV?d00001 diff --git a/wadsrc/static/sprites/SGRNA3A7.png b/wadsrc/static/sprites/SGRNA3A7.png new file mode 100644 index 0000000000000000000000000000000000000000..086a1b25ee02c4c5656bba9203d304a490a28917 GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^vOvtk!3HGfNp3R)QXJ_;j!8h84~W^Wye~5X(u~DH z?oJHr&dIz4a#+$GeH|GXHuiJ>Nn{1`ISV`@i-GD7gD~Uq{1quc4O*Tqjv*HQM<*Nd z9Wvl?EpG3Vm8fdyk(IPED0w4T#nZ-T>*UUN@IoVVfx+VGpISq=3aF?|Saam)$Isg* z3z*f_-j5Cq4ZFTI_B^|G*P(5X>OS$_u;@EEYuU!%s<$p2WeFABsZg{vcXrNq9>>cj zH*L;yatTa5z?#zkRO3I#(q5)bOspPL|ERCfI{y9WgY{Phc1JG}@?3d~n_w?(*{ahR;6R z<`wfPro68;d>%7xeSD{f4aikYHCIM+y5VkTCn+c>Di-X*q z7}lMWc?smOq&xaLGB9lH=l+ujQp8!{5n0T@z;_sg8IR|$NC65qdAc};Xawg@*v)%D zfrs_(@+C`B7}^%3bcpawnrP&Atgs}k=Mjs_>yzJpwx9SMl^vCR_1 Date: Sun, 22 Oct 2017 22:38:27 -0400 Subject: [PATCH 059/105] Add credits for grenade sprite --- wadsrc/static/credits/sgrn.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 wadsrc/static/credits/sgrn.txt diff --git a/wadsrc/static/credits/sgrn.txt b/wadsrc/static/credits/sgrn.txt new file mode 100644 index 000000000..b24ffc86d --- /dev/null +++ b/wadsrc/static/credits/sgrn.txt @@ -0,0 +1,2 @@ +The grenade sprite was made by ZDoom forumer Amuscaria, who gave permission to use Demon Eclipse resources for other things: +https://forum.zdoom.org/viewtopic.php?f=42&t=13397&p=642078#p642078 From 7d97963005851b75f684a0ee6b0f8d1213a82ea9 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 23 Oct 2017 11:23:30 +0300 Subject: [PATCH 060/105] Reduced code duplication in FString class Moved resetting of string data to null value into own function --- src/zstring.cpp | 15 +++++---------- src/zstring.h | 8 +++++++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/zstring.cpp b/src/zstring.cpp index a74edd01b..e9b41a6d7 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -66,8 +66,7 @@ FString::FString (const char *copyStr) { if (copyStr == NULL || *copyStr == '\0') { - NullString.RefCount++; - Chars = &NullString.Nothing[0]; + ResetToNull(); } else { @@ -87,8 +86,7 @@ FString::FString (char oneChar) { if (oneChar == '\0') { - NullString.RefCount++; - Chars = &NullString.Nothing[0]; + ResetToNull(); } else { @@ -220,8 +218,7 @@ FString &FString::operator = (const char *copyStr) if (copyStr == NULL || *copyStr == '\0') { Data()->Release(); - NullString.RefCount++; - Chars = &NullString.Nothing[0]; + ResetToNull(); } else { @@ -362,8 +359,7 @@ FString &FString::CopyCStrPart(const char *tail, size_t tailLen) else { Data()->Release(); - NullString.RefCount++; - Chars = &NullString.Nothing[0]; + ResetToNull(); } return *this; } @@ -373,8 +369,7 @@ void FString::Truncate(size_t newlen) if (newlen == 0) { Data()->Release(); - NullString.RefCount++; - Chars = &NullString.Nothing[0]; + ResetToNull(); } else if (newlen < Len()) { diff --git a/src/zstring.h b/src/zstring.h index cdb4dc521..e7ab098dd 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -120,7 +120,7 @@ enum ELumpNum class FString { public: - FString () : Chars(&NullString.Nothing[0]) { NullString.RefCount++; } + FString () { ResetToNull(); } // Copy constructors FString (const FString &other) { AttachToOther (other); } @@ -311,6 +311,12 @@ protected: const FStringData *Data() const { return (FStringData *)Chars - 1; } FStringData *Data() { return (FStringData *)Chars - 1; } + void ResetToNull() + { + NullString.RefCount++; + Chars = &NullString.Nothing[0]; + } + void AttachToOther (const FString &other); void AllocBuffer (size_t len); void ReallocBuffer (size_t newlen); From 3e43572a878704886d60e2543238fc21a3d3789e Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 23 Oct 2017 11:48:04 +0300 Subject: [PATCH 061/105] Added move semantics to FString class --- src/zstring.cpp | 15 +++++++++++++++ src/zstring.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/zstring.cpp b/src/zstring.cpp index e9b41a6d7..f4f57c4f3 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -211,6 +211,21 @@ FString &FString::operator = (const FString &other) } return *this; } + +FString &FString::operator = (FString &&other) +{ + assert (Chars != NULL); + + if (&other != this) + { + Data()->Release(); + Chars = other.Chars; + other.ResetToNull(); + } + + return *this; +} + FString &FString::operator = (const char *copyStr) { if (copyStr != Chars) diff --git a/src/zstring.h b/src/zstring.h index e7ab098dd..b6986361f 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -124,6 +124,7 @@ public: // Copy constructors FString (const FString &other) { AttachToOther (other); } + FString (FString &&other) : Chars(other.Chars) { other.ResetToNull(); } FString (const char *copyStr); FString (const char *copyStr, size_t copyLen); FString (char oneChar); @@ -165,6 +166,7 @@ public: const char &operator[] (unsigned long long index) const { return Chars[index]; } FString &operator = (const FString &other); + FString &operator = (FString &&other); FString &operator = (const char *copyStr); FString operator + (const FString &tail) const; From d526ddf7ae62ed15f75a116718951cd8206c2b6b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 23 Oct 2017 11:49:54 +0300 Subject: [PATCH 062/105] Extended FString class with functions to get first and last characters --- src/zstring.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/zstring.h b/src/zstring.h index b6986361f..b30bef2dc 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -187,6 +187,9 @@ public: FString &operator << (char tail) { return *this += tail; } FString &operator << (const FName &name) { return *this += name.GetChars(); } + const char &Front() const { assert(IsNotEmpty()); return Chars[0]; } + const char &Back() const { assert(IsNotEmpty()); return Chars[Len() - 1]; } + FString Left (size_t numChars) const; FString Right (size_t numChars) const; FString Mid (size_t pos, size_t numChars = ~(size_t)0) const; From cb982ec31376733afe647dec82e8579f29b73e3b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 23 Oct 2017 11:55:20 +0300 Subject: [PATCH 063/105] Use FString::Back() when possible Changed usages of str[str.Len() - 1] to str.Back() --- src/d_iwad.cpp | 2 +- src/d_main.cpp | 4 ++-- src/pathexpander.cpp | 2 +- src/sc_man.cpp | 4 ++-- src/scripting/thingdef_data.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index ebce048bc..f10d48fb7 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -405,7 +405,7 @@ void FIWadManager::CollectSearchPaths() for (auto &str : mSearchPaths) { FixPathSeperator(str); - if (str[str.Len() - 1] == '/') str.Truncate(str.Len() - 1); + if (str.Back() == '/') str.Truncate(str.Len() - 1); } } diff --git a/src/d_main.cpp b/src/d_main.cpp index 90dbb99b4..06a772066 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1720,7 +1720,7 @@ const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinp } if (lookfirstinprogdir) { - mysnprintf (wad, countof(wad), "%s%s%s", progdir.GetChars(), progdir[progdir.Len() - 1] != '/' ? "/" : "", file); + mysnprintf (wad, countof(wad), "%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); if (DirEntryExists (wad)) { return wad; @@ -1747,7 +1747,7 @@ const char *BaseFileSearch (const char *file, const char *ext, bool lookfirstinp dir = NicePath(value); if (dir.IsNotEmpty()) { - mysnprintf (wad, countof(wad), "%s%s%s", dir.GetChars(), dir[dir.Len() - 1] != '/' ? "/" : "", file); + mysnprintf (wad, countof(wad), "%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); if (DirEntryExists (wad)) { return wad; diff --git a/src/pathexpander.cpp b/src/pathexpander.cpp index 2ed0f3ec3..70f9fccc3 100644 --- a/src/pathexpander.cpp +++ b/src/pathexpander.cpp @@ -48,7 +48,7 @@ static FString BuildPath(const FString &base, const char *name) if (base.IsNotEmpty()) { current = base; - if (current[current.Len() - 1] != '/') current += '/'; + if (current.Back() != '/') current += '/'; } current += name; return current; diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 590cba58c..6482fbc10 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -321,11 +321,11 @@ void FScanner::PrepareScript () { // The scanner requires the file to end with a '\n', so add one if // it doesn't already. - if (ScriptBuffer.Len() == 0 || ScriptBuffer[ScriptBuffer.Len() - 1] != '\n') + if (ScriptBuffer.Len() == 0 || ScriptBuffer.Back() != '\n') { // If the last character in the buffer is a null character, change // it to a newline. Otherwise, append a newline to the end. - if (ScriptBuffer.Len() > 0 && ScriptBuffer[ScriptBuffer.Len() - 1] == '\0') + if (ScriptBuffer.Len() > 0 && ScriptBuffer.Back() == '\0') { ScriptBuffer.LockBuffer()[ScriptBuffer.Len() - 1] = '\n'; ScriptBuffer.UnlockBuffer(); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 5f4898b36..08fd1a910 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -1051,7 +1051,7 @@ FString FStringFormat(VM_ARGS) if (in_fmt) { if ((c >= '0' && c <= '9') || - c == '-' || c == '+' || (c == ' ' && fmt_current[fmt_current.Len() - 1] != ' ') || c == '#' || c == '.') + c == '-' || c == '+' || (c == ' ' && fmt_current.Back() != ' ') || c == '#' || c == '.') { fmt_current += c; } From 50d39771c0d72434685833b698258e48d6bce67f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 23 Oct 2017 11:56:39 +0300 Subject: [PATCH 064/105] Fixed out of bound read in zip file loader --- src/resourcefiles/file_zip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 1245cfabe..02e350998 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -312,7 +312,7 @@ bool FZipFile::Open(bool quiet) } // skip Directories - if (name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0) + if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0)) { skipped++; continue; From 66773b6a1ac7687ff5db4de27fe47f7029410f8e Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 23 Oct 2017 12:16:02 -0400 Subject: [PATCH 065/105] - added 'classicflight' user cvar which allows players to move forward and backward without pitch when flying --- src/d_netinfo.cpp | 2 ++ src/d_player.h | 4 ++++ src/namedef.h | 1 + src/p_user.cpp | 6 ++++++ wadsrc/static/zscript/shared/player.txt | 3 ++- 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index a476e4b8a..2928568d0 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -73,6 +73,7 @@ CVAR (Float, movebob, 0.25f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, stillbob, 0.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, wbobspeed, 1.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, playerclass, "Fighter", CVAR_USERINFO | CVAR_ARCHIVE); +CVAR (Bool, classicflight, false, CVAR_USERINFO | CVAR_ARCHIVE); enum { @@ -88,6 +89,7 @@ enum INFO_WBobSpeed, INFO_PlayerClass, INFO_ColorSet, + INFO_ClassicFlight, }; const char *GenderNames[3] = { "male", "female", "other" }; diff --git a/src/d_player.h b/src/d_player.h index 7d8dbf380..c8c5b0fc7 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -330,6 +330,10 @@ struct userinfo_t : TMap { return *static_cast(*CheckKey(NAME_PlayerClass)); } + bool GetClassicFlight() const + { + return *static_cast(*CheckKey(NAME_ClassicFlight)); + } PClassActor *GetPlayerClassType() const { return PlayerClasses[GetPlayerClassNum()].Type; diff --git a/src/namedef.h b/src/namedef.h index 5ba5bafd1..054c53e49 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -768,6 +768,7 @@ xx(ColorSet) xx(NeverSwitchOnPickup) xx(MoveBob) xx(StillBob) +xx(ClassicFlight) xx(WBobSpeed) xx(PlayerClass) xx(MonsterClass) diff --git a/src/p_user.cpp b/src/p_user.cpp index 520861651..d622827ba 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -813,6 +813,12 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetNeverSwitch) ACTION_RETURN_BOOL(self->userinfo.GetNeverSwitch()); } +DEFINE_ACTION_FUNCTION(_PlayerInfo, GetClassicFlight) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + ACTION_RETURN_BOOL(self->userinfo.GetClassicFlight()); +} + DEFINE_ACTION_FUNCTION(_PlayerInfo, GetColor) { PARAM_SELF_STRUCT_PROLOGUE(player_t); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 8b8710416..d43a59ce2 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -746,7 +746,7 @@ class PlayerPawn : Actor native void ForwardThrust (double move, double angle) { - if ((waterlevel || bNoGravity) && Pitch != 0) + if ((waterlevel || bNoGravity) && Pitch != 0 && !player.GetClassicFlight()) { double zpush = move * sin(Pitch); if (waterlevel && waterlevel < 2 && zpush < 0) zpush = 0; @@ -1484,6 +1484,7 @@ struct PlayerInfo native play // this is what internally is known as player_t native float GetAutoaim() const; native bool GetNoAutostartMap() const; native void SetFOV(float fov); + native bool GetClassicFlight() const; native clearscope bool HasWeaponsInSlot(int slot) const; bool IsTotallyFrozen() From 714259d7157cac3338266694ffeea9069c0b59cc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 23 Oct 2017 20:51:00 +0200 Subject: [PATCH 066/105] - removed the ugly grenades from the extra .pk3, now that the main file contains a much nicer and unproblematic replacement. --- wadsrc_extra/static/sprites/sgrna1.png | Bin 186 -> 0 bytes wadsrc_extra/static/sprites/sgrna5.png | Bin 225 -> 0 bytes wadsrc_extra/static/sprites/sgrna6a4.png | Bin 267 -> 0 bytes wadsrc_extra/static/sprites/sgrna7a3.png | Bin 192 -> 0 bytes wadsrc_extra/static/sprites/sgrna8a2.png | Bin 198 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 wadsrc_extra/static/sprites/sgrna1.png delete mode 100644 wadsrc_extra/static/sprites/sgrna5.png delete mode 100644 wadsrc_extra/static/sprites/sgrna6a4.png delete mode 100644 wadsrc_extra/static/sprites/sgrna7a3.png delete mode 100644 wadsrc_extra/static/sprites/sgrna8a2.png diff --git a/wadsrc_extra/static/sprites/sgrna1.png b/wadsrc_extra/static/sprites/sgrna1.png deleted file mode 100644 index 2ef3bbdf5edff9fe313ba41f1d7d18612b1a0205..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^93afX3?$7I7w-UZ(u*9EfHVsbGru#PB?F{Y0(?ST zfwa21y0x{nv$J!4e!jlG{_*3-moH!L@9%&6_HAKdVQFdU6*u*N0o5^<1o;IsI6S+N z2ILrcx;TbZ#3d&Lge4^;l${qz*iaBU`-H-pq**5vRNjRg*$^6dWMZTC38#j}#DyBn Z43(?da^{4KHv{!Dc)I$ztaD0e0swwdHn#u( diff --git a/wadsrc_extra/static/sprites/sgrna5.png b/wadsrc_extra/static/sprites/sgrna5.png deleted file mode 100644 index f3b2e1787709a219459b18e4aa8786c625e449ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^93afW3?x5a^xFyIq!&3R0cjQ>W`1WnO9n_g1^9%x z0%>)1b!%&De+C9;28L*M_HG6SeSQ7M3=H}C`OePH%a<<~78dsR_g~JyP|v`ynSnuC zTKYc&Looxxdj^K^@Nmr)Z~B3zFqQ=Q1v5B2yO9RuSbDlRhE&9{Hna*hI0zisr2c-z zm-|}GHw>61Y-_lVO>;k~Df0Vn7k6dmd&y&=n{95gu5PPmiU?|zH!fx@+wY)Y2Q-Ai M)78&qol`;+09bE59smFU diff --git a/wadsrc_extra/static/sprites/sgrna6a4.png b/wadsrc_extra/static/sprites/sgrna6a4.png deleted file mode 100644 index 7fd5497937613a4790649c06528053ec78e124c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~c!3-piujpS2;-nWjCV^-mX4XDhE(@eR0(?ST zfwZ)=w6(RhzP`RQ5HK*PtE($3D^H(3Jv=;ISXekZI=Y*IVf*&&_wV2L_xJzLz_6Tw zA)0|9J3Bi$Ir%gLLw{RTwAdz1; z=lhk1hbK!J^~sqShZ?yy*c=uMs@q_&T4!sR-~(=XGv+yKjc!i_TEyV#>gTe~DWM4f DLF`k4 diff --git a/wadsrc_extra/static/sprites/sgrna7a3.png b/wadsrc_extra/static/sprites/sgrna7a3.png deleted file mode 100644 index 99755ae051939f77837f795dd78afb57c0501d57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W+0VEjid}}ZSang$%lYlfx5py7`N-dCPDhcun zW?(3reAWWUOZ9Yd4B?PvJ+P3M$xwvh!u2JK7Hw*JBA_m~oz?lyES*MoBL)@G_^_Hr zg`=L^tGqM&6y`szliu-zQz0(P{@TH!x4X8hesi~ES8hA+WU88a+i|i~ONg&1Gh={R iLmyk%Mny;Fn*TjtNgx`CnYE9W%K~Ypk|4ie z28Oc9XDxudY)==*5Dr=0g9` Date: Tue, 24 Oct 2017 11:11:33 +0300 Subject: [PATCH 067/105] Added ability to get texture name from script Use TexMan.GetName(TextureID tex) member function --- src/textures/texturemanager.cpp | 14 ++++++++++++++ wadsrc/static/zscript/base.txt | 1 + 2 files changed, 15 insertions(+) diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index f7d9a539b..f7aa4926d 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1202,6 +1202,20 @@ int FTextureManager::CountLumpTextures (int lumpnum) // //========================================================================== +DEFINE_ACTION_FUNCTION(_TexMan, GetName) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + const FTexture* const tex = TexMan.ByIndex(texid); + ACTION_RETURN_STRING(nullptr == tex ? FString() : tex->Name); +} + +//========================================================================== +// +// +// +//========================================================================== + DEFINE_ACTION_FUNCTION(_TexMan, GetSize) { PARAM_PROLOGUE; diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 898265995..5575f3d0c 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -90,6 +90,7 @@ struct TexMan native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny); native static void ReplaceTextures(String from, String to, int flags); + native static String GetName(TextureID tex); native static int, int GetSize(TextureID tex); native static Vector2 GetScaledSize(TextureID tex); native static Vector2 GetScaledOffset(TextureID tex); From 1e7b692c77c8bdf55b1927a21231d45ba7acd726 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 24 Oct 2017 15:22:16 +0300 Subject: [PATCH 068/105] Disabled annoying GCC compilation warnings in Travis config These false positives could hide some real problem --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ef4d7165b..17dcd24b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ matrix: compiler: gcc env: - GCC_VERSION=5 - - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release" + - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-Wno-maybe-uninitialized" addons: apt: sources: @@ -32,7 +32,7 @@ matrix: compiler: gcc env: - GCC_VERSION=6 - - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=RelWithDebInfo" + - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_FLAGS=-Wno-maybe-uninitialized" addons: apt: sources: @@ -45,6 +45,7 @@ matrix: compiler: gcc env: - GCC_VERSION=7 + - CMAKE_OPTIONS="-DCMAKE_CXX_FLAGS=-Wno-implicit-fallthrough" addons: apt: sources: From 5f7a06c66e477d4e1f1462f3661ae125db8b315a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 24 Oct 2017 15:24:35 +0300 Subject: [PATCH 069/105] Fixed non-portable usage of __solaris__ preprocessor definition GCC: this use of "defined" may not be portable [-Wexpansion-to-defined] Clang: macro expansion producing 'defined' has undefined behavior [-Wexpansion-to-defined] --- src/m_alloc.cpp | 8 ++++---- src/posix/i_system.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/m_alloc.cpp b/src/m_alloc.cpp index bec5581e3..d08913b85 100644 --- a/src/m_alloc.cpp +++ b/src/m_alloc.cpp @@ -54,14 +54,14 @@ #endif #if defined(__APPLE__) #define _msize(p) malloc_size(p) -#elif __solaris__ || defined(__OpenBSD__) +#elif defined(__solaris__) || defined(__OpenBSD__) #define _msize(p) (*((size_t*)(p)-1)) #elif !defined(_WIN32) #define _msize(p) malloc_usable_size(p) // from glibc/FreeBSD #endif #ifndef _DEBUG -#if !__solaris__ && !defined(__OpenBSD__) +#if !defined(__solaris__) && !defined(__OpenBSD__) void *M_Malloc(size_t size) { void *block = malloc(size); @@ -131,7 +131,7 @@ void *M_Realloc(void *memblock, size_t size) #include #endif -#if !__solaris__ && !defined(__OpenBSD__) +#if !defined(__solaris__) && !defined(__OpenBSD__) void *M_Malloc_Dbg(size_t size, const char *file, int lineno) { void *block = _malloc_dbg(size, _NORMAL_BLOCK, file, lineno); @@ -199,7 +199,7 @@ void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) #endif #endif -#if !__solaris__ && !defined(__OpenBSD__) +#if !defined(__solaris__) && !defined(__OpenBSD__) void M_Free (void *block) { if (block != NULL) diff --git a/src/posix/i_system.h b/src/posix/i_system.h index 9b29185a3..0649b7f3c 100644 --- a/src/posix/i_system.h +++ b/src/posix/i_system.h @@ -30,7 +30,9 @@ #include #include -#define __solaris__ (defined(__sun) || defined(__sun__) || defined(__SRV4) || defined(__srv4__)) +#if defined(__sun) || defined(__sun__) || defined(__SRV4) || defined(__srv4__) +#define __solaris__ 1 +#endif #include "doomtype.h" From 6617294c2d7222d8c3011d31ecf28a1c943e2860 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 25 Oct 2017 10:33:18 +0300 Subject: [PATCH 070/105] Added ZScript functions GetBool() and SetBool() to CVar class --- wadsrc/static/zscript/base.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 5575f3d0c..0d0261a75 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -302,9 +302,11 @@ struct CVar native native static CVar FindCVar(Name name); native static CVar GetCVar(Name name, PlayerInfo player = null); + bool GetBool() { return GetInt(); } native int GetInt(); native double GetFloat(); native String GetString(); + void SetBool(bool b) { SetInt(b); } native void SetInt(int v); native void SetFloat(double v); native void SetString(String s); From b8406228e6cad323468da2bd99a3b486e81f30b1 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 25 Oct 2017 11:24:01 +0300 Subject: [PATCH 071/105] Made dynamic array's Find() and Max() functions contant https://forum.zdoom.org/viewtopic.php?t=58088 --- wadsrc/static/zscript/dynarrays.txt | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/wadsrc/static/zscript/dynarrays.txt b/wadsrc/static/zscript/dynarrays.txt index f1ff85afb..e378f79ff 100644 --- a/wadsrc/static/zscript/dynarrays.txt +++ b/wadsrc/static/zscript/dynarrays.txt @@ -7,7 +7,7 @@ struct DynArray_I8 native native void Copy(DynArray_I8 other); native void Move(DynArray_I8 other); - native uint Find(int item); + native uint Find(int item) const; native uint Push (int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -16,7 +16,7 @@ struct DynArray_I8 native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } @@ -26,7 +26,7 @@ struct DynArray_I16 native native void Copy(DynArray_I16 other); native void Move(DynArray_I16 other); - native uint Find(int item); + native uint Find(int item) const; native uint Push (int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -35,7 +35,7 @@ struct DynArray_I16 native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } @@ -45,7 +45,7 @@ struct DynArray_I32 native native void Copy(DynArray_I32 other); native void Move(DynArray_I32 other); - native uint Find(int item); + native uint Find(int item) const; native uint Push (int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -54,7 +54,7 @@ struct DynArray_I32 native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } @@ -64,7 +64,7 @@ struct DynArray_F32 native native void Copy(DynArray_F32 other); native void Move(DynArray_F32 other); - native uint Find(double item); + native uint Find(double item) const; native uint Push (double item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -73,7 +73,7 @@ struct DynArray_F32 native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } @@ -83,7 +83,7 @@ struct DynArray_F64 native native void Copy(DynArray_F64 other); native void Move(DynArray_F64 other); - native uint Find(double item); + native uint Find(double item) const; native uint Push (double item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -92,7 +92,7 @@ struct DynArray_F64 native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } @@ -102,7 +102,7 @@ struct DynArray_Ptr native native void Copy(DynArray_Ptr other); native void Move(DynArray_Ptr other); - native uint Find(voidptr item); + native uint Find(voidptr item) const; native uint Push (voidptr item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -111,7 +111,7 @@ struct DynArray_Ptr native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } @@ -121,7 +121,7 @@ struct DynArray_String native native void Copy(DynArray_String other); native void Move(DynArray_String other); - native uint Find(String item); + native uint Find(String item) const; native uint Push (String item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -130,6 +130,6 @@ struct DynArray_String native native void Grow (uint amount); native void Resize (uint amount); native uint Reserve (uint amount); - native uint Max (); + native uint Max () const; native void Clear (); } From 2fd5d0da549dadc745d273f5b7b890ac6159dd79 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 25 Oct 2017 09:31:37 -0400 Subject: [PATCH 072/105] - improve speed for ARMv7 processors by specifying hardware float calculations, and tuning it specifically for the Cortex-a7 CPU (for Raspberry Pi 2). --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc88800ee..222a39d36 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -342,9 +342,9 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") set (USE_ARMV8 0 CACHE BOOL "Use ARMv8 instructions - Raspberry Pi 3") if (USE_ARMV8) - set( CMAKE_CXX_FLAGS "-mcpu=cortex-a53 -mfpu=neon-fp-armv8 -mtune=cortex-a53 -mhard-float -DNO_SSE ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_CXX_FLAGS "-mcpu=cortex-a53 -mfpu=neon-fp-armv8 -mtune=cortex-a53 -mhard-float -DNO_SSE ${CMAKE_CXX_FLAGS}" ) else () - set( CMAKE_CXX_FLAGS "-mfpu=neon -DNO_SSE ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_CXX_FLAGS "-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mtune=cortex-a7 -mhard-float -DNO_SSE ${CMAKE_CXX_FLAGS}" ) endif () endif () From 79bdfe4ab24cc5be250ab1d72beecf755d089a64 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 26 Oct 2017 17:23:55 +0300 Subject: [PATCH 073/105] Fixed wrong owner for *evillaugh sound https://forum.zdoom.org/viewtopic.php?t=58274 --- wadsrc/static/zscript/raven/artitele.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/raven/artitele.txt b/wadsrc/static/zscript/raven/artitele.txt index 3242db92e..77a233dbe 100644 --- a/wadsrc/static/zscript/raven/artitele.txt +++ b/wadsrc/static/zscript/raven/artitele.txt @@ -49,7 +49,7 @@ class ArtiTeleport : Inventory } if (canlaugh) { // Full volume laugh - A_PlaySound ("*evillaugh", CHAN_VOICE, 1, false, ATTN_NONE); + Owner.A_PlaySound ("*evillaugh", CHAN_VOICE, 1, false, ATTN_NONE); } return true; } From 40a348b1f1b88b1918b771a5baf2e47849079c60 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 27 Oct 2017 18:15:24 +0300 Subject: [PATCH 074/105] Fixed potential crash in resolving of multiple assignment https://forum.zdoom.org/viewtopic.php?t=58055 https://forum.zdoom.org/viewtopic.php?t=58237 --- src/scripting/backend/codegen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 249537aaa..564240203 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2698,6 +2698,8 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) auto varaccess = new FxLocalVariable(singlevar, ScriptPosition); auto assignee = new FxTypeCast(varaccess, Base[i]->ValueType, false); LocalVarContainer->Add(new FxAssign(Base[i], assignee, false)); + // now temporary variable owns the current item + Base[i] = nullptr; } auto x = LocalVarContainer->Resolve(ctx); LocalVarContainer = nullptr; From da94008f394bc8a09d2a75269e032b51b0601f2c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 27 Oct 2017 18:23:18 +0300 Subject: [PATCH 075/105] Fixed indentation in dynarrays.txt --- wadsrc/static/zscript/dynarrays.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wadsrc/static/zscript/dynarrays.txt b/wadsrc/static/zscript/dynarrays.txt index e378f79ff..088e3cc41 100644 --- a/wadsrc/static/zscript/dynarrays.txt +++ b/wadsrc/static/zscript/dynarrays.txt @@ -7,7 +7,7 @@ struct DynArray_I8 native native void Copy(DynArray_I8 other); native void Move(DynArray_I8 other); - native uint Find(int item) const; + native uint Find(int item) const; native uint Push (int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -26,7 +26,7 @@ struct DynArray_I16 native native void Copy(DynArray_I16 other); native void Move(DynArray_I16 other); - native uint Find(int item) const; + native uint Find(int item) const; native uint Push (int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -45,7 +45,7 @@ struct DynArray_I32 native native void Copy(DynArray_I32 other); native void Move(DynArray_I32 other); - native uint Find(int item) const; + native uint Find(int item) const; native uint Push (int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -64,7 +64,7 @@ struct DynArray_F32 native native void Copy(DynArray_F32 other); native void Move(DynArray_F32 other); - native uint Find(double item) const; + native uint Find(double item) const; native uint Push (double item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -83,7 +83,7 @@ struct DynArray_F64 native native void Copy(DynArray_F64 other); native void Move(DynArray_F64 other); - native uint Find(double item) const; + native uint Find(double item) const; native uint Push (double item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -102,7 +102,7 @@ struct DynArray_Ptr native native void Copy(DynArray_Ptr other); native void Move(DynArray_Ptr other); - native uint Find(voidptr item) const; + native uint Find(voidptr item) const; native uint Push (voidptr item); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -121,7 +121,7 @@ struct DynArray_String native native void Copy(DynArray_String other); native void Move(DynArray_String other); - native uint Find(String item) const; + native uint Find(String item) const; native uint Push (String item); native bool Pop (); native void Delete (uint index, int deletecount = 1); From 3b3f2e20cce61f1cc578228b067ac4eb679978bf Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 28 Oct 2017 11:26:21 +0300 Subject: [PATCH 076/105] Added ability to split FString on tokens https://forum.zdoom.org/viewtopic.php?t=58114 --- src/zstring.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ src/zstring.h | 11 +++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/zstring.cpp b/src/zstring.cpp index f4f57c4f3..ea9c249bb 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -1162,6 +1162,49 @@ void FString::ReallocBuffer (size_t newlen) } } +TArray FString::Split(const FString &delimiter, const EmptyTokenType keepEmpty) const +{ + return Split(delimiter.GetChars(), keepEmpty); +} + +TArray FString::Split(const char *const delimiter, const EmptyTokenType keepEmpty) const +{ + TArray tokens; + Split(tokens, delimiter, keepEmpty); + return tokens; +} + +void FString::Split(TArray& tokens, const FString &delimiter, EmptyTokenType keepEmpty) const +{ + Split(tokens, delimiter.GetChars(), keepEmpty); +} + +void FString::Split(TArray& tokens, const char *delimiter, EmptyTokenType keepEmpty) const +{ + assert(nullptr != delimiter); + + const long selfLen = static_cast(Len()); + const long delimLen = static_cast(strlen(delimiter)); + long lastPos = 0; + + while (lastPos <= selfLen) + { + long pos = IndexOf(delimiter, lastPos); + + if (-1 == pos) + { + pos = selfLen; + } + + if (pos != lastPos || TOK_KEEPEMPTY == keepEmpty) + { + tokens.Push(FString(GetChars() + lastPos, pos - lastPos)); + } + + lastPos = pos + delimLen; + } +} + // Under Windows, use the system heap functions for managing string memory. // Under other OSs, use ordinary memory management instead. diff --git a/src/zstring.h b/src/zstring.h index b30bef2dc..c6cd44fc9 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -312,6 +312,17 @@ public: int CompareNoCase(const FString &other, int len) const { return strnicmp(Chars, other.Chars, len); } int CompareNoCase(const char *other, int len) const { return strnicmp(Chars, other, len); } + enum EmptyTokenType + { + TOK_SKIPEMPTY = 0, + TOK_KEEPEMPTY = 1, + }; + + TArray Split(const FString &delimiter, EmptyTokenType keepEmpty = TOK_KEEPEMPTY) const; + TArray Split(const char *delimiter, EmptyTokenType keepEmpty = TOK_KEEPEMPTY) const; + void Split(TArray& tokens, const FString &delimiter, EmptyTokenType keepEmpty = TOK_KEEPEMPTY) const; + void Split(TArray& tokens, const char *delimiter, EmptyTokenType keepEmpty = TOK_KEEPEMPTY) const; + protected: const FStringData *Data() const { return (FStringData *)Chars - 1; } FStringData *Data() { return (FStringData *)Chars - 1; } From c4865d2bb6b2cbe833a7b6d9a0ce5ab7221c15d0 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 28 Oct 2017 11:26:55 +0300 Subject: [PATCH 077/105] Exposed string split functionality to ZScript https://forum.zdoom.org/viewtopic.php?t=58114 --- src/scripting/thingdef_data.cpp | 10 ++++++++++ wadsrc/static/zscript/base.txt | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 08fd1a910..a90cb3566 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -1293,3 +1293,13 @@ DEFINE_ACTION_FUNCTION(FStringStruct, ToDouble) PARAM_SELF_STRUCT_PROLOGUE(FString); ACTION_RETURN_FLOAT(self->ToDouble()); } + +DEFINE_ACTION_FUNCTION(FStringStruct, Split) +{ + PARAM_SELF_STRUCT_PROLOGUE(FString); + PARAM_POINTER(tokens, TArray); + PARAM_STRING(delimiter); + PARAM_INT_DEF(keepEmpty); + self->Split(*tokens, delimiter, static_cast(keepEmpty)); + return 0; +} diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 0d0261a75..877c42b2b 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -659,6 +659,12 @@ enum EPickStart PPS_NOBLOCKINGCHECK = 2, } +enum EmptyTokenType +{ + TOK_SKIPEMPTY = 0, + TOK_KEEPEMPTY = 1, +} + // Although String is a builtin type, this is a convenient way to attach methods to it. struct StringStruct native { @@ -678,6 +684,7 @@ struct StringStruct native native void ToLower(); native int ToInt(int base = 0) const; native double ToDouble() const; + native void Split(out Array tokens, String delimiter, EmptyTokenType keepEmpty = TOK_KEEPEMPTY) const; } class SectorEffect : Thinker native From 527cc7ecf1226d4db24d3136868d440338e70aa7 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 Oct 2017 09:39:12 +0200 Subject: [PATCH 078/105] Changed MSBuild verbosity level to minimal in AppVeyor configuration --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4c54041bc..7dc4902ca 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -33,7 +33,7 @@ build_script: - md build - cd build - cmake -G "%GENERATOR%" -T "%TOOLSET%" .. - - cmake --build . --config "%CONFIGURATION%" + - cmake --build . --config "%CONFIGURATION%" -- /verbosity:minimal after_build: - set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%\ From 91fda180de67168455d7574384e811f10c18d48b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 Oct 2017 10:06:52 +0200 Subject: [PATCH 079/105] Added Wads.FindLump() to ZScript https://forum.zdoom.org/viewtopic.php?t=57814 --- src/w_wad.cpp | 10 ++++++++++ wadsrc/static/zscript/base.txt | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 773cd6673..495a98db3 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1086,6 +1086,16 @@ int FWadCollection::FindLump (const char *name, int *lastlump, bool anyns) return -1; } +DEFINE_ACTION_FUNCTION(_Wads, FindLump) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + PARAM_INT_DEF(startlump); + PARAM_INT_DEF(ns); + const bool isLumpValid = startlump >= 0 && startlump < Wads.GetNumLumps(); + ACTION_RETURN_INT(isLumpValid ? Wads.FindLump(name, &startlump, 0 != ns) : -1); +} + //========================================================================== // // W_FindLumpMulti diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 877c42b2b..97a4d65a2 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -631,7 +631,14 @@ struct Wads ns_firstskin, } + enum FindLumpNamespace + { + GlobalNamespace = 0, + AnyNamespace = 1, + } + native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false); + native static int FindLump(string name, int startlump = 0, FindLumpNamespace ns = GlobalNamespace); } struct TerrainDef native From 2f45218f70dfeaba25bcbd91f076d4e80ee1fcdb Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 Oct 2017 10:07:17 +0200 Subject: [PATCH 080/105] Added Wads.ReadLump() to ZScript https://forum.zdoom.org/viewtopic.php?t=57814 --- src/w_wad.cpp | 8 ++++++++ wadsrc/static/zscript/base.txt | 1 + 2 files changed, 9 insertions(+) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 495a98db3..2c8213828 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1290,6 +1290,14 @@ FMemLump FWadCollection::ReadLump (int lump) return FMemLump(FString(ELumpNum(lump))); } +DEFINE_ACTION_FUNCTION(_Wads, ReadLump) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + const bool isLumpValid = lump >= 0 && lump < Wads.GetNumLumps(); + ACTION_RETURN_STRING(isLumpValid ? Wads.ReadLump(lump).GetString() : FString()); +} + //========================================================================== // // OpenLumpNum diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 97a4d65a2..9c429fb4d 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -639,6 +639,7 @@ struct Wads native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false); native static int FindLump(string name, int startlump = 0, FindLumpNamespace ns = GlobalNamespace); + native static string ReadLump(int lump); } struct TerrainDef native From 415ed57713ffd511dfea0bb268871227617790fd Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 Oct 2017 15:11:49 +0200 Subject: [PATCH 081/105] Added Wads.CheckNumForFullName() to ZScript https://forum.zdoom.org/viewtopic.php?t=57814 --- src/w_wad.cpp | 7 +++++++ wadsrc/static/zscript/base.txt | 1 + 2 files changed, 8 insertions(+) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 2c8213828..412450d0a 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -567,6 +567,13 @@ int FWadCollection::CheckNumForFullName (const char *name, bool trynormal, int n return -1; } +DEFINE_ACTION_FUNCTION(_Wads, CheckNumForFullName) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + ACTION_RETURN_INT(Wads.CheckNumForFullName(name)); +} + int FWadCollection::CheckNumForFullName (const char *name, int wadnum) { uint32_t i; diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 9c429fb4d..a6866f0ff 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -638,6 +638,7 @@ struct Wads } native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false); + native static int CheckNumForFullName(string name); native static int FindLump(string name, int startlump = 0, FindLumpNamespace ns = GlobalNamespace); native static string ReadLump(int lump); } From ea6daf0212e802b328842b69c1ed0a861fd0c256 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 Oct 2017 16:14:04 +0200 Subject: [PATCH 082/105] Added workaround for MSVC 2017 internal compiler error game-music-emu\gme\fir_resampler.cpp(28): fatal error C1001: An internal error has occurred in the compiler. (compiler file 'f:\dd\vctools\compiler\utc\src\p2\main.c', line 256) --- game-music-emu/gme/Fir_Resampler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/game-music-emu/gme/Fir_Resampler.cpp b/game-music-emu/gme/Fir_Resampler.cpp index 7f0deeca3..355b95914 100644 --- a/game-music-emu/gme/Fir_Resampler.cpp +++ b/game-music-emu/gme/Fir_Resampler.cpp @@ -23,6 +23,10 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #undef PI #define PI 3.1415926535897932384626433832795029 +#if _MSC_VER >= 1911 && defined _M_X64 +#pragma float_control(precise, on, push) +#endif // _MSC_VER >= 1911 && _M_X64 + static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale, int count, short* out ) { @@ -52,6 +56,10 @@ static void gen_sinc( double rolloff, int width, double offset, double spacing, } } +#if _MSC_VER >= 1911 && defined _M_X64 +#pragma float_control(pop) +#endif // _MSC_VER >= 1911 && _M_X64 + Fir_Resampler_::Fir_Resampler_( int width, sample_t* impulses_ ) : width_( width ), write_offset( width * stereo - stereo ), From d543408fd4589b8a67e3d8e91b129830ed8c185c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 Oct 2017 16:15:03 +0200 Subject: [PATCH 083/105] Enabled MSVC 2017 64-bit target in AppVeyor configuration --- .appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 7dc4902ca..486eb2d78 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,10 +20,10 @@ environment: CONFIGURATION: Release TOOLSET: v141_xp APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017" -# - GENERATOR: "Visual Studio 15 2017 Win64" -# CONFIGURATION: Release -# TOOLSET: v141_xp -# APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017" + - GENERATOR: "Visual Studio 15 2017 Win64" + CONFIGURATION: Release + TOOLSET: v141_xp + APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017" - GENERATOR: "Visual Studio 14 2015 Win64" CONFIGURATION: Debug TOOLSET: v140 From 037bb1408b0fc8217ad3b11644d4998e1e720ae5 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 30 Oct 2017 19:45:21 +0000 Subject: [PATCH 084/105] - add search dirs for SDL2 for Hiaku OS --- cmake/FindSDL2.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake index 614426ccc..f759f9938 100644 --- a/cmake/FindSDL2.cmake +++ b/cmake/FindSDL2.cmake @@ -83,6 +83,7 @@ FIND_PATH(SDL2_INCLUDE_DIR SDL.h /opt/local # DarwinPorts /opt/csw # Blastwave /opt + /boot/system/develop/headers/SDL2 #Hiaku OS ) #MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}") @@ -96,6 +97,7 @@ FIND_LIBRARY(SDL2_LIBRARY_TEMP /opt/local /opt/csw /opt + /system/lib #Hiaku OS ) #MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}") From 62e91b23bdb246f784e22f76bbfdee3b7fcd832f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 1 Nov 2017 15:24:05 +0200 Subject: [PATCH 085/105] Extended String.LastIndexOf() with endIndex parameter https://forum.zdoom.org/viewtopic.php?t=57326 --- src/scripting/thingdef_data.cpp | 3 ++- wadsrc/static/zscript/base.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index a90cb3566..540b61a36 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -1264,7 +1264,8 @@ DEFINE_ACTION_FUNCTION(FStringStruct, LastIndexOf) { PARAM_SELF_STRUCT_PROLOGUE(FString); PARAM_STRING(substr); - ACTION_RETURN_INT(self->LastIndexOf(substr)); + PARAM_INT_DEF(endIndex); + ACTION_RETURN_INT(self->LastIndexOf(substr, endIndex)); } DEFINE_ACTION_FUNCTION(FStringStruct, ToUpper) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index a6866f0ff..9cba0cb09 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -688,7 +688,7 @@ struct StringStruct native native int CharCodeAt(int pos) const; native String Filter(); native int IndexOf(String substr, int startIndex = 0) const; - native int LastIndexOf(String substr) const; + native int LastIndexOf(String substr, int endIndex = 2147483647) const; native void ToUpper(); native void ToLower(); native int ToInt(int base = 0) const; From de7d8995d5a2e2d69b3a73a21090f391511df198 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 14:45:35 +0200 Subject: [PATCH 086/105] Added string representation of 'static const' token No more 'Unknown(-141)' in 'Expecting ...' error message --- src/sc_man_tokens.h | 1 + src/scripting/zscript/zcc_parser.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index b24cb369d..33be1c6ae 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -147,4 +147,5 @@ xx(TK_Offset, "'offset'") xx(TK_Slow, "'slow'") xx(TK_Bright, "'bright'") xx(TK_Let, "'let'") +xx(TK_StaticConst, "'static const'") #undef xx diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index e843b70de..a0af21c14 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -211,6 +211,7 @@ static void InitTokenMap() TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color); TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound); TOKENDEF2(TK_Let, ZCC_LET, NAME_let); + TOKENDEF2(TK_StaticConst, ZCC_STATICCONST,NAME_Staticconst); TOKENDEF (TK_Identifier, ZCC_IDENTIFIER); TOKENDEF (TK_StringConst, ZCC_STRCONST); From 587f6f0f91277f25f4ebc1f4c929df96fc39e560 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 14:49:08 +0200 Subject: [PATCH 087/105] Added wait for debugger feature to Cocoa backend Use -wait_for_debugger command line switch to display message box on startup It's available in Debug configuration only --- src/posix/cocoa/i_main.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index 4ac42261a..fd3e9a737 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -551,6 +551,16 @@ int main(int argc, char** argv) { s_restartedFromWADPicker = true; } +#if _DEBUG + else if (0 == strcmp(argument, "-wait_for_debugger")) + { + NSAlert* alert = [[NSAlert alloc] init]; + [alert setMessageText:@GAMENAME]; + [alert setInformativeText:@"Waiting for debugger..."]; + [alert addButtonWithTitle:@"Continue"]; + [alert runModal]; + } +#endif // _DEBUG else { s_argvStorage.Push(argument); From 57de598e4824d53a29acb69e706f559bcb3f420a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 15:51:13 +0200 Subject: [PATCH 088/105] Added implicit scope for if/else, while and do/while statements in ZScript Scope is added only for variable or constant definition so it will no longer leak to outer scope https://forum.zdoom.org/viewtopic.php?t=57848 --- src/scripting/zscript/zcc_compile.cpp | 49 +++++++++++++++++++++++++-- src/scripting/zscript/zcc_compile.h | 1 + 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 71f8e6d35..597180605 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -3495,7 +3495,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_IfStmt: { auto iff = static_cast(ast); - return new FxIfStatement(ConvertNode(iff->Condition), ConvertNode(iff->TruePath), ConvertNode(iff->FalsePath), *ast); + FxExpression *const truePath = ConvertImplicitScopeNode(ast, iff->TruePath); + FxExpression *const falsePath = ConvertImplicitScopeNode(ast, iff->FalsePath); + return new FxIfStatement(ConvertNode(iff->Condition), truePath, falsePath, *ast); } case AST_IterationStmt: @@ -3504,7 +3506,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) if (iter->CheckAt == ZCC_IterationStmt::End) { assert(iter->LoopBumper == nullptr); - return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast); + FxExpression *const loop = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), loop, *ast); } else if (iter->LoopBumper != nullptr) { @@ -3520,7 +3523,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } else { - return new FxWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast); + FxExpression *const loop = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxWhileLoop(ConvertNode(iter->LoopCondition), loop, *ast); } } @@ -3584,6 +3588,45 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return nullptr; } +//========================================================================== +// +// Wrapper around ConvertNode() that adds a scope (a compound statement) +// when needed to avoid leaking of variable or contant to an outer scope: +// +// if (true) int i; else bool b[1]; +// while (false) readonly a; +// do static const float f[] = {0}; while (false); +// +// Accessing such variables outside of their statements is now an error +// +//========================================================================== + +FxExpression *ZCCCompiler::ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Statement *nested) +{ + assert(nullptr != node); + + if (nullptr == nested) + { + return nullptr; + } + + FxExpression *nestedExpr = ConvertNode(nested); + assert(nullptr != nestedExpr); + + const EZCCTreeNodeType nestedType = nested->NodeType; + const bool needScope = AST_LocalVarStmt == nestedType || AST_StaticArrayStatement == nestedType; + + if (needScope) + { + FxCompoundStatement *implicitCompound = new FxCompoundStatement(*node); + implicitCompound->Add(nestedExpr); + + nestedExpr = implicitCompound; + } + + return nestedExpr; +} + FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *head) { diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index baa5c89f6..9a4a0af8b 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -145,6 +145,7 @@ private: FxExpression *ConvertAST(PContainerType *cclass, ZCC_TreeNode *ast); FxExpression *ConvertNode(ZCC_TreeNode *node); + FxExpression *ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Statement *nested); FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); DObject *Outer; From 81ea9fb372d0c677be4d8883f83c1164d98713af Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 18:01:13 +0200 Subject: [PATCH 089/105] Added runtime check for negative array indices in VM https://forum.zdoom.org/viewtopic.php?t=57886 --- src/scripting/vm/vmexec.h | 15 +++++++++++++++ src/scripting/vm/vmops.h | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index ec5da180f..37c0093fa 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -899,6 +899,11 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]); return 0; } + else if (reg.d[a] < 0) + { + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", reg.d[a]); + return 0; + } NEXTOP; OP(BOUND_K): @@ -908,6 +913,11 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]); return 0; } + else if (reg.d[a] < 0) + { + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", reg.d[a]); + return 0; + } NEXTOP; OP(BOUND_R): @@ -917,6 +927,11 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]); return 0; } + else if (reg.d[a] < 0) + { + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", reg.d[a]); + return 0; + } NEXTOP; OP(CONCAT): diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 97102f5de..cfdf3fce2 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -122,9 +122,9 @@ xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB // A == 2: (pB == ) then pc++ ; next instruction must JMP to another CATCH // A == 3: (pkB == ) then pc++ ; next instruction must JMP to another CATCH // for A > 0, exception is stored in pC -xx(BOUND, bound, RII16, NOP, 0, 0), // if rA >= BC, throw exception -xx(BOUND_K, bound, LKI, NOP, 0, 0), // if rA >= const[BC], throw exception -xx(BOUND_R, bound, RIRI, NOP, 0, 0), // if rA >= rB, throw exception +xx(BOUND, bound, RII16, NOP, 0, 0), // if rA < 0 or rA >= BC, throw exception +xx(BOUND_K, bound, LKI, NOP, 0, 0), // if rA < 0 or rA >= const[BC], throw exception +xx(BOUND_R, bound, RIRI, NOP, 0, 0), // if rA < 0 or rA >= rB, throw exception // String instructions. xx(CONCAT, concat, RSRSRS, NOP, 0, 0), // sA = sB..sC From dac5777a7095d457ea296b9bd9dc14b525d60665 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 3 Nov 2017 12:44:28 +0200 Subject: [PATCH 090/105] Removed obsolete declarations from codegen.h --- src/scripting/backend/codegen.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 58ac84d85..8ee32423f 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -319,8 +319,6 @@ protected: } public: - FxExpression *CheckIntForName(); - virtual ~FxExpression() {} virtual FxExpression *Resolve(FCompileContext &ctx); @@ -2132,7 +2130,6 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; - bool constructed = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); From 8104ef5189bd2dd42745e47c15d2f984b4213ec3 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 3 Nov 2017 13:33:36 +0200 Subject: [PATCH 091/105] Added warning for uninitialized variables in ZScript https://forum.zdoom.org/viewtopic.php?t=57868 --- src/scripting/backend/codegen.cpp | 36 +++++++++++++++++++++++++++---- src/scripting/backend/codegen.h | 9 ++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 564240203..1de09e741 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2692,6 +2692,7 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) for (unsigned i = 0; i < Base.Size(); i++) { auto singlevar = new FxLocalVariableDeclaration(rets[i], NAME_None, nullptr, 0, ScriptPosition); + singlevar->IsInitialized = true; LocalVarContainer->Add(singlevar); Base[i] = Base[i]->Resolve(ctx); ABORT(Base[i]); @@ -6031,7 +6032,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else { - auto x = new FxStackVariable(local->ValueType, local->StackOffset, ScriptPosition); + auto x = new FxStackVariable(local, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -6520,6 +6521,7 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + IsLocalVariable = ctx.FunctionArgs.Find(Variable) == ctx.FunctionArgs.Size(); return this; } @@ -6553,7 +6555,16 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); ret.RegCount = ValueType->GetRegCount(); - if (AddressRequested) ret.Target = true; + if (AddressRequested) + { + Variable->IsInitialized = true; + ret.Target = true; + } + else if (IsLocalVariable) + { + Variable->WarnIfUninitialized(ScriptPosition); + } + return ret; } } @@ -6895,8 +6906,9 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) // //========================================================================== -FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) - : FxMemberBase(EFX_StackVariable, Create(NAME_None, type, 0, offset), pos) +FxStackVariable::FxStackVariable(FxLocalVariableDeclaration *var, const FScriptPosition &pos) + : FxMemberBase(EFX_StackVariable, Create(NAME_None, var->ValueType, 0, var->StackOffset), pos) + , Variable(var) { } @@ -6947,6 +6959,8 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (AddressRequested) { + Variable->IsInitialized = true; + if (offsetreg >= 0) { ExpEmit obj(build, REGT_POINTER); @@ -6958,6 +6972,10 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) return build->FramePointer; } } + else + { + Variable->WarnIfUninitialized(ScriptPosition); + } ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); if (membervar->BitValue == -1) @@ -11403,6 +11421,16 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // For that all local stack variables need to live for the entire execution of a function. } +void FxLocalVariableDeclaration::WarnIfUninitialized(const FScriptPosition &varPos) const +{ + if (!IsInitialized && nullptr == Init) + { + varPos.Message(MSG_WARNING, + "Usage of uninitialized variable '%s' defined at line %i", + Name.GetChars(), ScriptPosition.ScriptLine); + } +} + FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 8ee32423f..f035039e2 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -1425,6 +1425,7 @@ class FxLocalVariable : public FxExpression public: FxLocalVariableDeclaration *Variable; bool AddressRequested; + bool IsLocalVariable; // false for function parameter and true otherwise int RegOffset; FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); @@ -1442,7 +1443,9 @@ public: class FxStackVariable : public FxMemberBase { public: - FxStackVariable(PType *type, int offset, const FScriptPosition&); + FxLocalVariableDeclaration *Variable; + + FxStackVariable(FxLocalVariableDeclaration*, const FScriptPosition&); ~FxStackVariable(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -2121,6 +2124,7 @@ class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; friend class FxLocalVariable; + friend class FxStackVariable; friend class FxStaticArrayVariable; FName Name; @@ -2130,6 +2134,7 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; + bool IsInitialized = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); @@ -2137,7 +2142,7 @@ public: ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); void SetReg(ExpEmit reginfo); - + void WarnIfUninitialized(const FScriptPosition &varPos) const; }; //========================================================================== From fafc636476f3b8ddd97fd2585d3a6f9f217eee20 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 3 Nov 2017 17:27:32 +0100 Subject: [PATCH 092/105] - allow allocating constructor of TArray to also reserve the allocated data and use this to properly handle the precalc arrays for the texture resizer. --- src/gl/textures/gl_hwtexture.cpp | 4 ++-- src/tarray.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index ac789504e..f6edec687 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -93,8 +93,8 @@ void FHardwareTexture::Resize(int width, int height, unsigned char *src_data, un // down we will need to gather a grid of pixels of the size of the scale // factor in each direction and then do an averaging of the pixels. - TArray vPrecalcs(height); - TArray hPrecalcs(width); + TArray vPrecalcs(height, true); + TArray hPrecalcs(width, true); ResampleBoxPrecalc(vPrecalcs, texheight); ResampleBoxPrecalc(hPrecalcs, texwidth); diff --git a/src/tarray.h b/src/tarray.h index 92a456550..acc080012 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -132,10 +132,10 @@ public: Count = 0; Array = NULL; } - TArray (int max) + TArray (int max, bool reserve = false) { Most = max; - Count = 0; + Count = reserve? max : 0; Array = (T *)M_Malloc (sizeof(T)*max); } TArray (const TArray &other) From a1562c5a767fd372d80e1834872b6e9af8592470 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 10:11:43 +0200 Subject: [PATCH 093/105] Use Xcode 9.1 for Travis builds --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 17dcd24b7..39893dd2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ git: matrix: include: - os: osx - osx_image: xcode9 + osx_image: xcode9.1 env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" From ba298ccd6e7414a4f425c21e8ad5b0d8cf434ab7 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 10:12:02 +0200 Subject: [PATCH 094/105] Added GCC 4.9 to Travis configuration --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 39893dd2b..c7ff08eaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,19 @@ matrix: env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" + - os: linux + compiler: gcc + env: + - GCC_VERSION=4.9 + - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-Wno-maybe-uninitialized" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.9 + - libsdl2-dev + - os: linux compiler: gcc env: From bd08568b90f9227055761f893565d4c886710b7c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Nov 2017 13:28:56 +0100 Subject: [PATCH 095/105] - Fix wrong math for model/light distance check --- src/gl/scene/gl_spritelight.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 8853f0c19..e348956bf 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -209,12 +209,12 @@ void gl_SetDynModelLight(AActor *self, bool hudmodel) { int group = subsector->sector->PortalGroup; DVector3 pos = light->PosRelative(group); - float radius = light->GetRadius(); + float radius = light->GetRadius() + self->renderradius; double dx = pos.X - x; double dy = pos.Y - y; double dz = pos.Z - z; double distSquared = dx * dx + dy * dy + dz * dz; - if (distSquared < radiusSquared + radius * radius) // Light and actor touches + if (distSquared < radius * radius) // Light and actor touches { if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector { From 274951839aa0d7fdb74b119fa83ff28215a5ea3b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 13:15:42 +0200 Subject: [PATCH 096/105] Removed unused parameter from several functions in FStateDefinitions class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/p_states.cpp:724:54: warning: parameter ‘actor’ set but not used [-Wunused-but-set-parameter] https://forum.zdoom.org/viewtopic.php?t=58364 --- src/info.cpp | 6 ++---- src/p_states.cpp | 18 ++++++++---------- src/scripting/thingdef.h | 6 +++--- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 94b263105..28feeb826 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -322,18 +322,16 @@ bool PClassActor::SetReplacement(FName replaceName) void AActor::Finalize(FStateDefinitions &statedef) { - AActor *defaults = this; - try { - statedef.FinishStates(GetClass(), defaults); + statedef.FinishStates(GetClass()); } catch (CRecoverableError &) { statedef.MakeStateDefines(nullptr); throw; } - statedef.InstallStates(GetClass(), defaults); + statedef.InstallStates(GetClass(), this); statedef.MakeStateDefines(nullptr); } diff --git a/src/p_states.cpp b/src/p_states.cpp index 8ec19e653..a330bec76 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -721,7 +721,7 @@ void FStateDefinitions::RetargetStates (intptr_t count, const char *target) // //========================================================================== -FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, char *name) +FState *FStateDefinitions::ResolveGotoLabel (PClassActor *mytype, char *name) { PClassActor *type = mytype; FState *state; @@ -741,7 +741,6 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, if (stricmp (classname, "Super") == 0) { type = ValidateActor(type->ParentClass); - actor = GetDefaultByType(type); } else { @@ -763,7 +762,6 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, if (type != stype) { type = static_cast(stype); - actor = GetDefaultByType (type); } } } @@ -836,16 +834,16 @@ void FStateDefinitions::FixStatePointers (PClassActor *actor, TArray & list) +void FStateDefinitions::ResolveGotoLabels (PClassActor *actor, TArray & list) { for (unsigned i = 0; i < list.Size(); i++) { if (list[i].State != NULL && list[i].DefineFlags == SDF_LABEL) { // It's not a valid state, so it must be a label string. Resolve it. - list[i].State = ResolveGotoLabel (defaults, actor, (char *)list[i].State); + list[i].State = ResolveGotoLabel (actor, (char *)list[i].State); list[i].DefineFlags = SDF_STATE; } - if (list[i].Children.Size() > 0) ResolveGotoLabels(actor, defaults, list[i].Children); + if (list[i].Children.Size() > 0) ResolveGotoLabels(actor, list[i].Children); } } @@ -1004,7 +1002,7 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS // //========================================================================== -int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) +int FStateDefinitions::FinishStates(PClassActor *actor) { int count = StateArray.Size(); @@ -1023,7 +1021,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) FixStatePointers(actor, StateLabels); // Fix state pointers that are gotos - ResolveGotoLabels(actor, defaults, StateLabels); + ResolveGotoLabels(actor, StateLabels); for (i = 0; i < count; i++) { @@ -1047,7 +1045,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) break; case SDF_LABEL: - realstates[i].NextState = ResolveGotoLabel(defaults, actor, (char *)realstates[i].NextState); + realstates[i].NextState = ResolveGotoLabel(actor, (char *)realstates[i].NextState); break; } } @@ -1055,7 +1053,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) else { // Fix state pointers that are gotos - ResolveGotoLabels(actor, defaults, StateLabels); + ResolveGotoLabels(actor, StateLabels); } return count; } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 29e648797..0d59dce5c 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -113,9 +113,9 @@ class FStateDefinitions FStateDefine *FindStateAddress(const char *name); FState *FindState(const char *name); - FState *ResolveGotoLabel(AActor *actor, PClassActor *mytype, char *name); + FState *ResolveGotoLabel(PClassActor *mytype, char *name); static void FixStatePointers(PClassActor *actor, TArray & list); - void ResolveGotoLabels(PClassActor *actor, AActor *defaults, TArray & list); + void ResolveGotoLabels(PClassActor *actor, TArray & list); public: FStateDefinitions() @@ -129,7 +129,7 @@ public: void AddStateLabel(const char *statename); int GetStateLabelIndex (FName statename); void InstallStates(PClassActor *info, AActor *defaults); - int FinishStates(PClassActor *actor, AActor *defaults); + int FinishStates(PClassActor *actor); void MakeStateDefines(const PClassActor *cls); void AddStateDefines(const FStateLabels *list); From 61ead4f4701a79b5f4d4f53fa73d534ebe15b244 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 13:18:22 +0200 Subject: [PATCH 097/105] Better STL compatibility for array iterator Extended iterator with types and functions required to use array objects in STL algorithms --- src/tarray.h | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/tarray.h b/src/tarray.h index acc080012..63eeb4eed 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -39,6 +39,7 @@ #include #include #include +#include #if !defined(_WIN32) #include // for intptr_t @@ -48,13 +49,37 @@ #include "m_alloc.h" -template class TIterator +template class TIterator : public std::iterator { public: + typedef typename TIterator::value_type value_type; + typedef typename TIterator::difference_type difference_type; + typedef typename TIterator::pointer pointer; + typedef typename TIterator::reference reference; + typedef typename TIterator::iterator_category iterator_category; + TIterator(T* ptr = nullptr) { m_ptr = ptr; } - bool operator==(const TIterator& other) const { return (m_ptr == other.m_ptr); } - bool operator!=(const TIterator& other) const { return (m_ptr != other.m_ptr); } - TIterator &operator++() { ++m_ptr; return (*this); } + + // Comparison operators + bool operator==(const TIterator &other) const { return m_ptr == other.m_ptr; } + bool operator!=(const TIterator &other) const { return m_ptr != other.m_ptr; } + bool operator< (const TIterator &other) const { return m_ptr < other.m_ptr; } + bool operator<=(const TIterator &other) const { return m_ptr <= other.m_ptr; } + bool operator> (const TIterator &other) const { return m_ptr > other.m_ptr; } + bool operator>=(const TIterator &other) const { return m_ptr >= other.m_ptr; } + + // Arithmetic operators + TIterator &operator++() { ++m_ptr; return *this; } + TIterator operator++(int) { pointer tmp = m_ptr; ++*this; return TIterator(tmp); } + TIterator &operator--() { --m_ptr; return *this; } + TIterator operator--(int) { pointer tmp = m_ptr; --*this; return TIterator(tmp); } + TIterator &operator+=(difference_type offset) { m_ptr += offset; return *this; } + TIterator operator+(difference_type offset) const { return TIterator(m_ptr + offset); } + friend TIterator operator+(difference_type offset, const TIterator &other) { return TIterator(offset + other.m_ptr); } + TIterator &operator-=(difference_type offset) { m_ptr -= offset; return *this; } + TIterator operator-(difference_type offset) const { return TIterator(m_ptr - offset); } + difference_type operator-(const TIterator &other) const { return m_ptr - other.m_ptr; } + T &operator*() { return *m_ptr; } const T &operator*() const { return *m_ptr; } T* operator->() { return m_ptr; } From 23e5d817469c2b3e84739b3b5a9ced44cca29d6f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Nov 2017 15:32:42 +0100 Subject: [PATCH 098/105] - Implement VSMatrix::inverseMatrix --- src/gl/data/gl_matrix.cpp | 210 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/src/gl/data/gl_matrix.cpp b/src/gl/data/gl_matrix.cpp index 115882857..9063fc59b 100644 --- a/src/gl/data/gl_matrix.cpp +++ b/src/gl/data/gl_matrix.cpp @@ -484,3 +484,213 @@ VSMatrix::multMatrix(FLOATTYPE *resMat, const FLOATTYPE *aMatrix) } memcpy(resMat, res, 16 * sizeof(FLOATTYPE)); } + +static double mat3Determinant(const FLOATTYPE *mMat3x3) +{ + return mMat3x3[0] * (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) + + mMat3x3[1] * (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) + + mMat3x3[2] * (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]); +} + +static double mat4Determinant(const FLOATTYPE *matrix) +{ + FLOATTYPE mMat3x3_a[9] = + { + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_b[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_c[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_d[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE a, b, c, d; + FLOATTYPE value; + + a = mat3Determinant(mMat3x3_a); + b = mat3Determinant(mMat3x3_b); + c = mat3Determinant(mMat3x3_c); + d = mat3Determinant(mMat3x3_d); + + value = matrix[0 * 4 + 0] * a; + value -= matrix[0 * 4 + 1] * b; + value += matrix[0 * 4 + 2] * c; + value -= matrix[0 * 4 + 3] * d; + + return value; +} + +static void mat4Adjoint(const FLOATTYPE *matrix, FLOATTYPE *result) +{ + FLOATTYPE mMat3x3_a[9] = + { + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_b[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_c[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_d[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE mMat3x3_e[9] = + { + matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_f[9] = + { + matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_g[9] = + { + matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_h[9] = + { + matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE mMat3x3_i[9] = + { + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_j[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_k[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_l[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE mMat3x3_m[9] = + { + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3] + }; + + FLOATTYPE mMat3x3_n[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3] + }; + + FLOATTYPE mMat3x3_o[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3] + }; + + FLOATTYPE mMat3x3_p[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2] + }; + + result[0 * 4 + 0] = mat3Determinant(mMat3x3_a); + result[1 * 4 + 0] = -mat3Determinant(mMat3x3_b); + result[2 * 4 + 0] = mat3Determinant(mMat3x3_c); + result[3 * 4 + 0] = -mat3Determinant(mMat3x3_d); + result[0 * 4 + 1] = -mat3Determinant(mMat3x3_e); + result[1 * 4 + 1] = mat3Determinant(mMat3x3_f); + result[2 * 4 + 1] = -mat3Determinant(mMat3x3_g); + result[3 * 4 + 1] = mat3Determinant(mMat3x3_h); + result[0 * 4 + 2] = mat3Determinant(mMat3x3_i); + result[1 * 4 + 2] = -mat3Determinant(mMat3x3_j); + result[2 * 4 + 2] = mat3Determinant(mMat3x3_k); + result[3 * 4 + 2] = -mat3Determinant(mMat3x3_l); + result[0 * 4 + 3] = -mat3Determinant(mMat3x3_m); + result[1 * 4 + 3] = mat3Determinant(mMat3x3_n); + result[2 * 4 + 3] = -mat3Determinant(mMat3x3_o); + result[3 * 4 + 3] = mat3Determinant(mMat3x3_p); +} + +bool VSMatrix::inverseMatrix(VSMatrix &result) +{ + // Calculate mat4 determinant + FLOATTYPE det = mat4Determinant(mMatrix); + + // Inverse unknown when determinant is close to zero + if (fabs(det) < 1e-15) + { + for (int i = 0; i < 16; i++) + result.mMatrix[i] = FLOATTYPE(0.0); + return false; + } + else + { + mat4Adjoint(mMatrix, result.mMatrix); + + FLOATTYPE invDet = FLOATTYPE(1.0) / det; + for (int i = 0; i < 16; i++) + { + result.mMatrix[i] = result.mMatrix[i] * invDet; + } + } + return true; +} From d4ebe51e837303007cf9dac4423c9d637412ece4 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Nov 2017 15:35:03 +0100 Subject: [PATCH 099/105] - Place the HUD model correctly in the world so that shader light calculations work --- src/gl/dynlights/gl_dynlight.h | 2 +- src/gl/dynlights/gl_dynlight1.cpp | 29 ++--------------------------- src/gl/models/gl_models.cpp | 30 +++++++++++++++--------------- src/gl/scene/gl_sprite.cpp | 2 +- src/gl/scene/gl_spritelight.cpp | 4 ++-- src/gl/scene/gl_wall.h | 2 +- src/gl/scene/gl_weapon.cpp | 2 +- 7 files changed, 23 insertions(+), 48 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index a85814b6b..1ecdca4ce 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -59,7 +59,7 @@ struct FDynLightData bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data); -void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata, bool hudmodel); +void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata); void gl_UploadLights(FDynLightData &data); diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index 92a503c8d..e42f89ac4 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -77,7 +77,7 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD return false; } - gl_AddLightToList(group, light, ldata, false); + gl_AddLightToList(group, light, ldata); return true; } @@ -86,38 +86,13 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD // Add one dynamic light to the light data list // //========================================================================== -void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata, bool hudmodel) +void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata) { int i = 0; DVector3 pos = light->PosRelative(group); float radius = light->GetRadius(); - if (hudmodel) - { - // HUD model is already translated and rotated. We must rotate the lights into that view space. - - DVector3 rotation; - DVector3 localpos = pos - r_viewpoint.Pos; - - rotation.X = localpos.X * r_viewpoint.Angles.Yaw.Sin() - localpos.Y * r_viewpoint.Angles.Yaw.Cos(); - rotation.Y = localpos.X * r_viewpoint.Angles.Yaw.Cos() + localpos.Y * r_viewpoint.Angles.Yaw.Sin(); - rotation.Z = localpos.Z; - localpos = rotation; - - rotation.X = localpos.X; - rotation.Y = localpos.Y * r_viewpoint.Angles.Pitch.Sin() - localpos.Z * r_viewpoint.Angles.Pitch.Cos(); - rotation.Z = localpos.Y * r_viewpoint.Angles.Pitch.Cos() + localpos.Z * r_viewpoint.Angles.Pitch.Sin(); - localpos = rotation; - - rotation.Y = localpos.Y; - rotation.Z = localpos.Z * r_viewpoint.Angles.Roll.Sin() - localpos.X * r_viewpoint.Angles.Roll.Cos(); - rotation.X = localpos.Z * r_viewpoint.Angles.Roll.Cos() + localpos.X * r_viewpoint.Angles.Roll.Sin(); - localpos = rotation; - - pos = localpos; - } - float cs; if (light->IsAdditive()) { diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 45b955b56..fcad2a95b 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -1095,33 +1095,33 @@ void gl_RenderHUDModel(DPSprite *psp, float ofsX, float ofsY) glFrontFace(GL_CCW); } - // [BB] The model has to be drawn independently from the position of the player, - // so we have to reset the view matrix. - gl_RenderState.mViewMatrix.loadIdentity(); - - // Need to reset the normal matrix too - gl_RenderState.mNormalViewMatrix.loadIdentity(); + // The model position and orientation has to be drawn independently from the position of the player, + // but we need to position it correctly in the world for light to work properly. + VSMatrix objectToWorldMatrix; + gl_RenderState.mViewMatrix.inverseMatrix(objectToWorldMatrix); // Scaling model (y scale for a sprite means height, i.e. z in the world!). - gl_RenderState.mViewMatrix.scale(smf->xscale, smf->zscale, smf->yscale); + objectToWorldMatrix.scale(smf->xscale, smf->zscale, smf->yscale); // Aplying model offsets (model offsets do not depend on model scalings). - gl_RenderState.mViewMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale); + objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale); // [BB] Weapon bob, very similar to the normal Doom weapon bob. - gl_RenderState.mViewMatrix.rotate(ofsX/4, 0, 1, 0); - gl_RenderState.mViewMatrix.rotate((ofsY-WEAPONTOP)/-4., 1, 0, 0); + objectToWorldMatrix.rotate(ofsX/4, 0, 1, 0); + objectToWorldMatrix.rotate((ofsY-WEAPONTOP)/-4., 1, 0, 0); // [BB] For some reason the jDoom models need to be rotated. - gl_RenderState.mViewMatrix.rotate(90.f, 0, 1, 0); + objectToWorldMatrix.rotate(90.f, 0, 1, 0); // Applying angleoffset, pitchoffset, rolloffset. - gl_RenderState.mViewMatrix.rotate(-smf->angleoffset, 0, 1, 0); - gl_RenderState.mViewMatrix.rotate(smf->pitchoffset, 0, 0, 1); - gl_RenderState.mViewMatrix.rotate(-smf->rolloffset, 1, 0, 0); - gl_RenderState.ApplyMatrices(); + objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0); + objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1); + objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0); + gl_RenderState.mModelMatrix = objectToWorldMatrix; + gl_RenderState.EnableModelMatrix(true); gl_RenderFrameModels( smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), nullptr, 0 ); + gl_RenderState.EnableModelMatrix(false); glDepthFunc(GL_LESS); if (!( playermo->RenderStyle == LegacyRenderStyles[STYLE_Normal] )) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 5ca2cd65d..154720022 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -335,7 +335,7 @@ void GLSprite::Draw(int pass) if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) { if (modelframe && !particle) - gl_SetDynModelLight(gl_light_sprites ? actor : NULL, false); + gl_SetDynModelLight(gl_light_sprites ? actor : NULL); else gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); } diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index e348956bf..2d2e65b76 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -177,7 +177,7 @@ void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callba BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback); } -void gl_SetDynModelLight(AActor *self, bool hudmodel) +void gl_SetDynModelLight(AActor *self) { // Legacy and deferred render paths gets the old flat model light if (gl.lightmethod != LM_DIRECT) @@ -218,7 +218,7 @@ void gl_SetDynModelLight(AActor *self, bool hudmodel) { if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector { - gl_AddLightToList(group, light, modellightdata, hudmodel); + gl_AddLightToList(group, light, modellightdata); addedLights.push_back(light); } } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 47cf5654c..aa0bbaed4 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -422,6 +422,6 @@ inline float Dist2(float x1,float y1,float x2,float y2) void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); -void gl_SetDynModelLight(AActor *self, bool hudmodel); +void gl_SetDynModelLight(AActor *self); #endif diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 551f34cbd..3d4224520 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -422,7 +422,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; if (smf) - gl_SetDynModelLight(playermo, true); + gl_SetDynModelLight(playermo); else gl_SetDynSpriteLight(playermo, NULL); } From 4beefb70075df5cfa3a923ef7c19fb9d6926b6de Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 6 Nov 2017 15:37:26 +0200 Subject: [PATCH 100/105] Removed warning for uninitialized variables in ZScript This reverts commit 8104ef5189bd2dd42745e47c15d2f984b4213ec3 --- src/scripting/backend/codegen.cpp | 36 ++++--------------------------- src/scripting/backend/codegen.h | 9 ++------ 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 1de09e741..564240203 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2692,7 +2692,6 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) for (unsigned i = 0; i < Base.Size(); i++) { auto singlevar = new FxLocalVariableDeclaration(rets[i], NAME_None, nullptr, 0, ScriptPosition); - singlevar->IsInitialized = true; LocalVarContainer->Add(singlevar); Base[i] = Base[i]->Resolve(ctx); ABORT(Base[i]); @@ -6032,7 +6031,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else { - auto x = new FxStackVariable(local, ScriptPosition); + auto x = new FxStackVariable(local->ValueType, local->StackOffset, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -6521,7 +6520,6 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); - IsLocalVariable = ctx.FunctionArgs.Find(Variable) == ctx.FunctionArgs.Size(); return this; } @@ -6555,16 +6553,7 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); ret.RegCount = ValueType->GetRegCount(); - if (AddressRequested) - { - Variable->IsInitialized = true; - ret.Target = true; - } - else if (IsLocalVariable) - { - Variable->WarnIfUninitialized(ScriptPosition); - } - + if (AddressRequested) ret.Target = true; return ret; } } @@ -6906,9 +6895,8 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) // //========================================================================== -FxStackVariable::FxStackVariable(FxLocalVariableDeclaration *var, const FScriptPosition &pos) - : FxMemberBase(EFX_StackVariable, Create(NAME_None, var->ValueType, 0, var->StackOffset), pos) - , Variable(var) +FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) + : FxMemberBase(EFX_StackVariable, Create(NAME_None, type, 0, offset), pos) { } @@ -6959,8 +6947,6 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (AddressRequested) { - Variable->IsInitialized = true; - if (offsetreg >= 0) { ExpEmit obj(build, REGT_POINTER); @@ -6972,10 +6958,6 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) return build->FramePointer; } } - else - { - Variable->WarnIfUninitialized(ScriptPosition); - } ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); if (membervar->BitValue == -1) @@ -11421,16 +11403,6 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // For that all local stack variables need to live for the entire execution of a function. } -void FxLocalVariableDeclaration::WarnIfUninitialized(const FScriptPosition &varPos) const -{ - if (!IsInitialized && nullptr == Init) - { - varPos.Message(MSG_WARNING, - "Usage of uninitialized variable '%s' defined at line %i", - Name.GetChars(), ScriptPosition.ScriptLine); - } -} - FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index f035039e2..8ee32423f 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -1425,7 +1425,6 @@ class FxLocalVariable : public FxExpression public: FxLocalVariableDeclaration *Variable; bool AddressRequested; - bool IsLocalVariable; // false for function parameter and true otherwise int RegOffset; FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); @@ -1443,9 +1442,7 @@ public: class FxStackVariable : public FxMemberBase { public: - FxLocalVariableDeclaration *Variable; - - FxStackVariable(FxLocalVariableDeclaration*, const FScriptPosition&); + FxStackVariable(PType *type, int offset, const FScriptPosition&); ~FxStackVariable(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -2124,7 +2121,6 @@ class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; friend class FxLocalVariable; - friend class FxStackVariable; friend class FxStaticArrayVariable; FName Name; @@ -2134,7 +2130,6 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; - bool IsInitialized = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); @@ -2142,7 +2137,7 @@ public: ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); void SetReg(ExpEmit reginfo); - void WarnIfUninitialized(const FScriptPosition &varPos) const; + }; //========================================================================== From d422392b94154a46bb36892f0480705ad9027151 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Fri, 3 Nov 2017 13:57:44 -0500 Subject: [PATCH 101/105] Extended LineAttack() with offsets and new flags Added forward and side offsets for LineAttack() function Added absolute offset and absolute position flags for LineAttack() function --- src/p_local.h | 16 ++++++----- src/p_map.cpp | 41 +++++++++++++++++++++++++---- wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/constants.txt | 13 +++++---- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 21c5db78b..c3fd29520 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -324,15 +324,17 @@ enum // P_AimLineAttack flags enum // P_LineAttack flags { LAF_ISMELEEATTACK = 1, - LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4, - LAF_NOINTERACT = 8, - LAF_TARGETISSOURCE = 16, - LAF_OVERRIDEZ = 32, + LAF_NORANDOMPUFFZ = 1 << 1, + LAF_NOIMPACTDECAL = 1 << 2, + LAF_NOINTERACT = 1 << 3, + LAF_TARGETISSOURCE= 1 << 4, + LAF_OVERRIDEZ = 1 << 5, + LAF_ABSOFFSET = 1 << 6, + LAF_ABSPOSITION = 1 << 7, }; -AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0); -AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0); +AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); +AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); void P_TraceBleed(int damage, const DVector3 &pos, AActor *target, DAngle angle, DAngle pitch); void P_TraceBleed(int damage, AActor *target, DAngle angle, DAngle pitch); diff --git a/src/p_map.cpp b/src/p_map.cpp index 569df7f2c..d71b22d85 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4395,7 +4395,8 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) //========================================================================== AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, - DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, double sz) + DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, + double sz, double offsetforward, double offsetside) { bool nointeract = !!(flags & LAF_NOINTERACT); DVector3 direction; @@ -4496,7 +4497,34 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (nointeract || (puffDefaults && puffDefaults->flags6 & MF6_NOTRIGGER)) tflags = TRACE_NoSky; else tflags = TRACE_NoSky | TRACE_Impact; - if (!Trace(t1->PosAtZ(shootz), t1->Sector, direction, distance, MF_SHOOTABLE, + // [MC] Check the flags and set the position according to what is desired. + // LAF_ABSPOSITION: Treat the offset parameters as direct coordinates. + // LAF_ABSOFFSET: Ignore the angle. + + DVector3 tempos; + + if (flags & LAF_ABSPOSITION) + { + tempos = DVector3(offsetforward, offsetside, sz); + } + else if (flags & LAF_ABSOFFSET) + { + tempos = t1->Vec2OffsetZ(offsetforward, offsetside, shootz); + } + else if (0.0 == offsetforward && 0.0 == offsetside) + { + // Default case so exact comparison is enough + tempos = t1->PosAtZ(shootz); + } + else + { + const double s = angle.Sin(); + const double c = angle.Cos(); + tempos = t1->Vec2OffsetZ(offsetforward * c + offsetside * s, offsetforward * s - offsetside * c, shootz); + } + + // Perform the trace. + if (!Trace(tempos, t1->Sector, direction, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, tflags, CheckForActor, &TData)) { // hit nothing if (!nointeract && puffDefaults && puffDefaults->ActiveSound) @@ -4702,7 +4730,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, - DAngle pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage, double sz) + DAngle pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage, + double sz, double offsetforward, double offsetside) { PClassActor *type = PClass::FindActor(pufftype); if (type == NULL) @@ -4716,7 +4745,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } else { - return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage, sz); + return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage, sz, offsetforward, offsetside); } } @@ -4732,10 +4761,12 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack) PARAM_INT_DEF(flags); PARAM_POINTER_DEF(victim, FTranslatedLineTarget); PARAM_FLOAT_DEF(offsetz); + PARAM_FLOAT_DEF(offsetforward); + PARAM_FLOAT_DEF(offsetside); int acdmg; if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from. - auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg, offsetz); + auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg, offsetz, offsetforward, offsetside); if (numret > 0) ret[0].SetObject(puff); if (numret > 1) ret[1].SetInt(acdmg), numret = 2; return numret; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 682c70af6..3d272b05d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -598,7 +598,7 @@ class Actor : Thinker native native virtual int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type); native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null); - native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0.); + native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0., double offsetforward = 0., double offsetside = 0.); native bool CheckSight(Actor target, int flags = 0); native bool IsVisible(Actor other, bool allaround, LookExParams params = null); native bool HitFriend(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 8fac0a22a..a8aea4123 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -878,11 +878,14 @@ enum EAimFlags enum ELineAttackFlags { - LAF_ISMELEEATTACK = 1, - LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4, - LAF_NOINTERACT = 8, - LAF_OVERRIDEZ = 32, + LAF_ISMELEEATTACK = 1, + LAF_NORANDOMPUFFZ = 1 << 1, + LAF_NOIMPACTDECAL = 1 << 2, + LAF_NOINTERACT = 1 << 3, + LAF_TARGETISSOURCE = 1 << 4, + LAF_OVERRIDEZ = 1 << 5, + LAF_ABSOFFSET = 1 << 6, + LAF_ABSPOSITION = 1 << 7, } const DEFMELEERANGE = 64; From f353f8b5aa5b486af048b7b969e6fcb0803f88bb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 7 Nov 2017 09:55:57 +0200 Subject: [PATCH 102/105] Improved OpenGL profile selection in SDL backend https://forum.zdoom.org/viewtopic.php?t=56852 --- src/posix/sdl/sdlglvideo.cpp | 93 +++++++++++++++++++++++------------- src/posix/sdl/sdlglvideo.h | 3 +- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index f09767f58..5b48c1c4c 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -38,6 +38,7 @@ #include "templates.h" #include "i_system.h" #include "i_video.h" +#include "m_argv.h" #include "v_video.h" #include "v_pfx.h" #include "stats.h" @@ -343,7 +344,7 @@ bool SDLGLVideo::SetResolution (int width, int height, int bits) // //========================================================================== -bool SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample) +void SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver) { SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); @@ -365,24 +366,18 @@ bool SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } - - return true; -} - -//========================================================================== -// -// -// -//========================================================================== - -bool SDLGLVideo::InitHardware (bool allowsoftware, int multisample) -{ - if (!SetupPixelFormat(allowsoftware, multisample)) + else if (glver[0] > 2) { - Printf ("R_OPENGL: Reverting to software mode...\n"); - return false; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glver[0]); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glver[1]); + } + else + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } - return true; } @@ -391,32 +386,66 @@ bool SDLGLVideo::InitHardware (bool allowsoftware, int multisample) SDLGLFB::SDLGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra) : SDLBaseFB (width, height, bgra) { + // NOTE: Core profiles were added with GL 3.2, so there's no sense trying + // to set core 3.1 or 3.0. We could try a forward-compatible context + // instead, but that would be too restrictive (w.r.t. shaders). + static const int glvers[][2] = { + { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, + { 3, 3 }, { 3, 2 }, { 2, 0 }, + { 0, 0 }, + }; + int glveridx = 0; int i; - - m_Lock=0; + m_Lock=0; UpdatePending = false; - - if (!static_cast(Video)->InitHardware(false, 0)) + + const char *version = Args->CheckValue("-glversion"); + if (version != NULL) { - vid_renderer = 0; - return; + double gl_version = strtod(version, NULL) + 0.01; + int vermaj = (int)gl_version; + int vermin = (int)(gl_version*10.0) % 10; + + while (glvers[glveridx][0] > vermaj || (glvers[glveridx][0] == vermaj && + glvers[glveridx][1] > vermin)) + { + glveridx++; + if (glvers[glveridx][0] == 0) + { + glveridx = 0; + break; + } + } } FString caption; caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - Screen = SDL_CreateWindow (caption, - SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), - width, height, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)|SDL_WINDOW_OPENGL); - if (Screen == NULL) - return; + for ( ; glvers[glveridx][0] > 0; ++glveridx) + { + static_cast(Video)->SetupPixelFormat(false, 0, glvers[glveridx]); - GLContext = SDL_GL_CreateContext(Screen); - if (GLContext == NULL) - return; + Screen = SDL_CreateWindow (caption, + SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), + SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), + width, height, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)|SDL_WINDOW_OPENGL + ); + if (Screen != NULL) + { + GLContext = SDL_GL_CreateContext(Screen); + if (GLContext != NULL) + { + m_supportsGamma = -1 != SDL_GetWindowGammaRamp(Screen, + m_origGamma[0], m_origGamma[1], m_origGamma[2] + ); + return; + } - m_supportsGamma = -1 != SDL_GetWindowGammaRamp(Screen, m_origGamma[0], m_origGamma[1], m_origGamma[2]); + SDL_DestroyWindow(Screen); + Screen = NULL; + } + } } SDLGLFB::~SDLGLFB () diff --git a/src/posix/sdl/sdlglvideo.h b/src/posix/sdl/sdlglvideo.h index 3d6de5c73..2dce3aeed 100644 --- a/src/posix/sdl/sdlglvideo.h +++ b/src/posix/sdl/sdlglvideo.h @@ -27,8 +27,7 @@ class SDLGLVideo : public IVideo bool NextMode (int *width, int *height, bool *letterbox); bool SetResolution (int width, int height, int bits); - bool SetupPixelFormat(bool allowsoftware, int multisample); - bool InitHardware (bool allowsoftware, int multisample); + void SetupPixelFormat(bool allowsoftware, int multisample, const int *glver); private: int IteratorMode; From e60c6d35c3b6a33ccbff6844f1be29ce880fa318 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 4 Nov 2017 12:52:33 +0200 Subject: [PATCH 103/105] Added tmpfileplus 2.0.0 https://www.di-mgt.com.au/c_function_to_create_temp_file.html https://www.di-mgt.com.au/tmpfileplus-2.0.0.zip --- docs/licenses/mpl.txt | 373 ++++++++++++++++++++++++++++++++++++++++++ src/tmpfileplus.c | 337 ++++++++++++++++++++++++++++++++++++++ src/tmpfileplus.h | 53 ++++++ 3 files changed, 763 insertions(+) create mode 100644 docs/licenses/mpl.txt create mode 100644 src/tmpfileplus.c create mode 100644 src/tmpfileplus.h diff --git a/docs/licenses/mpl.txt b/docs/licenses/mpl.txt new file mode 100644 index 000000000..14e2f777f --- /dev/null +++ b/docs/licenses/mpl.txt @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/src/tmpfileplus.c b/src/tmpfileplus.c new file mode 100644 index 000000000..9af0260b3 --- /dev/null +++ b/src/tmpfileplus.c @@ -0,0 +1,337 @@ +/* $Id: tmpfileplus.c $ */ +/* + * $Date: 2016-06-01 03:31Z $ + * $Revision: 2.0.0 $ + * $Author: dai $ + */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd + * . + */ + + +/* +* NAME +* tmpfileplus - create a unique temporary file +* +* SYNOPSIS +* FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep) +* +* DESCRIPTION +* The tmpfileplus() function opens a unique temporary file in binary +* read/write (w+b) mode. The file is opened with the O_EXCL flag, +* guaranteeing that the caller is the only user. The filename will consist +* of the string given by `prefix` followed by 10 random characters. If +* `prefix` is NULL, then the string "tmp." will be used instead. The file +* will be created in an appropriate directory chosen by the first +* successful attempt in the following sequence: +* +* a) The directory given by the `dir` argument (so the caller can specify +* a secure directory to take precedence). +* +* b) The directory name in the environment variables: +* +* (i) "TMP" [Windows only] +* (ii) "TEMP" [Windows only] +* (iii) "TMPDIR" [Unix only] +* +* c) `P_tmpdir` as defined in [Unix only] (in Windows, this is +* usually "\", which is no good). +* +* d) The current working directory. +* +* If a file cannot be created in any of the above directories, then the +* function fails and NULL is returned. +* +* If the argument `pathname` is not a null pointer, then it will point to +* the full pathname of the file. The pathname is allocated using `malloc` +* and therefore should be freed by `free`. +* +* If `keep` is nonzero and `pathname` is not a null pointer, then the file +* will be kept after it is closed. Otherwise the file will be +* automatically deleted when it is closed or the program terminates. +* +* +* RETURN VALUE +* The tmpfileplus() function returns a pointer to the open file stream, +* or NULL if a unique file cannot be opened. +* +* +* ERRORS +* ENOMEM Not enough memory to allocate filename. +* +*/ + +/* ADDED IN v2.0 */ + +/* +* NAME +* tmpfileplus_f - create a unique temporary file with filename stored in a fixed-length buffer +* +* SYNOPSIS +* FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep); +* +* DESCRIPTION +* Same as tmpfileplus() except receives filename in a fixed-length buffer. No allocated memory to free. + +* ERRORS +* E2BIG Resulting filename is too big for the buffer `pathnamebuf`. + +*/ + +#include "tmpfileplus.h" + +#include +#include +#include +#include +#include + +/* Non-ANSI include files that seem to work in both MSVC and Linux */ +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN32 +/* MSVC nags to enforce ISO C++ conformant function names with leading "_", + * so we define our own function names to avoid whingeing compilers... + */ +#define OPEN_ _open +#define FDOPEN_ _fdopen +#else +#define OPEN_ open +#define FDOPEN_ fdopen +#endif + + +/* DEBUGGING STUFF */ +#if defined(_DEBUG) && defined(SHOW_DPRINTF) +#define DPRINTF1(s, a1) printf(s, a1) +#else +#define DPRINTF1(s, a1) +#endif + + +#ifdef _WIN32 +#define FILE_SEPARATOR "\\" +#else +#define FILE_SEPARATOR "/" +#endif + +#define RANDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" +#define NRANDCHARS (sizeof(RANDCHARS) - 1) + +/** Replace each byte in string s with a random character from TEMPCHARS */ +static char *set_randpart(char *s) +{ + size_t i; + unsigned int r; + static unsigned int seed; /* NB static */ + + if (seed == 0) + { /* First time set our seed using current time and clock */ + seed = ((unsigned)time(NULL)<<8) ^ (unsigned)clock(); + } + srand(seed++); + for (i = 0; i < strlen(s); i++) + { + r = rand() % NRANDCHARS; + s[i] = (RANDCHARS)[r]; + } + return s; +} + +/** Return 1 if path is a valid directory otherwise 0 */ +static int is_valid_dir(const char *path) +{ + struct stat st; + if ((stat(path, &st) == 0) && (st.st_mode & S_IFDIR)) + return 1; + + return 0; +} + +/** Call getenv and save a copy in buf */ +static char *getenv_save(const char *varname, char *buf, size_t bufsize) +{ + char *ptr = getenv(varname); + buf[0] = '\0'; + if (ptr) + { + strncpy(buf, ptr, bufsize); + buf[bufsize-1] = '\0'; + return buf; + } + return NULL; +} + +/** + * Try and create a randomly-named file in directory `tmpdir`. + * If successful, allocate memory and set `tmpname_ptr` to full filepath, and return file pointer; + * otherwise return NULL. + * If `keep` is zero then create the file as temporary and it should not exist once closed. + */ +static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmpname_ptr, int keep) +/* PRE: + * pfx is not NULL and points to a valid null-terminated string + * tmpname_ptr is not NULL. + */ +{ + FILE *fp; + int fd; + char randpart[] = "1234567890"; + size_t lentempname; + int i; + char *tmpname = NULL; + int oflag, pmode; + +/* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed. + * In Unix, we use the unlink function after opening the file. (This does not work in Windows, + * which does not allow an open file to be unlinked.) + */ +#ifdef _WIN32 + /* MSVC flags */ + oflag = _O_BINARY|_O_CREAT|_O_EXCL|_O_RDWR; + if (!keep) + oflag |= _O_TEMPORARY; + pmode = _S_IREAD | _S_IWRITE; +#else + /* Standard POSIX flags */ + oflag = O_CREAT|O_EXCL|O_RDWR; + pmode = S_IRUSR|S_IWUSR; +#endif + + if (!tmpdir || !is_valid_dir(tmpdir)) { + errno = ENOENT; + return NULL; + } + + lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart); + DPRINTF1("lentempname=%d\n", lentempname); + tmpname = malloc(lentempname + 1); + if (!tmpname) + { + errno = ENOMEM; + return NULL; + } + /* If we don't manage to create a file after 10 goes, there is something wrong... */ + for (i = 0; i < 10; i++) + { + sprintf(tmpname, "%s%s%s%s", tmpdir, FILE_SEPARATOR, pfx, set_randpart(randpart)); + DPRINTF1("[%s]\n", tmpname); + fd = OPEN_(tmpname, oflag, pmode); + if (fd != -1) break; + } + DPRINTF1("strlen(tmpname)=%d\n", strlen(tmpname)); + if (fd != -1) + { /* Success, so return user a proper ANSI C file pointer */ + fp = FDOPEN_(fd, "w+b"); + errno = 0; + +#ifndef _WIN32 + /* [Unix only] And make sure the file will be deleted once closed */ + if (!keep) unlink(tmpname); +#endif + + } + else + { /* We failed */ + fp = NULL; + } + if (!fp) + { + free(tmpname); + tmpname = NULL; + } + + *tmpname_ptr = tmpname; + return fp; +} + +/**********************/ +/* EXPORTED FUNCTIONS */ +/**********************/ + +FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep) +{ + FILE *fp = NULL; + char *tmpname = NULL; + char *tmpdir = NULL; + const char *pfx = (prefix ? prefix : "tmp."); + char *tempdirs[12] = { 0 }; + char env1[FILENAME_MAX+1] = { 0 }; + char env2[FILENAME_MAX+1] = { 0 }; + char env3[FILENAME_MAX+1] = { 0 }; + int ntempdirs = 0; + int i; + + /* Set up a list of temp directories we will try in order */ + i = 0; + tempdirs[i++] = (char *)dir; +#ifdef _WIN32 + tempdirs[i++] = getenv_save("TMP", env1, sizeof(env1)); + tempdirs[i++] = getenv_save("TEMP", env2, sizeof(env2)); +#else + tempdirs[i++] = getenv_save("TMPDIR", env3, sizeof(env3)); + tempdirs[i++] = P_tmpdir; +#endif + tempdirs[i++] = "."; + ntempdirs = i; + + errno = 0; + + /* Work through list we set up before, and break once we are successful */ + for (i = 0; i < ntempdirs; i++) + { + tmpdir = tempdirs[i]; + DPRINTF1("Trying tmpdir=[%s]\n", tmpdir); + fp = mktempfile_internal(tmpdir, pfx, &tmpname, keep); + if (fp) break; + } + /* If we succeeded and the user passed a pointer, set it to the alloc'd pathname: the user must free this */ + if (fp && pathname) + *pathname = tmpname; + else /* Otherwise, free the alloc'd memory */ + free(tmpname); + + return fp; +} + +/* Same as tmpfileplus() but with fixed length buffer for output filename and no memory allocation */ +FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep) +{ + char *tmpbuf = NULL; + FILE *fp; + + /* If no buffer provided, do the normal way */ + if (!pathnamebuf || (int)pathsize <= 0) { + return tmpfileplus(dir, prefix, NULL, keep); + } + /* Call with a temporary buffer */ + fp = tmpfileplus(dir, prefix, &tmpbuf, keep); + if (fp && strlen(tmpbuf) > pathsize - 1) { + /* Succeeded but not enough room in output buffer, so clean up and return an error */ + pathnamebuf[0] = 0; + fclose(fp); + if (keep) remove(tmpbuf); + free(tmpbuf); + errno = E2BIG; + return NULL; + } + /* Copy name into buffer */ + strcpy(pathnamebuf, tmpbuf); + free(tmpbuf); + + return fp; +} + + diff --git a/src/tmpfileplus.h b/src/tmpfileplus.h new file mode 100644 index 000000000..6c6ac38a7 --- /dev/null +++ b/src/tmpfileplus.h @@ -0,0 +1,53 @@ +/* $Id: tmpfileplus.h $ */ +/* + * $Date: 2016-06-01 03:31Z $ + * $Revision: 2.0.0 $ + * $Author: dai $ + */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd + * . + */ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#ifndef TMPFILEPLUS_H_ +#define TMPFILEPLUS_H_ + +#include + +/** Create a unique temporary file. +@param dir (optional) directory to create file. If NULL use default TMP directory. +@param prefix (optional) prefix for file name. If NULL use "tmp.". +@param pathname (optional) pointer to a buffer to receive the temp filename. + Allocated using `malloc()`; user to free. Ignored if NULL. +@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing. + Otherwise file is automatically deleted when closed. +@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error. +@exception ENOMEM Not enough memory to allocate filename. +*/ +FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep); + + +/** Create a unique temporary file with filename stored in a fixed-length buffer. +@param dir (optional) directory to create file. If NULL use default directory. +@param prefix (optional) prefix for file name. If NULL use "tmp.". +@param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL. +@param pathsize Size of buffer to receive filename and its terminating null character. +@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing. + Otherwise file is automatically deleted when closed. +@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error. +@exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`. +*/ +FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep); + +#define TMPFILE_KEEP 1 + +#endif /* end TMPFILEPLUS_H_ */ From e6c9ccf3a1a4ce2c39b859352065c4206b0b404f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 4 Nov 2017 13:12:13 +0200 Subject: [PATCH 104/105] Changed tmpfileplus() to our needs Removed exclusive flag, made it C++ friendly, replaced unlink() with remove() --- src/tmpfileplus.c | 6 +++--- src/tmpfileplus.h | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tmpfileplus.c b/src/tmpfileplus.c index 9af0260b3..ddb71de09 100644 --- a/src/tmpfileplus.c +++ b/src/tmpfileplus.c @@ -200,13 +200,13 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp */ #ifdef _WIN32 /* MSVC flags */ - oflag = _O_BINARY|_O_CREAT|_O_EXCL|_O_RDWR; + oflag = _O_BINARY|_O_CREAT|_O_RDWR; if (!keep) oflag |= _O_TEMPORARY; pmode = _S_IREAD | _S_IWRITE; #else /* Standard POSIX flags */ - oflag = O_CREAT|O_EXCL|O_RDWR; + oflag = O_CREAT|O_RDWR; pmode = S_IRUSR|S_IWUSR; #endif @@ -239,7 +239,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp #ifndef _WIN32 /* [Unix only] And make sure the file will be deleted once closed */ - if (!keep) unlink(tmpname); + if (!keep) remove(tmpname); #endif } diff --git a/src/tmpfileplus.h b/src/tmpfileplus.h index 6c6ac38a7..e32ff5042 100644 --- a/src/tmpfileplus.h +++ b/src/tmpfileplus.h @@ -23,6 +23,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** Create a unique temporary file. @param dir (optional) directory to create file. If NULL use default TMP directory. @param prefix (optional) prefix for file name. If NULL use "tmp.". @@ -50,4 +54,8 @@ FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size #define TMPFILE_KEEP 1 +#ifdef __cplusplus +} +#endif + #endif /* end TMPFILEPLUS_H_ */ From 0e706bfecfd063f7c2a0bdf77fcdd43f577ff72e Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 4 Nov 2017 13:15:53 +0200 Subject: [PATCH 105/105] Use tmpfileplus() instead of tempnam() Finally get rid of security or deprecated warnings cause by tempnam() function usage --- src/CMakeLists.txt | 2 +- src/sound/i_music.cpp | 1 - src/sound/i_musicinterns.h | 1 - .../music_timiditypp_mididevice.cpp | 60 +++++++----------- src/sound/oalsound.cpp | 1 - src/tempfiles.cpp | 57 ----------------- src/tempfiles.h | 61 ------------------- 7 files changed, 24 insertions(+), 159 deletions(-) delete mode 100644 src/tempfiles.cpp delete mode 100644 src/tempfiles.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 222a39d36..7ede5128b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -958,7 +958,6 @@ set (PCH_SOURCES stats.cpp stringtable.cpp teaminfo.cpp - tempfiles.cpp v_blend.cpp v_collection.cpp v_draw.cpp @@ -1179,6 +1178,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE ${PCH_SOURCES} x86.cpp strnatcmp.c + tmpfileplus.c zstring.cpp math/asin.c math/atan.c diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index b66e5d096..19db0161d 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -59,7 +59,6 @@ extern void ChildSigHandler (int signum); #include "s_sound.h" #include "m_swap.h" #include "i_cd.h" -#include "tempfiles.h" #include "templates.h" #include "stats.h" #include "timidity/timidity.h" diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 9bf9f8aed..7bc5a31e5 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -1,5 +1,4 @@ -#include "tempfiles.h" #include "oplsynth/opl_mus_player.h" #include "c_cvars.h" #include "mus2midi.h" diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index b0ce41ead..d4c03534d 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -42,6 +42,7 @@ #include "cmdlib.h" #include "templates.h" #include "version.h" +#include "tmpfileplus.h" #ifndef _WIN32 #include @@ -81,13 +82,12 @@ public: protected: bool LaunchTimidity(); - FTempFileName DiskName; + char* DiskName; #ifdef _WIN32 HANDLE ReadWavePipe; HANDLE WriteWavePipe; HANDLE ChildProcess; FString CommandLine; - size_t LoopPos; bool Validated; bool ValidateTimidity(); #else // _WIN32 @@ -166,7 +166,7 @@ CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) //========================================================================== TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) - : DiskName("zmid"), + : DiskName(nullptr), #ifdef _WIN32 ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE), ChildProcess(INVALID_HANDLE_VALUE), @@ -194,12 +194,6 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) CommandLine += "\" "; } #endif - - if (DiskName == NULL) - { - Printf(PRINT_BOLD, "Could not create temp music file\n"); - return; - } } //========================================================================== @@ -210,6 +204,12 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) TimidityPPMIDIDevice::~TimidityPPMIDIDevice () { + if (nullptr != DiskName) + { + remove(DiskName); + free(DiskName); + } + #if _WIN32 if (WriteWavePipe != INVALID_HANDLE_VALUE) { @@ -252,17 +252,12 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) return false; } - // Tell TiMidity++ whether it should loop or not -#ifdef _WIN32 - CommandLine.LockBuffer()[LoopPos] = looping ? 'l' : ' '; - CommandLine.UnlockBuffer(); -#endif Looping = looping; // Write MIDI song to temporary file song->CreateSMF(midi, looping ? 0 : 1); - f = fopen(DiskName, "wb"); + f = tmpfileplus(nullptr, "zmid", &DiskName, 1); if (f == NULL) { Printf(PRINT_BOLD, "Could not open temp music file\n"); @@ -275,6 +270,16 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) { Printf(PRINT_BOLD, "Could not write temp music file\n"); } + +#ifdef _WIN32 + CommandLine.AppendFormat("-o - -Ors%c%c%c -id%c %s", + timidity_stereo ? 'S' : 'M', + timidity_8bit ? '8' : '1', + timidity_byteswap ? 'x' : ' ', + looping ? 'l' : ' ', + DiskName); +#endif + return false; } @@ -342,20 +347,6 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) } } -#ifdef _WIN32 - CommandLine += "-o - -Ors"; - CommandLine += timidity_stereo ? 'S' : 'M'; - CommandLine += timidity_8bit ? '8' : '1'; - if (timidity_byteswap) - { - CommandLine += 'x'; - } - - LoopPos = CommandLine.Len() + 4; - - CommandLine += " -idl "; - CommandLine += DiskName.GetName(); -#endif return 0; } @@ -463,12 +454,12 @@ bool TimidityPPMIDIDevice::ValidateTimidity() bool TimidityPPMIDIDevice::LaunchTimidity () { -#ifdef _WIN32 - if (CommandLine.IsEmpty()) + if (ExeName.IsEmpty() || nullptr == DiskName) { return false; } +#ifdef _WIN32 DPrintf (DMSG_NOTIFY, "cmd: \x1cG%s\n", CommandLine.GetChars()); STARTUPINFO startup = { sizeof(startup), }; @@ -516,11 +507,6 @@ bool TimidityPPMIDIDevice::LaunchTimidity () } return false; #else - if (ExeName.IsEmpty()) - { - return false; - } - if (WavePipe[0] != -1 && WavePipe[1] == -1 && Stream != NULL) { // Timidity was previously launched, so the write end of the pipe @@ -579,7 +565,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity () arglist.push_back("-"); arglist.push_back(outmodearg.c_str()); arglist.push_back(ifacearg.c_str()); - arglist.push_back(DiskName.GetName()); + arglist.push_back(DiskName); DPrintf(DMSG_NOTIFY, "Timidity EXE: \x1cG%s\n", exename); int i = 1; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index b9b0a1b10..c2867804d 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -57,7 +57,6 @@ #include "i_module.h" #include "i_music.h" #include "i_musicinterns.h" -#include "tempfiles.h" #include "cmdlib.h" FModule OpenALModule{"OpenAL"}; diff --git a/src/tempfiles.cpp b/src/tempfiles.cpp deleted file mode 100644 index 6ac782ccf..000000000 --- a/src/tempfiles.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -** tempfiles.cpp -** Temporary name generator. Deletes the temporary file when deconstructed. -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include "tempfiles.h" - -FTempFileName::FTempFileName (const char *prefix) -{ -// Under Linux, ld will complain that tempnam is dangerous, and -// mkstemp should be used instead. However, there is no mkstemp -// under VC++, and even if there was, I still need to know the -// file name so that it can be used as input to Timidity. - - Name = tempnam (NULL, prefix); -} - -FTempFileName::~FTempFileName () -{ - if (Name != NULL) - { - remove (Name); - free (Name); - Name = NULL; - } -} diff --git a/src/tempfiles.h b/src/tempfiles.h deleted file mode 100644 index fe267d71a..000000000 --- a/src/tempfiles.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -** tempfiles.h -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef __TEMPFILES_H__ -#define __TEMPFILES_H__ - -#ifdef _MSC_VER -#pragma once -#endif - -#include - -// Returns a file name suitable for use as a temp file. -// If you create a file with this name (and presumably you -// will), it will be deleted automatically by this class's -// destructor. - -class FTempFileName -{ -public: - FTempFileName (const char *prefix=NULL); - ~FTempFileName (); - - operator const char * () { return Name; } - const char * GetName () const { return Name; } - -private: - char *Name; -}; - -#endif //__TEMPFILES_H__