2009-05-20 17:51:55 +00:00
|
|
|
/* 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.
|
2014-02-18 02:34:24 +01:00
|
|
|
*
|
2009-05-20 17:51:55 +00:00
|
|
|
* 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.
|
2014-02-18 02:34:24 +01:00
|
|
|
*
|
2009-05-20 17:51:55 +00:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-07-27 21:00:37 -05:00
|
|
|
#include "common/config-manager.h"
|
2009-05-20 17:51:55 +00:00
|
|
|
#include "common/system.h"
|
|
|
|
|
|
|
|
#include "sci/sci.h"
|
2009-06-04 11:28:05 +00:00
|
|
|
#include "sci/debug.h"
|
2009-12-04 17:38:24 +00:00
|
|
|
#include "sci/event.h"
|
2009-05-20 17:51:55 +00:00
|
|
|
#include "sci/engine/state.h"
|
|
|
|
#include "sci/engine/kernel.h"
|
|
|
|
#include "sci/engine/gc.h"
|
2011-02-06 00:05:27 +00:00
|
|
|
#include "sci/graphics/cursor.h"
|
2019-06-23 00:46:53 +02:00
|
|
|
#include "sci/graphics/palette.h"
|
2016-08-22 19:56:06 +03:00
|
|
|
#ifdef ENABLE_SCI32
|
|
|
|
#include "sci/graphics/cursor32.h"
|
|
|
|
#endif
|
2010-05-24 17:21:11 +00:00
|
|
|
#include "sci/graphics/maciconbar.h"
|
2011-01-21 18:53:35 +00:00
|
|
|
#include "sci/console.h"
|
2019-07-08 08:55:45 +02:00
|
|
|
#ifdef ENABLE_SCI32
|
2019-07-07 22:25:24 +03:00
|
|
|
#include "sci/engine/hoyle5poker.h"
|
2019-07-08 08:55:45 +02:00
|
|
|
#endif
|
2009-05-20 17:51:55 +00:00
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
2019-01-05 20:08:47 +01:00
|
|
|
reg_t kRestartGame16(EngineState *s, int argc, reg_t *argv) {
|
2010-05-23 16:44:36 +00:00
|
|
|
s->shrinkStackToBase();
|
2009-05-28 22:42:18 +00:00
|
|
|
|
2010-06-08 21:05:46 +00:00
|
|
|
s->abortScriptProcessing = kAbortRestartGame; // Force vm to abort ASAP
|
2009-05-20 17:51:55 +00:00
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* kGameIsRestarting():
|
|
|
|
** Returns the restarting_flag in acc
|
|
|
|
*/
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) {
|
2010-07-31 14:09:42 +00:00
|
|
|
s->r_acc = make_reg(0, s->gameIsRestarting);
|
2009-05-20 17:51:55 +00:00
|
|
|
|
|
|
|
if (argc) { // Only happens during replay
|
2009-06-07 15:53:30 +00:00
|
|
|
if (!argv[0].toUint16()) // Set restarting flag
|
2010-07-31 14:09:42 +00:00
|
|
|
s->gameIsRestarting = GAMEISRESTARTING_NONE;
|
2009-05-20 17:51:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-17 09:32:16 +00:00
|
|
|
uint32 neededSleep = 30;
|
|
|
|
|
2011-09-24 01:31:18 +03:00
|
|
|
// WORKAROUNDS for scripts that are polling too quickly in scenes that
|
|
|
|
// are not animating much
|
2010-07-30 21:29:45 +00:00
|
|
|
switch (g_sci->getGameId()) {
|
2011-09-24 01:31:18 +03:00
|
|
|
case GID_CASTLEBRAIN:
|
|
|
|
// In Castle of Dr. Brain, memory color matching puzzle in the first
|
|
|
|
// room (room 100), the game scripts constantly poll the state of each
|
|
|
|
// stone when the user clicks on one. Since the scene is not animating
|
|
|
|
// much, this results in activating and deactivating each stone very
|
|
|
|
// quickly (together with its associated tone sound), depending on how
|
|
|
|
// low it is in the animate list. This worked somewhat in older PCs, but
|
|
|
|
// not in modern computers. We throttle the scene in order to allow the
|
|
|
|
// stones to display, otherwise the game scripts reset them too soon.
|
|
|
|
// Fixes bug #3127824.
|
|
|
|
if (s->currentRoomNumber() == 100) {
|
|
|
|
s->_throttleTrigger = true;
|
|
|
|
neededSleep = 60;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GID_ICEMAN:
|
|
|
|
// In ICEMAN the submarine control room is not animating much, so it
|
|
|
|
// runs way too fast. We calm it down even more, otherwise fighting
|
|
|
|
// against other submarines is almost impossible.
|
|
|
|
if (s->currentRoomNumber() == 27) {
|
|
|
|
s->_throttleTrigger = true;
|
|
|
|
neededSleep = 60;
|
|
|
|
}
|
|
|
|
break;
|
2010-07-30 21:29:45 +00:00
|
|
|
case GID_LSL3:
|
|
|
|
// LSL3 calculates a machinespeed variable during game startup
|
|
|
|
// (right after the filthy questions). This one would go through w/o
|
|
|
|
// throttling resulting in having to do 1000 pushups or something. Another
|
|
|
|
// way of handling this would be delaying incrementing of "machineSpeed"
|
|
|
|
// selector.
|
|
|
|
if (s->currentRoomNumber() == 290)
|
|
|
|
s->_throttleTrigger = true;
|
|
|
|
break;
|
2010-11-20 00:52:05 +00:00
|
|
|
case GID_SQ4:
|
2011-06-20 00:59:48 +02:00
|
|
|
// In SQ4 (floppy and CD) the sequel police appear way too quickly in
|
2010-11-20 00:52:05 +00:00
|
|
|
// the Skate-o-rama rooms, resulting in all sorts of timer issues, like
|
|
|
|
// #3109139 (which occurs because a police officer instantly teleports
|
|
|
|
// just before Roger exits and shoots him). We throttle these scenes a
|
2011-09-24 01:31:18 +03:00
|
|
|
// bit more, in order to prevent timer bugs related to the sequel police.
|
2010-11-20 00:52:05 +00:00
|
|
|
if (s->currentRoomNumber() == 405 || s->currentRoomNumber() == 406 ||
|
|
|
|
s->currentRoomNumber() == 410 || s->currentRoomNumber() == 411) {
|
|
|
|
s->_throttleTrigger = true;
|
|
|
|
neededSleep = 60;
|
|
|
|
}
|
2010-07-30 21:29:45 +00:00
|
|
|
default:
|
|
|
|
break;
|
2010-05-17 09:32:16 +00:00
|
|
|
}
|
2010-01-17 20:17:00 +00:00
|
|
|
|
2010-07-10 22:27:28 +00:00
|
|
|
s->speedThrottler(neededSleep);
|
2009-05-20 17:51:55 +00:00
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kHaveMouse(EngineState *s, int argc, reg_t *argv) {
|
2009-09-30 23:00:03 +00:00
|
|
|
return SIGNAL_REG;
|
2009-05-20 17:51:55 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 21:18:52 +00:00
|
|
|
enum kMemoryInfoFunc {
|
|
|
|
K_MEMORYINFO_LARGEST_HEAP_BLOCK = 0, // Largest heap block available
|
|
|
|
K_MEMORYINFO_FREE_HEAP = 1, // Total free heap memory
|
|
|
|
K_MEMORYINFO_LARGEST_HUNK_BLOCK = 2, // Largest available hunk memory block
|
|
|
|
K_MEMORYINFO_FREE_HUNK = 3, // Amount of free DOS paragraphs
|
|
|
|
K_MEMORYINFO_TOTAL_HUNK = 4 // Total amount of hunk memory (SCI01)
|
|
|
|
};
|
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) {
|
2010-06-23 17:30:18 +00:00
|
|
|
// The free heap size returned must not be 0xffff, or some memory
|
|
|
|
// calculations will overflow. Crazy Nick's games handle up to 32746
|
|
|
|
// bytes (0x7fea), otherwise they throw a warning that the memory is
|
|
|
|
// fragmented
|
|
|
|
const uint16 size = 0x7fea;
|
2009-08-20 21:18:52 +00:00
|
|
|
|
2012-06-18 05:21:59 +03:00
|
|
|
switch (argv[0].getOffset()) {
|
2009-08-20 21:18:52 +00:00
|
|
|
case K_MEMORYINFO_LARGEST_HEAP_BLOCK:
|
|
|
|
// In order to prevent "Memory fragmented" dialogs from
|
|
|
|
// popping up in some games, we must return FREE_HEAP - 2 here.
|
|
|
|
return make_reg(0, size - 2);
|
|
|
|
case K_MEMORYINFO_FREE_HEAP:
|
|
|
|
case K_MEMORYINFO_LARGEST_HUNK_BLOCK:
|
|
|
|
case K_MEMORYINFO_FREE_HUNK:
|
|
|
|
case K_MEMORYINFO_TOTAL_HUNK:
|
|
|
|
return make_reg(0, size);
|
2009-05-20 17:51:55 +00:00
|
|
|
|
|
|
|
default:
|
2012-06-18 05:21:59 +03:00
|
|
|
error("Unknown MemoryInfo operation: %04x", argv[0].getOffset());
|
2009-05-20 17:51:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
|
2010-01-31 19:47:54 +00:00
|
|
|
enum kMemorySegmentFunc {
|
|
|
|
K_MEMORYSEGMENT_SAVE_DATA = 0,
|
|
|
|
K_MEMORYSEGMENT_RESTORE_DATA = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
reg_t kMemorySegment(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
// MemorySegment provides access to a 256-byte block of memory that remains
|
|
|
|
// intact across restarts and restores
|
|
|
|
|
|
|
|
switch (argv[0].toUint16()) {
|
|
|
|
case K_MEMORYSEGMENT_SAVE_DATA: {
|
|
|
|
if (argc < 3)
|
|
|
|
error("Insufficient number of arguments passed to MemorySegment");
|
|
|
|
uint16 size = argv[2].toUint16();
|
|
|
|
|
|
|
|
if (!size)
|
|
|
|
size = s->_segMan->strlen(argv[1]) + 1;
|
|
|
|
|
2011-03-27 18:11:26 +03:00
|
|
|
if (size > EngineState::kMemorySegmentMax) {
|
|
|
|
// This was set to cut the block to 256 bytes. This should be an
|
|
|
|
// error, as we won't restore the full block that the game scripts
|
|
|
|
// request, thus error out instead.
|
|
|
|
//size = EngineState::kMemorySegmentMax;
|
|
|
|
error("kMemorySegment: Requested to save more than 256 bytes (%d)", size);
|
|
|
|
}
|
2010-01-31 19:47:54 +00:00
|
|
|
|
|
|
|
s->_memorySegmentSize = size;
|
|
|
|
|
|
|
|
// We assume that this won't be called on pointers
|
|
|
|
s->_segMan->memcpy(s->_memorySegment, argv[1], size);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case K_MEMORYSEGMENT_RESTORE_DATA:
|
|
|
|
s->_segMan->memcpy(argv[1], s->_memorySegment, s->_memorySegmentSize);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unknown MemorySegment operation %04x", argv[0].toUint16());
|
|
|
|
}
|
|
|
|
|
|
|
|
return argv[1];
|
|
|
|
}
|
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kFlushResources(EngineState *s, int argc, reg_t *argv) {
|
2010-02-06 19:41:55 +00:00
|
|
|
run_gc(s);
|
2011-01-01 12:48:12 +00:00
|
|
|
debugC(kDebugLevelRoom, "Entering room number %d", argv[0].toUint16());
|
2009-05-20 17:51:55 +00:00
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kSetDebug(EngineState *s, int argc, reg_t *argv) {
|
2011-01-21 19:56:23 +00:00
|
|
|
// WORKAROUND: For some reason, GK1 calls this unconditionally when
|
|
|
|
// watching the intro. Older (SCI0) games call it on room change if
|
|
|
|
// a flag is set, in which case the debugger SHOULD get activated.
|
|
|
|
// Therefore, don't break into the debugger in GK1, but do so elsewhere.
|
|
|
|
|
2011-01-21 19:33:36 +00:00
|
|
|
if (g_sci->getGameId() != GID_GK1) {
|
|
|
|
debug("Debug mode activated");
|
2011-06-20 00:59:48 +02:00
|
|
|
|
2011-01-21 19:33:36 +00:00
|
|
|
g_sci->getDebugger()->attach();
|
|
|
|
}
|
2009-05-20 17:51:55 +00:00
|
|
|
|
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2009-05-20 17:52:12 +00:00
|
|
|
enum {
|
2010-07-31 14:29:22 +00:00
|
|
|
KGETTIME_TICKS = 0,
|
|
|
|
KGETTIME_TIME_12HOUR = 1,
|
|
|
|
KGETTIME_TIME_24HOUR = 2,
|
|
|
|
KGETTIME_DATE = 3
|
2009-05-20 17:52:12 +00:00
|
|
|
};
|
2009-05-20 17:51:55 +00:00
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
|
2009-10-08 19:41:38 +00:00
|
|
|
TimeDate loc_time;
|
2009-05-20 17:51:55 +00:00
|
|
|
int retval = 0; // Avoid spurious warning
|
|
|
|
|
|
|
|
g_system->getTimeAndDate(loc_time);
|
|
|
|
|
2009-06-07 16:50:34 +00:00
|
|
|
int mode = (argc > 0) ? argv[0].toUint16() : 0;
|
2009-05-20 17:51:55 +00:00
|
|
|
|
2010-10-08 18:33:54 +00:00
|
|
|
// Modes 2 and 3 are supported since 0.629.
|
|
|
|
// This condition doesn't check that exactly, but close enough.
|
|
|
|
if (getSciVersion() == SCI_VERSION_0_EARLY && mode > 1)
|
2010-06-28 12:29:06 +00:00
|
|
|
error("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode);
|
2009-10-09 23:15:54 +00:00
|
|
|
|
2009-05-20 17:51:55 +00:00
|
|
|
switch (mode) {
|
2010-07-31 14:29:22 +00:00
|
|
|
case KGETTIME_TICKS :
|
2016-01-14 10:54:27 -06:00
|
|
|
retval = g_sci->getTickCount();
|
2011-01-01 12:48:12 +00:00
|
|
|
debugC(kDebugLevelTime, "GetTime(elapsed) returns %d", retval);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
2010-07-31 14:29:22 +00:00
|
|
|
case KGETTIME_TIME_12HOUR :
|
2009-05-21 10:34:13 +00:00
|
|
|
retval = ((loc_time.tm_hour % 12) << 12) | (loc_time.tm_min << 6) | (loc_time.tm_sec);
|
2011-01-01 12:48:12 +00:00
|
|
|
debugC(kDebugLevelTime, "GetTime(12h) returns %d", retval);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
2010-07-31 14:29:22 +00:00
|
|
|
case KGETTIME_TIME_24HOUR :
|
2009-05-21 10:34:13 +00:00
|
|
|
retval = (loc_time.tm_hour << 11) | (loc_time.tm_min << 5) | (loc_time.tm_sec >> 1);
|
2011-01-01 12:48:12 +00:00
|
|
|
debugC(kDebugLevelTime, "GetTime(24h) returns %d", retval);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
2010-07-31 14:29:22 +00:00
|
|
|
case KGETTIME_DATE :
|
2016-04-14 21:17:49 +03:00
|
|
|
{
|
|
|
|
// SCI0 late: Year since 1920 (0 = 1920, 1 = 1921, etc)
|
|
|
|
// SCI01 and newer: Year since 1980 (0 = 1980, 1 = 1981, etc)
|
|
|
|
// Atari ST SCI0 late versions use the newer base year.
|
|
|
|
int baseYear = 80;
|
|
|
|
if (getSciVersion() == SCI_VERSION_0_LATE && g_sci->getPlatform() == Common::kPlatformDOS) {
|
|
|
|
baseYear = 20;
|
|
|
|
}
|
|
|
|
retval = loc_time.tm_mday | ((loc_time.tm_mon + 1) << 5) | (((loc_time.tm_year - baseYear) & 0x7f) << 9);
|
2011-01-01 12:48:12 +00:00
|
|
|
debugC(kDebugLevelTime, "GetTime(date) returns %d", retval);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
2016-04-14 21:17:49 +03:00
|
|
|
}
|
2009-05-20 17:51:55 +00:00
|
|
|
default:
|
2010-06-28 12:29:06 +00:00
|
|
|
error("Attempt to use unknown GetTime mode %d", mode);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return make_reg(0, retval);
|
|
|
|
}
|
|
|
|
|
2009-05-20 17:52:12 +00:00
|
|
|
enum {
|
|
|
|
K_MEMORY_ALLOCATE_CRITICAL = 1,
|
|
|
|
K_MEMORY_ALLOCATE_NONCRITICAL = 2,
|
|
|
|
K_MEMORY_FREE = 3,
|
|
|
|
K_MEMORY_MEMCPY = 4,
|
|
|
|
K_MEMORY_PEEK = 5,
|
|
|
|
K_MEMORY_POKE = 6
|
|
|
|
};
|
2009-05-20 17:51:55 +00:00
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
|
2009-06-07 15:53:30 +00:00
|
|
|
switch (argv[0].toUint16()) {
|
2010-08-03 13:17:30 +00:00
|
|
|
case K_MEMORY_ALLOCATE_CRITICAL: {
|
|
|
|
int byteCount = argv[1].toUint16();
|
2016-02-08 21:12:37 +01:00
|
|
|
// Sierra themselves allocated at least 2 bytes more than requested.
|
|
|
|
// Probably as a safety margin. And they also made size even.
|
|
|
|
//
|
|
|
|
// This behavior is required by at least these:
|
2010-10-23 20:22:24 +00:00
|
|
|
// - pq3 (multilingual) room 202
|
|
|
|
// when plotting crimes, allocates the returned bytes from kStrLen
|
|
|
|
// on "W" and "E" and wants to put a string in there, which doesn't
|
|
|
|
// fit of course.
|
|
|
|
// - lsl5 (multilingual) room 280
|
|
|
|
// allocates memory according to a previous kStrLen for the name of
|
|
|
|
// the airport ladies (bug #3093818), which isn't enough
|
2016-02-08 21:12:37 +01:00
|
|
|
byteCount += 2 + (byteCount & 1);
|
2010-10-23 20:22:24 +00:00
|
|
|
|
2010-08-03 13:17:30 +00:00
|
|
|
if (!s->_segMan->allocDynmem(byteCount, "kMemory() critical", &s->r_acc)) {
|
2009-05-27 00:24:32 +00:00
|
|
|
error("Critical heap allocation failed");
|
2009-05-20 17:51:55 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-08-03 13:17:30 +00:00
|
|
|
}
|
2016-02-08 21:12:37 +01:00
|
|
|
case K_MEMORY_ALLOCATE_NONCRITICAL: {
|
|
|
|
int byteCount = argv[1].toUint16();
|
|
|
|
|
|
|
|
// See above
|
|
|
|
byteCount += 2 + (byteCount & 1);
|
|
|
|
|
|
|
|
s->_segMan->allocDynmem(byteCount, "kMemory() non-critical", &s->r_acc);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
2016-02-08 21:12:37 +01:00
|
|
|
}
|
2009-05-20 17:51:55 +00:00
|
|
|
case K_MEMORY_FREE :
|
2010-08-01 11:10:14 +00:00
|
|
|
if (!s->_segMan->freeDynmem(argv[1])) {
|
|
|
|
if (g_sci->getGameId() == GID_QFG1VGA) {
|
|
|
|
// Ignore script bug in QFG1VGA, when closing any conversation dialog with esc
|
|
|
|
} else {
|
|
|
|
// Usually, the result of a script bug. Non-critical
|
|
|
|
warning("Attempt to kMemory::free() non-dynmem pointer %04x:%04x", PRINT_REG(argv[1]));
|
|
|
|
}
|
2009-05-20 17:51:55 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case K_MEMORY_MEMCPY : {
|
2009-06-07 15:53:30 +00:00
|
|
|
int size = argv[3].toUint16();
|
2009-10-04 18:38:18 +00:00
|
|
|
s->_segMan->memcpy(argv[1], argv[2], size);
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case K_MEMORY_PEEK : {
|
2012-06-18 05:21:59 +03:00
|
|
|
if (!argv[1].getSegment()) {
|
2010-05-28 16:47:30 +00:00
|
|
|
// This occurs in KQ5CD when interacting with certain objects
|
|
|
|
warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
|
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2009-10-04 18:38:18 +00:00
|
|
|
SegmentRef ref = s->_segMan->dereference(argv[1]);
|
2009-05-20 17:51:55 +00:00
|
|
|
|
2009-09-27 01:50:26 +00:00
|
|
|
if (!ref.isValid() || ref.maxSize < 2) {
|
2010-06-28 12:29:06 +00:00
|
|
|
error("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
|
2009-05-20 17:51:55 +00:00
|
|
|
return s->r_acc;
|
|
|
|
}
|
2011-03-04 21:51:55 +01:00
|
|
|
if (ref.isRaw)
|
|
|
|
return make_reg(0, (int16)READ_SCIENDIAN_UINT16(ref.raw));
|
|
|
|
else {
|
2010-01-26 19:51:08 +00:00
|
|
|
if (ref.skipByte)
|
|
|
|
error("Attempt to peek memory at odd offset %04X:%04X", PRINT_REG(argv[1]));
|
2009-09-27 01:50:26 +00:00
|
|
|
return *(ref.reg);
|
2010-01-26 19:51:08 +00:00
|
|
|
}
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case K_MEMORY_POKE : {
|
2009-10-04 18:38:18 +00:00
|
|
|
SegmentRef ref = s->_segMan->dereference(argv[1]);
|
2009-05-20 17:51:55 +00:00
|
|
|
|
2009-09-27 01:50:26 +00:00
|
|
|
if (!ref.isValid() || ref.maxSize < 2) {
|
2010-06-28 12:29:06 +00:00
|
|
|
error("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1]));
|
2009-05-20 17:51:55 +00:00
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2009-09-27 01:50:26 +00:00
|
|
|
if (ref.isRaw) {
|
2012-06-18 05:21:59 +03:00
|
|
|
if (argv[2].getSegment()) {
|
2009-05-27 00:24:32 +00:00
|
|
|
error("Attempt to poke memory reference %04x:%04x to %04x:%04x", PRINT_REG(argv[2]), PRINT_REG(argv[1]));
|
2009-05-20 17:51:55 +00:00
|
|
|
return s->r_acc;
|
|
|
|
}
|
2012-06-18 05:21:59 +03:00
|
|
|
WRITE_SCIENDIAN_UINT16(ref.raw, argv[2].getOffset()); // Amiga versions are BE
|
2010-01-26 19:51:08 +00:00
|
|
|
} else {
|
|
|
|
if (ref.skipByte)
|
|
|
|
error("Attempt to poke memory at odd offset %04X:%04X", PRINT_REG(argv[1]));
|
2009-09-27 01:50:26 +00:00
|
|
|
*(ref.reg) = argv[2];
|
2010-01-26 19:51:08 +00:00
|
|
|
}
|
2009-05-20 17:51:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2011-02-06 00:05:27 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
|
|
|
reg_t kGetConfig(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
Common::String setting = s->_segMan->getString(argv[0]);
|
|
|
|
reg_t data = readSelector(s->_segMan, argv[1], SELECTOR(data));
|
|
|
|
|
2012-05-26 16:41:11 +03:00
|
|
|
// This function is used to get the benchmarked results stored in the
|
|
|
|
// resource.cfg configuration file in Phantasmagoria 1. Normally,
|
|
|
|
// the configuration file contains values stored by the installer
|
|
|
|
// regarding audio and video settings, which are then used by the
|
|
|
|
// executable. In Phantasmagoria, two extra executable files are used
|
|
|
|
// to perform system benchmarks:
|
|
|
|
// - CPUID for the CPU benchmarks, sets the cpu and cpuspeed settings
|
|
|
|
// - HDDTEC for the graphics and CD-ROM benchmarks, sets the videospeed setting
|
|
|
|
//
|
|
|
|
// These settings are then used by the game scripts directly to modify
|
|
|
|
// the game speed and graphics output. The result of this call is stored
|
|
|
|
// in global 178. The scripts check these values against the value 425.
|
|
|
|
// Anything below that makes Phantasmagoria awfully sluggish, so we're
|
|
|
|
// setting everything to 500, which makes the game playable.
|
|
|
|
|
2012-05-30 18:43:39 +02:00
|
|
|
setting.toLowercase();
|
|
|
|
|
2012-05-26 16:41:11 +03:00
|
|
|
if (setting == "videospeed") {
|
|
|
|
s->_segMan->strcpy(data, "500");
|
|
|
|
} else if (setting == "cpu") {
|
|
|
|
// We always return the fastest CPU setting that CPUID can detect
|
|
|
|
// (i.e. 586).
|
|
|
|
s->_segMan->strcpy(data, "586");
|
|
|
|
} else if (setting == "cpuspeed") {
|
|
|
|
s->_segMan->strcpy(data, "500");
|
2012-06-02 18:50:46 +02:00
|
|
|
} else if (setting == "language") {
|
|
|
|
Common::String languageId = Common::String::format("%d", g_sci->getSciLanguage());
|
|
|
|
s->_segMan->strcpy(data, languageId.c_str());
|
2012-06-13 12:26:13 +03:00
|
|
|
} else if (setting == "torindebug") {
|
|
|
|
// Used to enable the debug mode in Torin's Passage (French).
|
|
|
|
// If true, the debug mode is enabled.
|
|
|
|
s->_segMan->strcpy(data, "");
|
2012-06-14 12:10:39 +03:00
|
|
|
} else if (setting == "leakdump") {
|
|
|
|
// An unknown setting in LSL7. Likely used for debugging.
|
|
|
|
s->_segMan->strcpy(data, "");
|
|
|
|
} else if (setting == "startroom") {
|
|
|
|
// Debug setting in LSL7, specifies the room to start from.
|
|
|
|
s->_segMan->strcpy(data, "");
|
2016-07-11 13:02:05 -05:00
|
|
|
} else if (setting == "game") {
|
2016-07-23 11:17:06 +03:00
|
|
|
// Hoyle 5 startup, specifies the number of the game to start.
|
2018-10-23 01:32:26 +03:00
|
|
|
if (g_sci->getGameId() == GID_HOYLE5 &&
|
|
|
|
!g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 100)) &&
|
|
|
|
g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 700))) {
|
|
|
|
// Special case for Hoyle 5 Bridge: only one game is included (Bridge),
|
|
|
|
// so mimic the setting in 700.cfg and set the starting room number to 700.
|
|
|
|
s->_segMan->strcpy(data, "700");
|
|
|
|
} else {
|
|
|
|
s->_segMan->strcpy(data, "");
|
|
|
|
}
|
2016-07-23 11:17:06 +03:00
|
|
|
} else if (setting == "laptop") {
|
|
|
|
// Hoyle 5 startup.
|
|
|
|
s->_segMan->strcpy(data, "");
|
|
|
|
} else if (setting == "jumpto") {
|
|
|
|
// Hoyle 5 startup.
|
2016-07-11 13:02:05 -05:00
|
|
|
s->_segMan->strcpy(data, "");
|
2018-08-20 04:35:05 +03:00
|
|
|
} else if (setting == "klonchtsee") {
|
|
|
|
// Hoyle 5 - starting Solitaire.
|
|
|
|
s->_segMan->strcpy(data, "");
|
|
|
|
} else if (setting == "klonchtarr") {
|
|
|
|
// Hoyle 5 - starting Solitaire.
|
|
|
|
s->_segMan->strcpy(data, "");
|
2017-07-24 00:03:03 -05:00
|
|
|
} else if (setting == "deflang") {
|
|
|
|
// MGDX 4-language startup.
|
|
|
|
s->_segMan->strcpy(data, "");
|
2012-05-26 16:41:11 +03:00
|
|
|
} else {
|
|
|
|
error("GetConfig: Unknown configuration setting %s", setting.c_str());
|
|
|
|
}
|
|
|
|
|
2011-02-06 00:05:27 +00:00
|
|
|
return argv[1];
|
|
|
|
}
|
2012-05-26 16:41:11 +03:00
|
|
|
|
2012-06-09 16:29:14 +03:00
|
|
|
// Likely modelled after the Windows 3.1 function GetPrivateProfileInt:
|
|
|
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724345%28v=vs.85%29.aspx
|
2012-05-26 16:41:11 +03:00
|
|
|
reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv) {
|
2017-08-04 00:42:02 -05:00
|
|
|
if (g_sci->getPlatform() != Common::kPlatformWindows) {
|
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2012-05-26 16:41:11 +03:00
|
|
|
Common::String category = s->_segMan->getString(argv[0]); // always "config"
|
2012-05-30 18:43:39 +02:00
|
|
|
category.toLowercase();
|
2012-05-26 16:41:11 +03:00
|
|
|
Common::String setting = s->_segMan->getString(argv[1]);
|
2012-05-30 18:43:39 +02:00
|
|
|
setting.toLowercase();
|
2012-06-11 20:28:28 +03:00
|
|
|
// The third parameter is the default value returned if the configuration key is missing
|
2012-05-26 16:41:11 +03:00
|
|
|
|
2012-06-11 20:28:28 +03:00
|
|
|
if (category == "config" && setting == "videospeed") {
|
|
|
|
// We return the same fake value for videospeed as with kGetConfig
|
|
|
|
return make_reg(0, 500);
|
|
|
|
}
|
2012-05-26 16:41:11 +03:00
|
|
|
|
2012-06-11 20:28:28 +03:00
|
|
|
warning("kGetSierraProfileInt: Returning default value %d for unknown setting %s.%s", argv[2].toSint16(), category.c_str(), setting.c_str());
|
|
|
|
return argv[2];
|
2012-05-26 16:41:11 +03:00
|
|
|
}
|
|
|
|
|
2012-07-03 18:11:41 +03:00
|
|
|
reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
uint16 windowsOption = argv[0].toUint16();
|
|
|
|
switch (windowsOption) {
|
|
|
|
case 0:
|
|
|
|
// Title bar on/off in Phantasmagoria, we return 0 (off)
|
|
|
|
return NULL_REG;
|
|
|
|
default:
|
|
|
|
warning("GetWindowsOption: Unknown option %d", windowsOption);
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-20 21:06:16 -05:00
|
|
|
extern Common::String format(const Common::String &source, int argc, const reg_t *argv);
|
|
|
|
|
|
|
|
reg_t kPrintDebug(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
const Common::String debugString = s->_segMan->getString(argv[0]);
|
|
|
|
debugC(kDebugLevelGame, "%s", format(debugString, argc - 1, argv + 1).c_str());
|
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2011-02-06 00:05:27 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// kIconBar is really a subop of kMacPlatform for SCI1.1 Mac
|
2010-05-18 04:17:58 +00:00
|
|
|
reg_t kIconBar(EngineState *s, int argc, reg_t *argv) {
|
2011-02-06 00:05:27 +00:00
|
|
|
// Mac versions use their own tertiary platform functions
|
|
|
|
// to handle the outside-of-the-screen icon bar.
|
|
|
|
|
2011-02-03 02:26:57 +00:00
|
|
|
// QFG1 Mac calls this function to load the Mac icon bar (of which
|
|
|
|
// the resources do exist), but the game completely ignores it and
|
|
|
|
// uses the standard icon bar for the game. We do the same.
|
|
|
|
if (!g_sci->hasMacIconBar())
|
|
|
|
return NULL_REG;
|
|
|
|
|
2011-02-06 00:05:27 +00:00
|
|
|
switch (argv[0].toUint16()) {
|
2011-02-15 11:02:01 -05:00
|
|
|
case 0: // InitIconBar
|
2019-03-25 01:28:13 -07:00
|
|
|
g_sci->_gfxMacIconBar->initIcons(argv[1].toUint16(), &argv[2]);
|
2011-02-15 11:02:01 -05:00
|
|
|
break;
|
|
|
|
case 1: // DisposeIconBar
|
|
|
|
warning("kIconBar(Dispose)");
|
|
|
|
break;
|
2011-03-09 20:50:11 +01:00
|
|
|
case 2: // EnableIconBar (-1 = all)
|
|
|
|
debug(0, "kIconBar(Enable, %i)", argv[1].toSint16());
|
|
|
|
g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), true);
|
2011-02-15 11:02:01 -05:00
|
|
|
break;
|
2011-03-09 20:50:11 +01:00
|
|
|
case 3: // DisableIconBar (-1 = all)
|
|
|
|
debug(0, "kIconBar(Disable, %i)", argv[1].toSint16());
|
|
|
|
g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), false);
|
2011-02-06 00:05:27 +00:00
|
|
|
break;
|
2011-02-15 11:02:01 -05:00
|
|
|
case 4: // SetIconBarIcon
|
2011-03-09 20:50:11 +01:00
|
|
|
debug(0, "kIconBar(SetIcon, %d, %d)", argv[1].toUint16(), argv[2].toUint16());
|
|
|
|
if (argv[2].toSint16() == -1)
|
|
|
|
g_sci->_gfxMacIconBar->setInventoryIcon(argv[2].toSint16());
|
2011-02-06 00:05:27 +00:00
|
|
|
break;
|
|
|
|
default:
|
2011-02-15 11:02:01 -05:00
|
|
|
error("Unknown kIconBar(%d)", argv[0].toUint16());
|
2010-05-24 17:21:11 +00:00
|
|
|
}
|
2010-05-18 04:17:58 +00:00
|
|
|
|
2011-02-20 12:35:15 -05:00
|
|
|
g_sci->_gfxMacIconBar->drawIcons();
|
|
|
|
|
2010-05-18 04:17:58 +00:00
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
|
2011-02-06 00:05:27 +00:00
|
|
|
// kMacPlatform is really a subop of kPlatform for SCI1.1+ Mac
|
|
|
|
reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
// Mac versions use their own secondary platform functions
|
|
|
|
// to do various things. Why didn't they just declare a new
|
|
|
|
// kernel function?
|
2010-11-19 12:46:36 +00:00
|
|
|
|
2011-02-06 00:05:27 +00:00
|
|
|
switch (argv[0].toUint16()) {
|
|
|
|
case 0:
|
2011-02-15 11:02:01 -05:00
|
|
|
// Subop 0 has changed a few times
|
|
|
|
// In SCI1, its usage is still unknown
|
|
|
|
// In SCI1.1, it's NOP
|
|
|
|
// In SCI32, it's used for remapping cursor ID's
|
2017-09-24 22:27:02 -05:00
|
|
|
#ifdef ENABLE_SCI32_MAC
|
2015-12-29 01:44:11 +01:00
|
|
|
if (getSciVersion() >= SCI_VERSION_2_1_EARLY) // Set Mac cursor remap
|
2016-08-22 19:56:06 +03:00
|
|
|
g_sci->_gfxCursor32->setMacCursorRemapList(argc - 1, argv + 1);
|
2016-08-23 01:42:51 +03:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (getSciVersion() != SCI_VERSION_1_1)
|
2011-02-15 11:02:01 -05:00
|
|
|
warning("Unknown SCI1 kMacPlatform(0) call");
|
2011-02-06 00:05:27 +00:00
|
|
|
break;
|
2011-02-15 11:02:01 -05:00
|
|
|
case 4: // Handle icon bar code
|
2011-02-06 00:05:27 +00:00
|
|
|
return kIconBar(s, argc - 1, argv + 1);
|
2011-02-15 11:02:01 -05:00
|
|
|
case 7: // Unknown, but always return -1
|
|
|
|
return SIGNAL_REG;
|
2011-04-15 11:13:35 +03:00
|
|
|
case 1: // Unknown, calls QuickDraw region functions (KQ5, QFG1VGA, Dr. Brain 1)
|
|
|
|
break; // removed warning, as it produces a lot of spam in the console
|
2011-02-15 11:02:01 -05:00
|
|
|
case 2: // Unknown, "UseNextWaitEvent" (Various)
|
|
|
|
case 3: // Unknown, "ProcessOpenDocuments" (Various)
|
|
|
|
case 5: // Unknown, plays a sound (KQ7)
|
|
|
|
case 6: // Unknown, menu-related (Unused?)
|
|
|
|
warning("Unhandled kMacPlatform(%d)", argv[0].toUint16());
|
|
|
|
break;
|
2011-02-06 00:05:27 +00:00
|
|
|
default:
|
2011-02-15 11:02:01 -05:00
|
|
|
error("Unknown kMacPlatform(%d)", argv[0].toUint16());
|
2011-02-06 00:05:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return s->r_acc;
|
2010-11-19 12:46:36 +00:00
|
|
|
}
|
2010-11-19 14:19:02 +00:00
|
|
|
|
2009-10-30 22:53:00 +00:00
|
|
|
enum kSciPlatforms {
|
2016-08-22 19:48:56 +03:00
|
|
|
kSciPlatformMacintosh = 0,
|
2009-10-30 22:53:00 +00:00
|
|
|
kSciPlatformDOS = 1,
|
|
|
|
kSciPlatformWindows = 2
|
|
|
|
};
|
|
|
|
|
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
|
|
|
reg_t kPlatform(EngineState *s, int argc, reg_t *argv) {
|
2016-08-16 09:44:45 -05:00
|
|
|
enum Operation {
|
|
|
|
kPlatformUnknown = 0,
|
|
|
|
kPlatformGetPlatform = 4,
|
|
|
|
kPlatformUnknown5 = 5,
|
|
|
|
kPlatformIsHiRes = 6,
|
|
|
|
kPlatformWin311OrHigher = 7
|
|
|
|
};
|
|
|
|
|
2010-02-13 17:42:49 +00:00
|
|
|
bool isWindows = g_sci->getPlatform() == Common::kPlatformWindows;
|
2010-01-02 03:44:40 +00:00
|
|
|
|
2016-08-16 09:44:45 -05:00
|
|
|
if (argc == 0) {
|
2010-06-18 09:37:06 +00:00
|
|
|
// This is called in KQ5CD with no parameters, where it seems to do some
|
|
|
|
// graphics driver check. This kernel function didn't have subfunctions
|
|
|
|
// then. If 0 is returned, the game functions normally, otherwise all
|
|
|
|
// the animations show up like a slideshow (e.g. in the intro). So we
|
2016-08-16 09:44:45 -05:00
|
|
|
// return 0.
|
2010-01-01 17:16:12 +00:00
|
|
|
return NULL_REG;
|
|
|
|
}
|
2009-12-27 19:16:06 +00:00
|
|
|
|
2016-08-16 09:44:45 -05:00
|
|
|
if (g_sci->forceHiresGraphics()) {
|
|
|
|
// force Windows platform, so that hires-graphics are enabled
|
|
|
|
isWindows = true;
|
|
|
|
}
|
|
|
|
|
2010-01-02 03:44:40 +00:00
|
|
|
uint16 operation = (argc == 0) ? 0 : argv[0].toUint16();
|
2009-10-30 22:53:00 +00:00
|
|
|
|
|
|
|
switch (operation) {
|
2016-08-16 09:44:45 -05:00
|
|
|
case kPlatformUnknown:
|
2017-08-06 13:30:51 +02:00
|
|
|
// For Mac versions, kPlatform(0) with other args has more functionality. Otherwise, fall through.
|
2011-02-15 11:02:01 -05:00
|
|
|
if (g_sci->getPlatform() == Common::kPlatformMacintosh && argc > 1)
|
2011-02-06 00:05:27 +00:00
|
|
|
return kMacPlatform(s, argc - 1, argv + 1);
|
2017-08-06 13:30:51 +02:00
|
|
|
// fall through
|
2009-10-30 23:44:12 +00:00
|
|
|
case kPlatformGetPlatform:
|
2016-08-22 19:48:56 +03:00
|
|
|
if (isWindows)
|
|
|
|
return make_reg(0, kSciPlatformWindows);
|
|
|
|
else if (g_sci->getPlatform() == Common::kPlatformMacintosh)
|
|
|
|
return make_reg(0, kSciPlatformMacintosh);
|
|
|
|
else
|
|
|
|
return make_reg(0, kSciPlatformDOS);
|
2016-08-16 09:44:45 -05:00
|
|
|
case kPlatformUnknown5:
|
2009-10-30 23:44:12 +00:00
|
|
|
// This case needs to return the opposite of case 6 to get hires graphics
|
2016-08-16 09:44:45 -05:00
|
|
|
return make_reg(0, !isWindows);
|
2009-10-30 23:44:12 +00:00
|
|
|
case kPlatformIsHiRes:
|
2016-08-16 09:44:45 -05:00
|
|
|
case kPlatformWin311OrHigher:
|
2009-10-30 23:44:12 +00:00
|
|
|
return make_reg(0, isWindows);
|
|
|
|
default:
|
2010-06-28 12:29:06 +00:00
|
|
|
error("Unsupported kPlatform operation %d", operation);
|
2009-08-30 19:47:47 +00:00
|
|
|
}
|
2009-12-27 19:16:06 +00:00
|
|
|
|
2009-08-30 19:47:47 +00:00
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
|
2018-12-02 21:56:19 +01:00
|
|
|
extern void showScummVMDialog(const Common::String &message);
|
|
|
|
|
2016-08-16 09:44:45 -05:00
|
|
|
#ifdef ENABLE_SCI32
|
|
|
|
reg_t kPlatform32(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
enum Operation {
|
|
|
|
kGetPlatform = 0,
|
|
|
|
kGetCDSpeed = 1,
|
|
|
|
kGetColorDepth = 2,
|
|
|
|
kGetCDDrive = 3
|
|
|
|
};
|
|
|
|
|
2017-05-18 11:25:53 -05:00
|
|
|
Operation operation;
|
|
|
|
if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
|
|
|
|
if (argc == 0 || argv[0].toSint16() == 0) {
|
|
|
|
operation = kGetPlatform;
|
|
|
|
} else {
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
operation = argc > 0 ? (Operation)argv[0].toSint16() : kGetPlatform;
|
|
|
|
}
|
2016-08-16 09:44:45 -05:00
|
|
|
|
|
|
|
switch (operation) {
|
|
|
|
case kGetPlatform:
|
|
|
|
switch (g_sci->getPlatform()) {
|
|
|
|
case Common::kPlatformDOS:
|
|
|
|
return make_reg(0, kSciPlatformDOS);
|
|
|
|
case Common::kPlatformWindows:
|
|
|
|
return make_reg(0, kSciPlatformWindows);
|
2016-08-22 19:48:56 +03:00
|
|
|
case Common::kPlatformMacintosh:
|
2017-09-24 22:27:02 -05:00
|
|
|
#ifdef ENABLE_SCI32_MAC
|
2016-08-22 19:56:06 +03:00
|
|
|
// For Mac versions, kPlatform(0) with other args has more functionality
|
|
|
|
if (argc > 1)
|
|
|
|
return kMacPlatform(s, argc - 1, argv + 1);
|
|
|
|
else
|
2017-09-24 22:27:02 -05:00
|
|
|
#endif
|
2016-08-22 19:56:06 +03:00
|
|
|
return make_reg(0, kSciPlatformMacintosh);
|
2016-08-16 09:44:45 -05:00
|
|
|
default:
|
|
|
|
error("Unknown platform %d", g_sci->getPlatform());
|
|
|
|
}
|
|
|
|
case kGetColorDepth:
|
2017-09-09 15:53:41 -05:00
|
|
|
if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
|
|
|
|
return make_reg(0, /* 16-bit color */ 3);
|
|
|
|
} else {
|
|
|
|
return make_reg(0, /* 256 color */ 2);
|
|
|
|
}
|
2016-08-16 09:44:45 -05:00
|
|
|
case kGetCDSpeed:
|
2017-05-30 21:28:26 -05:00
|
|
|
// The value `4` comes from Rama DOS resource.cfg installed in DOSBox,
|
|
|
|
// and seems to correspond to the highest expected CD speed value
|
|
|
|
return make_reg(0, 4);
|
2016-08-16 09:44:45 -05:00
|
|
|
case kGetCDDrive:
|
|
|
|
default:
|
2017-05-18 11:25:53 -05:00
|
|
|
return NULL_REG;
|
2016-08-16 09:44:45 -05:00
|
|
|
}
|
|
|
|
}
|
2017-01-03 20:19:45 -06:00
|
|
|
|
|
|
|
reg_t kWebConnect(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
const Common::String baseUrl = "https://web.archive.org/web/1996/";
|
|
|
|
const Common::String gameUrl = argc > 0 ? s->_segMan->getString(argv[0]) : "http://www.sierra.com";
|
2017-05-21 19:27:52 -05:00
|
|
|
return make_reg(0, g_system->openUrl(baseUrl + gameUrl));
|
2017-01-03 20:19:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
reg_t kWinExec(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
2018-08-20 04:33:13 +03:00
|
|
|
|
|
|
|
reg_t kWinDLL(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
uint16 operation = argv[0].toUint16();
|
|
|
|
Common::String dllName = s->_segMan->getString(argv[1]);
|
|
|
|
|
|
|
|
switch (operation) {
|
|
|
|
case 0: // load DLL
|
|
|
|
// This is originally a call to LoadLibrary() and to the Watcom function GetIndirectFunctionHandle
|
|
|
|
return make_reg(0, 1000); // fake ID for loaded DLL, normally returned from Windows LoadLibrary()
|
|
|
|
case 1: // free DLL
|
|
|
|
// In the original, FreeLibrary() was called here for the loaded DLL
|
|
|
|
return TRUE_REG;
|
|
|
|
case 2: // call DLL function
|
|
|
|
if (dllName == "PENGIN16.DLL") {
|
|
|
|
// Poker engine logic for Hoyle 5
|
|
|
|
// This is originally a call to the Watcom function InvokeIndirectFunction()
|
2019-07-07 22:25:24 +03:00
|
|
|
SciArray *data = s->_segMan->lookupArray(argv[2]);
|
|
|
|
return hoyle5PokerEngine(data);
|
2018-08-20 04:33:13 +03:00
|
|
|
} else {
|
|
|
|
error("kWinDLL: Unknown DLL to invoke: %s", dllName.c_str());
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-16 09:44:45 -05:00
|
|
|
#endif
|
|
|
|
|
2018-12-02 21:56:19 +01:00
|
|
|
reg_t kKawaHacks(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
switch (argv[0].toUint16()) {
|
|
|
|
case 0: { // DoAlert
|
|
|
|
showScummVMDialog(s->_segMan->getString(argv[1]));
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
2019-06-23 00:46:53 +02:00
|
|
|
case 1: { // ZaWarudo
|
|
|
|
// Invert the color palette for the specified range.
|
|
|
|
uint16 from = argv[1].toUint16();
|
|
|
|
uint16 to = argv[2].toUint16();
|
|
|
|
Palette pal = g_sci->_gfxPalette16->_sysPalette;
|
|
|
|
for (uint16 i = from; i <= to; i++)
|
|
|
|
{
|
|
|
|
pal.colors[i].r = 255 - pal.colors[i].r;
|
|
|
|
pal.colors[i].g = 255 - pal.colors[i].g;
|
|
|
|
pal.colors[i].b = 255 - pal.colors[i].b;
|
|
|
|
}
|
|
|
|
g_sci->_gfxPalette16->set(&pal, true);
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
case 2: // SetTitleColors
|
2018-12-02 21:56:19 +01:00
|
|
|
// Unused, would change the colors for plain windows' title bars.
|
|
|
|
return NULL_REG;
|
|
|
|
case 3: // IsDebug
|
2019-06-23 00:46:53 +02:00
|
|
|
// Return 1 if running with an internal debugger, 2 if we have AddMenu support, 3 if both.
|
|
|
|
return make_reg(0, 3);
|
2018-12-02 21:56:19 +01:00
|
|
|
}
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
2019-06-23 00:46:53 +02:00
|
|
|
reg_t kKawaDbugStr(EngineState *s, int argc, reg_t *argv)
|
|
|
|
{
|
|
|
|
debug(Common::String::format(s->_segMan->getString(argv[0]).c_str(), argc - 1, argv + 1).c_str());
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
2018-12-02 21:56:19 +01:00
|
|
|
|
2010-06-11 07:47:57 +00:00
|
|
|
reg_t kEmpty(EngineState *s, int argc, reg_t *argv) {
|
2010-06-18 09:37:06 +00:00
|
|
|
// Placeholder for empty kernel functions which are still called from the
|
|
|
|
// engine scripts (like the empty kSetSynonyms function in SCI1.1). This
|
|
|
|
// differs from dummy functions because it does nothing and never throws a
|
|
|
|
// warning when it is called.
|
2010-06-11 07:47:57 +00:00
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
2010-07-21 14:50:31 +00:00
|
|
|
reg_t kStub(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
Kernel *kernel = g_sci->getKernel();
|
|
|
|
int kernelCallNr = -1;
|
2016-04-02 00:04:00 +02:00
|
|
|
int kernelSubCallNr = -1;
|
2010-07-21 14:50:31 +00:00
|
|
|
|
2011-03-07 23:21:27 +01:00
|
|
|
Common::List<ExecStack>::const_iterator callIterator = s->_executionStack.end();
|
2010-07-21 14:50:31 +00:00
|
|
|
if (callIterator != s->_executionStack.begin()) {
|
|
|
|
callIterator--;
|
|
|
|
ExecStack lastCall = *callIterator;
|
2016-04-02 00:04:00 +02:00
|
|
|
kernelCallNr = lastCall.debugKernelFunction;
|
|
|
|
kernelSubCallNr = lastCall.debugKernelSubFunction;
|
2010-07-21 14:50:31 +00:00
|
|
|
}
|
|
|
|
|
2016-04-02 00:04:00 +02:00
|
|
|
Common::String warningMsg;
|
|
|
|
if (kernelSubCallNr == -1) {
|
|
|
|
warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) +
|
|
|
|
Common::String::format("[%x]", kernelCallNr);
|
|
|
|
} else {
|
|
|
|
warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr, kernelSubCallNr) +
|
|
|
|
Common::String::format("[%x:%x]", kernelCallNr, kernelSubCallNr);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
warningMsg += " invoked. Params: " +
|
|
|
|
Common::String::format("%d", argc) + " (";
|
2010-07-21 14:50:31 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < argc; i++) {
|
2010-11-01 16:02:28 +00:00
|
|
|
warningMsg += Common::String::format("%04x:%04x", PRINT_REG(argv[i]));
|
2010-07-21 14:50:31 +00:00
|
|
|
warningMsg += (i == argc - 1 ? ")" : ", ");
|
|
|
|
}
|
|
|
|
|
|
|
|
warning("%s", warningMsg.c_str());
|
|
|
|
return s->r_acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
reg_t kStubNull(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
kStub(s, argc, argv);
|
|
|
|
return NULL_REG;
|
|
|
|
}
|
|
|
|
|
|
|
|
reg_t kDummy(EngineState *s, int argc, reg_t *argv) {
|
|
|
|
kStub(s, argc, argv);
|
|
|
|
error("Kernel function was called, which was considered to be unused - see log for details");
|
|
|
|
}
|
|
|
|
|
2009-05-20 17:51:55 +00:00
|
|
|
} // End of namespace Sci
|