[Scummvm-git-logs] scummvm master -> 1c394fb7fc49c9a894fb0091bcf1fb29573800b9

sev- sev at scummvm.org
Sat Jul 11 21:22:54 UTC 2020


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
1c394fb7fc DIRECTOR: Implement Director-specific PRNG and hook it to Lingo


Commit: 1c394fb7fc49c9a894fb0091bcf1fb29573800b9
    https://github.com/scummvm/scummvm/commit/1c394fb7fc49c9a894fb0091bcf1fb29573800b9
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2020-07-11T23:22:12+02:00

Commit Message:
DIRECTOR: Implement Director-specific PRNG and hook it to Lingo

Changed paths:
    engines/director/director.cpp
    engines/director/director.h
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/util.cpp
    engines/director/util.h


diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 6a2f51ea1c..58340a5eb9 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -45,8 +45,7 @@ uint32 wmMode = 0;
 
 DirectorEngine *g_director;
 
-DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc),
-		_rnd("director") {
+DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
 	DebugMan.addDebugChannel(kDebugLingoExec, "lingoexec", "Lingo Execution");
 	DebugMan.addDebugChannel(kDebugCompile, "compile", "Lingo Compilation");
 	DebugMan.addDebugChannel(kDebugParse, "parse", "Lingo code parsing");
diff --git a/engines/director/director.h b/engines/director/director.h
index e0d4035838..244179d613 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -23,7 +23,6 @@
 #ifndef DIRECTOR_DIRECTOR_H
 #define DIRECTOR_DIRECTOR_H
 
-#include "common/random.h"
 #include "common/rect.h"
 #include "common/str-array.h"
 
@@ -31,6 +30,7 @@
 #include "engines/engine.h"
 
 #include "director/types.h"
+#include "director/util.h"
 
 namespace Common {
 class MacResManager;
@@ -191,7 +191,7 @@ public:
 	void waitForClick();
 
 public:
-	Common::RandomSource _rnd;
+	RandomState _rnd;
 	Graphics::ManagedSurface *_surface;
 	Graphics::MacWindowManager *_wm;
 
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index fd9930ee1a..5118b0350d 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -396,7 +396,7 @@ void LB::b_power(int nargs) {
 
 void LB::b_random(int nargs) {
 	Datum max = g_lingo->pop();
-	Datum res((int)(g_lingo->_vm->_rnd.getRandomNumber(max.asInt() - 1) + 1));
+	Datum res((int)(g_director->_rnd.getRandom(max.asInt()) + 1));
 	g_lingo->push(res);
 }
 
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 0663dba1ac..274f79899b 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -656,7 +656,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		d.u.i = 1;
 		break;
 	case kTheRandomSeed:
-		getTheEntitySTUB(kTheRandomSeed);
+		d.type = INT;
+		d.u.i = g_director->_rnd.getSeed();
 		break;
 	case kTheResult:
 		getTheEntitySTUB(kTheResult);
@@ -904,7 +905,7 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		setTheEntitySTUB(kThePreLoadRAM);
 		break;
 	case kTheRandomSeed:
-		setTheEntitySTUB(kTheRandomSeed);
+		g_director->_rnd.setSeed(d.asInt());
 		break;
 	case kTheRomanLingo:
 		setTheEntitySTUB(kTheRomanLingo);
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index adda30cd47..84b28d79ca 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -537,5 +537,61 @@ Common::String dumpScriptName(const char *prefix, int type, int id, const char *
 	return Common::String::format("./dumps/%s-%s-%d.%s", prefix, typeName.c_str(), id, ext);
 }
 
+void RandomState::setSeed(int seed) {
+	init(32);
+
+	_seed = seed ? seed : 1;
+}
+
+int32 RandomState::getRandom(int32 range) {
+	int32 res;
+
+	if (_seed == 0)
+		init(32);
+
+	res = perlin(genNextRandom() * 71);
+
+	if (range > 0)
+		res = ((res & 0x7fffffff) % range);
+
+	return res;
+}
+
+static const uint32 masks[31] = {
+	0x00000003, 0x00000006, 0x0000000c, 0x00000014, 0x00000030, 0x00000060, 0x000000b8, 0x00000110,
+	0x00000240, 0x00000500, 0x00000ca0, 0x00001b00, 0x00003500, 0x00006000, 0x0000b400, 0x00012000,
+	0x00020400, 0x00072000, 0x00090000, 0x00140000, 0x00300000, 0x00400000, 0x00d80000, 0x01200000,
+	0x03880000, 0x07200000, 0x09000000, 0x14000000, 0x32800000, 0x48000000, 0xa3000000
+};
+
+void RandomState::init(int len) {
+	if (len < 2 || len > 32)
+		len = 32;
+
+	_seed = 1;
+	_len = (1 << len) - 1;
+	_mask = masks[len - 2];
+}
+
+int32 RandomState::genNextRandom() {
+	if (_seed & 1)
+		_seed = (_seed >> 1) ^ _mask;
+	else
+		_seed >>= 1;
+
+	return _seed;
+}
+
+int32 RandomState::perlin(int32 val) {
+	int32 res;
+
+	val = ((val << 13) ^ val) - (val >> 21);
+
+	res = (val * (val * val * 15731 + 789221) + 1376312589) & 0x7fffffff;
+	res += val;
+	res = ((res << 13) ^ res) - (res >> 21);
+
+	return res;
+}
 
 } // End of namespace Director
diff --git a/engines/director/util.h b/engines/director/util.h
index 9baacd3c15..038533d17c 100644
--- a/engines/director/util.h
+++ b/engines/director/util.h
@@ -48,6 +48,26 @@ Common::String dumpScriptName(const char *prefix, int type, int id, const char *
 
 bool processQuitEvent(bool click = false); // events.cpp
 
+class RandomState {
+public:
+    uint32 _seed;
+    uint32 _mask;
+    uint32 _len;
+
+    RandomState() {
+        _seed = _mask = _len = 0;
+    }
+
+    void setSeed(int seed);
+    uint32 getSeed() { return _seed; }
+    int32 getRandom(int32 range);
+
+private:
+    void init(int len);
+    int32 genNextRandom();
+    int32 perlin(int32 val);
+};
+
 } // End of namespace Director
 
 #endif




More information about the Scummvm-git-logs mailing list