diff options
Diffstat (limited to 'engines/sci/engine/kmath.cpp')
-rw-r--r-- | engines/sci/engine/kmath.cpp | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index dbf317860f..f3769b653b 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -29,16 +29,40 @@ namespace Sci { reg_t kRandom(EngineState *s, int argc, reg_t *argv) { - int fromNumber = argv[0].toUint16(); - int toNumber = argv[1].toUint16(); - double randomNumber = fromNumber + ((toNumber + 1.0 - fromNumber) * (rand() / (RAND_MAX + 1.0))); - return make_reg(0, (int)randomNumber); + switch (argc) { + case 1: // set seed to argv[0] + // SCI0/SCI01 just reset the seed to 0 instead of using argv[0] at all + return NULL_REG; + + case 2: { // get random number + int fromNumber = argv[0].toUint16(); + int toNumber = argv[1].toUint16(); + + // TODO/CHECKME: It is propbably not required to check whether + // toNumber is greater than fromNumber, at least not when one + // goes by their names, but let us be on the safe side and + // allow toNumber to be smaller than fromNumber too. + if (fromNumber > toNumber) + SWAP(fromNumber, toNumber); + + const uint diff = (uint)(toNumber - fromNumber); + + const int randomNumber = fromNumber + (int)g_sci->getRNG().getRandomNumber(diff); + return make_reg(0, randomNumber); + } + + case 3: // get seed + // SCI0/01 did not support this at all + // Actually we would have to return the previous seed + error("kRandom: scripts asked for previous seed"); + break; + + default: + error("kRandom: unsupported argc"); + } } reg_t kAbs(EngineState *s, int argc, reg_t *argv) { - // This is a hack, but so is the code in Hoyle1 that needs it. - if (argv[0].segment) - return make_reg(0, 0x3e9); // Yes people, this is an object return make_reg(0, abs(argv[0].toSint16())); } @@ -112,7 +136,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) { double cosval = cos(angle * PI / 180.0); if ((cosval < 0.0001) && (cosval > -0.0001)) { - warning("kCosDiv: Attempted division by zero"); + error("kCosDiv: Attempted division by zero"); return SIGNAL_REG; } else return make_reg(0, (int16)(value / cosval)); @@ -124,7 +148,7 @@ reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) { double sinval = sin(angle * PI / 180.0); if ((sinval < 0.0001) && (sinval > -0.0001)) { - warning("kSinDiv: Attempted division by zero"); + error("kSinDiv: Attempted division by zero"); return SIGNAL_REG; } else return make_reg(0, (int16)(value / sinval)); @@ -136,7 +160,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) { param -= 90; if ((param % 90) == 0) { - warning("kTimesTan: Attempted tan(pi/2)"); + error("kTimesTan: Attempted tan(pi/2)"); return SIGNAL_REG; } else return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale)); @@ -147,10 +171,28 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) { int scale = (argc > 1) ? argv[1].toSint16() : 1; if ((param % 90) == 0) { - warning("kTimesCot: Attempted tan(pi/2)"); + error("kTimesCot: Attempted tan(pi/2)"); return SIGNAL_REG; } else return make_reg(0, (int16)(tan(param * PI / 180.0) * scale)); } +#ifdef ENABLE_SCI32 + +reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { + int16 multiplicant = argv[0].toSint16(); + int16 multiplier = argv[1].toSint16(); + int16 denominator = argv[2].toSint16(); + + // Sanity check... + if (!denominator) { + error("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); + return NULL_REG; + } + + return make_reg(0, multiplicant * multiplier / denominator); +} + +#endif + } // End of namespace Sci |