mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 04:51:19 +00:00
- Remove all restrictions on what you can do with tags as line special arguments in xlat.
Something like 「(tag & 5) + (tag & 2) / 2」 is now a valid argument for a standard line translation. SVN r3345 (trunk)
This commit is contained in:
parent
4b2ae689ed
commit
ef88515dda
4 changed files with 251 additions and 83 deletions
165
src/p_xlat.cpp
165
src/p_xlat.cpp
|
@ -130,21 +130,33 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
|
|||
ld->activation = SPAC_UseThrough;
|
||||
}
|
||||
// Set special arguments.
|
||||
FXlatExprState state;
|
||||
state.tag = tag;
|
||||
state.linetype = special;
|
||||
for (int t = 0; t < LINETRANS_MAXARGS; ++t)
|
||||
{
|
||||
ld->args[t] = linetrans->args[t];
|
||||
// Apply tag modifications, if needed.
|
||||
int tagop = (linetrans->flags >> (LINETRANS_TAGSHIFT + t*TAGOP_NUMBITS)) & TAGOP_MASK;
|
||||
switch (tagop)
|
||||
int arg = linetrans->args[t];
|
||||
int argop = (linetrans->flags >> (LINETRANS_TAGSHIFT + t*TAGOP_NUMBITS)) & TAGOP_MASK;
|
||||
|
||||
switch (argop)
|
||||
{
|
||||
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 / ld->args[t]; break;
|
||||
case TAGOP_Mod: ld->args[t] = tag % ld->args[t]; 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;
|
||||
case ARGOP_Const:
|
||||
ld->args[t] = arg;
|
||||
break;
|
||||
case ARGOP_Tag:
|
||||
ld->args[t] = tag;
|
||||
break;
|
||||
case ARGOP_Expr:
|
||||
{
|
||||
int *xnode = &XlatExpressions[arg];
|
||||
state.bIsConstant = true;
|
||||
XlatExprEval[*xnode](&ld->args[t], xnode, &state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
ld->args[t] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,3 +361,132 @@ int P_TranslateSectorSpecial (int special)
|
|||
return special | mask;
|
||||
}
|
||||
|
||||
static const int *Expr_Const(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
*dest = xnode[-1];
|
||||
return xnode - 2;
|
||||
}
|
||||
|
||||
static const int *Expr_Tag(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
*dest = state->tag;
|
||||
state->bIsConstant = false;
|
||||
return xnode - 1;
|
||||
}
|
||||
|
||||
static const int *Expr_Add(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
*dest = op1 + op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_Sub(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
*dest = op1 - op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_Mul(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
*dest = op1 * op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static void Div0Check(int &op1, int &op2, const FXlatExprState *state)
|
||||
{
|
||||
if (op2 == 0)
|
||||
{
|
||||
Printf("Xlat: Division by 0 for line type %d\n", state->linetype);
|
||||
// Set some safe values
|
||||
op1 = 0;
|
||||
op2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const int *Expr_Div(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
Div0Check(op1, op2, state);
|
||||
*dest = op1 / op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_Mod(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
Div0Check(op1, op2, state);
|
||||
*dest = op1 % op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_And(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
*dest = op1 & op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_Or(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
*dest = op1 | op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_Xor(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op1, op2;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op2, xnode-1, state);
|
||||
xnode = XlatExprEval[xnode[0]](&op1, xnode, state);
|
||||
*dest = op1 ^ op2;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
static const int *Expr_Neg(int *dest, const int *xnode, FXlatExprState *state)
|
||||
{
|
||||
int op;
|
||||
|
||||
xnode = XlatExprEval[xnode[-1]](&op, xnode-1, state);
|
||||
*dest = -op;
|
||||
return xnode;
|
||||
}
|
||||
|
||||
const int* (*XlatExprEval[XEXP_COUNT])(int *dest, const int *xnode, FXlatExprState *state) =
|
||||
{
|
||||
Expr_Const,
|
||||
Expr_Tag,
|
||||
Expr_Add,
|
||||
Expr_Sub,
|
||||
Expr_Mul,
|
||||
Expr_Div,
|
||||
Expr_Mod,
|
||||
Expr_And,
|
||||
Expr_Or,
|
||||
Expr_Xor,
|
||||
Expr_Neg
|
||||
};
|
|
@ -57,6 +57,7 @@ DEFINE_TOKEN_TRANS(XLAT_)
|
|||
|
||||
static FString LastTranslator;
|
||||
TAutoGrowArray<FLineTrans> SimpleLineTranslations;
|
||||
TArray<int> XlatExpressions;
|
||||
FBoomTranslator Boomish[MAX_BOOMISH];
|
||||
int NumBoomish;
|
||||
TAutoGrowArray<FSectorTrans> SectorTranslations;
|
||||
|
@ -74,7 +75,7 @@ struct SpecialArgs
|
|||
struct SpecialArg
|
||||
{
|
||||
int arg;
|
||||
ELineTransTagOp tagop;
|
||||
ELineTransArgOp argop;
|
||||
};
|
||||
|
||||
struct ListFilter
|
||||
|
@ -108,6 +109,7 @@ struct XlatParseContext : public FParseContext
|
|||
XlatParseContext(void *parser, ParseFunc parse, int *tt)
|
||||
: FParseContext(parser, parse, tt)
|
||||
{
|
||||
DefiningLineType = -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -152,6 +154,8 @@ struct XlatParseContext : public FParseContext
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int DefiningLineType;
|
||||
};
|
||||
|
||||
#include "xlat_parser.c"
|
||||
|
@ -166,6 +170,7 @@ struct XlatParseContext : public FParseContext
|
|||
void P_ClearTranslator()
|
||||
{
|
||||
SimpleLineTranslations.Clear();
|
||||
XlatExpressions.Clear();
|
||||
NumBoomish = 0;
|
||||
SectorTranslations.Clear();
|
||||
SectorMasks.Clear();
|
||||
|
|
|
@ -4,18 +4,13 @@
|
|||
#include "doomtype.h"
|
||||
#include "tarray.h"
|
||||
|
||||
enum ELineTransTagOp
|
||||
enum ELineTransArgOp
|
||||
{
|
||||
TAGOP_None,
|
||||
TAGOP_Add,
|
||||
TAGOP_Mul,
|
||||
TAGOP_Div,
|
||||
TAGOP_Mod,
|
||||
TAGOP_And,
|
||||
TAGOP_Or,
|
||||
TAGOP_Xor,
|
||||
ARGOP_Const,
|
||||
ARGOP_Tag,
|
||||
ARGOP_Expr,
|
||||
|
||||
TAGOP_NUMBITS = 3,
|
||||
TAGOP_NUMBITS = 2,
|
||||
TAGOP_MASK = (1 << TAGOP_NUMBITS) - 1
|
||||
};
|
||||
|
||||
|
@ -25,6 +20,23 @@ enum
|
|||
LINETRANS_TAGSHIFT = 30 - LINETRANS_MAXARGS * TAGOP_NUMBITS,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XEXP_Const,
|
||||
XEXP_Tag,
|
||||
XEXP_Add,
|
||||
XEXP_Sub,
|
||||
XEXP_Mul,
|
||||
XEXP_Div,
|
||||
XEXP_Mod,
|
||||
XEXP_And,
|
||||
XEXP_Or,
|
||||
XEXP_Xor,
|
||||
XEXP_Neg,
|
||||
|
||||
XEXP_COUNT
|
||||
};
|
||||
|
||||
struct FLineTrans
|
||||
{
|
||||
int special;
|
||||
|
@ -95,12 +107,21 @@ struct FLineFlagTrans
|
|||
bool ismask;
|
||||
};
|
||||
|
||||
struct FXlatExprState
|
||||
{
|
||||
int linetype;
|
||||
int tag;
|
||||
bool bIsConstant;
|
||||
};
|
||||
|
||||
|
||||
extern TAutoGrowArray<FLineTrans> SimpleLineTranslations;
|
||||
extern TArray<int> XlatExpressions;
|
||||
extern FBoomTranslator Boomish[MAX_BOOMISH];
|
||||
extern int NumBoomish;
|
||||
extern TAutoGrowArray<FSectorTrans> SectorTranslations;
|
||||
extern TArray<FSectorMask> SectorMasks;
|
||||
extern FLineFlagTrans LineFlagTranslations[16];
|
||||
extern const int* (*XlatExprEval[XEXP_COUNT])(int *dest, const int *xnode, FXlatExprState *state);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -89,84 +89,85 @@ single_enum ::= SYM(A) EQUALS exp(B).
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
linetype_declaration ::= exp(linetype) EQUALS exp(flags) COMMA exp(special) LPAREN special_args(arg) RPAREN.
|
||||
%type linetype_exp {int}
|
||||
linetype_exp(Z) ::= exp(A).
|
||||
{
|
||||
Z = static_cast<XlatParseContext *>(context)->DefiningLineType = A;
|
||||
}
|
||||
|
||||
linetype_declaration ::= linetype_exp(linetype) EQUALS exp(flags) COMMA exp(special) LPAREN special_args(arg) RPAREN.
|
||||
{
|
||||
SimpleLineTranslations.SetVal(linetype,
|
||||
FLineTrans(special&0xffff, flags+arg.addflags, arg.args[0], arg.args[1], arg.args[2], arg.args[3], arg.args[4]));
|
||||
static_cast<XlatParseContext *>(context)->DefiningLineType = -1;
|
||||
}
|
||||
|
||||
linetype_declaration ::= exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN.
|
||||
linetype_declaration ::= linetype_exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN.
|
||||
{
|
||||
Printf ("%s, line %d: %s is undefined\n", context->SourceFile, context->SourceLine, S.sym);
|
||||
static_cast<XlatParseContext *>(context)->DefiningLineType = -1;
|
||||
}
|
||||
|
||||
%type exp_with_tag {int}
|
||||
exp_with_tag(A) ::= NUM(B). { XlatExpressions.Push(B.val); A = XlatExpressions.Push(XEXP_Const); }
|
||||
exp_with_tag(A) ::= TAG. { A = XlatExpressions.Push(XEXP_Tag); }
|
||||
exp_with_tag(A) ::= exp_with_tag PLUS exp_with_tag. { A = XlatExpressions.Push(XEXP_Add); }
|
||||
exp_with_tag(A) ::= exp_with_tag MINUS exp_with_tag. { A = XlatExpressions.Push(XEXP_Sub); }
|
||||
exp_with_tag(A) ::= exp_with_tag MULTIPLY exp_with_tag. { A = XlatExpressions.Push(XEXP_Mul); }
|
||||
exp_with_tag(A) ::= exp_with_tag DIVIDE exp_with_tag. { A = XlatExpressions.Push(XEXP_Div); }
|
||||
exp_with_tag(A) ::= exp_with_tag MODULUS exp_with_tag. { A = XlatExpressions.Push(XEXP_Mod); }
|
||||
exp_with_tag(A) ::= exp_with_tag OR exp_with_tag. { A = XlatExpressions.Push(XEXP_Or); }
|
||||
exp_with_tag(A) ::= exp_with_tag AND exp_with_tag. { A = XlatExpressions.Push(XEXP_And); }
|
||||
exp_with_tag(A) ::= exp_with_tag XOR exp_with_tag. { A = XlatExpressions.Push(XEXP_Xor); }
|
||||
exp_with_tag(A) ::= MINUS exp_with_tag. [NEG] { A = XlatExpressions.Push(XEXP_Neg); }
|
||||
exp_with_tag(A) ::= LPAREN exp_with_tag(B) RPAREN. { A = B; }
|
||||
|
||||
|
||||
%type special_arg {SpecialArg}
|
||||
|
||||
special_arg(Z) ::= exp(A).
|
||||
special_arg(Z) ::= exp_with_tag(A).
|
||||
{
|
||||
Z.arg = A;
|
||||
Z.tagop = TAGOP_None;
|
||||
}
|
||||
special_arg(Z) ::= TAG.
|
||||
{
|
||||
Z.arg = 0;
|
||||
Z.tagop = TAGOP_Add;
|
||||
}
|
||||
special_arg(Z) ::= TAG PLUS exp(A).
|
||||
{
|
||||
Z.arg = A;
|
||||
Z.tagop = TAGOP_Add;
|
||||
}
|
||||
special_arg(Z) ::= TAG MINUS exp(A).
|
||||
{
|
||||
Z.arg = -A;
|
||||
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");
|
||||
if (XlatExpressions[A] == XEXP_Tag)
|
||||
{ // Store tags directly
|
||||
Z.arg = 0;
|
||||
Z.argop = ARGOP_Tag;
|
||||
XlatExpressions.Delete(A);
|
||||
}
|
||||
else
|
||||
{ // Try and evaluate it. If it's a constant, store it and erase the
|
||||
// expression. Otherwise, store the index to the expression. We make
|
||||
// no attempt to simplify non-constant expressions.
|
||||
FXlatExprState state;
|
||||
int val;
|
||||
const int *endpt;
|
||||
int *xnode;
|
||||
|
||||
state.linetype = static_cast<XlatParseContext *>(context)->DefiningLineType;
|
||||
state.tag = 0;
|
||||
state.bIsConstant = true;
|
||||
xnode = &XlatExpressions[A];
|
||||
endpt = XlatExprEval[*xnode](&val, xnode, &state);
|
||||
if (state.bIsConstant)
|
||||
{
|
||||
Z.arg = val;
|
||||
Z.argop = ARGOP_Const;
|
||||
endpt++;
|
||||
assert(endpt >= &XlatExpressions[0]);
|
||||
XlatExpressions.Resize((unsigned)(endpt - &XlatExpressions[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
Z.arg = A;
|
||||
Z.argop = ARGOP_Expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
special_arg(Z) ::= TAG MODULUS exp(A).
|
||||
{
|
||||
Z.arg = A;
|
||||
Z.tagop = TAGOP_Mod;
|
||||
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.tagop << LINETRANS_TAGSHIFT;
|
||||
Z.addflags = A.argop << LINETRANS_TAGSHIFT;
|
||||
Z.argcount = 1;
|
||||
Z.args[0] = A.arg;
|
||||
Z.args[1] = 0;
|
||||
|
@ -179,7 +180,7 @@ multi_special_arg(Z) ::= multi_special_arg(A) COMMA special_arg(B).
|
|||
Z = A;
|
||||
if (Z.argcount < LINETRANS_MAXARGS)
|
||||
{
|
||||
Z.addflags |= B.tagop << (LINETRANS_TAGSHIFT + Z.argcount * TAGOP_NUMBITS);
|
||||
Z.addflags |= B.argop << (LINETRANS_TAGSHIFT + Z.argcount * TAGOP_NUMBITS);
|
||||
Z.args[Z.argcount] = B.arg;
|
||||
Z.argcount++;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue