aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/cdda.h4
-rw-r--r--engines/scumm/detection.cpp3
-rw-r--r--engines/scumm/he/intern_he.h5
-rw-r--r--engines/scumm/he/logic/moonbase_logic.cpp311
-rw-r--r--engines/scumm/he/moonbase/moonbase.cpp9
-rw-r--r--engines/scumm/he/moonbase/moonbase.h4
-rw-r--r--engines/scumm/he/moonbase/net_defines.h66
-rw-r--r--engines/scumm/he/moonbase/net_main.cpp199
-rw-r--r--engines/scumm/he/moonbase/net_main.h89
-rw-r--r--engines/scumm/he/script_v72he.cpp37
-rw-r--r--engines/scumm/module.mk5
-rw-r--r--engines/scumm/object.cpp10
-rw-r--r--engines/scumm/players/player_pce.cpp1
-rw-r--r--engines/scumm/script_v6.cpp11
-rw-r--r--engines/scumm/scumm.cpp24
15 files changed, 774 insertions, 4 deletions
diff --git a/engines/scumm/cdda.h b/engines/scumm/cdda.h
index c1e6e82c9e..6ecbfbb313 100644
--- a/engines/scumm/cdda.h
+++ b/engines/scumm/cdda.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 4c9d1221aa..e6740df482 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -974,7 +974,8 @@ bool ScummMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
- (f == kSavesSupportPlayTime);
+ (f == kSavesSupportPlayTime) ||
+ (f == kSimpleSavesNames);
}
bool ScummEngine::hasFeature(EngineFeature f) const {
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index c6abac3ecc..bd3cdb2c57 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -56,9 +56,11 @@ public:
Common::Rect _actorClipOverride; // HE specific
int _heTimers[16];
+ uint32 _pauseStartTime;
int getHETimer(int timer);
void setHETimer(int timer);
+ void pauseHETimers(bool pause);
public:
ScummEngine_v60he(OSystem *syst, const DetectorResult &dr);
@@ -94,6 +96,7 @@ protected:
Common::WriteStream *openSaveFileForAppending(const byte *fileName);
void deleteSaveFile(const byte *fileName);
void renameSaveFile(const byte *from, const byte *to);
+ void pauseEngineIntern(bool pause);
Common::SeekableReadStream *openSaveFileForReading(int slot, bool compat, Common::String &fileName);
Common::WriteStream *openSaveFileForWriting(int slot, bool compat, Common::String &fileName);
@@ -288,6 +291,8 @@ public:
virtual byte *getStringAddress(ResId idx);
virtual int setupStringArray(int size);
+ virtual int setupStringArrayFromString(const char *cStr);
+ virtual void getStringFromArray(int arrayNumber, char *buffer, int maxLength);
protected:
virtual void setupOpcodes();
diff --git a/engines/scumm/he/logic/moonbase_logic.cpp b/engines/scumm/he/logic/moonbase_logic.cpp
index 1b596fc54c..c504ad4fe8 100644
--- a/engines/scumm/he/logic/moonbase_logic.cpp
+++ b/engines/scumm/he/logic/moonbase_logic.cpp
@@ -24,6 +24,10 @@
#include "scumm/he/logic_he.h"
#include "scumm/he/moonbase/moonbase.h"
#include "scumm/he/moonbase/ai_main.h"
+#ifdef USE_SDL_NET
+#include "scumm/he/moonbase/net_main.h"
+#include "scumm/he/moonbase/net_defines.h"
+#endif
namespace Scumm {
@@ -54,6 +58,45 @@ private:
void op_ai_set_type(int op, int numArgs, int32 *args);
void op_ai_clean_up(int op, int numArgs, int32 *args);
+#ifdef USE_SDL_NET
+ void op_net_remote_start_script(int op, int numArgs, int32 *args);
+ void op_net_remote_send_array(int op, int numArgs, int32 *args);
+ int op_net_remote_start_function(int op, int numArgs, int32 *args);
+ int op_net_do_init_all(int op, int numArgs, int32 *args);
+ int op_net_do_init_provider(int op, int numArgs, int32 *args);
+ int op_net_do_init_session(int op, int numArgs, int32 *args);
+ int op_net_do_init_user(int op, int numArgs, int32 *args);
+ int op_net_query_providers(int op, int numArgs, int32 *args);
+ int op_net_get_provider_name(int op, int numArgs, int32 *args);
+ int op_net_set_provider(int op, int numArgs, int32 *args);
+ int op_net_close_provider(int op, int numArgs, int32 *args);
+ int op_net_start_query_sessions(int op, int numArgs, int32 *args);
+ int op_net_update_query_sessions(int op, int numArgs, int32 *args);
+ int op_net_stop_query_sessions(int op, int numArgs, int32 *args);
+ int op_net_query_sessions(int op, int numArgs, int32 *args);
+ int op_net_get_session_name(int op, int numArgs, int32 *args);
+ int op_net_get_session_player_count(int op, int numArgs, int32 *args);
+ int op_net_destroy_player(int op, int numArgs, int32 *args);
+ int op_net_get_player_long_name(int op, int numArgs, int32 *args);
+ int op_net_get_player_short_name(int op, int numArgs, int32 *args);
+ int op_net_create_session(int op, int numArgs, int32 *args);
+ int op_net_join_session(int op, int numArgs, int32 *args);
+ int op_net_end_session(int op, int numArgs, int32 *args);
+ int op_net_disable_session_player_join(int op, int numArgs, int32 *args);
+ int op_net_enable_session_player_join(int op, int numArgs, int32 *args);
+ int op_net_set_ai_player_count(int op, int numArgs, int32 *args);
+ int op_net_add_user(int op, int numArgs, int32 *args);
+ int op_net_remove_user(int op, int numArgs, int32 *args);
+ int op_net_who_sent_this(int op, int numArgs, int32 *args);
+ int op_net_who_am_i(int op, int numArgs, int32 *args);
+ int op_net_set_provider_by_name(int op, int numArgs, int32 *args);
+ void op_net_set_fake_latency(int op, int numArgs, int32 *args);
+ int op_net_get_host_name(int op, int numArgs, int32 *args);
+ int op_net_get_ip_from_name(int op, int numArgs, int32 *args);
+ int op_net_host_tcpip_game(int op, int numArgs, int32 *args);
+ int op_net_join_tcpip_game(int op, int numArgs, int32 *args);
+#endif
+
private:
ScummEngine_v100he *_vm1;
};
@@ -107,6 +150,7 @@ int LogicHEmoonbase::versionID() {
#define OP_NET_HOST_TCPIP_GAME 1517
#define OP_NET_JOIN_TCPIP_GAME 1518
#define OP_NET_SET_FAKE_LAG 1555
+#define OP_NET_SET_FAKE_LATENCY 1555 /* SET_FAKE_LAG is a valid alias for backwards compatibility */
#define OP_NET_GET_HOST_NAME 1556
#define OP_NET_GET_IP_FROM_NAME 1557
#define OP_NET_GET_SESSION_PLAYER_COUNT 1558
@@ -157,6 +201,86 @@ int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) {
op_ai_clean_up(op, numArgs, args);
break;
+#ifdef USE_SDL_NET
+ case OP_NET_REMOTE_START_SCRIPT:
+ op_net_remote_start_script(op, numArgs, args);
+ break;
+ case OP_NET_REMOTE_SEND_ARRAY:
+ op_net_remote_send_array(op, numArgs, args);
+ break;
+ case OP_NET_REMOTE_START_FUNCTION:
+ return op_net_remote_start_function(op, numArgs, args);
+ case OP_NET_DO_INIT_ALL:
+ return op_net_do_init_all(op, numArgs, args);
+ case OP_NET_DO_INIT_PROVIDER:
+ return op_net_do_init_provider(op, numArgs, args);
+ case OP_NET_DO_INIT_SESSION:
+ return op_net_do_init_session(op, numArgs, args);
+ case OP_NET_DO_INIT_USER:
+ return op_net_do_init_user(op, numArgs, args);
+ case OP_NET_QUERY_PROVIDERS:
+ return op_net_query_providers(op, numArgs, args);
+ case OP_NET_GET_PROVIDER_NAME:
+ return op_net_get_provider_name(op, numArgs, args);
+ case OP_NET_SET_PROVIDER:
+ return op_net_set_provider(op, numArgs, args);
+ case OP_NET_CLOSE_PROVIDER:
+ return op_net_close_provider(op, numArgs, args);
+ case OP_NET_START_QUERY_SESSIONS:
+ return op_net_start_query_sessions(op, numArgs, args);
+ case OP_NET_UPDATE_QUERY_SESSIONS:
+ return op_net_update_query_sessions(op, numArgs, args);
+ case OP_NET_STOP_QUERY_SESSIONS:
+ return op_net_stop_query_sessions(op, numArgs, args);
+ case OP_NET_QUERY_SESSIONS:
+ return op_net_query_sessions(op, numArgs, args);
+ case OP_NET_GET_SESSION_NAME:
+ return op_net_get_session_name(op, numArgs, args);
+ case OP_NET_GET_SESSION_PLAYER_COUNT:
+ return op_net_get_session_player_count(op, numArgs, args);
+ case OP_NET_DESTROY_PLAYER:
+ return op_net_destroy_player(op, numArgs, args);
+#if 1 // 12/2/99 BPT
+ case OP_NET_GET_PLAYER_LONG_NAME:
+ return op_net_get_player_long_name(op, numArgs, args);
+ case OP_NET_GET_PLAYER_SHORT_NAME:
+ return op_net_get_player_short_name(op, numArgs, args);
+#endif
+ case OP_NET_CREATE_SESSION:
+ return op_net_create_session(op, numArgs, args);
+ case OP_NET_JOIN_SESSION:
+ return op_net_join_session(op, numArgs, args);
+ case OP_NET_END_SESSION:
+ return op_net_end_session(op, numArgs, args);
+ case OP_NET_DISABLE_SESSION_PLAYER_JOIN:
+ return op_net_disable_session_player_join(op, numArgs, args);
+ case OP_NET_ENABLE_SESSION_PLAYER_JOIN:
+ return op_net_enable_session_player_join(op, numArgs, args);
+ case OP_NET_SET_AI_PLAYER_COUNT:
+ return op_net_set_ai_player_count(op, numArgs, args);
+ case OP_NET_ADD_USER:
+ return op_net_add_user(op, numArgs, args);
+ case OP_NET_REMOVE_USER:
+ return op_net_remove_user(op, numArgs, args);
+ case OP_NET_WHO_SENT_THIS:
+ return op_net_who_sent_this(op, numArgs, args);
+ case OP_NET_WHO_AM_I:
+ return op_net_who_am_i(op, numArgs, args);
+ case OP_NET_SET_PROVIDER_BY_NAME:
+ return op_net_set_provider_by_name(op, numArgs, args);
+ case OP_NET_SET_FAKE_LATENCY: // SET_FAKE_LAG is a valid alias for backwards compatibility
+ op_net_set_fake_latency(op, numArgs, args);
+ break;
+ case OP_NET_GET_HOST_NAME:
+ return op_net_get_host_name(op, numArgs, args);
+ case OP_NET_GET_IP_FROM_NAME:
+ return op_net_get_ip_from_name(op, numArgs, args);
+ case OP_NET_HOST_TCPIP_GAME:
+ return op_net_host_tcpip_game(op, numArgs, args);
+ case OP_NET_JOIN_TCPIP_GAME:
+ return op_net_join_tcpip_game(op, numArgs, args);
+#endif
+
default:
LogicHE::dispatch(op, numArgs, args);
}
@@ -248,6 +372,193 @@ void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) {
_vm1->_moonbase->_ai->cleanUpAI();
}
+#ifdef USE_SDL_NET
+void LogicHEmoonbase::op_net_remote_start_script(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->remoteStartScript(args[0], args[1], args[2], numArgs - 3, &args[3]);
+}
+
+void LogicHEmoonbase::op_net_remote_send_array(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->remoteSendArray(args[0], args[1], args[2], args[3]);
+}
+
+int LogicHEmoonbase::op_net_remote_start_function(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->remoteStartScriptFunction(args[0], args[1], args[2], args[3], numArgs - 4, &args[4]);
+}
+
+int LogicHEmoonbase::op_net_do_init_all(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->initAll();
+}
+
+int LogicHEmoonbase::op_net_do_init_provider(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->initProvider();
+}
+
+int LogicHEmoonbase::op_net_do_init_session(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->initSession();
+}
+
+int LogicHEmoonbase::op_net_do_init_user(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->initUser();
+}
+
+int LogicHEmoonbase::op_net_query_providers(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->queryProviders();
+}
+
+int LogicHEmoonbase::op_net_get_provider_name(int op, int numArgs, int32 *args) {
+ char name[MAX_PROVIDER_NAME];
+ _vm1->_moonbase->_net->getProviderName(args[0] - 1, name, sizeof(name));
+ return _vm1->setupStringArrayFromString(name);
+}
+
+int LogicHEmoonbase::op_net_set_provider(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->setProvider(args[0] - 1);
+}
+
+int LogicHEmoonbase::op_net_close_provider(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->closeProvider();
+}
+
+int LogicHEmoonbase::op_net_start_query_sessions(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->startQuerySessions();
+}
+
+int LogicHEmoonbase::op_net_update_query_sessions(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->updateQuerySessions();
+}
+
+int LogicHEmoonbase::op_net_stop_query_sessions(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->stopQuerySessions();
+ return 1;
+}
+
+int LogicHEmoonbase::op_net_query_sessions(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->querySessions();
+}
+
+int LogicHEmoonbase::op_net_get_session_name(int op, int numArgs, int32 *args) {
+ char name[MAX_PROVIDER_NAME];
+ _vm1->_moonbase->_net->getSessionName(args[0] - 1, name, sizeof(name));
+ return _vm1->setupStringArrayFromString(name);
+}
+
+int LogicHEmoonbase::op_net_get_session_player_count(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->getSessionPlayerCount(args[0] - 1);
+}
+
+int LogicHEmoonbase::op_net_destroy_player(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->destroyPlayer(args[0]);
+}
+
+int LogicHEmoonbase::op_net_get_player_long_name(int op, int numArgs, int32 *args) {
+ return _vm1->setupStringArrayFromString("long name"); // TODO: gdefMultiPlay.playername1
+}
+
+int LogicHEmoonbase::op_net_get_player_short_name(int op, int numArgs, int32 *args) {
+ return _vm1->setupStringArrayFromString("short"); // TODO: gdefMultiPlay.playername2
+}
+
+int LogicHEmoonbase::op_net_create_session(int op, int numArgs, int32 *args) {
+ char name[MAX_SESSION_NAME];
+ _vm1->getStringFromArray(args[0], name, sizeof(name));
+ return _vm1->_moonbase->_net->createSession(name);
+}
+
+int LogicHEmoonbase::op_net_join_session(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->joinSession(args[0] - 1);
+}
+
+int LogicHEmoonbase::op_net_end_session(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->endSession();
+}
+
+int LogicHEmoonbase::op_net_disable_session_player_join(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->disableSessionJoining();
+ return 1;
+}
+
+int LogicHEmoonbase::op_net_enable_session_player_join(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->enableSessionJoining();
+ return 1;
+}
+
+int LogicHEmoonbase::op_net_set_ai_player_count(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->setBotsCount(args[0]);
+ return 1;
+}
+
+int LogicHEmoonbase::op_net_add_user(int op, int numArgs, int32 *args) {
+ char userName[MAX_PLAYER_NAME];
+ _vm1->getStringFromArray(args[0], userName, sizeof(userName));
+ return _vm1->_moonbase->_net->addUser(userName, userName);
+}
+
+int LogicHEmoonbase::op_net_remove_user(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->removeUser();
+}
+
+int LogicHEmoonbase::op_net_who_sent_this(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->whoSentThis();
+}
+
+int LogicHEmoonbase::op_net_who_am_i(int op, int numArgs, int32 *args) {
+ return _vm1->_moonbase->_net->whoAmI();
+}
+
+int LogicHEmoonbase::op_net_set_provider_by_name(int op, int numArgs, int32 *args) {
+ // Parameter 1 is the provider name and
+ // Parameter 2 is the (optional) tcp/ip address
+ return _vm1->_moonbase->_net->setProviderByName(args[0], args[1]);
+}
+
+void LogicHEmoonbase::op_net_set_fake_latency(int op, int numArgs, int32 *args) {
+ _vm1->_moonbase->_net->setFakeLatency(args[0]);
+}
+
+int LogicHEmoonbase::op_net_get_host_name(int op, int numArgs, int32 *args) {
+ char name[MAX_HOSTNAME_SIZE];
+
+ if (_vm1->_moonbase->_net->getHostName(name, MAX_HOSTNAME_SIZE)) {
+ return _vm1->setupStringArrayFromString(name);
+ }
+
+ return 0;
+}
+
+int LogicHEmoonbase::op_net_get_ip_from_name(int op, int numArgs, int32 *args) {
+ char name[MAX_HOSTNAME_SIZE];
+ _vm1->getStringFromArray(args[0], name, sizeof(name));
+
+ char ip[MAX_IP_SIZE];
+
+ if (_vm1->_moonbase->_net->getIPfromName(ip, MAX_IP_SIZE, name)) {
+ return _vm1->setupStringArrayFromString(ip);
+ }
+
+ return 0;
+}
+
+int LogicHEmoonbase::op_net_host_tcpip_game(int op, int numArgs, int32 *args) {
+ char sessionName[MAX_SESSION_NAME];
+ char userName[MAX_PLAYER_NAME];
+
+ _vm1->getStringFromArray(args[0], sessionName, sizeof(sessionName));
+ _vm1->getStringFromArray(args[1], userName, sizeof(userName));
+
+ return _vm1->_moonbase->_net->hostGame(sessionName, userName);
+}
+
+int LogicHEmoonbase::op_net_join_tcpip_game(int op, int numArgs, int32 *args) {
+ char ip[MAX_IP_SIZE];
+ char userName[MAX_PLAYER_NAME];
+
+ _vm1->getStringFromArray(args[0], ip, sizeof(ip));
+ _vm1->getStringFromArray(args[1], userName, sizeof(userName));
+
+ return _vm1->_moonbase->_net->joinGame(ip, userName);
+}
+#endif
+
LogicHE *makeLogicHEmoonbase(ScummEngine_v100he *vm) {
return new LogicHEmoonbase(vm);
}
diff --git a/engines/scumm/he/moonbase/moonbase.cpp b/engines/scumm/he/moonbase/moonbase.cpp
index 15ababd321..941f32db23 100644
--- a/engines/scumm/he/moonbase/moonbase.cpp
+++ b/engines/scumm/he/moonbase/moonbase.cpp
@@ -23,6 +23,9 @@
#include "scumm/he/intern_he.h"
#include "scumm/he/moonbase/moonbase.h"
#include "scumm/he/moonbase/ai_main.h"
+#ifdef USE_SDL_NET
+#include "scumm/he/moonbase/net_main.h"
+#endif
namespace Scumm {
@@ -30,10 +33,16 @@ Moonbase::Moonbase(ScummEngine_v100he *vm) : _vm(vm) {
initFOW();
_ai = new AI(_vm);
+#ifdef USE_SDL_NET
+ _net = new Net(_vm);
+#endif
}
Moonbase::~Moonbase() {
delete _ai;
+#ifdef USE_SDL_NET
+ delete _net;
+#endif
}
int Moonbase::readFromArray(int array, int y, int x) {
diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h
index 71c03cb007..f3399ef192 100644
--- a/engines/scumm/he/moonbase/moonbase.h
+++ b/engines/scumm/he/moonbase/moonbase.h
@@ -30,6 +30,7 @@
namespace Scumm {
class AI;
+class Net;
class Moonbase {
public:
@@ -71,6 +72,9 @@ public:
uint32 _fowSentinelConditionBits;
AI *_ai;
+#ifdef USE_SDL_NET
+ Net *_net;
+#endif
private:
ScummEngine_v100he *_vm;
diff --git a/engines/scumm/he/moonbase/net_defines.h b/engines/scumm/he/moonbase/net_defines.h
new file mode 100644
index 0000000000..130ca1db94
--- /dev/null
+++ b/engines/scumm/he/moonbase/net_defines.h
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_HE_MOONBASE_NET_DEFINES_H
+#define SCUMM_HE_MOONBASE_NET_DEFINES_H
+
+namespace Scumm {
+
+// pnetwin.h
+
+#define PN_PRIORITY_HIGH 0x00000001
+
+#define PN_SENDTYPE_INDIVIDUAL 1
+#define PN_SENDTYPE_GROUP 2
+#define PN_SENDTYPE_HOST 3
+#define PN_SENDTYPE_ALL 4
+
+#define MAX_GAME_NAME 128 /* Used for the multiplayer networking code */
+#define MAX_PLAYER_NAME 128 /* Used for the multiplayer networking code */
+#define MAX_PROVIDER_NAME 128
+#define MAX_SESSION_NAME 128
+
+#define MAX_GAMES_POLLED 16
+#define MAX_PROVIDERS 16
+
+#define PACKETTYPE_REMOTESTARTSCRIPT 1
+#define PACKETTYPE_REMOTESTARTSCRIPTRETURN 2
+#define PACKETTYPE_REMOTESTARTSCRIPTRESULT 3
+#define PACKETTYPE_REMOTESENDSCUMMARRAY 4
+
+const int SESSION_ERROR = 0;
+const int USER_CREATED_SESSION = 1;
+const int USER_JOINED_SESSION = 2;
+
+const int TCPIP_PROVIDER = -1;
+const int NO_PROVIDER = -2;
+
+const int MAX_PACKET_SIZE = 4096; // bytes
+const int MAX_HOSTNAME_SIZE = 256;
+const int MAX_IP_SIZE = 32;
+const char LOCAL_HOST[] = "127.0.0.1"; //localhost
+
+#define NULL_IP ""; //no IP address (causes enumsessions to search local subnet)
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/he/moonbase/net_main.cpp b/engines/scumm/he/moonbase/net_main.cpp
new file mode 100644
index 0000000000..cdc2eef333
--- /dev/null
+++ b/engines/scumm/he/moonbase/net_main.cpp
@@ -0,0 +1,199 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/moonbase/moonbase.h"
+#include "scumm/he/moonbase/net_main.h"
+
+namespace Scumm {
+
+Net::Net(ScummEngine_v100he *vm) : _latencyTime(1), _fakeLatency(false), _vm(vm) {
+ //some defaults for fields
+}
+
+int Net::hostGame(char *sessionName, char *userName) {
+ warning("STUB: op_net_host_tcpip_game(\"%s\", \"%s\")", sessionName, userName); // PN_HostTCPIPGame
+ return 0;
+}
+
+int Net::joinGame(char *IP, char *userName) {
+ warning("STUB: Net::joinGame(\"%s\", \"%s\")", IP, userName); // PN_JoinTCPIPGame
+ return 0;
+}
+
+int Net::addUser(char *shortName, char *longName) {
+ warning("STUB: Net::addUser(\"%s\", \"%s\")", shortName, longName); // PN_AddUser
+ return 0;
+}
+
+int Net::removeUser() {
+ warning("STUB: Net::removeUser()"); // PN_RemoveUser
+ return 0;
+}
+
+int Net::whoSentThis() {
+ warning("STUB: Net::whoSentThis()"); // PN_WhoSentThis
+ return 0;
+}
+
+int Net::whoAmI() {
+ warning("STUB: Net::whoAmI()"); // PN_WhoAmI
+ return 0;
+}
+
+int Net::createSession(char *name) {
+ warning("STUB: Net::createSession(\"%s\")", name); // PN_CreateSession
+ return 0;
+}
+
+int Net::joinSession(int sessionIndex) {
+ warning("STUB: Net::joinSession(%d)", sessionIndex); // PN_JoinSession
+ return 0;
+}
+
+int Net::endSession() {
+ warning("STUB: Net::endSession()"); // PN_EndSession
+ return 0;
+}
+
+void Net::disableSessionJoining() {
+ warning("STUB: Net::disableSessionJoining()"); // PN_DisableSessionPlayerJoin
+}
+
+void Net::enableSessionJoining() {
+ warning("STUB: Net::enableSessionJoining()"); // PN_EnableSessionPlayerJoin
+}
+
+void Net::setBotsCount(int botsCount) {
+ warning("STUB: Net::setBotsCount(%d)", botsCount); // PN_SetAIPlayerCountKludge
+}
+
+int32 Net::setProviderByName(int32 parameter1, int32 parameter2) {
+ warning("STUB: Net::setProviderByName(%d, %d)", parameter1, parameter2); // PN_SetProviderByName
+ return 0;
+}
+
+void Net::setFakeLatency(int time) {
+ _latencyTime = time;
+ debug("NETWORK: Setting Fake Latency to %d ms \n", _latencyTime); // TODO: is it OK to use debug instead of SPUTM_xprintf?
+ _fakeLatency = true;
+}
+
+bool Net::destroyPlayer(int32 playerDPID) {
+ // bool PNETWIN_destroyplayer(DPID idPlayer)
+ warning("STUB: Net::destroyPlayer(%d)", playerDPID);
+ return false;
+}
+
+int32 Net::startQuerySessions() {
+ warning("STUB: Net::startQuerySessions()"); // StartQuerySessions
+ return 0;
+}
+
+int32 Net::updateQuerySessions() {
+ warning("STUB: Net::updateQuerySessions()"); // UpdateQuerySessions
+ return 0;
+}
+
+void Net::stopQuerySessions() {
+ warning("STUB: Net::stopQuerySessions()"); // StopQuerySessions
+}
+
+int Net::querySessions() {
+ warning("STUB: Net::querySessions()"); // PN_QuerySessions
+ return 0;
+}
+
+int Net::queryProviders() {
+ warning("STUB: Net::queryProviders()"); // PN_QueryProviders
+ return 0;
+}
+
+int Net::setProvider(int providerIndex) {
+ warning("STUB: Net::setProvider(%d)", providerIndex); // PN_SetProvider
+ return 0;
+}
+
+int Net::closeProvider() {
+ warning("STUB: Net::closeProvider()"); // PN_CloseProvider
+ return 0;
+}
+
+bool Net::initAll() {
+ warning("STUB: Net::initAll()"); // PN_DoInitAll
+ return false;
+}
+
+bool Net::initProvider() {
+ warning("STUB: Net::initProvider()"); // PN_DoInitProvider
+ return false;
+}
+
+bool Net::initSession() {
+ warning("STUB: Net::initSession()"); // PN_DoInitSession
+ return false;
+}
+
+bool Net::initUser() {
+ warning("STUB: Net::initUser()"); // PN_DoInitUser
+ return false;
+}
+
+void Net::remoteStartScript(int typeOfSend, int sendTypeParam, int priority, int argsCount, int32 *args) {
+ warning("STUB: Net::remoteStartScript(%d, %d, %d, %d, ...)", typeOfSend, sendTypeParam, priority, argsCount); // PN_RemoteStartScriptCommand
+}
+
+void Net::remoteSendArray(int typeOfSend, int sendTypeParam, int priority, int arrayIndex) {
+ warning("STUB: Net::remoteSendArray(%d, %d, %d, %d)", typeOfSend, sendTypeParam, priority, arrayIndex); // PN_RemoteSendArrayCommand
+}
+
+int Net::remoteStartScriptFunction(int typeOfSend, int sendTypeParam, int priority, int defaultReturnValue, int argsCount, int32 *args) {
+ warning("STUB: Net::remoteStartScriptFunction(%d, %d, %d, %d, %d, ...)", typeOfSend, sendTypeParam, priority, defaultReturnValue, argsCount); // PN_RemoteStartScriptFunction
+ return 0;
+}
+
+bool Net::getHostName(char *hostname, int length) {
+ warning("STUB: Net::getHostName(\"%s\", %d)", hostname, length); // PN_GetHostName
+ return false;
+}
+
+bool Net::getIPfromName(char *ip, int ipLength, char *nameBuffer) {
+ warning("STUB: Net::getIPfromName(\"%s\", %d, \"%s\")", ip, ipLength, nameBuffer); // PN_GetIPfromName
+ return false;
+}
+
+void Net::getSessionName(int sessionNumber, char *buffer, int length) {
+ warning("STUB: Net::getSessionName(%d, \"%s\", %d)", sessionNumber, buffer, length); // PN_GetSessionName
+}
+
+int Net::getSessionPlayerCount(int sessionNumber) {
+ warning("STUB: Net::getSessionPlayerCount(%d)", sessionNumber); // case GET_SESSION_PLAYER_COUNT_KLUDGE:
+ //assert(sessionNumber >= 0 && sessionNumber < NUMELEMENTS(gdefMultiPlay.gamedescptr));
+ //return gdefMultiPlay.gamedescptr[sessionNumber].currentplayers;
+ return 0;
+}
+
+void Net::getProviderName(int providerIndex, char *buffer, int length) {
+ warning("STUB: Net::getProviderName(%d, \"%s\", %d)", providerIndex, buffer, length); // PN_GetProviderName
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/moonbase/net_main.h b/engines/scumm/he/moonbase/net_main.h
new file mode 100644
index 0000000000..8350904fcd
--- /dev/null
+++ b/engines/scumm/he/moonbase/net_main.h
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_HE_MOONBASE_NET_MAIN_H
+#define SCUMM_HE_MOONBASE_NET_MAIN_H
+
+namespace Scumm {
+
+class ScummEngine_v100he;
+
+//this is a dummy based on ai_main.h Scumm::AI
+
+class Net {
+public:
+ Net(ScummEngine_v100he *vm);
+
+ int hostGame(char *sessionName, char *userName);
+ int joinGame(char *IP, char *userName);
+ int addUser(char *shortName, char *longName);
+ int removeUser();
+ int whoSentThis();
+ int whoAmI();
+ int createSession(char *name);
+ int joinSession(int sessionIndex);
+ int endSession();
+ void disableSessionJoining();
+ void enableSessionJoining();
+ void setBotsCount(int botsCount);
+ int32 setProviderByName(int32 parameter1, int32 parameter2);
+ void setFakeLatency(int time);
+ bool destroyPlayer(int32 playerDPID);
+ int32 startQuerySessions();
+ int32 updateQuerySessions();
+ void stopQuerySessions();
+ int querySessions();
+ int queryProviders();
+ int setProvider(int providerIndex);
+ int closeProvider();
+ bool initAll();
+ bool initProvider();
+ bool initSession();
+ bool initUser();
+ void remoteStartScript(int typeOfSend, int sendTypeParam, int priority, int argsCount, int32 *args);
+ void remoteSendArray(int typeOfSend, int sendTypeParam, int priority, int arrayIndex);
+ int remoteStartScriptFunction(int typeOfSend, int sendTypeParam, int priority, int defaultReturnValue, int argsCount, int32 *args);
+
+private:
+
+public:
+ //getters
+ bool getHostName(char *hostname, int length);
+ bool getIPfromName(char *ip, int ipLength, char *nameBuffer);
+ void getSessionName(int sessionNumber, char *buffer, int length);
+ int getSessionPlayerCount(int sessionNumber);
+ void getProviderName(int providerIndex, char *buffer, int length);
+
+private:
+ //mostly getters
+
+public:
+ //fields
+ int _latencyTime; // ms
+ bool _fakeLatency;
+
+ ScummEngine_v100he *_vm;
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index d32eb766cb..a922af1671 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -230,6 +230,23 @@ int ScummEngine_v72he::setupStringArray(int size) {
return readVar(0);
}
+int ScummEngine_v72he::setupStringArrayFromString(const char *cStr) {
+ // this is PUI_ScummStringArrayFromCString() found in PUSERMAC.cpp
+ // I can see how its done up there in setupStringArray()
+ // yet I'd note that 'SCUMMVAR_user_reserved' var was used instead of 0
+ // and strlen(), not strlen() + 1 was used
+ // plus, this function actually copies the string, not just 'sets up' the array
+
+ writeVar(0, 0);
+
+ int len = strlen(cStr) + 1;
+ byte *ptr = defineArray(0, kStringArray, 0, 0, 0, len);
+ if (ptr != nullptr)
+ Common::strlcpy((char*)ptr, cStr, len);
+
+ return readVar(0);
+}
+
void ScummEngine_v72he::readArrayFromIndexFile() {
int num;
int a, b, c;
@@ -1484,6 +1501,26 @@ void ScummEngine_v72he::writeFileFromArray(int slot, int32 resID) {
}
}
+void ScummEngine_v72he::getStringFromArray(int arrayNumber, char *buffer, int maxLength) {
+ // I'm not really sure it belongs here and not some other version
+ // this is ARRAY_GetStringFromArray() from ARRAYS.cpp of SPUTM
+
+ // this function makes a C-string out of <arrayNumber> contents
+
+ VAR(0) = arrayNumber; // it was 0 in original code, but I've seen ScummVM Moonbase code which uses VAR_U32_ARRAY_UNK
+
+ int i, ch;
+ for (i = 0; i < maxLength; ++i) {
+ if (!(ch = readArray(0, 0, i))) {
+ break;
+ }
+
+ buffer[i] = ch;
+ }
+
+ buffer[i] = 0;
+}
+
void ScummEngine_v72he::o72_writeFile() {
int32 resID = pop();
int slot = pop();
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 85ff1aa4cd..fee61ec29f 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -150,6 +150,11 @@ MODULE_OBJS += \
he/moonbase/distortion.o \
he/moonbase/moonbase.o \
he/moonbase/moonbase_fow.o
+
+ifdef USE_SDL_NET
+MODULE_OBJS += \
+ he/moonbase/net_main.o
+endif
endif
# This module can be built as a plugin
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index da94a34baf..cbc24a8b7e 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -110,6 +110,16 @@ void ScummEngine::setOwnerOf(int obj, int owner) {
// This causes it to try to remove object 0 from the inventory.
if (_game.id == GID_PASS && obj == 0 && vm.slot[_currentScript].number == 94)
return;
+
+ // WORKAROUND for bug #6802: assert() was triggered in freddi2.
+ // Bug is in room 39. Problem is script 10, in the localvar2==78 case;
+ // this only sets the obj id if var198 is non-zero, but in the asserting
+ // case, it is obj 0. That means two setOwnerOf calls are made with obj 0.
+ // The correct setOwnerOf calls are made afterwards, so just ignoring this
+ // seems to work just fine.
+ if (_game.id == GID_HEGAME && obj == 0 && _currentRoom == 39 && vm.slot[_currentScript].number == 10)
+ return;
+
assert(obj > 0);
if (owner == 0) {
diff --git a/engines/scumm/players/player_pce.cpp b/engines/scumm/players/player_pce.cpp
index 89a3b07798..778c40f46d 100644
--- a/engines/scumm/players/player_pce.cpp
+++ b/engines/scumm/players/player_pce.cpp
@@ -28,7 +28,6 @@
* LFO and noise channel support have been removed (not used by Loom PCE).
*/
-#include <math.h>
#include "scumm/players/player_pce.h"
#include "common/endian.h"
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index 6c81f17f2f..62c62c0b4a 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -707,6 +707,17 @@ void ScummEngine_v6::o6_ifNot() {
void ScummEngine_v6::o6_jump() {
int offset = fetchScriptWordSigned();
+ // WORKAROUND bug #6097: Pressing escape at the lake side entrance of
+ // the cave while Putt Putt is not on solid ground and still talking
+ // will cause the raft to disappear. This is a script bug in the
+ // original game and affects several versions.
+ if (_game.id == GID_PUTTZOO) {
+ if (_game.heversion == 73 && vm.slot[_currentScript].number == 206 && offset == 176 && !isScriptRunning(202))
+ _scummVars[244] = 35;
+ if (_game.features & GF_HE_985 && vm.slot[_currentScript].number == 2054 && offset == 178 && !isScriptRunning(2050))
+ _scummVars[202] = 35;
+ }
+
// WORKAROUND bug #2826144: Talking to the guard at the bigfoot party, after
// he's let you inside, will cause the game to hang, if you end the conversation.
// This is a script bug, due to a missing jump in one segment of the script.
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 72c6909f8c..107228453e 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2589,6 +2589,30 @@ void ScummEngine_v60he::setHETimer(int timer) {
_heTimers[timer] = _system->getMillis();
}
+void ScummEngine_v60he::pauseHETimers(bool pause) {
+ // The HE timers rely on system time which of course doesn't pause when
+ // the engine does. By adding the elapsed time we compensate for this.
+ // Fixes bug #6352
+ if (pause) {
+ // Pauses can be layered, we only need the start of the first
+ if (!_pauseStartTime)
+ _pauseStartTime = _system->getMillis();
+ } else {
+ int elapsedTime = _system->getMillis() - _pauseStartTime;
+ for (int i = 0; i < ARRAYSIZE(_heTimers); i++) {
+ if (_heTimers[i] != 0)
+ _heTimers[i] += elapsedTime;
+ }
+ _pauseStartTime = 0;
+ }
+}
+
+void ScummEngine_v60he::pauseEngineIntern(bool pause) {
+ pauseHETimers(pause);
+
+ ScummEngine::pauseEngineIntern(pause);
+}
+
void ScummEngine::pauseGame() {
pauseDialog();
}