SCI: Moved the few kernel functions that were in kernel.cpp to a new file kmisc.cpp
svn-id: r40738
This commit is contained in:
parent
6be7da1c83
commit
f5f48fff3a
3 changed files with 283 additions and 249 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue