diff --git a/src/p_xlat.cpp b/src/p_xlat.cpp index 7824adf2c..28792ff7a 100644 --- a/src/p_xlat.cpp +++ b/src/p_xlat.cpp @@ -133,10 +133,17 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) for (int t = 0; t < LINETRANS_MAXARGS; ++t) { ld->args[t] = linetrans->args[t]; - // Arguments that are tags have the tag's value added to them. - if (linetrans->flags & (1 << (LINETRANS_TAGSHIFT+t))) + // Apply tag modifications, if needed. + int tagop = (linetrans->flags >> (LINETRANS_TAGSHIFT + t*TAGOP_NUMBITS)) & TAGOP_MASK; + switch (tagop) { - ld->args[t] += tag; + case TAGOP_None: default: break; + case TAGOP_Add: ld->args[t] += tag; break; + case TAGOP_Mul: ld->args[t] *= tag; break; + case TAGOP_Div: ld->args[t] /= tag; break; + case TAGOP_And: ld->args[t] &= tag; break; + case TAGOP_Or: ld->args[t] |= tag; break; + case TAGOP_Xor: ld->args[t] ^= tag; break; } } diff --git a/src/xlat/parse_xlat.cpp b/src/xlat/parse_xlat.cpp index e5d277265..17cd42d21 100644 --- a/src/xlat/parse_xlat.cpp +++ b/src/xlat/parse_xlat.cpp @@ -74,7 +74,7 @@ struct SpecialArgs struct SpecialArg { int arg; - bool bIsTag; + ELineTransTagOp tagop; }; struct ListFilter diff --git a/src/xlat/xlat.h b/src/xlat/xlat.h index 0d020e75e..0653d4ab6 100644 --- a/src/xlat/xlat.h +++ b/src/xlat/xlat.h @@ -4,10 +4,24 @@ #include "doomtype.h" #include "tarray.h" +enum ELineTransTagOp +{ + TAGOP_None, + TAGOP_Add, + TAGOP_Mul, + TAGOP_Div, + TAGOP_And, + TAGOP_Or, + TAGOP_Xor, + + TAGOP_NUMBITS = 3, + TAGOP_MASK = (1 << TAGOP_NUMBITS) - 1 +}; + enum { - LINETRANS_TAGSHIFT = 24, - LINETRANS_MAXARGS = 5 + LINETRANS_MAXARGS = 5, + LINETRANS_TAGSHIFT = 30 - LINETRANS_MAXARGS * TAGOP_NUMBITS, }; struct FLineTrans diff --git a/src/xlat/xlat_parser.y b/src/xlat/xlat_parser.y index 046a950c9..1f14409c4 100644 --- a/src/xlat/xlat_parser.y +++ b/src/xlat/xlat_parser.y @@ -27,7 +27,7 @@ external_declaration ::= NOP. %left XOR. %left AND. %left MINUS PLUS. -%left MULTIPLY DIVIDE. +%left MULTIPLY DIVIDE MODULUS. %left NEG. %type exp {int} @@ -35,7 +35,7 @@ exp(A) ::= NUM(B). { A = B.val; } exp(A) ::= exp(B) PLUS exp(C). { A = B + C; } exp(A) ::= exp(B) MINUS exp(C). { A = B - C; } exp(A) ::= exp(B) MULTIPLY exp(C). { A = B * C; } -exp(A) ::= exp(B) DIVIDE exp(C). { if (C != 0) A = B / C; else context->PrintError("Division by Zero"); } +exp(A) ::= exp(B) DIVIDE exp(C). { if (C != 0) A = B / C; else context->PrintError("Division by zero"); } exp(A) ::= exp(B) OR exp(C). { A = B | C; } exp(A) ::= exp(B) AND exp(C). { A = B & C; } exp(A) ::= exp(B) XOR exp(C). { A = B ^ C; } @@ -104,29 +104,59 @@ linetype_declaration ::= exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN. special_arg(Z) ::= exp(A). { Z.arg = A; - Z.bIsTag = false; + Z.tagop = TAGOP_None; } special_arg(Z) ::= TAG. { Z.arg = 0; - Z.bIsTag = true; + Z.tagop = TAGOP_Add; } special_arg(Z) ::= TAG PLUS exp(A). { Z.arg = A; - Z.bIsTag = true; + Z.tagop = TAGOP_Add; } special_arg(Z) ::= TAG MINUS exp(A). { Z.arg = -A; - Z.bIsTag = true; + Z.tagop = TAGOP_Add; } +special_arg(Z) ::= TAG MULTIPLY exp(A). +{ + Z.arg = A; + Z.tagop = TAGOP_Mul; +} +special_arg(Z) ::= TAG DIVIDE exp(A). +{ + Z.arg = A; + Z.tagop = TAGOP_Div; + if (A == 0) + { + context->PrintError("Division by zero"); + } +} +special_arg(Z) ::= TAG OR exp(A). +{ + Z.arg = A; + Z.tagop = TAGOP_Or; +} +special_arg(Z) ::= TAG AND exp(A). +{ + Z.arg = A; + Z.tagop = TAGOP_And; +} +special_arg(Z) ::= TAG XOR exp(A). +{ + Z.arg = A; + Z.tagop = TAGOP_Xor; +} + %type multi_special_arg {SpecialArgs} multi_special_arg(Z) ::= special_arg(A). { - Z.addflags = A.bIsTag << LINETRANS_TAGSHIFT; + Z.addflags = A.tagop << LINETRANS_TAGSHIFT; Z.argcount = 1; Z.args[0] = A.arg; Z.args[1] = 0; @@ -139,7 +169,7 @@ multi_special_arg(Z) ::= multi_special_arg(A) COMMA special_arg(B). Z = A; if (Z.argcount < LINETRANS_MAXARGS) { - Z.addflags |= B.bIsTag << (LINETRANS_TAGSHIFT + Z.argcount); + Z.addflags |= B.tagop << (LINETRANS_TAGSHIFT + Z.argcount * TAGOP_NUMBITS); Z.args[Z.argcount] = B.arg; Z.argcount++; }