mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-02 17:03:13 +00:00
FREESCAPE: refactored conditional handling to make it work with castle
This commit is contained in:
parent
fc0b1480c1
commit
c4a0d162fb
@ -281,6 +281,7 @@ public:
|
||||
void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
|
||||
|
||||
// Instructions
|
||||
bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
|
||||
bool checkIfGreaterOrEqual(FCLInstruction &instruction);
|
||||
void executeIncrementVariable(FCLInstruction &instruction);
|
||||
void executeDecrementVariable(FCLInstruction &instruction);
|
||||
|
@ -33,7 +33,7 @@ uint8 k8bitMaxVariable = 64;
|
||||
uint8 k8bitMaxShield = 64;
|
||||
uint8 k8bitMaxEnergy = 64;
|
||||
|
||||
Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool enableActivated) {
|
||||
Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool multipleConditionals) {
|
||||
Common::String detokenisedStream;
|
||||
Common::Array<uint8>::size_type bytePointer = 0;
|
||||
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
|
||||
@ -56,28 +56,30 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
|
||||
|
||||
if (sizeOfTokenisedContent > 0)
|
||||
detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
|
||||
Token::Type newConditional = Token::UNKNOWN;
|
||||
Token::Type oldConditional = Token::UNKNOWN;
|
||||
uint16 newConditional = 0;
|
||||
uint16 oldConditional = 0;
|
||||
|
||||
while (bytePointer < sizeOfTokenisedContent) {
|
||||
// get the conditional type of the next operation
|
||||
uint8 conditionalByte = tokenisedCondition[bytePointer];
|
||||
uint8 conditionalByte = tokenisedCondition[bytePointer] & 0xc0;
|
||||
//detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", conditionalByte);
|
||||
newConditional = 0;
|
||||
|
||||
if ((conditionalByte & 0xc0) && enableActivated) {
|
||||
newConditional = Token::ACTIVATEDQ;
|
||||
} else if (conditionalByte & 0x80)
|
||||
newConditional = Token::SHOTQ;
|
||||
else if (conditionalByte & 0x40)
|
||||
newConditional = Token::TIMERQ;
|
||||
if (conditionalByte == 0x40)
|
||||
newConditional = kConditionalTimeout;
|
||||
else if (conditionalByte == 0x80)
|
||||
newConditional = kConditionalShot;
|
||||
else if (conditionalByte == 0xc0)
|
||||
newConditional = kConditionalActivated;
|
||||
else
|
||||
newConditional = Token::COLLIDEDQ;
|
||||
newConditional = kConditionalCollided;
|
||||
|
||||
// if the conditional type has changed then end the old conditional,
|
||||
// if we were in one, and begin a new one
|
||||
if (bytePointer == 0 || newConditional != oldConditional) {
|
||||
oldConditional = newConditional;
|
||||
FCLInstruction branch;
|
||||
branch = FCLInstruction(oldConditional);
|
||||
branch = FCLInstruction(Token::CONDITIONAL);
|
||||
|
||||
if (bytePointer > 0) {
|
||||
detokenisedStream += "ENDIF\n";
|
||||
@ -86,18 +88,23 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
|
||||
}
|
||||
|
||||
branch.setBranches(conditionalInstructions, nullptr);
|
||||
branch.setSource(oldConditional); // conditional flag
|
||||
instructions.push_back(branch);
|
||||
|
||||
if (oldConditional == Token::SHOTQ)
|
||||
detokenisedStream += "IF SHOT? THEN\n";
|
||||
else if (oldConditional == Token::TIMERQ)
|
||||
detokenisedStream += "IF TIMER? THEN\n";
|
||||
else if (oldConditional == Token::COLLIDEDQ)
|
||||
detokenisedStream += "IF COLLIDED? THEN\n";
|
||||
else if (oldConditional == Token::ACTIVATEDQ)
|
||||
detokenisedStream += "IF ACTIVATED? THEN\n";
|
||||
detokenisedStream += "IF ";
|
||||
|
||||
if (oldConditional & kConditionalShot)
|
||||
detokenisedStream += "SHOT? ";
|
||||
else if (oldConditional & kConditionalTimeout)
|
||||
detokenisedStream += "TIMER? ";
|
||||
else if (oldConditional & kConditionalCollided)
|
||||
detokenisedStream += "COLLIDED? ";
|
||||
else if (oldConditional & kConditionalActivated)
|
||||
detokenisedStream += "ACTIVATED? ";
|
||||
else
|
||||
error("Invalid conditional: %x", oldConditional);
|
||||
|
||||
detokenisedStream += "THEN\n";
|
||||
}
|
||||
|
||||
// get the actual operation
|
||||
|
@ -36,6 +36,13 @@ enum {
|
||||
k8bitVariableEnergyDrillerJet = 57
|
||||
};
|
||||
|
||||
enum {
|
||||
kConditionalShot = 1 << 0,
|
||||
kConditionalTimeout = 1 << 1,
|
||||
kConditionalCollided = 1 << 2,
|
||||
kConditionalActivated = 1 << 3,
|
||||
};
|
||||
|
||||
extern uint8 k8bitMaxVariable;
|
||||
extern uint8 k8bitMaxShield;
|
||||
extern uint8 k8bitMaxEnergy;
|
||||
|
@ -148,31 +148,13 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
|
||||
debugC(1, kFreescapeDebugCode, "Executing NOP at ip: %d", ip);
|
||||
break;
|
||||
|
||||
case Token::ACTIVATEDQ:
|
||||
if (shot) // TODO: implement interaction
|
||||
case Token::CONDITIONAL:
|
||||
if (checkConditional(instruction, shot, collided, timer, false)) // TODO: implement interaction
|
||||
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||
// else branch is always empty
|
||||
assert(instruction._elseInstructions == nullptr);
|
||||
break;
|
||||
|
||||
case Token::COLLIDEDQ:
|
||||
if (collided)
|
||||
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||
// else branch is always empty
|
||||
assert(instruction._elseInstructions == nullptr);
|
||||
break;
|
||||
case Token::SHOTQ:
|
||||
if (shot)
|
||||
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||
// else branch is always empty
|
||||
assert(instruction._elseInstructions == nullptr);
|
||||
break;
|
||||
case Token::TIMERQ:
|
||||
if (timer)
|
||||
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||
// else branch is always empty
|
||||
assert(instruction._elseInstructions == nullptr);
|
||||
break;
|
||||
case Token::VARNOTEQ:
|
||||
if (executeEndIfNotEqual(instruction))
|
||||
ip = codeSize;
|
||||
@ -355,6 +337,23 @@ bool FreescapeEngine::executeEndIfVisibilityIsEqual(FCLInstruction &instruction)
|
||||
return (obj->isInvisible() == (value != 0));
|
||||
}
|
||||
|
||||
bool FreescapeEngine::checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated) {
|
||||
uint16 conditional = instruction._source;
|
||||
bool result = false;
|
||||
|
||||
if (conditional & kConditionalShot)
|
||||
result |= shot;
|
||||
if (conditional & kConditionalTimeout)
|
||||
result |= timer;
|
||||
if (conditional & kConditionalCollided)
|
||||
result |= collided;
|
||||
if (conditional & kConditionalActivated)
|
||||
result |= activated;
|
||||
|
||||
debugC(1, kFreescapeDebugCode, "Check if conditional %x is true: %d!", conditional, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FreescapeEngine::checkIfGreaterOrEqual(FCLInstruction &instruction) {
|
||||
uint16 variable = instruction._source;
|
||||
uint16 value = instruction._destination;
|
||||
|
@ -30,12 +30,11 @@ namespace Freescape {
|
||||
struct Token {
|
||||
public:
|
||||
enum Type {
|
||||
ACTIVATEDQ,
|
||||
ADDVAR,
|
||||
AGAIN,
|
||||
AND,
|
||||
ANDV,
|
||||
COLLIDEDQ,
|
||||
CONDITIONAL,
|
||||
DELAY,
|
||||
DESTROY,
|
||||
DESTROYEDQ,
|
||||
@ -67,7 +66,6 @@ public:
|
||||
SCREEN,
|
||||
SOUND,
|
||||
SETVAR,
|
||||
SHOTQ,
|
||||
START,
|
||||
STARTANIM,
|
||||
STOPANIM,
|
||||
@ -75,7 +73,6 @@ public:
|
||||
SUBVAR,
|
||||
SYNCSND,
|
||||
THEN,
|
||||
TIMERQ,
|
||||
TOGVIS,
|
||||
TRIGANIM,
|
||||
UPDATEI,
|
||||
|
Loading…
x
Reference in New Issue
Block a user