From 587c0079e263b9c404865ce2c22ba9f02e5305f5 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 22 Oct 2016 23:19:24 +0100 Subject: [PATCH 1/4] Started work on FLIPX/FLIPY support for patches. Doesn't do anything yet, but the parser should know how to look for them now Note: I had to create M_UnGetToken in order to avoid problems with looking for patch parameters (marked by { and }) but not finding anything --- src/dehacked.c | 2 +- src/doomdef.h | 1 + src/m_misc.c | 21 ++++++++++++++++++--- src/r_data.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/r_data.h | 1 + 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 20f835981..920e5eec3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2778,7 +2778,7 @@ static void readpatch(MYFILE *f, const char *name, UINT16 wad) char *word2; char *tmp; INT32 i = 0, j = 0, value; - texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX}; + texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0}; // Jump to the texture this patch belongs to, which, // coincidentally, is always the last one on the buffer cache. diff --git a/src/doomdef.h b/src/doomdef.h index 410e740fa..d0ac3a676 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -407,6 +407,7 @@ void M_StartupLocale(void); extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL; char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); +void M_UnGetToken(void); char *sizeu1(size_t num); char *sizeu2(size_t num); char *sizeu3(size_t num); diff --git a/src/m_misc.c b/src/m_misc.c index cfe73d88f..d6ab40196 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1617,6 +1617,11 @@ INT32 axtoi(const char *hexStg) return intValue; } +// Token parser variables + +static UINT32 oldendPos = 0; // old value of endPos, used by M_UnGetToken +static UINT32 endPos = 0; // now external to M_GetToken, but still static + /** Token parser for TEXTURES, ANIMDEFS, and potentially other lumps later down the line. * Was originally R_GetTexturesToken when I was coding up the TEXTURES parser, until I realized I needed it for ANIMDEFS too. * Parses up to the next whitespace character or comma. When finding the start of the next token, whitespace is skipped. @@ -1631,7 +1636,7 @@ char *M_GetToken(const char *inputString) { static const char *stringToUse = NULL; // Populated if inputString != NULL; used otherwise static UINT32 startPos = 0; - static UINT32 endPos = 0; +// static UINT32 endPos = 0; static UINT32 stringLength = 0; static UINT8 inComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */ char *texturesToken = NULL; @@ -1641,12 +1646,12 @@ char *M_GetToken(const char *inputString) { stringToUse = inputString; startPos = 0; - endPos = 0; + oldendPos = endPos = 0; stringLength = strlen(inputString); } else { - startPos = endPos; + startPos = oldendPos = endPos; } if (stringToUse == NULL) return NULL; @@ -1777,6 +1782,16 @@ char *M_GetToken(const char *inputString) return texturesToken; } +/** Undoes the last M_GetToken call + * The current position along the string being parsed is reset to the last saved position. + * This exists mostly because of R_ParseTexture/R_ParsePatch honestly, but could be useful elsewhere? + * -Monster Iestyn (22/10/16) + */ +void M_UnGetToken(void) +{ + endPos = oldendPos; +} + /** Count bits in a number. */ UINT8 M_CountBits(UINT32 num, UINT8 size) diff --git a/src/r_data.c b/src/r_data.c index cb5cf3591..5c3d06649 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -502,6 +502,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) char *patchName = NULL; INT16 patchXPos; INT16 patchYPos; + UINT8 flip = 0; texpatch_t *resultPatch = NULL; lumpnum_t patchLumpNum; @@ -598,6 +599,47 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) } Z_Free(texturesToken); + // Patch parameters block (OPTIONAL) + // added by Monster Iestyn (22/10/16) + + // Left Curly Brace + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + ; // move on and ignore, R_ParseTextures will deal with this + else + { + if (strcmp(texturesToken,"{")==0) + { + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters should be",patchName); + } + while (strcmp(texturesToken,"}")!=0) + { + if (stricmp(texturesToken, "FLIPX")==0) + flip |= 1; + else if (stricmp(texturesToken, "FLIPY")==0) + flip |= 2; + Z_Free(texturesToken); + + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters or right curly brace should be",patchName); + } + } + } + else + { + // this is not what we wanted... + // undo last read so R_ParseTextures can re-get the token for its own purposes + M_UnGetToken(); + } + Z_Free(texturesToken); + } + if (actuallyLoadPatch == true) { // Check lump exists @@ -608,6 +650,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) resultPatch->originy = patchYPos; resultPatch->lump = patchLumpNum & 65535; resultPatch->wad = patchLumpNum>>16; + resultPatch->flip = flip; // Clean up a little after ourselves Z_Free(patchName); // Then return it diff --git a/src/r_data.h b/src/r_data.h index 69a2882af..1384ecac0 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -31,6 +31,7 @@ typedef struct // Block origin (always UL), which has already accounted for the internal origin of the patch. INT16 originx, originy; UINT16 wad, lump; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both } texpatch_t; // A maptexturedef_t describes a rectangular texture, From 410b55ebcd6d8688eba09873ba1f46ec3d150828 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 28 Nov 2016 22:21:54 +0000 Subject: [PATCH 2/4] Work on FLIPX/FLIPX support: *Added FLIPX/FLIPY support for multi-patch textures and single-patch textures without holes *Added FLIPY support for single-patch textures with holes; I'll sort FLIPX support out later --- src/r_data.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++---- src/r_data.h | 1 + src/r_segs.c | 35 +++++++++++++++++++++++++++++-- src/r_things.c | 2 +- src/r_things.h | 1 + 5 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index b39ede58c..f4910fa00 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -173,6 +173,43 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig } } +static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source, *dest; + INT32 topdelta, prevdelta = -1; + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topdelta = patchheight-patch->length-topdelta; + source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + dest = cache + position; + if (count > 0) + { + for (; dest < cache + position + count; --source) + *dest++ = *source; + } + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + // // R_GenerateTexture // @@ -191,7 +228,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; - int x, x1, x2, i; + int x, x1, x2, i, width, height; size_t blocksize; column_t *patchcol; UINT32 *colofs; @@ -239,6 +276,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) if (holey) { texture->holes = true; + texture->flip = patch->flip; blocksize = W_LumpLengthPwad(patch->wad, patch->lump); block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); @@ -259,6 +297,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) // multi-patch textures (or 'composite') texture->holes = false; + texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); texturememory += blocksize; block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); @@ -277,7 +316,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) { realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); + width = SHORT(realpatch->width); + height = SHORT(realpatch->height); + x2 = x1 + width; if (x1 < 0) x = 0; @@ -289,11 +330,17 @@ static UINT8 *R_GenerateTexture(size_t texnum) for (; x < x2; x++) { - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); + if (patch->flip & 1) + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); + else + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); // generate column ofset lookup colofs[x] = LONG((x * texture->height) + (texture->width*4)); - R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); + if (patch->flip & 2) + R_DrawFlippedColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height, height); + else + R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); } } @@ -469,6 +516,7 @@ void R_LoadTextures(void) texture->height = SHORT(patchlump->height)*patchcount; texture->patchcount = patchcount; texture->holes = false; + texture->flip = 0; // Allocate information for the texture's patches. for (k = 0; k < patchcount; k++) @@ -479,6 +527,7 @@ void R_LoadTextures(void) patch->originy = (INT16)(k*patchlump->height); patch->wad = (UINT16)w; patch->lump = texstart + j; + patch->flip = 0; } Z_Unlock(patchlump); diff --git a/src/r_data.h b/src/r_data.h index 1384ecac0..72054da5d 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -43,6 +43,7 @@ typedef struct char name[8]; INT16 width, height; boolean holes; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both // All the patches[patchcount] are drawn back to front into the cached texture. INT16 patchcount; diff --git a/src/r_segs.c b/src/r_segs.c index 257be2989..91fb0e5bd 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -276,6 +276,13 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) } } +// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value +// uses column2s_length for texture->height as above +static void R_DrawFlippedMaskedSegColumn(column_t *column) +{ + R_DrawFlippedMaskedColumn(column, column2s_length); +} + void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -347,7 +354,15 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 if (textures[texnum]->holes) - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawFlippedMaskedSegColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) @@ -700,6 +715,14 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } while (sprtopscreen < sprbotscreen); } +static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +{ + do { + R_DrawFlippedMaskedColumn(col, column2s_length); + sprtopscreen += dc_texheight*spryscale; + } while (sprtopscreen < sprbotscreen); +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -1027,7 +1050,15 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) - colfunc_2s = R_DrawRepeatMaskedColumn; //render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawRepeatFlippedMaskedColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) diff --git a/src/r_things.c b/src/r_things.c index 9f6cad529..5d560b53d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -712,7 +712,7 @@ void R_DrawMaskedColumn(column_t *column) dc_texturemid = basetexturemid; } -static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) +void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) { INT32 topscreen; INT32 bottomscreen; diff --git a/src/r_things.h b/src/r_things.h index 20dd25abf..572884d21 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -46,6 +46,7 @@ extern fixed_t windowtop; extern fixed_t windowbottom; void R_DrawMaskedColumn(column_t *column); +void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight); void R_SortVisSprites(void); //faB: find sprites in wadfile, replace existing, add new ones From 52a84cf3091b2bfd26b8e5505f7c39d0fad3941a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Dec 2016 21:43:27 +0000 Subject: [PATCH 3/4] Fix negative y offsets for both normal and y-flipped patches --- src/r_data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index f4910fa00..3e28b8ca2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -160,6 +160,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig if (position < 0) { count += position; + source -= position; // start further down the column position = 0; } @@ -193,6 +194,7 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT if (position < 0) { count += position; + source += position; // start further UP the column position = 0; } From 84f3102ad08788e4142c9020e0fabb225ea5abcf Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Dec 2016 22:37:33 +0000 Subject: [PATCH 4/4] Added FLIPX support for single patch textures with holes This completes FLIPX/FLIPY support for all textures --- src/r_data.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index 3e28b8ca2..350bd4175 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -289,6 +289,14 @@ static UINT8 *R_GenerateTexture(size_t texnum) colofs = (UINT32 *)(void *)(block + 8); texturecolumnofs[texnum] = colofs; blocktex = block; + if (patch->flip & 1) // flip the patch horizontally + { + UINT32 *realcolofs = (UINT32 *)realpatch->columnofs; + for (x = 0; x < texture->width; x++) + colofs[x] = realcolofs[texture->width-1-x]; // swap with the offset of the other side of the texture + } + // we can't as easily flip the patch vertically sadly though, + // we have wait until the texture itself is drawn to do that for (x = 0; x < texture->width; x++) colofs[x] = LONG(LONG(colofs[x]) + 3); goto done;