aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kernel.cpp249
-rw-r--r--engines/sci/engine/kmisc.cpp282
-rw-r--r--engines/sci/module.mk1
3 files changed, 283 insertions, 249 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 2d6c63d413..d7f200ee77 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -23,13 +23,8 @@
*
*/
-#include <time.h> // FIXME: For struct tm
-
-#include "common/system.h"
-
#include "sci/sci.h"
#include "sci/engine/intmap.h"
-#include "sci/engine/gc.h"
#include "sci/engine/kernel.h"
#include "sci/resource.h"
#include "sci/engine/state.h"
@@ -39,9 +34,6 @@
namespace Sci {
-#define SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR 0x75
-// kfunct_mappers below doubles for unknown kfunctions
-
static int sci_max_allowed_unknown_kernel_functions[] = {
0,
0x72, // SCI0
@@ -257,247 +249,6 @@ int kfree(EngineState *s, reg_t handle) {
return 0;
}
-char *old_save_dir; // FIXME get rid of this
-
-reg_t kRestartGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
-
- old_save_dir = strdup(deref_save_dir);
- s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
- s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; // This appears to help
- s->_executionStack.resize(s->execution_stack_base + 1);
- script_abort_flag = 1; // Force vm to abort ASAP
- return NULL_REG;
-}
-
-/* kGameIsRestarting():
-** Returns the restarting_flag in acc
-*/
-reg_t kGameIsRestarting(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
-
- if (old_save_dir && deref_save_dir) {
- strcpy(deref_save_dir, old_save_dir);
- free(old_save_dir);
- old_save_dir = NULL;
- }
-
- s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED));
-
- if (argc) { // Only happens during replay
- if (!UKPV(0)) // Set restarting flag
- s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED;
- }
-
- return s->r_acc;
-}
-
-reg_t kHaveMouse(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- return make_reg(0, -1);
-}
-
-reg_t kMemoryInfo(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- switch (argv[0].offset) {
- case 0: // Total free heap memory
- case 1: // Largest heap block available
- case 2: // Largest available hunk memory block
- case 3: // Total amount of hunk memory
- case 4: // Amount of free DOS paragraphs- SCI01
- return make_reg(0, 0x7fff); // Must not be 0xffff, or some memory calculations will overflow
-
- default:
- warning("Unknown MemoryInfo operation: %04x", argv[0].offset);
- }
-
- return NULL_REG;
-}
-
-reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- if (funct_nr >= SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR) {
- warning("Unhandled Unknown function %04x", funct_nr);
- return NULL_REG;
- } else {
- switch (kfunct_mappers[funct_nr].type) {
- case KF_NEW:
- return kfunct_mappers[funct_nr].fun(s, funct_nr, argc, argv);
- case KF_NONE:
- default:
- warning("Unhandled Unknown function %04x", funct_nr);
- return NULL_REG;
- }
- }
-}
-
-reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- run_gc(s);
- debugC(2, kDebugLevelRoom, "Entering room number %d", UKPV(0));
- return s->r_acc;
-}
-
-reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- sciprintf("Debug mode activated\n");
-
- script_debug_flag = 1; // Enter debug mode
- _debug_seeking = _debug_step_running = 0;
- return s->r_acc;
-}
-
-#define _K_NEW_GETTIME_TICKS 0
-#define _K_NEW_GETTIME_TIME_12HOUR 1
-#define _K_NEW_GETTIME_TIME_24HOUR 2
-#define _K_NEW_GETTIME_DATE 3
-
-reg_t kGetTime(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- tm loc_time;
- uint32 start_time;
- int retval = 0; // Avoid spurious warning
-
-#if 0
- // Reset optimization flags: If this function is called,
- // the game may be waiting for a timeout
- s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT);
-#endif
-
- g_system->getTimeAndDate(loc_time);
- start_time = g_system->getMillis() - s->game_start_time;
-
- if (argc && s->flags & GF_SCI0_OLDGETTIME) { // Use old semantics
- retval = loc_time.tm_sec + loc_time.tm_min * 60 + (loc_time.tm_hour % 12) * 3600;
- debugC(2, kDebugLevelTime, "GetTime(timeofday) returns %d", retval);
- return make_reg(0, retval);
- }
-
- int mode = UKPV_OR_ALT(0, 0);
-
- switch (mode) {
- case _K_NEW_GETTIME_TICKS :
- retval = start_time * 60 / 1000;
- debugC(2, kDebugLevelTime, "GetTime(elapsed) returns %d", retval);
- break;
- case _K_NEW_GETTIME_TIME_12HOUR :
- loc_time.tm_hour %= 12;
- retval = (loc_time.tm_min << 6) | (loc_time.tm_hour << 12) | (loc_time.tm_sec);
- debugC(2, kDebugLevelTime, "GetTime(12h) returns %d", retval);
- break;
- case _K_NEW_GETTIME_TIME_24HOUR :
- retval = (loc_time.tm_min << 5) | (loc_time.tm_sec >> 1) | (loc_time.tm_hour << 11);
- debugC(2, kDebugLevelTime, "GetTime(24h) returns %d", retval);
- break;
- case _K_NEW_GETTIME_DATE :
- retval = ((loc_time.tm_mon + 1) << 5) | loc_time.tm_mday | (((loc_time.tm_year + 1900) & 0x7f) << 9);
- debugC(2, kDebugLevelTime, "GetTime(date) returns %d", retval);
- break;
- default:
- warning("Attempt to use unknown GetTime mode %d", mode);
- break;
- }
-
- return make_reg(0, retval);
-}
-
-#define K_MEMORY_ALLOCATE_CRITICAL 1
-#define K_MEMORY_ALLOCATE_NONCRITICAL 2
-#define K_MEMORY_FREE 3
-#define K_MEMORY_MEMCPY 4
-#define K_MEMORY_PEEK 5
-#define K_MEMORY_POKE 6
-
-reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- switch (UKPV(0)) {
- case K_MEMORY_ALLOCATE_CRITICAL :
- if (!s->seg_manager->allocDynmem(UKPV(1), "kMemory() critical", &s->r_acc)) {
- error("Critical heap allocation failed\n");
- script_error_flag = script_debug_flag = 1;
- }
- return s->r_acc;
- break;
- case K_MEMORY_ALLOCATE_NONCRITICAL :
- s->seg_manager->allocDynmem(UKPV(1), "kMemory() non-critical", &s->r_acc);
- break;
- case K_MEMORY_FREE :
- if (s->seg_manager->freeDynmem(argv[1])) {
- error("Attempt to kMemory::free() non-dynmem pointer "PREG"!\n", PRINT_REG(argv[1]));
- }
- break;
- case K_MEMORY_MEMCPY : {
- int size = UKPV(3);
- byte *dest = kernel_dereference_bulk_pointer(s, argv[1], size);
- byte *src = kernel_dereference_bulk_pointer(s, argv[2], size);
-
- if (dest && src)
- memcpy(dest, src, size);
- else {
- warning("Could not execute kMemory:memcpy of %d bytes:", size);
- if (!dest) {
- warning(" dest ptr ("PREG") invalid/memory region too small", PRINT_REG(argv[1]));
- }
- if (!src) {
- warning(" src ptr ("PREG") invalid/memory region too small", PRINT_REG(argv[2]));
- }
- }
- break;
- }
- case K_MEMORY_PEEK : {
- byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
-
- if (!ref) {
- error("Attempt to poke invalid memory at "PREG"!\n", PRINT_REG(argv[1]));
- return s->r_acc;
- }
- if (s->seg_manager->_heap[argv[1].segment]->getType() == MEM_OBJ_LOCALS)
- return *((reg_t *) ref);
- else
- return make_reg(0, (int16)READ_LE_UINT16(ref));
- break;
- }
- case K_MEMORY_POKE : {
- byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
-
- if (!ref) {
- error("Attempt to poke invalid memory at "PREG"!\n", PRINT_REG(argv[1]));
- return s->r_acc;
- }
-
- if (s->seg_manager->_heap[argv[1].segment]->getType() == MEM_OBJ_LOCALS)
- *((reg_t *) ref) = argv[2];
- else {
- if (argv[2].segment) {
- error("Attempt to poke memory reference "PREG" to "PREG"!\n", PRINT_REG(argv[2]), PRINT_REG(argv[1]));
- return s->r_acc;
- WRITE_LE_UINT16(ref, argv[2].offset); // ???
- }
- }
- return s->r_acc;
- break;
- }
- }
-
- return s->r_acc;
-}
-
-reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- int i;
-
- sciprintf("Unimplemented syscall: %s[%x](", s->_kernelNames[funct_nr].c_str(), funct_nr);
-
- for (i = 0; i < argc; i++) {
- sciprintf(PREG, PRINT_REG(argv[i]));
- if (i + 1 < argc) sciprintf(", ");
- }
- sciprintf(")\n");
-
- return NULL_REG;
-}
-
-reg_t kNOP(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- warning("Kernel function 0x%02x invoked: unmapped", funct_nr);
-
- if (s->_kfuncTable[funct_nr].orig_name != SCRIPT_UNKNOWN_FUNCTION_STRING) {
- warning(" (but its name is known to be %s)", s->_kfuncTable[funct_nr].orig_name.c_str());
- }
-
- return NULL_REG;
-}
void kernel_compile_signature(const char **s) {
const char *src = *s;
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
new file mode 100644
index 0000000000..84c45a205a
--- /dev/null
+++ b/engines/sci/engine/kmisc.cpp
@@ -0,0 +1,282 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+
+#include <time.h> // FIXME: For struct tm
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/engine/kernel.h"
+#include "sci/engine/gc.h"
+
+namespace Sci {
+
+char *old_save_dir; // FIXME get rid of this
+
+reg_t kRestartGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
+
+ old_save_dir = strdup(deref_save_dir);
+ s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
+ s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; // This appears to help
+ s->_executionStack.resize(s->execution_stack_base + 1);
+ script_abort_flag = 1; // Force vm to abort ASAP
+ return NULL_REG;
+}
+
+/* kGameIsRestarting():
+** Returns the restarting_flag in acc
+*/
+reg_t kGameIsRestarting(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
+
+ if (old_save_dir && deref_save_dir) {
+ strcpy(deref_save_dir, old_save_dir);
+ free(old_save_dir);
+ old_save_dir = NULL;
+ }
+
+ s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED));
+
+ if (argc) { // Only happens during replay
+ if (!UKPV(0)) // Set restarting flag
+ s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED;
+ }
+
+ return s->r_acc;
+}
+
+reg_t kHaveMouse(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ return make_reg(0, -1);
+}
+
+reg_t kMemoryInfo(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ switch (argv[0].offset) {
+ case 0: // Total free heap memory
+ case 1: // Largest heap block available
+ case 2: // Largest available hunk memory block
+ case 3: // Total amount of hunk memory
+ case 4: // Amount of free DOS paragraphs- SCI01
+ return make_reg(0, 0x7fff); // Must not be 0xffff, or some memory calculations will overflow
+
+ default:
+ warning("Unknown MemoryInfo operation: %04x", argv[0].offset);
+ }
+
+ return NULL_REG;
+}
+
+#define SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR 0x75
+// kfunct_mappers below doubles for unknown kfunctions
+
+reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ if (funct_nr >= SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR) {
+ warning("Unhandled Unknown function %04x", funct_nr);
+ return NULL_REG;
+ } else {
+ switch (kfunct_mappers[funct_nr].type) {
+ case KF_NEW:
+ return kfunct_mappers[funct_nr].fun(s, funct_nr, argc, argv);
+ case KF_NONE:
+ default:
+ warning("Unhandled Unknown function %04x", funct_nr);
+ return NULL_REG;
+ }
+ }
+}
+
+reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ run_gc(s);
+ debugC(2, kDebugLevelRoom, "Entering room number %d", UKPV(0));
+ return s->r_acc;
+}
+
+reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ sciprintf("Debug mode activated\n");
+
+ script_debug_flag = 1; // Enter debug mode
+ _debug_seeking = _debug_step_running = 0;
+ return s->r_acc;
+}
+
+#define _K_NEW_GETTIME_TICKS 0
+#define _K_NEW_GETTIME_TIME_12HOUR 1
+#define _K_NEW_GETTIME_TIME_24HOUR 2
+#define _K_NEW_GETTIME_DATE 3
+
+reg_t kGetTime(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ tm loc_time;
+ uint32 start_time;
+ int retval = 0; // Avoid spurious warning
+
+#if 0
+ // Reset optimization flags: If this function is called,
+ // the game may be waiting for a timeout
+ s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT);
+#endif
+
+ g_system->getTimeAndDate(loc_time);
+ start_time = g_system->getMillis() - s->game_start_time;
+
+ if (argc && s->flags & GF_SCI0_OLDGETTIME) { // Use old semantics
+ retval = loc_time.tm_sec + loc_time.tm_min * 60 + (loc_time.tm_hour % 12) * 3600;
+ debugC(2, kDebugLevelTime, "GetTime(timeofday) returns %d", retval);
+ return make_reg(0, retval);
+ }
+
+ int mode = UKPV_OR_ALT(0, 0);
+
+ switch (mode) {
+ case _K_NEW_GETTIME_TICKS :
+ retval = start_time * 60 / 1000;
+ debugC(2, kDebugLevelTime, "GetTime(elapsed) returns %d", retval);
+ break;
+ case _K_NEW_GETTIME_TIME_12HOUR :
+ loc_time.tm_hour %= 12;
+ retval = (loc_time.tm_min << 6) | (loc_time.tm_hour << 12) | (loc_time.tm_sec);
+ debugC(2, kDebugLevelTime, "GetTime(12h) returns %d", retval);
+ break;
+ case _K_NEW_GETTIME_TIME_24HOUR :
+ retval = (loc_time.tm_min << 5) | (loc_time.tm_sec >> 1) | (loc_time.tm_hour << 11);
+ debugC(2, kDebugLevelTime, "GetTime(24h) returns %d", retval);
+ break;
+ case _K_NEW_GETTIME_DATE :
+ retval = ((loc_time.tm_mon + 1) << 5) | loc_time.tm_mday | (((loc_time.tm_year + 1900) & 0x7f) << 9);
+ debugC(2, kDebugLevelTime, "GetTime(date) returns %d", retval);
+ break;
+ default:
+ warning("Attempt to use unknown GetTime mode %d", mode);
+ break;
+ }
+
+ return make_reg(0, retval);
+}
+
+#define K_MEMORY_ALLOCATE_CRITICAL 1
+#define K_MEMORY_ALLOCATE_NONCRITICAL 2
+#define K_MEMORY_FREE 3
+#define K_MEMORY_MEMCPY 4
+#define K_MEMORY_PEEK 5
+#define K_MEMORY_POKE 6
+
+reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ switch (UKPV(0)) {
+ case K_MEMORY_ALLOCATE_CRITICAL :
+ if (!s->seg_manager->allocDynmem(UKPV(1), "kMemory() critical", &s->r_acc)) {
+ error("Critical heap allocation failed\n");
+ script_error_flag = script_debug_flag = 1;
+ }
+ return s->r_acc;
+ break;
+ case K_MEMORY_ALLOCATE_NONCRITICAL :
+ s->seg_manager->allocDynmem(UKPV(1), "kMemory() non-critical", &s->r_acc);
+ break;
+ case K_MEMORY_FREE :
+ if (s->seg_manager->freeDynmem(argv[1])) {
+ error("Attempt to kMemory::free() non-dynmem pointer "PREG"!\n", PRINT_REG(argv[1]));
+ }
+ break;
+ case K_MEMORY_MEMCPY : {
+ int size = UKPV(3);
+ byte *dest = kernel_dereference_bulk_pointer(s, argv[1], size);
+ byte *src = kernel_dereference_bulk_pointer(s, argv[2], size);
+
+ if (dest && src)
+ memcpy(dest, src, size);
+ else {
+ warning("Could not execute kMemory:memcpy of %d bytes:", size);
+ if (!dest) {
+ warning(" dest ptr ("PREG") invalid/memory region too small", PRINT_REG(argv[1]));
+ }
+ if (!src) {
+ warning(" src ptr ("PREG") invalid/memory region too small", PRINT_REG(argv[2]));
+ }
+ }
+ break;
+ }
+ case K_MEMORY_PEEK : {
+ byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
+
+ if (!ref) {
+ error("Attempt to poke invalid memory at "PREG"!\n", PRINT_REG(argv[1]));
+ return s->r_acc;
+ }
+ if (s->seg_manager->_heap[argv[1].segment]->getType() == MEM_OBJ_LOCALS)
+ return *((reg_t *) ref);
+ else
+ return make_reg(0, (int16)READ_LE_UINT16(ref));
+ break;
+ }
+ case K_MEMORY_POKE : {
+ byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
+
+ if (!ref) {
+ error("Attempt to poke invalid memory at "PREG"!\n", PRINT_REG(argv[1]));
+ return s->r_acc;
+ }
+
+ if (s->seg_manager->_heap[argv[1].segment]->getType() == MEM_OBJ_LOCALS)
+ *((reg_t *) ref) = argv[2];
+ else {
+ if (argv[2].segment) {
+ error("Attempt to poke memory reference "PREG" to "PREG"!\n", PRINT_REG(argv[2]), PRINT_REG(argv[1]));
+ return s->r_acc;
+ WRITE_LE_UINT16(ref, argv[2].offset); // ?
+ }
+ }
+ return s->r_acc;
+ break;
+ }
+ }
+
+ return s->r_acc;
+}
+
+reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ int i;
+
+ sciprintf("Unimplemented syscall: %s[%x](", s->_kernelNames[funct_nr].c_str(), funct_nr);
+
+ for (i = 0; i < argc; i++) {
+ sciprintf(PREG, PRINT_REG(argv[i]));
+ if (i + 1 < argc) sciprintf(", ");
+ }
+ sciprintf(")\n");
+
+ return NULL_REG;
+}
+
+reg_t kNOP(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+ warning("Kernel function 0x%02x invoked: unmapped", funct_nr);
+
+ if (s->_kfuncTable[funct_nr].orig_name != SCRIPT_UNKNOWN_FUNCTION_STRING) {
+ warning(" (but its name is known to be %s)", s->_kfuncTable[funct_nr].orig_name.c_str());
+ }
+
+ return NULL_REG;
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 441552f5bd..08318aad2a 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS = \
engine/klists.o \
engine/kmath.o \
engine/kmenu.o \
+ engine/kmisc.o \
engine/kmovement.o \
engine/kpathing.o \
engine/kscripts.o \