Merge remote-tracking branch 'gzdoom/master'

This commit is contained in:
Rachael Alexanderson 2018-01-06 18:00:45 -05:00
commit ed4079c480
4 changed files with 78 additions and 25 deletions

View file

@ -644,7 +644,7 @@ inline int PitchToACS(DAngle ang)
struct CallReturn
{
CallReturn(int pc, ScriptFunction *func, FBehavior *module, int32_t *locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway)
CallReturn(int pc, ScriptFunction *func, FBehavior *module, const ACSLocalVariables &locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway)
: ReturnFunction(func),
ReturnModule(module),
ReturnLocals(locals),
@ -656,7 +656,7 @@ struct CallReturn
ScriptFunction *ReturnFunction;
FBehavior *ReturnModule;
int32_t *ReturnLocals;
ACSLocalVariables ReturnLocals;
ACSLocalArrays *ReturnArrays;
int ReturnAddress;
int bDiscardResult;
@ -761,6 +761,35 @@ protected:
private:
DLevelScript();
int getbyte(int *&pc)
{
CheckInstructionPointer(pc);
int res = *(uint8_t *)pc;
pc = (int *)((uint8_t *)pc+1);
return res;
}
int getshort(int *&pc)
{
CheckInstructionPointer(pc);
int res = LittleShort( *(int16_t *)pc);
pc = (int *)((uint8_t *)pc+2);
return res;
}
void CheckInstructionPointer(int *pc) const
{
const uint32_t offset = activeBehavior->PC2Ofs(pc);
const uint32_t size = activeBehavior->GetDataSize();
if (offset >= size)
{
I_Error("Out of bounds instruction pointer in ACS VM");
}
}
friend class DACSThinker;
};
@ -6896,7 +6925,7 @@ enum
};
#define NEXTWORD (LittleLong(*pc++))
#define NEXTWORD (CheckInstructionPointer(pc), LittleLong(*pc++))
#define NEXTBYTE (fmt==ACS_LittleEnhanced?getbyte(pc):NEXTWORD)
#define NEXTSHORT (fmt==ACS_LittleEnhanced?getshort(pc):NEXTWORD)
#define STACK(a) (Stack[sp - (a)])
@ -6904,20 +6933,6 @@ enum
// Direct instructions that take strings need to have the tag applied.
#define TAGSTR(a) (a|activeBehavior->GetLibraryID())
inline int getbyte (int *&pc)
{
int res = *(uint8_t *)pc;
pc = (int *)((uint8_t *)pc+1);
return res;
}
inline int getshort (int *&pc)
{
int res = LittleShort( *(int16_t *)pc);
pc = (int *)((uint8_t *)pc+2);
return res;
}
static bool CharArrayParms(int &capacity, int &offset, int &a, FACSStackMemory& Stack, int &sp, bool ranged)
{
if (ranged)
@ -6967,7 +6982,7 @@ static void SetMarineSprite(AActor *marine, PClassActor *source)
int DLevelScript::RunScript ()
{
DACSThinker *controller = DACSThinker::ActiveThinker;
int32_t *locals = &Localvars[0];
ACSLocalVariables locals(Localvars);
ACSLocalArrays noarrays;
ACSLocalArrays *localarrays = &noarrays;
ScriptFunction *activeFunction = NULL;
@ -7335,7 +7350,6 @@ int DLevelScript::RunScript ()
int i;
ScriptFunction *func;
FBehavior *module;
int32_t *mylocals;
if(pcd == PCD_CALLSTACK)
{
@ -7364,9 +7378,9 @@ int DLevelScript::RunScript ()
state = SCRIPT_PleaseRemove;
break;
}
mylocals = locals;
const ACSLocalVariables mylocals = locals;
// The function's first argument is also its first local variable.
locals = &Stack[sp - func->ArgCount];
locals.Reset(&Stack[sp - func->ArgCount], func->ArgCount + func->LocalCount);
// Make space on the stack for any other variables the function uses.
for (i = 0; i < func->LocalCount; ++i)
{
@ -7405,7 +7419,7 @@ int DLevelScript::RunScript ()
sp -= sizeof(CallReturn)/sizeof(int);
retsp = &Stack[sp];
activeBehavior->GetFunctionProfileData(activeFunction)->AddRun(runaway - ret->EntryInstrCount);
sp = int(locals - &Stack[0]);
sp = int(locals.GetPointer() - &Stack[0]);
pc = ret->ReturnModule->Ofs2PC(ret->ReturnAddress);
activeFunction = ret->ReturnFunction;
activeBehavior = ret->ReturnModule;

View file

@ -147,6 +147,44 @@ struct ProfileCollector
int Index;
};
class ACSLocalVariables
{
public:
ACSLocalVariables(TArray<int32_t> &variables)
: memory(&variables[0])
, count(variables.Size())
{
}
void Reset(int32_t *const memory, const size_t count)
{
// TODO: pointer sanity check?
// TODO: constraints on count?
this->memory = memory;
this->count = count;
}
int32_t& operator[](const size_t index)
{
if (index >= count)
{
I_Error("Out of bounds access to local variables in ACS VM");
}
return memory[index];
}
const int32_t *GetPointer() const
{
return memory;
}
private:
int32_t *memory;
size_t count;
};
struct ACSLocalArrayInfo
{
unsigned int Size;
@ -173,7 +211,7 @@ struct ACSLocalArrays
}
// Bounds-checking Set and Get for local arrays
void Set(int *locals, int arraynum, int arrayentry, int value)
void Set(ACSLocalVariables &locals, int arraynum, int arrayentry, int value)
{
if ((unsigned int)arraynum < Count &&
(unsigned int)arrayentry < Info[arraynum].Size)
@ -181,7 +219,7 @@ struct ACSLocalArrays
locals[Info[arraynum].Offset + arrayentry] = value;
}
}
int Get(int *locals, int arraynum, int arrayentry)
int Get(ACSLocalVariables &locals, int arraynum, int arrayentry)
{
if ((unsigned int)arraynum < Count &&
(unsigned int)arrayentry < Info[arraynum].Size)

View file

@ -1044,7 +1044,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
player->SetLogNumber(reply->LogNumber);
}
if (replyText != NULL && isconsole)
if (nullptr != replyText && '\0' != replyText[0] && isconsole)
{
TerminalResponse(replyText);
}

View file

@ -168,6 +168,7 @@ class RandomSpawner : Actor
newmobj.SpawnFlags = SpawnFlags & ~MTF_SECRET; // MTF_SECRET needs special treatment to avoid incrementing the secret counter twice. It had already been processed for the spawner itself.
newmobj.HandleSpawnFlags();
newmobj.SpawnFlags = SpawnFlags;
newmobj.bCountSecret = SpawnFlags & MTF_SECRET; // "Transfer" count secret flag to spawned actor
newmobj.ChangeTid(tid);
newmobj.Vel = Vel;
newmobj.master = master; // For things such as DamageMaster/DamageChildren, transfer mastery.