Add math opcodes
This commit is contained in:
parent
a39f149817
commit
ecc6a8679b
|
@ -3268,4 +3268,29 @@ bool ProgramValue::isEmpty()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Matches Sfall implementation.
|
||||||
|
bool ProgramValue::isInt()
|
||||||
|
{
|
||||||
|
return opcode == VALUE_TYPE_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches Sfall implementation.
|
||||||
|
bool ProgramValue::isFloat()
|
||||||
|
{
|
||||||
|
return opcode == VALUE_TYPE_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches Sfall implementation.
|
||||||
|
float ProgramValue::asFloat()
|
||||||
|
{
|
||||||
|
switch (opcode) {
|
||||||
|
case VALUE_TYPE_INT:
|
||||||
|
return static_cast<float>(integerValue);
|
||||||
|
case VALUE_TYPE_FLOAT:
|
||||||
|
return floatValue;
|
||||||
|
default:
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fallout
|
} // namespace fallout
|
||||||
|
|
|
@ -149,6 +149,9 @@ typedef struct ProgramValue {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isEmpty();
|
bool isEmpty();
|
||||||
|
bool isInt();
|
||||||
|
bool isFloat();
|
||||||
|
float asFloat();
|
||||||
} ProgramValue;
|
} ProgramValue;
|
||||||
|
|
||||||
typedef std::vector<ProgramValue> ProgramStack;
|
typedef std::vector<ProgramValue> ProgramStack;
|
||||||
|
|
|
@ -175,6 +175,25 @@ static void op_set_bodypart_hit_modifier(Program* program)
|
||||||
combat_set_hit_location_penalty(hit_location, penalty);
|
combat_set_hit_location_penalty(hit_location, penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sqrt
|
||||||
|
static void op_sqrt(Program* program)
|
||||||
|
{
|
||||||
|
ProgramValue programValue = programStackPopValue(program);
|
||||||
|
programStackPushFloat(program, sqrtf(programValue.asFloat()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// abs
|
||||||
|
static void op_abs(Program* program)
|
||||||
|
{
|
||||||
|
ProgramValue programValue = programStackPopValue(program);
|
||||||
|
|
||||||
|
if (programValue.isInt()) {
|
||||||
|
programStackPushInteger(program, abs(programValue.integerValue));
|
||||||
|
} else {
|
||||||
|
programStackPushFloat(program, abs(programValue.asFloat()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get_proto_data
|
// get_proto_data
|
||||||
static void op_get_proto_data(Program* program)
|
static void op_get_proto_data(Program* program)
|
||||||
{
|
{
|
||||||
|
@ -395,6 +414,13 @@ static void opParseInt(Program* program)
|
||||||
programStackPushInteger(program, static_cast<int>(strtol(string, nullptr, 0)));
|
programStackPushInteger(program, static_cast<int>(strtol(string, nullptr, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// atof
|
||||||
|
static void op_atof(Program* program)
|
||||||
|
{
|
||||||
|
const char* string = programStackPopString(program);
|
||||||
|
programStackPushFloat(program, static_cast<float>(atof(string)));
|
||||||
|
}
|
||||||
|
|
||||||
// strlen
|
// strlen
|
||||||
static void opGetStringLength(Program* program)
|
static void opGetStringLength(Program* program)
|
||||||
{
|
{
|
||||||
|
@ -402,6 +428,22 @@ static void opGetStringLength(Program* program)
|
||||||
programStackPushInteger(program, static_cast<int>(strlen(string)));
|
programStackPushInteger(program, static_cast<int>(strlen(string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pow (^)
|
||||||
|
static void op_power(Program* program)
|
||||||
|
{
|
||||||
|
ProgramValue expValue = programStackPopValue(program);
|
||||||
|
ProgramValue baseValue = programStackPopValue(program);
|
||||||
|
|
||||||
|
// CE: Implementation is slightly different, check.
|
||||||
|
float result = powf(baseValue.asFloat(), expValue.asFloat());
|
||||||
|
|
||||||
|
if (baseValue.isInt() && expValue.isInt()) {
|
||||||
|
programStackPushInteger(program, static_cast<int>(result));
|
||||||
|
} else {
|
||||||
|
programStackPushFloat(program, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// message_str_game
|
// message_str_game
|
||||||
static void opGetMessage(Program* program)
|
static void opGetMessage(Program* program)
|
||||||
{
|
{
|
||||||
|
@ -430,6 +472,28 @@ static void opArtExists(Program* program)
|
||||||
programStackPushInteger(program, artExists(fid));
|
programStackPushInteger(program, artExists(fid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// div (/)
|
||||||
|
static void op_div(Program* program)
|
||||||
|
{
|
||||||
|
ProgramValue divisorValue = programStackPopValue(program);
|
||||||
|
ProgramValue dividendValue = programStackPopValue(program);
|
||||||
|
|
||||||
|
if (divisorValue.integerValue == 0) {
|
||||||
|
debugPrint("Division by zero");
|
||||||
|
|
||||||
|
// TODO: Looks like execution is not halted in Sfall's div, check.
|
||||||
|
programStackPushInteger(program, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dividendValue.isFloat() || divisorValue.isFloat()) {
|
||||||
|
programStackPushFloat(program, dividendValue.asFloat() / divisorValue.asFloat());
|
||||||
|
} else {
|
||||||
|
// Unsigned divison.
|
||||||
|
programStackPushInteger(program, static_cast<unsigned int>(dividendValue.integerValue) / static_cast<unsigned int>(divisorValue.integerValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sfallOpcodesInit()
|
void sfallOpcodesInit()
|
||||||
{
|
{
|
||||||
interpreterRegisterOpcode(0x8156, opReadByte);
|
interpreterRegisterOpcode(0x8156, opReadByte);
|
||||||
|
@ -448,6 +512,8 @@ void sfallOpcodesInit()
|
||||||
interpreterRegisterOpcode(0x81B6, op_set_car_current_town);
|
interpreterRegisterOpcode(0x81B6, op_set_car_current_town);
|
||||||
interpreterRegisterOpcode(0x81DF, op_get_bodypart_hit_modifier);
|
interpreterRegisterOpcode(0x81DF, op_get_bodypart_hit_modifier);
|
||||||
interpreterRegisterOpcode(0x81E0, op_set_bodypart_hit_modifier);
|
interpreterRegisterOpcode(0x81E0, op_set_bodypart_hit_modifier);
|
||||||
|
interpreterRegisterOpcode(0x81EC, op_sqrt);
|
||||||
|
interpreterRegisterOpcode(0x81ED, op_abs);
|
||||||
interpreterRegisterOpcode(0x8204, op_get_proto_data);
|
interpreterRegisterOpcode(0x8204, op_get_proto_data);
|
||||||
interpreterRegisterOpcode(0x8205, op_set_proto_data);
|
interpreterRegisterOpcode(0x8205, op_set_proto_data);
|
||||||
interpreterRegisterOpcode(0x820D, opListBegin);
|
interpreterRegisterOpcode(0x820D, opListBegin);
|
||||||
|
@ -465,10 +531,13 @@ void sfallOpcodesInit()
|
||||||
interpreterRegisterOpcode(0x8220, opGetScreenWidth);
|
interpreterRegisterOpcode(0x8220, opGetScreenWidth);
|
||||||
interpreterRegisterOpcode(0x8221, opGetScreenHeight);
|
interpreterRegisterOpcode(0x8221, opGetScreenHeight);
|
||||||
interpreterRegisterOpcode(0x8237, opParseInt);
|
interpreterRegisterOpcode(0x8237, opParseInt);
|
||||||
|
interpreterRegisterOpcode(0x8238, op_atof);
|
||||||
interpreterRegisterOpcode(0x824F, opGetStringLength);
|
interpreterRegisterOpcode(0x824F, opGetStringLength);
|
||||||
|
interpreterRegisterOpcode(0x8263, op_power);
|
||||||
interpreterRegisterOpcode(0x826B, opGetMessage);
|
interpreterRegisterOpcode(0x826B, opGetMessage);
|
||||||
interpreterRegisterOpcode(0x8267, opRound);
|
interpreterRegisterOpcode(0x8267, opRound);
|
||||||
interpreterRegisterOpcode(0x8274, opArtExists);
|
interpreterRegisterOpcode(0x8274, opArtExists);
|
||||||
|
interpreterRegisterOpcode(0x827F, op_div);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfallOpcodesExit()
|
void sfallOpcodesExit()
|
||||||
|
|
Loading…
Reference in New Issue