From 87e8f94fde8330e1d5e600cc7b3e5c24225d6158 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 May 2009 14:07:45 +0000 Subject: - Moved all the files out of /sci/scicore and into /sci - Moved /scicore/sciconsole.h into /engine, and renamed /engine/scriptconsole.cpp to /engine/sciconsole.cpp svn-id: r40608 --- engines/sci/engine/game.cpp | 2 +- engines/sci/engine/grammar.cpp | 4 +- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/kgraphics.cpp | 2 +- engines/sci/engine/kmenu.cpp | 2 +- engines/sci/engine/kmovement.cpp | 2 +- engines/sci/engine/kscripts.cpp | 2 +- engines/sci/engine/kstring.cpp | 2 +- engines/sci/engine/message.h | 2 +- engines/sci/engine/sciconsole.cpp | 956 +++++++++++++++++++++++++++++++++++ engines/sci/engine/sciconsole.h | 130 +++++ engines/sci/engine/script.cpp | 2 +- engines/sci/engine/scriptconsole.cpp | 956 ----------------------------------- engines/sci/engine/scriptdebug.cpp | 6 +- engines/sci/engine/state.h | 4 +- engines/sci/engine/vm.cpp | 2 +- 16 files changed, 1103 insertions(+), 973 deletions(-) create mode 100644 engines/sci/engine/sciconsole.cpp create mode 100644 engines/sci/engine/sciconsole.h delete mode 100644 engines/sci/engine/scriptconsole.cpp (limited to 'engines/sci/engine') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index b0df4aacde..5b25fea6e2 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -27,7 +27,7 @@ #include "common/file.h" #include "sci/sci.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/kernel_types.h" diff --git a/engines/sci/engine/grammar.cpp b/engines/sci/engine/grammar.cpp index d4483045cc..63cd8a9b4a 100644 --- a/engines/sci/engine/grammar.cpp +++ b/engines/sci/engine/grammar.cpp @@ -29,8 +29,8 @@ */ #include "sci/tools.h" -#include "sci/scicore/vocabulary.h" -#include "sci/scicore/sciconsole.h" +#include "sci/vocabulary.h" +#include "sci/engine/sciconsole.h" namespace Sci { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d22e04ea05..ad9b57c54f 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -31,7 +31,7 @@ #include "sci/engine/intmap.h" #include "sci/engine/gc.h" #include "sci/engine/kernel.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/gfx/operations.h" #include "sci/engine/kernel_types.h" diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index e32db3e1cb..e149acfc43 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -26,7 +26,7 @@ #include "common/system.h" #include "sci/sci.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/gfx/gfx_gui.h" diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 5f585b26de..771af2a661 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -24,7 +24,7 @@ */ #include "sci/sci.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/gfx/gfx_gui.h" diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 8b3c2d0db0..9b28c1fa6d 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -24,7 +24,7 @@ */ #include "sci/sci.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index f00731aab4..bb4c98761f 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -24,7 +24,7 @@ */ #include "sci/sci.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel_types.h" #include "sci/engine/kernel.h" diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index edb5424219..0be3ac706b 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -25,7 +25,7 @@ /* String and parser handling */ -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/message.h" #include "sci/engine/kernel.h" diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h index 82c5e4f721..b1cdb8ad99 100644 --- a/engines/sci/engine/message.h +++ b/engines/sci/engine/message.h @@ -26,7 +26,7 @@ #ifndef SCI_ENGINE_MESSAGE_H #define SCI_ENGINE_MESSAGE_H -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "common/stack.h" namespace Sci { diff --git a/engines/sci/engine/sciconsole.cpp b/engines/sci/engine/sciconsole.cpp new file mode 100644 index 0000000000..3cdb6a1768 --- /dev/null +++ b/engines/sci/engine/sciconsole.cpp @@ -0,0 +1,956 @@ +/* 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$ + * + */ + +/* Second half of the console implementation: VM dependent stuff */ +/* Remember, it doesn't have to be fast. */ + +#include "sci/engine/state.h" +#include "sci/engine/sciconsole.h" + +#include "sci/sci.h" // For _console only +#include "sci/console.h" // For _console only + +namespace Sci { + +#ifdef SCI_CONSOLE + +// console commands + +static int c_list(EngineState *s, const Common::Array &cmdParams); // lists various types of things +static int c_man(EngineState *s, const Common::Array &cmdParams); // 'manual page' +static int c_set(EngineState *s, const Common::Array &cmdParams); // sets an int variable +static int c_print(EngineState *s, const Common::Array &cmdParams); // prints a variable +static int c_size(EngineState *s, const Common::Array &cmdParams); // displays the size of a resource +static int c_dump(EngineState *s, const Common::Array &cmdParams); // gives a hex dump of a resource +//static int c_objinfo(EngineState *s, const Common::Array &cmdParams); // shows some info about one class +//static int c_objmethods(EngineState *s, const Common::Array &cmdParams); // Disassembles all methods of a class +static int c_hexgrep(EngineState *s, const Common::Array &cmdParams); // Searches a string in one resource or resource class +static int c_dissectscript(EngineState *s, const Common::Array &cmdParams); // Splits a script into objects and explains them + +struct cmd_mm_entry_t { + const char *name; + const char *description; +}; // All later structures must "extend" this + +// Simple info page +struct cmd_page_t : public cmd_mm_entry_t { +}; + +struct cmd_command_t : public cmd_mm_entry_t { + ConCommand command; + const char *param; +}; + +struct cmd_var_t : public cmd_mm_entry_t { + union { + int *intp; + char **charpp; + reg_t *reg; + } var; +}; + + +typedef void printfunc_t(cmd_mm_entry_t *data, int full); + +struct cmd_mm_struct_t { + const char *name; + void *data; // cmd_mm_entry_t + size_t size_per_entry; + printfunc_t *print; + int entries; // Number of used entries + int allocated; // Number of allocated entries +}; + +#define CMD_MM_ENTRIES 3 // command console memory and manual page manager +#define CMD_MM_DEFAULT_ALLOC 4 // Number of table entries to allocate per default + +#define CMD_MM_CMD 0 // Commands +#define CMD_MM_VAR 1 // Variables +#define CMD_MM_DOC 2 // Misc. documentation + +static const char *cmd_mm_names[CMD_MM_ENTRIES] = { + "Commands", + "Variables", + "Documentation" +}; +static size_t cmd_mm_sizes_per_entry[CMD_MM_ENTRIES] = { + sizeof(cmd_command_t), + sizeof(cmd_var_t), + sizeof(cmd_page_t) +}; + +static void _cmd_print_command(cmd_mm_entry_t *data, int full); +static void _cmd_print_var(cmd_mm_entry_t *data, int full); +static void _cmd_print_page(cmd_mm_entry_t *data, int full); + +static printfunc_t *cmd_mm_printers[CMD_MM_ENTRIES] = { + _cmd_print_command, + _cmd_print_var, + _cmd_print_page +}; + +static cmd_mm_struct_t cmd_mm[CMD_MM_ENTRIES]; + +static int _cmd_initialized = 0; +static int _lists_need_sorting = 0; + +void _cmd_exit() { + int t; + + for (t = 0; t < CMD_MM_ENTRIES; t++) + free(cmd_mm[t].data); +} + +static cmd_mm_entry_t *cmd_mm_find(const char *name, int type) { + int i; + + for (i = 0; i < cmd_mm[type].entries; i++) { + cmd_mm_entry_t *tmp = (cmd_mm_entry_t *)((byte *)cmd_mm[type].data + i * cmd_mm[type].size_per_entry); + if (!strcmp(tmp->name, name)) + return tmp; + } + + return NULL; +} + +static int _cmd_mm_comp(const void *a, const void *b) { + return strcmp(((cmd_mm_entry_t *) a)->name, ((cmd_mm_entry_t *) b)->name); +} + +void con_sort_all() { + int i; + + for (i = 0; i < CMD_MM_ENTRIES; i++) + if (cmd_mm[i].entries && _lists_need_sorting & (1 << i)) + qsort(cmd_mm[i].data, cmd_mm[i].entries, cmd_mm[i].size_per_entry, _cmd_mm_comp); + + _lists_need_sorting = 0; +} + +void con_init() { + if (!_cmd_initialized) { + int i; + + _cmd_initialized = 1; + for (i = 0; i < CMD_MM_ENTRIES; i++) { + cmd_mm[i].name = cmd_mm_names[i]; + cmd_mm[i].size_per_entry = cmd_mm_sizes_per_entry[i]; + cmd_mm[i].entries = 0; + cmd_mm[i].allocated = CMD_MM_DEFAULT_ALLOC; + cmd_mm[i].data = calloc(cmd_mm[i].allocated, cmd_mm[i].size_per_entry); + cmd_mm[i].print = cmd_mm_printers[i]; + } + + atexit(_cmd_exit); + + // Hook up some commands + con_hook_command(&c_list, "list", "s*", "Lists various things (try 'list')"); + con_hook_command(&c_man, "man", "s", "Gives a short description of something"); + con_hook_command(&c_print, "print", "s", "Prints an int variable"); + con_hook_command(&c_set, "set", "si", "Sets an int variable"); + con_hook_command(&c_size, "size", "si", "Displays the size of a resource"); + con_hook_command(&c_dump, "dump", "si", "HexDumps a resource"); + con_hook_command(&c_hexgrep, "hexgrep", "shh*", "Searches some resources for a\n" + " particular sequence of bytes, re-\n presented as hexadecimal numbers.\n\n" + "EXAMPLES:\n hexgrep script e8 03 c8 00\n hexgrep pic.042 fe"); + con_hook_command(&c_dissectscript, "dissectscript", "i", "Examines a script."); + + con_hook_page("addresses", "Passing address parameters\n\n" + " Address parameters may be passed in one of\n" + " three forms:\n" + " - ssss:oooo -- where 'ssss' denotes a\n" + " segment and 'oooo' an offset. Example:\n" + " \"a:c5\" would address something in seg-\n" + " ment 0xa at offset 0xc5.\n" + " - &scr:oooo -- where 'scr' is a script number\n" + " and oooo an offset within that script; will\n" + " fail if the script is not currently loaded\n" + " - $REG -- where 'REG' is one of 'PC', 'ACC',\n" + " 'PREV' or 'OBJ': References the address\n" + " indicated by the register of this name.\n" + " - $REG+n (or -n) -- Like $REG, but modifies\n" + " the offset part by a specific amount (which\n" + " is specified in hexadecimal).\n" + " - ?obj -- Looks up an object with the specified\n" + " name, uses its address. This will abort if\n" + " the object name is ambiguous; in that case,\n" + " a list of addresses and indices is provided.\n" + " ?obj.idx may be used to disambiguate 'obj'\n" + " by the index 'idx'.\n"); + } +} + +static inline int clone_is_used(CloneTable *t, int idx) { + return ENTRY_IS_VALID(t, idx); +} + +int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on success + int rel_offsetting = 0; + const char *offsetting = NULL; + // Non-NULL: Parse end of string for relative offsets + char *endptr; + + if (!s) { + sciprintf("Addresses can only be parsed if a global state is present"); + return 1; // Requires a valid state + } + + if (*str == '$') { // Register + rel_offsetting = 1; + + if (!scumm_strnicmp(str + 1, "PC", 2)) { + *dest = s->_executionStack[s->execution_stack_pos].addr.pc; + offsetting = str + 3; + } else if (!scumm_strnicmp(str + 1, "P", 1)) { + *dest = s->_executionStack[s->execution_stack_pos].addr.pc; + offsetting = str + 2; + } else if (!scumm_strnicmp(str + 1, "PREV", 4)) { + *dest = s->r_prev; + offsetting = str + 5; + } else if (!scumm_strnicmp(str + 1, "ACC", 3)) { + *dest = s->r_acc; + offsetting = str + 4; + } else if (!scumm_strnicmp(str + 1, "A", 1)) { + *dest = s->r_acc; + offsetting = str + 2; + } else if (!scumm_strnicmp(str + 1, "OBJ", 3)) { + *dest = s->_executionStack[s->execution_stack_pos].objp; + offsetting = str + 4; + } else if (!scumm_strnicmp(str + 1, "O", 1)) { + *dest = s->_executionStack[s->execution_stack_pos].objp; + offsetting = str + 2; + } else + return 1; // No matching register + + if (!*offsetting) + offsetting = NULL; + else if (*offsetting != '+' && *offsetting != '-') + return 1; + } else if (*str == '&') { + int script_nr; + // Look up by script ID + char *colon = (char *)strchr(str, ':'); + + if (!colon) + return 1; + *colon = 0; + offsetting = colon + 1; + + script_nr = strtol(str + 1, &endptr, 10); + + if (*endptr) + return 1; + + dest->segment = s->seg_manager->segGet(script_nr); + + if (!dest->segment) { + return 1; + } + } else if (*str == '?') { + int index = -1; + int times_found = 0; + char *tmp; + const char *str_objname; + char *str_suffix; + char suffchar = 0; + uint i; + // Parse obj by name + + tmp = (char *)strchr(str, '+'); + str_suffix = (char *)strchr(str, '-'); + if (tmp < str_suffix) + str_suffix = tmp; + if (str_suffix) { + suffchar = (*str_suffix); + *str_suffix = 0; + } + + tmp = (char *)strchr(str, '.'); + + if (tmp) { + *tmp = 0; + index = strtol(tmp + 1, &endptr, 16); + if (*endptr) + return -1; + } + + str_objname = str + 1; + + // Now all values are available; iterate over all objects. + for (i = 0; i < s->seg_manager->_heap.size(); i++) { + MemObject *mobj = s->seg_manager->_heap[i]; + int idx = 0; + int max_index = 0; + + if (mobj) { + if (mobj->getType() == MEM_OBJ_SCRIPT) + max_index = (*(Script *)mobj)._objects.size(); + else if (mobj->getType() == MEM_OBJ_CLONES) + max_index = (*(CloneTable *)mobj)._table.size(); + } + + while (idx < max_index) { + int valid = 1; + Object *obj = NULL; + reg_t objpos; + objpos.offset = 0; + objpos.segment = i; + + if (mobj->getType() == MEM_OBJ_SCRIPT) { + obj = &(*(Script *)mobj)._objects[idx]; + objpos.offset = obj->pos.offset; + } else if (mobj->getType() == MEM_OBJ_CLONES) { + obj = &((*(CloneTable *)mobj)._table[idx]); + objpos.offset = idx; + valid = clone_is_used((CloneTable *)mobj, idx); + } + + if (valid) { + char *objname = (char *)obj->base + + obj->_variables[SCRIPT_NAME_SELECTOR].offset; + if (!strcmp(objname, str_objname)) { + // Found a match! + if (index < 0 || + times_found == index) + *dest = objpos; + else if (times_found < 0 && index) { + if (index == 1) { + // First time we realized the ambiguity + sciprintf("Ambiguous:\n"); + sciprintf(" %3x: ["PREG"] %s\n", 0, PRINT_REG(*dest), str_objname); + } + sciprintf(" %3x: ["PREG"] %s\n", index, PRINT_REG(objpos), str_objname); + } + ++times_found; + } + } + ++idx; + } + + } + + if (!times_found) + return 1; + + if (times_found > 1 && index < 0) { + sciprintf("Ambiguous: Aborting.\n"); + return 1; // Ambiguous + } + + if (times_found <= index) + return 1; // Not found + + offsetting = str_suffix; + if (offsetting) + *str_suffix = suffchar; + rel_offsetting = 1; + } else { + char *colon = (char *)strchr(str, ':'); + + if (!colon) { + offsetting = str; + dest->segment = 0; + } else { + *colon = 0; + offsetting = colon + 1; + + dest->segment = strtol(str, &endptr, 16); + if (*endptr) + return 1; + } + } + if (offsetting) { + int val = strtol(offsetting, &endptr, 16); + + if (rel_offsetting) + dest->offset += val; + else + dest->offset = val; + + if (*endptr) + return 1; + } + + return 0; +} + +void con_parse(EngineState *s, const char *command) { + char *cmd = (command && command[0]) ? (char *)strdup(command) : (char *)strdup(" "); + char *_cmd = cmd; + int pos = 0; + + if (!_cmd_initialized) + con_init(); + + bool done = false; // are we done yet? + while (!done) { + cmd_command_t *command_todo; + bool quote = false; // quoting? + bool cdone = false; // Done with the current command? + bool onvar = true; // currently working on a variable? + cdone = 0; + pos = 0; + + Common::Array cmdParams; + + while (*cmd == ' ') + cmd++; + + while (!cdone) { + switch (cmd[pos]) { + case 0: + cdone = done = true; + case ';': + if (!quote) + cdone = true; + case ' ': + if (!quote) { + cmd[pos] = 0; + onvar = false; + } + break; + case '\\': // don't check next char for special meaning + memmove(cmd + pos, cmd + pos + 1, strlen(cmd + pos) - 1); + break; + case '"': + quote = !quote; + memmove(cmd + pos, cmd + pos + 1, strlen(cmd + pos)); + pos--; + break; + default: + if (!onvar) { + onvar = true; + cmd_param_t tmp; + tmp.str = cmd + pos; + cmdParams.push_back(tmp); + } + break; + } + pos++; + } + + if (quote) + sciprintf("unbalanced quotes\n"); + else if (strcmp(cmd, "") != 0) { + command_todo = (cmd_command_t *) cmd_mm_find(cmd, CMD_MM_CMD); + if (!command_todo) + sciprintf("%s: not found\n", cmd); + else { + uint minparams; + int need_state = 0; + + const char *paramt = command_todo->param; // parameter types + if (command_todo->param[0] == '!') { + need_state = 1; + paramt++; + } + + minparams = strlen(paramt); + + if ((paramt[0] != 0) && (paramt[strlen(paramt) - 1] == '*')) + minparams -= 2; + + if (cmdParams.size() < minparams) + sciprintf("%s: needs more than %d parameters\n", cmd, cmdParams.size()); + + else if ((cmdParams.size() > strlen(paramt)) && ((strlen(paramt) == 0) || paramt[strlen(paramt) - 1] != '*')) + sciprintf("%s: too many parameters", cmd); + else { + int do_execute = !need_state || s; // /me wants an implication arrow + char paramtype; + int paramtypepos = 0; + char *endptr; + + for (uint i = 0; i < cmdParams.size(); i++) { + paramtype = paramt[paramtypepos]; + + if ((paramt[paramtypepos + 1]) && (paramt[paramtypepos + 1] != '*')) + paramtypepos++; + // seek next param type unless end of string or '* ' + + switch (paramtype) { + // Now turn the parameters into variables of the appropriate types, + // unless they're strings, and store them into the cmdParams array + + case 'a': { + const char *oldname = cmdParams[i].str; + if (parse_reg_t(s, oldname, &(cmdParams[i].reg))) { + sciprintf("%s: '%s' is not an address or object\n", cmd, oldname); + do_execute = 0; + } + break; + } + + case 'i': { + const char *orgstr = cmdParams[i].str; + + cmdParams[i].val = strtol(orgstr, &endptr, 0); + if (*endptr != '\0') { + do_execute = 0; + sciprintf("%s: '%s' is not an int\n", cmd, orgstr); + } + } + break; + + case 'h': { + const char *orgstr = cmdParams[i].str; + + cmdParams[i].val = strtol(orgstr, &endptr, 16); + + if (*endptr != '\0') { + do_execute = 0; + sciprintf("%s: '%s' is not a hex number\n", cmd, orgstr); + } + + cmdParams[i].val &= 0xff; // Clip hex numbers to 0x00 ... 0xff + } + break; + + case 's': + break; + + default: + warning("Internal error: Heap corruption or prior assertion failed: " + "Unknown parameter type '%c' for function", paramtype); + + } + } + + if (do_execute) { + command_todo->command(s, cmdParams); + } else + fprintf(stderr, "Skipping command...\n"); + } + } + } + cmd += pos; + } + + free(_cmd); +} + +/* (unused) +static cmd_mm_entry_t *con_iterate_entry(int ID, int *counter) { + byte *retval; + con_init(); + + if (*counter >= cmd_mm[ID].entries) + return 0; + retval = cmd_mm[ID].data; + retval += (*counter) * cmd_mm[ID].size_per_entry; + + (*counter)++; + + return (cmd_mm_entry_t *)retval; +}*/ + +static cmd_mm_entry_t *con_alloc_page_entry(int ID) { + int entry; + + con_init(); + + if (cmd_mm[ID].entries >= cmd_mm[ID].allocated) { + int nextsize = cmd_mm[ID].allocated; + if (nextsize >= 64) + nextsize += 16; + else + nextsize <<= 1; + + cmd_mm[ID].data = realloc(cmd_mm[ID].data, nextsize * cmd_mm[ID].size_per_entry); + cmd_mm[ID].allocated = nextsize; + } + + _lists_need_sorting |= (1 << ID); + + entry = cmd_mm[ID].entries++; + return (cmd_mm_entry_t *)(((byte *)cmd_mm[ID].data) + entry * cmd_mm[ID].size_per_entry); +} + +int con_hook_page(const char *name, const char *body) { + cmd_page_t *page = (cmd_page_t *)con_alloc_page_entry(CMD_MM_DOC); + + page->name = name; + page->description = body; + + return 0; +} + +int con_hook_command(ConCommand command, const char *name, const char *param, const char *description) { + cmd_command_t *cmd = NULL; + unsigned int i; + + if (NULL == name) { + sciprintf("console.c: con_hook_command(): NULL passed for name\n"); + return -1; + } + + if (command == NULL) + return 1; + + if (param == NULL) + param = ""; + + if (description == NULL) + description = ""; + + i = 0; + while (param[i] != 0) { + switch (param[i]) { + case '*': + if (param[i + 1] != 0) + return 1; + if (i == 0) + return 1; + case 'h': + case '!': + case 'i': + case 'a': + case 's': + case 'r': + break; + default: + return 1; + } + i++; + } + cmd = (cmd_command_t *)con_alloc_page_entry(CMD_MM_CMD); + + cmd->command = command; + cmd->name = name; + cmd->param = param; + cmd->description = description; + + ((SciEngine *)g_engine)->_console->con_hook_command(command, name, param, description); + + return 0; +} + +int con_hook_int(int *pointer, const char *name, const char *description) { + cmd_var_t *var; + + if (pointer == NULL) + return 1; + + if (description == NULL) + description = ""; + + var = (cmd_var_t *) con_alloc_page_entry(CMD_MM_VAR); + + var->var.intp = pointer; + var->name = name; + var->description = description; + + return 0; +} + +// Console commands and support functions + +static ResourceType parseResourceType(const char *resid) { + // Gets the resource number of a resource string, or returns -1 + ResourceType res = kResourceTypeInvalid; + + for (int i = 0; i < kResourceTypeInvalid; i++) + if (strcmp(getResourceTypeName((ResourceType)i), resid) == 0) + res = (ResourceType)i; + + return res; +} + +static void _cmd_print_command(cmd_mm_entry_t *data, int full) { + const char *paramseeker = ((cmd_command_t *)data)->param; + + if (full) { + sciprintf("SYNOPSIS\n\n %s (%s) ", data->name, paramseeker); + + while (*paramseeker) { + switch (*paramseeker) { + case '!': + break; + case 'i': + sciprintf(" (int)"); + break; + case 'a': + sciprintf(" (addr)"); + break; + case 's': + sciprintf(" (string)"); + break; + case 'h': + sciprintf(" (hexbyte)"); + break; + case '*': + sciprintf("*"); + break; + default: + sciprintf(" (Unknown(%c))", *paramseeker); + } + paramseeker++; + } + + sciprintf("\n\nDESCRIPTION\n\n %s", data->description); + } else + sciprintf(" %s", data->name); +} + +static void _cmd_print_var(cmd_mm_entry_t *data, int full) { + cmd_var_t *var = (cmd_var_t *) data; + if (full) + sciprintf("VALUE\n\n"); + sciprintf(" %s = %d\n", var->name, *(var->var.intp)); + + if (full) + sciprintf("\n\nDESCRIPTION\n\n %s", data->description); +} + +static void _cmd_print_page(cmd_mm_entry_t *data, int full) { + if (full) + sciprintf("\n\nDESCRIPTION\n\n %s\n", data->description); + else + sciprintf("%s\n", data->name); +} + +static int c_list(EngineState *s, const Common::Array &cmdParams) { + if (_lists_need_sorting) + con_sort_all(); + + if (cmdParams.size() == 0) { + sciprintf("usage: list [type]\nwhere type is one of the following:\n" + "cmds - lists all commands\n" + "vars - lists all variables\n" + "docs - lists all misc. documentation\n" + "\n" + "restypes - lists all resource types\n" + "[resource] - lists all [resource]s"); + } else if (cmdParams.size() == 1) { + const char *mm_subsects[3] = {"cmds", "vars", "docs"}; + int mm_found = -1; + int i; + + for (i = 0; i < 3; i++) + if (mm_subsects[i] && !strcmp(mm_subsects[i], cmdParams[0].str)) + mm_found = i; + + if (mm_found >= 0) + for (i = 0; i < cmd_mm[mm_found].entries; i++) + cmd_mm[mm_found].print((cmd_mm_entry_t *)(((byte *)cmd_mm[mm_found].data) + i * cmd_mm[mm_found].size_per_entry), 0); + else { + if (!s) { + sciprintf("You need a state to do that!\n"); + return 1; + } + + else if (strcmp("restypes", cmdParams[0].str) == 0) { + for (i = 0; i < kResourceTypeInvalid; i++) + sciprintf("%s\n", getResourceTypeName((ResourceType)i)); + } else { + ResourceType res = parseResourceType(cmdParams[0].str); + if (res == kResourceTypeInvalid) + sciprintf("Unknown resource type: '%s'\n", cmdParams[0].str); + else { + for (i = 0; i < sci_max_resource_nr[s->resmgr->_sciVersion]; i++) + if (s->resmgr->testResource(res, i)) + sciprintf("%s.%03d\n", getResourceTypeName((ResourceType)res), i); + } + } + } + } else + sciprintf("list can only be used with one argument"); + return 0; +} + +static int c_man(EngineState *s, const Common::Array &cmdParams) { + int section = 0; + uint i; + Common::String name = cmdParams[0].str; + const char *c = strchr(name.c_str(), '.'); + cmd_mm_entry_t *entry = 0; + + if (c) { + section = atoi(c + 1); + name = Common::String(name.begin(), c); + } + + if (section < 0 || section >= CMD_MM_ENTRIES) { + sciprintf("Invalid section %d\n", section); + return 1; + } + + sciprintf("section:%d\n", section); + if (section) + entry = cmd_mm_find(name.c_str(), section - 1); + else + for (i = 0; i < CMD_MM_ENTRIES && !section; i++) { + if ((entry = cmd_mm_find(name.c_str(), i))) + section = i + 1; + } + + if (!entry) { + sciprintf("No manual entry\n"); + return 1; + } + + sciprintf("-- %s: %s.%d\n", cmd_mm[section - 1].name, name.c_str(), section); + cmd_mm[section - 1].print(entry, 1); + + return 0; +} + +static int c_set(EngineState *s, const Common::Array &cmdParams) { + cmd_var_t *var = (cmd_var_t *)cmd_mm_find(cmdParams[0].str, CMD_MM_VAR); + + if (var) + *(var->var.intp) = cmdParams[1].val; + + return 0; +} + +static int c_print(EngineState *s, const Common::Array &cmdParams) { + cmd_var_t *var = (cmd_var_t *)cmd_mm_find(cmdParams[0].str, CMD_MM_VAR); + + if (var) + sciprintf("%d", *(var->var.intp)); + else + sciprintf("Not defined."); + + return 0; +} + +static int c_size(EngineState *s, const Common::Array &cmdParams) { + ResourceType res = parseResourceType(cmdParams[0].str); + if (res == kResourceTypeInvalid) + sciprintf("Resource type '%s' is not valid\n", cmdParams[0].str); + else { + Resource *resource = s->resmgr->findResource(res, cmdParams[1].val, 0); + if (resource) { + sciprintf("Size: %d\n", resource->size); + } else + sciprintf("Resource %s.%03d not found\n", cmdParams[0].str, cmdParams[1].val); + } + + return 0; +} + +static int c_dump(EngineState *s, const Common::Array &cmdParams) { + ResourceType res = parseResourceType(cmdParams[0].str); + + if (res == kResourceTypeInvalid) + sciprintf("Resource type '%s' is not valid\n", cmdParams[0].str); + else { + Resource *resource = s->resmgr->findResource(res, cmdParams[1].val, 0); + if (resource) + Common::hexdump(resource->data, resource->size, 16, 0); + else + sciprintf("Resource %s.%03d not found\n", cmdParams[0].str, cmdParams[1].val); + } + + return 0; +} + +static int c_hexgrep(EngineState *s, const Common::Array &cmdParams) { + int i, seeklen, resnr, resmax; + unsigned char *seekstr = NULL; + Resource *script = NULL; + char *dot = (char *)strchr(cmdParams[0].str, '.'); + ResourceType restype; + + if (NULL == s) { + fprintf(stderr, "console.c: c_hexgrep(): NULL passed for s\r\n"); + return(-1); + } + + seeklen = cmdParams.size() - 1; + seekstr = (unsigned char *)malloc(seeklen); + + if (NULL == seekstr) { + fprintf(stderr, "console.c: c_hexgrep(): malloc failed for seekstr\r\n"); + return(-1); + } + + for (i = 0; i < seeklen; i++) + seekstr[i] = (byte)cmdParams[i + 1].val; + + if (dot) { + *dot = 0; + resmax = resnr = atoi(dot + 1); + } else { + resnr = 0; + resmax = 999; + } + + restype = parseResourceType(cmdParams[0].str); + if (restype == kResourceTypeInvalid) { + sciprintf("Unknown resource type \"%s\"\n", cmdParams[0].str); + free(seekstr); + return 1; + } + + for (; resnr <= resmax; resnr++) + if ((script = s->resmgr->findResource(restype, resnr, 0))) { + unsigned int seeker = 0, seekerold = 0; + int comppos = 0; + int output_script_name = 0; + + while (seeker < script->size) { + if (script->data[seeker] == seekstr[comppos]) { + if (comppos == 0) + seekerold = seeker; + + comppos++; + + if (comppos == seeklen) { + comppos = 0; + seeker = seekerold + 1; + + if (!output_script_name) { + sciprintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resnr); + output_script_name = 1; + } + sciprintf(" 0x%04x\n", seekerold); + } + } else + comppos = 0; + + seeker++; + } + } + + free(seekstr); + + return 0; +} + +static int c_dissectscript(EngineState *s, const Common::Array &cmdParams) { + if (NULL == s) { + sciprintf("console.c: c_dissectscript(): NULL passed for parameter s\n"); + return -1; + } + + script_dissect(s->resmgr, cmdParams[0].val, s->_selectorNames); + return 0; +} + +#endif // SCI_CONSOLE + +} // End of namespace Sci diff --git a/engines/sci/engine/sciconsole.h b/engines/sci/engine/sciconsole.h new file mode 100644 index 0000000000..b2060143aa --- /dev/null +++ b/engines/sci/engine/sciconsole.h @@ -0,0 +1,130 @@ +/* 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$ + * + */ + +/* Header file for the SCI console. +** Please note that the console does not use the priority field; the console +** should therefore be drawn after everything else has been drawn (with the +** possible exception of the mouse pointer). +*/ + +#ifndef SCI_SCICORE_SCICONSOLE_H +#define SCI_SCICORE_SCICONSOLE_H + +#include "common/scummsys.h" + +#include "sci/tools.h" +#include "sci/engine/state.h" +#include "sci/engine/vm_types.h" + +#define SCI_CONSOLE + +namespace Sci { + +struct gfx_pixmap_t; + +union cmd_param_t { + int32 val; + const char *str; + reg_t reg; +}; + + +typedef int (*ConCommand)(EngineState *s, const Common::Array &cmdParams); + +/*** FUNCTION DEFINITIONS ***/ + +void con_init(); +/* Initializes the command parser +** Parameters: (void) +** Returns : (void) +** This function will initialize hook up a few commands to the parser. +** It must be called before cmdParse() is used. +*/ + + +void con_parse(EngineState *s, const char *command); +/* Parses a command and summons appropriate facilities to handle it +** Parameters: (EngineState *) s: The EngineState to use +** command: The command to execute +** Returns : (void) +*/ + + +int con_hook_command(ConCommand command, const char *name, const char *param, const char *description); +/* Adds a command to the parser's command list +** Parameters: command: The command to add +** name: The command's name +** param: A description of the parameters it takes +** description: A short description of what it does +** Returns : 0 if successful, 1 if appending failed because +** of an incorrect *param string, 'command'==0, or +** 'name' already being in use. +** A valid param string is either empty (no parameters allowed) +** or contains one of the following tokens: +** ! Special token: EngineState* must be set for this function to be called +** i (an int) +** s (a 'string' (char *)) +** h (a byte, described in hexadecimal digits) +** a (a heap address, register or object name) +** r (any register value) +** x* (an arbitrary (possibly 0) number of 'x' tokens) +** The '*' token may only be used as the last token of the list. +** Another way to specify optional parameters is by means of the +** '-opt:t' notation, which allows an optional parameter of type 't' +** to be specified as 'opt:' when calling. See also the +** con_hasopt() and con_getopt() calls. +** +** Please note that the 'h' type does accept hexadecimal numbers greater +** than 0xff and less than 0x00, but clips them to this range. +** +** Example: "isi*" would define the function to take an int, a +** string, and an arbitrary number of ints as parameters (in that sequence). +** +** When the function is called, it can retrieve its parameters from cmd_params; +** the actual number of parameters is stored in cmd_paramlength. +** It is allowed to modify the char*s from a cmd_params[] element, as long +** as no element beyond strlen(cmd_params[x].str)+1 is accessed. +*/ + +int con_hook_page(const char *topic, const char *body); +/* Hooks a general information page to the manual page system +** Parameters: (const char *) topic: The topic name +** (const char *) body: The text body to assign to the topic +** Returns : (int) 0 on success +*/ + +int con_hook_int(int *pointer, const char *name, const char *description); +/* Adds an int to the list of modifyable ints. +** Parameters: pointer: Pointer to the int to add to the list +** name: Name for this value +** description: A short description for the value +** Returns : 0 on success, 1 if either value has already been added +** or if name is already being used for a different value. +** The internal list of int references is used by some of the basic commands. +*/ + +} // End of namespace Sci + +#endif // SCI_SCICORE_SCICONSOLE_H diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 828ea1f14d..7de9a7539e 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -24,7 +24,7 @@ */ #include "sci/sci.h" -#include "sci/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "common/util.h" diff --git a/engines/sci/engine/scriptconsole.cpp b/engines/sci/engine/scriptconsole.cpp deleted file mode 100644 index 569c14a519..0000000000 --- a/engines/sci/engine/scriptconsole.cpp +++ /dev/null @@ -1,956 +0,0 @@ -/* 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$ - * - */ - -/* Second half of the console implementation: VM dependent stuff */ -/* Remember, it doesn't have to be fast. */ - -#include "sci/engine/state.h" -#include "sci/scicore/sciconsole.h" - -#include "sci/sci.h" // For _console only -#include "sci/console.h" // For _console only - -namespace Sci { - -#ifdef SCI_CONSOLE - -// console commands - -static int c_list(EngineState *s, const Common::Array &cmdParams); // lists various types of things -static int c_man(EngineState *s, const Common::Array &cmdParams); // 'manual page' -static int c_set(EngineState *s, const Common::Array &cmdParams); // sets an int variable -static int c_print(EngineState *s, const Common::Array &cmdParams); // prints a variable -static int c_size(EngineState *s, const Common::Array &cmdParams); // displays the size of a resource -static int c_dump(EngineState *s, const Common::Array &cmdParams); // gives a hex dump of a resource -//static int c_objinfo(EngineState *s, const Common::Array &cmdParams); // shows some info about one class -//static int c_objmethods(EngineState *s, const Common::Array &cmdParams); // Disassembles all methods of a class -static int c_hexgrep(EngineState *s, const Common::Array &cmdParams); // Searches a string in one resource or resource class -static int c_dissectscript(EngineState *s, const Common::Array &cmdParams); // Splits a script into objects and explains them - -struct cmd_mm_entry_t { - const char *name; - const char *description; -}; // All later structures must "extend" this - -// Simple info page -struct cmd_page_t : public cmd_mm_entry_t { -}; - -struct cmd_command_t : public cmd_mm_entry_t { - ConCommand command; - const char *param; -}; - -struct cmd_var_t : public cmd_mm_entry_t { - union { - int *intp; - char **charpp; - reg_t *reg; - } var; -}; - - -typedef void printfunc_t(cmd_mm_entry_t *data, int full); - -struct cmd_mm_struct_t { - const char *name; - void *data; // cmd_mm_entry_t - size_t size_per_entry; - printfunc_t *print; - int entries; // Number of used entries - int allocated; // Number of allocated entries -}; - -#define CMD_MM_ENTRIES 3 // command console memory and manual page manager -#define CMD_MM_DEFAULT_ALLOC 4 // Number of table entries to allocate per default - -#define CMD_MM_CMD 0 // Commands -#define CMD_MM_VAR 1 // Variables -#define CMD_MM_DOC 2 // Misc. documentation - -static const char *cmd_mm_names[CMD_MM_ENTRIES] = { - "Commands", - "Variables", - "Documentation" -}; -static size_t cmd_mm_sizes_per_entry[CMD_MM_ENTRIES] = { - sizeof(cmd_command_t), - sizeof(cmd_var_t), - sizeof(cmd_page_t) -}; - -static void _cmd_print_command(cmd_mm_entry_t *data, int full); -static void _cmd_print_var(cmd_mm_entry_t *data, int full); -static void _cmd_print_page(cmd_mm_entry_t *data, int full); - -static printfunc_t *cmd_mm_printers[CMD_MM_ENTRIES] = { - _cmd_print_command, - _cmd_print_var, - _cmd_print_page -}; - -static cmd_mm_struct_t cmd_mm[CMD_MM_ENTRIES]; - -static int _cmd_initialized = 0; -static int _lists_need_sorting = 0; - -void _cmd_exit() { - int t; - - for (t = 0; t < CMD_MM_ENTRIES; t++) - free(cmd_mm[t].data); -} - -static cmd_mm_entry_t *cmd_mm_find(const char *name, int type) { - int i; - - for (i = 0; i < cmd_mm[type].entries; i++) { - cmd_mm_entry_t *tmp = (cmd_mm_entry_t *)((byte *)cmd_mm[type].data + i * cmd_mm[type].size_per_entry); - if (!strcmp(tmp->name, name)) - return tmp; - } - - return NULL; -} - -static int _cmd_mm_comp(const void *a, const void *b) { - return strcmp(((cmd_mm_entry_t *) a)->name, ((cmd_mm_entry_t *) b)->name); -} - -void con_sort_all() { - int i; - - for (i = 0; i < CMD_MM_ENTRIES; i++) - if (cmd_mm[i].entries && _lists_need_sorting & (1 << i)) - qsort(cmd_mm[i].data, cmd_mm[i].entries, cmd_mm[i].size_per_entry, _cmd_mm_comp); - - _lists_need_sorting = 0; -} - -void con_init() { - if (!_cmd_initialized) { - int i; - - _cmd_initialized = 1; - for (i = 0; i < CMD_MM_ENTRIES; i++) { - cmd_mm[i].name = cmd_mm_names[i]; - cmd_mm[i].size_per_entry = cmd_mm_sizes_per_entry[i]; - cmd_mm[i].entries = 0; - cmd_mm[i].allocated = CMD_MM_DEFAULT_ALLOC; - cmd_mm[i].data = calloc(cmd_mm[i].allocated, cmd_mm[i].size_per_entry); - cmd_mm[i].print = cmd_mm_printers[i]; - } - - atexit(_cmd_exit); - - // Hook up some commands - con_hook_command(&c_list, "list", "s*", "Lists various things (try 'list')"); - con_hook_command(&c_man, "man", "s", "Gives a short description of something"); - con_hook_command(&c_print, "print", "s", "Prints an int variable"); - con_hook_command(&c_set, "set", "si", "Sets an int variable"); - con_hook_command(&c_size, "size", "si", "Displays the size of a resource"); - con_hook_command(&c_dump, "dump", "si", "HexDumps a resource"); - con_hook_command(&c_hexgrep, "hexgrep", "shh*", "Searches some resources for a\n" - " particular sequence of bytes, re-\n presented as hexadecimal numbers.\n\n" - "EXAMPLES:\n hexgrep script e8 03 c8 00\n hexgrep pic.042 fe"); - con_hook_command(&c_dissectscript, "dissectscript", "i", "Examines a script."); - - con_hook_page("addresses", "Passing address parameters\n\n" - " Address parameters may be passed in one of\n" - " three forms:\n" - " - ssss:oooo -- where 'ssss' denotes a\n" - " segment and 'oooo' an offset. Example:\n" - " \"a:c5\" would address something in seg-\n" - " ment 0xa at offset 0xc5.\n" - " - &scr:oooo -- where 'scr' is a script number\n" - " and oooo an offset within that script; will\n" - " fail if the script is not currently loaded\n" - " - $REG -- where 'REG' is one of 'PC', 'ACC',\n" - " 'PREV' or 'OBJ': References the address\n" - " indicated by the register of this name.\n" - " - $REG+n (or -n) -- Like $REG, but modifies\n" - " the offset part by a specific amount (which\n" - " is specified in hexadecimal).\n" - " - ?obj -- Looks up an object with the specified\n" - " name, uses its address. This will abort if\n" - " the object name is ambiguous; in that case,\n" - " a list of addresses and indices is provided.\n" - " ?obj.idx may be used to disambiguate 'obj'\n" - " by the index 'idx'.\n"); - } -} - -static inline int clone_is_used(CloneTable *t, int idx) { - return ENTRY_IS_VALID(t, idx); -} - -int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on success - int rel_offsetting = 0; - const char *offsetting = NULL; - // Non-NULL: Parse end of string for relative offsets - char *endptr; - - if (!s) { - sciprintf("Addresses can only be parsed if a global state is present"); - return 1; // Requires a valid state - } - - if (*str == '$') { // Register - rel_offsetting = 1; - - if (!scumm_strnicmp(str + 1, "PC", 2)) { - *dest = s->_executionStack[s->execution_stack_pos].addr.pc; - offsetting = str + 3; - } else if (!scumm_strnicmp(str + 1, "P", 1)) { - *dest = s->_executionStack[s->execution_stack_pos].addr.pc; - offsetting = str + 2; - } else if (!scumm_strnicmp(str + 1, "PREV", 4)) { - *dest = s->r_prev; - offsetting = str + 5; - } else if (!scumm_strnicmp(str + 1, "ACC", 3)) { - *dest = s->r_acc; - offsetting = str + 4; - } else if (!scumm_strnicmp(str + 1, "A", 1)) { - *dest = s->r_acc; - offsetting = str + 2; - } else if (!scumm_strnicmp(str + 1, "OBJ", 3)) { - *dest = s->_executionStack[s->execution_stack_pos].objp; - offsetting = str + 4; - } else if (!scumm_strnicmp(str + 1, "O", 1)) { - *dest = s->_executionStack[s->execution_stack_pos].objp; - offsetting = str + 2; - } else - return 1; // No matching register - - if (!*offsetting) - offsetting = NULL; - else if (*offsetting != '+' && *offsetting != '-') - return 1; - } else if (*str == '&') { - int script_nr; - // Look up by script ID - char *colon = (char *)strchr(str, ':'); - - if (!colon) - return 1; - *colon = 0; - offsetting = colon + 1; - - script_nr = strtol(str + 1, &endptr, 10); - - if (*endptr) - return 1; - - dest->segment = s->seg_manager->segGet(script_nr); - - if (!dest->segment) { - return 1; - } - } else if (*str == '?') { - int index = -1; - int times_found = 0; - char *tmp; - const char *str_objname; - char *str_suffix; - char suffchar = 0; - uint i; - // Parse obj by name - - tmp = (char *)strchr(str, '+'); - str_suffix = (char *)strchr(str, '-'); - if (tmp < str_suffix) - str_suffix = tmp; - if (str_suffix) { - suffchar = (*str_suffix); - *str_suffix = 0; - } - - tmp = (char *)strchr(str, '.'); - - if (tmp) { - *tmp = 0; - index = strtol(tmp + 1, &endptr, 16); - if (*endptr) - return -1; - } - - str_objname = str + 1; - - // Now all values are available; iterate over all objects. - for (i = 0; i < s->seg_manager->_heap.size(); i++) { - MemObject *mobj = s->seg_manager->_heap[i]; - int idx = 0; - int max_index = 0; - - if (mobj) { - if (mobj->getType() == MEM_OBJ_SCRIPT) - max_index = (*(Script *)mobj)._objects.size(); - else if (mobj->getType() == MEM_OBJ_CLONES) - max_index = (*(CloneTable *)mobj)._table.size(); - } - - while (idx < max_index) { - int valid = 1; - Object *obj = NULL; - reg_t objpos; - objpos.offset = 0; - objpos.segment = i; - - if (mobj->getType() == MEM_OBJ_SCRIPT) { - obj = &(*(Script *)mobj)._objects[idx]; - objpos.offset = obj->pos.offset; - } else if (mobj->getType() == MEM_OBJ_CLONES) { - obj = &((*(CloneTable *)mobj)._table[idx]); - objpos.offset = idx; - valid = clone_is_used((CloneTable *)mobj, idx); - } - - if (valid) { - char *objname = (char *)obj->base - + obj->_variables[SCRIPT_NAME_SELECTOR].offset; - if (!strcmp(objname, str_objname)) { - // Found a match! - if (index < 0 || - times_found == index) - *dest = objpos; - else if (times_found < 0 && index) { - if (index == 1) { - // First time we realized the ambiguity - sciprintf("Ambiguous:\n"); - sciprintf(" %3x: ["PREG"] %s\n", 0, PRINT_REG(*dest), str_objname); - } - sciprintf(" %3x: ["PREG"] %s\n", index, PRINT_REG(objpos), str_objname); - } - ++times_found; - } - } - ++idx; - } - - } - - if (!times_found) - return 1; - - if (times_found > 1 && index < 0) { - sciprintf("Ambiguous: Aborting.\n"); - return 1; // Ambiguous - } - - if (times_found <= index) - return 1; // Not found - - offsetting = str_suffix; - if (offsetting) - *str_suffix = suffchar; - rel_offsetting = 1; - } else { - char *colon = (char *)strchr(str, ':'); - - if (!colon) { - offsetting = str; - dest->segment = 0; - } else { - *colon = 0; - offsetting = colon + 1; - - dest->segment = strtol(str, &endptr, 16); - if (*endptr) - return 1; - } - } - if (offsetting) { - int val = strtol(offsetting, &endptr, 16); - - if (rel_offsetting) - dest->offset += val; - else - dest->offset = val; - - if (*endptr) - return 1; - } - - return 0; -} - -void con_parse(EngineState *s, const char *command) { - char *cmd = (command && command[0]) ? (char *)strdup(command) : (char *)strdup(" "); - char *_cmd = cmd; - int pos = 0; - - if (!_cmd_initialized) - con_init(); - - bool done = false; // are we done yet? - while (!done) { - cmd_command_t *command_todo; - bool quote = false; // quoting? - bool cdone = false; // Done with the current command? - bool onvar = true; // currently working on a variable? - cdone = 0; - pos = 0; - - Common::Array cmdParams; - - while (*cmd == ' ') - cmd++; - - while (!cdone) { - switch (cmd[pos]) { - case 0: - cdone = done = true; - case ';': - if (!quote) - cdone = true; - case ' ': - if (!quote) { - cmd[pos] = 0; - onvar = false; - } - break; - case '\\': // don't check next char for special meaning - memmove(cmd + pos, cmd + pos + 1, strlen(cmd + pos) - 1); - break; - case '"': - quote = !quote; - memmove(cmd + pos, cmd + pos + 1, strlen(cmd + pos)); - pos--; - break; - default: - if (!onvar) { - onvar = true; - cmd_param_t tmp; - tmp.str = cmd + pos; - cmdParams.push_back(tmp); - } - break; - } - pos++; - } - - if (quote) - sciprintf("unbalanced quotes\n"); - else if (strcmp(cmd, "") != 0) { - command_todo = (cmd_command_t *) cmd_mm_find(cmd, CMD_MM_CMD); - if (!command_todo) - sciprintf("%s: not found\n", cmd); - else { - uint minparams; - int need_state = 0; - - const char *paramt = command_todo->param; // parameter types - if (command_todo->param[0] == '!') { - need_state = 1; - paramt++; - } - - minparams = strlen(paramt); - - if ((paramt[0] != 0) && (paramt[strlen(paramt) - 1] == '*')) - minparams -= 2; - - if (cmdParams.size() < minparams) - sciprintf("%s: needs more than %d parameters\n", cmd, cmdParams.size()); - - else if ((cmdParams.size() > strlen(paramt)) && ((strlen(paramt) == 0) || paramt[strlen(paramt) - 1] != '*')) - sciprintf("%s: too many parameters", cmd); - else { - int do_execute = !need_state || s; // /me wants an implication arrow - char paramtype; - int paramtypepos = 0; - char *endptr; - - for (uint i = 0; i < cmdParams.size(); i++) { - paramtype = paramt[paramtypepos]; - - if ((paramt[paramtypepos + 1]) && (paramt[paramtypepos + 1] != '*')) - paramtypepos++; - // seek next param type unless end of string or '* ' - - switch (paramtype) { - // Now turn the parameters into variables of the appropriate types, - // unless they're strings, and store them into the cmdParams array - - case 'a': { - const char *oldname = cmdParams[i].str; - if (parse_reg_t(s, oldname, &(cmdParams[i].reg))) { - sciprintf("%s: '%s' is not an address or object\n", cmd, oldname); - do_execute = 0; - } - break; - } - - case 'i': { - const char *orgstr = cmdParams[i].str; - - cmdParams[i].val = strtol(orgstr, &endptr, 0); - if (*endptr != '\0') { - do_execute = 0; - sciprintf("%s: '%s' is not an int\n", cmd, orgstr); - } - } - break; - - case 'h': { - const char *orgstr = cmdParams[i].str; - - cmdParams[i].val = strtol(orgstr, &endptr, 16); - - if (*endptr != '\0') { - do_execute = 0; - sciprintf("%s: '%s' is not a hex number\n", cmd, orgstr); - } - - cmdParams[i].val &= 0xff; // Clip hex numbers to 0x00 ... 0xff - } - break; - - case 's': - break; - - default: - warning("Internal error: Heap corruption or prior assertion failed: " - "Unknown parameter type '%c' for function", paramtype); - - } - } - - if (do_execute) { - command_todo->command(s, cmdParams); - } else - fprintf(stderr, "Skipping command...\n"); - } - } - } - cmd += pos; - } - - free(_cmd); -} - -/* (unused) -static cmd_mm_entry_t *con_iterate_entry(int ID, int *counter) { - byte *retval; - con_init(); - - if (*counter >= cmd_mm[ID].entries) - return 0; - retval = cmd_mm[ID].data; - retval += (*counter) * cmd_mm[ID].size_per_entry; - - (*counter)++; - - return (cmd_mm_entry_t *)retval; -}*/ - -static cmd_mm_entry_t *con_alloc_page_entry(int ID) { - int entry; - - con_init(); - - if (cmd_mm[ID].entries >= cmd_mm[ID].allocated) { - int nextsize = cmd_mm[ID].allocated; - if (nextsize >= 64) - nextsize += 16; - else - nextsize <<= 1; - - cmd_mm[ID].data = realloc(cmd_mm[ID].data, nextsize * cmd_mm[ID].size_per_entry); - cmd_mm[ID].allocated = nextsize; - } - - _lists_need_sorting |= (1 << ID); - - entry = cmd_mm[ID].entries++; - return (cmd_mm_entry_t *)(((byte *)cmd_mm[ID].data) + entry * cmd_mm[ID].size_per_entry); -} - -int con_hook_page(const char *name, const char *body) { - cmd_page_t *page = (cmd_page_t *)con_alloc_page_entry(CMD_MM_DOC); - - page->name = name; - page->description = body; - - return 0; -} - -int con_hook_command(ConCommand command, const char *name, const char *param, const char *description) { - cmd_command_t *cmd = NULL; - unsigned int i; - - if (NULL == name) { - sciprintf("console.c: con_hook_command(): NULL passed for name\n"); - return -1; - } - - if (command == NULL) - return 1; - - if (param == NULL) - param = ""; - - if (description == NULL) - description = ""; - - i = 0; - while (param[i] != 0) { - switch (param[i]) { - case '*': - if (param[i + 1] != 0) - return 1; - if (i == 0) - return 1; - case 'h': - case '!': - case 'i': - case 'a': - case 's': - case 'r': - break; - default: - return 1; - } - i++; - } - cmd = (cmd_command_t *)con_alloc_page_entry(CMD_MM_CMD); - - cmd->command = command; - cmd->name = name; - cmd->param = param; - cmd->description = description; - - ((SciEngine *)g_engine)->_console->con_hook_command(command, name, param, description); - - return 0; -} - -int con_hook_int(int *pointer, const char *name, const char *description) { - cmd_var_t *var; - - if (pointer == NULL) - return 1; - - if (description == NULL) - description = ""; - - var = (cmd_var_t *) con_alloc_page_entry(CMD_MM_VAR); - - var->var.intp = pointer; - var->name = name; - var->description = description; - - return 0; -} - -// Console commands and support functions - -static ResourceType parseResourceType(const char *resid) { - // Gets the resource number of a resource string, or returns -1 - ResourceType res = kResourceTypeInvalid; - - for (int i = 0; i < kResourceTypeInvalid; i++) - if (strcmp(getResourceTypeName((ResourceType)i), resid) == 0) - res = (ResourceType)i; - - return res; -} - -static void _cmd_print_command(cmd_mm_entry_t *data, int full) { - const char *paramseeker = ((cmd_command_t *)data)->param; - - if (full) { - sciprintf("SYNOPSIS\n\n %s (%s) ", data->name, paramseeker); - - while (*paramseeker) { - switch (*paramseeker) { - case '!': - break; - case 'i': - sciprintf(" (int)"); - break; - case 'a': - sciprintf(" (addr)"); - break; - case 's': - sciprintf(" (string)"); - break; - case 'h': - sciprintf(" (hexbyte)"); - break; - case '*': - sciprintf("*"); - break; - default: - sciprintf(" (Unknown(%c))", *paramseeker); - } - paramseeker++; - } - - sciprintf("\n\nDESCRIPTION\n\n %s", data->description); - } else - sciprintf(" %s", data->name); -} - -static void _cmd_print_var(cmd_mm_entry_t *data, int full) { - cmd_var_t *var = (cmd_var_t *) data; - if (full) - sciprintf("VALUE\n\n"); - sciprintf(" %s = %d\n", var->name, *(var->var.intp)); - - if (full) - sciprintf("\n\nDESCRIPTION\n\n %s", data->description); -} - -static void _cmd_print_page(cmd_mm_entry_t *data, int full) { - if (full) - sciprintf("\n\nDESCRIPTION\n\n %s\n", data->description); - else - sciprintf("%s\n", data->name); -} - -static int c_list(EngineState *s, const Common::Array &cmdParams) { - if (_lists_need_sorting) - con_sort_all(); - - if (cmdParams.size() == 0) { - sciprintf("usage: list [type]\nwhere type is one of the following:\n" - "cmds - lists all commands\n" - "vars - lists all variables\n" - "docs - lists all misc. documentation\n" - "\n" - "restypes - lists all resource types\n" - "[resource] - lists all [resource]s"); - } else if (cmdParams.size() == 1) { - const char *mm_subsects[3] = {"cmds", "vars", "docs"}; - int mm_found = -1; - int i; - - for (i = 0; i < 3; i++) - if (mm_subsects[i] && !strcmp(mm_subsects[i], cmdParams[0].str)) - mm_found = i; - - if (mm_found >= 0) - for (i = 0; i < cmd_mm[mm_found].entries; i++) - cmd_mm[mm_found].print((cmd_mm_entry_t *)(((byte *)cmd_mm[mm_found].data) + i * cmd_mm[mm_found].size_per_entry), 0); - else { - if (!s) { - sciprintf("You need a state to do that!\n"); - return 1; - } - - else if (strcmp("restypes", cmdParams[0].str) == 0) { - for (i = 0; i < kResourceTypeInvalid; i++) - sciprintf("%s\n", getResourceTypeName((ResourceType)i)); - } else { - ResourceType res = parseResourceType(cmdParams[0].str); - if (res == kResourceTypeInvalid) - sciprintf("Unknown resource type: '%s'\n", cmdParams[0].str); - else { - for (i = 0; i < sci_max_resource_nr[s->resmgr->_sciVersion]; i++) - if (s->resmgr->testResource(res, i)) - sciprintf("%s.%03d\n", getResourceTypeName((ResourceType)res), i); - } - } - } - } else - sciprintf("list can only be used with one argument"); - return 0; -} - -static int c_man(EngineState *s, const Common::Array &cmdParams) { - int section = 0; - uint i; - Common::String name = cmdParams[0].str; - const char *c = strchr(name.c_str(), '.'); - cmd_mm_entry_t *entry = 0; - - if (c) { - section = atoi(c + 1); - name = Common::String(name.begin(), c); - } - - if (section < 0 || section >= CMD_MM_ENTRIES) { - sciprintf("Invalid section %d\n", section); - return 1; - } - - sciprintf("section:%d\n", section); - if (section) - entry = cmd_mm_find(name.c_str(), section - 1); - else - for (i = 0; i < CMD_MM_ENTRIES && !section; i++) { - if ((entry = cmd_mm_find(name.c_str(), i))) - section = i + 1; - } - - if (!entry) { - sciprintf("No manual entry\n"); - return 1; - } - - sciprintf("-- %s: %s.%d\n", cmd_mm[section - 1].name, name.c_str(), section); - cmd_mm[section - 1].print(entry, 1); - - return 0; -} - -static int c_set(EngineState *s, const Common::Array &cmdParams) { - cmd_var_t *var = (cmd_var_t *)cmd_mm_find(cmdParams[0].str, CMD_MM_VAR); - - if (var) - *(var->var.intp) = cmdParams[1].val; - - return 0; -} - -static int c_print(EngineState *s, const Common::Array &cmdParams) { - cmd_var_t *var = (cmd_var_t *)cmd_mm_find(cmdParams[0].str, CMD_MM_VAR); - - if (var) - sciprintf("%d", *(var->var.intp)); - else - sciprintf("Not defined."); - - return 0; -} - -static int c_size(EngineState *s, const Common::Array &cmdParams) { - ResourceType res = parseResourceType(cmdParams[0].str); - if (res == kResourceTypeInvalid) - sciprintf("Resource type '%s' is not valid\n", cmdParams[0].str); - else { - Resource *resource = s->resmgr->findResource(res, cmdParams[1].val, 0); - if (resource) { - sciprintf("Size: %d\n", resource->size); - } else - sciprintf("Resource %s.%03d not found\n", cmdParams[0].str, cmdParams[1].val); - } - - return 0; -} - -static int c_dump(EngineState *s, const Common::Array &cmdParams) { - ResourceType res = parseResourceType(cmdParams[0].str); - - if (res == kResourceTypeInvalid) - sciprintf("Resource type '%s' is not valid\n", cmdParams[0].str); - else { - Resource *resource = s->resmgr->findResource(res, cmdParams[1].val, 0); - if (resource) - Common::hexdump(resource->data, resource->size, 16, 0); - else - sciprintf("Resource %s.%03d not found\n", cmdParams[0].str, cmdParams[1].val); - } - - return 0; -} - -static int c_hexgrep(EngineState *s, const Common::Array &cmdParams) { - int i, seeklen, resnr, resmax; - unsigned char *seekstr = NULL; - Resource *script = NULL; - char *dot = (char *)strchr(cmdParams[0].str, '.'); - ResourceType restype; - - if (NULL == s) { - fprintf(stderr, "console.c: c_hexgrep(): NULL passed for s\r\n"); - return(-1); - } - - seeklen = cmdParams.size() - 1; - seekstr = (unsigned char *)malloc(seeklen); - - if (NULL == seekstr) { - fprintf(stderr, "console.c: c_hexgrep(): malloc failed for seekstr\r\n"); - return(-1); - } - - for (i = 0; i < seeklen; i++) - seekstr[i] = (byte)cmdParams[i + 1].val; - - if (dot) { - *dot = 0; - resmax = resnr = atoi(dot + 1); - } else { - resnr = 0; - resmax = 999; - } - - restype = parseResourceType(cmdParams[0].str); - if (restype == kResourceTypeInvalid) { - sciprintf("Unknown resource type \"%s\"\n", cmdParams[0].str); - free(seekstr); - return 1; - } - - for (; resnr <= resmax; resnr++) - if ((script = s->resmgr->findResource(restype, resnr, 0))) { - unsigned int seeker = 0, seekerold = 0; - int comppos = 0; - int output_script_name = 0; - - while (seeker < script->size) { - if (script->data[seeker] == seekstr[comppos]) { - if (comppos == 0) - seekerold = seeker; - - comppos++; - - if (comppos == seeklen) { - comppos = 0; - seeker = seekerold + 1; - - if (!output_script_name) { - sciprintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resnr); - output_script_name = 1; - } - sciprintf(" 0x%04x\n", seekerold); - } - } else - comppos = 0; - - seeker++; - } - } - - free(seekstr); - - return 0; -} - -static int c_dissectscript(EngineState *s, const Common::Array &cmdParams) { - if (NULL == s) { - sciprintf("console.c: c_dissectscript(): NULL passed for parameter s\n"); - return -1; - } - - script_dissect(s->resmgr, cmdParams[0].val, s->_selectorNames); - return 0; -} - -#endif // SCI_CONSOLE - -} // End of namespace Sci diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 5dcf42cf59..8773b2b9c8 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -32,12 +32,12 @@ #include "sci/engine/kernel_types.h" #include "sci/engine/kernel.h" #include "sci/engine/savegame.h" +#include "sci/engine/sciconsole.h" #include "sci/gfx/gfx_widgets.h" #include "sci/gfx/gfx_gui.h" #include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual -#include "sci/scicore/resource.h" -#include "sci/scicore/sciconsole.h" -#include "sci/scicore/vocabulary.h" +#include "sci/resource.h" +#include "sci/vocabulary.h" #include "sci/sfx/iterator.h" #include "sci/sfx/sci_midi.h" diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index d8975a0aae..f6ec22a394 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -36,8 +36,8 @@ namespace Common { } #include "sci/sci.h" -#include "sci/scicore/vocabulary.h" -#include "sci/scicore/resource.h" +#include "sci/vocabulary.h" +#include "sci/resource.h" #include "sci/engine/kernel.h" // for kfunct_sig_pair_t #include "sci/engine/script.h" #include "sci/engine/seg_manager.h" diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 81b279f00f..73e4499d20 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/scicore/resource.h" +#include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/intmap.h" #include "sci/engine/kdebug.h" -- cgit v1.2.3