diff options
author | Max Horn | 2009-05-20 17:51:55 +0000 |
---|---|---|
committer | Max Horn | 2009-05-20 17:51:55 +0000 |
commit | f5f48fff3a8de6ac2f0bcb54514dd955009c3742 (patch) | |
tree | 8ef1dc18a4f828a2d3710ae452aba43a91124443 | |
parent | 6be7da1c8395addcfaf04981e593d52ec15f70f0 (diff) | |
download | scummvm-rg350-f5f48fff3a8de6ac2f0bcb54514dd955009c3742.tar.gz scummvm-rg350-f5f48fff3a8de6ac2f0bcb54514dd955009c3742.tar.bz2 scummvm-rg350-f5f48fff3a8de6ac2f0bcb54514dd955009c3742.zip |
SCI: Moved the few kernel functions that were in kernel.cpp to a new file kmisc.cpp
svn-id: r40738
-rw-r--r-- | engines/sci/engine/kernel.cpp | 249 | ||||
-rw-r--r-- | engines/sci/engine/kmisc.cpp | 282 | ||||
-rw-r--r-- | engines/sci/module.mk | 1 |
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 \ |