From 634e0234852ebb37d6cb10bc627d84ebaf35d56f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 4 Jun 2009 08:25:48 +0000 Subject: Turned debug_weak_validations on by default again, as apparently some games like SQ3 fail in some validations (e.g. when loading). Also, fixed a potential out of bounds access when copying the value of __FILE__ into a buffer (as its value can be quite long in some cases). svn-id: r41154 --- engines/sci/console.cpp | 2 +- engines/sci/engine/vm.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 67e324f078..baf89a5082 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -50,7 +50,7 @@ extern EngineState *g_EngineState; int debug_sleeptime_factor = 1; int debug_simulated_key = 0; bool debug_track_mouse_clicks = false; -bool debug_weak_validations = false; +bool debug_weak_validations = true; Console::Console(SciEngine *vm) : GUI::Debugger() { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 18e1ef7866..3539032760 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -121,15 +121,13 @@ static int validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int if (index < 0 || index >= max) { char txt[200]; char tmp[40]; - sprintf(txt, "[VM] Attempt to use invalid %s variable %04x ", names[type], index); + sprintf(txt, "[VM] validate_variable(): Attempt to use invalid %s variable %04x ", names[type], index); if (max == 0) strcat(txt, "(variable type invalid)"); else { sprintf(tmp, "(out of range [%d..%d])", 0, max - 1); strcat(txt, tmp); } - sprintf(tmp, " in %s, line %d\n", __FILE__, line); - strcat(txt, tmp); if (debug_weak_validations) warning(txt); -- cgit v1.2.3 From 70effa46e55100630df3b902918c75e77d505188 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 4 Jun 2009 08:28:20 +0000 Subject: Reordered the numpad keys so that they make more sense, and simplified the code which returns the values of shifted function keys svn-id: r41155 --- engines/sci/gfx/operations.cpp | 26 +++----------------------- engines/sci/uinput.h | 36 ++++++++++++++---------------------- 2 files changed, 17 insertions(+), 45 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index 7ab1bc28cd..49c73ac0fd 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -1326,28 +1326,8 @@ int _gfxop_shiftify(int c) { } } - switch (c) { - case SCI_K_F1 : - return SCI_K_SHIFT_F1; - case SCI_K_F2 : - return SCI_K_SHIFT_F2; - case SCI_K_F3 : - return SCI_K_SHIFT_F3; - case SCI_K_F4 : - return SCI_K_SHIFT_F4; - case SCI_K_F5 : - return SCI_K_SHIFT_F5; - case SCI_K_F6 : - return SCI_K_SHIFT_F6; - case SCI_K_F7 : - return SCI_K_SHIFT_F7; - case SCI_K_F8 : - return SCI_K_SHIFT_F8; - case SCI_K_F9 : - return SCI_K_SHIFT_F9; - case SCI_K_F10 : - return SCI_K_SHIFT_F10; - } + if (c >= SCI_K_F1 && c <= SCI_K_F10) + return c + 25; return c; } @@ -1488,7 +1468,7 @@ static sci_event_t scummvm_get_event(gfx_driver_t *drv) { // SCI_K_SHIFT_F1 == 84 << 8 input.data = SCI_K_F1 + ((input.data - Common::KEYCODE_F1)<<8); if (input.buckybits & (SCI_EVM_LSHIFT | SCI_EVM_RSHIFT)) - input.character = input.data + SCI_K_SHIFT_F1 - SCI_K_F1; + input.character = input.data + 25; else input.character = input.data; } else { diff --git a/engines/sci/uinput.h b/engines/sci/uinput.h index 165396a889..062265186b 100644 --- a/engines/sci/uinput.h +++ b/engines/sci/uinput.h @@ -72,17 +72,20 @@ struct sci_event_t { #define SCI_K_TAB '\t' #define SCI_K_SHIFT_TAB (0xf << 8) -#define SCI_K_END (79 << 8) -#define SCI_K_DOWN (80 << 8) -#define SCI_K_PGDOWN (81 << 8) -#define SCI_K_LEFT (75 << 8) -#define SCI_K_CENTER (76 << 8) -#define SCI_K_RIGHT (77 << 8) -#define SCI_K_HOME (71 << 8) -#define SCI_K_UP (72 << 8) -#define SCI_K_PGUP (73 << 8) -#define SCI_K_INSERT (82 << 8) -#define SCI_K_DELETE (83 << 8) +#define SCI_K_HOME (71 << 8) // 7 +#define SCI_K_UP (72 << 8) // 8 +#define SCI_K_PGUP (73 << 8) // 9 +// +#define SCI_K_LEFT (75 << 8) // 4 +#define SCI_K_CENTER (76 << 8) // 5 +#define SCI_K_RIGHT (77 << 8) // 6 +// +#define SCI_K_END (79 << 8) // 1 +#define SCI_K_DOWN (80 << 8) // 2 +#define SCI_K_PGDOWN (81 << 8) // 3 +// +#define SCI_K_INSERT (82 << 8) // 0 +#define SCI_K_DELETE (83 << 8) // . #define SCI_K_F1 (59<<8) #define SCI_K_F2 (60<<8) @@ -95,17 +98,6 @@ struct sci_event_t { #define SCI_K_F9 (67<<8) #define SCI_K_F10 (68<<8) -#define SCI_K_SHIFT_F1 (84<<8) -#define SCI_K_SHIFT_F2 (85<<8) -#define SCI_K_SHIFT_F3 (86<<8) -#define SCI_K_SHIFT_F4 (87<<8) -#define SCI_K_SHIFT_F5 (88<<8) -#define SCI_K_SHIFT_F6 (89<<8) -#define SCI_K_SHIFT_F7 (90<<8) -#define SCI_K_SHIFT_F8 (91<<8) -#define SCI_K_SHIFT_F9 (92<<8) -#define SCI_K_SHIFT_F10 (93<<8) - /*Values for buckybits */ #define SCI_EVM_RSHIFT (1<<0) #define SCI_EVM_LSHIFT (1<<1) -- cgit v1.2.3 From 382ebea3faa5f824ba385b9837c4106b6c1fe3c7 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 11:28:05 +0000 Subject: SCI: Renamed various debug related global variables to have a g_ prefix; and moved any 'extern' decls of them into a new header file svn-id: r41163 --- engines/sci/console.cpp | 27 ++++----- engines/sci/debug.h | 47 +++++++++++++++ engines/sci/engine/kernel.h | 5 -- engines/sci/engine/kevent.cpp | 23 ++++---- engines/sci/engine/kgraphics.cpp | 8 +-- engines/sci/engine/kmisc.cpp | 3 +- engines/sci/engine/scriptdebug.cpp | 113 +++++++++++++++++++------------------ engines/sci/engine/vm.cpp | 34 +++++------ engines/sci/engine/vm.h | 5 -- 9 files changed, 148 insertions(+), 117 deletions(-) create mode 100644 engines/sci/debug.h (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index baf89a5082..047c18bbb4 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -27,6 +27,7 @@ #include "sci/sci.h" #include "sci/console.h" +#include "sci/debug.h" #include "sci/resource.h" #include "sci/vocabulary.h" #include "sci/engine/savegame.h" @@ -47,21 +48,21 @@ namespace Sci { extern EngineState *g_EngineState; -int debug_sleeptime_factor = 1; -int debug_simulated_key = 0; -bool debug_track_mouse_clicks = false; -bool debug_weak_validations = true; +int g_debug_sleeptime_factor = 1; +int g_debug_simulated_key = 0; +bool g_debug_track_mouse_clicks = false; +bool g_debug_weak_validations = true; Console::Console(SciEngine *vm) : GUI::Debugger() { _vm = vm; // Variables - DVar_Register("sleeptime_factor", &debug_sleeptime_factor, DVAR_INT, 0); + DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0); DVar_Register("gc_interval", &script_gc_interval, DVAR_INT, 0); - DVar_Register("simulated_key", &debug_simulated_key, DVAR_INT, 0); - DVar_Register("track_mouse_clicks", &debug_track_mouse_clicks, DVAR_BOOL, 0); - DVar_Register("weak_validations", &debug_weak_validations, DVAR_BOOL, 0); + DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); + DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); + DVar_Register("weak_validations", &g_debug_weak_validations, DVAR_BOOL, 0); // General DCmd_Register("help", WRAP_METHOD(Console, cmdHelp)); @@ -667,7 +668,7 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { g_EngineState->successor = newstate; // Set successor script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game - _debugstate_valid = 0; + g_debugstate_valid = 0; shrink_execution_stack(g_EngineState, g_EngineState->execution_stack_base + 1); return 0; @@ -698,7 +699,7 @@ bool Console::cmdRestartGame(int argc, const char **argv) { g_EngineState->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; script_abort_flag = 1; - _debugstate_valid = 0; + g_debugstate_valid = 0; return false; } @@ -2347,9 +2348,9 @@ bool Console::cmdExit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully script_abort_flag = 1; // Terminate VM - _debugstate_valid = 0; - _debug_seeking = 0; - _debug_step_running = 0; + g_debugstate_valid = 0; + g_debug_seeking = 0; + g_debug_step_running = 0; } else if (!scumm_stricmp(argv[1], "now")) { // Quit ungracefully diff --git a/engines/sci/debug.h b/engines/sci/debug.h new file mode 100644 index 0000000000..ec44838826 --- /dev/null +++ b/engines/sci/debug.h @@ -0,0 +1,47 @@ +/* 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$ + * + */ + +#ifndef SCI_DEBUG_H +#define SCI_DEBUG_H + +namespace Sci { + +// Various global variables used for debugging are declared here + +extern int g_stop_on_event; + +extern int g_debugstate_valid; +extern int g_debug_seeking; +extern int g_debug_step_running; + +extern int g_debug_sleeptime_factor; +extern int g_debug_simulated_key; +extern bool g_debug_track_mouse_clicks; +extern bool g_debug_weak_validations; + + +} // End of namespace Sci + +#endif diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 862ca2514e..0db5b9205b 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -38,11 +38,6 @@ namespace Sci { struct Node; // from vm.h struct List; // from vm.h -extern int stop_on_event; - -extern int _debug_seeking; -extern int _debug_step_running; - #define AVOIDPATH_DYNMEM_STRING "AvoidPath polyline" //#define DEBUG_PARSER // enable for parser debugging diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index c0a137469e..b275e9c0b9 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -28,13 +28,12 @@ #include "sci/engine/kernel.h" #include "sci/gfx/gfx_widgets.h" #include "sci/gfx/gfx_state_internal.h" // required for GfxPort, GfxVisual -#include "sci/console.h" // for debug_simulated_key +#include "sci/console.h" +#include "sci/debug.h" // for g_debug_simulated_key namespace Sci { -int stop_on_event = 0; -extern int debug_simulated_key; -extern bool debug_track_mouse_clicks; +int g_stop_on_event = 0; #define SCI_VARIABLE_GAME_SPEED 3 @@ -53,13 +52,13 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { // If there's a simkey pending, and the game wants a keyboard event, use the // simkey instead of a normal event - if (debug_simulated_key && (mask & SCI_EVT_KEYBOARD)) { + if (g_debug_simulated_key && (mask & SCI_EVT_KEYBOARD)) { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event - PUT_SEL32V(obj, message, debug_simulated_key); + PUT_SEL32V(obj, message, g_debug_simulated_key); PUT_SEL32V(obj, modifiers, SCI_EVM_NUMLOCK); // Numlock on PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x); PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y); - debug_simulated_key = 0; + g_debug_simulated_key = 0; return make_reg(0, 1); } @@ -91,10 +90,10 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { case SCI_EVT_KEYBOARD: if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) { sciprintf("Debug mode activated\n"); - _debug_seeking = _debug_step_running = 0; + g_debug_seeking = g_debug_step_running = 0; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { sciprintf("Debug mode activated\n"); - _debug_seeking = _debug_step_running = 0; + g_debug_seeking = g_debug_step_running = 0; } else { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event s->r_acc = make_reg(0, 1); @@ -110,7 +109,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { int extra_bits = 0; // track left buttton clicks, if requested - if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && debug_track_mouse_clicks) { + if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && g_debug_track_mouse_clicks) { ((SciEngine *)g_engine)->getDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y); } @@ -138,8 +137,8 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->r_acc = NULL_REG; // Unknown or no event } - if ((s->r_acc.offset) && (stop_on_event)) { - stop_on_event = 0; + if ((s->r_acc.offset) && (g_stop_on_event)) { + g_stop_on_event = 0; } return s->r_acc; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 4c4be0242c..4ccc125eb4 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -27,7 +27,7 @@ #include "common/events.h" #include "sci/sci.h" -#include "sci/console.h" // for debug_sleeptime_factor +#include "sci/debug.h" // for g_debug_sleeptime_factor #include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" @@ -369,8 +369,6 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } -extern int oldx, oldy; - reg_t kMoveCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { Common::Point newpos; @@ -647,8 +645,6 @@ reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } -extern int debug_sleeptime_factor; - reg_t kWait(EngineState *s, int funct_nr, int argc, reg_t *argv) { uint32 time; int sleep_time = UKPV(0); @@ -660,7 +656,7 @@ reg_t kWait(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Reset optimization flags: Game is playing along nicely anyway s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT); - sleep_time *= debug_sleeptime_factor; + sleep_time *= g_debug_sleeptime_factor; GFX_ASSERT(gfxop_sleep(s->gfx_state, sleep_time * 1000 / 60)); return s->r_acc; diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 34d8b5397c..3673dbe3c4 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -28,6 +28,7 @@ #include // FIXME: For struct tm #include "sci/sci.h" +#include "sci/debug.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/gc.h" @@ -95,7 +96,7 @@ reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) { sciprintf("Debug mode activated\n"); - _debug_seeking = _debug_step_running = 0; + g_debug_seeking = g_debug_step_running = 0; return s->r_acc; } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 1f750abe58..f78362a320 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -26,6 +26,7 @@ // Script debugger functionality. Absolutely not threadsafe. #include "sci/sci.h" +#include "sci/debug.h" #include "sci/engine/state.h" #include "sci/engine/gc.h" #include "sci/engine/kernel_types.h" @@ -46,13 +47,13 @@ namespace Sci { -int _debugstate_valid = 0; // Set to 1 while script_debug is running -int _debug_step_running = 0; // Set to >0 to allow multiple stepping -int _debug_commands_not_hooked = 1; // Commands not hooked to the console yet? -int _debug_seeking = 0; // Stepping forward until some special condition is met -int _debug_seek_level = 0; // Used for seekers that want to check their exec stack depth -int _debug_seek_special = 0; // Used for special seeks(1) -reg_t _debug_seek_reg = NULL_REG; // Used for special seeks(2) +int g_debugstate_valid = 0; // Set to 1 while script_debug is running +int g_debug_step_running = 0; // Set to >0 to allow multiple stepping +static bool s_debug_commands_hooked = false; // Commands hooked to the console yet? +int g_debug_seeking = 0; // Stepping forward until some special condition is met +static int s_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth +static int s_debug_seek_special = 0; // Used for special seeks(1) +static reg_t s_debug_seek_reg = NULL_REG; // Used for special seeks(2) #define _DEBUG_SEEK_NOTHING 0 #define _DEBUG_SEEK_CALLK 1 // Step forward until callk is found @@ -121,9 +122,9 @@ static const char *_debug_get_input() { } int c_step(EngineState *s, const Common::Array &cmdParams) { - _debugstate_valid = 0; + g_debugstate_valid = 0; if (cmdParams.size() && (cmdParams[0].val > 0)) - _debug_step_running = cmdParams[0].val - 1; + g_debug_step_running = cmdParams[0].val - 1; return 0; } @@ -133,39 +134,39 @@ int c_step(EngineState *s, const Common::Array &cmdParams) { int c_stepover(EngineState *s, const Common::Array &cmdParams) { int opcode, opnumber; - if (!_debugstate_valid) { + if (!g_debugstate_valid) { sciprintf("Not in debug state\n"); return 1; } - _debugstate_valid = 0; + g_debugstate_valid = 0; opcode = s->_heap[*p_pc]; opnumber = opcode >> 1; if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { - _debug_seeking = _DEBUG_SEEK_SO; - _debug_seek_level = s->_executionStack.size()-1; - // Store in _debug_seek_special the offset of the next command after send + g_debug_seeking = _DEBUG_SEEK_SO; + s_debug_seek_level = s->_executionStack.size()-1; + // Store in s_debug_seek_special the offset of the next command after send switch (opcode) { case 0x46: // calle W - _debug_seek_special = *p_pc + 5; + s_debug_seek_special = *p_pc + 5; break; case 0x44: // callb W case 0x47: // calle B case 0x56: // super W - _debug_seek_special = *p_pc + 4; + s_debug_seek_special = *p_pc + 4; break; case 0x45: // callb B case 0x57: // super B case 0x4A: // send W case 0x54: // self W - _debug_seek_special = *p_pc + 3; + s_debug_seek_special = *p_pc + 3; break; default: - _debug_seek_special = *p_pc + 2; + s_debug_seek_special = *p_pc + 2; } } @@ -319,7 +320,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod opsize = scr[pos.offset]; opcode = opsize >> 1; - if (!_debugstate_valid) { + if (!g_debugstate_valid) { sciprintf("Not in debug state\n"); return retval; } @@ -540,7 +541,7 @@ extern GfxWidget *debug_widgets[]; extern int debug_widget_pos; static int c_gfx_print_widget(EngineState *s, const Common::Array &cmdParams) { - if (!_debugstate_valid) { + if (!g_debugstate_valid) { sciprintf("Not in debug state\n"); return 1; } @@ -695,9 +696,9 @@ static int c_disasm(EngineState *s, const Common::Array &cmdParams) } static int c_sg(EngineState *s, const Common::Array &cmdParams) { - _debug_seeking = _DEBUG_SEEK_GLOBAL; - _debug_seek_special = cmdParams[0].val; - _debugstate_valid = 0; + g_debug_seeking = _DEBUG_SEEK_GLOBAL; + s_debug_seek_special = cmdParams[0].val; + g_debugstate_valid = 0; return 0; } @@ -706,7 +707,7 @@ static int c_snk(EngineState *s, const Common::Array &cmdParams) { int callk_index; char *endptr; - if (!_debugstate_valid) { + if (!g_debugstate_valid) { sciprintf("Not in debug state\n"); return 1; } @@ -730,27 +731,27 @@ static int c_snk(EngineState *s, const Common::Array &cmdParams) { } } - _debug_seeking = _DEBUG_SEEK_SPECIAL_CALLK; - _debug_seek_special = callk_index; - _debugstate_valid = 0; + g_debug_seeking = _DEBUG_SEEK_SPECIAL_CALLK; + s_debug_seek_special = callk_index; + g_debugstate_valid = 0; } else { - _debug_seeking = _DEBUG_SEEK_CALLK; - _debugstate_valid = 0; + g_debug_seeking = _DEBUG_SEEK_CALLK; + g_debugstate_valid = 0; } return 0; } static int c_sret(EngineState *s, const Common::Array &cmdParams) { - _debug_seeking = _DEBUG_SEEK_LEVEL_RET; - _debug_seek_level = s->_executionStack.size()-1; - _debugstate_valid = 0; + g_debug_seeking = _DEBUG_SEEK_LEVEL_RET; + s_debug_seek_level = s->_executionStack.size()-1; + g_debugstate_valid = 0; return 0; } static int c_go(EngineState *s, const Common::Array &cmdParams) { - _debug_seeking = 0; - _debugstate_valid = 0; + g_debug_seeking = 0; + g_debugstate_valid = 0; return 0; } @@ -899,8 +900,8 @@ static void viewobjinfo(EngineState *s, HeapPtr pos) { // Breakpoint commands int c_se(EngineState *s, const Common::Array &cmdParams) { - stop_on_event = 1; - _debugstate_valid = 0; + g_stop_on_event = 1; + g_debugstate_valid = 0; return 0; } @@ -909,7 +910,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) { // Do we support a separate console? - int old_debugstate = _debugstate_valid; + int old_debugstate = g_debugstate_valid; p_var_segs = segids; p_vars = variables; @@ -921,15 +922,15 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * p_objp = objp; p_restadjust = restadjust; sciprintf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); - _debugstate_valid = 1; + g_debugstate_valid = 1; disassemble(s, *pc, 0, 1); - if (_debug_seeking == _DEBUG_SEEK_GLOBAL) - sciprintf("Global %d (0x%x) = %04x:%04x\n", _debug_seek_special, - _debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[_debug_seek_special])); + if (g_debug_seeking == _DEBUG_SEEK_GLOBAL) + sciprintf("Global %d (0x%x) = %04x:%04x\n", s_debug_seek_special, + s_debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[s_debug_seek_special])); - _debugstate_valid = old_debugstate; + g_debugstate_valid = old_debugstate; - if (_debug_seeking && !bp) { // Are we looking for something special? + if (g_debug_seeking && !bp) { // Are we looking for something special? MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); if (mobj) { @@ -941,9 +942,9 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * int paramb1 = pc->offset + 1 >= code_buf_size ? 0 : code_buf[pc->offset + 1]; int paramf1 = (opcode & 1) ? paramb1 : (pc->offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + pc->offset + 1)); - switch (_debug_seeking) { + switch (g_debug_seeking) { case _DEBUG_SEEK_SPECIAL_CALLK: - if (paramb1 != _debug_seek_special) + if (paramb1 != s_debug_seek_special) return; case _DEBUG_SEEK_CALLK: { @@ -953,13 +954,13 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * } case _DEBUG_SEEK_LEVEL_RET: { - if ((op != op_ret) || (_debug_seek_level < (int)s->_executionStack.size()-1)) + if ((op != op_ret) || (s_debug_seek_level < (int)s->_executionStack.size()-1)) return; break; } case _DEBUG_SEEK_SO: - if ((*pc != _debug_seek_reg) || (int)s->_executionStack.size()-1 != _debug_seek_level) + if ((*pc != s_debug_seek_reg) || (int)s->_executionStack.size()-1 != s_debug_seek_level) return; break; @@ -971,20 +972,20 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * return; // param or temp if ((op & 0x3) && s->_executionStack.back().local_segment > 0) return; // locals and not running in script.000 - if (paramf1 != _debug_seek_special) + if (paramf1 != s_debug_seek_special) return; // CORRECT global? break; } - _debug_seeking = _DEBUG_SEEK_NOTHING; + g_debug_seeking = _DEBUG_SEEK_NOTHING; // OK, found whatever we were looking for } } - _debugstate_valid = (_debug_step_running == 0); + g_debugstate_valid = (g_debug_step_running == 0); - if (_debugstate_valid) { + if (g_debugstate_valid) { p_pc = pc; p_sp = sp; p_pp = pp; @@ -998,8 +999,8 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * sciprintf("Step #%d\n", script_step_counter); disassemble(s, *pc, 0, 1); - if (_debug_commands_not_hooked) { - _debug_commands_not_hooked = 0; + if (!s_debug_commands_hooked) { + s_debug_commands_hooked = true; con_hook_command(c_step, "s", "i*", "Executes one or several operations\n\nEXAMPLES\n\n" " s 4\n\n Execute 4 commands\n\n s\n\n Execute next command"); @@ -1043,10 +1044,10 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * } // If commands were not hooked up } - if (_debug_step_running) - _debug_step_running--; + if (g_debug_step_running) + g_debug_step_running--; - while (_debugstate_valid) { + while (g_debugstate_valid) { int skipfirst = 0; const char *commandstring; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3539032760..345dcc5b9f 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -27,7 +27,7 @@ #include "common/stack.h" #include "sci/sci.h" -#include "sci/console.h" // for debug_weak_validations +#include "sci/debug.h" // for g_debug_weak_validations #include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/intmap.h" @@ -46,17 +46,13 @@ reg_t NULL_REG = {0, 0}; #undef STRICT_READ // Disallows reading from out-of-bounds parameters and locals -int script_abort_flag = 0; // Set to 1 to abort execution -int script_step_counter = 0; // Counts the number of steps executed -int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs +int script_abort_flag = 0; // Set to 1 to abort execution // FIXME: Avoid non-const global vars +int script_step_counter = 0; // Counts the number of steps executed // FIXME: Avoid non-const global vars +int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME: Avoid non-const global vars -extern int _debug_step_running; -extern int _debug_seeking; -extern bool debug_weak_validations; - -static bool breakpointFlag = false; -static reg_t _dummy_register; +static bool breakpointFlag = false; // FIXME: Avoid non-const global vars +static reg_t _dummy_register; // FIXME: Avoid non-const global vars // validation functionality @@ -90,7 +86,7 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) { static int validate_arithmetic(reg_t reg) { if (reg.segment) { - if (debug_weak_validations) + if (g_debug_weak_validations) warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment); else error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment); @@ -102,7 +98,7 @@ static int validate_arithmetic(reg_t reg) { static int signed_validate_arithmetic(reg_t reg) { if (reg.segment) { - if (debug_weak_validations) + if (g_debug_weak_validations) warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment); else error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment); @@ -129,7 +125,7 @@ static int validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int strcat(txt, tmp); } - if (debug_weak_validations) + if (g_debug_weak_validations) warning(txt); else error(txt); @@ -400,7 +396,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt default: sciprintf("Send error: Variable selector %04x in %04x:%04x called with %04x params\n", selector, PRINT_REG(send_obj), argc); script_debug_flag = 1; // Enter debug mode - _debug_seeking = _debug_step_running = 0; + g_debug_seeking = g_debug_step_running = 0; #endif } break; @@ -1431,8 +1427,8 @@ void run_vm(EngineState *s, int restoring) { #if 0 if (script_error_flag) { - _debug_step_running = 0; // Stop multiple execution - _debug_seeking = 0; // Stop special seeks + g_debug_step_running = 0; // Stop multiple execution + g_debug_seeking = 0; // Stop special seeks xs->addr.pc.offset = old_pc_offset; xs->sp = old_sp; } else @@ -2065,9 +2061,9 @@ const char *obj_get_name(EngineState *s, reg_t pos) { void quit_vm() { script_abort_flag = 1; // Terminate VM - _debugstate_valid = 0; - _debug_seeking = 0; - _debug_step_running = 0; + g_debugstate_valid = 0; + g_debug_seeking = 0; + g_debug_step_running = 0; } void shrink_execution_stack(EngineState *s, uint size) { diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 84e6cc4923..d7703e371e 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -806,11 +806,6 @@ extern int script_gc_interval; extern int script_step_counter; -extern int _debugstate_valid; -extern int _debug_seeking; -extern int _debug_step_running; - - typedef int kernel_function(struct EngineState *s); extern kernel_function* kfuncs[]; -- cgit v1.2.3 From 28242d289b4363a94143432a2e596d5beace0dcc Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 4 Jun 2009 11:35:17 +0000 Subject: SCI: Support for 16-bit DPCM. svn-id: r41164 --- engines/sci/engine/kscripts.cpp | 2 +- engines/sci/resource.cpp | 113 +++++++++++++++++++++++++++++----------- 2 files changed, 85 insertions(+), 30 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index abdf2b0447..e400cb0827 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -169,7 +169,7 @@ reg_t kResCheck(EngineState *s, int funct_nr, int argc, reg_t *argv) { uint seq = UKPV(5); warning("ResCheck: checking for currently unsupported %s resource: module %i; tuple (%i, %i, %i, %i)", getResourceTypeName(restype), module, noun, verb, cond, seq); - return NULL_REG; + return make_reg(0, 1); } default: Resource *res = s->resmgr->testResource(restype, UKPV(1)); diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index f9ae45b6cd..f946f753d4 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1178,7 +1178,7 @@ void ResourceSync::stopSync() { AudioResource::AudioResource(ResourceManager *resMgr, int sciVersion) { _resMgr = resMgr; _sciVersion = sciVersion; - _audioRate = 0; + _audioRate = 11025; _lang = 0; _audioMapSCI1 = 0; _audioMapSCI11 = 0; @@ -1269,8 +1269,8 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 // b cond // b seq // tb cOffset (cumulative offset) - // w syncSize (iff seq has bits 7 and 6 set) - // w syncAscSize (iff seq has bits 7 and 6 set) + // w syncSize (iff seq has bit 7 set) + // w syncAscSize (iff seq has bit 6 set) uint32 n; offset = 0; @@ -1316,21 +1316,32 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 int syncSkip = 0; - if ((n & 0xc0) == 0xc0) { - n ^= 0xc0; + if (n & 0x80) { + n ^= 0x80; if (getSync) { if (size) *size = READ_UINT16(ptr); } else { - syncSkip = READ_UINT16(ptr) + READ_UINT16(ptr + 2); - offset += syncSkip; + syncSkip = READ_UINT16(ptr); } + ptr += 2; + + if (n & 0x40) { + n ^= 0x40; + + if (!getSync) + syncSkip += READ_UINT16(ptr); + + ptr += 2; + } + + offset += syncSkip; + if (n == audioNumber) return true; - ptr += 4; } else { if (n == audioNumber) return !getSync; @@ -1343,10 +1354,64 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 return false; } +// FIXME: Move this to sound/adpcm.cpp? +// Note that the 16-bit version is also used in coktelvideo.cpp +static const uint16 tableDPCM16[128] = { + 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, + 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120, + 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0, + 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, + 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280, + 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0, + 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, + 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, + 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0, + 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480, + 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700, + 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, + 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 +}; + +static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21}; + +static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { + int16 *out = (int16 *) soundBuf; + + int32 s = 0; + for (uint32 i = 0; i < n; i++) { + byte b = audioStream.readByte(); + if (b & 0x80) + s -= tableDPCM16[b & 0x7f]; + else + s += tableDPCM16[b]; + + s = CLIP(s, -32768, 32767); + *out++ = TO_BE_16(s); + } +} + +static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) { + if (b & 8) + s -= tableDPCM8[7 - (b & 7)]; + else + s += tableDPCM8[b & 7]; + s = CLIP(s, 0, 255); + *soundBuf = s; +} + +static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { + int32 s = 0x80; + + for (uint i = 0; i < n; i++) { + byte b = audioStream.readByte(); + + deDPCM8Nibble(soundBuf++, s, b >> 4); + deDPCM8Nibble(soundBuf++, s, b & 0xf); + } +} + // Sierra SOL audio file reader // Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio -// TODO: improve this for later versions of the format, as this currently only reads -// raw PCM encoded files (not ADPCM compressed ones) byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 *audioRate, byte *flags) { byte audioFlags; byte type = audioStream->readByte(); @@ -1365,7 +1430,7 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 *flags = 0; if (audioFlags & kSolFlag16Bit) *flags |= Audio::Mixer::FLAG_16BITS; - if ((audioFlags & kSolFlagCompressed) || !(audioFlags & kSolFlagIsSigned)) + if (!(audioFlags & kSolFlagIsSigned)) *flags |= Audio::Mixer::FLAG_UNSIGNED; *size = audioStream->readUint16LE(); @@ -1376,25 +1441,12 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 byte *buffer; if (audioFlags & kSolFlagCompressed) { - if (audioFlags & kSolFlag16Bit) { - warning("Unsupported DPCM mode"); - return NULL; - } - buffer = new byte[*size * 2]; - byte sample = 0x80; - - for (uint i = 0; i < *size; i++) { - const int delta[] = {0, 1, 2, 3, 6, 10, 15, 21, -21, -15, -10, -6, -3, -2, -1, -0}; - - byte b = audioStream->readByte(); - - sample += delta[b >> 4]; - buffer[i * 2] = sample; - sample += delta[b & 0xf]; - buffer[i * 2 + 1] = sample; - } + if (audioFlags & kSolFlag16Bit) + deDPCM16(buffer, *audioStream, *size); + else + deDPCM8(buffer, *audioStream, *size); *size *= 2; } else { @@ -1498,7 +1550,10 @@ Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 vol } } - *sampleLen = size * 60 / _audioRate; + *sampleLen = (Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; + } else { + warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff, + (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff); } return audioStream; -- cgit v1.2.3 From 4f08dc538c91874aadb3abdd16eacee9a9ccccf6 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 11:44:55 +0000 Subject: SCI: cleanup svn-id: r41165 --- engines/sci/engine/vm.h | 13 +++++-------- engines/sci/vocabulary.cpp | 4 ++-- engines/sci/vocabulary.h | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index d7703e371e..70802bb377 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -769,13 +769,13 @@ enum BreakpointType { * Break when selector is executed. data contains (char *) selector name * (in the format Object::Method) */ - BREAK_SELECTOR = 1, + BREAK_SELECTOR, /** * Break when an exported function is called. data contains * script_no << 16 | export_no. */ - BREAK_EXPORT = 2 + BREAK_EXPORT }; struct Breakpoint { @@ -797,7 +797,9 @@ struct Breakpoint { extern int script_abort_flag; /** Number of kernel calls in between gcs; should be < 50000 */ -#define GC_INTERVAL 32768 +enum { + GC_INTERVAL = 32768 +}; /** Initially GC_DELAY, can be set at runtime */ extern int script_gc_interval; @@ -806,11 +808,6 @@ extern int script_gc_interval; extern int script_step_counter; -typedef int kernel_function(struct EngineState *s); - -extern kernel_function* kfuncs[]; -extern int max_instance; - /** * Executes function pubfunct of the specified script. * Parameters: (EngineState *) s: The state which is to be executed with diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp index 216ab211be..accdcc9eb1 100644 --- a/engines/sci/vocabulary.cpp +++ b/engines/sci/vocabulary.cpp @@ -93,7 +93,7 @@ Vocabulary::Vocabulary(ResourceManager *resmgr) : _resmgr(resmgr) { if (_resmgr->_sciVersion < SCI_VERSION_01_VGA && loadParserWords()) { loadSuffixes(); - if (getBranches()) + if (loadBranches()) // Now build a GNF grammar out of this _parserRules = buildGNF(); } else { @@ -247,7 +247,7 @@ void Vocabulary::freeSuffixes() { _parserSuffixes.clear(); } -bool Vocabulary::getBranches() { +bool Vocabulary::loadBranches() { Resource *resource = NULL; if (_vocabVersion == kVocabularySCI0) diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h index c8ed146917..9f0d277ef2 100644 --- a/engines/sci/vocabulary.h +++ b/engines/sci/vocabulary.h @@ -278,7 +278,7 @@ private: * @param branches The rules are stored into this Array * @return true on success, false on error */ - bool getBranches(); + bool loadBranches(); /* Frees a parser rule list as returned by vocab_build_gnf() ** Parameters: (parse_rule_list_t *) rule_list: The rule list to free -- cgit v1.2.3 From 6b1110b82d37c067dec5668d9ddaa1e51e5d0e91 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 11:45:17 +0000 Subject: SCI: Moved MemObject code into a separate source file svn-id: r41166 --- engines/sci/console.h | 1 + engines/sci/engine/memobj.cpp | 399 ++++++++++++++++++++++++++ engines/sci/engine/memobj.h | 556 +++++++++++++++++++++++++++++++++++++ engines/sci/engine/seg_manager.cpp | 360 ------------------------ engines/sci/engine/seg_manager.h | 1 + engines/sci/engine/vm.h | 517 +--------------------------------- engines/sci/module.mk | 1 + 7 files changed, 959 insertions(+), 876 deletions(-) create mode 100644 engines/sci/engine/memobj.cpp create mode 100644 engines/sci/engine/memobj.h (limited to 'engines/sci') diff --git a/engines/sci/console.h b/engines/sci/console.h index f0975837df..b97b14f354 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -33,6 +33,7 @@ namespace Sci { class SciEngine; +struct List; // Refer to the "addresses" command on how to pass address parameters int parse_reg_t(EngineState *s, const char *str, reg_t *dest); diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp new file mode 100644 index 0000000000..ef48270b41 --- /dev/null +++ b/engines/sci/engine/memobj.cpp @@ -0,0 +1,399 @@ +/* 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/endian.h" + +#include "sci/sci.h" +#include "sci/engine/memobj.h" +#include "sci/engine/intmap.h" +#include "sci/engine/seg_manager.h" +#include "sci/engine/state.h" +#include "sci/tools.h" + +namespace Sci { + +MemObject *MemObject::createMemObject(MemObjectType type) { + MemObject *mem = 0; + switch (type) { + case MEM_OBJ_SCRIPT: + mem = new Script(); + break; + case MEM_OBJ_CLONES: + mem = new CloneTable(); + break; + case MEM_OBJ_LOCALS: + mem = new LocalVariables(); + break; + case MEM_OBJ_SYS_STRINGS: + mem = new SystemStrings(); + break; + case MEM_OBJ_STACK: + mem = new DataStack(); + break; + case MEM_OBJ_HUNK: + mem = new HunkTable(); + break; + case MEM_OBJ_STRING_FRAG: + mem = new StringFrag(); + break; + case MEM_OBJ_LISTS: + mem = new ListTable(); + break; + case MEM_OBJ_NODES: + mem = new NodeTable(); + break; + case MEM_OBJ_DYNMEM: + mem = new DynMem(); + break; + default: + error("Unknown MemObject type %d", type); + break; + } + + assert(mem); + mem->_type = type; + return mem; +} + +void Script::freeScript() { + free(buf); + buf = NULL; + buf_size = 0; + + _objects.clear(); + + delete obj_indices; + obj_indices = 0; + _codeBlocks.clear(); +} + +// memory operations + +void Script::mcpyInOut(int dst, const void *src, size_t n) { + if (buf) { + assert(dst + n <= buf_size); + memcpy(buf + dst, src, n); + } +} + +int16 Script::getHeap(uint16 offset) const { + assert(offset + 1 < (int)buf_size); + return READ_LE_UINT16(buf + offset); +// return (buf[offset] | (buf[offset+1]) << 8); +} + +void Script::incrementLockers() { + lockers++; +} + +void Script::decrementLockers() { + if (lockers > 0) + lockers--; +} + +int Script::getLockers() const { + return lockers; +} + +void Script::setLockers(int lockers_) { + lockers = lockers_; +} + +void Script::setExportTableOffset(int offset) { + if (offset) { + export_table = (uint16 *)(buf + offset + 2); + exports_nr = READ_LE_UINT16((byte *)(export_table - 1)); + } else { + export_table = NULL; + exports_nr = 0; + } +} + +void Script::setSynonymsOffset(int offset) { + synonyms = buf + offset; +} + +byte *Script::getSynonyms() const { + return synonyms; +} + +void Script::setSynonymsNr(int n) { + synonyms_nr = n; +} + +int Script::getSynonymsNr() const { + return synonyms_nr; +} + +byte *MemObject::dereference(reg_t pointer, int *size) { + error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment", + PRINT_REG(pointer)); + return NULL; +} + +byte *Script::dereference(reg_t pointer, int *size) { + if (pointer.offset > buf_size) { + sciprintf("Error: Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n", + PRINT_REG(pointer), (uint)buf_size); + return NULL; + } + if (size) + *size = buf_size - pointer.offset; + return (byte *)(buf + pointer.offset); +} + +byte *LocalVariables::dereference(reg_t pointer, int *size) { + // FIXME: The following doesn't seem to be endian safe. + // To fix this, we'd have to always treat the reg_t + // values stored here as in the little endian format. + int count = _locals.size() * sizeof(reg_t); + byte *base = (byte *)&_locals[0]; + + if (size) + *size = count; + + return base + pointer.offset; +} + +byte *DataStack::dereference(reg_t pointer, int *size) { + int count = nr * sizeof(reg_t); + byte *base = (byte *)entries; + + if (size) + *size = count; + + return base + pointer.offset; +} + +byte *DynMem::dereference(reg_t pointer, int *size) { + int count = _size; + byte *base = (byte *)_buf; + + if (size) + *size = count; + + return base + pointer.offset; +} + +byte *SystemStrings::dereference(reg_t pointer, int *size) { + if (size) + *size = strings[pointer.offset].max_size; + if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name) + return (byte *)(strings[pointer.offset].value); + + // This occurs in KQ5CD when interacting with certain objects + warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); + return NULL; +} + + +//-------------------- script -------------------- +reg_t Script::findCanonicAddress(SegManager *segmgr, reg_t addr) { + addr.offset = 0; + return addr; +} + +void Script::freeAtAddress(SegManager *segmgr, reg_t addr) { + /* + sciprintf("[GC] Freeing script %04x:%04x\n", PRINT_REG(addr)); + if (locals_segment) + sciprintf("[GC] Freeing locals %04x:0000\n", locals_segment); + */ + + if (_markedAsDeleted) + segmgr->deallocateScript(nr); +} + +void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { + (*note)(param, make_reg(segId, 0)); +} + +void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { + Script *script = this; + + if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) { + int idx = RAW_GET_CLASS_INDEX(script, addr); + if (idx >= 0 && (uint)idx < script->_objects.size()) { + // Note all local variables, if we have a local variable environment + if (script->locals_segment) + (*note)(param, make_reg(script->locals_segment, 0)); + + Object &obj = script->_objects[idx]; + for (uint i = 0; i < obj._variables.size(); i++) + (*note)(param, obj._variables[i]); + } else { + warning("Request for outgoing script-object reference at %04x:%04x yielded invalid index %d", PRINT_REG(addr), idx); + } + } else { + /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ + /* Happens e.g. when we're looking into strings */ + } +} + + +//-------------------- clones -------------------- + +template +void Table::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { + for (uint i = 0; i < _table.size(); i++) + if (isValidEntry(i)) + (*note)(param, make_reg(segId, i)); +} + +void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { + CloneTable *clone_table = this; + Clone *clone; + +// assert(addr.segment == _segId); + + if (!clone_table->isValidEntry(addr.offset)) { + warning("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr)); +// BREAKPOINT(); + return; + } + + clone = &(clone_table->_table[addr.offset]); + + // Emit all member variables (including references to the 'super' delegate) + for (uint i = 0; i < clone->_variables.size(); i++) + (*note)(param, clone->_variables[i]); + + // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals. + (*note)(param, clone->pos); + //sciprintf("[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos)); +} + +void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) { + CloneTable *clone_table = this; + Object *victim_obj; + +// assert(addr.segment == _segId); + + victim_obj = &(clone_table->_table[addr.offset]); + +#ifdef GC_DEBUG + if (!(victim_obj->flags & OBJECT_FLAG_FREED)) + sciprintf("[GC] Warning: Clone %04x:%04x not reachable and not freed (freeing now)\n", PRINT_REG(addr)); +#ifdef GC_DEBUG_VERBOSE + else + sciprintf("[GC-DEBUG] Clone %04x:%04x: Freeing\n", PRINT_REG(addr)); +#endif +#endif + /* + sciprintf("[GC] Clone %04x:%04x: Freeing\n", PRINT_REG(addr)); + sciprintf("[GC] Clone had pos %04x:%04x\n", PRINT_REG(victim_obj->pos)); + */ + clone_table->freeEntry(addr.offset); +} + + +//-------------------- locals -------------------- +reg_t LocalVariables::findCanonicAddress(SegManager *segmgr, reg_t addr) { + // Reference the owning script + SegmentId owner_seg = segmgr->segGet(script_id); + + assert(owner_seg >= 0); + + return make_reg(owner_seg, 0); +} + +void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { +// assert(addr.segment == _segId); + + for (uint i = 0; i < _locals.size(); i++) + (*note)(param, _locals[i]); +} + + +//-------------------- stack -------------------- +reg_t DataStack::findCanonicAddress(SegManager *segmgr, reg_t addr) { + addr.offset = 0; + return addr; +} + +void DataStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { + fprintf(stderr, "Emitting %d stack entries\n", nr); + for (int i = 0; i < nr; i++) + (*note)(param, entries[i]); + fprintf(stderr, "DONE"); +} + + +//-------------------- lists -------------------- +void ListTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) { + freeEntry(sub_addr.offset); +} + +void ListTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { + if (!isValidEntry(addr.offset)) { + warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); + return; + } + + List *list = &(_table[addr.offset]); + + note(param, list->first); + note(param, list->last); + // We could probably get away with just one of them, but + // let's be conservative here. +} + + +//-------------------- nodes -------------------- +void NodeTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) { + freeEntry(sub_addr.offset); +} + +void NodeTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { + if (!isValidEntry(addr.offset)) { + warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); + return; + } + Node *node = &(_table[addr.offset]); + + // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us + // to walk around from any given node + note(param, node->pred); + note(param, node->succ); + note(param, node->key); + note(param, node->value); +} + + +//-------------------- hunk -------------------- + +//-------------------- dynamic memory -------------------- + +reg_t DynMem::findCanonicAddress(SegManager *segmgr, reg_t addr) { + addr.offset = 0; + return addr; +} + +void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { + (*note)(param, make_reg(segId, 0)); +} + + +} // End of namespace Sci diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h new file mode 100644 index 0000000000..a871d2dcb6 --- /dev/null +++ b/engines/sci/engine/memobj.h @@ -0,0 +1,556 @@ +/* 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$ + * + */ + +#ifndef SCI_ENGINE_MEMOBJ_H +#define SCI_ENGINE_MEMOBJ_H + +#include "common/serializer.h" +#include "sci/engine/vm_types.h" // for reg_t + +//#include "common/util.h" + +namespace Sci { + +enum MemObjectType { + MEM_OBJ_INVALID = 0, + MEM_OBJ_SCRIPT = 1, + MEM_OBJ_CLONES = 2, + MEM_OBJ_LOCALS = 3, + MEM_OBJ_STACK = 4, + MEM_OBJ_SYS_STRINGS = 5, + MEM_OBJ_LISTS = 6, + MEM_OBJ_NODES = 7, + MEM_OBJ_HUNK = 8, + MEM_OBJ_DYNMEM = 9, + MEM_OBJ_STRING_FRAG = 10, + + MEM_OBJ_MAX // For sanity checking +}; + +struct MemObject : public Common::Serializable { + MemObjectType _type; + int _segmgrId; /**< Internal value used by the seg_manager's hash map */ + + typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name + +public: + static MemObject *createMemObject(MemObjectType type); + +public: + virtual ~MemObject() {} + + inline MemObjectType getType() const { return _type; } + inline int getSegMgrId() const { return _segmgrId; } + + /** + * Dereferences a raw memory pointer. + * @param reg reference to dereference + * @param size if not NULL, set to the theoretical maximum size of the referenced data block + * @return the data block referenced + */ + virtual byte *dereference(reg_t pointer, int *size); + + /** + * Finds the canonic address associated with sub_reg. + * + * For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)). + * This address "governs" a in the sense that deallocating c(a) will deallocate a. + * + * @param sub_addr base address whose canonic address is to be found + */ + virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr) { return sub_addr; } + + /** + * Deallocates all memory associated with the specified address. + * @param sub_addr address (within the given segment) to deallocate + */ + virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr) {} + + /** + * Iterates over and reports all addresses within the current segment. + * @param note Invoked for each address on which free_at_address() makes sense + * @param param parameter passed to 'note' + */ + virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {} + + /** + * Iterates over all references reachable from the specified object. + * @param object object (within the current segment) to analyse + * @param param parameter passed to 'note' + * @param note Invoked for each outgoing reference within the object + * Note: This function may also choose to report numbers (segment 0) as adresses + */ + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note) {} +}; + + +// TODO: Implement the following class +struct StringFrag : public MemObject { + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + +struct IntMapper; + +enum { + SYS_STRINGS_MAX = 4, + + SYS_STRING_SAVEDIR = 0, + SYS_STRING_PARSER_BASE = 1, + + MAX_PARSER_BASE = 64 +}; + +struct SystemString { + char *name; + int max_size; + reg_t *value; +}; + +struct SystemStrings : public MemObject { + SystemString strings[SYS_STRINGS_MAX]; + +public: + SystemStrings() { + memset(strings, 0, sizeof(strings)); + } + ~SystemStrings() { + for (int i = 0; i < SYS_STRINGS_MAX; i++) { + SystemString *str = &strings[i]; + if (str->name) { + free(str->name); + str->name = NULL; + + free(str->value); + str->value = NULL; + + str->max_size = 0; + } + } + } + + virtual byte *dereference(reg_t pointer, int *size); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + +/** This struct is used to buffer the list of send calls in send_selector() */ +struct CallsStruct { + union { + reg_t func; + reg_t *var; + } address; + StackPtr argp; + int argc; + Selector selector; + StackPtr sp; /**< Stack pointer */ + int type; /**< Same as ExecStack.type */ +}; + +struct LocalVariables : public MemObject { + int script_id; /**< Script ID this local variable block belongs to */ + Common::Array _locals; + +public: + LocalVariables() { + script_id = 0; + } + + virtual byte *dereference(reg_t pointer, int *size); + virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + +/** Clone has been marked as 'freed' */ +#define OBJECT_FLAG_FREED (0x1 << 0) + +struct Object { + int flags; + reg_t pos; /**< Object offset within its script; for clones, this is their base */ + int variable_names_nr; /**< Number of variable names, may be less than variables_nr */ + int methods_nr; + byte *base; /**< Points to a buffer all relative references (code, strings) point to */ + byte *base_obj; /**< base + object offset within base */ + uint16 *base_method; /**< Pointer to the method selector area for this object */ + uint16 *base_vars; /**< Pointer to the varselector area for this object */ + Common::Array _variables; +}; + +struct CodeBlock { + reg_t pos; + int size; +}; + +#define VM_OBJECT_GET_VARSELECTOR(obj, i) \ + (s->version < SCI_VERSION_1_1 ? \ + READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \ + *(obj->base_vars + i)) +#define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i]) +#define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \ + (s->version < SCI_VERSION_1_1 ? \ + READ_LE_UINT16((byte *) (obj->base_method + i)) : \ + READ_LE_UINT16((byte *) (obj->base_method + i*2 + 1))) +#define VM_OBJECT_READ_FUNCTION(obj, i) \ + (s->version < SCI_VERSION_1_1 ? \ + make_reg(obj->pos.segment, \ + READ_LE_UINT16((byte *) (obj->base_method \ + + obj->methods_nr + 1 \ + + i))) : \ + make_reg(obj->pos.segment, \ + READ_LE_UINT16((byte *) (obj->base_method \ + + i * 2 + 2)))) + + + + +struct Script : public MemObject { + int nr; /**< Script number */ + byte *buf; /**< Static data buffer, or NULL if not used */ + size_t buf_size; + size_t script_size; + size_t heap_size; + + byte *synonyms; /**< Synonyms block or 0 if not present*/ + byte *heap_start; /**< Start of heap if SCI1.1, NULL otherwise */ + uint16 *export_table; /**< Abs. offset of the export table or 0 if not present */ + + IntMapper *obj_indices; + + int exports_nr; /**< Number of entries in the exports table */ + int synonyms_nr; /**< Number of entries in the synonyms block */ + int lockers; /**< Number of classes and objects that require this script */ + + /** + * Table for objects, contains property variables. + * Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET, + * see VM_OBJECT_[GS]ET_INDEX() + */ + Common::Array _objects; + + int locals_offset; + int locals_segment; /**< The local variable segment */ + LocalVariables *locals_block; + + Common::Array _codeBlocks; + int relocated; + bool _markedAsDeleted; + +public: + Script() { + nr = 0; + buf = NULL; + buf_size = 0; + script_size = 0; + heap_size = 0; + + synonyms = NULL; + heap_start = NULL; + export_table = NULL; + + obj_indices = NULL; + + locals_offset = 0; + locals_segment = 0; + locals_block = NULL; + + relocated = 0; + _markedAsDeleted = 0; + } + + ~Script() { + freeScript(); + } + + void freeScript(); + + virtual byte *dereference(reg_t pointer, int *size); + virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); + virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); + + // script lock operations + + /** Increments the number of lockers of this script by one. */ + void incrementLockers(); + + /** Decrements the number of lockers of this script by one. */ + void decrementLockers(); + + /** + * Retrieves the number of locks held on this script. + * @return the number of locks held on the previously identified script + */ + int getLockers() const; + + /** Sets the number of locks held on this script. */ + void setLockers(int lockers); + + /** + * Retrieves a pointer to the synonyms associated with this script + * @return pointer to the synonyms, in non-parsed format. + */ + byte *getSynonyms() const; + + /** + * Retrieves the number of synonyms associated with this script. + * @return the number of synonyms associated with this script + */ + int getSynonymsNr() const; + + + /** + * Sets the script-relative offset of the exports table. + * @param offset script-relative exports table offset + */ + void setExportTableOffset(int offset); + + /** + * Sets the script-relative offset of the synonyms associated with this script. + * @param offset script-relative offset of the synonyms block + */ + void setSynonymsOffset(int offset); + + /** + * Sets the number of synonyms associated with this script, + * @param nr number of synonyms, as to be stored within the script + */ + void setSynonymsNr(int nr); + + + /** + * Copies a byte string into a script's heap representation. + * @param dst script-relative offset of the destination area + * @param src pointer to the data source location + * @param n number of bytes to copy + */ + void mcpyInOut(int dst, const void *src, size_t n); + + + /** + * Marks the script as deleted. + * This will not actually delete the script. If references remain present on the + * heap or the stack, the script will stay in memory in a quasi-deleted state until + * either unreachable (resulting in its eventual deletion) or reloaded (resulting + * in its data being updated). + */ + void markDeleted() { + _markedAsDeleted = true; + } + + /** + * Marks the script as not deleted. + */ + void unmarkDeleted() { + _markedAsDeleted = false; + } + + /** + * Determines whether the script is marked as being deleted. + */ + bool isMarkedAsDeleted() const { + return _markedAsDeleted; + } + + /** + * Retrieves a 16 bit value from within a script's heap representation. + * @param offset offset to read from + * @return the value read from the specified location + */ + int16 getHeap(uint16 offset) const; + +}; + +/** Data stack */ +struct DataStack : MemObject { + int nr; /**< Number of stack entries */ + reg_t *entries; + +public: + DataStack() { + nr = 0; + entries = NULL; + } + ~DataStack() { + free(entries); + entries = NULL; + } + + virtual byte *dereference(reg_t pointer, int *size); + virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + +#define CLONE_USED -1 +#define CLONE_NONE -1 + +typedef Object Clone; + +struct Node { + reg_t pred; /**< Predecessor node */ + reg_t succ; /**< Successor node */ + reg_t key; + reg_t value; +}; /* List nodes */ + +struct List { + reg_t first; + reg_t last; +}; + +struct Hunk { + void *mem; + unsigned int size; + const char *type; +}; + +template +struct Table : public MemObject { + typedef T value_type; + struct Entry : public T { + int next_free; /* Only used for free entries */ + }; + enum { HEAPENTRY_INVALID = -1 }; + + + int first_free; /**< Beginning of a singly linked list for entries */ + int entries_used; /**< Statistical information */ + + Common::Array _table; + +public: + Table() { + initTable(); + } + + void initTable() { + entries_used = 0; + first_free = HEAPENTRY_INVALID; + _table.clear(); + } + + int allocEntry() { + entries_used++; + if (first_free != HEAPENTRY_INVALID) { + int oldff = first_free; + first_free = _table[oldff].next_free; + + _table[oldff].next_free = oldff; + return oldff; + } else { + uint newIdx = _table.size(); + _table.push_back(Entry()); + _table[newIdx].next_free = newIdx; // Tag as 'valid' + return newIdx; + } + } + + bool isValidEntry(int idx) { + return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx; + } + + virtual void freeEntry(int idx) { + if (idx < 0 || (uint)idx >= _table.size()) + ::error("Table::freeEntry: Attempt to release invalid table index %d", idx); + + _table[idx].next_free = first_free; + first_free = idx; + entries_used--; + } + + virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); +}; + + +/* CloneTable */ +struct CloneTable : public Table { + virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + + +/* NodeTable */ +struct NodeTable : public Table { + virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + + +/* ListTable */ +struct ListTable : public Table { + virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + + +/* HunkTable */ +struct HunkTable : public Table { + virtual void freeEntry(int idx) { + Table::freeEntry(idx); + + free(_table[idx].mem); + } + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + + +// Free-style memory +struct DynMem : public MemObject { + int _size; + char *_description; + byte *_buf; + +public: + DynMem() : _size(0), _description(0), _buf(0) {} + ~DynMem() { + free(_description); + _description = NULL; + free(_buf); + _buf = NULL; + } + + virtual byte *dereference(reg_t pointer, int *size); + virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); + virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + + +} // End of namespace Sci + +#endif // SCI_ENGINE_VM_H diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 69a939dae9..840c9bc525 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -232,49 +232,6 @@ int SegManager::deallocateScript(int script_nr) { return 1; } -MemObject *MemObject::createMemObject(MemObjectType type) { - MemObject *mem = 0; - switch (type) { - case MEM_OBJ_SCRIPT: - mem = new Script(); - break; - case MEM_OBJ_CLONES: - mem = new CloneTable(); - break; - case MEM_OBJ_LOCALS: - mem = new LocalVariables(); - break; - case MEM_OBJ_SYS_STRINGS: - mem = new SystemStrings(); - break; - case MEM_OBJ_STACK: - mem = new DataStack(); - break; - case MEM_OBJ_HUNK: - mem = new HunkTable(); - break; - case MEM_OBJ_STRING_FRAG: - mem = new StringFrag(); - break; - case MEM_OBJ_LISTS: - mem = new ListTable(); - break; - case MEM_OBJ_NODES: - mem = new NodeTable(); - break; - case MEM_OBJ_DYNMEM: - mem = new DynMem(); - break; - default: - error("Unknown MemObject type %d", type); - break; - } - - assert(mem); - mem->_type = type; - return mem; -} - MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectType type) { MemObject *mem = MemObject::createMemObject(type); if (!mem) { @@ -294,33 +251,6 @@ MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectTyp return mem; } -void Script::freeScript() { - free(buf); - buf = NULL; - buf_size = 0; - - _objects.clear(); - - delete obj_indices; - obj_indices = 0; - _codeBlocks.clear(); -} - -// memory operations - -void Script::mcpyInOut(int dst, const void *src, size_t n) { - if (buf) { - assert(dst + n <= buf_size); - memcpy(buf + dst, src, n); - } -} - -int16 Script::getHeap(uint16 offset) const { - VERIFY(offset + 1 < (int)buf_size, "invalid offset\n"); - return READ_LE_UINT16(buf + offset); -// return (buf[offset] | (buf[offset+1]) << 8); -} - // return the seg if script_id is valid and in the map, else -1 SegmentId SegManager::segGet(int script_id) const { return id_seg_map->lookupKey(script_id); @@ -367,53 +297,10 @@ bool SegManager::scriptIsLoaded(SegmentId seg) { return getScriptIfLoaded(seg) != 0; } -void Script::incrementLockers() { - lockers++; -} - -void Script::decrementLockers() { - if (lockers > 0) - lockers--; -} - -int Script::getLockers() const { - return lockers; -} - -void Script::setLockers(int lockers_) { - lockers = lockers_; -} - -void Script::setExportTableOffset(int offset) { - if (offset) { - export_table = (uint16 *)(buf + offset + 2); - exports_nr = READ_LE_UINT16((byte *)(export_table - 1)); - } else { - export_table = NULL; - exports_nr = 0; - } -} - void SegManager::setExportWidth(int flag) { exports_wide = flag; } -void Script::setSynonymsOffset(int offset) { - synonyms = buf + offset; -} - -byte *Script::getSynonyms() const { - return synonyms; -} - -void Script::setSynonymsNr(int n) { - synonyms_nr = n; -} - -int Script::getSynonymsNr() const { - return synonyms_nr; -} - int SegManager::relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location) { int rel = location - block_location; @@ -925,67 +812,6 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) { return &(table->_table[offset]); } -byte *MemObject::dereference(reg_t pointer, int *size) { - error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment", - PRINT_REG(pointer)); - return NULL; -} - -byte *Script::dereference(reg_t pointer, int *size) { - if (pointer.offset > buf_size) { - sciprintf("Error: Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n", - PRINT_REG(pointer), (uint)buf_size); - return NULL; - } - if (size) - *size = buf_size - pointer.offset; - return (byte *)(buf + pointer.offset); -} - -byte *LocalVariables::dereference(reg_t pointer, int *size) { - // FIXME: The following doesn't seem to be endian safe. - // To fix this, we'd have to always treat the reg_t - // values stored here as in the little endian format. - int count = _locals.size() * sizeof(reg_t); - byte *base = (byte *)&_locals[0]; - - if (size) - *size = count; - - return base + pointer.offset; -} - -byte *DataStack::dereference(reg_t pointer, int *size) { - int count = nr * sizeof(reg_t); - byte *base = (byte *)entries; - - if (size) - *size = count; - - return base + pointer.offset; -} - -byte *DynMem::dereference(reg_t pointer, int *size) { - int count = _size; - byte *base = (byte *)_buf; - - if (size) - *size = count; - - return base + pointer.offset; -} - -byte *SystemStrings::dereference(reg_t pointer, int *size) { - if (size) - *size = strings[pointer.offset].max_size; - if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name) - return (byte *)(strings[pointer.offset].value); - - // This occurs in KQ5CD when interacting with certain objects - warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); - return NULL; -} - byte *SegManager::dereference(reg_t pointer, int *size) { if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) { // This occurs in KQ5CD when interacting with certain objects @@ -1048,191 +874,5 @@ void SegManager::dbgPrint(const char* msg, void *i) { } -//-------------------- script -------------------- -reg_t Script::findCanonicAddress(SegManager *segmgr, reg_t addr) { - addr.offset = 0; - return addr; -} - -void Script::freeAtAddress(SegManager *segmgr, reg_t addr) { - /* - sciprintf("[GC] Freeing script %04x:%04x\n", PRINT_REG(addr)); - if (locals_segment) - sciprintf("[GC] Freeing locals %04x:0000\n", locals_segment); - */ - - if (_markedAsDeleted) - segmgr->deallocateScript(nr); -} - -void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { - (*note)(param, make_reg(segId, 0)); -} - -void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - Script *script = this; - - if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) { - int idx = RAW_GET_CLASS_INDEX(script, addr); - if (idx >= 0 && (uint)idx < script->_objects.size()) { - // Note all local variables, if we have a local variable environment - if (script->locals_segment) - (*note)(param, make_reg(script->locals_segment, 0)); - - Object &obj = script->_objects[idx]; - for (uint i = 0; i < obj._variables.size(); i++) - (*note)(param, obj._variables[i]); - } else { - warning("Request for outgoing script-object reference at %04x:%04x yielded invalid index %d", PRINT_REG(addr), idx); - } - } else { - /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ - /* Happens e.g. when we're looking into strings */ - } -} - - -//-------------------- clones -------------------- - -template -void Table::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { - for (uint i = 0; i < _table.size(); i++) - if (isValidEntry(i)) - (*note)(param, make_reg(segId, i)); -} - -void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - CloneTable *clone_table = this; - Clone *clone; - -// assert(addr.segment == _segId); - - if (!clone_table->isValidEntry(addr.offset)) { - warning("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr)); -// BREAKPOINT(); - return; - } - - clone = &(clone_table->_table[addr.offset]); - - // Emit all member variables (including references to the 'super' delegate) - for (uint i = 0; i < clone->_variables.size(); i++) - (*note)(param, clone->_variables[i]); - - // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals. - (*note)(param, clone->pos); - //sciprintf("[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos)); -} - -void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) { - CloneTable *clone_table = this; - Object *victim_obj; - -// assert(addr.segment == _segId); - - victim_obj = &(clone_table->_table[addr.offset]); - -#ifdef GC_DEBUG - if (!(victim_obj->flags & OBJECT_FLAG_FREED)) - sciprintf("[GC] Warning: Clone %04x:%04x not reachable and not freed (freeing now)\n", PRINT_REG(addr)); -#ifdef GC_DEBUG_VERBOSE - else - sciprintf("[GC-DEBUG] Clone %04x:%04x: Freeing\n", PRINT_REG(addr)); -#endif -#endif - /* - sciprintf("[GC] Clone %04x:%04x: Freeing\n", PRINT_REG(addr)); - sciprintf("[GC] Clone had pos %04x:%04x\n", PRINT_REG(victim_obj->pos)); - */ - clone_table->freeEntry(addr.offset); -} - - -//-------------------- locals -------------------- -reg_t LocalVariables::findCanonicAddress(SegManager *segmgr, reg_t addr) { - // Reference the owning script - SegmentId owner_seg = segmgr->segGet(script_id); - - assert(owner_seg >= 0); - - return make_reg(owner_seg, 0); -} - -void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { -// assert(addr.segment == _segId); - - for (uint i = 0; i < _locals.size(); i++) - (*note)(param, _locals[i]); -} - - -//-------------------- stack -------------------- -reg_t DataStack::findCanonicAddress(SegManager *segmgr, reg_t addr) { - addr.offset = 0; - return addr; -} - -void DataStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - fprintf(stderr, "Emitting %d stack entries\n", nr); - for (int i = 0; i < nr; i++) - (*note)(param, entries[i]); - fprintf(stderr, "DONE"); -} - - -//-------------------- lists -------------------- -void ListTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) { - freeEntry(sub_addr.offset); -} - -void ListTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - if (!isValidEntry(addr.offset)) { - warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; - } - - List *list = &(_table[addr.offset]); - - note(param, list->first); - note(param, list->last); - // We could probably get away with just one of them, but - // let's be conservative here. -} - - -//-------------------- nodes -------------------- -void NodeTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) { - freeEntry(sub_addr.offset); -} - -void NodeTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - if (!isValidEntry(addr.offset)) { - warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; - } - Node *node = &(_table[addr.offset]); - - // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us - // to walk around from any given node - note(param, node->pred); - note(param, node->succ); - note(param, node->key); - note(param, node->value); -} - - -//-------------------- hunk -------------------- - -//-------------------- dynamic memory -------------------- - -reg_t DynMem::findCanonicAddress(SegManager *segmgr, reg_t addr) { - addr.offset = 0; - return addr; -} - -void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { - (*note)(param, make_reg(segId, 0)); -} - } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 643385fd74..dc91d60e69 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -29,6 +29,7 @@ #include "common/scummsys.h" #include "common/serializer.h" #include "sci/engine/vm.h" +#include "sci/engine/memobj.h" namespace Sci { diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 70802bb377..39ffbb2760 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -28,7 +28,6 @@ /* VM and kernel declarations */ -#include "common/serializer.h" #include "sci/engine/vm_types.h" // for reg_t #include "common/util.h" @@ -38,128 +37,8 @@ namespace Sci { class SegManager; struct EngineState; typedef int sci_version_t; - -enum MemObjectType { - MEM_OBJ_INVALID = 0, - MEM_OBJ_SCRIPT = 1, - MEM_OBJ_CLONES = 2, - MEM_OBJ_LOCALS = 3, - MEM_OBJ_STACK = 4, - MEM_OBJ_SYS_STRINGS = 5, - MEM_OBJ_LISTS = 6, - MEM_OBJ_NODES = 7, - MEM_OBJ_HUNK = 8, - MEM_OBJ_DYNMEM = 9, - MEM_OBJ_STRING_FRAG = 10, - - MEM_OBJ_MAX // For sanity checking -}; - -struct MemObject : public Common::Serializable { - MemObjectType _type; - int _segmgrId; /**< Internal value used by the seg_manager's hash map */ - - typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name - -public: - static MemObject *createMemObject(MemObjectType type); - -public: - virtual ~MemObject() {} - - inline MemObjectType getType() const { return _type; } - inline int getSegMgrId() const { return _segmgrId; } - - /** - * Dereferences a raw memory pointer. - * @param reg reference to dereference - * @param size if not NULL, set to the theoretical maximum size of the referenced data block - * @return the data block referenced - */ - virtual byte *dereference(reg_t pointer, int *size); - - /** - * Finds the canonic address associated with sub_reg. - * - * For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)). - * This address "governs" a in the sense that deallocating c(a) will deallocate a. - * - * @param sub_addr base address whose canonic address is to be found - */ - virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr) { return sub_addr; } - - /** - * Deallocates all memory associated with the specified address. - * @param sub_addr address (within the given segment) to deallocate - */ - virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr) {} - - /** - * Iterates over and reports all addresses within the current segment. - * @param note Invoked for each address on which free_at_address() makes sense - * @param param parameter passed to 'note' - */ - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {} - - /** - * Iterates over all references reachable from the specified object. - * @param object object (within the current segment) to analyse - * @param param parameter passed to 'note' - * @param note Invoked for each outgoing reference within the object - * Note: This function may also choose to report numbers (segment 0) as adresses - */ - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note) {} -}; - - -// TODO: Implement the following class -struct StringFrag : public MemObject { - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - struct IntMapper; - -enum { - SYS_STRINGS_MAX = 4, - - SYS_STRING_SAVEDIR = 0, - SYS_STRING_PARSER_BASE = 1, - - MAX_PARSER_BASE = 64 -}; - -struct SystemString { - char *name; - int max_size; - reg_t *value; -}; - -struct SystemStrings : public MemObject { - SystemString strings[SYS_STRINGS_MAX]; - -public: - SystemStrings() { - memset(strings, 0, sizeof(strings)); - } - ~SystemStrings() { - for (int i = 0; i < SYS_STRINGS_MAX; i++) { - SystemString *str = &strings[i]; - if (str->name) { - free(str->name); - str->name = NULL; - - free(str->value); - str->value = NULL; - - str->max_size = 0; - } - } - } - - virtual byte *dereference(reg_t pointer, int *size); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; +struct Object; /** Number of bytes to be allocated for the stack */ #define VM_STACK_SIZE 0x1000 @@ -243,400 +122,6 @@ struct Class { #define IS_CLASS(obj) (obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS) -/** This struct is used to buffer the list of send calls in send_selector() */ -struct CallsStruct { - union { - reg_t func; - reg_t *var; - } address; - StackPtr argp; - int argc; - Selector selector; - StackPtr sp; /**< Stack pointer */ - int type; /**< Same as ExecStack.type */ -}; - -struct LocalVariables : public MemObject { - int script_id; /**< Script ID this local variable block belongs to */ - Common::Array _locals; - -public: - LocalVariables() { - script_id = 0; - } - - virtual byte *dereference(reg_t pointer, int *size); - virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - -/** Clone has been marked as 'freed' */ -#define OBJECT_FLAG_FREED (0x1 << 0) - -struct Object { - int flags; - reg_t pos; /**< Object offset within its script; for clones, this is their base */ - int variable_names_nr; /**< Number of variable names, may be less than variables_nr */ - int methods_nr; - byte *base; /**< Points to a buffer all relative references (code, strings) point to */ - byte *base_obj; /**< base + object offset within base */ - uint16 *base_method; /**< Pointer to the method selector area for this object */ - uint16 *base_vars; /**< Pointer to the varselector area for this object */ - Common::Array _variables; -}; - -struct CodeBlock { - reg_t pos; - int size; -}; - -#define VM_OBJECT_GET_VARSELECTOR(obj, i) \ - (s->version < SCI_VERSION_1_1 ? \ - READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \ - *(obj->base_vars + i)) -#define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i]) -#define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \ - (s->version < SCI_VERSION_1_1 ? \ - READ_LE_UINT16((byte *) (obj->base_method + i)) : \ - READ_LE_UINT16((byte *) (obj->base_method + i*2 + 1))) -#define VM_OBJECT_READ_FUNCTION(obj, i) \ - (s->version < SCI_VERSION_1_1 ? \ - make_reg(obj->pos.segment, \ - READ_LE_UINT16((byte *) (obj->base_method \ - + obj->methods_nr + 1 \ - + i))) : \ - make_reg(obj->pos.segment, \ - READ_LE_UINT16((byte *) (obj->base_method \ - + i * 2 + 2)))) - - - - -struct Script : public MemObject { - int nr; /**< Script number */ - byte *buf; /**< Static data buffer, or NULL if not used */ - size_t buf_size; - size_t script_size; - size_t heap_size; - - byte *synonyms; /**< Synonyms block or 0 if not present*/ - byte *heap_start; /**< Start of heap if SCI1.1, NULL otherwise */ - uint16 *export_table; /**< Abs. offset of the export table or 0 if not present */ - - IntMapper *obj_indices; - - int exports_nr; /**< Number of entries in the exports table */ - int synonyms_nr; /**< Number of entries in the synonyms block */ - int lockers; /**< Number of classes and objects that require this script */ - - /** - * Table for objects, contains property variables. - * Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET, - * see VM_OBJECT_[GS]ET_INDEX() - */ - Common::Array _objects; - - int locals_offset; - int locals_segment; /**< The local variable segment */ - LocalVariables *locals_block; - - Common::Array _codeBlocks; - int relocated; - bool _markedAsDeleted; - -public: - Script() { - nr = 0; - buf = NULL; - buf_size = 0; - script_size = 0; - heap_size = 0; - - synonyms = NULL; - heap_start = NULL; - export_table = NULL; - - obj_indices = NULL; - - locals_offset = 0; - locals_segment = 0; - locals_block = NULL; - - relocated = 0; - _markedAsDeleted = 0; - } - - ~Script() { - freeScript(); - } - - void freeScript(); - - virtual byte *dereference(reg_t pointer, int *size); - virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); - virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); - - // script lock operations - - /** Increments the number of lockers of this script by one. */ - void incrementLockers(); - - /** Decrements the number of lockers of this script by one. */ - void decrementLockers(); - - /** - * Retrieves the number of locks held on this script. - * @return the number of locks held on the previously identified script - */ - int getLockers() const; - - /** Sets the number of locks held on this script. */ - void setLockers(int lockers); - - /** - * Retrieves a pointer to the synonyms associated with this script - * @return pointer to the synonyms, in non-parsed format. - */ - byte *getSynonyms() const; - - /** - * Retrieves the number of synonyms associated with this script. - * @return the number of synonyms associated with this script - */ - int getSynonymsNr() const; - - - /** - * Sets the script-relative offset of the exports table. - * @param offset script-relative exports table offset - */ - void setExportTableOffset(int offset); - - /** - * Sets the script-relative offset of the synonyms associated with this script. - * @param offset script-relative offset of the synonyms block - */ - void setSynonymsOffset(int offset); - - /** - * Sets the number of synonyms associated with this script, - * @param nr number of synonyms, as to be stored within the script - */ - void setSynonymsNr(int nr); - - - /** - * Copies a byte string into a script's heap representation. - * @param dst script-relative offset of the destination area - * @param src pointer to the data source location - * @param n number of bytes to copy - */ - void mcpyInOut(int dst, const void *src, size_t n); - - - /** - * Marks the script as deleted. - * This will not actually delete the script. If references remain present on the - * heap or the stack, the script will stay in memory in a quasi-deleted state until - * either unreachable (resulting in its eventual deletion) or reloaded (resulting - * in its data being updated). - */ - void markDeleted() { - _markedAsDeleted = true; - } - - /** - * Marks the script as not deleted. - */ - void unmarkDeleted() { - _markedAsDeleted = false; - } - - /** - * Determines whether the script is marked as being deleted. - */ - bool isMarkedAsDeleted() const { - return _markedAsDeleted; - } - - /** - * Retrieves a 16 bit value from within a script's heap representation. - * @param offset offset to read from - * @return the value read from the specified location - */ - int16 getHeap(uint16 offset) const; - -}; - -/** Data stack */ -struct DataStack : MemObject { - int nr; /**< Number of stack entries */ - reg_t *entries; - -public: - DataStack() { - nr = 0; - entries = NULL; - } - ~DataStack() { - free(entries); - entries = NULL; - } - - virtual byte *dereference(reg_t pointer, int *size); - virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - -#define CLONE_USED -1 -#define CLONE_NONE -1 - -typedef Object Clone; - -struct Node { - reg_t pred; /**< Predecessor node */ - reg_t succ; /**< Successor node */ - reg_t key; - reg_t value; -}; /* List nodes */ - -struct List { - reg_t first; - reg_t last; -}; - -struct Hunk { - void *mem; - unsigned int size; - const char *type; -}; - -template -struct Table : public MemObject { - typedef T value_type; - struct Entry : public T { - int next_free; /* Only used for free entries */ - }; - enum { HEAPENTRY_INVALID = -1 }; - - - int first_free; /**< Beginning of a singly linked list for entries */ - int entries_used; /**< Statistical information */ - - Common::Array _table; - -public: - Table() { - initTable(); - } - - void initTable() { - entries_used = 0; - first_free = HEAPENTRY_INVALID; - _table.clear(); - } - - int allocEntry() { - entries_used++; - if (first_free != HEAPENTRY_INVALID) { - int oldff = first_free; - first_free = _table[oldff].next_free; - - _table[oldff].next_free = oldff; - return oldff; - } else { - uint newIdx = _table.size(); - _table.push_back(Entry()); - _table[newIdx].next_free = newIdx; // Tag as 'valid' - return newIdx; - } - } - - bool isValidEntry(int idx) { - return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx; - } - - virtual void freeEntry(int idx) { - if (idx < 0 || (uint)idx >= _table.size()) - ::error("Table::freeEntry: Attempt to release invalid table index %d", idx); - - _table[idx].next_free = first_free; - first_free = idx; - entries_used--; - } - - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); -}; - - -/* CloneTable */ -struct CloneTable : public Table { - virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - - -/* NodeTable */ -struct NodeTable : public Table { - virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - - -/* ListTable */ -struct ListTable : public Table { - virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - - -/* HunkTable */ -struct HunkTable : public Table { - virtual void freeEntry(int idx) { - Table::freeEntry(idx); - - free(_table[idx].mem); - } - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; - - -// Free-style memory -struct DynMem : public MemObject { - int _size; - char *_description; - byte *_buf; - -public: - DynMem() : _size(0), _description(0), _buf(0) {} - ~DynMem() { - free(_description); - _description = NULL; - free(_buf); - _buf = NULL; - } - - virtual byte *dereference(reg_t pointer, int *size); - virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); - - virtual void saveLoadWithSerializer(Common::Serializer &ser); -}; /** Contains selector IDs for a few selected selectors */ struct selector_map_t { diff --git a/engines/sci/module.mk b/engines/sci/module.mk index f67d81e6e9..f2c58bcd8d 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -27,6 +27,7 @@ MODULE_OBJS = \ engine/ksound.o \ engine/kstring.o \ engine/message.o \ + engine/memobj.o \ engine/said.o \ engine/savegame.o \ engine/script.o \ -- cgit v1.2.3 From 9e196ce9f5094ae0a12f0dea6167748477ad82c4 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 4 Jun 2009 14:29:20 +0000 Subject: SCI: Message: Added support for escape sequences. svn-id: r41169 --- engines/sci/engine/kstring.cpp | 12 ++++----- engines/sci/engine/message.cpp | 56 +++++++++++++++++++++++++++++++++++++++--- engines/sci/engine/message.h | 2 +- 3 files changed, 60 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 20f0f4793b..3898664921 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -713,7 +713,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_MESSAGE_NEXT: { reg_t bufferReg; char *buffer = NULL; - const char *str; + Common::String str; reg_t retval; if (func == K_MESSAGE_GET) { @@ -735,18 +735,18 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { else retval = make_reg(0, s->_msgState.getTalker()); } else { - str = DUMMY_MESSAGE; + str = Common::String(DUMMY_MESSAGE); retval = NULL_REG; } if (!bufferReg.isNull()) { - int len = strlen(str) + 1; + int len = str.size() + 1; buffer = kernel_dereference_char_pointer(s, bufferReg, len); if (buffer) { - strcpy(buffer, str); + strcpy(buffer, str.c_str()); } else { - warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str); + warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str.c_str()); // Set buffer to empty string if possible buffer = kernel_dereference_char_pointer(s, bufferReg, 1); @@ -763,7 +763,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { MessageState tempState; if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple) && tempState.getMessage()) - return make_reg(0, strlen(tempState.getText()) + 1); + return make_reg(0, tempState.getText().size() + 1); else return NULL_REG; } diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 61151e3218..4f5efa106c 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -153,9 +153,59 @@ int MessageState::getLastModule() { return _lastReturnedModule; } -char *MessageState::getText() { - int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); - return (char *)_currentResource->data + offset; +Common::String MessageState::getText() { + char *str = (char *)_currentResource->data + READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); + + Common::String strippedStr; + Common::String skippedSubstr; + bool skipping = false; + + for (uint i = 0; i < strlen(str); i++) { + if (skipping) { + // Skip stage direction + skippedSubstr += str[i]; + + // Hopefully these locale-dependant functions are good enough + if (islower(str[i]) || isdigit(str[i])) { + // Lowercase or digit found, this is not a stage direction + strippedStr += skippedSubstr; + skipping = false; + } else if (str[i] == ')') { + // End of stage direction, skip trailing white space + while ((i + 1 < strlen(str)) && isspace(str[i + 1])) + i++; + skipping = false; + } + } else { + if (str[i] == '(') { + // Start skipping stage direction + skippedSubstr = str[i]; + skipping = true; + } else if (str[i] == '\\') { + // Escape sequence + if ((i + 2 < strlen(str)) && isdigit(str[i + 1]) && isdigit(str[i + 2])) { + // Hex escape sequence + char hexStr[3]; + + hexStr[0] = str[++i]; + hexStr[1] = str[++i]; + hexStr[2] = 0; + + char *endptr; + int hexNr = strtol(hexStr, &endptr, 16); + if (*endptr == 0) + strippedStr += hexNr; + } else if (i + 1 < strlen(str)) { + // Literal escape sequence + strippedStr += str[++i]; + } + } else { + strippedStr += str[i]; + } + } + } + + return strippedStr; } void MessageState::gotoNext() { diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h index b1cdb8ad99..5e30095a0c 100644 --- a/engines/sci/engine/message.h +++ b/engines/sci/engine/message.h @@ -54,7 +54,7 @@ public: MessageTuple getRefTuple(); int getMessage(); void gotoNext(); - char *getText(); + Common::String getText(); int getTalker(); int getLength(); MessageTuple &getLastTuple(); -- cgit v1.2.3 From a440d77408cf8e5cb4f570a3eeb0ee28338ab15d Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 4 Jun 2009 15:56:11 +0000 Subject: SCI: Added support for early SCI1.1 audio maps. svn-id: r41170 --- engines/sci/resource.cpp | 175 ++++++++++++++++++++++++++++++++--------------- engines/sci/resource.h | 2 + 2 files changed, 122 insertions(+), 55 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index f946f753d4..55059a1089 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1252,14 +1252,8 @@ bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &o return false; } -bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) { - // 65535.MAP structure: - // ========= - // 6 byte entries: - // w nEntry - // dw offset - - // Other map files: +bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size) { + // Map structure: // =============== // Header: // dw baseOffset @@ -1275,6 +1269,114 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 uint32 n; offset = 0; + byte *ptr = _audioMapSCI11->data; + + offset = READ_UINT32(ptr); + ptr += 4; + + while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { + n = READ_BE_UINT32(ptr); + ptr += 4; + + if (n == 0xffffffff) + break; + + offset += (READ_UINT16(ptr) | (ptr[2] << 16)); + ptr += 3; + + int syncSkip = 0; + + if (n & 0x80) { + n ^= 0x80; + + if (getSync) { + if (size) + *size = READ_UINT16(ptr); + } else { + syncSkip = READ_UINT16(ptr); + } + + ptr += 2; + + if (n & 0x40) { + n ^= 0x40; + + if (!getSync) + syncSkip += READ_UINT16(ptr); + + ptr += 2; + } + + offset += syncSkip; + + if (n == audioNumber) + return true; + + } else { + if (n == audioNumber) + return !getSync; + } + + offset -= syncSkip; + } + + return false; +} + +bool AudioResource::findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size) { + // Map structure: + // =============== + // 10-byte entries: + // b noun + // b verb + // b cond + // b seq + // dw offset + // w syncSize + syncAscSize + + uint32 n; + offset = 0; + + byte *ptr = _audioMapSCI11->data; + + while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { + n = READ_BE_UINT32(ptr); + ptr += 4; + + if (n == 0xffffffff) + break; + + offset = READ_UINT32(ptr); + ptr += 4; + + int syncSize = READ_UINT16(ptr); + ptr += 2; + + if (n == audioNumber) { + if (getSync) { + if (size) + *size = syncSize; + return true; + } else { + offset += syncSize; + return true; + } + } + } + + return false; +} + +bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) { + // 65535.MAP structure: + // ========= + // 6 byte entries: + // w nEntry + // dw offset + + uint32 n; + offset = 0; + if (_audioMapSCI11 && _audioMapSCI11->number != volume) { _resMgr->unlockResource(_audioMapSCI11, _audioMapSCI11->number, kResourceTypeMap); _audioMapSCI11 = 0; @@ -1301,53 +1403,16 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 return true; } } else { - offset = READ_UINT32(ptr); - ptr += 4; - - while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { - n = READ_BE_UINT32(ptr); - ptr += 4; - - if (n == 0xffffffff) - break; - - offset += (READ_UINT16(ptr) | (ptr[2] << 16)); - ptr += 3; - - int syncSkip = 0; - - if (n & 0x80) { - n ^= 0x80; - - if (getSync) { - if (size) - *size = READ_UINT16(ptr); - } else { - syncSkip = READ_UINT16(ptr); - } - - ptr += 2; - - if (n & 0x40) { - n ^= 0x40; - - if (!getSync) - syncSkip += READ_UINT16(ptr); - - ptr += 2; - } - - offset += syncSkip; - - if (n == audioNumber) - return true; - - } else { - if (n == audioNumber) - return !getSync; - } - - offset -= syncSkip; + // In early SCI1.1 the map is terminated with 10x 0xff, in late SCI1.1 + // with 11x 0xff. If we look at the 11th last byte in an early SCI1.1 + // map, this will be the high byte of the Sync length of the last entry. + // As Sync resources are relative small, we should never encounter a + // Sync with a size of 0xffnn. As such, the following heuristic should be + // sufficient to tell these map formats apart. + if (_audioMapSCI11->size >= 11 && (ptr[_audioMapSCI11->size - 11] == 0xff)) + return findAudEntrySCI11Late(audioNumber, offset, getSync, size); + else { + return findAudEntrySCI11Early(audioNumber, offset, getSync, size); } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index a693f696db..b1ae3d23ba 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -343,6 +343,8 @@ private: bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size); bool findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync = false, uint32 *size = NULL); + bool findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size); + bool findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size); }; } // End of namespace Sci -- cgit v1.2.3 From 3da455420a122a53b22329ed59297ba0428c1497 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 4 Jun 2009 16:18:35 +0000 Subject: SCI: Audio: Fixed bug in reading of SOL header. svn-id: r41171 --- engines/sci/resource.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 55059a1089..05dcf95bd0 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1487,6 +1487,12 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 } int headerSize = audioStream->readByte(); + + if (headerSize != 11 && headerSize != 12) { + warning("SOL audio header of size %i not supported", headerSize); + return NULL; + } + audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) *audioRate = audioStream->readUint16LE(); audioFlags = audioStream->readByte(); @@ -1498,10 +1504,12 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 if (!(audioFlags & kSolFlagIsSigned)) *flags |= Audio::Mixer::FLAG_UNSIGNED; - *size = audioStream->readUint16LE(); + *size = audioStream->readUint32LE(); - if (headerSize == 12) - *size |= audioStream->readByte() << 16; + if (headerSize == 12) { + // Unknown byte + audioStream->readByte(); + } byte *buffer; -- cgit v1.2.3 From 3091de6735aecac10cd18c7807bf74c7037cef91 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 20:50:51 +0000 Subject: SCI: Added FIXME comment to not_register() svn-id: r41172 --- engines/sci/engine/state.cpp | 3 +++ engines/sci/engine/state.h | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 5936c4fedb..2677ff4131 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -126,5 +126,8 @@ EngineState::EngineState() : _dirseeker(this) { EngineState::~EngineState() { } +uint16 EngineState::currentRoomNumber() const { + return KP_UINT(script_000->locals_block->_locals[13]); +} } // End of namespace Sci diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 0623aa35fd..561db322ef 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -48,7 +48,6 @@ namespace Common { namespace Sci { class Menubar; -struct kfunct_sig_pair_t; // from kernel.h struct GfxState; struct GfxPort; @@ -208,7 +207,7 @@ public: reg_t parser_event; /**< The event passed to Parse() and later used by Said() */ Script *script_000; /**< script 000, e.g. for globals */ - uint16 currentRoomNumber() const { return KP_UINT(script_000->locals_block->_locals[13]); } + uint16 currentRoomNumber() const; /* Debugger data: */ Breakpoint *bp_list; /**< List of breakpoints */ @@ -250,6 +249,13 @@ public: */ PaletteEntry get_pic_color(EngineState *s, int color); +// FIXME: Document this strange function. +// It seems to negate the given register but only if the "cantBeHere" exists. +// My guess: Since some SCI versions have cantBeHere and some have canBeHere, +// this function allows unifying the code, making it look identical for both +// kinds of SCI games. That's fine, but the name not_register is rather +// misleading. A different name (and a different place for declaring this) +// would be highly welcome. static inline reg_t not_register(EngineState *s, reg_t r) { if (s->_kernel->_selectorMap.cantBeHere != -1) return make_reg(0, !r.offset); -- cgit v1.2.3 From ae3c6c30531aa1def49939baf5a15c2e227365ae Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 20:51:09 +0000 Subject: SCI: cleanup svn-id: r41173 --- engines/sci/console.cpp | 2 +- engines/sci/engine/kernel.cpp | 36 ++++++++++++++++------------- engines/sci/engine/kernel.h | 12 +++++----- engines/sci/engine/kernel_types.h | 48 ++++++++++++++++++++++----------------- 4 files changed, 54 insertions(+), 44 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 047c18bbb4..685d0fbb91 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1646,7 +1646,7 @@ bool Console::cmdValueType(int argc, const char **argv) { return true; } - int t = determine_reg_type(g_EngineState, val, 1); + int t = determine_reg_type(g_EngineState, val, true); int invalid = t & KSIG_INVALID; switch (t & ~KSIG_INVALID) { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 719ff16334..40c7be207d 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -298,16 +298,16 @@ static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = { /*0x88*/ "DbugStr" }; -enum KernelFunctionType { +enum KernelFuncType { KF_NEW = 1, KF_NONE = -1, /**< No mapping, but name is known */ KF_TERMINATOR = -42 /**< terminates kfunct_mappers */ }; struct SciKernelFunction { - KernelFunctionType type; + KernelFuncType type; const char *name; - kfunct *fun; /* The actual function */ + KernelFunc *fun; /* The actual function */ const char *signature; /* kfunct signature */ }; @@ -469,7 +469,14 @@ SciKernelFunction kfunct_mappers[] = { {KF_TERMINATOR, NULL, NULL, NULL} // Terminator }; -static const char *argtype_description[] = { "Undetermined", "List", "Node", "Object", "Reference", "Arithmetic" }; +static const char *argtype_description[] = { + "Undetermined", + "List", + "Node", + "Object", + "Reference", + "Arithmetic" +}; Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) { memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t @@ -490,10 +497,6 @@ Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) { } Kernel::~Kernel() { - _selectorNames.clear(); - _opcodes.clear(); - _kernelNames.clear(); - _kfuncTable.clear(); } bool Kernel::loadSelectorNames(bool isOldSci0) { @@ -577,7 +580,7 @@ int kfree(EngineState *s, reg_t handle) { return 0; } -void kernel_compile_signature(const char **s) { +static void kernel_compile_signature(const char **s) { const char *src = *s; char *result; int ellipsis = 0; @@ -724,7 +727,7 @@ void Kernel::mapFunctions() { return; } -int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) { +int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid) { MemObject *mobj; if (!reg.segment) { @@ -806,9 +809,10 @@ const char *kernel_argtype_description(int type) { return argtype_description[sci_ffs(type)]; } -int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *argv) { +bool kernel_matches_signature(EngineState *s, const char *sig, int argc, const reg_t *argv) { + // Always "match" if no signature is given if (!sig) - return 1; + return true; while (*sig && argc) { if ((*sig & KSIG_ANY) != KSIG_ANY) { @@ -816,17 +820,17 @@ int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *a if (!type) { sciprintf("[KERN] Could not determine type of ref %04x:%04x; failing signature check\n", PRINT_REG(*argv)); - return 0; + return false; } if (type & KSIG_INVALID) { sciprintf("[KERN] ref %04x:%04x was determined to be a %s, but the reference itself is invalid\n", PRINT_REG(*argv), kernel_argtype_description(type)); - return 0; + return false; } if (!(type & *sig)) - return 0; + return false; } if (!(*sig & KSIG_ELLIPSIS)) @@ -836,7 +840,7 @@ int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *a } if (argc) - return 0; // Too many arguments + return false; // Too many arguments else return (*sig == 0 || (*sig & KSIG_ELLIPSIS)); } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 0db5b9205b..1fc9cd4b25 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -47,12 +47,12 @@ struct opcode { }; /* Generic description: */ -typedef reg_t kfunct(EngineState *s, int funct_nr, int argc, reg_t *argv); +typedef reg_t KernelFunc(EngineState *s, int funct_nr, int argc, reg_t *argv); -struct kfunct_sig_pair_t { - kfunct *fun; /* The actual function */ - const char *signature; /* kfunct signature */ - Common::String orig_name; /* Original name, in case we couldn't map it */ +struct KernelFuncWithSignature { + KernelFunc *fun; /**< The actual function */ + const char *signature; /**< KernelFunc signature */ + Common::String orig_name; /**< Original name, in case we couldn't map it */ }; class Kernel { @@ -88,7 +88,7 @@ public: void dumpScriptClass(char *data, int seeker, int objsize); selector_map_t _selectorMap; /**< Shortcut list for important selectors */ - Common::Array _kfuncTable; /**< Table of kernel functions */ + Common::Array _kfuncTable; /**< Table of kernel functions */ private: /** diff --git a/engines/sci/engine/kernel_types.h b/engines/sci/engine/kernel_types.h index 24478c9119..8927586a8e 100644 --- a/engines/sci/engine/kernel_types.h +++ b/engines/sci/engine/kernel_types.h @@ -64,30 +64,36 @@ namespace Sci { #define KSIG_ALLOW_INV 0x20 #define KSIG_INVALID KSIG_ALLOW_INV -int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *argv); -/* Determines whether a list of registers matches a given signature -** Parameters: (EngineState *) s: The state to operate on -** (char *) sig: The signature to test against -** (int) argc: Number of arguments to test -** (reg_t *) argv: Argument list -** Returns : (int) 0 iff the signature was not matched -*/ +/** + * Determines whether a list of registers matches a given signature. + * If no signature is given (i.e., if sig is NULL), this is always + * treated as a match. + * + * @param s state to operate on + * @param sig signature to test against + * @param argc number of arguments to test + * @param argv argument list + * @return true if the signature was matched, false otherwise + */ +bool kernel_matches_signature(EngineState *s, const char *sig, int argc, const reg_t *argv); -int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid); -/* Determines the type of the object indicated by reg -** Parameters: (EngineState *) s: The state to operate on -** (reg_t) reg: The register to check -** (int) allow_invalid: Allow invalid pointer values -** Returns : one of KSIG_* below KSIG_NULL. -** KSIG_INVALID set if the type of reg can be determined, but is invalid. -** 0 on error. -*/ +/** + * Determines the type of the object indicated by reg. + * @param s state to operate on + * @param reg register to check + * @param allow_invalid determines whether invalid pointer (=offset) values are allowed + * @return one of KSIG_* below KSIG_NULL. + * KSIG_INVALID set if the type of reg can be determined, but is invalid. + * 0 on error. + */ +int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid); +/** + * Returns a textual description of the type of an object. + * @param type type value to describe + * @return pointer to a (static) descriptive string + */ const char *kernel_argtype_description(int type); -/* Returns a textual description of the type of an object -** Parameters: (int) type: The type value to describe -** Returns: (const char *) Pointer to a (static) descriptive string -*/ } // End of namespace Sci -- cgit v1.2.3 From f08f5c3bbf882b817ed6fc04530044e406ddd04f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 20:51:24 +0000 Subject: SCI: Slightly modified kAddAfter so that it does not modify its arguments needlessly svn-id: r41174 --- engines/sci/engine/kgraphics.cpp | 2 +- engines/sci/engine/klists.cpp | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 4ccc125eb4..8413a7887b 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -769,7 +769,7 @@ static int collides_with(EngineState *s, Common::Rect area, reg_t other_obj, int return 0; } -reg_t kCanBeHere(EngineState *s, int funct_nr, int argc, reg_t * argv) { +reg_t kCanBeHere(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argv[0]; reg_t cliplist_ref = KP_ALT(1, NULL_REG); List *cliplist = NULL; diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 029954d00f..43d1f25e01 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -310,7 +310,7 @@ reg_t kAddToFront(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kAddAfter(EngineState *s, int funct_nr, int argc, reg_t *argv) { - List *l =lookup_list(s, argv[0]); + List *l = lookup_list(s, argv[0]); Node *firstnode = argv[1].isNull() ? NULL : lookup_node(s, argv[1]); Node *newnode = lookup_node(s, argv[2]); @@ -341,12 +341,11 @@ reg_t kAddAfter(EngineState *s, int funct_nr, int argc, reg_t *argv) { else lookup_node(s, oldnext)->pred = argv[2]; - return s->r_acc; } else { // !firstnode - // Prepare call to AddToFront... - argv[1] = argv[0]; - return kAddToFront(s, funct_nr, 2, argv + 1); // Set as initial list node + _k_add_to_front(s, argv[0], argv[2]); // Set as initial list node } + + return s->r_acc; } reg_t kAddToEnd(EngineState *s, int funct_nr, int argc, reg_t *argv) { -- cgit v1.2.3 From 23a9b5544cdbb129ce88aaf5ee1835a283b9578e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 20:51:40 +0000 Subject: SCI: Added MemObject::isValidOffset method; use it to simplify determine_reg_type svn-id: r41175 --- engines/sci/engine/kernel.cpp | 53 ++++++++++--------------------- engines/sci/engine/memobj.cpp | 72 ++++++++++++++++++++++++++----------------- engines/sci/engine/memobj.h | 44 +++++++++++++++++--------- 3 files changed, 90 insertions(+), 79 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 40c7be207d..d3bcae508c 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -729,12 +729,14 @@ void Kernel::mapFunctions() { int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid) { MemObject *mobj; + int type = 0; if (!reg.segment) { + type = KSIG_ARITHMETIC; if (!reg.offset) - return KSIG_ARITHMETIC | KSIG_NULL; + type |= KSIG_NULL; - return KSIG_ARITHMETIC; + return type; } if ((reg.segment >= s->seg_manager->_heap.size()) || !s->seg_manager->_heap[reg.segment]) @@ -755,52 +757,31 @@ int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid) { return KSIG_REF; case MEM_OBJ_CLONES: - if (allow_invalid || ((CloneTable *)mobj)->isValidEntry(reg.offset)) - return KSIG_OBJECT; - else - return KSIG_OBJECT | KSIG_INVALID; + type = KSIG_OBJECT; + break; case MEM_OBJ_LOCALS: - if (allow_invalid || reg.offset < (*(LocalVariables *)mobj)._locals.size() * sizeof(reg_t)) - return KSIG_REF; - else - return KSIG_REF | KSIG_INVALID; - case MEM_OBJ_STACK: - if (allow_invalid || reg.offset < (*(DataStack *)mobj).nr * sizeof(reg_t)) - return KSIG_REF; - else - return KSIG_REF | KSIG_INVALID; - case MEM_OBJ_SYS_STRINGS: - if (allow_invalid || (reg.offset < SYS_STRINGS_MAX - && (*(SystemStrings *)mobj).strings[reg.offset].name)) - return KSIG_REF; - else - return KSIG_REF | KSIG_INVALID; + case MEM_OBJ_DYNMEM: + type = KSIG_REF; + break; case MEM_OBJ_LISTS: - if (allow_invalid || ((ListTable *)mobj)->isValidEntry(reg.offset)) - return KSIG_LIST; - else - return KSIG_LIST | KSIG_INVALID; + type = KSIG_LIST; + break; case MEM_OBJ_NODES: - if (allow_invalid || ((NodeTable *)mobj)->isValidEntry(reg.offset)) - return KSIG_NODE; - else - return KSIG_NODE | KSIG_INVALID; - - case MEM_OBJ_DYNMEM: - if (allow_invalid || reg.offset < (*(DynMem *)mobj)._size) - return KSIG_REF; - else - return KSIG_REF | KSIG_INVALID; + type = KSIG_NODE; + break; default: return 0; - } + + if (!allow_invalid && !mobj->isValidOffset(reg.offset)) + type |= KSIG_INVALID; + return type; } const char *kernel_argtype_description(int type) { diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp index ef48270b41..c0775ae51e 100644 --- a/engines/sci/engine/memobj.cpp +++ b/engines/sci/engine/memobj.cpp @@ -89,21 +89,6 @@ void Script::freeScript() { _codeBlocks.clear(); } -// memory operations - -void Script::mcpyInOut(int dst, const void *src, size_t n) { - if (buf) { - assert(dst + n <= buf_size); - memcpy(buf + dst, src, n); - } -} - -int16 Script::getHeap(uint16 offset) const { - assert(offset + 1 < (int)buf_size); - return READ_LE_UINT16(buf + offset); -// return (buf[offset] | (buf[offset+1]) << 8); -} - void Script::incrementLockers() { lockers++; } @@ -147,12 +132,31 @@ int Script::getSynonymsNr() const { return synonyms_nr; } +// memory operations + +void Script::mcpyInOut(int dst, const void *src, size_t n) { + if (buf) { + assert(dst + n <= buf_size); + memcpy(buf + dst, src, n); + } +} + +int16 Script::getHeap(uint16 offset) const { + assert(offset + 1 < (int)buf_size); + return READ_LE_UINT16(buf + offset); +// return (buf[offset] | (buf[offset+1]) << 8); +} + byte *MemObject::dereference(reg_t pointer, int *size) { error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment", PRINT_REG(pointer)); return NULL; } +bool Script::isValidOffset(uint16 offset) const { + return offset < buf_size; +} + byte *Script::dereference(reg_t pointer, int *size) { if (pointer.offset > buf_size) { sciprintf("Error: Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n", @@ -161,42 +165,52 @@ byte *Script::dereference(reg_t pointer, int *size) { } if (size) *size = buf_size - pointer.offset; - return (byte *)(buf + pointer.offset); + return buf + pointer.offset; +} + +bool LocalVariables::isValidOffset(uint16 offset) const { + return offset < _locals.size() * sizeof(reg_t); } byte *LocalVariables::dereference(reg_t pointer, int *size) { + if (size) + *size = _locals.size() * sizeof(reg_t); + // FIXME: The following doesn't seem to be endian safe. // To fix this, we'd have to always treat the reg_t // values stored here as in the little endian format. - int count = _locals.size() * sizeof(reg_t); byte *base = (byte *)&_locals[0]; - - if (size) - *size = count; - return base + pointer.offset; } -byte *DataStack::dereference(reg_t pointer, int *size) { - int count = nr * sizeof(reg_t); - byte *base = (byte *)entries; +bool DataStack::isValidOffset(uint16 offset) const { + return offset < nr * sizeof(reg_t); +} +byte *DataStack::dereference(reg_t pointer, int *size) { if (size) - *size = count; + *size = nr * sizeof(reg_t); + byte *base = (byte *)entries; return base + pointer.offset; } -byte *DynMem::dereference(reg_t pointer, int *size) { - int count = _size; - byte *base = (byte *)_buf; +bool DynMem::isValidOffset(uint16 offset) const { + return offset < _size; +} +byte *DynMem::dereference(reg_t pointer, int *size) { if (size) - *size = count; + *size = _size; + byte *base = (byte *)_buf; return base + pointer.offset; } +bool SystemStrings::isValidOffset(uint16 offset) const { + return offset < SYS_STRINGS_MAX && strings[offset].name; +} + byte *SystemStrings::dereference(reg_t pointer, int *size) { if (size) *size = strings[pointer.offset].max_size; diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h index a871d2dcb6..7b9c2e507a 100644 --- a/engines/sci/engine/memobj.h +++ b/engines/sci/engine/memobj.h @@ -64,11 +64,17 @@ public: inline MemObjectType getType() const { return _type; } inline int getSegMgrId() const { return _segmgrId; } + /** + * Check whether the given offset into this memory object is valid, + * i.e., suitable for passing to dereference. + */ + virtual bool isValidOffset(uint16 offset) const = 0; + /** * Dereferences a raw memory pointer. - * @param reg reference to dereference - * @param size if not NULL, set to the theoretical maximum size of the referenced data block - * @return the data block referenced + * @param reg reference to dereference + * @param size if not NULL, set to the theoretical maximum size of the referenced data block + * @return the data block referenced */ virtual byte *dereference(reg_t pointer, int *size); @@ -108,6 +114,8 @@ public: // TODO: Implement the following class struct StringFrag : public MemObject { + virtual bool isValidOffset(uint16 offset) const { return false; } + virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -150,6 +158,7 @@ public: } } + virtual bool isValidOffset(uint16 offset) const; virtual byte *dereference(reg_t pointer, int *size); virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -177,6 +186,7 @@ public: script_id = 0; } + virtual bool isValidOffset(uint16 offset) const; virtual byte *dereference(reg_t pointer, int *size); virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); @@ -286,6 +296,7 @@ public: void freeScript(); + virtual bool isValidOffset(uint16 offset) const; virtual byte *dereference(reg_t pointer, int *size); virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); @@ -343,15 +354,6 @@ public: void setSynonymsNr(int nr); - /** - * Copies a byte string into a script's heap representation. - * @param dst script-relative offset of the destination area - * @param src pointer to the data source location - * @param n number of bytes to copy - */ - void mcpyInOut(int dst, const void *src, size_t n); - - /** * Marks the script as deleted. * This will not actually delete the script. If references remain present on the @@ -377,13 +379,21 @@ public: return _markedAsDeleted; } + /** + * Copies a byte string into a script's heap representation. + * @param dst script-relative offset of the destination area + * @param src pointer to the data source location + * @param n number of bytes to copy + */ + void mcpyInOut(int dst, const void *src, size_t n); + + /** * Retrieves a 16 bit value from within a script's heap representation. * @param offset offset to read from * @return the value read from the specified location */ int16 getHeap(uint16 offset) const; - }; /** Data stack */ @@ -401,6 +411,7 @@ public: entries = NULL; } + virtual bool isValidOffset(uint16 offset) const; virtual byte *dereference(reg_t pointer, int *size); virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); @@ -472,7 +483,11 @@ public: } } - bool isValidEntry(int idx) { + virtual bool isValidOffset(uint16 offset) const { + return isValidEntry(offset); + } + + bool isValidEntry(int idx) const { return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx; } @@ -543,6 +558,7 @@ public: _buf = NULL; } + virtual bool isValidOffset(uint16 offset) const; virtual byte *dereference(reg_t pointer, int *size); virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr); virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); -- cgit v1.2.3 From 870db34cd1e435891e02f54c1c0dc013f257135d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 21:42:24 +0000 Subject: SCI: Renamed _kfuncTable -> _kernelFuncs; and simplified/streamlined the kernel func map in kernel.cpp a bit svn-id: r41176 --- engines/sci/engine/kernel.cpp | 80 +++++++++++++++++--------------------- engines/sci/engine/kernel.h | 2 +- engines/sci/engine/kmisc.cpp | 2 +- engines/sci/engine/scriptdebug.cpp | 2 +- engines/sci/engine/vm.cpp | 8 ++-- 5 files changed, 43 insertions(+), 51 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d3bcae508c..3b998c7092 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -298,21 +298,14 @@ static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = { /*0x88*/ "DbugStr" }; -enum KernelFuncType { - KF_NEW = 1, - KF_NONE = -1, /**< No mapping, but name is known */ - KF_TERMINATOR = -42 /**< terminates kfunct_mappers */ -}; - struct SciKernelFunction { - KernelFuncType type; const char *name; KernelFunc *fun; /* The actual function */ const char *signature; /* kfunct signature */ }; -#define DEFUN(nm, cname, sig) {KF_NEW, nm, cname, sig} -#define NOFUN(nm) {KF_NONE, nm, NULL, NULL} +#define DEFUN(name, fun, sig) {name, fun, sig} +#define NOFUN(name) {name, NULL, NULL} SciKernelFunction kfunct_mappers[] = { /*00*/ DEFUN("Load", kLoad, "iii*"), @@ -434,8 +427,8 @@ SciKernelFunction kfunct_mappers[] = { /*6f*/ DEFUN("6f", kTimesCos, "ii"), /*70*/ DEFUN("Graph", kGraph, ".*"), /*71*/ DEFUN("Joystick", kJoystick, ".*"), - /*72*/ NOFUN(NULL), - /*73*/ NOFUN(NULL), + /*72*/ NOFUN("unknown72"), + /*73*/ NOFUN("unknown73"), // Experimental functions /*74*/ DEFUN("FileIO", kFileIO, "i.*"), @@ -464,9 +457,9 @@ SciKernelFunction kfunct_mappers[] = { DEFUN("SetVideoMode", kSetVideoMode, "i"), // Special and NOP stuff - {KF_NEW, NULL, k_Unknown, NULL}, + {NULL, k_Unknown, NULL}, - {KF_TERMINATOR, NULL, NULL, NULL} // Terminator + {NULL, NULL, NULL} // Terminator }; static const char *argtype_description[] = { @@ -673,50 +666,49 @@ void Kernel::mapFunctions() { functions_nr = max_functions_nr; } - _kfuncTable.resize(functions_nr); + _kernelFuncs.resize(functions_nr); for (uint functnr = 0; functnr < functions_nr; functnr++) { - int seeker, found = -1; - Common::String sought_name; + int found = -1; + // First, get the name, if known, of the kernel function with number functnr + Common::String sought_name; if (functnr < getKernelNamesSize()) sought_name = getKernelName(functnr); - if (!sought_name.empty()) - for (seeker = 0; (found == -1) && kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++) - if (kfunct_mappers[seeker].name && sought_name == kfunct_mappers[seeker].name) - found = seeker; // Found a kernel function with the same name! + // If the name is known, look it up in kfunct_mappers. This table + // maps kernel func names to actual function (pointers). + if (!sought_name.empty()) { + for (uint seeker = 0; (found == -1) && kfunct_mappers[seeker].name; seeker++) + if (sought_name == kfunct_mappers[seeker].name) + found = seeker; // Found a kernel function with the correct name! + } + + // Reset the table entry + _kernelFuncs[functnr].fun = NULL; + _kernelFuncs[functnr].signature = NULL; + _kernelFuncs[functnr].orig_name = sought_name; if (found == -1) { if (!sought_name.empty()) { - warning("Kernel function %s[%x] unmapped", getKernelName(functnr).c_str(), functnr); - _kfuncTable[functnr].fun = kNOP; + // No match but a name was given -> NOP + warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functnr); + _kernelFuncs[functnr].fun = kNOP; } else { + // No match and no name was given -> must be an unknown opcode warning("Flagging kernel function %x as unknown", functnr); - _kfuncTable[functnr].fun = k_Unknown; + _kernelFuncs[functnr].fun = k_Unknown; } - - _kfuncTable[functnr].signature = NULL; - _kfuncTable[functnr].orig_name = sought_name; - } else - switch (kfunct_mappers[found].type) { - case KF_NONE: - _kfuncTable[functnr].signature = NULL; - ++ignored; - break; - - case KF_NEW: - _kfuncTable[functnr].fun = kfunct_mappers[found].fun; - _kfuncTable[functnr].signature = kfunct_mappers[found].signature; - _kfuncTable[functnr].orig_name.clear(); - kernel_compile_signature(&(_kfuncTable[functnr].signature)); + } else { + // A match in kfunct_mappers was found + if (kfunct_mappers[found].fun) { + _kernelFuncs[functnr].fun = kfunct_mappers[found].fun; + _kernelFuncs[functnr].signature = kfunct_mappers[found].signature; + kernel_compile_signature(&(_kernelFuncs[functnr].signature)); ++mapped; - break; - case KF_TERMINATOR: - error("Unexpectedly encountered KF_TERMINATOR"); - break; - } - + } else + ++ignored; + } } // for all functions requesting to be mapped sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, getKernelNamesSize(), mapped); diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 1fc9cd4b25..ddc3f93cb7 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -88,7 +88,7 @@ public: void dumpScriptClass(char *data, int seeker, int objsize); selector_map_t _selectorMap; /**< Shortcut list for important selectors */ - Common::Array _kfuncTable; /**< Table of kernel functions */ + Common::Array _kernelFuncs; /**< Table of kernel functions */ private: /** diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 3673dbe3c4..2cb3ecfb41 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -249,7 +249,7 @@ reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kNOP(EngineState *s, int funct_nr, int argc, reg_t *argv) { - warning("Kernel function 0x%02x (%s) invoked: unmapped", funct_nr, s->_kernel->_kfuncTable[funct_nr].orig_name.c_str()); + warning("Kernel function 0x%02x (%s) invoked: unmapped", funct_nr, s->_kernel->_kernelFuncs[funct_nr].orig_name.c_str()); return NULL_REG; } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index f78362a320..dd4173dd0f 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -411,7 +411,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } if (opcode == op_callk) - sciprintf(" %s[%x]", (param_value < s->_kernel->_kfuncTable.size()) ? + sciprintf(" %s[%x]", (param_value < s->_kernel->_kernelFuncs.size()) ? ((param_value < s->_kernel->getKernelNamesSize()) ? s->_kernel->getKernelName(param_value).c_str() : "[Unknown(postulated)]") : "", param_value); else diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 345dcc5b9f..0e7f932333 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -976,7 +976,7 @@ void run_vm(EngineState *s, int restoring) { s->r_amp_rest = 0; // We just used up the restadjust, remember? } - if (opparams[0] >= (int)s->_kernel->_kfuncTable.size()) { + if (opparams[0] >= (int)s->_kernel->_kernelFuncs.size()) { error("Invalid kernel function 0x%x requested\n", opparams[0]); } else { int argc = ASSERT_ARITHMETIC(xs->sp[0]); @@ -984,11 +984,11 @@ void run_vm(EngineState *s, int restoring) { if (!(s->flags & GF_SCI0_OLD)) argc += restadjust; - if (s->_kernel->_kfuncTable[opparams[0]].signature - && !kernel_matches_signature(s, s->_kernel->_kfuncTable[opparams[0]].signature, argc, xs->sp + 1)) { + if (s->_kernel->_kernelFuncs[opparams[0]].signature + && !kernel_matches_signature(s, s->_kernel->_kernelFuncs[opparams[0]].signature, argc, xs->sp + 1)) { error("[VM] Invalid arguments to kernel call %x\n", opparams[0]); } else { - s->r_acc = s->_kernel->_kfuncTable[opparams[0]].fun(s, opparams[0], argc, xs->sp + 1); + s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], argc, xs->sp + 1); } // Call kernel function -- cgit v1.2.3 From 10c54394bd2f97a6a59a4fc1aedfcad09c40f1dc Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 21:44:39 +0000 Subject: SCI: Renamed EngineState::flags and version to _flags and _version (following our conventions); also slightly changed the EngineState constructor to init _version & _flags, and used this to make them constant svn-id: r41177 --- engines/sci/engine/game.cpp | 19 +++++++++---------- engines/sci/engine/kevent.cpp | 2 +- engines/sci/engine/kgraphics.cpp | 22 +++++++++++----------- engines/sci/engine/kmisc.cpp | 2 +- engines/sci/engine/kmovement.cpp | 6 +++--- engines/sci/engine/ksound.cpp | 8 ++++---- engines/sci/engine/memobj.h | 6 +++--- engines/sci/engine/savegame.cpp | 12 ++++-------- engines/sci/engine/scriptdebug.cpp | 4 ++-- engines/sci/engine/seg_manager.cpp | 8 ++++---- engines/sci/engine/state.cpp | 6 ++---- engines/sci/engine/state.h | 8 ++++---- engines/sci/engine/vm.cpp | 34 +++++++++++++++++----------------- engines/sci/engine/vm.h | 18 +++++++++--------- engines/sci/sci.cpp | 36 ++++++++++++++++-------------------- 15 files changed, 90 insertions(+), 101 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 6aba9b3f10..bfd38f2c1b 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -43,7 +43,7 @@ int _reset_graphics_input(EngineState *s) { gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 }; debug(2, "Initializing graphics"); - if (s->resmgr->_sciVersion <= SCI_VERSION_01 || (s->flags & GF_SCI1_EGA)) { + if (s->resmgr->_sciVersion <= SCI_VERSION_01 || (s->_flags & GF_SCI1_EGA)) { int i; for (i = 0; i < 16; i++) { @@ -66,7 +66,7 @@ int _reset_graphics_input(EngineState *s) { } else { resource = s->resmgr->findResource(kResourceTypePalette, 999, 1); if (resource) { - if (s->version < SCI_VERSION_1_1) + if (s->_version < SCI_VERSION_1_1) s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal1(999, resource->data, resource->size)); else s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal11(999, resource->data, resource->size)); @@ -89,7 +89,7 @@ int _reset_graphics_input(EngineState *s) { s->priority_first = 42; // Priority zone 0 ends here - if (s->flags & GF_SCI0_OLDGFXFUNCS) + if (s->_flags & GF_SCI0_OLDGFXFUNCS) s->priority_last = 200; else s->priority_last = 190; @@ -259,7 +259,7 @@ static int create_class_table_sci0(EngineState *s) { Resource *script = s->resmgr->findResource(kResourceTypeScript, scriptnr, 0); if (script) { - if (s->flags & GF_SCI0_OLD) + if (s->_flags & GF_SCI0_OLD) magic_offset = seeker = 2; else magic_offset = seeker = 0; @@ -324,13 +324,12 @@ static int create_class_table_sci0(EngineState *s) { } // Architectural stuff: Init/Unintialize engine -int script_init_engine(EngineState *s, sci_version_t version) { +int script_init_engine(EngineState *s) { int result; s->kernel_opt_flags = 0; - s->version = version; - if (s->version >= SCI_VERSION_1_1) + if (s->_version >= SCI_VERSION_1_1) result = create_class_table_sci11(s); else result = create_class_table_sci0(s); @@ -340,7 +339,7 @@ int script_init_engine(EngineState *s, sci_version_t version) { return 1; } - s->seg_manager = new SegManager(s->version >= SCI_VERSION_1_1); + s->seg_manager = new SegManager(s->_version >= SCI_VERSION_1_1); s->gc_countdown = GC_INTERVAL - 1; SegmentId script_000_segment = script_get_segment(s, 0, SCRIPT_GET_LOCK); @@ -370,7 +369,7 @@ int script_init_engine(EngineState *s, sci_version_t version) { s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet - s->_kernel = new Kernel(s->resmgr, (s->flags & GF_SCI0_OLD)); + s->_kernel = new Kernel(s->resmgr, (s->_flags & GF_SCI0_OLD)); s->_vocabulary = new Vocabulary(s->resmgr); s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING; @@ -378,7 +377,7 @@ int script_init_engine(EngineState *s, sci_version_t version) { s->bp_list = NULL; // No breakpoints defined s->have_bp = 0; - if ((s->flags & GF_SCI1_LOFSABSOLUTE) && s->version < SCI_VERSION_1_1) + if ((s->_flags & GF_SCI1_LOFSABSOLUTE) && s->_version < SCI_VERSION_1_1) s->seg_manager->setExportWidth(1); else s->seg_manager->setExportWidth(0); diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index b275e9c0b9..66395035c8 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -42,7 +42,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argv[1]; sci_event_t e; int oldx, oldy; - int modifier_mask = s->version <= SCI_VERSION_0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK; + int modifier_mask = s->_version <= SCI_VERSION_0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK; if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) { // Penalty time- too many requests to this function without waiting! diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 8413a7887b..fc23e4f6ef 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -163,7 +163,7 @@ int _find_view_priority(EngineState *s, int y) { return j; return 14; // Maximum } else { - if (!(s->flags & GF_SCI0_OLDGFXFUNCS)) + if (!(s->_flags & GF_SCI0_OLDGFXFUNCS)) return SCI0_VIEW_PRIORITY_14_ZONES(y); else return SCI0_VIEW_PRIORITY(y) == 15 ? 14 : SCI0_VIEW_PRIORITY(y); @@ -171,7 +171,7 @@ int _find_view_priority(EngineState *s, int y) { } int _find_priority_band(EngineState *s, int nr) { - if (!(s->flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 14)) { + if (!(s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 14)) { if (nr == 15) return 0xffff; else { @@ -180,7 +180,7 @@ int _find_priority_band(EngineState *s, int nr) { return 0; } - if ((s->flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 15)) { + if ((s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 15)) { warning("Attempt to get priority band %d", nr); return 0; } @@ -190,7 +190,7 @@ int _find_priority_band(EngineState *s, int nr) { else { int retval; - if (!(s->flags & GF_SCI0_OLDGFXFUNCS)) + if (!(s->_flags & GF_SCI0_OLDGFXFUNCS)) retval = SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr); else retval = SCI0_PRIORITY_BAND_FIRST(nr); @@ -303,7 +303,7 @@ static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argc) { case 1 : - if (s->version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1_1) { if (SKPV(0) == 0 || SKPV(0) == 1 || SKPV(0) == -1) { // Newer (SCI1.1) semantics: show/hide cursor g_system->showMouse(SKPV(0) != 0); @@ -317,7 +317,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { } break; case 2 : - if (s->version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1_1) { // Pre-SCI1.1: set cursor according to the first parameter, and toggle its // visibility based on the second parameter // Some late SCI1 games actually use the SCI1.1 version of this call (EcoQuest 1 @@ -685,7 +685,7 @@ void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int funct_nr, int argc, angle %= 360; - if (!(s->flags & GF_SCI0_OLD)) { + if (!(s->_flags & GF_SCI0_OLD)) { if (angle < 45) loop = 3; else if (angle < 136) @@ -997,7 +997,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { if ((argc > 1) && (UKPV(1) & K_DRAWPIC_FLAG_MIRRORED)) picFlags |= DRAWPIC1_FLAG_MIRRORED; - if (s->flags & GF_SCI0_OLDGFXFUNCS) { + if (s->_flags & GF_SCI0_OLDGFXFUNCS) { if (!SKPV_OR_ALT(2, 0)) add_to_pic = 0; } else { @@ -1050,7 +1050,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->priority_first = 42; - if (s->flags & GF_SCI0_OLDGFXFUNCS) + if (s->_flags & GF_SCI0_OLDGFXFUNCS) s->priority_last = 200; else s->priority_last = 190; @@ -1135,7 +1135,7 @@ void _k_base_setter(EngineState *s, reg_t object) { // does not exist (earliest one was KQ4 SCI, version 0.000.274). This code is left here // for reference only #if 0 - if (s->version <= SCI_VERSION_0) + if (s->_version <= SCI_VERSION_0) --absrect.top; // Compensate for early SCI OB1 'bug' #endif @@ -1346,7 +1346,7 @@ static void _k_disable_delete_for_now(EngineState *s, reg_t obj) { * that game - bringing the save/load dialog on a par with SCI0. */ if (type == K_CONTROL_BUTTON && text && (s->_gameName == "sq4") && - s->version < SCI_VERSION_1_1 && !strcmp(text, " Delete ")) { + s->_version < SCI_VERSION_1_1 && !strcmp(text, " Delete ")) { PUT_SEL32V(obj, state, (state | kControlStateDisabled) & ~kControlStateEnabled); } } diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 2cb3ecfb41..2e86362404 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -121,7 +121,7 @@ reg_t kGetTime(EngineState *s, int funct_nr, int argc, reg_t *argv) { g_system->getTimeAndDate(loc_time); start_time = g_system->getMillis() - s->game_start_time; - if ((s->flags & GF_SCI0_OLDGETTIME) && argc) { // Use old semantics + if ((s->_flags & GF_SCI0_OLDGETTIME) && argc) { // Use old semantics retval = (loc_time.tm_hour % 12) * 3600 + loc_time.tm_min * 60 + loc_time.tm_sec; debugC(2, kDebugLevelTime, "GetTime(timeofday) returns %d", retval); return make_reg(0, retval); diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index cd4307678b..b116fa4093 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -273,7 +273,7 @@ static void bresenham_autodetect(EngineState *s) { } buf = s->seg_manager->getScript(fptr.segment)->buf + fptr.offset; - handle_movecnt = (s->version <= SCI_VERSION_0 || checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT; + handle_movecnt = (s->_version <= SCI_VERSION_0 || checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT; sciprintf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ? "ignore" : "increment"); } else { warning("bresenham_autodetect failed"); @@ -292,7 +292,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) { int completed = 0; int max_movcnt = GET_SEL32V(client, moveSpeed); - if (s->version > SCI_VERSION_0) + if (s->_version > SCI_VERSION_0) signal &= ~_K_VIEW_SIG_FLAG_HIT_OBSTACLE; if (handle_movecnt == UNINITIALIZED) @@ -379,7 +379,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) { completed = 1; } - if (s->version > SCI_VERSION_0) + if (s->_version > SCI_VERSION_0) if (completed) invoke_selector(INV_SEL(mover, moveDone, kStopOnInvalidSelector), 0); diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 3586b6b1ed..b0fbda36f9 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -154,7 +154,7 @@ void process_sound_events(EngineState *s) { /* Get all sound events, apply their song_handle_t handle; int cue; - if (s->version >= SCI_VERSION_01) + if (s->_version >= SCI_VERSION_01) return; /* SCI01 and later explicitly poll for everything */ @@ -964,9 +964,9 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) { - if (s->version >= SCI_VERSION_1_1 || s->flags & GF_SCI1_NEWDOSOUND) + if (s->_version >= SCI_VERSION_1_1 || s->_flags & GF_SCI1_NEWDOSOUND) return kDoSound_SCI1(s, funct_nr, argc, argv); - else if (s->version >= SCI_VERSION_01) + else if (s->_version >= SCI_VERSION_01) return kDoSound_SCI01(s, funct_nr, argc, argv); else return kDoSound_SCI0(s, funct_nr, argc, argv); @@ -978,7 +978,7 @@ reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) { int sampleLen = 0; if (!s->_sound._audioResource) - s->_sound._audioResource = new AudioResource(s->resmgr, s->version); + s->_sound._audioResource = new AudioResource(s->resmgr, s->_version); switch (UKPV(0)) { case kSciAudioWPlay: diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h index 7b9c2e507a..c006caaddc 100644 --- a/engines/sci/engine/memobj.h +++ b/engines/sci/engine/memobj.h @@ -215,16 +215,16 @@ struct CodeBlock { }; #define VM_OBJECT_GET_VARSELECTOR(obj, i) \ - (s->version < SCI_VERSION_1_1 ? \ + (s->_version < SCI_VERSION_1_1 ? \ READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \ *(obj->base_vars + i)) #define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i]) #define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \ - (s->version < SCI_VERSION_1_1 ? \ + (s->_version < SCI_VERSION_1_1 ? \ READ_LE_UINT16((byte *) (obj->base_method + i)) : \ READ_LE_UINT16((byte *) (obj->base_method + i*2 + 1))) #define VM_OBJECT_READ_FUNCTION(obj, i) \ - (s->version < SCI_VERSION_1_1 ? \ + (s->_version < SCI_VERSION_1_1 ? \ make_reg(obj->pos.segment, \ READ_LE_UINT16((byte *) (obj->base_method \ + obj->methods_nr + 1 \ diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index bf099816e3..a69e96eb3d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -458,7 +458,7 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename SavegameMetadata meta; meta.savegame_version = CURRENT_SAVEGAME_VERSION; meta.savegame_name = savename; - meta.version = s->version; + meta.version = s->_version; meta.game_version = s->game_version; meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); @@ -497,7 +497,7 @@ static SegmentId find_unique_seg_by_type(SegManager *self, int type) { } static byte *find_unique_script_block(EngineState *s, byte *buf, int type) { - if (s->flags & GF_SCI0_OLD) + if (s->_flags & GF_SCI0_OLD) buf += 2; do { @@ -545,7 +545,7 @@ static void load_script(EngineState *s, SegmentId seg) { assert(scr->buf); script = s->resmgr->findResource(kResourceTypeScript, scr->nr, 0); - if (s->version >= SCI_VERSION_1_1) + if (s->_version >= SCI_VERSION_1_1) heap = s->resmgr->findResource(kResourceTypeHeap, scr->nr, 0); memcpy(scr->buf, script->data, script->size); @@ -759,11 +759,9 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. - retval = new EngineState(); + retval = new EngineState(s->resmgr, s->_version, s->_flags); // Copy some old data - retval->version = s->version; - retval->flags = s->flags; retval->gfx_state = s->gfx_state; retval->sound_mute = s->sound_mute; retval->sound_volume = s->sound_volume; @@ -781,8 +779,6 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->gfx_state = s->gfx_state; retval->old_screen = 0; - retval->resmgr = s->resmgr; - temp = retval->_sound._songlib; retval->_sound.sfx_init(retval->resmgr, s->sfx_init_flags); retval->sfx_init_flags = s->sfx_init_flags; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index dd4173dd0f..4581c0a37c 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -271,7 +271,7 @@ int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) { selectors = obj->_variables.size(); - if (s->version < SCI_VERSION_1_1) + if (s->_version < SCI_VERSION_1_1) selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; else { if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) { @@ -466,7 +466,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod int stackframe = (scr[pos.offset + 2] >> 1) + (*p_restadjust); int argc = ((*p_sp)[- stackframe - 1]).offset; - if (!(s->flags & GF_SCI0_OLD)) + if (!(s->_flags & GF_SCI0_OLD)) argc += (*p_restadjust); sciprintf(" Kernel params: ("); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 840c9bc525..dcf7180501 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -135,13 +135,13 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { scr.script_size = script->size; scr.heap_size = 0; // Set later - if (!script || (s->version >= SCI_VERSION_1_1 && !heap)) { + if (!script || (s->_version >= SCI_VERSION_1_1 && !heap)) { error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap"); } - if (s->flags & GF_SCI0_OLD) { + if (s->_flags & GF_SCI0_OLD) { scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2; //locals_size = READ_LE_UINT16(script->data) * 2; - } else if (s->version < SCI_VERSION_1_1) { + } else if (s->_version < SCI_VERSION_1_1) { scr.buf_size = script->size; } else { scr.buf_size = script->size + heap->size; @@ -189,7 +189,7 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) { scr.obj_indices = new IntMapper(); - if (s->version >= SCI_VERSION_1_1) + if (s->_version >= SCI_VERSION_1_1) scr.heap_start = scr.buf + scr.script_size; else scr.heap_start = scr.buf; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 2677ff4131..3040e4c462 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -27,7 +27,8 @@ namespace Sci { -EngineState::EngineState() : _dirseeker(this) { +EngineState::EngineState(ResourceManager *res, sci_version_t version, uint32 flags) +: resmgr(res), _version(version), _flags(flags), _dirseeker(this) { widget_serial_counter = 0; resmgr = 0; @@ -80,9 +81,6 @@ EngineState::EngineState() : _dirseeker(this) { last_wait_time = 0; - version = 0; - flags = 0; - kernel_opt_flags = 0; _fileHandles.resize(5); diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 561db322ef..15c1c2e63e 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -109,7 +109,7 @@ public: struct EngineState : public Common::Serializable { public: - EngineState(); + EngineState(ResourceManager *res, sci_version_t version, uint32 flags); virtual ~EngineState(); virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -118,6 +118,9 @@ public: ResourceManager *resmgr; /**< The resource manager */ + const sci_version_t _version; /**< The approximated patchlevel of the version to emulate */ + const uint32 _flags; /**< Specific game flags */ + Common::String _gameName; /**< Designation of the primary object (which inherits from Game) */ char *game_version; @@ -174,9 +177,6 @@ public: uint32 game_start_time; /**< The time at which the interpreter was started */ uint32 last_wait_time; /**< The last time the game invoked Wait() */ - sci_version_t version; /**< The approximated patchlevel of the version to emulate */ - uint32 flags; /**< Specific game flags */ - unsigned int kernel_opt_flags; /**< Kernel optimization flags- used for performance tweaking */ /* Kernel File IO stuff */ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 0e7f932333..fe9523197e 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -971,7 +971,7 @@ void run_vm(EngineState *s, int restoring) { gc_countdown(s); xs->sp -= (opparams[1] >> 1) + 1; - if (!(s->flags & GF_SCI0_OLD)) { + if (!(s->_flags & GF_SCI0_OLD)) { xs->sp -= restadjust; s->r_amp_rest = 0; // We just used up the restadjust, remember? } @@ -981,7 +981,7 @@ void run_vm(EngineState *s, int restoring) { } else { int argc = ASSERT_ARITHMETIC(xs->sp[0]); - if (!(s->flags & GF_SCI0_OLD)) + if (!(s->_flags & GF_SCI0_OLD)) argc += restadjust; if (s->_kernel->_kernelFuncs[opparams[0]].signature @@ -998,7 +998,7 @@ void run_vm(EngineState *s, int restoring) { xs_new = &(s->_executionStack.back()); s->_executionStackPosChanged = true; - if (!(s->flags & GF_SCI0_OLD)) + if (!(s->_flags & GF_SCI0_OLD)) restadjust = s->r_amp_rest; } @@ -1201,10 +1201,10 @@ void run_vm(EngineState *s, int restoring) { case 0x39: // lofsa s->r_acc.segment = xs->addr.pc.segment; - if (s->version >= SCI_VERSION_1_1) { + if (s->_version >= SCI_VERSION_1_1) { s->r_acc.offset = opparams[0] + local_script->script_size; } else { - if (s->flags & GF_SCI1_LOFSABSOLUTE) + if (s->_flags & GF_SCI1_LOFSABSOLUTE) s->r_acc.offset = opparams[0]; else s->r_acc.offset = xs->addr.pc.offset + opparams[0]; @@ -1221,7 +1221,7 @@ void run_vm(EngineState *s, int restoring) { case 0x3a: // lofss r_temp.segment = xs->addr.pc.segment; - if (s->flags & GF_SCI1_LOFSABSOLUTE) + if (s->_flags & GF_SCI1_LOFSABSOLUTE) r_temp.offset = opparams[0]; else r_temp.offset = xs->addr.pc.offset + opparams[0]; @@ -1441,7 +1441,7 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) { // Determines if obj explicitly defines slc as a varselector // Returns -1 if not found - if (s->version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1_1) { int varnum = obj->variable_names_nr; int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET; int i; @@ -1514,7 +1514,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select // Early SCI versions used the LSB in the selector ID as a read/write // toggle, meaning that we must remove it for selector lookup. - if (s->flags & GF_SCI0_OLD) + if (s->_flags & GF_SCI0_OLD) selector_id &= ~1; if (!obj) { @@ -1608,12 +1608,12 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, *was_new = 1; *script = s->resmgr->findResource(kResourceTypeScript, script_nr, 0); - if (s->version >= SCI_VERSION_1_1) + if (s->_version >= SCI_VERSION_1_1) *heap = s->resmgr->findResource(kResourceTypeHeap, script_nr, 0); - if (!*script || (s->version >= SCI_VERSION_1_1 && !heap)) { + if (!*script || (s->_version >= SCI_VERSION_1_1 && !heap)) { sciprintf("Script 0x%x requested but not found\n", script_nr); - if (s->version >= SCI_VERSION_1_1) { + if (s->_version >= SCI_VERSION_1_1) { if (*heap) sciprintf("Inconsistency: heap resource WAS found\n"); else if (*script) @@ -1680,7 +1680,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { Script *scr = s->seg_manager->getScript(seg_id); - if (s->flags & GF_SCI0_OLD) { + if (s->_flags & GF_SCI0_OLD) { // int locals_nr = READ_LE_UINT16(script->data); @@ -1849,14 +1849,14 @@ int script_instantiate_sci11(EngineState *s, int script_nr) { } int script_instantiate(EngineState *s, int script_nr) { - if (s->version >= SCI_VERSION_1_1) + if (s->_version >= SCI_VERSION_1_1) return script_instantiate_sci11(s, script_nr); else return script_instantiate_sci0(s, script_nr); } void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { - reg_t reg = make_reg(seg, (s->flags & GF_SCI0_OLD) ? 2 : 0); + reg_t reg = make_reg(seg, (s->_flags & GF_SCI0_OLD) ? 2 : 0); int objtype, objlength; Script *scr = s->seg_manager->getScript(seg); @@ -1900,7 +1900,7 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { } void script_uninstantiate(EngineState *s, int script_nr) { - reg_t reg = make_reg(0, (s->flags & GF_SCI0_OLD) ? 2 : 0); + reg_t reg = make_reg(0, (s->_flags & GF_SCI0_OLD) ? 2 : 0); reg.segment = s->seg_manager->segGet(script_nr); Script *scr = script_locate_by_segment(s, reg.segment); @@ -1921,7 +1921,7 @@ void script_uninstantiate(EngineState *s, int script_nr) { if (s->_classtable[i].reg.segment == reg.segment) s->_classtable[i].reg = NULL_REG; - if (s->version < SCI_VERSION_1_1) + if (s->_version < SCI_VERSION_1_1) script_uninstantiate_sci0(s, script_nr, reg.segment); else sciprintf("FIXME: Add proper script uninstantiation for SCI 1.1\n"); @@ -1959,7 +1959,7 @@ static EngineState *_game_run(EngineState *s, int restoring) { game_exit(s); script_free_engine(s); - script_init_engine(s, s->version); + script_init_engine(s); game_init(s); sfx_reset_player(); _init_stack_base_with_selector(s, s->_kernel->_selectorMap.play); diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 39ffbb2760..f8e11b9b88 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -67,12 +67,12 @@ struct Object; #define SCRIPT_FUNCTAREAPTR_MAGIC 8 -8 /** Offset of the name pointer */ -#define SCRIPT_NAME_OFFSET (s->version < SCI_VERSION_1_1 ? 14 -8 : 16) -#define SCRIPT_NAME_SELECTOR (s->version < SCI_VERSION_1_1 ? 3 : 8) +#define SCRIPT_NAME_OFFSET (s->_version < SCI_VERSION_1_1 ? 14 -8 : 16) +#define SCRIPT_NAME_SELECTOR (s->_version < SCI_VERSION_1_1 ? 3 : 8) /** Object-relative offset of the -info- selector */ -#define SCRIPT_INFO_OFFSET (s->version < SCI_VERSION_1_1 ? 12 -8 : 14) -#define SCRIPT_INFO_SELECTOR (s->version < SCI_VERSION_1_1 ? 2 : 7) +#define SCRIPT_INFO_OFFSET (s->_version < SCI_VERSION_1_1 ? 12 -8 : 14) +#define SCRIPT_INFO_SELECTOR (s->_version < SCI_VERSION_1_1 ? 2 : 7) /** Flag fo the -info- selector */ #define SCRIPT_INFO_CLONE 0x0001 @@ -84,18 +84,18 @@ struct Object; /** Magical object identifier */ #define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234 /** Offset of this identifier */ -#define SCRIPT_OBJECT_MAGIC_OFFSET (s->version < SCI_VERSION_1_1 ? -8 : 0) +#define SCRIPT_OBJECT_MAGIC_OFFSET (s->_version < SCI_VERSION_1_1 ? -8 : 0) /** Script-relative offset of the species ID */ #define SCRIPT_SPECIES_OFFSET 8 -8 -#define SCRIPT_SUPERCLASS_OFFSET (s->version < SCI_VERSION_1_1 ? 10 -8 : 12) +#define SCRIPT_SUPERCLASS_OFFSET (s->_version < SCI_VERSION_1_1 ? 10 -8 : 12) /*---------------------------------*/ /* Script selector index variables */ /*---------------------------------*/ -#define SCRIPT_SPECIES_SELECTOR (s->version < SCI_VERSION_1_1 ? 0 : 5) -#define SCRIPT_SUPERCLASS_SELECTOR (s->version < SCI_VERSION_1_1 ? 1 : 6) +#define SCRIPT_SPECIES_SELECTOR (s->_version < SCI_VERSION_1_1 ? 0 : 5) +#define SCRIPT_SUPERCLASS_SELECTOR (s->_version < SCI_VERSION_1_1 ? 1 : 6) #define SCRIPT_CLASSSCRIPT_SELECTOR 4 /** Magic adjustment value for lofsa and lofss */ @@ -402,7 +402,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * ** Returns : (void) */ -int script_init_engine(EngineState *s, sci_version_t version); +int script_init_engine(EngineState *s); /* Initializes a EngineState block ** Parameters: (EngineState *) s: The state to initialize ** Returns : 0 on success, 1 if vocab.996 (the class table) is missing or corrupted diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index eb75beab8f..8083ddad73 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -124,11 +124,10 @@ Common::Error SciEngine::run() { // FIXME/TODO: Move some of the stuff below to init() - sci_version_t version; + const sci_version_t version = getVersion(); + const uint32 flags = getFlags(); int res_version = getResourceVersion(); - version = getVersion(); - _resmgr = new ResourceManager(res_version, 256 * 1024); if (!_resmgr) { @@ -144,37 +143,34 @@ Common::Error SciEngine::run() { map_MIDI_instruments(_resmgr); #endif - _gamestate = new EngineState(); - _gamestate->resmgr = _resmgr; - _gamestate->gfx_state = NULL; - _gamestate->flags = getFlags(); + _gamestate = new EngineState(_resmgr, version, flags); // Verify that we haven't got an invalid game detection entry if (version < SCI_VERSION_1_EARLY) { // SCI0/SCI01 - if (_gamestate->flags & GF_SCI1_EGA || - _gamestate->flags & GF_SCI1_LOFSABSOLUTE || - _gamestate->flags & GF_SCI1_NEWDOSOUND) { + if (flags & GF_SCI1_EGA || + flags & GF_SCI1_LOFSABSOLUTE || + flags & GF_SCI1_NEWDOSOUND) { error("This game entry is erroneous. It's marked as SCI0/SCI01, but it has SCI1 flags set"); } } else if (version >= SCI_VERSION_1_EARLY && version <= SCI_VERSION_1_LATE) { // SCI1 - if (_gamestate->flags & GF_SCI0_OLD || - _gamestate->flags & GF_SCI0_OLDGFXFUNCS || - _gamestate->flags & GF_SCI0_OLDGETTIME) { + if (flags & GF_SCI0_OLD || + flags & GF_SCI0_OLDGFXFUNCS || + flags & GF_SCI0_OLDGETTIME) { error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set"); } } else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) { - if (_gamestate->flags & GF_SCI1_EGA || - _gamestate->flags & GF_SCI1_LOFSABSOLUTE || - _gamestate->flags & GF_SCI1_NEWDOSOUND) { + if (flags & GF_SCI1_EGA || + flags & GF_SCI1_LOFSABSOLUTE || + flags & GF_SCI1_NEWDOSOUND) { error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI1 flags set"); } - if (_gamestate->flags & GF_SCI0_OLD || - _gamestate->flags & GF_SCI0_OLDGFXFUNCS || - _gamestate->flags & GF_SCI0_OLDGETTIME) { + if (flags & GF_SCI0_OLD || + flags & GF_SCI0_OLDGFXFUNCS || + flags & GF_SCI0_OLDGETTIME) { error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set"); } @@ -183,7 +179,7 @@ Common::Error SciEngine::run() { error ("Unknown SCI version in game entry"); } - if (script_init_engine(_gamestate, version)) + if (script_init_engine(_gamestate)) return Common::kUnknownError; -- cgit v1.2.3 From 4f4005f0b09668b608962ce32988ce63e269e55c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 21:53:45 +0000 Subject: oops svn-id: r41178 --- engines/sci/engine/state.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 3040e4c462..0e4b63acee 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -31,8 +31,6 @@ EngineState::EngineState(ResourceManager *res, sci_version_t version, uint32 fla : resmgr(res), _version(version), _flags(flags), _dirseeker(this) { widget_serial_counter = 0; - resmgr = 0; - game_version = 0; gfx_state = 0; -- cgit v1.2.3 From fa02e0df7b48a3d24984d78117dc2952d0b6c5b4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jun 2009 22:16:31 +0000 Subject: SCI: Made some members of class Resource protected; some cleanup svn-id: r41180 --- engines/sci/resource.cpp | 29 +++++++++++------------------ engines/sci/resource.h | 17 ++++++++++------- engines/sci/vocabulary.cpp | 2 +- 3 files changed, 22 insertions(+), 26 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 05dcf95bd0..4999299f75 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -63,7 +63,7 @@ enum SolFlags { kSolFlagIsSigned = 1 << 3 }; -const char *sci_error_types[] = { +static const char *sci_error_types[] = { "No error", "I/O error", "Resource is empty (size 0)", @@ -78,7 +78,7 @@ const char *sci_error_types[] = { }; // These are the 20 resource types supported by SCI1.1 -const char *resourceTypeNames[] = { +static const char *resourceTypeNames[] = { "view", "pic", "script", "text", "sound", "memory", "vocab", "font", "cursor", "patch", "bitmap", "palette", "cdaudio", @@ -86,7 +86,7 @@ const char *resourceTypeNames[] = { "audio36", "sync36" }; -const char *resourceTypeSuffixes[] = { +static const char *resourceTypeSuffixes[] = { "v56", "p56", "scr", "tex", "snd", " ", "voc", "fon", "cur", "pat", "bit", "pal", "cda", "aud", "syn", @@ -97,13 +97,6 @@ const char *getResourceTypeName(ResourceType restype) { return resourceTypeNames[restype]; } -const char *getResourceTypeSuffix(ResourceType restype) { - return resourceTypeSuffixes[restype]; -} - -typedef int decomp_funct(Resource *result, Common::ReadStream &stream, int sci_version); -typedef void patch_sprintf_funct(char *string, Resource *res); - //-- Resource main functions -- Resource::Resource() { data = NULL; @@ -290,7 +283,7 @@ int sci0_get_compression_method(Common::ReadStream &stream) { return compressionMethod; } -int sci_test_view_type(ResourceManager *mgr) { +int ResourceManager::guessSciVersion() { Common::File file; char filename[MAXPATHLEN]; int compression; @@ -298,7 +291,7 @@ int sci_test_view_type(ResourceManager *mgr) { int i; for (i = 0; i < 1000; i++) { - res = mgr->testResource(kResourceTypeView, i); + res = testResource(kResourceTypeView, i); if (!res) continue; @@ -322,7 +315,7 @@ int sci_test_view_type(ResourceManager *mgr) { // Try the same thing with pics for (i = 0; i < 1000; i++) { - res = mgr->testResource(kResourceTypePic, i); + res = testResource(kResourceTypePic, i); if (!res) continue; @@ -442,14 +435,14 @@ ResourceManager::ResourceManager(int version, int maxMemory) { switch (_mapVersion) { case SCI_VERSION_0: if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) { - version = sci_test_view_type(this) ? SCI_VERSION_01_VGA : SCI_VERSION_0; + version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0; } else if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) { - version = sci_test_view_type(this); + version = guessSciVersion(); if (version != SCI_VERSION_01_VGA) { version = testResource(kResourceTypeVocab, 912) ? SCI_VERSION_0 : SCI_VERSION_01; } } else { - version = sci_test_view_type(this) ? SCI_VERSION_01_VGA : SCI_VERSION_0; + version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0; } break; case SCI_VERSION_01_VGA_ODD: @@ -586,7 +579,7 @@ void ResourceManager::freeOldResources(int last_invulnerable) { } } -Resource *ResourceManager::findResource(ResourceType type, int number, int lock) { +Resource *ResourceManager::findResource(ResourceType type, int number, bool lock) { Resource *retval; if (number >= sci_max_resource_nr[_sciVersion]) { @@ -863,7 +856,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { SearchMan.listMatchingMembers(files, mask); // SCI1 and later naming - nnn.typ mask = "*."; - mask += getResourceTypeSuffix((ResourceType)i); + mask += resourceTypeSuffixes[i]; SearchMan.listMatchingMembers(files, mask); for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); x++) { bAdd = false; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index b1ae3d23ba..eade4acbd0 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -88,7 +88,6 @@ enum ResSourceType { #define SCI1_RESMAP_ENTRIES_SIZE 6 #define SCI11_RESMAP_ENTRIES_SIZE 5 -extern const char *sci_error_types[]; extern const char *sci_version_types[]; extern const int sci_max_resource_nr[]; /**< Highest possible resource numbers */ @@ -118,8 +117,6 @@ enum ResourceType { }; const char *getResourceTypeName(ResourceType restype); -// Suffixes for SCI1 patch files -const char *getResourceTypeSuffix(ResourceType restype); #define sci0_last_resource kResourceTypePatch #define sci1_last_resource kResourceTypeHeap @@ -141,8 +138,11 @@ struct ResourceSource { ResourceSource *next; }; +class ResourceManager; + /** Class for storing resources in memory */ class Resource { + friend class ResourceManager; public: Resource(); ~Resource(); @@ -155,10 +155,11 @@ public: uint16 number; ResourceType type; uint32 id; //!< contains number and type. - unsigned int size; - unsigned int file_offset; /**< Offset in file */ + uint32 size; +protected: + uint32 file_offset; /**< Offset in file */ ResourceStatus status; - unsigned short lockers; /**< Number of places where this resource was locked */ + uint16 lockers; /**< Number of places where this resource was locked */ ResourceSource *source; }; @@ -191,7 +192,7 @@ public: * @note Locked resources are guaranteed not to have their contents freed until * they are unlocked explicitly (by unlockResource). */ - Resource *findResource(ResourceType type, int number, int lock); + Resource *findResource(ResourceType type, int number, bool lock); /* Unlocks a previously locked resource ** (Resource *) res: The resource to free @@ -291,6 +292,8 @@ protected: void printLRU(); void addToLRU(Resource *res); void removeFromLRU(Resource *res); + + int guessSciVersion(); }; /** diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp index accdcc9eb1..b12114d845 100644 --- a/engines/sci/vocabulary.cpp +++ b/engines/sci/vocabulary.cpp @@ -241,7 +241,7 @@ void Vocabulary::freeSuffixes() { else resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 0); - if (resource && resource->status == kResStatusLocked) + if (resource) _resmgr->unlockResource(resource, resource->number, kResourceTypeVocab); _parserSuffixes.clear(); -- cgit v1.2.3 From 8e987c80d1d66815687c8aac0efdc5543e2b697a Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 4 Jun 2009 23:55:08 +0000 Subject: SCI: Fixed some endian bugs related to speech handling. READ_UINT* are not LE, but use native endianness. Thanks to clone2727 for pointing this out. svn-id: r41181 --- engines/sci/resource.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 4999299f75..8299b718f4 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1231,7 +1231,7 @@ bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &o return false; byte *ptr = _audioMapSCI1; - while ((n = READ_UINT16(ptr)) != 0xFFFF) { + while ((n = READ_LE_UINT16(ptr)) != 0xFFFF) { if (n == audioNumber) { off = READ_LE_UINT32(ptr + 2); size = READ_LE_UINT32(ptr + 6); @@ -1264,7 +1264,7 @@ bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bo byte *ptr = _audioMapSCI11->data; - offset = READ_UINT32(ptr); + offset = READ_LE_UINT32(ptr); ptr += 4; while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { @@ -1274,7 +1274,7 @@ bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bo if (n == 0xffffffff) break; - offset += (READ_UINT16(ptr) | (ptr[2] << 16)); + offset += READ_LE_UINT24(ptr); ptr += 3; int syncSkip = 0; @@ -1284,9 +1284,9 @@ bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bo if (getSync) { if (size) - *size = READ_UINT16(ptr); + *size = READ_LE_UINT16(ptr); } else { - syncSkip = READ_UINT16(ptr); + syncSkip = READ_LE_UINT16(ptr); } ptr += 2; @@ -1295,7 +1295,7 @@ bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bo n ^= 0x40; if (!getSync) - syncSkip += READ_UINT16(ptr); + syncSkip += READ_LE_UINT16(ptr); ptr += 2; } @@ -1339,10 +1339,10 @@ bool AudioResource::findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, b if (n == 0xffffffff) break; - offset = READ_UINT32(ptr); + offset = READ_LE_UINT32(ptr); ptr += 4; - int syncSize = READ_UINT16(ptr); + int syncSize = READ_LE_UINT16(ptr); ptr += 2; if (n == audioNumber) { @@ -1383,13 +1383,13 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 if (volume == 65535) { while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { - n = READ_UINT16(ptr); + n = READ_LE_UINT16(ptr); ptr += 2; if (n == 0xffff) break; - offset = READ_UINT32(ptr); + offset = READ_LE_UINT32(ptr); ptr += 4; if (n == audioNumber) -- cgit v1.2.3 From 3c58a6ca8f1e74bc9f7ba7022d01b95710d5b03e Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 5 Jun 2009 01:12:52 +0000 Subject: SCI: Audio: Fixed bug in sample length computation. svn-id: r41186 --- engines/sci/resource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 8299b718f4..24b4d9beed 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1616,7 +1616,7 @@ Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 vol } } - *sampleLen = (Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; + *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; } else { warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff, (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff); -- cgit v1.2.3 From 24cb130b264285ff9635ee8242063ed2afaade11 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 5 Jun 2009 18:05:45 +0000 Subject: Removed some unused code and performed some cleanup svn-id: r41197 --- engines/sci/gfx/gfx_driver.cpp | 3 --- engines/sci/gfx/gfx_driver.h | 34 ---------------------------------- engines/sci/gfx/operations.cpp | 31 ++++++------------------------- engines/sci/gfx/operations.h | 9 --------- 4 files changed, 6 insertions(+), 71 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index 2418f45824..c63bdf98f8 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -305,9 +305,6 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common: } gfx_driver_t gfx_driver_scummvm = { - NULL, - 0, 0, - 0, NULL, scummvm_init, scummvm_exit, diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h index 254f619b34..47b5e7de21 100644 --- a/engines/sci/gfx/gfx_driver.h +++ b/engines/sci/gfx/gfx_driver.h @@ -38,10 +38,6 @@ enum gfx_buffer_t { }; -/* graphics driver hints */ -#define GFX_CAPABILITY_SHADING (1<<0) -#define GFX_CAPABILITY_STIPPLED_LINES (1<<6) - /* Principial graphics driver architecture ** --------------------------------------- ** @@ -71,38 +67,8 @@ struct gfx_driver_t { /* Graphics driver */ gfx_mode_t *mode; /* Currently active mode, NULL if no mode is active */ - int pointer_x, pointer_y; /* Mouse pointer position */ - - int capabilities; /* The driver's capabilities: A list of flags that may - ** be pre-defined or set after a successful initialization. - */ - /* Capability flags: - ** - ** The words MUST, SHOULD and MAY are to be interpreted as described in - ** the IETF RFC 1123. - ** - ** GFX_CAPABILITY_SHADING: draw_filled_rect() supports drawing shaded - ** rectangles. - ** GFX_CAPABILITY_STIPPLED_LINES: The driver is able to draw stippled lines - ** horizontally and vertically (xl = 0 or yl = 0). - */ - /*** Initialization ***/ - int (*set_parameter)(gfx_driver_t *drv, char *attribute, char *value); - /* Sets a driver-specific parameter - ** Parameters: (gfx_driver_t *) drv: Pointer to the affected driver - ** (char *) attribute: Name of the attribute/parameter to set - ** (char *) value: The value to set, or NULL to query the value - ** Returns : (int) GFX_OK or GFX_FATAL, which signals a fatal error - ** condition. - ** This function should make extensive use of sciprintf() to signal invalid - ** values or unapplicable attributes. - ** Note that it may be called either before initialization (to interpret - ** config file or command line parameters) or afterwars (from the command - ** console). - */ - int (*init)(gfx_driver_t *drv, int xres, int yres, int bytespp); /* Attempts to initialize a specific graphics mode diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index 49c73ac0fd..d9dc539c79 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -265,8 +265,9 @@ static int _gfxop_draw_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm, int prior } static void _gfxop_full_pointer_refresh(GfxState *state) { - state->pointer_pos.x = state->driver->pointer_x / state->driver->mode->xfact; - state->pointer_pos.y = state->driver->pointer_y / state->driver->mode->yfact; + Common::Point mousePoint = g_system->getEventManager()->getMousePos(); + state->pointer_pos.x = mousePoint.x / state->driver->mode->xfact; + state->pointer_pos.y = mousePoint.y / state->driver->mode->yfact; } static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer); @@ -450,12 +451,6 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, return GFX_OK; } -int gfxop_set_parameter(GfxState *state, char *attribute, char *value) { - BASIC_CHECKS(GFX_FATAL); - - return state->driver->set_parameter(state->driver, attribute, value); -} - int gfxop_exit(GfxState *state) { BASIC_CHECKS(GFX_ERROR); @@ -822,8 +817,7 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common GFXWARN("Attempt to draw stippled line which is neither an hbar nor a vbar: (%d,%d) -- (%d,%d)\n", start.x, start.y, end.x, end.y); return GFX_ERROR; } - if (!(state->driver->capabilities & GFX_CAPABILITY_STIPPLED_LINES)) - return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode); + return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode); } if ((retval = state->driver->draw_line(state->driver, start, end, color, line_mode, line_style))) { @@ -923,8 +917,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); - if (PALETTE_MODE || !(state->driver->capabilities & GFX_CAPABILITY_SHADING)) - shade_type = GFX_BOX_SHADE_FLAT; + shade_type = GFX_BOX_SHADE_FLAT; _gfxop_add_dirty(state, box); @@ -1244,9 +1237,7 @@ int gfxop_set_pointer_position(GfxState *state, Common::Point pos) { return 0; // Not fatal } - state->driver->pointer_x = pos.x * state->driver->mode->xfact; - state->driver->pointer_y = pos.y * state->driver->mode->yfact; - g_system->warpMouse(state->driver->pointer_x, state->driver->pointer_y); + g_system->warpMouse(pos.x * state->driver->mode->xfact, pos.y * state->driver->mode->yfact); _gfxop_full_pointer_refresh(state); return 0; @@ -1373,8 +1364,6 @@ static sci_event_t scummvm_get_event(gfx_driver_t *drv) { // Don't generate events for mouse movement while (found && ev.type == Common::EVENT_MOUSEMOVE) { - drv->pointer_x = ev.mouse.x; - drv->pointer_y = ev.mouse.y; found = em->pollEvent(ev); } @@ -1538,26 +1527,18 @@ static sci_event_t scummvm_get_event(gfx_driver_t *drv) { case Common::EVENT_LBUTTONDOWN: input.type = SCI_EVT_MOUSE_PRESS; input.data = 1; - drv->pointer_x = p.x; - drv->pointer_y = p.y; break; case Common::EVENT_RBUTTONDOWN: input.type = SCI_EVT_MOUSE_PRESS; input.data = 2; - drv->pointer_x = p.x; - drv->pointer_y = p.y; break; case Common::EVENT_LBUTTONUP: input.type = SCI_EVT_MOUSE_RELEASE; input.data = 1; - drv->pointer_x = p.x; - drv->pointer_y = p.y; break; case Common::EVENT_RBUTTONUP: input.type = SCI_EVT_MOUSE_RELEASE; input.data = 2; - drv->pointer_x = p.x; - drv->pointer_y = p.y; break; // Misc events diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index 2f4a443509..88af32c624 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -152,15 +152,6 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, ** to provide any useful graphics support */ -int gfxop_set_parameter(GfxState *state, char *attribute, char *value); -/* Sets a driver-specific parameter -** Parameters: (GfxState *) state: The state, encapsulating the driver object to manipulate -** (char *) attribute: The attribute to set -** (char *) value: The value the attribute should be set to -** Returns : (int) GFX_OK on success, GFX_FATAL on fatal error conditions triggered -** by the command -*/ - int gfxop_exit(GfxState *state); /* Deinitializes a currently active driver ** Parameters: (GfxState *) state: The state encapsulating the driver in question -- cgit v1.2.3 From 7c84cca81d4fd7eeadd3d6903d80e1e856c2d5a0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 5 Jun 2009 19:04:14 +0000 Subject: Moved some more debug commands to ScummVM's coneole and removed some unused code svn-id: r41198 --- engines/sci/console.cpp | 239 ++++++++++++++++++++++++++++- engines/sci/console.h | 1 + engines/sci/engine/kfile.cpp | 2 +- engines/sci/engine/scriptdebug.cpp | 297 ------------------------------------- engines/sci/engine/vm.cpp | 4 +- engines/sci/engine/vm.h | 4 +- engines/sci/gfx/gfx_widgets.cpp | 12 +- engines/sci/gfx/gfx_widgets.h | 2 +- 8 files changed, 248 insertions(+), 313 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 685d0fbb91..26ff08d065 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -63,6 +63,7 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); DVar_Register("weak_validations", &g_debug_weak_validations, DVAR_BOOL, 0); + DVar_Register("script_abort_flag", &script_abort_flag, DVAR_INT, 0); // General DCmd_Register("help", WRAP_METHOD(Console, cmdHelp)); @@ -115,6 +116,9 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DCmd_Register("dynamic_views", WRAP_METHOD(Console, cmdDynamicViews)); DCmd_Register("dropped_views", WRAP_METHOD(Console, cmdDroppedViews)); DCmd_Register("status_bar", WRAP_METHOD(Console, cmdStatusBarColors)); +#ifdef GFXW_DEBUG_WIDGETS + DCmd_Register("print_widget", WRAP_METHOD(Console, cmdPrintWidget)); +#endif // Segments DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); DCmd_Register("segment_info", WRAP_METHOD(Console, cmdSegmentInfo)); @@ -182,6 +186,14 @@ void Console::postEnter() { _vm->_mixer->pauseAll(false); } + +#if 0 +// Unused +#define LOOKUP_SPECIES(species) (\ + (species >= 1000) ? species : *(s->_classtable[species].scriptposp) \ + + s->_classtable[species].class_offset) +#endif + bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("\n"); DebugPrintf("Variables\n"); @@ -191,6 +203,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("simulated_key: Add a key with the specified scan code to the event list\n"); DebugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n"); DebugPrintf("weak_validations: Turns some validation errors into warnings\n"); + DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n"); DebugPrintf("\n"); DebugPrintf("Commands\n"); DebugPrintf("--------\n"); @@ -248,6 +261,9 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" dynamic_views - Lists active dynamic views\n"); DebugPrintf(" dropped_views - Lists dropped dynamic views\n"); DebugPrintf(" status_bar - Sets the colors of the status bar\n"); +#ifdef GFXW_DEBUG_WIDGETS + DebugPrintf(" print_widget - Shows active widgets (no params) or information on the specified widget indices\n"); +#endif DebugPrintf("\n"); DebugPrintf("Segments:\n"); DebugPrintf(" segment_table - Lists all segments\n"); @@ -667,7 +683,7 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { if (newstate) { g_EngineState->successor = newstate; // Set successor - script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game + script_abort_flag = 2; // Abort current game with replay g_debugstate_valid = 0; shrink_execution_stack(g_EngineState, g_EngineState->execution_stack_base + 1); @@ -2678,4 +2694,225 @@ int printObject(EngineState *s, reg_t pos) { return 0; } +#define GETRECT(ll, rr, tt, bb) \ + ll = GET_SELECTOR(pos, ll); \ + rr = GET_SELECTOR(pos, rr); \ + tt = GET_SELECTOR(pos, tt); \ + bb = GET_SELECTOR(pos, bb); + +#if 0 +// TODO Re-implement this +static void viewobjinfo(EngineState *s, HeapPtr pos) { + char *signals[16] = { + "stop_update", + "updated", + "no_update", + "hidden", + "fixed_priority", + "always_update", + "force_update", + "remove", + "frozen", + "is_extra", + "hit_obstacle", + "doesnt_turn", + "no_cycler", + "ignore_horizon", + "ignore_actor", + "dispose!" + }; + + int x, y, z, priority; + int cel, loop, view, signal; + int nsLeft, nsRight, nsBottom, nsTop; + int lsLeft, lsRight, lsBottom, lsTop; + int brLeft, brRight, brBottom, brTop; + int i; + int have_rects = 0; + Common::Rect nsrect, nsrect_clipped, brrect; + + if (lookup_selector(s, pos, s->_kernel->_selectorMap.nsBottom, NULL) == kSelectorVariable) { + GETRECT(nsLeft, nsRight, nsBottom, nsTop); + GETRECT(lsLeft, lsRight, lsBottom, lsTop); + GETRECT(brLeft, brRight, brBottom, brTop); + have_rects = 1; + } + + GETRECT(view, loop, signal, cel); + + sciprintf("\n-- View information:\ncel %d/%d/%d at ", view, loop, cel); + + x = GET_SELECTOR(pos, x); + y = GET_SELECTOR(pos, y); + priority = GET_SELECTOR(pos, priority); + if (s->_kernel->_selectorMap.z > 0) { + z = GET_SELECTOR(pos, z); + sciprintf("(%d,%d,%d)\n", x, y, z); + } else + sciprintf("(%d,%d)\n", x, y); + + if (priority == -1) + sciprintf("No priority.\n\n"); + else + sciprintf("Priority = %d (band starts at %d)\n\n", priority, PRIORITY_BAND_FIRST(priority)); + + if (have_rects) { + sciprintf("nsRect: [%d..%d]x[%d..%d]\n", nsLeft, nsRight, nsTop, nsBottom); + sciprintf("lsRect: [%d..%d]x[%d..%d]\n", lsLeft, lsRight, lsTop, lsBottom); + sciprintf("brRect: [%d..%d]x[%d..%d]\n", brLeft, brRight, brTop, brBottom); + } + + nsrect = get_nsrect(s, pos, 0); + nsrect_clipped = get_nsrect(s, pos, 1); + brrect = set_base(s, pos); + sciprintf("new nsRect: [%d..%d]x[%d..%d]\n", nsrect.x, nsrect.xend, nsrect.y, nsrect.yend); + sciprintf("new clipped nsRect: [%d..%d]x[%d..%d]\n", nsrect_clipped.x, nsrect_clipped.xend, nsrect_clipped.y, nsrect_clipped.yend); + sciprintf("new brRect: [%d..%d]x[%d..%d]\n", brrect.x, brrect.xend, brrect.y, brrect.yend); + sciprintf("\n signals = %04x:\n", signal); + + for (i = 0; i < 16; i++) + if (signal & (1 << i)) + sciprintf(" %04x: %s\n", 1 << i, signals[i]); +} +#endif +#undef GETRECT + +#define GETRECT(ll, rr, tt, bb) \ + ll = GET_SELECTOR(pos, ll); \ + rr = GET_SELECTOR(pos, rr); \ + tt = GET_SELECTOR(pos, tt); \ + bb = GET_SELECTOR(pos, bb); + +#if 0 +// Draws the nsRect and brRect of a dynview object. nsRect is green, brRect is blue. +// TODO: Re-implement this +static int c_gfx_draw_viewobj(EngineState *s, const Common::Array &cmdParams) { + HeapPtr pos = (HeapPtr)(cmdParams[0].val); + int is_view; + int x, y, priority; + int nsLeft, nsRight, nsBottom, nsTop; + int brLeft, brRight, brBottom, brTop; + + if (!s) { + sciprintf("Not in debug state!\n"); + return 1; + } + + if ((pos < 4) || (pos > 0xfff0)) { + sciprintf("Invalid address.\n"); + return 1; + } + + if (((int16)READ_LE_UINT16(s->heap + pos + SCRIPT_OBJECT_MAGIC_OFFSET)) != SCRIPT_OBJECT_MAGIC_NUMBER) { + sciprintf("Not an object.\n"); + return 0; + } + + + is_view = (lookup_selector(s, pos, s->_kernel->_selectorMap.x, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, s->_kernel->_selectorMap.brLeft, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, s->_kernel->_selectorMap.signal, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, s->_kernel->_selectorMap.nsTop, NULL) == kSelectorVariable); + + if (!is_view) { + sciprintf("Not a dynamic View object.\n"); + return 0; + } + + x = GET_SELECTOR(pos, x); + y = GET_SELECTOR(pos, y); + priority = GET_SELECTOR(pos, priority); + GETRECT(brLeft, brRight, brBottom, brTop); + GETRECT(nsLeft, nsRight, nsBottom, nsTop); + gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen); + + brTop += 10; + brBottom += 10; + nsTop += 10; + nsBottom += 10; + + gfxop_fill_box(s->gfx_state, gfx_rect(nsLeft, nsTop, nsRight - nsLeft + 1, nsBottom - nsTop + 1), s->ega_colors[2]); + gfxop_fill_box(s->gfx_state, gfx_rect(brLeft, brTop, brRight - brLeft + 1, brBottom - brTop + 1), s->ega_colors[1]); + gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y - 1, 3, 3), s->ega_colors[0]); + gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y, 3, 1), s->ega_colors[priority]); + gfxop_fill_box(s->gfx_state, gfx_rect(x, y - 1, 1, 3), s->ega_colors[priority]); + gfxop_update(s->gfx_state); + + return 0; +} +#endif +#undef GETRECT + +#if 0 +// Executes one operation skipping over sends +// TODO Re-implement this +int c_stepover(EngineState *s, const Common::Array &cmdParams) { + int opcode, opnumber; + + if (!g_debugstate_valid) { + sciprintf("Not in debug state\n"); + return 1; + } + + g_debugstate_valid = 0; + opcode = s->_heap[*p_pc]; + opnumber = opcode >> 1; + if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || + opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { + g_debug_seeking = _DEBUG_SEEK_SO; + s_debug_seek_level = s->_executionStack.size()-1; + // Store in s_debug_seek_special the offset of the next command after send + switch (opcode) { + case 0x46: // calle W + s_debug_seek_special = *p_pc + 5; + break; + + case 0x44: // callb W + case 0x47: // calle B + case 0x56: // super W + s_debug_seek_special = *p_pc + 4; + break; + + case 0x45: // callb B + case 0x57: // super B + case 0x4A: // send W + case 0x54: // self W + s_debug_seek_special = *p_pc + 3; + break; + + default: + s_debug_seek_special = *p_pc + 2; + } + } + + return 0; +} +#endif + +#ifdef GFXW_DEBUG_WIDGETS +extern GfxWidget *debug_widgets[]; +extern int debug_widget_pos; + +// If called with no parameters, it shows which widgets are active +// With parameters, it lists the widget corresponding to the numerical index specified (for each parameter). +bool Console::cmdPrintWidget(int argc, const char **argv) { + if (argc > 1) { + for (int i = 0; i < argc; i++) { + int widget_nr = atoi(argv[1]); + + DebugPrintf("===== Widget #%d:\n", widget_nr); + debug_widgets[widget_nr]->print(0); + } + } else if (debug_widget_pos > 1) { + DebugPrintf("Widgets 0-%d are active\n", debug_widget_pos - 1); + } else if (debug_widget_pos == 1) { + DebugPrintf("Widget 0 is active\n"); + } else { + DebugPrintf("No widgets are active\n"); + } + + return true; +} +#endif + } // End of namespace Sci diff --git a/engines/sci/console.h b/engines/sci/console.h index b97b14f354..b2e66daa0f 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -98,6 +98,7 @@ private: bool cmdDynamicViews(int argc, const char **argv); bool cmdDroppedViews(int argc, const char **argv); bool cmdStatusBarColors(int argc, const char **argv); + bool cmdPrintWidget(int argc, const char **argv); // Segments bool cmdPrintSegmentTable(int argc, const char **argv); bool cmdSegmentInfo(int argc, const char **argv); diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 11d1cb457e..87ddb46e50 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -654,7 +654,7 @@ reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (newstate) { s->successor = newstate; - script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game + script_abort_flag = 2; // Abort current game with replay shrink_execution_stack(s, s->execution_stack_base + 1); } else { s->r_acc = make_reg(0, 1); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 4581c0a37c..26ba01b440 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -53,7 +53,6 @@ static bool s_debug_commands_hooked = false; // Commands hooked to the console y int g_debug_seeking = 0; // Stepping forward until some special condition is met static int s_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth static int s_debug_seek_special = 0; // Used for special seeks(1) -static reg_t s_debug_seek_reg = NULL_REG; // Used for special seeks(2) #define _DEBUG_SEEK_NOTHING 0 #define _DEBUG_SEEK_CALLK 1 // Step forward until callk is found @@ -92,35 +91,12 @@ struct cmd_command_t : public cmd_mm_entry_t { const char *param; }; -#if 0 -// Unused -#define LOOKUP_SPECIES(species) (\ - (species >= 1000) ? species : *(s->_classtable[species].scriptposp) \ - + s->_classtable[species].class_offset) -#endif - // Dummy function, so that it compiles int con_hook_command(ConCommand command, const char *name, const char *param, const char *description) { return 0; } -static const char *_debug_get_input() { - char newinpbuf[256]; - - printf("> "); - if (!fgets(newinpbuf, 254, stdin)) - return NULL; - - size_t l = strlen(newinpbuf); - if (l > 0 && newinpbuf[0] != '\n') { - if (newinpbuf[l-1] == '\n') newinpbuf[l-1] = 0; - memcpy(inputbuf, newinpbuf, 256); - } - - return inputbuf; -} - int c_step(EngineState *s, const Common::Array &cmdParams) { g_debugstate_valid = 0; if (cmdParams.size() && (cmdParams[0].val > 0)) @@ -129,51 +105,6 @@ int c_step(EngineState *s, const Common::Array &cmdParams) { return 0; } -#if 0 -// TODO Re-implement con:so -int c_stepover(EngineState *s, const Common::Array &cmdParams) { - int opcode, opnumber; - - if (!g_debugstate_valid) { - sciprintf("Not in debug state\n"); - return 1; - } - - g_debugstate_valid = 0; - opcode = s->_heap[*p_pc]; - opnumber = opcode >> 1; - if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || - opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { - g_debug_seeking = _DEBUG_SEEK_SO; - s_debug_seek_level = s->_executionStack.size()-1; - // Store in s_debug_seek_special the offset of the next command after send - switch (opcode) { - case 0x46: // calle W - s_debug_seek_special = *p_pc + 5; - break; - - case 0x44: // callb W - case 0x47: // calle B - case 0x56: // super W - s_debug_seek_special = *p_pc + 4; - break; - - case 0x45: // callb B - case 0x57: // super B - case 0x4A: // send W - case 0x54: // self W - s_debug_seek_special = *p_pc + 3; - break; - - default: - s_debug_seek_special = *p_pc + 2; - } - } - - return 0; -} -#endif - enum { _parse_eoi, _parse_token_pareno, @@ -536,103 +467,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod return retval; } -#ifdef GFXW_DEBUG_WIDGETS -extern GfxWidget *debug_widgets[]; -extern int debug_widget_pos; - -static int c_gfx_print_widget(EngineState *s, const Common::Array &cmdParams) { - if (!g_debugstate_valid) { - sciprintf("Not in debug state\n"); - return 1; - } - - if (cmdParams.size()) { - unsigned int i; - for (i = 0; i < cmdParams.size() ; i++) { - int widget_nr = cmdParams[i].val; - - sciprintf("===== Widget #%d:\n", widget_nr); - debug_widgets[widget_nr]->print(0); - } - - } else if (debug_widget_pos > 1) - sciprintf("Widgets 0-%d are active\n", debug_widget_pos - 1); - else if (debug_widget_pos == 1) - sciprintf("Widget 0 is active\n"); - else - sciprintf("No widgets are active\n"); - - return 0; -} -#endif - -#define GETRECT(ll, rr, tt, bb) \ - ll = GET_SELECTOR(pos, ll); \ - rr = GET_SELECTOR(pos, rr); \ - tt = GET_SELECTOR(pos, tt); \ - bb = GET_SELECTOR(pos, bb); - -#if 0 -// Unreferenced - removed -static int c_gfx_draw_viewobj(EngineState *s, const Common::Array &cmdParams) { -// TODO: Re-implement gfx_draw_viewobj -#if 0 - HeapPtr pos = (HeapPtr)(cmdParams[0].val); - int is_view; - int x, y, priority; - int nsLeft, nsRight, nsBottom, nsTop; - int brLeft, brRight, brBottom, brTop; - - if (!s) { - sciprintf("Not in debug state!\n"); - return 1; - } - - if ((pos < 4) || (pos > 0xfff0)) { - sciprintf("Invalid address.\n"); - return 1; - } - - if (((int16)READ_LE_UINT16(s->heap + pos + SCRIPT_OBJECT_MAGIC_OFFSET)) != SCRIPT_OBJECT_MAGIC_NUMBER) { - sciprintf("Not an object.\n"); - return 0; - } - - - is_view = (lookup_selector(s, pos, s->_kernel->_selectorMap.x, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_kernel->_selectorMap.brLeft, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_kernel->_selectorMap.signal, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_kernel->_selectorMap.nsTop, NULL) == kSelectorVariable); - - if (!is_view) { - sciprintf("Not a dynamic View object.\n"); - return 0; - } - - x = GET_SELECTOR(pos, x); - y = GET_SELECTOR(pos, y); - priority = GET_SELECTOR(pos, priority); - GETRECT(brLeft, brRight, brBottom, brTop); - GETRECT(nsLeft, nsRight, nsBottom, nsTop); - gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen); - - brTop += 10; - brBottom += 10; - nsTop += 10; - nsBottom += 10; - - gfxop_fill_box(s->gfx_state, gfx_rect(nsLeft, nsTop, nsRight - nsLeft + 1, nsBottom - nsTop + 1), s->ega_colors[2]); - gfxop_fill_box(s->gfx_state, gfx_rect(brLeft, brTop, brRight - brLeft + 1, brBottom - brTop + 1), s->ega_colors[1]); - gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y - 1, 3, 3), s->ega_colors[0]); - gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y, 3, 1), s->ega_colors[priority]); - gfxop_fill_box(s->gfx_state, gfx_rect(x, y - 1, 1, 3), s->ega_colors[priority]); - gfxop_update(s->gfx_state); - - return 0; -#endif -} -#endif - static int c_disasm_addr(EngineState *s, const Common::Array &cmdParams) { reg_t vpc = cmdParams[0].reg; int op_count = 1; @@ -811,92 +645,6 @@ static int c_send(EngineState *s, const Common::Array &cmdParams) { return 0; } - -#define GETRECT(ll, rr, tt, bb) \ - ll = GET_SELECTOR(pos, ll); \ - rr = GET_SELECTOR(pos, rr); \ - tt = GET_SELECTOR(pos, tt); \ - bb = GET_SELECTOR(pos, bb); - -#if 0 -#ifdef __GNUC__ -#warning "Re-implement viewobjinfo" -#endif -static void viewobjinfo(EngineState *s, HeapPtr pos) { - char *signals[16] = { - "stop_update", - "updated", - "no_update", - "hidden", - "fixed_priority", - "always_update", - "force_update", - "remove", - "frozen", - "is_extra", - "hit_obstacle", - "doesnt_turn", - "no_cycler", - "ignore_horizon", - "ignore_actor", - "dispose!" - }; - - int x, y, z, priority; - int cel, loop, view, signal; - int nsLeft, nsRight, nsBottom, nsTop; - int lsLeft, lsRight, lsBottom, lsTop; - int brLeft, brRight, brBottom, brTop; - int i; - int have_rects = 0; - Common::Rect nsrect, nsrect_clipped, brrect; - - if (lookup_selector(s, pos, s->_kernel->_selectorMap.nsBottom, NULL) == kSelectorVariable) { - GETRECT(nsLeft, nsRight, nsBottom, nsTop); - GETRECT(lsLeft, lsRight, lsBottom, lsTop); - GETRECT(brLeft, brRight, brBottom, brTop); - have_rects = 1; - } - - GETRECT(view, loop, signal, cel); - - sciprintf("\n-- View information:\ncel %d/%d/%d at ", view, loop, cel); - - x = GET_SELECTOR(pos, x); - y = GET_SELECTOR(pos, y); - priority = GET_SELECTOR(pos, priority); - if (s->_kernel->_selectorMap.z > 0) { - z = GET_SELECTOR(pos, z); - sciprintf("(%d,%d,%d)\n", x, y, z); - } else - sciprintf("(%d,%d)\n", x, y); - - if (priority == -1) - sciprintf("No priority.\n\n"); - else - sciprintf("Priority = %d (band starts at %d)\n\n", priority, PRIORITY_BAND_FIRST(priority)); - - if (have_rects) { - sciprintf("nsRect: [%d..%d]x[%d..%d]\n", nsLeft, nsRight, nsTop, nsBottom); - sciprintf("lsRect: [%d..%d]x[%d..%d]\n", lsLeft, lsRight, lsTop, lsBottom); - sciprintf("brRect: [%d..%d]x[%d..%d]\n", brLeft, brRight, brTop, brBottom); - } - - nsrect = get_nsrect(s, pos, 0); - nsrect_clipped = get_nsrect(s, pos, 1); - brrect = set_base(s, pos); - sciprintf("new nsRect: [%d..%d]x[%d..%d]\n", nsrect.x, nsrect.xend, nsrect.y, nsrect.yend); - sciprintf("new clipped nsRect: [%d..%d]x[%d..%d]\n", nsrect_clipped.x, nsrect_clipped.xend, nsrect_clipped.y, nsrect_clipped.yend); - sciprintf("new brRect: [%d..%d]x[%d..%d]\n", brrect.x, brrect.xend, brrect.y, brrect.yend); - sciprintf("\n signals = %04x:\n", signal); - - for (i = 0; i < 16; i++) - if (signal & (1 << i)) - sciprintf(" %04x: %s\n", 1 << i, signals[i]); -} -#endif -#undef GETRECT - // Breakpoint commands int c_se(EngineState *s, const Common::Array &cmdParams) { @@ -959,13 +707,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * break; } - case _DEBUG_SEEK_SO: - if ((*pc != s_debug_seek_reg) || (int)s->_executionStack.size()-1 != s_debug_seek_level) - return; - break; - case _DEBUG_SEEK_GLOBAL: - if (op < op_sag) return; if ((op & 0x3) > 1) @@ -1004,10 +746,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * con_hook_command(c_step, "s", "i*", "Executes one or several operations\n\nEXAMPLES\n\n" " s 4\n\n Execute 4 commands\n\n s\n\n Execute next command"); -#if 0 - // TODO Re-implement con:so - con_hook_command(c_stepover, "so", "", "Executes one operation skipping over sends"); -#endif con_hook_command(c_disasm_addr, "disasm-addr", "!as*", "Disassembles one or more commands\n\n" "USAGE\n\n disasm-addr [startaddr] \n\n" " Valid options are:\n" @@ -1023,50 +761,15 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * con_hook_command(c_go, "go", "", "Executes the script.\n"); con_hook_command(c_set_parse_nodes, "set_parse_nodes", "s*", "Sets the contents of all parse nodes.\n" " Input token must be separated by\n blanks."); - -#ifdef GFXW_DEBUG_WIDGETS - con_hook_command(c_gfx_print_widget, "gfx_print_widget", "i*", "If called with no parameters, it\n shows which widgets are active.\n" - " With parameters, it lists the\n widget corresponding to the\n numerical index specified (for\n each parameter)."); -#endif - -#if 0 - // TODO: Re-enable con:draw_viewobj - con_hook_command(c_gfx_draw_viewobj, "draw_viewobj", "i", "Draws the nsRect and brRect of a\n dynview object.\n\n nsRect is green, brRect\n" - " is blue.\n"); -#endif con_hook_command(c_sg, "sg", "!i", "Steps until the global variable with the\n" "specified index is modified.\n\nSEE ALSO\n\n" " s.1, snk.1, so.1, bpx.1"); -/* - con_hook_int(&script_abort_flag, "script_abort_flag", "Set != 0 to abort execution\n"); -*/ } // If commands were not hooked up } if (g_debug_step_running) g_debug_step_running--; - - while (g_debugstate_valid) { - int skipfirst = 0; - const char *commandstring; - - // Suspend music playing - s->_sound.sfx_suspend(true); - - commandstring = _debug_get_input(); - - // Check if a specific destination has been given - if (commandstring && (commandstring[0] == '.' || commandstring[0] == ':')) - skipfirst = 1; - - //if (commandstring && commandstring[0] != ':') - // con_parse(s, commandstring + skipfirst); - sciprintf("\n"); - - // Resume music playing - s->_sound.sfx_suspend(false); - } } } // End of namespace Sci diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fe9523197e..fd8ce33f51 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -46,7 +46,7 @@ reg_t NULL_REG = {0, 0}; #undef STRICT_READ // Disallows reading from out-of-bounds parameters and locals -int script_abort_flag = 0; // Set to 1 to abort execution // FIXME: Avoid non-const global vars +int script_abort_flag = 0; // Set to 1 to abort execution. Set to 2 to force a replay afterwards // FIXME: Avoid non-const global vars int script_step_counter = 0; // Counts the number of steps executed // FIXME: Avoid non-const global vars int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME: Avoid non-const global vars @@ -1978,7 +1978,7 @@ static EngineState *_game_run(EngineState *s, int restoring) { s = successor; g_EngineState = s; - if (script_abort_flag == SCRIPT_ABORT_WITH_REPLAY) { + if (script_abort_flag == 2) { sciprintf("Restarting with replay()\n"); s->_executionStack.clear(); // Restart with replay diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index f8e11b9b88..5bfbe71ce9 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -272,12 +272,10 @@ struct Breakpoint { Breakpoint *next; }; -#define SCRIPT_ABORT_WITH_REPLAY 1025 - /** * Set this to 1 to abort script execution immediately. Aborting will leave the * debug exec stack intact. - * Set it to SCRIPT_ABORT_WITH_REPLAY to force a replay afterwards. + * Set it to 2 to force a replay afterwards. */ extern int script_abort_flag; diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp index ad9464811e..e17ffae6f1 100644 --- a/engines/sci/gfx/gfx_widgets.cpp +++ b/engines/sci/gfx/gfx_widgets.cpp @@ -49,10 +49,8 @@ GfxWidget *debug_widgets[GFXW_DEBUG_WIDGETS]; int debug_widget_pos = 0; static void _gfxw_debug_add_widget(GfxWidget *widget) { - if (debug_widget_pos == GFXW_DEBUG_WIDGETS) { - GFXERROR("WIDGET DEBUG: Allocated the maximum number of %d widgets- Aborting!\n", GFXW_DEBUG_WIDGETS); - BREAKPOINT(); - } + if (debug_widget_pos == GFXW_DEBUG_WIDGETS) + error("WIDGET DEBUG: Allocated the maximum number of %d widgets- Aborting!\n", GFXW_DEBUG_WIDGETS); debug_widgets[debug_widget_pos++] = widget; } @@ -68,13 +66,11 @@ static void _gfxw_debug_remove_widget(GfxWidget *widget) { } if (found > 1) { - GFXERROR("While removing widget: Found it %d times!\n", found); - BREAKPOINT(); + error("While removing widget: Found it %d times!\n", found); } if (found == 0) { - GFXERROR("Attempted removal of unregistered widget!\n"); - BREAKPOINT(); + error("Attempted removal of unregistered widget!\n"); } } #else // !GFXW_DEBUG_WIDGETS diff --git a/engines/sci/gfx/gfx_widgets.h b/engines/sci/gfx/gfx_widgets.h index 5b43c2cad6..6c8e848664 100644 --- a/engines/sci/gfx/gfx_widgets.h +++ b/engines/sci/gfx/gfx_widgets.h @@ -51,7 +51,7 @@ struct GfxWidget; /* Enable the next line to keep a list of pointers to all widgets, with up to the specified amount ** of members (/SLOW/) */ -/* #define GFXW_DEBUG_WIDGETS 2048 */ +//#define GFXW_DEBUG_WIDGETS 2048 /* Our strategy for dirty rectangle management */ #define GFXW_DIRTY_STRATEGY GFXOP_DIRTY_FRAMES_CLUSTERS -- cgit v1.2.3 From da36901b0751b9d4faaae30dce230b67d75e04e6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 5 Jun 2009 23:08:35 +0000 Subject: Cleanup svn-id: r41202 --- engines/sci/engine/kgraphics.cpp | 4 ++-- engines/sci/gfx/gfx_driver.cpp | 13 +++++-------- engines/sci/sfx/core.cpp | 6 +++--- 3 files changed, 10 insertions(+), 13 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index fc23e4f6ef..1e0e675603 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -304,7 +304,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argc) { case 1 : if (s->_version < SCI_VERSION_1_1) { - if (SKPV(0) == 0 || SKPV(0) == 1 || SKPV(0) == -1) { + if (SKPV(0) <= 1) { // Newer (SCI1.1) semantics: show/hide cursor g_system->showMouse(SKPV(0) != 0); } else { @@ -329,7 +329,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { // this would open the menu on top. LSL5 is an exception, as the game can open // the menu when the player presses a button during the intro, but the cursor is // not placed on (x, 0) or (x, 1) - if (SKPV(1) == 0 || SKPV(1) == 1 || SKPV(1) == -1) { + if (SKPV(1) <= 1) { GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, SKPV(1) == 0 ? GFXOP_NO_POINTER : SKPV(0))); } else { // newer (SCI1.1) semantics: set pointer position diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index c63bdf98f8..fcac77245e 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -36,7 +36,6 @@ namespace Sci { struct _scummvm_driver_state { gfx_pixmap_t *priority[2]; byte *visual[2]; - uint8 *pointer_data; int xsize, ysize; }; @@ -53,7 +52,6 @@ static int scummvm_init(gfx_driver_t *drv, int xfact, int yfact, int bytespp) { S->xsize = xfact * 320; S->ysize = yfact * 200; - S->pointer_data = NULL; //S->buckystate = 0; for (i = 0; i < 2; i++) { @@ -94,9 +92,6 @@ static void scummvm_exit(gfx_driver_t *drv) { S->visual[i] = NULL; } - delete[] S->pointer_data; - S->pointer_data = NULL; - delete S; } } @@ -284,8 +279,7 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common: if ((pointer == NULL) || (hotspot == NULL)) { g_system->showMouse(false); } else { - delete[] S->pointer_data; - S->pointer_data = create_cursor(drv, pointer, 1); + uint8 *cursorData = create_cursor(drv, pointer, 1); // FIXME: The palette size check is a workaround for cursors using non-palette colour GFX_CURSOR_TRANSPARENT // Note that some cursors don't have a palette in SQ5 @@ -297,8 +291,11 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common: if (!pointer->palette) color_key = 63; - g_system->setMouseCursor(S->pointer_data, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); + g_system->setMouseCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); g_system->showMouse(true); + + delete[] cursorData; + cursorData = 0; } return GFX_OK; diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp index f4e07d3b84..7e3395b7d3 100644 --- a/engines/sci/sfx/core.cpp +++ b/engines/sci/sfx/core.cpp @@ -807,14 +807,14 @@ void SfxState::sfx_add_song(SongIterator *it, int priority, song_handle_t handle setSongStatus( song, SOUND_STATUS_STOPPED); fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle); - if (song->status == SOUND_STATUS_PLAYING - || song->status == SOUND_STATUS_SUSPENDED) { + if (song->status == SOUND_STATUS_PLAYING || song->status == SOUND_STATUS_SUSPENDED) { delete it; error("Unexpected (error): Song %ld still playing/suspended (%d)", handle, song->status); return; - } else + } else { song_lib_remove(_songlib, handle); /* No duplicates */ + } } -- cgit v1.2.3